Files
fusion/docs/mcp.md
gsxdsm 3bfdb16650 FN-7033: document MCP operator workflows
Add a canonical MCP guide with operator workflows and contract coverage.

- Add docs/mcp.md covering MCP settings resolution, transports, secret references, validation, dashboard management, CLI commands, import/export, and AI lane forwarding.
- Link the MCP guide from the docs index, CLI reference, settings reference, secrets docs, and dashboard guide.
- Add a documentation contract test that checks required guide sections and source-aligned MCP surfaces.

Files changed:
 docs/README.md                                     |   1 +
 docs/cli-reference.md                              |   2 +-
 docs/dashboard-guide.md                            |   2 +-
 docs/mcp.md                                        | 221 +++++++++++++++++++++
 docs/secrets.md                                    |   2 +-
 docs/settings-reference.md                         |   2 +
 .../src/__tests__/mcp-documentation.test.ts        |  65 ++++++
 7 files changed, 292 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-7033

Fusion-Task-Lineage: 530abc69-0247-49ee-9487-54d8e2a1b988
2026-06-26 02:52:51 -07:00

13 KiB

MCP (Model Context Protocol)

← Back to docs index

MCP (Model Context Protocol) is a standard way to attach external tool servers to AI runtimes. Fusion stores trusted MCP server definitions in settings, resolves the effective global/project configuration, materializes any referenced secrets only at use time, and forwards enabled servers to MCP-capable AI lanes so those lanes can use the same operator-approved tools.

Overview

MCP support lets Fusion operators configure external stdio, SSE, or streamable HTTP MCP servers once and make them available to AI sessions that support MCP. Enabled servers are treated as trusted once configured: after an operator saves a server definition, Fusion may forward it to supported AI lanes without asking again for each session.

MCP configuration lives in the mcpServers settings key at both scopes:

  • Global settings hold shared MCP declarations.
  • Project settings hold project-specific declarations.
  • Effective resolution is project-over-global by server name: global servers load first, same-named project servers replace them, and same-named project servers with enabled:false disable the inherited global server.
  • The project-level mcpServers.enabled flag overrides the global flag when it is set. If the effective flag is false, no MCP servers are active.

Expected outcome: when mcpServers.enabled resolves to true and at least one enabled server definition is valid, supported AI runtimes receive the effective server set for new sessions.

Server definitions and transports

Every server has a unique name, an optional per-server enabled flag, and exactly one transport:

Transport Required fields Optional sensitive fields Notes
stdio command env args may provide command arguments.
sse url headers Uses an SSE endpoint.
streamable-http url headers The CLI also accepts http as an alias and stores streamable-http.

Definitions use these shapes:

{ "name": "local-tools", "enabled": true, "transport": "stdio", "command": "node", "args": ["server.js"], "env": { "API_KEY": { "secretRef": "sec_...", "scope": "project" } } }
{ "name": "docs-sse", "transport": "sse", "url": "https://example.test/sse", "headers": { "Authorization": { "secretRef": "sec_...", "scope": "global" } } }
{ "name": "docs-http", "transport": "streamable-http", "url": "https://example.test/mcp", "headers": { "Authorization": { "secretRef": "sec_...", "scope": "project" } } }

Expected outcome: settings validation accepts only the required fields for the selected transport, rejects duplicate server names within one stored settings array, and rejects plaintext sensitive values.

Secret references

Fusion never persists raw MCP environment values, header values, or token-like material in settings. Sensitive maps store only Fusion-managed secret references:

{ "secretRef": "sec_...", "scope": "project" }

Use scope: "project" for secrets stored in the current project and scope: "global" for secrets stored in the global secrets database. The plaintext value lives in the encrypted Secrets store, not in mcpServers.

Fusion materializes MCP secret references only at the use seam:

  • when creating an AI session for an MCP-capable runtime;
  • when running a bounded validation/reachability probe;
  • when importing plaintext Claude Desktop env/header values and immediately creating Fusion secrets.

