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 +6 -0
- package/README.md +47 -104
- package/install.js +107 -0
- package/package.json +5 -1
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
60
|
+
### Server Options
|
|
60
61
|
|
|
61
62
|
```json
|
|
62
63
|
{
|
|
63
64
|
"mcpServers": {
|
|
64
|
-
"
|
|
65
|
+
"my-server": {
|
|
65
66
|
"command": "npx",
|
|
66
|
-
"args": ["-y", "
|
|
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
|
|
94
|
-
| `url` | HTTP endpoint (
|
|
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
|
|
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
|
|
84
|
+
| `debug` | Show server stderr (default: false) |
|
|
100
85
|
|
|
101
86
|
### Import Existing Configs
|
|
102
87
|
|
|
103
|
-
Already have MCP set up
|
|
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
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
mcp({
|
|
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
|
-
|
|
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
|
|
158
|
-
| `/mcp-auth <server>` | OAuth setup
|
|
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
|
|
121
|
+
See [ARCHITECTURE.md](./ARCHITECTURE.md) for details. Short version:
|
|
179
122
|
|
|
180
|
-
- One `mcp` tool
|
|
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
|
|
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.
|
|
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",
|