pi-codemcp

Typed, sandboxed Code Mode access to configured MCP servers for Pi

Packages

Package details

extension

Install pi-codemcp from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-codemcp
Package
pi-codemcp
Version
2.0.1
Published
Oct 28, 2026
Downloads
353/mo · 238/wk
Author
yolonir
License
MIT
Types
extension
Size
713.7 KB
Dependencies
2 dependencies · 3 peers
Pi manifest JSON
{
  "image": "https://raw.githubusercontent.com/yolonir/pi-codemcp/main/media/preview.png",
  "extensions": [
    "./extensions/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

pi-codemcp

[!IMPORTANT] Something failed? Please open an issue.

Please do not assume your failure is too specific or not worth reporting. Platform differences, strange schemas, slow startup, confusing rendering, OAuth problems, and rough edges are exactly the reports that make this project better.

Open an issue at https://github.com/yolonir/pi-codemcp/issues, or use Extension is broken! in /codemcp → Settings to ask the agent to investigate and prepare one.

You can ask your coding agent to do the work:

Reproduce this pi-codemcp problem, redact all credentials and private data,
collect the pi-codemcp version, Pi version, OS/architecture, MCP transport,
minimal configuration shape, exact error, and relevant logs, then open a
GitHub issue at https://github.com/yolonir/pi-codemcp/issues.

If the agent cannot create the issue, ask it to prepare the title and body for you. I would much rather receive an incomplete report than have someone hit a problem, abandon the package, and never say anything. I will read the issues and work through them.

Typed, sandboxed Code Mode for your MCP servers in Pi.

The agent discovers the tools it needs, writes a Python program, and runs dependent or parallel calls across MCP servers. Intermediate data stays in the sandbox; only the program's compact return value goes back to the model.

Install

pi install npm:pi-codemcp

Reads <agent-dir>/mcp.json. Supports stdio, Streamable HTTP, SSE, bearer authentication, and FastMCP-managed OAuth.

Open /codemcp to manage servers, individual tools, profiles, saved chains, settings, and usage stats. Changes are saved immediately. Tool output expands with Pi's normal Ctrl+O.

No separate Python, uv, Bun, or just installation is needed. The package bootstraps a locked Python 3.13 runtime on first use; this needs network access unless already cached. Pi startup does not wait for MCP connections.

How it works

Discover tools → load selected contracts → execute a program → return compact data
Tool Purpose
codemcp_search Search capabilities or browse the compact catalog.
codemcp_route Optional Jev routing: select tools, roles, and composition guidance.
codemcp_inspect Load exact typed SDK contracts for selected calls.
codemcp_execute Type-check and run a sandboxed Python program.
codemcp_edit Patch the previous program and rerun it.
codemcp_save_chain Save a tested program as a reusable tool, with user approval.
codemcp_manage_chains List chains; explicitly confirm enable, disable, revalidate, or delete.

Independent calls can use asyncio.gather; dependent calls pass earlier outputs into later inputs. Filtering and aggregation happen inside the sandbox, without model round trips for every intermediate result.

Optional Jev routing

Provide TYPESAFE_API_KEY, then set Enable Jev → true in /codemcp → Settings. This replaces codemcp_search with codemcp_route as the agent's discovery tool.

  1. The agent calls codemcp_route with a short intent, such as “read staging logs to diagnose the approval error.” The extension includes the original user request and up to three preceding user/assistant messages as context. A changed subtask can be routed again with a new intent.
  2. Enabled tool names and descriptions go to Jev in parallel chunks of up to 40. Jev scores relevance to that subtask (including prerequisites), assigns workflow roles, and checks whether an intermediate model decision or user approval is needed.
  3. CodeMCP ranks and filters the answers, selects at most eight tools, derives composition guidance, and fetches their exact typed contracts.
  4. The agent writes the actual codemcp_execute program, keeping a checkpoint between stages when needed.

Jev does not execute tools or block ordinary messages. Routing sends the intent, your request, recent context, and tool descriptions to TypeSafe, so it is opt-in. Without a key, local search stays active; a failed route enables search as a fallback. The SDK also honors TYPESAFE_BASE_URL and TYPESAFE_DEFAULT_MODEL.

MCP configuration

Use an mcpServers object or a root-level server map:

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
    },
    "linear": {
      "type": "http",
      "url": "https://mcp.linear.app/mcp",
      "auth": "oauth"
    }
  }
}

Set disabled: true or enabled: false to disable a server. For stdio, only a safe base environment, comma-separated variables in MY_PI_CHILD_ENV_ALLOWLIST / MY_PI_MCP_ENV_ALLOWLIST, and explicit server env values are passed through. Remote headers can reference allowed environment variables with ${NAME}.

Press A on the Servers tab to add a server without leaving /codemcp. Search the public Agentage MCP Catalog mirror for an editable HTTP or stdio config, or paste one named server entry directly. The manager validates names and transport fields, rejects -/_ collisions, writes <agent-dir>/mcp.json atomically, and hot-reloads the running sidecar. Catalog secrets are emitted as ${NAME} environment references rather than literal values.

Settings

Edit settings in /codemcp or <agent-dir>/pi-codemcp/settings.json. Defaults: 30-second execution and tool timeouts, 50 upstream calls, 16 KiB returned data, 50 KiB rendered output, and a 24-hour catalog cache.

{
  "version": 2,
  "jevEnabled": false,
  "backgroundWarmup": true,
  "cacheTtlHours": 24,
  "executionTimeoutSeconds": 30,
  "toolTimeoutSeconds": 30,
  "maxCalls": 50,
  "resultLimitKiB": 16,
  "outputLimitKiB": 50,
  "disabledTools": {
    "linear": ["delete_issue"]
  }
}

