Skip to content

mcp: load servers from <agentDir>/mcp.json and bind extensions - #60

Open
hello-pollux wants to merge 2 commits into
frolic:mainfrom
hello-pollux:pollux/mcp-support
Open

hello-pollux wants to merge 2 commits into
frolic:mainfrom
hello-pollux:pollux/mcp-support

Conversation

@hello-pollux

Copy link
Copy Markdown
Contributor

MCP was configured but dead. pi 1.x loads its MCP extension from the app layer, and this harness did neither half of what that requires.

1. Nothing read the config

The extension context has no agentDir, so pi's default loader resolves mcp.json against ~/.pi/agent and never saw this bot's file (I confirmed it: ctx.agentDir === undefined). src/mcp/loadAgentMcpConfig.ts reads <agentDir>/mcp.json synchronously (pi's loadConfig is sync), builds typed stdio/HTTP configs without casts, keeps disabled entries listed (enabled: false), and collects problems in errors so one bad entry can't drop the rest.

2. No extension ever started

pi's app layer calls session.bindExtensions() after creating a session — that call is what emits session_start. Without it, any extension that registers work at session start silently does nothing (MCP connecting is one). Called here with mode: "print" (headless: hasUI: false, so terminal-only paths are skipped) and an error logger.

Wiring mirrors pi's own app: the factory is registered as a built-in ({name, factory, replaceable, builtin}) and activated via additionalExtensionPaths: ["builtin:mcp"].

Verification

With a real MCP server declared (https://mcp.specification.website/mcp, exposure: direct), the session's active tool list came back as:

read, bash, edit, write, remember, mcp__website_spec__search,
mcp__website_spec__list_topics, mcp__website_spec__get_topic,
mcp__website_spec__get_checklist, mcp__website_spec__get_categories,
mcp__website_spec__get_changes
  • 7 new tests for the loader (missing file, HTTP, stdio, disabled entry, broken entry alongside a good one, invalid JSON, non-string args/env)
  • bun test: 113 pass, 0 fail
  • tsc --noEmit: clean

Note for review

The bindExtensions call is a behavior change beyond MCP — it starts the extension lifecycle this harness had been skipping. Worth a look on its own merits; nothing in the existing tests regressed, and the memory extension's remember tool still registers (it does so at load time, not session start).

MCP was configured but dead: pi 1.x loads the MCP extension from the app
layer, and this harness did neither half of what that needs.

1. **Nothing read the config.** The extension context has no `agentDir`,
   so pi's default loader resolves `mcp.json` against `~/.pi/agent` and
   never saw this bot's file. `src/mcp/loadAgentMcpConfig.ts` reads
   `<agentDir>/mcp.json` synchronously (pi's `loadConfig` is sync), builds
   typed stdio/HTTP configs, keeps disabled entries listed, and collects
   problems in `errors` so one bad entry can't drop the rest.

2. **No extension ever started.** pi's app layer calls
   `session.bindExtensions()` after creating a session; that is what emits
   `session_start`. Without it, extensions that register work at session
   start (MCP connecting is one) silently do nothing. Called with
   `mode: "print"` (headless — `hasUI: false`) and an error logger.

Wiring mirrors pi's own app: the factory is registered as a built-in and
activated through `additionalExtensionPaths: ["builtin:mcp"]`.

Verified end to end: with a spec MCP server declared, the session's active
tools include mcp__website_spec__{search,list_topics,get_topic,
get_checklist,get_categories,get_changes}. 7 new tests cover the loader;
full suite 113 pass, tsc clean.
…Access

The test file indexed servers[0] and destructured a possibly-empty array, so
`bun run typecheck` failed on six TS18048/TS2532 errors and CI has been red on
this branch since it was opened. Narrow through an onlyServer() helper that
throws instead of asserting.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant