fastmcp 1.22.4 → 1.23.1

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 CHANGED
@@ -432,7 +432,6 @@ server.addTool({
432
432
  });
433
433
  ```
434
434
 
435
-
436
435
  #### Logging
437
436
 
438
437
  Tools can log messages to the client using the `log` object in the context object:
@@ -517,6 +516,40 @@ server.addTool({
517
516
  });
518
517
  ```
519
518
 
519
+ #### Tool Annotations
520
+
521
+ As of the MCP Specification (2025-03-26), tools can include annotations that provide richer context and control by adding metadata about a tool's behavior:
522
+
523
+ ```typescript
524
+ server.addTool({
525
+ name: "fetch-content",
526
+ description: "Fetch content from a URL",
527
+ parameters: z.object({
528
+ url: z.string(),
529
+ }),
530
+ annotations: {
531
+ title: "Web Content Fetcher", // Human-readable title for UI display
532
+ readOnlyHint: true, // Tool doesn't modify its environment
533
+ openWorldHint: true, // Tool interacts with external entities
534
+ },
535
+ execute: async (args) => {
536
+ return await fetchWebpageContent(args.url);
537
+ },
538
+ });
539
+ ```
540
+
541
+ The available annotations are:
542
+
543
+ | Annotation | Type | Default | Description |
544
+ | :---------------- | :------ | :------ | :----------------------------------------------------------------------------------------------------------------------------------- |
545
+ | `title` | string | - | A human-readable title for the tool, useful for UI display |
546
+ | `readOnlyHint` | boolean | `false` | If true, indicates the tool does not modify its environment |
547
+ | `destructiveHint` | boolean | `true` | If true, the tool may perform destructive updates (only meaningful when `readOnlyHint` is false) |
548
+ | `idempotentHint` | boolean | `false` | If true, calling the tool repeatedly with the same arguments has no additional effect (only meaningful when `readOnlyHint` is false) |
549
+ | `openWorldHint` | boolean | `true` | If true, the tool may interact with an "open world" of external entities |
550
+
551
+ These annotations help clients and LLMs better understand how to use the tools and what to expect when calling them.
552
+
520
553
  ### Resources
521
554
 
