> 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/folder-format.md).

# The standard FlowCP folder

The **standard FlowCP folder** is the portable, human- and git-friendly layout a server **exports to** and **imports from**. One folder fully describes a server's MCP surface — tools, skills, prompts, widgets, resources — plus the configuration the standalone runtime needs to serve it.

It is the same shape whether you:

* run `flowcp export` to download a published server,
* hand-author a server in a Git repository, or
* self-host with the FlowCP standalone runtime.

## Layout

```
my-server/
├── config.yaml          # server identity, auth mode, apiBaseUrl, requiredEnv
├── README.md            # run instructions (generated on export)
├── Tools/
│   ├── openapi.json     # the source OpenAPI document (reference / authoring input)
│   └── <tool>.yaml      # one file per tool: definition + policy
├── Skills/   <name>.md   # frontmatter + Markdown body
├── Prompts/  <name>.md   # frontmatter + Markdown body
├── Widgets/  <name>.html # widget HTML (+ <name>.json metadata sidecar)
├── Resources/ <name>.md  # frontmatter + body (the resource content)
└── Docs/     <slug>.md   # product documentation; nested, e.g.
                          #   Docs/guides/webhooks.md → docs://guides/webhooks
```

Directory names are **Capitalized** (`Tools/`, `Skills/`, …). Lowercase names (`tools/`, `skills/`, …) are also accepted when importing, so older repositories and `flowcp sync` working copies keep importing unchanged.

## `config.yaml`

Everything that isn't stored per item lives here:

```yaml
formatVersion: 1
exportedAt: 2026-06-22T00:00:00.000Z
server:
  id: srv_123
  slug: acme
  name: Acme
  description: The Acme API
  authMode: bearer        # user_oauth | api_key | bearer | none
  provider: openapi       # bubble | openapi | git
  manifestVersion: 1
  toolExposure: auto
  hasAuthSecret: true     # the *fact* a credential exists — never its value
apiBaseUrl: https://api.acme.test
requiredEnv:
  - name: FLOWCP_UPSTREAM_SECRET
    description: Bearer token sent to your upstream API on every tool call.
    required: true
```

> **Secrets are never written to a folder.** Only the fact a credential exists (`hasAuthSecret`) and its placement (in `config.yaml`'s `authConfig`) are recorded. You supply the value at run time via the environment.

## `Tools/`

A tool is generated from your OpenAPI spec, so the recommended way to author tools by hand is to drop an **`openapi.json`** in `Tools/` and let FlowCP generate them on import.

An export additionally writes one **`<tool>.yaml`** per tool — the exact definition and policy as configured in the dashboard (so any hand edits to a description, schema, risk level, or widget link are preserved):

```yaml
name: get_order
description: Get an order by id
method: GET
path: /orders/{id}
enabled: true
riskLevel: read
requiresConfirmation: false
requiredScope: orders:read
widget: order_card        # links to Widgets/order_card.html by slug
inputSchema:
  type: object
  properties:
    id: { type: string }
```

The standalone runtime reads these per-tool files directly — it does not need to regenerate tools from the OpenAPI document.

## Content files

`Skills/`, `Prompts/`, `Resources/`, and `Docs/` use Markdown with a `---`-fenced frontmatter block; `Widgets/` use an `.html` file plus an optional `.json` metadata sidecar. This is the **same on-disk format `flowcp sync` reads and writes**, so a folder committed by hand and one written by the CLI behave identically. Cross-references are stored by name/slug — an endpoint resource points at its backing tool with `tool: <tool_name>`, and a tool points at its widget with `widget: <widget_slug>`.

`Docs/` is the one nested directory: a page's slug is its file path below `Docs/` (minus the extension), so `Docs/guides/webhooks.md` is served at `docs://guides/webhooks`, and an `index.md` or `README.md` collapses to its parent directory. Only `title`, `description`, `mimeType`, `enabled`, and `sortOrder` are written to a page's frontmatter — its headings, content hash, and length are re-derived from the body on import, so a hand-edited page never carries stale metadata. See [Serve product documentation](/guides/serve-product-docs.md).

Internal ids are intentionally omitted; they are re-synthesized from names on import, which keeps exports stable in `git diff` and lets folders be authored entirely by hand.

## Import a folder

```bash
flowcp import folder ./my-server --server <serverId>
```

This upserts the folder's skills, prompts, widgets, resources, and documentation pages into the target server. Imported items follow the platform's **default-deny** rule. To import tools, connect the app to the folder's `Tools/openapi.json`.

## Run a folder (self-host)

Set `FLOWCP_FOLDER_PATH` to the folder and start the standalone runtime — see [Export & self-host your MCP server](/guides/self-host-export.md).
