@ohmymcp/pi-directx

The MCP-Direct bridge for Pi: turn any MCP server into native Pi tools — createMCPBridge + registerToolsFromMCP + jsonSchemaToTypeBox + sanitizeParams. Reuse when building any Pi MCP-direct extension.

Packages

Package details

extension

Install @ohmymcp/pi-directx from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@ohmymcp/pi-directx
Package
@ohmymcp/pi-directx
Version
0.1.0
Published
Aug 5, 2026
Downloads
144/mo · 21/wk
Author
ev3lynx
License
unknown
Types
extension
Size
27.5 KB
Dependencies
1 dependency · 0 peers

Security note

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

README

@ohmymcp/pi-directx

The MCP-Direct bridge for Pi — turn any MCP server into native Pi tools. One shared module for building MCP-direct extensions: no pi-mcp-adapter, no duplicated glue.

pi-directx materializes the proven MCP-Direct pattern (spawn server → JSON-RPC 2.0 stdio handshake → tools/listregisterTool each tool) into a small, typed, reusable library. It was extracted from ~1,250 lines of near-identical code that lived inline in 5 Pi extensions (devctx, everything, exa, firecrawl-mcp, sequential-thinking) — they now all ride on this module.

Install

npm install @ohmymcp/pi-directx
# or as a Pi package source:
pi install npm:@ohmymcp/pi-directx@0.1.0

Usage — a full MCP-direct extension in ~25 lines

// extensions/my-server.ts
import { createMCPBridge, registerToolsFromMCP } from '@ohmymcp/pi-directx';

export default function (pi: any) {
  const bridge = createMCPBridge('my-mcp-server', {
    env: { ...process.env },
    onLog: (l) => pi.logger?.info(`[MyServer] ${l}`),
    onError: (e) => pi.logger?.error(`[MyServer] ${e}`),
  });

  registerToolsFromMCP(pi, {
    bridge,
    label: 'MyServer',
    prefix: 'myserver_',                                   // optional tool-name prefix
    steeringTools: ['myserver_orient', 'myserver_connect'], // attach promptGuidelines
    guidelines: ['Session start: use these tools first.'],
  });

  pi.on('session_shutdown', () => bridge.close());
}

API

Export Signature What it does
createMCPBridge (cmd: string, opts?: MCPBridgeOptions) => MCPBridge Spawns the server; owns JSON-RPC 2.0 request routing (requestId, 30s timeout, exit cleanup). bridge.call(method, params) sends a request and resolves the result.
registerToolsFromMCP (pi: any, opts: RegisterToolsOptions) => Promise<{initialized, tools}> initializetools/listregisterTool for every discovered tool. Encapsulates schema conversion, param sanitization, promptSnippet (REQUIRED for tool visibility in Pi) and optional steering.
jsonSchemaToTypeBox (jsonSchema: any) => TSchema Converts MCP JSON Schema → Pi's TypeBox schema (enums, optionals, nested objects).
sanitizeParams (params: any, jsonSchema: any) => any Reconciles string-typed LLM params against the schema (string→boolean/number) before forwarding.

createMCPBridge options

interface MCPBridgeOptions {
  args?: string[];              // e.g. ['-y', '@scope/server']
  env?: typeof process.env;
  cwd?: string;
  timeoutMs?: number;           // default 30000
  onLog?: (line: string) => void;    // non-JSON stdout + stderr
  onError?: (message: string) => void;
  onExit?: (code: number | null) => void;
}

registerToolsFromMCP options

interface RegisterToolsOptions {
  bridge: MCPBridge;
  label?: string;               // UI label prefix, e.g. 'Devctx'
  prefix?: string;              // tool-name prefix, e.g. 'everything_'
  clientName?: string;          // clientInfo.name for initialize
  clientVersion?: string;
  protocolVersion?: string;     // default '2024-11-05'
  steeringTools?: string[];     // tools that get promptGuidelines
  guidelines?: string[];        // steering bullets
  onRegistered?: (toolName: string) => void;
}

Why the key contracts matter

  • promptSnippet is REQUIRED — Pi omits custom tools from the "Available tools" system-prompt section without it; the agent would never learn the tools exist. registerToolsFromMCP attaches it automatically.
  • promptGuidelines steering — attach guidance to session-start tools only, so it appears once instead of N× duplicating in the system prompt.
  • sanitizeParams — LLMs pass booleans/numbers as strings; reconcile against the JSON schema before the server sees them.
  • 30s timeout — a hung server rejects + cleans up pending requests instead of leaking.

Development

npm install
npm run build      # tsc → dist/ (mcp-direct.js + .d.ts)
npm run smoke      # spawns devctx-mcp, asserts 30 tools / snippets / steering / live call

License

MIT