522
555
  [Resources](https://modelcontextprotocol.io/docs/concepts/resources) represent any kind of data that an MCP server wants to make available to clients. This can include:
@@ -712,10 +745,10 @@ import { AuthError } from "fastmcp";
712
745
  const server = new FastMCP({
713
746
  name: "My Server",
714
747
  version: "1.0.0",
715
- authenticate: ({request}) => {
748
+ authenticate: ({ request }) => {
716
749
  const apiKey = request.headers["x-api-key"];
717
750
 
718
- if (apiKey !== '123') {
751
+ if (apiKey !== "123") {
719
752
  throw new Response(null, {
720
753
  status: 401,
721
754
  statusText: "Unauthorized",
@@ -725,7 +758,7 @@ const server = new FastMCP({
725
758
  // Whatever you return here will be accessible in the `context.session` object.
726
759
  return {
727
760
  id: 1,
728
- }
761
+ };
729
762
  },
730
763
  });
731
764
  ```
@@ -741,6 +774,19 @@ server.addTool({
741
774
  });
742
775
  ```
743
776
 
777
+ ### Providing Instructions
778
+
779
+ You can provide instructions to the server using the `instructions` option:
780
+
781
+ ```ts
782
+ const server = new FastMCP({
783
+ name: "My Server",
784
+ version: "1.0.0",
785
+ instructions:
786
+ 'Instructions describing how to use the server and its features.\n\nThis can be used by clients to improve the LLM\'s understanding of available tools, resources, etc. It can be thought of like a "hint" to the model. For example, this information MAY be added to the system prompt.',
787
+ });
788
+ ```
789
+
744
790
  ### Sessions
745
791
 
746
792
  The `session` object is an instance of `FastMCPSession` and it describes active client sessions.
@@ -870,10 +916,7 @@ Follow the guide https://modelcontextprotocol.io/quickstart/user and add the fol
870
916
  "mcpServers": {
871
917
  "my-mcp-server": {
872
918
  "command": "npx",
873
- "args": [
874
- "tsx",
875
- "/PATH/TO/YOUR_PROJECT/src/index.ts"
876
- ],
919
+ "args": ["tsx", "/PATH/TO/YOUR_PROJECT/src/index.ts"],
877
920
  "env": {
878
921
  "YOUR_ENV_VAR": "value"
879
922
  }
package/dist/FastMCP.d.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
2
3
  import { AudioContent, Root, ClientCapabilities, CreateMessageRequestSchema } from '@modelcontextprotocol/sdk/types.js';
3
4
  import { StandardSchemaV1 } from '@standard-schema/spec';
4
- import { z } from 'zod';
5
- import { StrictEventEmitter } from 'strict-event-emitter-types';
6
5
  import { EventEmitter } from 'events';
7
- import { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
8
6
  import http from 'http';
7
+ import { StrictEventEmitter } from 'strict-event-emitter-types';
8
+ import { z } from 'zod';
9
9
 
10
10
  type SSEServer = {
11
11
  close: () => Promise<void>;
@@ -19,49 +19,43 @@ type FastMCPEvents<T extends FastMCPSessionAuth> = {
19
19
  }) => void;
20
20
  };
21
21
  type FastMCPSessionEvents = {
22
- rootsChanged: (event: {
23
- roots: Root[];
24
- }) => void;
25
22
  error: (event: {
26
23
  error: Error;
27
24
  }) => void;
25
+ rootsChanged: (event: {
26
+ roots: Root[];
27
+ }) => void;
28
28
  };
29
29
  /**
30
30
  * Generates an image content object from a URL, file path, or buffer.
31
31
  */
32
32
  declare const imageContent: (input: {
33
- url: string;
33
+ buffer: Buffer;
34
34
  } | {
35
35
  path: string;
36
36
  } | {
37
- buffer: Buffer;
37
+ url: string;
38
38
  }) => Promise<ImageContent>;
39
39
  declare const audioContent: (input: {
40
- url: string;
40
+ buffer: Buffer;
41
41
  } | {
42
42
  path: string;
43
43
  } | {
44
- buffer: Buffer;
44
+ url: string;
45
45
  }) => Promise<AudioContent>;
46
- declare abstract class FastMCPError extends Error {
47
- constructor(message?: string);
48
- }
46
+ type Context<T extends FastMCPSessionAuth> = {
47
+ log: {
48
+ debug: (message: string, data?: SerializableValue) => void;
49
+ error: (message: string, data?: SerializableValue) => void;
50
+ info: (message: string, data?: SerializableValue) => void;
51
+ warn: (message: string, data?: SerializableValue) => void;
52
+ };
53
+ reportProgress: (progress: Progress) => Promise<void>;
54
+ session: T | undefined;
55
+ };
49
56
  type Extra = unknown;
50
57
  type Extras = Record<string, Extra>;
51
- declare class UnexpectedStateError extends FastMCPError {
52
- extras?: Extras;
53
- constructor(message: string, extras?: Extras);
54
- }
55
- /**
56
- * An error that is meant to be surfaced to the user.
57
- */
58
- declare class UserError extends UnexpectedStateError {
59
- }
60
- type ToolParameters = StandardSchemaV1;
61
58
  type Literal = boolean | null | number | string | undefined;
62
- type SerializableValue = Literal | SerializableValue[] | {
63
- [key: string]: SerializableValue;
64
- };
65
59
  type Progress = {
66
60
  /**
67
61
  * The progress thus far. This should increase every time progress is made, even if the total is unknown.
@@ -72,93 +66,82 @@ type Progress = {
72
66
  */
73
67
  total?: number;
74
68
  };
75
- type Context<T extends FastMCPSessionAuth> = {
76
- session: T | undefined;
77
- reportProgress: (progress: Progress) => Promise<void>;
78
- log: {
79
- debug: (message: string, data?: SerializableValue) => void;
80
- error: (message: string, data?: SerializableValue) => void;
81
- info: (message: string, data?: SerializableValue) => void;
82
- warn: (message: string, data?: SerializableValue) => void;
83
- };
84
- };
69
+ type SerializableValue = {
70
+ [key: string]: SerializableValue;
71
+ } | Literal | SerializableValue[];
85
72
  type TextContent = {
86
- type: "text";
87
73
  text: string;
74
+ type: "text";
88
75
  };
76
+ type ToolParameters = StandardSchemaV1;
77
+ declare abstract class FastMCPError extends Error {
78
+ constructor(message?: string);
79
+ }
80
+ declare class UnexpectedStateError extends FastMCPError {
81
+ extras?: Extras;
82
+ constructor(message: string, extras?: Extras);
83
+ }
84
+ /**
85
+ * An error that is meant to be surfaced to the user.
86
+ */
87
+ declare class UserError extends UnexpectedStateError {
88
+ }
89
89
  type ImageContent = {
90
- type: "image";
91
90
  data: string;
92
91
  mimeType: string;
92
+ type: "image";
93
93
  };
94
- type Content = TextContent | ImageContent;
94
+ type Content = ImageContent | TextContent;
95
95
  type ContentResult = {
96
96
  content: Content[];
97
97
  isError?: boolean;
98
98
  };
99
99
  type Completion = {
100
- values: string[];
101
- total?: number;
102
100
  hasMore?: boolean;
101
+ total?: number;
102
+ values: string[];
103
103
  };
104
- type Tool<T extends FastMCPSessionAuth, Params extends ToolParameters = ToolParameters> = {
105
- name: string;
104
+ type ArgumentValueCompleter = (value: string) => Promise<Completion>;
105
+ type InputPrompt<Arguments extends InputPromptArgument[] = InputPromptArgument[], Args = PromptArgumentsToObject<Arguments>> = {
106
+ arguments?: InputPromptArgument[];
106
107
  description?: string;
107
- parameters?: Params;
108
- execute: (args: StandardSchemaV1.InferOutput<Params>, context: Context<T>) => Promise<string | ContentResult | TextContent | ImageContent | AudioContent>;
109
- };
110
- type ResourceResult = {
111
- text: string;
112
- } | {
113
- blob: string;
114
- };
115
- type InputResourceTemplateArgument = Readonly<{
108
+ load: (args: Args) => Promise<string>;
116
109
  name: string;
117
- description?: string;
110
+ };
111
+ type InputPromptArgument = Readonly<{
118
112
  complete?: ArgumentValueCompleter;
119
- }>;
120
- type ResourceTemplateArgument = Readonly<{
121
- name: string;
122
113
  description?: string;
123
- complete?: ArgumentValueCompleter;
124
- }>;
125
- type ResourceTemplate<Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[]> = {
126
- uriTemplate: string;
114
+ enum?: string[];
127
115
  name: string;
128
- description?: string;
129
- mimeType?: string;
116
+ required?: boolean;
117
+ }>;
118
+ type InputResourceTemplate<Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[]> = {
130
119
  arguments: Arguments;
131
- complete?: (name: string, value: string) => Promise<Completion>;
120
+ description?: string;
132
121
  load: (args: ResourceTemplateArgumentsToObject<Arguments>) => Promise<ResourceResult>;
133
- };
134
- type ResourceTemplateArgumentsToObject<T extends {
122
+ mimeType?: string;
135
123
  name: string;
136
- }[]> = {
137
- [K in T[number]["name"]]: string;
138
- };
139
- type InputResourceTemplate<Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[]> = {
140
124
  uriTemplate: string;
141
- name: string;
142
- description?: string;
143
- mimeType?: string;
144
- arguments: Arguments;
145
- load: (args: ResourceTemplateArgumentsToObject<Arguments>) => Promise<ResourceResult>;
146
125
  };
147
- type Resource = {
148
- uri: string;
149
- name: string;
126
+ type InputResourceTemplateArgument = Readonly<{
127
+ complete?: ArgumentValueCompleter;
150
128
  description?: string;
151
- mimeType?: string;
152
- load: () => Promise<ResourceResult | ResourceResult[]>;
153
- complete?: (name: string, value: string) => Promise<Completion>;
154
- };
155
- type ArgumentValueCompleter = (value: string) => Promise<Completion>;
156
- type InputPromptArgument = Readonly<{
157
129
  name: string;
130
+ }>;
131
+ type LoggingLevel = "alert" | "critical" | "debug" | "emergency" | "error" | "info" | "notice" | "warning";
132
+ type Prompt<Arguments extends PromptArgument[] = PromptArgument[], Args = PromptArgumentsToObject<Arguments>> = {
133
+ arguments?: PromptArgument[];
134
+ complete?: (name: string, value: string) => Promise<Completion>;
158
135
  description?: string;
159
- required?: boolean;
136
+ load: (args: Args) => Promise<string>;
137
+ name: string;
138
+ };
139
+ type PromptArgument = Readonly<{
160
140
  complete?: ArgumentValueCompleter;
141
+ description?: string;
161
142
  enum?: string[];
143
+ name: string;
144
+ required?: boolean;
162
145
  }>;
163
146
  type PromptArgumentsToObject<T extends {
164
147
  name: string;
@@ -168,89 +151,141 @@ type PromptArgumentsToObject<T extends {
168
151
  name: K;
169
152
  }>["required"] extends true ? string : string | undefined;
170
153
  };
171
- type InputPrompt<Arguments extends InputPromptArgument[] = InputPromptArgument[], Args = PromptArgumentsToObject<Arguments>> = {
172
- name: string;
154
+ type Resource = {
155
+ complete?: (name: string, value: string) => Promise<Completion>;
173
156
  description?: string;
174
- arguments?: InputPromptArgument[];
175
- load: (args: Args) => Promise<string>;
176
- };
177
- type PromptArgument = Readonly<{
157
+ load: () => Promise<ResourceResult | ResourceResult[]>;
158
+ mimeType?: string;
178
159
  name: string;
160
+ uri: string;
161
+ };
162
+ type ResourceResult = {
163
+ blob: string;
164
+ } | {
165
+ text: string;
166
+ };
167
+ type ResourceTemplate<Arguments extends ResourceTemplateArgument[] = ResourceTemplateArgument[]> = {
168
+ arguments: Arguments;
169
+ complete?: (name: string, value: string) => Promise<Completion>;
179
170
  description?: string;
180
- required?: boolean;
171
+ load: (args: ResourceTemplateArgumentsToObject<Arguments>) => Promise<ResourceResult>;
172
+ mimeType?: string;
173
+ name: string;
174
+ uriTemplate: string;
175
+ };
176
+ type ResourceTemplateArgument = Readonly<{
181
177
  complete?: ArgumentValueCompleter;
182
- enum?: string[];
183
- }>;
184
- type Prompt<Arguments extends PromptArgument[] = PromptArgument[], Args = PromptArgumentsToObject<Arguments>> = {
185
- arguments?: PromptArgument[];
186
- complete?: (name: string, value: string) => Promise<Completion>;
187
178
  description?: string;
188
- load: (args: Args) => Promise<string>;
189
179
  name: string;
180
+ }>;
181
+ type ResourceTemplateArgumentsToObject<T extends {
182
+ name: string;
183
+ }[]> = {
184
+ [K in T[number]["name"]]: string;
190
185
  };
191
186
  type ServerOptions<T extends FastMCPSessionAuth> = {
187
+ authenticate?: Authenticate<T>;
188
+ instructions?: string;
192
189
  name: string;
193
190
  version: `${number}.${number}.${number}`;
194
- authenticate?: Authenticate<T>;
195
191
  };
196
- type LoggingLevel = "debug" | "info" | "notice" | "warning" | "error" | "critical" | "alert" | "emergency";
192
+ type Tool<T extends FastMCPSessionAuth, Params extends ToolParameters = ToolParameters> = {
193
+ annotations?: ToolAnnotations;
194
+ description?: string;
195
+ execute: (args: StandardSchemaV1.InferOutput<Params>, context: Context<T>) => Promise<AudioContent | ContentResult | ImageContent | string | TextContent>;
196
+ name: string;
197
+ parameters?: Params;
198
+ };
199
+ /**
200
+ * Tool annotations as defined in MCP Specification (2025-03-26)
201
+ * These provide hints about a tool's behavior.
202
+ */
203
+ type ToolAnnotations = {
204
+ /**
205
+ * If true, the tool may perform destructive updates
206
+ * Only meaningful when readOnlyHint is false
207
+ * @default true
208
+ */
209
+ destructiveHint?: boolean;
210
+ /**
211
+ * If true, calling the tool repeatedly with the same arguments has no additional effect
212
+ * Only meaningful when readOnlyHint is false
213
+ * @default false
214
+ */
215
+ idempotentHint?: boolean;
216
+ /**
217
+ * If true, the tool may interact with an "open world" of external entities
218
+ * @default true
219
+ */
220
+ openWorldHint?: boolean;
221
+ /**
222
+ * If true, indicates the tool does not modify its environment
223
+ * @default false
224
+ */
225
+ readOnlyHint?: boolean;
226
+ /**
227
+ * A human-readable title for the tool, useful for UI display
228
+ */
229
+ title?: string;
230
+ };
197
231
  declare const FastMCPSessionEventEmitterBase: {
198
232
  new (): StrictEventEmitter<EventEmitter, FastMCPSessionEvents>;
199
233
  };
200
- declare class FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {
201
- }
234
+ type FastMCPSessionAuth = Record<string, unknown> | undefined;
202
235
  type SamplingResponse = {
236
+ content: AudioContent | ImageContent | TextContent;
203
237
  model: string;
204
- stopReason?: "endTurn" | "stopSequence" | "maxTokens" | string;
205
- role: "user" | "assistant";
206
- content: TextContent | ImageContent | AudioContent;
238
+ role: "assistant" | "user";
239
+ stopReason?: "endTurn" | "maxTokens" | "stopSequence" | string;
207
240
  };
208
- type FastMCPSessionAuth = Record<string, unknown> | undefined;
241
+ declare class FastMCPSessionEventEmitter extends FastMCPSessionEventEmitterBase {
242
+ }
209
243
  declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth> extends FastMCPSessionEventEmitter {
210
244
  #private;
211
- constructor({ auth, name, version, tools, resources, resourcesTemplates, prompts, }: {
245
+ get clientCapabilities(): ClientCapabilities | null;
246
+ get loggingLevel(): LoggingLevel;
247
+ get roots(): Root[];
248
+ get server(): Server;
249
+ constructor({ auth, instructions, name, prompts, resources, resourcesTemplates, tools, version, }: {
212
250
  auth?: T;
251
+ instructions?: string;
213
252
  name: string;
214
- version: string;
215
- tools: Tool<T>[];
253
+ prompts: Prompt[];
216
254
  resources: Resource[];
217
255
  resourcesTemplates: InputResourceTemplate[];
218
- prompts: Prompt[];
256
+ tools: Tool<T>[];
257
+ version: string;
219
258
  });
259
+ close(): Promise<void>;
260
+ connect(transport: Transport): Promise<void>;
261
+ requestSampling(message: z.infer<typeof CreateMessageRequestSchema>["params"]): Promise<SamplingResponse>;
262
+ private addPrompt;
220
263
  private addResource;
221
264
  private addResourceTemplate;
222
- private addPrompt;
223
- get clientCapabilities(): ClientCapabilities | null;
224
- get server(): Server;
225
- requestSampling(message: z.infer<typeof CreateMessageRequestSchema>["params"]): Promise<SamplingResponse>;
226
- connect(transport: Transport): Promise<void>;
227
- get roots(): Root[];
228
- close(): Promise<void>;
229
- private setupErrorHandling;
230
- get loggingLevel(): LoggingLevel;
231
265
  private setupCompleteHandlers;
232
- private setupRootsHandlers;
266
+ private setupErrorHandling;
233
267
  private setupLoggingHandlers;
234
- private setupToolHandlers;
268
+ private setupPromptHandlers;
235
269
  private setupResourceHandlers;
236
270
  private setupResourceTemplateHandlers;
237
- private setupPromptHandlers;
271
+ private setupRootsHandlers;
272
+ private setupToolHandlers;
238
273
  }
239
274
  declare const FastMCPEventEmitterBase: {
240
275
  new (): StrictEventEmitter<EventEmitter, FastMCPEvents<FastMCPSessionAuth>>;
241
276
  };
277
+ type Authenticate<T> = (request: http.IncomingMessage) => Promise<T>;
242
278
  declare class FastMCPEventEmitter extends FastMCPEventEmitterBase {
243
279
  }
244
- type Authenticate<T> = (request: http.IncomingMessage) => Promise<T>;
245
280
  declare class FastMCP<T extends Record<string, unknown> | undefined = undefined> extends FastMCPEventEmitter {
246
281
  #private;
247
282
  options: ServerOptions<T>;
248
- constructor(options: ServerOptions<T>);
249
283
  get sessions(): FastMCPSession<T>[];
284
+ constructor(options: ServerOptions<T>);
250
285
  /**
251
- * Adds a tool to the server.
286
+ * Adds a prompt to the server.
252
287
  */
253
- addTool<Params extends ToolParameters>(tool: Tool<T, Params>): void;
288
+ addPrompt<const Args extends InputPromptArgument[]>(prompt: InputPrompt<Args>): void;
254
289
  /**
255
290
  * Adds a resource to the server.
256
291
  */
@@ -260,20 +295,20 @@ declare class FastMCP<T extends Record<string, unknown> | undefined = undefined>
260
295
  */
261
296
  addResourceTemplate<const Args extends InputResourceTemplateArgument[]>(resource: InputResourceTemplate<Args>): void;
262
297
  /**
263
- * Adds a prompt to the server.
298
+ * Adds a tool to the server.
264
299
  */
265
- addPrompt<const Args extends InputPromptArgument[]>(prompt: InputPrompt<Args>): void;
300
+ addTool<Params extends ToolParameters>(tool: Tool<T, Params>): void;
266
301
  /**
267
302
  * Starts the server.
268
303
  */
269
304
  start(options?: {
270
- transportType: "stdio";
271
- } | {
272
- transportType: "sse";
273
305
  sse: {
274
306
  endpoint: `/${string}`;
275
307
  port: number;
276
308
  };
309
+ transportType: "sse";
310
+ } | {
311
+ transportType: "stdio";
277
312
  }): Promise<void>;
278
313
  /**
279
314
  * Stops the server.