feat(cli): project MCP tools into the routed CLI via routes.mcpCommands (#102 stage 4) - #275
Conversation
Compile selected generated MCP tools into the shared CLI graph with fail-closed mutation confirmation and route-contract parity.
# Conflicts: # packages/agent-bundle/tests/projection/mcp-in-memory.test.ts
🦋 Changeset detectedLatest commit: 1e64e2c The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1e64e2c71e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ' if (command.mcp !== undefined) {', | ||
| ' return openRenderedSession({', | ||
| " invocation: { kind: 'tool', props: { input: parsed, operationId: command.routeId } },", | ||
| ' props: { input: parsed },', | ||
| ` request: { artifactEpoch: ${JSON.stringify(generatedRouteArtifactEpoch(options.plugin))}, kind: 'tool', operationId: command.routeId, surface: command.mcp.tool },`, |
There was a problem hiding this comment.
Mount MCP context providers in projected CLI runs
In the generated packed-CLI path, selecting this MCP branch still sends the tool through generatedRenderedRouteWorkerSource, whose runAgentRequest setup neither imports nor executes model.providers and does not install the framework processLifetime provider, unlike generatedRouteFlightWorkerSource. Consequently, a valid MCP tool that reads (await agent()).providers.projectAuth succeeds through its generated MCP server but sees a missing provider or fails when invoked through the new projected CLI; pass the compiled providers into this worker and mount them using the tool invocation before rendering.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
…tool scopes (#223) (#276) * feat(runtime): observe transport identity in generated MCP request scopes (#223) Generated MCP tool, resource, and prompt request scopes now observe the negotiated client identity as a native host and derive workspace from the server process cwd, alongside the existing native session and authInfo actor, forwarding all four axes into the Flight worker. Typed unavailability is preserved where a transport genuinely lacks an axis (bare stdio supplies no sessionId or authInfo). The in-memory projection level mirrors the worker boundary so mcp-in-memory stays faithful, with the harness context seam still winning. Proof assertions flip from honest absence to the positive contract at the generated-server integration, mcp-in-memory, and packed journey levels; also repairs the packed listTools assertion left stale when #273 added the context fixture route. * test(packed): reconcile packed listTools with the mutation-probe harness tool (#275)
Second of two #102 stage-4 PRs (the acceptance pass landed as #274). Implements the issue's "MCPorter-based CLI projection" line in-house, per the recorded #107 gate G7 (no hard MCPorter dependency): the projection runs over the compiled route graph and invokes routes locally — zero new dependencies, no second command model. MCPorter remains usable independently against the generated MCP server as a live-server client.
What this adds
routes.mcpCommands: true | { include?, exclude? }— selects tools from generated MCP servers into the same collision-checked command graph and generated executable assrc/cli/**routes, including standalone (nosrc/cli/**at all). Patterns match<server>:<tool>with literal text plus*; any pattern matching nothing (orinclude: []) fails compilation with new diagnostic AB4822 listing the available identities. Malformed config is AB4804;routes.cli: 'conventional'+mcpCommandsis AB4804.<bin> <server> <tool>, one optional--input '<JSON object>'(omitted →{}; invalid JSON/arrays/null/scalars → usage exit 2 before any route execution). The route's own zodinputSchemastays the single validation authority.annotations.readOnlyHint === true; every other tool (missing or malformed annotations included) synthesizes a required--yesand exits 2 without executing the route when absent (proven by a side-effect-counting fixture tool).invocation: { kind: 'tool', props: { input, operationId } }and request context{ kind: 'tool', operationId, surface: <tool>, artifactEpoch }, identical to the generated MCP server; a parity test asserts CLI--jsonoutput equals the in-memory MCPstructuredContentfor identical input. All rendered output modes (Markdown/TTY progress/--json/--ndjson) come along for free from the shared shell.routes.mcpCommands.excluderecovery.mcp: { server, tool, confirm }on compiled commands, surfaced through the test-manifest, dev route manifest, and Workbench's strict manifest decoder (schema extended; no UI changes).Review notes
context,strict-report,ticket,wait) into the projection expectations and registered the newmutation-probefixture in the contract matrix.Local gates (merged with latest main)
rslint0 errors / 0 warnings (939 files)cli-dispatch-mcpsuite), packed CLI journey 1/0agent-bundleminor