Appearance
mcporter
mcporter is the registry + broker layer that makes any MCP server accessible to Z.E.N. Z.E.N. doesn't speak MCP directly; mcporter does. Every MCP server you register with mcporter shows up as a Z.E.N. connector at mcporter.<server>, and every tool that server exposes becomes a mcp.<server>.<tool> entry in the tool registry.
That means: once mcporter is wired in, adding Notion, Slack, GitHub, Postgres, your own custom MCP server, or any community MCP package is a one-line mcporter add command — no Z.E.N. config changes, no workflow rewrites.
This is the recommended path for MCP. The legacy per-node mcp: field (Claude-SDK-direct) still works but is the old way; mcporter is the registry-first path everything else flows through.
Install mcporter
bash
bun install -g mcporter
# or
npm install -g mcporterbash
mcporter --version
mcporter list --jsonmcporter list returns the registered servers + their status. Empty on first install; that's normal.
Add an MCP server
bash
mcporter add <package-or-alias>mcporter prompts for any required config (API keys, OAuth tokens, workspace ids) and persists per-server credentials. Common shapes:
bash
# Standard @modelcontextprotocol packages
mcporter add @modelcontextprotocol/server-github
mcporter add @modelcontextprotocol/server-postgres
# Community packages
mcporter add notion-mcp
mcporter add slack-mcp
# Custom local server
mcporter add ./path/to/my-mcp-serverAfter adding, verify mcporter sees it as ready:
bash
mcporter list --json | jq '.[] | {id, status, tools: .tools | length}'status: "ready" and a non-zero tools count mean mcporter started the server, ran its tools/list handshake, and is ready to broker calls.
Verify Z.E.N. picked it up
Z.E.N.'s mcporter connector adapter scans mcporter list at boot. Restart the daemon (or wait for the next workflow run if you're CLI-only):
bash
zen serve # restart your daemonThen:
bash
# Connector entry for the server you added
curl -s http://localhost:3090/api/connectors | jq '.connectors[] | select(.id == "mcporter.<server>")'
# All tools that server exposed
curl -s http://localhost:3090/api/tools | jq '.tools[] | select(.connectorId == "mcporter.<server>") | .id'Settings → Connectors shows the new connector with an mcp chip + the tool count. Settings → Tools lets you browse the individual tool ids.
Use it from a workflow
Two consumption shapes, both work:
Direct tool invocation (deterministic):
yaml
- id: search
tool: mcp.notion.search
tool_args:
query: Q3 planning
pageSize: 20Through an agent (agent picks which tools to call):
yaml
- id: research
agent:
harness: hermes/acp
prompt: |
Look through my Notion workspace for any pages mentioning Q3 planning
and summarize them in 200 words.The agent path works for any harness whose capability matrix shows tools.mcp: true (Settings → Harnesses). Hermes, Claude, and Pi all support it; the agent decides at runtime which mcporter-registered tools to call.
Discover what a tool takes
bash
mcporter inspect <server> <tool-name>Returns the tool's JSON Schema for args. Settings → Tools also shows this inline.
Remove an MCP server
bash
mcporter remove <server>
zen serve # restart so Z.E.N. drops it from the registryThe connector + all its tools disappear from /api/connectors and /api/tools after restart. Workflows that referenced the removed tools will fail at runtime with UnknownToolError.
Where credentials live
mcporter owns the credentials. Z.E.N. just reports hasAuth: true on the connector. Rotating a key is an mcporter operation:
bash
mcporter config <server>mcporter persists per-server config under its own state directory (typically ~/.mcporter/). Z.E.N. never touches these files.
Gotchas
- mcporter is a separate install. Z.E.N. doesn't bundle it. If
mcporter --versionfails, everymcp.*tool will beUnknownToolErroruntil mcporter is on PATH. - Daemon PATH stripping. Same story as gws: if the daemon's PATH doesn't reach mcporter, the connector won't register. Set
PATHin~/.zen/.envor symlink mcporter into/usr/local/bin. - Server status matters at every boot. If an MCP server crashes between Z.E.N. restarts,
mcporter listwill show it as failed and Z.E.N. will skip it. Restart the MCP server first (mcporter restart <server>), then restart Z.E.N. - Each server is its own connector.
mcporter add notiondoesn't get you Slack; that's a separate command. - Tool ids include the server name.
mcp.notion.searchandmcp.slack.searchare distinct entries even when both servers expose asearchtool — the connector id segment disambiguates.
Skills + docs
/zen-add-mcp-serverbundled skill walks the install + verify flow when the user asks the AI to wire one up- Tools reference — the registry concept
- Connectors reference — how mcporter is itself a connector adapter
- Legacy per-node mcp: field — the older path (Claude-SDK only)
- mcporter on GitHub: https://github.com/AndrewWalter/mcporter
- MCP spec: https://modelcontextprotocol.io