Older settings are migrated on load, including discoveryMode → jevEnabled.

Profiles

Profile controls sit above the server list on the first /codemcp tab. Press P to open the profile picker: the active profile has a checkmark, the cursor selection is highlighted, and each profile shows its server and tool-exclusion counts. Choose + Create profile (or press N) to name a copy of the current setup, with a preview of the included servers. Press X to delete the selected profile in the picker, or the active profile from the server list, with inline confirmation. All actions stay inside the same fixed-size manager window; Escape cancels profile editing without closing it. Creating a new profile also activates it. Server and tool toggles then edit that profile automatically; other profiles and the base configuration stay unchanged.

Profiles live in <agent-dir>/pi-codemcp/settings.json, alongside a persistent activeProfile selection:

{
  "version": 2,
  "activeProfile": "research",
  "profiles": {
    "research": {
      "servers": ["linear", "filesystem"],
      "disabledTools": {"linear": ["delete_issue"]}
    },
    "observability": {
      "servers": ["grafana"],
      "disabledTools": {}
    }
  }
}

Only server names and tool exclusions are stored—connection definitions and credentials remain in mcp.json. An active profile replaces the base server enable flags and disabledTools policy: only its listed servers are enabled, including servers disabled in the base configuration. Servers added through /codemcp are included in the active profile; servers added outside the manager stay disabled until selected. Newly discovered tools are enabled unless excluded. An empty server list disables all servers.

Set activeProfile to null (the default) to use mcp.json enable flags and the base disabledTools again. Deleting the active profile also restores that base configuration, after confirmation. Unknown profile names and malformed profiles fail validation. Settings such as timeouts, Jev, and saved-chain enablement remain shared; chains cannot bypass the active profile's MCP policy. After editing profile JSON manually, reload Pi to apply server selection changes.

Saved chains

With your approval, a successfully executed program can be saved with explicit input/output JSON Schemas. One manifest exposes both:

mcp_chain_weekly_digest(...)   # native Pi tool
chains.weekly_digest(...)     # typed call inside another CodeMCP program

Chains can call MCP tools or other chains. Nested calls share time and call budgets; inputs and outputs are validated. Changed dependency contracts mark chains stale for revalidation.

  • Project: <project>/.pi/pi-codemcp/chains (activated in trusted projects).
  • Global: <agent-dir>/pi-codemcp/chains, when explicitly requested.

Project chains override same-named global chains, even when disabled. Manifests store code and schemas, not credentials or execution results. Manage them through /codemcp.

Execution and safety

FastMCP handles transports, validation, and OAuth. Pydantic Monty type-checks and executes Python without host filesystem, environment, network, or subprocess access. External access is only through the exposed MCP and saved-chain calls.

  • Use Python's collections.Counter for counts, itertools.batched for batches, base64 for encoding, and classes or dataclasses for local data processing. Import these modules normally; SDK namespaces are prebound, not importable. Generator functions (yield), gzip, asyncio.create_task, and __import__ remain unsupported.
  • Monty workers are reused for the lifetime of the sidecar, but each program gets fresh sessions; variables and inputs do not leak between executions. Saved-chain and refinement inputs use Monty's native input bindings. Workers close on sidecar shutdown, and execution-setting changes recreate the pool.
  • Type errors stop execution before any upstream call. Time, memory, call count, and output size are bounded.
  • SDK namespaces are native sandbox objects: api = linear; await api.list_issues(...) works without rewriting the program. Only enabled tool methods are exposed; validation and call limits apply equally through aliases. Direct calls and simple namespace aliases keep type stubs and chain dependencies selective. Passing a namespace into arbitrary code conservatively includes its complete interface.
  • Enabled tools retain their upstream permissions. Chains cannot bypass server or per-tool policy.
  • No automatic call retries or cross-service rollback: a later failure does not undo earlier side effects.
  • codemcp_edit reruns the whole program, including upstream calls; it is not a continuation.
  • Unscoped search returns available results plus explicit discovery_failures; server-scoped search fails if that server is unavailable.

Incomplete schemas use recursive JsonValue, not Any. Use the prebound expect_object, expect_list, expect_string, and expect_integer helpers to narrow values. inspect_json(value, samples=2, max_depth=3) returns a bounded structural summary.

Oversized results fail explicitly. If the value fits the in-memory refinement cache, the error includes a result_ref. Pass it as inputRef in a follow-up codemcp_execute to filter the retained value as input without repeating upstream calls. References expire after five minutes and are valid only in the originating sidecar.

Failures distinguish preflight, runtime, timeout, cancelled, and oversized result stages. Rendered output has a separate outputLimitKiB cap.

Development

just init           # locked dependencies and hooks
just check          # locks, lint, types, and tests
just release-check  # also verify the packed clean-install path
pi -ne -e . --no-session

Uses Bun and uv with Python 3.13. For sidecar debugging:

uv run --project sidecar --frozen -m sidecar.cli doctor --agent-dir ~/.pi/agent
uv run --project sidecar --frozen -m sidecar.cli search "linear issues"
uv run --project sidecar --frozen -m sidecar.cli execute --code-file plan.py

Conventional Commit titles drive Release Please. Feature PRs do not publish; merging the release PR triggers the verified npm release.

Release automation requires the Actions secret RELEASE_PLEASE_TOKEN: a fine-grained PAT scoped to this repository with Contents, Pull requests, and Issues read/write permissions. It lets release PR checks run automatically without the GITHUB_TOKEN approval gate; release PRs still require an explicit merge.

Credits

Inspired by Cloudflare's Code Mode. Independent implementation for Pi using FastMCP and Pydantic Monty.

MIT