Expected outcome: API responses, CLI output, settings JSON, exports, and structured logs show secret references or counts/status metadata only; they do not include decrypted env/header values.

Validation and reachability

The dashboard Test control calls POST /api/mcp/validate for one server. The route accepts a JSON body with either:

  • name — resolve a configured server by name in the current project context; or
  • server / definition — validate and probe the supplied server definition.

timeoutMs is optional, must be positive, and is capped at 30000 milliseconds. The response is:

{ "status": "valid", "message": "..." }

status is one of:

Status Meaning
valid The definition resolved, secrets materialized, and the bounded probe reached the server.
unreachable The definition resolved, but the probe could not reach the server within the bounded check.
error Validation, secret resolution, spawn, fetch, or protocol setup failed.

Expected outcome: validation returns only { status, message? }; resolved env and headers values are never returned.

Note: fn mcp validate currently validates stored definitions and reports whether they satisfy Fusion's schema. It does not perform the dashboard/API reachability probe.

Managing servers in the dashboard

  1. Open Settings → Global → MCP Servers for shared defaults, or Settings → Project → MCP Servers for project-specific servers. Expected outcome: the Global MCP servers or Project MCP servers card appears.
  2. Turn on Enable MCP servers for this scope. Expected outcome: the current scope's mcpServers.enabled draft becomes true; project scope overrides global enablement when saved.
  3. Click Add server. Choose stdio, SSE, or HTTP, then enter the required command or url. Expected outcome: the editor only asks for fields used by that transport and saves HTTP as streamable-http.
  4. Add sensitive values under Environment secret refs for stdio or Header secret refs for sse / streamable-http. Choose an existing secret or create a new secret with Create secret. Expected outcome: the settings draft receives only { secretRef, scope }; the plaintext creation value is stored in Secrets, not in settings.
  5. Save the server. Expected outcome: the row appears with its transport, state badge, and validation status of Not tested.
  6. In project settings, review inherited rows from global settings. Use Override to replace an inherited server or Disable to add a same-named project disabled entry. Expected outcome: state badges identify inherited, overridden, project-local, and disabled-global behavior before you save.
  7. Click Test on a server row. Expected outcome: the row shows Testing… while pending, then valid, unreachable, or error with the returned message.
  8. Use the Import pane to paste JSON or choose Upload JSON. Expected outcome: Claude Desktop-style servers are added to the draft, duplicate names are rejected, and plaintext env/header values are converted into newly created Fusion secrets plus secret references.
  9. Use Copy Fusion MCP JSON and then Download JSON when needed. Expected outcome: the export contains Fusion MCP JSON with secret references, and no plaintext secret values.
  10. Save the Settings modal. Expected outcome: the selected global or project mcpServers settings are persisted and used by subsequent MCP-capable AI sessions.

Managing servers from the CLI

  1. List configured servers:

    fn mcp list [--project <name>] [--json]
    

    Expected outcome: Fusion prints global, project, and effective servers with secret summaries such as project secret, never decrypted values.

  2. Add a stdio server:

    fn mcp add local-tools --scope project --transport stdio --command node --arg server.js --env API_KEY=my-existing-secret --secret-scope project
    

    Expected outcome: Fusion resolves my-existing-secret by id or key, stores it as { secretRef, scope }, and prints ✓ Added MCP server "local-tools" to project scope.

  3. Add an SSE or streamable HTTP server:

    fn mcp add docs --scope global --transport sse --url https://example.test/sse --header Authorization=docs-token --secret-scope global
    fn mcp add http-docs --scope project --transport http --url https://example.test/mcp --secret-ref docs-token --secret-scope project
    

    Expected outcome: sse stores an SSE server, http is normalized to streamable-http, and --secret-ref supplies a token-like default secret field when no explicit --env or --header is present.

  4. Create secrets while adding or editing:

    fn mcp add private-docs --scope project --transport streamable-http --url https://example.test/mcp --create-secret-header Authorization=Bearer-token-value
    

    Expected outcome: the CLI creates a Fusion secret with a suggested MCP key and persists only the new secret reference in settings.

  5. Edit a scoped server:

    fn mcp edit local-tools --scope project --command node --args '["server.js","--verbose"]'
    

    Expected outcome: only the selected global or project declaration changes; effective project-over-global behavior is recomputed later by name.

  6. Enable or disable a server:

    fn mcp enable local-tools --scope project
    fn mcp disable local-tools --scope project
    

    Expected outcome: Fusion flips the selected declaration's enabled flag. At project scope, disabling a same-named inherited server masks the global declaration without deleting it.

  7. Remove a scoped declaration:

    fn mcp remove local-tools --scope project
    

    Expected outcome: the selected declaration is deleted. If you remove a project override, a same-named global server may become effective again.

  8. Validate stored definitions:

    fn mcp validate [--scope global|project|effective] [--json]
    

    Expected outcome: Fusion reports whether stored definitions satisfy the MCP settings schema. Use the dashboard Test control or POST /api/mcp/validate for reachability.

