Code Mode MCP

Code Mode MCP

Composes arbitrary MCP tools using JavaScript, enabling discovery, composition, and execution of other MCP servers through a single 'exec' tool.

Category
Visit Server

README

Code Mode MCP

Compose arbitrary MCP tools with JavaScript through one agent-agnostic stdio MCP server.

The server exposes one tool, exec. Upstream schemas stay out of the model's initial context: JavaScript finds relevant tools with ranked search(), inspects exact schemas with describe(), and invokes normalized functions on tools.

Independent and experimental. This is not an OpenAI or Pi product. The Code Mode API may change before version 1.0.

Upgrading from pi-code-mode-mcp? See MIGRATION.md.

What it does

MCP client (Pi, Claude, Codex, or another host)
  └─ exec({ code })
      └─ standalone code-mode-mcp process
          ├─ tools.mcp__github__search_issues(...)
          ├─ tools.mcp__computer_use__get_app_state(...)
          └─ Promise.all(...)
  • one model-facing MCP tool instead of every upstream schema;
  • stdio, Streamable HTTP, and legacy SSE upstream transports;
  • JavaScript loops, branching, parallel calls, transformation, and filtering;
  • in-code discovery and exact JSON Schema inspection;
  • text, image, audio, resource, structured-content, error, and metadata forwarding;
  • nested cancellation, progress, elicitation, sampling, roots, logging, and tools/list_changed handling;
  • bearer auth, OAuth client credentials, and interactive authorization-code OAuth;
  • explicit, JSON-only, in-memory session state;
  • no automatic persistence of tool results, screenshots, logs, or intermediate values.

Normal client tools remain available directly. Code Mode composes the MCP servers configured behind it; it does not replace the host's direct tools or convert host-native tools into nested MCP functions.

Requirements

  • Node.js 22 or newer
  • an MCP client that can launch a stdio server

Install

Install the exact npm release globally:

npm install --global code-mode-mcp@0.2.0
code-mode-mcp --help

Or build a source checkout:

git clone https://github.com/tmustier/code-mode-mcp.git
cd code-mode-mcp
npm ci
npm run prepublishOnly

The source executable is dist/cli.js after the build.

Configure upstream MCP servers

Create ~/.config/code-mode-mcp/mcp.json:

{
  "settings": {
    "executionTimeoutMs": 120000,
    "requestTimeoutMs": 120000
  },
  "mcpServers": {
    "computer-use": {
      "command": "node",
      "args": [
        "/absolute/path/to/codex-computer-use-mcp/dist/mcp-server.js"
      ],
      "requestTimeoutMs": 180000
    },
    "remote": {
      "url": "https://example.com/mcp",
      "auth": "bearer",
      "bearerTokenEnv": "EXAMPLE_MCP_TOKEN"
    }
  }
}

Validate without starting MCP:

code-mode-mcp --check-config \
  --config ~/.config/code-mode-mcp/mcp.json

The JSON summary excludes commands, arguments, headers, tokens, and environment values.

Configuration lookup

When --config is omitted, the first existing file wins:

  1. $CODE_MODE_MCP_CONFIG
  2. ./.code-mode-mcp.json
  3. ~/.config/code-mode-mcp/mcp.json
  4. legacy ~/.config/pi-code-mode-mcp/mcp.json

PI_CODE_MODE_MCP_CONFIG and PI_CODE_MODE_MCP_HOME remain compatibility fallbacks.

The file uses the standard mcpServers object. Each server defines exactly one of:

  • command, with optional args, env, and cwd;
  • url, with optional transport, headers, and auth.

URL transport defaults to Streamable HTTP with SSE fallback. Set transport to "streamable-http" or "sse" to require one.

Strings support ${VAR} and exact $env:VAR environment expansion. Relative cwd and settings.stateDir paths resolve from the config file.

OAuth

{
  "mcpServers": {
    "linear": {
      "url": "https://mcp.example.com/mcp",
      "auth": "oauth",
      "oauth": {
        "grantType": "authorization_code",
        "scope": "read write"
      }
    }
  }
}

For authorization-code OAuth, the server opens a loopback callback and forwards the authorization URL through MCP URL elicitation. The outer client decides whether to open it. Unsupported interaction returns cancel; the server never invents accept or decline.

