pi-mcp-client 0.4.0 → 0.6.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.
@@ -0,0 +1,247 @@
1
+ # Authentication
2
+
3
+ [Back to the README](../README.md)
4
+
5
+ You manage authentication through `/mcp login` and `/mcp logout`. The assistant
6
+ can't initiate an OAuth login: only your explicit login command opens the browser.
7
+ For externally managed bearer tokens, use
8
+ [headers and secret commands](configuration.md#secret-commands) instead.
9
+
10
+ ## Sign in with OAuth
11
+
12
+ Add the HTTP server, then log in:
13
+
14
+ ```text
15
+ /mcp add --scope global example https://mcp.example.com/mcp
16
+ /mcp login example
17
+ ```
18
+
19
+ Replace the example URL with your server's URL. This flow requires dynamic
20
+ client registration or a [pre-registered public client](#use-a-pre-registered-client).
21
+ Adding a URL alone isn't enough for servers such as Slack.
22
+
23
+ Login uses the effective server definition (the trusted project override, if
24
+ present; otherwise the global definition) and starts the SDK's OAuth discovery
25
+ and authorization flow. It doesn't change configuration files. Adding a server
26
+ still doesn't connect or open a browser.
27
+
28
+ HTTP servers use automatic authentication by default:
29
+
30
+ - Configured Authorization headers take precedence over OAuth.
31
+ - Otherwise, connections reuse stored OAuth tokens when available. The SDK
32
+ handles authentication challenges and refreshes existing grants.
33
+ - Without a grant, an authentication challenge asks you to run `/mcp login`.
34
+ Discovery and tool calls never register a new client or open a browser.
35
+ - A missing or locked keyring doesn't block public servers. If the server
36
+ requires OAuth, an unavailable keyring is an error; no credentials are stored
37
+ outside the OS credential store.
38
+
39
+ The `oauth` configuration field and `--oauth` switch aren't supported. Remove
40
+ these from existing definitions and commands; HTTP authentication is automatic.
41
+
42
+ If the server uses an Authorization header, login asks you to remove that header
43
+ before switching to OAuth; it never replaces existing header credentials.
44
+ Stdio servers manage their own authentication and don't support OAuth login.
45
+
46
+ The extension supports public clients with dynamic registration or a
47
+ pre-registered client ID. Both use PKCE and a loopback callback at
48
+ `http://127.0.0.1:19847/callback` by default. Normal login opens a local listener
49
+ that your browser must be able to reach.
50
+
51
+ Authentication times out after two minutes; you can cancel it with Escape in the
52
+ terminal UI. Explicit login always starts a fresh authorization flow, even if a
53
+ refresh token is already stored. The browser callback page identifies **Pi MCP
54
+ Client** and asks you to return to Pi; receiving a callback doesn't yet mean the
55
+ token exchange succeeded.
56
+
57
+ OAuth tokens and client registrations are stored in the operating system
58
+ credential store, bound to the configured server name, URL, client ID (if any),
59
+ and authorization-server issuer. There is no plaintext credential fallback. PKCE
60
+ verifiers and callback state stay in memory. Linux requires a working Secret
61
+ Service/keyring session.
62
+
63
+ ### Upgrade from earlier versions
64
+
65
+ Credentials now include the configured server name in their identity. Earlier
66
+ entries keyed only by URL and client ID aren't migrated or deleted: assigning a
67
+ shared grant to a name could select the wrong account. Run `/mcp login <server>`
68
+ again for each named connection after upgrading. Revoke old grants at the service
69
+ if needed; the new logout command doesn't remove those earlier keyring entries.
70
+ Changing scopes or the callback port doesn't select a different store.
71
+
72
+ ## Use multiple accounts
73
+
74
+ Each named server has its own OAuth login, even when multiple definitions use
75
+ the same endpoint and client ID. No profile setting is required:
76
+
77
+ ```json
78
+ {
79
+ "mcpServers": {
80
+ "cloudflare-personal": { "url": "https://mcp.cloudflare.com/mcp" },
81
+ "cloudflare-work": { "url": "https://mcp.cloudflare.com/mcp" }
82
+ }
83
+ }
84
+ ```
85
+
86
+ Log in to each connection separately:
87
+
88
+ ```text
89
+ /mcp login cloudflare-personal
90
+ /mcp login cloudflare-work
91
+ ```
92
+
93
+ Choose the intended account in the browser for each login. Names are local
94
+ labels, not verified account identities, and don't change browser cookies. Use
95
+ `--no-browser` to open the authorization URL in a different browser profile if
96
+ needed. Both connections can remain active; tool names identify their server.
97
+
98
+ Definitions with the same name, URL, and client ID reuse credentials across
99
+ projects. Global and trusted project definitions still resolve to one effective
100
+ definition per name. Use different names when you need separate accounts.
101
+
102
+ Renaming a server or changing its URL or client ID requires a new login. Log out
103
+ before making these changes if you want to remove the old credentials. Removing
104
+ a server definition alone doesn't delete its credentials.
105
+
106
+ ## Use a pre-registered client
107
+
108
+ For a server without dynamic registration, register a **public/native** client
109
+ with the service, using the exact callback URL and token endpoint authentication
110
+ method `none`. Then configure its client ID:
111
+
112
+ ```json
113
+ {
114
+ "mcpServers": {
115
+ "example": {
116
+ "url": "https://mcp.example.com/mcp",
117
+ "oauthClientId": "${EXAMPLE_OAUTH_CLIENT_ID}"
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ Run `/mcp reload`, then `/mcp login example`. The configured ID is used for login,
124
+ token refresh, and revocation; the extension never falls back to dynamic
125
+ registration if it is rejected. `/mcp get example` identifies the client as
126
+ pre-registered without printing the ID.
127
+
128
+ Changing the client ID selects separate credentials and requires a new login.
129
+ Log out before changing or removing the ID if you want to delete its old
130
+ credentials. After the first successful grant, a pre-registered client is pinned
131
+ to its authorization-server issuer. If that issuer changes, verify the server
132
+ configuration before logging out and logging in again to trust the replacement.
133
+
134
+ ### Slack setup requirements
135
+
136
+ [Slack doesn't support dynamic client registration](https://docs.slack.dev/ai/slack-mcp-server/).
137
+ Without a registered client, login fails before opening a browser. Configure
138
+ `oauthClientId` with your Slack app's client ID, and ensure the app supports
139
+ public-client PKCE. Apps requiring a client secret aren't supported by this
140
+ extension. Slack also requires an eligible internal or Marketplace-published
141
+ app and any workspace administrator approval required by your workspace.
142
+
143
+ Register the exact callback URL shown by `/mcp get slack` in the app settings
144
+ (default: `http://127.0.0.1:19847/callback`). For example:
145
+
146
+ ```json
147
+ {
148
+ "mcpServers": {
149
+ "slack": {
150
+ "url": "https://mcp.slack.com/mcp",
151
+ "oauthClientId": "${SLACK_OAUTH_CLIENT_ID}"
152
+ }
153
+ }
154
+ }
155
+ ```
156
+
157
+ Set the environment variable before starting Pi. Run `/mcp reload`, then
158
+ `/mcp login slack`. A configured ID appears as **OAuth (pre-registered public
159
+ client)** in `/mcp get slack`; the ID itself stays hidden. A client ID alone
160
+ doesn't guarantee that the app permits this login flow or callback address.
161
+ `--no-browser` doesn't fix registration or app-approval problems.
162
+
163
+ ## Set scopes and callback ports
164
+
165
+ Configure scopes and a callback port in the server definition:
166
+
167
+ ```json
168
+ {
169
+ "mcpServers": {
170
+ "example": {
171
+ "url": "https://mcp.example.com/mcp",
172
+ "oauthScopes": ["read", "write"],
173
+ "oauthCallbackPort": 19848
174
+ }
175
+ }
176
+ }
177
+ ```
178
+
179
+ Or set them when adding the server:
180
+
181
+ ```text
182
+ /mcp add --scope global --oauth-scope read --oauth-scope write --oauth-callback-port 19848 example https://mcp.example.com/mcp
183
+ ```
184
+
185
+ The callback becomes `http://127.0.0.1:19848/callback`. Pre-registered clients must
186
+ allow that exact URL. The listener stays bound to loopback; arbitrary callback
187
+ hosts and paths aren't supported. If the port is occupied, choose another port or
188
+ use manual login.
189
+
190
+ Scopes are case-sensitive OAuth tokens, each up to 256 characters, without spaces,
191
+ quotes, or backslashes. Omit `oauthScopes` to retain SDK/server-driven selection;
192
+ an empty array is rejected. The SDK may also request `offline_access` when the
193
+ service advertises refresh-token support. Requested scopes aren't a guarantee of
194
+ granted permissions or a per-tool permission policy.
195
+
196
+ After changing these options, run `/mcp reload`, then `/mcp login example`.
197
+ Changing configuration never starts authorization or revokes existing grants.
198
+ Scopes and callback ports don't select separate credential stores: definitions
199
+ sharing a name, URL, and client ID still share credentials. Explicit login renews a
200
+ dynamic registration when its requested options change. `/mcp get example` shows
201
+ the requested scopes and callback address without connecting.
202
+
203
+ ## Sign in remotely or without launching a browser
204
+
205
+ When Pi runs over SSH, or you don't want it to launch a browser, use:
206
+
207
+ ```text
208
+ /mcp login example --no-browser
209
+ ```
210
+
211
+ 1. Open the authorization URL shown in Pi's interactive dialog in your browser.
212
+ 2. Complete sign-in. The browser may show a connection error at the loopback
213
+ callback address; this is expected when the browser and Pi run on different
214
+ machines.
215
+ 3. Copy the full callback URL from the browser's address bar and paste it into
216
+ the **Callback URL** dialog in Pi, not into chat or a slash command.
217
+
218
+ Manual login doesn't open a browser or bind a callback port. The extension
219
+ validates the callback address, state, and authorization response before
220
+ exchanging the code. It doesn't write authorization URLs or pasted callbacks to
221
+ session entries, catalogs, notifications, or logs. Treat the callback URL as
222
+ sensitive; your browser history and clipboard may still contain it.
223
+
224
+ `--no-browser` still requires an interactive UI and an available OS credential
225
+ store. It isn't unattended authentication: print and JSON modes refuse OAuth
226
+ login. Use externally managed bearer headers for unattended access. Confidential
227
+ clients requiring a client secret aren't supported yet.
228
+
229
+ ## Sign out
230
+
231
+ Run `/mcp logout <server>` to remove that named server's stored tokens and client
232
+ registrations, close its connection, and deactivate its tools. Other named
233
+ servers keep their local credentials, connections, and active tools, even when
234
+ they use the same URL and client ID. Configuration and enabled state stay
235
+ unchanged. Disabled servers accept logout too. Header and server-managed
236
+ credentials remain untouched.
237
+
238
+ Local removal happens before a bounded attempt to revoke tokens at the original
239
+ authorization server. The result distinguishes accepted revocation, unsupported
240
+ revocation, and unconfirmed revocation. When revocation isn't confirmed, remove the
241
+ grant at the service if needed. Repeating logout is safe. Other running Pi sessions
242
+ using the same named credentials may need to reconnect; logout cannot recall
243
+ requests already sent to a server. Remote revocation behavior depends on the
244
+ service and can affect related grants beyond this local connection.
245
+
246
+ Removing a server definition doesn't remove its credentials. Log out before
247
+ [removing the definition](commands.md#add-and-remove-servers) if you want both.
@@ -0,0 +1,150 @@
1
+ # Behavior and permissions
2
+
3
+ [Back to the README](../README.md)
4
+
5
+ This page explains how the extension manages state and displays results. For the
6
+ assistant's tool-call interface, see the [tool reference](tool-reference.md).
7
+
8
+ ## Sessions
9
+
10
+ - Active tools accumulate rather than rotating with each prompt.
11
+ - Resume and branch navigation restore tools activated through `mcp_tools` on
12
+ the selected branch. Discovery results never restore tools.
13
+ - Compaction retains the acquired tool set. New sessions start fresh.
14
+ - Pi uses native deferred loading where supported by the model and provider.
15
+ Other providers receive the expanded tool list normally.
16
+ - Discovery respects server filters; activation also respects Pi's tool exclusions.
17
+ An explicit tool allowlist must include both `mcp_tools` and the native tools
18
+ the assistant needs to load.
19
+
20
+ ## Resource snapshots
21
+
22
+ Resource reads never start OAuth login, follow links in resource bodies, or
23
+ subscribe to live updates. Repeated reads fetch fresh content; earlier results
24
+ stay as snapshots. Resuming a session or navigating its branches doesn't re-read
25
+ resources. Watches have their own
26
+ [memory-only lifecycle](commands.md#watch-resource-changes) and never fetch content
27
+ automatically.
28
+
29
+ Resource content and selected metadata, including URIs, become session data and
30
+ may be sensitive. [Private spill files](troubleshooting.md#large-results) can also
31
+ contain sensitive data and aren't automatically deleted.
32
+
33
+ ## Prompt snapshots
34
+
35
+ Prompt discovery fetches metadata only. You explicitly enter arguments and fetch a
36
+ preview through `/mcp prompts` or `/mcp prompt`. Only **Use prompt** adds the
37
+ reviewed snapshot to the conversation and starts a model turn. Cancelling a
38
+ preview adds no message and doesn't write a spill file. Arguments already sent to
39
+ the server can't be recalled.
40
+
41
+ The transcript labels accepted snapshots **mcp prompt** with their server, name,
42
+ and message count. Expand the entry to inspect its contents. Server-provided
43
+ `user` and `assistant` roles remain fields in source-labeled data, not fabricated
44
+ conversation history or system instructions. Terminal control sequences are
45
+ removed before previewing and sending text. Selecting a prompt grants no additional
46
+ tool permissions and never activates tools.
47
+
48
+ Previously accepted snapshots don't change or refetch on catalog notifications,
49
+ resume, or branch navigation. Session replacement, tree navigation, and
50
+ configuration reload invalidate pending selections. The agent must be idle when
51
+ you choose **Use prompt**; another active turn is never silently interrupted.
52
+ Accepted content becomes session data and may contain sensitive information.
53
+
54
+ ## Discovery and caching
55
+
56
+ Connections start on demand, never while the extension factory loads. A search
57
+ without the requested cached metadata contacts configured servers, with at most
58
+ four server discoveries in flight. A server-scoped search only contacts that
59
+ server. Activation discovers only the servers named by its identifiers, with the
60
+ same concurrency bound. Failed servers are reported as unavailable, not mistaken
61
+ for an empty catalog.
62
+
63
+ Tool catalogs are cached privately under `~/.pi/agent/cache/pi-mcp-client/`, keyed
64
+ by server configuration and working directory. Disk caches expire after 24 hours.
65
+ They contain tool metadata, not configured credentials. Cached tool-only discovery
66
+ and activation need no connection; invocation refreshes the live catalog before
67
+ calling the tool.
68
+
69
+ Resource metadata, including template catalogs, and prompt metadata are held only
70
+ in memory for up to five minutes, not written to the tool catalog cache. Mixed
71
+ discovery therefore may connect even when tools are cached on disk. Resource-list notifications,
72
+ disconnection, and explicit refresh invalidate resource metadata without reading
73
+ content. Tool and resource catalog failures are reported independently; healthy
74
+ candidates remain available. The SDK handles pagination. Resource catalogs are
75
+ limited to 10,000 entries and 4 MiB of descriptor data; oversized catalogs fail
76
+ rather than silently returning a partial list. Reads bypass the SDK content cache.
77
+
78
+ Prompt-list notifications invalidate only prompt metadata; they never fetch prompt
79
+ content or change a pending preview. Disconnection and explicit refresh also
80
+ invalidate prompt metadata. Prompt catalog failures don't suppress healthy
81
+ tool or resource candidates. The SDK handles prompt pagination. Prompt catalogs
82
+ share the 10,000-entry and 4 MiB limits and reject invalid or duplicate descriptors
83
+ rather than presenting a partial catalog.
84
+
85
+ Connections remain open until shutdown or an explicit lifecycle action such as
86
+ reconnection or configuration reload.
87
+
88
+ When a connected server reports a tool-list change, the extension invalidates its
89
+ memory and disk catalogs. The next discovery or activation fetches the current
90
+ list, including new or removed tools. Notifications don't replace active tool
91
+ definitions: the assistant must activate changed schemas again before use. Calls
92
+ validate the live catalog before execution and refuse removed or changed tools.
93
+ Disconnected, cache-only searches can't receive notifications and still use the
94
+ 24-hour disk-cache expiry.
95
+
96
+ ## Result display
97
+
98
+ The UI labels discovery calls **mcp discover**, activation calls **mcp activate**,
99
+ resource reads **mcp read**, and argument completions **mcp complete**.
100
+
101
+ Discovery rows show `○` for inactive candidates and `●` for already active tools,
102
+ without a status suffix. These reflect the state when discovery runs; earlier
103
+ results don't update retroactively. Activation results use `✔︎` for success and
104
+ `✘︎` for failure. Descriptions stay gray; identifiers remain prominent.
105
+
106
+ Exact and template reads use the same compact status row:
107
+
108
+ ```text
109
+ mcp read
110
+ ✔︎ warehouse · schema://tables/events
111
+ ```
112
+
113
+ Expand a tool result to see JSON objects and arrays formatted with two-space
114
+ indentation and syntax highlighting. Explicit JSON resource MIME types (including
115
+ `application/*+json`) and structured content identify JSON without guessing.
116
+ Other explicit MIME types stay plain text; unlabeled text is checked for JSON.
117
+
118
+ Formatting changes only the display, not the response sent to the assistant.
119
+ Invalid or truncated JSON stays plain text. Results that would exceed formatting
120
+ limits also stay plain text. Resource-link MIME types describe the linked content,
121
+ not the displayed link label. Supported images use the existing result display;
122
+ see [large results](troubleshooting.md#large-results) for size limits.
123
+
124
+ ## Trust and permissions
125
+
126
+ Only load configuration you trust. Server executables and secret commands run
127
+ with your user permissions; trusted project configuration can replace global
128
+ connections and settings.
129
+
130
+ Configuration imports require an explicit file, scope, selection, and final
131
+ confirmation. Import previews hide connection values; review the source file
132
+ before trusting it. Inline credentials are copied only with the selected whole
133
+ server definitions. Importing doesn't run or authenticate servers, but enabled
134
+ imports can execute programs or send credentials when used afterward.
135
+
136
+ Server metadata, resource content, and prompt content are untrusted data. Discovery never
137
+ activates tools. Explicit activation exposes schemas but doesn't approve tool
138
+ side effects or provide per-call confirmation. Use tool filters and Pi permission
139
+ extensions for additional controls. Cancelling a call doesn't guarantee that the
140
+ server rolled back its effects. The extension doesn't retry failed tool
141
+ invocations; verify an interrupted operation's outcome before trying again.
142
+
143
+ `includeTools` and `excludeTools` apply only to tools, not resources or prompts. Keeping
144
+ `mcp_tools` available permits resource reads from enabled servers, subject to the
145
+ server's authorization. `kind: "tools"` filters one search; it isn't an access
146
+ restriction. Disable a server to prevent all access, or exclude `mcp_tools` through
147
+ Pi's tool restrictions to prevent discovery and resource operations. Already active
148
+ native tools have their own tool restrictions. Per-resource permission policies
149
+ aren't implemented. Prompt selection uses explicit user commands, not the
150
+ model-facing tool allowlist; disable the server to prevent prompt access.