AI agents & the MCP server

The daemon knows what’s actually running: which processes and Docker containers advertised PZ_TUNNEL, their ports, the tunnel domains and health paths, who-talks-to-whom between tunnels, and which HTTP routes were exercised. Port Zero exposes this observed runtime truth two ways:

  • portzero inspect — for humans: readable text, no JSON.
  • portzero mcp — for AI coding agents: a Model Context Protocol server (JSON-RPC 2.0 over stdio).

Both read the same daemon state, fresh on each call.

portzero agents setup

The fastest path for any of the coding agents below: run one command instead of hand-copying JSON into a config file.

$ portzero agents setup

It detects which of Claude Code, Codex, pi.dev, opencode, and Grok Build are installed, then for each one it finds:

  • registers the portzero mcp server (via the agent’s own mcp add command where one exists — Claude Code, Codex — or a safe read-modify-write of its config file otherwise, preserving any other servers already configured), and
  • writes a short marker-delimited block into that agent’s user-level instructions file (~/.claude/CLAUDE.md, ~/.config/opencode/AGENTS.md, ~/.grok/AGENTS.md) explaining the MCP tools below, so the agent knows to reach for them.

Safe to re-run any time — already-configured agents are left alone, and content outside the marker block in an instructions file is never touched. Codex and pi.dev currently have no confirmed user-level instructions file, so only their MCP registration step runs. Use --dry-run to preview changes without writing anything.

portzero inspect

$ portzero inspect
portzero inspect — observed runtime truth
Daemon: running

TUNNELS
  api--alice.tunnel.portzero.cloud
      url:    https://api--alice.tunnel.portzero.cloud
      health: /health
      source: container myapp-api-1 (abc123def456)
  web.portzero.local
      url:    http://web.portzero.local
      health: /healthz
      source: process pid 456 (/work/web)

OBSERVED EDGES (who-talks-to-whom)
  web--alice.tunnel.portzero.cloud -> api--alice.tunnel.portzero.cloud  [http, 12 req]

EXERCISED ROUTES (smoke-test inventory)
  api--alice.tunnel.portzero.cloud
      GET    /health  x30
      POST   /users   x3  (tests: signup flow)

For a machine-readable view, use the MCP server.

The MCP server (portzero mcp)

portzero mcp speaks the MCP stdio transport: newline-delimited JSON-RPC 2.0 on stdin/stdout. An agent launches it as a subprocess. portzero agents setup (above) registers it automatically for supported agents; for anything else, or to see what it writes, register it by hand, for example in a Claude Code mcpServers config:

{
  "mcpServers": {
    "portzero": {
      "command": "portzero",
      "args": ["mcp"]
    }
  }
}

Tools

Every tool returns a JSON text block. The daemon-state tools take no arguments; the two cloud-backed feedback tools take typed arguments, passed the standard MCP way as the arguments object inside tools/call params.

ToolArgumentsReturns
overviewnoneEverything at once: services, tunnels, observed edges, exercised routes, and the observability caveat.
list_servicesnoneDiscovered processes/containers with PZ_TUNNEL: domain, port, source (process pid + cwd, or container id/name), health path.
list_tunnelsnoneTunnel domains (Local + Cloud), resolved URLs, health paths, and cloud review status.
observed_edgesnonefrom → to dependency edges between tunnels (protocol, request count, last seen).
exercised_routesnoneHTTP routes hit per tunnel (method, path, count) — a smoke-test inventory.
list_feedbackstatus?Feedback threads from portzero.cloud: reviewer comments pinned on your tunneled app. Requires portzero login.
propose_fixthread_id, fix_commit, fix_summary, and optional cost args (agent?, model?, tokens_in?, tokens_out?, cost_usd?, session_id?)Marks a feedback thread as fixed by a commit. The optional cost args attach what the fix cost, so per-comment cost accrues. Requires portzero login.
cost_of_commitshaAttributed agent cost of one commit, with provenance + confidence. Consent-gated.
cost_of_prnumberAggregate agent cost of a PR (sum over its commits), with provenance. Consent-gated.
cost_of_linesfile, start, endCost of a line range: blames locally to a set of commits, then resolves their cost. Consent-gated.
submit_bug_reporttitle, body, context?Reports a bug in Port Zero itself (not the user’s app) to the Port Zero team. Requires portzero login.
submit_feature_requesttitle, body, context?Requests a Port Zero feature on the user’s behalf. Requires portzero login.

