toolcraft 0.0.306 → 0.0.308
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/composition.json +3 -3
- package/dist/composition.json +3 -3
- package/node_modules/tiny-http-mcp-server/dist/composition.json +1 -1
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/README.md +22 -1
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/default-oauth-client-provider.js +27 -13
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/loopback-authorization.d.ts +5 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/loopback-authorization.js +134 -72
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.d.ts +2 -0
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/token-endpoint.js +5 -1
- package/node_modules/tiny-http-mcp-server/node_modules/mcp-oauth/dist/client/types.d.ts +9 -1
- package/node_modules/tiny-http-mcp-server/package.json +1 -1
- package/node_modules/tiny-mcp-client/README.md +3 -1
- package/node_modules/tiny-mcp-client/dist/index.d.ts +12 -2
- package/node_modules/tiny-mcp-client/dist/index.js +235 -115
- package/node_modules/tiny-stdio-mcp-server/dist/composition.json +1 -1
- package/node_modules/toolcraft-schema/README.md +7 -0
- package/node_modules/toolcraft-schema/dist/index.d.ts +1 -0
- package/node_modules/toolcraft-schema/dist/json.d.ts +5 -1
- package/node_modules/toolcraft-schema/dist/json.js +9 -3
- package/node_modules/toolcraft-schema/package.json +1 -1
- package/package.json +2 -2
|
@@ -152,11 +152,17 @@ var HttpResponseMessages = class {
|
|
|
152
152
|
};
|
|
153
153
|
|
|
154
154
|
// ../toolcraft-schema/dist/json.js
|
|
155
|
-
function isJsonValue(value) {
|
|
155
|
+
function isJsonValue(value, options = {}) {
|
|
156
|
+
const maxNodes = options.maxNodes ?? 1e4;
|
|
157
|
+
const maxDepth = options.maxDepth ?? 64;
|
|
158
|
+
if (!Number.isSafeInteger(maxNodes) || maxNodes < 1)
|
|
159
|
+
throw new Error("maxNodes must be a positive safe integer");
|
|
160
|
+
if (!Number.isSafeInteger(maxDepth) || maxDepth < 0 || maxDepth > 256)
|
|
161
|
+
throw new Error("maxDepth must be an integer between 0 and 256");
|
|
156
162
|
const ancestors = /* @__PURE__ */ new Set();
|
|
157
163
|
let nodes = 0;
|
|
158
164
|
const visit = (item, depth) => {
|
|
159
|
-
if (++nodes >
|
|
165
|
+
if (++nodes > maxNodes || depth > maxDepth)
|
|
160
166
|
return false;
|
|
161
167
|
if (item === null || typeof item === "string" || typeof item === "boolean")
|
|
162
168
|
return true;
|
|
@@ -182,7 +188,7 @@ function isJsonValue(value) {
|
|
|
182
188
|
ancestors.add(item);
|
|
183
189
|
let valid = true;
|
|
184
190
|
if (Array.isArray(item)) {
|
|
185
|
-
if (item.length >
|
|
191
|
+
if (item.length > maxNodes)
|
|
186
192
|
valid = false;
|
|
187
193
|
else
|
|
188
194
|
for (let index = 0; index < item.length; index++) {
|
|
@@ -4102,47 +4108,137 @@ function getOwnEntry4(record2, key2) {
|
|
|
4102
4108
|
|
|
4103
4109
|
// ../mcp-oauth/dist/client/loopback-authorization.js
|
|
4104
4110
|
async function createLoopbackAuthorizationSession(options = {}) {
|
|
4105
|
-
|
|
4111
|
+
options.signal?.throwIfAborted();
|
|
4112
|
+
const timeoutMs = options.timeoutMs ?? 12e4;
|
|
4113
|
+
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 2147483647)
|
|
4114
|
+
throw new Error("OAuth authorization timeoutMs must be a positive supported timer interval");
|
|
4115
|
+
const target = loopbackTarget(options);
|
|
4106
4116
|
const server = options.createServer ? options.createServer() : http.createServer();
|
|
4107
|
-
const
|
|
4108
|
-
|
|
4117
|
+
const controller = new AbortController();
|
|
4118
|
+
let closed = false;
|
|
4119
|
+
let used = false;
|
|
4120
|
+
const callerAbort = () => controller.abort(options.signal?.reason);
|
|
4121
|
+
const teardown = () => {
|
|
4122
|
+
if (closed)
|
|
4123
|
+
return;
|
|
4124
|
+
closed = true;
|
|
4125
|
+
clearTimeout(timer);
|
|
4126
|
+
options.signal?.removeEventListener("abort", callerAbort);
|
|
4127
|
+
server.closeAllConnections?.();
|
|
4128
|
+
server.close();
|
|
4129
|
+
};
|
|
4130
|
+
const timer = setTimeout(() => controller.abort(new Error("OAuth authorization timed out")), timeoutMs);
|
|
4131
|
+
timer.unref?.();
|
|
4132
|
+
controller.signal.addEventListener("abort", teardown, { once: true });
|
|
4133
|
+
options.signal?.addEventListener("abort", callerAbort, { once: true });
|
|
4134
|
+
if (options.signal?.aborted)
|
|
4135
|
+
callerAbort();
|
|
4136
|
+
let port;
|
|
4137
|
+
try {
|
|
4138
|
+
port = await startServer(server, target.port, target.host, controller.signal);
|
|
4139
|
+
} catch (error) {
|
|
4140
|
+
controller.abort(error);
|
|
4141
|
+
throw error;
|
|
4142
|
+
}
|
|
4143
|
+
const redirectUri = options.redirectUri ?? `http://127.0.0.1:${port}${target.callbackPath}`;
|
|
4109
4144
|
return {
|
|
4110
4145
|
redirectUri,
|
|
4111
4146
|
async waitForCode(authorizationUrl) {
|
|
4112
|
-
|
|
4147
|
+
controller.signal.throwIfAborted();
|
|
4148
|
+
if (used)
|
|
4149
|
+
throw new Error("OAuth authorization session has already been used");
|
|
4150
|
+
used = true;
|
|
4151
|
+
try {
|
|
4152
|
+
return await waitForAuthorizationCode(server, authorizationUrl, options, target.callbackPath, controller.signal);
|
|
4153
|
+
} finally {
|
|
4154
|
+
clearTimeout(timer);
|
|
4155
|
+
}
|
|
4113
4156
|
},
|
|
4114
4157
|
close() {
|
|
4115
|
-
|
|
4116
|
-
server.close();
|
|
4158
|
+
controller.abort(new Error("OAuth authorization session closed"));
|
|
4117
4159
|
}
|
|
4118
4160
|
};
|
|
4119
4161
|
}
|
|
4120
|
-
|
|
4162
|
+
function loopbackTarget(options) {
|
|
4163
|
+
if (options.redirectUri !== void 0) {
|
|
4164
|
+
let url;
|
|
4165
|
+
try {
|
|
4166
|
+
url = new URL(options.redirectUri);
|
|
4167
|
+
} catch (cause) {
|
|
4168
|
+
throw new Error("Invalid OAuth loopback redirect URI", { cause });
|
|
4169
|
+
}
|
|
4170
|
+
const forbiddenQuery = ["code", "state", "error", "error_description", "iss"];
|
|
4171
|
+
if (url.protocol !== "http:" || !["localhost", "127.0.0.1", "[::1]"].includes(url.hostname) || url.username || url.password || url.hash || url.port === "0" || forbiddenQuery.some((name) => url.searchParams.has(name)) || [...options.redirectUri].some((char) => char.codePointAt(0) <= 32) || options.callbackPath !== void 0 && options.callbackPath !== url.pathname)
|
|
4172
|
+
throw new Error("Invalid OAuth loopback redirect URI");
|
|
4173
|
+
return { port: url.port ? Number(url.port) : 80, host: url.hostname === "[::1]" ? "::1" : url.hostname, callbackPath: url.pathname };
|
|
4174
|
+
}
|
|
4175
|
+
const callbackPath = options.callbackPath ?? "/callback";
|
|
4176
|
+
const parsed = new URL(callbackPath, "http://127.0.0.1");
|
|
4177
|
+
if (!callbackPath.startsWith("/") || parsed.origin !== "http://127.0.0.1" || parsed.pathname !== callbackPath || parsed.search || parsed.hash)
|
|
4178
|
+
throw new Error("Invalid OAuth loopback callback path");
|
|
4179
|
+
return { port: 0, host: "127.0.0.1", callbackPath };
|
|
4180
|
+
}
|
|
4181
|
+
async function startServer(server, port, host, signal) {
|
|
4182
|
+
signal.throwIfAborted();
|
|
4121
4183
|
return new Promise((resolve, reject) => {
|
|
4122
|
-
const
|
|
4184
|
+
const cleanup = () => {
|
|
4123
4185
|
server.off("error", handleError);
|
|
4186
|
+
signal.removeEventListener("abort", aborted);
|
|
4187
|
+
};
|
|
4188
|
+
const handleError = (error) => {
|
|
4189
|
+
cleanup();
|
|
4124
4190
|
reject(error);
|
|
4125
4191
|
};
|
|
4192
|
+
const aborted = () => {
|
|
4193
|
+
cleanup();
|
|
4194
|
+
reject(signal.reason);
|
|
4195
|
+
};
|
|
4126
4196
|
server.once("error", handleError);
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4197
|
+
signal.addEventListener("abort", aborted, { once: true });
|
|
4198
|
+
try {
|
|
4199
|
+
server.listen(port, host, () => {
|
|
4200
|
+
cleanup();
|
|
4201
|
+
if (signal.aborted) {
|
|
4202
|
+
server.close();
|
|
4203
|
+
reject(signal.reason);
|
|
4204
|
+
return;
|
|
4205
|
+
}
|
|
4206
|
+
const address = server.address();
|
|
4207
|
+
if (address === null || typeof address === "string") {
|
|
4208
|
+
reject(new Error("OAuth listener has no TCP address"));
|
|
4209
|
+
return;
|
|
4210
|
+
}
|
|
4211
|
+
resolve(address.port);
|
|
4212
|
+
});
|
|
4213
|
+
} catch (error) {
|
|
4214
|
+
cleanup();
|
|
4215
|
+
reject(error);
|
|
4216
|
+
}
|
|
4132
4217
|
});
|
|
4133
4218
|
}
|
|
4134
|
-
function waitForAuthorizationCode(server, authorizationUrl, options, callbackPath) {
|
|
4219
|
+
function waitForAuthorizationCode(server, authorizationUrl, options, callbackPath, signal) {
|
|
4220
|
+
signal.throwIfAborted();
|
|
4135
4221
|
const expectedAuthorization = readExpectedAuthorizationCallback(authorizationUrl);
|
|
4136
4222
|
return new Promise((resolve, reject) => {
|
|
4137
4223
|
let settled = false;
|
|
4138
4224
|
const settle = (fn) => {
|
|
4139
|
-
if (
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4225
|
+
if (settled)
|
|
4226
|
+
return;
|
|
4227
|
+
settled = true;
|
|
4228
|
+
server.off("request", request);
|
|
4229
|
+
signal.removeEventListener("abort", aborted);
|
|
4230
|
+
fn();
|
|
4143
4231
|
};
|
|
4144
|
-
|
|
4145
|
-
|
|
4232
|
+
const aborted = () => settle(() => reject(signal.reason));
|
|
4233
|
+
const request = (req, res) => {
|
|
4234
|
+
let url;
|
|
4235
|
+
try {
|
|
4236
|
+
url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
4237
|
+
} catch {
|
|
4238
|
+
res.writeHead(400);
|
|
4239
|
+
res.end("Invalid callback URL");
|
|
4240
|
+
return;
|
|
4241
|
+
}
|
|
4146
4242
|
if (url.pathname !== callbackPath) {
|
|
4147
4243
|
res.writeHead(404);
|
|
4148
4244
|
res.end("Not found");
|
|
@@ -4157,21 +4253,8 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
|
|
|
4157
4253
|
};
|
|
4158
4254
|
try {
|
|
4159
4255
|
validateAuthorizationCallbackBinding(callbackParameters, expectedAuthorization);
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
res.end(error instanceof Error ? error.message : "Invalid OAuth callback");
|
|
4163
|
-
settle(() => reject(error instanceof Error ? error : new Error(String(error))));
|
|
4164
|
-
return;
|
|
4165
|
-
}
|
|
4166
|
-
const authorizationError = callbackParameters.error;
|
|
4167
|
-
if (authorizationError !== null) {
|
|
4168
|
-
const description = callbackParameters.errorDescription ?? authorizationError;
|
|
4169
|
-
res.writeHead(400);
|
|
4170
|
-
res.end(`Authorization failed: ${description}`);
|
|
4171
|
-
settle(() => reject(createAuthorizationError(authorizationError, description)));
|
|
4172
|
-
return;
|
|
4173
|
-
}
|
|
4174
|
-
try {
|
|
4256
|
+
if (callbackParameters.error !== null)
|
|
4257
|
+
throw createAuthorizationError(callbackParameters.error, callbackParameters.errorDescription ?? callbackParameters.error);
|
|
4175
4258
|
const code = validateAuthorizationCallbackParameters(callbackParameters, expectedAuthorization);
|
|
4176
4259
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
4177
4260
|
res.end(buildSuccessPage(options.landingPage));
|
|
@@ -4179,35 +4262,27 @@ function waitForAuthorizationCode(server, authorizationUrl, options, callbackPat
|
|
|
4179
4262
|
} catch (error) {
|
|
4180
4263
|
res.writeHead(400);
|
|
4181
4264
|
res.end(error instanceof Error ? error.message : "Invalid OAuth callback");
|
|
4182
|
-
settle(() => reject(error
|
|
4265
|
+
settle(() => reject(error));
|
|
4183
4266
|
}
|
|
4184
|
-
}
|
|
4267
|
+
};
|
|
4268
|
+
server.on("request", request);
|
|
4269
|
+
signal.addEventListener("abort", aborted, { once: true });
|
|
4185
4270
|
if (options.readLine !== void 0) {
|
|
4186
|
-
options.readLine().then((input) => {
|
|
4187
|
-
|
|
4188
|
-
if (callbackParameters === null) {
|
|
4189
|
-
settle(() => reject(new Error("OAuth callback missing authorization code")));
|
|
4271
|
+
void Promise.resolve().then(() => settled ? void 0 : options.readLine()).then((input) => {
|
|
4272
|
+
if (settled)
|
|
4190
4273
|
return;
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
} catch (error) {
|
|
4201
|
-
settle(() => reject(error instanceof Error ? error : new Error(String(error))));
|
|
4202
|
-
}
|
|
4203
|
-
}).catch((error) => {
|
|
4204
|
-
settle(() => reject(error instanceof Error ? error : new Error(String(error))));
|
|
4205
|
-
});
|
|
4274
|
+
const callbackParameters = extractCallbackParametersFromInput(input);
|
|
4275
|
+
if (callbackParameters === null)
|
|
4276
|
+
throw new Error("OAuth callback missing authorization code");
|
|
4277
|
+
validateAuthorizationCallbackBinding(callbackParameters, expectedAuthorization);
|
|
4278
|
+
if (callbackParameters.error !== null)
|
|
4279
|
+
throw createAuthorizationError(callbackParameters.error, callbackParameters.errorDescription ?? callbackParameters.error);
|
|
4280
|
+
const code = validateAuthorizationCallbackParameters(callbackParameters, expectedAuthorization);
|
|
4281
|
+
settle(() => resolve(code));
|
|
4282
|
+
}).catch((error) => settle(() => reject(error)));
|
|
4206
4283
|
}
|
|
4207
4284
|
if (options.openBrowser !== void 0) {
|
|
4208
|
-
options.openBrowser(authorizationUrl).catch((error) =>
|
|
4209
|
-
settle(() => reject(error));
|
|
4210
|
-
});
|
|
4285
|
+
void Promise.resolve().then(() => settled ? void 0 : options.openBrowser(authorizationUrl)).catch((error) => settle(() => reject(error)));
|
|
4211
4286
|
}
|
|
4212
4287
|
});
|
|
4213
4288
|
}
|
|
@@ -4387,6 +4462,7 @@ async function exchangeAuthorizationCode(input) {
|
|
|
4387
4462
|
resource
|
|
4388
4463
|
},
|
|
4389
4464
|
fetch: input.fetch,
|
|
4465
|
+
signal: input.signal,
|
|
4390
4466
|
now: input.now
|
|
4391
4467
|
});
|
|
4392
4468
|
}
|
|
@@ -4402,6 +4478,7 @@ async function refreshAccessToken(input) {
|
|
|
4402
4478
|
resource
|
|
4403
4479
|
},
|
|
4404
4480
|
fetch: input.fetch,
|
|
4481
|
+
signal: input.signal,
|
|
4405
4482
|
now: input.now
|
|
4406
4483
|
});
|
|
4407
4484
|
}
|
|
@@ -4413,7 +4490,9 @@ async function requestTokens(input) {
|
|
|
4413
4490
|
if (input.clientSecret !== void 0) {
|
|
4414
4491
|
body.set("client_secret", input.clientSecret);
|
|
4415
4492
|
}
|
|
4416
|
-
|
|
4493
|
+
input.signal?.throwIfAborted();
|
|
4494
|
+
const deadline = AbortSignal.timeout(3e4);
|
|
4495
|
+
const signal = input.signal === void 0 ? deadline : AbortSignal.any([input.signal, deadline]);
|
|
4417
4496
|
const response = await fetchMcpResponse(input.fetch, input.tokenEndpoint, {
|
|
4418
4497
|
method: "POST",
|
|
4419
4498
|
headers: {
|
|
@@ -4525,7 +4604,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4525
4604
|
async authorizeRequest(input) {
|
|
4526
4605
|
assertNoAccessTokenInUrl(input.requestUrl, "Protected resource request URL");
|
|
4527
4606
|
const requestUrl = canonicalizeResourceIndicator(input.requestUrl);
|
|
4528
|
-
const session = await ensureAuthorizedSession(requestUrl, void 0, input.fetch, false);
|
|
4607
|
+
const session = await ensureAuthorizedSession(requestUrl, void 0, input.fetch, false, false, input.signal);
|
|
4529
4608
|
const accessToken = session?.tokens?.accessToken;
|
|
4530
4609
|
if (session === null || accessToken === void 0 || session.tokens === void 0 || isExpired(session.tokens, now)) {
|
|
4531
4610
|
return;
|
|
@@ -4543,12 +4622,13 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4543
4622
|
const session = await ensureAuthorizedSession(resource, {
|
|
4544
4623
|
...input.discovery,
|
|
4545
4624
|
resource
|
|
4546
|
-
}, input.fetch, true, forceRefresh);
|
|
4625
|
+
}, input.fetch, true, forceRefresh, input.signal);
|
|
4547
4626
|
if (session?.tokens?.accessToken === void 0) {
|
|
4548
4627
|
return { action: "fail" };
|
|
4549
4628
|
}
|
|
4550
4629
|
return { action: "retry" };
|
|
4551
4630
|
} catch (error) {
|
|
4631
|
+
input.signal?.throwIfAborted();
|
|
4552
4632
|
return {
|
|
4553
4633
|
action: "fail",
|
|
4554
4634
|
error: error instanceof Error ? error : new Error(String(error))
|
|
@@ -4556,9 +4636,11 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4556
4636
|
}
|
|
4557
4637
|
}
|
|
4558
4638
|
};
|
|
4559
|
-
async function ensureAuthorizedSession(resource, discovery, fetch2, allowInteractive, forceRefresh = false) {
|
|
4639
|
+
async function ensureAuthorizedSession(resource, discovery, fetch2, allowInteractive, forceRefresh = false, signal) {
|
|
4640
|
+
signal?.throwIfAborted();
|
|
4560
4641
|
const canonicalResource = canonicalizeResourceIndicator(resource);
|
|
4561
4642
|
let session = await loadSession(canonicalResource);
|
|
4643
|
+
signal?.throwIfAborted();
|
|
4562
4644
|
if (discovery !== void 0 && getOwnString2(discovery.authorizationServerMetadata, "issuer") !== discovery.authorizationServer) {
|
|
4563
4645
|
throw new Error("OAuth discovery authorization-server issuer mismatch");
|
|
4564
4646
|
}
|
|
@@ -4571,7 +4653,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4571
4653
|
return session;
|
|
4572
4654
|
}
|
|
4573
4655
|
if (session?.tokens?.refreshToken !== void 0 && sessionDiscovery !== void 0 && (forceRefresh || isExpired(session.tokens, now))) {
|
|
4574
|
-
session = await refreshSession(canonicalResource, session, sessionDiscovery, fetch2);
|
|
4656
|
+
session = await refreshSession(canonicalResource, session, sessionDiscovery, fetch2, signal);
|
|
4575
4657
|
if (session?.tokens !== void 0 && !isExpired(session.tokens, now)) {
|
|
4576
4658
|
return session;
|
|
4577
4659
|
}
|
|
@@ -4583,9 +4665,12 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4583
4665
|
if (!allowInteractive || sessionDiscovery === void 0) {
|
|
4584
4666
|
return session;
|
|
4585
4667
|
}
|
|
4586
|
-
|
|
4668
|
+
if (options.allowInteractive === false)
|
|
4669
|
+
throw new Error("OAuth interactive authorization is disabled");
|
|
4670
|
+
return authorizeSession(canonicalResource, session, sessionDiscovery, fetch2, signal);
|
|
4587
4671
|
}
|
|
4588
|
-
async function refreshSession(resource, session, discovery, fetch2) {
|
|
4672
|
+
async function refreshSession(resource, session, discovery, fetch2, signal) {
|
|
4673
|
+
signal?.throwIfAborted();
|
|
4589
4674
|
assertSecureOAuthFlowEndpoints(discovery.authorizationServerMetadata);
|
|
4590
4675
|
const inFlight = refreshPromises.get(resource);
|
|
4591
4676
|
if (inFlight !== void 0) {
|
|
@@ -4607,10 +4692,12 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4607
4692
|
refreshToken: session.tokens.refreshToken,
|
|
4608
4693
|
resource,
|
|
4609
4694
|
fetch: fetch2,
|
|
4695
|
+
signal,
|
|
4610
4696
|
now
|
|
4611
4697
|
});
|
|
4612
4698
|
break;
|
|
4613
4699
|
} catch (error) {
|
|
4700
|
+
signal?.throwIfAborted();
|
|
4614
4701
|
if (error instanceof OAuthError && error.error === "invalid_grant") {
|
|
4615
4702
|
const clearedSession = clearSessionTokens(session);
|
|
4616
4703
|
await saveSession(resource, clearedSession);
|
|
@@ -4645,7 +4732,8 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4645
4732
|
refreshPromises.set(resource, promise);
|
|
4646
4733
|
return promise;
|
|
4647
4734
|
}
|
|
4648
|
-
async function authorizeSession(resource, existingSession, discovery, fetch2) {
|
|
4735
|
+
async function authorizeSession(resource, existingSession, discovery, fetch2, signal) {
|
|
4736
|
+
signal?.throwIfAborted();
|
|
4649
4737
|
const inFlight = authorizationPromises.get(resource);
|
|
4650
4738
|
if (inFlight !== void 0) {
|
|
4651
4739
|
return inFlight;
|
|
@@ -4661,11 +4749,14 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4661
4749
|
openBrowser: options.browser.openBrowser,
|
|
4662
4750
|
readLine: options.browser.readLine,
|
|
4663
4751
|
createServer: options.browser.createServer,
|
|
4664
|
-
landingPage: options.browser.landingPage
|
|
4752
|
+
landingPage: options.browser.landingPage,
|
|
4753
|
+
redirectUri: options.browser.redirectUri,
|
|
4754
|
+
signal: options.browser.signal === void 0 ? signal : signal === void 0 ? options.browser.signal : AbortSignal.any([signal, options.browser.signal]),
|
|
4755
|
+
timeoutMs: options.browser.timeoutMs
|
|
4665
4756
|
});
|
|
4666
4757
|
let resolvedClient = null;
|
|
4667
4758
|
try {
|
|
4668
|
-
resolvedClient = await resolveClient(currentSession, discovery, loopback.redirectUri, fetch2);
|
|
4759
|
+
resolvedClient = await resolveClient(currentSession, discovery, loopback.redirectUri, fetch2, signal);
|
|
4669
4760
|
const sessionWithoutTokens = {
|
|
4670
4761
|
resource,
|
|
4671
4762
|
authorizationServer: discovery.authorizationServer,
|
|
@@ -4693,6 +4784,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4693
4784
|
redirectUri: loopback.redirectUri,
|
|
4694
4785
|
resource,
|
|
4695
4786
|
fetch: fetch2,
|
|
4787
|
+
signal,
|
|
4696
4788
|
now
|
|
4697
4789
|
});
|
|
4698
4790
|
const session = {
|
|
@@ -4702,6 +4794,7 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4702
4794
|
await saveSession(resource, session);
|
|
4703
4795
|
return session;
|
|
4704
4796
|
} catch (error) {
|
|
4797
|
+
signal?.throwIfAborted();
|
|
4705
4798
|
if (shouldReRegisterStoredDynamicClient(error, resolvedClient, reRegistrationAttempted)) {
|
|
4706
4799
|
reRegistrationAttempted = true;
|
|
4707
4800
|
await clearRegisteredClient(discovery.authorizationServer);
|
|
@@ -4727,7 +4820,8 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4727
4820
|
authorizationPromises.set(resource, finalPromise);
|
|
4728
4821
|
return finalPromise;
|
|
4729
4822
|
}
|
|
4730
|
-
async function resolveClient(existingSession, discovery, redirectUri, fetch2) {
|
|
4823
|
+
async function resolveClient(existingSession, discovery, redirectUri, fetch2, parentSignal) {
|
|
4824
|
+
parentSignal?.throwIfAborted();
|
|
4731
4825
|
const configuredClient = normalizeConfiguredClient(options.client);
|
|
4732
4826
|
if (options.client.mode === "static") {
|
|
4733
4827
|
if (configuredClient === null) {
|
|
@@ -4777,7 +4871,8 @@ function createDefaultOAuthClientProvider(options) {
|
|
|
4777
4871
|
}
|
|
4778
4872
|
}
|
|
4779
4873
|
const registrationBody = buildClientRegistrationBody(getClientMetadata(options.client), redirectUri);
|
|
4780
|
-
const
|
|
4874
|
+
const deadline = AbortSignal.timeout(3e4);
|
|
4875
|
+
const signal = parentSignal === void 0 ? deadline : AbortSignal.any([parentSignal, deadline]);
|
|
4781
4876
|
const response = await fetchMcpResponse(fetch2, registrationEndpoint, {
|
|
4782
4877
|
method: "POST",
|
|
4783
4878
|
headers: {
|
|
@@ -5340,8 +5435,10 @@ async function readJsonResponse(response, label, signal) {
|
|
|
5340
5435
|
throw new Error(`${label} response must be valid JSON`);
|
|
5341
5436
|
}
|
|
5342
5437
|
}
|
|
5343
|
-
async function fetchMetadata(fetch2, location, label) {
|
|
5344
|
-
|
|
5438
|
+
async function fetchMetadata(fetch2, location, label, parentSignal) {
|
|
5439
|
+
parentSignal?.throwIfAborted();
|
|
5440
|
+
const deadline = AbortSignal.timeout(1e4);
|
|
5441
|
+
const signal = parentSignal === void 0 ? deadline : AbortSignal.any([deadline, parentSignal]);
|
|
5345
5442
|
const response = await fetchMcpResponse(fetch2, location, {
|
|
5346
5443
|
method: "GET",
|
|
5347
5444
|
headers: { Accept: "application/json" },
|
|
@@ -5443,7 +5540,7 @@ var OAuthMetadataDiscovery = class {
|
|
|
5443
5540
|
this.fetchImpl = fetch2;
|
|
5444
5541
|
this.cache = cache;
|
|
5445
5542
|
}
|
|
5446
|
-
async discoverProtectedResource(resource, resourceMetadataUrl) {
|
|
5543
|
+
async discoverProtectedResource(resource, resourceMetadataUrl, signal) {
|
|
5447
5544
|
const locations = /* @__PURE__ */ new Set([resolveProtectedResourceMetadataUrl(resource, resourceMetadataUrl)]);
|
|
5448
5545
|
if (resourceMetadataUrl === void 0) {
|
|
5449
5546
|
locations.add(new URL("/.well-known/oauth-protected-resource", resource).toString());
|
|
@@ -5452,17 +5549,19 @@ var OAuthMetadataDiscovery = class {
|
|
|
5452
5549
|
for (const location of locations) {
|
|
5453
5550
|
try {
|
|
5454
5551
|
const metadata = validateProtectedResourceMetadata(
|
|
5455
|
-
await fetchMetadata(this.fetchImpl, location, "Protected resource metadata"),
|
|
5552
|
+
await fetchMetadata(this.fetchImpl, location, "Protected resource metadata", signal),
|
|
5456
5553
|
resource
|
|
5457
5554
|
);
|
|
5458
5555
|
return { location, metadata };
|
|
5459
5556
|
} catch (error) {
|
|
5557
|
+
signal?.throwIfAborted();
|
|
5460
5558
|
lastError = error;
|
|
5461
5559
|
}
|
|
5462
5560
|
}
|
|
5463
5561
|
throw lastError;
|
|
5464
5562
|
}
|
|
5465
|
-
async discover(resourceUrl, { resourceMetadataUrl } = {}) {
|
|
5563
|
+
async discover(resourceUrl, { resourceMetadataUrl, signal } = {}) {
|
|
5564
|
+
signal?.throwIfAborted();
|
|
5466
5565
|
const cacheKey = canonicalizeResourceIndicator(resourceUrl);
|
|
5467
5566
|
resolveProtectedResourceMetadataUrl(cacheKey, resourceMetadataUrl);
|
|
5468
5567
|
const memoryCachedResult = this.memoryCache.get(cacheKey);
|
|
@@ -5470,6 +5569,7 @@ var OAuthMetadataDiscovery = class {
|
|
|
5470
5569
|
return structuredClone(memoryCachedResult);
|
|
5471
5570
|
}
|
|
5472
5571
|
const sharedCachedResult = await this.cache?.get(cacheKey);
|
|
5572
|
+
signal?.throwIfAborted();
|
|
5473
5573
|
if (sharedCachedResult !== null && sharedCachedResult !== void 0 && resourceMetadataUrl === void 0) {
|
|
5474
5574
|
try {
|
|
5475
5575
|
const result = validateCachedDiscovery(sharedCachedResult, cacheKey);
|
|
@@ -5479,7 +5579,7 @@ var OAuthMetadataDiscovery = class {
|
|
|
5479
5579
|
await this.cache?.delete?.(cacheKey);
|
|
5480
5580
|
}
|
|
5481
5581
|
}
|
|
5482
|
-
const { location: resourceMetadataLocation, metadata: resourceMetadata } = await this.discoverProtectedResource(cacheKey, resourceMetadataUrl);
|
|
5582
|
+
const { location: resourceMetadataLocation, metadata: resourceMetadata } = await this.discoverProtectedResource(cacheKey, resourceMetadataUrl, signal);
|
|
5483
5583
|
const authorizationServerErrors = [];
|
|
5484
5584
|
for (const authorizationServer of resourceMetadata.authorization_servers) {
|
|
5485
5585
|
const normalizedAuthorizationServer = validateAuthorizationServerIssuer(authorizationServer);
|
|
@@ -5487,7 +5587,7 @@ var OAuthMetadataDiscovery = class {
|
|
|
5487
5587
|
for (const authorizationServerMetadataUrl of metadataLocations) {
|
|
5488
5588
|
try {
|
|
5489
5589
|
const authorizationServerMetadata = validateAuthorizationServerMetadata(
|
|
5490
|
-
await fetchMetadata(this.fetchImpl, authorizationServerMetadataUrl, "Authorization server metadata"),
|
|
5590
|
+
await fetchMetadata(this.fetchImpl, authorizationServerMetadataUrl, "Authorization server metadata", signal),
|
|
5491
5591
|
normalizedAuthorizationServer
|
|
5492
5592
|
);
|
|
5493
5593
|
const result = {
|
|
@@ -5502,6 +5602,7 @@ var OAuthMetadataDiscovery = class {
|
|
|
5502
5602
|
await this.cache?.set(cacheKey, structuredClone(result));
|
|
5503
5603
|
return result;
|
|
5504
5604
|
} catch (error) {
|
|
5605
|
+
signal?.throwIfAborted();
|
|
5505
5606
|
authorizationServerErrors.push(
|
|
5506
5607
|
`${authorizationServerMetadataUrl}: ${error instanceof Error ? error.message : String(error)}`
|
|
5507
5608
|
);
|
|
@@ -6642,6 +6743,7 @@ var HttpTransport = class {
|
|
|
6642
6743
|
oauthProvider;
|
|
6643
6744
|
oauthMetadataDiscovery;
|
|
6644
6745
|
inFlightFetchAbortControllers = /* @__PURE__ */ new Set();
|
|
6746
|
+
inFlightOAuthAbortControllers = /* @__PURE__ */ new Set();
|
|
6645
6747
|
openResponseReaders = /* @__PURE__ */ new Set();
|
|
6646
6748
|
modernRequests = /* @__PURE__ */ new Map();
|
|
6647
6749
|
modernMode = false;
|
|
@@ -6711,7 +6813,7 @@ var HttpTransport = class {
|
|
|
6711
6813
|
this.rejectLegacyEndpoint = void 0;
|
|
6712
6814
|
this.resolveLegacyEndpoint = void 0;
|
|
6713
6815
|
this.toolParameterHeaders.clear();
|
|
6714
|
-
this.abortInFlightFetches();
|
|
6816
|
+
this.abortInFlightFetches(reason);
|
|
6715
6817
|
this.cancelOpenResponseReaders();
|
|
6716
6818
|
if (!this.writeStream.destroyed && !this.writeStream.writableEnded) {
|
|
6717
6819
|
this.writeStream.end();
|
|
@@ -6747,12 +6849,14 @@ var HttpTransport = class {
|
|
|
6747
6849
|
this.resolveClosed = void 0;
|
|
6748
6850
|
resolveClosed?.({ reason: closeReason });
|
|
6749
6851
|
}
|
|
6750
|
-
abortInFlightFetches() {
|
|
6751
|
-
for (const controller of this.modernRequests.values()) controller.abort();
|
|
6852
|
+
abortInFlightFetches(reason) {
|
|
6853
|
+
for (const controller of this.modernRequests.values()) controller.abort(reason);
|
|
6752
6854
|
this.modernRequests.clear();
|
|
6753
6855
|
for (const abortController of this.inFlightFetchAbortControllers) {
|
|
6754
|
-
abortController.abort();
|
|
6856
|
+
abortController.abort(reason);
|
|
6755
6857
|
}
|
|
6858
|
+
for (const controller of this.inFlightOAuthAbortControllers) controller.abort(reason);
|
|
6859
|
+
this.inFlightOAuthAbortControllers.clear();
|
|
6756
6860
|
this.inFlightFetchAbortControllers.clear();
|
|
6757
6861
|
}
|
|
6758
6862
|
cancelOpenResponseReaders() {
|
|
@@ -6818,7 +6922,7 @@ var HttpTransport = class {
|
|
|
6818
6922
|
const response = await this.fetchWithOAuthRetry({
|
|
6819
6923
|
url: postUrl,
|
|
6820
6924
|
method: "POST",
|
|
6821
|
-
createHeaders: () => this.createPostHeaders(message, modern),
|
|
6925
|
+
createHeaders: (signal) => this.createPostHeaders(message, modern, signal),
|
|
6822
6926
|
body: line,
|
|
6823
6927
|
controller
|
|
6824
6928
|
});
|
|
@@ -6858,7 +6962,7 @@ var HttpTransport = class {
|
|
|
6858
6962
|
this.modernRequests.delete(id);
|
|
6859
6963
|
}
|
|
6860
6964
|
}
|
|
6861
|
-
async createPostHeaders(message, modern = false) {
|
|
6965
|
+
async createPostHeaders(message, modern = false, signal) {
|
|
6862
6966
|
const headers = new Headers(this.headers);
|
|
6863
6967
|
headers.set("Accept", "application/json, text/event-stream");
|
|
6864
6968
|
headers.set("Content-Type", "application/json");
|
|
@@ -6888,9 +6992,9 @@ var HttpTransport = class {
|
|
|
6888
6992
|
headers.set("Mcp-Session-Id", this.sessionId);
|
|
6889
6993
|
headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
|
|
6890
6994
|
}
|
|
6891
|
-
return this.authorizeRequestHeaders(headers);
|
|
6995
|
+
return this.authorizeRequestHeaders(headers, signal);
|
|
6892
6996
|
}
|
|
6893
|
-
async createGetHeaders() {
|
|
6997
|
+
async createGetHeaders(signal) {
|
|
6894
6998
|
const headers = new Headers(this.headers);
|
|
6895
6999
|
headers.set("Accept", "text/event-stream");
|
|
6896
7000
|
if (this.sessionId !== void 0) {
|
|
@@ -6900,20 +7004,26 @@ var HttpTransport = class {
|
|
|
6900
7004
|
if (this.lastEventId !== void 0) {
|
|
6901
7005
|
headers.set("Last-Event-ID", this.lastEventId);
|
|
6902
7006
|
}
|
|
6903
|
-
return this.authorizeRequestHeaders(headers);
|
|
7007
|
+
return this.authorizeRequestHeaders(headers, signal);
|
|
6904
7008
|
}
|
|
6905
|
-
async createDeleteHeaders(sessionId) {
|
|
7009
|
+
async createDeleteHeaders(sessionId, signal) {
|
|
6906
7010
|
const headers = new Headers(this.headers);
|
|
6907
7011
|
headers.set("Mcp-Session-Id", sessionId);
|
|
6908
7012
|
headers.set("MCP-Protocol-Version", MCP_PROTOCOL_VERSION);
|
|
6909
|
-
return this.authorizeRequestHeaders(headers);
|
|
7013
|
+
return this.authorizeRequestHeaders(headers, signal);
|
|
6910
7014
|
}
|
|
6911
|
-
async authorizeRequestHeaders(headers) {
|
|
7015
|
+
async authorizeRequestHeaders(headers, signal) {
|
|
7016
|
+
signal?.throwIfAborted();
|
|
6912
7017
|
await this.oauthProvider?.authorizeRequest?.({
|
|
6913
7018
|
requestUrl: new URL(this.url),
|
|
6914
7019
|
headers,
|
|
6915
|
-
|
|
7020
|
+
signal,
|
|
7021
|
+
fetch: (url, init) => fetchMcpResponse(this.fetchImpl, url, {
|
|
7022
|
+
...init,
|
|
7023
|
+
signal: signal === void 0 ? init?.signal : init?.signal == null ? signal : AbortSignal.any([signal, init.signal])
|
|
7024
|
+
})
|
|
6916
7025
|
});
|
|
7026
|
+
signal?.throwIfAborted();
|
|
6917
7027
|
return headers;
|
|
6918
7028
|
}
|
|
6919
7029
|
captureSessionId(response) {
|
|
@@ -6950,7 +7060,7 @@ var HttpTransport = class {
|
|
|
6950
7060
|
return this.legacyEndpointReady;
|
|
6951
7061
|
}
|
|
6952
7062
|
async sendSessionTerminationRequest(sessionId, signal) {
|
|
6953
|
-
const headers = await this.createDeleteHeaders(sessionId);
|
|
7063
|
+
const headers = await this.createDeleteHeaders(sessionId, signal);
|
|
6954
7064
|
signal.throwIfAborted();
|
|
6955
7065
|
const response = await fetchMcpResponse(this.fetchImpl, this.url, {
|
|
6956
7066
|
method: "DELETE",
|
|
@@ -6973,7 +7083,7 @@ var HttpTransport = class {
|
|
|
6973
7083
|
async consumeGetSseStream() {
|
|
6974
7084
|
const response = await this.fetchWithOAuthRetry({
|
|
6975
7085
|
method: "GET",
|
|
6976
|
-
createHeaders: () => this.createGetHeaders()
|
|
7086
|
+
createHeaders: (signal) => this.createGetHeaders(signal)
|
|
6977
7087
|
});
|
|
6978
7088
|
if (this.disposed) {
|
|
6979
7089
|
void response.body?.cancel().catch(() => void 0);
|
|
@@ -7056,7 +7166,7 @@ var HttpTransport = class {
|
|
|
7056
7166
|
const message = responseBody.length === 0 ? `HTTP transport POST failed (${statusDescriptor})` : `HTTP transport POST failed (${statusDescriptor}): ${responseBody}`;
|
|
7057
7167
|
throw new HttpTransportError(message, response.status, "POST");
|
|
7058
7168
|
}
|
|
7059
|
-
async maybeHandleUnauthorizedResponse(response) {
|
|
7169
|
+
async maybeHandleUnauthorizedResponse(response, signal) {
|
|
7060
7170
|
if (response.status !== 401 || this.oauthProvider === void 0) {
|
|
7061
7171
|
return false;
|
|
7062
7172
|
}
|
|
@@ -7067,7 +7177,7 @@ var HttpTransport = class {
|
|
|
7067
7177
|
const challenge = parseBearerWwwAuthenticateHeader(response.headers.get("WWW-Authenticate"));
|
|
7068
7178
|
const resourceMetadataUrl = challenge?.params.resource_metadata;
|
|
7069
7179
|
try {
|
|
7070
|
-
const discovery = await discoveryClient.discover(this.url, { resourceMetadataUrl });
|
|
7180
|
+
const discovery = await discoveryClient.discover(this.url, { resourceMetadataUrl, signal });
|
|
7071
7181
|
const providerResponse = response.clone();
|
|
7072
7182
|
let result;
|
|
7073
7183
|
try {
|
|
@@ -7076,8 +7186,13 @@ var HttpTransport = class {
|
|
|
7076
7186
|
response: providerResponse,
|
|
7077
7187
|
challenge,
|
|
7078
7188
|
discovery,
|
|
7079
|
-
|
|
7189
|
+
signal,
|
|
7190
|
+
fetch: (url, init) => fetchMcpResponse(this.fetchImpl, url, {
|
|
7191
|
+
...init,
|
|
7192
|
+
signal: init?.signal == null ? signal : AbortSignal.any([signal, init.signal])
|
|
7193
|
+
})
|
|
7080
7194
|
});
|
|
7195
|
+
signal.throwIfAborted();
|
|
7081
7196
|
} finally {
|
|
7082
7197
|
void providerResponse.body?.cancel().catch(() => void 0);
|
|
7083
7198
|
}
|
|
@@ -7207,25 +7322,30 @@ var HttpTransport = class {
|
|
|
7207
7322
|
`);
|
|
7208
7323
|
}
|
|
7209
7324
|
async fetchWithOAuthRetry(input) {
|
|
7210
|
-
const
|
|
7211
|
-
|
|
7212
|
-
|
|
7325
|
+
const controller = input.controller ?? new AbortController();
|
|
7326
|
+
this.inFlightOAuthAbortControllers.add(controller);
|
|
7327
|
+
const request = async () => {
|
|
7328
|
+
controller.signal.throwIfAborted();
|
|
7329
|
+
const headers = await input.createHeaders(controller.signal);
|
|
7330
|
+
controller.signal.throwIfAborted();
|
|
7331
|
+
return this.fetchWithAbort(input.url ?? this.url, {
|
|
7213
7332
|
method: input.method,
|
|
7214
|
-
headers
|
|
7333
|
+
headers,
|
|
7215
7334
|
body: input.body
|
|
7216
|
-
},
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7335
|
+
}, controller);
|
|
7336
|
+
};
|
|
7337
|
+
try {
|
|
7338
|
+
let response = await request();
|
|
7339
|
+
if (await this.maybeHandleUnauthorizedResponse(response, controller.signal)) response = await request();
|
|
7340
|
+
const oauthError = this.oauthProvider === void 0 ? null : this.readOAuthChallengeError(response);
|
|
7341
|
+
if (oauthError !== null) {
|
|
7342
|
+
void response.body?.cancel().catch(() => void 0);
|
|
7343
|
+
throw oauthError;
|
|
7344
|
+
}
|
|
7345
|
+
return response;
|
|
7346
|
+
} finally {
|
|
7347
|
+
this.inFlightOAuthAbortControllers.delete(controller);
|
|
7227
7348
|
}
|
|
7228
|
-
return response;
|
|
7229
7349
|
}
|
|
7230
7350
|
readOAuthChallengeError(response) {
|
|
7231
7351
|
if (response.status !== 401 && response.status !== 403) {
|