pi-mcp-adapter 2.38.0 → 3.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 +24 -1
- package/OAUTH.md +1 -1
- package/README.md +56 -48
- package/cli.js +9 -9
- package/commands.ts +21 -10
- package/config.ts +199 -35
- package/direct-tool-surface.ts +1 -1
- package/direct-tools.ts +7 -5
- package/dist/config.d.ts +13 -0
- package/dist/config.js +184 -33
- package/dist/config.js.map +1 -1
- package/dist/package-mcp-loader.d.ts +9 -1
- package/dist/package-mcp-loader.js +8 -4
- package/dist/package-mcp-loader.js.map +1 -1
- package/dist/state.d.ts +5 -1
- package/dist/types.d.ts +12 -2
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +7 -0
- package/dist/utils.js.map +1 -1
- package/index.ts +70 -19
- package/init.ts +14 -4
- package/mcp-code.ts +55 -28
- package/mcp-panel.ts +6 -5
- package/mcp-script-wasm.ts +24 -0
- package/mcp-script-worker.mjs +228 -116
- package/mcp-setup-panel.ts +9 -10
- package/mcp-status.ts +8 -1
- package/namespace-tools.ts +5 -1
- package/package-mcp-loader.ts +21 -6
- package/package.json +4 -1
- package/project-server-trust.ts +199 -0
- package/prompts.ts +5 -5
- package/proxy-modes.ts +35 -29
- package/semantic-search.ts +1 -1
- package/state.ts +5 -1
- package/types.ts +12 -1
- package/utils.ts +11 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [3.0.0] - 2026-09-26
|
|
11
|
+
|
|
12
|
+
### Highlights
|
|
13
|
+
|
|
14
|
+
- The adapter now has its own config file, `mcp-adapter.json`, so it can run alongside Pi's upcoming built-in MCP support without starting the same servers twice. If you used `mcp.json` with the adapter, rename it (see Breaking).
|
|
15
|
+
- Opening a repository no longer starts its MCP servers on its own. Project servers wait until you trust the project and approve each server.
|
|
16
|
+
- `mcpScript` code now runs in a QuickJS sandbox that scripts cannot escape to reach your files or processes.
|
|
17
|
+
- MCP servers can now match each request to the Pi tool call that made it.
|
|
18
|
+
|
|
19
|
+
### Breaking
|
|
20
|
+
|
|
21
|
+
- The adapter no longer reads `<Pi agent dir>/mcp.json` or `.pi/mcp.json`. Those files now belong to Pi's built-in MCP support. Rename yours to `mcp-adapter.json` in the same folder. The format is the same, so `mv` is enough; if `mcp-adapter.json` already exists, merge the two. Until you do, Pi shows a warning with the exact command. `.mcp.json`, `~/.config/mcp/mcp.json`, and `--mcp-config` work as before.
|
|
22
|
+
- The interactive command is now `/mcp-adapter`. `/mcp` still works as a shortcut when Pi's built-in MCP extension is not installed.
|
|
23
|
+
|
|
24
|
+
### Security
|
|
25
|
+
|
|
26
|
+
- `mcpScript` now runs scripts in a memory-limited QuickJS/WASM sandbox instead of Node's `vm` module, which scripts could escape to reach `process`, the filesystem, or child processes ([#676](https://github.com/nicobailon/pi-mcp-adapter/issues/676)). Each script can emit up to 16 MiB of output, and error messages are capped at 64 KiB. Values pass between the script and Pi as JSON, so values that are not plain JSON still show up but may be formatted differently than before.
|
|
27
|
+
- MCP servers defined by a project no longer start until the project is trusted and you approve the server. This covers `.mcp.json`, `.pi/mcp-adapter.json`, and servers a project brings in through imports, plugins, repo-local host configs, or Pi packages in its settings. In an untrusted project they stay blocked. In a trusted interactive session, Pi shows the server's command or URL and asks once; the approval is saved, and Pi asks again if the server definition changes. Headless sessions skip unapproved servers unless your user-global config sets `settings.projectServers` to `"allow"`. `/mcp-adapter status` shows why a server is blocked. Fixes [#675](https://github.com/nicobailon/pi-mcp-adapter/issues/675).
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- MCP tool calls now include the id of the Pi tool call that made them, under `_meta["pi-mcp-adapter/toolCallId"]`, so servers can match requests to Pi's tool calls in their logs and traces. Direct tools, the `mcp` tool, and `mcp__<server>` tools send it. `mcpScript` calls do not, because a script is not a single tool call. Thanks to [@sebavalaris](https://github.com/sebavalaris) for [PR #673](https://github.com/nicobailon/pi-mcp-adapter/pull/673).
|
|
32
|
+
|
|
10
33
|
## [2.38.0] - 2026-09-26
|
|
11
34
|
|
|
12
35
|
### Highlights
|
|
@@ -751,7 +774,7 @@ The ranked search scoring, did-you-mean suggestions, approval patterns, endpoint
|
|
|
751
774
|
- Added a dedicated Pi-owned onboarding state file so shared-config hints behave as one-time guidance instead of repeating every session.
|
|
752
775
|
|
|
753
776
|
### Changed
|
|
754
|
-
-
|
|
777
|
+
- At the time, updated config precedence to prefer shared MCP files first, with `.pi/mcp.json` as the final project override. This legacy layout is superseded by the `mcp-adapter.json` hard cutover documented above.
|
|
755
778
|
- Updated Claude Code compatibility probing to prefer modern Claude MCP config locations before legacy paths.
|
|
756
779
|
- Updated project scaffolding so generated `.mcp.json` files are safe minimal shells instead of fake placeholder servers that fail on first reload.
|
|
757
780
|
- Updated the setup panel and README for clearer first-run guidance, improved spacing, and a more digestible shared-MCP-first setup story.
|
package/OAUTH.md
CHANGED
|
@@ -171,7 +171,7 @@ The SDK automatically:
|
|
|
171
171
|
To clear stored OAuth credentials and force a fresh authorization:
|
|
172
172
|
|
|
173
173
|
```
|
|
174
|
-
/mcp logout my-oauth-server
|
|
174
|
+
/mcp-adapter logout my-oauth-server
|
|
175
175
|
```
|
|
176
176
|
|
|
177
177
|
Within one Pi process, logout is a linearizable boundary: OAuth work that began
|
package/README.md
CHANGED
|
@@ -32,11 +32,11 @@ The adapter reads standard MCP files automatically. No extra setup needed if you
|
|
|
32
32
|
|
|
33
33
|
| You already have... | What happens |
|
|
34
34
|
|---------------------|--------------|
|
|
35
|
-
| `.mcp.json` or `~/.config/mcp/mcp.json` | Pi uses it immediately. Use `.mcp.json` for project/team sharing and `~/.config/mcp/mcp.json` for all projects.
|
|
36
|
-
| Host-specific configs (Cursor, Claude Code, Codex, etc.) but no standard MCP files | Run `/mcp setup` to adopt those host configs into Pi. The setup flow shows exactly what it found, lets you pick which ones to import, and previews the exact file changes before writing. |
|
|
37
|
-
| Nothing configured yet | Run `/mcp setup`, choose project `.mcp.json` or global `~/.config/mcp/mcp.json`, then scaffold a minimal config, add a curated known server, quick-add RepoPrompt, or inspect what the adapter discovered on your machine. |
|
|
35
|
+
| `.mcp.json` or `~/.config/mcp/mcp.json` | Pi uses it immediately. Use `.mcp.json` for project/team sharing and `~/.config/mcp/mcp.json` for all projects. |
|
|
36
|
+
| Host-specific configs (Cursor, Claude Code, Codex, etc.) but no standard MCP files | Run `/mcp-adapter setup` to adopt those host configs into Pi. The setup flow shows exactly what it found, lets you pick which ones to import, and previews the exact file changes before writing. |
|
|
37
|
+
| Nothing configured yet | Run `/mcp-adapter setup`, choose project `.mcp.json` or global `~/.config/mcp/mcp.json`, then scaffold a minimal config, add a curated known server, quick-add RepoPrompt, or inspect what the adapter discovered on your machine. |
|
|
38
38
|
|
|
39
|
-
If you prefer the terminal, you can also run `pi-mcp-adapter init` after install to scan for host-specific configs and add missing compatibility imports to the
|
|
39
|
+
If you prefer the terminal, you can also run `pi-mcp-adapter init` after install to scan for host-specific configs and add missing compatibility imports to the adapter config (`~/.pi/agent/mcp-adapter.json` by default, or `$PI_CODING_AGENT_DIR/mcp-adapter.json` when set).
|
|
40
40
|
|
|
41
41
|
## Quick Start
|
|
42
42
|
|
|
@@ -55,27 +55,25 @@ Preferred project config: `.mcp.json`
|
|
|
55
55
|
|
|
56
56
|
Preferred user-global shared config: `~/.config/mcp/mcp.json` (for all projects). Pi also reads the tool-agnostic global paths `~/.agents/mcp.json` and `~/.agents/mcp/mcp.json` as compatibility inputs.
|
|
57
57
|
|
|
58
|
-
Pi-
|
|
58
|
+
The adapter does not read Pi's `<Pi agent dir>/mcp.json` or `.pi/mcp.json` at all. If you previously used either file with this adapter, rename it to `mcp-adapter.json`; the format is unchanged, so a plain `mv` works (merge the files if the target already exists). This leaves `mcp.json` exclusively to Pi's built-in MCP support, so Pi and the adapter never start the same servers.
|
|
59
59
|
|
|
60
|
-
-
|
|
61
|
-
- `.pi/mcp.json` — Pi project override
|
|
62
|
-
|
|
63
|
-
Host-specific configs are detected and shown by `/mcp setup` and `pi-mcp-adapter init`, but they are compatibility inputs rather than normal setup paths and are not loaded automatically. The normal `/mcp` panel does not scan host-specific files when `settings.hostConfigDiscovery` is `"off"`. To explicitly opt in to host-config fallback discovery, set `settings.hostConfigDiscovery` to `"on"` or run `pi-mcp-adapter init --discover-host-configs`. The default is `"off"`; `"prompt"` is available for integrations that want detection without activation. Host configs are lower precedence than every shared and Pi-owned source, and `/mcp setup` continues to offer explicit import adoption. Discovery reports source paths, provenance, and same-name conflicts; it never writes to external host files or silently launches commands from them.
|
|
60
|
+
Host-specific configs are detected and shown by `/mcp-adapter setup` and `pi-mcp-adapter init`, but they are compatibility inputs rather than normal setup paths and are not loaded automatically. The normal `/mcp-adapter` panel does not scan host-specific files when `settings.hostConfigDiscovery` is `"off"`. To explicitly opt in to host-config fallback discovery, set `settings.hostConfigDiscovery` to `"on"` or run `pi-mcp-adapter init --discover-host-configs`. The default is `"off"`; `"prompt"` is available for integrations that want detection without activation. Host configs are lower precedence than every normal config source, and `/mcp-adapter setup` continues to offer explicit import adoption. Discovery reports source paths, provenance, and same-name conflicts; it never writes to external host files or silently launches commands from them.
|
|
64
61
|
|
|
65
62
|
Precedence is (later entries win):
|
|
66
63
|
|
|
67
64
|
1. `~/.config/mcp/mcp.json`
|
|
68
65
|
2. `~/.agents/mcp.json`
|
|
69
66
|
3. `~/.agents/mcp/mcp.json`
|
|
70
|
-
4. `<Pi agent dir>/mcp.json`
|
|
71
|
-
5. `.mcp.json`
|
|
72
|
-
6. `.
|
|
67
|
+
4. `<Pi agent dir>/mcp-adapter.json`
|
|
68
|
+
5. opted-in ancestors, farthest first: `.mcp.json`, `.pi/mcp-adapter.json`
|
|
69
|
+
6. `.mcp.json`
|
|
70
|
+
7. `.pi/mcp-adapter.json`
|
|
73
71
|
|
|
74
|
-
Ancestor discovery is off by default. To opt in, set `settings.ancestorConfigRoots` in a user-global config
|
|
72
|
+
Ancestor discovery is off by default. To opt in, set `settings.ancestorConfigRoots` in a user-global source (`~/.config/mcp/mcp.json`, either `~/.agents` MCP file, or the global `mcp-adapter.json`) or in the explicitly selected `--mcp-config`/`configPath` file, for example `"ancestorConfigRoots": ["~/work/team"]`. Each root must be an explicit absolute path or `~/...` and resolve to an existing directory under `$HOME`. Roots that do not contain the canonical cwd are ignored. If several roots match, only the nearest (deepest) is used. Project files cannot enable discovery or extend the boundary.
|
|
75
73
|
|
|
76
|
-
Within the selected root,
|
|
74
|
+
Within the selected root, `.mcp.json` and `<configDir>/mcp-adapter.json` load from the root through parent(cwd), farthest first. Nearer directories override farther ones, adapter config overrides shared config within each directory, and cwd files win over ancestors. Search never goes above the configured root or `$HOME`; the boundary limits discovery but is not a file-ownership or symlink-target sandbox. Only configure roots whose project files you trust.
|
|
77
75
|
|
|
78
|
-
`/mcp disable <server>` and `/mcp enable <server>` persist only the `disabled` field in the project-local `.pi/mcp.json`,
|
|
76
|
+
`/mcp-adapter disable <server>` and `/mcp-adapter enable <server>` persist only the `disabled` field in the project-local `.pi/mcp-adapter.json`, the highest-precedence adapter layer. The source file is never rewritten and credentials are never copied. Run `/reload` after changing the flag so registered tool surfaces are refreshed. Supplied in-memory `createMcpAdapter({ config })` configurations are isolated and do not read or write this project override; the commands are unavailable in that mode.
|
|
79
77
|
|
|
80
78
|
Servers are **lazy by default** — they won't connect until you actually call one of their tools. The adapter caches tool metadata so search and describe work without live connections.
|
|
81
79
|
|
|
@@ -102,7 +100,7 @@ Two calls instead of 26 tools cluttering the context.
|
|
|
102
100
|
|
|
103
101
|
### File Layout
|
|
104
102
|
|
|
105
|
-
Use
|
|
103
|
+
Use shared MCP files when you want one setup to work across hosts, and adapter-owned files for adapter-specific overrides or settings.
|
|
106
104
|
|
|
107
105
|
| File | Purpose |
|
|
108
106
|
|------|---------|
|
|
@@ -110,8 +108,10 @@ Use the shared MCP files when you want one setup to work across hosts, and Pi-ow
|
|
|
110
108
|
| `~/.agents/mcp.json` | User-global tool-agnostic MCP config |
|
|
111
109
|
| `~/.agents/mcp/mcp.json` | User-global tool-agnostic MCP config |
|
|
112
110
|
| `.mcp.json` | Project-local shared MCP config |
|
|
113
|
-
| `<Pi agent dir>/mcp.json` | Pi
|
|
114
|
-
|
|
|
111
|
+
| `<Pi agent dir>/mcp.json` | Pi built-in MCP config; never read by this adapter |
|
|
112
|
+
| `<Pi agent dir>/mcp-adapter.json` | Global adapter settings, imports, and overrides (`~/.pi/agent/mcp-adapter.json` by default) |
|
|
113
|
+
| `.pi/mcp.json` | Project Pi built-in MCP config; never read by this adapter |
|
|
114
|
+
| `.pi/mcp-adapter.json` | Project adapter settings and overrides |
|
|
115
115
|
|
|
116
116
|
For local stdio servers, a leading `~/` is expanded to the current user's home
|
|
117
117
|
directory in `command`, `args`, and `cwd`. On Windows, the equivalent `~\\`
|
|
@@ -137,7 +137,7 @@ The adapter can load MCP servers from [Agent Plugins](https://agent-plugins.org/
|
|
|
137
137
|
|
|
138
138
|
Each directory must contain a valid Agent Plugins 1.0 `plugin.json`. If it also has a root `mcp.json`, the adapter loads its `mcpServers` entries and prefixes them as `<plugin>__<server>`. The loader uses the Agent Plugins transport declared by each server `type` and skips invalid entries without blocking other servers. For stdio plugin servers, `${PLUGIN_ROOT}` and `${PLUGIN_DATA}` are expanded only in `args`, `env`, and `cwd`; the adapter sets both variables for the child process and stores plugin data under the Pi agent directory.
|
|
139
139
|
|
|
140
|
-
`inheritEnv` is an adapter-specific
|
|
140
|
+
`inheritEnv` is an adapter-specific field, not an Agent Plugins or OpenCode schema field. Do not add it to a plugin's strict `mcp.json`; to opt a plugin stdio server out of host-environment inheritance, set `inheritEnv: false` in an `mcp-adapter.json` override using the translated `<plugin>__<server>` name:
|
|
141
141
|
|
|
142
142
|
```json
|
|
143
143
|
{
|
|
@@ -147,7 +147,7 @@ Each directory must contain a valid Agent Plugins 1.0 `plugin.json`. If it also
|
|
|
147
147
|
}
|
|
148
148
|
```
|
|
149
149
|
|
|
150
|
-
Agent Plugins is a portable package format. Native
|
|
150
|
+
Agent Plugins is a portable package format. Native adapter config remains `.mcp.json`, `~/.config/mcp/mcp.json`, and `mcp-adapter.json` overrides.
|
|
151
151
|
|
|
152
152
|
### Local Claude plugin bundles
|
|
153
153
|
|
|
@@ -265,7 +265,7 @@ The public subpath exposes only token read/update helpers plus a status helper.
|
|
|
265
265
|
|
|
266
266
|
### Runtime status snapshots
|
|
267
267
|
|
|
268
|
-
Extensions can subscribe to the adapter's versioned shared event-bus channel instead of parsing `/mcp` or `mcp({})` output:
|
|
268
|
+
Extensions can subscribe to the adapter's versioned shared event-bus channel instead of parsing `/mcp-adapter` or `mcp({})` output:
|
|
269
269
|
|
|
270
270
|
```ts
|
|
271
271
|
import { MCP_STATUS_EVENT, type McpStatusSnapshot } from "pi-mcp-adapter";
|
|
@@ -322,7 +322,7 @@ In the configuration examples below, `30000` is illustrative only. If `requestTi
|
|
|
322
322
|
| `oauth.authServerMetadataUrl` | HTTPS URL of an OAuth/OIDC authorization-server metadata document. When set, this document is authoritative instead of MCP protected-resource discovery; its issuer remains validated by default |
|
|
323
323
|
| `oauth.skipIssuerMetadataValidation` | `true` disables the OAuth authorization-server metadata issuer check for this server. This weakens OAuth mix-up protection and should only be used for known-misconfigured internal servers while their metadata is being fixed. |
|
|
324
324
|
| `bearerToken` / `bearerTokenEnv` | Token or env var name; `bearerToken` supports `${VAR}` and `$env:VAR` interpolation. A leading `!` in `bearerToken` runs a command when the HTTP server connects; use `!!` for a literal leading `!`. |
|
|
325
|
-
| `bearerTokenStore` | Set to `true` to read a static bearer token from the adapter-owned OS credential store when `auth` is `"bearer"` and no `bearerToken` or `bearerTokenEnv` is configured. Stored records are keyed only by the server name, bind to the resolved server URL, and are never named by config. Store a token with `pi-mcp-adapter token set <server>`, which reads it from a masked prompt or stdin pipe and never from an argument. `/mcp token status <server>` and `/mcp token remove <server>` manage non-secret state inside Pi; `/mcp token set` stays disabled until Pi exposes masked secret input. |
|
|
325
|
+
| `bearerTokenStore` | Set to `true` to read a static bearer token from the adapter-owned OS credential store when `auth` is `"bearer"` and no `bearerToken` or `bearerTokenEnv` is configured. Stored records are keyed only by the server name, bind to the resolved server URL, and are never named by config. Store a token with `pi-mcp-adapter token set <server>`, which reads it from a masked prompt or stdin pipe and never from an argument. `/mcp-adapter token status <server>` and `/mcp-adapter token remove <server>` manage non-secret state inside Pi; `/mcp-adapter token set` stays disabled until Pi exposes masked secret input. |
|
|
326
326
|
| `lifecycle` | `"lazy"` (default), `"eager"`, `"keep-alive"`, or `"lazy-keep-alive"` |
|
|
327
327
|
| `idleTimeout` | Minutes before idle disconnect (overrides global) |
|
|
328
328
|
| `requestTimeoutMs` | Request timeout in milliseconds for live MCP calls (overrides global; if omitted or `<= 0`, the MCP SDK default timeout is used) |
|
|
@@ -427,9 +427,9 @@ Install an MCP endpoint without editing configuration:
|
|
|
427
427
|
mcp({ action: "install", url: "https://example.com/mcp" })
|
|
428
428
|
```
|
|
429
429
|
|
|
430
|
-
Install validates and connects the endpoint. New entries use a name derived from the hostname and are saved to
|
|
430
|
+
Install validates and connects the endpoint. New entries use a name derived from the hostname and are saved to the global `mcp-adapter.json`; existing URL entries are reused without rewriting. Pass `server` to choose a name or `target: "project"` to save to the project's `.mcp.json`. Unsafe URLs, name collisions, and failed connections are not persisted.
|
|
431
431
|
|
|
432
|
-
Set `settings.allowInstall` to `false` in
|
|
432
|
+
Set `settings.allowInstall` to `false` in `mcp-adapter.json` or another adapter config source (not Pi's `mcp.json` or `settings.json`) to block `mcp({ action: "install" })` for constrained or headless agents. Connect, search, tool calls, authentication, runtime registration, and interactive setup are unaffected.
|
|
433
433
|
|
|
434
434
|
In exclusive config mode, a project target must be the active config path; otherwise use the global target. URL install cannot promote runtime-registered servers: save their complete definitions manually so required headers and transport/auth settings are retained.
|
|
435
435
|
|
|
@@ -461,6 +461,12 @@ mcp({
|
|
|
461
461
|
|
|
462
462
|
You can also pass only the `code` query parameter with `args: { code: "..." }`. Treat authorization URLs and codes as sensitive; they can grant access to the MCP server until the flow expires or completes.
|
|
463
463
|
|
|
464
|
+
### Project server trust
|
|
465
|
+
|
|
466
|
+
Servers defined or changed by project-scoped MCP files (`.mcp.json`, `.pi/mcp-adapter.json`, and opted-in ancestor project files) do not run merely because a repository was opened. This includes servers brought in through project `imports`, `claudePlugins`, `settings.agentPluginPaths`, repo-local host config files (even when imports or discovery are enabled globally), or Pi packages listed in project `.pi/settings.json`. If Pi reports the project as untrusted, the adapter blocks them. In a trusted interactive session, the adapter shows the source file and command or URL and asks once before the first connection. The approval is stored under the Pi agent directory and is tied to the canonical project path, server name, and complete effective definition; changing the definition requires a new approval. Blocked servers are identified in the panel, while MCP status includes the required trust or approval action.
|
|
467
|
+
|
|
468
|
+
In print, JSON, and RPC sessions, an unapproved project server is skipped. To intentionally allow project servers in trusted headless sessions, set `"projectServers": "allow"` in the **user-global** `settings` object. The default is `"ask"`; project files cannot change this policy. Explicit config files, programmatic configuration, global/import/plugin servers, and runtime registrations retain their existing behavior. Project servers are always excluded from extension-load initialization and are admitted only after `session_start` supplies Pi's trust context.
|
|
469
|
+
|
|
464
470
|
### Lifecycle Modes
|
|
465
471
|
|
|
466
472
|
- **`lazy`** (default) — Don't connect at startup. Connect on first tool call. Disconnect after idle timeout. Cached metadata keeps search/list working without connections.
|
|
@@ -489,6 +495,7 @@ When any enabled server uses `eager` or `keep-alive`, initialization also starts
|
|
|
489
495
|
"notifyOnStartupConnect": true,
|
|
490
496
|
"warnOnLargeDirectTools": true,
|
|
491
497
|
"hostConfigDiscovery": "off",
|
|
498
|
+
"projectServers": "ask",
|
|
492
499
|
"approveTools": ["github_delete_*", "notion_update_*"],
|
|
493
500
|
"oauthDir": ".pi/mcp-oauth",
|
|
494
501
|
"trace": {
|
|
@@ -510,11 +517,12 @@ When any enabled server uses `eager` or `keep-alive`, initialization also starts
|
|
|
510
517
|
| `requestTimeoutMs` | Global request timeout in milliseconds for live MCP calls (if omitted or `<= 0`, the MCP SDK default timeout is used) |
|
|
511
518
|
| `deferWithMissingMetadata` | Allow lazy startup to defer when persisted metadata is missing or invalid (default: `false`). See [Direct Tools](#direct-tools) for the startup tradeoff. |
|
|
512
519
|
| `showStatusIcon` | Show the plug icon in MCP status and connection text (default: `true`). Set to `false` for plain `MCP: ...` text. |
|
|
513
|
-
| `mcpFooterStatus` | MCP footer verbosity: `"full"` (default), `"compact"` for `MCP connected/enabled`, or `"off"` to clear the persistent footer status. `/mcp status` remains available. |
|
|
520
|
+
| `mcpFooterStatus` | MCP footer verbosity: `"full"` (default), `"compact"` for `MCP connected/enabled`, or `"off"` to clear the persistent footer status. `/mcp-adapter status` remains available. |
|
|
514
521
|
| `toolResultRendering` | MCP tool result row style: `"compact"` (default) uses self-rendered rows, or `"boxed"` restores the legacy Pi boxed tool row. |
|
|
515
522
|
| `collapsedResultLines` | Number of result text lines to show before expansion: `1`, `2`, or `3`. Defaults to `1` in compact mode and `3` in boxed mode. |
|
|
516
523
|
| `notifyOnStartupConnect` | Show successful startup connection notices (default: `true`). Set to `false` to suppress routine `MCP: N servers connected (M tools)` notices. Connection errors and authentication warnings remain visible. |
|
|
517
524
|
| `hostConfigDiscovery` | Host-specific config policy: `"off"` (default), `"prompt"` (detect/report only), or `"on"` (explicitly load detected host configs as the lowest-precedence fallback) |
|
|
525
|
+
| `projectServers` | Project-server admission policy for trusted headless sessions: `"ask"` (default, skip unapproved servers) or `"allow"`. Only user-global or explicitly selected config may set it; project files are ignored. |
|
|
518
526
|
| `ancestorConfigRoots` | Trusted absolute or `~/...` roots for opt-in ancestor config discovery. Only user-global or explicitly selected config may set it; roots outside cwd are ignored and the deepest matching root is used. |
|
|
519
527
|
| `agentPluginPaths` | Agent Plugins package directories to load MCP servers from. Relative paths resolve from the active project cwd. |
|
|
520
528
|
| `approveTools` | `true` to require approval before every MCP tool call, or an array of glob patterns such as `["github_delete_*", "notion_update_*"]`. Per-server `approveTools` overrides this. |
|
|
@@ -529,7 +537,7 @@ When any enabled server uses `eager` or `keep-alive`, initialization also starts
|
|
|
529
537
|
| `freezeDirectTools` | Keep direct-tool registration stable after the initial sync so metadata updates and explicit reconnects do not rebuild the system prompt. Proxy/search/cache metadata still refreshes. Default: false. |
|
|
530
538
|
| `scriptMode` | Register the MCP-only `mcpScript` plain-JavaScript tool (default: true). Set to `false` to hide it. |
|
|
531
539
|
| `exposeResources` | Expose MCP resources as tools (default: `true`). Set to `false` to disable globally across all servers. Per-server `exposeResources` overrides this. |
|
|
532
|
-
| `jev` | Optional System One Jev settings. A valid System One key enables semantic search across every enabled MCP server by default; `semanticSearch: false` disables it. `scriptEvaluation` remains disabled by default and requires an `allowedServers` source allowlist when enabled. `jev: false` disables both. Run `/mcp jev setup` for guided configuration. |
|
|
540
|
+
| `jev` | Optional System One Jev settings. A valid System One key enables semantic search across every enabled MCP server by default; `semanticSearch: false` disables it. `scriptEvaluation` remains disabled by default and requires an `allowedServers` source allowlist when enabled. `jev: false` disables both. Run `/mcp-adapter jev setup` for guided configuration. |
|
|
533
541
|
| `disableProxyTool` | Hide the `mcp` proxy tool once configured direct tools are fully available from cache. Ignored while any server uses `directTools: "search"`, whose tools are registered inactive and can only be activated through the gateway (`mcp({ search })` or a successful `mcp({ tool })` call). |
|
|
534
542
|
| `autoAuth` | Auto-run OAuth on `connect`/tool calls when a server needs auth, then retry once (default: false). |
|
|
535
543
|
| `sampling` | Allow MCP servers to sample through Pi models, honoring `modelPreferences.hints` before current/default fallback (default: true when UI approval is available). |
|
|
@@ -628,7 +636,7 @@ The quickest desktop setup is:
|
|
|
628
636
|
pi-mcp-adapter key set systemone
|
|
629
637
|
```
|
|
630
638
|
|
|
631
|
-
That is enough to use semantic search across all enabled MCP tools. Run `/mcp jev setup` in Pi when you want to restrict which enabled servers may share semantic-search data. The command saves a project-scoped allowlist and reloads Pi automatically. Verify the stored credential at any time with `pi-mcp-adapter key status systemone`.
|
|
639
|
+
That is enough to use semantic search across all enabled MCP tools. Run `/mcp-adapter jev setup` in Pi when you want to restrict which enabled servers may share semantic-search data. The command saves a project-scoped allowlist and reloads Pi automatically. Verify the stored credential at any time with `pi-mcp-adapter key status systemone`.
|
|
632
640
|
|
|
633
641
|
`SYSTEMONE_API_KEY` is for CI/headless use and overrides the keyring. Stdio MCP subprocesses inherit the host environment by default, so set `inheritEnv: false` where they must not receive it. The script worker receives no key, SDK, endpoint, headers, or environment.
|
|
634
642
|
|
|
@@ -705,7 +713,7 @@ The upstream tool executes before this check and may already have side effects.
|
|
|
705
713
|
|
|
706
714
|
For a tool-restricted subagent, launch the child Pi with its tool allowlist set to `["mcpScript"]`. Have the parent discover MCP tool names with `mcp({ search: "..." })` and include the relevant prefixed names in the child's task; the child can then loop, filter, and chain those MCP calls without filesystem, shell, or edit tools. The adapter's ordinary lazy connection, authentication, abort handling, and approval gates still apply to every call.
|
|
707
715
|
|
|
708
|
-
`mcpScript`
|
|
716
|
+
`mcpScript` runs in an isolated QuickJS/WASM VM with a 64 MiB memory cap, a 16 MiB serialized output-block budget, and no Node.js, filesystem, network, timer, or process globals. Script error messages are capped at 64 KiB. MCP tool calls can still have external side effects and remain subject to the adapter's normal approval gates. It is distinct from Pi's code-mode skill: Pi's skill batches general Pi tools, while `mcpScript` exposes MCP calls only and can be the child's sole tool.
|
|
709
717
|
|
|
710
718
|
### MCP Prompts
|
|
711
719
|
|
|
@@ -714,7 +722,7 @@ MCP servers can advertise prompt templates alongside tools and resources. The ad
|
|
|
714
722
|
```text
|
|
715
723
|
/mcp__agent_board__create_plan "harden retry policy"
|
|
716
724
|
/mcp__agent_board__review_pipeline status=paused
|
|
717
|
-
/mcp prompts
|
|
725
|
+
/mcp-adapter prompts
|
|
718
726
|
```
|
|
719
727
|
|
|
720
728
|
Prompt results are flattened into one user message, preserving `[user]` and `[assistant]` role markers for multi-message results. Servers without the `prompts` capability are not probed.
|
|
@@ -821,11 +829,11 @@ To hide specific tools while still using `directTools: true`, add `excludeTools`
|
|
|
821
829
|
}
|
|
822
830
|
```
|
|
823
831
|
|
|
824
|
-
`includeTools` and `excludeTools` filter direct tools, proxy search/list/describe, and the `/mcp` panel view.
|
|
832
|
+
`includeTools` and `excludeTools` filter direct tools, proxy search/list/describe, and the `/mcp-adapter` panel view.
|
|
825
833
|
|
|
826
834
|
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 an advisory but still registers the tools you configured. Set `settings.warnOnLargeDirectTools` to `false` to suppress this advisory.
|
|
827
835
|
|
|
828
|
-
Direct tools register from the metadata cache in the Pi agent dir (`~/.pi/agent/mcp-cache.json` by default, or `$PI_CODING_AGENT_DIR/mcp-cache.json` when set), so no server connections are needed at startup. On the first session after adding `directTools` to a new server, the cache won't exist yet — tools fall back to proxy-only while the cache populates, then the extension hot-loads the refreshed direct tools into the current session. When `mcp({ connect: "<server>" })` is what discovers them, the connect result lists the new tools in `addedToolNames`, so Pi can load their definitions from that point in the transcript instead of rewriting the active tool list. Servers that advertise MCP list-change notifications refresh the current session when their tool or resource list changes. On Pi versions that expose `pi.unregisterTool()`, stale direct tools are removed from the registry during refresh; older Pi versions still deactivate them from the active tool set. To force a refresh: `/mcp reconnect <server>`.
|
|
836
|
+
Direct tools register from the metadata cache in the Pi agent dir (`~/.pi/agent/mcp-cache.json` by default, or `$PI_CODING_AGENT_DIR/mcp-cache.json` when set), so no server connections are needed at startup. On the first session after adding `directTools` to a new server, the cache won't exist yet — tools fall back to proxy-only while the cache populates, then the extension hot-loads the refreshed direct tools into the current session. When `mcp({ connect: "<server>" })` is what discovers them, the connect result lists the new tools in `addedToolNames`, so Pi can load their definitions from that point in the transcript instead of rewriting the active tool list. Servers that advertise MCP list-change notifications refresh the current session when their tool or resource list changes. On Pi versions that expose `pi.unregisterTool()`, stale direct tools are removed from the registry during refresh; older Pi versions still deactivate them from the active tool set. To force a refresh: `/mcp-adapter reconnect <server>`.
|
|
829
837
|
|
|
830
838
|
For faster startup, set `settings.deferWithMissingMetadata` to `true`. Servers with missing or invalid metadata (expired, mismatched, or non-cacheable) then contribute no tools, prompts, resources, or search entries until the first MCP operation starts the runtime and loads live metadata; the `mcp` gateway stays available. Because Pi cannot unregister slash commands, cached prompt commands also wait for live metadata under this setting. `eager`/`keep-alive` servers and cold `MCP_DIRECT_TOOLS` selections still start immediately.
|
|
831
839
|
|
|
@@ -835,11 +843,11 @@ Set `settings.directToolResultDetails` to `"bounded"` when an extension needs st
|
|
|
835
843
|
|
|
836
844
|
If prompt-cache stability matters more than direct-tool hot-loading, set `settings.freezeDirectTools` to `true`. The initial direct-tool sync still runs, but later metadata updates and explicit reconnects keep the registered tool surface unchanged while proxy/search/cache metadata refreshes normally.
|
|
837
845
|
|
|
838
|
-
When you change direct-tool toggles in `/mcp`, the extension updates direct tool registration in the current session. Broader setup writes from `/mcp setup` still use Pi's normal reload flow because they can add or restructure MCP config files.
|
|
846
|
+
When you change direct-tool toggles in `/mcp-adapter`, the extension updates direct tool registration in the current session. Broader setup writes from `/mcp-adapter setup` still use Pi's normal reload flow because they can add or restructure MCP config files.
|
|
839
847
|
|
|
840
|
-
**Interactive configuration:** Run `/mcp` to open an interactive panel showing all servers with connection status, tools, and direct/proxy toggles. You can reconnect servers, toggle tools between direct and proxy, and enable or disable servers (`ctrl+d`) from the same overlay. For OAuth, press Enter on a server that needs auth or `ctrl+a` on any OAuth server. The Save action defaults to `ctrl+s` and can be remapped with the `mcp.panel.save` keybinding.
|
|
848
|
+
**Interactive configuration:** Run `/mcp-adapter` to open an interactive panel showing all servers with connection status, tools, and direct/proxy toggles. `/mcp` is also available as an alias when Pi's built-in MCP extension is not installed. You can reconnect servers, toggle tools between direct and proxy, and enable or disable servers (`ctrl+d`) from the same overlay. For OAuth, press Enter on a server that needs auth or `ctrl+a` on any OAuth server. The Save action defaults to `ctrl+s` and can be remapped with the `mcp.panel.save` keybinding.
|
|
841
849
|
|
|
842
|
-
**Guided first-run setup:** Run `/mcp setup` to choose the normal write target for new shared servers — project `.mcp.json` or global `~/.config/mcp/mcp.json` — 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 selected config, add a curated known server (DeepWiki, Context7, Notion, GitHub, or Chrome DevTools), or quick-add RepoPrompt into a standard/shared MCP file.
|
|
850
|
+
**Guided first-run setup:** Run `/mcp-adapter setup` to choose the normal write target for new shared servers — project `.mcp.json` or global `~/.config/mcp/mcp.json` — 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 selected config, add a curated known server (DeepWiki, Context7, Notion, GitHub, or Chrome DevTools), or quick-add RepoPrompt into a standard/shared MCP file.
|
|
843
851
|
|
|
844
852
|
**Subagent integration:** If you use the subagent extension, agents can request direct MCP tools in their frontmatter with `mcp:server-name` syntax. See the subagent README for details.
|
|
845
853
|
|
|
@@ -921,7 +929,7 @@ Supported compatibility imports: `cursor`, `claude-code`, `claude-desktop`, `ope
|
|
|
921
929
|
|
|
922
930
|
### Project Config
|
|
923
931
|
|
|
924
|
-
Prefer `.mcp.json` for project-local shared MCP config and `~/.config/mcp/mcp.json` for user-global shared MCP config. Use `.pi/mcp.json`
|
|
932
|
+
Prefer `.mcp.json` for project-local shared MCP config and `~/.config/mcp/mcp.json` for user-global shared MCP config. Use `.pi/mcp-adapter.json` for adapter-specific project overrides. Pi `mcp.json` files are not adapter inputs; project files override user-global sources.
|
|
925
933
|
|
|
926
934
|
## Usage
|
|
927
935
|
|
|
@@ -979,24 +987,24 @@ Servers that provide usage guidance via the MCP `instructions` field surface it
|
|
|
979
987
|
|
|
980
988
|
| Command | What it does |
|
|
981
989
|
|---------|--------------|
|
|
982
|
-
| `/mcp` | Interactive panel and first-run onboarding surface |
|
|
983
|
-
| `/
|
|
984
|
-
| `/mcp setup` | Guided setup for imports, a minimal `.mcp.json`, curated known servers, RepoPrompt quick-add, and config-path inspection |
|
|
985
|
-
| `/mcp jev setup` | Restrict which servers may share semantic-search data, save the project policy, and reload Pi |
|
|
986
|
-
| `/mcp edit [project\|global]` | Open `.mcp.json` (default) or `~/.config/mcp/mcp.json` in an editor; Ctrl+G opens `$EDITOR`; saves a valid JSONC object and reloads |
|
|
987
|
-
| `/mcp tools` | List all tools |
|
|
988
|
-
| `/mcp prompts` | List all MCP prompts registered as slash commands |
|
|
989
|
-
| `/mcp reconnect` | Reconnect all servers |
|
|
990
|
-
| `/mcp reconnect <server>` | Connect or reconnect a single server |
|
|
991
|
-
| `/mcp disable <server>` | Disable a server in the project-local `.pi/mcp.json` (requires `/reload` to apply) |
|
|
992
|
-
| `/mcp enable <server>` | Enable through the project-local override layer (requires `/reload` to apply) |
|
|
993
|
-
| `/mcp logout <server>` | Clear stored OAuth credentials for a server and disconnect it |
|
|
990
|
+
| `/mcp-adapter` | Interactive panel and first-run onboarding surface |
|
|
991
|
+
| `/mcp` | Alias for `/mcp-adapter` only when Pi's built-in MCP extension is not installed |
|
|
992
|
+
| `/mcp-adapter setup` | Guided setup for imports, a minimal `.mcp.json`, curated known servers, RepoPrompt quick-add, and config-path inspection |
|
|
993
|
+
| `/mcp-adapter jev setup` | Restrict which servers may share semantic-search data, save the project policy, and reload Pi |
|
|
994
|
+
| `/mcp-adapter edit [project\|global]` | Open `.mcp.json` (default) or `~/.config/mcp/mcp.json` in an editor; Ctrl+G opens `$EDITOR`; saves a valid JSONC object and reloads |
|
|
995
|
+
| `/mcp-adapter tools` | List all tools |
|
|
996
|
+
| `/mcp-adapter prompts` | List all MCP prompts registered as slash commands |
|
|
997
|
+
| `/mcp-adapter reconnect` | Reconnect all servers |
|
|
998
|
+
| `/mcp-adapter reconnect <server>` | Connect or reconnect a single server |
|
|
999
|
+
| `/mcp-adapter disable <server>` | Disable a server in the project-local `.pi/mcp-adapter.json` (requires `/reload` to apply) |
|
|
1000
|
+
| `/mcp-adapter enable <server>` | Enable through the project-local override layer (requires `/reload` to apply) |
|
|
1001
|
+
| `/mcp-adapter logout <server>` | Clear stored OAuth credentials for a server and disconnect it |
|
|
994
1002
|
| `/mcp-auth` | Open an OAuth server picker in interactive UI sessions |
|
|
995
1003
|
| `/mcp-auth <server>` | OAuth setup for a specific server |
|
|
996
1004
|
|
|
997
1005
|
If `settings.autoAuth` is `true`, `mcp({ connect: ... })`, `mcp({ tool: ... })`, and direct tool calls automatically run OAuth when needed and retry once.
|
|
998
1006
|
|
|
999
|
-
In interactive sessions, you can also authenticate from `/mcp` with `ctrl+a` or Enter on a server that needs auth. `/mcp-auth` without a server only opens a picker in the interactive UI. For gateway authorization and manual callback completion, see [Remote/headless OAuth](#remoteheadless-oauth).
|
|
1007
|
+
In interactive sessions, you can also authenticate from `/mcp-adapter` with `ctrl+a` or Enter on a server that needs auth. `/mcp-auth` without a server only opens a picker in the interactive UI. For gateway authorization and manual callback completion, see [Remote/headless OAuth](#remoteheadless-oauth).
|
|
1000
1008
|
|
|
1001
1009
|
### MCP output schemas
|
|
1002
1010
|
|
package/cli.js
CHANGED
|
@@ -38,12 +38,12 @@ function getAgentDir() {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
const AGENT_DIR = getAgentDir();
|
|
41
|
-
const PI_CONFIG_PATH = path.join(AGENT_DIR, "mcp.json");
|
|
41
|
+
const PI_CONFIG_PATH = path.join(AGENT_DIR, "mcp-adapter.json");
|
|
42
42
|
const GENERIC_GLOBAL_CONFIG_PATH = path.join(HOME, ".config", "mcp", "mcp.json");
|
|
43
43
|
const AGENTS_GLOBAL_CONFIG_PATH = path.join(HOME, ".agents", "mcp.json");
|
|
44
44
|
const AGENTS_NESTED_GLOBAL_CONFIG_PATH = path.join(HOME, ".agents", "mcp", "mcp.json");
|
|
45
45
|
const PROJECT_CONFIG_PATH = path.resolve(process.cwd(), ".mcp.json");
|
|
46
|
-
const PROJECT_PI_CONFIG_PATH = path.resolve(process.cwd(), getConfigDirName(), "mcp.json");
|
|
46
|
+
const PROJECT_PI_CONFIG_PATH = path.resolve(process.cwd(), getConfigDirName(), "mcp-adapter.json");
|
|
47
47
|
|
|
48
48
|
const IMPORT_PATHS = {
|
|
49
49
|
cursor: [path.join(HOME, ".cursor", "mcp.json")],
|
|
@@ -131,9 +131,9 @@ function printDiscovery(log, imports) {
|
|
|
131
131
|
["User-global standard MCP", GENERIC_GLOBAL_CONFIG_PATH],
|
|
132
132
|
["User-global .agents MCP", AGENTS_GLOBAL_CONFIG_PATH],
|
|
133
133
|
["User-global .agents nested MCP", AGENTS_NESTED_GLOBAL_CONFIG_PATH],
|
|
134
|
-
["
|
|
134
|
+
["MCP adapter global override", PI_CONFIG_PATH],
|
|
135
135
|
["Project standard MCP", PROJECT_CONFIG_PATH],
|
|
136
|
-
["Project
|
|
136
|
+
["Project MCP adapter override", PROJECT_PI_CONFIG_PATH],
|
|
137
137
|
];
|
|
138
138
|
|
|
139
139
|
for (const [label, filePath] of paths) {
|
|
@@ -171,8 +171,8 @@ async function runInit(argv, log = console.log) {
|
|
|
171
171
|
|
|
172
172
|
const discoverySettingChanged = discoverHostConfigs && existingConfig.settings?.hostConfigDiscovery !== "on";
|
|
173
173
|
if (importsToAdd.length === 0 && !discoverySettingChanged) {
|
|
174
|
-
log("\nNo
|
|
175
|
-
log("Standard MCP configs are discovered automatically
|
|
174
|
+
log("\nNo MCP adapter config changes needed.");
|
|
175
|
+
log("Standard MCP configs are discovered automatically. Pi's mcp.json files are reserved for built-in MCP; adapter settings belong in mcp-adapter.json.");
|
|
176
176
|
return 0;
|
|
177
177
|
}
|
|
178
178
|
|
|
@@ -184,10 +184,10 @@ async function runInit(argv, log = console.log) {
|
|
|
184
184
|
};
|
|
185
185
|
|
|
186
186
|
if (importsToAdd.length > 0) {
|
|
187
|
-
log(`\nDetected host configs to import into
|
|
187
|
+
log(`\nDetected host configs to import into the MCP adapter: ${importsToAdd.join(", ")}`);
|
|
188
188
|
}
|
|
189
189
|
if (discoverySettingChanged) {
|
|
190
|
-
log("Opting in to host-specific fallback discovery (standard and
|
|
190
|
+
log("Opting in to host-specific fallback discovery (standard and adapter-owned configs still take precedence).");
|
|
191
191
|
}
|
|
192
192
|
|
|
193
193
|
if (dryRun) {
|
|
@@ -197,7 +197,7 @@ async function runInit(argv, log = console.log) {
|
|
|
197
197
|
|
|
198
198
|
writePiConfig(nextConfig);
|
|
199
199
|
log(`Updated ${PI_CONFIG_PATH}`);
|
|
200
|
-
log("
|
|
200
|
+
log("The adapter reads standard MCP configs automatically and stores adapter-specific imports in mcp-adapter.json; Pi's mcp.json is never read by the adapter.");
|
|
201
201
|
if (discoverySettingChanged) {
|
|
202
202
|
log("Host config discovery is explicit and does not write to or execute commands from external host files.");
|
|
203
203
|
}
|
package/commands.ts
CHANGED
|
@@ -32,6 +32,7 @@ import { loadOnboardingState, markSetupCompleted as persistSetupCompleted, markS
|
|
|
32
32
|
import { formatTerminalError, openPath, resolveServerUrl, sanitizeTerminalText } from "./utils.ts";
|
|
33
33
|
import { isAbortError } from "./runtime-owner.ts";
|
|
34
34
|
import { resolveJevCredential } from "./jev-key-store.ts";
|
|
35
|
+
import { describeProjectServerBlock } from "./project-server-trust.ts";
|
|
35
36
|
|
|
36
37
|
function terminalHyperlink(label: string, url: string): string {
|
|
37
38
|
return `\u001B]8;;${sanitizeTerminalText(url)}\u001B\\${sanitizeTerminalText(label)}\u001B]8;;\u001B\\`;
|
|
@@ -75,7 +76,7 @@ export async function setupJevSemanticSearch(
|
|
|
75
76
|
if (credential.status !== "present") {
|
|
76
77
|
const detail = credential.status === "unavailable" ? ` ${credential.message}` : "";
|
|
77
78
|
ctx.ui.notify(
|
|
78
|
-
`Jev needs a System One API key.${detail}\nRun \`pi-mcp-adapter key set systemone\` in a terminal, then run \`/mcp jev setup\` again.`,
|
|
79
|
+
`Jev needs a System One API key.${detail}\nRun \`pi-mcp-adapter key set systemone\` in a terminal, then run \`/mcp-adapter jev setup\` again.`,
|
|
79
80
|
"error",
|
|
80
81
|
);
|
|
81
82
|
return false;
|
|
@@ -141,18 +142,26 @@ export async function showStatus(state: McpExtensionState, ctx: ExtensionContext
|
|
|
141
142
|
if (!ctx.hasUI) return;
|
|
142
143
|
|
|
143
144
|
const lines: string[] = ["MCP Server Status:", ""];
|
|
145
|
+
if (state.migrationNotices?.length) {
|
|
146
|
+
lines.push(...state.migrationNotices.map((notice) => `⚠ ${notice}`), "");
|
|
147
|
+
}
|
|
144
148
|
if (!state.programmaticConfig) {
|
|
145
149
|
lines.push(
|
|
146
150
|
"Shared MCP config: .mcp.json for this project/team or ~/.config/mcp/mcp.json for all projects.",
|
|
147
|
-
"
|
|
151
|
+
"mcp-adapter.json files hold compatibility imports and adapter-specific overrides; Pi's mcp.json files are reserved for Pi and ignored.",
|
|
148
152
|
"",
|
|
149
153
|
);
|
|
150
154
|
}
|
|
151
155
|
|
|
152
156
|
for (const name of Object.keys(state.config.mcpServers)) {
|
|
153
157
|
const definition = state.config.mcpServers[name];
|
|
158
|
+
const block = state.blockedProjectServers?.get(name);
|
|
159
|
+
if (block) {
|
|
160
|
+
lines.push(`⊘ ${name}: ${describeProjectServerBlock(block.reason)}`);
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
154
163
|
if (isServerDisabled(definition)) {
|
|
155
|
-
lines.push(`⊘ ${name}: disabled (run /mcp enable ${name}, then /reload)`);
|
|
164
|
+
lines.push(`⊘ ${name}: disabled (run /mcp-adapter enable ${name}, then /reload)`);
|
|
156
165
|
continue;
|
|
157
166
|
}
|
|
158
167
|
const connection = state.manager.getConnection(name);
|
|
@@ -198,7 +207,7 @@ export async function showStatus(state: McpExtensionState, ctx: ExtensionContext
|
|
|
198
207
|
|
|
199
208
|
if (Object.keys(state.config.mcpServers).length === 0) {
|
|
200
209
|
lines.push("No MCP servers configured");
|
|
201
|
-
lines.push("Run /mcp setup to add a server to .mcp.json or ~/.config/mcp/mcp.json");
|
|
210
|
+
lines.push("Run /mcp-adapter setup to add a server to .mcp.json or ~/.config/mcp/mcp.json");
|
|
202
211
|
}
|
|
203
212
|
|
|
204
213
|
ctx.ui.notify(lines.join("\n"), "info");
|
|
@@ -280,7 +289,7 @@ export async function reconnectServer(
|
|
|
280
289
|
return false;
|
|
281
290
|
}
|
|
282
291
|
if (isServerDisabled(definition)) {
|
|
283
|
-
if (ui) ui.notify(`MCP: ${name} is disabled. Run /mcp enable ${name}, then /reload.`, "warning");
|
|
292
|
+
if (ui) ui.notify(`MCP: ${name} is disabled. Run /mcp-adapter enable ${name}, then /reload.`, "warning");
|
|
284
293
|
return false;
|
|
285
294
|
}
|
|
286
295
|
|
|
@@ -378,7 +387,7 @@ export async function authenticateServer(
|
|
|
378
387
|
return { ok: false, message };
|
|
379
388
|
}
|
|
380
389
|
if (isServerDisabled(definition)) {
|
|
381
|
-
const message = `Server "${serverName}" is disabled. Run /mcp enable ${serverName}, then /reload.`;
|
|
390
|
+
const message = `Server "${serverName}" is disabled. Run /mcp-adapter enable ${serverName}, then /reload.`;
|
|
382
391
|
ui.notify(message, "warning");
|
|
383
392
|
return { ok: false, message };
|
|
384
393
|
}
|
|
@@ -492,7 +501,7 @@ function validateBearerTokenStoreServer(
|
|
|
492
501
|
const safeName = sanitizeTerminalText(serverName);
|
|
493
502
|
const definition = state.config.mcpServers[serverName];
|
|
494
503
|
if (!definition) return { ok: false, message: `Server "${safeName}" not found in config`, type: "error" };
|
|
495
|
-
if (isServerDisabled(definition)) return { ok: false, message: `Server "${safeName}" is disabled. Run /mcp enable ${safeName}, then /reload.`, type: "warning" };
|
|
504
|
+
if (isServerDisabled(definition)) return { ok: false, message: `Server "${safeName}" is disabled. Run /mcp-adapter enable ${safeName}, then /reload.`, type: "warning" };
|
|
496
505
|
if (definition.auth !== "bearer" || definition.bearerTokenStore !== true) {
|
|
497
506
|
return { ok: false, message: `Server "${safeName}" is not configured for bearerTokenStore.`, type: "error" };
|
|
498
507
|
}
|
|
@@ -572,7 +581,7 @@ function buildSharedConfigNoticeLines(configOverridePath: string | undefined, cw
|
|
|
572
581
|
return {
|
|
573
582
|
lines: [
|
|
574
583
|
`Using standard MCP config from ${sourceList}.`,
|
|
575
|
-
"Use .mcp.json for project/team config or ~/.config/mcp/mcp.json for all projects.
|
|
584
|
+
"Use .mcp.json for project/team config or ~/.config/mcp/mcp.json for all projects. The adapter writes compatibility imports and adapter-specific overrides into mcp-adapter.json files when needed.",
|
|
576
585
|
],
|
|
577
586
|
fingerprint: discovery.fingerprint,
|
|
578
587
|
};
|
|
@@ -588,7 +597,7 @@ export async function openMcpSetup(
|
|
|
588
597
|
): Promise<PanelFlowResult> {
|
|
589
598
|
if (!ctx.hasUI) return { configChanged: false };
|
|
590
599
|
if (!canRenderPanel(ctx)) {
|
|
591
|
-
ctx.ui.notify(`The interactive MCP setup panel is only available in the terminal UI (current mode: ${ctx.mode}). Edit .mcp.json directly, or run /mcp status to review servers.`, "info");
|
|
600
|
+
ctx.ui.notify(`The interactive MCP setup panel is only available in the terminal UI (current mode: ${ctx.mode}). Edit .mcp.json directly, or run /mcp-adapter status to review servers.`, "info");
|
|
592
601
|
return { configChanged: false };
|
|
593
602
|
}
|
|
594
603
|
if (state.programmaticConfig) {
|
|
@@ -685,6 +694,7 @@ function buildMcpPanelCallbacks(
|
|
|
685
694
|
getConnectionStatus: (serverName: string) => {
|
|
686
695
|
authStatusFailures.delete(serverName);
|
|
687
696
|
const definition = config.mcpServers[serverName];
|
|
697
|
+
if (state.blockedProjectServers?.has(serverName)) return "blocked";
|
|
688
698
|
if (isServerDisabled(definition)) return "disabled";
|
|
689
699
|
const connection = state.manager.getConnection(serverName);
|
|
690
700
|
let serverUrl: string | undefined;
|
|
@@ -713,7 +723,8 @@ function buildMcpPanelCallbacks(
|
|
|
713
723
|
if (getFailureAgeSeconds(state, serverName) !== null) return "failed";
|
|
714
724
|
return "idle";
|
|
715
725
|
},
|
|
716
|
-
getFailureMessage: (serverName: string) =>
|
|
726
|
+
getFailureMessage: (serverName: string) => state.blockedProjectServers?.get(serverName)?.reason
|
|
727
|
+
?? authStatusFailures.get(serverName) ?? getFailureMessage(state, serverName),
|
|
717
728
|
refreshCacheAfterReconnect: (serverName: string) => {
|
|
718
729
|
const freshCache = loadMetadataCache();
|
|
719
730
|
return freshCache?.servers?.[serverName] ?? null;
|