@fitchmultz/pi-mcp-adapter 6.0.0 → 7.1.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 (111) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/OAUTH.md +1 -1
  3. package/README.md +27 -18
  4. package/dist/app-bridge.bundle.js +14 -14
  5. package/dist/config.js +41 -16
  6. package/dist/direct-tools.js +1 -1
  7. package/dist/gateway-arguments.d.ts +1 -1
  8. package/dist/index.js +38 -59
  9. package/dist/lifecycle.d.ts +2 -2
  10. package/dist/lifecycle.js +2 -2
  11. package/dist/mcp-auth-flow.js +2 -2
  12. package/dist/mcp-auth.d.ts +1 -1
  13. package/dist/mcp-auth.js +3 -3
  14. package/dist/mcp-code.d.ts +6 -6
  15. package/dist/mcp-code.js +11 -10
  16. package/dist/mcp-oauth-provider.d.ts +5 -5
  17. package/dist/mcp-oauth-provider.js +5 -5
  18. package/dist/mcp-output-guard.d.ts +1 -1
  19. package/dist/mcp-output-guard.js +1 -1
  20. package/dist/mcp-panel.d.ts +2 -2
  21. package/dist/mcp-panel.js +2 -2
  22. package/dist/mcp-setup-panel.d.ts +5 -4
  23. package/dist/mcp-setup-panel.js +15 -7
  24. package/dist/mcp-trace.d.ts +1 -1
  25. package/dist/mcp-trace.js +1 -1
  26. package/dist/npx-resolver.js +8 -4
  27. package/dist/proxy-modes.d.ts +2 -2
  28. package/dist/proxy-modes.js +20 -19
  29. package/dist/sampling-handler.js +1 -0
  30. package/dist/search-ranking.js +6 -2
  31. package/dist/server-manager.d.ts +2 -2
  32. package/dist/server-manager.js +44 -27
  33. package/dist/session-recovery.d.ts +7 -4
  34. package/dist/session-recovery.js +76 -10
  35. package/dist/tool-loader.d.ts +7 -2
  36. package/dist/tool-loader.js +56 -5
  37. package/dist/tool-metadata.d.ts +43 -43
  38. package/dist/tool-result-renderer.d.ts +3 -3
  39. package/dist/tool-result-renderer.js +3 -3
  40. package/dist/ui-resource-handler.d.ts +2 -2
  41. package/dist/ui-resource-handler.js +2 -2
  42. package/dist/ui-server.js +5 -4
  43. package/dist/ui-stream-types.d.ts +8 -8
  44. package/dist/unix-socket-transport.d.ts +1 -1
  45. package/dist/unix-socket-transport.js +1 -1
  46. package/dist/utils.d.ts +1 -0
  47. package/dist/utils.js +14 -0
  48. package/package.json +34 -98
  49. package/skills/mcp-scripting/SKILL.md +2 -0
  50. package/abort.ts +0 -34
  51. package/agent-dir.ts +0 -24
  52. package/app-bridge.bundle.js +0 -109
  53. package/banner.png +0 -0
  54. package/checkpoint.ts +0 -55
  55. package/commands.ts +0 -622
  56. package/config.ts +0 -1204
  57. package/consent-manager.ts +0 -25
  58. package/direct-tools.ts +0 -75
  59. package/elicitation-handler.ts +0 -349
  60. package/error-signal.ts +0 -21
  61. package/gateway-arguments.ts +0 -73
  62. package/glimpse-ui.ts +0 -80
  63. package/host-html-template.ts +0 -456
  64. package/index.ts +0 -767
  65. package/init.ts +0 -613
  66. package/legacy-migration.ts +0 -47
  67. package/lifecycle.ts +0 -165
  68. package/logger.ts +0 -127
  69. package/mcp-auth-flow.ts +0 -975
  70. package/mcp-auth.ts +0 -793
  71. package/mcp-callback-server.ts +0 -450
  72. package/mcp-code.ts +0 -412
  73. package/mcp-keyring-helper.cjs +0 -89
  74. package/mcp-oauth-provider.ts +0 -774
  75. package/mcp-output-guard.ts +0 -530
  76. package/mcp-panel.ts +0 -907
  77. package/mcp-script-worker.mjs +0 -131
  78. package/mcp-setup-panel.ts +0 -666
  79. package/mcp-status.ts +0 -110
  80. package/mcp-trace.ts +0 -295
  81. package/metadata-cache.ts +0 -271
  82. package/npx-resolver.ts +0 -488
  83. package/onboarding-state.ts +0 -58
  84. package/panel-keys.ts +0 -37
  85. package/prompts.ts +0 -337
  86. package/proxy-modes.ts +0 -1109
  87. package/resource-tools.ts +0 -52
  88. package/runtime-owner.ts +0 -123
  89. package/sampling-handler.ts +0 -276
  90. package/scripts/build-app-bridge.mjs +0 -15
  91. package/scripts/build.mjs +0 -132
  92. package/scripts/prepare.mjs +0 -103
  93. package/search-ranking.ts +0 -132
  94. package/server-manager.ts +0 -1320
  95. package/session-recovery.ts +0 -316
  96. package/state.ts +0 -64
  97. package/tool-approval.ts +0 -78
  98. package/tool-loader.ts +0 -153
  99. package/tool-metadata.ts +0 -240
  100. package/tool-registrar.ts +0 -74
  101. package/tool-result-renderer.ts +0 -294
  102. package/tsconfig.build.json +0 -13
  103. package/tsconfig.json +0 -16
  104. package/types.ts +0 -785
  105. package/ui-resource-handler.ts +0 -249
  106. package/ui-server.ts +0 -808
  107. package/ui-session.ts +0 -568
  108. package/ui-stream-types.ts +0 -89
  109. package/ui-tool-visibility.ts +0 -25
  110. package/unix-socket-transport.ts +0 -85
  111. package/utils.ts +0 -307
package/CHANGELOG.md CHANGED
@@ -5,6 +5,39 @@ 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
+ ## [Unreleased]
9
+
10
+ ## [7.1.0] - 2026-09-27
11
+
12
+ ### Changed
13
+
14
+ - Keep full MCP gateway/script schemas inactive until selected with `mcp_search({ enable: ["gateway", "script"] })`. Typed discovery still loads matches in one call. Selections persist on the current session branch; configured pins, legacy resource pins, configuration restrictions, and loader-excluded host allowlists retain their behavior.
15
+ - `npm run typecheck` now also checks the test suite under the same strict settings as the source.
16
+
17
+ ## [7.0.0] - 2026-09-26
18
+
19
+ ### Breaking changes
20
+
21
+ - Node.js 24 or later is required. The development baseline is Pi 0.87.1.
22
+ - Package `exports` now resolve to the compiled `dist/` modules and declarations. The npm tarball no longer ships TypeScript sources, build scripts, or tsconfig files; standalone Node consumers import the package directly without a TypeScript loader.
23
+ - `zod` is a regular dependency only, no longer a required peer.
24
+
25
+ ### Changed
26
+
27
+ - Update the MCP client and core SDK to 2.1.0, `@napi-rs/keyring` to 2.1.0 (credential-store failures now surface as errors instead of empty reads), `open` to 11.0.4, and `smol-toml` to 1.9.0. Pin all runtime dependencies to exact versions.
28
+ - MCP clients report the adapter's package version instead of a stale `4.3.1`.
29
+ - Build with TypeScript 7 and test with Vitest 5. OAuth tests, conformance, and fixtures run on Node's native type stripping; `tsx` is removed. `npm test` now also runs the OAuth suite.
30
+ - Git installs copy the committed MCP Apps bridge bundle instead of rebuilding it, so they no longer need esbuild. `npm run build:bridge` regenerates it, and a test fails when it drifts.
31
+ - The MCP conformance runner is fetched on demand instead of installing a second MCP SDK into every source install.
32
+ - CI qualifies official Pi and the maintained fork with the shared Pi compatibility automation, and rejects lockfile URLs outside the public npm registry.
33
+
34
+ ### Fixed
35
+
36
+ - Prevent project stdio overrides, including OpenCode working-directory and environment changes, from inheriting another config source's environment secrets.
37
+ - Refuse MCP setup writes when an existing config cannot be read, preserving the file and showing the error in the setup preview.
38
+ - Keep a shared initial MCP connection alive when one caller cancels, so other callers can continue without a false failure backoff.
39
+ - Let npm resolve explicit version ranges and tags for MCP server commands instead of launching an arbitrary cached version. Exact versions retain the direct-launch optimization.
40
+
8
41
  ## [6.0.0] - 2026-09-22
9
42
 
10
43
  ### Breaking changes
package/OAUTH.md CHANGED
@@ -207,7 +207,7 @@ For browser authorization, this will:
207
207
 
208
208
  ### Remote/headless authentication
209
209
 
210
- When Pi runs over SSH or in a headless environment, use the proxy tool to retrieve the authorization URL instead of relying on OS browser launch:
210
+ When Pi runs over SSH or in a headless environment, use the proxy tool to retrieve the authorization URL instead of relying on OS browser launch. If `mcp` is inactive, first call `mcp_search({ enable: ["gateway"] })` (no query needed):
211
211
 
212
212
  ```
213
213
  mcp({ action: "auth-start", server: "my-oauth-server" })
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # Fitch MCP Adapter
6
6
 
7
- Use MCP servers with [Pi](https://github.com/badlogic/pi-mono/) without burning your context window.
7
+ Use MCP servers with [Pi](https://github.com/earendil-works/pi) without burning your context window.
8
8
 
9
9
  An independently maintained distribution of [Nico's Pi MCP Adapter](https://github.com/nicobailon/pi-mcp-adapter), under the original MIT license.
10
10
 
@@ -16,17 +16,17 @@ Mario wrote about [why you might not need MCP](https://mariozechner.at/posts/202
16
16
 
17
17
  His take: skip MCP entirely, write simple CLI tools instead.
18
18
 
19
- The MCP ecosystem has useful databases, browsers, and APIs. This adapter keeps their full tool schemas out of context until needed. `mcp_search` discovers and loads typed tools for the next request; `mcp` handles explicit gateway actions, and `mcp_script` composes MCP calls in JavaScript. Lazy servers stay disconnected until selected discovery or a call needs them.
19
+ The MCP ecosystem has useful databases, browsers, and APIs. This adapter keeps their full tool schemas out of context until needed. Only `mcp_search` and configured pins start active. `mcp_search` discovers and loads typed tools for the next request; `mcp_search({ enable: ["gateway"] })` loads `mcp` for gateway actions, and `mcp_search({ enable: ["script"] })` loads `mcp_script` for JavaScript composition. Lazy servers stay disconnected until selected discovery or a call needs them.
20
20
 
21
21
  ## Pi release qualification
22
22
 
23
- The development baseline is official Pi **0.87.0**; host peers remain wildcard. `npm run check:compat` verifies the installed selected SDK and manifest CLI identity, builds/typechecks, runs the existing Vitest and memory-only OAuth suites, then packs and loads a runtime-only consumer through native SDK startup/reload and the actual bundled RPC CLI. Existing real reload/direct-tool tests retain their local MCP servers and cleanup assertions. The fork lane requires native checkpoint tests for both an idle adapter and a live stdio server (which must block sleep without being stopped).
23
+ The development baseline is official Pi **0.87.1**; host peers remain wildcard. `npm run check:compat` verifies the installed SDK and CLI identity, builds and typechecks, runs Vitest and memory-only OAuth tests, then loads a packed consumer through the native SDK and CLI.
24
24
 
25
- This credential-free Pi gate excludes only the separately built interactive-visualizer example's three tests. To qualify that example, retain the existing CI steps: install its dependencies, run `npm run --prefix examples/interactive-visualizer build`, then run the complete `npm test`. MCP protocol conformance remains a separate `npm run test:conformance` gate. None of these checks should read live server configs, launch an authenticated browser, or use real OAuth credentials. Use an empty HOME/agent directory and disposable working directory.
25
+ GitHub CI runs that contract on Node 24 against both official Pi and the maintained fork through the shared Pi compatibility automation, including fresh Git and npm installations loaded by the real Pi CLI. A second job checks lockfile registry hosts, published type declarations, the built interactive visualizer, and MCP protocol conformance. These checks use local MCP fixtures and disposable agent directories, never live credentials or paid providers.
26
26
 
27
27
  ## Install
28
28
 
29
- Requires Pi 0.87.0 or later and Node.js 22.19.0 or later.
29
+ Requires Pi 0.87.1 or later and Node.js 24 or later.
30
30
 
31
31
  ```bash
