Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/test/mcp/src/inMemoryEventStore.ts
3520 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
import { EventStore } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
6
import { JSONRPCMessage } from '@modelcontextprotocol/sdk/types.js';
7
8
/**
9
* Simple in-memory implementation of the EventStore interface for resumability
10
* This is primarily intended for examples and testing, not for production use
11
* where a persistent storage solution would be more appropriate.
12
*/
13
export class InMemoryEventStore implements EventStore {
14
private events: Map<string, { streamId: string; message: JSONRPCMessage }> = new Map();
15
16
/**
17
* Generates a unique event ID for a given stream ID
18
*/
19
private generateEventId(streamId: string): string {
20
return `${streamId}_${Date.now()}_${Math.random().toString(36).substring(2, 10)}`;
21
}
22
23
/**
24
* Extracts the stream ID from an event ID
25
*/
26
private getStreamIdFromEventId(eventId: string): string {
27
const parts = eventId.split('_');
28
return parts.length > 0 ? parts[0] : '';
29
}
30
31
/**
32
* Stores an event with a generated event ID
33
* Implements EventStore.storeEvent
34
*/
35
async storeEvent(streamId: string, message: JSONRPCMessage): Promise<string> {
36
const eventId = this.generateEventId(streamId);
37
this.events.set(eventId, { streamId, message });
38
return eventId;
39
}
40
41
/**
42
* Replays events that occurred after a specific event ID
43
* Implements EventStore.replayEventsAfter
44
*/
45
async replayEventsAfter(lastEventId: string,
46
{ send }: { send: (eventId: string, message: JSONRPCMessage) => Promise<void> }
47
): Promise<string> {
48
if (!lastEventId || !this.events.has(lastEventId)) {
49
return '';
50
}
51
52
// Extract the stream ID from the event ID
53
const streamId = this.getStreamIdFromEventId(lastEventId);
54
if (!streamId) {
55
return '';
56
}
57
58
let foundLastEvent = false;
59
60
// Sort events by eventId for chronological ordering
61
const sortedEvents = [...this.events.entries()].sort((a, b) => a[0].localeCompare(b[0]));
62
63
for (const [eventId, { streamId: eventStreamId, message }] of sortedEvents) {
64
// Only include events from the same stream
65
if (eventStreamId !== streamId) {
66
continue;
67
}
68
69
// Start sending events after we find the lastEventId
70
if (eventId === lastEventId) {
71
foundLastEvent = true;
72
continue;
73
}
74
75
if (foundLastEvent) {
76
await send(eventId, message);
77
}
78
}
79
return streamId;
80
}
81
}
82
83