@herbertgao/pi-extensions 2026.9.17 → 2026.9.18
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/README.md +14 -15
- package/node_modules/@herbertgao/pi-bark/package.json +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +4 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +4 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +75 -75
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
- package/node_modules/@herbertgao/resume-from/package.json +4 -2
- package/node_modules/@herbertgao/sol-pi/package.json +6 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +99 -99
- package/node_modules/@pi-plugins/fast-mode/package.json +1 -1
- package/node_modules/@tifan/pi-handoff/package.json +1 -1
- package/node_modules/@tifan/pi-handoff/src/index.ts +56 -26
- package/node_modules/@tifan/pi-mermaid-open/package.json +1 -1
- package/node_modules/@tifan/pi-preferred-thinking/package.json +1 -1
- package/node_modules/@tifan/pi-recap/package.json +1 -1
- package/node_modules/@tifan/pi-rename/package.json +1 -1
- package/node_modules/pi-antigravity/package.json +2 -2
- package/node_modules/pi-lens/package.json +158 -158
- package/node_modules/pi-multi-account/package.json +2 -2
- package/node_modules/pi-typesafe/README.md +1 -1
- package/node_modules/pi-typesafe/dist/auth.d.ts +9 -5
- package/node_modules/pi-typesafe/dist/auth.js +7 -3
- package/node_modules/pi-typesafe/dist/backends.d.ts +33 -3
- package/node_modules/pi-typesafe/dist/backends.js +95 -1
- package/node_modules/pi-typesafe/dist/client.d.ts +5 -5
- package/node_modules/pi-typesafe/dist/client.js +12 -9
- package/node_modules/pi-typesafe/dist/credentials.d.ts +14 -8
- package/node_modules/pi-typesafe/dist/credentials.js +10 -7
- package/node_modules/pi-typesafe/dist/errors.d.ts +2 -2
- package/node_modules/pi-typesafe/dist/index.d.ts +2 -2
- package/node_modules/pi-typesafe/dist/index.js +1 -1
- package/node_modules/pi-typesafe/dist/login.d.ts +2 -2
- package/node_modules/pi-typesafe/dist/login.js +2 -2
- package/node_modules/pi-typesafe/package.json +5 -5
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/remote-pi/package.json +5 -1
- package/package.json +16 -28
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +0 -1013
- package/node_modules/pi-mcp-adapter/LICENSE +0 -21
- package/node_modules/pi-mcp-adapter/OAUTH.md +0 -369
- package/node_modules/pi-mcp-adapter/README.md +0 -1021
- package/node_modules/pi-mcp-adapter/abort.ts +0 -34
- package/node_modules/pi-mcp-adapter/agent-dir.ts +0 -68
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +0 -416
- package/node_modules/pi-mcp-adapter/agent-plugin-provenance.ts +0 -36
- package/node_modules/pi-mcp-adapter/app-bridge.bundle.js +0 -67
- package/node_modules/pi-mcp-adapter/banner.png +0 -0
- package/node_modules/pi-mcp-adapter/bearer-command-resolver.ts +0 -193
- package/node_modules/pi-mcp-adapter/claude-plugin-loader.ts +0 -365
- package/node_modules/pi-mcp-adapter/cli.js +0 -454
- package/node_modules/pi-mcp-adapter/commands.ts +0 -861
- package/node_modules/pi-mcp-adapter/config.ts +0 -1565
- package/node_modules/pi-mcp-adapter/consent-manager.ts +0 -95
- package/node_modules/pi-mcp-adapter/direct-tool-surface.ts +0 -244
- package/node_modules/pi-mcp-adapter/direct-tools.ts +0 -428
- package/node_modules/pi-mcp-adapter/dist/abort.d.ts +0 -2
- package/node_modules/pi-mcp-adapter/dist/abort.js +0 -36
- package/node_modules/pi-mcp-adapter/dist/abort.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/agent-dir.d.ts +0 -10
- package/node_modules/pi-mcp-adapter/dist/agent-dir.js +0 -63
- package/node_modules/pi-mcp-adapter/dist/agent-dir.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.d.ts +0 -8
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +0 -398
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.d.ts +0 -1
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js +0 -31
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-provenance.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.d.ts +0 -6
- package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.js +0 -194
- package/node_modules/pi-mcp-adapter/dist/bearer-command-resolver.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.d.ts +0 -9
- package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js +0 -362
- package/node_modules/pi-mcp-adapter/dist/claude-plugin-loader.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/config.d.ts +0 -134
- package/node_modules/pi-mcp-adapter/dist/config.js +0 -1361
- package/node_modules/pi-mcp-adapter/dist/config.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/consent-manager.d.ts +0 -18
- package/node_modules/pi-mcp-adapter/dist/consent-manager.js +0 -88
- package/node_modules/pi-mcp-adapter/dist/consent-manager.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/elicitation-handler.d.ts +0 -17
- package/node_modules/pi-mcp-adapter/dist/elicitation-handler.js +0 -316
- package/node_modules/pi-mcp-adapter/dist/elicitation-handler.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/errors.d.ts +0 -131
- package/node_modules/pi-mcp-adapter/dist/errors.js +0 -278
- package/node_modules/pi-mcp-adapter/dist/errors.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/http-ca.d.ts +0 -8
- package/node_modules/pi-mcp-adapter/dist/http-ca.js +0 -88
- package/node_modules/pi-mcp-adapter/dist/http-ca.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/jev-client.d.ts +0 -14
- package/node_modules/pi-mcp-adapter/dist/jev-client.js +0 -367
- package/node_modules/pi-mcp-adapter/dist/jev-client.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/jev-contracts.d.ts +0 -77
- package/node_modules/pi-mcp-adapter/dist/jev-contracts.js +0 -2
- package/node_modules/pi-mcp-adapter/dist/jev-contracts.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/jev-key-store.d.ts +0 -51
- package/node_modules/pi-mcp-adapter/dist/jev-key-store.js +0 -205
- package/node_modules/pi-mcp-adapter/dist/jev-key-store.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/json-schema-validator.d.ts +0 -2
- package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js +0 -68
- package/node_modules/pi-mcp-adapter/dist/json-schema-validator.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/lifecycle.d.ts +0 -56
- package/node_modules/pi-mcp-adapter/dist/lifecycle.js +0 -410
- package/node_modules/pi-mcp-adapter/dist/lifecycle.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/logger.d.ts +0 -51
- package/node_modules/pi-mcp-adapter/dist/logger.js +0 -131
- package/node_modules/pi-mcp-adapter/dist/logger.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.d.ts +0 -26
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.js +0 -103
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-fetch.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.d.ts +0 -118
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.js +0 -1097
- package/node_modules/pi-mcp-adapter/dist/mcp-auth-flow.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-auth.d.ts +0 -170
- package/node_modules/pi-mcp-adapter/dist/mcp-auth.js +0 -1142
- package/node_modules/pi-mcp-adapter/dist/mcp-auth.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.d.ts +0 -24
- package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js +0 -203
- package/node_modules/pi-mcp-adapter/dist/mcp-bearer-store.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.d.ts +0 -53
- package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.js +0 -441
- package/node_modules/pi-mcp-adapter/dist/mcp-callback-server.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.d.ts +0 -148
- package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.js +0 -689
- package/node_modules/pi-mcp-adapter/dist/mcp-oauth-provider.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-probe.d.ts +0 -6
- package/node_modules/pi-mcp-adapter/dist/mcp-probe.js +0 -166
- package/node_modules/pi-mcp-adapter/dist/mcp-probe.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-tasks.d.ts +0 -102
- package/node_modules/pi-mcp-adapter/dist/mcp-tasks.js +0 -369
- package/node_modules/pi-mcp-adapter/dist/mcp-tasks.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/mcp-trace.d.ts +0 -95
- package/node_modules/pi-mcp-adapter/dist/mcp-trace.js +0 -242
- package/node_modules/pi-mcp-adapter/dist/mcp-trace.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.d.ts +0 -19
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +0 -301
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/npx-resolver.d.ts +0 -6
- package/node_modules/pi-mcp-adapter/dist/npx-resolver.js +0 -505
- package/node_modules/pi-mcp-adapter/dist/npx-resolver.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.d.ts +0 -2
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +0 -144
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/request-headers-command.d.ts +0 -10
- package/node_modules/pi-mcp-adapter/dist/request-headers-command.js +0 -312
- package/node_modules/pi-mcp-adapter/dist/request-headers-command.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/resource-tools.d.ts +0 -1
- package/node_modules/pi-mcp-adapter/dist/resource-tools.js +0 -15
- package/node_modules/pi-mcp-adapter/dist/resource-tools.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/runtime-owner.d.ts +0 -13
- package/node_modules/pi-mcp-adapter/dist/runtime-owner.js +0 -97
- package/node_modules/pi-mcp-adapter/dist/runtime-owner.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/sampling-handler.d.ts +0 -17
- package/node_modules/pi-mcp-adapter/dist/sampling-handler.js +0 -203
- package/node_modules/pi-mcp-adapter/dist/sampling-handler.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/secure-keyring.d.ts +0 -11
- package/node_modules/pi-mcp-adapter/dist/secure-keyring.js +0 -172
- package/node_modules/pi-mcp-adapter/dist/secure-keyring.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/server-manager.d.ts +0 -157
- package/node_modules/pi-mcp-adapter/dist/server-manager.js +0 -1745
- package/node_modules/pi-mcp-adapter/dist/server-manager.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/session-approvals.d.ts +0 -34
- package/node_modules/pi-mcp-adapter/dist/session-approvals.js +0 -140
- package/node_modules/pi-mcp-adapter/dist/session-approvals.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/session-recovery.d.ts +0 -26
- package/node_modules/pi-mcp-adapter/dist/session-recovery.js +0 -142
- package/node_modules/pi-mcp-adapter/dist/session-recovery.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/state.d.ts +0 -73
- package/node_modules/pi-mcp-adapter/dist/state.js +0 -2
- package/node_modules/pi-mcp-adapter/dist/state.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +0 -642
- package/node_modules/pi-mcp-adapter/dist/types.js +0 -331
- package/node_modules/pi-mcp-adapter/dist/types.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.d.ts +0 -6
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js +0 -37
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.d.ts +0 -17
- package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.js +0 -219
- package/node_modules/pi-mcp-adapter/dist/ui-resource-handler.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.d.ts +0 -104
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js +0 -59
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.d.ts +0 -4
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js +0 -27
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.d.ts +0 -15
- package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.js +0 -85
- package/node_modules/pi-mcp-adapter/dist/unix-socket-transport.js.map +0 -1
- package/node_modules/pi-mcp-adapter/dist/utils.d.ts +0 -41
- package/node_modules/pi-mcp-adapter/dist/utils.js +0 -417
- package/node_modules/pi-mcp-adapter/dist/utils.js.map +0 -1
- package/node_modules/pi-mcp-adapter/elicitation-handler.ts +0 -358
- package/node_modules/pi-mcp-adapter/error-signal.ts +0 -32
- package/node_modules/pi-mcp-adapter/errors.ts +0 -364
- package/node_modules/pi-mcp-adapter/examples/jev-accessibility-loop.mjs +0 -85
- package/node_modules/pi-mcp-adapter/examples/jev-semantic-filter.mjs +0 -34
- package/node_modules/pi-mcp-adapter/failure-backoff.ts +0 -23
- package/node_modules/pi-mcp-adapter/glimpse-ui.ts +0 -80
- package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -515
- package/node_modules/pi-mcp-adapter/http-ca.ts +0 -84
- package/node_modules/pi-mcp-adapter/index.ts +0 -2106
- package/node_modules/pi-mcp-adapter/init.ts +0 -721
- package/node_modules/pi-mcp-adapter/jev-client.ts +0 -300
- package/node_modules/pi-mcp-adapter/jev-contracts.ts +0 -53
- package/node_modules/pi-mcp-adapter/jev-key-store.ts +0 -192
- package/node_modules/pi-mcp-adapter/json-schema-validator.ts +0 -83
- package/node_modules/pi-mcp-adapter/lazy-loader.ts +0 -7
- package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -457
- package/node_modules/pi-mcp-adapter/logger.ts +0 -169
- package/node_modules/pi-mcp-adapter/mcp-auth-fetch.ts +0 -113
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +0 -1296
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +0 -1287
- package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +0 -250
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +0 -534
- package/node_modules/pi-mcp-adapter/mcp-code.ts +0 -495
- package/node_modules/pi-mcp-adapter/mcp-install.ts +0 -60
- package/node_modules/pi-mcp-adapter/mcp-keyring-helper.cjs +0 -89
- package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +0 -819
- package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +0 -511
- package/node_modules/pi-mcp-adapter/mcp-panel-theme.ts +0 -104
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +0 -1099
- package/node_modules/pi-mcp-adapter/mcp-probe.ts +0 -201
- package/node_modules/pi-mcp-adapter/mcp-references.ts +0 -373
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +0 -137
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +0 -747
- package/node_modules/pi-mcp-adapter/mcp-status.ts +0 -105
- package/node_modules/pi-mcp-adapter/mcp-tasks.ts +0 -467
- package/node_modules/pi-mcp-adapter/mcp-trace.ts +0 -306
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +0 -362
- package/node_modules/pi-mcp-adapter/namespace-tools.ts +0 -334
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +0 -543
- package/node_modules/pi-mcp-adapter/oauth-handler.ts +0 -30
- package/node_modules/pi-mcp-adapter/oauth.ts +0 -52
- package/node_modules/pi-mcp-adapter/onboarding-state.ts +0 -76
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +0 -156
- package/node_modules/pi-mcp-adapter/package.json +0 -219
- package/node_modules/pi-mcp-adapter/panel-keys.ts +0 -53
- package/node_modules/pi-mcp-adapter/prompts.ts +0 -385
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +0 -1735
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +0 -333
- package/node_modules/pi-mcp-adapter/resource-tools.ts +0 -17
- package/node_modules/pi-mcp-adapter/runtime-owner.ts +0 -106
- package/node_modules/pi-mcp-adapter/sampling-handler.ts +0 -261
- package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +0 -144
- package/node_modules/pi-mcp-adapter/search-ranking.ts +0 -309
- package/node_modules/pi-mcp-adapter/secure-keyring.ts +0 -170
- package/node_modules/pi-mcp-adapter/semantic-search.ts +0 -186
- package/node_modules/pi-mcp-adapter/server-manager.ts +0 -2088
- package/node_modules/pi-mcp-adapter/session-approvals.ts +0 -201
- package/node_modules/pi-mcp-adapter/session-recovery.ts +0 -158
- package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +0 -49
- package/node_modules/pi-mcp-adapter/state.ts +0 -71
- package/node_modules/pi-mcp-adapter/tool-approval.ts +0 -205
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +0 -302
- package/node_modules/pi-mcp-adapter/tool-registrar.ts +0 -255
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +0 -573
- package/node_modules/pi-mcp-adapter/ts-shape.ts +0 -149
- package/node_modules/pi-mcp-adapter/types.ts +0 -1120
- package/node_modules/pi-mcp-adapter/ui-app-bridge-helpers.ts +0 -40
- package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +0 -266
- package/node_modules/pi-mcp-adapter/ui-server.ts +0 -993
- package/node_modules/pi-mcp-adapter/ui-session.ts +0 -624
- package/node_modules/pi-mcp-adapter/ui-stream-types.ts +0 -89
- package/node_modules/pi-mcp-adapter/ui-tool-visibility.ts +0 -25
- package/node_modules/pi-mcp-adapter/unix-socket-transport.ts +0 -85
- package/node_modules/pi-mcp-adapter/utils.ts +0 -464
|
@@ -1,1120 +0,0 @@
|
|
|
1
|
-
// types.ts - Core type definitions
|
|
2
|
-
import type {
|
|
3
|
-
CallToolResult,
|
|
4
|
-
ContentBlock as McpContentBlock,
|
|
5
|
-
ListPromptsResult,
|
|
6
|
-
ListResourcesResult,
|
|
7
|
-
ListToolsResult,
|
|
8
|
-
Transport as McpTransport,
|
|
9
|
-
} from "@modelcontextprotocol/client";
|
|
10
|
-
import type { TextContent, ImageContent } from "@earendil-works/pi-ai";
|
|
11
|
-
import type { UiStreamMode, UiStreamSummary } from "./ui-stream-types.ts";
|
|
12
|
-
import type { UiToolVisibility } from "./ui-tool-visibility.ts";
|
|
13
|
-
import { createHash } from "node:crypto";
|
|
14
|
-
|
|
15
|
-
export type Transport = McpTransport;
|
|
16
|
-
|
|
17
|
-
/** Versioned shared-event-bus channel for read-only MCP runtime snapshots. */
|
|
18
|
-
export const MCP_STATUS_EVENT = "pi-mcp-adapter/status/v1";
|
|
19
|
-
|
|
20
|
-
export const MCP_STATUS_SNAPSHOT_VERSION = 1 as const;
|
|
21
|
-
|
|
22
|
-
export type McpServerRuntimeStatus =
|
|
23
|
-
| "connected"
|
|
24
|
-
| "cached"
|
|
25
|
-
| "failed"
|
|
26
|
-
| "needs-auth"
|
|
27
|
-
| "not-connected"
|
|
28
|
-
| "disabled";
|
|
29
|
-
|
|
30
|
-
export type McpListenState =
|
|
31
|
-
| "active"
|
|
32
|
-
| "dropped"
|
|
33
|
-
| "re-establishing"
|
|
34
|
-
| "legacy"
|
|
35
|
-
| "not-listening"
|
|
36
|
-
| "disconnected";
|
|
37
|
-
|
|
38
|
-
export interface McpServerStatusSnapshot {
|
|
39
|
-
readonly name: string;
|
|
40
|
-
readonly status: McpServerRuntimeStatus;
|
|
41
|
-
readonly toolCount: number;
|
|
42
|
-
readonly directToolCount: number;
|
|
43
|
-
readonly resourceCount?: number;
|
|
44
|
-
readonly failedAgoSeconds?: number;
|
|
45
|
-
readonly disabled: boolean;
|
|
46
|
-
readonly listenState: McpListenState;
|
|
47
|
-
readonly catalogStale?: boolean;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface McpStatusSnapshot {
|
|
51
|
-
readonly version: typeof MCP_STATUS_SNAPSHOT_VERSION;
|
|
52
|
-
readonly servers: ReadonlyArray<McpServerStatusSnapshot>;
|
|
53
|
-
readonly totalTools: number;
|
|
54
|
-
readonly totalResources: number;
|
|
55
|
-
readonly connectedCount: number;
|
|
56
|
-
readonly disabledCount: number;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Minimal event-bus surface the status publisher needs. Lives here (leaf
|
|
61
|
-
* module) so `state.ts` can reference it without importing `mcp-status.ts`,
|
|
62
|
-
* which imports the state type back — an import cycle at type level.
|
|
63
|
-
*/
|
|
64
|
-
export interface McpStatusEventBus {
|
|
65
|
-
emit(channel: string, data: unknown): void;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Import sources for config
|
|
69
|
-
export type ImportKind =
|
|
70
|
-
| "cursor"
|
|
71
|
-
| "claude-code"
|
|
72
|
-
| "claude-desktop"
|
|
73
|
-
| "codex"
|
|
74
|
-
| "opencode"
|
|
75
|
-
| "windsurf"
|
|
76
|
-
| "vscode";
|
|
77
|
-
|
|
78
|
-
type SdkTool = ListToolsResult["tools"][number];
|
|
79
|
-
type SdkResource = ListResourcesResult["resources"][number];
|
|
80
|
-
type SdkPrompt = ListPromptsResult["prompts"][number];
|
|
81
|
-
type SdkPromptArgument = NonNullable<SdkPrompt["arguments"]>[number];
|
|
82
|
-
|
|
83
|
-
// MCP wire definitions derive their field types from the installed SDK while
|
|
84
|
-
// retaining the adapter's deliberately smaller public surface.
|
|
85
|
-
export interface McpTool {
|
|
86
|
-
name: SdkTool["name"];
|
|
87
|
-
title?: SdkTool["title"];
|
|
88
|
-
description?: SdkTool["description"];
|
|
89
|
-
inputSchema?: SdkTool["inputSchema"]; // JSON Schema
|
|
90
|
-
outputSchema?: SdkTool["outputSchema"]; // JSON Schema for structuredContent
|
|
91
|
-
_meta?: SdkTool["_meta"];
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export interface McpResource {
|
|
95
|
-
uri: SdkResource["uri"];
|
|
96
|
-
name: SdkResource["name"];
|
|
97
|
-
description?: SdkResource["description"];
|
|
98
|
-
mimeType?: SdkResource["mimeType"];
|
|
99
|
-
_meta?: SdkResource["_meta"];
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export interface McpPromptArgument {
|
|
103
|
-
name: SdkPromptArgument["name"];
|
|
104
|
-
description?: SdkPromptArgument["description"];
|
|
105
|
-
required?: SdkPromptArgument["required"];
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
export interface McpPrompt {
|
|
109
|
-
name: SdkPrompt["name"];
|
|
110
|
-
title?: SdkPrompt["title"];
|
|
111
|
-
description?: SdkPrompt["description"];
|
|
112
|
-
arguments?: SdkPrompt["arguments"];
|
|
113
|
-
_meta?: SdkPrompt["_meta"];
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
export interface UiResourceMeta {
|
|
117
|
-
csp?: UiResourceCsp;
|
|
118
|
-
permissions?: UiResourcePermissions;
|
|
119
|
-
domain?: string;
|
|
120
|
-
prefersBorder?: boolean;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export interface UiResourceContent {
|
|
124
|
-
uri: string;
|
|
125
|
-
html: string;
|
|
126
|
-
mimeType?: string;
|
|
127
|
-
meta: UiResourceMeta;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export interface UiProxyRequestBody<TParams> {
|
|
131
|
-
token: string;
|
|
132
|
-
params: TParams;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
export interface UiProxyResult<T = Record<string, unknown>> {
|
|
136
|
-
ok: boolean;
|
|
137
|
-
result?: T;
|
|
138
|
-
error?: string;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
export interface UiResourceCsp {
|
|
142
|
-
resourceDomains?: string[];
|
|
143
|
-
connectDomains?: string[];
|
|
144
|
-
frameDomains?: string[];
|
|
145
|
-
baseUriDomains?: string[];
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
export interface UiResourcePermissions {
|
|
149
|
-
camera?: {};
|
|
150
|
-
microphone?: {};
|
|
151
|
-
geolocation?: {};
|
|
152
|
-
clipboardWrite?: {};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
export interface UiToolInfo {
|
|
156
|
-
id?: string | number;
|
|
157
|
-
tool: {
|
|
158
|
-
name: string;
|
|
159
|
-
description?: string;
|
|
160
|
-
inputSchema?: unknown;
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export interface UiHostContext {
|
|
165
|
-
toolInfo?: UiToolInfo;
|
|
166
|
-
theme?: "light" | "dark";
|
|
167
|
-
styles?: Record<string, unknown>;
|
|
168
|
-
displayMode?: UiDisplayMode;
|
|
169
|
-
availableDisplayModes?: UiDisplayMode[];
|
|
170
|
-
containerDimensions?: {
|
|
171
|
-
width?: number;
|
|
172
|
-
maxWidth?: number;
|
|
173
|
-
height?: number;
|
|
174
|
-
maxHeight?: number;
|
|
175
|
-
};
|
|
176
|
-
[key: string]: unknown;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
export type UiDisplayMode = "inline" | "fullscreen" | "pip";
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Live handle to a started UI tool session. Lives here (leaf module) so
|
|
183
|
-
* `state.ts` can reference it without importing `ui-server.ts`, which
|
|
184
|
-
* imports the state type back — an import cycle at type level.
|
|
185
|
-
*/
|
|
186
|
-
export interface UiServerHandle {
|
|
187
|
-
url: string;
|
|
188
|
-
port: number;
|
|
189
|
-
/** URL of the second-origin MCP Apps sandbox proxy. */
|
|
190
|
-
proxyUrl: string;
|
|
191
|
-
proxyPort: number;
|
|
192
|
-
sessionToken: string;
|
|
193
|
-
serverName: string;
|
|
194
|
-
toolName: string;
|
|
195
|
-
viewer?: "browser" | "glimpse" | "orca" | "suppressed";
|
|
196
|
-
windowOpen?: boolean;
|
|
197
|
-
close: (reason?: string) => void;
|
|
198
|
-
sendToolInput: (args: Record<string, unknown>) => void;
|
|
199
|
-
sendToolResult: (result: CallToolResult) => void;
|
|
200
|
-
sendResultPatch: (result: CallToolResult) => void;
|
|
201
|
-
sendToolCancelled: (reason: string) => void;
|
|
202
|
-
sendResourceUpdated: (uri: string) => void;
|
|
203
|
-
sendHostContext: (context: UiHostContext) => void;
|
|
204
|
-
/** Get accumulated messages from this session */
|
|
205
|
-
getSessionMessages: () => UiSessionMessages;
|
|
206
|
-
getStreamSummary: () => UiStreamSummary | undefined;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
// Re-export stream types from the shared lightweight module.
|
|
210
|
-
// This allows the example package to import stream schemas without pulling the full types.ts dependency graph.
|
|
211
|
-
export {
|
|
212
|
-
UI_STREAM_HOST_CONTEXT_KEY,
|
|
213
|
-
UI_STREAM_REQUEST_META_KEY,
|
|
214
|
-
UI_STREAM_RESULT_PATCH_METHOD,
|
|
215
|
-
SERVER_STREAM_RESULT_PATCH_METHOD,
|
|
216
|
-
UI_STREAM_STRUCTURED_CONTENT_KEY,
|
|
217
|
-
uiStreamModeSchema,
|
|
218
|
-
visualizationStreamPhaseSchema,
|
|
219
|
-
visualizationStreamFrameTypeSchema,
|
|
220
|
-
visualizationStreamStatusSchema,
|
|
221
|
-
uiStreamHostContextSchema,
|
|
222
|
-
visualizationStreamEnvelopeSchema,
|
|
223
|
-
uiStreamCallToolResultSchema,
|
|
224
|
-
uiStreamResultPatchNotificationSchema,
|
|
225
|
-
serverStreamResultPatchNotificationSchema,
|
|
226
|
-
getUiStreamHostContext,
|
|
227
|
-
getVisualizationStreamEnvelope,
|
|
228
|
-
type UiStreamMode,
|
|
229
|
-
type VisualizationStreamPhase,
|
|
230
|
-
type VisualizationStreamFrameType,
|
|
231
|
-
type VisualizationStreamStatus,
|
|
232
|
-
type UiStreamHostContext,
|
|
233
|
-
type VisualizationStreamEnvelope,
|
|
234
|
-
type UiStreamCallToolResult,
|
|
235
|
-
type UiStreamResultPatchNotification,
|
|
236
|
-
type ServerStreamResultPatchNotification,
|
|
237
|
-
type UiStreamSummary,
|
|
238
|
-
} from "./ui-stream-types.ts";
|
|
239
|
-
|
|
240
|
-
export interface UiMessageParams {
|
|
241
|
-
role?: string;
|
|
242
|
-
content?: unknown[];
|
|
243
|
-
type?: "prompt" | "notify" | "intent" | "message";
|
|
244
|
-
message?: string;
|
|
245
|
-
prompt?: string;
|
|
246
|
-
intent?: string;
|
|
247
|
-
params?: Record<string, unknown>;
|
|
248
|
-
[key: string]: unknown;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/**
|
|
252
|
-
* Extract prompt text from either legacy MCP UI message shapes or native AppBridge user messages.
|
|
253
|
-
*/
|
|
254
|
-
export function extractUiPromptText(params: UiMessageParams): string | undefined {
|
|
255
|
-
if (params.type === "prompt" || params.prompt) {
|
|
256
|
-
const prompt = params.prompt ?? String(params.message ?? "");
|
|
257
|
-
return prompt || undefined;
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
if (params.role === "user" && Array.isArray(params.content)) {
|
|
261
|
-
const text = params.content
|
|
262
|
-
.map((block) => (block && typeof block === "object" && "text" in block ? String((block as { text?: unknown }).text ?? "") : ""))
|
|
263
|
-
.filter(Boolean)
|
|
264
|
-
.join("\n\n");
|
|
265
|
-
return text || undefined;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
return undefined;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/**
|
|
272
|
-
* Structured UI handoff recovered from a canonical prompt envelope.
|
|
273
|
-
*/
|
|
274
|
-
export interface UiPromptHandoff {
|
|
275
|
-
intent: string;
|
|
276
|
-
params: Record<string, unknown>;
|
|
277
|
-
raw: string;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Parse a canonical named UI handoff encoded as `intent\n{json}`.
|
|
282
|
-
*/
|
|
283
|
-
export function parseUiPromptHandoff(prompt: string): UiPromptHandoff | undefined {
|
|
284
|
-
const newlineIndex = prompt.indexOf("\n");
|
|
285
|
-
if (newlineIndex <= 0) {
|
|
286
|
-
return undefined;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const intent = prompt.slice(0, newlineIndex).trim();
|
|
290
|
-
const payloadText = prompt.slice(newlineIndex + 1).trim();
|
|
291
|
-
if (!intent || !payloadText) {
|
|
292
|
-
return undefined;
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(intent)) {
|
|
296
|
-
return undefined;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
try {
|
|
300
|
-
const parsed = JSON.parse(payloadText);
|
|
301
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
302
|
-
return undefined;
|
|
303
|
-
}
|
|
304
|
-
return {
|
|
305
|
-
intent,
|
|
306
|
-
params: parsed as Record<string, unknown>,
|
|
307
|
-
raw: prompt,
|
|
308
|
-
};
|
|
309
|
-
} catch {
|
|
310
|
-
return undefined;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
/**
|
|
315
|
-
* Accumulated messages from a UI session.
|
|
316
|
-
* Collected during the session and available when it ends.
|
|
317
|
-
*/
|
|
318
|
-
export interface UiSessionMessages {
|
|
319
|
-
prompts: string[];
|
|
320
|
-
notifications: string[];
|
|
321
|
-
intents: Array<{ intent: string; params?: Record<string, unknown> }>;
|
|
322
|
-
contexts: UiModelContextUpdate[];
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
export interface UiModelContextUpdate {
|
|
326
|
-
summary: string;
|
|
327
|
-
truncated: boolean;
|
|
328
|
-
payload?: Record<string, unknown>;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
export interface UiModelContextParams {
|
|
332
|
-
content?: McpContentBlock[];
|
|
333
|
-
structuredContent?: Record<string, unknown>;
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
export function createUiModelContextUpdate(params: UiModelContextParams, maxChars = 12_000): UiModelContextUpdate | undefined {
|
|
337
|
-
const payload = Object.fromEntries(
|
|
338
|
-
Object.entries(params).filter(([, value]) => value !== undefined),
|
|
339
|
-
);
|
|
340
|
-
if (Object.keys(payload).length === 0) return undefined;
|
|
341
|
-
|
|
342
|
-
const serialized = JSON.stringify(payload);
|
|
343
|
-
if (serialized.length <= maxChars) {
|
|
344
|
-
return { payload, summary: serialized, truncated: false };
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
return {
|
|
348
|
-
summary: `${serialized.slice(0, Math.max(0, maxChars - 1))}…`,
|
|
349
|
-
truncated: true,
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
export interface UiOpenLinkResult {
|
|
354
|
-
isError?: boolean;
|
|
355
|
-
[key: string]: unknown;
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
export interface UiDisplayModeRequest {
|
|
359
|
-
mode?: UiDisplayMode;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
export interface UiDisplayModeResult {
|
|
363
|
-
mode: UiDisplayMode;
|
|
364
|
-
[key: string]: unknown;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Content types from MCP
|
|
368
|
-
export interface McpContent {
|
|
369
|
-
type: "text" | "image" | "audio" | "resource" | "resource_link";
|
|
370
|
-
text?: string;
|
|
371
|
-
data?: string;
|
|
372
|
-
mimeType?: string;
|
|
373
|
-
resource?: {
|
|
374
|
-
uri: string;
|
|
375
|
-
text?: string;
|
|
376
|
-
blob?: string;
|
|
377
|
-
};
|
|
378
|
-
uri?: string;
|
|
379
|
-
name?: string;
|
|
380
|
-
description?: string;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// Pi content block type
|
|
384
|
-
export type ContentBlock = TextContent | ImageContent;
|
|
385
|
-
|
|
386
|
-
// OAuth configuration (SDK handles auto-discovery and dynamic registration)
|
|
387
|
-
export interface OAuthConfig {
|
|
388
|
-
/** OAuth grant type (defaults to authorization_code) */
|
|
389
|
-
grantType?: "authorization_code" | "client_credentials";
|
|
390
|
-
/** Pre-registered client ID (optional, dynamic registration used if not provided) */
|
|
391
|
-
clientId?: string;
|
|
392
|
-
/** Client secret for confidential clients; requires an explicit clientId when clientMetadataUrl is set. */
|
|
393
|
-
clientSecret?: string;
|
|
394
|
-
/** Operator-supplied public HTTPS Client ID Metadata Document URL (SEP-991); opt-in, with DCR remaining the default. */
|
|
395
|
-
clientMetadataUrl?: string;
|
|
396
|
-
/** Requested OAuth scopes */
|
|
397
|
-
scope?: string;
|
|
398
|
-
/** Extra authorization URL parameters for provider-specific extensions. Flow-owned parameters cannot be overridden. */
|
|
399
|
-
authorizationParams?: Record<string, string>;
|
|
400
|
-
/** Authorization-code redirect URI. Loopback URIs may use `{port}` for an OS-assigned port; HTTPS redirects use manual completion. */
|
|
401
|
-
redirectUri?: string;
|
|
402
|
-
/** Client display name for dynamic registration */
|
|
403
|
-
clientName?: string;
|
|
404
|
-
/** Client homepage URI for dynamic registration */
|
|
405
|
-
clientUri?: string;
|
|
406
|
-
/** Client logo URL for dynamic registration; shown on consent screens */
|
|
407
|
-
logoUri?: string;
|
|
408
|
-
/** HTTPS URL for an authorization-server metadata document used instead of MCP discovery */
|
|
409
|
-
authServerMetadataUrl?: string;
|
|
410
|
-
/** Security-weakening escape hatch for known-misconfigured authorization servers. */
|
|
411
|
-
skipIssuerMetadataValidation?: boolean;
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/**
|
|
415
|
-
* Trusted executable invoked for every outbound HTTP request. The adapter
|
|
416
|
-
* writes a versioned JSON request envelope to stdin and expects a JSON object
|
|
417
|
-
* containing headers on stdout. This is intended for caller-bound signing
|
|
418
|
-
* schemes whose headers depend on the exact request body.
|
|
419
|
-
*/
|
|
420
|
-
export interface HttpRequestHeadersCommand {
|
|
421
|
-
command: string;
|
|
422
|
-
args?: string[];
|
|
423
|
-
env?: Record<string, string>;
|
|
424
|
-
timeoutMs?: number;
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
// Server configuration
|
|
428
|
-
export interface ServerEntry {
|
|
429
|
-
command?: string;
|
|
430
|
-
args?: string[];
|
|
431
|
-
/** Explicit rmcp-mux Unix-domain socket path. Mutually exclusive with command and url. */
|
|
432
|
-
socket?: string;
|
|
433
|
-
env?: Record<string, string>;
|
|
434
|
-
/** Inherit the adapter process environment for stdio servers. Defaults to true; false keeps SDK platform defaults plus explicit env overlays. */
|
|
435
|
-
inheritEnv?: boolean;
|
|
436
|
-
cwd?: string;
|
|
437
|
-
// HTTP fields
|
|
438
|
-
url?: string;
|
|
439
|
-
/** PEM CA bundle replacing default roots for this HTTPS MCP origin only. */
|
|
440
|
-
caFile?: string;
|
|
441
|
-
headers?: Record<string, string>;
|
|
442
|
-
/** Add or replace HTTP headers by running a trusted command for each request. */
|
|
443
|
-
requestHeadersCommand?: HttpRequestHeadersCommand;
|
|
444
|
-
/**
|
|
445
|
-
* Authentication type:
|
|
446
|
-
* - 'oauth' - Use OAuth 2.1 (auto-discovers endpoints, supports dynamic client registration)
|
|
447
|
-
* - 'bearer' - Use static Bearer token
|
|
448
|
-
* - false - Disable authentication
|
|
449
|
-
* If not specified and url is present, OAuth will be auto-detected unless custom headers are configured
|
|
450
|
-
*/
|
|
451
|
-
auth?: "oauth" | "bearer" | false;
|
|
452
|
-
bearerToken?: string;
|
|
453
|
-
bearerTokenEnv?: string;
|
|
454
|
-
/** Read a static bearer token from the adapter-owned OS credential store. */
|
|
455
|
-
bearerTokenStore?: true;
|
|
456
|
-
/**
|
|
457
|
-
* OAuth configuration (optional).
|
|
458
|
-
* If not provided, the SDK will attempt dynamic client registration.
|
|
459
|
-
* Set to false to explicitly disable OAuth for this server.
|
|
460
|
-
*/
|
|
461
|
-
oauth?: OAuthConfig | false;
|
|
462
|
-
lifecycle?: "keep-alive" | "lazy" | "lazy-keep-alive" | "eager";
|
|
463
|
-
idleTimeout?: number; // minutes, overrides global setting
|
|
464
|
-
requestTimeoutMs?: number; // milliseconds, overrides global request timeout when > 0
|
|
465
|
-
// Resource handling
|
|
466
|
-
exposeResources?: boolean;
|
|
467
|
-
// Direct tool registration
|
|
468
|
-
directTools?: boolean | string[] | "search";
|
|
469
|
-
// Override settings.toolPrefix for this server.
|
|
470
|
-
toolPrefix?: ToolPrefix;
|
|
471
|
-
// Include/exclude specific MCP tools/resources by original or prefixed name
|
|
472
|
-
includeTools?: string[];
|
|
473
|
-
excludeTools?: string[];
|
|
474
|
-
/**
|
|
475
|
-
* Extra search keywords per tool, keyed by original name, prefixed name, or
|
|
476
|
-
* glob (same matching rules as includeTools/excludeTools). Keywords boost
|
|
477
|
-
* mcp({ search }) ranking only — they never appear in tool schemas,
|
|
478
|
-
* describe output, or the metadata cache.
|
|
479
|
-
*/
|
|
480
|
-
searchKeywords?: Record<string, string[]>;
|
|
481
|
-
// Require interactive approval before calling matching MCP tools/resources.
|
|
482
|
-
approveTools?: boolean | string[];
|
|
483
|
-
// Debug
|
|
484
|
-
debug?: boolean; // Show server stderr (default: false)
|
|
485
|
-
/** Enable metadata-only JSONL protocol tracing for this server. */
|
|
486
|
-
trace?: boolean;
|
|
487
|
-
/** Force a specific HTTP MCP transport. Used by Agent Plugins, whose `type` declares the transport and forbids client fallback. */
|
|
488
|
-
httpTransport?: "streamable-http" | "sse";
|
|
489
|
-
/** Client-managed persistent data directory for Agent Plugin stdio servers. */
|
|
490
|
-
pluginDataDir?: string;
|
|
491
|
-
/** Treat env values as already resolved literals. Used for Agent Plugin env rules. */
|
|
492
|
-
literalEnv?: boolean;
|
|
493
|
-
/**
|
|
494
|
-
* MCP protocol era negotiation for this server. Defaults to `"legacy"`
|
|
495
|
-
* (byte-equivalent to pre-2026 behavior — no `versionNegotiation` is sent).
|
|
496
|
-
* `"auto"` offers the SDK's default 2026-07-28+ modern versions with
|
|
497
|
-
* legacy fallback; `"2026-07-28"` pins the connection to that revision
|
|
498
|
-
* with no fallback. `auto` and `2026-07-28` must be set explicitly.
|
|
499
|
-
*/
|
|
500
|
-
protocolVersion?: "legacy" | "auto" | "2026-07-28";
|
|
501
|
-
/**
|
|
502
|
-
* MCP Tasks extension (io.modelcontextprotocol/tasks, SEP-2663) support.
|
|
503
|
-
* On 2026-07-28 connections where the server advertises the extension, tool
|
|
504
|
-
* calls that return a task handle are transparently polled to completion,
|
|
505
|
-
* task-time elicitation is routed through the normal elicitation UI, and
|
|
506
|
-
* aborting a call cancels the remote task. Enabled by default; set to
|
|
507
|
-
* false to keep the plain synchronous call path.
|
|
508
|
-
*/
|
|
509
|
-
tasks?: boolean;
|
|
510
|
-
// Keep configuration visible without allowing connections or execution.
|
|
511
|
-
disabled?: boolean;
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
/** Only the literal boolean `true` disables a server. */
|
|
515
|
-
export function isServerDisabled(definition: ServerEntry | undefined): boolean {
|
|
516
|
-
return definition?.disabled === true;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
// Output guard tuning (settings.outputGuard object form)
|
|
520
|
-
export interface McpOutputGuardSettings {
|
|
521
|
-
/** Maximum inline MCP text output bytes before truncation/spill-to-disk. Defaults to 51200 (50 KiB). */
|
|
522
|
-
maxBytes?: number;
|
|
523
|
-
/** Maximum inline MCP text output lines before truncation/spill-to-disk. Defaults to 2000. */
|
|
524
|
-
maxLines?: number;
|
|
525
|
-
/** Maximum details.mcpResult JSON bytes kept raw; larger results are summarized and spilled to disk. Defaults to 16384 (16 KiB). */
|
|
526
|
-
detailsMaxBytes?: number;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
// Settings
|
|
530
|
-
export type ToolPrefix = "server" | "none" | "short" | "mcp";
|
|
531
|
-
|
|
532
|
-
const ENCODED_SERVER_NAMESPACE_MARKER = "_mcpns_";
|
|
533
|
-
// Provider tool-name limit (64 for Bedrock, Anthropic, OpenAI) minus the `mcp__` proxy prefix.
|
|
534
|
-
const MAX_SERVER_NAMESPACE_LENGTH = 59;
|
|
535
|
-
|
|
536
|
-
export function formatServerNamespace(serverName: string): string {
|
|
537
|
-
const normalized = serverName.replace(/-/g, "_");
|
|
538
|
-
const safe = /^[A-Za-z0-9_]*$/.test(normalized) && !normalized.startsWith(ENCODED_SERVER_NAMESPACE_MARKER);
|
|
539
|
-
const body = safe ? normalized : encodeServerNamespace(normalized);
|
|
540
|
-
const namespace = safe ? body : `${ENCODED_SERVER_NAMESPACE_MARKER}${body}`;
|
|
541
|
-
if (namespace.length <= MAX_SERVER_NAMESPACE_LENGTH) return namespace;
|
|
542
|
-
// Hash the ASCII encoding, not the raw name: lone surrogates and U+FFFD share UTF-8 bytes.
|
|
543
|
-
const digest = createHash("sha256").update(namespace, "utf8").digest("hex").slice(0, 16);
|
|
544
|
-
// `_h_` cannot start an encoded body: `h` is neither `_` nor a hexadecimal digit.
|
|
545
|
-
const hashPrefix = `${ENCODED_SERVER_NAMESPACE_MARKER}_h_`;
|
|
546
|
-
const head = body.slice(0, MAX_SERVER_NAMESPACE_LENGTH - hashPrefix.length - digest.length - 1);
|
|
547
|
-
return `${hashPrefix}${head}_${digest}`;
|
|
548
|
-
}
|
|
549
|
-
|
|
550
|
-
// `_` becomes `__`, so `__` and `_<hex>_` form a prefix code and the encoding stays injective.
|
|
551
|
-
function encodeServerNamespace(name: string): string {
|
|
552
|
-
return Array.from(name, character => {
|
|
553
|
-
if (character === "_") return "__";
|
|
554
|
-
return /^[A-Za-z0-9]$/.test(character) ? character : `_${character.codePointAt(0)!.toString(16)}_`;
|
|
555
|
-
}).join("");
|
|
556
|
-
}
|
|
557
|
-
export type HostConfigDiscovery = "off" | "prompt" | "on";
|
|
558
|
-
export type McpFooterStatus = "full" | "compact" | "off";
|
|
559
|
-
|
|
560
|
-
export interface McpTraceSettings {
|
|
561
|
-
/** Enable tracing for all servers unless a server sets trace to false. */
|
|
562
|
-
enabled?: boolean;
|
|
563
|
-
/** JSONL destination; relative paths are resolved from the session cwd. */
|
|
564
|
-
file?: string;
|
|
565
|
-
/** Maximum per-session trace file size in bytes. */
|
|
566
|
-
maxBytes?: number;
|
|
567
|
-
/** Maximum events retained in the per-session trace file. */
|
|
568
|
-
maxEvents?: number;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
export const MCP_TOOL_APPROVAL_REQUEST_EVENT = "pi-mcp-adapter:tool-approval-request" as const;
|
|
572
|
-
|
|
573
|
-
export type McpToolApprovalOrigin = "proxy" | "direct" | "script" | "resource" | "iframe";
|
|
574
|
-
export type McpToolApprovalDecision = "allow_once" | "allow_for_session" | "deny" | "abstain";
|
|
575
|
-
export type McpToolApprovalHandler = () => McpToolApprovalDecision | Promise<McpToolApprovalDecision>;
|
|
576
|
-
|
|
577
|
-
export interface McpToolApprovalRequest {
|
|
578
|
-
requestId: string;
|
|
579
|
-
serverName: string;
|
|
580
|
-
originalToolName: string;
|
|
581
|
-
prefixedToolName: string;
|
|
582
|
-
args: Record<string, unknown>;
|
|
583
|
-
origin: McpToolApprovalOrigin;
|
|
584
|
-
signal?: AbortSignal;
|
|
585
|
-
claim(handler: McpToolApprovalHandler): boolean;
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
export type { JevAnswer, JevErrorCode, JevEvaluateInput, JevEvaluationData, JevEvaluationEnvelope, JevJson, JevQuestion } from "./jev-contracts.ts";
|
|
589
|
-
|
|
590
|
-
export interface McpSettings {
|
|
591
|
-
toolPrefix?: ToolPrefix;
|
|
592
|
-
/** Allow agents to persist remote MCP endpoints with the install action. Defaults to true. */
|
|
593
|
-
allowInstall?: boolean;
|
|
594
|
-
/** Show the plug prefix in MCP status and connection text (default: true). Set to false to disable it. */
|
|
595
|
-
showStatusIcon?: boolean;
|
|
596
|
-
/** Footer status verbosity: full details, compact connected/enabled count, or no footer status. Defaults to full. */
|
|
597
|
-
mcpFooterStatus?: McpFooterStatus;
|
|
598
|
-
/** Show successful startup connection notifications. Defaults to true. */
|
|
599
|
-
notifyOnStartupConnect?: boolean;
|
|
600
|
-
/** Discover detected host-specific MCP configs only when explicitly enabled. */
|
|
601
|
-
hostConfigDiscovery?: HostConfigDiscovery;
|
|
602
|
-
/** Trusted HOME-contained roots from which to discover ancestor project configs. */
|
|
603
|
-
ancestorConfigRoots?: string[];
|
|
604
|
-
/** Agent Plugin package directories to load MCP servers from. */
|
|
605
|
-
agentPluginPaths?: string[];
|
|
606
|
-
idleTimeout?: number; // minutes, default 10, 0 to disable
|
|
607
|
-
requestTimeoutMs?: number; // milliseconds, overrides the SDK request timeout when > 0
|
|
608
|
-
/** Defer lazy runtime startup even when persisted metadata is missing or invalid. Defaults to false. */
|
|
609
|
-
deferWithMissingMetadata?: boolean;
|
|
610
|
-
directTools?: boolean | "search";
|
|
611
|
-
/** Register per-server mcp__<server> namespace proxies. Defaults to true. */
|
|
612
|
-
namespaceProxyTools?: boolean;
|
|
613
|
-
/**
|
|
614
|
-
* Validate direct-tool inputs against the advertised schema after recovering
|
|
615
|
-
* one JSON string layer for object and array properties. Defaults to false.
|
|
616
|
-
*/
|
|
617
|
-
strictDirectToolArguments?: boolean;
|
|
618
|
-
/**
|
|
619
|
-
* Include the byte-bounded raw MCP result in direct-tool details. The default
|
|
620
|
-
* `lean` mode keeps the existing small details object.
|
|
621
|
-
*/
|
|
622
|
-
directToolResultDetails?: "lean" | "bounded";
|
|
623
|
-
/** Show the advisory when 75 or more direct tools resolve. Defaults to true. */
|
|
624
|
-
warnOnLargeDirectTools?: boolean;
|
|
625
|
-
/** Register the trusted MCP-only JavaScript scripting tool. Defaults to true; set false to hide it. */
|
|
626
|
-
scriptMode?: boolean;
|
|
627
|
-
/** Expose MCP resources as tools (default: true). Set to false to disable globally across all servers. */
|
|
628
|
-
exposeResources?: boolean;
|
|
629
|
-
/** Optional Jev (System One) integrations. A valid key enables semantic search; script evaluation remains disabled by default. */
|
|
630
|
-
jev?: false | {
|
|
631
|
-
semanticSearch?: boolean;
|
|
632
|
-
scriptEvaluation?: boolean;
|
|
633
|
-
/** Restrict semantic-search metadata and allow script-evaluation sources. Semantic search defaults to every enabled server. */
|
|
634
|
-
allowedServers?: string[];
|
|
635
|
-
model?: string;
|
|
636
|
-
requestTimeoutMs?: number;
|
|
637
|
-
maxRetries?: number;
|
|
638
|
-
maxStateBytes?: number;
|
|
639
|
-
maxQuestionsPerRequest?: number;
|
|
640
|
-
maxEvaluationsPerScript?: number;
|
|
641
|
-
maxEvaluationBytesPerScript?: number;
|
|
642
|
-
/** Cumulative provider-reported input plus output tokens per script. Defaults to 32768. */
|
|
643
|
-
maxEvaluationTokensPerScript?: number;
|
|
644
|
-
/** Maximum semantic candidates per request. Defaults to 127; range 2..127. */
|
|
645
|
-
semanticCandidateLimit?: number;
|
|
646
|
-
semanticMinProbability?: number;
|
|
647
|
-
};
|
|
648
|
-
/** Render MCP tool results as compact self-rendered rows by default, or as the legacy boxed row. */
|
|
649
|
-
toolResultRendering?: "compact" | "boxed";
|
|
650
|
-
/** Number of result text lines to show before expansion. Supports 1, 2, or 3. Defaults to 1 in compact mode and 3 in boxed mode. */
|
|
651
|
-
collapsedResultLines?: 1 | 2 | 3;
|
|
652
|
-
/** Default approval gate for matching tools/resources; per-server settings override it. */
|
|
653
|
-
approveTools?: boolean | string[];
|
|
654
|
-
disableProxyTool?: boolean;
|
|
655
|
-
/** Freeze direct-tool registration after the initial sync. Automatic metadata updates
|
|
656
|
-
* and explicit reconnects won't rebuild the system prompt, preserving the
|
|
657
|
-
* prompt-cache prefix. Proxy/search/cache metadata still refreshes. Default: false. */
|
|
658
|
-
freezeDirectTools?: boolean;
|
|
659
|
-
autoAuth?: boolean;
|
|
660
|
-
sampling?: boolean;
|
|
661
|
-
samplingAutoApprove?: boolean;
|
|
662
|
-
elicitation?: boolean;
|
|
663
|
-
/**
|
|
664
|
-
* Guard oversized MCP tool/resource output before it is returned to the model.
|
|
665
|
-
* Defaults to true (50 KiB / 2,000 lines inline text, 16 KiB details.mcpResult).
|
|
666
|
-
* Set to false to restore raw MCP output behavior, or pass an object to tune
|
|
667
|
-
* the limits. Env kill switch: MCP_OUTPUT_GUARD=0.
|
|
668
|
-
*/
|
|
669
|
-
outputGuard?: boolean | McpOutputGuardSettings;
|
|
670
|
-
/**
|
|
671
|
-
* Opt-in metadata-only MCP protocol tracing. Payloads, prompts, tool
|
|
672
|
-
* arguments/results, authorization data, and URLs are never persisted.
|
|
673
|
-
*/
|
|
674
|
-
trace?: McpTraceSettings;
|
|
675
|
-
/**
|
|
676
|
-
* Message returned in tool results when a server needs (re-)authentication.
|
|
677
|
-
* "${server}" is substituted with the server name. Defaults to a TUI
|
|
678
|
-
* instruction when unset.
|
|
679
|
-
*/
|
|
680
|
-
authRequiredMessage?: string;
|
|
681
|
-
/** Explicitly use AES-256-GCM files keyed by PI_MCP_ADAPTER_OAUTH_FILE_KEY instead of the OS credential store. */
|
|
682
|
-
oauthCredentialStore?: "encrypted-file";
|
|
683
|
-
/**
|
|
684
|
-
* Legacy OAuth tokens.json import directory.
|
|
685
|
-
* Relative paths are resolved from the project root (cwd).
|
|
686
|
-
* Takes precedence over the agent's mcp-oauth/ legacy import directory but
|
|
687
|
-
* can still be overridden by the MCP_OAUTH_DIR env variable.
|
|
688
|
-
*
|
|
689
|
-
* Persistent OAuth credentials are stored in the operating system credential
|
|
690
|
-
* store, not this directory. Existing plaintext tokens.json files found here
|
|
691
|
-
* are imported once and removed.
|
|
692
|
-
*/
|
|
693
|
-
oauthDir?: string;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
|
-
export interface ClaudePluginConfig {
|
|
697
|
-
/** Explicit local Claude plugin directory. File-based config resolves relative paths from the active project cwd; createMcpAdapter snapshots programmatic paths against process.cwd(). */
|
|
698
|
-
path: string;
|
|
699
|
-
/** Load the plugin's root .mcp.json as low-precedence MCP defaults. */
|
|
700
|
-
mcp?: boolean;
|
|
701
|
-
/** Expose the plugin's root skills/ directory to Pi resource discovery. */
|
|
702
|
-
skills?: boolean;
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
// Root config
|
|
706
|
-
export interface McpConfig {
|
|
707
|
-
mcpServers: Record<string, ServerEntry>;
|
|
708
|
-
imports?: ImportKind[];
|
|
709
|
-
settings?: McpSettings;
|
|
710
|
-
claudePlugins?: ClaudePluginConfig[];
|
|
711
|
-
}
|
|
712
|
-
|
|
713
|
-
export interface McpAdapterOptions {
|
|
714
|
-
config?: McpConfig;
|
|
715
|
-
configPath?: string;
|
|
716
|
-
}
|
|
717
|
-
|
|
718
|
-
// Alias for clarity
|
|
719
|
-
export type ServerDefinition = ServerEntry;
|
|
720
|
-
|
|
721
|
-
export interface ToolMetadata {
|
|
722
|
-
name: string; // Prefixed tool name (e.g., "xcodebuild_list_sims")
|
|
723
|
-
originalName: string; // Original MCP tool name (e.g., "list_sims")
|
|
724
|
-
description: string;
|
|
725
|
-
resourceUri?: string; // For resource tools: the URI to read
|
|
726
|
-
uiResourceUri?: string; // For app-enabled tools: the UI resource URI
|
|
727
|
-
uiVisibility?: UiToolVisibility[];
|
|
728
|
-
inputSchema?: unknown; // JSON Schema for parameters (stored for describe/errors)
|
|
729
|
-
outputSchema?: unknown; // Server schema for structuredContent (stored for describe)
|
|
730
|
-
uiStreamMode?: UiStreamMode;
|
|
731
|
-
}
|
|
732
|
-
|
|
733
|
-
export interface PromptMetadata {
|
|
734
|
-
serverName: string;
|
|
735
|
-
originalName: string;
|
|
736
|
-
commandName: string;
|
|
737
|
-
title?: string;
|
|
738
|
-
description: string;
|
|
739
|
-
arguments: McpPromptArgument[];
|
|
740
|
-
}
|
|
741
|
-
|
|
742
|
-
export interface DirectToolSpec {
|
|
743
|
-
/** Registered inactive; `mcp({ search })` or a successful `mcp({ tool })` call activates it (directTools: "search"). */
|
|
744
|
-
lazy?: boolean;
|
|
745
|
-
serverName: string;
|
|
746
|
-
originalName: string;
|
|
747
|
-
prefixedName: string;
|
|
748
|
-
description: string;
|
|
749
|
-
inputSchema?: unknown;
|
|
750
|
-
resourceUri?: string;
|
|
751
|
-
uiResourceUri?: string;
|
|
752
|
-
uiStreamMode?: UiStreamMode;
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
export interface ServerProvenance {
|
|
756
|
-
path: string;
|
|
757
|
-
kind: "user" | "project" | "import";
|
|
758
|
-
importKind?: string;
|
|
759
|
-
}
|
|
760
|
-
|
|
761
|
-
export interface McpAuthResult {
|
|
762
|
-
ok: boolean;
|
|
763
|
-
message?: string;
|
|
764
|
-
}
|
|
765
|
-
|
|
766
|
-
export interface CachedTool {
|
|
767
|
-
name: string;
|
|
768
|
-
description?: string;
|
|
769
|
-
inputSchema?: unknown;
|
|
770
|
-
outputSchema?: unknown;
|
|
771
|
-
uiResourceUri?: string;
|
|
772
|
-
uiVisibility?: UiToolVisibility[];
|
|
773
|
-
uiStreamMode?: "eager" | "stream-first";
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
export interface CachedResource {
|
|
777
|
-
uri: string;
|
|
778
|
-
name: string;
|
|
779
|
-
description?: string;
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
export interface CachedPrompt {
|
|
783
|
-
name: string;
|
|
784
|
-
title?: string;
|
|
785
|
-
description?: string;
|
|
786
|
-
arguments?: { name: string; description?: string; required?: boolean }[];
|
|
787
|
-
}
|
|
788
|
-
|
|
789
|
-
export interface ServerCacheEntry {
|
|
790
|
-
configHash: string;
|
|
791
|
-
tools: CachedTool[];
|
|
792
|
-
resources: CachedResource[];
|
|
793
|
-
prompts?: CachedPrompt[];
|
|
794
|
-
instructions?: string;
|
|
795
|
-
/** Server-level hints from the aggregated tools/list result. */
|
|
796
|
-
ttlMs?: ListToolsResult["ttlMs"];
|
|
797
|
-
cacheScope?: ListToolsResult["cacheScope"];
|
|
798
|
-
cachedAt: number;
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
export interface MetadataCache {
|
|
802
|
-
version: number;
|
|
803
|
-
servers: Record<string, ServerCacheEntry>;
|
|
804
|
-
}
|
|
805
|
-
|
|
806
|
-
export interface McpPanelCallbacks {
|
|
807
|
-
reconnect: (serverName: string) => Promise<boolean>;
|
|
808
|
-
canAuthenticate: (serverName: string) => boolean;
|
|
809
|
-
authenticate: (serverName: string) => Promise<McpAuthResult>;
|
|
810
|
-
getConnectionStatus: (serverName: string) => "connected" | "idle" | "failed" | "needs-auth" | "disabled";
|
|
811
|
-
getFailureMessage?: (serverName: string) => string | null;
|
|
812
|
-
refreshCacheAfterReconnect: (serverName: string) => ServerCacheEntry | null;
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
export interface McpPanelResult {
|
|
816
|
-
changes: Map<string, true | string[] | false>;
|
|
817
|
-
/** Servers whose disabled flag changed during the panel session (name → new disabled state). */
|
|
818
|
-
disabledChanges: Map<string, boolean>;
|
|
819
|
-
cancelled: boolean;
|
|
820
|
-
}
|
|
821
|
-
|
|
822
|
-
/**
|
|
823
|
-
* Get server prefix based on tool prefix mode.
|
|
824
|
-
*/
|
|
825
|
-
function sanitizeServerPrefix(serverName: string, preserveProviderValid = true): string {
|
|
826
|
-
const validCharacters = preserveProviderValid ? /^[A-Za-z0-9_-]$/ : /^[A-Za-z0-9]$/;
|
|
827
|
-
return Array.from(serverName, char =>
|
|
828
|
-
validCharacters.test(char) ? char : `_${char.codePointAt(0)!.toString(16)}_`,
|
|
829
|
-
).join("");
|
|
830
|
-
}
|
|
831
|
-
|
|
832
|
-
export function getServerPrefix(
|
|
833
|
-
serverName: string,
|
|
834
|
-
mode: ToolPrefix
|
|
835
|
-
): string {
|
|
836
|
-
if (mode === "none") return "";
|
|
837
|
-
if (mode === "short") {
|
|
838
|
-
let short = sanitizeServerPrefix(serverName.replace(/-?mcp$/i, ""));
|
|
839
|
-
if (!short) short = "mcp";
|
|
840
|
-
return short;
|
|
841
|
-
}
|
|
842
|
-
if (mode === "mcp") return `mcp__${sanitizeServerPrefix(serverName)}`;
|
|
843
|
-
return sanitizeServerPrefix(serverName);
|
|
844
|
-
}
|
|
845
|
-
|
|
846
|
-
/**
|
|
847
|
-
* Format a tool name with server prefix.
|
|
848
|
-
*/
|
|
849
|
-
export function formatToolName(
|
|
850
|
-
toolName: string,
|
|
851
|
-
serverName: string,
|
|
852
|
-
prefix: ToolPrefix
|
|
853
|
-
): string {
|
|
854
|
-
const p = getServerPrefix(serverName, prefix);
|
|
855
|
-
const sanitized = toolName.replace(/\./g, "_");
|
|
856
|
-
if (p && sanitized.startsWith(`${p}_`) && sanitized.length > p.length + 1) {
|
|
857
|
-
return sanitized;
|
|
858
|
-
}
|
|
859
|
-
return p ? `${p}_${sanitized}` : sanitized;
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
export function resolveToolPrefix(
|
|
863
|
-
definition?: Pick<ServerEntry, "toolPrefix">,
|
|
864
|
-
globalPrefix?: ToolPrefix,
|
|
865
|
-
): ToolPrefix {
|
|
866
|
-
return definition?.toolPrefix ?? globalPrefix ?? "server";
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
/** A canonical name has an owner only when exactly one eligible entry produces it. */
|
|
870
|
-
export function resolveUniqueNameOwnership<T>(
|
|
871
|
-
entries: readonly T[],
|
|
872
|
-
getName: (entry: T) => string,
|
|
873
|
-
): { unique: T[]; collisions: Map<string, T[]> } {
|
|
874
|
-
const owners = new Map<string, T[]>();
|
|
875
|
-
for (const entry of entries) {
|
|
876
|
-
const name = getName(entry);
|
|
877
|
-
const named = owners.get(name) ?? [];
|
|
878
|
-
named.push(entry);
|
|
879
|
-
owners.set(name, named);
|
|
880
|
-
}
|
|
881
|
-
const collisions = new Map([...owners].filter(([, named]) => named.length > 1));
|
|
882
|
-
return {
|
|
883
|
-
unique: entries.filter((entry) => !collisions.has(getName(entry))),
|
|
884
|
-
collisions,
|
|
885
|
-
};
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
/**
|
|
889
|
-
* Resolve a configured MCP server name from a prefixed tool name.
|
|
890
|
-
*
|
|
891
|
-
* When the proxy tool is addressed with a fully-qualified name such as
|
|
892
|
-
* `searxng_searxng_web_search`, downstream policy systems (for example a
|
|
893
|
-
* permission gate) need to recover the owning server so they can evaluate
|
|
894
|
-
* server-scoped rules against the bare server name. This performs the inverse
|
|
895
|
-
* of {@link getServerPrefix}: it finds the longest configured server prefix
|
|
896
|
-
* that the tool name starts with and returns that server's name.
|
|
897
|
-
*
|
|
898
|
-
* @param toolName - the tool name as passed to the proxy `mcp({ tool })` call.
|
|
899
|
-
* @param serverNames - the configured MCP server names (keys of `mcpServers`).
|
|
900
|
-
* @param prefix - the active tool-prefix mode.
|
|
901
|
-
* @returns the resolved server name, or `undefined` when no prefix matches or
|
|
902
|
-
* the prefix mode is `"none"`.
|
|
903
|
-
*/
|
|
904
|
-
export function resolveServerFromToolName(
|
|
905
|
-
toolName: string,
|
|
906
|
-
serverNames: Iterable<string>,
|
|
907
|
-
prefix: ToolPrefix,
|
|
908
|
-
): string | undefined {
|
|
909
|
-
if (prefix === "none") return undefined;
|
|
910
|
-
const candidates: { name: string; prefix: string }[] = [];
|
|
911
|
-
for (const name of serverNames) {
|
|
912
|
-
const p = getServerPrefix(name, prefix);
|
|
913
|
-
if (p && toolName.startsWith(p + "_")) candidates.push({ name, prefix: p });
|
|
914
|
-
}
|
|
915
|
-
if (candidates.length === 0) return undefined;
|
|
916
|
-
candidates.sort((a, b) => b.prefix.length - a.prefix.length);
|
|
917
|
-
const best = candidates[0];
|
|
918
|
-
// Fail safe: short mode can intentionally map names such as foo and foo-mcp
|
|
919
|
-
// to the same prefix. Return undefined so a downstream permission gate uses
|
|
920
|
-
// its existing wildcard path rather than enforcing a rule against the wrong server.
|
|
921
|
-
if (candidates.some((c) => c.prefix === best!.prefix && c.name !== best!.name)) {
|
|
922
|
-
return undefined;
|
|
923
|
-
}
|
|
924
|
-
return best?.name;
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
export function sanitizePromptName(name: string): string {
|
|
928
|
-
const cleaned = name.replace(/[^A-Za-z0-9_-]+/g, "_").replace(/^[_-]+|[_-]+$/g, "");
|
|
929
|
-
if (!cleaned) return "prompt";
|
|
930
|
-
return /^[0-9]/.test(cleaned) ? `_${cleaned}` : cleaned;
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
export function formatPromptCommandName(
|
|
934
|
-
promptName: string,
|
|
935
|
-
serverName: string,
|
|
936
|
-
prefix: ToolPrefix,
|
|
937
|
-
): string {
|
|
938
|
-
const serverPart = getServerPrefix(serverName, prefix) || sanitizeServerPrefix(serverName) || "server";
|
|
939
|
-
return `mcp__${serverPart}__${sanitizePromptName(promptName)}`;
|
|
940
|
-
}
|
|
941
|
-
|
|
942
|
-
function getLegacyServerPrefix(serverName: string, mode: ToolPrefix): string {
|
|
943
|
-
if (mode === "none") return "";
|
|
944
|
-
if (mode === "short") return sanitizeServerPrefix(serverName.replace(/-?mcp$/i, ""), false) || "mcp";
|
|
945
|
-
if (mode === "mcp") return `mcp__${sanitizeServerPrefix(serverName, false)}`;
|
|
946
|
-
return sanitizeServerPrefix(serverName, false);
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
function formatLegacyToolName(toolName: string, serverName: string, prefix: ToolPrefix): string {
|
|
950
|
-
const serverPrefix = getLegacyServerPrefix(serverName, prefix);
|
|
951
|
-
const sanitizedToolName = toolName.replace(/[.-]/g, "_");
|
|
952
|
-
return serverPrefix ? `${serverPrefix}_${sanitizedToolName}` : sanitizedToolName;
|
|
953
|
-
}
|
|
954
|
-
|
|
955
|
-
export function getToolNameCandidates(toolName: string, serverName: string, prefix: ToolPrefix, includeLegacy = true): Set<string> {
|
|
956
|
-
const candidates = new Set<string>([
|
|
957
|
-
toolName,
|
|
958
|
-
formatToolName(toolName, serverName, prefix),
|
|
959
|
-
formatToolName(toolName, serverName, "server"),
|
|
960
|
-
formatToolName(toolName, serverName, "short"),
|
|
961
|
-
formatToolName(toolName, serverName, "mcp"),
|
|
962
|
-
]);
|
|
963
|
-
if (includeLegacy) {
|
|
964
|
-
const legacyToolName = toolName.replace(/-/g, "_");
|
|
965
|
-
candidates.add(legacyToolName);
|
|
966
|
-
candidates.add(formatToolName(legacyToolName, serverName, prefix));
|
|
967
|
-
candidates.add(formatToolName(legacyToolName, serverName, "server"));
|
|
968
|
-
candidates.add(formatToolName(legacyToolName, serverName, "short"));
|
|
969
|
-
candidates.add(formatToolName(legacyToolName, serverName, "mcp"));
|
|
970
|
-
candidates.add(formatLegacyToolName(toolName, serverName, prefix));
|
|
971
|
-
candidates.add(formatLegacyToolName(toolName, serverName, "server"));
|
|
972
|
-
candidates.add(formatLegacyToolName(toolName, serverName, "short"));
|
|
973
|
-
candidates.add(formatLegacyToolName(toolName, serverName, "mcp"));
|
|
974
|
-
candidates.add(formatToolName(toolName, serverName, prefix).replace(/-/g, "_"));
|
|
975
|
-
candidates.add(formatToolName(toolName, serverName, "server").replace(/-/g, "_"));
|
|
976
|
-
candidates.add(formatToolName(toolName, serverName, "short").replace(/-/g, "_"));
|
|
977
|
-
candidates.add(formatToolName(toolName, serverName, "mcp").replace(/-/g, "_"));
|
|
978
|
-
}
|
|
979
|
-
return candidates;
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
function globToRegExp(pattern: string): RegExp {
|
|
983
|
-
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
984
|
-
return new RegExp(`^${escaped}$`);
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
export interface ToolSelectorCandidateIndex {
|
|
988
|
-
readonly allCurrentCandidates: ReadonlySet<string>;
|
|
989
|
-
readonly matchingCountByPattern: Map<string, number>;
|
|
990
|
-
readonly matcherByPattern: Map<string, RegExp>;
|
|
991
|
-
readonly additionalCurrentCandidatesByToolName?: ReadonlyMap<string, ReadonlySet<string>>;
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
export function createToolSelectorCandidateIndex(
|
|
995
|
-
allCurrentCandidates: Set<string>,
|
|
996
|
-
additionalCurrentCandidatesByToolName?: ReadonlyMap<string, ReadonlySet<string>>,
|
|
997
|
-
): ToolSelectorCandidateIndex {
|
|
998
|
-
return {
|
|
999
|
-
allCurrentCandidates,
|
|
1000
|
-
matchingCountByPattern: new Map<string, number>(),
|
|
1001
|
-
matcherByPattern: new Map<string, RegExp>(),
|
|
1002
|
-
...(additionalCurrentCandidatesByToolName ? { additionalCurrentCandidatesByToolName } : {}),
|
|
1003
|
-
};
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
export function matchesToolPattern(candidates: Set<string>, patterns?: unknown): boolean {
|
|
1007
|
-
if (!Array.isArray(patterns) || patterns.length === 0) return false;
|
|
1008
|
-
|
|
1009
|
-
for (const pattern of patterns) {
|
|
1010
|
-
if (typeof pattern !== "string") continue;
|
|
1011
|
-
if (!pattern.includes("*") && !pattern.includes("?") && candidates.has(pattern)) {
|
|
1012
|
-
return true;
|
|
1013
|
-
}
|
|
1014
|
-
if ((pattern.includes("*") || pattern.includes("?")) && [...candidates].some(candidate => globToRegExp(pattern).test(candidate))) {
|
|
1015
|
-
return true;
|
|
1016
|
-
}
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
return false;
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
|
-
export type ToolSelectorCandidateContext = Set<string> | ToolSelectorCandidateIndex;
|
|
1023
|
-
|
|
1024
|
-
function indexHasOtherCurrentMatch(
|
|
1025
|
-
index: ToolSelectorCandidateIndex,
|
|
1026
|
-
toolName: string,
|
|
1027
|
-
currentCandidates: Set<string>,
|
|
1028
|
-
pattern: string,
|
|
1029
|
-
): boolean {
|
|
1030
|
-
const additionalCandidates = index.additionalCurrentCandidatesByToolName?.get(toolName);
|
|
1031
|
-
const hasCandidate = (candidate: string): boolean =>
|
|
1032
|
-
index.allCurrentCandidates.has(candidate) || additionalCandidates?.has(candidate) === true;
|
|
1033
|
-
const isGlob = pattern.includes("*") || pattern.includes("?");
|
|
1034
|
-
if (!isGlob) {
|
|
1035
|
-
return hasCandidate(pattern) && !currentCandidates.has(pattern);
|
|
1036
|
-
}
|
|
1037
|
-
|
|
1038
|
-
let matcher = index.matcherByPattern.get(pattern);
|
|
1039
|
-
if (!matcher) {
|
|
1040
|
-
matcher = globToRegExp(pattern);
|
|
1041
|
-
index.matcherByPattern.set(pattern, matcher);
|
|
1042
|
-
}
|
|
1043
|
-
let matchingCount = index.matchingCountByPattern.get(pattern);
|
|
1044
|
-
if (matchingCount === undefined) {
|
|
1045
|
-
matchingCount = 0;
|
|
1046
|
-
for (const candidate of index.allCurrentCandidates) {
|
|
1047
|
-
if (matcher.test(candidate)) matchingCount++;
|
|
1048
|
-
}
|
|
1049
|
-
index.matchingCountByPattern.set(pattern, matchingCount);
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
let totalMatchingCount = matchingCount;
|
|
1053
|
-
if (additionalCandidates) {
|
|
1054
|
-
for (const candidate of additionalCandidates) {
|
|
1055
|
-
if (!index.allCurrentCandidates.has(candidate) && matcher.test(candidate)) totalMatchingCount++;
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
if (totalMatchingCount === 0) return false;
|
|
1059
|
-
|
|
1060
|
-
let currentMatchingCount = 0;
|
|
1061
|
-
for (const candidate of currentCandidates) {
|
|
1062
|
-
if (hasCandidate(candidate) && matcher.test(candidate)) currentMatchingCount++;
|
|
1063
|
-
}
|
|
1064
|
-
return totalMatchingCount > currentMatchingCount;
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
function matchesToolSelector(
|
|
1068
|
-
toolName: string,
|
|
1069
|
-
serverName: string,
|
|
1070
|
-
prefix: ToolPrefix,
|
|
1071
|
-
patterns: unknown,
|
|
1072
|
-
otherCurrentCandidates?: ToolSelectorCandidateContext,
|
|
1073
|
-
): boolean {
|
|
1074
|
-
if (!Array.isArray(patterns) || patterns.length === 0) return false;
|
|
1075
|
-
const currentCandidates = getToolNameCandidates(toolName, serverName, prefix, false);
|
|
1076
|
-
if (matchesToolPattern(currentCandidates, patterns)) return true;
|
|
1077
|
-
if (!otherCurrentCandidates) return matchesToolPattern(getToolNameCandidates(toolName, serverName, prefix), patterns);
|
|
1078
|
-
const legacyCandidates = getToolNameCandidates(toolName, serverName, prefix);
|
|
1079
|
-
for (const candidate of currentCandidates) legacyCandidates.delete(candidate);
|
|
1080
|
-
return patterns.some(pattern => {
|
|
1081
|
-
if (typeof pattern !== "string" || !matchesToolPattern(legacyCandidates, [pattern])) return false;
|
|
1082
|
-
const hasCollision = otherCurrentCandidates instanceof Set
|
|
1083
|
-
? matchesToolPattern(otherCurrentCandidates, [pattern])
|
|
1084
|
-
: indexHasOtherCurrentMatch(otherCurrentCandidates, toolName, currentCandidates, pattern);
|
|
1085
|
-
return !hasCollision;
|
|
1086
|
-
});
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
export function isToolIncluded(
|
|
1090
|
-
toolName: string,
|
|
1091
|
-
serverName: string,
|
|
1092
|
-
prefix: ToolPrefix,
|
|
1093
|
-
includeTools?: unknown,
|
|
1094
|
-
otherCurrentCandidates?: ToolSelectorCandidateContext,
|
|
1095
|
-
): boolean {
|
|
1096
|
-
if (!Array.isArray(includeTools) || includeTools.length === 0) return true;
|
|
1097
|
-
return matchesToolSelector(toolName, serverName, prefix, includeTools, otherCurrentCandidates);
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
export function isToolExcluded(
|
|
1101
|
-
toolName: string,
|
|
1102
|
-
serverName: string,
|
|
1103
|
-
prefix: ToolPrefix,
|
|
1104
|
-
excludeTools?: unknown,
|
|
1105
|
-
otherCurrentCandidates?: ToolSelectorCandidateContext,
|
|
1106
|
-
): boolean {
|
|
1107
|
-
return matchesToolSelector(toolName, serverName, prefix, excludeTools, otherCurrentCandidates);
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
export function isToolAllowed(
|
|
1111
|
-
toolName: string,
|
|
1112
|
-
serverName: string,
|
|
1113
|
-
prefix: ToolPrefix,
|
|
1114
|
-
includeTools?: unknown,
|
|
1115
|
-
excludeTools?: unknown,
|
|
1116
|
-
otherCurrentCandidates?: ToolSelectorCandidateContext,
|
|
1117
|
-
): boolean {
|
|
1118
|
-
return isToolIncluded(toolName, serverName, prefix, includeTools, otherCurrentCandidates)
|
|
1119
|
-
&& !isToolExcluded(toolName, serverName, prefix, excludeTools, otherCurrentCandidates);
|
|
1120
|
-
}
|