@fitchmultz/pi-mcp-adapter 7.0.0 → 7.1.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 CHANGED
@@ -7,6 +7,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [7.1.1] - 2026-10-01
11
+
12
+ ### Changed
13
+
14
+ - Update MCP Apps to 2.0.3 in the adapter and interactive visualizer, keeping their dependency graphs aligned.
15
+ - Qualify development against official Pi 0.99.2 and the current maintained fork, keeping host peers wildcard and the declared Pi/Node floors unchanged.
16
+ - Update development validation to Vitest 5.0.3 and npm 12.2.0.
17
+ - Use current public Pi tool activation and request-boundary scheduling APIs, preserving authentication, approval, and checkpoint barriers.
18
+
19
+ ### Fixed
20
+
21
+ - Keep development TypeBox aligned with the official Pi baseline and block standalone updates that load a second version during source startup.
22
+ - Upgrade the split MCP client, core, and server SDKs together to 2.2.0 in the adapter and interactive visualizer. Native discovery now retains changing catalog pages that reuse an opaque cursor instead of silently dropping later tools.
23
+ - Bound native catalog walks, including automatic refreshes, to 1,024 pages and reject oversized or nonterminating catalogs without publishing partial results.
24
+
25
+ ## [7.1.0] - 2026-09-27
26
+
27
+ ### Changed
28
+
29
+ - 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.
30
+ - `npm run typecheck` now also checks the test suite under the same strict settings as the source.
31
+
10
32
  ## [7.0.0] - 2026-09-26
11
33
 
12
34
  ### 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" })
@@ -413,7 +413,7 @@ The OAuth implementation uses the following modules:
413
413
 
414
414
  ## Issuer compatibility
415
415
 
416
- SDK 2.0.0 checks that authorization-server metadata returns the issuer advertised by discovery. Some providers advertise a path-scoped issuer but return the origin instead. If the provider cannot be corrected, explicitly opt out for that server only:
416
+ SDK v2 checks that authorization-server metadata returns the issuer advertised by discovery. Some providers advertise a path-scoped issuer but return the origin instead. If the provider cannot be corrected, explicitly opt out for that server only:
417
417
 
418
418
  ```json
419
419
  {
@@ -431,7 +431,7 @@ The default remains strict, including when `protocolVersion` is `"legacy"`. The
431
431
 
432
432
  ## SDK Integration
433
433
 
434
- The implementation uses the official split MCP SDK v2 client and OAuth APIs. SDK v1 remains installed only because the current MCP Apps package requires it:
434
+ The implementation uses the official split MCP SDK v2 client and OAuth APIs. MCP Apps also uses this split SDK graph; SDK v1 is not a runtime dependency:
435
435
 
436
436
  ```typescript
437
437
  import { StreamableHTTPClientTransport } from "@modelcontextprotocol/client"
package/README.md CHANGED
@@ -16,14 +16,16 @@ 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.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.
23
+ The development baseline is official Pi **0.99.2**; host peers remain wildcard and the declared Pi/Node floors are unchanged. Current-host checks do not requalify older Pi versions. `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
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
+ Keep the development TypeBox pin aligned with the official Pi baseline's dependency, updating it only with that cohort. Standalone TypeBox updates are disabled: a second version in source installs adds measurable startup cost. Published peers remain optional wildcard dependencies, and qualification selects each host's actual TypeBox version.
28
+
27
29
  ## Install
28
30
 
29
31
  Requires Pi 0.87.1 or later and Node.js 24 or later.
@@ -34,6 +36,13 @@ pi install npm:@fitchmultz/pi-mcp-adapter
34
36
 
35
37
  Or install from Git: `pi install git:github.com/fitchmultz/pi-mcp-adapter`.
36
38
 
39
+ On **Android/Termux**, Git/source installs and type checks require an Android-native
40
+ TypeScript 7 compiler as `tsgo` on `PATH`. The [Fold development environment](https://github.com/fitchmultz/fold-dev-environment)
41
+ provides a pinned native build (validated with `7.1.0-dev.20260904.1`). npm's TypeScript
42
+ package has no Android binary, and its Linux binary probes a syscall Android blocks.
43
+ macOS/Linux use the package-local pinned compiler. Published precompiled packages
44
+ do not need a compiler at runtime.
45
+
37
46
  Restart Pi after installation. Existing v4 users should migrate first.
38
47
 
39
48
  ### Upgrading from v5
@@ -124,7 +133,9 @@ mcp_search({ query: "take screenshot", server: "chrome-devtools" })
124
133
 
125
134
  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.
126
135
 
127
- If the host only permits `mcp`, use explicit gateway actions instead:
136
+ 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.
137
+
138
+ If the host only permits `mcp` (and excludes `mcp_search`), it stays eager. Use explicit gateway actions instead:
128
139
 
129
140
  ```js
130
141
  mcp({ action: "search", query: "take screenshot", server: "chrome-devtools" })
@@ -256,7 +267,9 @@ In the configuration examples below, `30000` is illustrative only. If `requestTi
256
267
 
257
268
  ### Transport compatibility
258
269
 
259
- The adapter uses official split MCP SDK 2.0.0. HTTP connections automatically negotiate protocol `2026-07-28` and fall back to older revisions using the SDK's native rules. The SDK generates protocol metadata, method/name headers, and schema-driven `Mcp-Param-*` headers. Modern HTTP supports streamed POST responses without opening a legacy standalone GET stream. Deprecated SSE is tried only when the Streamable HTTP handshake rejects the endpoint with HTTP 404, 405, 406, or 415—not after a timeout, network failure, or authentication failure.
270
+ The adapter uses official split MCP SDK 2.2.0. HTTP connections automatically negotiate protocol `2026-07-28` and fall back to older revisions using the SDK's native rules. The SDK generates protocol metadata, method/name headers, and schema-driven `Mcp-Param-*` headers. Modern HTTP supports streamed POST responses without opening a legacy standalone GET stream. Deprecated SSE is tried only when the Streamable HTTP handshake rejects the endpoint with HTTP 404, 405, 406, or 415—not after a timeout, network failure, or authentication failure.
271
+
272
+ Native catalog discovery follows changing pages even when their opaque cursor repeats. Catalogs exceeding 1,024 pages fail explicitly instead of publishing a partial list or walking indefinitely; this also bounds automatic catalog refreshes.
260
273
 
261
274
  For known legacy servers, set `protocolVersion: "legacy"`. This is also the workaround for servers that answer `server/discover` with an HTTP 200 JSON-RPC error whose `id` is `null`: SDK 2.0.0 cannot negotiate that response. The adapter reports the native failure rather than inventing authentication guidance or overriding the SDK's fallback classifier. Stdio and Unix sockets remain legacy by default. Explicit `"auto"` on native stdio uses the SDK's disposable probe process before starting the session process.
262
275
 
@@ -409,6 +422,8 @@ If Pi is running on a remote server and cannot open a local browser, start OAuth
409
422
 
410
423
  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.
411
424
 
425
+ If the gateway is inactive, first call `mcp_search({ enable: ["gateway"] })`.
426
+
412
427
  ```js
413
428
  mcp({ action: "auth-start", server: "linear-server" })
414
429
  ```
@@ -481,7 +496,7 @@ Persistent OAuth is unsupported out of the box on Android/Termux because `@napi-
481
496
  | `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. |
482
497
  | `directTools` | Global default for all servers (default: false). Per-server overrides this. |
483
498
  | `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. |
484
- | `scriptMode` | Register the MCP-only `mcp_script` plain-JavaScript tool (default: true). Set to `false` to hide it. |
499
+ | `scriptMode` | Make the MCP-only `mcp_script` plain-JavaScript tool loadable (default: true). Set to `false` to hide it. |
485
500
  | `disableProxyTool` | Hide `mcp` once configured pinned tools are available. Legacy resource pins keep it available for resource access. |
486
501
  | `autoAuth` | Auto-run OAuth on `connect`/tool calls when a server needs auth, then retry once (default: false). |
487
502
  | `sampling` | Allow MCP servers to sample through Pi models, honoring `modelPreferences.hints` before current/default fallback (default: true when UI approval is available). |
@@ -531,7 +546,7 @@ Tune the limits with the object form:
531
546
 
532
547
  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.
533
548
 
534
- Read a retained result without repeating the MCP operation:
549
+ Read a retained result without repeating the MCP operation. Load the gateway first if inactive with `mcp_search({ enable: ["gateway"] })`:
535
550
 
536
551
  ```js
537
552
  mcp({ action: "read-result", ref: "/returned/result/path", path: "/structuredContent/rows", fields: ["id", "title"], offset: 0, limit: 12000 })
@@ -541,7 +556,7 @@ mcp({ action: "read-result", ref: "/returned/result/path", path: "/structuredCon
541
556
 
542
557
  ### MCP Scripting
543
558
 
544
- 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.
559
+ 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.
545
560
 
546
561
  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:
547
562
 
@@ -606,7 +621,7 @@ See the bundled `mcp-scripting` skill for the workflow and exact return shapes.
606
621
 
607
622
  ### MCP Resources
608
623
 
609
- Resources are catalog entries addressed by URI, separate from tools:
624
+ Resources are catalog entries addressed by URI, separate from tools. Load the gateway first if inactive with `mcp_search({ enable: ["gateway"] })`:
610
625
 
611
626
  ```js
