fastmcp 3.19.3 → 3.20.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/.roo/mcp.json +11 -0
- package/README.md +83 -0
- package/dist/FastMCP.d.ts +16 -1
- package/dist/FastMCP.js +29 -5
- package/dist/FastMCP.js.map +1 -1
- package/jsr.json +1 -1
- package/package.json +1 -1
- package/src/FastMCP.session-id.test.ts +359 -0
- package/src/FastMCP.test.ts +2 -0
- package/src/FastMCP.ts +58 -5
- package/src/examples/session-id-counter.ts +230 -0
package/.roo/mcp.json
ADDED
package/README.md
CHANGED
|
@@ -11,6 +11,7 @@ A TypeScript framework for building [MCP](https://glama.ai/mcp) servers capable
|
|
|
11
11
|
- Simple Tool, Resource, Prompt definition
|
|
12
12
|
- [Authentication](#authentication)
|
|
13
13
|
- [Passing headers through context](#passing-headers-through-context)
|
|
14
|
+
- [Session ID and Request ID tracking](#session-id-and-request-id-tracking)
|
|
14
15
|
- [Sessions](#sessions)
|
|
15
16
|
- [Image content](#returning-an-image)
|
|
16
17
|
- [Audio content](#returning-an-audio)
|
|
@@ -1529,6 +1530,88 @@ Tool result: {
|
|
|
1529
1530
|
}
|
|
1530
1531
|
```
|
|
1531
1532
|
|
|
1533
|
+
#### Session ID and Request ID Tracking
|
|
1534
|
+
|
|
1535
|
+
FastMCP automatically exposes session and request IDs to tool handlers through the context parameter. This enables per-session state management and request tracking.
|
|
1536
|
+
|
|
1537
|
+
**Session ID** (`context.sessionId`):
|
|
1538
|
+
|
|
1539
|
+
- Available only for HTTP-based transports (HTTP Stream, SSE)
|
|
1540
|
+
- Extracted from the `Mcp-Session-Id` header
|
|
1541
|
+
- Remains constant across multiple requests from the same client
|
|
1542
|
+
- Useful for maintaining per-session state, counters, or user-specific data
|
|
1543
|
+
|
|
1544
|
+
**Request ID** (`context.requestId`):
|
|
1545
|
+
|
|
1546
|
+
- Available for all transports when provided by the client
|
|
1547
|
+
- Unique for each individual request
|
|
1548
|
+
- Useful for request tracing and debugging
|
|
1549
|
+
|
|
1550
|
+
```ts
|
|
1551
|
+
import { FastMCP } from "fastmcp";
|
|
1552
|
+
import { z } from "zod";
|
|
1553
|
+
|
|
1554
|
+
const server = new FastMCP({
|
|
1555
|
+
name: "Session Counter Server",
|
|
1556
|
+
version: "1.0.0",
|
|
1557
|
+
});
|
|
1558
|
+
|
|
1559
|
+
// Per-session counter storage
|
|
1560
|
+
const sessionCounters = new Map<string, number>();
|
|
1561
|
+
|
|
1562
|
+
server.addTool({
|
|
1563
|
+
name: "increment_counter",
|
|
1564
|
+
description: "Increment a per-session counter",
|
|
1565
|
+
parameters: z.object({}),
|
|
1566
|
+
execute: async (args, context) => {
|
|
1567
|
+
if (!context.sessionId) {
|
|
1568
|
+
return "Session ID not available (requires HTTP transport)";
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
const counter = sessionCounters.get(context.sessionId) || 0;
|
|
1572
|
+
const newCounter = counter + 1;
|
|
1573
|
+
sessionCounters.set(context.sessionId, newCounter);
|
|
1574
|
+
|
|
1575
|
+
return `Counter for session ${context.sessionId}: ${newCounter}`;
|
|
1576
|
+
},
|
|
1577
|
+
});
|
|
1578
|
+
|
|
1579
|
+
server.addTool({
|
|
1580
|
+
name: "show_ids",
|
|
1581
|
+
description: "Display session and request IDs",
|
|
1582
|
+
parameters: z.object({}),
|
|
1583
|
+
execute: async (args, context) => {
|
|
1584
|
+
return `Session ID: ${context.sessionId || "N/A"}
|
|
1585
|
+
Request ID: ${context.requestId || "N/A"}`;
|
|
1586
|
+
},
|
|
1587
|
+
});
|
|
1588
|
+
|
|
1589
|
+
server.start({
|
|
1590
|
+
transportType: "httpStream",
|
|
1591
|
+
httpStream: {
|
|
1592
|
+
port: 8080,
|
|
1593
|
+
},
|
|
1594
|
+
});
|
|
1595
|
+
```
|
|
1596
|
+
|
|
1597
|
+
**Use Cases:**
|
|
1598
|
+
|
|
1599
|
+
- **Per-session state management**: Maintain counters, caches, or temporary data unique to each client session
|
|
1600
|
+
- **User authentication and authorization**: Track authenticated users across requests
|
|
1601
|
+
- **Session-specific resource management**: Allocate and manage resources per session
|
|
1602
|
+
- **Multi-tenant implementations**: Isolate data and operations by session
|
|
1603
|
+
- **Request tracing**: Track individual requests for debugging and monitoring
|
|
1604
|
+
|
|
1605
|
+
**Example:**
|
|
1606
|
+
|
|
1607
|
+
See [`src/examples/session-id-counter.ts`](src/examples/session-id-counter.ts) for a complete example demonstrating session-based counter management.
|
|
1608
|
+
|
|
1609
|
+
**Notes:**
|
|
1610
|
+
|
|
1611
|
+
- Session IDs are automatically generated by the MCP transport layer
|
|
1612
|
+
- In stateless mode, session IDs are not persisted across requests
|
|
1613
|
+
- For stdio transport, `sessionId` will be `undefined` as there's no HTTP session concept
|
|
1614
|
+
|
|
1532
1615
|
### Providing Instructions
|
|
1533
1616
|
|
|
1534
1617
|
You can provide instructions to the server using the `instructions` option:
|
package/dist/FastMCP.d.ts
CHANGED
|
@@ -62,7 +62,19 @@ type Context<T extends FastMCPSessionAuth> = {
|
|
|
62
62
|
warn: (message: string, data?: SerializableValue) => void;
|
|
63
63
|
};
|
|
64
64
|
reportProgress: (progress: Progress) => Promise<void>;
|
|
65
|
+
/**
|
|
66
|
+
* Request ID from the current MCP request.
|
|
67
|
+
* Available for all transports when the client provides it.
|
|
68
|
+
*/
|
|
69
|
+
requestId?: string;
|
|
65
70
|
session: T | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* Session ID from the Mcp-Session-Id header.
|
|
73
|
+
* Only available for HTTP-based transports (SSE, HTTP Stream).
|
|
74
|
+
* Can be used to track per-session state, implement session-specific
|
|
75
|
+
* counters, or maintain user-specific data across multiple requests.
|
|
76
|
+
*/
|
|
77
|
+
sessionId?: string;
|
|
66
78
|
streamContent: (content: Content | Content[]) => Promise<void>;
|
|
67
79
|
};
|
|
68
80
|
type Extra = unknown;
|
|
@@ -549,7 +561,9 @@ declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth>
|
|
|
549
561
|
get loggingLevel(): LoggingLevel;
|
|
550
562
|
get roots(): Root[];
|
|
551
563
|
get server(): Server;
|
|
552
|
-
|
|
564
|
+
get sessionId(): string | undefined;
|
|
565
|
+
set sessionId(value: string | undefined);
|
|
566
|
+
constructor({ auth, instructions, logger, name, ping, prompts, resources, resourcesTemplates, roots, sessionId, tools, transportType, utils, version, }: {
|
|
553
567
|
auth?: T;
|
|
554
568
|
instructions?: string;
|
|
555
569
|
logger: Logger;
|
|
@@ -559,6 +573,7 @@ declare class FastMCPSession<T extends FastMCPSessionAuth = FastMCPSessionAuth>
|
|
|
559
573
|
resources: Resource<T>[];
|
|
560
574
|
resourcesTemplates: InputResourceTemplate<T>[];
|
|
561
575
|
roots?: ServerOptions<T>["roots"];
|
|
576
|
+
sessionId?: string;
|
|
562
577
|
tools: Tool<T>[];
|
|
563
578
|
transportType?: "httpStream" | "stdio";
|
|
564
579
|
utils?: ServerOptions<T>["utils"];
|
package/dist/FastMCP.js
CHANGED
|
@@ -233,6 +233,12 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
233
233
|
get server() {
|
|
234
234
|
return this.#server;
|
|
235
235
|
}
|
|
236
|
+
get sessionId() {
|
|
237
|
+
return this.#sessionId;
|
|
238
|
+
}
|
|
239
|
+
set sessionId(value) {
|
|
240
|
+
this.#sessionId = value;
|
|
241
|
+
}
|
|
236
242
|
#auth;
|
|
237
243
|
#capabilities = {};
|
|
238
244
|
#clientCapabilities;
|
|
@@ -248,6 +254,11 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
248
254
|
#roots = [];
|
|
249
255
|
#rootsConfig;
|
|
250
256
|
#server;
|
|
257
|
+
/**
|
|
258
|
+
* Session ID from the Mcp-Session-Id header (HTTP transports only).
|
|
259
|
+
* Used to track per-session state across multiple requests.
|
|
260
|
+
*/
|
|
261
|
+
#sessionId;
|
|
251
262
|
#utils;
|
|
252
263
|
constructor({
|
|
253
264
|
auth,
|
|
@@ -259,6 +270,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
259
270
|
resources,
|
|
260
271
|
resourcesTemplates,
|
|
261
272
|
roots,
|
|
273
|
+
sessionId,
|
|
262
274
|
tools,
|
|
263
275
|
transportType,
|
|
264
276
|
utils,
|
|
@@ -269,6 +281,7 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
269
281
|
this.#logger = logger;
|
|
270
282
|
this.#pingConfig = ping;
|
|
271
283
|
this.#rootsConfig = roots;
|
|
284
|
+
this.#sessionId = sessionId;
|
|
272
285
|
this.#needsEventLoopFlush = transportType === "httpStream";
|
|
273
286
|
if (tools.length) {
|
|
274
287
|
this.#capabilities.tools = {};
|
|
@@ -329,6 +342,12 @@ var FastMCPSession = class extends FastMCPSessionEventEmitter {
|
|
|
329
342
|
this.#connectionState = "connecting";
|
|
330
343
|
try {
|
|
331
344
|
await this.#server.connect(transport);
|
|
345
|
+
if ("sessionId" in transport) {
|
|
346
|
+
const transportWithSessionId = transport;
|
|
347
|
+
if (typeof transportWithSessionId.sessionId === "string") {
|
|
348
|
+
this.#sessionId = transportWithSessionId.sessionId;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
332
351
|
let attempt = 0;
|
|
333
352
|
const maxAttempts = 10;
|
|
334
353
|
const retryDelay = 100;
|
|
@@ -900,7 +919,9 @@ ${error instanceof Error ? error.stack : JSON.stringify(error)}`
|
|
|
900
919
|
},
|
|
901
920
|
log,
|
|
902
921
|
reportProgress,
|
|
922
|
+
requestId: typeof request.params?._meta?.requestId === "string" ? request.params._meta.requestId : void 0,
|
|
903
923
|
session: this.#auth,
|
|
924
|
+
sessionId: this.#sessionId,
|
|
904
925
|
streamContent
|
|
905
926
|
});
|
|
906
927
|
const maybeStringResult = await (tool.timeoutMs ? Promise.race([
|
|
@@ -1125,7 +1146,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1125
1146
|
`[FastMCP info] Starting server in stateless mode on HTTP Stream at http://${httpConfig.host}:${httpConfig.port}${httpConfig.endpoint}`
|
|
1126
1147
|
);
|
|
1127
1148
|
this.#httpStreamServer = await startHTTPServer({
|
|
1128
|
-
authenticate: this.#authenticate,
|
|
1149
|
+
...this.#authenticate ? { authenticate: this.#authenticate } : {},
|
|
1129
1150
|
createServer: async (request) => {
|
|
1130
1151
|
let auth;
|
|
1131
1152
|
if (this.#authenticate) {
|
|
@@ -1134,7 +1155,8 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1134
1155
|
throw new Error("Authentication required");
|
|
1135
1156
|
}
|
|
1136
1157
|
}
|
|
1137
|
-
|
|
1158
|
+
const sessionId = Array.isArray(request.headers["mcp-session-id"]) ? request.headers["mcp-session-id"][0] : request.headers["mcp-session-id"];
|
|
1159
|
+
return this.#createSession(auth, sessionId);
|
|
1138
1160
|
},
|
|
1139
1161
|
enableJsonResponse: httpConfig.enableJsonResponse,
|
|
1140
1162
|
eventStore: httpConfig.eventStore,
|
|
@@ -1156,13 +1178,14 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1156
1178
|
});
|
|
1157
1179
|
} else {
|
|
1158
1180
|
this.#httpStreamServer = await startHTTPServer({
|
|
1159
|
-
authenticate: this.#authenticate,
|
|
1181
|
+
...this.#authenticate ? { authenticate: this.#authenticate } : {},
|
|
1160
1182
|
createServer: async (request) => {
|
|
1161
1183
|
let auth;
|
|
1162
1184
|
if (this.#authenticate) {
|
|
1163
1185
|
auth = await this.#authenticate(request);
|
|
1164
1186
|
}
|
|
1165
|
-
|
|
1187
|
+
const sessionId = Array.isArray(request.headers["mcp-session-id"]) ? request.headers["mcp-session-id"][0] : request.headers["mcp-session-id"];
|
|
1188
|
+
return this.#createSession(auth, sessionId);
|
|
1166
1189
|
},
|
|
1167
1190
|
enableJsonResponse: httpConfig.enableJsonResponse,
|
|
1168
1191
|
eventStore: httpConfig.eventStore,
|
|
@@ -1213,7 +1236,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1213
1236
|
* Creates a new FastMCPSession instance with the current configuration.
|
|
1214
1237
|
* Used both for regular sessions and stateless requests.
|
|
1215
1238
|
*/
|
|
1216
|
-
#createSession(auth) {
|
|
1239
|
+
#createSession(auth, sessionId) {
|
|
1217
1240
|
if (auth && typeof auth === "object" && "authenticated" in auth && !auth.authenticated) {
|
|
1218
1241
|
const errorMessage = "error" in auth && typeof auth.error === "string" ? auth.error : "Authentication failed";
|
|
1219
1242
|
throw new Error(errorMessage);
|
|
@@ -1231,6 +1254,7 @@ var FastMCP = class extends FastMCPEventEmitter {
|
|
|
1231
1254
|
resources: this.#resources,
|
|
1232
1255
|
resourcesTemplates: this.#resourcesTemplates,
|
|
1233
1256
|
roots: this.#options.roots,
|
|
1257
|
+
sessionId,
|
|
1234
1258
|
tools: allowedTools,
|
|
1235
1259
|
transportType: "httpStream",
|
|
1236
1260
|
utils: this.#options.utils,
|