pi-mcp-adapter 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.2.0] - 2026-01-19
9
+
10
+ ### Added
11
+
12
+ - **npx installer** - Run `npx pi-mcp-adapter` to install (downloads files, installs deps, configures settings.json)
13
+
8
14
  ## [1.1.0] - 2026-01-19
9
15
 
10
16
  ### Changed
package/README.md CHANGED
@@ -1,25 +1,42 @@
1
1
  # Pi MCP Adapter
2
2
 
3
- Connect [Pi](https://github.com/badlogic/pi-mono/) to any MCP server without burning your context window.
3
+ Use MCP servers with [Pi](https://github.com/badlogic/pi-mono/) without burning your context window.
4
+
5
+ https://github.com/user-attachments/assets/4b7c66ff-e27e-4639-b195-22c3db406a5a
6
+
7
+ ## Why This Exists
8
+
9
+ Mario (Pi's creator) wrote about [why you might not need MCP](https://mariozechner.at/posts/2025-11-02-what-if-you-dont-need-mcp/). The core issue: MCP servers ship dozens of tools with verbose descriptions. Playwright MCP has 21 tools eating 13.7k tokens. Chrome DevTools MCP has 26 tools eating 18k tokens. Connect a few servers and you've burned 30-50k tokens before the conversation starts. That's context bloat, slower responses, higher costs, and confused agents drowning in tool options.
10
+
11
+ His solution: skip MCP, write simple CLI tools.
12
+
13
+ But there's an active ecosystem of well-maintained MCP servers for databases, browsers, APIs, file systems, and more. This adapter lets you tap into that ecosystem without the context cost. One proxy tool (~200 tokens) instead of hundreds of individual tool definitions. The LLM discovers what it needs on-demand.
14
+
15
+ ## Install
16
+
17
+ ```bash
18
+ npx pi-mcp-adapter
19
+ ```
20
+
21
+ This downloads the extension to `~/.pi/agent/extensions/pi-mcp-adapter/`, installs dependencies, and configures Pi to load it. Restart Pi after installation.
22
+
23
+ ## Quick Start
24
+
25
+ Create `~/.pi/agent/mcp.json`:
4
26
 
5
27
  ```json
6
28
  {
7
29
  "mcpServers": {
8
30
  "chrome-devtools": {
9
31
  "command": "npx",
10
- "args": ["-y", "chrome-devtools-mcp@latest"]
32
+ "args": ["-y", "chrome-devtools-mcp@latest"],
33
+ "lifecycle": "keep-alive"
11
34
  }
12
35
  }
13
36
  }
14
37
  ```
15
38
 
16
- ## The Problem
17
-
18
- MCP servers expose tools for databases, browsers, file systems, APIs. But each tool definition costs ~200 tokens when sent to the LLM. A server with 50 tools? That's 10,000 tokens gone before you've even started. Three servers and you've lost 30K tokens to tool definitions alone.
19
-
20
- ## The Solution
21
-
22
- One proxy tool. The LLM searches for what it needs, sees the schema, and calls it:
39
+ The LLM searches for tools, sees their schemas, and calls them:
23
40
 
24
41
  ```
25
42
  mcp({ search: "screenshot" })
@@ -36,71 +53,39 @@ chrome_devtools_take_screenshot
36
53
  mcp({ tool: "chrome_devtools_take_screenshot", args: { format: "png" } })
37
54
  ```
38
55
 
39
- Two calls. ~200 tokens for the proxy tool instead of 30K+ for every tool definition.
40
-
41
- ## Install
42
-
43
- ```bash
44
- cd ~/.pi/agent/extensions
45
- npm install pi-mcp-adapter
46
- ```
47
-
48
- Or clone it:
49
-
50
- ```bash
51
- git clone https://github.com/nicobailon/pi-mcp-adapter
52
- cd pi-mcp-adapter && npm install
53
- ```
54
-
55
- Restart Pi.
56
+ Two calls instead of 26 tools cluttering the context.
56
57
 
57
58
  ## Config
58
59
 
59
- Create `~/.pi/agent/mcp.json`:
60
+ ### Server Options
60
61
 
61
62
  ```json
62
63
  {
63
64
  "mcpServers": {
64
- "chrome-devtools": {
65
+ "my-server": {
65
66
  "command": "npx",
66
- "args": ["-y", "chrome-devtools-mcp@latest"],
67
+ "args": ["-y", "some-mcp-server"],
67
68
  "lifecycle": "keep-alive"
68
69
  }
69
70
  }
70
71
  }
71
72
  ```
72
73
 
73
- For HTTP servers:
74
-
75
- ```json
76
- {
77
- "mcpServers": {
78
- "remote-api": {
79
- "url": "https://api.example.com/mcp",
80
- "auth": "bearer",
81
- "bearerTokenEnv": "API_TOKEN"
82
- }
83
- }
84
- }
85
- ```
86
-
87
- ### Options
88
-
89
74
  | Field | Description |
90
75
  |-------|-------------|
91
76
  | `command` | Executable for stdio transport |
92
77
  | `args` | Command arguments |
93
- | `env` | Environment variables (`${VAR}` interpolation supported) |
94
- | `url` | HTTP endpoint (tries StreamableHTTP, falls back to SSE) |
78
+ | `env` | Environment variables (`${VAR}` interpolation) |
79
+ | `url` | HTTP endpoint (StreamableHTTP with SSE fallback) |
95
80
  | `auth` | `"bearer"` or `"oauth"` |
96
- | `bearerToken` / `bearerTokenEnv` | Token or env var containing token |
81
+ | `bearerToken` / `bearerTokenEnv` | Token or env var |
97
82
  | `lifecycle` | `"keep-alive"` for auto-reconnect |
98
83
  | `exposeResources` | Expose MCP resources as tools (default: true) |
99
- | `debug` | Show server stderr output (default: false) |
84
+ | `debug` | Show server stderr (default: false) |
100
85
 
101
86
  ### Import Existing Configs
102
87
 
103
- Already have MCP set up in Cursor or Claude? Import it:
88
+ Already have MCP set up elsewhere? Import it:
104
89
 
105
90
  ```json
106
91
  {
@@ -113,40 +98,14 @@ Supported: `cursor`, `claude-code`, `claude-desktop`, `vscode`, `windsurf`, `cod
113
98
 
114
99
  ## Usage
115
100
 
116
- ### Search
117
-
118
- ```
119
- mcp({ search: "screenshot navigate" })
120
- ```
121
-
122
- Space-separated words are OR'd. Results include parameter schemas by default.
123
-
124
- Use `includeSchemas: false` for compact output, `regex: true` for regex matching.
125
-
126
- ### Describe
127
-
128
- ```
129
- mcp({ describe: "chrome_devtools_take_screenshot" })
130
- ```
131
-
132
- Full details for a specific tool. Mostly redundant now that search includes schemas.
101
+ | Mode | Example |
102
+ |------|---------|
103
+ | Search | `mcp({ search: "screenshot navigate" })` |
104
+ | Describe | `mcp({ describe: "tool_name" })` |
105
+ | Call | `mcp({ tool: "...", args: {...} })` |
106
+ | Status | `mcp({ })` or `mcp({ server: "name" })` |
133
107
 
134
- ### Call
135
-
136
- ```
137
- mcp({ tool: "chrome_devtools_navigate_page", args: { type: "url", url: "https://example.com" } })
138
- ```
139
-
140
- If you pass bad arguments, the error includes the expected schema.
141
-
142
- ### Status
143
-
144
- ```
145
- mcp({ })
146
- mcp({ server: "chrome-devtools" })
147
- ```
148
-
149
- See connected servers and their tools.
108
+ Search includes parameter schemas by default. Space-separated words are OR'd.
150
109
 
151
110
  ## Commands
152
111
 
@@ -154,32 +113,16 @@ See connected servers and their tools.
154
113
  |---------|--------------|
155
114
  | `/mcp` | Server status |
156
115
  | `/mcp tools` | List all tools |
157
- | `/mcp reconnect` | Reconnect all servers |
158
- | `/mcp-auth <server>` | OAuth setup instructions |
159
-
160
- ## OAuth
161
-
162
- For OAuth servers, get a token from your provider and save it:
163
-
164
- ```bash
165
- mkdir -p ~/.pi/agent/mcp-oauth/my-server
166
- cat > ~/.pi/agent/mcp-oauth/my-server/tokens.json << 'EOF'
167
- {
168
- "access_token": "your-token",
169
- "token_type": "bearer"
170
- }
171
- EOF
172
- ```
173
-
174
- Then `/mcp reconnect`.
116
+ | `/mcp reconnect` | Reconnect servers |
117
+ | `/mcp-auth <server>` | OAuth setup |
175
118
 
176
119
  ## How It Works
177
120
 
178
- See [ARCHITECTURE.md](./ARCHITECTURE.md) for the full breakdown. The short version:
121
+ See [ARCHITECTURE.md](./ARCHITECTURE.md) for details. Short version:
179
122
 
180
- - One `mcp` tool registered with Pi (~200 tokens)
123
+ - One `mcp` tool in context (~200 tokens)
181
124
  - Tool metadata stored in a map, looked up at call time
182
- - MCP server validates arguments (no schema conversion needed)
125
+ - MCP server validates arguments
183
126
  - Keep-alive servers get health checks and auto-reconnect
184
127
 
185
128
  ## Limitations
package/install.js ADDED
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const https = require("https");
6
+ const os = require("os");
7
+ const { execSync } = require("child_process");
8
+
9
+ const REPO_URL = "https://raw.githubusercontent.com/nicobailon/pi-mcp-adapter/master";
10
+ const EXT_DIR = path.join(os.homedir(), ".pi", "agent", "extensions", "pi-mcp-adapter");
11
+ const SETTINGS_FILE = path.join(os.homedir(), ".pi", "agent", "settings.json");
12
+ const EXT_PATH = "~/.pi/agent/extensions/pi-mcp-adapter/index.ts";
13
+
14
+ const FILES = [
15
+ "index.ts",
16
+ "types.ts",
17
+ "config.ts",
18
+ "server-manager.ts",
19
+ "tool-registrar.ts",
20
+ "resource-tools.ts",
21
+ "lifecycle.ts",
22
+ "oauth-handler.ts",
23
+ "package.json",
24
+ "tsconfig.json",
25
+ "README.md",
26
+ "CHANGELOG.md",
27
+ "ARCHITECTURE.md",
28
+ "LICENSE",
29
+ ];
30
+
31
+ function download(url) {
32
+ return new Promise((resolve, reject) => {
33
+ https.get(url, (res) => {
34
+ if (res.statusCode === 301 || res.statusCode === 302) {
35
+ return download(res.headers.location).then(resolve).catch(reject);
36
+ }
37
+ if (res.statusCode !== 200) {
38
+ return reject(new Error(`Failed to download ${url}: ${res.statusCode}`));
39
+ }
40
+ let data = "";
41
+ res.on("data", (chunk) => (data += chunk));
42
+ res.on("end", () => resolve(data));
43
+ res.on("error", reject);
44
+ }).on("error", reject);
45
+ });
46
+ }
47
+
48
+ async function main() {
49
+ console.log("Installing pi-mcp-adapter...\n");
50
+
51
+ fs.mkdirSync(EXT_DIR, { recursive: true });
52
+ console.log(`Created directory: ${EXT_DIR}`);
53
+
54
+ for (const file of FILES) {
55
+ console.log(`Downloading ${file}...`);
56
+ const content = await download(`${REPO_URL}/${file}`);
57
+ fs.writeFileSync(path.join(EXT_DIR, file), content);
58
+ }
59
+
60
+ console.log("\nInstalling dependencies...");
61
+ try {
62
+ execSync("npm install --production", { cwd: EXT_DIR, stdio: "inherit" });
63
+ } catch (err) {
64
+ console.error("Warning: npm install failed. You may need to run it manually.");
65
+ }
66
+
67
+ console.log(`\nUpdating settings: ${SETTINGS_FILE}`);
68
+
69
+ let settings = {};
70
+ if (fs.existsSync(SETTINGS_FILE)) {
71
+ try {
72
+ settings = JSON.parse(fs.readFileSync(SETTINGS_FILE, "utf-8"));
73
+ } catch (err) {
74
+ console.error(`Warning: Could not parse existing settings.json: ${err.message}`);
75
+ console.error("Creating new settings file...");
76
+ }
77
+ }
78
+
79
+ if (!Array.isArray(settings.extensions)) {
80
+ settings.extensions = [];
81
+ }
82
+
83
+ const hasMcpExt = settings.extensions.some(p =>
84
+ p === EXT_PATH ||
85
+ p.includes("/extensions/pi-mcp-adapter/index.ts") ||
86
+ p.includes("/extensions/pi-mcp-adapter")
87
+ );
88
+
89
+ if (!hasMcpExt) {
90
+ settings.extensions.push(EXT_PATH);
91
+ console.log(`Added "${EXT_PATH}" to extensions array`);
92
+ } else {
93
+ console.log("Extension already configured in settings.json");
94
+ }
95
+
96
+ fs.mkdirSync(path.dirname(SETTINGS_FILE), { recursive: true });
97
+ fs.writeFileSync(SETTINGS_FILE, JSON.stringify(settings, null, 2) + "\n");
98
+
99
+ console.log("\nInstallation complete!");
100
+ console.log("\nCreate ~/.pi/agent/mcp.json to configure MCP servers.");
101
+ console.log("Restart pi to load the extension.");
102
+ }
103
+
104
+ main().catch((err) => {
105
+ console.error(`\nInstallation failed: ${err.message}`);
106
+ process.exit(1);
107
+ });
package/package.json CHANGED
@@ -1,10 +1,13 @@
1
1
  {
2
2
  "name": "pi-mcp-adapter",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "MCP (Model Context Protocol) adapter extension for Pi coding agent",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Nico Bailon",
8
+ "bin": {
9
+ "pi-mcp-adapter": "./install.js"
10
+ },
8
11
  "repository": {
9
12
  "type": "git",
10
13
  "url": "https://github.com/nicobailon/pi-mcp-adapter"
@@ -23,6 +26,7 @@
23
26
  "extensions": ["./index.ts"]
24
27
  },
25
28
  "files": [
29
+ "install.js",
26
30
  "index.ts",
27
31
  "types.ts",
28
32
  "config.ts",