612
627
  mcp({ action: "resources", server: "docs", limit: 12, offset: 0 })
@@ -637,11 +652,11 @@ URL mode is advertised only in TUI mode. The adapter displays the requesting ser
637
652
 
638
653
  `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.
639
654
 
640
- 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.
655
+ 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.
641
656
 
642
- 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.
657
+ Both official Pi and the maintained fork use public tool registration and active-tool APIs. Discovered tools retain their flat prefixed names, with `mcp_<server>` namespace metadata for grouping. Always use the exact name returned by discovery rather than constructing names. Inactive tools are not exposed through deferred/codemode execution; loading them still requires the same allowlist and selection checks.
643
658
 
644
- 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.
659
+ Tool execution uses Pi's public request-boundary scheduling, not retired native async or pending-call APIs. Configured approval, MCP App UI consent, and the `beforeExecute` sequential checkpoint barrier remain binding. This is separate from local `mcp_script` orchestration.
645
660
 
646
661
  Add `directTools` to pin frequently used tools into the initial active set:
647
662
 
@@ -737,7 +752,7 @@ Run `/mcp` to see known tools, pinned counts, resource counts, and connection st
737
752
 
738
753
  ### MCP UI Integration
739
754
 
740
- MCP servers can ship interactive UIs via [MCP Apps](https://github.com/modelcontextprotocol/ext-apps). The adapter uses MCP Apps 2.0.0 with the split MCP SDK 2.0.0 runtime. When you call a tool that has a UI resource, the adapter opens it in a native macOS window via [Glimpse](https://github.com/hazat/glimpse) if available, otherwise falls back to the browser.
755
+ MCP servers can ship interactive UIs via [MCP Apps](https://github.com/modelcontextprotocol/ext-apps). The adapter uses MCP Apps 2.0.3. When you call a tool that has a UI resource, the adapter opens it in a native macOS window via [Glimpse](https://github.com/hazat/glimpse) if available, otherwise falls back to the browser.
741
756
 
742
757
  **How it works:**
743
758
 
@@ -748,7 +763,7 @@ MCP servers can ship interactive UIs via [MCP Apps](https://github.com/modelcont
748
763
 
749
764
  **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.
750
765
 
751
- **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.
766
+ **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.
752
767
 
753
768
  **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.
754
769
 
@@ -820,6 +835,7 @@ Prefer `.mcp.json` for project-local shared MCP config. Use `.pi/fitch-mcp-adapt
820
835
  | Action | Example |
821
836
  |--------|---------|
822
837
  | Discover and load typed tools | `mcp_search({ query: "screenshot", server: "chrome-devtools", limit: 5 })` |
838
+ | Load gateway / script | `mcp_search({ enable: ["gateway", "script"] })` |
823
839
  | Status | `mcp({ action: "status" })` |
824
840
  | List server tools | `mcp({ action: "list", server: "name", limit: 12, offset: 0 })` |
825
841
  | Search without activation | `mcp({ action: "search", query: "screenshot navigate", limit: 12 })` |
@@ -834,7 +850,7 @@ Prefer `.mcp.json` for project-local shared MCP config. Use `.pi/fitch-mcp-adapt
834
850
  | Auth start | `mcp({ action: "auth-start", server: "name" })` |
835
851
  | Auth complete | `mcp({ action: "auth-complete", server: "name" })` after the browser callback, or supply `args: { redirectUrl: "..." }` |
836
852
 
837
- `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.
853
+ 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.
838
854
 
839
855
  `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.
840
856
 
@@ -875,7 +891,7 @@ Advertised tool `outputSchema` values support JSON Schema draft-07 and 2020-12.
875
891
 
876
892
  ## How It Works
877
893
 
878
- - Stable `mcp_search`, `mcp`, and optional `mcp_script` entry points; full typed schemas load when selected
894
+ - Eager `mcp_search`; full `mcp`, optional `mcp_script`, and typed schemas load when selected
879
895
  - Lazy servers connect on selected discovery or calls; configured pins and eager/keep-alive servers can bootstrap intentionally
880
896
  - Tool metadata is cached to disk so search/list/describe work without live connections
881
897
  - Idle servers disconnect after 10 minutes (configurable), reconnect automatically on next use