Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesMcp ServerMCP server — Code Map

MCP server — Code Map

Module wiring

  • apps/api/src/mcp/mcp.module.ts — imports AiModule (which exports ToolRegistryService and ToolRunnerService); registered in app.module.ts.

Endpoints

  • apps/api/src/mcp/mcp.controller.ts
    • McpController (@Public(), own auth): POST /mcp (Streamable HTTP, stateless, JSON responses), GET|DELETE /mcp → 405. Passes the user agent and any mcp-session-id header to McpService.createServer.
    • McpWellKnownController: GET /.well-known/oauth-protected-resource[/mcp], GET /.well-known/oauth-authorization-server.
  • apps/api/src/mcp/mcp-oauth-metadata.ts — clerkFrontendApiUrl (from the publishable key), publicBaseUrl (from API_BASE_URL).

Auth

  • apps/api/src/mcp/mcp-auth.service.ts — token → Clerk user id (test bypass → session JWT → Clerk OAuth access token), then user → active staff membership → org selection → AgentRuntime.
  • apps/api/src/auth/auth.guard.ts — isTestAuthBypassEnabled shared with the guard.

Tool adapter

  • apps/api/src/mcp/mcp-tool-adapter.ts — isMcpExposed(meta) (MCP’s own exposure rules: normal kind, confirm: 'never'), mcpSummary (the leaf’s mcp.summary when it declares one), mcpToolName, toMcpText (dotted → underscore tool names), toMcpTool(meta), toCallToolResult.
  • apps/api/src/mcp/mcp.service.ts — MCP_INSTRUCTIONS (day grain); createServer (async) builds the per-request Server with the instructions, tools/list + tools/call; calls go through ToolRunnerService.execute and are tracked as mcp.tool.executed.
  • apps/api/src/mcp/mcp-write-shape.ts — programmingWriteShape: the counts/enums a programming write adds to mcp.tool.executed.
  • apps/api/src/ai/agent/tools/tool.types.ts — ToolMcpMeta (AgentToolMetadata.mcp: summary, the description MCP serves instead of the shared one); set through @AgentTool({ mcp }) in decorators.ts.
  • apps/api/src/ai/agent/tools/tool-registry.service.ts — definitionsForRole(role): the provider-neutral projection both the Anthropic router-tools (toolsForRole(role)) and MCP build from.
  • apps/api/src/ai/agent/tools/tool-runner.service.ts — returns the validated input next to the result.

Tests

  • mcp.service.unit.spec.ts — list/call over a real SDK client (in-memory transport): role scoping, exposure rules, validation, audit, denied tools, day-grain instructions/tools/summaries, Spotter listing and running the day write, write-shape telemetry.
  • mcp-tool-adapter.unit.spec.ts — every production Spotter leaf projects to a valid, uniquely-named MCP tool; MCP ⊆ Spotter per role; workouts_parse / workouts_upsert on both channels.
  • mcp-well-known.unit.spec.ts — protected-resource metadata: resource origin and authorization server.
  • mcp-auth.service.unit.spec.ts — token kinds, revoked/expired, bypass gating, org selection, locale.
  • apps/api/src/ai/agent/tools/leaves/workouts.tools.unit.spec.ts — workouts_upsert flattening/validation (date), fill wiring and scoring for MCP section writes by channel, and the Spotter refusal of hand-authored sourceText/scores.
  • apps/api/test/e2e/day-grain-coaching.e2e.spec.ts — Capacity’s real 2026-09-27 day over POST /mcp: one upsert with five parts, warnings, an untitled re-send named for its date, publish once, read-back, the workout’s and the athlete’s assignment’s displayName; and Spotter (POST /organizations/:orgId/agent/messages, model stubbed) handed workouts.parse/workouts.upsert and the day-grain prompt. Fixture: apps/api/test/e2e/fixtures/capacity-day-2026-09-27.ts.
  • apps/api/test/e2e/day-grain-parse.e2e.spec.ts — Danny’s four real days through workouts_parse (replayed extractions): one workout with its parts, titles never the brief (proposal, stored workout, assignment displayName), and a suggestion confirmed with save.resolutions saving in one call.

Scheduled programming source sync

  • apps/api/src/ai/agent/tools/leaves/read.tools.ts — source-ref workout listing and pagination.
  • apps/api/src/ai/agent/tools/leaves/workouts.tools.ts — source text, score slots and parts in section replacement; upsert; SectionFidelityService.fill for MCP writes; refuseHandAuthoredText (Spotter never sends sourceText/scores).
  • apps/api/src/ai/agent/tools/leaves/programs.tools.ts — source-ref session listing and removal.
  • apps/api/src/workout-assignments/program-sessions.service.ts — org-scoped lookup, athlete activity, and transactional removal.
  • scripts/mcp-programming-sync.mjs — minimal OAuth PKCE client; guide.