@fitchmultz/pi-mcp-adapter 5.0.0 → 6.0.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.
- package/CHANGELOG.md +25 -1
- package/OAUTH.md +3 -3
- package/README.md +153 -85
- package/app-bridge.bundle.js +75 -33
- package/commands.ts +9 -6
- package/direct-tools.ts +25 -358
- package/dist/app-bridge.bundle.js +75 -33
- package/dist/commands.js +9 -6
- package/dist/direct-tools.d.ts +2 -4
- package/dist/direct-tools.js +21 -319
- package/dist/gateway-arguments.d.ts +33 -0
- package/dist/gateway-arguments.js +63 -0
- package/dist/index.js +181 -276
- package/dist/init.js +6 -20
- package/dist/mcp-code.d.ts +2 -1
- package/dist/mcp-code.js +87 -41
- package/dist/mcp-output-guard.d.ts +57 -2
- package/dist/mcp-output-guard.js +129 -24
- package/dist/mcp-panel.d.ts +1 -1
- package/dist/mcp-panel.js +34 -97
- package/dist/mcp-script-worker.mjs +5 -2
- package/dist/mcp-status.js +2 -1
- package/dist/metadata-cache.d.ts +1 -1
- package/dist/metadata-cache.js +25 -88
- package/dist/prompts.d.ts +1 -1
- package/dist/prompts.js +1 -1
- package/dist/proxy-modes.d.ts +40 -6
- package/dist/proxy-modes.js +270 -485
- package/dist/resource-tools.d.ts +15 -0
- package/dist/resource-tools.js +26 -1
- package/dist/sampling-handler.js +4 -1
- package/dist/search-ranking.d.ts +0 -2
- package/dist/search-ranking.js +66 -137
- package/dist/state.d.ts +1 -1
- package/dist/tool-loader.d.ts +32 -0
- package/dist/tool-loader.js +152 -0
- package/dist/tool-metadata.d.ts +67 -0
- package/dist/tool-metadata.js +23 -17
- package/dist/tool-registrar.d.ts +4 -4
- package/dist/tool-registrar.js +18 -13
- package/dist/tool-result-renderer.d.ts +3 -0
- package/dist/tool-result-renderer.js +8 -3
- package/dist/types.d.ts +11 -36
- package/dist/utils.js +2 -4
- package/gateway-arguments.ts +73 -0
- package/index.ts +166 -299
- package/init.ts +6 -20
- package/mcp-code.ts +71 -45
- package/mcp-output-guard.ts +145 -27
- package/mcp-panel.ts +38 -109
- package/mcp-script-worker.mjs +5 -2
- package/mcp-status.ts +2 -1
- package/metadata-cache.ts +31 -93
- package/package.json +14 -9
- package/prompts.ts +1 -1
- package/proxy-modes.ts +265 -517
- package/resource-tools.ts +36 -1
- package/sampling-handler.ts +4 -1
- package/scripts/build-app-bridge.mjs +15 -0
- package/scripts/build.mjs +3 -2
- package/scripts/prepare.mjs +1 -0
- package/search-ranking.ts +71 -135
- package/skills/mcp-scripting/SKILL.md +67 -20
- package/state.ts +1 -1
- package/tool-loader.ts +153 -0
- package/tool-metadata.ts +22 -17
- package/tool-registrar.ts +18 -13
- package/tool-result-renderer.ts +10 -2
- package/types.ts +15 -40
- package/utils.ts +2 -4
- package/dist/ts-shape.d.ts +0 -2
- package/dist/ts-shape.js +0 -147
- package/ts-shape.ts +0 -145
package/CHANGELOG.md
CHANGED
|
@@ -5,7 +5,31 @@ 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
|
-
## [
|
|
8
|
+
## [6.0.0] - 2026-09-22
|
|
9
|
+
|
|
10
|
+
### Breaking changes
|
|
11
|
+
|
|
12
|
+
- New gateway calls require an explicit `action` (`status`, `search`, `list`, `describe`, `call`, `connect`, `instructions`, `resources`, `read-resource`, `read-result`, `auth-start`, `auth-complete`, or `ui-messages`) and object arguments. Stored v5 optional-mode calls and JSON-string arguments are normalized only at ingress.
|
|
13
|
+
- `mcp_search` discovers and loads full typed tool schemas for the next request, without executing a hit. `directTools` pins the initial active set; other eligible tools remain available for later discovery. Host tool allowlists and `MCP_DIRECT_TOOLS=__none__` remain binding.
|
|
14
|
+
- Resources are listed and read explicitly by server and URI, not registered as synthetic functions. The panel shows separate resource counts and only real-tool pin choices. Legacy resource aliases remain gateway/script-callable; old resource pins keep the gateway available even with `disableProxyTool` enabled.
|
|
15
|
+
- Script `tools.describe` preserves complete JSON Schema and raw descriptor fields rather than returning `inputTypeScript`. Update consumers to use `inputSchema` and optional `outputSchema`.
|
|
16
|
+
- Cold caches no longer trigger connections to every lazy server. Global search reports partial catalog coverage; selected server discovery, configured pins, and eager/keep-alive startup remain intentional connection paths.
|
|
17
|
+
- Metadata cache format 2 preserves raw tool/resource descriptors and reads legacy format 1. Downgrading to v5 ignores format 2 and requires rediscovery. Config paths and the OAuth namespace are unchanged from v5; see [migration](README.md#upgrading-from-v5).
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- Branch-scoped typed-tool selection in native Pi session entries, restored on resume, reload, tree navigation, and working-directory changes. Optional native tool-search hosts use exact namespaced lazy references; official Pi 0.87.0 uses the ordinary loader with the same discover-then-call workflow. Existing pins keep flat names.
|
|
22
|
+
- Conditional native asynchronous execution for typed tools when the host and selected model route both support it, excluding configured approval, MCP App UI, and sequential checkpoint flows.
|
|
23
|
+
- Gateway `resources`, `read-resource`, and `read-result` actions; script `tools.resources`, `tools.readResource`, and `tools.readResult` methods. Resource access retains exposure, filtering, authentication, and approval policy.
|
|
24
|
+
- Model-visible references to retained raw results for structured, media, resource, oversized, and extra-field payloads. Saved-result readback selects JSON Pointers/fields before bounded character paging and never repeats a server call. Artifacts respect the SDK host's `outputDirectory`.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Search uses MiniSearch over tool names, descriptions, and parameter guidance. Discovery and descriptions retain canonical descriptors, including output schemas, annotations, and `_meta`; app-only tools stay hidden from the model and panel.
|
|
29
|
+
- Typed, gateway, and script calls share dispatch, authentication, approvals, and call capture. Scripts receive raw MCP results, including error-result data, without rendering unused text artifacts. Tiny plain-text results remain inline.
|
|
30
|
+
- Render `structuredContent` alongside content blocks instead of suppressing it when text or images are present. Existing output byte/line limits still bound model-facing text.
|
|
31
|
+
- MCP Apps uses 2.0.0 alongside the split MCP SDK 2.0.0 runtime, removing the runtime SDK 1 dependency.
|
|
32
|
+
- Panel and command status distinguish real tools, resources, startup pins, and undiscovered catalogs while retaining authentication, reconnect, and error controls.
|
|
9
33
|
|
|
10
34
|
## [5.0.0] - 2026-09-19
|
|
11
35
|
|
package/OAUTH.md
CHANGED
|
@@ -231,7 +231,7 @@ mcp({
|
|
|
231
231
|
})
|
|
232
232
|
```
|
|
233
233
|
|
|
234
|
-
You can also pass only the `code` query parameter with `args: { code: "..." }`. JSON-string
|
|
234
|
+
You can also pass only the `code` query parameter with `args: { code: "..." }`. Use object arguments; JSON-string arguments are accepted only by the stored-v5-call ingress compatibility path. Redirect URL completion validates the saved OAuth state; raw code completion is available for providers that display a code directly.
|
|
235
235
|
|
|
236
236
|
### Newly required permissions
|
|
237
237
|
|
|
@@ -248,8 +248,8 @@ Auth-only connection replacement lets accepted native operations finish on the o
|
|
|
248
248
|
Once authenticated, use the server normally:
|
|
249
249
|
|
|
250
250
|
```
|
|
251
|
-
mcp({ server: "my-oauth-server" })
|
|
252
|
-
mcp({ tool: "my-tool", args: { key: "value" } })
|
|
251
|
+
mcp({ action: "list", server: "my-oauth-server" })
|
|
252
|
+
mcp({ action: "call", server: "my-oauth-server", tool: "my-tool", args: { key: "value" } })
|
|
253
253
|
```
|
|
254
254
|
|
|
255
255
|
The SDK automatically:
|
package/README.md
CHANGED
|
@@ -16,11 +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
|
-
|
|
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.
|
|
20
|
+
|
|
21
|
+
## Pi release qualification
|
|
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).
|
|
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.
|
|
20
26
|
|
|
21
27
|
## Install
|
|
22
28
|
|
|
23
|
-
Requires Pi 0.
|
|
29
|
+
Requires Pi 0.87.0 or later and Node.js 22.19.0 or later.
|
|
24
30
|
|
|
25
31
|
```bash
|
|
26
32
|
pi install npm:@fitchmultz/pi-mcp-adapter
|
|
@@ -30,9 +36,19 @@ Or install from Git: `pi install git:github.com/fitchmultz/pi-mcp-adapter`.
|
|
|
30
36
|
|
|
31
37
|
Restart Pi after installation. Existing v4 users should migrate first.
|
|
32
38
|
|
|
39
|
+
### Upgrading from v5
|
|
40
|
+
|
|
41
|
+
Version 6 keeps v5's package, config paths, and OAuth namespace. No credential migration is needed.
|
|
42
|
+
|
|
43
|
+
- Use `mcp_search({ query: "...", server: "name" })` to discover and load typed tools. It loads matches for the next request; it never executes a search hit. `directTools` now pins tools at startup rather than deciding which tools can ever be loaded.
|
|
44
|
+
- Give every new gateway call an explicit `action`: `mcp({ action: "search", query: "..." })`, `mcp({ action: "describe", tool: "..." })`, or `mcp({ action: "call", tool: "...", args: {} })`. Arguments are objects. Stored v5 calls with optional mode fields or JSON-string arguments are normalized at the ingress compatibility boundary; they are not the advertised v6 interface.
|
|
45
|
+
- Resources use `resources` and `read-resource` actions, or `tools.resources` and `tools.readResource` in scripts. Generated `read_<resource>` aliases remain callable through gateway/script compatibility, but no longer appear as functions or panel checkboxes. Remove resource aliases from `directTools`; legacy resource pins keep the gateway available even with `disableProxyTool: true`.
|
|
46
|
+
- Script descriptions always return complete JSON Schema in `inputSchema`, with `outputSchema` and other descriptor fields when supplied. Replace `inputTypeScript` consumers. Calls keep raw MCP results, including error-result data; use returned result references for bounded readback without another server call.
|
|
47
|
+
- Global search reports partial catalog coverage instead of starting every uncached lazy server. Select a server to discover it. Cache format 2 preserves raw descriptors and still reads format 1; downgrading to v5 ignores format 2 and requires rediscovery.
|
|
48
|
+
|
|
33
49
|
### Upgrading from v4
|
|
34
50
|
|
|
35
|
-
|
|
51
|
+
The Fitch distribution uses its own package, state paths and OAuth credential namespace. Remove the previous adapter package entry from Pi settings (for example, `pi remove npm:pi-mcp-adapter` for the unscoped npm source), then install the distribution above. Keep only one adapter loaded in a Pi host.
|
|
36
52
|
|
|
37
53
|
After installation, **before restarting Pi**, run from your project directory:
|
|
38
54
|
|
|
@@ -98,26 +114,23 @@ Project layers and project-local host imports are read only after Pi marks the p
|
|
|
98
114
|
|
|
99
115
|
`/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.
|
|
100
116
|
|
|
101
|
-
Servers are **lazy by default
|
|
117
|
+
Servers are **lazy by default**. Cached tool descriptors can be searched without a live connection. To discover an uncached server and load the tools relevant to a task:
|
|
102
118
|
|
|
119
|
+
```js
|
|
120
|
+
mcp_search({ query: "take screenshot", server: "chrome-devtools" })
|
|
103
121
|
```
|
|
104
|
-
mcp({ search: "screenshot" })
|
|
105
|
-
```
|
|
106
|
-
```
|
|
107
|
-
chrome_devtools_take_screenshot
|
|
108
|
-
Take a screenshot of the page or element.
|
|
109
122
|
|
|
110
|
-
|
|
111
|
-
format (enum: "png", "jpeg", "webp") [default: "png"]
|
|
112
|
-
fullPage (boolean) - Full page instead of viewport
|
|
113
|
-
```
|
|
114
|
-
```
|
|
115
|
-
mcp({ tool: "chrome_devtools_take_screenshot", args: { format: "png" } })
|
|
116
|
-
```
|
|
123
|
+
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.
|
|
117
124
|
|
|
118
|
-
|
|
125
|
+
If the host only permits `mcp`, use explicit gateway actions instead:
|
|
119
126
|
|
|
120
|
-
|
|
127
|
+
```js
|
|
128
|
+
mcp({ action: "search", query: "take screenshot", server: "chrome-devtools" })
|
|
129
|
+
mcp({ action: "describe", tool: "chrome_devtools_take_screenshot" })
|
|
130
|
+
mcp({ action: "call", tool: "chrome_devtools_take_screenshot", args: { format: "png" } })
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Gateway search returns schemas without activating direct tools. All paths preserve the same authentication, approval, and call-capture behavior.
|
|
121
134
|
|
|
122
135
|
## Config
|
|
123
136
|
|
|
@@ -223,7 +236,7 @@ Before any asynchronous flush, the adapter fences owned activity and pauses its
|
|
|
223
236
|
|
|
224
237
|
### Runtime status snapshots
|
|
225
238
|
|
|
226
|
-
Extensions can subscribe to the adapter's versioned shared event-bus channel instead of parsing `/mcp` or `mcp({})` output:
|
|
239
|
+
Extensions can subscribe to the adapter's versioned shared event-bus channel instead of parsing `/mcp` or `mcp({ action: "status" })` output:
|
|
227
240
|
|
|
228
241
|
```ts
|
|
229
242
|
import { MCP_STATUS_EVENT, type McpStatusSnapshot } from "@fitchmultz/pi-mcp-adapter";
|
|
@@ -235,7 +248,7 @@ pi.events.on(MCP_STATUS_EVENT, (snapshot) => {
|
|
|
235
248
|
});
|
|
236
249
|
```
|
|
237
250
|
|
|
238
|
-
`MCP_STATUS_EVENT` is `fitch-mcp-adapter/status/v1`. The snapshot is read-only machine-readable data with copied per-server entries. It includes `totalTools`, `totalResources`, `connectedCount`, and `disabledCount`; each server includes `name`, `status`, `toolCount`, and `disabled`, with `resourceCount` when known and `failedAgoSeconds` only for an active failure. Reading status never connects a lazy server, starts authentication, or exposes SDK clients, transports, credentials, or server definitions. An initial snapshot is emitted after initialization, updates are emitted for status and metadata changes, and an empty snapshot is emitted when the session shuts down.
|
|
251
|
+
`MCP_STATUS_EVENT` is `fitch-mcp-adapter/status/v1`. The snapshot is read-only machine-readable data with copied per-server entries. It includes `totalTools`, `totalResources`, `connectedCount`, and `disabledCount`; each server includes `name`, `status`, `toolCount`, and `disabled`, with `resourceCount` when known, `catalogKnown` indicating whether discovery has completed, and `failedAgoSeconds` only for an active failure. An unknown catalog is not a confirmed zero-tool server. Reading status never connects a lazy server, starts authentication, or exposes SDK clients, transports, credentials, or server definitions. An initial snapshot is emitted after initialization, updates are emitted for status and metadata changes, and an empty snapshot is emitted when the session shuts down.
|
|
239
252
|
|
|
240
253
|
In the configuration examples below, `30000` is illustrative only. If `requestTimeoutMs` is omitted or set to `<= 0`, the MCP SDK default timeout is used.
|
|
241
254
|
|
|
@@ -306,10 +319,10 @@ This transport-failure option does not retry OAuth failures, JSON-RPC errors, to
|
|
|
306
319
|
| `lifecycle` | `"lazy"` (default), `"eager"`, `"keep-alive"`, or `"lazy-keep-alive"` |
|
|
307
320
|
| `idleTimeout` | Minutes before idle disconnect (overrides global) |
|
|
308
321
|
| `requestTimeoutMs` | Request timeout in milliseconds for live MCP calls (overrides global; if omitted or `<= 0`, the MCP SDK default timeout is used) |
|
|
309
|
-
| `exposeResources` |
|
|
310
|
-
| `directTools` | `true`, `string[]`, or `false` —
|
|
322
|
+
| `exposeResources` | Make MCP resources available through resource listing/reading (default: true) |
|
|
323
|
+
| `directTools` | `true`, `string[]`, or `false` — pin real tools into the initial active tool set |
|
|
311
324
|
| `toolPrefix` | Override global `settings.toolPrefix` for this server (`"server"`, `"short"`, `"none"`, or `"mcp"`) |
|
|
312
|
-
| `includeTools` | `string[]` of tool names or glob patterns to expose (matches original names like `get_screenshot`,
|
|
325
|
+
| `includeTools` | `string[]` of tool names or glob patterns to expose (matches original names like `get_screenshot`, legacy resource filter aliases like `read_figjam`, and prefixed names like `figma_get_screenshot`) |
|
|
313
326
|
| `excludeTools` | `string[]` of tool names or glob patterns to hide (applied after `includeTools`) |
|
|
314
327
|
| `debug` | Show server stderr (default: false) |
|
|
315
328
|
| `trace` | Enable metadata-only JSONL protocol tracing for this server; payloads, prompts, tool arguments/results, authorization data, and URLs are never persisted |
|
|
@@ -424,10 +437,10 @@ Persistent OAuth is unsupported out of the box on Android/Termux because `@napi-
|
|
|
424
437
|
|
|
425
438
|
### Lifecycle Modes
|
|
426
439
|
|
|
427
|
-
- **`lazy`** (default) —
|
|
440
|
+
- **`lazy`** (default) — Connect on selected discovery or first call, then disconnect after idle timeout. Cached metadata keeps search/list working without connections. Configured pins can intentionally discover their server at startup.
|
|
428
441
|
- **`eager`** — Connect at startup but don't auto-reconnect if the connection drops. No idle timeout by default (set `idleTimeout` explicitly to enable).
|
|
429
442
|
- **`keep-alive`** — Connect at startup. Auto-reconnect via health checks. No idle timeout. Use for servers you always need available.
|
|
430
|
-
- **`lazy-keep-alive`** —
|
|
443
|
+
- **`lazy-keep-alive`** — Connect on selected discovery or first call (like `lazy`); configured pins can discover it at startup. 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.
|
|
431
444
|
|
|
432
445
|
### Settings
|
|
433
446
|
|
|
@@ -465,9 +478,9 @@ Persistent OAuth is unsupported out of the box on Android/Termux because `@napi-
|
|
|
465
478
|
| `oauthDir` | Parent directory for legacy OAuth imports. Runtime uses its `fitch-mcp-adapter/` child; explicit v4 migration reads the original directory. Relative paths resolve from the active project cwd. `FITCH_MCP_OAUTH_DIR` overrides the final runtime import path; the old `MCP_OAUTH_DIR` is read only by explicit migration. Persistent credentials live in the OS credential store. |
|
|
466
479
|
| `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. |
|
|
467
480
|
| `directTools` | Global default for all servers (default: false). Per-server overrides this. |
|
|
468
|
-
| `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({ connect: "server" })` or `/mcp reconnect <server>` to refresh deliberately. Default: false. |
|
|
481
|
+
| `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. |
|
|
469
482
|
| `scriptMode` | Register the MCP-only `mcp_script` plain-JavaScript tool (default: true). Set to `false` to hide it. |
|
|
470
|
-
| `disableProxyTool` | Hide
|
|
483
|
+
| `disableProxyTool` | Hide `mcp` once configured pinned tools are available. Legacy resource pins keep it available for resource access. |
|
|
471
484
|
| `autoAuth` | Auto-run OAuth on `connect`/tool calls when a server needs auth, then retry once (default: false). |
|
|
472
485
|
| `sampling` | Allow MCP servers to sample through Pi models, honoring `modelPreferences.hints` before current/default fallback (default: true when UI approval is available). |
|
|
473
486
|
| `samplingAutoApprove` | Skip sampling confirmation prompts. Required for sampling in non-UI sessions (default: false). |
|
|
@@ -501,7 +514,8 @@ Oversized MCP tool/resource results are guarded by default so a single huge resp
|
|
|
501
514
|
|
|
502
515
|
- Inline text output is capped at **50 KiB / 2,000 lines** (matching Pi's built-in `bash` guard). Larger output is truncated to a head preview and the full text is saved to a temp file whose path is included in the result, so the agent can `read`/`grep` it.
|
|
503
516
|
- **Image content blocks pass through unchanged** — only text output is guarded. Images are delivered to the provider as native image content.
|
|
504
|
-
- In
|
|
517
|
+
- In gateway and direct modes, `details.mcpResult` is kept raw when its JSON is **≤ 16 KiB**; larger results use a compact summary and retain the full raw JSON in a file. Scripts receive the raw result before model-facing rendering, so they can reduce it without creating an unused text preview.
|
|
518
|
+
- Structured data, media, resources, extra protocol fields, and oversized results include a model-visible **result reference** to the saved raw result. Tiny plain-text results remain inline without an artifact. `structuredContent` is shown even when the server also returns content blocks.
|
|
505
519
|
|
|
506
520
|
Tune the limits with the object form:
|
|
507
521
|
|
|
@@ -513,11 +527,19 @@ Tune the limits with the object form:
|
|
|
513
527
|
}
|
|
514
528
|
```
|
|
515
529
|
|
|
516
|
-
Set `"outputGuard": false` — or the env kill switch `MCP_OUTPUT_GUARD=0` — to disable the guard and restore raw output behavior. 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.
|
|
530
|
+
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
|
+
|
|
532
|
+
Read a retained result without repeating the MCP operation:
|
|
533
|
+
|
|
534
|
+
```js
|
|
535
|
+
mcp({ action: "read-result", ref: "/returned/result/path", path: "/structuredContent/rows", fields: ["id", "title"], offset: 0, limit: 12000 })
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
`path` is an RFC 6901 JSON Pointer; `fields` keeps immediate keys on the selected object or each object in an array. Selection happens before paging. `offset` and `limit` count **characters in the selected, pretty-printed JSON**, starting at zero—not rows, lines, or bytes. Readback defaults to 12,000 characters and remains bounded by the output byte/line caps. Continue with `details.nextOffset` until it is `null`. Readback requires an existing adapter output artifact in this host's output directory; it never calls the server again. The same operation is available as `tools.readResult` in scripts.
|
|
517
539
|
|
|
518
540
|
### MCP Scripting
|
|
519
541
|
|
|
520
|
-
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.
|
|
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.
|
|
521
543
|
|
|
522
544
|
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:
|
|
523
545
|
|
|
@@ -531,29 +553,65 @@ The bundled `mcp-scripting` skill is a separate Pi package resource. To hide tha
|
|
|
531
553
|
|
|
532
554
|
Preserve any version pin in `source` if your existing package entry has one. You can also disable package resources through `pi config`.
|
|
533
555
|
|
|
534
|
-
|
|
556
|
+
First inspect candidate schemas. This script discovers and describes without executing a search hit:
|
|
535
557
|
|
|
536
558
|
```js
|
|
537
|
-
const
|
|
538
|
-
|
|
539
|
-
|
|
559
|
+
const found = await tools.search({ query: "search issues", server: "github" });
|
|
560
|
+
if (found.error) return found;
|
|
561
|
+
emit(found.coverage);
|
|
562
|
+
for (const item of found.items) {
|
|
563
|
+
emit(await tools.describe({ path: item.path, server: item.server }));
|
|
564
|
+
}
|
|
565
|
+
```
|
|
540
566
|
|
|
541
|
-
|
|
542
|
-
if (details.error) return details;
|
|
567
|
+
After choosing a tool and checking its schema, pass ordinary JavaScript as `mcp_script`'s `code` argument:
|
|
543
568
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
569
|
+
```js
|
|
570
|
+
const results = [];
|
|
571
|
+
for (const query of ["is:open label:bug", "is:open label:docs"]) {
|
|
572
|
+
const result = await tools.call("github_search_issues", { query });
|
|
573
|
+
if (!result.ok) return result;
|
|
574
|
+
results.push({ query, data: result.data });
|
|
575
|
+
}
|
|
576
|
+
return results;
|
|
548
577
|
```
|
|
549
578
|
|
|
550
|
-
|
|
579
|
+
The script API is:
|
|
580
|
+
|
|
581
|
+
| Method | Result |
|
|
582
|
+
|--------|--------|
|
|
583
|
+
| `tools.search({ query, server?, limit?, offset? })` | `{ items, total, hasMore, nextOffset, coverage }`; items include `path`, `name`, and `server`; discovery errors include `error` |
|
|
584
|
+
| `tools.describe({ path, server? })` | Complete descriptor with `path`, `server`, `name`, and the server's `inputSchema`, `outputSchema`, `title`, annotations, `_meta`, and other fields when present; failures contain `error` |
|
|
585
|
+
| `tools.call(path, args, server?)` or `tools.exact_flat_name(args)` | `{ ok: true, data, resultRef? }` or `{ ok: false, error: { code, message, ... }, data?, resultRef? }` |
|
|
586
|
+
| `tools.resources({ server, limit?, offset? })` | `{ mode: "resources", server, items, total, hasMore, nextOffset }`; failures contain `error` |
|
|
587
|
+
| `tools.readResource({ server, uri })` | The call envelope above, with raw resource data in `data.contents` |
|
|
588
|
+
| `tools.readResult({ ref, path?, fields?, offset?, limit? })` | `{ content, details }`; readback text and `details.nextOffset`, or `details.error` on failure |
|
|
589
|
+
| `emit(value)` / `console.log(value)` | Captured output before the final return value |
|
|
590
|
+
|
|
591
|
+
For an ambiguous flat name, call `tools.call(descriptor.name, args, descriptor.server)` using the original name and server returned by describe.
|
|
592
|
+
|
|
593
|
+
Search/resource pages default to 12 items, maximum 100. `coverage` contains `complete`, `knownServers`, and `unknownServers`. Selecting an uncached server discovers it; global search does not connect every lazy server. Script discovery does not activate typed tools. Descriptions retain JSON Schema rather than a lossy TypeScript projection.
|
|
551
594
|
|
|
552
|
-
|
|
595
|
+
`data` is the raw MCP result: tool calls usually return `{ content, structuredContent?, isError?, ... }`; resource reads return `{ contents, ... }`. Error results retain their raw data when available. Handle `ok: false`; ordinary call failures do not automatically stop the script. Capture failures stop dependent work, and ambiguous outcomes require provider readback instead of blindly repeating a call. Result details include a concise `calls` trace and saved result references. Reduce raw results before emitting them; the final output uses the normal output guard.
|
|
553
596
|
|
|
554
|
-
|
|
597
|
+
Use JavaScript loops and Promise utilities; fluent helpers such as `tools.find(...).one()`, `tools.parallel(...)`, and `tools.retry(...)` are not provided. Await every call before returning. The default timeout is 30 seconds unless the SDK host overrides it with `defaultScriptTimeoutMs`; an explicit per-script `timeoutMs` wins. Each script runs in a local worker that is terminated on timeout or cancellation, including infinite loops.
|
|
555
598
|
|
|
556
|
-
|
|
599
|
+
For a tool-restricted subagent, a host can allow only `mcp_script`; include the relevant exact tool names or let the script use its discovery methods. A gateway-only host can use `mcp({ action: "search", query: "..." })` without activating tools outside its allowlist. Authentication, approvals, filters, and cancellation apply to every call.
|
|
600
|
+
|
|
601
|
+
`mcp_script` is a trusted agent-authored MCP scripting layer, not an isolation boundary. The worker exposes no Node, filesystem, or network globals such as `process`, `Buffer`, or `fetch`. Run Pi in an isolated environment if you need isolation. This is local orchestration, not provider-native programmatic tool calling; it does not claim Codex native PTC support. Pi's general code-mode skill is separate and batches general Pi tools.
|
|
602
|
+
|
|
603
|
+
See the bundled `mcp-scripting` skill for the workflow and exact return shapes.
|
|
604
|
+
|
|
605
|
+
### MCP Resources
|
|
606
|
+
|
|
607
|
+
Resources are catalog entries addressed by URI, separate from tools:
|
|
608
|
+
|
|
609
|
+
```js
|
|
610
|
+
mcp({ action: "resources", server: "docs", limit: 12, offset: 0 })
|
|
611
|
+
mcp({ action: "read-resource", server: "docs", uri: "docs://guide" })
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
List first, then use the exact URI. Listings preserve the server's resource descriptor fields, including name, title, MIME type, icons, and `_meta` when supplied. `exposeResources`, include/exclude filters, disabled servers, authentication, and approval policy remain binding. Existing `read_<resource>` filter names still select resources, but these compatibility aliases are not typed functions and cannot be pinned in `/mcp`. Scripts use `tools.resources` and `tools.readResource`.
|
|
557
615
|
|
|
558
616
|
### MCP Prompts
|
|
559
617
|
|
|
@@ -573,9 +631,17 @@ When Pi exposes dialog-capable UI, the adapter advertises form elicitation suppo
|
|
|
573
631
|
|
|
574
632
|
URL mode is advertised only in TUI mode. The adapter displays the requesting server, target host, and full URL, and always requires consent before opening the browser. It also handles URL-required tool errors (`-32042`) and completion notifications; after completing the browser interaction, retry the original tool call.
|
|
575
633
|
|
|
576
|
-
###
|
|
634
|
+
### Typed Discovery and Pinned Tools
|
|
635
|
+
|
|
636
|
+
`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
|
+
|
|
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.
|
|
577
639
|
|
|
578
|
-
|
|
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.
|
|
641
|
+
|
|
642
|
+
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
|
+
|
|
644
|
+
Add `directTools` to pin frequently used tools into the initial active set:
|
|
579
645
|
|
|
580
646
|
Per-server:
|
|
581
647
|
|
|
@@ -602,9 +668,9 @@ Per-server:
|
|
|
602
668
|
|
|
603
669
|
| Value | Behavior |
|
|
604
670
|
|-------|----------|
|
|
605
|
-
| `true` |
|
|
606
|
-
| `["tool_a", "tool_b"]` |
|
|
607
|
-
| Omitted or `false` |
|
|
671
|
+
| `true` | Pin all eligible real tools from this server |
|
|
672
|
+
| `["tool_a", "tool_b"]` | Pin these tools (use original MCP names) |
|
|
673
|
+
| Omitted or `false` | No initial pins; load tools with `mcp_search` when needed (default) |
|
|
608
674
|
|
|
609
675
|
To set a global default for all servers:
|
|
610
676
|
|
|
@@ -621,11 +687,11 @@ To set a global default for all servers:
|
|
|
621
687
|
}
|
|
622
688
|
```
|
|
623
689
|
|
|
624
|
-
Per-server `directTools` overrides the global setting. The example above
|
|
690
|
+
Per-server `directTools` overrides the global setting. The example above pins tools for every server except `huge-server`, whose tools remain discoverable.
|
|
625
691
|
|
|
626
|
-
Set `MCP_DIRECT_TOOLS=__none__` before loading the adapter to suppress all direct-tool registration, including
|
|
692
|
+
Set `MCP_DIRECT_TOOLS=__none__` before loading the adapter to suppress all direct-tool registration, including pins and search-driven activation. `mcp_search` can still discover schemas and report that no functions were loaded; use gateway or script calls instead. Normal tool filters, host allowlists, and disabled-server settings still apply.
|
|
627
693
|
|
|
628
|
-
To expose only a subset of a
|
|
694
|
+
To expose only a subset of a server, add `includeTools`. Values can be exact original names, prefixed names, or simple glob patterns. Legacy `read_<resource>` names continue to filter resource access:
|
|
629
695
|
|
|
630
696
|
```json
|
|
631
697
|
{
|
|
@@ -653,17 +719,15 @@ To hide specific tools while still using `directTools: true`, add `excludeTools`
|
|
|
653
719
|
}
|
|
654
720
|
```
|
|
655
721
|
|
|
656
|
-
`includeTools` and `excludeTools` filter
|
|
657
|
-
|
|
658
|
-
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[]`. If 75+ direct tools resolve, the adapter prints a warning but still registers the tools you configured.
|
|
722
|
+
`includeTools` and `excludeTools` filter typed tools, gateway/script discovery, resource access, and the `/mcp` panel. App-only tools stay out of the model catalog and pin choices.
|
|
659
723
|
|
|
660
|
-
|
|
724
|
+
Active schemas consume context; inactive cached schemas do not. Pin the tools you routinely need and discover the rest as the task requires.
|
|
661
725
|
|
|
662
|
-
|
|
726
|
+
Valid cached descriptors avoid startup connections. Missing or stale metadata for configured pins is discovered intentionally at startup; eager and keep-alive servers also connect as configured. An empty cache does not trigger discovery of every lazy server. Search coverage reports which configured servers are still unknown.
|
|
663
727
|
|
|
664
|
-
|
|
728
|
+
MCP catalog notifications and reconnects refresh eligible metadata. Removed tools leave the active set. `settings.freezeDirectTools: true` keeps the automatic registered surface stable after initial sync; deliberate `mcp({ action: "connect", server: "name" })` or `/mcp reconnect <server>` refreshes remain available.
|
|
665
729
|
|
|
666
|
-
|
|
730
|
+
Run `/mcp` to see known tools, pinned counts, resource counts, and connection state. Uncached servers say **undiscovered**. Expand a server to pin or unpin real tools; resources have no checkboxes and use the resource actions instead. Pin changes apply to the current session and persist through `directTools`. Discovered session selections are separate from these startup pins: unpinning leaves a tool active if discovery already selected it for the current branch. Press Enter on a server that needs auth or `ctrl+a` on an OAuth server to authenticate; `ctrl+r` reconnects. Broader setup changes still use Pi's normal reload flow.
|
|
667
731
|
|
|
668
732
|
**Guided first-run setup:** Run `/mcp setup` to inspect detected shared MCP files, adopt compatibility imports from other hosts, open discovered config paths, preview exact before/after file diffs for writes, scaffold a minimal project `.mcp.json`, add a curated known server (DeepWiki, Context7, Notion, GitHub, or Chrome DevTools), or quick-add RepoPrompt into a standard/shared MCP file.
|
|
669
733
|
|
|
@@ -671,7 +735,7 @@ When you change direct-tool toggles in `/mcp`, the extension updates direct tool
|
|
|
671
735
|
|
|
672
736
|
### MCP UI Integration
|
|
673
737
|
|
|
674
|
-
MCP servers can ship interactive UIs via
|
|
738
|
+
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.
|
|
675
739
|
|
|
676
740
|
**How it works:**
|
|
677
741
|
|
|
@@ -715,7 +779,7 @@ Returns accumulated messages from UI sessions. Each message includes `type`, `se
|
|
|
715
779
|
- Tool consent gates whether UIs can call MCP tools (never/once-per-server/always)
|
|
716
780
|
- `_meta.ui.visibility` controls audience: tools marked app-only stay out of the model tool list, and tools marked model-only cannot be called from the UI iframe.
|
|
717
781
|
- Works with both stdio and HTTP MCP servers
|
|
718
|
-
- Uses a local
|
|
782
|
+
- Uses a local MCP Apps AppBridge bundle for browser↔server communication
|
|
719
783
|
- Enforces CSP from standard `_meta.ui.csp` and OpenAI-compatible `_meta["openai/widgetCSP"]` metadata in the response header while preserving provider HTML.
|
|
720
784
|
|
|
721
785
|
### Local Example: Interactive Visualizer
|
|
@@ -751,32 +815,34 @@ Prefer `.mcp.json` for project-local shared MCP config. Use `.pi/fitch-mcp-adapt
|
|
|
751
815
|
|
|
752
816
|
## Usage
|
|
753
817
|
|
|
754
|
-
|
|
|
755
|
-
|
|
756
|
-
|
|
|
757
|
-
|
|
|
758
|
-
|
|
|
759
|
-
|
|
|
760
|
-
|
|
|
761
|
-
|
|
|
762
|
-
|
|
|
818
|
+
| Action | Example |
|
|
819
|
+
|--------|---------|
|
|
820
|
+
| Discover and load typed tools | `mcp_search({ query: "screenshot", server: "chrome-devtools", limit: 5 })` |
|
|
821
|
+
| Status | `mcp({ action: "status" })` |
|
|
822
|
+
| List server tools | `mcp({ action: "list", server: "name", limit: 12, offset: 0 })` |
|
|
823
|
+
| Search without activation | `mcp({ action: "search", query: "screenshot navigate", limit: 12 })` |
|
|
824
|
+
| Describe | `mcp({ action: "describe", tool: "tool_name", server: "name" })` |
|
|
825
|
+
| Instructions | `mcp({ action: "instructions", server: "name" })` |
|
|
826
|
+
| Call | `mcp({ action: "call", tool: "tool_name", args: { key: "value" } })` |
|
|
827
|
+
| Connect or refresh | `mcp({ action: "connect", server: "name", limit: 12, offset: 0 })` |
|
|
828
|
+
| List resources | `mcp({ action: "resources", server: "name" })` |
|
|
829
|
+
| Read resource | `mcp({ action: "read-resource", server: "name", uri: "docs://guide" })` |
|
|
830
|
+
| Read saved result | `mcp({ action: "read-result", ref: "/returned/result/path", path: "/structuredContent" })` |
|
|
763
831
|
| UI messages | `mcp({ action: "ui-messages" })` |
|
|
764
832
|
| Auth start | `mcp({ action: "auth-start", server: "name" })` |
|
|
765
833
|
| Auth complete | `mcp({ action: "auth-complete", server: "name" })` after the browser callback, or supply `args: { redirectUrl: "..." }` |
|
|
766
834
|
|
|
767
|
-
`
|
|
768
|
-
|
|
769
|
-
MCP proxy and direct-tool results render compactly by default: long text shows the first three terminal-wrapped lines plus Pi's configured `app.tools.expand` keybinding hint, while the full result remains available when expanded and is still returned unchanged to the model.
|
|
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.
|
|
770
836
|
|
|
771
|
-
|
|
837
|
+
`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.
|
|
772
838
|
|
|
773
|
-
|
|
839
|
+
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.
|
|
774
840
|
|
|
775
|
-
|
|
841
|
+
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.
|
|
776
842
|
|
|
777
|
-
The
|
|
843
|
+
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.
|
|
778
844
|
|
|
779
|
-
|
|
845
|
+
Gateway and typed-tool results render compactly in the terminal: long text shows the first three terminal-wrapped lines with Pi's `app.tools.expand` hint. Expanding reveals the guarded result. Structured data and saved-result references remain visible to the model.
|
|
780
846
|
|
|
781
847
|
## Commands
|
|
782
848
|
|
|
@@ -784,7 +850,8 @@ Servers that provide usage guidance via the MCP `instructions` field surface it
|
|
|
784
850
|
|---------|--------------|
|
|
785
851
|
| `/mcp` | Interactive panel and first-run onboarding surface |
|
|
786
852
|
| `/mcp setup` | Guided setup for imports, a minimal `.mcp.json`, curated known servers, RepoPrompt quick-add, and config-path inspection |
|
|
787
|
-
| `/mcp tools` | List
|
|
853
|
+
| `/mcp tools` | List discovered real tools, excluding resource aliases |
|
|
854
|
+
| `/mcp status` | Show connection state and separate tool/resource counts |
|
|
788
855
|
| `/mcp prompts` | List all MCP prompts registered as slash commands |
|
|
789
856
|
| `/mcp reconnect` | Reconnect all servers |
|
|
790
857
|
| `/mcp reconnect <server>` | Connect or reconnect a single server |
|
|
@@ -794,24 +861,25 @@ Servers that provide usage guidance via the MCP `instructions` field surface it
|
|
|
794
861
|
| `/mcp-auth` | Open an OAuth server picker in interactive UI sessions |
|
|
795
862
|
| `/mcp-auth <server>` | OAuth setup for a specific server |
|
|
796
863
|
|
|
797
|
-
If `settings.autoAuth` is `true`, `mcp({ connect: ... })`,
|
|
864
|
+
If `settings.autoAuth` is `true`, `mcp({ action: "connect", server: "..." })`, gateway calls, and typed/script tool calls may run OAuth when needed, with at most one automatic auth attempt per invocation and one post-auth retry. Browser authorization requires an interactive host. Auth-only replacement preserves accepted work on the old client; ordinary `/mcp reconnect` and panel `ctrl+r` remain hard resets.
|
|
798
865
|
|
|
799
866
|
In interactive sessions, you can also authenticate from `/mcp` with `ctrl+a` or Enter on a server that needs auth. In remote/headless sessions, use the proxy tool's `auth-start` and `auth-complete` actions. Complete without arguments when the browser reaches Pi's callback, or paste the redirect URL when it cannot. `/mcp-auth` without a server only opens a picker in the interactive UI.
|
|
800
867
|
|
|
801
868
|
### MCP output schemas
|
|
802
869
|
|
|
803
|
-
Advertised tool `outputSchema` values support JSON Schema draft-07 and 2020-12. Unstamped schemas use the SDK's 2020-12 default. Returned `structuredContent` is validated against the advertised schema for both proxy and direct-tool calls.
|
|
870
|
+
Advertised tool `outputSchema` values support JSON Schema draft-07 and 2020-12. Unstamped schemas use the SDK's 2020-12 default. Returned `structuredContent` is validated against the advertised schema for both proxy and direct-tool calls. Any JSON structured value—including `null`, `false`, and `0`—is rendered as text, including alongside non-empty content or images. The raw result remains available for script reduction and saved-result readback.
|
|
804
871
|
|
|
805
872
|
## How It Works
|
|
806
873
|
|
|
807
|
-
-
|
|
808
|
-
-
|
|
874
|
+
- Stable `mcp_search`, `mcp`, and optional `mcp_script` entry points; full typed schemas load when selected
|
|
875
|
+
- Lazy servers connect on selected discovery or calls; configured pins and eager/keep-alive servers can bootstrap intentionally
|
|
809
876
|
- Tool metadata is cached to disk so search/list/describe work without live connections
|
|
810
877
|
- Idle servers disconnect after 10 minutes (configurable), reconnect automatically on next use
|
|
811
878
|
- npx-based servers resolve to direct binary paths, skipping the ~143 MB npm parent process
|
|
812
|
-
-
|
|
879
|
+
- Pi validates loaded typed-tool arguments against their schemas; gateway and script arguments are validated by the MCP server
|
|
813
880
|
- Keep-alive servers get health checks and auto-reconnect
|
|
814
|
-
-
|
|
881
|
+
- `directTools` pins initial tools; search-driven selections persist separately on the native session branch
|
|
882
|
+
- Resources use explicit URI-based listing and reading, without synthetic function definitions
|
|
815
883
|
|
|
816
884
|
## Limitations
|
|
817
885
|
|