OAuth tokens, dynamic client registration, PKCE verifier, and discovery metadata are stored as mode-0600 files under settings.stateDir (default ~/.config/code-mode-mcp). No tool result is stored there.

Add to any MCP client

Configure the outer server in any client that can launch stdio MCP processes:

{
  "mcpServers": {
    "code-mode": {
      "command": "npx",
      "args": [
        "-y",
        "code-mode-mcp@0.2.0",
        "--config",
        "/Users/you/.config/code-mode-mcp/mcp.json"
      ]
    }
  }
}

Keep the upstream file separate. Do not configure Code Mode as its own upstream server.

Pi through pi-mcp-adapter

Pi can add lifecycle and direct-tool settings in ~/.pi/agent/mcp.json or .pi/mcp.json:

{
  "mcpServers": {
    "code-mode": {
      "command": "npx",
      "args": [
        "-y",
        "code-mode-mcp@0.2.0",
        "--config",
        "/Users/you/.config/code-mode-mcp/mcp.json"
      ],
      "lifecycle": "lazy",
      "requestTimeoutMs": 180000,
      "directTools": ["exec"]
    }
  }
}

Restart or reload Pi after changing MCP configuration. The native Computer Use Pi extension and all normal Pi tools remain active alongside Code Mode.

exec API

Input:

{
  "code": "return search('app screenshot accessibility', { limit: 5 });",
  "session_id": "optional-session",
  "timeout_ms": 120000,
  "max_output_chars": 51200
}

code is a raw JavaScript async function body, not JSON-encoded source or a markdown fence.

Discover

return search("app screenshot accessibility", { limit: 5 });

search() ranks tool names and descriptions and returns compact { name, server, tool, title?, description, score } matches. Use a short keyword query; rephrase or remove a term if it returns no result. It accepts optional { server, limit } filters; the maximum limit is 50. Inspect one exact schema:

return describe("mcp__computer_use__get_app_state");

ALL_TOOLS remains a frozen complete inventory for deterministic enumeration or custom filtering when ranked search is insufficient.

ALL_SERVERS reports connection status and bounded error messages for enabled upstreams.

Compose

const apps = await tools.mcp__computer_use__list_apps({});
const selected = ["Calculator", "TextEdit"];
const states = await Promise.all(
  selected.map(app => tools.mcp__computer_use__get_app_state({ app }))
);
return states.map((state, index) => ({
  app: selected[index],
  text: state.content.find(block => block.type === "text")?.text.slice(0, 500)
}));

Use call(name, args) when a name is selected dynamically.

Return rich output

Returning a complete MCP CallToolResult preserves its blocks and fields:

return await tools.mcp__computer_use__get_app_state({ app: "Calculator" });

Select output explicitly when intermediate results are large:

const result = await tools.mcp__computer_use__get_app_state({ app: "Calculator" });
text("Current Calculator state");
image(result.content.find(block => block.type === "image"), "original");

Helpers:

  • text(value) emits a text block;
  • image(dataUrlOrMcpImage, detail?) emits an image;
  • emit(contentBlock) emits any valid MCP content block;
  • console.log() and related methods are captured and returned, not written to MCP stdout.

Returned text is bounded in memory. The server never spills full output to disk. Filter and aggregate inside the code cell for the best context efficiency.

Session state

store("cursor", { page: 2 });
return load("cursor");

store, load, and clearStore use explicit JSON-only, process-memory state. It disappears when the Code Mode server exits. The default session_id is "default".

Host authority and fault containment

Generated code intentionally has the same authority as this Node process. It can use process, require(), dynamic import(), fetch(), filesystem, network, environment, and child-process APIs. node:vm supplies a fresh context, captured console, tracked standard timers, and synchronous timeout interruption; it is not a security sandbox.

The standalone stdio process is the fault boundary. A synchronous tight loop is interrupted by node:vm. A loop that wedges the process after an asynchronous continuation may require the outer MCP client to terminate and restart the stdio server. This is why Code Mode is separate from Pi rather than an in-process extension.

See ARCHITECTURE.md, SECURITY.md, and ADR 0001.

Development

npm ci
npm run check
npm test
npm run prepublishOnly
npm pack --dry-run

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured