v1.14.1-mcp-poc: single-server MCP client against Context7
Validates the MCP-client loop end-to-end against one real MCP server before the full v1.15 port. New services/mcp-client.ts wraps @modelcontextprotocol/sdk v1.29.0 with Streamable HTTP transport. On startup (when MCP_CONTEXT7_URL is set), connects to Context7, discovers tools via tools/list, wraps each as a ToolDef prefixed context7_<name>, and appends to ALL_TOOLS via appendMcpTools. Read-only invariant guard rejects any tool with readOnlyHint: false. Tool dispatch is transparent — executeToolCall routes MCP calls through the ToolDef execute wrapper, which strips the prefix before calling the MCP server. Result size capped at 5MB with truncation. Graceful degradation: server down at startup → zero tools; server down mid-session → error result, model self-corrects. Adversarial review caught that a Zod .default() on the URL config made MCP always-on instead of opt-in — fixed by removing the default. MCP_CONTEXT7_URL must be explicitly set to enable. ALL_TOOLS changed from ReadonlyArray to mutable to support late-registration. appendMcpTools re-sorts and rebuilds TOOLS_BY_NAME after append. 348/348 server tests passing (16 new mcp-client tests). No schema changes, no frontend changes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,10 @@
|
||||
|
||||
All notable changes per release tag. Most recent on top, ordered by tag creation date (which matches the git history). Tag names follow `vMAJOR.MINOR.PATCH-slug` — the slug describes what shipped, so the tag name alone is enough to recall the batch.
|
||||
|
||||
## v1.14.1-mcp-poc — 2026-05-23
|
||||
|
||||
Single-server MCP client PoC against Context7. New `apps/server/src/services/mcp-client.ts` (~200 lines) wraps `@modelcontextprotocol/sdk` v1.29.0 with Streamable HTTP transport. On startup (when `MCP_CONTEXT7_URL` is set), connects to Context7, discovers tools via `tools/list`, wraps each as a `ToolDef` prefixed `context7_<name>`, and appends to `ALL_TOOLS` (alpha-sorted for prompt-cache stability). `appendMcpTools()` in `tools.ts` handles the late-registration; `ALL_TOOLS` changed from `ReadonlyArray` to mutable to support it. Read-only invariant guard rejects any MCP tool with `readOnlyHint: false` (MCP SDK v1.29.0 uses `readOnlyHint`, not `readOnly`). Tool dispatch is transparent — `executeToolCall` routes MCP tool calls through the `ToolDef.execute` wrapper, which strips the `context7_` prefix before calling the MCP server. Graceful degradation: MCP server down at startup → zero tools, warn log; MCP server down mid-session → error-shaped result, model self-corrects. Result size capped at 5MB with truncation (matches native `view_file`'s `MAX_FILE_BYTES`). Adversarial review caught that the Zod `.default('https://...')` on the URL config made MCP effectively always-on instead of opt-in — fixed by removing the default. 348/348 server tests passing (16 new mcp-client tests covering tool wrapping, read-only guard, name prefixing, content extraction). No schema changes, no frontend changes. Proves the MCP tool-discovery → tool-call → result-render loop end-to-end before the full v1.15 port.
|
||||
|
||||
## v1.14.0-outer-loop — 2026-05-23
|
||||
|
||||
Converts the inference engine's ad-hoc `executeToolPhase → runAssistantTurn` recursion into an explicit `while` loop with a configurable step cap. A step is one stream-and-tool-execute iteration; the loop terminates on non-tool finish, step-cap hit, doom-loop, budget exhaustion, abort, or synthesis success. `MAX_STEPS = 200` is the hard ceiling (4x the old effective limit from budget); per-agent `steps:` field in AGENTS.md frontmatter sets tighter caps (Refactorer: 5, Architect: 20, others: unset = bounded only by MAX_STEPS). `executeToolPhase` no longer recurses — returns a `ToolPhaseResult` struct (`action: 'continue' | 'paused' | 'synthesis_done'`) so the caller (the while loop) decides whether to continue or break. `steps: 0` is handled as "no tool calls allowed" — one text-only stream phase, tool calls ignored with a warn log. Step-cap hits produce a sentinel summary (reuses `cap_hit` kind so `CapHitSentinel.tsx` renders it without frontend changes; text distinguishes "Step limit reached" from "Tool budget exhausted"). Doom-loop check migrated from pre-recursion position to top of loop body — same predicate (`detectDoomLoop`), same threshold (3 identical calls), `break` instead of `return`. `step_start` parts are in the schema CHECK but not emitted as message_parts in v1.14 — writing to the assistant message before the stream phase creates a sequence-0 collision with `partsFromAssistantMessage`; a structured log line is emitted instead. Adversarial review caught the collision pre-deploy. 332/332 server tests passing; no frontend changes. Pairs with `v1.13.20-drop-legacy-cols` (parts is now the sole source of truth, and this batch's loop operates entirely through parts).
|
||||
|
||||
Reference in New Issue
Block a user