32
32
  pi install npm:@fitchmultz/pi-mcp-adapter
@@ -110,6 +110,8 @@ Precedence is:
110
110
  5. `.mcp.json`
111
111
  6. `.pi/fitch-mcp-adapter/mcp.json`
112
112
 
113
+ If a higher-precedence config changes a stdio server's `command`, `args`, or `cwd`, it must explicitly supply any `env` values that the new process needs; the previous definition's `env` is not inherited. An OpenCode `environment` override also replaces the previous map rather than merging its keys.
114
+
113
115
  Project layers and project-local host imports are read only after Pi marks the project trusted. Until then, the adapter uses global configuration only, does not start project-defined servers, and blocks project configuration panels and writes.
114
116
 
115
117
  `/mcp disable <server>` and `/mcp enable <server>` persist only the `disabled` field in the project-local `.pi/fitch-mcp-adapter/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.
@@ -122,7 +124,9 @@ mcp_search({ query: "take screenshot", server: "chrome-devtools" })
122
124
 
123
125
  The returned exact tool references become available with their full argument schemas on the next model request. The agent then calls the chosen typed tool normally. Discovery does not run it.
124
126
 
125
- If the host only permits `mcp`, use explicit gateway actions instead:
127
+ To use resources, authentication, UI messages, saved-result readback, or fallback calls, first load the gateway with `mcp_search({ enable: ["gateway"] })`. No query is required and enabling alone performs no integration action or remote connection. Use `enable: ["script"]` for composition, or enable both together. Normal typed search still takes just one discovery call before a typed call.
128
+
129
+ If the host only permits `mcp` (and excludes `mcp_search`), it stays eager. Use explicit gateway actions instead:
126
130
 
127
131
  ```js
128
132
  mcp({ action: "search", query: "take screenshot", server: "chrome-devtools" })
