Skip to content

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 mcporter
bash
mcporter --version
mcporter list --json

mcporter 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-server

After 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 daemon

Then:

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: 20

Through 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 registry

The 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 --version fails, every mcp.* tool will be UnknownToolError until 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 PATH in ~/.zen/.env or symlink mcporter into /usr/local/bin.
  • Server status matters at every boot. If an MCP server crashes between Z.E.N. restarts, mcporter list will 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 notion doesn't get you Slack; that's a separate command.
  • Tool ids include the server name. mcp.notion.search and mcp.slack.search are distinct entries even when both servers expose a search tool — the connector id segment disambiguates.

Skills + docs

AI that follows a recipe, not a conversation.