pi-mcp-client 0.0.0 → 0.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.
Files changed (4) hide show
  1. package/README.md +338 -0
  2. package/dist/index.js +3726 -0
  3. package/package.json +54 -8
  4. package/index.js +0 -2
package/README.md ADDED
@@ -0,0 +1,338 @@
1
+ # 🔌 Pi MCP Client
2
+
3
+ MCP tools for Pi, discovered on demand and called natively through the official
4
+ TypeScript SDK. No bridge process and no invocation proxy.
5
+
6
+ ## 🚀 Installation
7
+
8
+ ```sh
9
+ pi install npm:pi-mcp-client
10
+ ```
11
+
12
+ ## ✨ Usage
13
+
14
+ First, add a server to `~/.pi/agent/mcp.json`. This public documentation server
15
+ does not require credentials:
16
+
17
+ ```json
18
+ {
19
+ "mcpServers": {
20
+ "cloudflare-docs": {
21
+ "type": "http",
22
+ "url": "https://docs.mcp.cloudflare.com/mcp"
23
+ }
24
+ }
25
+ }
26
+ ```
27
+
28
+ Start a new Pi session and ask it to search Cloudflare's documentation. Use `/mcp`
29
+ to inspect the connection. For authenticated services, see [OAuth](#oauth) or
30
+ [secret commands](#secret-commands).
31
+
32
+ Pi searches for the tools it needs, then calls those tools directly. Search
33
+ loads up to five matching tools by default, or up to 50 with `limit`. Results
34
+ use local BM25-based ranking, with tool names weighted more strongly than
35
+ descriptions and support for prefix matching. Full schemas become available on
36
+ the next model turn, without a separate describe step. Previously loaded tools
37
+ remain available as the conversation continues.
38
+
39
+ ### Session behavior
40
+
41
+ - Tools accumulate rather than rotating with each prompt.
42
+ - Resume and branch navigation restore tools acquired on the selected branch.
43
+ - Compaction retains the acquired tool set. New sessions start fresh.
44
+ - Pi uses native deferred loading where supported by the model and provider.
45
+ Other providers receive the expanded tool list normally.
46
+ - Search respects server filters and Pi's tool exclusions. An explicit tool
47
+ allowlist must include both `mcp_search` and the native tools you want to load.
48
+
49
+ ### Commands
50
+
51
+ | Command | Purpose |
52
+ | --- | --- |
53
+ | `/mcp`, `/mcp list`, `/mcp status` | Show a server status matrix with catalog and loaded-tool counts. |
54
+ | `/mcp inspect <server>` | Inspect status and configuration, including disabled servers. Connection values are hidden. |
55
+ | `/mcp tools <server>` | Browse the server's tools and inspect descriptions without activating tools. |
56
+ | `/mcp reload` | Apply configuration changes without restarting Pi. |
57
+ | `/mcp auth <server>` | Authenticate an OAuth-enabled HTTP server. |
58
+ | `/mcp reconnect <server>` | Replace a connection and refresh its catalog. |
59
+ | `/mcp refresh <server>` | Refresh a server's catalog without loading additional tools. |
60
+
61
+ The status matrix uses glyphs to distinguish idle (`○`), connected (`●`),
62
+ connecting (`▶︎`), disabled (`○`), and failed (`✘︎`) servers. Idle is normal:
63
+ connections open on demand. A dash (`—`) means the catalog hasn't been fetched,
64
+ not that the server has no tools. The **Loaded** column counts tools currently
65
+ active for the assistant.
66
+
67
+ After refreshing a changed schema, search for the tool again to load its current
68
+ definition. Calls validate the live catalog before execution and refuse removed
69
+ or changed tools. The extension does not retry failed tool invocations; after an
70
+ interrupted call, check whether the operation completed before trying again.
71
+
72
+ ## ⚙️ Configuration
73
+
74
+ Add connections to `~/.pi/agent/mcp.json`, or `.mcp.json` in a trusted project.
75
+ These files use the common Claude/Cursor-style `mcpServers` format, not a universal
76
+ MCP configuration standard. VS Code's `servers` format and Codex's TOML format
77
+ are not supported.
78
+
79
+ `PI_CODING_AGENT_DIR` overrides the global Pi directory. Project connections
80
+ replace same-named global connections in full; connection fields are not merged.
81
+
82
+ ```json
83
+ {
84
+ "mcpServers": {
85
+ "docs": {
86
+ "type": "http",
87
+ "url": "https://mcp.example.com/mcp",
88
+ "headers": {
89
+ "Authorization": "Bearer ${DOCS_TOKEN}"
90
+ }
91
+ },
92
+ "local": {
93
+ "type": "stdio",
94
+ "command": "node",
95
+ "args": ["/absolute/path/to/server.js"],
96
+ "env": {
97
+ "DATABASE_URL": "${DATABASE_URL}"
98
+ }
99
+ }
100
+ }
101
+ }
102
+ ```
103
+
104
+ | Field | Purpose |
105
+ | --- | --- |
106
+ | `type` | Optional `stdio` or `http`. If omitted, inferred from `command` or `url`. A conflicting type is rejected. |
107
+ | `command`, `args` | Executable and arguments for a stdio server. No shell is used. |
108
+ | `cwd` | Working directory for stdio; defaults to Pi's current directory. Relative paths resolve there. |
109
+ | `env` | Additional environment variables for stdio. |
110
+ | `url` | Streamable HTTP endpoint; mutually exclusive with `command`. |
111
+ | `headers` | HTTP request headers, including optional bearer authentication. |
112
+
113
+ Strings in `command`, `args`, `cwd`, `env`, `url`, and `headers` support `${VAR}`
114
+ interpolation. Missing variables prevent that server from connecting.
115
+
116
+ Only stdio and Streamable HTTP are supported; `type: "sse"` is rejected rather
117
+ than treated as HTTP. Unsupported connection fields cause a configuration error
118
+ rather than silently changing their meaning.
119
+
120
+ ### Secret commands
121
+
122
+ In **`headers` and stdio `env` values only**, a leading `!` runs a secret-generating
123
+ shell command when the server connects:
124
+
125
+ ```json
126
+ {
127
+ "mcpServers": {
128
+ "example": {
129
+ "type": "http",
130
+ "url": "https://mcp.example.com/mcp",
131
+ "headers": {
132
+ "Authorization": "!token=$(op read 'op://Private/Example/token') && printf 'Bearer %s' \"$token\""
133
+ }
134
+ }
135
+ }
136
+ }
137
+ ```
138
+
139
+ These two fields also support Pi-style `$VAR` interpolation, `$$` for a literal
140
+ `$`, and `$!` for a literal `!`. Only a leading `!` in the original configuration
141
+ triggers execution; interpolated values and command output never do. Shell
142
+ commands handle their own variable expansion.
143
+
144
+ Commands use `/bin/sh` on Unix or Pi's shell selection on Windows, inherit Pi's
145
+ process environment, and run in the server's configured `cwd` (the project
146
+ directory by default). They run once per connection, including reconnections,
147
+ not during configuration loading, status display, or cached discovery. Cold
148
+ searches can connect and therefore execute commands. Concurrent connection
149
+ requests share the same resolution.
150
+
151
+ The client trims stdout and rejects empty output, nonzero exits, output above
152
+ 64 KiB, and resolution taking more than 10 seconds (or a shorter `timeoutMs`).
153
+ Session shutdown cancels pending commands. Cancelling an individual search stops
154
+ waiting but leaves shared connection work running for other callers. The client
155
+ discards command stderr and does not include resolved secrets in errors, session
156
+ records, or catalog caches. Commands themselves remain responsible for avoiding
157
+ side effects or writing secrets to disk. Only configure commands you trust;
158
+ project configuration still requires project trust.
159
+
160
+ ### Pi-specific options
161
+
162
+ Put descriptions, authentication choices, filters, and timeouts directly in each
163
+ `mcpServers.<server>` definition in `~/.pi/agent/mcp.json` (or a trusted project's
164
+ `.mcp.json`):
165
+
166
+ ```json
167
+ {
168
+ "mcpServers": {
169
+ "docs": {
170
+ "type": "http",
171
+ "url": "https://mcp.example.com/mcp",
172
+ "description": "Search product documentation",
173
+ "oauth": true,
174
+ "includeTools": ["get_*", "search_*"]
175
+ }
176
+ }
177
+ }
178
+ ```
179
+
180
+ | Field | Purpose |
181
+ | --- | --- |
182
+ | `description` | Short capability description for Pi's server directory. |
183
+ | `oauth` | Set to `true` to use OAuth instead of an Authorization header on an HTTP connection. |
184
+ | `disabled` | Prevent this server from connecting or exposing tools. |
185
+ | `includeTools` | Optional allowlist of original MCP tool names; `*` matches any sequence. An empty list exposes nothing. |
186
+ | `excludeTools` | Denylist applied after `includeTools`. |
187
+ | `timeoutMs` | Request timeout, from 100 to 600000 ms. Defaults: 15 seconds for discovery/HTTP requests, 30 seconds for stdio tool calls. |
188
+ | `protocol` | `auto` (default) for SDK protocol-version negotiation, or `legacy` for an explicit legacy handshake. |
189
+
190
+ A trusted project's server definition replaces the same-named global definition
191
+ in full, including these options. Fields and tool-filter lists are not merged.
192
+ Every definition must include a `url` or `command`, even when `disabled` is true.
193
+
194
+ These options are specific to Pi MCP Client, not standardized MCP connection
195
+ fields. Other clients may reject them when you copy a definition.
196
+
197
+ After editing your configuration, run `/mcp reload` to apply it without restarting
198
+ Pi. Reload validates the new configuration before replacing the current setup;
199
+ invalid configuration leaves the previous setup intact. It closes existing
200
+ connections, which reopen on demand, and deactivates tools from changed, removed,
201
+ or disabled server definitions. Unchanged active tools remain available.
202
+
203
+ Use `/mcp inspect <server>` to check the effective transport, protocol, filters,
204
+ and connection status without connecting or running secret commands. Connection
205
+ values—including commands, arguments, URLs, headers, and environment variables—
206
+ are hidden because any of them can contain credentials.
207
+
208
+ Use `/mcp tools <server>` to fetch the current catalog and browse a scrollable
209
+ list. Each row shows the tool name and description, trimmed to the terminal width
210
+ with an ellipsis. Select a tool to see a multiline signature and parameter details,
211
+ with each parameter in a separate paragraph. Browsing respects your include and
212
+ exclude filters and doesn't activate tools or add their schemas to the assistant's
213
+ context. This command requires an interactive UI.
214
+
215
+ ### Discovery and caching
216
+
217
+ Connections start on demand, never while the extension factory loads. A search
218
+ without a cached catalog contacts configured servers, with at most four discoveries
219
+ in flight. A server-scoped search only contacts that server. Failed servers are
220
+ reported as unsearched, not mistaken for an empty catalog.
221
+
222
+ Catalogs are cached privately under `~/.pi/agent/cache/pi-mcp-client/`, keyed by
223
+ server configuration and working directory. Disk caches expire after 24 hours.
224
+ They contain tool metadata, not configured credentials. Cached search needs no
225
+ connection; invocation refreshes the live catalog before calling the tool.
226
+ Connections remain open until shutdown or explicit reconnection.
227
+
228
+ When a connected server reports a tool-list change, the extension invalidates its
229
+ memory and disk catalogs. The next search fetches the current list, including new
230
+ or removed tools. Notifications don't replace active tool definitions: changed
231
+ schemas require another `mcp_search` before use. Disconnected, cache-only searches
232
+ can't receive notifications and still use the 24-hour disk-cache expiry.
233
+
234
+ ### OAuth
235
+
236
+ Set `"oauth": true` under `mcpServers.<server>` in `mcp.json`, without an
237
+ Authorization header in its connection, then run `/mcp auth <server>`. Pi opens the
238
+ browser only for this explicit command. Automatic discovery never opens a browser.
239
+
240
+ OAuth tokens and client registrations are stored in the operating system
241
+ credential store, bound to the server URL and authorization-server issuer.
242
+ There is no plaintext credential fallback. PKCE verifiers and callback state stay
243
+ in memory.
244
+
245
+ The initial implementation supports dynamically registered public clients with a
246
+ local callback at `http://127.0.0.1:19847/callback`. The browser must be able to
247
+ reach that address on the Pi machine. Authentication times out after two minutes;
248
+ you can cancel it with Escape in the terminal UI.
249
+ Pre-registered OAuth clients, remote callback pasting, and headless interactive
250
+ OAuth are not supported yet. Use bearer headers for headless access.
251
+
252
+ ### Trust and permissions
253
+
254
+ Only load configuration you trust. Server executables and secret commands run
255
+ with your user permissions; trusted project configuration can replace global
256
+ connections and settings.
257
+
258
+ Server metadata is untrusted. Search activates tools but does not approve their
259
+ side effects or provide per-call confirmation. Use tool filters and Pi permission
260
+ extensions for additional controls. Cancelling a call does not guarantee that the
261
+ server rolled back its effects.
262
+
263
+ ## 🧰 Requirements
264
+
265
+ - Pi 0.85.1 or later, with additive dynamic tool loading.
266
+ - Node.js 22 or later.
267
+ - The server executable for stdio connections.
268
+ - An available OS credential store for OAuth. Linux requires a working Secret
269
+ Service/keyring session.
270
+
271
+ This extension uses `@modelcontextprotocol/client` 2.0.0 and defaults to automatic
272
+ SDK protocol-version negotiation. On stdio, negotiation probes using an additional
273
+ short-lived process. Set `"protocol": "legacy"` in a server definition if that
274
+ server requires an explicit legacy handshake.
275
+
276
+ ## 🩺 Troubleshooting
277
+
278
+ Start with `/mcp`. Failures use a consistent code, a short explanation, and a
279
+ recovery hint, for example:
280
+
281
+ ```text
282
+ linear: [authentication_required] Authentication is required. Run /mcp auth linear.
283
+ ```
284
+
285
+ Search and tool results also carry structured diagnostics in their result details:
286
+ `code`, `operation`, optional `server`, `message`, and `hint`. Partial discovery
287
+ keeps healthy servers' results and identifies servers it could not search. An
288
+ unavailable server is not an empty catalog.
289
+
290
+ | Code | What to check |
291
+ | --- | --- |
292
+ | `configuration_invalid` | JSON syntax, supported fields, transport type, and required environment variables. Reload Pi after editing. |
293
+ | `authentication_required` | Run `/mcp auth <server>` for OAuth, or check the Authorization header. |
294
+ | `permission_denied` | Account permissions, OAuth scopes, and service access policy. |
295
+ | `credential_store_unavailable` | Unlock or enable the OS keyring; Linux needs a Secret Service session. |
296
+ | `secret_lookup_failed` | Secret helper installation, login, exit status, nonempty stdout, and output size. |
297
+ | `connection_failed` | Server executable, working directory, endpoint, network, and TLS configuration. |
298
+ | `timeout` | Server responsiveness and the applicable request, secret-command, or OAuth time limit. |
299
+ | `protocol_error` | Server compatibility and the `protocol` setting. |
300
+ | `tool_changed` | Server filters and the current tool schema; search again. Reload Pi if connection configuration changed. |
301
+ | `tool_error` | The server's tool result and inputs; verify the outcome before retrying. |
302
+ | `oauth_failed` | Browser access to the callback and support for dynamically registered public clients. |
303
+ | `callback_unavailable` | Another process using local port 19847. |
304
+ | `busy` | Wait for discovery to finish before reconnecting. |
305
+ | `cancelled` | Retry when ready; verify any interrupted tool operation first. |
306
+ | `operation_failed` | An unclassified failure; inspect server status and configuration. |
307
+
308
+ Diagnostics never echo raw exception messages, HTTP bodies, command stderr,
309
+ credential values, or stack traces. Unknown errors stay generic rather than
310
+ being classified by potentially sensitive message text. Tool-call failures are
311
+ not replayed automatically; verify the outcome before retrying. Server-provided tool
312
+ results remain visible as content, even when the tool reports an error; they are
313
+ not sanitized transport diagnostics.
314
+
315
+ ### Large results
316
+
317
+ Text results are limited to 2,000 lines or 50 KiB. Larger results are saved as
318
+ private temporary JSON files, with their paths included in the output. Supported
319
+ images pass through within an 8 MiB base64 budget; other binary content is kept in
320
+ the full result file. Temporary result files are not automatically deleted and
321
+ may contain sensitive data.
322
+
323
+ ### v0.1 scope
324
+
325
+ The first release focuses on tools. Legacy SSE transport, MCP Apps, resource
326
+ browsing, prompt commands, roots, sampling, and elicitation are not supported.
327
+ See the [post-v0.1 backlog](https://github.com/mavam/pi-mcp-client/blob/main/TODO.md)
328
+ for follow-up work; it is not a release commitment.
329
+
330
+ ## 🧹 Uninstall
331
+
332
+ ```sh
333
+ pi remove npm:pi-mcp-client
334
+ ```
335
+
336
+ ## 📄 License
337
+
338
+ [MIT](LICENSE)