@karashiiro/mcp 0.3.0 → 0.4.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 +15 -21
- package/dist/event-store.d.ts +26 -0
- package/dist/event-store.d.ts.map +1 -1
- package/dist/event-store.js +37 -0
- package/dist/event-store.js.map +1 -1
- package/dist/http.d.ts +22 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +116 -3
- package/dist/http.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -32,13 +32,9 @@ function createServer() {
|
|
|
32
32
|
version: "1.0.0",
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
server.registerTool(
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
async () => ({
|
|
39
|
-
content: [{ type: "text", text: "Hello from MCP!" }],
|
|
40
|
-
}),
|
|
41
|
-
);
|
|
35
|
+
server.registerTool("hello", { description: "Says hello" }, async () => ({
|
|
36
|
+
content: [{ type: "text", text: "Hello from MCP!" }],
|
|
37
|
+
}));
|
|
42
38
|
|
|
43
39
|
return server;
|
|
44
40
|
}
|
|
@@ -60,13 +56,9 @@ function createServer() {
|
|
|
60
56
|
version: "1.0.0",
|
|
61
57
|
});
|
|
62
58
|
|
|
63
|
-
server.registerTool(
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
async () => ({
|
|
67
|
-
content: [{ type: "text", text: "Hello from MCP!" }],
|
|
68
|
-
}),
|
|
69
|
-
);
|
|
59
|
+
server.registerTool("hello", { description: "Says hello" }, async () => ({
|
|
60
|
+
content: [{ type: "text", text: "Hello from MCP!" }],
|
|
61
|
+
}));
|
|
70
62
|
|
|
71
63
|
return server;
|
|
72
64
|
}
|
|
@@ -151,7 +143,7 @@ const handle = await serveHttp(createServer, {
|
|
|
151
143
|
port: 8080,
|
|
152
144
|
sessions: {
|
|
153
145
|
legacySse: {
|
|
154
|
-
sseEndpoint: "/sse",
|
|
146
|
+
sseEndpoint: "/sse", // default: "/sse"
|
|
155
147
|
messagesEndpoint: "/messages", // default: "/messages"
|
|
156
148
|
},
|
|
157
149
|
},
|
|
@@ -162,11 +154,11 @@ const handle = await serveHttp(createServer, {
|
|
|
162
154
|
|
|
163
155
|
This package provides multiple entry points for optimal bundle size:
|
|
164
156
|
|
|
165
|
-
| Entry Point
|
|
166
|
-
|
|
167
|
-
| `@karashiiro/mcp`
|
|
168
|
-
| `@karashiiro/mcp/stdio` | Stdio transport only
|
|
169
|
-
| `@karashiiro/mcp/http`
|
|
157
|
+
| Entry Point | Description | Requires Hono |
|
|
158
|
+
| ----------------------- | --------------------------- | ------------- |
|
|
159
|
+
| `@karashiiro/mcp` | Everything (re-exports all) | Yes |
|
|
160
|
+
| `@karashiiro/mcp/stdio` | Stdio transport only | No |
|
|
161
|
+
| `@karashiiro/mcp/http` | HTTP transport only | Yes |
|
|
170
162
|
|
|
171
163
|
If you only need stdio transport, import from `@karashiiro/mcp/stdio` to avoid bundling Hono.
|
|
172
164
|
|
|
@@ -181,7 +173,9 @@ The library provides two factory types for type-safe server creation:
|
|
|
181
173
|
type StatelessServerFactory = () => McpServer | Promise<McpServer>;
|
|
182
174
|
|
|
183
175
|
// For stateful mode (serveHttp with sessions)
|
|
184
|
-
type StatefulServerFactory = (
|
|
176
|
+
type StatefulServerFactory = (
|
|
177
|
+
sessionId: string,
|
|
178
|
+
) => McpServer | Promise<McpServer>;
|
|
185
179
|
```
|
|
186
180
|
|
|
187
181
|
Both factory types support async initialization by returning a `Promise<McpServer>`.
|
package/dist/event-store.d.ts
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
import type { EventStore } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
2
2
|
import type { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Options for configuring the in-memory event store.
|
|
5
|
+
*/
|
|
6
|
+
export interface InMemoryEventStoreOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Maximum number of events to store per stream.
|
|
9
|
+
* When exceeded, oldest events are evicted (FIFO).
|
|
10
|
+
* Defaults to undefined (no limit).
|
|
11
|
+
*/
|
|
12
|
+
maxEventsPerStream?: number;
|
|
13
|
+
}
|
|
3
14
|
/**
|
|
4
15
|
* In-memory event store for SSE resumability.
|
|
5
16
|
* Stores events in memory and allows replaying them from a specific point.
|
|
@@ -7,7 +18,22 @@ import type { JSONRPCMessage } from "@modelcontextprotocol/sdk/types.js";
|
|
|
7
18
|
*/
|
|
8
19
|
export declare class InMemoryEventStore implements EventStore {
|
|
9
20
|
private events;
|
|
21
|
+
private readonly maxEventsPerStream;
|
|
22
|
+
constructor(options?: InMemoryEventStoreOptions);
|
|
10
23
|
storeEvent(streamId: string, message: JSONRPCMessage): Promise<string>;
|
|
24
|
+
/**
|
|
25
|
+
* Evict oldest events for a stream if it exceeds maxEventsPerStream.
|
|
26
|
+
*/
|
|
27
|
+
private evictOldestIfNeeded;
|
|
28
|
+
/**
|
|
29
|
+
* Clear all events from the store.
|
|
30
|
+
* Call this when the session is being deleted.
|
|
31
|
+
*/
|
|
32
|
+
clear(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Get the current number of events stored.
|
|
35
|
+
*/
|
|
36
|
+
get size(): number;
|
|
11
37
|
replayEventsAfter(lastEventId: string, { send }: {
|
|
12
38
|
send: (eventId: string, message: JSONRPCMessage) => Promise<void>;
|
|
13
39
|
}): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-store.d.ts","sourceRoot":"","sources":["../src/event-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+DAA+D,CAAC;AAChG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,UAAU;IACnD,OAAO,CAAC,MAAM,CAGV;
|
|
1
|
+
{"version":3,"file":"event-store.d.ts","sourceRoot":"","sources":["../src/event-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+DAA+D,CAAC;AAChG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;GAIG;AACH,qBAAa,kBAAmB,YAAW,UAAU;IACnD,OAAO,CAAC,MAAM,CAGV;IACJ,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAqB;IAExD,YAAY,OAAO,GAAE,yBAA8B,EAElD;IAEK,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAU3E;IAED;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAe3B;;;OAGG;IACH,KAAK,IAAI,IAAI,CAEZ;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,iBAAiB,CACrB,WAAW,EAAE,MAAM,EACnB,EACE,IAAI,EACL,EAAE;QAAE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,GACvE,OAAO,CAAC,MAAM,CAAC,CA2BjB;CACF"}
|
package/dist/event-store.js
CHANGED
|
@@ -5,11 +5,48 @@
|
|
|
5
5
|
*/
|
|
6
6
|
export class InMemoryEventStore {
|
|
7
7
|
events = new Map();
|
|
8
|
+
maxEventsPerStream;
|
|
9
|
+
constructor(options = {}) {
|
|
10
|
+
this.maxEventsPerStream = options.maxEventsPerStream;
|
|
11
|
+
}
|
|
8
12
|
async storeEvent(streamId, message) {
|
|
9
13
|
const eventId = `${streamId}_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
10
14
|
this.events.set(eventId, { streamId, message });
|
|
15
|
+
// Evict oldest events if limit exceeded
|
|
16
|
+
if (this.maxEventsPerStream !== undefined) {
|
|
17
|
+
this.evictOldestIfNeeded(streamId);
|
|
18
|
+
}
|
|
11
19
|
return eventId;
|
|
12
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Evict oldest events for a stream if it exceeds maxEventsPerStream.
|
|
23
|
+
*/
|
|
24
|
+
evictOldestIfNeeded(streamId) {
|
|
25
|
+
if (this.maxEventsPerStream === undefined)
|
|
26
|
+
return;
|
|
27
|
+
// Get all events for this stream, sorted by ID (contains timestamp)
|
|
28
|
+
const streamEvents = Array.from(this.events.entries())
|
|
29
|
+
.filter(([, event]) => event.streamId === streamId)
|
|
30
|
+
.sort(([a], [b]) => a.localeCompare(b));
|
|
31
|
+
// Remove oldest events until we're under the limit
|
|
32
|
+
while (streamEvents.length > this.maxEventsPerStream) {
|
|
33
|
+
const [oldestId] = streamEvents.shift();
|
|
34
|
+
this.events.delete(oldestId);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Clear all events from the store.
|
|
39
|
+
* Call this when the session is being deleted.
|
|
40
|
+
*/
|
|
41
|
+
clear() {
|
|
42
|
+
this.events.clear();
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the current number of events stored.
|
|
46
|
+
*/
|
|
47
|
+
get size() {
|
|
48
|
+
return this.events.size;
|
|
49
|
+
}
|
|
13
50
|
async replayEventsAfter(lastEventId, { send, }) {
|
|
14
51
|
const lastEvent = this.events.get(lastEventId);
|
|
15
52
|
if (!lastEvent) {
|
package/dist/event-store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"event-store.js","sourceRoot":"","sources":["../src/event-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"event-store.js","sourceRoot":"","sources":["../src/event-store.ts"],"names":[],"mappings":"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"}
|
package/dist/http.d.ts
CHANGED
|
@@ -13,6 +13,28 @@ export interface LegacySseOptions {
|
|
|
13
13
|
}
|
|
14
14
|
export interface HttpServerSessionOptions {
|
|
15
15
|
sessionIdGenerator?: () => string;
|
|
16
|
+
/**
|
|
17
|
+
* Session time-to-live in milliseconds. Sessions without activity for this
|
|
18
|
+
* duration will be automatically cleaned up. Defaults to 30 minutes.
|
|
19
|
+
* Set to 0 or undefined to disable automatic cleanup.
|
|
20
|
+
*/
|
|
21
|
+
sessionTtlMs?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Interval in milliseconds for checking expired sessions.
|
|
24
|
+
* Defaults to 60000 (1 minute). Only used if sessionTtlMs is set.
|
|
25
|
+
*/
|
|
26
|
+
cleanupIntervalMs?: number;
|
|
27
|
+
/**
|
|
28
|
+
* Callback invoked when a session is closed.
|
|
29
|
+
* Called for all cleanup paths: TTL expiration, DELETE requests, transport close, and server shutdown.
|
|
30
|
+
* Useful for cleaning up session-scoped resources like database connections or client state.
|
|
31
|
+
*
|
|
32
|
+
* Note: In TTL cleanup, the callback is invoked but not awaited to avoid blocking the cleanup interval.
|
|
33
|
+
* In all other paths (DELETE, transport close, shutdown), async callbacks are awaited.
|
|
34
|
+
*
|
|
35
|
+
* @param sessionId - The ID of the session being closed
|
|
36
|
+
*/
|
|
37
|
+
onSessionClosed?: (sessionId: string) => void | Promise<void>;
|
|
16
38
|
/**
|
|
17
39
|
* Enable legacy SSE transport compatibility.
|
|
18
40
|
* When provided, adds /sse and /messages endpoints for older clients.
|
package/dist/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,wBAAwB;IACvC,kBAAkB,CAAC,EAAE,MAAM,MAAM,CAAC;IAClC;;;;OAIG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA2B,SAAQ,qBAAqB;IACvE,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,qBAAqB;IACtE,QAAQ,EAAE,wBAAwB,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,0BAA0B,GAC1B,yBAAyB,CAAC;
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,EACtB,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,YAAY,EACZ,sBAAsB,EACtB,qBAAqB,GACtB,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,wBAAwB;IACvC,kBAAkB,CAAC,EAAE,MAAM,MAAM,CAAC;IAClC;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;OASG;IACH,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D;;;;OAIG;IACH,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,0BAA2B,SAAQ,qBAAqB;IACvE,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;GAEG;AACH,MAAM,WAAW,yBAA0B,SAAQ,qBAAqB;IACtE,QAAQ,EAAE,wBAAwB,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GACzB,0BAA0B,GAC1B,yBAAyB,CAAC;AAyD9B;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,aAAa,EAAE,sBAAsB,EACrC,OAAO,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,qBAAqB,EAAE,UAAU,CAAC,CAAC,GAAG;IAC3D,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB,GACA,OAAO,CAAC,YAAY,CAAC,CAAC;AAEzB;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CACvB,aAAa,EAAE,qBAAqB,EACpC,OAAO,EAAE,OAAO,CAAC,qBAAqB,CAAC,GAAG;IACxC,QAAQ,EAAE,wBAAwB,CAAC;CACpC,GACA,OAAO,CAAC,YAAY,CAAC,CAAC"}
|
package/dist/http.js
CHANGED
|
@@ -70,6 +70,63 @@ async function serveHttpStateless(serverFactory, options) {
|
|
|
70
70
|
function serveHttpStateful(serverFactory, options) {
|
|
71
71
|
const sessions = new Map();
|
|
72
72
|
const sessionIdGenerator = options.sessions.sessionIdGenerator ?? uuidv4;
|
|
73
|
+
const onSessionClosed = options.sessions.onSessionClosed;
|
|
74
|
+
// Helper to safely invoke onSessionClosed callback
|
|
75
|
+
// Catches errors to prevent user code from breaking cleanup
|
|
76
|
+
const notifySessionClosed = (sessionId) => {
|
|
77
|
+
if (onSessionClosed) {
|
|
78
|
+
try {
|
|
79
|
+
// Fire and forget - don't await to avoid blocking
|
|
80
|
+
// Errors are caught and ignored to prevent breaking cleanup
|
|
81
|
+
Promise.resolve(onSessionClosed(sessionId)).catch(() => {
|
|
82
|
+
// Ignore errors from user callback
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Ignore synchronous errors from user callback
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
// Async version for paths where we can await
|
|
91
|
+
const notifySessionClosedAsync = async (sessionId) => {
|
|
92
|
+
if (onSessionClosed) {
|
|
93
|
+
try {
|
|
94
|
+
await onSessionClosed(sessionId);
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Ignore errors from user callback
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
// Session TTL configuration
|
|
102
|
+
const sessionTtlMs = options.sessions.sessionTtlMs;
|
|
103
|
+
const cleanupIntervalMs = options.sessions.cleanupIntervalMs ?? 60000; // Default 1 minute
|
|
104
|
+
// Set up periodic cleanup for expired sessions
|
|
105
|
+
let cleanupInterval;
|
|
106
|
+
if (sessionTtlMs && sessionTtlMs > 0) {
|
|
107
|
+
cleanupInterval = setInterval(() => {
|
|
108
|
+
const now = Date.now();
|
|
109
|
+
for (const [sessionId, session] of sessions) {
|
|
110
|
+
// Skip sessions with active streaming connections
|
|
111
|
+
if (session.activeStreams > 0) {
|
|
112
|
+
continue;
|
|
113
|
+
}
|
|
114
|
+
if (now - session.lastActivity > sessionTtlMs) {
|
|
115
|
+
// Session expired - close transport and remove
|
|
116
|
+
session.transport.close().catch(() => {
|
|
117
|
+
// Ignore close errors for expired sessions
|
|
118
|
+
});
|
|
119
|
+
// Clear event store if this is a streamable HTTP session
|
|
120
|
+
if (session.type === "streamable-http") {
|
|
121
|
+
session.eventStore.clear();
|
|
122
|
+
}
|
|
123
|
+
sessions.delete(sessionId);
|
|
124
|
+
// Notify callback (fire and forget to avoid blocking interval)
|
|
125
|
+
notifySessionClosed(sessionId);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}, cleanupIntervalMs);
|
|
129
|
+
}
|
|
73
130
|
// Legacy SSE options
|
|
74
131
|
const legacySse = options.sessions?.legacySse;
|
|
75
132
|
const sseEndpoint = legacySse?.sseEndpoint ?? "/sse";
|
|
@@ -79,6 +136,26 @@ function serveHttpStateful(serverFactory, options) {
|
|
|
79
136
|
// Main MCP endpoint (Streamable HTTP)
|
|
80
137
|
app.all(options.endpoint, async (c) => {
|
|
81
138
|
const sessionId = c.req.header("mcp-session-id");
|
|
139
|
+
// Handle DELETE method for session termination
|
|
140
|
+
if (c.req.method === "DELETE") {
|
|
141
|
+
if (!sessionId) {
|
|
142
|
+
return c.text("Session ID required for DELETE", 400);
|
|
143
|
+
}
|
|
144
|
+
const session = sessions.get(sessionId);
|
|
145
|
+
if (!session) {
|
|
146
|
+
return c.text("Session not found", 404);
|
|
147
|
+
}
|
|
148
|
+
// Close the transport and clean up
|
|
149
|
+
await session.transport.close();
|
|
150
|
+
// Clear event store if this is a streamable HTTP session
|
|
151
|
+
if (session.type === "streamable-http") {
|
|
152
|
+
session.eventStore.clear();
|
|
153
|
+
}
|
|
154
|
+
sessions.delete(sessionId);
|
|
155
|
+
// Notify callback (awaited since we're in async context)
|
|
156
|
+
await notifySessionClosedAsync(sessionId);
|
|
157
|
+
return c.body(null, 204);
|
|
158
|
+
}
|
|
82
159
|
// Clone the request so we can read the body without consuming it
|
|
83
160
|
const rawRequest = c.req.raw;
|
|
84
161
|
const bodyText = await rawRequest.text();
|
|
@@ -113,6 +190,8 @@ function serveHttpStateful(serverFactory, options) {
|
|
|
113
190
|
transport,
|
|
114
191
|
server,
|
|
115
192
|
eventStore,
|
|
193
|
+
lastActivity: Date.now(),
|
|
194
|
+
activeStreams: 0,
|
|
116
195
|
};
|
|
117
196
|
sessions.set(sid, session);
|
|
118
197
|
},
|
|
@@ -120,7 +199,10 @@ function serveHttpStateful(serverFactory, options) {
|
|
|
120
199
|
// Connect server to transport before handling the request
|
|
121
200
|
await server.connect(transport);
|
|
122
201
|
transport.onclose = () => {
|
|
202
|
+
eventStore.clear();
|
|
123
203
|
sessions.delete(sid);
|
|
204
|
+
// Notify callback (fire and forget since onclose is sync)
|
|
205
|
+
notifySessionClosed(sid);
|
|
124
206
|
};
|
|
125
207
|
return transport.handleRequest(recreateRequest());
|
|
126
208
|
}
|
|
@@ -141,6 +223,8 @@ function serveHttpStateful(serverFactory, options) {
|
|
|
141
223
|
id: null,
|
|
142
224
|
}, 400);
|
|
143
225
|
}
|
|
226
|
+
// Update last activity for TTL tracking
|
|
227
|
+
session.lastActivity = Date.now();
|
|
144
228
|
return session.transport.handleRequest(recreateRequest());
|
|
145
229
|
}
|
|
146
230
|
// Invalid request (no session ID, not an initialize request)
|
|
@@ -155,16 +239,21 @@ function serveHttpStateful(serverFactory, options) {
|
|
|
155
239
|
const transport = new SSEServerTransport(messagesEndpoint, outgoing);
|
|
156
240
|
// Create server with session ID (supports async factories)
|
|
157
241
|
const server = await serverFactory(transport.sessionId);
|
|
158
|
-
// Store session
|
|
242
|
+
// Store session - SSE connection counts as an active stream
|
|
159
243
|
const session = {
|
|
160
244
|
type: "sse",
|
|
161
245
|
transport,
|
|
162
246
|
server,
|
|
247
|
+
lastActivity: Date.now(),
|
|
248
|
+
activeStreams: 1, // SSE connection is an active stream
|
|
163
249
|
};
|
|
164
250
|
sessions.set(transport.sessionId, session);
|
|
165
|
-
// Cleanup on close
|
|
251
|
+
// Cleanup on close - SSE stream is no longer active
|
|
166
252
|
transport.onclose = () => {
|
|
253
|
+
session.activeStreams = 0;
|
|
167
254
|
sessions.delete(transport.sessionId);
|
|
255
|
+
// Notify callback (fire and forget since onclose is sync)
|
|
256
|
+
notifySessionClosed(transport.sessionId);
|
|
168
257
|
};
|
|
169
258
|
// Connect and start
|
|
170
259
|
await server.connect(transport);
|
|
@@ -193,6 +282,8 @@ function serveHttpStateful(serverFactory, options) {
|
|
|
193
282
|
}, 400);
|
|
194
283
|
}
|
|
195
284
|
const { incoming, outgoing } = c.env;
|
|
285
|
+
// Update last activity for TTL tracking
|
|
286
|
+
session.lastActivity = Date.now();
|
|
196
287
|
// Parse body for SSEServerTransport
|
|
197
288
|
const bodyText = await c.req.text();
|
|
198
289
|
let parsedBody = null;
|
|
@@ -211,7 +302,29 @@ function serveHttpStateful(serverFactory, options) {
|
|
|
211
302
|
port: options.port,
|
|
212
303
|
hostname: options.host,
|
|
213
304
|
});
|
|
214
|
-
|
|
305
|
+
// Create handle that also clears the cleanup interval
|
|
306
|
+
const baseHandle = createHandle(httpServer);
|
|
307
|
+
return {
|
|
308
|
+
close: async () => {
|
|
309
|
+
if (cleanupInterval) {
|
|
310
|
+
clearInterval(cleanupInterval);
|
|
311
|
+
}
|
|
312
|
+
// Close all active sessions and clear their event stores
|
|
313
|
+
for (const [sessionId, session] of sessions) {
|
|
314
|
+
await session.transport.close().catch(() => {
|
|
315
|
+
// Ignore close errors during shutdown
|
|
316
|
+
});
|
|
317
|
+
// Clear event store if this is a streamable HTTP session
|
|
318
|
+
if (session.type === "streamable-http") {
|
|
319
|
+
session.eventStore.clear();
|
|
320
|
+
}
|
|
321
|
+
// Notify callback (awaited since we're in async shutdown)
|
|
322
|
+
await notifySessionClosedAsync(sessionId);
|
|
323
|
+
}
|
|
324
|
+
sessions.clear();
|
|
325
|
+
await baseHandle.close();
|
|
326
|
+
},
|
|
327
|
+
};
|
|
215
328
|
}
|
|
216
329
|
function addCors(app) {
|
|
217
330
|
// Enable CORS for all origins
|
package/dist/http.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAmB,MAAM,mBAAmB,CAAC;AAE3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AAEzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAC;AAC7E,OAAO,EAAE,wCAAwC,EAAE,MAAM,+DAA+D,CAAC;AACzH,OAAO,EAAE,mBAAmB,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../src/http.ts"],"names":[],"mappings":"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"}
|