> For the complete documentation index, see [llms.txt](https://docs.flowcp.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.flowcp.ai/guides/serve-product-docs.md).

# Serve product documentation

Tools let an AI agent *act* on your API. **Documentation pages** teach it what your product actually means — so when a user asks "how do webhook retries work?", the agent answers from your docs instead of guessing.

Each enabled page is served as an MCP resource at `docs://<slug>`, and the runtime adds two built-in tools:

* **`search_docs`** — free-text search across your page titles, descriptions, slugs, and headings. Returns matching pages with their `docs://` URIs. Called with no query, it lists the available pages, so it doubles as a table of contents.
* **`read_doc`** — returns one page's full text by slug. This is the fallback for AI clients that don't surface resources.

Both tools appear only once you have at least one **enabled** page, so a server without documentation never advertises them.

## Why not just use a Resource?

You can put a short document in a [static resource](/guides/offer-resources.md), and for one or two pages that is fine. Documentation is a separate capability because a real docs corpus is much larger: pages are stored so that the runtime can list and rank hundreds of them without loading a single page body, and only fetches a body when a client actually reads that page. That is also why the documentation list in the dashboard shows each page's size — it is metadata, not content.

Use **Skills** for *procedures* ("to refund an order, first call…") and **Documentation** for *reference* ("these are the order states and what each means").

## Opening the documentation list

From your app's dashboard, click the **Documentation** tab. The page lists every documentation page on the selected server with an on/off switch, its `docs://` URI, its size, and — for pages that came from a connected repo — a **From repo** badge and the file path it was imported from. A line above the list shows how many pages are enabled. If your app has multiple environments (branches), use the branch buttons to switch between them.

## Writing a page in the dashboard

1. Click **New page**.
2. Fill in the fields:
   * **Slug** — a path-like, lowercase identifier, e.g. `guides/webhooks`. This is what the page is served at: `docs://guides/webhooks`. Use `/` to group related pages.
   * **Title** — optional. Left empty, it defaults to the page's first markdown heading.
   * **Description** — a one-line summary. This is what an agent sees in `search_docs` results, so write it as the question the page answers.
   * **Content** — the page body, in markdown. Headings are indexed for search, so a page with clear `##` sections is easier for an agent to find.
3. Click **Create page**.

New pages are created **disabled**, following the platform's default-deny model — see [Default-deny model](/security/default-deny-model.md).

## Importing pages from a Git repository

If your app is connected to a GitHub or GitLab repository, commit markdown files to a **`Docs/`** directory and FlowCP imports them on each import run:

```
Docs/
├── overview.md              → docs://overview
├── guides/
│   ├── index.md             → docs://guides
│   └── webhooks.md          → docs://guides/webhooks
└── reference/
    └── errors.md            → docs://reference/errors
```

* The file path becomes the slug — sub-directories are the page hierarchy.
* `index.md` and `README.md` collapse to their parent directory, so `Docs/guides/index.md` is served at `docs://guides`.
* Both `.md` and `.mdx` files are imported. A lowercase `docs/` directory works too.
* Optional front matter sets `title`, `description`, and `sortOrder`:

  ```markdown
  ---
  title: 'Setting up webhooks'
  description: 'Register an endpoint and verify signatures'
  ---

  # Setting up webhooks

  …
  ```

Imported pages are created **disabled**, and re-running the import is safe: pages whose content hasn't changed are left alone, and pages you authored by hand in the dashboard are never overwritten. Editing an imported page in the dashboard works, but the next import overwrites your edit — change the file in the repo instead.

See [Connect your API](/guides/connect-your-api.md) for connecting a repository, and [The standard FlowCP folder](/guides/folder-format.md) for the full folder layout.

## Enabling a page

Toggle the switch on a page's row to **On** to offer it to AI clients. Changes take effect immediately — no re-publish required. Disabled pages are never listed, never searchable, and never readable.

## Editing and deleting

* Click the **pencil** icon to edit a page. Because the list doesn't carry page bodies, the editor loads the full page when it opens.
* Click the **trash** icon to delete a page. This cannot be undone.

## Limits

* Up to **500 pages** per server, and **200,000 characters** per page.
* The repo importer walks up to three directory levels below `Docs/` and imports up to 400 files per run.

## Documentation and version history

Documentation pages are **not** part of a server's [version history](/guides/version-history.md) snapshots, and restoring an earlier version leaves your pages untouched. Pages are content — version them in the repository they come from. Every documentation change is still recorded in the server's change log for auditing.

## Keeping pages in sync from your terminal

The [FlowCP CLI](/reference/cli.md) syncs documentation alongside your other content:

```bash
flowcp sync pull     # write Docs/**.md from the server
flowcp sync push     # upload local Docs/**.md to the server
```

An [exported server](/guides/self-host-export.md) also carries its documentation: each page is written to `Docs/<slug>.md`, and a self-hosted runtime serves the bodies straight from that folder.