Importing Claude Desktop configuration

  1. Prepare a Claude Desktop-style JSON file or paste payload:

    {
      "mcpServers": {
        "docs": {
          "command": "node",
          "args": ["server.js"],
          "env": { "API_KEY": "plaintext-from-claude-config" }
        }
      }
    }
    

    Expected outcome: Fusion recognizes the mcpServers object and maps each entry to a named MCP server.

  2. Import from the dashboard by opening Settings → Global → MCP Servers or Settings → Project → MCP Servers, pasting the JSON into Import, or choosing Upload JSON, then clicking Import. Expected outcome: plaintext env/header values are converted into Fusion secrets with prompt access policy and settings receive only secret references.

  3. Import from the CLI:

    fn mcp import ./claude_desktop_config.json --scope project --yes
    

    Expected outcome: the CLI prints an import summary, creates Fusion secrets for plaintext env/header values, replaces them with secret references, and imports the definitions into the selected scope.

  4. Review the imported rows with fn mcp list or the dashboard card before saving/applying broader settings changes. Expected outcome: duplicate names are visible, secret fields show as references, and effective project-over-global behavior is clear.

Exporting Fusion MCP configuration

  1. Export from the dashboard by opening the MCP settings card and clicking Copy Fusion MCP JSON. Expected outcome: the JSON is copied when clipboard access is available, and the export text appears for manual copy.

  2. Click Download JSON after generating the dashboard export. Expected outcome: the browser downloads fusion-mcp-servers.json.

  3. Export from the CLI:

    fn mcp export --scope effective --output fusion-mcp-servers.json
    fn mcp export --scope global --json
    

    Expected outcome: --output writes the JSON to a file; without --output, Fusion prints JSON to stdout. global, project, and effective choose stored global declarations, stored project declarations, or resolved project-over-global output.

  4. Inspect the exported secret fields. Expected outcome: env/header values remain { secretRef, scope } references and are not decrypted into plaintext.

How MCP servers reach AI lanes

When an AI lane starts a session, Fusion resolves the effective mcpServers settings, materializes secret references through the scoped secrets store, and passes the resulting in-memory server declarations to runtimes that support MCP. The forwarding path covers chat/planning, executor, reviewer, validator, merger, workflow model nodes, summarization, evaluator, research, cron/automation, mission, and reflection paths.

Runtime support is guarded. Claude/pi/ACP-compatible runtimes receive MCP servers; mock or unsupported runtimes skip forwarding and emit only structured count/provider/runtime metadata. Skipped forwarding is not a settings error: it means the selected runtime does not accept MCP server declarations.

Expected outcome: enabling a server makes it available to subsequent supported AI sessions, while unsupported sessions continue without MCP tools and without logging secret-bearing server definitions.

See Settings Reference for the mcpServers settings contract and Agents for runtime/model lane behavior.