sensorium-mcp 2.15.3 → 2.16.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.
Files changed (37) hide show
  1. package/dist/http-server.d.ts +16 -0
  2. package/dist/http-server.d.ts.map +1 -0
  3. package/dist/http-server.js +248 -0
  4. package/dist/http-server.js.map +1 -0
  5. package/dist/index.js +133 -1988
  6. package/dist/index.js.map +1 -1
  7. package/dist/response-builders.d.ts +34 -0
  8. package/dist/response-builders.d.ts.map +1 -0
  9. package/dist/response-builders.js +114 -0
  10. package/dist/response-builders.js.map +1 -0
  11. package/dist/stdio-server.d.ts +8 -0
  12. package/dist/stdio-server.d.ts.map +1 -0
  13. package/dist/stdio-server.js +23 -0
  14. package/dist/stdio-server.js.map +1 -0
  15. package/dist/tools/memory-tools.d.ts +36 -0
  16. package/dist/tools/memory-tools.d.ts.map +1 -0
  17. package/dist/tools/memory-tools.js +352 -0
  18. package/dist/tools/memory-tools.js.map +1 -0
  19. package/dist/tools/session-tools.d.ts +46 -0
  20. package/dist/tools/session-tools.d.ts.map +1 -0
  21. package/dist/tools/session-tools.js +255 -0
  22. package/dist/tools/session-tools.js.map +1 -0
  23. package/dist/tools/start-session-tool.d.ts +43 -0
  24. package/dist/tools/start-session-tool.d.ts.map +1 -0
  25. package/dist/tools/start-session-tool.js +188 -0
  26. package/dist/tools/start-session-tool.js.map +1 -0
  27. package/dist/tools/utility-tools.d.ts +34 -0
  28. package/dist/tools/utility-tools.d.ts.map +1 -0
  29. package/dist/tools/utility-tools.js +256 -0
  30. package/dist/tools/utility-tools.js.map +1 -0
  31. package/dist/tools/wait-tool.d.ts +69 -0
  32. package/dist/tools/wait-tool.d.ts.map +1 -0
  33. package/dist/tools/wait-tool.js +702 -0
  34. package/dist/tools/wait-tool.js.map +1 -0
  35. package/dist/types.d.ts +2 -0
  36. package/dist/types.d.ts.map +1 -1
  37. package/package.json +1 -1
