pi-mcp-client 0.3.2 โ†’ 0.4.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.
Files changed (3) hide show
  1. package/README.md +399 -49
  2. package/dist/index.js +2172 -1091
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # ๐Ÿ”Œ Pi MCP Client
2
2
 
3
- MCP tools for Pi, discovered on demand and called natively through the official
4
- TypeScript SDK. No bridge process and no invocation proxy.
3
+ MCP tools and resources for Pi, discovered on demand through the official
4
+ TypeScript SDK. Read resources as context and call tools natively. No bridge
5
+ process and no invocation proxy.
5
6
 
6
7
  ## ๐Ÿš€ Installation
7
8
 
@@ -29,23 +30,38 @@ Start a new Pi session and ask it to search Cloudflare's documentation. Use `/mc
29
30
  to inspect the connection. For authenticated services, see [OAuth](#oauth) or
30
31
  [secret commands](#secret-commands).
31
32
 
32
- Pi discovers candidates, explicitly activates the tools it needs, then calls
33
- those tools natively. One `mcp_tools` tool supports both steps:
33
+ Pi discovers tool and resource metadata, reads selected resources as context,
34
+ and explicitly activates tools before calling them natively. One `mcp_tools`
35
+ tool supports discovery, reads, activation, and resource argument completions:
34
36
 
35
37
  ```js
36
- // Discover candidates. Never activates, even for an exact-name query.
37
- mcp_tools({ query: "list teams", server: "linear", limit: 5 })
38
+ // Discover tool and resource metadata. Never reads content or activates tools.
39
+ mcp_tools({ query: "database schema", server: "warehouse", limit: 5 })
40
+
41
+ // Read one resource into the conversation as a tool result.
42
+ mcp_tools({ read: { server: "warehouse", uri: "schema://analytics" } })
43
+
44
+ // Restrict discovery to tools when no resource context is needed.
45
+ mcp_tools({ query: "list teams", server: "linear", kind: "tools" })
38
46
 
39
47
  // Activate exact identifiers. Never invokes.
40
48
  mcp_tools({ activate: ["linear.list_teams", "linear.get_team"] })
41
49
  ```
42
50
 
43
- Pass exactly one of `query` or `activate`. The optional `server` and `limit`
44
- fields are valid only with `query`. Discovery returns up to five candidates by
45
- default, or up to 50 with `limit`. Each candidate shows its exact activation
46
- identifier, a short description, required parameter names only, and `[loaded]`
47
- if already active. Results use local BM25-based ranking, with tool names weighted
48
- more strongly than descriptions and support for prefix matching.
51
+ Pass exactly one of `query`, `activate`, `read`, or `complete`. The optional
52
+ `kind`, `server`, and `limit` fields are query-only; reads and completions carry
53
+ their server inside their respective objects.
54
+ `kind` defaults to `all`, or accepts `tools` and `resources`. Discovery returns up
55
+ to five candidates by default, or up to 50 with `limit`, across both kinds.
56
+
57
+ Tool candidates show an exact activation identifier, a short description,
58
+ required parameter names only, and `[loaded]` if already active. Resource
59
+ candidates show the owning server, title or name, exact URI, description, and
60
+ content type when supplied. Concrete resources and tools include exact next-call arguments; templates
61
+ include a read-call shape and variable names.
62
+ Search uses local BM25-based ranking of metadata, with names and resource titles
63
+ weighted more strongly than descriptions, and support for prefix matching.
64
+ Resource content isn't fetched or searched during discovery.
49
65
 
50
66
  Activation accepts 1โ€“50 exact `server.tool` or `mcp__server__tool` identifiers,
51
67
  ignores duplicates, and works without a prior search. Typos never activate fuzzy
@@ -59,8 +75,140 @@ can never become an active tool. Previously loaded tools remain available.
59
75
 
60
76
  `mcp_tools` replaces `mcp_search` without backward compatibility. Update explicit
61
77
  Pi tool allowlists to use `mcp_tools` and activate the tools you need again in
62
- existing sessions. The UI labels discovery calls **mcp discover** and activation
63
- calls **mcp activate**.
78
+ existing sessions. The UI labels discovery calls **mcp discover**, activation
79
+ calls **mcp activate**, resource reads **mcp read**, and argument completions
80
+ **mcp complete**.
81
+
82
+ ### Read resources as context
83
+
84
+ Ask Pi to use relevant context, such as a database schema or API guide. It can
85
+ discover the resource and read it without a browser, picker, or attachment dialog:
86
+
87
+ ```js
88
+ mcp_tools({ query: "authentication guide", kind: "resources" })
89
+ mcp_tools({ read: { server: "docs", uri: "docs://authentication" } })
90
+ ```
91
+
92
+ A read fetches one exact resource URI through its configured server's MCP
93
+ `resources/read` operation. It doesn't open a local file or make a generic HTTP
94
+ request, even for `file:` or `https:` URIs. There is no fallback when the server
95
+ can't read the URI. The server still controls which data it returns.
96
+
97
+ Tool-returned resource links include an exact `mcp_tools({read: ...})` call. Such
98
+ links can be read directly, without prior discovery or activation; linked
99
+ resources don't have to appear in the catalog.
100
+
101
+ Reading attaches content as the tool result itself, not as a second message. The
102
+ result identifies the source server and URIs and labels the content as untrusted
103
+ data. JSON and supported images use the existing result display. Large text is
104
+ truncated at 2,000 lines or 50 KiB; oversized results and unsupported binary
105
+ content are retained in a private temporary file. A resource read fetches the
106
+ server's full response before applying output limits; it isn't a streaming or
107
+ partial-content reader.
108
+
109
+ Reads never activate tools, start OAuth login, follow links in resource bodies,
110
+ or subscribe to live updates. Repeated reads fetch fresh content; earlier results
111
+ stay as snapshots. Resuming a session or navigating its branches doesn't re-read
112
+ resources. Resource content and selected metadata, including URIs, become session
113
+ data and may be sensitive. Private spill files can also contain sensitive data.
114
+
115
+ `includeTools` and `excludeTools` apply only to tools, not resources. Keeping
116
+ `mcp_tools` available permits resource reads from enabled servers, subject to the
117
+ server's authorization. `kind: "tools"` filters one search; it isn't an access
118
+ restriction. Disable a server to prevent all access, or exclude `mcp_tools` through
119
+ Pi's tool restrictions. Per-resource permission policies aren't implemented.
120
+
121
+ ### Read parameterized resources
122
+
123
+ Resource discovery also lists URI templates, such as `schema://tables/{table}`,
124
+ without enumerating every possible table. Templates have a `[template]` label,
125
+ variable names, and a read-call shape whose arguments you fill with known values:
126
+
127
+ ```js
128
+ mcp_tools({ query: "table schema", server: "warehouse", kind: "resources" })
129
+ mcp_tools({
130
+ read: {
131
+ server: "warehouse",
132
+ template: "schema://tables/{table}",
133
+ arguments: { table: "events" }
134
+ }
135
+ })
136
+ ```
137
+
138
+ Use either `uri` or `template` plus `arguments` inside `read`, never both. The
139
+ selected server must advertise the exact template. The official SDK expands
140
+ strings or string arrays into a concrete URI, then reads it through that same
141
+ server. Template variables aren't an input schema: no required fields or allowed
142
+ values are inferred. Use values from your request or prior results; Pi should
143
+ ask when a needed value is unknown rather than inventing an identifier.
144
+
145
+ Template reads use the same compact status row as exact reads:
146
+
147
+ ```text
148
+ mcp read
149
+ โœ”๏ธŽ warehouse ยท schema://tables/events
150
+ ```
151
+
152
+ Expanded output includes the template, supplied arguments, and resource content.
153
+ The same authorization, cancellation, output limits, and snapshot rules apply.
154
+ Template catalogs are memory-only, expire after five minutes, and are invalidated
155
+ with resource metadata. Argument data is limited to 64 KiB and expanded URIs to
156
+ 4,096 characters.
157
+
158
+ ### Complete resource arguments
159
+
160
+ Ask the server for suggested values for one advertised template variable:
161
+
162
+ ```js
163
+ mcp_tools({
164
+ complete: {
165
+ server: "warehouse",
166
+ template: "schema://tables/{table}",
167
+ argument: { name: "table", value: "ev" }
168
+ }
169
+ })
170
+ ```
171
+
172
+ `value` is the current prefix and can be empty. For dependent suggestions, add
173
+ `arguments: { knownVariable: "value" }` inside `complete`. These context values
174
+ must be strings, not arrays. The server must advertise completion support and
175
+ the exact template; the variable must occur in that template.
176
+
177
+ The result contains `values` and, when supplied by the server, `total` and
178
+ `hasMore`. Narrow the prefix when more matches are available. Suggestions are
179
+ untrusted server data, not a required-field schema or instructions. Completion
180
+ never reads resources, activates tools, or chooses a value automatically. Use
181
+ `complete` alone, without query, activation, read, or search options. Requests
182
+ are limited to 64 KiB; output uses the same 2,000-line / 50 KiB limit and private
183
+ spill files as other results.
184
+
185
+ ### Watch resource changes
186
+
187
+ Subscriptions are explicit user commands, not model-facing tool operations:
188
+
189
+ ```text
190
+ /mcp subscribe warehouse schema://tables/events
191
+ /mcp subscriptions
192
+ /mcp unsubscribe warehouse schema://tables/events
193
+ ```
194
+
195
+ Use an exact absolute URI from discovery, a template read, or a resource link.
196
+ The configured server must support resource subscriptions. Pi uses the SDK's
197
+ negotiated protocol: legacy resource subscriptions or modern filtered streams.
198
+ It never opens the URI as a file or generic URL.
199
+
200
+ An update marks the watch as changed (`โ†ป`) and shows a UI notification. Repeated
201
+ updates coalesce into that marker until you unsubscribe. No content is fetched,
202
+ no model turn starts, and existing attachments remain unchanged. Read explicitly
203
+ for a new snapshot; unsubscribe and subscribe again to reset the change marker.
204
+
205
+ Watches are memory-only, limited to 50 per server connection, and require an
206
+ interactive UI (TUI or RPC). Repeating a subscribe command is idempotent. Session
207
+ replacement, tree navigation, configuration reload, disconnection, and exit
208
+ clear the affected watches. They are never restored or automatically retried;
209
+ use `/mcp subscriptions` to inspect currently active watches. Cancellation and
210
+ connection failures can leave an uncertain server-side outcome; cleanup is
211
+ best-effort.
64
212
 
65
213
  ### Result display
66
214
 
@@ -95,14 +243,20 @@ not the displayed link label.
95
243
  | Command | Purpose |
96
244
  | --- | --- |
97
245
  | `/mcp`, `/mcp list`, `/mcp status` | Show a server status matrix with catalog and loaded-tool counts. |
98
- | `/mcp inspect <server>` | Inspect status and configuration, including disabled servers. Connection values are hidden. |
246
+ | `/mcp add --scope <scope> [options] <server> <url>` | Save an HTTP server without connecting. For stdio, use `<server> -- <command> [args...]`. |
247
+ | `/mcp remove --scope <scope> <server>` | Remove a definition from the selected scope, retaining credentials. |
248
+ | `/mcp get <server>` | Inspect status and configuration, including disabled servers. Connection values are hidden. |
99
249
  | `/mcp tools <server>` | Browse the server's tools and inspect descriptions without activating tools. |
100
250
  | `/mcp reload` | Apply configuration changes without restarting Pi. |
101
251
  | `/mcp enable <server>` | Enable a server in its effective configuration file. |
102
252
  | `/mcp disable <server>` | Disable a server, close its connection, and deactivate its tools. |
103
- | `/mcp auth <server>` | Authenticate an OAuth-enabled HTTP server. |
253
+ | `/mcp login <server> [--no-browser]` | Authenticate an OAuth-enabled HTTP server; optionally paste the callback URL in an interactive dialog. |
254
+ | `/mcp logout <server>` | Remove local OAuth credentials and attempt remote revocation, including for disabled servers. |
104
255
  | `/mcp reconnect <server>` | Replace a connection and refresh its catalog. |
105
- | `/mcp refresh <server>` | Refresh a server's catalog without loading additional tools. |
256
+ | `/mcp refresh <server>` | Refresh tool and resource metadata without reading resources or loading additional tools. |
257
+ | `/mcp subscribe <server> <uri>` | Watch changes to one exact resource URI without fetching content. |
258
+ | `/mcp unsubscribe <server> <uri>` | Stop watching one resource. |
259
+ | `/mcp subscriptions` | List active resource watches and their change markers. |
106
260
 
107
261
  The status matrix uses glyphs to distinguish idle (`โ—‹`), connected (`โ—`),
108
262
  connecting (`โ–ถ๏ธŽ`), disabled (`โ—‹`), and failed (`โœ˜๏ธŽ`) servers. Idle is normal:
@@ -227,6 +381,9 @@ Put descriptions, authentication choices, filters, and timeouts directly in each
227
381
  | --- | --- |
228
382
  | `description` | Short capability description for Pi's server directory. |
229
383
  | `oauth` | Set to `true` to use OAuth instead of an Authorization header on an HTTP connection. |
384
+ | `oauthClientId` | Optional pre-registered public client ID. Requires `oauth: true`; supports `${ENV_VAR}` interpolation, not secret commands. |
385
+ | `oauthScopes` | Optional array of 1โ€“100 unique OAuth scope tokens to request at login. Requires `oauth: true`; omitted scopes use SDK/server defaults. Values are literal, without interpolation. |
386
+ | `oauthCallbackPort` | Optional loopback callback port, from 1 to 65535. Defaults to `19847`. Requires `oauth: true`. |
230
387
  | `disabled` | Prevent this server from connecting or exposing tools. |
231
388
  | `includeTools` | Optional allowlist of original MCP tool names; `*` matches any sequence. An empty list exposes nothing. |
232
389
  | `excludeTools` | Denylist applied after `includeTools`. |
@@ -261,10 +418,13 @@ search and deactivates its tools. Enabling does not connect, authenticate, or lo
261
418
  tools; ask the assistant to discover the capabilities you need. Other running Pi
262
419
  sessions pick up the saved change when they reload their MCP configuration.
263
420
 
264
- Use `/mcp inspect <server>` to check the effective transport, protocol, filters,
421
+ Use `/mcp get <server>` to check the effective transport, protocol, filters,
265
422
  and connection status without connecting or running secret commands. Connection
266
423
  valuesโ€”including commands, arguments, URLs, headers, and environment variablesโ€”
267
- are hidden because any of them can contain credentials.
424
+ are hidden because any of them can contain credentials. Authentication status shows
425
+ whether OAuth tokens are stored, not whether they are valid. A locked or unavailable
426
+ credential store is reported separately from missing tokens. Header and stdio
427
+ credentials are identified as externally managed; inspection never executes them.
268
428
 
269
429
  Use `/mcp tools <server>` to fetch the current catalog and browse a scrollable
270
430
  list. Each row shows the tool name and description, trimmed to the terminal width
@@ -273,19 +433,103 @@ with each parameter in a separate paragraph. Browsing respects your include and
273
433
  exclude filters and doesn't activate tools or add their schemas to the assistant's
274
434
  context. This command requires an interactive UI.
275
435
 
436
+ ### Add and remove servers
437
+
438
+ Both commands require an explicit `--scope global` or `--scope project`:
439
+
440
+ - **Global:** `~/.pi/agent/mcp.json`.
441
+ - **Project:** `.mcp.json` in the current trusted project. Untrusted project files
442
+ are neither read nor changed.
443
+
444
+ Add an HTTP server by URL, or a stdio server after `--`:
445
+
446
+ ```text
447
+ /mcp add --scope global docs https://docs.mcp.cloudflare.com/mcp
448
+ /mcp add --scope project local -- node "/path with spaces/server.js"
449
+ ```
450
+
451
+ Put options before the server name. `--transport http` or `--transport stdio` is
452
+ optional; the URL form selects HTTP and the `--` form selects stdio. Arguments
453
+ support single and double quotes and backslash escaping, but are never evaluated
454
+ by a shell. Shell syntax such as `$(...)`, pipes, and globs stays literal. For
455
+ Windows paths with backslashes, single quotes preserve the path verbatim.
456
+
457
+ Additional options:
458
+
459
+ | Option | Purpose |
460
+ | --- | --- |
461
+ | `--replace` | Replace the complete definition in the selected scope, or create an override of a same-named definition in the other scope. Existing fields are not merged. |
462
+ | `--header 'Name: value'` | Add an HTTP header. Repeat for different header names. |
463
+ | `--env KEY=value` | Add a stdio environment override. Repeat for different variable names. |
464
+ | `--oauth` | Enable OAuth for an HTTP server. |
465
+ | `--oauth-client-id ID` | Use a pre-registered public client. Requires `--oauth`. |
466
+ | `--oauth-scope SCOPE` | Request an OAuth scope. Repeat for additional scopes. Requires `--oauth`. |
467
+ | `--oauth-callback-port PORT` | Set the loopback callback port. Requires `--oauth`. |
468
+
469
+ For example, retain an environment reference rather than typing a token:
470
+
471
+ ```text
472
+ /mcp add --scope global --header 'Authorization: Bearer ${DOCS_TOKEN}' docs https://mcp.example.com/mcp
473
+ /mcp add --scope global --oauth --oauth-client-id '${CLIENT_ID}' service https://mcp.example.com/mcp
474
+ ```
475
+
476
+ Define referenced environment variables before running the command. Validation
477
+ checks the resolved configuration, but saves the references, not their values.
478
+ Secret commands in headers or environment overrides are saved without running
479
+ them. Avoid typing literal credentials in command input or project files; use
480
+ [environment references and secret commands](#secret-commands) instead.
481
+
482
+ Adding never starts a server, opens a browser, or activates tools. Duplicate names
483
+ in global or trusted project configuration are rejected unless you supply
484
+ `--replace`. Project definitions take precedence; writing a global definition does
485
+ not replace a project override. Other server options, such as tool filters, remain
486
+ available by editing the configuration file.
487
+
488
+ Remove a definition from a specific scope:
489
+
490
+ ```text
491
+ /mcp remove --scope project local
492
+ ```
493
+
494
+ Removal is distinct from disabling and logout: it deletes the selected definition,
495
+ not its OAuth credentials. Run `/mcp logout <server>` first if you also want to
496
+ remove credentials. Removing a project override exposes any same-named global
497
+ definition; the command reports when a definition in the other scope remains.
498
+ Removing a name absent from the selected scope fails without changing either file.
499
+
500
+ Successful edits apply immediately using the same connection and tool reconciliation
501
+ as `/mcp reload`. Connections close and reopen on demand; tools whose effective
502
+ definition changed or disappeared are deactivated, while unchanged active tools
503
+ remain available. Other Pi sessions pick up saved changes when they reload.
504
+
505
+ Writes preserve unrelated settings, follow existing file symlinks, and replace
506
+ files atomically. New files are private; existing file permissions are preserved.
507
+ If global and project configuration point to the same file, scoped edits are
508
+ refused until you separate them. Empty configuration files are retained rather
509
+ than deleted.
510
+
276
511
  ### Discovery and caching
277
512
 
278
513
  Connections start on demand, never while the extension factory loads. A search
279
- without a cached catalog contacts configured servers, with at most four discoveries
280
- in flight. A server-scoped search only contacts that server. Activation discovers
514
+ without the requested cached metadata contacts configured servers, with at most
515
+ four server discoveries in flight. A server-scoped search only contacts that server. Activation discovers
281
516
  only the servers named by its identifiers, with the same concurrency bound.
282
517
  Failed servers are reported as unavailable, not mistaken for an empty catalog.
283
518
 
284
- Catalogs are cached privately under `~/.pi/agent/cache/pi-mcp-client/`, keyed by
519
+ Tool catalogs are cached privately under `~/.pi/agent/cache/pi-mcp-client/`, keyed by
285
520
  server configuration and working directory. Disk caches expire after 24 hours.
286
- They contain tool metadata, not configured credentials. Cached discovery and
287
- activation need no connection; invocation refreshes the live catalog before
521
+ They contain tool metadata, not configured credentials. Cached tool-only discovery
522
+ and activation need no connection; invocation refreshes the live catalog before
288
523
  calling the tool.
524
+
525
+ Resource metadata is held only in memory for up to five minutes, not written to
526
+ the tool catalog cache. Mixed discovery therefore may connect even when tools
527
+ are cached on disk. Resource-list notifications, disconnection, and explicit
528
+ refresh invalidate resource metadata without reading content. Tool and resource
529
+ catalog failures are reported independently; healthy candidates remain available.
530
+ The SDK handles pagination. Resource catalogs are limited to 10,000 entries and
531
+ 4 MiB of descriptor data; oversized catalogs fail rather than silently returning
532
+ a partial list. Reads bypass the SDK content cache.
289
533
  Connections remain open until shutdown or explicit reconnection.
290
534
 
291
535
  When a connected server reports a tool-list change, the extension invalidates its
@@ -297,20 +541,130 @@ can't receive notifications and still use the 24-hour disk-cache expiry.
297
541
  ### OAuth
298
542
 
299
543
  Set `"oauth": true` under `mcpServers.<server>` in `mcp.json`, without an
300
- Authorization header in its connection, then run `/mcp auth <server>`. Pi opens the
544
+ Authorization header in its connection, then run `/mcp login <server>`. Pi opens the
301
545
  browser only for this explicit command. Automatic discovery never opens a browser.
302
546
 
303
547
  OAuth tokens and client registrations are stored in the operating system
304
- credential store, bound to the server URL and authorization-server issuer.
548
+ credential store, bound to the server URL, configured client ID (if any), and
549
+ authorization-server issuer.
305
550
  There is no plaintext credential fallback. PKCE verifiers and callback state stay
306
551
  in memory.
307
552
 
308
- The initial implementation supports dynamically registered public clients with a
309
- local callback at `http://127.0.0.1:19847/callback`. The browser must be able to
310
- reach that address on the Pi machine. Authentication times out after two minutes;
311
- you can cancel it with Escape in the terminal UI.
312
- Pre-registered OAuth clients, remote callback pasting, and headless interactive
313
- OAuth are not supported yet. Use bearer headers for headless access.
553
+ Run `/mcp logout <server>` to remove stored tokens and client registrations. Logout
554
+ also closes connections and deactivates tools for configured OAuth servers sharing
555
+ the same URL and configured client ID, since they share credentials. Configuration and enabled state stay
556
+ unchanged. Disabled servers accept logout too. Header and server-managed credentials
557
+ remain untouched.
558
+
559
+ Local removal happens before a bounded attempt to revoke tokens at the original
560
+ authorization server. The result distinguishes accepted revocation, unsupported
561
+ revocation, and unconfirmed revocation. When revocation isn't confirmed, remove the
562
+ grant at the service if needed. Repeating logout is safe. Other running Pi sessions
563
+ may need to reconnect; logout cannot recall requests already sent to a server.
564
+ No browser opens until you explicitly run `/mcp login <server>`.
565
+
566
+ Public clients can use dynamic registration or a pre-registered client ID. Both
567
+ use PKCE and a loopback callback at `http://127.0.0.1:19847/callback` by default.
568
+ Normal login opens a local listener that the browser must be able to reach.
569
+ Authentication times out after two minutes; you can cancel it with Escape in the
570
+ terminal UI. Explicit login always starts a fresh authorization flow, even if a
571
+ refresh token is already stored. The browser callback page identifies **Pi MCP
572
+ Client** and asks you to return to Pi; receiving a callback doesn't yet mean the
573
+ token exchange succeeded.
574
+
575
+ For a server without dynamic registration, register a **public/native** client
576
+ with the service, using that exact callback URL and token endpoint authentication
577
+ method `none`. Then configure its client ID:
578
+
579
+ ```json
580
+ {
581
+ "mcpServers": {
582
+ "example": {
583
+ "url": "https://mcp.example.com/mcp",
584
+ "oauth": true,
585
+ "oauthClientId": "${EXAMPLE_OAUTH_CLIENT_ID}"
586
+ }
587
+ }
588
+ }
589
+ ```
590
+
591
+ Run `/mcp reload`, then `/mcp login example`. The configured ID is used for login,
592
+ token refresh, and revocation; Pi never falls back to dynamic registration if it
593
+ is rejected. `/mcp get example` identifies the client as pre-registered without
594
+ printing the ID.
595
+
596
+ Changing the client ID selects separate credentials and requires a new login.
597
+ Log out before changing or removing the ID if you want to delete its old
598
+ credentials. After the first successful grant, a pre-registered client is pinned
599
+ to its authorization-server issuer. If that issuer changes, verify the server
600
+ configuration before logging out and logging in again to trust the replacement.
601
+
602
+ #### Requested scopes and callback ports
603
+
604
+ Configure scopes and a callback port in the server definition:
605
+
606
+ ```json
607
+ {
608
+ "mcpServers": {
609
+ "example": {
610
+ "url": "https://mcp.example.com/mcp",
611
+ "oauth": true,
612
+ "oauthScopes": ["read", "write"],
613
+ "oauthCallbackPort": 19848
614
+ }
615
+ }
616
+ }
617
+ ```
618
+
619
+ Or set them when adding the server:
620
+
621
+ ```text
622
+ /mcp add --scope global --oauth --oauth-scope read --oauth-scope write --oauth-callback-port 19848 example https://mcp.example.com/mcp
623
+ ```
624
+
625
+ The callback becomes `http://127.0.0.1:19848/callback`. Pre-registered clients must
626
+ allow that exact URL. The listener stays bound to loopback; arbitrary callback
627
+ hosts and paths aren't supported. If the port is occupied, choose another port or
628
+ use manual login.
629
+
630
+ Scopes are case-sensitive OAuth tokens, each up to 256 characters, without spaces,
631
+ quotes, or backslashes. Omit `oauthScopes` to retain SDK/server-driven selection;
632
+ an empty array is rejected. The SDK may also request `offline_access` when the
633
+ service advertises refresh-token support. Requested scopes aren't a guarantee of
634
+ granted permissions or a per-tool permission policy.
635
+
636
+ After changing these options, run `/mcp reload`, then `/mcp login example`.
637
+ Changing configuration never starts authorization or revokes existing grants.
638
+ Scopes and callback ports don't select separate credential stores: definitions
639
+ sharing a URL and client ID still share credentials. Explicit login renews a
640
+ dynamic registration when its requested options change. `/mcp get example` shows
641
+ the requested scopes and callback address without connecting.
642
+
643
+ #### Manual and remote login
644
+
645
+ When Pi runs over SSH, or you don't want it to launch a browser, use:
646
+
647
+ ```text
648
+ /mcp login example --no-browser
649
+ ```
650
+
651
+ 1. Open the authorization URL shown in Pi's interactive dialog in your browser.
652
+ 2. Complete sign-in. The browser may show a connection error at the loopback
653
+ callback address; this is expected when the browser and Pi run on different
654
+ machines.
655
+ 3. Copy the full callback URL from the browser's address bar and paste it into
656
+ the **Callback URL** dialog in Pi, not into chat or a slash command.
657
+
658
+ Manual login doesn't open a browser or bind a callback port. Pi validates the
659
+ callback address, state, and authorization response before exchanging the code.
660
+ Authorization URLs and pasted callbacks aren't written to session entries,
661
+ catalogs, notifications, or logs by this extension. Treat the callback URL as
662
+ sensitive; your browser history and clipboard may still contain it.
663
+
664
+ `--no-browser` still requires an interactive UI and an available OS credential
665
+ store. It isn't unattended authentication: print and JSON modes refuse OAuth
666
+ login. Use externally managed bearer headers for unattended access. Confidential
667
+ clients requiring a client secret aren't supported yet.
314
668
 
315
669
  ### Trust and permissions
316
670
 
@@ -343,7 +697,7 @@ Start with `/mcp`. Failures use a consistent code, a short explanation, and a
343
697
  recovery hint, for example:
344
698
 
345
699
  ```text
346
- linear: [authentication_required] Authentication is required. Run /mcp auth linear.
700
+ linear: [authentication_required] Authentication is required. Run /mcp login linear.
347
701
  ```
348
702
 
349
703
  Search and tool results also carry structured diagnostics in their result details:
@@ -354,7 +708,7 @@ unavailable server is not an empty catalog.
354
708
  | Code | What to check |
355
709
  | --- | --- |
356
710
  | `configuration_invalid` | JSON syntax, supported fields, transport type, and required environment variables. Reload Pi after editing. |
357
- | `authentication_required` | Run `/mcp auth <server>` for OAuth, or check the Authorization header. |
711
+ | `authentication_required` | Run `/mcp login <server>` for OAuth, or check the Authorization header. |
358
712
  | `permission_denied` | Account permissions, OAuth scopes, and service access policy. |
359
713
  | `credential_store_unavailable` | Unlock or enable the OS keyring; Linux needs a Secret Service session. |
360
714
  | `secret_lookup_failed` | Secret helper installation, login, exit status, nonempty stdout, and output size. |
@@ -363,8 +717,17 @@ unavailable server is not an empty catalog.
363
717
  | `protocol_error` | Server compatibility and the `protocol` setting. |
364
718
  | `tool_changed` | Server filters and the current tool schema; activate the exact identifier again. Reload Pi if connection configuration changed. |
365
719
  | `tool_error` | The server's tool result and inputs; verify the outcome before retrying. |
366
- | `oauth_failed` | Browser access to the callback and support for dynamically registered public clients. |
367
- | `callback_unavailable` | Another process using local port 19847. |
720
+ | `resource_invalid` | Use an exact absolute resource URI from discovery or a tool-returned link. |
721
+ | `resource_not_found` | Refresh resource metadata or obtain a new link. |
722
+ | `resources_unsupported` | Use the server's tools instead, or choose a resource-capable server. |
723
+ | `completions_unsupported` | Supply known template values or ask for them. |
724
+ | `completion_invalid` | Use an advertised template variable and a string prefix. |
725
+ | `subscriptions_unsupported` | Choose a server with subscription support, or read explicitly when needed. |
726
+ | `subscription_limit` | Remove a watch before adding another; the limit is 50 per connection. |
727
+ | `catalog_changed` | Retry discovery after the server catalog settles. |
728
+ | `oauth_failed` | Browser access to the callback and support for public clients, using dynamic registration or the configured client ID. |
729
+ | `oauth_issuer_changed` | Verify the authorization-server change before logging out and logging in again. |
730
+ | `callback_unavailable` | Another process using the configured loopback port (default 19847). Change `oauthCallbackPort` or use `/mcp login <server> --no-browser`. |
368
731
  | `busy` | Wait for discovery to finish before reconnecting. |
369
732
  | `cancelled` | Retry when ready; verify any interrupted tool operation first. |
370
733
  | `operation_failed` | An unclassified failure; inspect server status and configuration. |
@@ -384,19 +747,6 @@ images pass through within an 8 MiB base64 budget; other binary content is kept
384
747
  the full result file. Temporary result files are not automatically deleted and
385
748
  may contain sensitive data.
386
749
 
387
- ### v0.1 scope
388
-
389
- The first release focuses on tools. Legacy SSE transport, MCP Apps, resource
390
- browsing, prompt commands, roots, sampling, and elicitation are not supported.
391
- See the [post-v0.1 backlog](https://github.com/mavam/pi-mcp-client/blob/main/TODO.md)
392
- for follow-up work; it is not a release commitment.
393
-
394
- ## ๐Ÿงน Uninstall
395
-
396
- ```sh
397
- pi remove npm:pi-mcp-client
398
- ```
399
-
400
750
  ## ๐Ÿ“„ License
401
751
 
402
752
  [MIT](LICENSE)