list_feedback and propose_fix are the same Review records workflow available via the CLI; without stored credentials they return an isError: true result with a “Not logged in” message.

submit_bug_report and submit_feature_request send product feedback straight to the Port Zero team. They deliberately differ in how freely an agent should reach for them:

  • Bug reports have no gate — if the portzero CLI, daemon, tunnels, the dashboard, or the cloud API misbehaves, file one with reproduction steps.
  • Feature requests carry a high bar: an agent should submit one only when the missing feature would make things much easier for the user, and only after asking the user and getting explicit confirmation — never on its own initiative.

Both require portzero login and return the same “Not logged in” isError result otherwise.

Measuring agent cost

Port Zero measures what the agent labor costs, not just what it produced. Cost attaches to the review loop you already run: per comment, per commit, per PR, and per line. The three cost_of_* tools above read it; propose_fix’s optional cost args and the session-end hook below record it.

The session-end cost hook

portzero agents installs a session-end hook in each supported coding agent. When an agent session ends, the hook reads the session’s usage, attributes it to the commits made in that window (git HEAD/reflog), and — on a consented repo — records it. The hook uploads usage metadata only: agent, model, token counts, dollar cost. It never sends your prompts, your code, or any session content.

What you grant, per repo, is a training-data licence: permission for Port Zero to use that repo’s review history — diffs, comments, fix commits, verdicts — plus cost/usage metadata in its training corpus. Sessions are never included, on any plan.

That licence is what pays for the features offered on a data-for-access basis, and granting it is what turns them on for the repo:

  • Cost tracking — on free and paid plans alike.
  • The review link — PR replies flowing back into a comment thread, and the commits referencing a thread shown with the lines they changed. Included outright on Team and Enterprise, which do not license their data for training at all.

The licence is the thing you are agreeing to; those features are what it buys. The dashboard shows the exact Terms version at the moment you grant it, and records that version with your consent.

  • Default off, per repo. Set it in app.portzero.net on the repo’s configuration page. It works for a free personal account on a repo with no GitHub App, not just teams.
  • Not consented? Nothing is stored — no history, no aggregates. The only thing you see is an ephemeral end-of-session teaser: the hook prints that session’s cost once and persists nothing, and the cost_of_* tools return a consent_required result pointing at the dashboard toggle.
  • Turn it off any time. Cost tracking turns off with it. Revoking stops future capture and removes the repo from the corpus (it cannot untrain models already trained).

Who sees what

Cost visibility is per repo, set alongside consent:

  • Private (default). Each contributor sees only their own cost. Team owners and admins always see everyone’s.
  • Team. Any team member sees per-person breakdowns.
  • The PR line is separate. A post_to_pr switch — independent of visibility — posts one line to the PR showing only the aggregate total across all contributors, never a per-person breakdown. It can be on even while cost stays private.

Every number carries its provenancemeasured, reported, or inferred — and unattributed cost is shown as unknown, never $0.

Privacy

Hooks upload usage metadata only: never your prompts, your code, or any session content. Session data is excluded from training regardless of consent. See Terms and Privacy for the training-data grant in full.

Extraction skill for AI agents

portzero skill install drops a PaaS-agnostic extraction skill into your project (default .claude/skills/, or --print / --dir for other agent tools). It teaches an AI coding agent to consume the MCP tools above (plus your compose file) and extract everything needed to configure production hosting on any platform — which containers are public vs. internal, ports, health paths, service dependencies, and a smoke-test route list. The skill extracts and interprets only; it contains no platform-specific templates.

Observability caveat

Only traffic addressed via tunnel names is observed. Container-to-container traffic over compose-internal DNS — e.g. one compose service reaching another as http://db:5432 on the shared compose network — never passes through the daemon and does not appear in observed edges or exercised routes. Treat the edge/route data as a lower bound on real dependencies: everything shown is real, but internal service-to-service calls that never used a tunnel name are invisible. When extracting a production topology, combine this with your compose file, which shows the internal wiring.

One-shot prompt for a repo

Paste this into Claude Code, Cursor, or any agent working in your repo:

Install Port Zero (https://portzero.net/install.sh) and set PZ_TUNNEL so this
project's dev server gets a stable web.<project>.portzero.local URL. Docs:
https://portzero.net/llms.txt

See /llms.txt for the condensed reference agents should read first.