fastmcp 4.22.5 → 4.22.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/FastMCP.cjs +3 -3
- package/dist/FastMCP.js +2 -2
- package/dist/auth/index.cjs +2 -2
- package/dist/auth/index.js +1 -1
- package/dist/{chunk-XPKMA7DH.js → chunk-ISYL7EKR.js} +5 -2
- package/dist/{chunk-XPKMA7DH.js.map → chunk-ISYL7EKR.js.map} +1 -1
- package/dist/{chunk-A6QGY7T7.js → chunk-NI4JFIL4.js} +143 -72
- package/dist/chunk-NI4JFIL4.js.map +1 -0
- package/dist/{chunk-PAWIMJ72.cjs → chunk-QICOIGCH.cjs} +149 -78
- package/dist/chunk-QICOIGCH.cjs.map +1 -0
- package/dist/{chunk-YOBCXNFP.cjs → chunk-YLLBANV4.cjs} +5 -2
- package/dist/chunk-YLLBANV4.cjs.map +1 -0
- package/dist/examples/custom-routes.cjs +3 -3
- package/dist/examples/custom-routes.js +2 -2
- package/dist/openapi/index.cjs +7 -7
- package/dist/openapi/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-A6QGY7T7.js.map +0 -1
- package/dist/chunk-PAWIMJ72.cjs.map +0 -1
- package/dist/chunk-YOBCXNFP.cjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var _chunkYLLBANV4cjs = require('./chunk-YLLBANV4.cjs');
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
var _chunkO22SYZMCcjs = require('./chunk-O22SYZMC.cjs');
|
|
@@ -134,7 +134,7 @@ var DiscoveryDocumentCache = class {
|
|
|
134
134
|
throw error;
|
|
135
135
|
}
|
|
136
136
|
if (!res.ok) {
|
|
137
|
-
await
|
|
137
|
+
await _chunkYLLBANV4cjs.cancelResponseBody.call(void 0, res);
|
|
138
138
|
throw new Error(
|
|
139
139
|
`Failed to fetch discovery document from ${url}: ${res.status} ${res.statusText}`
|
|
140
140
|
);
|
|
@@ -230,7 +230,7 @@ var imageContent = async (input) => {
|
|
|
230
230
|
signal: AbortSignal.timeout(timeoutMs)
|
|
231
231
|
});
|
|
232
232
|
if (!response.ok) {
|
|
233
|
-
await
|
|
233
|
+
await _chunkYLLBANV4cjs.cancelResponseBody.call(void 0, response);
|
|
234
234
|
throw new Error(
|
|
235
235
|
`Server responded with status: ${response.status} - ${response.statusText}`
|
|
236
236
|
);
|
|
@@ -292,7 +292,7 @@ var audioContent = async (input) => {
|
|
|
292
292
|
signal: AbortSignal.timeout(timeoutMs)
|
|
293
293
|
});
|
|
294
294
|
if (!response.ok) {
|
|
295
|
-
await
|
|
295
|
+
await _chunkYLLBANV4cjs.cancelResponseBody.call(void 0, response);
|
|
296
296
|
throw new Error(
|
|
297
297
|
`Server responded with status: ${response.status} - ${response.statusText}`
|
|
298
298
|
);
|
|
@@ -684,77 +684,12 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
684
684
|
throw new UnexpectedStateError("Server is already connected");
|
|
685
685
|
}
|
|
686
686
|
this.#connectionState = "connecting";
|
|
687
|
+
const streamableHttp = !this.#stateless && isStreamableHttpTransport(transport);
|
|
687
688
|
try {
|
|
688
689
|
await this.#server.connect(transport);
|
|
689
|
-
if (!
|
|
690
|
-
|
|
691
|
-
const maxAttempts = 10;
|
|
692
|
-
const retryDelay = 100;
|
|
693
|
-
while (attempt++ < maxAttempts) {
|
|
694
|
-
const capabilities = this.#server.getClientCapabilities();
|
|
695
|
-
if (capabilities) {
|
|
696
|
-
this.#clientCapabilities = capabilities;
|
|
697
|
-
break;
|
|
698
|
-
}
|
|
699
|
-
await _promises3.setTimeout.call(void 0, retryDelay);
|
|
700
|
-
}
|
|
701
|
-
if (!this.#clientCapabilities) {
|
|
702
|
-
this.#logger.warn(
|
|
703
|
-
`[FastMCP warning] could not infer client capabilities after ${maxAttempts} attempts. Connection may be unstable.`
|
|
704
|
-
);
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
if (_optionalChain([this, 'access', _12 => _12.#rootsConfig, 'optionalAccess', _13 => _13.enabled]) !== false && _optionalChain([this, 'access', _14 => _14.#clientCapabilities, 'optionalAccess', _15 => _15.roots, 'optionalAccess', _16 => _16.listChanged]) && typeof this.#server.listRoots === "function") {
|
|
708
|
-
try {
|
|
709
|
-
const roots = await this.#server.listRoots();
|
|
710
|
-
this.#roots = _optionalChain([roots, 'optionalAccess', _17 => _17.roots]) || [];
|
|
711
|
-
} catch (e) {
|
|
712
|
-
if (e instanceof _typesjs.McpError && e.code === _typesjs.ErrorCode.MethodNotFound) {
|
|
713
|
-
this.#logger.debug(
|
|
714
|
-
"[FastMCP debug] listRoots method not supported by client"
|
|
715
|
-
);
|
|
716
|
-
} else {
|
|
717
|
-
this.#logger.error(
|
|
718
|
-
`[FastMCP error] received error listing roots.
|
|
719
|
-
|
|
720
|
-
${e instanceof Error ? e.stack : JSON.stringify(e)}`
|
|
721
|
-
);
|
|
722
|
-
}
|
|
723
|
-
}
|
|
724
|
-
}
|
|
725
|
-
if (this.#clientCapabilities) {
|
|
726
|
-
const pingConfig = this.#getPingConfig();
|
|
727
|
-
if (pingConfig.enabled) {
|
|
728
|
-
this.#pingInterval = setInterval(async () => {
|
|
729
|
-
if (this.#pingInFlight) {
|
|
730
|
-
return;
|
|
731
|
-
}
|
|
732
|
-
this.#pingInFlight = true;
|
|
733
|
-
try {
|
|
734
|
-
await this.#server.ping();
|
|
735
|
-
} catch (e4) {
|
|
736
|
-
const logLevel = pingConfig.logLevel;
|
|
737
|
-
if (logLevel === "debug") {
|
|
738
|
-
this.#logger.debug("[FastMCP debug] server ping failed");
|
|
739
|
-
} else if (logLevel === "warning") {
|
|
740
|
-
this.#logger.warn(
|
|
741
|
-
"[FastMCP warning] server is not responding to ping"
|
|
742
|
-
);
|
|
743
|
-
} else if (logLevel === "error") {
|
|
744
|
-
this.#logger.error(
|
|
745
|
-
"[FastMCP error] server is not responding to ping"
|
|
746
|
-
);
|
|
747
|
-
} else {
|
|
748
|
-
this.#logger.info("[FastMCP info] server ping failed");
|
|
749
|
-
}
|
|
750
|
-
} finally {
|
|
751
|
-
this.#pingInFlight = false;
|
|
752
|
-
}
|
|
753
|
-
}, pingConfig.intervalMs);
|
|
754
|
-
}
|
|
690
|
+
if (!streamableHttp) {
|
|
691
|
+
await this.#setUpSession(false);
|
|
755
692
|
}
|
|
756
|
-
this.#connectionState = "ready";
|
|
757
|
-
this.emit("ready");
|
|
758
693
|
} catch (error) {
|
|
759
694
|
this.#connectionState = "error";
|
|
760
695
|
const errorEvent = {
|
|
@@ -763,6 +698,18 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
|
|
|
763
698
|
this.emit("error", errorEvent);
|
|
764
699
|
throw error;
|
|
765
700
|
}
|
|
701
|
+
if (streamableHttp) {
|
|
702
|
+
this.#setUpSession(true).catch((error) => {
|
|
703
|
+
this.#connectionState = "error";
|
|
704
|
+
if (this.listenerCount("error") > 0) {
|
|
705
|
+
this.emit("error", {
|
|
706
|
+
error: error instanceof Error ? error : new Error(String(error))
|
|
707
|
+
});
|
|
708
|
+
} else {
|
|
709
|
+
this.#logger.error("[FastMCP error] session setup failed", error);
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
}
|
|
766
713
|
}
|
|
767
714
|
promptsListChanged(prompts) {
|
|
768
715
|
if (!this.#canRefresh("prompts")) {
|
|
@@ -931,7 +878,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
931
878
|
},
|
|
932
879
|
elicit: (params, options) => this.#server.elicitInput(params, options),
|
|
933
880
|
log: this.#createLog(),
|
|
934
|
-
requestId: typeof _optionalChain([meta, 'optionalAccess',
|
|
881
|
+
requestId: typeof _optionalChain([meta, 'optionalAccess', _12 => _12.requestId]) === "string" ? meta.requestId : void 0,
|
|
935
882
|
session: this.#auth,
|
|
936
883
|
sessionId: this.sessionId
|
|
937
884
|
};
|
|
@@ -953,8 +900,8 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
953
900
|
};
|
|
954
901
|
}
|
|
955
902
|
#formatSchemaIssues(issues) {
|
|
956
|
-
return _optionalChain([this, 'access',
|
|
957
|
-
const path = _optionalChain([issue, 'access',
|
|
903
|
+
return _optionalChain([this, 'access', _13 => _13.#utils, 'optionalAccess', _14 => _14.formatInvalidParamsErrorMessage]) ? this.#utils.formatInvalidParamsErrorMessage(issues) : issues.map((issue) => {
|
|
904
|
+
const path = _optionalChain([issue, 'access', _15 => _15.path, 'optionalAccess', _16 => _16.join, 'call', _17 => _17(".")]) || "root";
|
|
958
905
|
return `${path}: ${issue.message}`;
|
|
959
906
|
}).join(", ");
|
|
960
907
|
}
|
|
@@ -967,6 +914,52 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
967
914
|
logLevel: pingConfig.logLevel || "debug"
|
|
968
915
|
};
|
|
969
916
|
}
|
|
917
|
+
/**
|
|
918
|
+
* Fetches the client's roots if it advertised `roots.listChanged`.
|
|
919
|
+
*
|
|
920
|
+
* Over Streamable HTTP a server-initiated request travels on the client's
|
|
921
|
+
* standalone GET stream, which the client opens only after initialization,
|
|
922
|
+
* and the transport drops a request sent before that. So there each attempt
|
|
923
|
+
* is bounded and retried, and the result is announced with `rootsChanged`.
|
|
924
|
+
*/
|
|
925
|
+
async #loadRoots(streamableHttp) {
|
|
926
|
+
if (_optionalChain([this, 'access', _18 => _18.#rootsConfig, 'optionalAccess', _19 => _19.enabled]) === false || !_optionalChain([this, 'access', _20 => _20.#clientCapabilities, 'optionalAccess', _21 => _21.roots, 'optionalAccess', _22 => _22.listChanged]) || typeof this.#server.listRoots !== "function") {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
const maxAttempts = streamableHttp ? 5 : 1;
|
|
930
|
+
for (let attempt = 1; ; attempt++) {
|
|
931
|
+
try {
|
|
932
|
+
const roots = await this.#server.listRoots(
|
|
933
|
+
void 0,
|
|
934
|
+
streamableHttp ? { timeout: 1e3 } : void 0
|
|
935
|
+
);
|
|
936
|
+
this.#roots = _optionalChain([roots, 'optionalAccess', _23 => _23.roots]) || [];
|
|
937
|
+
if (streamableHttp) {
|
|
938
|
+
this.emit("rootsChanged", { roots: this.#roots });
|
|
939
|
+
}
|
|
940
|
+
return;
|
|
941
|
+
} catch (e) {
|
|
942
|
+
if (this.#connectionState === "closed") {
|
|
943
|
+
return;
|
|
944
|
+
}
|
|
945
|
+
if (attempt < maxAttempts && e instanceof _typesjs.McpError && e.code === _typesjs.ErrorCode.RequestTimeout) {
|
|
946
|
+
continue;
|
|
947
|
+
}
|
|
948
|
+
if (e instanceof _typesjs.McpError && e.code === _typesjs.ErrorCode.MethodNotFound) {
|
|
949
|
+
this.#logger.debug(
|
|
950
|
+
"[FastMCP debug] listRoots method not supported by client"
|
|
951
|
+
);
|
|
952
|
+
} else {
|
|
953
|
+
this.#logger.error(
|
|
954
|
+
`[FastMCP error] received error listing roots.
|
|
955
|
+
|
|
956
|
+
${e instanceof Error ? e.stack : JSON.stringify(e)}`
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
return;
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
}
|
|
970
963
|
/**
|
|
971
964
|
* `sendLoggingMessage` rejects once the client has hung up, and these four
|
|
972
965
|
* callers are synchronous, so the rejection has nowhere to go. Swallow it the
|
|
@@ -991,6 +984,67 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
991
984
|
);
|
|
992
985
|
});
|
|
993
986
|
}
|
|
987
|
+
async #setUpSession(streamableHttp) {
|
|
988
|
+
if (!this.#stateless) {
|
|
989
|
+
let attempt = 0;
|
|
990
|
+
const maxAttempts = 10;
|
|
991
|
+
const retryDelay = 100;
|
|
992
|
+
while (attempt++ < maxAttempts) {
|
|
993
|
+
const capabilities = this.#server.getClientCapabilities();
|
|
994
|
+
if (capabilities) {
|
|
995
|
+
this.#clientCapabilities = capabilities;
|
|
996
|
+
break;
|
|
997
|
+
}
|
|
998
|
+
await _promises3.setTimeout.call(void 0, retryDelay);
|
|
999
|
+
}
|
|
1000
|
+
if (!this.#clientCapabilities) {
|
|
1001
|
+
this.#logger.warn(
|
|
1002
|
+
`[FastMCP warning] could not infer client capabilities after ${maxAttempts} attempts. Connection may be unstable.`
|
|
1003
|
+
);
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
if (this.#connectionState === "closed") {
|
|
1007
|
+
return;
|
|
1008
|
+
}
|
|
1009
|
+
if (streamableHttp) {
|
|
1010
|
+
void this.#loadRoots(true);
|
|
1011
|
+
} else {
|
|
1012
|
+
await this.#loadRoots(false);
|
|
1013
|
+
}
|
|
1014
|
+
if (this.#clientCapabilities) {
|
|
1015
|
+
const pingConfig = this.#getPingConfig();
|
|
1016
|
+
if (pingConfig.enabled) {
|
|
1017
|
+
this.#pingInterval = setInterval(async () => {
|
|
1018
|
+
if (this.#pingInFlight) {
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
this.#pingInFlight = true;
|
|
1022
|
+
try {
|
|
1023
|
+
await this.#server.ping();
|
|
1024
|
+
} catch (e4) {
|
|
1025
|
+
const logLevel = pingConfig.logLevel;
|
|
1026
|
+
if (logLevel === "debug") {
|
|
1027
|
+
this.#logger.debug("[FastMCP debug] server ping failed");
|
|
1028
|
+
} else if (logLevel === "warning") {
|
|
1029
|
+
this.#logger.warn(
|
|
1030
|
+
"[FastMCP warning] server is not responding to ping"
|
|
1031
|
+
);
|
|
1032
|
+
} else if (logLevel === "error") {
|
|
1033
|
+
this.#logger.error(
|
|
1034
|
+
"[FastMCP error] server is not responding to ping"
|
|
1035
|
+
);
|
|
1036
|
+
} else {
|
|
1037
|
+
this.#logger.info("[FastMCP info] server ping failed");
|
|
1038
|
+
}
|
|
1039
|
+
} finally {
|
|
1040
|
+
this.#pingInFlight = false;
|
|
1041
|
+
}
|
|
1042
|
+
}, pingConfig.intervalMs);
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
this.#connectionState = "ready";
|
|
1046
|
+
this.emit("ready");
|
|
1047
|
+
}
|
|
994
1048
|
/**
|
|
995
1049
|
* Periodically writes to the response stream of an in-flight tool call, so an
|
|
996
1050
|
* idle-connection timeout (proxy, load balancer) does not close it while a
|
|
@@ -1306,7 +1360,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1306
1360
|
const uriTemplate = _uritemplates2.default.call(void 0,
|
|
1307
1361
|
resourceTemplate.uriTemplate
|
|
1308
1362
|
);
|
|
1309
|
-
const match = uriTemplate
|
|
1363
|
+
const match = matchUriTemplate(uriTemplate, request.params.uri);
|
|
1310
1364
|
if (!match) {
|
|
1311
1365
|
continue;
|
|
1312
1366
|
}
|
|
@@ -1667,9 +1721,26 @@ function convertObjectToSnakeCase(obj) {
|
|
|
1667
1721
|
}
|
|
1668
1722
|
return result;
|
|
1669
1723
|
}
|
|
1724
|
+
function isStreamableHttpTransport(transport) {
|
|
1725
|
+
return "handleRequest" in transport && typeof transport.handleRequest === "function";
|
|
1726
|
+
}
|
|
1670
1727
|
function joinPaths(basePath, path) {
|
|
1671
1728
|
return `${basePath}${normalizePath(path)}`;
|
|
1672
1729
|
}
|
|
1730
|
+
function matchUriTemplate(template, uri) {
|
|
1731
|
+
const match = template.fromUri(uri);
|
|
1732
|
+
if (!match) {
|
|
1733
|
+
return void 0;
|
|
1734
|
+
}
|
|
1735
|
+
const checksQuery = !/\{[?&]/.test(template.template);
|
|
1736
|
+
const checksFragment = !template.template.includes("{#");
|
|
1737
|
+
const shape = (value) => [
|
|
1738
|
+
value.split(/[?#]/, 1)[0].split("/").length,
|
|
1739
|
+
checksQuery && value.includes("?"),
|
|
1740
|
+
checksFragment && value.includes("#")
|
|
1741
|
+
].join();
|
|
1742
|
+
return shape(template.fill(match)) === shape(uri) ? match : void 0;
|
|
1743
|
+
}
|
|
1673
1744
|
function normalizeBasePath(path) {
|
|
1674
1745
|
if (!path || path === "/") {
|
|
1675
1746
|
return "";
|
|
@@ -1950,7 +2021,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1950
2021
|
}
|
|
1951
2022
|
for (const template of this.#resourcesTemplates) {
|
|
1952
2023
|
const parsedTemplate = _uritemplates2.default.call(void 0, template.uriTemplate);
|
|
1953
|
-
const params = parsedTemplate
|
|
2024
|
+
const params = matchUriTemplate(parsedTemplate, uri);
|
|
1954
2025
|
if (!params) {
|
|
1955
2026
|
continue;
|
|
1956
2027
|
}
|
|
@@ -3052,4 +3123,4 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
3052
3123
|
|
|
3053
3124
|
|
|
3054
3125
|
exports.DiscoveryDocumentCache = DiscoveryDocumentCache; exports.jsonSchemaAdapter = jsonSchemaAdapter; exports.MEDIA_FETCH_TIMEOUT_MS = MEDIA_FETCH_TIMEOUT_MS; exports.imageContent = imageContent; exports.audioContent = audioContent; exports.FastMCPError = FastMCPError; exports.SessionError = SessionError; exports.UnexpectedStateError = UnexpectedStateError; exports.UserError = UserError; exports.ServerState = ServerState; exports.FastMCPSession = FastMCPSession; exports.FastMCP = FastMCP;
|
|
3055
|
-
//# sourceMappingURL=chunk-
|
|
3126
|
+
//# sourceMappingURL=chunk-QICOIGCH.cjs.map
|