pi-mcp-client 0.10.0 → 0.12.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/README.md +44 -4
- package/dist/auth.d.ts +72 -0
- package/dist/authorization-review.d.ts +7 -0
- package/dist/authorization.d.ts +14 -0
- package/dist/catalog.d.ts +42 -0
- package/dist/chunk-CETPDAJH.js +5488 -0
- package/dist/codex-import.d.ts +6 -0
- package/dist/config-commands.d.ts +13 -0
- package/dist/config.d.ts +95 -0
- package/dist/diagnostics.d.ts +71 -0
- package/dist/dpop.d.ts +10 -0
- package/dist/durable.d.ts +28 -0
- package/dist/durable.js +196 -0
- package/dist/elicitation.d.ts +62 -0
- package/dist/exposure.d.ts +17 -0
- package/dist/format.d.ts +5 -0
- package/dist/import-command.d.ts +9 -0
- package/dist/imports.d.ts +37 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +1654 -6972
- package/dist/management.d.ts +15 -0
- package/dist/oauth-fetch.d.ts +4 -0
- package/dist/oauth-page.d.ts +28 -0
- package/dist/output.d.ts +62 -0
- package/dist/prompt-command.d.ts +12 -0
- package/dist/prompt-selector.d.ts +6 -0
- package/dist/prompts.d.ts +25 -0
- package/dist/registered.d.ts +13 -0
- package/dist/render.d.ts +13 -0
- package/dist/resources.d.ts +58 -0
- package/dist/runtime.d.ts +218 -0
- package/dist/secrets.d.ts +6 -0
- package/dist/status-panel.d.ts +10 -0
- package/dist/subscriptions.d.ts +18 -0
- package/dist/tool-schema.d.ts +23 -0
- package/docs/authentication.md +9 -10
- package/docs/behavior.md +46 -25
- package/docs/commands.md +11 -11
- package/docs/configuration.md +52 -35
- package/docs/durable.md +62 -0
- package/docs/troubleshooting.md +7 -8
- package/package.json +32 -10
package/README.md
CHANGED
|
@@ -3,6 +3,38 @@
|
|
|
3
3
|
Connect Pi to MCP servers so the model can use their tools and read their
|
|
4
4
|
resources. You can also browse, preview, and use server-provided prompts.
|
|
5
5
|
|
|
6
|
+
> [!NOTE]
|
|
7
|
+
> On Pi **0.99.1 and later**, this extension is no longer needed for basic MCP
|
|
8
|
+
> use: Pi has built-in support for server tools, resources, and OAuth. Keep this
|
|
9
|
+
> extension if you need OS-backed credential storage or the additional features
|
|
10
|
+
> below.
|
|
11
|
+
|
|
12
|
+
## ⚖️ Do you need this extension?
|
|
13
|
+
|
|
14
|
+
Comparison with [Pi 1.0.0](https://github.com/earendil-works/pi/releases/tag/v1.0.0).
|
|
15
|
+
|
|
16
|
+
| Feature | Built-in MCP | Pi MCP Client |
|
|
17
|
+
| --- | :---: | :---: |
|
|
18
|
+
| HTTP and stdio server tools | ✅ | ✅ |
|
|
19
|
+
| OAuth sign-in and token refresh | ✅ | ✅ |
|
|
20
|
+
| Tool namespaces and codemode calls | ✅ | ✅ |
|
|
21
|
+
| Resource listing, URI templates, and reads | ✅ | ✅ |
|
|
22
|
+
| [Separate OAuth accounts at the same endpoint](docs/authentication.md#use-multiple-accounts) | ✅ | ✅ |
|
|
23
|
+
| [OAuth credentials in the OS credential store](docs/authentication.md#sign-in-with-oauth) | ❌ | ✅ |
|
|
24
|
+
| [DPoP-bound OAuth tokens](docs/authentication.md#use-dpop-bound-tokens) | ❌ | ✅ |
|
|
25
|
+
| [Server prompts with preview before use](docs/commands.md#use-server-prompts) | ❌ | ✅ |
|
|
26
|
+
| [Resource argument completion](docs/tool-reference.md#complete-resource-arguments) | ❌ | ✅ |
|
|
27
|
+
| [Resource change watches](docs/commands.md#watch-resource-changes) | ❌ | ✅ |
|
|
28
|
+
| [Server requests for user input (elicitation)](docs/behavior.md#server-requests-for-input) | ❌ | ✅ |
|
|
29
|
+
| [Configuration imports with preview](docs/commands.md#import-server-definitions) | ❌ | ✅ |
|
|
30
|
+
| OAuth clients requiring a client secret | ✅ | ❌ |
|
|
31
|
+
| [OAuth authorization-server metadata override](https://github.com/earendil-works/pi/blob/v1.0.0/packages/coding-agent/docs/mcp.md#authenticate-with-oauth) | ✅ | ❌ |
|
|
32
|
+
| HTTP authentication with a provider's `/login` token | ✅ | ❌ |
|
|
33
|
+
|
|
34
|
+
Both read the same `mcp.json` files, but OAuth credentials don't transfer between
|
|
35
|
+
implementations. See
|
|
36
|
+
[switching to built-in MCP](docs/behavior.md#pis-built-in-mcp-support).
|
|
37
|
+
|
|
6
38
|
## 🚀 Installation
|
|
7
39
|
|
|
8
40
|
```sh
|
|
@@ -43,9 +75,9 @@ permissions. Tool activation isn't a per-call approval prompt. See
|
|
|
43
75
|
## ⚙️ Configuration
|
|
44
76
|
|
|
45
77
|
Store server definitions in `~/.pi/agent/mcp.json` or a trusted project's
|
|
46
|
-
`.mcp.json
|
|
47
|
-
[
|
|
48
|
-
same-named global definitions in full.
|
|
78
|
+
`.pi/mcp.json`, the same files and shape as Pi's built-in MCP support. Project
|
|
79
|
+
servers load only in a project that Pi [trusts](docs/behavior.md#project-trust).
|
|
80
|
+
Project definitions replace same-named global definitions in full.
|
|
49
81
|
You can edit these files or use `/mcp add` and `/mcp remove`. To reuse a
|
|
50
82
|
Claude/Cursor JSON or Codex TOML file, run `/mcp import --scope global <path>` and
|
|
51
83
|
review the selected connections before saving.
|
|
@@ -65,9 +97,17 @@ Detailed guides:
|
|
|
65
97
|
- [Troubleshooting](docs/troubleshooting.md): Error codes, recovery, and large
|
|
66
98
|
results.
|
|
67
99
|
|
|
100
|
+
## 🧬 Pi Durable
|
|
101
|
+
|
|
102
|
+
Custom hosts can use the experimental `pi-mcp-client/durable` adapter for
|
|
103
|
+
metadata discovery, native tool activation, resource reads, and template
|
|
104
|
+
completion. It shares configuration and the MCP credential store with this
|
|
105
|
+
extension. See [the durable host contract](docs/durable.md) for installation,
|
|
106
|
+
restart ordering, trust, and UI requirements.
|
|
107
|
+
|
|
68
108
|
## 🧰 Requirements
|
|
69
109
|
|
|
70
|
-
- Pi 0.
|
|
110
|
+
- Pi 0.99 or later.
|
|
71
111
|
- Node.js 22 or later.
|
|
72
112
|
- The server executable for stdio connections.
|
|
73
113
|
- An available OS credential store for OAuth. Linux requires a working Secret
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { type OAuthClientProvider, type DpopSession, type OAuthClientInformationContext, type OAuthClientMetadata, type OAuthDiscoveryState, type StoredOAuthClientInformation, type StoredOAuthTokens } from "@modelcontextprotocol/client";
|
|
2
|
+
import { type ServerConfig, type ClientOptions } from "./config.js";
|
|
3
|
+
export type OAuthOptions = Pick<ClientOptions, "oauthScopes" | "oauthCallbackPort" | "oauthDpop">;
|
|
4
|
+
export declare function callbackUrl(options?: OAuthOptions): string;
|
|
5
|
+
/** Validate the full handoff URL before giving the response to the SDK. */
|
|
6
|
+
export declare function parseCallback(value: string, redirect: string, state: string): URLSearchParams;
|
|
7
|
+
export interface OAuthIdentity {
|
|
8
|
+
server: string;
|
|
9
|
+
url: string;
|
|
10
|
+
clientId?: string;
|
|
11
|
+
}
|
|
12
|
+
export interface SecretStore {
|
|
13
|
+
read(): string | null;
|
|
14
|
+
write(value: string): void;
|
|
15
|
+
remove(): void;
|
|
16
|
+
}
|
|
17
|
+
export type CredentialStoreFactory = (identity: OAuthIdentity) => Promise<SecretStore>;
|
|
18
|
+
export declare function credentialKey({ server, url, clientId }: OAuthIdentity): string;
|
|
19
|
+
export declare function credentialStore(identity: OAuthIdentity): Promise<SecretStore>;
|
|
20
|
+
export declare class OAuthProvider implements OAuthClientProvider {
|
|
21
|
+
private readonly store;
|
|
22
|
+
private readonly redirect?;
|
|
23
|
+
private readonly options;
|
|
24
|
+
readonly redirectUrl: string;
|
|
25
|
+
readonly clientMetadata: OAuthClientMetadata;
|
|
26
|
+
private data;
|
|
27
|
+
private snapshot;
|
|
28
|
+
private readonly epoch;
|
|
29
|
+
private readonly key;
|
|
30
|
+
private verifier?;
|
|
31
|
+
private discovery?;
|
|
32
|
+
private requestedScope?;
|
|
33
|
+
private dpopSession?;
|
|
34
|
+
private resolvedDpopSession?;
|
|
35
|
+
readonly expectedState: `${string}-${string}-${string}-${string}-${string}`;
|
|
36
|
+
private readonly clientId?;
|
|
37
|
+
constructor(identity: OAuthIdentity, store: SecretStore, redirect?: ((url: URL) => void | Promise<void>) | undefined, options?: OAuthOptions);
|
|
38
|
+
private assertCurrent;
|
|
39
|
+
private save;
|
|
40
|
+
state(): `${string}-${string}-${string}-${string}-${string}`;
|
|
41
|
+
clientInformation(ctx?: OAuthClientInformationContext): ({
|
|
42
|
+
client_id: string;
|
|
43
|
+
client_secret?: string | undefined;
|
|
44
|
+
client_id_issued_at?: number | undefined;
|
|
45
|
+
client_secret_expires_at?: number | undefined;
|
|
46
|
+
} & {
|
|
47
|
+
issuer?: string;
|
|
48
|
+
}) | undefined;
|
|
49
|
+
private lookupClientInformation;
|
|
50
|
+
saveClientInformation(info: StoredOAuthClientInformation, ctx?: OAuthClientInformationContext): void;
|
|
51
|
+
tokens(ctx?: OAuthClientInformationContext): StoredOAuthTokens | undefined;
|
|
52
|
+
saveTokens(tokens: StoredOAuthTokens): void;
|
|
53
|
+
dpop(): Promise<DpopSession | undefined>;
|
|
54
|
+
saveCodeVerifier(value: string): void;
|
|
55
|
+
codeVerifier(): string;
|
|
56
|
+
saveDiscoveryState(value: OAuthDiscoveryState): void;
|
|
57
|
+
discoveryState(): OAuthDiscoveryState | undefined;
|
|
58
|
+
redirectToAuthorization(url: URL): Promise<void>;
|
|
59
|
+
invalidateCredentials(scope: "all" | "client" | "tokens" | "verifier" | "discovery"): void;
|
|
60
|
+
}
|
|
61
|
+
/** Reuse stored tokens without requiring a working keyring for public servers.
|
|
62
|
+
* Only explicit login may register a client or open a browser; background
|
|
63
|
+
* authentication may reuse or refresh existing grants through the SDK.
|
|
64
|
+
*/
|
|
65
|
+
export declare function connectionAuthProvider(server: string, config: ServerConfig, storeFactory?: CredentialStoreFactory): Promise<OAuthClientProvider | undefined>;
|
|
66
|
+
export type Revocation = "confirmed" | "unsupported" | "unconfirmed" | "not-needed";
|
|
67
|
+
/** Local removal is unconditional; revocation is bounded, issuer-bound, and best effort. */
|
|
68
|
+
export declare function logout(identity: OAuthIdentity, store: SecretStore, signal?: AbortSignal): Promise<Revocation>;
|
|
69
|
+
/** Explicit user action only; OAuth never opens a browser during search or execution. */
|
|
70
|
+
export declare function authenticate(identity: OAuthIdentity, open: (url: string) => Promise<void>, signal?: AbortSignal, store?: SecretStore, options?: OAuthOptions & {
|
|
71
|
+
handoff?: (authorizationUrl: string, signal: AbortSignal) => Promise<string | undefined>;
|
|
72
|
+
}): Promise<void>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ExtensionContext, KeybindingsManager, Theme } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import { type Component } from "@earendil-works/pi-tui";
|
|
3
|
+
export declare function reviewAuthorization(ctx: ExtensionContext, server: string, requested: string[], combined: string[], grantedScopesKnown: boolean, signal: AbortSignal): Promise<boolean>;
|
|
4
|
+
/** Height-bounded plain-text review. Enter advances; only explicit 'a' on the
|
|
5
|
+
* last page approves. Resize reflows the body and resets review to its start.
|
|
6
|
+
*/
|
|
7
|
+
export declare function authorizationReview(server: string, text: string, rows: () => number, theme: Theme, keys: KeybindingsManager, done: (approved: boolean) => void, render: () => void): Component;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type OAuthIdentity, type OAuthOptions, type SecretStore } from "./auth.js";
|
|
2
|
+
/** Server scope names are data, not instructions. Keep their size and rendering bounded. */
|
|
3
|
+
export declare function parseScopes(value: string | undefined): string[] | undefined;
|
|
4
|
+
export declare function authorizationOptions(identity: OAuthIdentity, store: SecretStore, options: OAuthOptions, required: string[]): {
|
|
5
|
+
options: OAuthOptions;
|
|
6
|
+
grantedScopesKnown: boolean;
|
|
7
|
+
};
|
|
8
|
+
/** Scope names have already been reviewed; don't repeat an unbounded list in a loader. */
|
|
9
|
+
export declare function loginSummary(options: OAuthOptions, reviewed: boolean): string;
|
|
10
|
+
export interface ScopeChallenge {
|
|
11
|
+
scopes: string[];
|
|
12
|
+
identity: string;
|
|
13
|
+
expires: number;
|
|
14
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { TSchema } from "typebox";
|
|
2
|
+
/** The MCP tool annotation hints Pi forwards to permission extensions. */
|
|
3
|
+
export interface ToolHints {
|
|
4
|
+
readOnlyHint?: boolean;
|
|
5
|
+
destructiveHint?: boolean;
|
|
6
|
+
idempotentHint?: boolean;
|
|
7
|
+
openWorldHint?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Keep only boolean hints; everything else a server sends is untrusted noise. */
|
|
10
|
+
export declare function toolHints(value: unknown): ToolHints | undefined;
|
|
11
|
+
export interface CatalogTool {
|
|
12
|
+
server: string;
|
|
13
|
+
name: string;
|
|
14
|
+
nativeName: string;
|
|
15
|
+
description: string;
|
|
16
|
+
inputSchema: TSchema;
|
|
17
|
+
annotations?: ToolHints;
|
|
18
|
+
identity: string;
|
|
19
|
+
schemaHash: string;
|
|
20
|
+
}
|
|
21
|
+
export declare function plain(value: string): string;
|
|
22
|
+
export declare function line(value: string): string;
|
|
23
|
+
export declare function nativeName(server: string, name: string): string;
|
|
24
|
+
export declare function prepareTool(server: string, identity: string, tool: {
|
|
25
|
+
name: string;
|
|
26
|
+
description?: string;
|
|
27
|
+
inputSchema: unknown;
|
|
28
|
+
annotations?: unknown;
|
|
29
|
+
}): CatalogTool;
|
|
30
|
+
/** Discovery exposes names, never a callable signature. */
|
|
31
|
+
export declare function summarize(tool: CatalogTool, includeIdentifier?: boolean): string;
|
|
32
|
+
/** Suggestions are informational only; resolution is case-sensitive and exact. */
|
|
33
|
+
export declare function resolveTools(tools: CatalogTool[], identifiers: string[]): {
|
|
34
|
+
identifier: string;
|
|
35
|
+
tool: CatalogTool | undefined;
|
|
36
|
+
suggestions: string[];
|
|
37
|
+
}[];
|
|
38
|
+
export declare const DEFAULT_SEARCH_LIMIT = 5;
|
|
39
|
+
export declare const MAX_SEARCH_LIMIT = 50;
|
|
40
|
+
export declare function tokens(text: string): string[];
|
|
41
|
+
/** Exact selectors win; ordinary retrieval weights names over descriptions. */
|
|
42
|
+
export declare function searchTools(tools: CatalogTool[], query: string, server?: string, limit?: number): CatalogTool[];
|