@0xkobold/pi-mcp
Model Context Protocol (MCP) integration for pi-coding-agent. Connect to any MCP server (stdio, SSE, StreamableHTTP, WebSocket) and use its tools, resources, and prompts natively.
Package details
Install @0xkobold/pi-mcp from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@0xkobold/pi-mcp- Package
@0xkobold/pi-mcp- Version
0.4.0- Published
- Apr 7, 2026
- Downloads
- 353/mo ยท 150/wk
- Author
- moikapy
- License
- MIT
- Types
- extension, skill
- Size
- 170.7 KB
- Dependencies
- 1 dependency ยท 2 peers
Pi manifest JSON
{
"extensions": [
"./dist/index.js"
],
"skills": [
"./skills/mcp/SKILL.md"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
@0xkobold/pi-mcp
Model Context Protocol (MCP) integration for pi-coding-agent
Connect to any MCP server and use its tools, resources, and prompts natively within your pi agent.
Features
- ๐ Four Transport Types - stdio, SSE, StreamableHTTP, and WebSocket
- ๐ง Auto Tool Registration - MCP tools appear as native pi tools (with progressive dispatch for 50+ tool servers)
- ๐ Tool Filtering - Allowlist/denylist to control which tools are registered
- ๐ฆ Resource Access - Read MCP server resources directly (with TTL caching)
- ๐ฌ Prompt Templates - Use MCP prompt templates
- ๐ฑ Roots Support - Servers can discover workspace roots
- ๐ Auto-Reconnect - Reconnects on disconnect with exponential backoff
- ๐ Env Interpolation -
${VAR}in config resolved from environment - ๐ฅ Claude Desktop Import - Import servers from
~/.claude/mcp.json - ๐ Health Monitoring - Uptime, call counts, error tracking in
/mcp status - ๐งช Sampling Support - Handle MCP
sampling/createMessagerequests via configurable callback - ๐๏ธ Multi-Project Config -
.0xkobold/mcp.jsonmerges with global config - โ๏ธ Hot Config - Add/remove servers without restart (commands)
Quick Start
1. Configure servers
Edit ~/.0xkobold/mcp.json:
{
"servers": [
{
"name": "filesystem",
"transport": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"]
},
"enabled": true,
"autoReconnect": true
}
],
"importClaudeDesktop": true
}
2. Or use commands
/mcp add filesystem npx -y @modelcontextprotocol/server-filesystem /home/user
/mcp enable filesystem
/mcp connect filesystem
3. Use tools
The agent will automatically discover and use MCP tools. You can also:
/mcp list # See all configured servers
/mcp status # See active connections
/mcp discover # Find available tools
Commands
| Command | Description |
|---|---|
/mcp |
Show help |
/mcp list |
List all configured servers |
/mcp connect <name> |
Connect to a server |
/mcp disconnect <name> |
Disconnect from a server |
/mcp enable <name> |
Enable auto-connect for a server |
/mcp disable <name> |
Disable auto-connect for a server |
/mcp add <name> <cmd> [args] |
Add a stdio server |
/mcp add-http <name> <url> |
Add an HTTP server |
/mcp add-ws <name> <url> |
Add a WebSocket server |
/mcp filter <name> allow <tools> |
Only register listed tools for server |
/mcp filter <name> deny <tools> |
Register all except listed tools |
/mcp filter <name> clear |
Remove tool filters for server |
/mcp remove <name> |
Remove a server from config |
/mcp refresh <name> |
Re-discover tools/resources/prompts |
/mcp import |
Import servers from Claude Desktop config |
/mcp status |
Show active connections |
Tools
| Tool | Description |
|---|---|
mcp_discover |
List available MCP tools, resources, and prompts |
mcp_call_tool |
Call any MCP tool by server + tool name |
mcp_<server>_<tool> |
Individual tools (auto-registered per server) |
mcp_<server>_read_resource |
Read a resource from an MCP server |
mcp_<server>_get_prompt |
Get a prompt from an MCP server |
Transport Types
stdio
Spawns a local process and communicates via stdin/stdout:
{
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"],
"env": { "API_KEY": "..." },
"cwd": "/working/dir"
}
StreamableHTTP
Modern HTTP transport (recommended for remote servers):
{
"type": "streamable-http",
"url": "https://example.com/mcp",
"headers": { "Authorization": "Bearer ..." }
}
SSE (legacy)
Server-Sent Events transport:
{
"type": "sse",
"url": "https://example.com/sse"
}
WebSocket
Real-time bidirectional transport:
{
"type": "websocket",
"url": "ws://localhost:8080/mcp"
}
Tool Filtering
Control which tools are registered per server using allowlist or denylist:
// Only register specific tools (allowlist)
{
"name": "filesystem",
"allowedTools": ["read_file", "list_directory"],
...
}
// Register all except (denylist)
{
"name": "github",
"deniedTools": ["delete_repository", "create_issue"],
...
}
Or via commands:
/mcp filter github allow search_repositories,get_file_contents
/mcp filter filesystem deny write_file,delete_file
/mcp filter github clear
Environment Variable Interpolation
Use ${ENV_VAR} patterns in config values to avoid hardcoding secrets:
{
"name": "github",
"transport": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
HTTP headers also support interpolation:
{
"transport": {
"type": "streamable-http",
"url": "https://api.example.com/mcp",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
}
As a Library
You can use @0xkobold/pi-mcp as a standalone library, without pi-coding-agent:
// Main entry โ extension + all re-exports
import mcpExtension, {
MCPConnectionManager,
ResourceCache,
interpolateEnv,
loadConfig,
saveConfig,
createDefaultConfig,
isToolAllowed,
} from "@0xkobold/pi-mcp";
// Client subpath โ connection management only
import { MCPConnectionManager, type MCPServerConfig } from "@0xkobold/pi-mcp/client";
// Config subpath โ config loading/saving only
import { loadConfig, upsertServer, type MCPConfig } from "@0xkobold/pi-mcp/config";
// Tools subpath โ tool registration utilities only
import { isToolAllowed, DEFAULT_MAX_TOOLS } from "@0xkobold/pi-mcp/tools";
Quick start without pi-coding-agent:
import { MCPConnectionManager } from "@0xkobold/pi-mcp/client";
const manager = new MCPConnectionManager([process.cwd()]);
const serverConfig = {
name: "filesystem",
transport: { type: "stdio", command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] },
enabled: true,
autoReconnect: true,
};
const info = await manager.connect(serverConfig);
console.log(`Connected: ${info.tools.length} tools`);
const result = await manager.callTool("filesystem", "read_file", { path: "/tmp/hello.txt" });
console.log(result);
Architecture
src/
โโโ index.ts # Extension entry point (commands, tools, lifecycle)
โโโ client/
โ โโโ index.ts # MCPConnectionManager, ResourceCache, env interpolation
โโโ config/
โ โโโ index.ts # Config loading/saving, Claude Desktop import, project merge
โโโ tools/
โโโ index.ts # Tool bridge - MCP tools โ pi tools (with filtering)
Configuration
Config file: ~/.0xkobold/mcp.json
Full schema:
{
"servers": [
{
"name": "string (required)",
"transport": {
"type": "stdio | sse | streamable-http | websocket",
// stdio fields:
"command": "string",
"args": ["string"],
"env": {},
"cwd": "string",
// http/sse fields:
"url": "string",
"headers": {},
"sessionId": "string",
// websocket fields:
"url": "ws://..."
},
"enabled": false,
"autoReconnect": true,
"maxReconnectAttempts": 5,
"reconnectDelayMs": 1000,
"connectTimeoutMs": 30000,
"allowedTools": ["tool_name"],
"deniedTools": ["tool_name"],
"maxTools": 50
}
],
"importClaudeDesktop": true
}
Claude Desktop Compatibility
Set "importClaudeDesktop": true to automatically discover servers from:
~/.claude/mcp.json~/.config/claude-code/mcp.json
Or run /mcp import to manually import.
Development
# Install dependencies
bun install
# Build
bun run build
# Development watch
bun run dev
# Test
bun test # 95 tests, 182 assertions
bun test test/unit.test.ts # Unit tests only
bun test test/integration.test.ts # Integration tests (requires npx)
Sampling Support
MCP servers can request LLM sampling via sampling/createMessage. The extension registers a handler for this capability.
- Default handler: Logs the request and returns a placeholder response (pi extensions don't have direct LLM completion access)
- Custom handler: Pass a
SamplingHandlerfunction toMCPConnectionManagerconstructor:
import { MCPConnectionManager, type SamplingHandler } from "@0xkobold/pi-mcp/client";
const handler: SamplingHandler = async (params) => {
// Bridge to your LLM here
return {
role: "assistant",
content: { type: "text", text: "LLM response" },
model: "your-model",
stopReason: "endTurn",
};
};
const manager = new MCPConnectionManager(["/workspace"], 50, 300_000, handler);
License
MIT