fastmcp 4.21.1 → 4.22.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/README.md +23 -6
- package/dist/FastMCP.cjs +4 -3
- package/dist/FastMCP.cjs.map +1 -1
- package/dist/FastMCP.d.cts +9 -3
- package/dist/FastMCP.d.ts +9 -3
- package/dist/FastMCP.js +3 -2
- package/dist/{OAuthProvider-C4idKF29.d.cts → OAuthProvider-BcDb5bOz.d.cts} +8 -1
- package/dist/{OAuthProvider-C4idKF29.d.ts → OAuthProvider-BcDb5bOz.d.ts} +8 -1
- package/dist/auth/index.cjs +2 -2
- package/dist/auth/index.d.cts +2 -2
- package/dist/auth/index.d.ts +2 -2
- package/dist/auth/index.js +1 -1
- package/dist/{chunk-JNP6BG5L.js → chunk-43N2Q6ZI.js} +146 -36
- package/dist/chunk-43N2Q6ZI.js.map +1 -0
- package/dist/chunk-O22SYZMC.cjs +22 -0
- package/dist/chunk-O22SYZMC.cjs.map +1 -0
- package/dist/chunk-UMDUIBFW.js +22 -0
- package/dist/chunk-UMDUIBFW.js.map +1 -0
- package/dist/{chunk-IKH7YBYP.cjs → chunk-V4JBWBT4.cjs} +150 -40
- package/dist/chunk-V4JBWBT4.cjs.map +1 -0
- package/dist/{chunk-AR3LVWUF.js → chunk-XPKMA7DH.js} +22 -1
- package/dist/chunk-XPKMA7DH.js.map +1 -0
- package/dist/{chunk-GTPK7A57.cjs → chunk-YOBCXNFP.cjs} +22 -1
- package/dist/chunk-YOBCXNFP.cjs.map +1 -0
- package/dist/edge/index.cjs +7 -4
- package/dist/edge/index.cjs.map +1 -1
- package/dist/edge/index.js +6 -3
- package/dist/edge/index.js.map +1 -1
- package/dist/examples/custom-routes.cjs +4 -3
- package/dist/examples/custom-routes.cjs.map +1 -1
- package/dist/examples/custom-routes.js +3 -2
- package/dist/examples/custom-routes.js.map +1 -1
- package/dist/openapi/index.cjs +25 -9
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.d.cts +5 -3
- package/dist/openapi/index.d.ts +5 -3
- package/dist/openapi/index.js +21 -5
- package/dist/openapi/index.js.map +1 -1
- package/package.json +2 -2
- package/dist/chunk-AR3LVWUF.js.map +0 -1
- package/dist/chunk-GTPK7A57.cjs.map +0 -1
- package/dist/chunk-IKH7YBYP.cjs.map +0 -1
- package/dist/chunk-JNP6BG5L.js.map +0 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
cancelResponseBody
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-XPKMA7DH.js";
|
|
4
|
+
import {
|
|
5
|
+
strictInputSchema
|
|
6
|
+
} from "./chunk-UMDUIBFW.js";
|
|
4
7
|
|
|
5
8
|
// src/FastMCP.ts
|
|
6
9
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -376,21 +379,6 @@ function assertToolSchemas(tool) {
|
|
|
376
379
|
assertStandardSchema(tool.name, "outputSchema", tool.outputSchema);
|
|
377
380
|
}
|
|
378
381
|
}
|
|
379
|
-
function strictInputSchema(schema) {
|
|
380
|
-
const isDictionary = typeof schema.additionalProperties === "object" && Object.keys(schema.properties ?? {}).length === 0;
|
|
381
|
-
return {
|
|
382
|
-
...schema,
|
|
383
|
-
additionalProperties: isDictionary ? schema.additionalProperties : false,
|
|
384
|
-
...schema.properties && {
|
|
385
|
-
properties: Object.fromEntries(
|
|
386
|
-
Object.entries(schema.properties).map(([key, value]) => [
|
|
387
|
-
key,
|
|
388
|
-
typeof value === "object" && value.type === "object" ? strictInputSchema(value) : value
|
|
389
|
-
])
|
|
390
|
-
)
|
|
391
|
-
}
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
382
|
var STREAM_KEEPALIVE_LOGGER = "fastmcp-keepalive";
|
|
395
383
|
var STREAM_KEEPALIVE_DEFAULT_INTERVAL_MS = 2e4;
|
|
396
384
|
var TextContentZodSchema = z.object({
|
|
@@ -476,6 +464,17 @@ var capCompletionValues = (completion) => {
|
|
|
476
464
|
values: completion.values.slice(0, COMPLETION_VALUES_LIMIT)
|
|
477
465
|
};
|
|
478
466
|
};
|
|
467
|
+
var DEFAULT_LOGGING_LEVEL = "info";
|
|
468
|
+
var LOGGING_LEVEL_SEVERITY = {
|
|
469
|
+
alert: 6,
|
|
470
|
+
critical: 5,
|
|
471
|
+
debug: 0,
|
|
472
|
+
emergency: 7,
|
|
473
|
+
error: 4,
|
|
474
|
+
info: 1,
|
|
475
|
+
notice: 2,
|
|
476
|
+
warning: 3
|
|
477
|
+
};
|
|
479
478
|
var FastMCPSessionEventEmitterBase = EventEmitter;
|
|
480
479
|
var ServerState = /* @__PURE__ */ ((ServerState2) => {
|
|
481
480
|
ServerState2["Error"] = "error";
|
|
@@ -493,7 +492,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
493
492
|
return this.#connectionState === "ready";
|
|
494
493
|
}
|
|
495
494
|
get loggingLevel() {
|
|
496
|
-
return this.#loggingLevel;
|
|
495
|
+
return this.#loggingLevel ?? DEFAULT_LOGGING_LEVEL;
|
|
497
496
|
}
|
|
498
497
|
get roots() {
|
|
499
498
|
return this.#roots;
|
|
@@ -537,11 +536,16 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
537
536
|
*/
|
|
538
537
|
#abortController = new AbortController();
|
|
539
538
|
#auth;
|
|
539
|
+
#authRequired;
|
|
540
540
|
#capabilities = {};
|
|
541
541
|
#clientCapabilities;
|
|
542
542
|
#connectionState = "connecting";
|
|
543
543
|
#logger;
|
|
544
|
-
|
|
544
|
+
/**
|
|
545
|
+
* The minimum level the client asked for with `logging/setLevel`, or
|
|
546
|
+
* `undefined` while it has not asked. See {@link DEFAULT_LOGGING_LEVEL}.
|
|
547
|
+
*/
|
|
548
|
+
#loggingLevel;
|
|
545
549
|
#needsEventLoopFlush = false;
|
|
546
550
|
#onToolCall;
|
|
547
551
|
#pingConfig;
|
|
@@ -572,9 +576,16 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
572
576
|
*/
|
|
573
577
|
#subscriptions = /* @__PURE__ */ new Set();
|
|
574
578
|
#transportType;
|
|
579
|
+
/**
|
|
580
|
+
* Capabilities this session has already warned about in `#canRefresh`, so a
|
|
581
|
+
* server that registers a hundred resources at runtime logs one line rather
|
|
582
|
+
* than a hundred.
|
|
583
|
+
*/
|
|
584
|
+
#unnegotiatedWarnings = /* @__PURE__ */ new Set();
|
|
575
585
|
#utils;
|
|
576
586
|
constructor({
|
|
577
587
|
auth,
|
|
588
|
+
authRequired = false,
|
|
578
589
|
hasTools,
|
|
579
590
|
icons,
|
|
580
591
|
instructions,
|
|
@@ -598,6 +609,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
598
609
|
}) {
|
|
599
610
|
super();
|
|
600
611
|
this.#auth = auth;
|
|
612
|
+
this.#authRequired = authRequired;
|
|
601
613
|
this.#logger = logger;
|
|
602
614
|
this.#onToolCall = onToolCall;
|
|
603
615
|
this.#pingConfig = ping;
|
|
@@ -609,7 +621,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
609
621
|
this.#needsEventLoopFlush = transportType === "httpStream";
|
|
610
622
|
const supportsTools = hasTools ?? tools.length > 0;
|
|
611
623
|
if (supportsTools) {
|
|
612
|
-
this.#capabilities.tools = {};
|
|
624
|
+
this.#capabilities.tools = { listChanged: true };
|
|
613
625
|
}
|
|
614
626
|
if (resources.length || resourcesTemplates.length) {
|
|
615
627
|
this.#capabilities.resources = { listChanged: true, subscribe: true };
|
|
@@ -753,6 +765,9 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
|
|
|
753
765
|
}
|
|
754
766
|
}
|
|
755
767
|
promptsListChanged(prompts) {
|
|
768
|
+
if (!this.#canRefresh("prompts")) {
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
756
771
|
this.#prompts.clear();
|
|
757
772
|
for (const prompt of prompts) {
|
|
758
773
|
this.addPrompt(prompt);
|
|
@@ -767,6 +782,9 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
|
|
|
767
782
|
return this.#server.createMessage(message, options);
|
|
768
783
|
}
|
|
769
784
|
resourcesListChanged(resources) {
|
|
785
|
+
if (!this.#canRefresh("resources")) {
|
|
786
|
+
return;
|
|
787
|
+
}
|
|
770
788
|
this.#resources.clear();
|
|
771
789
|
for (const resource of resources) {
|
|
772
790
|
this.addResource(resource);
|
|
@@ -775,6 +793,9 @@ ${e instanceof Error ? e.stack : JSON.stringify(e)}`
|
|
|
775
793
|
this.triggerListChangedNotification("notifications/resources/list_changed");
|
|
776
794
|
}
|
|
777
795
|
resourceTemplatesListChanged(resourceTemplates) {
|
|
796
|
+
if (!this.#canRefresh("resources")) {
|
|
797
|
+
return;
|
|
798
|
+
}
|
|
778
799
|
this.#resourceTemplates.clear();
|
|
779
800
|
for (const resourceTemplate of resourceTemplates) {
|
|
780
801
|
this.addResourceTemplate(resourceTemplate);
|
|
@@ -804,7 +825,12 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
804
825
|
}
|
|
805
826
|
}
|
|
806
827
|
toolsListChanged(tools) {
|
|
807
|
-
this
|
|
828
|
+
if (!this.#canRefresh("tools")) {
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
this.setupToolHandlers(
|
|
832
|
+
toolsVisibleTo(tools, this.#auth, this.#authRequired)
|
|
833
|
+
);
|
|
808
834
|
this.triggerListChangedNotification("notifications/tools/list_changed");
|
|
809
835
|
}
|
|
810
836
|
async triggerListChangedNotification(method) {
|
|
@@ -864,6 +890,30 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
864
890
|
this.#abortController.abort(new SessionError("Session closed"));
|
|
865
891
|
}
|
|
866
892
|
}
|
|
893
|
+
/**
|
|
894
|
+
* Whether this session can be told about a primitive added at runtime.
|
|
895
|
+
*
|
|
896
|
+
* A session that connected before the server had any tool, resource or prompt
|
|
897
|
+
* of its own never advertised that capability, and MCP fixes capabilities
|
|
898
|
+
* during `initialize` for the life of the session. Registering the handler
|
|
899
|
+
* anyway makes the SDK throw `Server does not support <capability>` — out of
|
|
900
|
+
* `addTool()`, `addResource()`, `addResourceTemplate()` or `addPrompt()`,
|
|
901
|
+
* which are the public builder methods, and out of the middle of the loop
|
|
902
|
+
* over sessions, so the sessions after this one never heard about the change
|
|
903
|
+
* either. Warn once instead and let the rest of the loop run.
|
|
904
|
+
*/
|
|
905
|
+
#canRefresh(capability) {
|
|
906
|
+
if (this.#capabilities[capability]) {
|
|
907
|
+
return true;
|
|
908
|
+
}
|
|
909
|
+
if (!this.#unnegotiatedWarnings.has(capability)) {
|
|
910
|
+
this.#unnegotiatedWarnings.add(capability);
|
|
911
|
+
this.#logger.warn(
|
|
912
|
+
`[FastMCP warning] This session advertised no '${capability}' capability, because the server had none when the client connected, so it cannot be shown the ones registered since. Register one before start(), or reconnect the client; sessions that connect from now on do see them.`
|
|
913
|
+
);
|
|
914
|
+
}
|
|
915
|
+
return false;
|
|
916
|
+
}
|
|
867
917
|
/**
|
|
868
918
|
* Builds the context object passed as the third argument to
|
|
869
919
|
* `resource.load` / `resourceTemplate.load` / `prompt.load`.
|
|
@@ -924,6 +974,9 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
924
974
|
* disconnects mid-tool takes the server process down with it.
|
|
925
975
|
*/
|
|
926
976
|
#sendLog(level, message, context) {
|
|
977
|
+
if (this.#loggingLevel && LOGGING_LEVEL_SEVERITY[level] < LOGGING_LEVEL_SEVERITY[this.#loggingLevel]) {
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
927
980
|
this.#server.sendLoggingMessage({
|
|
928
981
|
data: {
|
|
929
982
|
context,
|
|
@@ -947,6 +1000,12 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
947
1000
|
* request's own stream, which is the only server-to-client route that exists
|
|
948
1001
|
* when running stateless.
|
|
949
1002
|
*
|
|
1003
|
+
* It is deliberately not filtered against the level the client set with
|
|
1004
|
+
* `logging/setLevel`, unlike the `log` object a tool is handed: its job is to
|
|
1005
|
+
* put bytes on the stream, and a client that asked for `error` only would
|
|
1006
|
+
* otherwise switch off a feature the server opted into. Raise
|
|
1007
|
+
* `streamKeepalive.logLevel` if the level it uses matters to you.
|
|
1008
|
+
*
|
|
950
1009
|
* @returns a function that stops the keepalive.
|
|
951
1010
|
*/
|
|
952
1011
|
#startStreamKeepalive(extra, toolName) {
|
|
@@ -1067,9 +1126,10 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1067
1126
|
const ref = request.params.ref;
|
|
1068
1127
|
const prompt = "name" in ref && this.#prompts.get(ref.name);
|
|
1069
1128
|
if (!prompt) {
|
|
1070
|
-
throw new
|
|
1071
|
-
|
|
1072
|
-
|
|
1129
|
+
throw new McpError(
|
|
1130
|
+
ErrorCode.InvalidParams,
|
|
1131
|
+
`Unknown prompt: ${ref.name}`
|
|
1132
|
+
);
|
|
1073
1133
|
}
|
|
1074
1134
|
if (!prompt.complete) {
|
|
1075
1135
|
throw new UnexpectedStateError("Prompt does not support completion", {
|
|
@@ -1095,9 +1155,10 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
1095
1155
|
(resource2) => resource2.uriTemplate === ref.uri
|
|
1096
1156
|
);
|
|
1097
1157
|
if (!resource) {
|
|
1098
|
-
throw new
|
|
1099
|
-
|
|
1100
|
-
|
|
1158
|
+
throw new McpError(
|
|
1159
|
+
ErrorCode.InvalidParams,
|
|
1160
|
+
`Unknown resource template: ${ref.uri}`
|
|
1161
|
+
);
|
|
1101
1162
|
}
|
|
1102
1163
|
if (!("uriTemplate" in resource)) {
|
|
1103
1164
|
throw new UnexpectedStateError("Unexpected resource");
|
|
@@ -1627,6 +1688,17 @@ function parseBasicAuthHeader(authHeader) {
|
|
|
1627
1688
|
return null;
|
|
1628
1689
|
}
|
|
1629
1690
|
}
|
|
1691
|
+
function protectedResourceMetadataUrl(resource) {
|
|
1692
|
+
let url;
|
|
1693
|
+
try {
|
|
1694
|
+
url = new URL(resource);
|
|
1695
|
+
} catch {
|
|
1696
|
+
return `${resource}/.well-known/oauth-protected-resource`;
|
|
1697
|
+
}
|
|
1698
|
+
const path = url.pathname === "/" ? "" : url.pathname;
|
|
1699
|
+
url.pathname = `/.well-known/oauth-protected-resource${path}`;
|
|
1700
|
+
return url.toString();
|
|
1701
|
+
}
|
|
1630
1702
|
var OAUTH_PROXY_MAX_BODY_SIZE = 1024 * 1024;
|
|
1631
1703
|
var OAUTH_CREDENTIAL_RESPONSE_HEADERS = {
|
|
1632
1704
|
"Cache-Control": "no-store",
|
|
@@ -1645,8 +1717,13 @@ function stripBasePath(path, basePath) {
|
|
|
1645
1717
|
}
|
|
1646
1718
|
return null;
|
|
1647
1719
|
}
|
|
1648
|
-
function toolsVisibleTo(tools, auth) {
|
|
1649
|
-
|
|
1720
|
+
function toolsVisibleTo(tools, auth, authRequired) {
|
|
1721
|
+
if (auth) {
|
|
1722
|
+
return tools.filter(
|
|
1723
|
+
(tool) => tool.canAccess ? tool.canAccess(auth) : true
|
|
1724
|
+
);
|
|
1725
|
+
}
|
|
1726
|
+
return authRequired ? tools.filter((tool) => !tool.canAccess) : tools;
|
|
1650
1727
|
}
|
|
1651
1728
|
var FastMCPEventEmitterBase = EventEmitter;
|
|
1652
1729
|
var FastMCPEventEmitter = class extends FastMCPEventEmitterBase {
|
|
@@ -1664,10 +1741,9 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1664
1741
|
this.#authenticate = options.authenticate;
|
|
1665
1742
|
}
|
|
1666
1743
|
if (!options.oauth) {
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
};
|
|
1744
|
+
const oauth = options.auth.getOAuthConfig();
|
|
1745
|
+
this.#providerResourceBase = oauth.protectedResource.resource;
|
|
1746
|
+
this.#options = { ...options, oauth };
|
|
1671
1747
|
}
|
|
1672
1748
|
} else {
|
|
1673
1749
|
this.#authenticate = options.authenticate;
|
|
@@ -1685,6 +1761,8 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1685
1761
|
#logger;
|
|
1686
1762
|
#options;
|
|
1687
1763
|
#prompts = [];
|
|
1764
|
+
/** The auth provider's base URL, when it supplied the OAuth config. */
|
|
1765
|
+
#providerResourceBase;
|
|
1688
1766
|
#resources = [];
|
|
1689
1767
|
#resourcesTemplates = [];
|
|
1690
1768
|
#serverState = "stopped" /* Stopped */;
|
|
@@ -2027,6 +2105,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2027
2105
|
if (config.transportType === "stdio") {
|
|
2028
2106
|
const transport = new StdioServerTransport();
|
|
2029
2107
|
let auth;
|
|
2108
|
+
const authRequired = this.#authenticate !== void 0;
|
|
2030
2109
|
if (this.#authenticate) {
|
|
2031
2110
|
try {
|
|
2032
2111
|
auth = await this.#authenticate(
|
|
@@ -2038,9 +2117,15 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2038
2117
|
error instanceof Error ? error.message : String(error)
|
|
2039
2118
|
);
|
|
2040
2119
|
}
|
|
2120
|
+
if (!auth && this.#tools.some((tool) => tool.canAccess)) {
|
|
2121
|
+
this.#logger.warn(
|
|
2122
|
+
"[FastMCP warning] The stdio session has no auth, so tools gated by canAccess are hidden from it."
|
|
2123
|
+
);
|
|
2124
|
+
}
|
|
2041
2125
|
}
|
|
2042
2126
|
const session = new FastMCPSession({
|
|
2043
2127
|
auth,
|
|
2128
|
+
authRequired,
|
|
2044
2129
|
hasTools: this.#tools.length > 0,
|
|
2045
2130
|
icons: this.#options.icons,
|
|
2046
2131
|
instructions: this.#options.instructions,
|
|
@@ -2054,7 +2139,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2054
2139
|
roots: this.#options.roots,
|
|
2055
2140
|
streamKeepalive: this.#options.streamKeepalive,
|
|
2056
2141
|
title: this.#options.title,
|
|
2057
|
-
tools: toolsVisibleTo(this.#tools, auth),
|
|
2142
|
+
tools: toolsVisibleTo(this.#tools, auth, authRequired),
|
|
2058
2143
|
transportType: "stdio",
|
|
2059
2144
|
utils: this.#options.utils,
|
|
2060
2145
|
version: this.#options.version,
|
|
@@ -2104,6 +2189,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2104
2189
|
httpConfig.basePath,
|
|
2105
2190
|
httpConfig.endpoint
|
|
2106
2191
|
);
|
|
2192
|
+
this.#useEndpointAsResource(httpConfig.endpoint);
|
|
2107
2193
|
if (httpConfig.stateless) {
|
|
2108
2194
|
this.#logger.info(
|
|
2109
2195
|
`[FastMCP info] Starting server in stateless mode on HTTP Stream at ${protocol}://${httpConfig.host}:${httpConfig.port}${streamEndpoint}`
|
|
@@ -2224,8 +2310,10 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2224
2310
|
const errorMessage = "error" in auth && typeof auth.error === "string" ? auth.error : "Authentication failed";
|
|
2225
2311
|
throw this.#createUnauthorizedResponse(errorMessage);
|
|
2226
2312
|
}
|
|
2313
|
+
const authRequired = this.#authenticate !== void 0;
|
|
2227
2314
|
return new FastMCPSession({
|
|
2228
2315
|
auth,
|
|
2316
|
+
authRequired,
|
|
2229
2317
|
hasTools: this.#tools.length > 0,
|
|
2230
2318
|
icons: this.#options.icons,
|
|
2231
2319
|
instructions: this.#options.instructions,
|
|
@@ -2241,7 +2329,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2241
2329
|
stateless,
|
|
2242
2330
|
streamKeepalive: this.#options.streamKeepalive,
|
|
2243
2331
|
title: this.#options.title,
|
|
2244
|
-
tools: toolsVisibleTo(this.#tools, auth),
|
|
2332
|
+
tools: toolsVisibleTo(this.#tools, auth, authRequired),
|
|
2245
2333
|
transportType: "httpStream",
|
|
2246
2334
|
utils: this.#options.utils,
|
|
2247
2335
|
version: this.#options.version,
|
|
@@ -2270,7 +2358,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2270
2358
|
];
|
|
2271
2359
|
if (resource) {
|
|
2272
2360
|
wwwAuthenticateParts.push(
|
|
2273
|
-
`resource_metadata="${resource}
|
|
2361
|
+
`resource_metadata="${protectedResourceMetadataUrl(resource)}"`
|
|
2274
2362
|
);
|
|
2275
2363
|
}
|
|
2276
2364
|
return new Response(
|
|
@@ -2921,6 +3009,28 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
2921
3009
|
session.toolsListChanged(tools);
|
|
2922
3010
|
}
|
|
2923
3011
|
}
|
|
3012
|
+
/**
|
|
3013
|
+
* RFC 9728: the protected resource is the MCP endpoint clients connect to,
|
|
3014
|
+
* and the metadata served at `/.well-known/oauth-protected-resource<endpoint>`
|
|
3015
|
+
* must name it. An auth provider only knows its base URL, so the endpoint is
|
|
3016
|
+
* appended once the server knows it. An explicit `oauth` config is left as
|
|
3017
|
+
* it is.
|
|
3018
|
+
*/
|
|
3019
|
+
#useEndpointAsResource(endpoint) {
|
|
3020
|
+
const oauth = this.#options.oauth;
|
|
3021
|
+
if (this.#providerResourceBase === void 0 || !oauth?.protectedResource)
|
|
3022
|
+
return;
|
|
3023
|
+
this.#options = {
|
|
3024
|
+
...this.#options,
|
|
3025
|
+
oauth: {
|
|
3026
|
+
...oauth,
|
|
3027
|
+
protectedResource: {
|
|
3028
|
+
...oauth.protectedResource,
|
|
3029
|
+
resource: `${this.#providerResourceBase.replace(/\/+$/, "")}${normalizePath(endpoint)}`
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
};
|
|
3033
|
+
}
|
|
2924
3034
|
};
|
|
2925
3035
|
|
|
2926
3036
|
export {
|
|
@@ -2937,4 +3047,4 @@ export {
|
|
|
2937
3047
|
FastMCPSession,
|
|
2938
3048
|
FastMCP
|
|
2939
3049
|
};
|
|
2940
|
-
//# sourceMappingURL=chunk-
|
|
3050
|
+
//# sourceMappingURL=chunk-43N2Q6ZI.js.map
|