@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 +22 -0
- package/OAUTH.md +3 -3
- package/README.md +31 -15
- package/dist/app-bridge.bundle.js +13 -13
- package/dist/direct-tools.js +1 -1
- package/dist/index.js +40 -67
- package/dist/mcp-output-guard.js +1 -1
- package/dist/proxy-modes.js +11 -10
- package/dist/server-manager.js +2 -1
- package/dist/tool-loader.d.ts +11 -21
- package/dist/tool-loader.js +85 -48
- package/dist/ui-server.js +1 -1
- package/package.json +12 -12
- package/skills/mcp-scripting/SKILL.md +2 -0
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
|
|
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.
|
|
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`
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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` |
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
-
|
|
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
|