MCP Server
Connect your agent to any Model Context Protocol server — Notion, Linear, Sentry, GitHub's MCP, your own self-hosted server — and give the LLM the server's tools. The Pai sidecar injects the bearer token on outbound HTTPS; the agent never holds the real credential.
Get credentials
Get a bearer token or API key from the MCP server vendor:
- Hosted MCP servers (Notion, Linear, Sentry, etc.) — follow the vendor's instructions. Typically a developer console lets you create an API key.
- Self-hosted / stdio servers (the official MCP reference servers, in-house servers) — often unauthenticated. You can skip this step if the server doesn't require a token.
Setup
Store the token (if any), then create a Provider. Two transport modes:
SSE (hosted servers)
Most hosted MCP servers use SSE over HTTPS:
# 1. Store the bearer token in a Pai secret
pai add secret linear-mcp-token --from-literal token=lin_api_YOUR_TOKEN
# 2. Create the Provider
pai apply -f - <<EOF
apiVersion: pai.io/v1
kind: Provider
metadata:
name: linear
spec:
type: mcp
mcp:
url: https://mcp.linear.app/sse
transport: sse
auth:
type: api-key
secretRef: linear-mcp-token
policy:
mcp:
allowedTools: [list_issues, create_issue, search_issues]
deniedTools: [delete_issue]
EOF
stdio (self-hosted subprocess)
For MCP servers that run as a subprocess (e.g. the official reference servers):
apiVersion: pai.io/v1
kind: Provider
metadata:
name: filesystem
spec:
type: mcp
mcp:
transport: stdio
command: ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/workspace"]
# no auth: stdio servers typically don't need one
Include the server binary in the Agent's packages so it's installed before the harness starts:
spec:
packages:
npm: ["@modelcontextprotocol/server-filesystem"]
Config fields
| Field | Description |
|---|---|
mcp.transport | sse (default) or stdio |
mcp.url | SSE endpoint URL (required for transport: sse) |
mcp.command | Command + args to launch the server (required for transport: stdio) |
auth.secretRef | Pai secret containing the bearer token. Optional for stdio; required for authenticated SSE servers |
policy.mcp.allowedTools | Tool names the agent may call. Empty = all permitted |
policy.mcp.deniedTools | Tool names blocked. Evaluated before allowedTools |
Attach to an agent
spec:
providers:
- linear
What happens next depends on the agent mode:
-
Harness-backed agents (task / template) — Pai's harness includes a built-in MCP client. At startup it calls
tools/liston the server, applies theallowedTools/deniedToolsfilter, and registers each tool with the LLM aslinear__<tool_name>. The agent can invoke them directly. -
Service agents (
spec.type: service) — your runtime (OpenClaw, LangChain, a hand-rolled loop) is its own MCP client. Pai handles auth and policy; you still need to tell your runtime to connect to the upstream URL. Typical setup:spec:
type: service
image: ghcr.io/myorg/my-agent:latest
providers: [linear] # Pai: sidecar interception + policy
configFiles:
- path: /home/node/.openclaw/openclaw.json
content: |
{
"mcpServers": [
{"name": "linear", "url": "https://mcp.linear.app/sse"}
]
}The runtime's config format (
.mcp.json,openclaw.json, etc.) is opaque to Pai. Only the outbound HTTPS request matters — the sidecar intercepts, injects the token, and enforces the tool policy.
Access control
policy.mcp.allowedTools / deniedTools gate which tools the agent can call — Pai filters the server's tool catalogue at registration time (harness agents) or at tools/call time (both modes). Combine with audit.enforcement: audit to validate a tool allowlist against live traffic before flipping it to enforce. See the Policy reference for the full field list.
Related
- MCP Gateway — expose an in-cluster MCP Provider to tools running on developer laptops (Claude Code, Cline, etc.).
- Agent → Providers — attaching providers to agents and narrowing per-agent.