Use pz with an AI agent
pz mcp serves the current project to any Model Context Protocol
client, such as Claude Code, VS Code, GitHub Copilot CLI, or opencode, as a set of typed tools:
introspect the project, run pz validate/pz compile/pz plan as a fix loop, author
connections.yml/pipelines/*.sql with self-verifying edits, and, only if you opt in, actually
run the project. pz never calls an LLM itself; the agent lives entirely on the other side of the
protocol. Read this guide to connect a client. The full envelope and tool table live in the
MCP contract reference.
Prerequisites
Section titled “Prerequisites”- A
pzproject. Follow the quickstart if you don’t have one yet. - One of the four supported clients, or any MCP client that can launch a local stdio server.
-
Wire up one or more clients in one command, from the project directory:
Terminal window pz mcp init claude-codepz mcp init vscode claude-code copilot-cli opencode # several at oncepz mcp init --all # all fourThis is merge-preserving: existing config files keep every other key and every other server entry, and only the
pzentry is written or updated. Re-running is idempotent.For each client,
pz mcp initalso installs the embeddedpz-pipelinesskill, aSKILL.mdplus an authoring guide, into the locations that client’s ecosystem looks for skills in. Pass--skill-locationsto override which locations get installed; see the CLI reference for the full token list. -
Decide whether the agent may run the project. Without
--allow-run, the server exposes only introspection, verification, and authoring tools. It can read your project, validate its own edits, and iterate onconnections.yml/pipeline SQL, but it cannot move data, hit a real database, or advance a watermark. The three execution tools are absent from the tool listing entirely when the flag is off, not present-but-refusing, so a connected agent never plans around a capability it doesn’t have.Add
--allow-runonly when you want the agent to run the project itself:Terminal window pz mcp --allow-run # direct invocationpz mcp init claude-code --allow-run # baked into the generated client configThat’s a server-start flag, decided by whoever launches
pz mcp, not something a model can toggle from inside a conversation. A gated run reports once, when it finishes, with the full node-by-node summary; its events do not stream to the client as progress notifications in this version. Watch a long run live with the CLI’s own output or the NDJSON event stream instead. -
If your client isn’t one of the four, wire it up by hand. Every client needs the same two things: a command to launch (
pz mcp, optionally with--allow-run) and a working directory at the project root.Client Config file Top-level key vscode<project>/.vscode/mcp.jsonservers.pzclaude-code<project>/.mcp.jsonmcpServers.pzcopilot-cli~/.copilot/mcp-config.jsonmcpServers.pzopencode<project>/opencode.jsonmcp.pzFor a generic client:
command: pz,args: [mcp](add--allow-runif the client supports execution tools), andcwdset to the project root. A client that can’t setcwdcan pass the directory explicitly instead:args: [mcp, --project, /path/to/project].
Verify
Section titled “Verify”Ask the connected client to call pz_project_overview. A working connection returns the
project’s name, flows, connections, and pipelines; a failed one means the client couldn’t launch
pz mcp or reach it over stdio, usually a wrong command path or working directory.
Concurrency
Section titled “Concurrency”The server takes no long-lived project lock. Mutation tools are atomic per call, writing to a
temp file and renaming over the original, but there is no cross-call transaction, and a gated run
takes the same run lock a CLI-invoked pz run does. Two agents (or an agent and a human) pointed
at one project behave like two humans with two terminals: last write wins on files, and a run
racing a concurrent run excludes the loser rather than corrupting shared state. Running two agents
against the same project concurrently and expecting them to merge cleanly is not supported.
Secrets
Section titled “Secrets”The MCP surface extends the project’s existing secret-hygiene rule to authoring. Connection
config values never leave the server: pz_project_overview returns connection names and
connector types only, never a config value. The mutation tools that write connection config
require any option whose key name contains password, secret, token, key, or
connection_string to be a ${VAR} reference, the whole value and nothing else. A literal value
in that shape is refused before any file is written.
A newly exported environment variable does not reach a running server: pz mcp resolves ${VAR}
against the environment it was launched in, inherited from the client at launch. Set the variable
where the client will pick it up, then restart the server. See
Secure connection config for getting a secret into that
environment in the first place.
Paths stay inside the project
Section titled “Paths stay inside the project”Under pz mcp, a localfiles path:/root:/base_dir: that resolves outside the project
directory, ../ traversal or an absolute path elsewhere, is refused, whether it sits in existing
config or in a block an authoring tool proposes to write. The plain pz CLI is unchanged: a
project that legitimately reads outside its own directory still runs from the terminal, it just
isn’t drivable through an agent.
Troubleshooting
Section titled “Troubleshooting”| If you see | Do |
|---|---|
PZ0605 from pz mcp init |
No client was named and no --all was passed, an existing config file failed to parse as JSON even tolerantly, or --skill-locations named an unrecognized token. The message names which. |
PZ0611 from pz mcp init |
An existing client config file legally carries comments or trailing commas (JSONC) that merging in the pz entry would silently delete, so pz refused to rewrite it. Paste in the entry the error message gives you by hand instead. |
PZ0601 from a mutation tool |
The proposed connection config carries a credential-shaped value that isn’t a ${VAR} reference. Move it into the environment and reference it with ${VAR} instead. |
PZ0103 after exporting a new secret |
The running server never saw it. Set the variable where the client launches pz mcp from, then restart the server. |
PZ0604 on a run tool |
Another run already holds the project’s run lock, from the CLI or another MCP call. Wait for it to finish. |
PZ0606 from a mutation tool |
A localfiles path resolves outside the project directory. Point it back inside the project, or make the edit from the CLI instead. |
Related
Section titled “Related”- MCP contract reference: the full result envelope, every tool’s inputs and results, and the PZ06xx error codes.
- Secure connection config: getting a secret into the environment the MCP server reads.
- CLI reference: every
pz mcpandpz mcp initflag. - Author a connector: what an agent using the authoring tools is ultimately editing.