fastmcp 1.13.0 → 1.15.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 +41 -1
- package/dist/FastMCP.d.ts +39 -4
- package/dist/FastMCP.js +120 -9
- package/dist/FastMCP.js.map +1 -1
- package/jsr.json +1 -1
- package/package.json +3 -1
- package/src/FastMCP.test.ts +155 -1
- package/src/FastMCP.ts +200 -19
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
A TypeScript framework for building [MCP](https://modelcontextprotocol.io/) servers capable of handling client sessions.
|
|
4
4
|
|
|
5
5
|
> [!NOTE]
|
|
6
|
+
>
|
|
6
7
|
> For a Python implementation, see [FastMCP](https://github.com/jlowin/fastmcp).
|
|
7
8
|
|
|
8
9
|
## Features
|
|
@@ -364,6 +365,7 @@ server.addResource({
|
|
|
364
365
|
```
|
|
365
366
|
|
|
366
367
|
> [!NOTE]
|
|
368
|
+
>
|
|
367
369
|
> `load` can return multiple resources. This could be used, for example, to return a list of files inside a directory when the directory is read.
|
|
368
370
|
>
|
|
369
371
|
> ```ts
|
|
@@ -389,6 +391,8 @@ async load() {
|
|
|
389
391
|
}
|
|
390
392
|
```
|
|
391
393
|
|
|
394
|
+
### Resource templates
|
|
395
|
+
|
|
392
396
|
You can also define resource templates:
|
|
393
397
|
|
|
394
398
|
```ts
|
|
@@ -411,6 +415,41 @@ server.addResourceTemplate({
|
|
|
411
415
|
});
|
|
412
416
|
```
|
|
413
417
|
|
|
418
|
+
#### Resource template argument auto-completion
|
|
419
|
+
|
|
420
|
+
Provide `complete` functions for resource template arguments to enable automatic completion:
|
|
421
|
+
|
|
422
|
+
```ts
|
|
423
|
+
server.addResourceTemplate({
|
|
424
|
+
uriTemplate: "file:///logs/{name}.log",
|
|
425
|
+
name: "Application Logs",
|
|
426
|
+
mimeType: "text/plain",
|
|
427
|
+
arguments: [
|
|
428
|
+
{
|
|
429
|
+
name: "name",
|
|
430
|
+
description: "Name of the log",
|
|
431
|
+
required: true,
|
|
432
|
+
complete: async (value) => {
|
|
433
|
+
if (value === "Example") {
|
|
434
|
+
return {
|
|
435
|
+
values: ["Example Log"],
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
return {
|
|
440
|
+
values: [],
|
|
441
|
+
};
|
|
442
|
+
},
|
|
443
|
+
},
|
|
444
|
+
],
|
|
445
|
+
async load({ name }) {
|
|
446
|
+
return {
|
|
447
|
+
text: `Example log content for ${name}`,
|
|
448
|
+
};
|
|
449
|
+
},
|
|
450
|
+
});
|
|
451
|
+
```
|
|
452
|
+
|
|
414
453
|
### Prompts
|
|
415
454
|
|
|
416
455
|
[Prompts](https://modelcontextprotocol.io/docs/concepts/prompts) enable servers to define reusable prompt templates and workflows that clients can easily surface to users and LLMs. They provide a powerful way to standardize and share common LLM interactions.
|
|
@@ -464,7 +503,7 @@ server.addPrompt({
|
|
|
464
503
|
});
|
|
465
504
|
```
|
|
466
505
|
|
|
467
|
-
####
|
|
506
|
+
#### Prompt argument auto-completion using `enum`
|
|
468
507
|
|
|
469
508
|
If you provide an `enum` array for an argument, the server will automatically provide completions for the argument.
|
|
470
509
|
|
|
@@ -586,6 +625,7 @@ npx fastmcp inspect server.ts
|
|
|
586
625
|
## Showcase
|
|
587
626
|
|
|
588
627
|
> [!NOTE]
|
|
628
|
+
>
|
|
589
629
|
> If you've developed a server using FastMCP, please [submit a PR](https://github.com/punkpeye/fastmcp) to showcase it here!
|
|
590
630
|
|
|
591
631
|
- https://github.com/apinetwork/piapi-mcp-server
|
package/dist/FastMCP.d.ts
CHANGED
|
@@ -102,12 +102,36 @@ type ResourceResult = {
|
|
|
102
102
|
} | {
|
|
103
103
|
blob: string;
|
|
104
104
|
};
|
|
105
|
+
type InputResourceTemplateArgument = Readonly<{
|
|
106
|
+
name: string;
|
|
107
|
+
description?: string;
|
|
108
|
+
complete?: ArgumentValueCompleter;
|
|
109
|
+
}>;
|
|
110
|
+
type ResourceTemplateArgument = Readonly<{
|
|
111
|
+
name: string;
|
|
112
|
+
description?: string;
|
|
113
|
+
complete?: ArgumentValueCompleter;
|
|
114
|
+
}>;
|
|
115
|
+
type ResourceTemplateArgumentsToObject<T extends {
|
|
116
|
+
name: string;
|
|
117
|
+
}[]> = {
|
|
118
|
+
[K in T[number]["name"]]: string;
|
|
119
|
+
};
|
|
120
|
+
type InputResourceTemplate<Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[]> = {
|
|
121
|
+
uriTemplate: string;
|
|
122
|
+
name: string;
|
|
123
|
+
description?: string;
|
|
124
|
+
mimeType?: string;
|
|
125
|
+
arguments: Arguments;
|
|
126
|
+
load: (args: ResourceTemplateArgumentsToObject<Arguments>) => Promise<ResourceResult>;
|
|
127
|
+
};
|
|
105
128
|
type Resource = {
|
|
106
129
|
uri: string;
|
|
107
130
|
name: string;
|
|
108
131
|
description?: string;
|
|
109
132
|
mimeType?: string;
|
|
110
133
|
load: () => Promise<ResourceResult | ResourceResult[]>;
|
|
134
|
+
complete?: (name: string, value: string) => Promise<Completion>;
|
|
111
135
|
};
|
|
112
136
|
type ArgumentValueCompleter = (value: string) => Promise<Completion>;
|
|
113
137
|
type InputPromptArgument = Readonly<{
|
|
@@ -117,12 +141,15 @@ type InputPromptArgument = Readonly<{
|
|
|
117
141
|
complete?: ArgumentValueCompleter;
|
|
118
142
|
enum?: string[];
|
|
119
143
|
}>;
|
|
120
|
-
type
|
|
144
|
+
type PromptArgumentsToObject<T extends {
|
|
145
|
+
name: string;
|
|
146
|
+
required?: boolean;
|
|
147
|
+
}[]> = {
|
|
121
148
|
[K in T[number]["name"]]: Extract<T[number], {
|
|
122
149
|
name: K;
|
|
123
150
|
}>["required"] extends true ? string : string | undefined;
|
|
124
151
|
};
|
|
125
|
-
type InputPrompt<Arguments extends InputPromptArgument[] = InputPromptArgument[], Args =
|
|
152
|
+
type InputPrompt<Arguments extends InputPromptArgument[] = InputPromptArgument[], Args = PromptArgumentsToObject<Arguments>> = {
|
|
126
153
|
name: string;
|
|
127
154
|
description?: string;
|
|
128
155
|
arguments?: InputPromptArgument[];
|
|
@@ -135,7 +162,7 @@ type PromptArgument = Readonly<{
|
|
|
135
162
|
complete?: ArgumentValueCompleter;
|
|
136
163
|
enum?: string[];
|
|
137
164
|
}>;
|
|
138
|
-
type Prompt<Arguments extends PromptArgument[] = PromptArgument[], Args =
|
|
165
|
+
type Prompt<Arguments extends PromptArgument[] = PromptArgument[], Args = PromptArgumentsToObject<Arguments>> = {
|
|
139
166
|
arguments?: PromptArgument[];
|
|
140
167
|
complete?: (name: string, value: string) => Promise<Completion>;
|
|
141
168
|
description?: string;
|
|
@@ -154,13 +181,16 @@ declare class FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase
|
|
|
154
181
|
}
|
|
155
182
|
declare class FastMCPSession extends FastMCPSessionEventEmitter {
|
|
156
183
|
#private;
|
|
157
|
-
constructor({ name, version, tools, resources, prompts, }: {
|
|
184
|
+
constructor({ name, version, tools, resources, resourcesTemplates, prompts, }: {
|
|
158
185
|
name: string;
|
|
159
186
|
version: string;
|
|
160
187
|
tools: Tool[];
|
|
161
188
|
resources: Resource[];
|
|
189
|
+
resourcesTemplates: InputResourceTemplate[];
|
|
162
190
|
prompts: Prompt[];
|
|
163
191
|
});
|
|
192
|
+
private addResource;
|
|
193
|
+
private addResourceTemplate;
|
|
164
194
|
private addPrompt;
|
|
165
195
|
get clientCapabilities(): ClientCapabilities | null;
|
|
166
196
|
get server(): Server;
|
|
@@ -174,6 +204,7 @@ declare class FastMCPSession extends FastMCPSessionEventEmitter {
|
|
|
174
204
|
private setupLoggingHandlers;
|
|
175
205
|
private setupToolHandlers;
|
|
176
206
|
private setupResourceHandlers;
|
|
207
|
+
private setupResourceTemplateHandlers;
|
|
177
208
|
private setupPromptHandlers;
|
|
178
209
|
}
|
|
179
210
|
declare const FastMCPEventEmitterBase: {
|
|
@@ -194,6 +225,10 @@ declare class FastMCP extends FastMCPEventEmitter {
|
|
|
194
225
|
* Adds a resource to the server.
|
|
195
226
|
*/
|
|
196
227
|
addResource(resource: Resource): void;
|
|
228
|
+
/**
|
|
229
|
+
* Adds a resource template to the server.
|
|
230
|
+
*/
|
|
231
|
+
addResourceTemplate<const Args extends InputResourceTemplateArgument[]>(resource: InputResourceTemplate<Args>): void;
|
|
197
232
|
/**
|
|
198
233
|
* Adds a prompt to the server.
|
|
199
234
|
*/
|
package/dist/FastMCP.js
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
GetPromptRequestSchema,
|
|
9
9
|
ListPromptsRequestSchema,
|
|
10
10
|
ListResourcesRequestSchema,
|
|
11
|
+
ListResourceTemplatesRequestSchema,
|
|
11
12
|
ListToolsRequestSchema,
|
|
12
13
|
McpError,
|
|
13
14
|
ReadResourceRequestSchema,
|
|
@@ -22,6 +23,7 @@ import { fileTypeFromBuffer } from "file-type";
|
|
|
22
23
|
import { EventEmitter } from "events";
|
|
23
24
|
import Fuse from "fuse.js";
|
|
24
25
|
import { startSSEServer } from "mcp-proxy";
|
|
26
|
+
import parseURITemplate from "uri-templates";
|
|
25
27
|
var imageContent = async (input) => {
|
|
26
28
|
let rawData;
|
|
27
29
|
if ("url" in input) {
|
|
@@ -108,23 +110,26 @@ var FastMCPSessionEventEmitter = class extends FastMCPSessionEventEmitterBase {
|
|
|
108
110
|
};
|
|
109
111
|
var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
110
112
|
#capabilities = {};
|
|
111
|
-
#loggingLevel = "info";
|
|
112
|
-
#server;
|
|
113
113
|
#clientCapabilities;
|
|
114
|
-
#
|
|
114
|
+
#loggingLevel = "info";
|
|
115
115
|
#prompts = [];
|
|
116
|
+
#resources = [];
|
|
117
|
+
#resourceTemplates = [];
|
|
118
|
+
#roots = [];
|
|
119
|
+
#server;
|
|
116
120
|
constructor({
|
|
117
121
|
name,
|
|
118
122
|
version,
|
|
119
123
|
tools,
|
|
120
124
|
resources,
|
|
125
|
+
resourcesTemplates,
|
|
121
126
|
prompts
|
|
122
127
|
}) {
|
|
123
128
|
super();
|
|
124
129
|
if (tools.length) {
|
|
125
130
|
this.#capabilities.tools = {};
|
|
126
131
|
}
|
|
127
|
-
if (resources.length) {
|
|
132
|
+
if (resources.length || resourcesTemplates.length) {
|
|
128
133
|
this.#capabilities.resources = {};
|
|
129
134
|
}
|
|
130
135
|
if (prompts.length) {
|
|
@@ -145,13 +150,45 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
145
150
|
if (tools.length) {
|
|
146
151
|
this.setupToolHandlers(tools);
|
|
147
152
|
}
|
|
148
|
-
if (resources.length) {
|
|
153
|
+
if (resources.length || resourcesTemplates.length) {
|
|
154
|
+
for (const resource of resources) {
|
|
155
|
+
this.addResource(resource);
|
|
156
|
+
}
|
|
149
157
|
this.setupResourceHandlers(resources);
|
|
158
|
+
if (resourcesTemplates.length) {
|
|
159
|
+
for (const resourceTemplate of resourcesTemplates) {
|
|
160
|
+
this.addResourceTemplate(resourceTemplate);
|
|
161
|
+
}
|
|
162
|
+
this.setupResourceTemplateHandlers(resourcesTemplates);
|
|
163
|
+
}
|
|
150
164
|
}
|
|
151
165
|
if (prompts.length) {
|
|
152
166
|
this.setupPromptHandlers(prompts);
|
|
153
167
|
}
|
|
154
168
|
}
|
|
169
|
+
addResource(inputResource) {
|
|
170
|
+
this.#resources.push(inputResource);
|
|
171
|
+
}
|
|
172
|
+
addResourceTemplate(inputResourceTemplate) {
|
|
173
|
+
const completers = {};
|
|
174
|
+
for (const argument of inputResourceTemplate.arguments ?? []) {
|
|
175
|
+
if (argument.complete) {
|
|
176
|
+
completers[argument.name] = argument.complete;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
const resourceTemplate = {
|
|
180
|
+
...inputResourceTemplate,
|
|
181
|
+
complete: async (name, value) => {
|
|
182
|
+
if (completers[name]) {
|
|
183
|
+
return await completers[name](value);
|
|
184
|
+
}
|
|
185
|
+
return {
|
|
186
|
+
values: []
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
this.#resourceTemplates.push(resourceTemplate);
|
|
191
|
+
}
|
|
155
192
|
addPrompt(inputPrompt) {
|
|
156
193
|
const completers = {};
|
|
157
194
|
const enums = {};
|
|
@@ -267,6 +304,36 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
267
304
|
completion
|
|
268
305
|
};
|
|
269
306
|
}
|
|
307
|
+
if (request.params.ref.type === "ref/resource") {
|
|
308
|
+
const resource = this.#resourceTemplates.find(
|
|
309
|
+
(resource2) => resource2.uriTemplate === request.params.ref.uri
|
|
310
|
+
);
|
|
311
|
+
if (!resource) {
|
|
312
|
+
throw new UnexpectedStateError("Unknown resource", {
|
|
313
|
+
request
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
if (!("uriTemplate" in resource)) {
|
|
317
|
+
throw new UnexpectedStateError("Unexpected resource");
|
|
318
|
+
}
|
|
319
|
+
if (!resource.complete) {
|
|
320
|
+
throw new UnexpectedStateError(
|
|
321
|
+
"Resource does not support completion",
|
|
322
|
+
{
|
|
323
|
+
request
|
|
324
|
+
}
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
const completion = CompletionZodSchema.parse(
|
|
328
|
+
await resource.complete(
|
|
329
|
+
request.params.argument.name,
|
|
330
|
+
request.params.argument.value
|
|
331
|
+
)
|
|
332
|
+
);
|
|
333
|
+
return {
|
|
334
|
+
completion
|
|
335
|
+
};
|
|
336
|
+
}
|
|
270
337
|
throw new UnexpectedStateError("Unexpected completion request", {
|
|
271
338
|
request
|
|
272
339
|
});
|
|
@@ -422,6 +489,27 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
422
489
|
(resource2) => "uri" in resource2 && resource2.uri === request.params.uri
|
|
423
490
|
);
|
|
424
491
|
if (!resource) {
|
|
492
|
+
for (const resourceTemplate of this.#resourceTemplates) {
|
|
493
|
+
const uriTemplate = parseURITemplate(
|
|
494
|
+
resourceTemplate.uriTemplate
|
|
495
|
+
);
|
|
496
|
+
const match = uriTemplate.fromUri(request.params.uri);
|
|
497
|
+
if (!match) {
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
const uri = uriTemplate.fill(match);
|
|
501
|
+
const result = await resourceTemplate.load(match);
|
|
502
|
+
return {
|
|
503
|
+
contents: [
|
|
504
|
+
{
|
|
505
|
+
uri,
|
|
506
|
+
mimeType: resourceTemplate.mimeType,
|
|
507
|
+
name: resourceTemplate.name,
|
|
508
|
+
...result
|
|
509
|
+
}
|
|
510
|
+
]
|
|
511
|
+
};
|
|
512
|
+
}
|
|
425
513
|
throw new McpError(
|
|
426
514
|
ErrorCode.MethodNotFound,
|
|
427
515
|
`Unknown resource: ${request.params.uri}`
|
|
@@ -464,10 +552,24 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
464
552
|
};
|
|
465
553
|
}
|
|
466
554
|
}
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
}
|
|
470
|
-
|
|
555
|
+
throw new UnexpectedStateError("Unknown resource request", {
|
|
556
|
+
request
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
setupResourceTemplateHandlers(resourceTemplates) {
|
|
562
|
+
this.#server.setRequestHandler(
|
|
563
|
+
ListResourceTemplatesRequestSchema,
|
|
564
|
+
async () => {
|
|
565
|
+
return {
|
|
566
|
+
resourceTemplates: resourceTemplates.map((resourceTemplate) => {
|
|
567
|
+
return {
|
|
568
|
+
name: resourceTemplate.name,
|
|
569
|
+
uriTemplate: resourceTemplate.uriTemplate
|
|
570
|
+
};
|
|
571
|
+
})
|
|
572
|
+
};
|
|
471
573
|
}
|
|
472
574
|
);
|
|
473
575
|
}
|
|
@@ -536,6 +638,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
536
638
|
#options;
|
|
537
639
|
#prompts = [];
|
|
538
640
|
#resources = [];
|
|
641
|
+
#resourcesTemplates = [];
|
|
539
642
|
#sessions = [];
|
|
540
643
|
#sseServer = null;
|
|
541
644
|
#tools = [];
|
|
@@ -554,6 +657,12 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
554
657
|
addResource(resource) {
|
|
555
658
|
this.#resources.push(resource);
|
|
556
659
|
}
|
|
660
|
+
/**
|
|
661
|
+
* Adds a resource template to the server.
|
|
662
|
+
*/
|
|
663
|
+
addResourceTemplate(resource) {
|
|
664
|
+
this.#resourcesTemplates.push(resource);
|
|
665
|
+
}
|
|
557
666
|
/**
|
|
558
667
|
* Adds a prompt to the server.
|
|
559
668
|
*/
|
|
@@ -573,6 +682,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
573
682
|
version: this.#options.version,
|
|
574
683
|
tools: this.#tools,
|
|
575
684
|
resources: this.#resources,
|
|
685
|
+
resourcesTemplates: this.#resourcesTemplates,
|
|
576
686
|
prompts: this.#prompts
|
|
577
687
|
});
|
|
578
688
|
await session.connect(transport);
|
|
@@ -591,6 +701,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
591
701
|
version: this.#options.version,
|
|
592
702
|
tools: this.#tools,
|
|
593
703
|
resources: this.#resources,
|
|
704
|
+
resourcesTemplates: this.#resourcesTemplates,
|
|
594
705
|
prompts: this.#prompts
|
|
595
706
|
});
|
|
596
707
|
},
|
package/dist/FastMCP.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/FastMCP.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ClientCapabilities,\n CompleteRequestSchema,\n ErrorCode,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListToolsRequestSchema,\n McpError,\n ReadResourceRequestSchema,\n Root,\n RootsListChangedNotificationSchema,\n ServerCapabilities,\n SetLevelRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport { z } from \"zod\";\nimport { setTimeout as delay } from \"timers/promises\";\nimport { readFile } from \"fs/promises\";\nimport { fileTypeFromBuffer } from \"file-type\";\nimport { StrictEventEmitter } from \"strict-event-emitter-types\";\nimport { EventEmitter } from \"events\";\nimport Fuse from \"fuse.js\";\nimport { startSSEServer } from \"mcp-proxy\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype FastMCPEvents = {\n connect: (event: { session: FastMCPSession }) => void;\n disconnect: (event: { session: FastMCPSession }) => void;\n};\n\ntype FastMCPSessionEvents = {\n rootsChanged: (event: { roots: Root[] }) => void;\n error: (event: { error: Error }) => void;\n};\n\n/**\n * Generates an image content object from a URL, file path, or buffer.\n */\nexport const imageContent = async (\n input: { url: string } | { path: string } | { buffer: Buffer },\n): Promise<ImageContent> => {\n let rawData: Buffer;\n\n if (\"url\" in input) {\n const response = await fetch(input.url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch image from URL: ${response.statusText}`);\n }\n\n rawData = Buffer.from(await response.arrayBuffer());\n } else if (\"path\" in input) {\n rawData = await readFile(input.path);\n } else if (\"buffer\" in input) {\n rawData = input.buffer;\n } else {\n throw new Error(\n \"Invalid input: Provide a valid 'url', 'path', or 'buffer'\",\n );\n }\n\n const mimeType = await fileTypeFromBuffer(rawData);\n\n const base64Data = rawData.toString(\"base64\");\n\n return {\n type: \"image\",\n data: base64Data,\n mimeType: mimeType?.mime ?? \"image/png\",\n } as const;\n};\n\nabstract class FastMCPError extends Error {\n public constructor(message?: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\ntype Extra = unknown;\n\ntype Extras = Record<string, Extra>;\n\nexport class UnexpectedStateError extends FastMCPError {\n public extras?: Extras;\n\n public constructor(message: string, extras?: Extras) {\n super(message);\n this.name = new.target.name;\n this.extras = extras;\n }\n}\n\n/**\n * An error that is meant to be surfaced to the user.\n */\nexport class UserError extends UnexpectedStateError {}\n\ntype ToolParameters = z.ZodTypeAny;\n\ntype Literal = boolean | null | number | string | undefined;\n\ntype SerializableValue =\n | Literal\n | SerializableValue[]\n | { [key: string]: SerializableValue };\n\ntype Progress = {\n /**\n * The progress thus far. This should increase every time progress is made, even if the total is unknown.\n */\n progress: number;\n /**\n * Total number of items to process (or total progress required), if known.\n */\n total?: number;\n};\n\ntype Context = {\n reportProgress: (progress: Progress) => Promise<void>;\n log: {\n debug: (message: string, data?: SerializableValue) => void;\n error: (message: string, data?: SerializableValue) => void;\n info: (message: string, data?: SerializableValue) => void;\n warn: (message: string, data?: SerializableValue) => void;\n };\n};\n\ntype TextContent = {\n type: \"text\";\n text: string;\n};\n\nconst TextContentZodSchema = z\n .object({\n type: z.literal(\"text\"),\n /**\n * The text content of the message.\n */\n text: z.string(),\n })\n .strict() satisfies z.ZodType<TextContent>;\n\ntype ImageContent = {\n type: \"image\";\n data: string;\n mimeType: string;\n};\n\nconst ImageContentZodSchema = z\n .object({\n type: z.literal(\"image\"),\n /**\n * The base64-encoded image data.\n */\n data: z.string().base64(),\n /**\n * The MIME type of the image. Different providers may support different image types.\n */\n mimeType: z.string(),\n })\n .strict() satisfies z.ZodType<ImageContent>;\n\ntype Content = TextContent | ImageContent;\n\nconst ContentZodSchema = z.discriminatedUnion(\"type\", [\n TextContentZodSchema,\n ImageContentZodSchema,\n]) satisfies z.ZodType<Content>;\n\ntype ContentResult = {\n content: Content[];\n isError?: boolean;\n};\n\nconst ContentResultZodSchema = z\n .object({\n content: ContentZodSchema.array(),\n isError: z.boolean().optional(),\n })\n .strict() satisfies z.ZodType<ContentResult>;\n\ntype Completion = {\n values: string[];\n total?: number;\n hasMore?: boolean;\n};\n\n/**\n * https://github.com/modelcontextprotocol/typescript-sdk/blob/3164da64d085ec4e022ae881329eee7b72f208d4/src/types.ts#L983-L1003\n */\nconst CompletionZodSchema = z.object({\n /**\n * An array of completion values. Must not exceed 100 items.\n */\n values: z.array(z.string()).max(100),\n /**\n * The total number of completion options available. This can exceed the number of values actually sent in the response.\n */\n total: z.optional(z.number().int()),\n /**\n * Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown.\n */\n hasMore: z.optional(z.boolean()),\n}) satisfies z.ZodType<Completion>;\n\ntype Tool<Params extends ToolParameters = ToolParameters> = {\n name: string;\n description?: string;\n parameters?: Params;\n execute: (\n args: z.infer<Params>,\n context: Context,\n ) => Promise<string | ContentResult | TextContent | ImageContent>;\n};\n\ntype ResourceResult =\n | {\n text: string;\n }\n | {\n blob: string;\n };\n\ntype Resource = {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n load: () => Promise<ResourceResult | ResourceResult[]>;\n};\n\ntype ArgumentValueCompleter = (value: string) => Promise<Completion>;\n\ntype InputPromptArgument = Readonly<{\n name: string;\n description?: string;\n required?: boolean;\n complete?: ArgumentValueCompleter;\n enum?: string[];\n}>;\n\ntype ArgumentsToObject<T extends InputPromptArgument[]> = {\n [K in T[number][\"name\"]]: Extract<\n T[number],\n { name: K }\n >[\"required\"] extends true\n ? string\n : string | undefined;\n};\n\ntype InputPrompt<\n Arguments extends InputPromptArgument[] = InputPromptArgument[],\n Args = ArgumentsToObject<Arguments>,\n> = {\n name: string;\n description?: string;\n arguments?: InputPromptArgument[];\n load: (args: Args) => Promise<string>;\n};\n\ntype PromptArgument = Readonly<{\n name: string;\n description?: string;\n required?: boolean;\n complete?: ArgumentValueCompleter;\n enum?: string[];\n}>;\n\ntype Prompt<\n Arguments extends PromptArgument[] = PromptArgument[],\n Args = ArgumentsToObject<Arguments>,\n> = {\n arguments?: PromptArgument[];\n complete?: (name: string, value: string) => Promise<Completion>;\n description?: string;\n load: (args: Args) => Promise<string>;\n name: string;\n};\n\ntype ServerOptions = {\n name: string;\n version: `${number}.${number}.${number}`;\n};\n\ntype LoggingLevel =\n | \"debug\"\n | \"info\"\n | \"notice\"\n | \"warning\"\n | \"error\"\n | \"critical\"\n | \"alert\"\n | \"emergency\";\n\nconst FastMCPSessionEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPSessionEvents>;\n} = EventEmitter;\n\nclass FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {}\n\nexport class FastMCPSession extends FastMCPSessionEventEmitter {\n #capabilities: ServerCapabilities = {};\n #loggingLevel: LoggingLevel = \"info\";\n #server: Server;\n #clientCapabilities?: ClientCapabilities;\n #roots: Root[] = [];\n #prompts: Prompt[] = [];\n\n constructor({\n name,\n version,\n tools,\n resources,\n prompts,\n }: {\n name: string;\n version: string;\n tools: Tool[];\n resources: Resource[];\n prompts: Prompt[];\n }) {\n super();\n\n if (tools.length) {\n this.#capabilities.tools = {};\n }\n\n if (resources.length) {\n this.#capabilities.resources = {};\n }\n\n if (prompts.length) {\n for (const prompt of prompts) {\n this.addPrompt(prompt);\n }\n\n this.#capabilities.prompts = {};\n }\n\n this.#capabilities.logging = {};\n\n this.#server = new Server(\n { name: name, version: version },\n { capabilities: this.#capabilities },\n );\n\n this.setupErrorHandling();\n this.setupLoggingHandlers();\n this.setupRootsHandlers();\n this.setupCompleteHandlers();\n\n if (tools.length) {\n this.setupToolHandlers(tools);\n }\n\n if (resources.length) {\n this.setupResourceHandlers(resources);\n }\n\n if (prompts.length) {\n this.setupPromptHandlers(prompts);\n }\n }\n\n private addPrompt(inputPrompt: InputPrompt) {\n const completers: Record<string, ArgumentValueCompleter> = {};\n const enums: Record<string, string[]> = {};\n\n for (const argument of inputPrompt.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n\n if (argument.enum) {\n enums[argument.name] = argument.enum;\n }\n }\n\n const prompt = {\n ...inputPrompt,\n complete: async (name: string, value: string) => {\n if (completers[name]) {\n return await completers[name](value);\n }\n\n if (enums[name]) {\n const fuse = new Fuse(enums[name], {\n keys: [\"value\"],\n });\n\n const result = fuse.search(value);\n\n return {\n values: result.map((item) => item.item),\n total: result.length,\n };\n }\n\n return {\n values: [],\n };\n },\n };\n\n this.#prompts.push(prompt);\n }\n\n public get clientCapabilities(): ClientCapabilities | null {\n return this.#clientCapabilities ?? null;\n }\n\n public get server(): Server {\n return this.#server;\n }\n\n #pingInterval: ReturnType<typeof setInterval> | null = null;\n\n public async connect(transport: Transport) {\n if (this.#server.transport) {\n throw new UnexpectedStateError(\"Server is already connected\");\n }\n\n await this.#server.connect(transport);\n\n let attempt = 0;\n\n while (attempt++ < 10) {\n const capabilities = await this.#server.getClientCapabilities();\n\n if (capabilities) {\n this.#clientCapabilities = capabilities;\n\n break;\n }\n\n await delay(100);\n }\n\n if (!this.#clientCapabilities) {\n throw new UnexpectedStateError(\"Server did not connect\");\n }\n\n if (this.#clientCapabilities?.roots) {\n const roots = await this.#server.listRoots();\n\n this.#roots = roots.roots;\n }\n\n this.#pingInterval = setInterval(async () => {\n try {\n await this.#server.ping();\n } catch (error) {\n this.emit(\"error\", {\n error: error as Error,\n });\n }\n }, 1000);\n }\n\n public get roots(): Root[] {\n return this.#roots;\n }\n\n public async close() {\n if (this.#pingInterval) {\n clearInterval(this.#pingInterval);\n }\n\n await this.#server.close();\n }\n\n private setupErrorHandling() {\n this.#server.onerror = (error) => {\n console.error(\"[MCP Error]\", error);\n };\n }\n\n public get loggingLevel(): LoggingLevel {\n return this.#loggingLevel;\n }\n\n private setupCompleteHandlers() {\n this.#server.setRequestHandler(CompleteRequestSchema, async (request) => {\n if (request.params.ref.type === \"ref/prompt\") {\n const prompt = this.#prompts.find(\n (prompt) => prompt.name === request.params.ref.name,\n );\n\n if (!prompt) {\n throw new UnexpectedStateError(\"Unknown prompt\", {\n request,\n });\n }\n\n if (!prompt.complete) {\n throw new UnexpectedStateError(\"Prompt does not support completion\", {\n request,\n });\n }\n\n const completion = CompletionZodSchema.parse(\n await prompt.complete(\n request.params.argument.name,\n request.params.argument.value,\n ),\n );\n\n return {\n completion,\n };\n }\n\n throw new UnexpectedStateError(\"Unexpected completion request\", {\n request,\n });\n });\n }\n\n private setupRootsHandlers() {\n this.#server.setNotificationHandler(\n RootsListChangedNotificationSchema,\n () => {\n this.#server.listRoots().then((roots) => {\n this.#roots = roots.roots;\n\n this.emit(\"rootsChanged\", {\n roots: roots.roots,\n });\n });\n },\n );\n }\n\n private setupLoggingHandlers() {\n this.#server.setRequestHandler(SetLevelRequestSchema, (request) => {\n this.#loggingLevel = request.params.level;\n\n return {};\n });\n }\n\n private setupToolHandlers(tools: Tool[]) {\n this.#server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: tools.map((tool) => {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.parameters\n ? zodToJsonSchema(tool.parameters)\n : undefined,\n };\n }),\n };\n });\n\n this.#server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const tool = tools.find((tool) => tool.name === request.params.name);\n\n if (!tool) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown tool: ${request.params.name}`,\n );\n }\n\n let args: any = undefined;\n\n if (tool.parameters) {\n const parsed = tool.parameters.safeParse(request.params.arguments);\n\n if (!parsed.success) {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Invalid ${request.params.name} arguments`,\n );\n }\n\n args = parsed.data;\n }\n\n const progressToken = request.params?._meta?.progressToken;\n\n let result: ContentResult;\n\n try {\n const reportProgress = async (progress: Progress) => {\n await this.#server.notification({\n method: \"notifications/progress\",\n params: {\n ...progress,\n progressToken,\n },\n });\n };\n\n const log = {\n debug: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n level: \"debug\",\n data: {\n message,\n context,\n },\n });\n },\n error: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n level: \"error\",\n data: {\n message,\n context,\n },\n });\n },\n info: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n level: \"info\",\n data: {\n message,\n context,\n },\n });\n },\n warn: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n level: \"warning\",\n data: {\n message,\n context,\n },\n });\n },\n };\n\n const maybeStringResult = await tool.execute(args, {\n reportProgress,\n log,\n });\n\n if (typeof maybeStringResult === \"string\") {\n result = ContentResultZodSchema.parse({\n content: [{ type: \"text\", text: maybeStringResult }],\n });\n } else if (\"type\" in maybeStringResult) {\n result = ContentResultZodSchema.parse({\n content: [maybeStringResult],\n });\n } else {\n result = ContentResultZodSchema.parse(maybeStringResult);\n }\n } catch (error) {\n if (error instanceof UserError) {\n return {\n content: [{ type: \"text\", text: error.message }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: `Error: ${error}` }],\n isError: true,\n };\n }\n\n return result;\n });\n }\n\n private setupResourceHandlers(resources: Resource[]) {\n this.#server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return {\n resources: resources.map((resource) => {\n return {\n uri: resource.uri,\n name: resource.name,\n mimeType: resource.mimeType,\n };\n }),\n };\n });\n\n this.#server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request) => {\n if (\"uri\" in request.params) {\n const resource = resources.find(\n (resource) =>\n \"uri\" in resource && resource.uri === request.params.uri,\n );\n\n if (!resource) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown resource: ${request.params.uri}`,\n );\n }\n\n if (!(\"uri\" in resource)) {\n throw new UnexpectedStateError(\"Resource does not support reading\");\n }\n\n let maybeArrayResult: Awaited<ReturnType<Resource[\"load\"]>>;\n\n try {\n maybeArrayResult = await resource.load();\n } catch (error) {\n throw new McpError(\n ErrorCode.InternalError,\n `Error reading resource: ${error}`,\n {\n uri: resource.uri,\n },\n );\n }\n\n if (Array.isArray(maybeArrayResult)) {\n return {\n contents: maybeArrayResult.map((result) => ({\n uri: resource.uri,\n mimeType: resource.mimeType,\n name: resource.name,\n ...result,\n })),\n };\n } else {\n return {\n contents: [\n {\n uri: resource.uri,\n mimeType: resource.mimeType,\n name: resource.name,\n ...maybeArrayResult,\n },\n ],\n };\n }\n }\n\n if (\"uriTemplate\" in request.params) {\n throw new UnexpectedStateError(\"Not implemented\");\n }\n\n throw new UnexpectedStateError(\"Unknown resource request\");\n },\n );\n }\n\n private setupPromptHandlers(prompts: Prompt[]) {\n this.#server.setRequestHandler(ListPromptsRequestSchema, async () => {\n return {\n prompts: prompts.map((prompt) => {\n return {\n name: prompt.name,\n description: prompt.description,\n arguments: prompt.arguments,\n complete: prompt.complete,\n };\n }),\n };\n });\n\n this.#server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const prompt = prompts.find(\n (prompt) => prompt.name === request.params.name,\n );\n\n if (!prompt) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown prompt: ${request.params.name}`,\n );\n }\n\n const args = request.params.arguments;\n\n for (const arg of prompt.arguments ?? []) {\n if (arg.required && !(args && arg.name in args)) {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Missing required argument: ${arg.name}`,\n );\n }\n }\n\n let result: Awaited<ReturnType<Prompt[\"load\"]>>;\n\n try {\n result = await prompt.load(args as Record<string, string | undefined>);\n } catch (error) {\n throw new McpError(\n ErrorCode.InternalError,\n `Error loading prompt: ${error}`,\n );\n }\n\n return {\n description: prompt.description,\n messages: [\n {\n role: \"user\",\n content: { type: \"text\", text: result },\n },\n ],\n };\n });\n }\n}\n\nconst FastMCPEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPEvents>;\n} = EventEmitter;\n\nclass FastMCPEventEmitter extends FastMCPEventEmitterBase {}\n\nexport class FastMCP extends FastMCPEventEmitter {\n #options: ServerOptions;\n #prompts: InputPrompt[] = [];\n #resources: Resource[] = [];\n #sessions: FastMCPSession[] = [];\n #sseServer: SSEServer | null = null;\n #tools: Tool[] = [];\n\n constructor(public options: ServerOptions) {\n super();\n\n this.#options = options;\n }\n\n public get sessions(): FastMCPSession[] {\n return this.#sessions;\n }\n\n /**\n * Adds a tool to the server.\n */\n public addTool<Params extends ToolParameters>(tool: Tool<Params>) {\n this.#tools.push(tool as unknown as Tool);\n }\n\n /**\n * Adds a resource to the server.\n */\n public addResource(resource: Resource) {\n this.#resources.push(resource);\n }\n\n /**\n * Adds a prompt to the server.\n */\n public addPrompt<const Args extends InputPromptArgument[]>(\n prompt: InputPrompt<Args>,\n ) {\n this.#prompts.push(prompt);\n }\n\n /**\n * Starts the server.\n */\n public async start(\n options:\n | { transportType: \"stdio\" }\n | {\n transportType: \"sse\";\n sse: { endpoint: `/${string}`; port: number };\n } = {\n transportType: \"stdio\",\n },\n ) {\n if (options.transportType === \"stdio\") {\n const transport = new StdioServerTransport();\n\n const session = new FastMCPSession({\n name: this.#options.name,\n version: this.#options.version,\n tools: this.#tools,\n resources: this.#resources,\n prompts: this.#prompts,\n });\n\n await session.connect(transport);\n\n this.#sessions.push(session);\n\n this.emit(\"connect\", {\n session,\n });\n\n console.error(`server is running on stdio`);\n } else if (options.transportType === \"sse\") {\n this.#sseServer = await startSSEServer<FastMCPSession>({\n endpoint: options.sse.endpoint as `/${string}`,\n port: options.sse.port,\n createServer: async () => {\n return new FastMCPSession({\n name: this.#options.name,\n version: this.#options.version,\n tools: this.#tools,\n resources: this.#resources,\n prompts: this.#prompts,\n });\n },\n onClose: (session) => {\n this.emit(\"disconnect\", {\n session,\n });\n },\n onConnect: async (session) => {\n this.#sessions.push(session);\n\n this.emit(\"connect\", {\n session,\n });\n },\n });\n\n console.error(\n `server is running on SSE at http://localhost:${options.sse.port}${options.sse.endpoint}`,\n );\n } else {\n throw new Error(\"Invalid transport type\");\n }\n }\n\n /**\n * Stops the server.\n */\n public async stop() {\n if (this.#sseServer) {\n this.#sseServer.close();\n }\n }\n}\n"],"mappings":"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","names":["prompt","tool","resource"]}
|
|
1
|
+
{"version":3,"sources":["../src/FastMCP.ts"],"sourcesContent":["import { Server } from \"@modelcontextprotocol/sdk/server/index.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport {\n CallToolRequestSchema,\n ClientCapabilities,\n CompleteRequestSchema,\n ErrorCode,\n GetPromptRequestSchema,\n ListPromptsRequestSchema,\n ListResourcesRequestSchema,\n ListResourceTemplatesRequestSchema,\n ListToolsRequestSchema,\n McpError,\n ReadResourceRequestSchema,\n Root,\n RootsListChangedNotificationSchema,\n ServerCapabilities,\n SetLevelRequestSchema,\n} from \"@modelcontextprotocol/sdk/types.js\";\nimport { zodToJsonSchema } from \"zod-to-json-schema\";\nimport { z } from \"zod\";\nimport { setTimeout as delay } from \"timers/promises\";\nimport { readFile } from \"fs/promises\";\nimport { fileTypeFromBuffer } from \"file-type\";\nimport { StrictEventEmitter } from \"strict-event-emitter-types\";\nimport { EventEmitter } from \"events\";\nimport Fuse from \"fuse.js\";\nimport { startSSEServer } from \"mcp-proxy\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport parseURITemplate from \"uri-templates\";\n\nexport type SSEServer = {\n close: () => Promise<void>;\n};\n\ntype FastMCPEvents = {\n connect: (event: { session: FastMCPSession }) => void;\n disconnect: (event: { session: FastMCPSession }) => void;\n};\n\ntype FastMCPSessionEvents = {\n rootsChanged: (event: { roots: Root[] }) => void;\n error: (event: { error: Error }) => void;\n};\n\n/**\n * Generates an image content object from a URL, file path, or buffer.\n */\nexport const imageContent = async (\n input: { url: string } | { path: string } | { buffer: Buffer },\n): Promise<ImageContent> => {\n let rawData: Buffer;\n\n if (\"url\" in input) {\n const response = await fetch(input.url);\n\n if (!response.ok) {\n throw new Error(`Failed to fetch image from URL: ${response.statusText}`);\n }\n\n rawData = Buffer.from(await response.arrayBuffer());\n } else if (\"path\" in input) {\n rawData = await readFile(input.path);\n } else if (\"buffer\" in input) {\n rawData = input.buffer;\n } else {\n throw new Error(\n \"Invalid input: Provide a valid 'url', 'path', or 'buffer'\",\n );\n }\n\n const mimeType = await fileTypeFromBuffer(rawData);\n\n const base64Data = rawData.toString(\"base64\");\n\n return {\n type: \"image\",\n data: base64Data,\n mimeType: mimeType?.mime ?? \"image/png\",\n } as const;\n};\n\nabstract class FastMCPError extends Error {\n public constructor(message?: string) {\n super(message);\n this.name = new.target.name;\n }\n}\n\ntype Extra = unknown;\n\ntype Extras = Record<string, Extra>;\n\nexport class UnexpectedStateError extends FastMCPError {\n public extras?: Extras;\n\n public constructor(message: string, extras?: Extras) {\n super(message);\n this.name = new.target.name;\n this.extras = extras;\n }\n}\n\n/**\n * An error that is meant to be surfaced to the user.\n */\nexport class UserError extends UnexpectedStateError {}\n\ntype ToolParameters = z.ZodTypeAny;\n\ntype Literal = boolean | null | number | string | undefined;\n\ntype SerializableValue =\n | Literal\n | SerializableValue[]\n | { [key: string]: SerializableValue };\n\ntype Progress = {\n /**\n * The progress thus far. This should increase every time progress is made, even if the total is unknown.\n */\n progress: number;\n /**\n * Total number of items to process (or total progress required), if known.\n */\n total?: number;\n};\n\ntype Context = {\n reportProgress: (progress: Progress) => Promise<void>;\n log: {\n debug: (message: string, data?: SerializableValue) => void;\n error: (message: string, data?: SerializableValue) => void;\n info: (message: string, data?: SerializableValue) => void;\n warn: (message: string, data?: SerializableValue) => void;\n };\n};\n\ntype TextContent = {\n type: \"text\";\n text: string;\n};\n\nconst TextContentZodSchema = z\n .object({\n type: z.literal(\"text\"),\n /**\n * The text content of the message.\n */\n text: z.string(),\n })\n .strict() satisfies z.ZodType<TextContent>;\n\ntype ImageContent = {\n type: \"image\";\n data: string;\n mimeType: string;\n};\n\nconst ImageContentZodSchema = z\n .object({\n type: z.literal(\"image\"),\n /**\n * The base64-encoded image data.\n */\n data: z.string().base64(),\n /**\n * The MIME type of the image. Different providers may support different image types.\n */\n mimeType: z.string(),\n })\n .strict() satisfies z.ZodType<ImageContent>;\n\ntype Content = TextContent | ImageContent;\n\nconst ContentZodSchema = z.discriminatedUnion(\"type\", [\n TextContentZodSchema,\n ImageContentZodSchema,\n]) satisfies z.ZodType<Content>;\n\ntype ContentResult = {\n content: Content[];\n isError?: boolean;\n};\n\nconst ContentResultZodSchema = z\n .object({\n content: ContentZodSchema.array(),\n isError: z.boolean().optional(),\n })\n .strict() satisfies z.ZodType<ContentResult>;\n\ntype Completion = {\n values: string[];\n total?: number;\n hasMore?: boolean;\n};\n\n/**\n * https://github.com/modelcontextprotocol/typescript-sdk/blob/3164da64d085ec4e022ae881329eee7b72f208d4/src/types.ts#L983-L1003\n */\nconst CompletionZodSchema = z.object({\n /**\n * An array of completion values. Must not exceed 100 items.\n */\n values: z.array(z.string()).max(100),\n /**\n * The total number of completion options available. This can exceed the number of values actually sent in the response.\n */\n total: z.optional(z.number().int()),\n /**\n * Indicates whether there are additional completion options beyond those provided in the current response, even if the exact total is unknown.\n */\n hasMore: z.optional(z.boolean()),\n}) satisfies z.ZodType<Completion>;\n\ntype Tool<Params extends ToolParameters = ToolParameters> = {\n name: string;\n description?: string;\n parameters?: Params;\n execute: (\n args: z.infer<Params>,\n context: Context,\n ) => Promise<string | ContentResult | TextContent | ImageContent>;\n};\n\ntype ResourceResult =\n | {\n text: string;\n }\n | {\n blob: string;\n };\n\ntype InputResourceTemplateArgument = Readonly<{\n name: string;\n description?: string;\n complete?: ArgumentValueCompleter;\n}>;\n\ntype ResourceTemplateArgument = Readonly<{\n name: string;\n description?: string;\n complete?: ArgumentValueCompleter;\n}>;\n\ntype ResourceTemplate<\n Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[],\n> = {\n uriTemplate: string;\n name: string;\n description?: string;\n mimeType?: string;\n arguments: Arguments;\n complete?: (name: string, value: string) => Promise<Completion>;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n ) => Promise<ResourceResult>;\n};\n\ntype ResourceTemplateArgumentsToObject<T extends { name: string }[]> = {\n [K in T[number][\"name\"]]: string;\n};\n\ntype InputResourceTemplate<\n Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[],\n> = {\n uriTemplate: string;\n name: string;\n description?: string;\n mimeType?: string;\n arguments: Arguments;\n load: (\n args: ResourceTemplateArgumentsToObject<Arguments>,\n ) => Promise<ResourceResult>;\n};\n\ntype Resource = {\n uri: string;\n name: string;\n description?: string;\n mimeType?: string;\n load: () => Promise<ResourceResult | ResourceResult[]>;\n complete?: (name: string, value: string) => Promise<Completion>;\n};\n\ntype ArgumentValueCompleter = (value: string) => Promise<Completion>;\n\ntype InputPromptArgument = Readonly<{\n name: string;\n description?: string;\n required?: boolean;\n complete?: ArgumentValueCompleter;\n enum?: string[];\n}>;\n\ntype PromptArgumentsToObject<T extends { name: string; required?: boolean }[]> =\n {\n [K in T[number][\"name\"]]: Extract<\n T[number],\n { name: K }\n >[\"required\"] extends true\n ? string\n : string | undefined;\n };\n\ntype InputPrompt<\n Arguments extends InputPromptArgument[] = InputPromptArgument[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n name: string;\n description?: string;\n arguments?: InputPromptArgument[];\n load: (args: Args) => Promise<string>;\n};\n\ntype PromptArgument = Readonly<{\n name: string;\n description?: string;\n required?: boolean;\n complete?: ArgumentValueCompleter;\n enum?: string[];\n}>;\n\ntype Prompt<\n Arguments extends PromptArgument[] = PromptArgument[],\n Args = PromptArgumentsToObject<Arguments>,\n> = {\n arguments?: PromptArgument[];\n complete?: (name: string, value: string) => Promise<Completion>;\n description?: string;\n load: (args: Args) => Promise<string>;\n name: string;\n};\n\ntype ServerOptions = {\n name: string;\n version: `${number}.${number}.${number}`;\n};\n\ntype LoggingLevel =\n | \"debug\"\n | \"info\"\n | \"notice\"\n | \"warning\"\n | \"error\"\n | \"critical\"\n | \"alert\"\n | \"emergency\";\n\nconst FastMCPSessionEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPSessionEvents>;\n} = EventEmitter;\n\nclass FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {}\n\nexport class FastMCPSession extends FastMCPSessionEventEmitter {\n #capabilities: ServerCapabilities = {};\n #clientCapabilities?: ClientCapabilities;\n #loggingLevel: LoggingLevel = \"info\";\n #prompts: Prompt[] = [];\n #resources: Resource[] = [];\n #resourceTemplates: ResourceTemplate[] = [];\n #roots: Root[] = [];\n #server: Server;\n\n constructor({\n name,\n version,\n tools,\n resources,\n resourcesTemplates,\n prompts,\n }: {\n name: string;\n version: string;\n tools: Tool[];\n resources: Resource[];\n resourcesTemplates: InputResourceTemplate[];\n prompts: Prompt[];\n }) {\n super();\n\n if (tools.length) {\n this.#capabilities.tools = {};\n }\n\n if (resources.length || resourcesTemplates.length) {\n this.#capabilities.resources = {};\n }\n\n if (prompts.length) {\n for (const prompt of prompts) {\n this.addPrompt(prompt);\n }\n\n this.#capabilities.prompts = {};\n }\n\n this.#capabilities.logging = {};\n\n this.#server = new Server(\n { name: name, version: version },\n { capabilities: this.#capabilities },\n );\n\n this.setupErrorHandling();\n this.setupLoggingHandlers();\n this.setupRootsHandlers();\n this.setupCompleteHandlers();\n\n if (tools.length) {\n this.setupToolHandlers(tools);\n }\n\n if (resources.length || resourcesTemplates.length) {\n for (const resource of resources) {\n this.addResource(resource);\n }\n\n this.setupResourceHandlers(resources);\n\n if (resourcesTemplates.length) {\n for (const resourceTemplate of resourcesTemplates) {\n this.addResourceTemplate(resourceTemplate);\n }\n\n this.setupResourceTemplateHandlers(resourcesTemplates);\n }\n }\n\n if (prompts.length) {\n this.setupPromptHandlers(prompts);\n }\n }\n\n private addResource(inputResource: Resource) {\n this.#resources.push(inputResource);\n }\n\n private addResourceTemplate(inputResourceTemplate: InputResourceTemplate) {\n const completers: Record<string, ArgumentValueCompleter> = {};\n\n for (const argument of inputResourceTemplate.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n }\n\n const resourceTemplate = {\n ...inputResourceTemplate,\n complete: async (name: string, value: string) => {\n if (completers[name]) {\n return await completers[name](value);\n }\n\n return {\n values: [],\n };\n },\n };\n\n this.#resourceTemplates.push(resourceTemplate);\n }\n\n private addPrompt(inputPrompt: InputPrompt) {\n const completers: Record<string, ArgumentValueCompleter> = {};\n const enums: Record<string, string[]> = {};\n\n for (const argument of inputPrompt.arguments ?? []) {\n if (argument.complete) {\n completers[argument.name] = argument.complete;\n }\n\n if (argument.enum) {\n enums[argument.name] = argument.enum;\n }\n }\n\n const prompt = {\n ...inputPrompt,\n complete: async (name: string, value: string) => {\n if (completers[name]) {\n return await completers[name](value);\n }\n\n if (enums[name]) {\n const fuse = new Fuse(enums[name], {\n keys: [\"value\"],\n });\n\n const result = fuse.search(value);\n\n return {\n values: result.map((item) => item.item),\n total: result.length,\n };\n }\n\n return {\n values: [],\n };\n },\n };\n\n this.#prompts.push(prompt);\n }\n\n public get clientCapabilities(): ClientCapabilities | null {\n return this.#clientCapabilities ?? null;\n }\n\n public get server(): Server {\n return this.#server;\n }\n\n #pingInterval: ReturnType<typeof setInterval> | null = null;\n\n public async connect(transport: Transport) {\n if (this.#server.transport) {\n throw new UnexpectedStateError(\"Server is already connected\");\n }\n\n await this.#server.connect(transport);\n\n let attempt = 0;\n\n while (attempt++ < 10) {\n const capabilities = await this.#server.getClientCapabilities();\n\n if (capabilities) {\n this.#clientCapabilities = capabilities;\n\n break;\n }\n\n await delay(100);\n }\n\n if (!this.#clientCapabilities) {\n throw new UnexpectedStateError(\"Server did not connect\");\n }\n\n if (this.#clientCapabilities?.roots) {\n const roots = await this.#server.listRoots();\n\n this.#roots = roots.roots;\n }\n\n this.#pingInterval = setInterval(async () => {\n try {\n await this.#server.ping();\n } catch (error) {\n this.emit(\"error\", {\n error: error as Error,\n });\n }\n }, 1000);\n }\n\n public get roots(): Root[] {\n return this.#roots;\n }\n\n public async close() {\n if (this.#pingInterval) {\n clearInterval(this.#pingInterval);\n }\n\n await this.#server.close();\n }\n\n private setupErrorHandling() {\n this.#server.onerror = (error) => {\n console.error(\"[MCP Error]\", error);\n };\n }\n\n public get loggingLevel(): LoggingLevel {\n return this.#loggingLevel;\n }\n\n private setupCompleteHandlers() {\n this.#server.setRequestHandler(CompleteRequestSchema, async (request) => {\n if (request.params.ref.type === \"ref/prompt\") {\n const prompt = this.#prompts.find(\n (prompt) => prompt.name === request.params.ref.name,\n );\n\n if (!prompt) {\n throw new UnexpectedStateError(\"Unknown prompt\", {\n request,\n });\n }\n\n if (!prompt.complete) {\n throw new UnexpectedStateError(\"Prompt does not support completion\", {\n request,\n });\n }\n\n const completion = CompletionZodSchema.parse(\n await prompt.complete(\n request.params.argument.name,\n request.params.argument.value,\n ),\n );\n\n return {\n completion,\n };\n }\n\n if (request.params.ref.type === \"ref/resource\") {\n const resource = this.#resourceTemplates.find(\n (resource) => resource.uriTemplate === request.params.ref.uri,\n );\n\n if (!resource) {\n throw new UnexpectedStateError(\"Unknown resource\", {\n request,\n });\n }\n\n if (!(\"uriTemplate\" in resource)) {\n throw new UnexpectedStateError(\"Unexpected resource\");\n }\n\n if (!resource.complete) {\n throw new UnexpectedStateError(\n \"Resource does not support completion\",\n {\n request,\n },\n );\n }\n\n const completion = CompletionZodSchema.parse(\n await resource.complete(\n request.params.argument.name,\n request.params.argument.value,\n ),\n );\n\n return {\n completion,\n };\n }\n\n throw new UnexpectedStateError(\"Unexpected completion request\", {\n request,\n });\n });\n }\n\n private setupRootsHandlers() {\n this.#server.setNotificationHandler(\n RootsListChangedNotificationSchema,\n () => {\n this.#server.listRoots().then((roots) => {\n this.#roots = roots.roots;\n\n this.emit(\"rootsChanged\", {\n roots: roots.roots,\n });\n });\n },\n );\n }\n\n private setupLoggingHandlers() {\n this.#server.setRequestHandler(SetLevelRequestSchema, (request) => {\n this.#loggingLevel = request.params.level;\n\n return {};\n });\n }\n\n private setupToolHandlers(tools: Tool[]) {\n this.#server.setRequestHandler(ListToolsRequestSchema, async () => {\n return {\n tools: tools.map((tool) => {\n return {\n name: tool.name,\n description: tool.description,\n inputSchema: tool.parameters\n ? zodToJsonSchema(tool.parameters)\n : undefined,\n };\n }),\n };\n });\n\n this.#server.setRequestHandler(CallToolRequestSchema, async (request) => {\n const tool = tools.find((tool) => tool.name === request.params.name);\n\n if (!tool) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown tool: ${request.params.name}`,\n );\n }\n\n let args: any = undefined;\n\n if (tool.parameters) {\n const parsed = tool.parameters.safeParse(request.params.arguments);\n\n if (!parsed.success) {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Invalid ${request.params.name} arguments`,\n );\n }\n\n args = parsed.data;\n }\n\n const progressToken = request.params?._meta?.progressToken;\n\n let result: ContentResult;\n\n try {\n const reportProgress = async (progress: Progress) => {\n await this.#server.notification({\n method: \"notifications/progress\",\n params: {\n ...progress,\n progressToken,\n },\n });\n };\n\n const log = {\n debug: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n level: \"debug\",\n data: {\n message,\n context,\n },\n });\n },\n error: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n level: \"error\",\n data: {\n message,\n context,\n },\n });\n },\n info: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n level: \"info\",\n data: {\n message,\n context,\n },\n });\n },\n warn: (message: string, context?: SerializableValue) => {\n this.#server.sendLoggingMessage({\n level: \"warning\",\n data: {\n message,\n context,\n },\n });\n },\n };\n\n const maybeStringResult = await tool.execute(args, {\n reportProgress,\n log,\n });\n\n if (typeof maybeStringResult === \"string\") {\n result = ContentResultZodSchema.parse({\n content: [{ type: \"text\", text: maybeStringResult }],\n });\n } else if (\"type\" in maybeStringResult) {\n result = ContentResultZodSchema.parse({\n content: [maybeStringResult],\n });\n } else {\n result = ContentResultZodSchema.parse(maybeStringResult);\n }\n } catch (error) {\n if (error instanceof UserError) {\n return {\n content: [{ type: \"text\", text: error.message }],\n isError: true,\n };\n }\n\n return {\n content: [{ type: \"text\", text: `Error: ${error}` }],\n isError: true,\n };\n }\n\n return result;\n });\n }\n\n private setupResourceHandlers(resources: Resource[]) {\n this.#server.setRequestHandler(ListResourcesRequestSchema, async () => {\n return {\n resources: resources.map((resource) => {\n return {\n uri: resource.uri,\n name: resource.name,\n mimeType: resource.mimeType,\n };\n }),\n };\n });\n\n this.#server.setRequestHandler(\n ReadResourceRequestSchema,\n async (request) => {\n if (\"uri\" in request.params) {\n const resource = resources.find(\n (resource) =>\n \"uri\" in resource && resource.uri === request.params.uri,\n );\n\n if (!resource) {\n for (const resourceTemplate of this.#resourceTemplates) {\n const uriTemplate = parseURITemplate(\n resourceTemplate.uriTemplate,\n );\n\n const match = uriTemplate.fromUri(request.params.uri);\n\n if (!match) {\n continue;\n }\n\n const uri = uriTemplate.fill(match);\n\n const result = await resourceTemplate.load(match);\n\n return {\n contents: [\n {\n uri: uri,\n mimeType: resourceTemplate.mimeType,\n name: resourceTemplate.name,\n ...result,\n },\n ],\n };\n }\n\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown resource: ${request.params.uri}`,\n );\n }\n\n if (!(\"uri\" in resource)) {\n throw new UnexpectedStateError(\"Resource does not support reading\");\n }\n\n let maybeArrayResult: Awaited<ReturnType<Resource[\"load\"]>>;\n\n try {\n maybeArrayResult = await resource.load();\n } catch (error) {\n throw new McpError(\n ErrorCode.InternalError,\n `Error reading resource: ${error}`,\n {\n uri: resource.uri,\n },\n );\n }\n\n if (Array.isArray(maybeArrayResult)) {\n return {\n contents: maybeArrayResult.map((result) => ({\n uri: resource.uri,\n mimeType: resource.mimeType,\n name: resource.name,\n ...result,\n })),\n };\n } else {\n return {\n contents: [\n {\n uri: resource.uri,\n mimeType: resource.mimeType,\n name: resource.name,\n ...maybeArrayResult,\n },\n ],\n };\n }\n }\n\n throw new UnexpectedStateError(\"Unknown resource request\", {\n request,\n });\n },\n );\n }\n\n private setupResourceTemplateHandlers(resourceTemplates: ResourceTemplate[]) {\n this.#server.setRequestHandler(\n ListResourceTemplatesRequestSchema,\n async () => {\n return {\n resourceTemplates: resourceTemplates.map((resourceTemplate) => {\n return {\n name: resourceTemplate.name,\n uriTemplate: resourceTemplate.uriTemplate,\n };\n }),\n };\n },\n );\n }\n\n private setupPromptHandlers(prompts: Prompt[]) {\n this.#server.setRequestHandler(ListPromptsRequestSchema, async () => {\n return {\n prompts: prompts.map((prompt) => {\n return {\n name: prompt.name,\n description: prompt.description,\n arguments: prompt.arguments,\n complete: prompt.complete,\n };\n }),\n };\n });\n\n this.#server.setRequestHandler(GetPromptRequestSchema, async (request) => {\n const prompt = prompts.find(\n (prompt) => prompt.name === request.params.name,\n );\n\n if (!prompt) {\n throw new McpError(\n ErrorCode.MethodNotFound,\n `Unknown prompt: ${request.params.name}`,\n );\n }\n\n const args = request.params.arguments;\n\n for (const arg of prompt.arguments ?? []) {\n if (arg.required && !(args && arg.name in args)) {\n throw new McpError(\n ErrorCode.InvalidRequest,\n `Missing required argument: ${arg.name}`,\n );\n }\n }\n\n let result: Awaited<ReturnType<Prompt[\"load\"]>>;\n\n try {\n result = await prompt.load(args as Record<string, string | undefined>);\n } catch (error) {\n throw new McpError(\n ErrorCode.InternalError,\n `Error loading prompt: ${error}`,\n );\n }\n\n return {\n description: prompt.description,\n messages: [\n {\n role: \"user\",\n content: { type: \"text\", text: result },\n },\n ],\n };\n });\n }\n}\n\nconst FastMCPEventEmitterBase: {\n new (): StrictEventEmitter<EventEmitter, FastMCPEvents>;\n} = EventEmitter;\n\nclass FastMCPEventEmitter extends FastMCPEventEmitterBase {}\n\nexport class FastMCP extends FastMCPEventEmitter {\n #options: ServerOptions;\n #prompts: InputPrompt[] = [];\n #resources: Resource[] = [];\n #resourcesTemplates: InputResourceTemplate[] = [];\n #sessions: FastMCPSession[] = [];\n #sseServer: SSEServer | null = null;\n #tools: Tool[] = [];\n\n constructor(public options: ServerOptions) {\n super();\n\n this.#options = options;\n }\n\n public get sessions(): FastMCPSession[] {\n return this.#sessions;\n }\n\n /**\n * Adds a tool to the server.\n */\n public addTool<Params extends ToolParameters>(tool: Tool<Params>) {\n this.#tools.push(tool as unknown as Tool);\n }\n\n /**\n * Adds a resource to the server.\n */\n public addResource(resource: Resource) {\n this.#resources.push(resource);\n }\n\n /**\n * Adds a resource template to the server.\n */\n public addResourceTemplate<\n const Args extends InputResourceTemplateArgument[],\n >(resource: InputResourceTemplate<Args>) {\n this.#resourcesTemplates.push(resource);\n }\n\n /**\n * Adds a prompt to the server.\n */\n public addPrompt<const Args extends InputPromptArgument[]>(\n prompt: InputPrompt<Args>,\n ) {\n this.#prompts.push(prompt);\n }\n\n /**\n * Starts the server.\n */\n public async start(\n options:\n | { transportType: \"stdio\" }\n | {\n transportType: \"sse\";\n sse: { endpoint: `/${string}`; port: number };\n } = {\n transportType: \"stdio\",\n },\n ) {\n if (options.transportType === \"stdio\") {\n const transport = new StdioServerTransport();\n\n const session = new FastMCPSession({\n name: this.#options.name,\n version: this.#options.version,\n tools: this.#tools,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n prompts: this.#prompts,\n });\n\n await session.connect(transport);\n\n this.#sessions.push(session);\n\n this.emit(\"connect\", {\n session,\n });\n\n console.error(`server is running on stdio`);\n } else if (options.transportType === \"sse\") {\n this.#sseServer = await startSSEServer<FastMCPSession>({\n endpoint: options.sse.endpoint as `/${string}`,\n port: options.sse.port,\n createServer: async () => {\n return new FastMCPSession({\n name: this.#options.name,\n version: this.#options.version,\n tools: this.#tools,\n resources: this.#resources,\n resourcesTemplates: this.#resourcesTemplates,\n prompts: this.#prompts,\n });\n },\n onClose: (session) => {\n this.emit(\"disconnect\", {\n session,\n });\n },\n onConnect: async (session) => {\n this.#sessions.push(session);\n\n this.emit(\"connect\", {\n session,\n });\n },\n });\n\n console.error(\n `server is running on SSE at http://localhost:${options.sse.port}${options.sse.endpoint}`,\n );\n } else {\n throw new Error(\"Invalid transport type\");\n }\n }\n\n /**\n * Stops the server.\n */\n public async stop() {\n if (this.#sseServer) {\n this.#sseServer.close();\n }\n }\n}\n"],"mappings":"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","names":["prompt","resource","tool"]}
|
package/jsr.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fastmcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.15.0",
|
|
4
4
|
"main": "dist/FastMCP.js",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "tsup",
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"fuse.js": "^7.0.0",
|
|
28
28
|
"mcp-proxy": "^2.4.0",
|
|
29
29
|
"strict-event-emitter-types": "^2.0.0",
|
|
30
|
+
"uri-templates": "^0.2.0",
|
|
30
31
|
"yargs": "^17.7.2",
|
|
31
32
|
"zod": "^3.24.1",
|
|
32
33
|
"zod-to-json-schema": "^3.24.1"
|
|
@@ -50,6 +51,7 @@
|
|
|
50
51
|
"@sebbo2002/semantic-release-jsr": "^2.0.2",
|
|
51
52
|
"@tsconfig/node22": "^22.0.0",
|
|
52
53
|
"@types/node": "^22.10.2",
|
|
54
|
+
"@types/uri-templates": "^0.1.34",
|
|
53
55
|
"@types/yargs": "^17.0.33",
|
|
54
56
|
"eslint": "^9.17.0",
|
|
55
57
|
"eslint-plugin-perfectionist": "^4.4.0",
|
package/src/FastMCP.test.ts
CHANGED
|
@@ -951,7 +951,7 @@ test("session sends pings to the client", async () => {
|
|
|
951
951
|
});
|
|
952
952
|
});
|
|
953
953
|
|
|
954
|
-
test("prompt
|
|
954
|
+
test("completes prompt arguments", async () => {
|
|
955
955
|
await runWithTestServer({
|
|
956
956
|
server: async () => {
|
|
957
957
|
const server = new FastMCP({
|
|
@@ -1055,3 +1055,157 @@ test("adds automatic prompt argument completion when enum is provided", async ()
|
|
|
1055
1055
|
},
|
|
1056
1056
|
});
|
|
1057
1057
|
});
|
|
1058
|
+
|
|
1059
|
+
test("completes template resource arguments", async () => {
|
|
1060
|
+
await runWithTestServer({
|
|
1061
|
+
server: async () => {
|
|
1062
|
+
const server = new FastMCP({
|
|
1063
|
+
name: "Test",
|
|
1064
|
+
version: "1.0.0",
|
|
1065
|
+
});
|
|
1066
|
+
|
|
1067
|
+
server.addResourceTemplate({
|
|
1068
|
+
uriTemplate: "issue:///{issueId}",
|
|
1069
|
+
name: "Issue",
|
|
1070
|
+
mimeType: "text/plain",
|
|
1071
|
+
arguments: [
|
|
1072
|
+
{
|
|
1073
|
+
name: "issueId",
|
|
1074
|
+
description: "ID of the issue",
|
|
1075
|
+
complete: async (value) => {
|
|
1076
|
+
if (value === "123") {
|
|
1077
|
+
return {
|
|
1078
|
+
values: ["123456"],
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
return {
|
|
1083
|
+
values: [],
|
|
1084
|
+
};
|
|
1085
|
+
},
|
|
1086
|
+
},
|
|
1087
|
+
],
|
|
1088
|
+
load: async ({ issueId }) => {
|
|
1089
|
+
return {
|
|
1090
|
+
text: `Issue ${issueId}`,
|
|
1091
|
+
};
|
|
1092
|
+
},
|
|
1093
|
+
});
|
|
1094
|
+
|
|
1095
|
+
return server;
|
|
1096
|
+
},
|
|
1097
|
+
run: async ({ client }) => {
|
|
1098
|
+
const response = await client.complete({
|
|
1099
|
+
ref: {
|
|
1100
|
+
type: "ref/resource",
|
|
1101
|
+
uri: "issue:///{issueId}",
|
|
1102
|
+
},
|
|
1103
|
+
argument: {
|
|
1104
|
+
name: "issueId",
|
|
1105
|
+
value: "123",
|
|
1106
|
+
},
|
|
1107
|
+
});
|
|
1108
|
+
|
|
1109
|
+
expect(response).toEqual({
|
|
1110
|
+
completion: {
|
|
1111
|
+
values: ["123456"],
|
|
1112
|
+
},
|
|
1113
|
+
});
|
|
1114
|
+
},
|
|
1115
|
+
});
|
|
1116
|
+
});
|
|
1117
|
+
|
|
1118
|
+
test("lists resource templates", async () => {
|
|
1119
|
+
await runWithTestServer({
|
|
1120
|
+
server: async () => {
|
|
1121
|
+
const server = new FastMCP({
|
|
1122
|
+
name: "Test",
|
|
1123
|
+
version: "1.0.0",
|
|
1124
|
+
});
|
|
1125
|
+
|
|
1126
|
+
server.addResourceTemplate({
|
|
1127
|
+
uriTemplate: "file:///logs/{name}.log",
|
|
1128
|
+
name: "Application Logs",
|
|
1129
|
+
mimeType: "text/plain",
|
|
1130
|
+
arguments: [
|
|
1131
|
+
{
|
|
1132
|
+
name: "name",
|
|
1133
|
+
description: "Name of the log",
|
|
1134
|
+
required: true,
|
|
1135
|
+
},
|
|
1136
|
+
],
|
|
1137
|
+
load: async ({ name }) => {
|
|
1138
|
+
return {
|
|
1139
|
+
text: `Example log content for ${name}`,
|
|
1140
|
+
};
|
|
1141
|
+
},
|
|
1142
|
+
});
|
|
1143
|
+
|
|
1144
|
+
return server;
|
|
1145
|
+
},
|
|
1146
|
+
run: async ({ client }) => {
|
|
1147
|
+
expect(await client.listResourceTemplates()).toEqual({
|
|
1148
|
+
resourceTemplates: [
|
|
1149
|
+
{
|
|
1150
|
+
name: "Application Logs",
|
|
1151
|
+
uriTemplate: "file:///logs/{name}.log",
|
|
1152
|
+
},
|
|
1153
|
+
],
|
|
1154
|
+
});
|
|
1155
|
+
},
|
|
1156
|
+
});
|
|
1157
|
+
});
|
|
1158
|
+
|
|
1159
|
+
test("clients reads a resource accessed via a resource template", async () => {
|
|
1160
|
+
const loadSpy = vi.fn((_args) => {
|
|
1161
|
+
return {
|
|
1162
|
+
text: "Example log content",
|
|
1163
|
+
};
|
|
1164
|
+
});
|
|
1165
|
+
|
|
1166
|
+
await runWithTestServer({
|
|
1167
|
+
server: async () => {
|
|
1168
|
+
const server = new FastMCP({
|
|
1169
|
+
name: "Test",
|
|
1170
|
+
version: "1.0.0",
|
|
1171
|
+
});
|
|
1172
|
+
|
|
1173
|
+
server.addResourceTemplate({
|
|
1174
|
+
uriTemplate: "file:///logs/{name}.log",
|
|
1175
|
+
name: "Application Logs",
|
|
1176
|
+
mimeType: "text/plain",
|
|
1177
|
+
arguments: [
|
|
1178
|
+
{
|
|
1179
|
+
name: "name",
|
|
1180
|
+
description: "Name of the log",
|
|
1181
|
+
},
|
|
1182
|
+
],
|
|
1183
|
+
async load(args) {
|
|
1184
|
+
return loadSpy(args);
|
|
1185
|
+
},
|
|
1186
|
+
});
|
|
1187
|
+
|
|
1188
|
+
return server;
|
|
1189
|
+
},
|
|
1190
|
+
run: async ({ client }) => {
|
|
1191
|
+
expect(
|
|
1192
|
+
await client.readResource({
|
|
1193
|
+
uri: "file:///logs/app.log",
|
|
1194
|
+
}),
|
|
1195
|
+
).toEqual({
|
|
1196
|
+
contents: [
|
|
1197
|
+
{
|
|
1198
|
+
uri: "file:///logs/app.log",
|
|
1199
|
+
name: "Application Logs",
|
|
1200
|
+
text: "Example log content",
|
|
1201
|
+
mimeType: "text/plain",
|
|
1202
|
+
},
|
|
1203
|
+
],
|
|
1204
|
+
});
|
|
1205
|
+
|
|
1206
|
+
expect(loadSpy).toHaveBeenCalledWith({
|
|
1207
|
+
name: "app",
|
|
1208
|
+
});
|
|
1209
|
+
},
|
|
1210
|
+
});
|
|
1211
|
+
});
|
package/src/FastMCP.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
GetPromptRequestSchema,
|
|
9
9
|
ListPromptsRequestSchema,
|
|
10
10
|
ListResourcesRequestSchema,
|
|
11
|
+
ListResourceTemplatesRequestSchema,
|
|
11
12
|
ListToolsRequestSchema,
|
|
12
13
|
McpError,
|
|
13
14
|
ReadResourceRequestSchema,
|
|
@@ -26,6 +27,7 @@ import { EventEmitter } from "events";
|
|
|
26
27
|
import Fuse from "fuse.js";
|
|
27
28
|
import { startSSEServer } from "mcp-proxy";
|
|
28
29
|
import { Transport } from "@modelcontextprotocol/sdk/shared/transport.js";
|
|
30
|
+
import parseURITemplate from "uri-templates";
|
|
29
31
|
|
|
30
32
|
export type SSEServer = {
|
|
31
33
|
close: () => Promise<void>;
|
|
@@ -230,12 +232,56 @@ type ResourceResult =
|
|
|
230
232
|
blob: string;
|
|
231
233
|
};
|
|
232
234
|
|
|
235
|
+
type InputResourceTemplateArgument = Readonly<{
|
|
236
|
+
name: string;
|
|
237
|
+
description?: string;
|
|
238
|
+
complete?: ArgumentValueCompleter;
|
|
239
|
+
}>;
|
|
240
|
+
|
|
241
|
+
type ResourceTemplateArgument = Readonly<{
|
|
242
|
+
name: string;
|
|
243
|
+
description?: string;
|
|
244
|
+
complete?: ArgumentValueCompleter;
|
|
245
|
+
}>;
|
|
246
|
+
|
|
247
|
+
type ResourceTemplate<
|
|
248
|
+
Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[],
|
|
249
|
+
> = {
|
|
250
|
+
uriTemplate: string;
|
|
251
|
+
name: string;
|
|
252
|
+
description?: string;
|
|
253
|
+
mimeType?: string;
|
|
254
|
+
arguments: Arguments;
|
|
255
|
+
complete?: (name: string, value: string) => Promise<Completion>;
|
|
256
|
+
load: (
|
|
257
|
+
args: ResourceTemplateArgumentsToObject<Arguments>,
|
|
258
|
+
) => Promise<ResourceResult>;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
type ResourceTemplateArgumentsToObject<T extends { name: string }[]> = {
|
|
262
|
+
[K in T[number]["name"]]: string;
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
type InputResourceTemplate<
|
|
266
|
+
Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[],
|
|
267
|
+
> = {
|
|
268
|
+
uriTemplate: string;
|
|
269
|
+
name: string;
|
|
270
|
+
description?: string;
|
|
271
|
+
mimeType?: string;
|
|
272
|
+
arguments: Arguments;
|
|
273
|
+
load: (
|
|
274
|
+
args: ResourceTemplateArgumentsToObject<Arguments>,
|
|
275
|
+
) => Promise<ResourceResult>;
|
|
276
|
+
};
|
|
277
|
+
|
|
233
278
|
type Resource = {
|
|
234
279
|
uri: string;
|
|
235
280
|
name: string;
|
|
236
281
|
description?: string;
|
|
237
282
|
mimeType?: string;
|
|
238
283
|
load: () => Promise<ResourceResult | ResourceResult[]>;
|
|
284
|
+
complete?: (name: string, value: string) => Promise<Completion>;
|
|
239
285
|
};
|
|
240
286
|
|
|
241
287
|
type ArgumentValueCompleter = (value: string) => Promise<Completion>;
|
|
@@ -248,18 +294,19 @@ type InputPromptArgument = Readonly<{
|
|
|
248
294
|
enum?: string[];
|
|
249
295
|
}>;
|
|
250
296
|
|
|
251
|
-
type
|
|
252
|
-
|
|
253
|
-
T[number]
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
297
|
+
type PromptArgumentsToObject<T extends { name: string; required?: boolean }[]> =
|
|
298
|
+
{
|
|
299
|
+
[K in T[number]["name"]]: Extract<
|
|
300
|
+
T[number],
|
|
301
|
+
{ name: K }
|
|
302
|
+
>["required"] extends true
|
|
303
|
+
? string
|
|
304
|
+
: string | undefined;
|
|
305
|
+
};
|
|
259
306
|
|
|
260
307
|
type InputPrompt<
|
|
261
308
|
Arguments extends InputPromptArgument[] = InputPromptArgument[],
|
|
262
|
-
Args =
|
|
309
|
+
Args = PromptArgumentsToObject<Arguments>,
|
|
263
310
|
> = {
|
|
264
311
|
name: string;
|
|
265
312
|
description?: string;
|
|
@@ -277,7 +324,7 @@ type PromptArgument = Readonly<{
|
|
|
277
324
|
|
|
278
325
|
type Prompt<
|
|
279
326
|
Arguments extends PromptArgument[] = PromptArgument[],
|
|
280
|
-
Args =
|
|
327
|
+
Args = PromptArgumentsToObject<Arguments>,
|
|
281
328
|
> = {
|
|
282
329
|
arguments?: PromptArgument[];
|
|
283
330
|
complete?: (name: string, value: string) => Promise<Completion>;
|
|
@@ -309,23 +356,27 @@ class FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {}
|
|
|
309
356
|
|
|
310
357
|
export class FastMCPSession extends FastMCPSessionEventEmitter {
|
|
311
358
|
#capabilities: ServerCapabilities = {};
|
|
312
|
-
#loggingLevel: LoggingLevel = "info";
|
|
313
|
-
#server: Server;
|
|
314
359
|
#clientCapabilities?: ClientCapabilities;
|
|
315
|
-
#
|
|
360
|
+
#loggingLevel: LoggingLevel = "info";
|
|
316
361
|
#prompts: Prompt[] = [];
|
|
362
|
+
#resources: Resource[] = [];
|
|
363
|
+
#resourceTemplates: ResourceTemplate[] = [];
|
|
364
|
+
#roots: Root[] = [];
|
|
365
|
+
#server: Server;
|
|
317
366
|
|
|
318
367
|
constructor({
|
|
319
368
|
name,
|
|
320
369
|
version,
|
|
321
370
|
tools,
|
|
322
371
|
resources,
|
|
372
|
+
resourcesTemplates,
|
|
323
373
|
prompts,
|
|
324
374
|
}: {
|
|
325
375
|
name: string;
|
|
326
376
|
version: string;
|
|
327
377
|
tools: Tool[];
|
|
328
378
|
resources: Resource[];
|
|
379
|
+
resourcesTemplates: InputResourceTemplate[];
|
|
329
380
|
prompts: Prompt[];
|
|
330
381
|
}) {
|
|
331
382
|
super();
|
|
@@ -334,7 +385,7 @@ export class FastMCPSession extends FastMCPSessionEventEmitter {
|
|
|
334
385
|
this.#capabilities.tools = {};
|
|
335
386
|
}
|
|
336
387
|
|
|
337
|
-
if (resources.length) {
|
|
388
|
+
if (resources.length || resourcesTemplates.length) {
|
|
338
389
|
this.#capabilities.resources = {};
|
|
339
390
|
}
|
|
340
391
|
|
|
@@ -362,8 +413,20 @@ export class FastMCPSession extends FastMCPSessionEventEmitter {
|
|
|
362
413
|
this.setupToolHandlers(tools);
|
|
363
414
|
}
|
|
364
415
|
|
|
365
|
-
if (resources.length) {
|
|
416
|
+
if (resources.length || resourcesTemplates.length) {
|
|
417
|
+
for (const resource of resources) {
|
|
418
|
+
this.addResource(resource);
|
|
419
|
+
}
|
|
420
|
+
|
|
366
421
|
this.setupResourceHandlers(resources);
|
|
422
|
+
|
|
423
|
+
if (resourcesTemplates.length) {
|
|
424
|
+
for (const resourceTemplate of resourcesTemplates) {
|
|
425
|
+
this.addResourceTemplate(resourceTemplate);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
this.setupResourceTemplateHandlers(resourcesTemplates);
|
|
429
|
+
}
|
|
367
430
|
}
|
|
368
431
|
|
|
369
432
|
if (prompts.length) {
|
|
@@ -371,6 +434,35 @@ export class FastMCPSession extends FastMCPSessionEventEmitter {
|
|
|
371
434
|
}
|
|
372
435
|
}
|
|
373
436
|
|
|
437
|
+
private addResource(inputResource: Resource) {
|
|
438
|
+
this.#resources.push(inputResource);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
private addResourceTemplate(inputResourceTemplate: InputResourceTemplate) {
|
|
442
|
+
const completers: Record<string, ArgumentValueCompleter> = {};
|
|
443
|
+
|
|
444
|
+
for (const argument of inputResourceTemplate.arguments ?? []) {
|
|
445
|
+
if (argument.complete) {
|
|
446
|
+
completers[argument.name] = argument.complete;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const resourceTemplate = {
|
|
451
|
+
...inputResourceTemplate,
|
|
452
|
+
complete: async (name: string, value: string) => {
|
|
453
|
+
if (completers[name]) {
|
|
454
|
+
return await completers[name](value);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return {
|
|
458
|
+
values: [],
|
|
459
|
+
};
|
|
460
|
+
},
|
|
461
|
+
};
|
|
462
|
+
|
|
463
|
+
this.#resourceTemplates.push(resourceTemplate);
|
|
464
|
+
}
|
|
465
|
+
|
|
374
466
|
private addPrompt(inputPrompt: InputPrompt) {
|
|
375
467
|
const completers: Record<string, ArgumentValueCompleter> = {};
|
|
376
468
|
const enums: Record<string, string[]> = {};
|
|
@@ -519,6 +611,42 @@ export class FastMCPSession extends FastMCPSessionEventEmitter {
|
|
|
519
611
|
};
|
|
520
612
|
}
|
|
521
613
|
|
|
614
|
+
if (request.params.ref.type === "ref/resource") {
|
|
615
|
+
const resource = this.#resourceTemplates.find(
|
|
616
|
+
(resource) => resource.uriTemplate === request.params.ref.uri,
|
|
617
|
+
);
|
|
618
|
+
|
|
619
|
+
if (!resource) {
|
|
620
|
+
throw new UnexpectedStateError("Unknown resource", {
|
|
621
|
+
request,
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
if (!("uriTemplate" in resource)) {
|
|
626
|
+
throw new UnexpectedStateError("Unexpected resource");
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
if (!resource.complete) {
|
|
630
|
+
throw new UnexpectedStateError(
|
|
631
|
+
"Resource does not support completion",
|
|
632
|
+
{
|
|
633
|
+
request,
|
|
634
|
+
},
|
|
635
|
+
);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
const completion = CompletionZodSchema.parse(
|
|
639
|
+
await resource.complete(
|
|
640
|
+
request.params.argument.name,
|
|
641
|
+
request.params.argument.value,
|
|
642
|
+
),
|
|
643
|
+
);
|
|
644
|
+
|
|
645
|
+
return {
|
|
646
|
+
completion,
|
|
647
|
+
};
|
|
648
|
+
}
|
|
649
|
+
|
|
522
650
|
throw new UnexpectedStateError("Unexpected completion request", {
|
|
523
651
|
request,
|
|
524
652
|
});
|
|
@@ -699,6 +827,33 @@ export class FastMCPSession extends FastMCPSessionEventEmitter {
|
|
|
699
827
|
);
|
|
700
828
|
|
|
701
829
|
if (!resource) {
|
|
830
|
+
for (const resourceTemplate of this.#resourceTemplates) {
|
|
831
|
+
const uriTemplate = parseURITemplate(
|
|
832
|
+
resourceTemplate.uriTemplate,
|
|
833
|
+
);
|
|
834
|
+
|
|
835
|
+
const match = uriTemplate.fromUri(request.params.uri);
|
|
836
|
+
|
|
837
|
+
if (!match) {
|
|
838
|
+
continue;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
const uri = uriTemplate.fill(match);
|
|
842
|
+
|
|
843
|
+
const result = await resourceTemplate.load(match);
|
|
844
|
+
|
|
845
|
+
return {
|
|
846
|
+
contents: [
|
|
847
|
+
{
|
|
848
|
+
uri: uri,
|
|
849
|
+
mimeType: resourceTemplate.mimeType,
|
|
850
|
+
name: resourceTemplate.name,
|
|
851
|
+
...result,
|
|
852
|
+
},
|
|
853
|
+
],
|
|
854
|
+
};
|
|
855
|
+
}
|
|
856
|
+
|
|
702
857
|
throw new McpError(
|
|
703
858
|
ErrorCode.MethodNotFound,
|
|
704
859
|
`Unknown resource: ${request.params.uri}`,
|
|
@@ -746,11 +901,25 @@ export class FastMCPSession extends FastMCPSessionEventEmitter {
|
|
|
746
901
|
}
|
|
747
902
|
}
|
|
748
903
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
}
|
|
904
|
+
throw new UnexpectedStateError("Unknown resource request", {
|
|
905
|
+
request,
|
|
906
|
+
});
|
|
907
|
+
},
|
|
908
|
+
);
|
|
909
|
+
}
|
|
752
910
|
|
|
753
|
-
|
|
911
|
+
private setupResourceTemplateHandlers(resourceTemplates: ResourceTemplate[]) {
|
|
912
|
+
this.#server.setRequestHandler(
|
|
913
|
+
ListResourceTemplatesRequestSchema,
|
|
914
|
+
async () => {
|
|
915
|
+
return {
|
|
916
|
+
resourceTemplates: resourceTemplates.map((resourceTemplate) => {
|
|
917
|
+
return {
|
|
918
|
+
name: resourceTemplate.name,
|
|
919
|
+
uriTemplate: resourceTemplate.uriTemplate,
|
|
920
|
+
};
|
|
921
|
+
}),
|
|
922
|
+
};
|
|
754
923
|
},
|
|
755
924
|
);
|
|
756
925
|
}
|
|
@@ -826,6 +995,7 @@ export class FastMCP extends FastMCPEventEmitter {
|
|
|
826
995
|
#options: ServerOptions;
|
|
827
996
|
#prompts: InputPrompt[] = [];
|
|
828
997
|
#resources: Resource[] = [];
|
|
998
|
+
#resourcesTemplates: InputResourceTemplate[] = [];
|
|
829
999
|
#sessions: FastMCPSession[] = [];
|
|
830
1000
|
#sseServer: SSEServer | null = null;
|
|
831
1001
|
#tools: Tool[] = [];
|
|
@@ -854,6 +1024,15 @@ export class FastMCP extends FastMCPEventEmitter {
|
|
|
854
1024
|
this.#resources.push(resource);
|
|
855
1025
|
}
|
|
856
1026
|
|
|
1027
|
+
/**
|
|
1028
|
+
* Adds a resource template to the server.
|
|
1029
|
+
*/
|
|
1030
|
+
public addResourceTemplate<
|
|
1031
|
+
const Args extends InputResourceTemplateArgument[],
|
|
1032
|
+
>(resource: InputResourceTemplate<Args>) {
|
|
1033
|
+
this.#resourcesTemplates.push(resource);
|
|
1034
|
+
}
|
|
1035
|
+
|
|
857
1036
|
/**
|
|
858
1037
|
* Adds a prompt to the server.
|
|
859
1038
|
*/
|
|
@@ -884,6 +1063,7 @@ export class FastMCP extends FastMCPEventEmitter {
|
|
|
884
1063
|
version: this.#options.version,
|
|
885
1064
|
tools: this.#tools,
|
|
886
1065
|
resources: this.#resources,
|
|
1066
|
+
resourcesTemplates: this.#resourcesTemplates,
|
|
887
1067
|
prompts: this.#prompts,
|
|
888
1068
|
});
|
|
889
1069
|
|
|
@@ -906,6 +1086,7 @@ export class FastMCP extends FastMCPEventEmitter {
|
|
|
906
1086
|
version: this.#options.version,
|
|
907
1087
|
tools: this.#tools,
|
|
908
1088
|
resources: this.#resources,
|
|
1089
|
+
resourcesTemplates: this.#resourcesTemplates,
|
|
909
1090
|
prompts: this.#prompts,
|
|
910
1091
|
});
|
|
911
1092
|
},
|