Tool Surface Setup
FlyDocs ships a local MCP server and a command runner so your coding agent works your issue tracker with typed tool calls. What flydocs init registers for Claude Code, Cursor, VS Code and Codex, and how flydocs doctor checks it.
FlyDocs ships a small MCP server and a command runner so your coding agent
can work your issue tracker with typed tool calls instead of shell
commands. Both are set up for you by flydocs init and
flydocs update. This guide covers what those commands write
into your repo, why each write is safe, and how to check the result.
This page is about the local server, flydocs mcp,
which runs on your machine next to your code. FlyDocs also runs a hosted
server for chat clients and machines without a checkout. That one is
covered under Remote MCP, and the two can be
connected side by side.
What You End Up With
| You get | Reached as |
|---|---|
| The lifecycle tools, in your editor | flydocs mcp (stdio MCP server) |
| Every other workflow operation | flydocs run <operation-id> |
| No approval prompt for either | Two standing rules in your settings |
The server is spawned by your editor, over stdio, on demand. Nothing listens on a port, and nothing runs in the background.
The Setup Sequence
npm install -g @flydocs/cli # 1.3.0 or later
cd your-project
flydocs init # registers the server, records the interpreter
flydocs update # writes the managed permission block
flydocs doctor --tools # verifies all of it flydocs init registers flydocs mcp with Claude
Code, Cursor and VS Code, and offers to register it with Codex. It also
resolves the Python interpreter once, here, where you are watching, rather
than on the hot path of the first tool call.
flydocs update does that again (idempotently) and additionally
writes the managed permission block. 1.3.0 is the first release that ships
flydocs mcp; an older CLI cannot serve the registration.
Restart your editor after the first run. MCP registrations
are read at startup; a running editor will not notice a new
.mcp.json, .cursor/mcp.json or
.vscode/mcp.json.
Which clients get registered
| Client | Registered by init and update | Where |
|---|---|---|
| Claude Code | Yes | .mcp.json in the project, under mcpServers |
| Cursor | Yes | .cursor/mcp.json in the project, under mcpServers |
| VS Code | Yes | .vscode/mcp.json in the project, under servers |
| Codex | Offered, once per machine | ~/.codex/config.toml, under [mcp_servers.flydocs] |
Codex has no project-level MCP file, only one machine-wide config, so
FlyDocs asks before touching it. The offer appears only when the
codex command is on your PATH and there is a terminal to ask
in. A declined or non-interactive run writes nothing and never changes the
exit code. Register later with flydocs connect codex, and
remove it with flydocs disconnect codex. Nothing else removes
that block, because every Codex session on the machine uses it.
Enabling in Cursor
Cursor requires a one-time enable for a newly registered project server.
After flydocs init writes .cursor/mcp.json, open
Settings → Cursor Settings → MCP and toggle the
flydocs server on. You only do this once per project.
Alternatively, use the one-click install link:
Add FlyDocs to Cursor
— it registers the same flydocs mcp entry and prompts you to
enable it in one step.
What Gets Written
| File | Written by | Contents |
|---|---|---|
.mcp.json | init, update | A flydocs entry under mcpServers → flydocs mcp |
.cursor/mcp.json | init, update | The same entry, with "type": "stdio" (Cursor's schema) |
.vscode/mcp.json | init, update | The same entry with "type": "stdio", under a servers key (VS Code's schema) |
~/.codex/config.toml | Codex offer in init and update; connect codex | A [mcp_servers.flydocs] table. Machine-wide, written only after you agree |
.claude/settings.json | update | Two permissions.allow rules + a flydocsManaged record |
.claude/.flydocs-backup/ | update | A copy of the settings file taken before any write |
.flydocs/config.json → runtime | init, update | The Python interpreter found on this machine; never sent to the server |
The three project registration files, .mcp.json,
.cursor/mcp.json and .vscode/mcp.json, are added
to .gitignore (from CLI 1.3.24), as are
.claude/settings.json and the backup directory. They are
per-machine. A teammate gets their own by running
flydocs init or flydocs update in their clone.
Ignoring a path never untracks a file your team already committed.
Windsurf also reads Claude Code's .mcp.json, so it needs no file
of its own. VS Code does not: its agent mode reads only
.vscode/mcp.json, under a servers key, and ignores
.mcp.json. That is why VS Code has its own entry.
In a multi-repo workspace
Registrations are written into each repo and at the
workspace root. An editor reads the registration from whatever directory it
was opened in, and flydocs mcp resolves its repo from the same
directory, so a child repo you can open on its own needs its own copy.
Why Each Write Is Safe
- Your other MCP servers survive. Only the
flydocskey inside the server map (mcpServers, orserversfor VS Code) is ever read or written. In Codex's config, only the[mcp_servers.flydocs]table is. When the entry is already correct, nothing is written at all — a repeatflydocs updateleaves the file byte-identical. - A file FlyDocs cannot read is never overwritten. An
.mcp.jsonwith a syntax error may still hold half your team's server list; FlyDocs reports it and leaves it alone. Same for.vscode/mcp.jsonand.claude/settings.json. - The permission block is replaced atomically, after a backup.
The settings file is written to a temporary file, flushed, and renamed —
a torn settings file would silently disable your hooks as well as your
permissions. The previous content is copied under
.claude/.flydocs-backup/before the first byte changes. - Rules are removed only on an exact match. FlyDocs
records exactly which rules it wrote, under a top-level
flydocsManagedkey. A rule you wrote yourself is never removed, even if it looks similar. See Managed Permissions for the modes and fields. - Nothing machine-specific reaches the server. The
resolved Python interpreter is stored under a
runtimekey that is CLI-local, preserved across syncs, and never part of what your workspace syncs up.
Options Worth Knowing
| Flag | Effect |
|---|---|
flydocs update --no-overwrite | Keep an existing flydocs MCP entry instead of replacing it |
flydocs connect codex | Register the local server with Codex, in ~/.codex/config.toml |
flydocs doctor --tools | Run only the tool-surface checks |
flydocs doctor --tools --fix | Repair what FlyDocs owns, then re-check everything |
flydocs doctor --json | The same results as one JSON document, for CI |
flydocs mcp --verbose | Run the server by hand with tool calls logged to stderr |
What flydocs doctor Verifies
flydocs doctor --tools answers the questions this setup cannot
answer for itself. Every check has a stable ID, and those IDs are what the
Troubleshooting guide is
organised by. The IDs are a contract: they appear in
--json output and in CI logs, and a check is added rather than
an ID reused.
| ID | Question it answers |
|---|---|
surface.scope | Which directory is being examined |
mcp.server | Does this build’s server complete a real handshake |
mcp.tools-budget | Does the tool list stay inside its context budget |
mcp.command | Is flydocs on PATH, and new enough (1.3.0 or later) to serve mcp |
mcp.registration.claude | Does .mcp.json point at flydocs mcp |
mcp.registration.cursor | Does .cursor/mcp.json point at flydocs mcp |
mcp.registration.vscode | Does .vscode/mcp.json hold flydocs under servers |
mcp.registration.codex | Does ~/.codex/config.toml hold [mcp_servers.flydocs] (optional; a warning only when Codex is installed and the block is missing) |
mcp.remote.registration.claude | Is the remote flydocs-cloud server registered in ~/.claude.json (optional, offline) |
mcp.remote.registration.cursor | Is flydocs-cloud in ~/.cursor/mcp.json (optional, offline) |
mcp.remote.registration.codex | Is [mcp_servers.flydocs-cloud] in ~/.codex/config.toml (optional, offline) |
mcp.remote.registration.vscode | Is flydocs-cloud in the user-level VS Code mcp.json (optional, offline) |
permissions.settings | Does .claude/settings.json parse |
permissions.block | Is the managed block present and current |
permissions.default-mode | Is the agent default mode distributed only when the workspace asks for it, and is nothing in the way |
permissions.auto-noop | Does a project-level settings file set defaultMode to auto, which Claude Code ignores there |
permissions.ownerless-config | Does this repo’s config carry a workspace ID, so the default mode can be recorded against it |
otel.pipe | Does the managed telemetry block match what the workspace opted into |
run.registry | Do the operation registry and its entrypoints load |
run.interpreter | Can flydocs run find a Python 3 interpreter |
run.dry-run | Does an operation resolve end to end |
runtime.python | Does the recorded interpreter still exist |
release.signing | Is the installed release verified against a signing key this machine trusts |
Exit code is 0 if and only if nothing failed; warnings never
fail the command, which makes flydocs doctor --tools safe to
put in CI.
What FlyDocs Does Not Do Here
- It does not run a server in the background, or open a port.
-
It does not ask for OAuth. On stdio, credentials come from the
environment and from
~/.flydocs/credentials— which is what the MCP specification prescribes for local servers. The hosted server signs in with OAuth instead; see Connect your agent. -
It does not probe your PATH during
initorupdate. That question — "is theflydocsyour editor will spawn the same one that wrote this file?" — belongs toflydocs doctor, and ismcp.command. -
It does not touch any MCP server entry other than
flydocs, or any permission rule it did not write.
Next
- Managed Permissions: modes, policy fields, and what an admin controls
- Troubleshooting: keyed to the doctor check IDs above
- Skill Operations: contributing operations from a skill
- Remote MCP: the hosted server, its tools, and how to connect to it