@earendil-works/pi-mcp 1.0.4 → 1.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/CHANGELOG.md +10 -0
- package/dist/auth-provider.d.ts +4 -0
- package/dist/auth-provider.d.ts.map +1 -1
- package/dist/auth-provider.js.map +1 -1
- package/dist/oauth/discovery.d.ts +3 -0
- package/dist/oauth/discovery.d.ts.map +1 -1
- package/dist/oauth/discovery.js +8 -5
- package/dist/oauth/discovery.js.map +1 -1
- package/dist/oauth/flow.d.ts +4 -0
- package/dist/oauth/flow.d.ts.map +1 -1
- package/dist/oauth/flow.js +12 -2
- package/dist/oauth/flow.js.map +1 -1
- package/dist/transports/streamable-http.d.ts +3 -0
- package/dist/transports/streamable-http.d.ts.map +1 -1
- package/dist/transports/streamable-http.js +17 -14
- package/dist/transports/streamable-http.js.map +1 -1
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.1.0] - 2026-10-07
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- Added a `signal` option to `authorizeMcp()`, `registerClient()`, the token request functions, and the discovery functions, which aborts their requests. An aborted refresh no longer falls back to a new authorization ([#10565](https://github.com/earendil-works/pi/issues/10565))
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- Fixed `StreamableHttpTransport.close()` calling `AuthProvider.token()`, which could refresh tokens over the network before the session DELETE and delay closing; the DELETE now reuses the token of the last request ([#10565](https://github.com/earendil-works/pi/issues/10565))
|
|
12
|
+
|
|
3
13
|
## [1.0.4] - 2026-10-05
|
|
4
14
|
|
|
5
15
|
### Fixed
|
package/dist/auth-provider.d.ts
CHANGED
|
@@ -9,6 +9,10 @@ export interface UnauthorizedContext {
|
|
|
9
9
|
}
|
|
10
10
|
/** Supplies bearer tokens to an MCP HTTP transport and may refresh them after a 401 response. */
|
|
11
11
|
export interface AuthProvider {
|
|
12
|
+
/**
|
|
13
|
+
* Token for the next request. May refresh it over the network first, so the transport calls it only
|
|
14
|
+
* before requests whose answer it waits for. Closing a session reuses the token of the last request.
|
|
15
|
+
*/
|
|
12
16
|
token(): Promise<string | undefined>;
|
|
13
17
|
onUnauthorized?(context: UnauthorizedContext): Promise<void>;
|
|
14
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-provider.d.ts","sourceRoot":"","sources":["../src/auth-provider.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEtF,MAAM,WAAW,mBAAmB;IACnC,wFAAwF;IACxF,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,GAAG,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC;IAChB,+HAA+H;IAC/H,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iGAAiG;AACjG,MAAM,WAAW,YAAY;IAC5B,KAAK,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACrC,cAAc,CAAC,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D"}
|
|
1
|
+
{"version":3,"file":"auth-provider.d.ts","sourceRoot":"","sources":["../src/auth-provider.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEtF,MAAM,WAAW,mBAAmB;IACnC,wFAAwF;IACxF,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,GAAG,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC;IAChB,+HAA+H;IAC/H,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,iGAAiG;AACjG,MAAM,WAAW,YAAY;IAC5B;;;OAGG;IACH,KAAK,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACrC,cAAc,CAAC,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC7D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-provider.js","sourceRoot":"","sources":["../src/auth-provider.ts"],"names":[],"mappings":"","sourcesContent":["export type McpFetch = (input: string | URL, init?: RequestInit) => Promise<Response>;\n\nexport interface UnauthorizedContext {\n\t/** The 401 response, or a 403 response whose challenge reports `insufficient_scope`. */\n\tresponse: Response;\n\tserverUrl: URL;\n\tfetch: McpFetch;\n\t/** Access token the rejected request carried, if any. A different current token means another request already refreshed it. */\n\ttoken?: string;\n}\n\n/** Supplies bearer tokens to an MCP HTTP transport and may refresh them after a 401 response. */\nexport interface AuthProvider {\n\ttoken(): Promise<string | undefined>;\n\tonUnauthorized?(context: UnauthorizedContext): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"auth-provider.js","sourceRoot":"","sources":["../src/auth-provider.ts"],"names":[],"mappings":"","sourcesContent":["export type McpFetch = (input: string | URL, init?: RequestInit) => Promise<Response>;\n\nexport interface UnauthorizedContext {\n\t/** The 401 response, or a 403 response whose challenge reports `insufficient_scope`. */\n\tresponse: Response;\n\tserverUrl: URL;\n\tfetch: McpFetch;\n\t/** Access token the rejected request carried, if any. A different current token means another request already refreshed it. */\n\ttoken?: string;\n}\n\n/** Supplies bearer tokens to an MCP HTTP transport and may refresh them after a 401 response. */\nexport interface AuthProvider {\n\t/**\n\t * Token for the next request. May refresh it over the network first, so the transport calls it only\n\t * before requests whose answer it waits for. Closing a session reuses the token of the last request.\n\t */\n\ttoken(): Promise<string | undefined>;\n\tonUnauthorized?(context: UnauthorizedContext): Promise<void>;\n}\n"]}
|
|
@@ -5,6 +5,7 @@ export declare function discoverProtectedResourceMetadata(serverUrl: string | UR
|
|
|
5
5
|
resourceMetadataUrl?: string | URL;
|
|
6
6
|
protocolVersion?: string;
|
|
7
7
|
fetch?: McpFetch;
|
|
8
|
+
signal?: AbortSignal;
|
|
8
9
|
}): Promise<OAuthProtectedResourceMetadata>;
|
|
9
10
|
export declare function buildAuthorizationServerDiscoveryUrls(authorizationServerUrl: string | URL): {
|
|
10
11
|
url: URL;
|
|
@@ -14,6 +15,7 @@ export declare function discoverAuthorizationServerMetadata(authorizationServerU
|
|
|
14
15
|
fetch?: McpFetch;
|
|
15
16
|
protocolVersion?: string;
|
|
16
17
|
skipIssuerValidation?: boolean;
|
|
18
|
+
signal?: AbortSignal;
|
|
17
19
|
}): Promise<AuthorizationServerMetadata | undefined>;
|
|
18
20
|
export declare function discoverOAuthServerInfo(serverUrl: string | URL, options?: {
|
|
19
21
|
resourceMetadataUrl?: URL;
|
|
@@ -21,6 +23,7 @@ export declare function discoverOAuthServerInfo(serverUrl: string | URL, options
|
|
|
21
23
|
authorizationServerMetadataUrl?: URL;
|
|
22
24
|
fetch?: McpFetch;
|
|
23
25
|
skipIssuerValidation?: boolean;
|
|
26
|
+
signal?: AbortSignal;
|
|
24
27
|
}): Promise<OAuthServerInfo>;
|
|
25
28
|
export declare function resourceUrlFromServerUrl(value: string | URL): URL;
|
|
26
29
|
export declare function selectResource(serverUrl: string | URL, metadata?: OAuthProtectedResourceMetadata): string | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/oauth/discovery.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EACN,KAAK,2BAA2B,EAChC,KAAK,cAAc,EACnB,KAAK,8BAA8B,EACnC,KAAK,eAAe,EAGpB,MAAM,YAAY,CAAC;AAsBpB,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAiB1E;
|
|
1
|
+
{"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/oauth/discovery.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAGpD,OAAO,EACN,KAAK,2BAA2B,EAChC,KAAK,cAAc,EACnB,KAAK,8BAA8B,EACnC,KAAK,eAAe,EAGpB,MAAM,YAAY,CAAC;AAsBpB,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,cAAc,CAiB1E;AAcD,wBAAsB,iCAAiC,CACtD,SAAS,EAAE,MAAM,GAAG,GAAG,EACvB,OAAO,GAAE;IACR,mBAAmB,CAAC,EAAE,MAAM,GAAG,GAAG,CAAC;IACnC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,MAAM,CAAC,EAAE,WAAW,CAAC;CAChB,GACJ,OAAO,CAAC,8BAA8B,CAAC,CA0BzC;AAED,wBAAgB,qCAAqC,CACpD,sBAAsB,EAAE,MAAM,GAAG,GAAG,GAClC;IAAE,GAAG,EAAE,GAAG,CAAC;IAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;CAAE,EAAE,CASxC;AAED,wBAAsB,mCAAmC,CACxD,sBAAsB,EAAE,MAAM,GAAG,GAAG,EACpC,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,QAAQ,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,WAAW,CAAA;CAAO,GAChH,OAAO,CAAC,2BAA2B,GAAG,SAAS,CAAC,CAwBlD;AAED,wBAAsB,uBAAuB,CAC5C,SAAS,EAAE,MAAM,GAAG,GAAG,EACvB,OAAO,GAAE;IACR,mBAAmB,CAAC,EAAE,GAAG,CAAC;IAC1B,gHAAgH;IAChH,8BAA8B,CAAC,EAAE,GAAG,CAAC;IACrC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;CAChB,GACJ,OAAO,CAAC,eAAe,CAAC,CAoC1B;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,GAAG,GAAG,CAIjE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,EAAE,QAAQ,CAAC,EAAE,8BAA8B,GAAG,MAAM,GAAG,SAAS,CAarH"}
|
package/dist/oauth/discovery.js
CHANGED
|
@@ -43,9 +43,10 @@ export function parseWwwAuthenticate(header) {
|
|
|
43
43
|
errorDescription: field(header, "error_description"),
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
|
-
async function fetchMetadata(url, fetch, protocolVersion) {
|
|
46
|
+
async function fetchMetadata(url, fetch, protocolVersion, signal) {
|
|
47
47
|
return fetch(url, {
|
|
48
48
|
headers: { Accept: "application/json", "MCP-Protocol-Version": protocolVersion },
|
|
49
|
+
signal,
|
|
49
50
|
});
|
|
50
51
|
}
|
|
51
52
|
export async function discoverProtectedResourceMetadata(serverUrl, options = {}) {
|
|
@@ -54,10 +55,10 @@ export async function discoverProtectedResourceMetadata(serverUrl, options = {})
|
|
|
54
55
|
const version = options.protocolVersion ?? LATEST_PROTOCOL_VERSION;
|
|
55
56
|
let response = await fetchMetadata(options.resourceMetadataUrl
|
|
56
57
|
? new URL(options.resourceMetadataUrl)
|
|
57
|
-
: new URL(`/.well-known/oauth-protected-resource${pathSuffix(server.pathname)}`, server.origin), fetch, version);
|
|
58
|
+
: new URL(`/.well-known/oauth-protected-resource${pathSuffix(server.pathname)}`, server.origin), fetch, version, options.signal);
|
|
58
59
|
if (!options.resourceMetadataUrl && server.pathname !== "/" && isDiscoveryMiss(response.status)) {
|
|
59
60
|
discard(response);
|
|
60
|
-
response = await fetchMetadata(new URL("/.well-known/oauth-protected-resource", server.origin), fetch, version);
|
|
61
|
+
response = await fetchMetadata(new URL("/.well-known/oauth-protected-resource", server.origin), fetch, version, options.signal);
|
|
61
62
|
}
|
|
62
63
|
if (!response.ok) {
|
|
63
64
|
discard(response);
|
|
@@ -79,7 +80,7 @@ export function buildAuthorizationServerDiscoveryUrls(authorizationServerUrl) {
|
|
|
79
80
|
export async function discoverAuthorizationServerMetadata(authorizationServerUrl, options = {}) {
|
|
80
81
|
const fetch = options.fetch ?? globalThis.fetch;
|
|
81
82
|
for (const { url } of buildAuthorizationServerDiscoveryUrls(authorizationServerUrl)) {
|
|
82
|
-
const response = await fetchMetadata(url, fetch, options.protocolVersion ?? LATEST_PROTOCOL_VERSION);
|
|
83
|
+
const response = await fetchMetadata(url, fetch, options.protocolVersion ?? LATEST_PROTOCOL_VERSION, options.signal);
|
|
83
84
|
if (!response.ok) {
|
|
84
85
|
discard(response);
|
|
85
86
|
if (isDiscoveryMiss(response.status))
|
|
@@ -104,6 +105,7 @@ export async function discoverOAuthServerInfo(serverUrl, options = {}) {
|
|
|
104
105
|
resourceMetadata = await discoverProtectedResourceMetadata(serverUrl, {
|
|
105
106
|
resourceMetadataUrl: options.resourceMetadataUrl,
|
|
106
107
|
fetch: options.fetch,
|
|
108
|
+
signal: options.signal,
|
|
107
109
|
});
|
|
108
110
|
}
|
|
109
111
|
catch (error) {
|
|
@@ -112,7 +114,7 @@ export async function discoverOAuthServerInfo(serverUrl, options = {}) {
|
|
|
112
114
|
}
|
|
113
115
|
if (options.authorizationServerMetadataUrl) {
|
|
114
116
|
const url = options.authorizationServerMetadataUrl;
|
|
115
|
-
const response = await fetchMetadata(url, options.fetch ?? globalThis.fetch, LATEST_PROTOCOL_VERSION);
|
|
117
|
+
const response = await fetchMetadata(url, options.fetch ?? globalThis.fetch, LATEST_PROTOCOL_VERSION, options.signal);
|
|
116
118
|
if (!response.ok) {
|
|
117
119
|
discard(response);
|
|
118
120
|
throw new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);
|
|
@@ -126,6 +128,7 @@ export async function discoverOAuthServerInfo(serverUrl, options = {}) {
|
|
|
126
128
|
authorizationServerMetadata: await discoverAuthorizationServerMetadata(authorizationServerUrl, {
|
|
127
129
|
fetch: options.fetch,
|
|
128
130
|
skipIssuerValidation: options.skipIssuerValidation,
|
|
131
|
+
signal: options.signal,
|
|
129
132
|
}),
|
|
130
133
|
resourceMetadata,
|
|
131
134
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/oauth/discovery.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Adapted from modelcontextprotocol/typescript-sdk v1.29.0 src/client/auth.ts.\n * Copyright (c) 2024 Anthropic, PBC. Licensed under MIT; see LICENSES/.\n * Modified to remove Zod/CORS shims and enforce authorization-server issuer validation.\n */\n\nimport type { McpFetch } from \"../auth-provider.ts\";\nimport { LATEST_PROTOCOL_VERSION } from \"../protocol/types.ts\";\nimport { OAuthIssuerMismatchError } from \"./errors.ts\";\nimport {\n\ttype AuthorizationServerMetadata,\n\ttype OAuthChallenge,\n\ttype OAuthProtectedResourceMetadata,\n\ttype OAuthServerInfo,\n\tparseAuthorizationServerMetadata,\n\tparseProtectedResourceMetadata,\n} from \"./types.ts\";\n\nfunction discard(response: Response | undefined): void {\n\tvoid response?.body?.cancel().catch(() => {});\n}\n\n/** 4xx and 502 mean \"not here\", so discovery tries the next candidate URL. */\nfunction isDiscoveryMiss(status: number): boolean {\n\treturn (status >= 400 && status < 500) || status === 502;\n}\n\n/** Path suffix for `/.well-known/<kind><path>`; empty for the root path. */\nfunction pathSuffix(pathname: string): string {\n\treturn pathname.endsWith(\"/\") ? pathname.slice(0, -1) : pathname;\n}\n\nfunction field(header: string, name: string): string | undefined {\n\tconst match = header.match(new RegExp(String.raw`(?:^|[,\\s])${name}=(?:\"([^\"]*)\"|([^\\s,]+))`, \"i\"));\n\t// An empty value (`scope=\"\"`) carries no information, so it counts as absent.\n\treturn match?.[1] || match?.[2] || undefined;\n}\n\nexport function parseWwwAuthenticate(header: string | null): OAuthChallenge {\n\tif (!header) return {};\n\tconst scheme = header.trimStart().split(/\\s+/, 1)[0]?.toLowerCase();\n\tif (scheme !== \"bearer\" && scheme !== \"dpop\") return {};\n\tconst resourceMetadata = field(header, \"resource_metadata\");\n\tlet resourceMetadataUrl: URL | undefined;\n\tif (resourceMetadata) {\n\t\ttry {\n\t\t\tresourceMetadataUrl = new URL(resourceMetadata);\n\t\t} catch {}\n\t}\n\treturn {\n\t\tresourceMetadataUrl,\n\t\tscope: field(header, \"scope\"),\n\t\terror: field(header, \"error\"),\n\t\terrorDescription: field(header, \"error_description\"),\n\t};\n}\n\nasync function fetchMetadata(url: URL, fetch: McpFetch, protocolVersion: string): Promise<Response> {\n\treturn fetch(url, {\n\t\theaders: { Accept: \"application/json\", \"MCP-Protocol-Version\": protocolVersion },\n\t});\n}\n\nexport async function discoverProtectedResourceMetadata(\n\tserverUrl: string | URL,\n\toptions: { resourceMetadataUrl?: string | URL; protocolVersion?: string; fetch?: McpFetch } = {},\n): Promise<OAuthProtectedResourceMetadata> {\n\tconst server = new URL(serverUrl);\n\tconst fetch = options.fetch ?? globalThis.fetch;\n\tconst version = options.protocolVersion ?? LATEST_PROTOCOL_VERSION;\n\tlet response = await fetchMetadata(\n\t\toptions.resourceMetadataUrl\n\t\t\t? new URL(options.resourceMetadataUrl)\n\t\t\t: new URL(`/.well-known/oauth-protected-resource${pathSuffix(server.pathname)}`, server.origin),\n\t\tfetch,\n\t\tversion,\n\t);\n\tif (!options.resourceMetadataUrl && server.pathname !== \"/\" && isDiscoveryMiss(response.status)) {\n\t\tdiscard(response);\n\t\tresponse = await fetchMetadata(new URL(\"/.well-known/oauth-protected-resource\", server.origin), fetch, version);\n\t}\n\tif (!response.ok) {\n\t\tdiscard(response);\n\t\tthrow new Error(`HTTP ${response.status} loading OAuth protected resource metadata`);\n\t}\n\treturn parseProtectedResourceMetadata(await response.json());\n}\n\nexport function buildAuthorizationServerDiscoveryUrls(\n\tauthorizationServerUrl: string | URL,\n): { url: URL; type: \"oauth\" | \"oidc\" }[] {\n\tconst issuer = new URL(authorizationServerUrl);\n\tconst path = pathSuffix(issuer.pathname);\n\tconst urls: { url: URL; type: \"oauth\" | \"oidc\" }[] = [\n\t\t{ url: new URL(`/.well-known/oauth-authorization-server${path}`, issuer.origin), type: \"oauth\" },\n\t\t{ url: new URL(`/.well-known/openid-configuration${path}`, issuer.origin), type: \"oidc\" },\n\t];\n\tif (path) urls.push({ url: new URL(`${path}/.well-known/openid-configuration`, issuer.origin), type: \"oidc\" });\n\treturn urls;\n}\n\nexport async function discoverAuthorizationServerMetadata(\n\tauthorizationServerUrl: string | URL,\n\toptions: { fetch?: McpFetch; protocolVersion?: string; skipIssuerValidation?: boolean } = {},\n): Promise<AuthorizationServerMetadata | undefined> {\n\tconst fetch = options.fetch ?? globalThis.fetch;\n\tfor (const { url } of buildAuthorizationServerDiscoveryUrls(authorizationServerUrl)) {\n\t\tconst response = await fetchMetadata(url, fetch, options.protocolVersion ?? LATEST_PROTOCOL_VERSION);\n\t\tif (!response.ok) {\n\t\t\tdiscard(response);\n\t\t\tif (isDiscoveryMiss(response.status)) continue;\n\t\t\tthrow new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);\n\t\t}\n\t\tconst metadata = parseAuthorizationServerMetadata(await response.json());\n\t\tif (!options.skipIssuerValidation) {\n\t\t\tconst expected = String(authorizationServerUrl);\n\t\t\t// URL parsing adds a trailing slash to bare origins, so compare without one on either side.\n\t\t\tconst trim = (value: string) => (value.endsWith(\"/\") ? value.slice(0, -1) : value);\n\t\t\tif (trim(metadata.issuer) !== trim(expected)) throw new OAuthIssuerMismatchError(expected, metadata.issuer);\n\t\t}\n\t\treturn metadata;\n\t}\n\treturn undefined;\n}\n\nexport async function discoverOAuthServerInfo(\n\tserverUrl: string | URL,\n\toptions: {\n\t\tresourceMetadataUrl?: URL;\n\t\t/** Metadata document to use instead of discovery. It is trusted as configured, so its issuer is not checked. */\n\t\tauthorizationServerMetadataUrl?: URL;\n\t\tfetch?: McpFetch;\n\t\tskipIssuerValidation?: boolean;\n\t} = {},\n): Promise<OAuthServerInfo> {\n\tlet resourceMetadata: OAuthProtectedResourceMetadata | undefined;\n\ttry {\n\t\tresourceMetadata = await discoverProtectedResourceMetadata(serverUrl, {\n\t\t\tresourceMetadataUrl: options.resourceMetadataUrl,\n\t\t\tfetch: options.fetch,\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof TypeError) throw error;\n\t}\n\tif (options.authorizationServerMetadataUrl) {\n\t\tconst url = options.authorizationServerMetadataUrl;\n\t\tconst response = await fetchMetadata(url, options.fetch ?? globalThis.fetch, LATEST_PROTOCOL_VERSION);\n\t\tif (!response.ok) {\n\t\t\tdiscard(response);\n\t\t\tthrow new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);\n\t\t}\n\t\tconst metadata = parseAuthorizationServerMetadata(await response.json());\n\t\treturn { authorizationServerUrl: metadata.issuer, authorizationServerMetadata: metadata, resourceMetadata };\n\t}\n\tconst authorizationServerUrl = resourceMetadata?.authorization_servers?.[0] ?? String(new URL(\"/\", serverUrl));\n\treturn {\n\t\tauthorizationServerUrl,\n\t\tauthorizationServerMetadata: await discoverAuthorizationServerMetadata(authorizationServerUrl, {\n\t\t\tfetch: options.fetch,\n\t\t\tskipIssuerValidation: options.skipIssuerValidation,\n\t\t}),\n\t\tresourceMetadata,\n\t};\n}\n\nexport function resourceUrlFromServerUrl(value: string | URL): URL {\n\tconst url = new URL(value);\n\turl.hash = \"\";\n\treturn url;\n}\n\nexport function selectResource(serverUrl: string | URL, metadata?: OAuthProtectedResourceMetadata): string | undefined {\n\tif (!metadata) return undefined;\n\tconst requested = resourceUrlFromServerUrl(serverUrl);\n\tconst configured = new URL(metadata.resource);\n\tif (requested.origin !== configured.origin) {\n\t\tthrow new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);\n\t}\n\tconst requestedPath = requested.pathname.endsWith(\"/\") ? requested.pathname : `${requested.pathname}/`;\n\tconst configuredPath = configured.pathname.endsWith(\"/\") ? configured.pathname : `${configured.pathname}/`;\n\tif (!requestedPath.startsWith(configuredPath)) {\n\t\tthrow new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);\n\t}\n\treturn metadata.resource;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/oauth/discovery.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Adapted from modelcontextprotocol/typescript-sdk v1.29.0 src/client/auth.ts.\n * Copyright (c) 2024 Anthropic, PBC. Licensed under MIT; see LICENSES/.\n * Modified to remove Zod/CORS shims and enforce authorization-server issuer validation.\n */\n\nimport type { McpFetch } from \"../auth-provider.ts\";\nimport { LATEST_PROTOCOL_VERSION } from \"../protocol/types.ts\";\nimport { OAuthIssuerMismatchError } from \"./errors.ts\";\nimport {\n\ttype AuthorizationServerMetadata,\n\ttype OAuthChallenge,\n\ttype OAuthProtectedResourceMetadata,\n\ttype OAuthServerInfo,\n\tparseAuthorizationServerMetadata,\n\tparseProtectedResourceMetadata,\n} from \"./types.ts\";\n\nfunction discard(response: Response | undefined): void {\n\tvoid response?.body?.cancel().catch(() => {});\n}\n\n/** 4xx and 502 mean \"not here\", so discovery tries the next candidate URL. */\nfunction isDiscoveryMiss(status: number): boolean {\n\treturn (status >= 400 && status < 500) || status === 502;\n}\n\n/** Path suffix for `/.well-known/<kind><path>`; empty for the root path. */\nfunction pathSuffix(pathname: string): string {\n\treturn pathname.endsWith(\"/\") ? pathname.slice(0, -1) : pathname;\n}\n\nfunction field(header: string, name: string): string | undefined {\n\tconst match = header.match(new RegExp(String.raw`(?:^|[,\\s])${name}=(?:\"([^\"]*)\"|([^\\s,]+))`, \"i\"));\n\t// An empty value (`scope=\"\"`) carries no information, so it counts as absent.\n\treturn match?.[1] || match?.[2] || undefined;\n}\n\nexport function parseWwwAuthenticate(header: string | null): OAuthChallenge {\n\tif (!header) return {};\n\tconst scheme = header.trimStart().split(/\\s+/, 1)[0]?.toLowerCase();\n\tif (scheme !== \"bearer\" && scheme !== \"dpop\") return {};\n\tconst resourceMetadata = field(header, \"resource_metadata\");\n\tlet resourceMetadataUrl: URL | undefined;\n\tif (resourceMetadata) {\n\t\ttry {\n\t\t\tresourceMetadataUrl = new URL(resourceMetadata);\n\t\t} catch {}\n\t}\n\treturn {\n\t\tresourceMetadataUrl,\n\t\tscope: field(header, \"scope\"),\n\t\terror: field(header, \"error\"),\n\t\terrorDescription: field(header, \"error_description\"),\n\t};\n}\n\nasync function fetchMetadata(\n\turl: URL,\n\tfetch: McpFetch,\n\tprotocolVersion: string,\n\tsignal: AbortSignal | undefined,\n): Promise<Response> {\n\treturn fetch(url, {\n\t\theaders: { Accept: \"application/json\", \"MCP-Protocol-Version\": protocolVersion },\n\t\tsignal,\n\t});\n}\n\nexport async function discoverProtectedResourceMetadata(\n\tserverUrl: string | URL,\n\toptions: {\n\t\tresourceMetadataUrl?: string | URL;\n\t\tprotocolVersion?: string;\n\t\tfetch?: McpFetch;\n\t\tsignal?: AbortSignal;\n\t} = {},\n): Promise<OAuthProtectedResourceMetadata> {\n\tconst server = new URL(serverUrl);\n\tconst fetch = options.fetch ?? globalThis.fetch;\n\tconst version = options.protocolVersion ?? LATEST_PROTOCOL_VERSION;\n\tlet response = await fetchMetadata(\n\t\toptions.resourceMetadataUrl\n\t\t\t? new URL(options.resourceMetadataUrl)\n\t\t\t: new URL(`/.well-known/oauth-protected-resource${pathSuffix(server.pathname)}`, server.origin),\n\t\tfetch,\n\t\tversion,\n\t\toptions.signal,\n\t);\n\tif (!options.resourceMetadataUrl && server.pathname !== \"/\" && isDiscoveryMiss(response.status)) {\n\t\tdiscard(response);\n\t\tresponse = await fetchMetadata(\n\t\t\tnew URL(\"/.well-known/oauth-protected-resource\", server.origin),\n\t\t\tfetch,\n\t\t\tversion,\n\t\t\toptions.signal,\n\t\t);\n\t}\n\tif (!response.ok) {\n\t\tdiscard(response);\n\t\tthrow new Error(`HTTP ${response.status} loading OAuth protected resource metadata`);\n\t}\n\treturn parseProtectedResourceMetadata(await response.json());\n}\n\nexport function buildAuthorizationServerDiscoveryUrls(\n\tauthorizationServerUrl: string | URL,\n): { url: URL; type: \"oauth\" | \"oidc\" }[] {\n\tconst issuer = new URL(authorizationServerUrl);\n\tconst path = pathSuffix(issuer.pathname);\n\tconst urls: { url: URL; type: \"oauth\" | \"oidc\" }[] = [\n\t\t{ url: new URL(`/.well-known/oauth-authorization-server${path}`, issuer.origin), type: \"oauth\" },\n\t\t{ url: new URL(`/.well-known/openid-configuration${path}`, issuer.origin), type: \"oidc\" },\n\t];\n\tif (path) urls.push({ url: new URL(`${path}/.well-known/openid-configuration`, issuer.origin), type: \"oidc\" });\n\treturn urls;\n}\n\nexport async function discoverAuthorizationServerMetadata(\n\tauthorizationServerUrl: string | URL,\n\toptions: { fetch?: McpFetch; protocolVersion?: string; skipIssuerValidation?: boolean; signal?: AbortSignal } = {},\n): Promise<AuthorizationServerMetadata | undefined> {\n\tconst fetch = options.fetch ?? globalThis.fetch;\n\tfor (const { url } of buildAuthorizationServerDiscoveryUrls(authorizationServerUrl)) {\n\t\tconst response = await fetchMetadata(\n\t\t\turl,\n\t\t\tfetch,\n\t\t\toptions.protocolVersion ?? LATEST_PROTOCOL_VERSION,\n\t\t\toptions.signal,\n\t\t);\n\t\tif (!response.ok) {\n\t\t\tdiscard(response);\n\t\t\tif (isDiscoveryMiss(response.status)) continue;\n\t\t\tthrow new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);\n\t\t}\n\t\tconst metadata = parseAuthorizationServerMetadata(await response.json());\n\t\tif (!options.skipIssuerValidation) {\n\t\t\tconst expected = String(authorizationServerUrl);\n\t\t\t// URL parsing adds a trailing slash to bare origins, so compare without one on either side.\n\t\t\tconst trim = (value: string) => (value.endsWith(\"/\") ? value.slice(0, -1) : value);\n\t\t\tif (trim(metadata.issuer) !== trim(expected)) throw new OAuthIssuerMismatchError(expected, metadata.issuer);\n\t\t}\n\t\treturn metadata;\n\t}\n\treturn undefined;\n}\n\nexport async function discoverOAuthServerInfo(\n\tserverUrl: string | URL,\n\toptions: {\n\t\tresourceMetadataUrl?: URL;\n\t\t/** Metadata document to use instead of discovery. It is trusted as configured, so its issuer is not checked. */\n\t\tauthorizationServerMetadataUrl?: URL;\n\t\tfetch?: McpFetch;\n\t\tskipIssuerValidation?: boolean;\n\t\tsignal?: AbortSignal;\n\t} = {},\n): Promise<OAuthServerInfo> {\n\tlet resourceMetadata: OAuthProtectedResourceMetadata | undefined;\n\ttry {\n\t\tresourceMetadata = await discoverProtectedResourceMetadata(serverUrl, {\n\t\t\tresourceMetadataUrl: options.resourceMetadataUrl,\n\t\t\tfetch: options.fetch,\n\t\t\tsignal: options.signal,\n\t\t});\n\t} catch (error) {\n\t\tif (error instanceof TypeError) throw error;\n\t}\n\tif (options.authorizationServerMetadataUrl) {\n\t\tconst url = options.authorizationServerMetadataUrl;\n\t\tconst response = await fetchMetadata(\n\t\t\turl,\n\t\t\toptions.fetch ?? globalThis.fetch,\n\t\t\tLATEST_PROTOCOL_VERSION,\n\t\t\toptions.signal,\n\t\t);\n\t\tif (!response.ok) {\n\t\t\tdiscard(response);\n\t\t\tthrow new Error(`HTTP ${response.status} loading authorization server metadata from ${url}`);\n\t\t}\n\t\tconst metadata = parseAuthorizationServerMetadata(await response.json());\n\t\treturn { authorizationServerUrl: metadata.issuer, authorizationServerMetadata: metadata, resourceMetadata };\n\t}\n\tconst authorizationServerUrl = resourceMetadata?.authorization_servers?.[0] ?? String(new URL(\"/\", serverUrl));\n\treturn {\n\t\tauthorizationServerUrl,\n\t\tauthorizationServerMetadata: await discoverAuthorizationServerMetadata(authorizationServerUrl, {\n\t\t\tfetch: options.fetch,\n\t\t\tskipIssuerValidation: options.skipIssuerValidation,\n\t\t\tsignal: options.signal,\n\t\t}),\n\t\tresourceMetadata,\n\t};\n}\n\nexport function resourceUrlFromServerUrl(value: string | URL): URL {\n\tconst url = new URL(value);\n\turl.hash = \"\";\n\treturn url;\n}\n\nexport function selectResource(serverUrl: string | URL, metadata?: OAuthProtectedResourceMetadata): string | undefined {\n\tif (!metadata) return undefined;\n\tconst requested = resourceUrlFromServerUrl(serverUrl);\n\tconst configured = new URL(metadata.resource);\n\tif (requested.origin !== configured.origin) {\n\t\tthrow new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);\n\t}\n\tconst requestedPath = requested.pathname.endsWith(\"/\") ? requested.pathname : `${requested.pathname}/`;\n\tconst configuredPath = configured.pathname.endsWith(\"/\") ? configured.pathname : `${configured.pathname}/`;\n\tif (!requestedPath.startsWith(configuredPath)) {\n\t\tthrow new Error(`Protected resource ${metadata.resource} does not match MCP server ${requested}`);\n\t}\n\treturn metadata.resource;\n}\n"]}
|
package/dist/oauth/flow.d.ts
CHANGED
|
@@ -41,6 +41,8 @@ export interface OAuthFlowOptions {
|
|
|
41
41
|
*/
|
|
42
42
|
authorizationServerMetadataUrl?: URL;
|
|
43
43
|
fetch?: McpFetch;
|
|
44
|
+
/** Aborts every request of the flow. Requests have no time limit of their own; combine with a timeout as needed. */
|
|
45
|
+
signal?: AbortSignal;
|
|
44
46
|
skipIssuerValidation?: boolean;
|
|
45
47
|
/**
|
|
46
48
|
* Go straight to the authorization redirect instead of refreshing stored tokens, for example when the
|
|
@@ -55,6 +57,7 @@ export interface TokenRequestOptions {
|
|
|
55
57
|
resource?: string;
|
|
56
58
|
addClientAuthentication?: AddClientAuthentication;
|
|
57
59
|
fetch?: McpFetch;
|
|
60
|
+
signal?: AbortSignal;
|
|
58
61
|
}
|
|
59
62
|
export declare function startAuthorization(authorizationServerUrl: string | URL, options: {
|
|
60
63
|
metadata?: AuthorizationServerMetadata;
|
|
@@ -72,6 +75,7 @@ export declare function registerClient(authorizationServerUrl: string | URL, opt
|
|
|
72
75
|
clientMetadata: OAuthClientMetadata;
|
|
73
76
|
scope?: string;
|
|
74
77
|
fetch?: McpFetch;
|
|
78
|
+
signal?: AbortSignal;
|
|
75
79
|
}): Promise<OAuthClientInformationFull>;
|
|
76
80
|
export declare function exchangeAuthorizationCode(authorizationServerUrl: string | URL, options: TokenRequestOptions & {
|
|
77
81
|
code: string;
|
package/dist/oauth/flow.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/oauth/flow.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/oauth/flow.ts"],"names":[],"mappings":"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"}
|
package/dist/oauth/flow.js
CHANGED
|
@@ -100,7 +100,12 @@ async function tokenRequest(authorizationServerUrl, options, params) {
|
|
|
100
100
|
else {
|
|
101
101
|
applyClientAuthentication(selectClientAuthMethod(options.clientInformation, options.metadata?.token_endpoint_auth_methods_supported ?? []), options.clientInformation, headers, params);
|
|
102
102
|
}
|
|
103
|
-
const response = await (options.fetch ?? globalThis.fetch)(url, {
|
|
103
|
+
const response = await (options.fetch ?? globalThis.fetch)(url, {
|
|
104
|
+
method: "POST",
|
|
105
|
+
headers,
|
|
106
|
+
body: params,
|
|
107
|
+
signal: options.signal,
|
|
108
|
+
});
|
|
104
109
|
const text = await response.text();
|
|
105
110
|
let value;
|
|
106
111
|
try {
|
|
@@ -127,6 +132,7 @@ export async function registerClient(authorizationServerUrl, options) {
|
|
|
127
132
|
application_type: options.clientMetadata.application_type ?? applicationType(options.clientMetadata.redirect_uris),
|
|
128
133
|
...(options.scope ? { scope: options.scope } : {}),
|
|
129
134
|
}),
|
|
135
|
+
signal: options.signal,
|
|
130
136
|
});
|
|
131
137
|
if (!response.ok)
|
|
132
138
|
throw new OAuthRegistrationError(response.status, await response.text());
|
|
@@ -169,6 +175,7 @@ async function runFlow(provider, options) {
|
|
|
169
175
|
(await discoverAuthorizationServerMetadata(cached.authorizationServerUrl, {
|
|
170
176
|
fetch: options.fetch,
|
|
171
177
|
skipIssuerValidation: options.skipIssuerValidation,
|
|
178
|
+
signal: options.signal,
|
|
172
179
|
})),
|
|
173
180
|
resourceMetadata: cached.resourceMetadata,
|
|
174
181
|
}
|
|
@@ -177,6 +184,7 @@ async function runFlow(provider, options) {
|
|
|
177
184
|
authorizationServerMetadataUrl: metadataUrl,
|
|
178
185
|
fetch: options.fetch,
|
|
179
186
|
skipIssuerValidation: options.skipIssuerValidation,
|
|
187
|
+
signal: options.signal,
|
|
180
188
|
});
|
|
181
189
|
if (!metadataUrl) {
|
|
182
190
|
await provider.saveDiscoveryState?.({
|
|
@@ -206,6 +214,7 @@ async function runFlow(provider, options) {
|
|
|
206
214
|
clientMetadata: provider.clientMetadata,
|
|
207
215
|
scope,
|
|
208
216
|
fetch: options.fetch,
|
|
217
|
+
signal: options.signal,
|
|
209
218
|
});
|
|
210
219
|
await provider.saveClientInformation(client);
|
|
211
220
|
}
|
|
@@ -217,6 +226,7 @@ async function runFlow(provider, options) {
|
|
|
217
226
|
resource,
|
|
218
227
|
addClientAuthentication: provider.addClientAuthentication,
|
|
219
228
|
fetch: options.fetch,
|
|
229
|
+
signal: options.signal,
|
|
220
230
|
};
|
|
221
231
|
if (options.authorizationCode) {
|
|
222
232
|
// RFC 9207: never send a code from another authorization server to this one.
|
|
@@ -248,7 +258,7 @@ async function runFlow(provider, options) {
|
|
|
248
258
|
return "AUTHORIZED";
|
|
249
259
|
}
|
|
250
260
|
catch (error) {
|
|
251
|
-
if (error instanceof OAuthInsecureEndpointError)
|
|
261
|
+
if (options.signal?.aborted || error instanceof OAuthInsecureEndpointError)
|
|
252
262
|
throw error;
|
|
253
263
|
if (error instanceof OAuthError && error.code !== "server_error")
|
|
254
264
|
throw error;
|
package/dist/oauth/flow.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/oauth/flow.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Adapted from modelcontextprotocol/typescript-sdk v1.29.0 src/client/auth.ts.\n * Copyright (c) 2024 Anthropic, PBC. Licensed under MIT; see LICENSES/.\n * Modified to remove SDK/Zod dependencies and use WebCrypto for PKCE.\n */\n\nimport type { AuthProvider, McpFetch, UnauthorizedContext } from \"../auth-provider.ts\";\nimport { isObject } from \"../protocol/jsonrpc.ts\";\nimport {\n\tdiscoverAuthorizationServerMetadata,\n\tdiscoverOAuthServerInfo,\n\tparseWwwAuthenticate,\n\tselectResource,\n} from \"./discovery.ts\";\nimport {\n\tMcpOAuthAuthorizationRequiredError,\n\tOAuthError,\n\tOAuthInsecureEndpointError,\n\tOAuthIssuerMismatchError,\n\tOAuthRegistrationError,\n} from \"./errors.ts\";\nimport {\n\ttype AuthorizationServerMetadata,\n\ttype OAuthClientInformation,\n\ttype OAuthClientInformationFull,\n\ttype OAuthClientInformationMixed,\n\ttype OAuthClientMetadata,\n\ttype OAuthDiscoveryState,\n\ttype OAuthTokens,\n\tparseClientInformation,\n\tparseOAuthTokens,\n} from \"./types.ts\";\n\nexport type AddClientAuthentication = (\n\theaders: Headers,\n\tparams: URLSearchParams,\n\turl: string | URL,\n\tmetadata?: AuthorizationServerMetadata,\n) => void | Promise<void>;\n\n/** A Client ID Metadata Document: an https URL used as `client_id`, and a redirect URI it lists. */\nexport interface OAuthClientMetadataDocument {\n\turl: string;\n\tredirectUrl: string;\n}\n\nexport interface OAuthClientProvider {\n\treadonly redirectUrl: string | URL;\n\treadonly clientMetadata: OAuthClientMetadata;\n\t/**\n\t * Client ID Metadata Document to identify as instead of registering dynamically, or `undefined` to\n\t * register. Called when no client information is stored; the document is not stored. `metadata` is\n\t * `undefined` when the authorization server has none; check `client_id_metadata_document_supported`.\n\t */\n\tclientMetadataDocument?(metadata: AuthorizationServerMetadata | undefined): OAuthClientMetadataDocument | undefined;\n\tstate?(): string | Promise<string>;\n\tclientInformation(): OAuthClientInformationMixed | undefined | Promise<OAuthClientInformationMixed | undefined>;\n\tsaveClientInformation?(information: OAuthClientInformationMixed): void | Promise<void>;\n\ttokens(): OAuthTokens | undefined | Promise<OAuthTokens | undefined>;\n\tsaveTokens(tokens: OAuthTokens): void | Promise<void>;\n\tredirectToAuthorization(url: URL): void | Promise<void>;\n\tsaveCodeVerifier(verifier: string): void | Promise<void>;\n\tcodeVerifier(): string | Promise<string>;\n\taddClientAuthentication?: AddClientAuthentication;\n\tinvalidateCredentials?(kind: \"all\" | \"client\" | \"tokens\" | \"verifier\" | \"discovery\"): void | Promise<void>;\n\tsaveDiscoveryState?(state: OAuthDiscoveryState): void | Promise<void>;\n\tdiscoveryState?(): OAuthDiscoveryState | undefined | Promise<OAuthDiscoveryState | undefined>;\n}\n\nexport interface OAuthFlowOptions {\n\tserverUrl: string | URL;\n\tauthorizationCode?: string;\n\t/** `iss` parameter of the authorization response that delivered `authorizationCode` (RFC 9207). */\n\tiss?: string;\n\tscope?: string;\n\tresourceMetadataUrl?: URL;\n\t/**\n\t * Authorization server metadata document to use instead of discovery, for servers that advertise a\n\t * wrong authorization server or none. It is trusted as configured. Must use https, except on loopback.\n\t */\n\tauthorizationServerMetadataUrl?: URL;\n\tfetch?: McpFetch;\n\tskipIssuerValidation?: boolean;\n\t/**\n\t * Go straight to the authorization redirect instead of refreshing stored tokens, for example when the\n\t * server asks for scopes the current grant lacks (a refresh keeps the old scope).\n\t */\n\tskipRefresh?: boolean;\n}\n\nexport type OAuthFlowResult = \"AUTHORIZED\" | \"REDIRECT\";\ntype ClientAuthMethod = \"client_secret_basic\" | \"client_secret_post\" | \"none\";\n\nexport interface TokenRequestOptions {\n\tmetadata?: AuthorizationServerMetadata;\n\tclientInformation: OAuthClientInformationMixed;\n\tresource?: string;\n\taddClientAuthentication?: AddClientAuthentication;\n\tfetch?: McpFetch;\n}\n\nfunction loopback(hostname: string): boolean {\n\treturn hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"[::1]\" || hostname === \"::1\";\n}\n\n/**\n * The OpenID Connect `application_type` for `redirect_uris` (MCP SEP-837). Without one, OpenID Connect servers\n * assume `web`, which rejects http loopback redirect URIs. Loopback hosts and custom schemes are native (RFC 8252).\n */\nfunction applicationType(redirectUris: readonly string[]): \"native\" | \"web\" {\n\tconst native = redirectUris.some((uri) => {\n\t\tif (!URL.canParse(uri)) return false;\n\t\tconst url = new URL(uri);\n\t\treturn (url.protocol !== \"http:\" && url.protocol !== \"https:\") || loopback(url.hostname);\n\t});\n\treturn native ? \"native\" : \"web\";\n}\n\nfunction secureEndpoint(value: string | URL): URL {\n\tconst url = new URL(value);\n\tif (url.protocol !== \"https:\" && !loopback(url.hostname)) throw new OAuthInsecureEndpointError(url.href);\n\treturn url;\n}\n\nfunction selectClientAuthMethod(information: OAuthClientInformationMixed, supported: string[]): ClientAuthMethod {\n\tconst hinted = \"token_endpoint_auth_method\" in information ? information.token_endpoint_auth_method : undefined;\n\tif (\n\t\thinted &&\n\t\t[\"client_secret_basic\", \"client_secret_post\", \"none\"].includes(hinted) &&\n\t\t(supported.length === 0 || supported.includes(hinted))\n\t) {\n\t\treturn hinted as ClientAuthMethod;\n\t}\n\tif (supported.length === 0) return information.client_secret ? \"client_secret_basic\" : \"none\";\n\tif (information.client_secret && supported.includes(\"client_secret_basic\")) return \"client_secret_basic\";\n\tif (information.client_secret && supported.includes(\"client_secret_post\")) return \"client_secret_post\";\n\tif (supported.includes(\"none\")) return \"none\";\n\treturn information.client_secret ? \"client_secret_post\" : \"none\";\n}\n\nfunction applyClientAuthentication(\n\tmethod: ClientAuthMethod,\n\tinformation: OAuthClientInformation,\n\theaders: Headers,\n\tparams: URLSearchParams,\n): void {\n\tif (method === \"client_secret_basic\") {\n\t\tif (!information.client_secret) throw new Error(\"client_secret_basic requires a client secret\");\n\t\theaders.set(\n\t\t\t\"Authorization\",\n\t\t\t`Basic ${Buffer.from(`${information.client_id}:${information.client_secret}`).toString(\"base64\")}`,\n\t\t);\n\t} else {\n\t\tparams.set(\"client_id\", information.client_id);\n\t\tif (method === \"client_secret_post\" && information.client_secret)\n\t\t\tparams.set(\"client_secret\", information.client_secret);\n\t}\n}\n\nasync function pkce(): Promise<{ verifier: string; challenge: string }> {\n\tconst bytes = crypto.getRandomValues(new Uint8Array(32));\n\tconst verifier = Buffer.from(bytes).toString(\"base64url\");\n\tconst digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(verifier));\n\treturn { verifier, challenge: Buffer.from(digest).toString(\"base64url\") };\n}\n\nexport async function startAuthorization(\n\tauthorizationServerUrl: string | URL,\n\toptions: {\n\t\tmetadata?: AuthorizationServerMetadata;\n\t\tclientInformation: OAuthClientInformationMixed;\n\t\tredirectUrl: string | URL;\n\t\tscope?: string;\n\t\tstate?: string;\n\t\tresource?: string;\n\t},\n): Promise<{ authorizationUrl: URL; codeVerifier: string }> {\n\tconst metadata = options.metadata;\n\tif (metadata && !metadata.response_types_supported.includes(\"code\")) {\n\t\tthrow new Error(\"Authorization server does not support authorization codes\");\n\t}\n\tif (metadata?.code_challenge_methods_supported && !metadata.code_challenge_methods_supported.includes(\"S256\")) {\n\t\tthrow new Error(\"Authorization server does not support PKCE S256\");\n\t}\n\tconst url = new URL(metadata?.authorization_endpoint ?? new URL(\"/authorize\", authorizationServerUrl));\n\tconst { verifier, challenge } = await pkce();\n\turl.searchParams.set(\"response_type\", \"code\");\n\turl.searchParams.set(\"client_id\", options.clientInformation.client_id);\n\turl.searchParams.set(\"code_challenge\", challenge);\n\turl.searchParams.set(\"code_challenge_method\", \"S256\");\n\turl.searchParams.set(\"redirect_uri\", String(options.redirectUrl));\n\tif (options.state) url.searchParams.set(\"state\", options.state);\n\tif (options.scope) url.searchParams.set(\"scope\", options.scope);\n\tif (options.scope?.split(/\\s+/).includes(\"offline_access\")) url.searchParams.set(\"prompt\", \"consent\");\n\tif (options.resource) url.searchParams.set(\"resource\", options.resource);\n\treturn { authorizationUrl: url, codeVerifier: verifier };\n}\n\nasync function tokenRequest(\n\tauthorizationServerUrl: string | URL,\n\toptions: TokenRequestOptions,\n\tparams: URLSearchParams,\n): Promise<OAuthTokens> {\n\tconst url = secureEndpoint(options.metadata?.token_endpoint ?? new URL(\"/token\", authorizationServerUrl));\n\tconst headers = new Headers({ Accept: \"application/json\", \"content-type\": \"application/x-www-form-urlencoded\" });\n\tif (options.resource) params.set(\"resource\", options.resource);\n\tif (options.addClientAuthentication) {\n\t\tawait options.addClientAuthentication(headers, params, url, options.metadata);\n\t} else {\n\t\tapplyClientAuthentication(\n\t\t\tselectClientAuthMethod(\n\t\t\t\toptions.clientInformation,\n\t\t\t\toptions.metadata?.token_endpoint_auth_methods_supported ?? [],\n\t\t\t),\n\t\t\toptions.clientInformation,\n\t\t\theaders,\n\t\t\tparams,\n\t\t);\n\t}\n\tconst response = await (options.fetch ?? globalThis.fetch)(url, { method: \"POST\", headers, body: params });\n\tconst text = await response.text();\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(text);\n\t} catch {}\n\t// Servers may report OAuth errors with any status, so check the body before the status.\n\tif (isObject(value) && typeof value.error === \"string\") {\n\t\tthrow new OAuthError(\n\t\t\tvalue.error,\n\t\t\ttypeof value.error_description === \"string\" ? value.error_description : value.error,\n\t\t\ttypeof value.error_uri === \"string\" ? value.error_uri : undefined,\n\t\t);\n\t}\n\tif (!response.ok) throw new OAuthError(\"server_error\", `HTTP ${response.status}: ${text}`);\n\treturn parseOAuthTokens(value);\n}\n\nexport async function registerClient(\n\tauthorizationServerUrl: string | URL,\n\toptions: {\n\t\tmetadata?: AuthorizationServerMetadata;\n\t\tclientMetadata: OAuthClientMetadata;\n\t\tscope?: string;\n\t\tfetch?: McpFetch;\n\t},\n): Promise<OAuthClientInformationFull> {\n\tconst endpoint = options.metadata?.registration_endpoint;\n\tif (options.metadata && !endpoint)\n\t\tthrow new Error(\"Authorization server does not support dynamic client registration\");\n\tconst response = await (options.fetch ?? globalThis.fetch)(\n\t\tnew URL(endpoint ?? new URL(\"/register\", authorizationServerUrl)),\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Accept: \"application/json\", \"content-type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\t...options.clientMetadata,\n\t\t\t\tapplication_type:\n\t\t\t\t\toptions.clientMetadata.application_type ?? applicationType(options.clientMetadata.redirect_uris),\n\t\t\t\t...(options.scope ? { scope: options.scope } : {}),\n\t\t\t}),\n\t\t},\n\t);\n\tif (!response.ok) throw new OAuthRegistrationError(response.status, await response.text());\n\treturn parseClientInformation(await response.json());\n}\n\nexport async function exchangeAuthorizationCode(\n\tauthorizationServerUrl: string | URL,\n\toptions: TokenRequestOptions & { code: string; codeVerifier: string; redirectUrl: string | URL },\n): Promise<OAuthTokens> {\n\treturn tokenRequest(\n\t\tauthorizationServerUrl,\n\t\toptions,\n\t\tnew URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tcode: options.code,\n\t\t\tcode_verifier: options.codeVerifier,\n\t\t\tredirect_uri: String(options.redirectUrl),\n\t\t}),\n\t);\n}\n\nexport async function refreshAuthorization(\n\tauthorizationServerUrl: string | URL,\n\toptions: TokenRequestOptions & { refreshToken: string },\n): Promise<OAuthTokens> {\n\tconst tokens = await tokenRequest(\n\t\tauthorizationServerUrl,\n\t\toptions,\n\t\tnew URLSearchParams({ grant_type: \"refresh_token\", refresh_token: options.refreshToken }),\n\t);\n\treturn { refresh_token: options.refreshToken, ...tokens };\n}\n\nfunction withScope(tokens: OAuthTokens, scope: string | undefined): OAuthTokens {\n\treturn tokens.scope === undefined && scope ? { ...tokens, scope } : tokens;\n}\n\n/**\n * Scopes for a step-up authorization: the challenged scopes plus the ones granted so far, since a\n * challenge may list only the missing scopes and a token with just those would lose access the old\n * one had (SEP-2350). Without challenged scopes, `undefined` lets the flow pick its default.\n */\nexport function stepUpScope(granted: string | undefined, challenged: string | undefined): string | undefined {\n\tif (!challenged) return undefined;\n\tconst scopes = [granted, challenged].flatMap((scope) => scope?.split(/\\s+/).filter(Boolean) ?? []);\n\treturn [...new Set(scopes)].join(\" \");\n}\n\nasync function runFlow(provider: OAuthClientProvider, options: OAuthFlowOptions): Promise<OAuthFlowResult> {\n\tconst metadataUrl = options.authorizationServerMetadataUrl && secureEndpoint(options.authorizationServerMetadataUrl);\n\t// With a configured metadata URL, discovery is not cached, so changing the URL applies at once.\n\tconst cached = metadataUrl ? undefined : await provider.discoveryState?.();\n\tconst discovered = cached?.authorizationServerUrl\n\t\t? {\n\t\t\t\tauthorizationServerUrl: cached.authorizationServerUrl,\n\t\t\t\tauthorizationServerMetadata:\n\t\t\t\t\tcached.authorizationServerMetadata ??\n\t\t\t\t\t(await discoverAuthorizationServerMetadata(cached.authorizationServerUrl, {\n\t\t\t\t\t\tfetch: options.fetch,\n\t\t\t\t\t\tskipIssuerValidation: options.skipIssuerValidation,\n\t\t\t\t\t})),\n\t\t\t\tresourceMetadata: cached.resourceMetadata,\n\t\t\t}\n\t\t: await discoverOAuthServerInfo(options.serverUrl, {\n\t\t\t\tresourceMetadataUrl: options.resourceMetadataUrl,\n\t\t\t\tauthorizationServerMetadataUrl: metadataUrl,\n\t\t\t\tfetch: options.fetch,\n\t\t\t\tskipIssuerValidation: options.skipIssuerValidation,\n\t\t\t});\n\tif (!metadataUrl) {\n\t\tawait provider.saveDiscoveryState?.({\n\t\t\t...discovered,\n\t\t\t...(options.resourceMetadataUrl ? { resourceMetadataUrl: options.resourceMetadataUrl.href } : {}),\n\t\t});\n\t}\n\tconst metadata = discovered.authorizationServerMetadata;\n\tconst resource = selectResource(options.serverUrl, discovered.resourceMetadata);\n\t// `||`, not `??`: an empty scope (for example from `scopes_supported: []`) falls through to the next source.\n\tconst scope =\n\t\toptions.scope || discovered.resourceMetadata?.scopes_supported?.join(\" \") || provider.clientMetadata.scope;\n\tconst stored = await provider.clientInformation();\n\tconst clientDocument = stored ? undefined : provider.clientMetadataDocument?.(metadata);\n\tif (clientDocument) {\n\t\tconst url = new URL(clientDocument.url);\n\t\tif (url.protocol !== \"https:\" || url.pathname === \"/\") throw new Error(\"Invalid OAuth client metadata URL\");\n\t}\n\tlet client = stored ?? (clientDocument && { client_id: clientDocument.url });\n\tif (!client) {\n\t\tif (options.authorizationCode) throw new Error(\"OAuth client information is missing during code exchange\");\n\t\tif (!provider.saveClientInformation) throw new Error(\"OAuth client information cannot be persisted\");\n\t\tclient = await registerClient(discovered.authorizationServerUrl, {\n\t\t\tmetadata,\n\t\t\tclientMetadata: provider.clientMetadata,\n\t\t\tscope,\n\t\t\tfetch: options.fetch,\n\t\t});\n\t\tawait provider.saveClientInformation(client);\n\t}\n\t// The document's redirect URI may differ from the provider's, for example by a server-specific path.\n\tconst redirectUrl = clientDocument?.redirectUrl ?? provider.redirectUrl;\n\tconst tokenOptions: TokenRequestOptions = {\n\t\tmetadata,\n\t\tclientInformation: client,\n\t\tresource,\n\t\taddClientAuthentication: provider.addClientAuthentication,\n\t\tfetch: options.fetch,\n\t};\n\tif (options.authorizationCode) {\n\t\t// RFC 9207: never send a code from another authorization server to this one.\n\t\tconst iss = options.iss;\n\t\tif (metadata && (iss !== undefined || metadata.authorization_response_iss_parameter_supported)) {\n\t\t\tif (iss !== metadata.issuer) throw new OAuthIssuerMismatchError(metadata.issuer, iss);\n\t\t}\n\t\tconst tokens = await exchangeAuthorizationCode(discovered.authorizationServerUrl, {\n\t\t\t...tokenOptions,\n\t\t\tcode: options.authorizationCode,\n\t\t\tcodeVerifier: await provider.codeVerifier(),\n\t\t\tredirectUrl,\n\t\t});\n\t\t// A response without `scope` grants the requested scope (RFC 6749 §5.1). Recorded so a step-up can\n\t\t// keep it. Callers pass the options of the authorization request, so `scope` is what was requested.\n\t\tawait provider.saveTokens(withScope(tokens, scope));\n\t\treturn \"AUTHORIZED\";\n\t}\n\tconst existing = options.skipRefresh ? undefined : await provider.tokens();\n\tif (existing?.refresh_token) {\n\t\ttry {\n\t\t\tconst tokens = await refreshAuthorization(discovered.authorizationServerUrl, {\n\t\t\t\t...tokenOptions,\n\t\t\t\trefreshToken: existing.refresh_token,\n\t\t\t});\n\t\t\t// A refresh without `scope` keeps the scope of the grant (RFC 6749 §6).\n\t\t\tawait provider.saveTokens(withScope(tokens, existing.scope));\n\t\t\treturn \"AUTHORIZED\";\n\t\t} catch (error) {\n\t\t\tif (error instanceof OAuthInsecureEndpointError) throw error;\n\t\t\tif (error instanceof OAuthError && error.code !== \"server_error\") throw error;\n\t\t}\n\t}\n\tconst state = await provider.state?.();\n\tconst authorization = await startAuthorization(discovered.authorizationServerUrl, {\n\t\tmetadata,\n\t\tclientInformation: client,\n\t\tredirectUrl,\n\t\tscope,\n\t\tstate,\n\t\tresource,\n\t});\n\tawait provider.saveCodeVerifier(authorization.codeVerifier);\n\tawait provider.redirectToAuthorization(authorization.authorizationUrl);\n\treturn \"REDIRECT\";\n}\n\nexport async function authorizeMcp(provider: OAuthClientProvider, options: OAuthFlowOptions): Promise<OAuthFlowResult> {\n\ttry {\n\t\treturn await runFlow(provider, options);\n\t} catch (error) {\n\t\tif (error instanceof OAuthError && [\"invalid_client\", \"unauthorized_client\"].includes(error.code)) {\n\t\t\tawait provider.invalidateCredentials?.(\"all\");\n\t\t\treturn runFlow(provider, options);\n\t\t}\n\t\tif (error instanceof OAuthError && error.code === \"invalid_grant\") {\n\t\t\tawait provider.invalidateCredentials?.(\"tokens\");\n\t\t\treturn runFlow(provider, options);\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Auth provider for `StreamableHttpTransport`. After a 401 it refreshes the tokens, or throws\n * `McpOAuthAuthorizationRequiredError` when the user has to authorize (again). Concurrent 401s share\n * one refresh, and a request whose token was already replaced is just retried: with rotating refresh\n * tokens, a second refresh with the old refresh token would fail and discard the new grant.\n */\nexport function adaptOAuthProvider(provider: OAuthClientProvider): AuthProvider {\n\tlet inFlight: Promise<void> | undefined;\n\treturn {\n\t\ttoken: async () => (await provider.tokens())?.access_token,\n\t\tonUnauthorized: async (context: UnauthorizedContext) => {\n\t\t\tconst challenge = parseWwwAuthenticate(context.response.headers.get(\"www-authenticate\"));\n\t\t\tconst insufficientScope = challenge.error === \"insufficient_scope\";\n\t\t\tif (!insufficientScope && !inFlight && context.token !== undefined) {\n\t\t\t\tconst current = (await provider.tokens())?.access_token;\n\t\t\t\tif (current !== undefined && current !== context.token) return;\n\t\t\t}\n\t\t\tinFlight ??= Promise.resolve(insufficientScope ? provider.tokens() : undefined)\n\t\t\t\t.then((granted) =>\n\t\t\t\t\tauthorizeMcp(provider, {\n\t\t\t\t\t\tserverUrl: context.serverUrl,\n\t\t\t\t\t\tresourceMetadataUrl: challenge.resourceMetadataUrl,\n\t\t\t\t\t\tscope: insufficientScope ? stepUpScope(granted?.scope, challenge.scope) : challenge.scope,\n\t\t\t\t\t\tfetch: context.fetch,\n\t\t\t\t\t\tskipRefresh: insufficientScope,\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.then((result) => {\n\t\t\t\t\tif (result === \"REDIRECT\") throw new McpOAuthAuthorizationRequiredError();\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tinFlight = undefined;\n\t\t\t\t});\n\t\t\tawait inFlight;\n\t\t},\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/oauth/flow.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Adapted from modelcontextprotocol/typescript-sdk v1.29.0 src/client/auth.ts.\n * Copyright (c) 2024 Anthropic, PBC. Licensed under MIT; see LICENSES/.\n * Modified to remove SDK/Zod dependencies and use WebCrypto for PKCE.\n */\n\nimport type { AuthProvider, McpFetch, UnauthorizedContext } from \"../auth-provider.ts\";\nimport { isObject } from \"../protocol/jsonrpc.ts\";\nimport {\n\tdiscoverAuthorizationServerMetadata,\n\tdiscoverOAuthServerInfo,\n\tparseWwwAuthenticate,\n\tselectResource,\n} from \"./discovery.ts\";\nimport {\n\tMcpOAuthAuthorizationRequiredError,\n\tOAuthError,\n\tOAuthInsecureEndpointError,\n\tOAuthIssuerMismatchError,\n\tOAuthRegistrationError,\n} from \"./errors.ts\";\nimport {\n\ttype AuthorizationServerMetadata,\n\ttype OAuthClientInformation,\n\ttype OAuthClientInformationFull,\n\ttype OAuthClientInformationMixed,\n\ttype OAuthClientMetadata,\n\ttype OAuthDiscoveryState,\n\ttype OAuthTokens,\n\tparseClientInformation,\n\tparseOAuthTokens,\n} from \"./types.ts\";\n\nexport type AddClientAuthentication = (\n\theaders: Headers,\n\tparams: URLSearchParams,\n\turl: string | URL,\n\tmetadata?: AuthorizationServerMetadata,\n) => void | Promise<void>;\n\n/** A Client ID Metadata Document: an https URL used as `client_id`, and a redirect URI it lists. */\nexport interface OAuthClientMetadataDocument {\n\turl: string;\n\tredirectUrl: string;\n}\n\nexport interface OAuthClientProvider {\n\treadonly redirectUrl: string | URL;\n\treadonly clientMetadata: OAuthClientMetadata;\n\t/**\n\t * Client ID Metadata Document to identify as instead of registering dynamically, or `undefined` to\n\t * register. Called when no client information is stored; the document is not stored. `metadata` is\n\t * `undefined` when the authorization server has none; check `client_id_metadata_document_supported`.\n\t */\n\tclientMetadataDocument?(metadata: AuthorizationServerMetadata | undefined): OAuthClientMetadataDocument | undefined;\n\tstate?(): string | Promise<string>;\n\tclientInformation(): OAuthClientInformationMixed | undefined | Promise<OAuthClientInformationMixed | undefined>;\n\tsaveClientInformation?(information: OAuthClientInformationMixed): void | Promise<void>;\n\ttokens(): OAuthTokens | undefined | Promise<OAuthTokens | undefined>;\n\tsaveTokens(tokens: OAuthTokens): void | Promise<void>;\n\tredirectToAuthorization(url: URL): void | Promise<void>;\n\tsaveCodeVerifier(verifier: string): void | Promise<void>;\n\tcodeVerifier(): string | Promise<string>;\n\taddClientAuthentication?: AddClientAuthentication;\n\tinvalidateCredentials?(kind: \"all\" | \"client\" | \"tokens\" | \"verifier\" | \"discovery\"): void | Promise<void>;\n\tsaveDiscoveryState?(state: OAuthDiscoveryState): void | Promise<void>;\n\tdiscoveryState?(): OAuthDiscoveryState | undefined | Promise<OAuthDiscoveryState | undefined>;\n}\n\nexport interface OAuthFlowOptions {\n\tserverUrl: string | URL;\n\tauthorizationCode?: string;\n\t/** `iss` parameter of the authorization response that delivered `authorizationCode` (RFC 9207). */\n\tiss?: string;\n\tscope?: string;\n\tresourceMetadataUrl?: URL;\n\t/**\n\t * Authorization server metadata document to use instead of discovery, for servers that advertise a\n\t * wrong authorization server or none. It is trusted as configured. Must use https, except on loopback.\n\t */\n\tauthorizationServerMetadataUrl?: URL;\n\tfetch?: McpFetch;\n\t/** Aborts every request of the flow. Requests have no time limit of their own; combine with a timeout as needed. */\n\tsignal?: AbortSignal;\n\tskipIssuerValidation?: boolean;\n\t/**\n\t * Go straight to the authorization redirect instead of refreshing stored tokens, for example when the\n\t * server asks for scopes the current grant lacks (a refresh keeps the old scope).\n\t */\n\tskipRefresh?: boolean;\n}\n\nexport type OAuthFlowResult = \"AUTHORIZED\" | \"REDIRECT\";\ntype ClientAuthMethod = \"client_secret_basic\" | \"client_secret_post\" | \"none\";\n\nexport interface TokenRequestOptions {\n\tmetadata?: AuthorizationServerMetadata;\n\tclientInformation: OAuthClientInformationMixed;\n\tresource?: string;\n\taddClientAuthentication?: AddClientAuthentication;\n\tfetch?: McpFetch;\n\tsignal?: AbortSignal;\n}\n\nfunction loopback(hostname: string): boolean {\n\treturn hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"[::1]\" || hostname === \"::1\";\n}\n\n/**\n * The OpenID Connect `application_type` for `redirect_uris` (MCP SEP-837). Without one, OpenID Connect servers\n * assume `web`, which rejects http loopback redirect URIs. Loopback hosts and custom schemes are native (RFC 8252).\n */\nfunction applicationType(redirectUris: readonly string[]): \"native\" | \"web\" {\n\tconst native = redirectUris.some((uri) => {\n\t\tif (!URL.canParse(uri)) return false;\n\t\tconst url = new URL(uri);\n\t\treturn (url.protocol !== \"http:\" && url.protocol !== \"https:\") || loopback(url.hostname);\n\t});\n\treturn native ? \"native\" : \"web\";\n}\n\nfunction secureEndpoint(value: string | URL): URL {\n\tconst url = new URL(value);\n\tif (url.protocol !== \"https:\" && !loopback(url.hostname)) throw new OAuthInsecureEndpointError(url.href);\n\treturn url;\n}\n\nfunction selectClientAuthMethod(information: OAuthClientInformationMixed, supported: string[]): ClientAuthMethod {\n\tconst hinted = \"token_endpoint_auth_method\" in information ? information.token_endpoint_auth_method : undefined;\n\tif (\n\t\thinted &&\n\t\t[\"client_secret_basic\", \"client_secret_post\", \"none\"].includes(hinted) &&\n\t\t(supported.length === 0 || supported.includes(hinted))\n\t) {\n\t\treturn hinted as ClientAuthMethod;\n\t}\n\tif (supported.length === 0) return information.client_secret ? \"client_secret_basic\" : \"none\";\n\tif (information.client_secret && supported.includes(\"client_secret_basic\")) return \"client_secret_basic\";\n\tif (information.client_secret && supported.includes(\"client_secret_post\")) return \"client_secret_post\";\n\tif (supported.includes(\"none\")) return \"none\";\n\treturn information.client_secret ? \"client_secret_post\" : \"none\";\n}\n\nfunction applyClientAuthentication(\n\tmethod: ClientAuthMethod,\n\tinformation: OAuthClientInformation,\n\theaders: Headers,\n\tparams: URLSearchParams,\n): void {\n\tif (method === \"client_secret_basic\") {\n\t\tif (!information.client_secret) throw new Error(\"client_secret_basic requires a client secret\");\n\t\theaders.set(\n\t\t\t\"Authorization\",\n\t\t\t`Basic ${Buffer.from(`${information.client_id}:${information.client_secret}`).toString(\"base64\")}`,\n\t\t);\n\t} else {\n\t\tparams.set(\"client_id\", information.client_id);\n\t\tif (method === \"client_secret_post\" && information.client_secret)\n\t\t\tparams.set(\"client_secret\", information.client_secret);\n\t}\n}\n\nasync function pkce(): Promise<{ verifier: string; challenge: string }> {\n\tconst bytes = crypto.getRandomValues(new Uint8Array(32));\n\tconst verifier = Buffer.from(bytes).toString(\"base64url\");\n\tconst digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(verifier));\n\treturn { verifier, challenge: Buffer.from(digest).toString(\"base64url\") };\n}\n\nexport async function startAuthorization(\n\tauthorizationServerUrl: string | URL,\n\toptions: {\n\t\tmetadata?: AuthorizationServerMetadata;\n\t\tclientInformation: OAuthClientInformationMixed;\n\t\tredirectUrl: string | URL;\n\t\tscope?: string;\n\t\tstate?: string;\n\t\tresource?: string;\n\t},\n): Promise<{ authorizationUrl: URL; codeVerifier: string }> {\n\tconst metadata = options.metadata;\n\tif (metadata && !metadata.response_types_supported.includes(\"code\")) {\n\t\tthrow new Error(\"Authorization server does not support authorization codes\");\n\t}\n\tif (metadata?.code_challenge_methods_supported && !metadata.code_challenge_methods_supported.includes(\"S256\")) {\n\t\tthrow new Error(\"Authorization server does not support PKCE S256\");\n\t}\n\tconst url = new URL(metadata?.authorization_endpoint ?? new URL(\"/authorize\", authorizationServerUrl));\n\tconst { verifier, challenge } = await pkce();\n\turl.searchParams.set(\"response_type\", \"code\");\n\turl.searchParams.set(\"client_id\", options.clientInformation.client_id);\n\turl.searchParams.set(\"code_challenge\", challenge);\n\turl.searchParams.set(\"code_challenge_method\", \"S256\");\n\turl.searchParams.set(\"redirect_uri\", String(options.redirectUrl));\n\tif (options.state) url.searchParams.set(\"state\", options.state);\n\tif (options.scope) url.searchParams.set(\"scope\", options.scope);\n\tif (options.scope?.split(/\\s+/).includes(\"offline_access\")) url.searchParams.set(\"prompt\", \"consent\");\n\tif (options.resource) url.searchParams.set(\"resource\", options.resource);\n\treturn { authorizationUrl: url, codeVerifier: verifier };\n}\n\nasync function tokenRequest(\n\tauthorizationServerUrl: string | URL,\n\toptions: TokenRequestOptions,\n\tparams: URLSearchParams,\n): Promise<OAuthTokens> {\n\tconst url = secureEndpoint(options.metadata?.token_endpoint ?? new URL(\"/token\", authorizationServerUrl));\n\tconst headers = new Headers({ Accept: \"application/json\", \"content-type\": \"application/x-www-form-urlencoded\" });\n\tif (options.resource) params.set(\"resource\", options.resource);\n\tif (options.addClientAuthentication) {\n\t\tawait options.addClientAuthentication(headers, params, url, options.metadata);\n\t} else {\n\t\tapplyClientAuthentication(\n\t\t\tselectClientAuthMethod(\n\t\t\t\toptions.clientInformation,\n\t\t\t\toptions.metadata?.token_endpoint_auth_methods_supported ?? [],\n\t\t\t),\n\t\t\toptions.clientInformation,\n\t\t\theaders,\n\t\t\tparams,\n\t\t);\n\t}\n\tconst response = await (options.fetch ?? globalThis.fetch)(url, {\n\t\tmethod: \"POST\",\n\t\theaders,\n\t\tbody: params,\n\t\tsignal: options.signal,\n\t});\n\tconst text = await response.text();\n\tlet value: unknown;\n\ttry {\n\t\tvalue = JSON.parse(text);\n\t} catch {}\n\t// Servers may report OAuth errors with any status, so check the body before the status.\n\tif (isObject(value) && typeof value.error === \"string\") {\n\t\tthrow new OAuthError(\n\t\t\tvalue.error,\n\t\t\ttypeof value.error_description === \"string\" ? value.error_description : value.error,\n\t\t\ttypeof value.error_uri === \"string\" ? value.error_uri : undefined,\n\t\t);\n\t}\n\tif (!response.ok) throw new OAuthError(\"server_error\", `HTTP ${response.status}: ${text}`);\n\treturn parseOAuthTokens(value);\n}\n\nexport async function registerClient(\n\tauthorizationServerUrl: string | URL,\n\toptions: {\n\t\tmetadata?: AuthorizationServerMetadata;\n\t\tclientMetadata: OAuthClientMetadata;\n\t\tscope?: string;\n\t\tfetch?: McpFetch;\n\t\tsignal?: AbortSignal;\n\t},\n): Promise<OAuthClientInformationFull> {\n\tconst endpoint = options.metadata?.registration_endpoint;\n\tif (options.metadata && !endpoint)\n\t\tthrow new Error(\"Authorization server does not support dynamic client registration\");\n\tconst response = await (options.fetch ?? globalThis.fetch)(\n\t\tnew URL(endpoint ?? new URL(\"/register\", authorizationServerUrl)),\n\t\t{\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Accept: \"application/json\", \"content-type\": \"application/json\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\t...options.clientMetadata,\n\t\t\t\tapplication_type:\n\t\t\t\t\toptions.clientMetadata.application_type ?? applicationType(options.clientMetadata.redirect_uris),\n\t\t\t\t...(options.scope ? { scope: options.scope } : {}),\n\t\t\t}),\n\t\t\tsignal: options.signal,\n\t\t},\n\t);\n\tif (!response.ok) throw new OAuthRegistrationError(response.status, await response.text());\n\treturn parseClientInformation(await response.json());\n}\n\nexport async function exchangeAuthorizationCode(\n\tauthorizationServerUrl: string | URL,\n\toptions: TokenRequestOptions & { code: string; codeVerifier: string; redirectUrl: string | URL },\n): Promise<OAuthTokens> {\n\treturn tokenRequest(\n\t\tauthorizationServerUrl,\n\t\toptions,\n\t\tnew URLSearchParams({\n\t\t\tgrant_type: \"authorization_code\",\n\t\t\tcode: options.code,\n\t\t\tcode_verifier: options.codeVerifier,\n\t\t\tredirect_uri: String(options.redirectUrl),\n\t\t}),\n\t);\n}\n\nexport async function refreshAuthorization(\n\tauthorizationServerUrl: string | URL,\n\toptions: TokenRequestOptions & { refreshToken: string },\n): Promise<OAuthTokens> {\n\tconst tokens = await tokenRequest(\n\t\tauthorizationServerUrl,\n\t\toptions,\n\t\tnew URLSearchParams({ grant_type: \"refresh_token\", refresh_token: options.refreshToken }),\n\t);\n\treturn { refresh_token: options.refreshToken, ...tokens };\n}\n\nfunction withScope(tokens: OAuthTokens, scope: string | undefined): OAuthTokens {\n\treturn tokens.scope === undefined && scope ? { ...tokens, scope } : tokens;\n}\n\n/**\n * Scopes for a step-up authorization: the challenged scopes plus the ones granted so far, since a\n * challenge may list only the missing scopes and a token with just those would lose access the old\n * one had (SEP-2350). Without challenged scopes, `undefined` lets the flow pick its default.\n */\nexport function stepUpScope(granted: string | undefined, challenged: string | undefined): string | undefined {\n\tif (!challenged) return undefined;\n\tconst scopes = [granted, challenged].flatMap((scope) => scope?.split(/\\s+/).filter(Boolean) ?? []);\n\treturn [...new Set(scopes)].join(\" \");\n}\n\nasync function runFlow(provider: OAuthClientProvider, options: OAuthFlowOptions): Promise<OAuthFlowResult> {\n\tconst metadataUrl = options.authorizationServerMetadataUrl && secureEndpoint(options.authorizationServerMetadataUrl);\n\t// With a configured metadata URL, discovery is not cached, so changing the URL applies at once.\n\tconst cached = metadataUrl ? undefined : await provider.discoveryState?.();\n\tconst discovered = cached?.authorizationServerUrl\n\t\t? {\n\t\t\t\tauthorizationServerUrl: cached.authorizationServerUrl,\n\t\t\t\tauthorizationServerMetadata:\n\t\t\t\t\tcached.authorizationServerMetadata ??\n\t\t\t\t\t(await discoverAuthorizationServerMetadata(cached.authorizationServerUrl, {\n\t\t\t\t\t\tfetch: options.fetch,\n\t\t\t\t\t\tskipIssuerValidation: options.skipIssuerValidation,\n\t\t\t\t\t\tsignal: options.signal,\n\t\t\t\t\t})),\n\t\t\t\tresourceMetadata: cached.resourceMetadata,\n\t\t\t}\n\t\t: await discoverOAuthServerInfo(options.serverUrl, {\n\t\t\t\tresourceMetadataUrl: options.resourceMetadataUrl,\n\t\t\t\tauthorizationServerMetadataUrl: metadataUrl,\n\t\t\t\tfetch: options.fetch,\n\t\t\t\tskipIssuerValidation: options.skipIssuerValidation,\n\t\t\t\tsignal: options.signal,\n\t\t\t});\n\tif (!metadataUrl) {\n\t\tawait provider.saveDiscoveryState?.({\n\t\t\t...discovered,\n\t\t\t...(options.resourceMetadataUrl ? { resourceMetadataUrl: options.resourceMetadataUrl.href } : {}),\n\t\t});\n\t}\n\tconst metadata = discovered.authorizationServerMetadata;\n\tconst resource = selectResource(options.serverUrl, discovered.resourceMetadata);\n\t// `||`, not `??`: an empty scope (for example from `scopes_supported: []`) falls through to the next source.\n\tconst scope =\n\t\toptions.scope || discovered.resourceMetadata?.scopes_supported?.join(\" \") || provider.clientMetadata.scope;\n\tconst stored = await provider.clientInformation();\n\tconst clientDocument = stored ? undefined : provider.clientMetadataDocument?.(metadata);\n\tif (clientDocument) {\n\t\tconst url = new URL(clientDocument.url);\n\t\tif (url.protocol !== \"https:\" || url.pathname === \"/\") throw new Error(\"Invalid OAuth client metadata URL\");\n\t}\n\tlet client = stored ?? (clientDocument && { client_id: clientDocument.url });\n\tif (!client) {\n\t\tif (options.authorizationCode) throw new Error(\"OAuth client information is missing during code exchange\");\n\t\tif (!provider.saveClientInformation) throw new Error(\"OAuth client information cannot be persisted\");\n\t\tclient = await registerClient(discovered.authorizationServerUrl, {\n\t\t\tmetadata,\n\t\t\tclientMetadata: provider.clientMetadata,\n\t\t\tscope,\n\t\t\tfetch: options.fetch,\n\t\t\tsignal: options.signal,\n\t\t});\n\t\tawait provider.saveClientInformation(client);\n\t}\n\t// The document's redirect URI may differ from the provider's, for example by a server-specific path.\n\tconst redirectUrl = clientDocument?.redirectUrl ?? provider.redirectUrl;\n\tconst tokenOptions: TokenRequestOptions = {\n\t\tmetadata,\n\t\tclientInformation: client,\n\t\tresource,\n\t\taddClientAuthentication: provider.addClientAuthentication,\n\t\tfetch: options.fetch,\n\t\tsignal: options.signal,\n\t};\n\tif (options.authorizationCode) {\n\t\t// RFC 9207: never send a code from another authorization server to this one.\n\t\tconst iss = options.iss;\n\t\tif (metadata && (iss !== undefined || metadata.authorization_response_iss_parameter_supported)) {\n\t\t\tif (iss !== metadata.issuer) throw new OAuthIssuerMismatchError(metadata.issuer, iss);\n\t\t}\n\t\tconst tokens = await exchangeAuthorizationCode(discovered.authorizationServerUrl, {\n\t\t\t...tokenOptions,\n\t\t\tcode: options.authorizationCode,\n\t\t\tcodeVerifier: await provider.codeVerifier(),\n\t\t\tredirectUrl,\n\t\t});\n\t\t// A response without `scope` grants the requested scope (RFC 6749 §5.1). Recorded so a step-up can\n\t\t// keep it. Callers pass the options of the authorization request, so `scope` is what was requested.\n\t\tawait provider.saveTokens(withScope(tokens, scope));\n\t\treturn \"AUTHORIZED\";\n\t}\n\tconst existing = options.skipRefresh ? undefined : await provider.tokens();\n\tif (existing?.refresh_token) {\n\t\ttry {\n\t\t\tconst tokens = await refreshAuthorization(discovered.authorizationServerUrl, {\n\t\t\t\t...tokenOptions,\n\t\t\t\trefreshToken: existing.refresh_token,\n\t\t\t});\n\t\t\t// A refresh without `scope` keeps the scope of the grant (RFC 6749 §6).\n\t\t\tawait provider.saveTokens(withScope(tokens, existing.scope));\n\t\t\treturn \"AUTHORIZED\";\n\t\t} catch (error) {\n\t\t\tif (options.signal?.aborted || error instanceof OAuthInsecureEndpointError) throw error;\n\t\t\tif (error instanceof OAuthError && error.code !== \"server_error\") throw error;\n\t\t}\n\t}\n\tconst state = await provider.state?.();\n\tconst authorization = await startAuthorization(discovered.authorizationServerUrl, {\n\t\tmetadata,\n\t\tclientInformation: client,\n\t\tredirectUrl,\n\t\tscope,\n\t\tstate,\n\t\tresource,\n\t});\n\tawait provider.saveCodeVerifier(authorization.codeVerifier);\n\tawait provider.redirectToAuthorization(authorization.authorizationUrl);\n\treturn \"REDIRECT\";\n}\n\nexport async function authorizeMcp(provider: OAuthClientProvider, options: OAuthFlowOptions): Promise<OAuthFlowResult> {\n\ttry {\n\t\treturn await runFlow(provider, options);\n\t} catch (error) {\n\t\tif (error instanceof OAuthError && [\"invalid_client\", \"unauthorized_client\"].includes(error.code)) {\n\t\t\tawait provider.invalidateCredentials?.(\"all\");\n\t\t\treturn runFlow(provider, options);\n\t\t}\n\t\tif (error instanceof OAuthError && error.code === \"invalid_grant\") {\n\t\t\tawait provider.invalidateCredentials?.(\"tokens\");\n\t\t\treturn runFlow(provider, options);\n\t\t}\n\t\tthrow error;\n\t}\n}\n\n/**\n * Auth provider for `StreamableHttpTransport`. After a 401 it refreshes the tokens, or throws\n * `McpOAuthAuthorizationRequiredError` when the user has to authorize (again). Concurrent 401s share\n * one refresh, and a request whose token was already replaced is just retried: with rotating refresh\n * tokens, a second refresh with the old refresh token would fail and discard the new grant.\n */\nexport function adaptOAuthProvider(provider: OAuthClientProvider): AuthProvider {\n\tlet inFlight: Promise<void> | undefined;\n\treturn {\n\t\ttoken: async () => (await provider.tokens())?.access_token,\n\t\tonUnauthorized: async (context: UnauthorizedContext) => {\n\t\t\tconst challenge = parseWwwAuthenticate(context.response.headers.get(\"www-authenticate\"));\n\t\t\tconst insufficientScope = challenge.error === \"insufficient_scope\";\n\t\t\tif (!insufficientScope && !inFlight && context.token !== undefined) {\n\t\t\t\tconst current = (await provider.tokens())?.access_token;\n\t\t\t\tif (current !== undefined && current !== context.token) return;\n\t\t\t}\n\t\t\tinFlight ??= Promise.resolve(insufficientScope ? provider.tokens() : undefined)\n\t\t\t\t.then((granted) =>\n\t\t\t\t\tauthorizeMcp(provider, {\n\t\t\t\t\t\tserverUrl: context.serverUrl,\n\t\t\t\t\t\tresourceMetadataUrl: challenge.resourceMetadataUrl,\n\t\t\t\t\t\tscope: insufficientScope ? stepUpScope(granted?.scope, challenge.scope) : challenge.scope,\n\t\t\t\t\t\tfetch: context.fetch,\n\t\t\t\t\t\tskipRefresh: insufficientScope,\n\t\t\t\t\t}),\n\t\t\t\t)\n\t\t\t\t.then((result) => {\n\t\t\t\t\tif (result === \"REDIRECT\") throw new McpOAuthAuthorizationRequiredError();\n\t\t\t\t})\n\t\t\t\t.finally(() => {\n\t\t\t\t\tinFlight = undefined;\n\t\t\t\t});\n\t\t\tawait inFlight;\n\t\t},\n\t};\n}\n"]}
|
|
@@ -56,6 +56,8 @@ export declare class StreamableHttpTransport extends TransportEvents implements
|
|
|
56
56
|
private sessionIdValue;
|
|
57
57
|
private protocolVersion;
|
|
58
58
|
private getStreamStarted;
|
|
59
|
+
/** Access token of the latest request, which `close()` reuses instead of asking the auth provider. */
|
|
60
|
+
private lastToken;
|
|
59
61
|
constructor(options: StreamableHttpTransportOptions);
|
|
60
62
|
get sessionId(): string | undefined;
|
|
61
63
|
start(): Promise<void>;
|
|
@@ -68,6 +70,7 @@ export declare class StreamableHttpTransport extends TransportEvents implements
|
|
|
68
70
|
*/
|
|
69
71
|
private authorizedFetch;
|
|
70
72
|
private headers;
|
|
73
|
+
private buildHeaders;
|
|
71
74
|
private captureSession;
|
|
72
75
|
private checkResponse;
|
|
73
76
|
private consumeSse;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamable-http.d.ts","sourceRoot":"","sources":["../../src/transports/streamable-http.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAKN,KAAK,cAAc,EAInB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAA6B,KAAK,YAAY,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAQ/F,MAAM,WAAW,QAAQ;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,iBAAiB;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC/B,0GAA0G;IAC1G,IAAI,CAAC,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,6DAA6D;IAC7D,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AAED,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAoEpH;AAED,MAAM,WAAW,8BAA8B;IAC9C,0GAA0G;IAC1G,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,8BAA8B;IAC9C,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,gFAAgF;IAChF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,uGAAuG;IACvG,SAAS,CAAC,EAAE,8BAA8B,CAAC;CAC3C;AAED,qBAAa,YAAa,SAAQ,KAAK;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,YAAY,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,SAAK,EAKrD;CACD;AAED,qBAAa,oBAAqB,SAAQ,YAAY;IACrD,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAExC,YAAY,QAAQ,EAAE,QAAQ,EAAE,IAAI,SAAK,EAIxC;CACD;AAED,qBAAa,sBAAuB,SAAQ,YAAY;IACvD,YAAY,IAAI,SAAK,EAGpB;CACD;AAmCD,qBAAa,uBAAwB,SAAQ,eAAgB,YAAW,YAAY;IACnF,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAClB,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,8BAA8B,CAAC,CAAC;IAC3D,OAAO,CAAC,KAAK,CAAW;IACxB,OAAO,CAAC,UAAU,CAAyB;IAC3C,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAqB;IAC3C,OAAO,CAAC,eAAe,CAAqB;IAC5C,OAAO,CAAC,gBAAgB,CAAS;
|
|
1
|
+
{"version":3,"file":"streamable-http.d.ts","sourceRoot":"","sources":["../../src/transports/streamable-http.ts"],"names":[],"mappings":"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"}
|
|
@@ -138,6 +138,8 @@ export class StreamableHttpTransport extends TransportEvents {
|
|
|
138
138
|
sessionIdValue;
|
|
139
139
|
protocolVersion;
|
|
140
140
|
getStreamStarted = false;
|
|
141
|
+
/** Access token of the latest request, which `close()` reuses instead of asking the auth provider. */
|
|
142
|
+
lastToken;
|
|
141
143
|
constructor(options) {
|
|
142
144
|
super();
|
|
143
145
|
this.options = Object.freeze({ ...options, headers: options.headers ? { ...options.headers } : undefined });
|
|
@@ -200,20 +202,17 @@ export class StreamableHttpTransport extends TransportEvents {
|
|
|
200
202
|
this.closed = true;
|
|
201
203
|
this.controller.abort();
|
|
202
204
|
if (this.started && this.sessionIdValue) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
+
// Best effort: the session expires on the server anyway. The auth provider may refresh tokens
|
|
206
|
+
// over the network, so it is not asked here and closing never waits for a refresh.
|
|
205
207
|
try {
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
.
|
|
209
|
-
.
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
// Resolving auth headers failed; the session will expire on the server.
|
|
213
|
-
}
|
|
214
|
-
finally {
|
|
215
|
-
clearTimeout(timeout);
|
|
208
|
+
const response = await this.fetch(this.url, {
|
|
209
|
+
method: "DELETE",
|
|
210
|
+
headers: this.buildHeaders({}, this.lastToken),
|
|
211
|
+
signal: AbortSignal.timeout(1_000),
|
|
212
|
+
});
|
|
213
|
+
await discard(response);
|
|
216
214
|
}
|
|
215
|
+
catch { }
|
|
217
216
|
}
|
|
218
217
|
this.emitClose();
|
|
219
218
|
}
|
|
@@ -242,6 +241,11 @@ export class StreamableHttpTransport extends TransportEvents {
|
|
|
242
241
|
}
|
|
243
242
|
}
|
|
244
243
|
async headers(extra = {}) {
|
|
244
|
+
const token = await this.options.authProvider?.token();
|
|
245
|
+
this.lastToken = token;
|
|
246
|
+
return { headers: this.buildHeaders(extra, token), ...(token ? { token } : {}) };
|
|
247
|
+
}
|
|
248
|
+
buildHeaders(extra, token) {
|
|
245
249
|
const headers = new Headers(this.options.headers);
|
|
246
250
|
for (const [name, value] of Object.entries(extra))
|
|
247
251
|
headers.set(name, value);
|
|
@@ -249,10 +253,9 @@ export class StreamableHttpTransport extends TransportEvents {
|
|
|
249
253
|
headers.set("Mcp-Session-Id", this.sessionIdValue);
|
|
250
254
|
if (this.protocolVersion)
|
|
251
255
|
headers.set("MCP-Protocol-Version", this.protocolVersion);
|
|
252
|
-
const token = await this.options.authProvider?.token();
|
|
253
256
|
if (token)
|
|
254
257
|
headers.set("Authorization", `Bearer ${token}`);
|
|
255
|
-
return
|
|
258
|
+
return headers;
|
|
256
259
|
}
|
|
257
260
|
captureSession(response) {
|
|
258
261
|
const sessionId = response.headers.get("mcp-session-id");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"streamable-http.js","sourceRoot":"","sources":["../../src/transports/streamable-http.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AuthProvider, McpFetch } from \"../auth-provider.ts\";\nimport {\n\tisJsonRpcRequest,\n\tisJsonRpcResponse,\n\tJSON_RPC_ERROR_CODES,\n\ttype JsonRpcId,\n\ttype JsonRpcMessage,\n\tMcpConnectionClosedError,\n\tparseJsonRpcMessage,\n\ttoError,\n} from \"../protocol/jsonrpc.ts\";\nimport { DEFAULT_MAX_MESSAGE_BYTES, type McpTransport, TransportEvents } from \"./transport.ts\";\n\nconst MAX_ERROR_BODY_BYTES = 8 * 1024;\nconst ERROR_MESSAGE_BODY_CHARS = 500;\nconst DEFAULT_RECONNECT_INITIAL_DELAY_MS = 1_000;\nconst DEFAULT_RECONNECT_MAX_DELAY_MS = 30_000;\nconst DEFAULT_RECONNECT_MAX_RETRIES = 5;\n\nexport interface SseEvent {\n\tevent?: string;\n\tdata: string;\n\tid?: string;\n}\n\nexport interface ConsumeSseOptions {\n\tmaxEventBytes?: number;\n\tonEvent(event: SseEvent): void;\n\t/** Called for every `id` field, including events without data (for example resumption priming events). */\n\tonId?(id: string): void;\n\t/** Called for every valid `retry` field, in milliseconds. */\n\tonRetry?(delayMs: number): void;\n}\n\nexport async function consumeSseStream(stream: ReadableStream<Uint8Array>, options: ConsumeSseOptions): Promise<void> {\n\tconst reader = stream.getReader();\n\tconst decoder = new TextDecoder();\n\tlet buffered = \"\";\n\tlet eventName: string | undefined;\n\tlet eventId: string | undefined;\n\tlet dataLines: string[] = [];\n\t// Bytes of the pending event's data, including the \"\\n\" joins, so events streamed as many\n\t// short `data:` lines without a terminating blank line cannot grow without bound.\n\tlet dataBytes = 0;\n\tconst maxEventBytes = options.maxEventBytes ?? DEFAULT_MAX_MESSAGE_BYTES;\n\n\tconst dispatch = () => {\n\t\tif (dataLines.length === 0) {\n\t\t\teventName = undefined;\n\t\t\teventId = undefined;\n\t\t\treturn;\n\t\t}\n\t\tconst data = dataLines.join(\"\\n\");\n\t\toptions.onEvent({ ...(eventName ? { event: eventName } : {}), data, ...(eventId ? { id: eventId } : {}) });\n\t\teventName = undefined;\n\t\teventId = undefined;\n\t\tdataLines = [];\n\t\tdataBytes = 0;\n\t};\n\n\tconst processLine = (rawLine: string) => {\n\t\tconst line = rawLine.endsWith(\"\\r\") ? rawLine.slice(0, -1) : rawLine;\n\t\tif (line === \"\") {\n\t\t\tdispatch();\n\t\t\treturn;\n\t\t}\n\t\tif (line.startsWith(\":\")) return;\n\t\tconst colon = line.indexOf(\":\");\n\t\tconst field = colon < 0 ? line : line.slice(0, colon);\n\t\tlet value = colon < 0 ? \"\" : line.slice(colon + 1);\n\t\tif (value.startsWith(\" \")) value = value.slice(1);\n\t\tif (field === \"data\") {\n\t\t\tdataBytes += Buffer.byteLength(value) + (dataLines.length > 0 ? 1 : 0);\n\t\t\tif (dataBytes > maxEventBytes) throw new Error(`MCP SSE event exceeds ${maxEventBytes} bytes`);\n\t\t\tdataLines.push(value);\n\t\t} else if (field === \"event\") eventName = value;\n\t\telse if (field === \"id\" && !value.includes(\"\\0\")) {\n\t\t\teventId = value;\n\t\t\toptions.onId?.(value);\n\t\t} else if (field === \"retry\" && /^\\d+$/.test(value)) options.onRetry?.(Number(value));\n\t};\n\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tbuffered += decoder.decode(value, { stream: true });\n\t\t\tlet newline = buffered.indexOf(\"\\n\");\n\t\t\twhile (newline >= 0) {\n\t\t\t\tprocessLine(buffered.slice(0, newline));\n\t\t\t\tbuffered = buffered.slice(newline + 1);\n\t\t\t\tnewline = buffered.indexOf(\"\\n\");\n\t\t\t}\n\t\t\tif (Buffer.byteLength(buffered) > maxEventBytes)\n\t\t\t\tthrow new Error(`MCP SSE event exceeds ${maxEventBytes} bytes`);\n\t\t}\n\t\tbuffered += decoder.decode();\n\t\tif (buffered) processLine(buffered);\n\t\tdispatch();\n\t} finally {\n\t\treader.releaseLock();\n\t}\n}\n\nexport interface StreamableHttpReconnectOptions {\n\t/** Delay before the first reconnection attempt, unless the server sent a `retry` field. Default: 1000. */\n\tinitialDelayMs?: number;\n\t/** Upper bound for the exponential backoff. Default: 30000. */\n\tmaxDelayMs?: number;\n\t/** Consecutive failed attempts before giving up on a stream. Default: 5. */\n\tmaxRetries?: number;\n}\n\nexport interface StreamableHttpTransportOptions {\n\turl: string | URL;\n\theaders?: Record<string, string>;\n\tfetch?: McpFetch;\n\t/** Open the server-to-client GET stream after initialization. Default: true. */\n\topenGetStream?: boolean;\n\tmaxMessageBytes?: number;\n\tauthProvider?: AuthProvider;\n\t/** Reconnection of dropped SSE streams (the GET stream, and response streams that carry event IDs). */\n\treconnect?: StreamableHttpReconnectOptions;\n}\n\nexport class McpHttpError extends Error {\n\treadonly status: number;\n\treadonly body: string;\n\n\tconstructor(status: number, message: string, body = \"\") {\n\t\tsuper(message);\n\t\tthis.name = \"McpHttpError\";\n\t\tthis.status = status;\n\t\tthis.body = body;\n\t}\n}\n\nexport class McpAuthRequiredError extends McpHttpError {\n\treadonly wwwAuthenticate: string | null;\n\n\tconstructor(response: Response, body = \"\") {\n\t\tsuper(401, \"MCP server requires authentication\", body);\n\t\tthis.name = \"McpAuthRequiredError\";\n\t\tthis.wwwAuthenticate = response.headers.get(\"www-authenticate\");\n\t}\n}\n\nexport class McpSessionExpiredError extends McpHttpError {\n\tconstructor(body = \"\") {\n\t\tsuper(404, \"MCP session expired\", body);\n\t\tthis.name = \"McpSessionExpiredError\";\n\t}\n}\n\nfunction contentType(response: Response): string | undefined {\n\treturn response.headers.get(\"content-type\")?.split(\";\", 1)[0]?.trim().toLowerCase();\n}\n\n/** 401, or 403 with an `insufficient_scope` bearer challenge (step-up authorization). */\nfunction needsAuthorization(response: Response): boolean {\n\tif (response.status === 401) return true;\n\tif (response.status !== 403) return false;\n\treturn /(?:^|[\\s,])error=\"?insufficient_scope\"?/i.test(response.headers.get(\"www-authenticate\") ?? \"\");\n}\n\n/** Statuses worth retrying when a stream fails to (re)open. */\nfunction isTransientStatus(status: number): boolean {\n\treturn status === 408 || status === 429 || status >= 500;\n}\n\nfunction discard(response: Response): Promise<void> {\n\treturn response.body?.cancel().catch(() => {}) ?? Promise.resolve();\n}\n\nfunction describeHttpFailure(status: number, body: string): string {\n\tconst text = body.trim();\n\tconst snippet = text.length > ERROR_MESSAGE_BODY_CHARS ? `${text.slice(0, ERROR_MESSAGE_BODY_CHARS - 3)}...` : text;\n\treturn `MCP HTTP request failed with status ${status}${snippet ? `: ${snippet}` : \"\"}`;\n}\n\ninterface StreamCursor {\n\tlastEventId: string | undefined;\n\tretryMs: number | undefined;\n\t/** Whether the stream delivered any event since it was (re)opened. */\n\treceived: boolean;\n}\n\nexport class StreamableHttpTransport extends TransportEvents implements McpTransport {\n\treadonly url: URL;\n\treadonly options: Readonly<StreamableHttpTransportOptions>;\n\tprivate fetch: McpFetch;\n\tprivate controller = new AbortController();\n\tprivate started = false;\n\tprivate closed = false;\n\tprivate sessionIdValue: string | undefined;\n\tprivate protocolVersion: string | undefined;\n\tprivate getStreamStarted = false;\n\n\tconstructor(options: StreamableHttpTransportOptions) {\n\t\tsuper();\n\t\tthis.options = Object.freeze({ ...options, headers: options.headers ? { ...options.headers } : undefined });\n\t\tthis.url = new URL(options.url);\n\t\tconst fetch = options.fetch ?? globalThis.fetch;\n\t\t// Call fetch without a receiver. `this.fetch(...)` and `context.fetch(...)` would pass the transport or\n\t\t// the auth context as `this`, which Cloudflare Workers reject for the platform fetch (\"Illegal invocation\").\n\t\tthis.fetch = (input, init) => fetch(input, init);\n\t}\n\n\tget sessionId(): string | undefined {\n\t\treturn this.sessionIdValue;\n\t}\n\n\tasync start(): Promise<void> {\n\t\tif (this.started) throw new Error(\"MCP Streamable HTTP transport already started\");\n\t\tif (this.closed) throw new McpConnectionClosedError();\n\t\tthis.started = true;\n\t}\n\n\tsetProtocolVersion(version: string): void {\n\t\tthis.protocolVersion = version;\n\t}\n\n\tasync send(message: JsonRpcMessage): Promise<void> {\n\t\tif (!this.started || this.closed) throw new McpConnectionClosedError();\n\t\tconst response = await this.authorizedFetch(\"POST\", {\n\t\t\theaders: { accept: \"application/json, text/event-stream\", \"content-type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(message),\n\t\t});\n\t\tawait this.checkResponse(response);\n\t\tthis.captureSession(response);\n\n\t\tif (!isJsonRpcRequest(message)) {\n\t\t\t// Notifications and responses are acknowledged with 202 and carry no reply; ignore any body.\n\t\t\tawait discard(response);\n\t\t\t// The server-to-client stream may only open once the session is initialized.\n\t\t\tif (\"method\" in message && message.method === \"notifications/initialized\") this.startGetStream();\n\t\t\treturn;\n\t\t}\n\t\tif (response.status === 202 || response.status === 204) {\n\t\t\tthrow new McpHttpError(response.status, `MCP server accepted request ${message.method} without a response`);\n\t\t}\n\t\tconst type = contentType(response);\n\t\tif (type === \"application/json\") {\n\t\t\tconst body: unknown = await response.json();\n\t\t\tfor (const item of Array.isArray(body) ? body : [body]) this.emitMessage(parseJsonRpcMessage(item));\n\t\t\treturn;\n\t\t}\n\t\tif (type === \"text/event-stream\" && response.body) {\n\t\t\tvoid this.consumeResponseStream(response.body, message.id);\n\t\t\treturn;\n\t\t}\n\t\tawait discard(response);\n\t\tthrow new McpHttpError(response.status, `Unsupported MCP response content type: ${type ?? \"missing\"}`);\n\t}\n\n\tasync close(): Promise<void> {\n\t\tif (this.closed) return;\n\t\tthis.closed = true;\n\t\tthis.controller.abort();\n\t\tif (this.started && this.sessionIdValue) {\n\t\t\tconst controller = new AbortController();\n\t\t\tconst timeout = setTimeout(() => controller.abort(), 1_000);\n\t\t\ttry {\n\t\t\t\tconst { headers } = await this.headers();\n\t\t\t\tawait this.fetch(this.url, { method: \"DELETE\", headers, signal: controller.signal })\n\t\t\t\t\t.then(discard)\n\t\t\t\t\t.catch(() => undefined);\n\t\t\t} catch {\n\t\t\t\t// Resolving auth headers failed; the session will expire on the server.\n\t\t\t} finally {\n\t\t\t\tclearTimeout(timeout);\n\t\t\t}\n\t\t}\n\t\tthis.emitClose();\n\t}\n\n\t/**\n\t * Fetch with auth headers. A 401 (or a 403 asking for more scope) is handed to the auth provider\n\t * once, and the request is retried with whatever credentials it left behind.\n\t */\n\tprivate async authorizedFetch(\n\t\tmethod: \"GET\" | \"POST\",\n\t\tinit: { headers: Record<string, string>; body?: string },\n\t): Promise<Response> {\n\t\tconst onUnauthorized = this.options.authProvider?.onUnauthorized?.bind(this.options.authProvider);\n\t\tfor (let attempt = 0; ; attempt++) {\n\t\t\tconst { headers, token } = await this.headers(init.headers);\n\t\t\tconst response = await this.fetch(this.url, {\n\t\t\t\tmethod,\n\t\t\t\theaders,\n\t\t\t\tbody: init.body,\n\t\t\t\tsignal: this.controller.signal,\n\t\t\t});\n\t\t\tif (attempt > 0 || !onUnauthorized || !needsAuthorization(response)) return response;\n\t\t\ttry {\n\t\t\t\tawait onUnauthorized({ response, serverUrl: this.url, fetch: this.fetch, token });\n\t\t\t} finally {\n\t\t\t\tawait discard(response);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async headers(extra: Record<string, string> = {}): Promise<{ headers: Headers; token?: string }> {\n\t\tconst headers = new Headers(this.options.headers);\n\t\tfor (const [name, value] of Object.entries(extra)) headers.set(name, value);\n\t\tif (this.sessionIdValue) headers.set(\"Mcp-Session-Id\", this.sessionIdValue);\n\t\tif (this.protocolVersion) headers.set(\"MCP-Protocol-Version\", this.protocolVersion);\n\t\tconst token = await this.options.authProvider?.token();\n\t\tif (token) headers.set(\"Authorization\", `Bearer ${token}`);\n\t\treturn { headers, ...(token ? { token } : {}) };\n\t}\n\n\tprivate captureSession(response: Response): void {\n\t\tconst sessionId = response.headers.get(\"mcp-session-id\");\n\t\tif (sessionId) this.sessionIdValue = sessionId;\n\t}\n\n\tprivate async checkResponse(response: Response): Promise<void> {\n\t\tif (response.ok) return;\n\t\tconst body = (await response.text().catch(() => \"\")).slice(0, MAX_ERROR_BODY_BYTES);\n\t\tif (response.status === 401) throw new McpAuthRequiredError(response, body);\n\t\tif (response.status === 404 && this.sessionIdValue) throw new McpSessionExpiredError(body);\n\t\tthrow new McpHttpError(response.status, describeHttpFailure(response.status, body), body);\n\t}\n\n\tprivate async consumeSse(\n\t\tstream: ReadableStream<Uint8Array>,\n\t\tcursor: StreamCursor,\n\t\tonMessage?: (message: JsonRpcMessage) => void,\n\t): Promise<void> {\n\t\tawait consumeSseStream(stream, {\n\t\t\tmaxEventBytes: this.options.maxMessageBytes ?? DEFAULT_MAX_MESSAGE_BYTES,\n\t\t\tonId: (id) => {\n\t\t\t\tcursor.lastEventId = id;\n\t\t\t},\n\t\t\tonRetry: (delayMs) => {\n\t\t\t\tcursor.retryMs = delayMs;\n\t\t\t},\n\t\t\tonEvent: (event) => {\n\t\t\t\tcursor.received = true;\n\t\t\t\t// Events without data prime resumption; other event types are not JSON-RPC.\n\t\t\t\tif (!event.data.trim() || (event.event !== undefined && event.event !== \"message\")) return;\n\t\t\t\tlet message: JsonRpcMessage;\n\t\t\t\ttry {\n\t\t\t\t\tmessage = parseJsonRpcMessage(JSON.parse(event.data));\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.emitError(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tonMessage?.(message);\n\t\t\t\tthis.emitMessage(message);\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Read the SSE stream answering one request. When the stream ends or breaks before the response\n\t * arrives and the server assigned event IDs, resume it with GET and `Last-Event-ID`, as the\n\t * server may close response streams at will. Otherwise only this request fails.\n\t */\n\tprivate async consumeResponseStream(body: ReadableStream<Uint8Array>, requestId: JsonRpcId): Promise<void> {\n\t\tconst cursor: StreamCursor = { lastEventId: undefined, retryMs: undefined, received: false };\n\t\tlet answered = false;\n\t\tconst onMessage = (message: JsonRpcMessage) => {\n\t\t\tif (isJsonRpcResponse(message) && message.id === requestId) answered = true;\n\t\t};\n\t\tlet stream: ReadableStream<Uint8Array> | undefined = body;\n\t\tlet failure: unknown;\n\t\tfor (let attempt = 0; ; ) {\n\t\t\tif (stream) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.consumeSse(stream, cursor, onMessage);\n\t\t\t\t\tfailure = undefined;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tfailure = error;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (answered || this.closed) return;\n\t\t\tif (failure !== undefined && !this.isRetryable(failure)) break;\n\t\t\tif (cursor.lastEventId === undefined || attempt >= this.maxRetries()) break;\n\t\t\tif (cursor.received) attempt = 0;\n\t\t\tcursor.received = false;\n\t\t\tif (!(await this.sleep(this.reconnectDelay(attempt++, cursor.retryMs)))) return;\n\t\t\ttry {\n\t\t\t\tstream = await this.openSseStream(cursor.lastEventId);\n\t\t\t} catch (error) {\n\t\t\t\tfailure = error;\n\t\t\t\tif (!this.isRetryable(error)) break;\n\t\t\t\tstream = undefined;\n\t\t\t}\n\t\t}\n\t\tif (this.closed) return;\n\t\tconst reason = failure === undefined ? \"stream ended without a response\" : toError(failure).message;\n\t\tthis.emitMessage({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tid: requestId,\n\t\t\terror: { code: JSON_RPC_ERROR_CODES.internalError, message: `MCP response stream failed: ${reason}` },\n\t\t});\n\t}\n\n\tprivate startGetStream(): void {\n\t\tif (this.options.openGetStream === false || this.getStreamStarted || this.closed) return;\n\t\tthis.getStreamStarted = true;\n\t\tvoid this.runGetStream();\n\t}\n\n\t/** Keep the server-to-client stream open, reconnecting with backoff when it drops. */\n\tprivate async runGetStream(): Promise<void> {\n\t\tconst cursor: StreamCursor = { lastEventId: undefined, retryMs: undefined, received: false };\n\t\tfor (let attempt = 0; !this.closed; ) {\n\t\t\ttry {\n\t\t\t\tconst stream = await this.openSseStream(cursor.lastEventId);\n\t\t\t\t// The server does not offer a GET stream.\n\t\t\t\tif (!stream) return;\n\t\t\t\tconst openedAt = Date.now();\n\t\t\t\tawait this.consumeSse(stream, cursor);\n\t\t\t\t// A stream that stayed up for a while counts as healthy, even if it was idle.\n\t\t\t\tif (cursor.received || Date.now() - openedAt > this.maxDelay()) attempt = 0;\n\t\t\t} catch (error) {\n\t\t\t\tif (this.closed) return;\n\t\t\t\tif (!this.isRetryable(error)) {\n\t\t\t\t\tthis.emitError(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcursor.received = false;\n\t\t\tif (attempt >= this.maxRetries()) {\n\t\t\t\tthis.emitError(new Error(\"MCP server-to-client stream dropped and could not be reopened\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!(await this.sleep(this.reconnectDelay(attempt++, cursor.retryMs)))) return;\n\t\t}\n\t}\n\n\t/** Open a GET SSE stream. Resolves to undefined when the server answers 405 (no GET stream). */\n\tprivate async openSseStream(lastEventId: string | undefined): Promise<ReadableStream<Uint8Array> | undefined> {\n\t\tconst response = await this.authorizedFetch(\"GET\", {\n\t\t\theaders: {\n\t\t\t\taccept: \"text/event-stream\",\n\t\t\t\t...(lastEventId === undefined ? {} : { \"last-event-id\": lastEventId }),\n\t\t\t},\n\t\t});\n\t\tif (response.status === 405) {\n\t\t\tawait discard(response);\n\t\t\treturn undefined;\n\t\t}\n\t\tawait this.checkResponse(response);\n\t\tthis.captureSession(response);\n\t\tconst type = contentType(response);\n\t\tif (type !== \"text/event-stream\" || !response.body) {\n\t\t\tawait discard(response);\n\t\t\tthrow new McpHttpError(response.status, `Unsupported MCP GET response content type: ${type ?? \"missing\"}`);\n\t\t}\n\t\treturn response.body;\n\t}\n\n\t/**\n\t * Network failures and transient statuses are retried; auth, session, and protocol errors are not.\n\t * `fetch` reports network failures, including a connection dropped mid-body, as `TypeError`.\n\t */\n\tprivate isRetryable(error: unknown): boolean {\n\t\tif (error instanceof McpHttpError) return isTransientStatus(error.status);\n\t\tif (error instanceof TypeError) return true;\n\t\tconst code = (error as { code?: unknown } | undefined)?.code;\n\t\treturn typeof code === \"string\" && (code.startsWith(\"E\") || code.startsWith(\"UND_ERR\"));\n\t}\n\n\tprivate reconnectDelay(attempt: number, serverDelayMs: number | undefined): number {\n\t\tif (serverDelayMs !== undefined) return serverDelayMs;\n\t\tconst initial = this.options.reconnect?.initialDelayMs ?? DEFAULT_RECONNECT_INITIAL_DELAY_MS;\n\t\treturn Math.min(initial * 2 ** attempt, this.maxDelay());\n\t}\n\n\tprivate maxDelay(): number {\n\t\treturn this.options.reconnect?.maxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS;\n\t}\n\n\tprivate maxRetries(): number {\n\t\treturn this.options.reconnect?.maxRetries ?? DEFAULT_RECONNECT_MAX_RETRIES;\n\t}\n\n\t/** Resolves false when the transport closed while waiting. */\n\tprivate sleep(ms: number): Promise<boolean> {\n\t\tconst signal = this.controller.signal;\n\t\tif (signal.aborted) return Promise.resolve(false);\n\t\treturn new Promise((resolve) => {\n\t\t\tconst onAbort = () => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(false);\n\t\t\t};\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\tresolve(true);\n\t\t\t}, ms);\n\t\t\t// A reconnect wait alone does not keep the process alive.\n\t\t\ttimer.unref?.();\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t});\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"streamable-http.js","sourceRoot":"","sources":["../../src/transports/streamable-http.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AuthProvider, McpFetch } from \"../auth-provider.ts\";\nimport {\n\tisJsonRpcRequest,\n\tisJsonRpcResponse,\n\tJSON_RPC_ERROR_CODES,\n\ttype JsonRpcId,\n\ttype JsonRpcMessage,\n\tMcpConnectionClosedError,\n\tparseJsonRpcMessage,\n\ttoError,\n} from \"../protocol/jsonrpc.ts\";\nimport { DEFAULT_MAX_MESSAGE_BYTES, type McpTransport, TransportEvents } from \"./transport.ts\";\n\nconst MAX_ERROR_BODY_BYTES = 8 * 1024;\nconst ERROR_MESSAGE_BODY_CHARS = 500;\nconst DEFAULT_RECONNECT_INITIAL_DELAY_MS = 1_000;\nconst DEFAULT_RECONNECT_MAX_DELAY_MS = 30_000;\nconst DEFAULT_RECONNECT_MAX_RETRIES = 5;\n\nexport interface SseEvent {\n\tevent?: string;\n\tdata: string;\n\tid?: string;\n}\n\nexport interface ConsumeSseOptions {\n\tmaxEventBytes?: number;\n\tonEvent(event: SseEvent): void;\n\t/** Called for every `id` field, including events without data (for example resumption priming events). */\n\tonId?(id: string): void;\n\t/** Called for every valid `retry` field, in milliseconds. */\n\tonRetry?(delayMs: number): void;\n}\n\nexport async function consumeSseStream(stream: ReadableStream<Uint8Array>, options: ConsumeSseOptions): Promise<void> {\n\tconst reader = stream.getReader();\n\tconst decoder = new TextDecoder();\n\tlet buffered = \"\";\n\tlet eventName: string | undefined;\n\tlet eventId: string | undefined;\n\tlet dataLines: string[] = [];\n\t// Bytes of the pending event's data, including the \"\\n\" joins, so events streamed as many\n\t// short `data:` lines without a terminating blank line cannot grow without bound.\n\tlet dataBytes = 0;\n\tconst maxEventBytes = options.maxEventBytes ?? DEFAULT_MAX_MESSAGE_BYTES;\n\n\tconst dispatch = () => {\n\t\tif (dataLines.length === 0) {\n\t\t\teventName = undefined;\n\t\t\teventId = undefined;\n\t\t\treturn;\n\t\t}\n\t\tconst data = dataLines.join(\"\\n\");\n\t\toptions.onEvent({ ...(eventName ? { event: eventName } : {}), data, ...(eventId ? { id: eventId } : {}) });\n\t\teventName = undefined;\n\t\teventId = undefined;\n\t\tdataLines = [];\n\t\tdataBytes = 0;\n\t};\n\n\tconst processLine = (rawLine: string) => {\n\t\tconst line = rawLine.endsWith(\"\\r\") ? rawLine.slice(0, -1) : rawLine;\n\t\tif (line === \"\") {\n\t\t\tdispatch();\n\t\t\treturn;\n\t\t}\n\t\tif (line.startsWith(\":\")) return;\n\t\tconst colon = line.indexOf(\":\");\n\t\tconst field = colon < 0 ? line : line.slice(0, colon);\n\t\tlet value = colon < 0 ? \"\" : line.slice(colon + 1);\n\t\tif (value.startsWith(\" \")) value = value.slice(1);\n\t\tif (field === \"data\") {\n\t\t\tdataBytes += Buffer.byteLength(value) + (dataLines.length > 0 ? 1 : 0);\n\t\t\tif (dataBytes > maxEventBytes) throw new Error(`MCP SSE event exceeds ${maxEventBytes} bytes`);\n\t\t\tdataLines.push(value);\n\t\t} else if (field === \"event\") eventName = value;\n\t\telse if (field === \"id\" && !value.includes(\"\\0\")) {\n\t\t\teventId = value;\n\t\t\toptions.onId?.(value);\n\t\t} else if (field === \"retry\" && /^\\d+$/.test(value)) options.onRetry?.(Number(value));\n\t};\n\n\ttry {\n\t\twhile (true) {\n\t\t\tconst { done, value } = await reader.read();\n\t\t\tif (done) break;\n\t\t\tbuffered += decoder.decode(value, { stream: true });\n\t\t\tlet newline = buffered.indexOf(\"\\n\");\n\t\t\twhile (newline >= 0) {\n\t\t\t\tprocessLine(buffered.slice(0, newline));\n\t\t\t\tbuffered = buffered.slice(newline + 1);\n\t\t\t\tnewline = buffered.indexOf(\"\\n\");\n\t\t\t}\n\t\t\tif (Buffer.byteLength(buffered) > maxEventBytes)\n\t\t\t\tthrow new Error(`MCP SSE event exceeds ${maxEventBytes} bytes`);\n\t\t}\n\t\tbuffered += decoder.decode();\n\t\tif (buffered) processLine(buffered);\n\t\tdispatch();\n\t} finally {\n\t\treader.releaseLock();\n\t}\n}\n\nexport interface StreamableHttpReconnectOptions {\n\t/** Delay before the first reconnection attempt, unless the server sent a `retry` field. Default: 1000. */\n\tinitialDelayMs?: number;\n\t/** Upper bound for the exponential backoff. Default: 30000. */\n\tmaxDelayMs?: number;\n\t/** Consecutive failed attempts before giving up on a stream. Default: 5. */\n\tmaxRetries?: number;\n}\n\nexport interface StreamableHttpTransportOptions {\n\turl: string | URL;\n\theaders?: Record<string, string>;\n\tfetch?: McpFetch;\n\t/** Open the server-to-client GET stream after initialization. Default: true. */\n\topenGetStream?: boolean;\n\tmaxMessageBytes?: number;\n\tauthProvider?: AuthProvider;\n\t/** Reconnection of dropped SSE streams (the GET stream, and response streams that carry event IDs). */\n\treconnect?: StreamableHttpReconnectOptions;\n}\n\nexport class McpHttpError extends Error {\n\treadonly status: number;\n\treadonly body: string;\n\n\tconstructor(status: number, message: string, body = \"\") {\n\t\tsuper(message);\n\t\tthis.name = \"McpHttpError\";\n\t\tthis.status = status;\n\t\tthis.body = body;\n\t}\n}\n\nexport class McpAuthRequiredError extends McpHttpError {\n\treadonly wwwAuthenticate: string | null;\n\n\tconstructor(response: Response, body = \"\") {\n\t\tsuper(401, \"MCP server requires authentication\", body);\n\t\tthis.name = \"McpAuthRequiredError\";\n\t\tthis.wwwAuthenticate = response.headers.get(\"www-authenticate\");\n\t}\n}\n\nexport class McpSessionExpiredError extends McpHttpError {\n\tconstructor(body = \"\") {\n\t\tsuper(404, \"MCP session expired\", body);\n\t\tthis.name = \"McpSessionExpiredError\";\n\t}\n}\n\nfunction contentType(response: Response): string | undefined {\n\treturn response.headers.get(\"content-type\")?.split(\";\", 1)[0]?.trim().toLowerCase();\n}\n\n/** 401, or 403 with an `insufficient_scope` bearer challenge (step-up authorization). */\nfunction needsAuthorization(response: Response): boolean {\n\tif (response.status === 401) return true;\n\tif (response.status !== 403) return false;\n\treturn /(?:^|[\\s,])error=\"?insufficient_scope\"?/i.test(response.headers.get(\"www-authenticate\") ?? \"\");\n}\n\n/** Statuses worth retrying when a stream fails to (re)open. */\nfunction isTransientStatus(status: number): boolean {\n\treturn status === 408 || status === 429 || status >= 500;\n}\n\nfunction discard(response: Response): Promise<void> {\n\treturn response.body?.cancel().catch(() => {}) ?? Promise.resolve();\n}\n\nfunction describeHttpFailure(status: number, body: string): string {\n\tconst text = body.trim();\n\tconst snippet = text.length > ERROR_MESSAGE_BODY_CHARS ? `${text.slice(0, ERROR_MESSAGE_BODY_CHARS - 3)}...` : text;\n\treturn `MCP HTTP request failed with status ${status}${snippet ? `: ${snippet}` : \"\"}`;\n}\n\ninterface StreamCursor {\n\tlastEventId: string | undefined;\n\tretryMs: number | undefined;\n\t/** Whether the stream delivered any event since it was (re)opened. */\n\treceived: boolean;\n}\n\nexport class StreamableHttpTransport extends TransportEvents implements McpTransport {\n\treadonly url: URL;\n\treadonly options: Readonly<StreamableHttpTransportOptions>;\n\tprivate fetch: McpFetch;\n\tprivate controller = new AbortController();\n\tprivate started = false;\n\tprivate closed = false;\n\tprivate sessionIdValue: string | undefined;\n\tprivate protocolVersion: string | undefined;\n\tprivate getStreamStarted = false;\n\t/** Access token of the latest request, which `close()` reuses instead of asking the auth provider. */\n\tprivate lastToken: string | undefined;\n\n\tconstructor(options: StreamableHttpTransportOptions) {\n\t\tsuper();\n\t\tthis.options = Object.freeze({ ...options, headers: options.headers ? { ...options.headers } : undefined });\n\t\tthis.url = new URL(options.url);\n\t\tconst fetch = options.fetch ?? globalThis.fetch;\n\t\t// Call fetch without a receiver. `this.fetch(...)` and `context.fetch(...)` would pass the transport or\n\t\t// the auth context as `this`, which Cloudflare Workers reject for the platform fetch (\"Illegal invocation\").\n\t\tthis.fetch = (input, init) => fetch(input, init);\n\t}\n\n\tget sessionId(): string | undefined {\n\t\treturn this.sessionIdValue;\n\t}\n\n\tasync start(): Promise<void> {\n\t\tif (this.started) throw new Error(\"MCP Streamable HTTP transport already started\");\n\t\tif (this.closed) throw new McpConnectionClosedError();\n\t\tthis.started = true;\n\t}\n\n\tsetProtocolVersion(version: string): void {\n\t\tthis.protocolVersion = version;\n\t}\n\n\tasync send(message: JsonRpcMessage): Promise<void> {\n\t\tif (!this.started || this.closed) throw new McpConnectionClosedError();\n\t\tconst response = await this.authorizedFetch(\"POST\", {\n\t\t\theaders: { accept: \"application/json, text/event-stream\", \"content-type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(message),\n\t\t});\n\t\tawait this.checkResponse(response);\n\t\tthis.captureSession(response);\n\n\t\tif (!isJsonRpcRequest(message)) {\n\t\t\t// Notifications and responses are acknowledged with 202 and carry no reply; ignore any body.\n\t\t\tawait discard(response);\n\t\t\t// The server-to-client stream may only open once the session is initialized.\n\t\t\tif (\"method\" in message && message.method === \"notifications/initialized\") this.startGetStream();\n\t\t\treturn;\n\t\t}\n\t\tif (response.status === 202 || response.status === 204) {\n\t\t\tthrow new McpHttpError(response.status, `MCP server accepted request ${message.method} without a response`);\n\t\t}\n\t\tconst type = contentType(response);\n\t\tif (type === \"application/json\") {\n\t\t\tconst body: unknown = await response.json();\n\t\t\tfor (const item of Array.isArray(body) ? body : [body]) this.emitMessage(parseJsonRpcMessage(item));\n\t\t\treturn;\n\t\t}\n\t\tif (type === \"text/event-stream\" && response.body) {\n\t\t\tvoid this.consumeResponseStream(response.body, message.id);\n\t\t\treturn;\n\t\t}\n\t\tawait discard(response);\n\t\tthrow new McpHttpError(response.status, `Unsupported MCP response content type: ${type ?? \"missing\"}`);\n\t}\n\n\tasync close(): Promise<void> {\n\t\tif (this.closed) return;\n\t\tthis.closed = true;\n\t\tthis.controller.abort();\n\t\tif (this.started && this.sessionIdValue) {\n\t\t\t// Best effort: the session expires on the server anyway. The auth provider may refresh tokens\n\t\t\t// over the network, so it is not asked here and closing never waits for a refresh.\n\t\t\ttry {\n\t\t\t\tconst response = await this.fetch(this.url, {\n\t\t\t\t\tmethod: \"DELETE\",\n\t\t\t\t\theaders: this.buildHeaders({}, this.lastToken),\n\t\t\t\t\tsignal: AbortSignal.timeout(1_000),\n\t\t\t\t});\n\t\t\t\tawait discard(response);\n\t\t\t} catch {}\n\t\t}\n\t\tthis.emitClose();\n\t}\n\n\t/**\n\t * Fetch with auth headers. A 401 (or a 403 asking for more scope) is handed to the auth provider\n\t * once, and the request is retried with whatever credentials it left behind.\n\t */\n\tprivate async authorizedFetch(\n\t\tmethod: \"GET\" | \"POST\",\n\t\tinit: { headers: Record<string, string>; body?: string },\n\t): Promise<Response> {\n\t\tconst onUnauthorized = this.options.authProvider?.onUnauthorized?.bind(this.options.authProvider);\n\t\tfor (let attempt = 0; ; attempt++) {\n\t\t\tconst { headers, token } = await this.headers(init.headers);\n\t\t\tconst response = await this.fetch(this.url, {\n\t\t\t\tmethod,\n\t\t\t\theaders,\n\t\t\t\tbody: init.body,\n\t\t\t\tsignal: this.controller.signal,\n\t\t\t});\n\t\t\tif (attempt > 0 || !onUnauthorized || !needsAuthorization(response)) return response;\n\t\t\ttry {\n\t\t\t\tawait onUnauthorized({ response, serverUrl: this.url, fetch: this.fetch, token });\n\t\t\t} finally {\n\t\t\t\tawait discard(response);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate async headers(extra: Record<string, string> = {}): Promise<{ headers: Headers; token?: string }> {\n\t\tconst token = await this.options.authProvider?.token();\n\t\tthis.lastToken = token;\n\t\treturn { headers: this.buildHeaders(extra, token), ...(token ? { token } : {}) };\n\t}\n\n\tprivate buildHeaders(extra: Record<string, string>, token: string | undefined): Headers {\n\t\tconst headers = new Headers(this.options.headers);\n\t\tfor (const [name, value] of Object.entries(extra)) headers.set(name, value);\n\t\tif (this.sessionIdValue) headers.set(\"Mcp-Session-Id\", this.sessionIdValue);\n\t\tif (this.protocolVersion) headers.set(\"MCP-Protocol-Version\", this.protocolVersion);\n\t\tif (token) headers.set(\"Authorization\", `Bearer ${token}`);\n\t\treturn headers;\n\t}\n\n\tprivate captureSession(response: Response): void {\n\t\tconst sessionId = response.headers.get(\"mcp-session-id\");\n\t\tif (sessionId) this.sessionIdValue = sessionId;\n\t}\n\n\tprivate async checkResponse(response: Response): Promise<void> {\n\t\tif (response.ok) return;\n\t\tconst body = (await response.text().catch(() => \"\")).slice(0, MAX_ERROR_BODY_BYTES);\n\t\tif (response.status === 401) throw new McpAuthRequiredError(response, body);\n\t\tif (response.status === 404 && this.sessionIdValue) throw new McpSessionExpiredError(body);\n\t\tthrow new McpHttpError(response.status, describeHttpFailure(response.status, body), body);\n\t}\n\n\tprivate async consumeSse(\n\t\tstream: ReadableStream<Uint8Array>,\n\t\tcursor: StreamCursor,\n\t\tonMessage?: (message: JsonRpcMessage) => void,\n\t): Promise<void> {\n\t\tawait consumeSseStream(stream, {\n\t\t\tmaxEventBytes: this.options.maxMessageBytes ?? DEFAULT_MAX_MESSAGE_BYTES,\n\t\t\tonId: (id) => {\n\t\t\t\tcursor.lastEventId = id;\n\t\t\t},\n\t\t\tonRetry: (delayMs) => {\n\t\t\t\tcursor.retryMs = delayMs;\n\t\t\t},\n\t\t\tonEvent: (event) => {\n\t\t\t\tcursor.received = true;\n\t\t\t\t// Events without data prime resumption; other event types are not JSON-RPC.\n\t\t\t\tif (!event.data.trim() || (event.event !== undefined && event.event !== \"message\")) return;\n\t\t\t\tlet message: JsonRpcMessage;\n\t\t\t\ttry {\n\t\t\t\t\tmessage = parseJsonRpcMessage(JSON.parse(event.data));\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.emitError(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tonMessage?.(message);\n\t\t\t\tthis.emitMessage(message);\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Read the SSE stream answering one request. When the stream ends or breaks before the response\n\t * arrives and the server assigned event IDs, resume it with GET and `Last-Event-ID`, as the\n\t * server may close response streams at will. Otherwise only this request fails.\n\t */\n\tprivate async consumeResponseStream(body: ReadableStream<Uint8Array>, requestId: JsonRpcId): Promise<void> {\n\t\tconst cursor: StreamCursor = { lastEventId: undefined, retryMs: undefined, received: false };\n\t\tlet answered = false;\n\t\tconst onMessage = (message: JsonRpcMessage) => {\n\t\t\tif (isJsonRpcResponse(message) && message.id === requestId) answered = true;\n\t\t};\n\t\tlet stream: ReadableStream<Uint8Array> | undefined = body;\n\t\tlet failure: unknown;\n\t\tfor (let attempt = 0; ; ) {\n\t\t\tif (stream) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.consumeSse(stream, cursor, onMessage);\n\t\t\t\t\tfailure = undefined;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tfailure = error;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (answered || this.closed) return;\n\t\t\tif (failure !== undefined && !this.isRetryable(failure)) break;\n\t\t\tif (cursor.lastEventId === undefined || attempt >= this.maxRetries()) break;\n\t\t\tif (cursor.received) attempt = 0;\n\t\t\tcursor.received = false;\n\t\t\tif (!(await this.sleep(this.reconnectDelay(attempt++, cursor.retryMs)))) return;\n\t\t\ttry {\n\t\t\t\tstream = await this.openSseStream(cursor.lastEventId);\n\t\t\t} catch (error) {\n\t\t\t\tfailure = error;\n\t\t\t\tif (!this.isRetryable(error)) break;\n\t\t\t\tstream = undefined;\n\t\t\t}\n\t\t}\n\t\tif (this.closed) return;\n\t\tconst reason = failure === undefined ? \"stream ended without a response\" : toError(failure).message;\n\t\tthis.emitMessage({\n\t\t\tjsonrpc: \"2.0\",\n\t\t\tid: requestId,\n\t\t\terror: { code: JSON_RPC_ERROR_CODES.internalError, message: `MCP response stream failed: ${reason}` },\n\t\t});\n\t}\n\n\tprivate startGetStream(): void {\n\t\tif (this.options.openGetStream === false || this.getStreamStarted || this.closed) return;\n\t\tthis.getStreamStarted = true;\n\t\tvoid this.runGetStream();\n\t}\n\n\t/** Keep the server-to-client stream open, reconnecting with backoff when it drops. */\n\tprivate async runGetStream(): Promise<void> {\n\t\tconst cursor: StreamCursor = { lastEventId: undefined, retryMs: undefined, received: false };\n\t\tfor (let attempt = 0; !this.closed; ) {\n\t\t\ttry {\n\t\t\t\tconst stream = await this.openSseStream(cursor.lastEventId);\n\t\t\t\t// The server does not offer a GET stream.\n\t\t\t\tif (!stream) return;\n\t\t\t\tconst openedAt = Date.now();\n\t\t\t\tawait this.consumeSse(stream, cursor);\n\t\t\t\t// A stream that stayed up for a while counts as healthy, even if it was idle.\n\t\t\t\tif (cursor.received || Date.now() - openedAt > this.maxDelay()) attempt = 0;\n\t\t\t} catch (error) {\n\t\t\t\tif (this.closed) return;\n\t\t\t\tif (!this.isRetryable(error)) {\n\t\t\t\t\tthis.emitError(error);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t\tcursor.received = false;\n\t\t\tif (attempt >= this.maxRetries()) {\n\t\t\t\tthis.emitError(new Error(\"MCP server-to-client stream dropped and could not be reopened\"));\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (!(await this.sleep(this.reconnectDelay(attempt++, cursor.retryMs)))) return;\n\t\t}\n\t}\n\n\t/** Open a GET SSE stream. Resolves to undefined when the server answers 405 (no GET stream). */\n\tprivate async openSseStream(lastEventId: string | undefined): Promise<ReadableStream<Uint8Array> | undefined> {\n\t\tconst response = await this.authorizedFetch(\"GET\", {\n\t\t\theaders: {\n\t\t\t\taccept: \"text/event-stream\",\n\t\t\t\t...(lastEventId === undefined ? {} : { \"last-event-id\": lastEventId }),\n\t\t\t},\n\t\t});\n\t\tif (response.status === 405) {\n\t\t\tawait discard(response);\n\t\t\treturn undefined;\n\t\t}\n\t\tawait this.checkResponse(response);\n\t\tthis.captureSession(response);\n\t\tconst type = contentType(response);\n\t\tif (type !== \"text/event-stream\" || !response.body) {\n\t\t\tawait discard(response);\n\t\t\tthrow new McpHttpError(response.status, `Unsupported MCP GET response content type: ${type ?? \"missing\"}`);\n\t\t}\n\t\treturn response.body;\n\t}\n\n\t/**\n\t * Network failures and transient statuses are retried; auth, session, and protocol errors are not.\n\t * `fetch` reports network failures, including a connection dropped mid-body, as `TypeError`.\n\t */\n\tprivate isRetryable(error: unknown): boolean {\n\t\tif (error instanceof McpHttpError) return isTransientStatus(error.status);\n\t\tif (error instanceof TypeError) return true;\n\t\tconst code = (error as { code?: unknown } | undefined)?.code;\n\t\treturn typeof code === \"string\" && (code.startsWith(\"E\") || code.startsWith(\"UND_ERR\"));\n\t}\n\n\tprivate reconnectDelay(attempt: number, serverDelayMs: number | undefined): number {\n\t\tif (serverDelayMs !== undefined) return serverDelayMs;\n\t\tconst initial = this.options.reconnect?.initialDelayMs ?? DEFAULT_RECONNECT_INITIAL_DELAY_MS;\n\t\treturn Math.min(initial * 2 ** attempt, this.maxDelay());\n\t}\n\n\tprivate maxDelay(): number {\n\t\treturn this.options.reconnect?.maxDelayMs ?? DEFAULT_RECONNECT_MAX_DELAY_MS;\n\t}\n\n\tprivate maxRetries(): number {\n\t\treturn this.options.reconnect?.maxRetries ?? DEFAULT_RECONNECT_MAX_RETRIES;\n\t}\n\n\t/** Resolves false when the transport closed while waiting. */\n\tprivate sleep(ms: number): Promise<boolean> {\n\t\tconst signal = this.controller.signal;\n\t\tif (signal.aborted) return Promise.resolve(false);\n\t\treturn new Promise((resolve) => {\n\t\t\tconst onAbort = () => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(false);\n\t\t\t};\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\tresolve(true);\n\t\t\t}, ms);\n\t\t\t// A reconnect wait alone does not keep the process alive.\n\t\t\ttimer.unref?.();\n\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t});\n\t}\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@earendil-works/pi-mcp",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Standalone Model Context Protocol client for pi and other applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/cross-spawn": "6.0.6",
|
|
58
|
-
"shx": "0.4
|
|
58
|
+
"shx": "0.3.4",
|
|
59
59
|
"vitest": "4.1.11"
|
|
60
60
|
}
|
|
61
61
|
}
|