MCP Tools

Yaaf loads MCP tools from a config file. The path is resolved in this order:

  1. --mcp <path> passed to ask, chat, agent, or run (or as a global option before the subcommand).
  2. YAAF_MCP_FILE from the process environment or .env file.
  3. .yaaf/mcp.json auto-discovered in the current working directory.

When none of these is set and no .yaaf/mcp.json exists, yaaf runs without MCP tools.

The file must use the VS Code MCP configuration shape unchanged, but yaaf keeps project-owned MCP config under .yaaf/mcp.json for auto-discovery and examples. For explicit non-default paths, pass a normal file path such as ./configs/docs.mcp.json.

For project-owned defaults, drop a .yaaf/mcp.json at the repository root and yaaf will pick it up automatically for both regular commands and yaaf run <script> invocations launched from that directory.

Supported Config Shape

Supported top-level fields:

  • servers: required object keyed by server id.

Supported server types:

  • http: JSON-RPC over HTTP POST.
  • sse: accepted as an HTTP-style server entry; text/event-stream responses are parsed for data: payloads.
  • stdio: JSON-RPC over newline-delimited stdio on Windows, macOS, and Linux builds.

Supported server fields:

  • url for http and sse servers.
  • headers for http and sse servers.
  • command and args for stdio servers.
  • env and envFile for stdio process environment overrides.

Minimal HTTP server:

{
  "servers": {
    "docs": {
      "type": "http",
      "url": "http://127.0.0.1:3000/mcp"
    }
  }
}

Minimal stdio server:

{
  "servers": {
    "hello": {
      "type": "stdio",
      "command": "uv",
      "args": ["--directory", "${workspaceFolder}/mcp-servers", "run", "python", "hello_stdio.py"]
    }
  }
}

For the repository fixture servers, Linux uses the same uv-based stdio setup as macOS. There are no extra Linux-only stdio fixture prerequisites beyond having uv available.

Variable Substitution

Yaaf expands variables recursively in string values inside each server object.

Supported variables:

  • ${workspaceFolder}: replaced with the current workspace root using forward slashes.
  • ${env:NAME}: replaced with the process environment variable value, or an empty string if it is not set.

Example with workspace and environment variables:

{
  "servers": {
    "docs": {
      "type": "http",
      "url": "${env:DOCS_MCP_URL}",
      "headers": {
        "Authorization": "Bearer ${env:DOCS_MCP_TOKEN}"
      }
    },
    "hello": {
      "type": "stdio",
      "command": "uv",
      "args": ["--directory", "${workspaceFolder}/mcp-servers", "run", "python", "hello_stdio.py"],
      "envFile": "${workspaceFolder}/.env",
      "env": {
        "YAAF_HELLO_MODE": "local"
      }
    }
  }
}

envFile lines use NAME=value. Empty names, comment lines starting with #, and lines without = are ignored. Inline env values override values loaded from envFile.

Values under headers and env are redacted from doctor output, including the active MCP diagnostics added to each server report.

Tool Names

MCP tools are exposed as <server>.<tool>. A server named docs with a remote tool named lookup becomes docs.lookup:

yaaf doctor
yaaf doctor --format json --pretty
yaaf ask --tool docs.lookup "Look up the install steps."
yaaf chat --tool docs.lookup "What does this API do?"
yaaf agent --name react --tool docs.lookup "Summarize the docs for this feature."

doctor now performs an active initialize plus tools/list check for each configured server. In text mode it shows per-server initialize status and discovered tool names such as docs.lookup; in JSON mode each mcp.servers[] entry gains an active object with initialize and tools results.

Runtime Behavior

Implemented JSON-RPC lifecycle:

  • initialize with the latest generated supported protocol version.
  • Negotiated protocolVersion validation.
  • notifications/initialized after successful initialization.
  • Per-server session caching.

Implemented MCP methods:

  • tools/list, including nextCursor pagination.
  • tools/call.

HTTP behavior:

  • Sends Accept: application/json, text/event-stream.
  • Sends MCP-Protocol-Version after negotiation.
  • Stores and re-sends Mcp-Session-Id when returned by the server.
  • Parses both JSON responses and SSE-style data: response payloads.

Tool call results are normalized into yaaf's tool result shape. Text content blocks are joined with newlines, non-text content blocks are preserved as JSON text, and structuredContent is used as JSON text when there are no content blocks.

Schema Support

Protocol version metadata is generated from the official versioned MCP JSON schemas in modelcontextprotocol/modelcontextprotocol.

Current generated protocol versions:

  • 2024-11-05
  • 2025-03-26
  • 2025-06-18
  • 2025-11-25

Refresh generated schema files with:

./scripts/UpdateMcpSchemas.ps1

Generated files include one backend implementation per protocol version under libyaaf/mcp/schema/schema-<version>.cpp, plus the registry/factory used by the native client.

Fixture Servers

Real hello-world MCP fixture servers live in mcp-servers. They expose:

  • hello(name?: string): returns Hello, <name>!.
  • repeat(text: string, count?: integer): repeats text a bounded number of times.

The optional local fixture stack also starts httpbin plus the HTTP and SSE fixtures for manual transport debugging and smoke checks:

docker compose -f docker-compose.fixture-stack.yml up

Fixture URLs exposed by that stack:

  • HTTP client fixture: http://127.0.0.1:18082
  • HTTP client fixture through mitmproxy visibility: http://host.docker.internal:18082
  • HTTP: http://127.0.0.1:39231/mcp
  • HTTP through mitmproxy visibility: http://host.docker.internal:39231/mcp
  • SSE: http://127.0.0.1:39232/mcp

Not Implemented Yet

Yaaf currently does not implement native client APIs for prompts, resources, resource subscriptions, roots, sampling, elicitation, logging level control, task APIs, progress or cancellation handling, OAuth flows, JSON-RPC batching, or long-lived SSE event streams beyond extracting response payloads from HTTP responses.

The implementation-level support matrix is maintained in libyaaf/mcp/README.md.