@jini-ai/mcp 0.1.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/LICENSE +201 -0
- package/dist/agent-install/index.d.ts +9 -0
- package/dist/agent-install/index.d.ts.map +1 -0
- package/dist/agent-install/index.js +9 -0
- package/dist/agent-install/index.js.map +1 -0
- package/dist/agent-install/install.d.ts +97 -0
- package/dist/agent-install/install.d.ts.map +1 -0
- package/dist/agent-install/install.js +410 -0
- package/dist/agent-install/install.js.map +1 -0
- package/dist/bin/serve.d.ts +75 -0
- package/dist/bin/serve.d.ts.map +1 -0
- package/dist/bin/serve.js +79 -0
- package/dist/bin/serve.js.map +1 -0
- package/dist/client/client.d.ts +48 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +242 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/index.d.ts +8 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +8 -0
- package/dist/client/index.js.map +1 -0
- package/dist/core/config.d.ts +157 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +475 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/index.d.ts +14 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +14 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/install-info.d.ts +69 -0
- package/dist/core/install-info.d.ts.map +1 -0
- package/dist/core/install-info.js +79 -0
- package/dist/core/install-info.js.map +1 -0
- package/dist/core/oauth.d.ts +274 -0
- package/dist/core/oauth.d.ts.map +1 -0
- package/dist/core/oauth.js +667 -0
- package/dist/core/oauth.js.map +1 -0
- package/dist/core/secure-write.d.ts +17 -0
- package/dist/core/secure-write.d.ts.map +1 -0
- package/dist/core/secure-write.js +72 -0
- package/dist/core/secure-write.js.map +1 -0
- package/dist/core/tokens.d.ts +72 -0
- package/dist/core/tokens.d.ts.map +1 -0
- package/dist/core/tokens.js +197 -0
- package/dist/core/tokens.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/server/daemon-client.d.ts +21 -0
- package/dist/server/daemon-client.d.ts.map +1 -0
- package/dist/server/daemon-client.js +176 -0
- package/dist/server/daemon-client.js.map +1 -0
- package/dist/server/index.d.ts +18 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +18 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/resource-protocol.d.ts +38 -0
- package/dist/server/resource-protocol.d.ts.map +1 -0
- package/dist/server/resource-protocol.js +68 -0
- package/dist/server/resource-protocol.js.map +1 -0
- package/dist/server/resources/active-resource.d.ts +12 -0
- package/dist/server/resources/active-resource.d.ts.map +1 -0
- package/dist/server/resources/active-resource.js +46 -0
- package/dist/server/resources/active-resource.js.map +1 -0
- package/dist/server/tool-protocol.d.ts +45 -0
- package/dist/server/tool-protocol.d.ts.map +1 -0
- package/dist/server/tool-protocol.js +74 -0
- package/dist/server/tool-protocol.js.map +1 -0
- package/dist/server/tool-server.d.ts +105 -0
- package/dist/server/tool-server.d.ts.map +1 -0
- package/dist/server/tool-server.js +96 -0
- package/dist/server/tool-server.js.map +1 -0
- package/dist/server/tools/delegated-tool.d.ts +15 -0
- package/dist/server/tools/delegated-tool.d.ts.map +1 -0
- package/dist/server/tools/delegated-tool.js +90 -0
- package/dist/server/tools/delegated-tool.js.map +1 -0
- package/dist/server/tools/run-tools.d.ts +14 -0
- package/dist/server/tools/run-tools.d.ts.map +1 -0
- package/dist/server/tools/run-tools.js +142 -0
- package/dist/server/tools/run-tools.js.map +1 -0
- package/dist/server/tools/tool-catalog-tools.d.ts +8 -0
- package/dist/server/tools/tool-catalog-tools.d.ts.map +1 -0
- package/dist/server/tools/tool-catalog-tools.js +66 -0
- package/dist/server/tools/tool-catalog-tools.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/core/install-info
|
|
3
|
+
* Pure builder for the MCP install-info payload (command/args/env) shared by the
|
|
4
|
+
* daemon route, the settings UI, and its test fixture, so every install surface
|
|
5
|
+
* configures byte-identical bytes. Part of the MCP `core` kernel; intentionally
|
|
6
|
+
* side-effect-free and depends on no sibling subdirectory.
|
|
7
|
+
*/
|
|
8
|
+
// Pure builder for the MCP install-info payload. Extracted from the HTTP
|
|
9
|
+
// handler so the test fixture and the production handler share the exact
|
|
10
|
+
// env/argv/buildHint shape; a divergence here is the difference between an
|
|
11
|
+
// MCP snippet that works and one that EPERMs out when pasted into an IDE
|
|
12
|
+
// (Antigravity / Cursor / VS Code), or silently misses the sidecar
|
|
13
|
+
// transport endpoint.
|
|
14
|
+
//
|
|
15
|
+
// Side effects (fs.existsSync probes, process.execPath, the
|
|
16
|
+
// ELECTRON_RUN_AS_NODE env read, data-dir resolution, sidecar IPC
|
|
17
|
+
// detection) all stay in the caller. This module is intentionally pure so
|
|
18
|
+
// it can be unit-tested without booting a daemon.
|
|
19
|
+
/**
|
|
20
|
+
* Build the `McpInstallPayload` from resolved runtime facts.
|
|
21
|
+
* Decides whether to bake `--daemon-url` into args (direct launch) or omit it
|
|
22
|
+
* (sidecar mode, where the spawned process discovers the URL via the IPC socket).
|
|
23
|
+
* Also pins the data-dir env var to prevent EPERM failures in packaged installs
|
|
24
|
+
* and injects `ELECTRON_RUN_AS_NODE=1` when running under Electron.
|
|
25
|
+
* @param inputs Runtime facts collected by the production route or test fixture.
|
|
26
|
+
* @returns The install payload; `buildHint` is non-null when prerequisites are missing.
|
|
27
|
+
*/
|
|
28
|
+
export function buildMcpInstallPayload(inputs) {
|
|
29
|
+
const subcommand = inputs.subcommand ?? 'mcp';
|
|
30
|
+
const hints = [];
|
|
31
|
+
if (!inputs.cliExists) {
|
|
32
|
+
hints.push(`CLI entry is missing at ${inputs.cliPath}. Rebuild the daemon or packaged app and refresh.`);
|
|
33
|
+
}
|
|
34
|
+
if (!inputs.nodeExists) {
|
|
35
|
+
hints.push(`Node-compatible runtime at ${inputs.execPath} no longer exists. Reinstall the runtime and restart the daemon.`);
|
|
36
|
+
}
|
|
37
|
+
// Pin the data-dir env var to the daemon's resolved data root so the
|
|
38
|
+
// spawned MCP process writes to the same directory the daemon already
|
|
39
|
+
// uses even when the IDE that launched it does not inherit the packaged
|
|
40
|
+
// app's environment. Without this, the process falls back to a
|
|
41
|
+
// per-cwd data dir which for packaged installs can be a read-only app
|
|
42
|
+
// bundle that trips EPERM.
|
|
43
|
+
const env = {
|
|
44
|
+
[inputs.dataDirEnvVar]: inputs.dataDir,
|
|
45
|
+
...inputs.sidecarEnv,
|
|
46
|
+
};
|
|
47
|
+
if (inputs.electronAsNode) {
|
|
48
|
+
env.ELECTRON_RUN_AS_NODE = '1';
|
|
49
|
+
}
|
|
50
|
+
// Sidecar mode: omit --daemon-url so the spawned MCP process discovers
|
|
51
|
+
// the live URL via the IPC status socket on every spawn, surviving
|
|
52
|
+
// ephemeral-port restarts. Direct launches have no socket and need the
|
|
53
|
+
// URL baked.
|
|
54
|
+
const args = inputs.isSidecarMode
|
|
55
|
+
? [inputs.cliPath, subcommand]
|
|
56
|
+
: [
|
|
57
|
+
inputs.cliPath,
|
|
58
|
+
subcommand,
|
|
59
|
+
'--daemon-url',
|
|
60
|
+
`http://127.0.0.1:${inputs.port}`,
|
|
61
|
+
];
|
|
62
|
+
return {
|
|
63
|
+
command: inputs.execPath,
|
|
64
|
+
args,
|
|
65
|
+
env,
|
|
66
|
+
daemonUrl: `http://127.0.0.1:${inputs.port}`,
|
|
67
|
+
webBaseUrl: typeof inputs.webBaseUrl === 'string' && inputs.webBaseUrl.length > 0
|
|
68
|
+
? inputs.webBaseUrl
|
|
69
|
+
: null,
|
|
70
|
+
// Surface platform so the install panel can localize path hints
|
|
71
|
+
// (~/.cursor vs %USERPROFILE%\.cursor) and keyboard shortcuts
|
|
72
|
+
// (Cmd vs Ctrl).
|
|
73
|
+
platform: inputs.platform,
|
|
74
|
+
cliExists: inputs.cliExists,
|
|
75
|
+
nodeExists: inputs.nodeExists,
|
|
76
|
+
buildHint: hints.length ? hints.join(' ') : null,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=install-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-info.js","sourceRoot":"","sources":["../../src/core/install-info.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,yEAAyE;AACzE,yEAAyE;AACzE,2EAA2E;AAC3E,yEAAyE;AACzE,mEAAmE;AACnE,sBAAsB;AACtB,EAAE;AACF,4DAA4D;AAC5D,kEAAkE;AAClE,0EAA0E;AAC1E,kDAAkD;AAuDlD;;;;;;;;GAQG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAoC;IAEpC,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,KAAK,CAAC;IAC9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QACtB,KAAK,CAAC,IAAI,CACR,2BAA2B,MAAM,CAAC,OAAO,mDAAmD,CAC7F,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CACR,8BAA8B,MAAM,CAAC,QAAQ,kEAAkE,CAChH,CAAC;IACJ,CAAC;IACD,qEAAqE;IACrE,sEAAsE;IACtE,wEAAwE;IACxE,+DAA+D;IAC/D,sEAAsE;IACtE,2BAA2B;IAC3B,MAAM,GAAG,GAA2B;QAClC,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,OAAO;QACtC,GAAG,MAAM,CAAC,UAAU;KACrB,CAAC;IACF,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QAC1B,GAAG,CAAC,oBAAoB,GAAG,GAAG,CAAC;IACjC,CAAC;IACD,uEAAuE;IACvE,mEAAmE;IACnE,uEAAuE;IACvE,aAAa;IACb,MAAM,IAAI,GAAG,MAAM,CAAC,aAAa;QAC/B,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC;QAC9B,CAAC,CAAC;YACE,MAAM,CAAC,OAAO;YACd,UAAU;YACV,cAAc;YACd,oBAAoB,MAAM,CAAC,IAAI,EAAE;SAClC,CAAC;IACN,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,QAAQ;QACxB,IAAI;QACJ,GAAG;QACH,SAAS,EAAE,oBAAoB,MAAM,CAAC,IAAI,EAAE;QAC5C,UAAU,EACR,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;YACnE,CAAC,CAAC,MAAM,CAAC,UAAU;YACnB,CAAC,CAAC,IAAI;QACV,gEAAgE;QAChE,8DAA8D;QAC9D,iBAAiB;QACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,UAAU,EAAE,MAAM,CAAC,UAAU;QAC7B,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI;KACjD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/core/oauth
|
|
3
|
+
* Daemon-side OAuth 2.1 / PKCE client for remote (HTTP / SSE) MCP servers:
|
|
4
|
+
* auth-server discovery, dynamic client registration, the authorize/token/refresh
|
|
5
|
+
* exchanges, and the in-memory `PendingAuthCache`. Part of the MCP `core` kernel;
|
|
6
|
+
* depends on no sibling subdirectory.
|
|
7
|
+
*/
|
|
8
|
+
import { createValidatingLookup } from '@jini-ai/platform';
|
|
9
|
+
/** RFC 9728 `oauth-protected-resource` document fields we use. */
|
|
10
|
+
export interface ProtectedResourceMetadata {
|
|
11
|
+
resource?: string;
|
|
12
|
+
authorization_servers?: string[];
|
|
13
|
+
scopes_supported?: string[];
|
|
14
|
+
}
|
|
15
|
+
/** RFC 8414 / OIDC discovery document fields we use. */
|
|
16
|
+
export interface AuthorizationServerMetadata {
|
|
17
|
+
issuer: string;
|
|
18
|
+
authorization_endpoint: string;
|
|
19
|
+
token_endpoint: string;
|
|
20
|
+
registration_endpoint?: string;
|
|
21
|
+
scopes_supported?: string[];
|
|
22
|
+
response_types_supported?: string[];
|
|
23
|
+
grant_types_supported?: string[];
|
|
24
|
+
code_challenge_methods_supported?: string[];
|
|
25
|
+
token_endpoint_auth_methods_supported?: string[];
|
|
26
|
+
}
|
|
27
|
+
/** Cached client registration for a given auth server + redirect URI. */
|
|
28
|
+
export interface RegisteredClient {
|
|
29
|
+
authServerIssuer: string;
|
|
30
|
+
redirectUri: string;
|
|
31
|
+
clientId: string;
|
|
32
|
+
clientSecret?: string;
|
|
33
|
+
registeredAt: number;
|
|
34
|
+
}
|
|
35
|
+
/** RFC 6749 §5.1 token endpoint response (subset). */
|
|
36
|
+
export interface OAuthTokenResponse {
|
|
37
|
+
access_token: string;
|
|
38
|
+
token_type?: string;
|
|
39
|
+
expires_in?: number;
|
|
40
|
+
refresh_token?: string;
|
|
41
|
+
scope?: string;
|
|
42
|
+
}
|
|
43
|
+
/** In-flight authorization request. Stashed in memory while the user
|
|
44
|
+
* approves in their browser. */
|
|
45
|
+
export interface PendingAuthState {
|
|
46
|
+
serverId: string;
|
|
47
|
+
authServerIssuer: string;
|
|
48
|
+
tokenEndpoint: string;
|
|
49
|
+
clientId: string;
|
|
50
|
+
clientSecret?: string;
|
|
51
|
+
redirectUri: string;
|
|
52
|
+
codeVerifier: string;
|
|
53
|
+
scope?: string;
|
|
54
|
+
resourceUrl?: string;
|
|
55
|
+
createdAt: number;
|
|
56
|
+
}
|
|
57
|
+
type DnsLookupCb = Parameters<typeof createValidatingLookup>[0];
|
|
58
|
+
/**
|
|
59
|
+
* Read a response body up to `maxBytes`, aborting `controller` (when given)
|
|
60
|
+
* and throwing the moment the cap is exceeded rather than buffering an
|
|
61
|
+
* unbounded body first. Falls back to a single `res.text()` call (tolerant
|
|
62
|
+
* of a throw, matching the old `safeText`'s forgiving error-path behavior)
|
|
63
|
+
* for response-like test doubles that don't expose a real `ReadableStream`
|
|
64
|
+
* body.
|
|
65
|
+
*
|
|
66
|
+
* `controller` is real, intentional API surface — a caller that already has
|
|
67
|
+
* an in-flight fetch's `AbortController` can pass it so an oversized
|
|
68
|
+
* response stops being pulled from upstream the moment the cap is exceeded,
|
|
69
|
+
* not merely rejected after the fact — but no real call site in this file
|
|
70
|
+
* currently has one in scope to pass (each of the four call sites reads a
|
|
71
|
+
* `Response` it received after its own `safeOAuthFetch` call already
|
|
72
|
+
* returned, by which point that call's own `AbortController` is out of
|
|
73
|
+
* scope). Exported (not just internal) so this real, functioning behavior
|
|
74
|
+
* is directly unit-testable without inventing an unused call site just to
|
|
75
|
+
* reach it — matching this repo's established "extract into a directly-
|
|
76
|
+
* testable pure function" convention.
|
|
77
|
+
*/
|
|
78
|
+
export declare function readCappedText(res: Response, maxBytes: number, controller?: AbortController): Promise<string>;
|
|
79
|
+
/**
|
|
80
|
+
* Generate a cryptographically random PKCE code verifier (RFC 7636 §4.1).
|
|
81
|
+
* Produces a 64-byte base64url-encoded string, within the 43–128 character range.
|
|
82
|
+
* @returns A fresh code verifier string for use in a single authorization request.
|
|
83
|
+
*/
|
|
84
|
+
export declare function generateCodeVerifier(): string;
|
|
85
|
+
/**
|
|
86
|
+
* Derive the S256 PKCE code challenge from a code verifier (RFC 7636 §4.2).
|
|
87
|
+
* Computes `BASE64URL(SHA256(ASCII(verifier)))`.
|
|
88
|
+
* @param verifier The code verifier string produced by `generateCodeVerifier`.
|
|
89
|
+
* @returns The base64url-encoded SHA-256 hash to pass as `code_challenge`.
|
|
90
|
+
*/
|
|
91
|
+
export declare function deriveCodeChallenge(verifier: string): string;
|
|
92
|
+
/**
|
|
93
|
+
* Generate a cryptographically random OAuth `state` parameter.
|
|
94
|
+
* Used as the CSRF token for the authorization request; must be unique per flow.
|
|
95
|
+
* @returns A base64url-encoded 32-byte random string.
|
|
96
|
+
*/
|
|
97
|
+
export declare function generateState(): string;
|
|
98
|
+
/**
|
|
99
|
+
* Try to fetch the protected-resource metadata for a given MCP URL.
|
|
100
|
+
*
|
|
101
|
+
* Per RFC 9728, the well-known is at the resource origin's
|
|
102
|
+
* `/.well-known/oauth-protected-resource[<path>]`. We try both the
|
|
103
|
+
* path-suffixed form and the bare `/.well-known/...` so servers that
|
|
104
|
+
* only publish at the root still work.
|
|
105
|
+
*
|
|
106
|
+
* @param lookupImpl Injectable `dns.lookup` for the connection-time SSRF
|
|
107
|
+
* guard (tests only — see `safeOAuthFetch`).
|
|
108
|
+
*/
|
|
109
|
+
export declare function discoverProtectedResource(resourceUrl: string, fetchImpl?: typeof fetch, lookupImpl?: DnsLookupCb): Promise<ProtectedResourceMetadata | null>;
|
|
110
|
+
/**
|
|
111
|
+
* Fetch the authorization-server metadata for an issuer URL. Tries both
|
|
112
|
+
* the OAuth (RFC 8414) and OIDC layouts (`/.well-known/oauth-authorization-server`
|
|
113
|
+
* and `/.well-known/openid-configuration`); some providers only publish one.
|
|
114
|
+
*
|
|
115
|
+
* Per RFC 8414 §3.3, a discovery document's `issuer` — when present — MUST
|
|
116
|
+
* match the issuer used to construct the request; a mismatched document is
|
|
117
|
+
* rejected rather than trusted (SEC-RB-001 / CR-005). Every endpoint the
|
|
118
|
+
* document names (`authorization_endpoint`, `token_endpoint`,
|
|
119
|
+
* `registration_endpoint`) is additionally required to be an absolute
|
|
120
|
+
* `https:` URL sharing the queried issuer's own origin, so a compromised or
|
|
121
|
+
* hostile document can't redirect DCR or token exchange at an unrelated
|
|
122
|
+
* origin.
|
|
123
|
+
*
|
|
124
|
+
* @param lookupImpl Injectable `dns.lookup` for the connection-time SSRF
|
|
125
|
+
* guard (tests only — see `safeOAuthFetch`).
|
|
126
|
+
*/
|
|
127
|
+
export declare function discoverAuthServer(issuer: string, fetchImpl?: typeof fetch, lookupImpl?: DnsLookupCb): Promise<AuthorizationServerMetadata | null>;
|
|
128
|
+
/**
|
|
129
|
+
* POST to the auth server's `registration_endpoint` per RFC 7591. Returns
|
|
130
|
+
* a freshly issued client_id (and optional client_secret). Caller is
|
|
131
|
+
* responsible for caching the result.
|
|
132
|
+
* @param lookupImpl Injectable `dns.lookup` for the connection-time SSRF
|
|
133
|
+
* guard (tests only — see `safeOAuthFetch`).
|
|
134
|
+
*/
|
|
135
|
+
export declare function registerClient(registrationEndpoint: string, redirectUri: string, fetchImpl?: typeof fetch, lookupImpl?: DnsLookupCb): Promise<{
|
|
136
|
+
clientId: string;
|
|
137
|
+
clientSecret?: string;
|
|
138
|
+
}>;
|
|
139
|
+
/**
|
|
140
|
+
* Cached version of `registerClient`. Looks up `(authServerIssuer, redirectUri)`
|
|
141
|
+
* in the cache file and re-uses the existing client; falls back to a fresh
|
|
142
|
+
* DCR call when nothing is cached.
|
|
143
|
+
* @param lookupImpl Injectable `dns.lookup` for the connection-time SSRF
|
|
144
|
+
* guard (tests only — see `safeOAuthFetch`).
|
|
145
|
+
*/
|
|
146
|
+
export declare function getOrRegisterClient(dataDir: string, authServer: AuthorizationServerMetadata, redirectUri: string, fetchImpl?: typeof fetch, lookupImpl?: DnsLookupCb): Promise<RegisteredClient>;
|
|
147
|
+
/** Inputs required to assemble the authorization redirect URL. */
|
|
148
|
+
export interface AuthorizeUrlInput {
|
|
149
|
+
authServer: AuthorizationServerMetadata;
|
|
150
|
+
clientId: string;
|
|
151
|
+
redirectUri: string;
|
|
152
|
+
state: string;
|
|
153
|
+
codeChallenge: string;
|
|
154
|
+
scope?: string;
|
|
155
|
+
/** RFC 8707 resource indicator — narrows the issued token to the target MCP server. */
|
|
156
|
+
resource?: string;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Assemble the authorization endpoint URL the user's browser must be directed to.
|
|
160
|
+
* Sets PKCE parameters (`code_challenge`, `code_challenge_method=S256`), the `state`
|
|
161
|
+
* CSRF token, and optionally the RFC 8707 `resource` indicator.
|
|
162
|
+
* @param input All parameters needed to build the URL.
|
|
163
|
+
* @returns The fully-qualified authorization URL as a string.
|
|
164
|
+
*/
|
|
165
|
+
export declare function buildAuthorizeUrl(input: AuthorizeUrlInput): string;
|
|
166
|
+
/** Inputs for the authorization-code → token exchange (RFC 6749 §4.1.3). */
|
|
167
|
+
export interface ExchangeCodeInput {
|
|
168
|
+
tokenEndpoint: string;
|
|
169
|
+
clientId: string;
|
|
170
|
+
clientSecret?: string;
|
|
171
|
+
redirectUri: string;
|
|
172
|
+
code: string;
|
|
173
|
+
codeVerifier: string;
|
|
174
|
+
/** RFC 8707 resource indicator to include in the token request. */
|
|
175
|
+
resource?: string;
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Exchange an authorization code for access and refresh tokens (RFC 6749 §4.1.3).
|
|
179
|
+
* Includes the PKCE `code_verifier` and, when supplied, the RFC 8707 `resource`
|
|
180
|
+
* indicator. Throws when the token endpoint returns a non-2xx status.
|
|
181
|
+
* @param input The code-exchange parameters.
|
|
182
|
+
* @param fetchImpl Injectable fetch, defaults to the global `fetch`.
|
|
183
|
+
* @param lookupImpl Injectable `dns.lookup` for the connection-time SSRF
|
|
184
|
+
* guard (tests only — see `safeOAuthFetch`).
|
|
185
|
+
* @returns The token endpoint response containing at least an `access_token`.
|
|
186
|
+
*/
|
|
187
|
+
export declare function exchangeCodeForToken(input: ExchangeCodeInput, fetchImpl?: typeof fetch, lookupImpl?: DnsLookupCb): Promise<OAuthTokenResponse>;
|
|
188
|
+
/** Inputs for the refresh-token → new-access-token exchange (RFC 6749 §6). */
|
|
189
|
+
export interface RefreshTokenInput {
|
|
190
|
+
tokenEndpoint: string;
|
|
191
|
+
clientId: string;
|
|
192
|
+
clientSecret?: string;
|
|
193
|
+
refreshToken: string;
|
|
194
|
+
scope?: string;
|
|
195
|
+
/** RFC 8707 resource indicator, included when the original token was resource-scoped. */
|
|
196
|
+
resource?: string;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Exchange a refresh token for a new access token (RFC 6749 §6).
|
|
200
|
+
* Preserves scope and resource binding from the original authorization.
|
|
201
|
+
* Throws when the token endpoint returns a non-2xx status.
|
|
202
|
+
* @param input The refresh parameters.
|
|
203
|
+
* @param fetchImpl Injectable fetch, defaults to the global `fetch`.
|
|
204
|
+
* @param lookupImpl Injectable `dns.lookup` for the connection-time SSRF
|
|
205
|
+
* guard (tests only — see `safeOAuthFetch`).
|
|
206
|
+
* @returns A fresh `OAuthTokenResponse`; the server may issue a new refresh token.
|
|
207
|
+
*/
|
|
208
|
+
export declare function refreshAccessToken(input: RefreshTokenInput, fetchImpl?: typeof fetch, lookupImpl?: DnsLookupCb): Promise<OAuthTokenResponse>;
|
|
209
|
+
/**
|
|
210
|
+
* The OAuth dance is split across two HTTP requests on our side:
|
|
211
|
+
* 1. the "start" request — we mint state + verifier
|
|
212
|
+
* 2. the "callback" request — browser returns code + state
|
|
213
|
+
* State has to survive between (1) and (2) on the daemon. We keep it in a
|
|
214
|
+
* Map with a TTL sweeper; persistence isn't needed because the user has
|
|
215
|
+
* to complete auth in the same daemon process anyway (state is single-use).
|
|
216
|
+
*/
|
|
217
|
+
export declare class PendingAuthCache {
|
|
218
|
+
private readonly ttlMs;
|
|
219
|
+
private store;
|
|
220
|
+
private timer;
|
|
221
|
+
constructor(ttlMs?: number);
|
|
222
|
+
/**
|
|
223
|
+
* Store a pending auth state keyed by the OAuth `state` parameter.
|
|
224
|
+
* Starts the TTL sweeper if it is not already running.
|
|
225
|
+
* @param state The random `state` string from the authorization request.
|
|
226
|
+
* @param value The associated pending auth metadata to stash.
|
|
227
|
+
*/
|
|
228
|
+
put(state: string, value: PendingAuthState): void;
|
|
229
|
+
/** One-shot consume — any successful callback removes the state so a
|
|
230
|
+
* replay can't reuse it. */
|
|
231
|
+
consume(state: string): PendingAuthState | null;
|
|
232
|
+
/** Return the number of pending auth states currently held in the cache. */
|
|
233
|
+
size(): number;
|
|
234
|
+
/** Stop the background sweeper. Used by tests; production lets the
|
|
235
|
+
* timer ride on the process lifetime. */
|
|
236
|
+
stop(): void;
|
|
237
|
+
private startSweeper;
|
|
238
|
+
private sweep;
|
|
239
|
+
}
|
|
240
|
+
/** Inputs for the full pre-redirect OAuth dance. */
|
|
241
|
+
export interface BeginAuthInput {
|
|
242
|
+
/** The `McpServerConfig.id` of the server being authorized. */
|
|
243
|
+
serverId: string;
|
|
244
|
+
/** The MCP server endpoint URL (used for protected-resource discovery). */
|
|
245
|
+
serverUrl: string;
|
|
246
|
+
/** The OAuth redirect URI the daemon has registered. */
|
|
247
|
+
redirectUri: string;
|
|
248
|
+
/** The resolved data directory (for caching the client registration). */
|
|
249
|
+
dataDir: string;
|
|
250
|
+
scope?: string;
|
|
251
|
+
/** Injectable fetch implementation; defaults to the global `fetch`. */
|
|
252
|
+
fetchImpl?: typeof fetch;
|
|
253
|
+
/** Injectable `dns.lookup` for the connection-time SSRF guard (tests only). */
|
|
254
|
+
lookupImpl?: DnsLookupCb;
|
|
255
|
+
}
|
|
256
|
+
/** Result of `beginAuth`: everything needed to redirect the browser and later complete the flow. */
|
|
257
|
+
export interface BeginAuthResult {
|
|
258
|
+
/** The fully-qualified authorization URL to redirect the user's browser to. */
|
|
259
|
+
authorizeUrl: string;
|
|
260
|
+
/** The random `state` string; must be passed to `PendingAuthCache.put` before redirecting. */
|
|
261
|
+
state: string;
|
|
262
|
+
/** The pending-auth metadata to store in `PendingAuthCache` keyed by `state`. */
|
|
263
|
+
pending: PendingAuthState;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Run the entire pre-redirect half of the OAuth dance:
|
|
267
|
+
* discovery → DCR (cached) → PKCE → authorize URL.
|
|
268
|
+
*
|
|
269
|
+
* Returns everything the caller needs to (a) push the user's browser at the
|
|
270
|
+
* correct authorize URL, and (b) finish the flow when the callback hits.
|
|
271
|
+
*/
|
|
272
|
+
export declare function beginAuth(input: BeginAuthInput): Promise<BeginAuthResult>;
|
|
273
|
+
export {};
|
|
274
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../src/core/oauth.ts"],"names":[],"mappings":"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"}
|