pi-mcp-adapter 2.11.0 → 2.12.1
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 +51 -2
- package/README.md +71 -17
- package/cli.js +4 -1
- package/commands.ts +220 -84
- package/config.ts +349 -44
- package/direct-tools.ts +138 -33
- package/elicitation-handler.ts +10 -11
- package/host-html-template.ts +36 -38
- package/index.ts +490 -97
- package/init.ts +284 -59
- package/lifecycle.ts +87 -29
- package/mcp-auth-flow.ts +429 -131
- package/mcp-auth.ts +79 -55
- package/mcp-callback-server.ts +88 -27
- package/mcp-oauth-provider.ts +152 -39
- package/mcp-panel.ts +118 -38
- package/metadata-cache.ts +83 -8
- package/npx-resolver.ts +81 -21
- package/oauth-handler.ts +1 -1
- package/package.json +47 -7
- package/prompts.ts +353 -0
- package/proxy-modes.ts +301 -100
- package/runtime-owner.ts +91 -0
- package/sampling-handler.ts +19 -11
- package/server-manager.ts +533 -77
- package/session-recovery.ts +152 -0
- package/state.ts +14 -1
- package/tool-metadata.ts +17 -4
- package/tool-result-renderer.ts +47 -18
- package/types.ts +76 -16
- package/ui-resource-handler.ts +109 -14
- package/ui-server.ts +41 -8
- package/ui-session.ts +118 -26
- package/utils.ts +106 -8
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [2.12.1] - 2026-07-24
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Restored the SDK v1 dependency required by the MCP Apps bridge during Pi managed installs, where peer dependencies are intentionally not auto-installed. Thanks Nikolai Ugelvik (@NikolaiUgelvik), @warmwaffles, and @max-miller1204 for issue #212.
|
|
14
|
+
|
|
15
|
+
## [2.12.0] - 2026-07-24
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- Added MCP prompts support as Pi slash commands under the `mcp__<server>__<prompt>` namespace, with capability-gated discovery, cache-backed startup registration, argument validation, lazy dispatch, and `/mcp prompts` listing. Thanks to Egor Egorov (@ee92) for PR #203.
|
|
19
|
+
- Hot-loaded refreshed direct MCP tools after metadata reconnects, lazy connects, direct-tool panel changes, and MCP list-change notifications. Thanks Devin Bost (@devinbost) for PR #72.
|
|
20
|
+
- Migrated the MCP client and interactive visualizer to the exact-pinned MCP SDK v2 beta.5 packages, with automatic protocol negotiation and client conformance coverage. Thanks Matt Carey (@mattzcarey) for PR #210.
|
|
21
|
+
- Added disabled MCP server definitions plus `/mcp disable` and `/mcp enable` project-local overrides that preserve visibility while preventing execution. Thanks Ömer Ulusoy (@ulusoyomer) for PR #61.
|
|
22
|
+
- Added argument completions for `/mcp` subcommands and reconnect/logout server names. Thanks @sting8k for PR #8.
|
|
23
|
+
- Surfaced MCP connection failure reasons from bounded stdio diagnostics in status output and the `/mcp` panel, with a shortcut to copy the selected failure. Thanks @parkuman for PR #197.
|
|
24
|
+
- Added Codex MCP imports from `.codex/config.toml`, with fallback to the existing JSON config. Thanks @npo-mmenke for PR #31.
|
|
25
|
+
- Added explicit OpenCode V1 MCP imports from global and project `opencode.json` files, including nested config merging and environment interpolation. Thanks @NicoAvanzDev for PR #25.
|
|
26
|
+
- Added environment-variable interpolation for HTTP MCP server URLs, with missing URL variables failing closed before requests are sent. Thanks @ozeias for PR #206.
|
|
27
|
+
- Added `settings.oauthDir` to store MCP OAuth credentials in a project-specific directory, with `MCP_OAUTH_DIR` still taking precedence. Thanks @Termina1 for PR #105.
|
|
28
|
+
- Added `lazy-keep-alive` lifecycle mode for MCP servers that should start on first use and then stay resident with health-check reconnects. Thanks @ricardoraposo for PR #143.
|
|
29
|
+
- Added `MCP_UI_VIEWER=none` / `off` / `disabled` to suppress MCP UI browser or Glimpse windows while keeping inline tool results available. Thanks @stevekrouse for PR #172.
|
|
30
|
+
- Surfaced MCP server `instructions` from the initialize handshake: captured at connect time, cached alongside tool metadata, shown as a truncated head in the `mcp` proxy tool description, previewed in `mcp({ server: "name" })` listings, and available in full via the new `mcp({ instructions: "name" })` mode. Thanks @JeongJuhyeon for issue #188 and PR #189.
|
|
31
|
+
- Added `createMcpAdapter({ config, configPath })` for isolated SDK configuration and file-path overrides. Thanks @Cansiny0320 for PR #86.
|
|
32
|
+
|
|
33
|
+
### Changed
|
|
34
|
+
- Removed stale hot-loaded direct tools from Pi's registry when `pi.unregisterTool()` is available, while preserving active-tool deactivation fallback for older Pi hosts.
|
|
35
|
+
- Deferred loading the regex safety checker until regex search is used, improving startup time. Thanks @kaushikgopal for PR #175.
|
|
36
|
+
- Declared Pi host packages as optional peer dependencies with exact development pins, reducing extension install footprint and avoiding host version conflicts. Thanks @t0dorakis for PR #200.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
- Started MCP initialization at extension load when any server is configured with `lifecycle: "eager"` or `"keep-alive"`, so hosts that drive Pi programmatically without `session_start` still connect startup servers. Thanks Brian Gebel (@ductiletoaster) for PR #170.
|
|
40
|
+
- Enforced normalized standard `_meta.ui.csp` and OpenAI-compatible `_meta["openai/widgetCSP"]` metadata with response headers while preserving provider HTML. Thanks @IdoHadar for PR #195.
|
|
41
|
+
- Avoided MCP renderer crashes without a TUI theme and preserved status-bar updates with plain fallback text. Thanks @fankangsong for PR #183.
|
|
42
|
+
- Abandoned MCP initialization quietly when a session is disposed during eager or keep-alive connection setup. Thanks @luisfontes for PR #192.
|
|
43
|
+
- Fenced MCP runtime ownership across Pi reloads so stale callbacks and late connections cannot outlive their session. Thanks @uuunk (Paul Lorsbach) for PR #202.
|
|
44
|
+
- Added `toolPrefix: "mcp"` support for `mcp__<server>_<tool>` names across direct and proxy MCP tool paths. Thanks @riicodespretty for PR #99.
|
|
45
|
+
- Sanitized dotted MCP tool names before registering them with Pi. Thanks @benjaminrickels for PR #190.
|
|
46
|
+
- Reconnected OAuth MCP servers automatically after successful panel or `/mcp-auth` authorization, and made panel reconnect force a fresh connection like `/mcp reconnect`. Thanks @mightymatth for issue #171.
|
|
47
|
+
- Recovered stale Streamable HTTP MCP sessions that report `-32000 Server not initialized` after a server restart. Thanks @vicary for issue #184.
|
|
48
|
+
- Kept npm cache lookups working on Windows by resolving `npm` through `cross-spawn`. Thanks @zeyadhost for PR #201.
|
|
49
|
+
- Kept direct MCP tool registration working when a host TypeBox shim does not expose `Type.Unsafe`. Thanks @RaviTharuma for PR #198.
|
|
50
|
+
- Kept exact `npx` package specs from reusing a different same-name package version from npm's `_npx` cache. Thanks @danhrahal for issue #178.
|
|
51
|
+
- Kept POST-only Streamable HTTP servers on the Streamable HTTP transport when the optional GET stream returns 405. Thanks @ramhaidar for issue #204.
|
|
52
|
+
- Kept manual OAuth `auth-start` / `auth-complete` flows from being invalidated by keep-alive health checks, and made reserved manual callback states show a manual completion page instead of a CSRF error. Thanks @oozle for issue #207.
|
|
53
|
+
- Accepted object-valued `mcp.args` in addition to JSON strings, avoiding double-encoded tool arguments while preserving provider-compatible string calls. Thanks @johnny-smitherson for issue #205.
|
|
54
|
+
- Collapsed long single-line MCP results according to terminal-wrapped visual lines. Thanks @xz-dev for PR #181 and @maxpaulus43 for PR #177.
|
|
55
|
+
- Recovered Streamable HTTP MCP sessions after a server restart invalidates the previous session ID. Thanks @damselem for PR #194.
|
|
56
|
+
- Used server-advertised OAuth protected-resource metadata during authorization so resource servers can point Pi at the correct authorization server. Thanks @jameswarren for issue #173 and PR #174.
|
|
57
|
+
- Dropped inherited HTTP auth when a higher-precedence MCP config repoints a server URL, while preserving explicit OAuth disable flags. Thanks @ductiletoaster for PR #182.
|
|
58
|
+
|
|
10
59
|
## [2.11.0] - 2026-07-03
|
|
11
60
|
|
|
12
61
|
### Changed
|
|
@@ -24,9 +73,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
24
73
|
- Normalized direct MCP tool schemas so draft metadata and strict top-level additional properties do not break Pi registration. Thanks @marchellodev for issue #2/PR #3 and @comtihon for PR #144.
|
|
25
74
|
- Routed interactive `/mcp-auth` OAuth URLs through Pi UI notifications so long authorization links remain intact instead of being truncated by raw terminal output. Thanks @feoh for issue #147/PR #148.
|
|
26
75
|
- Respected configured HTTP headers before implicit OAuth auto-detection so API-key/custom-header MCP servers do not trigger OAuth DCR. Thanks @OnlyXianzo for issue #158.
|
|
27
|
-
- Propagated Pi abort signals into MCP connect, resource, and tool requests so cancelled calls settle promptly. Thanks @xz-dev for PR #159.
|
|
76
|
+
- Propagated Pi abort signals into MCP connect, resource, and tool requests so cancelled calls settle promptly. Thanks @xz-dev for PR #159 and @murrayju for PR #149.
|
|
28
77
|
- Re-flagged failed MCP tool calls (`tool_error`/`call_failed`) as errors so they are recorded as failures (`isError: true`) instead of successes. Thanks @ishinder for PR #157.
|
|
29
|
-
- Honored configured `requestTimeoutMs` during MCP connection, discovery, tool, resource, and UI proxy requests. Thanks @mizuikki for PR #155.
|
|
78
|
+
- Honored configured `requestTimeoutMs` during MCP connection, discovery, tool, resource, and UI proxy requests. Thanks @mizuikki for PR #155 and @danecando for PR #62.
|
|
30
79
|
- Rendered successful MCP `structuredContent` when servers return it without `content`. Thanks @dovixman for PR #146.
|
|
31
80
|
|
|
32
81
|
## [2.10.0] - 2026-06-13
|
package/README.md
CHANGED
|
@@ -65,6 +65,8 @@ Precedence is:
|
|
|
65
65
|
3. `.mcp.json`
|
|
66
66
|
4. `.pi/mcp.json`
|
|
67
67
|
|
|
68
|
+
`/mcp disable <server>` and `/mcp enable <server>` persist only the `disabled` field in the project-local `.pi/mcp.json`, which is the highest-precedence Pi layer. Enabling removes the project flag when lower layers are enabled, or writes `false` when needed to override a disabled lower source. This applies even when the effective server came from a shared global/project file, an imported host config, or `configPath`; the source file is never rewritten and credentials are never copied. Run `/reload` after changing the flag so registered tool surfaces are refreshed. The manual equivalent is to add `{ "disabled": true }` to a server in any normal MCP config. Supplied in-memory `createMcpAdapter({ config })` configurations are isolated and do not read or write this project override; the commands are unavailable in that mode.
|
|
69
|
+
|
|
68
70
|
Servers are **lazy by default** — they won't connect until you actually call one of their tools. The adapter caches tool metadata so search and describe work without live connections.
|
|
69
71
|
|
|
70
72
|
```
|
|
@@ -79,10 +81,10 @@ chrome_devtools_take_screenshot
|
|
|
79
81
|
fullPage (boolean) - Full page instead of viewport
|
|
80
82
|
```
|
|
81
83
|
```
|
|
82
|
-
mcp({ tool: "chrome_devtools_take_screenshot", args:
|
|
84
|
+
mcp({ tool: "chrome_devtools_take_screenshot", args: { format: "png" } })
|
|
83
85
|
```
|
|
84
86
|
|
|
85
|
-
|
|
87
|
+
`args` can be a JSON object or a JSON string. Prefer the object form when your model handles it reliably; the string form remains supported for providers that need simpler schemas.
|
|
86
88
|
|
|
87
89
|
Two calls instead of 26 tools cluttering the context.
|
|
88
90
|
|
|
@@ -101,6 +103,33 @@ Use the shared MCP files when you want one setup to work across hosts, and Pi-ow
|
|
|
101
103
|
|
|
102
104
|
Pi-specific files are the write targets for imported or shared global servers when Pi needs to persist adapter-only settings such as `directTools`.
|
|
103
105
|
|
|
106
|
+
### SDK configuration
|
|
107
|
+
|
|
108
|
+
Use `createMcpAdapter` when an SDK or server integration already owns its MCP configuration:
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
import { createMcpAdapter } from "pi-mcp-adapter";
|
|
112
|
+
|
|
113
|
+
const extension = createMcpAdapter({
|
|
114
|
+
config: {
|
|
115
|
+
mcpServers: {
|
|
116
|
+
docs: {
|
|
117
|
+
url: "https://mcp.example.com/mcp",
|
|
118
|
+
lifecycle: "eager",
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// Register `extension` with the host SDK.
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
The package ships TypeScript source for Pi's source-loader and SDK integrations. Use a TypeScript-capable loader/toolchain (for example `node --import tsx`) when importing the package from a standalone Node process; raw Node ESM does not execute the `.ts` entry directly.
|
|
128
|
+
|
|
129
|
+
A supplied `config` is a complete, isolated snapshot. It is not merged with files, imports, global config, project config, or `--mcp-config`, and it is never mutated. Each adapter factory and session receives its own clone, so separate integrations can use different servers and settings safely. In this mode, server status, reconnect, explicit `/mcp-auth <server>`, proxy calls, and direct tools continue to work; setup and no-argument auth/status panels report the limitation instead of discovering or writing ambient config.
|
|
130
|
+
|
|
131
|
+
With `configPath` and no `config`, the adapter keeps normal file merge behavior, and that path takes precedence over argv and `--mcp-config`. The default export keeps the normal file-based behavior. OAuth credentials remain persistent and are shared by the configured server name by default; callers requiring strict same-name credential-file isolation should set distinct `settings.oauthDir` values. URL binding prevents credentials from being accepted for a different server URL. CSRF state and PKCE verifiers are flow-local, so concurrent authorization flows do not share transient secrets.
|
|
132
|
+
|
|
104
133
|
In the configuration examples below, `30000` is illustrative only. If `requestTimeoutMs` is omitted or set to `<= 0`, the MCP SDK default timeout is used.
|
|
105
134
|
|
|
106
135
|
### Server Options
|
|
@@ -125,7 +154,7 @@ In the configuration examples below, `30000` is illustrative only. If `requestTi
|
|
|
125
154
|
| `args` | Command arguments |
|
|
126
155
|
| `env` | Environment variables; supports `${VAR}` and `$env:VAR` interpolation |
|
|
127
156
|
| `cwd` | Working directory; supports `${VAR}`, `$env:VAR`, and `~` expansion |
|
|
128
|
-
| `url` | HTTP endpoint (StreamableHTTP with SSE fallback) |
|
|
157
|
+
| `url` | HTTP endpoint (StreamableHTTP with SSE fallback); supports raw `${VAR}` and `$env:VAR` interpolation, and missing URL variables fail before any request is sent |
|
|
129
158
|
| `headers` | HTTP headers; supports `${VAR}` and `$env:VAR` interpolation |
|
|
130
159
|
| `auth` | `"bearer"` or `"oauth"` |
|
|
131
160
|
| `oauth.grantType` | `"authorization_code"` (default) or `"client_credentials"` for non-interactive machine auth |
|
|
@@ -136,13 +165,14 @@ In the configuration examples below, `30000` is illustrative only. If `requestTi
|
|
|
136
165
|
| `oauth.clientName` | Client display name advertised during dynamic registration |
|
|
137
166
|
| `oauth.clientUri` | Client homepage URI advertised during dynamic registration |
|
|
138
167
|
| `bearerToken` / `bearerTokenEnv` | Token or env var name; `bearerToken` supports `${VAR}` and `$env:VAR` interpolation |
|
|
139
|
-
| `lifecycle` | `"lazy"` (default), `"eager"`, or `"keep-alive"` |
|
|
168
|
+
| `lifecycle` | `"lazy"` (default), `"eager"`, `"keep-alive"`, or `"lazy-keep-alive"` |
|
|
140
169
|
| `idleTimeout` | Minutes before idle disconnect (overrides global) |
|
|
141
170
|
| `requestTimeoutMs` | Request timeout in milliseconds for live MCP calls (overrides global; if omitted or `<= 0`, the MCP SDK default timeout is used) |
|
|
142
171
|
| `exposeResources` | Expose MCP resources as tools (default: true) |
|
|
143
172
|
| `directTools` | `true`, `string[]`, or `false` — register tools individually instead of through proxy |
|
|
144
173
|
| `excludeTools` | `string[]` of tool names to hide (matches original names like `get_screenshot` and prefixed names like `figma_get_screenshot`) |
|
|
145
174
|
| `debug` | Show server stderr (default: false) |
|
|
175
|
+
| `disabled` | Keep the server visible in config and status, but prevent connections, authentication, tools, and resource calls (only literal `true` disables it) |
|
|
146
176
|
|
|
147
177
|
For pre-registered browser OAuth clients, set `oauth.redirectUri` to the exact callback registered with the provider, for example `"http://localhost:3118/callback"`. Dynamic clients normally omit it and use a lazy OS-assigned localhost callback port.
|
|
148
178
|
|
|
@@ -160,17 +190,20 @@ Open the returned authorization URL in your local browser. After approval, your
|
|
|
160
190
|
mcp({
|
|
161
191
|
action: "auth-complete",
|
|
162
192
|
server: "linear-server",
|
|
163
|
-
args:
|
|
193
|
+
args: { redirectUrl: "http://localhost:19876/callback?code=...&state=..." }
|
|
164
194
|
})
|
|
165
195
|
```
|
|
166
196
|
|
|
167
|
-
You can also pass only the `code` query parameter with `args:
|
|
197
|
+
You can also pass only the `code` query parameter with `args: { code: "..." }`. Treat authorization URLs and codes as sensitive; they can grant access to the MCP server until the flow expires or completes.
|
|
168
198
|
|
|
169
199
|
### Lifecycle Modes
|
|
170
200
|
|
|
171
201
|
- **`lazy`** (default) — Don't connect at startup. Connect on first tool call. Disconnect after idle timeout. Cached metadata keeps search/list working without connections.
|
|
172
202
|
- **`eager`** — Connect at startup but don't auto-reconnect if the connection drops. No idle timeout by default (set `idleTimeout` explicitly to enable).
|
|
173
203
|
- **`keep-alive`** — Connect at startup. Auto-reconnect via health checks. No idle timeout. Use for servers you always need available.
|
|
204
|
+
- **`lazy-keep-alive`** — Don't connect at startup. Connect on first tool call (like `lazy`). Once spawned, never idle-shut down and auto-reconnect via health checks if the process dies (like `keep-alive`). Use for servers that are expensive to start but should stay resident after their first use.
|
|
205
|
+
|
|
206
|
+
When any enabled server uses `eager` or `keep-alive`, initialization also starts when the extension loads. This supports hosts that embed Pi programmatically and never emit `session_start`; if a session does start later, the session-owned runtime supersedes the load-time runtime.
|
|
174
207
|
|
|
175
208
|
### Settings
|
|
176
209
|
|
|
@@ -179,7 +212,8 @@ You can also pass only the `code` query parameter with `args: '{"code":"..."}'`.
|
|
|
179
212
|
"settings": {
|
|
180
213
|
"toolPrefix": "server",
|
|
181
214
|
"idleTimeout": 10,
|
|
182
|
-
"requestTimeoutMs": 30000
|
|
215
|
+
"requestTimeoutMs": 30000,
|
|
216
|
+
"oauthDir": ".pi/mcp-oauth"
|
|
183
217
|
},
|
|
184
218
|
"mcpServers": { }
|
|
185
219
|
}
|
|
@@ -187,9 +221,10 @@ You can also pass only the `code` query parameter with `args: '{"code":"..."}'`.
|
|
|
187
221
|
|
|
188
222
|
| Setting | Description |
|
|
189
223
|
|---------|-------------|
|
|
190
|
-
| `toolPrefix` | `"server"` (default), `"short"` (strips `-mcp` suffix), or `"
|
|
224
|
+
| `toolPrefix` | `"server"` (default), `"short"` (strips `-mcp` suffix), `"none"`, or `"mcp"` (prefixes with `mcp__`, using server-mode normalization) |
|
|
191
225
|
| `idleTimeout` | Global idle timeout in minutes (default: 10, 0 to disable) |
|
|
192
226
|
| `requestTimeoutMs` | Global request timeout in milliseconds for live MCP calls (if omitted or `<= 0`, the MCP SDK default timeout is used) |
|
|
227
|
+
| `oauthDir` | OAuth credential directory for this MCP config. Relative paths resolve from the active project cwd. `MCP_OAUTH_DIR` still wins when set. |
|
|
193
228
|
| `directTools` | Global default for all servers (default: false). Per-server overrides this. |
|
|
194
229
|
| `disableProxyTool` | Hide the `mcp` proxy tool once configured direct tools are fully available from cache. |
|
|
195
230
|
| `autoAuth` | Auto-run OAuth on `connect`/tool calls when a server needs auth, then retry once (default: false). |
|
|
@@ -220,6 +255,18 @@ Tune the limits with the object form:
|
|
|
220
255
|
|
|
221
256
|
Set `"outputGuard": false` — or the env kill switch `MCP_OUTPUT_GUARD=0` — to disable the guard and restore raw output behavior. Saved temp files are created with mode `0600` under the system temp directory and are not cleaned up automatically; note that spilled MCP output may contain sensitive data.
|
|
222
257
|
|
|
258
|
+
### MCP Prompts
|
|
259
|
+
|
|
260
|
+
MCP servers can advertise prompt templates alongside tools and resources. The adapter registers cached prompt definitions as Pi slash commands under `/mcp__<server>__<prompt>`, and refreshes their metadata whenever a server connects. Arguments support positional and `key=value` forms with quoting; required arguments are validated before `prompts/get` is called.
|
|
261
|
+
|
|
262
|
+
```text
|
|
263
|
+
/mcp__agent_board__create_plan "harden retry policy"
|
|
264
|
+
/mcp__agent_board__review_pipeline status=paused
|
|
265
|
+
/mcp prompts
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Prompt results are flattened into one user message, preserving `[user]` and `[assistant]` role markers for multi-message results. Servers without the `prompts` capability are not probed.
|
|
269
|
+
|
|
223
270
|
### MCP Elicitation
|
|
224
271
|
|
|
225
272
|
When Pi exposes dialog-capable UI, the adapter advertises form elicitation support. Forms use Pi's stock `select()` and `input()` dialogs, validate the response, and provide a review/edit step before submission. Explicit refusal maps to MCP `decline`; dismissing a dialog maps to `cancel`.
|
|
@@ -294,9 +341,9 @@ To exclude specific tools while still using `directTools: true`, add `excludeToo
|
|
|
294
341
|
|
|
295
342
|
Each direct tool costs ~150-300 tokens in the system prompt (name + description + schema). Good for targeted sets of 5-20 tools. For servers with 75+ tools, stick with the proxy or pick specific tools with a `string[]`.
|
|
296
343
|
|
|
297
|
-
Direct tools register from the metadata cache in the Pi agent dir (`~/.pi/agent/mcp-cache.json` by default, or `$PI_CODING_AGENT_DIR/mcp-cache.json` when set), so no server connections are needed at startup. On the first session after adding `directTools` to a new server, the cache won't exist yet — tools fall back to proxy-only
|
|
344
|
+
Direct tools register from the metadata cache in the Pi agent dir (`~/.pi/agent/mcp-cache.json` by default, or `$PI_CODING_AGENT_DIR/mcp-cache.json` when set), so no server connections are needed at startup. On the first session after adding `directTools` to a new server, the cache won't exist yet — tools fall back to proxy-only while the cache populates, then the extension hot-loads the refreshed direct tools into the current session. Servers that advertise MCP list-change notifications refresh the current session when their tool or resource list changes. On Pi versions that expose `pi.unregisterTool()`, stale direct tools are removed from the registry during refresh; older Pi versions still deactivate them from the active tool set. To force a refresh: `/mcp reconnect <server>`.
|
|
298
345
|
|
|
299
|
-
When you change direct-tool toggles in `/mcp
|
|
346
|
+
When you change direct-tool toggles in `/mcp`, the extension updates direct tool registration in the current session. Broader setup writes from `/mcp setup` still use Pi's normal reload flow because they can add or restructure MCP config files.
|
|
300
347
|
|
|
301
348
|
**Interactive configuration:** Run `/mcp` to open an interactive panel showing all servers with connection status, tools, and direct/proxy toggles. You can reconnect servers and toggle tools between direct and proxy from the same overlay. For OAuth, press Enter on a server that needs auth or `ctrl+a` on any OAuth server.
|
|
302
349
|
|
|
@@ -315,7 +362,7 @@ MCP servers can ship interactive UIs via the [MCP UI](https://github.com/MCP-UI-
|
|
|
315
362
|
3. pi-mcp-adapter fetches the UI HTML and opens it in an iframe
|
|
316
363
|
4. The UI can call MCP tools and send messages back to the agent
|
|
317
364
|
|
|
318
|
-
**Native rendering:** On macOS, if [Glimpse](https://github.com/hazat/glimpse) is installed (`pi install npm:glimpseui`), UIs open in a native WKWebView window instead of a browser tab. Set `MCP_UI_VIEWER=browser` to force the browser,
|
|
365
|
+
**Native rendering:** On macOS, if [Glimpse](https://github.com/hazat/glimpse) is installed (`pi install npm:glimpseui`), UIs open in a native WKWebView window instead of a browser tab. Set `MCP_UI_VIEWER=browser` to force the browser, `MCP_UI_VIEWER=glimpse` to require native rendering, or `MCP_UI_VIEWER=none` (also accepts `off` / `disabled`) to suppress the window entirely — the tool still runs and its inline result is returned to the agent, but no browser or native window opens. This is useful for headless setups, CI, or users who want the tool output delivered inline as text only. When suppressed, a one-line info notification shows the UI URL so it can still be opened manually if needed.
|
|
319
366
|
|
|
320
367
|
**Bidirectional communication:** The UI talks back. When it sends a prompt or intent, the message is stored and `triggerTurn()` wakes the agent. The agent retrieves messages via `mcp({ action: "ui-messages" })` and responds, enabling conversational UIs where the app and agent collaborate in real-time.
|
|
321
368
|
|
|
@@ -350,6 +397,7 @@ Returns accumulated messages from UI sessions. Each message includes `type`, `se
|
|
|
350
397
|
- Tool consent gates whether UIs can call MCP tools (never/once-per-server/always)
|
|
351
398
|
- Works with both stdio and HTTP MCP servers
|
|
352
399
|
- Uses a local 408KB AppBridge bundle (MCP SDK + Zod) for browser↔server communication
|
|
400
|
+
- Enforces CSP from standard `_meta.ui.csp` and OpenAI-compatible `_meta["openai/widgetCSP"]` metadata in the response header while preserving provider HTML.
|
|
353
401
|
|
|
354
402
|
### Local Example: Interactive Visualizer
|
|
355
403
|
|
|
@@ -369,14 +417,14 @@ Shared MCP files are loaded automatically. Use `imports` only for host-specific
|
|
|
369
417
|
|
|
370
418
|
```json
|
|
371
419
|
{
|
|
372
|
-
"imports": ["cursor", "claude-code", "claude-desktop"],
|
|
420
|
+
"imports": ["cursor", "claude-code", "claude-desktop", "opencode"],
|
|
373
421
|
"mcpServers": { }
|
|
374
422
|
}
|
|
375
423
|
```
|
|
376
424
|
|
|
377
|
-
Supported compatibility imports: `cursor`, `claude-code`, `claude-desktop`, `vscode`, `windsurf`, `codex`
|
|
425
|
+
Supported compatibility imports: `cursor`, `claude-code`, `claude-desktop`, `opencode`, `vscode`, `windsurf`, `codex`
|
|
378
426
|
|
|
379
|
-
`pi-mcp-adapter init` detects these host-specific configs and adds missing imports to the Pi agent dir config for you.
|
|
427
|
+
`pi-mcp-adapter init` detects these host-specific configs and adds missing imports to the Pi agent dir config for you. The `opencode` import reads OpenCode V1 `mcp` entries from both `~/.config/opencode/opencode.json` and the project `opencode.json`, with project fields taking precedence. It is explicit-import only; OpenCode V2, inline content, managed configs, and remote discovery are not supported.
|
|
380
428
|
|
|
381
429
|
### Project Config
|
|
382
430
|
|
|
@@ -390,18 +438,21 @@ Prefer `.mcp.json` for project-local shared MCP config. Use `.pi/mcp.json` only
|
|
|
390
438
|
| List server | `mcp({ server: "name" })` |
|
|
391
439
|
| Search | `mcp({ search: "screenshot navigate" })` |
|
|
392
440
|
| Describe | `mcp({ describe: "tool_name" })` |
|
|
393
|
-
|
|
|
441
|
+
| Instructions | `mcp({ instructions: "name" })` |
|
|
442
|
+
| Call | `mcp({ tool: "...", args: { key: "value" } })` |
|
|
394
443
|
| Connect | `mcp({ connect: "server-name" })` |
|
|
395
444
|
| UI messages | `mcp({ action: "ui-messages" })` |
|
|
396
445
|
| Auth start | `mcp({ action: "auth-start", server: "name" })` |
|
|
397
|
-
| Auth complete | `mcp({ action: "auth-complete", server: "name", args:
|
|
446
|
+
| Auth complete | `mcp({ action: "auth-complete", server: "name", args: { redirectUrl: "..." } })` |
|
|
398
447
|
|
|
399
|
-
MCP proxy and direct-tool results render compactly by default: long text shows the first three lines plus a `Ctrl+O to expand` hint, while the full result remains available when expanded and is still returned unchanged to the model.
|
|
448
|
+
MCP proxy and direct-tool results render compactly by default: long text shows the first three terminal-wrapped lines plus a `Ctrl+O to expand` hint, while the full result remains available when expanded and is still returned unchanged to the model.
|
|
400
449
|
|
|
401
450
|
Search includes both MCP tools and Pi tools (from extensions). Pi tools appear first with `[pi tool]` prefix. Space-separated words are OR'd.
|
|
402
451
|
|
|
403
452
|
Tool names are fuzzy-matched on hyphens and underscores — `context7_resolve_library_id` finds `context7_resolve-library-id`.
|
|
404
453
|
|
|
454
|
+
Servers that provide usage guidance via the MCP `instructions` field surface it at three levels: a truncated head in the `mcp` proxy tool description itself (so the model sees it without any call), a longer preview at the end of `mcp({ server: "name" })` listings, and the full text via `mcp({ instructions: "name" })`. Instructions are captured at connect time and cached alongside tool metadata, so they stay available without a live connection.
|
|
455
|
+
|
|
405
456
|
## Commands
|
|
406
457
|
|
|
407
458
|
| Command | What it does |
|
|
@@ -409,8 +460,11 @@ Tool names are fuzzy-matched on hyphens and underscores — `context7_resolve_li
|
|
|
409
460
|
| `/mcp` | Interactive panel and first-run onboarding surface |
|
|
410
461
|
| `/mcp setup` | Guided setup for imports, a minimal `.mcp.json`, RepoPrompt quick-add, and config-path inspection |
|
|
411
462
|
| `/mcp tools` | List all tools |
|
|
463
|
+
| `/mcp prompts` | List all MCP prompts registered as slash commands |
|
|
412
464
|
| `/mcp reconnect` | Reconnect all servers |
|
|
413
465
|
| `/mcp reconnect <server>` | Connect or reconnect a single server |
|
|
466
|
+
| `/mcp disable <server>` | Disable a server in the project-local `.pi/mcp.json` (requires `/reload` to apply) |
|
|
467
|
+
| `/mcp enable <server>` | Enable through the project-local override layer (requires `/reload` to apply) |
|
|
414
468
|
| `/mcp logout <server>` | Clear stored OAuth credentials for a server and disconnect it |
|
|
415
469
|
| `/mcp-auth` | Open an OAuth server picker in interactive UI sessions |
|
|
416
470
|
| `/mcp-auth <server>` | OAuth setup for a specific server |
|
package/cli.js
CHANGED
|
@@ -29,7 +29,10 @@ const IMPORT_PATHS = {
|
|
|
29
29
|
path.join(HOME, ".claude", "claude_desktop_config.json"),
|
|
30
30
|
],
|
|
31
31
|
"claude-desktop": [path.join(HOME, "Library", "Application Support", "Claude", "claude_desktop_config.json")],
|
|
32
|
-
codex: [
|
|
32
|
+
codex: [
|
|
33
|
+
path.join(HOME, ".codex", "config.toml"),
|
|
34
|
+
path.join(HOME, ".codex", "config.json"),
|
|
35
|
+
],
|
|
33
36
|
windsurf: [path.join(HOME, ".windsurf", "mcp.json")],
|
|
34
37
|
vscode: [path.resolve(process.cwd(), ".vscode", "mcp.json")],
|
|
35
38
|
};
|