@@ -172,7 +176,7 @@ const extension = createMcpAdapter({
172
176
  // Register `extension` with the host SDK.
173
177
  ```
174
178
 
175
- 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.
179
+ The package exports compiled ESM and declarations from `dist/`, so a standalone Node process can import it directly.
176
180
 
177
181
  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.
178
182
 
@@ -270,11 +274,11 @@ For known legacy servers, set `protocolVersion: "legacy"`. This is also the work
270
274
 
271
275
  `retryOnTransportFailure` is off by default. Enabling it trusts the configured server's explicit `readOnlyHint: true` or `idempotentHint: true` tool annotations for at most one new `callTool` request on the same modern HTTP client. Annotations are retained in live/cached metadata and describe output; the live catalog takes precedence over frozen direct-tool metadata. Eligible failures are a rejected tool POST fetch before response headers arrive, an HTTP 5xx tool response without a JSON-RPC error, or an SSE response body disconnecting before its JSON-RPC response arrives. The first attempt may already have run. Fresh SDK request IDs are not idempotency keys.
272
276
 
273
- Unknown or non-idempotent tools remain callable but are never automatically redispatched after those failures. An unresolved transport failure returns internal `ambiguous_outcome` details with server/tool/call identity and readback instructions. Use the original saved arguments and the provider's supported operation/resource identity to read the prior result, then continue the remaining work; do not blindly repeat a write or rerun its whole script. Missing annotations are not permission denial. Confirmed pre-dispatch legacy-session and authentication recovery remain available.
277
+ Unknown or non-idempotent tools remain callable but are never automatically redispatched after those failures. An unresolved transport failure, interrupted JSON response body, closed connection, or cancellation/deadline while a dispatched tool request awaits its response returns internal `ambiguous_outcome` details with server/tool/call identity and readback instructions. Scripts retain these outcomes in their `calls` trace even when stopped by an overall timeout, cancellation, or early return. Use the original saved arguments and the provider's supported operation/resource identity to read the prior result, then continue the remaining work; do not blindly repeat a write or rerun its whole script. Missing annotations are not permission denial. Confirmed pre-dispatch legacy-session and authentication recovery remain available.
274
278
 
275
279
  A broken SSE body fails only the affected request, even when retries are disabled. Completed responses and later stream notifications remain intact. Native SSE resumption stays SDK-owned: a server-provided event ID lets the SDK resume the existing stream before any adapter retry.
276
280
 
277
- This transport-failure option does not retry OAuth failures, JSON-RPC errors, tool error results, invalid responses, cancellation, or expired deadlines. Permission recovery uses the separate existing `autoAuth` gate, not this option. JSON response-body failures, clean SSE endings without a response, and streams that merely stop making progress are not replayed. The original tool deadline covers SDK subrequests and retries, and modern retry never stacks with legacy expired-session recovery. Native header-schema refresh and multi-round-trip input handling remain SDK-owned.
281
+ This transport-failure option does not retry OAuth failures, JSON-RPC errors, tool error results, invalid responses, closed connections, cancellation, or expired deadlines. Permission recovery uses the separate existing `autoAuth` gate, not this option. JSON response-body failures, clean SSE endings without a response, and streams that merely stop making progress are not replayed. The original tool deadline covers SDK subrequests and retries, and modern retry never stacks with legacy expired-session recovery. Native header-schema refresh and multi-round-trip input handling remain SDK-owned.
278
282
 
279
283
  ### Server Options
280
284
 
@@ -407,6 +411,8 @@ If Pi is running on a remote server and cannot open a local browser, start OAuth
407
411
 
408
412
  On Linux, if credential access fails because Pi inherited a revoked session keyring, the adapter uses a best-effort recovery path through `keyctl session - node <packaged helper>` so explicit re-authentication can write fresh credentials without killing a long-lived tmux server. This path requires `keyctl` and `node` on `PATH`; missing, locked, or otherwise unavailable credential stores still fail closed.
409
413
 
414
+ If the gateway is inactive, first call `mcp_search({ enable: ["gateway"] })`.
415
+
410
416
  ```js
411
417
  mcp({ action: "auth-start", server: "linear-server" })
412
418
  ```
@@ -479,7 +485,7 @@ Persistent OAuth is unsupported out of the box on Android/Termux because `@napi-
479
485
  | `mcpServers.<name>.oauth.authorizationParams` | Extra authorization URL parameters for provider-specific OAuth extensions. Flow-owned parameters such as `client_id`, `redirect_uri`, `scope`, `state`, `code_challenge`, `response_type`, and `resource` cannot be overridden. |
480
486
  | `directTools` | Global default for all servers (default: false). Per-server overrides this. |
481
487
  | `freezeDirectTools` | Keep direct-tool registration stable after the initial sync so automatic reconnects and list-change notifications do not rebuild the system prompt. Use `mcp({ action: "connect", server: "server" })` or `/mcp reconnect <server>` to refresh deliberately. Default: false. |
482
- | `scriptMode` | Register the MCP-only `mcp_script` plain-JavaScript tool (default: true). Set to `false` to hide it. |
488
+ | `scriptMode` | Make the MCP-only `mcp_script` plain-JavaScript tool loadable (default: true). Set to `false` to hide it. |
483
489
  | `disableProxyTool` | Hide `mcp` once configured pinned tools are available. Legacy resource pins keep it available for resource access. |
484
490
  | `autoAuth` | Auto-run OAuth on `connect`/tool calls when a server needs auth, then retry once (default: false). |
485
491
  | `sampling` | Allow MCP servers to sample through Pi models, honoring `modelPreferences.hints` before current/default fallback (default: true when UI approval is available). |
@@ -529,7 +535,7 @@ Tune the limits with the object form:
529
535
 
530
536
  Set `"outputGuard": false` — or the env kill switch `MCP_OUTPUT_GUARD=0` — to disable the guard and restore raw output behavior. Recovery notices remain visible even when a configured cap is too small to fit them. Saved files are created with mode `0600` under the system temp directory (or the SDK host's `outputDirectory`) and are not cleaned up automatically; note that spilled MCP output may contain sensitive data.
531
537
 
532
- Read a retained result without repeating the MCP operation:
538
+ Read a retained result without repeating the MCP operation. Load the gateway first if inactive with `mcp_search({ enable: ["gateway"] })`:
533
539
 
534
540
  ```js
535
541
  mcp({ action: "read-result", ref: "/returned/result/path", path: "/structuredContent/rows", fields: ["id", "title"], offset: 0, limit: 12000 })
@@ -539,7 +545,7 @@ mcp({ action: "read-result", ref: "/returned/result/path", path: "/structuredCon
539
545
 
540
546
  ### MCP Scripting
541
547
 
542
- For multi-call MCP work, write ordinary JavaScript: discover, inspect, call, loop, filter, chain, or fan out, then return one result. Run that code with the default-on `mcp_script` tool. Use `mcp_search` for typed discovery, a loaded typed tool for a single call, and `mcp` for explicit gateway actions. Set `settings.scriptMode` to `false` to hide the scripting tool.
548
+ For multi-call MCP work, write ordinary JavaScript: discover, inspect, call, loop, filter, chain, or fan out, then return one result. Load the script tool with `mcp_search({ enable: ["script"] })`, then run that code with `mcp_script`. Use `mcp_search` for typed discovery, a loaded typed tool for a single call, and `mcp` for explicit gateway actions. Set `settings.scriptMode` to `false` to hide the scripting tool.
543
549
 
544
550
  The bundled `mcp-scripting` skill is a separate Pi package resource. To hide that skill while keeping the adapter extension installed, replace the package entry in Pi settings with the object form and disable package skills:
545
551
 
@@ -604,7 +610,7 @@ See the bundled `mcp-scripting` skill for the workflow and exact return shapes.
604
610
 
605
611
  ### MCP Resources
606
612
 
607
- Resources are catalog entries addressed by URI, separate from tools:
613
+ Resources are catalog entries addressed by URI, separate from tools. Load the gateway first if inactive with `mcp_search({ enable: ["gateway"] })`:
608
614
 
609
615
  ```js
610
616
  mcp({ action: "resources", server: "docs", limit: 12, offset: 0 })
@@ -635,9 +641,9 @@ URL mode is advertised only in TUI mode. The adapter displays the requesting ser
635
641
 
636
642
  `mcp_search({ query, server?, limit?, offset? })` searches real tools and loads the matching typed functions for the next request. It defaults to five matches, with a maximum of 100 and zero-based pagination. Use a specific query, or an empty query with `server` to browse that server. It does not execute a hit or rewrite dynamic instructions into the system prompt.
637
643
 
638
- Cached eligible schemas register inactive; only pins and tools selected for the current branch are active. The adapter persists canonical `{ server, tool }` selections in native Pi session entries and restores them across resume, reload, branch navigation, and working-directory changes. Host tool allowlists remain binding.
644
+ Cached eligible schemas and the full gateway/script definitions register inactive; only pins and tools selected for the current branch are active. Legacy resource pins keep the gateway eager. Allowed gateway/script tools also stay eager when the host excludes the loader, so restricted hosts remain usable. The adapter persists canonical `{ server, tool }` selections and enabled gateway/script features in native Pi session entries and restores them across resume, reload, branch navigation, and working-directory changes. Host tool allowlists remain binding. Manual deselection survives reload. Loaded schemas remain available rather than unloading each turn; activation changes declarations and can invalidate the prompt-cache prefix.
639
645
 
640
- On hosts with native tool-search support, lazy tools use exact references in namespace `mcp_<server>` with the original tool name as the leaf. Existing direct pins retain their flat prefixed names. On official Pi 0.87.0, the ordinary `mcp_search` loader activates flat tools with the same discover-then-call workflow. Always use the exact reference returned by discovery rather than constructing names.
646
+ On hosts with native tool-search support, lazy tools use exact references in namespace `mcp_<server>` with the original tool name as the leaf. Existing direct pins retain their flat prefixed names. On official Pi 0.87.1, which has no native tool search, the ordinary `mcp_search` loader activates flat tools with the same discover-then-call workflow. Always use the exact reference returned by discovery rather than constructing names.
641
647
 
642
648
  Typed tools may opt into native asynchronous execution only when both the host's pending-call API and the selected model route support it. Tools requiring configured approval, an MCP App UI, or the `beforeExecute` sequential checkpoint barrier keep ordinary awaited execution. This is separate from local `mcp_script` orchestration.
643
649
 
@@ -746,7 +752,7 @@ MCP servers can ship interactive UIs via [MCP Apps](https://github.com/modelcont
746
752
 
747
753
  **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.
748
754
 
749
- **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.
755
+ **Bidirectional communication:** The UI talks back. When it sends a prompt or intent, the message is stored and `triggerTurn()` wakes the agent. The agent loads the gateway if inactive with `mcp_search({ enable: ["gateway"] })`, then retrieves messages via `mcp({ action: "ui-messages" })` and responds, enabling conversational UIs where the app and agent collaborate in real-time.
750
756
 
751
757
  **Session reuse:** When the agent calls the same tool again while its UI is already open, the adapter pushes the new result to the existing window instead of replacing it. This enables live updates — the agent can refine a chart, add data, or respond to user input without losing the current view. Different tools still replace the session as before.
752
758
 
@@ -818,6 +824,7 @@ Prefer `.mcp.json` for project-local shared MCP config. Use `.pi/fitch-mcp-adapt
818
824
  | Action | Example |
819
825
  |--------|---------|
820
826
  | Discover and load typed tools | `mcp_search({ query: "screenshot", server: "chrome-devtools", limit: 5 })` |
827
+ | Load gateway / script | `mcp_search({ enable: ["gateway", "script"] })` |
821
828
  | Status | `mcp({ action: "status" })` |
822
829
  | List server tools | `mcp({ action: "list", server: "name", limit: 12, offset: 0 })` |
823
830
  | Search without activation | `mcp({ action: "search", query: "screenshot navigate", limit: 12 })` |
@@ -832,12 +839,14 @@ Prefer `.mcp.json` for project-local shared MCP config. Use `.pi/fitch-mcp-adapt
832
839
  | Auth start | `mcp({ action: "auth-start", server: "name" })` |
833
840
  | Auth complete | `mcp({ action: "auth-complete", server: "name" })` after the browser callback, or supply `args: { redirectUrl: "..." }` |
834
841
 
835
- `action` is required. Search requires `query`; describe/call require `tool`; list/connect/instructions/resources/auth require `server`; resource reads require `server` and `uri`; saved-result reads require `ref`. Pass object `args`. Optional `server` disambiguates tool calls and descriptions.
842
+ Load `mcp` first if inactive using the row above. `action` is required. Search requires `query`; describe/call require `tool`; list/connect/instructions/resources/auth require `server`; resource reads require `server` and `uri`; saved-result reads require `ref`. Pass object `args`. Optional `server` disambiguates tool calls and descriptions.
836
843
 
837
844
  `connect` refreshes an already connected server, including tools, resources, prompts, and instructions. Server-scoped discovery connects that server if its catalog is unknown. Global search uses known catalogs and returns `coverage: { complete, knownServers, unknownServers }`; partial coverage is never presented as an exhaustive result. Gateway search provides schemas without activating functions, so it works for gateway-only hosts.
838
845
 
839
846
  Search ranks names, descriptions, and parameter guidance using MiniSearch. Catalog pages use item offsets: gateway/script search and lists default to 12, while `mcp_search` defaults to 5; maximum 100. Follow the returned `nextOffset`. Saved-result readback uses character offsets instead.
840
847
 
848
+ An exact, case-sensitive public tool name ranks before lexical matches; with `server`, an exact original tool name also ranks first within that server. Unscoped original names do not select an account. All remaining matches retain MiniSearch order. Search continuation and retry calls preserve their entry point: `mcp_search` loads the next page, while gateway search remains metadata-only.
849
+
841
850
  Describe preserves the complete server descriptor, including JSON Schemas, annotations, `_meta`, and extensions when present. Search and typed-tool discovery exclude app-only tools and resources. Legacy hyphen/underscore matching remains a compatibility convenience; ambiguous names require an explicit server rather than executing an arbitrary match. Use the exact names returned by discovery.
842
851
 
843
852
  The gateway description stays stable as catalogs and credentials change. Server instructions are available through `action: "instructions"` and previews in server listings, rather than injected dynamically into the prompt.
@@ -871,7 +880,7 @@ Advertised tool `outputSchema` values support JSON Schema draft-07 and 2020-12.
871
880
 
872
881
  ## How It Works
873
882
 
874
- - Stable `mcp_search`, `mcp`, and optional `mcp_script` entry points; full typed schemas load when selected
883
+ - Eager `mcp_search`; full `mcp`, optional `mcp_script`, and typed schemas load when selected
875
884
  - Lazy servers connect on selected discovery or calls; configured pins and eager/keep-alive servers can bootstrap intentionally
876
885
  - Tool metadata is cached to disk so search/list/describe work without live connections
877
886
  - Idle servers disconnect after 10 minutes (configurable), reconnect automatically on next use