fastmcp 4.23.5 → 4.23.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 +5 -0
- package/dist/FastMCP.cjs +3 -3
- package/dist/FastMCP.d.cts +2 -1
- package/dist/FastMCP.d.ts +2 -1
- package/dist/FastMCP.js +2 -2
- package/dist/{chunk-OUD755CE.js → chunk-7WNI6AGD.js} +169 -78
- package/dist/chunk-7WNI6AGD.js.map +1 -0
- package/dist/{chunk-O22SYZMC.cjs → chunk-MPFPOZ2H.cjs} +16 -2
- package/dist/chunk-MPFPOZ2H.cjs.map +1 -0
- package/dist/{chunk-MI6R72UA.cjs → chunk-TBMRFQ6M.cjs} +209 -118
- package/dist/chunk-TBMRFQ6M.cjs.map +1 -0
- package/dist/{chunk-UMDUIBFW.js → chunk-YZ5QEHBX.js} +16 -2
- package/dist/chunk-YZ5QEHBX.js.map +1 -0
- package/dist/edge/index.cjs +7 -4
- package/dist/edge/index.cjs.map +1 -1
- package/dist/edge/index.js +7 -4
- package/dist/edge/index.js.map +1 -1
- 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-MI6R72UA.cjs.map +0 -1
- package/dist/chunk-O22SYZMC.cjs.map +0 -1
- package/dist/chunk-OUD755CE.js.map +0 -1
- package/dist/chunk-UMDUIBFW.js.map +0 -1
package/README.md
CHANGED
|
@@ -1286,6 +1286,11 @@ after `logging/setLevel` with `error`, `log.debug` and `log.info` reach nobody.
|
|
|
1286
1286
|
Until a client asks, every level is sent. The level in force is readable as
|
|
1287
1287
|
[`session.loggingLevel`](#logginglevel).
|
|
1288
1288
|
|
|
1289
|
+
Each message travels on the stream of the request that logged it, so logging
|
|
1290
|
+
works in `stateless` mode too. With `httpStream.enableJsonResponse`, which
|
|
1291
|
+
answers each request with a single JSON body, messages logged while a request
|
|
1292
|
+
runs are dropped.
|
|
1293
|
+
|
|
1289
1294
|
#### Errors
|
|
1290
1295
|
|
|
1291
1296
|
The errors that are meant to be shown to the user should be thrown as `UserError` instances:
|
package/dist/FastMCP.cjs
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
var
|
|
14
|
+
var _chunkTBMRFQ6Mcjs = require('./chunk-TBMRFQ6M.cjs');
|
|
15
15
|
|
|
16
16
|
|
|
17
17
|
|
|
@@ -25,7 +25,7 @@ var _chunkMI6R72UAcjs = require('./chunk-MI6R72UA.cjs');
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
var _chunkC7TBI7A5cjs = require('./chunk-C7TBI7A5.cjs');
|
|
28
|
-
require('./chunk-
|
|
28
|
+
require('./chunk-MPFPOZ2H.cjs');
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
|
|
@@ -50,5 +50,5 @@ require('./chunk-O22SYZMC.cjs');
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
exports.AuthProvider = _chunkC7TBI7A5cjs.AuthProvider; exports.AzureProvider = _chunkC7TBI7A5cjs.AzureProvider; exports.DiscoveryDocumentCache =
|
|
53
|
+
exports.AuthProvider = _chunkC7TBI7A5cjs.AuthProvider; exports.AzureProvider = _chunkC7TBI7A5cjs.AzureProvider; exports.DiscoveryDocumentCache = _chunkTBMRFQ6Mcjs.DiscoveryDocumentCache; exports.FastMCP = _chunkTBMRFQ6Mcjs.FastMCP; exports.FastMCPError = _chunkTBMRFQ6Mcjs.FastMCPError; exports.FastMCPSession = _chunkTBMRFQ6Mcjs.FastMCPSession; exports.GitHubProvider = _chunkC7TBI7A5cjs.GitHubProvider; exports.GoogleProvider = _chunkC7TBI7A5cjs.GoogleProvider; exports.MEDIA_FETCH_TIMEOUT_MS = _chunkTBMRFQ6Mcjs.MEDIA_FETCH_TIMEOUT_MS; exports.OAuthProvider = _chunkC7TBI7A5cjs.OAuthProvider; exports.ServerState = _chunkTBMRFQ6Mcjs.ServerState; exports.SessionError = _chunkTBMRFQ6Mcjs.SessionError; exports.UnexpectedStateError = _chunkTBMRFQ6Mcjs.UnexpectedStateError; exports.UserError = _chunkTBMRFQ6Mcjs.UserError; exports.audioContent = _chunkTBMRFQ6Mcjs.audioContent; exports.getAuthSession = _chunkC7TBI7A5cjs.getAuthSession; exports.imageContent = _chunkTBMRFQ6Mcjs.imageContent; exports.jsonSchemaAdapter = _chunkTBMRFQ6Mcjs.jsonSchemaAdapter; exports.requireAll = _chunkC7TBI7A5cjs.requireAll; exports.requireAny = _chunkC7TBI7A5cjs.requireAny; exports.requireAuth = _chunkC7TBI7A5cjs.requireAuth; exports.requireRole = _chunkC7TBI7A5cjs.requireRole; exports.requireScopes = _chunkC7TBI7A5cjs.requireScopes;
|
|
54
54
|
//# sourceMappingURL=FastMCP.cjs.map
|
package/dist/FastMCP.d.cts
CHANGED
|
@@ -925,7 +925,7 @@ declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth>
|
|
|
925
925
|
*/
|
|
926
926
|
get sessionId(): string | undefined;
|
|
927
927
|
set sessionId(value: string | undefined);
|
|
928
|
-
constructor({ auth, authRequired, hasTools, icons, instructions, logger, name, onToolCall, ping, prompts, resources, resourcesTemplates, roots, sessionId, stateless, streamKeepalive, title, tools, transportType, utils, version, websiteUrl, }: {
|
|
928
|
+
constructor({ auth, authRequired, enableJsonResponse, hasTools, icons, instructions, logger, name, onToolCall, ping, prompts, resources, resourcesTemplates, roots, sessionId, stateless, streamKeepalive, title, tools, transportType, utils, version, websiteUrl, }: {
|
|
929
929
|
auth?: T;
|
|
930
930
|
/**
|
|
931
931
|
* Whether the server authenticates its sessions (`authenticate` is
|
|
@@ -933,6 +933,7 @@ declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth>
|
|
|
933
933
|
* gated by `canAccess` (see `toolsVisibleTo`).
|
|
934
934
|
*/
|
|
935
935
|
authRequired?: boolean;
|
|
936
|
+
enableJsonResponse?: boolean;
|
|
936
937
|
/**
|
|
937
938
|
* Whether the server has any tools at all, including ones this session's
|
|
938
939
|
* `canAccess` filtering removed from `tools`. Defaults to `tools.length > 0`.
|
package/dist/FastMCP.d.ts
CHANGED
|
@@ -925,7 +925,7 @@ declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth>
|
|
|
925
925
|
*/
|
|
926
926
|
get sessionId(): string | undefined;
|
|
927
927
|
set sessionId(value: string | undefined);
|
|
928
|
-
constructor({ auth, authRequired, hasTools, icons, instructions, logger, name, onToolCall, ping, prompts, resources, resourcesTemplates, roots, sessionId, stateless, streamKeepalive, title, tools, transportType, utils, version, websiteUrl, }: {
|
|
928
|
+
constructor({ auth, authRequired, enableJsonResponse, hasTools, icons, instructions, logger, name, onToolCall, ping, prompts, resources, resourcesTemplates, roots, sessionId, stateless, streamKeepalive, title, tools, transportType, utils, version, websiteUrl, }: {
|
|
929
929
|
auth?: T;
|
|
930
930
|
/**
|
|
931
931
|
* Whether the server authenticates its sessions (`authenticate` is
|
|
@@ -933,6 +933,7 @@ declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth>
|
|
|
933
933
|
* gated by `canAccess` (see `toolsVisibleTo`).
|
|
934
934
|
*/
|
|
935
935
|
authRequired?: boolean;
|
|
936
|
+
enableJsonResponse?: boolean;
|
|
936
937
|
/**
|
|
937
938
|
* Whether the server has any tools at all, including ones this session's
|
|
938
939
|
* `canAccess` filtering removed from `tools`. Defaults to `tools.length > 0`.
|
package/dist/FastMCP.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
audioContent,
|
|
12
12
|
imageContent,
|
|
13
13
|
jsonSchemaAdapter
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-7WNI6AGD.js";
|
|
15
15
|
import {
|
|
16
16
|
AuthProvider,
|
|
17
17
|
AzureProvider,
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
requireRole,
|
|
26
26
|
requireScopes
|
|
27
27
|
} from "./chunk-CA2EPNZF.js";
|
|
28
|
-
import "./chunk-
|
|
28
|
+
import "./chunk-YZ5QEHBX.js";
|
|
29
29
|
export {
|
|
30
30
|
AuthProvider,
|
|
31
31
|
AzureProvider,
|
|
@@ -2,8 +2,9 @@ import {
|
|
|
2
2
|
cancelResponseBody
|
|
3
3
|
} from "./chunk-CA2EPNZF.js";
|
|
4
4
|
import {
|
|
5
|
-
strictInputSchema
|
|
6
|
-
|
|
5
|
+
strictInputSchema,
|
|
6
|
+
zodInputSchema
|
|
7
|
+
} from "./chunk-YZ5QEHBX.js";
|
|
7
8
|
|
|
8
9
|
// src/FastMCP.ts
|
|
9
10
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -225,6 +226,16 @@ function unwrapDefault(value) {
|
|
|
225
226
|
|
|
226
227
|
// src/FastMCP.ts
|
|
227
228
|
var MEDIA_FETCH_TIMEOUT_MS = 3e4;
|
|
229
|
+
var isSvg = (buffer) => {
|
|
230
|
+
let text = buffer.toString("utf8").trimStart();
|
|
231
|
+
const preamble = /^(?:<\?[\s\S]*?\?>|<!--[\s\S]*?-->|<!DOCTYPE\s[^[>]*(?:\[[\s\S]*?\]\s*)?>)/;
|
|
232
|
+
let match = preamble.exec(text);
|
|
233
|
+
while (match) {
|
|
234
|
+
text = text.slice(match[0].length).trimStart();
|
|
235
|
+
match = preamble.exec(text);
|
|
236
|
+
}
|
|
237
|
+
return /^<svg(?:\s|\/?>)/.test(text);
|
|
238
|
+
};
|
|
228
239
|
var imageContent = async (input) => {
|
|
229
240
|
let rawData;
|
|
230
241
|
try {
|
|
@@ -267,16 +278,17 @@ var imageContent = async (input) => {
|
|
|
267
278
|
);
|
|
268
279
|
}
|
|
269
280
|
const { fileTypeFromBuffer } = await import("file-type");
|
|
270
|
-
const
|
|
271
|
-
|
|
281
|
+
const fileType = await fileTypeFromBuffer(rawData);
|
|
282
|
+
const mimeType = (!fileType || fileType.mime === "application/xml") && isSvg(rawData) ? "image/svg+xml" : fileType?.mime;
|
|
283
|
+
if (!mimeType || !mimeType.startsWith("image/")) {
|
|
272
284
|
console.warn(
|
|
273
|
-
`Warning: Content may not be a valid image. Detected MIME: ${mimeType
|
|
285
|
+
`Warning: Content may not be a valid image. Detected MIME: ${mimeType || "unknown"}`
|
|
274
286
|
);
|
|
275
287
|
}
|
|
276
288
|
const base64Data = rawData.toString("base64");
|
|
277
289
|
return {
|
|
278
290
|
data: base64Data,
|
|
279
|
-
mimeType: mimeType
|
|
291
|
+
mimeType: mimeType ?? "image/png",
|
|
280
292
|
type: "image"
|
|
281
293
|
};
|
|
282
294
|
} catch (error) {
|
|
@@ -287,8 +299,27 @@ var imageContent = async (input) => {
|
|
|
287
299
|
}
|
|
288
300
|
}
|
|
289
301
|
};
|
|
302
|
+
var AUDIO_CONTAINER_TYPES = /* @__PURE__ */ new Map([
|
|
303
|
+
["video/3gpp", "audio/3gpp"],
|
|
304
|
+
["video/3gpp2", "audio/3gpp2"],
|
|
305
|
+
["video/matroska", "audio/matroska"],
|
|
306
|
+
["video/mp4", "audio/mp4"],
|
|
307
|
+
["video/ogg", "audio/ogg"],
|
|
308
|
+
["video/webm", "audio/webm"]
|
|
309
|
+
]);
|
|
310
|
+
var resolveAudioMimeType = (detected, declared) => {
|
|
311
|
+
if (detected?.startsWith("audio/")) {
|
|
312
|
+
return detected;
|
|
313
|
+
}
|
|
314
|
+
const declaredMime = declared?.split(";", 1)[0].trim().toLowerCase();
|
|
315
|
+
if (declaredMime?.startsWith("audio/")) {
|
|
316
|
+
return declaredMime;
|
|
317
|
+
}
|
|
318
|
+
return (detected && AUDIO_CONTAINER_TYPES.get(detected)) ?? detected;
|
|
319
|
+
};
|
|
290
320
|
var audioContent = async (input) => {
|
|
291
321
|
let rawData;
|
|
322
|
+
let declaredMimeType = null;
|
|
292
323
|
try {
|
|
293
324
|
if ("url" in input) {
|
|
294
325
|
const timeoutMs = input.timeoutMs ?? MEDIA_FETCH_TIMEOUT_MS;
|
|
@@ -302,6 +333,7 @@ var audioContent = async (input) => {
|
|
|
302
333
|
`Server responded with status: ${response.status} - ${response.statusText}`
|
|
303
334
|
);
|
|
304
335
|
}
|
|
336
|
+
declaredMimeType = response.headers.get("content-type");
|
|
305
337
|
rawData = Buffer.from(await response.arrayBuffer());
|
|
306
338
|
} catch (error) {
|
|
307
339
|
if (error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError")) {
|
|
@@ -329,16 +361,17 @@ var audioContent = async (input) => {
|
|
|
329
361
|
);
|
|
330
362
|
}
|
|
331
363
|
const { fileTypeFromBuffer } = await import("file-type");
|
|
332
|
-
const
|
|
333
|
-
|
|
364
|
+
const detected = await fileTypeFromBuffer(rawData);
|
|
365
|
+
const mimeType = resolveAudioMimeType(detected?.mime, declaredMimeType);
|
|
366
|
+
if (!mimeType || !mimeType.startsWith("audio/")) {
|
|
334
367
|
console.warn(
|
|
335
|
-
`Warning: Content may not be a valid audio file. Detected MIME: ${mimeType
|
|
368
|
+
`Warning: Content may not be a valid audio file. Detected MIME: ${mimeType || "unknown"}`
|
|
336
369
|
);
|
|
337
370
|
}
|
|
338
371
|
const base64Data = rawData.toString("base64");
|
|
339
372
|
return {
|
|
340
373
|
data: base64Data,
|
|
341
|
-
mimeType: mimeType
|
|
374
|
+
mimeType: mimeType ?? "audio/mpeg",
|
|
342
375
|
type: "audio"
|
|
343
376
|
};
|
|
344
377
|
} catch (error) {
|
|
@@ -510,6 +543,8 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
510
543
|
#capabilities = {};
|
|
511
544
|
#clientCapabilities;
|
|
512
545
|
#connectionState = "connecting";
|
|
546
|
+
// Caller-supplied transports leave the response mode unspecified.
|
|
547
|
+
#enableJsonResponse;
|
|
513
548
|
#logger;
|
|
514
549
|
/**
|
|
515
550
|
* The minimum level the client asked for with `logging/setLevel`, or
|
|
@@ -545,6 +580,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
545
580
|
* to interested clients only.
|
|
546
581
|
*/
|
|
547
582
|
#subscriptions = /* @__PURE__ */ new Set();
|
|
583
|
+
#tools;
|
|
548
584
|
#transportType;
|
|
549
585
|
/**
|
|
550
586
|
* Capabilities this session has already warned about in `#canRefresh`, so a
|
|
@@ -553,9 +589,11 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
553
589
|
*/
|
|
554
590
|
#unnegotiatedWarnings = /* @__PURE__ */ new Set();
|
|
555
591
|
#utils;
|
|
592
|
+
#visibleTools = [];
|
|
556
593
|
constructor({
|
|
557
594
|
auth,
|
|
558
595
|
authRequired = false,
|
|
596
|
+
enableJsonResponse,
|
|
559
597
|
hasTools,
|
|
560
598
|
icons,
|
|
561
599
|
instructions,
|
|
@@ -580,6 +618,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
580
618
|
super();
|
|
581
619
|
this.#auth = auth;
|
|
582
620
|
this.#authRequired = authRequired;
|
|
621
|
+
this.#enableJsonResponse = enableJsonResponse;
|
|
583
622
|
this.#logger = logger;
|
|
584
623
|
this.#onToolCall = onToolCall;
|
|
585
624
|
this.#pingConfig = ping;
|
|
@@ -587,6 +626,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
587
626
|
this.#sessionId = sessionId;
|
|
588
627
|
this.#stateless = stateless;
|
|
589
628
|
this.#streamKeepaliveConfig = streamKeepalive;
|
|
629
|
+
this.#tools = tools;
|
|
590
630
|
this.#transportType = transportType;
|
|
591
631
|
this.#needsEventLoopFlush = transportType === "httpStream";
|
|
592
632
|
const supportsTools = hasTools ?? tools.length > 0;
|
|
@@ -620,7 +660,9 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
620
660
|
this.setupRootsHandlers();
|
|
621
661
|
this.setupCompleteHandlers();
|
|
622
662
|
if (supportsTools) {
|
|
623
|
-
this.setupToolHandlers(
|
|
663
|
+
this.setupToolHandlers(
|
|
664
|
+
toolsVisibleTo(tools, this.#auth, this.#authRequired)
|
|
665
|
+
);
|
|
624
666
|
}
|
|
625
667
|
if (resources.length || resourcesTemplates.length) {
|
|
626
668
|
for (const resource of resources) {
|
|
@@ -741,6 +783,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
741
783
|
if (!this.#canRefresh("tools")) {
|
|
742
784
|
return;
|
|
743
785
|
}
|
|
786
|
+
this.#tools = tools;
|
|
744
787
|
this.setupToolHandlers(
|
|
745
788
|
toolsVisibleTo(tools, this.#auth, this.#authRequired)
|
|
746
789
|
);
|
|
@@ -765,6 +808,11 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
765
808
|
*/
|
|
766
809
|
updateAuth(auth) {
|
|
767
810
|
this.#auth = auth;
|
|
811
|
+
const tools = toolsVisibleTo(this.#tools, auth, this.#authRequired);
|
|
812
|
+
if (tools.length !== this.#visibleTools.length || tools.some((tool, index) => tool !== this.#visibleTools[index])) {
|
|
813
|
+
this.setupToolHandlers(tools);
|
|
814
|
+
this.triggerListChangedNotification("notifications/tools/list_changed");
|
|
815
|
+
}
|
|
768
816
|
}
|
|
769
817
|
waitForReady() {
|
|
770
818
|
if (this.isReady) {
|
|
@@ -832,6 +880,19 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
832
880
|
}
|
|
833
881
|
return false;
|
|
834
882
|
}
|
|
883
|
+
/**
|
|
884
|
+
* When `start()` streams responses, an elicitation goes out on its request's
|
|
885
|
+
* own SSE stream, as the SDK's `extra.sendRequest` does, so it reaches a
|
|
886
|
+
* client that never opened the optional standalone GET stream. A JSON
|
|
887
|
+
* response cannot carry it, and a transport passed to `connect()` does not
|
|
888
|
+
* say which mode it uses, so those keep the session's standalone stream.
|
|
889
|
+
*/
|
|
890
|
+
#createElicit(requestId) {
|
|
891
|
+
return (params, options) => this.#server.elicitInput(
|
|
892
|
+
params,
|
|
893
|
+
this.#enableJsonResponse === false ? { ...options, relatedRequestId: requestId } : options
|
|
894
|
+
);
|
|
895
|
+
}
|
|
835
896
|
/**
|
|
836
897
|
* Builds the context object passed as the third argument to
|
|
837
898
|
* `resource.load` / `resourceTemplate.load` / `prompt.load`.
|
|
@@ -842,31 +903,31 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
842
903
|
* are tied to a tool call's progress token / streaming notification,
|
|
843
904
|
* which resource and prompt reads do not have.
|
|
844
905
|
*/
|
|
845
|
-
#createLoadContext(meta) {
|
|
906
|
+
#createLoadContext(meta, sendNotification, requestId) {
|
|
846
907
|
return {
|
|
847
908
|
client: {
|
|
848
909
|
version: this.#server.getClientVersion()
|
|
849
910
|
},
|
|
850
|
-
elicit:
|
|
851
|
-
log: this.#createLog(),
|
|
911
|
+
elicit: this.#createElicit(requestId),
|
|
912
|
+
log: this.#createLog(sendNotification),
|
|
852
913
|
requestId: typeof meta?.requestId === "string" ? meta.requestId : void 0,
|
|
853
914
|
session: this.#auth,
|
|
854
915
|
sessionId: this.sessionId
|
|
855
916
|
};
|
|
856
917
|
}
|
|
857
|
-
#createLog() {
|
|
918
|
+
#createLog(sendNotification) {
|
|
858
919
|
return {
|
|
859
920
|
debug: (message, context) => {
|
|
860
|
-
this.#sendLog("debug", message, context);
|
|
921
|
+
this.#sendLog(sendNotification, "debug", message, context);
|
|
861
922
|
},
|
|
862
923
|
error: (message, context) => {
|
|
863
|
-
this.#sendLog("error", message, context);
|
|
924
|
+
this.#sendLog(sendNotification, "error", message, context);
|
|
864
925
|
},
|
|
865
926
|
info: (message, context) => {
|
|
866
|
-
this.#sendLog("info", message, context);
|
|
927
|
+
this.#sendLog(sendNotification, "info", message, context);
|
|
867
928
|
},
|
|
868
929
|
warn: (message, context) => {
|
|
869
|
-
this.#sendLog("warning", message, context);
|
|
930
|
+
this.#sendLog(sendNotification, "warning", message, context);
|
|
870
931
|
}
|
|
871
932
|
};
|
|
872
933
|
}
|
|
@@ -932,22 +993,23 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
|
|
|
932
993
|
}
|
|
933
994
|
}
|
|
934
995
|
/**
|
|
935
|
-
*
|
|
996
|
+
* Sending rejects once the client has hung up, and these four
|
|
936
997
|
* callers are synchronous, so the rejection has nowhere to go. Swallow it the
|
|
937
998
|
* way every other notification sender in this class does, or a client that
|
|
938
999
|
* disconnects mid-tool takes the server process down with it.
|
|
939
1000
|
*/
|
|
940
|
-
#sendLog(level, message, context) {
|
|
1001
|
+
#sendLog(sendNotification, level, message, context) {
|
|
941
1002
|
if (this.#loggingLevel && LOGGING_LEVEL_SEVERITY[level] < LOGGING_LEVEL_SEVERITY[this.#loggingLevel]) {
|
|
942
1003
|
return;
|
|
943
1004
|
}
|
|
944
|
-
|
|
1005
|
+
const params = {
|
|
945
1006
|
data: {
|
|
946
1007
|
context,
|
|
947
1008
|
message
|
|
948
1009
|
},
|
|
949
1010
|
level
|
|
950
|
-
}
|
|
1011
|
+
};
|
|
1012
|
+
sendNotification({ method: "notifications/message", params }).catch(() => this.#server.sendLoggingMessage(params)).catch((error) => {
|
|
951
1013
|
this.#logger.error(
|
|
952
1014
|
`[FastMCP error] failed to send ${level} log notification.
|
|
953
1015
|
|
|
@@ -1258,54 +1320,61 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1258
1320
|
prompts: cachedPromptsList
|
|
1259
1321
|
};
|
|
1260
1322
|
});
|
|
1261
|
-
this.#server.setRequestHandler(
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
`Unknown prompt: ${request.params.name}`
|
|
1267
|
-
);
|
|
1268
|
-
}
|
|
1269
|
-
const args = request.params.arguments;
|
|
1270
|
-
for (const arg of prompt.arguments ?? []) {
|
|
1271
|
-
if (arg.required && !(args && Object.hasOwn(args, arg.name))) {
|
|
1323
|
+
this.#server.setRequestHandler(
|
|
1324
|
+
GetPromptRequestSchema,
|
|
1325
|
+
async (request, extra) => {
|
|
1326
|
+
const prompt = this.#prompts.get(request.params.name);
|
|
1327
|
+
if (!prompt) {
|
|
1272
1328
|
throw new McpError(
|
|
1273
1329
|
ErrorCode.InvalidParams,
|
|
1274
|
-
`
|
|
1330
|
+
`Unknown prompt: ${request.params.name}`
|
|
1275
1331
|
);
|
|
1276
1332
|
}
|
|
1333
|
+
const args = request.params.arguments;
|
|
1334
|
+
for (const arg of prompt.arguments ?? []) {
|
|
1335
|
+
if (arg.required && !(args && Object.hasOwn(args, arg.name))) {
|
|
1336
|
+
throw new McpError(
|
|
1337
|
+
ErrorCode.InvalidParams,
|
|
1338
|
+
`Prompt '${request.params.name}' requires argument '${arg.name}': ${arg.description || "No description provided"}`
|
|
1339
|
+
);
|
|
1340
|
+
}
|
|
1341
|
+
}
|
|
1342
|
+
let result;
|
|
1343
|
+
try {
|
|
1344
|
+
result = await prompt.load(
|
|
1345
|
+
args ?? {},
|
|
1346
|
+
this.#auth,
|
|
1347
|
+
this.#createLoadContext(
|
|
1348
|
+
request.params?._meta,
|
|
1349
|
+
extra.sendNotification,
|
|
1350
|
+
extra.requestId
|
|
1351
|
+
)
|
|
1352
|
+
);
|
|
1353
|
+
} catch (error) {
|
|
1354
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1355
|
+
throw new McpError(
|
|
1356
|
+
ErrorCode.InternalError,
|
|
1357
|
+
`Failed to load prompt '${request.params.name}': ${errorMessage}`
|
|
1358
|
+
);
|
|
1359
|
+
}
|
|
1360
|
+
if (typeof result === "string") {
|
|
1361
|
+
return {
|
|
1362
|
+
description: prompt.description,
|
|
1363
|
+
messages: [
|
|
1364
|
+
{
|
|
1365
|
+
content: { text: result, type: "text" },
|
|
1366
|
+
role: "user"
|
|
1367
|
+
}
|
|
1368
|
+
]
|
|
1369
|
+
};
|
|
1370
|
+
} else {
|
|
1371
|
+
return {
|
|
1372
|
+
description: prompt.description,
|
|
1373
|
+
messages: result.messages
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1277
1376
|
}
|
|
1278
|
-
|
|
1279
|
-
try {
|
|
1280
|
-
result = await prompt.load(
|
|
1281
|
-
args ?? {},
|
|
1282
|
-
this.#auth,
|
|
1283
|
-
this.#createLoadContext(request.params?._meta)
|
|
1284
|
-
);
|
|
1285
|
-
} catch (error) {
|
|
1286
|
-
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1287
|
-
throw new McpError(
|
|
1288
|
-
ErrorCode.InternalError,
|
|
1289
|
-
`Failed to load prompt '${request.params.name}': ${errorMessage}`
|
|
1290
|
-
);
|
|
1291
|
-
}
|
|
1292
|
-
if (typeof result === "string") {
|
|
1293
|
-
return {
|
|
1294
|
-
description: prompt.description,
|
|
1295
|
-
messages: [
|
|
1296
|
-
{
|
|
1297
|
-
content: { text: result, type: "text" },
|
|
1298
|
-
role: "user"
|
|
1299
|
-
}
|
|
1300
|
-
]
|
|
1301
|
-
};
|
|
1302
|
-
} else {
|
|
1303
|
-
return {
|
|
1304
|
-
description: prompt.description,
|
|
1305
|
-
messages: result.messages
|
|
1306
|
-
};
|
|
1307
|
-
}
|
|
1308
|
-
});
|
|
1377
|
+
);
|
|
1309
1378
|
}
|
|
1310
1379
|
setupResourceHandlers() {
|
|
1311
1380
|
let cachedResourcesList = null;
|
|
@@ -1329,7 +1398,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1329
1398
|
});
|
|
1330
1399
|
this.#server.setRequestHandler(
|
|
1331
1400
|
ReadResourceRequestSchema,
|
|
1332
|
-
async (request) => {
|
|
1401
|
+
async (request, extra) => {
|
|
1333
1402
|
if ("uri" in request.params) {
|
|
1334
1403
|
const resource = this.#resources.get(request.params.uri);
|
|
1335
1404
|
if (!resource) {
|
|
@@ -1345,7 +1414,11 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1345
1414
|
const result = await resourceTemplate.load(
|
|
1346
1415
|
match,
|
|
1347
1416
|
this.#auth,
|
|
1348
|
-
this.#createLoadContext(
|
|
1417
|
+
this.#createLoadContext(
|
|
1418
|
+
request.params?._meta,
|
|
1419
|
+
extra.sendNotification,
|
|
1420
|
+
extra.requestId
|
|
1421
|
+
)
|
|
1349
1422
|
);
|
|
1350
1423
|
const resources = Array.isArray(result) ? result : [result];
|
|
1351
1424
|
return {
|
|
@@ -1371,7 +1444,11 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1371
1444
|
try {
|
|
1372
1445
|
maybeArrayResult = await resource.load(
|
|
1373
1446
|
this.#auth,
|
|
1374
|
-
this.#createLoadContext(
|
|
1447
|
+
this.#createLoadContext(
|
|
1448
|
+
request.params?._meta,
|
|
1449
|
+
extra.sendNotification,
|
|
1450
|
+
extra.requestId
|
|
1451
|
+
)
|
|
1375
1452
|
);
|
|
1376
1453
|
} catch (error) {
|
|
1377
1454
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -1471,6 +1548,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1471
1548
|
}
|
|
1472
1549
|
}
|
|
1473
1550
|
setupToolHandlers(tools) {
|
|
1551
|
+
this.#visibleTools = tools;
|
|
1474
1552
|
const toolsMap = new Map(tools.map((tool) => [tool.name, tool]));
|
|
1475
1553
|
let cachedToolsList = null;
|
|
1476
1554
|
this.#server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
@@ -1484,7 +1562,9 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1484
1562
|
return {
|
|
1485
1563
|
annotations: tool.annotations,
|
|
1486
1564
|
description: tool.description,
|
|
1487
|
-
inputSchema: tool.parameters ? strictInputSchema(
|
|
1565
|
+
inputSchema: tool.parameters ? strictInputSchema(
|
|
1566
|
+
tool.parameters["~standard"].vendor === "zod" && "_zod" in tool.parameters ? zodInputSchema(tool.parameters, "draft-7") : await toJsonSchema(tool.parameters)
|
|
1567
|
+
) : {
|
|
1488
1568
|
additionalProperties: false,
|
|
1489
1569
|
properties: {},
|
|
1490
1570
|
type: "object"
|
|
@@ -1553,7 +1633,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1553
1633
|
);
|
|
1554
1634
|
}
|
|
1555
1635
|
};
|
|
1556
|
-
const log = this.#createLog();
|
|
1636
|
+
const log = this.#createLog(extra.sendNotification);
|
|
1557
1637
|
const streamContent = async (content) => {
|
|
1558
1638
|
const contentArray = Array.isArray(content) ? content : [content];
|
|
1559
1639
|
try {
|
|
@@ -1593,7 +1673,7 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1593
1673
|
client: {
|
|
1594
1674
|
version: this.#server.getClientVersion()
|
|
1595
1675
|
},
|
|
1596
|
-
elicit:
|
|
1676
|
+
elicit: this.#createElicit(extra.requestId),
|
|
1597
1677
|
log,
|
|
1598
1678
|
reportProgress,
|
|
1599
1679
|
requestId: typeof request.params?._meta?.requestId === "string" ? request.params._meta.requestId : void 0,
|
|
@@ -2217,7 +2297,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2217
2297
|
roots: this.#options.roots,
|
|
2218
2298
|
streamKeepalive: this.#options.streamKeepalive,
|
|
2219
2299
|
title: this.#options.title,
|
|
2220
|
-
tools:
|
|
2300
|
+
tools: this.#tools,
|
|
2221
2301
|
transportType: "stdio",
|
|
2222
2302
|
utils: this.#options.utils,
|
|
2223
2303
|
version: this.#options.version,
|
|
@@ -2273,7 +2353,12 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2273
2353
|
auth = this.#requireAuthenticated(await authenticate(request));
|
|
2274
2354
|
}
|
|
2275
2355
|
const sessionId = Array.isArray(request.headers["mcp-session-id"]) ? request.headers["mcp-session-id"][0] : request.headers["mcp-session-id"];
|
|
2276
|
-
return this.#createSession(
|
|
2356
|
+
return this.#createSession(
|
|
2357
|
+
auth,
|
|
2358
|
+
sessionId,
|
|
2359
|
+
true,
|
|
2360
|
+
httpConfig.enableJsonResponse
|
|
2361
|
+
);
|
|
2277
2362
|
},
|
|
2278
2363
|
enableJsonResponse: httpConfig.enableJsonResponse,
|
|
2279
2364
|
eventStore: httpConfig.eventStore,
|
|
@@ -2315,7 +2400,12 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2315
2400
|
auth = this.#requireAuthenticated(await authenticate(request));
|
|
2316
2401
|
}
|
|
2317
2402
|
const sessionId = Array.isArray(request.headers["mcp-session-id"]) ? request.headers["mcp-session-id"][0] : request.headers["mcp-session-id"];
|
|
2318
|
-
return this.#createSession(
|
|
2403
|
+
return this.#createSession(
|
|
2404
|
+
auth,
|
|
2405
|
+
sessionId,
|
|
2406
|
+
false,
|
|
2407
|
+
httpConfig.enableJsonResponse
|
|
2408
|
+
);
|
|
2319
2409
|
},
|
|
2320
2410
|
enableJsonResponse: httpConfig.enableJsonResponse,
|
|
2321
2411
|
eventStore: httpConfig.eventStore,
|
|
@@ -2404,7 +2494,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2404
2494
|
* Creates a new FastMCPSession instance with the current configuration.
|
|
2405
2495
|
* Used both for regular sessions and stateless requests.
|
|
2406
2496
|
*/
|
|
2407
|
-
#createSession(auth, sessionId, stateless = false) {
|
|
2497
|
+
#createSession(auth, sessionId, stateless = false, enableJsonResponse) {
|
|
2408
2498
|
if (auth && typeof auth === "object" && "authenticated" in auth && !auth.authenticated) {
|
|
2409
2499
|
const errorMessage = "error" in auth && typeof auth.error === "string" ? auth.error : "Authentication failed";
|
|
2410
2500
|
throw this.#createUnauthorizedResponse(errorMessage);
|
|
@@ -2413,6 +2503,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2413
2503
|
return new FastMCPSession({
|
|
2414
2504
|
auth,
|
|
2415
2505
|
authRequired,
|
|
2506
|
+
enableJsonResponse,
|
|
2416
2507
|
hasTools: this.#tools.length > 0,
|
|
2417
2508
|
icons: this.#options.icons,
|
|
2418
2509
|
instructions: this.#options.instructions,
|
|
@@ -2428,7 +2519,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2428
2519
|
stateless,
|
|
2429
2520
|
streamKeepalive: this.#options.streamKeepalive,
|
|
2430
2521
|
title: this.#options.title,
|
|
2431
|
-
tools:
|
|
2522
|
+
tools: this.#tools,
|
|
2432
2523
|
transportType: "httpStream",
|
|
2433
2524
|
utils: this.#options.utils,
|
|
2434
2525
|
version: this.#options.version,
|
|
@@ -3156,4 +3247,4 @@ export {
|
|
|
3156
3247
|
FastMCPSession,
|
|
3157
3248
|
FastMCP
|
|
3158
3249
|
};
|
|
3159
|
-
//# sourceMappingURL=chunk-
|
|
3250
|
+
//# sourceMappingURL=chunk-7WNI6AGD.js.map
|