pi-mcp-client 0.9.0 → 0.10.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/dist/index.js +831 -85
- package/docs/authentication.md +75 -0
- package/docs/commands.md +2 -1
- package/docs/configuration.md +2 -1
- package/docs/troubleshooting.md +10 -0
- package/package.json +4 -3
package/docs/authentication.md
CHANGED
|
@@ -200,6 +200,81 @@ sharing a name, URL, and client ID still share credentials. Explicit login renew
|
|
|
200
200
|
dynamic registration when its requested options change. `/mcp get example` shows
|
|
201
201
|
the requested scopes and callback address without connecting.
|
|
202
202
|
|
|
203
|
+
## Use DPoP-bound tokens
|
|
204
|
+
|
|
205
|
+
DPoP binds an access token to a signing key, so possession of the token alone
|
|
206
|
+
isn't enough to use it. Enable it for an OAuth HTTP server whose service supports
|
|
207
|
+
ES256 proofs:
|
|
208
|
+
|
|
209
|
+
```json
|
|
210
|
+
{
|
|
211
|
+
"mcpServers": {
|
|
212
|
+
"example": {
|
|
213
|
+
"url": "https://mcp.example.com/mcp",
|
|
214
|
+
"oauthDpop": true
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Run `/mcp reload`, then `/mcp login example`. For a new definition, you can use
|
|
221
|
+
`/mcp add --scope global --oauth-dpop example https://mcp.example.com/mcp`.
|
|
222
|
+
|
|
223
|
+
Only explicit login creates a key. The private key stays in the OS credential
|
|
224
|
+
store alongside the named server's OAuth credentials, bound to its issuer and
|
|
225
|
+
registered client. Connections and token refreshes reuse it across sessions;
|
|
226
|
+
proofs and server nonces aren't persisted. There is no plaintext fallback, and
|
|
227
|
+
keys aren't stored in configuration or session history. This protects keys at
|
|
228
|
+
rest, not against a compromised Pi process or OS account.
|
|
229
|
+
|
|
230
|
+
The SDK signs fresh request proofs and handles bounded nonce challenges. Enabling
|
|
231
|
+
DPoP requests proof support; it doesn't require the service to issue bound tokens.
|
|
232
|
+
If the service issues Bearer access tokens, resource requests still use Bearer
|
|
233
|
+
authentication. Refresh tokens can be DPoP-bound independently; their binding is
|
|
234
|
+
retained even if the access token is Bearer or the signing key is lost.
|
|
235
|
+
`/mcp get example` shows whether DPoP is configured, not whether a grant is bound.
|
|
236
|
+
|
|
237
|
+
If a bound access or refresh token's key is missing, sign in again at the same
|
|
238
|
+
issuer. If the key is corrupt or belongs to a different client, use
|
|
239
|
+
`/mcp logout example` before signing in. Login checks the signing key before
|
|
240
|
+
opening the browser. Disabling DPoP doesn't convert bound tokens to Bearer
|
|
241
|
+
tokens: enable it again or log out and obtain a new grant.
|
|
242
|
+
Logout removes the key and tokens locally and attempts remote token revocation.
|
|
243
|
+
A changed issuer requires explicit logout before trusting its replacement.
|
|
244
|
+
|
|
245
|
+
## Approve additional permissions
|
|
246
|
+
|
|
247
|
+
A server can reject a request with an OAuth scope challenge—for example, when
|
|
248
|
+
searching works but creating an issue requires write access. The operation stops
|
|
249
|
+
with `oauth_scope_required`; it doesn't open a browser or retry automatically.
|
|
250
|
+
|
|
251
|
+
Run the indicated command yourself:
|
|
252
|
+
|
|
253
|
+
```text
|
|
254
|
+
/mcp login example
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Page through the server's requested scope names and the combined set of configured,
|
|
258
|
+
previously granted, and requested scopes. In the terminal, press `a` on the last
|
|
259
|
+
page to approve; in RPC, select **Approve sign-in**. Approving starts a fresh login.
|
|
260
|
+
You can also use `--no-browser`. Declining, cancelling sign-in, or a failed token
|
|
261
|
+
exchange leaves your existing grant unchanged. Reloading configuration cancels
|
|
262
|
+
an active login. After signing in, explicitly retry the operation; sign-in never
|
|
263
|
+
replays it. Successful grants retain their requested scopes even when the service
|
|
264
|
+
omits the optional scope field from its token response. If previously granted
|
|
265
|
+
scopes are unknown, the review warns that they might not be retained. Configure
|
|
266
|
+
`oauthScopes` with the permissions you need rather than relying on unspecified
|
|
267
|
+
service defaults. After review, the sign-in dialog shows a scope count instead
|
|
268
|
+
of repeating the full list.
|
|
269
|
+
|
|
270
|
+
Scope names are untrusted service data, not instructions. Requests are bounded to
|
|
271
|
+
100 scope names and kept only in this Pi session for ten minutes. Reloading
|
|
272
|
+
configuration, ending the session, or logging out discards them. Login uses the
|
|
273
|
+
configured server's OAuth discovery, not URLs supplied in a scope challenge.
|
|
274
|
+
Invalid or missing scope names require checking `oauthScopes` against the service's
|
|
275
|
+
requirements instead. Headless operation reports the challenge but cannot approve
|
|
276
|
+
additional permissions.
|
|
277
|
+
|
|
203
278
|
## Sign in remotely or without launching a browser
|
|
204
279
|
|
|
205
280
|
When Pi runs over SSH, or you don't want it to launch a browser, use:
|
package/docs/commands.md
CHANGED
|
@@ -20,7 +20,7 @@ The model's separate interface is documented in the [tool reference](tool-refere
|
|
|
20
20
|
| `/mcp reload` | Apply configuration changes without restarting Pi. |
|
|
21
21
|
| `/mcp enable <server>` | Enable a server in its effective configuration file. |
|
|
22
22
|
| `/mcp disable <server>` | Disable a server, close its connection, and deactivate its tools. |
|
|
23
|
-
| `/mcp login <server> [--no-browser]` | Authenticate an HTTP server
|
|
23
|
+
| `/mcp login <server> [--no-browser]` | Authenticate an HTTP server or review additional permissions it requested; optionally paste the callback URL in an interactive dialog. Configuration stays unchanged. |
|
|
24
24
|
| `/mcp logout <server>` | Remove local OAuth credentials and attempt remote revocation, including for disabled servers. |
|
|
25
25
|
| `/mcp reconnect <server>` | Replace a connection and refresh its catalog. |
|
|
26
26
|
| `/mcp refresh <server>` | Refresh tool, resource, and prompt metadata without fetching content or loading additional tools. |
|
|
@@ -145,6 +145,7 @@ Windows paths with backslashes, single quotes preserve the path verbatim.
|
|
|
145
145
|
| `--oauth-client-id ID` | Use a pre-registered public client. |
|
|
146
146
|
| `--oauth-scope SCOPE` | Request an OAuth scope. Repeat for additional scopes. |
|
|
147
147
|
| `--oauth-callback-port PORT` | Set the loopback callback port. |
|
|
148
|
+
| `--oauth-dpop` | Request DPoP-bound OAuth tokens using an OS-backed signing key. |
|
|
148
149
|
|
|
149
150
|
Retain environment references rather than typing tokens:
|
|
150
151
|
|
package/docs/configuration.md
CHANGED
|
@@ -137,6 +137,7 @@ server definition:
|
|
|
137
137
|
| `oauthClientId` | Optional pre-registered public client ID. Supports `${ENV_VAR}` interpolation, not secret commands. |
|
|
138
138
|
| `oauthScopes` | Optional array of 1–100 unique OAuth scope tokens to request at login. Omitted scopes use SDK/server defaults. Values are literal, without interpolation. |
|
|
139
139
|
| `oauthCallbackPort` | Optional loopback callback port, from 1 to 65535. Defaults to `19847`. |
|
|
140
|
+
| `oauthDpop` | Opt in to DPoP proofs with ES256 keys stored in the OS keyring. Defaults to `false`. Run a fresh login after enabling it. |
|
|
140
141
|
| `disabled` | Prevent this server from connecting or exposing tools and resources. |
|
|
141
142
|
| `includeTools` | Optional allowlist of original MCP tool names; `*` matches any sequence. An empty list exposes no tools. |
|
|
142
143
|
| `excludeTools` | Denylist applied after `includeTools`. |
|
|
@@ -145,7 +146,7 @@ server definition:
|
|
|
145
146
|
| `toolTimeoutMs` | Optional timeout for tool calls only, from 100 to 600000 ms. Overrides `timeoutMs` for calls without changing metadata or resource deadlines. Time spent answering [server requests](behavior.md#server-requests-for-input) doesn't count. |
|
|
146
147
|
| `protocol` | `auto` (default) for SDK protocol-version negotiation, or `legacy` for an explicit legacy handshake. |
|
|
147
148
|
|
|
148
|
-
OAuth client IDs, scopes,
|
|
149
|
+
OAuth client IDs, scopes, callback ports, and DPoP require HTTP without an Authorization
|
|
149
150
|
header. HTTP authentication is automatic; remove the obsolete `oauth` field from
|
|
150
151
|
existing definitions. See [authentication](authentication.md).
|
|
151
152
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -45,6 +45,8 @@ unavailable server isn't an empty catalog.
|
|
|
45
45
|
| `oauth_registration_rejected` | The server rejected dynamic registration. Check public/native client eligibility and the callback URL, or configure an approved public client ID. |
|
|
46
46
|
| `oauth_client_rejected` | Check the client ID, app approval, and public-client authentication (token endpoint method `none`). A rejected client doesn't necessarily mean a client secret is required. |
|
|
47
47
|
| `oauth_pkce_unsupported` | The authorization server must support S256 PKCE. Login without PKCE isn't supported. |
|
|
48
|
+
| `oauth_scope_required` | Run `/mcp login <server>` to review additional permissions, then explicitly retry the operation. |
|
|
49
|
+
| `oauth_dpop_unavailable` | Enable DPoP again, or log out before signing in if you disabled it deliberately or its stored key is corrupt or mismatched. |
|
|
48
50
|
| `oauth_scope_rejected` | Check `oauthScopes` against the service's allowed scopes and app permissions. Reload after changes, then log in again. |
|
|
49
51
|
| `oauth_grant_rejected` | Log in again for a fresh code. If it still fails, check the client and exact callback URL. |
|
|
50
52
|
| `oauth_redirect_rejected` | Register the exact callback host, port, and `/callback` path shown by `/mcp get <server>`. Manual login uses the same callback URL. |
|
|
@@ -72,6 +74,14 @@ remain visible as content, even when the tool reports an error; they aren't
|
|
|
72
74
|
sanitized transport diagnostics. Tool-call failures aren't replayed automatically;
|
|
73
75
|
verify the outcome before retrying.
|
|
74
76
|
|
|
77
|
+
## OAuth warnings in the terminal
|
|
78
|
+
|
|
79
|
+
The MCP SDK can print a sanitized warning when a refresh token expires or is
|
|
80
|
+
revoked. In an interactive terminal, this can temporarily disrupt the display
|
|
81
|
+
until Pi redraws it. Remote error details are removed, but these SDK warnings
|
|
82
|
+
can't currently be routed through Pi's UI. Follow the accompanying diagnostic
|
|
83
|
+
if another login is needed; the warning alone doesn't mean sign-in started.
|
|
84
|
+
|
|
75
85
|
## Missing project servers
|
|
76
86
|
|
|
77
87
|
A project's `.mcp.json` loads only after an explicit trust decision, even in
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-mcp-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "MCP tools for Pi, discovered on demand and called natively through the official SDK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,8 +39,9 @@
|
|
|
39
39
|
"prepack": "bun run build"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@modelcontextprotocol/client": "2.
|
|
42
|
+
"@modelcontextprotocol/client": "2.1.0",
|
|
43
43
|
"@napi-rs/keyring": "^1.3.0",
|
|
44
|
+
"jose": "^6.1.3",
|
|
44
45
|
"minisearch": "^7.2.0",
|
|
45
46
|
"smol-toml": "^1.8.0"
|
|
46
47
|
},
|
|
@@ -48,7 +49,7 @@
|
|
|
48
49
|
"@earendil-works/pi-ai": "^0.85.1",
|
|
49
50
|
"@earendil-works/pi-coding-agent": "^0.85.1",
|
|
50
51
|
"@earendil-works/pi-tui": "^0.85.1",
|
|
51
|
-
"@modelcontextprotocol/server": "2.
|
|
52
|
+
"@modelcontextprotocol/server": "2.1.0",
|
|
52
53
|
"@types/bun": "^1.3.0",
|
|
53
54
|
"@types/node": "^24.0.0",
|
|
54
55
|
"esbuild": "^0.25.0",
|