@@ -0,0 +1,16 @@
1
+ /**
2
+ * HTTP/SSE transport bootstrap for the MCP server.
3
+ *
4
+ * Handles:
5
+ * - HTTP server creation with all routes (POST/GET/DELETE /mcp)
6
+ * - CORS handling
7
+ * - Dashboard routing
8
+ * - Auth checking (MCP_HTTP_SECRET)
9
+ * - Session management (transports map, activity tracking)
10
+ * - Session reaper interval
11
+ * - Graceful shutdown (SIGINT/SIGTERM/SIGBREAK)
12
+ */
13
+ import type { Database } from "better-sqlite3";
14
+ import type { CreateMcpServerFn } from "./types.js";
15
+ export declare function startHttpServer(createMcpServerFn: CreateMcpServerFn, getMemoryDb: () => Database, closeMemoryDb: () => void): void;
16
+ //# sourceMappingURL=http-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server.d.ts","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAO/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,wBAAgB,eAAe,CAC7B,iBAAiB,EAAE,iBAAiB,EACpC,WAAW,EAAE,MAAM,QAAQ,EAC3B,aAAa,EAAE,MAAM,IAAI,GACxB,IAAI,CAmON"}
@@ -0,0 +1,248 @@
1
+ /**
2
+ * HTTP/SSE transport bootstrap for the MCP server.
3
+ *
4
+ * Handles:
5
+ * - HTTP server creation with all routes (POST/GET/DELETE /mcp)
6
+ * - CORS handling
7
+ * - Dashboard routing
8
+ * - Auth checking (MCP_HTTP_SECRET)
9
+ * - Session management (transports map, activity tracking)
10
+ * - Session reaper interval
11
+ * - Graceful shutdown (SIGINT/SIGTERM/SIGBREAK)
12
+ */
13
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
14
+ import { isInitializeRequest } from "@modelcontextprotocol/sdk/types.js";
15
+ import { randomUUID, timingSafeEqual } from "node:crypto";
16
+ import { createServer } from "node:http";
17
+ import { config } from "./config.js";
18
+ import { handleDashboardRequest } from "./dashboard.js";
19
+ import { rateLimiter } from "./rate-limiter.js";
20
+ import { threadSessionRegistry } from "./sessions.js";
21
+ export function startHttpServer(createMcpServerFn, getMemoryDb, closeMemoryDb) {
22
+ const httpPort = parseInt(process.env.MCP_HTTP_PORT, 10);
23
+ const httpBind = process.env.MCP_HTTP_BIND ?? "127.0.0.1";
24
+ const transports = new Map();
25
+ /** Tracks the last time each HTTP session received any request (epoch ms). */
26
+ const sessionLastActivity = new Map();
27
+ const MCP_HTTP_SECRET = process.env.MCP_HTTP_SECRET;
28
+ const MAX_BODY_SIZE = 10 * 1024 * 1024; // 10MB
29
+ const serverStartTime = Date.now();
30
+ async function parseBody(req) {
31
+ return new Promise((resolve, reject) => {
32
+ const chunks = [];
33
+ let totalSize = 0;
34
+ req.on("data", (c) => {
35
+ totalSize += c.length;
36
+ if (totalSize > MAX_BODY_SIZE) {
37
+ req.destroy();
38
+ reject(new Error("Request body too large"));
39
+ return;
40
+ }
41
+ chunks.push(c);
42
+ });
43
+ req.on("end", () => {
44
+ try {
45
+ resolve(JSON.parse(Buffer.concat(chunks).toString()));
46
+ }
47
+ catch (e) {
48
+ reject(e);
49
+ }
50
+ });
51
+ req.on("error", reject);
52
+ });
53
+ }
54
+ const httpServer = createServer(async (req, res) => {
55
+ try {
56
+ // CORS for local dev (restrict to localhost)
57
+ const origin = req.headers.origin ?? "";
58
+ const allowedOrigin = origin.match(/^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/) ? origin : "";
59
+ res.setHeader("Access-Control-Allow-Origin", allowedOrigin);
60
+ res.setHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, OPTIONS");
61
+ res.setHeader("Access-Control-Allow-Headers", "Content-Type, mcp-session-id, Authorization");
62
+ res.setHeader("Access-Control-Expose-Headers", "mcp-session-id");
63
+ if (req.method === "OPTIONS") {
64
+ res.writeHead(204);
65
+ res.end();
66
+ return;
67
+ }
68
+ // ── Dashboard routes (served before MCP auth) ─────────────────────
69
+ const dashCtx = {
70
+ getDb: getMemoryDb,
71
+ getActiveSessions: () => {
72
+ const sessions = [];
73
+ for (const [sid, _transport] of transports) {
74
+ // Find which thread this session belongs to
75
+ let threadId = 0;
76
+ for (const [tid, entries] of threadSessionRegistry) {
77
+ if (entries.some(e => e.mcpSessionId === sid)) {
78
+ threadId = tid;
79
+ break;
80
+ }
81
+ }
82
+ sessions.push({
83
+ threadId,
84
+ mcpSessionId: sid,
85
+ lastActivity: sessionLastActivity.get(sid) ?? 0,
86
+ transportType: "http",
87
+ });
88
+ }
89
+ return sessions;
90
+ },
91
+ serverStartTime,
92
+ };
93
+ // Dashboard HTML pages: no auth needed (SPA handles auth in browser)
94
+ // Dashboard API routes: auth handled by handleDashboardRequest internally
95
+ const dashUrl = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
96
+ const isDashboardPage = dashUrl.pathname === "/" || dashUrl.pathname === "/dashboard";
97
+ const isDashboardApi = dashUrl.pathname.startsWith("/api/");
98
+ if (isDashboardPage || isDashboardApi) {
99
+ const handled = handleDashboardRequest(req, res, dashCtx, MCP_HTTP_SECRET);
100
+ if (handled)
101
+ return;
102
+ }
103
+ // Auth check — if MCP_HTTP_SECRET is set, require Bearer token.
104
+ // Use constant-time comparison to prevent timing attacks.
105
+ if (MCP_HTTP_SECRET) {
106
+ const auth = req.headers.authorization ?? "";
107
+ const expected = `Bearer ${MCP_HTTP_SECRET}`;
108
+ const authBuf = Buffer.from(auth);
109
+ const expectedBuf = Buffer.from(expected);
110
+ if (authBuf.length !== expectedBuf.length || !timingSafeEqual(authBuf, expectedBuf)) {
111
+ res.writeHead(401, { "Content-Type": "application/json" });
112
+ res.end(JSON.stringify({ error: "Unauthorized" }));
113
+ return;
114
+ }
115
+ }
116
+ if (req.url !== "/mcp") {
117
+ res.writeHead(404, { "Content-Type": "text/plain" });
118
+ res.end("Not Found");
119
+ return;
120
+ }
121
+ const sessionId = req.headers["mcp-session-id"];
122
+ if (req.method === "POST") {
123
+ let body;
124
+ try {
125
+ body = await parseBody(req);
126
+ }
127
+ catch {
128
+ res.writeHead(413, { "Content-Type": "text/plain" });
129
+ res.end("Request body too large or malformed");
130
+ return;
131
+ }
132
+ // Existing session
133
+ if (sessionId && transports.has(sessionId)) {
134
+ sessionLastActivity.set(sessionId, Date.now());
135
+ await transports.get(sessionId).handleRequest(req, res, body);
136
+ return;
137
+ }
138
+ // New session — must be initialize
139
+ if (!sessionId && isInitializeRequest(body)) {
140
+ let capturedSid;
141
+ const transport = new StreamableHTTPServerTransport({
142
+ sessionIdGenerator: () => randomUUID(),
143
+ onsessioninitialized: (sid) => {
144
+ capturedSid = sid;
145
+ transports.set(sid, transport);
146
+ sessionLastActivity.set(sid, Date.now());
147
+ },
148
+ });
149
+ transport.onclose = () => {
150
+ const sid = transport.sessionId;
151
+ if (sid) {
152
+ transports.delete(sid);
153
+ sessionLastActivity.delete(sid);
154
+ rateLimiter.removeSession(sid);
155
+ }
156
+ };
157
+ // Create a fresh Server per HTTP session — a single Server can only
158
+ // connect to one transport, so concurrent clients each need their own.
159
+ const sessionServer = createMcpServerFn(() => capturedSid, () => { try {
160
+ transport.close();
161
+ }
162
+ catch (_) { /* best-effort */ } });
163
+ await sessionServer.connect(transport);
164
+ await transport.handleRequest(req, res, body);
165
+ return;
166
+ }
167
+ res.writeHead(400, { "Content-Type": "application/json" });
168
+ res.end(JSON.stringify({
169
+ jsonrpc: "2.0",
170
+ error: { code: -32000, message: "Bad Request: No valid session ID or not an initialize request" },
171
+ id: null,
172
+ }));
173
+ return;
174
+ }
175
+ if (req.method === "GET") {
176
+ if (!sessionId || !transports.has(sessionId)) {
177
+ res.writeHead(400, { "Content-Type": "text/plain" });
178
+ res.end("Invalid or missing session ID");
179
+ return;
180
+ }
181
+ sessionLastActivity.set(sessionId, Date.now());
182
+ await transports.get(sessionId).handleRequest(req, res);
183
+ return;
184
+ }
185
+ if (req.method === "DELETE") {
186
+ if (!sessionId || !transports.has(sessionId)) {
187
+ res.writeHead(400, { "Content-Type": "text/plain" });
188
+ res.end("Invalid or missing session ID");
189
+ return;
190
+ }
191
+ sessionLastActivity.set(sessionId, Date.now());
192
+ await transports.get(sessionId).handleRequest(req, res);
193
+ return;
194
+ }
195
+ res.writeHead(405, { "Content-Type": "text/plain" });
196
+ res.end("Method Not Allowed");
197
+ }
198
+ catch (err) {
199
+ process.stderr.write(`[http] Unhandled error: ${typeof err === 'object' && err !== null && 'message' in err ? err.message : String(err)}\n`);
200
+ if (!res.headersSent) {
201
+ res.writeHead(500, { "Content-Type": "application/json" });
202
+ res.end(JSON.stringify({ jsonrpc: "2.0", error: { code: -32603, message: "Internal error" }, id: null }));
203
+ }
204
+ }
205
+ });
206
+ httpServer.listen(httpPort, httpBind, () => {
207
+ process.stderr.write(`Remote Copilot MCP server running on http://${httpBind}:${httpPort}/mcp\n`);
208
+ });
209
+ // ── Session reaper — close abandoned SSE sessions every 10 minutes ──────
210
+ const STALE_SESSION_MS = 2 * config.WAIT_TIMEOUT_MINUTES * 60 * 1000;
211
+ const sessionReaperInterval = setInterval(() => {
212
+ const now = Date.now();
213
+ for (const [sid, transport] of transports) {
214
+ const lastActive = sessionLastActivity.get(sid) ?? 0;
215
+ if (now - lastActive > STALE_SESSION_MS) {
216
+ process.stderr.write(`[session-reaper] Closing stale session ${sid} (idle ${Math.round((now - lastActive) / 60000)}m)\n`);
217
+ try {
218
+ transport.close();
219
+ }
220
+ catch (_) { /* best-effort */ }
221
+ transports.delete(sid);
222
+ sessionLastActivity.delete(sid);
223
+ rateLimiter.removeSession(sid);
224
+ }
225
+ }
226
+ }, 10 * 60 * 1000);
227
+ // Simple shutdown — close transports, DB, and exit.
228
+ const shutdown = () => {
229
+ clearInterval(sessionReaperInterval);
230
+ for (const [sid, t] of transports) {
231
+ try {
232
+ t.close();
233
+ }
234
+ catch (_) { /* best-effort */ }
235
+ transports.delete(sid);
236
+ }
237
+ httpServer.close();
238
+ closeMemoryDb();
239
+ process.exit(0);
240
+ };
241
+ process.on("SIGINT", shutdown);
242
+ process.on("SIGTERM", shutdown);
243
+ if (process.platform === "win32") {
244
+ process.on("SIGBREAK", shutdown);
245
+ }
246
+ process.on("exit", () => { closeMemoryDb(); });
247
+ }
248
+ //# sourceMappingURL=http-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-server.js","sourceRoot":"","sources":["../src/http-server.ts"],"names":[],"mappings":"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"}