screenpipe-mcp 0.18.6 → 0.18.7
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/dist/http-server.js +6 -3
- package/dist/http-server.test.js +71 -0
- package/package.json +1 -1
- package/src/http-server.test.ts +78 -0
- package/src/http-server.ts +6 -4
package/dist/http-server.js
CHANGED
|
@@ -284,11 +284,14 @@ function buildHttpServer(config) {
|
|
|
284
284
|
const server = createMcpServer(fetchAPI);
|
|
285
285
|
const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({
|
|
286
286
|
sessionIdGenerator: () => crypto.randomUUID(),
|
|
287
|
+
onsessioninitialized: (newSessionId) => {
|
|
288
|
+
sessions.set(newSessionId, { server, transport });
|
|
289
|
+
},
|
|
290
|
+
onsessionclosed: (closedSessionId) => {
|
|
291
|
+
sessions.delete(closedSessionId);
|
|
292
|
+
},
|
|
287
293
|
});
|
|
288
294
|
await server.connect(transport);
|
|
289
|
-
if (transport.sessionId) {
|
|
290
|
-
sessions.set(transport.sessionId, { server, transport });
|
|
291
|
-
}
|
|
292
295
|
session = { server, transport };
|
|
293
296
|
}
|
|
294
297
|
await session.transport.handleRequest(req, res);
|
package/dist/http-server.test.js
CHANGED
|
@@ -147,3 +147,74 @@ const http_server_1 = require("./http-server");
|
|
|
147
147
|
(0, vitest_1.expect)((0, http_server_1.isAuthorized)(lan("Bearer SECRET"), "secret")).toBe(false);
|
|
148
148
|
});
|
|
149
149
|
});
|
|
150
|
+
(0, vitest_1.describe)("buildHttpServer", () => {
|
|
151
|
+
(0, vitest_1.it)("persists initialized sessions so tools/list works on the next request", async () => {
|
|
152
|
+
const server = (0, http_server_1.buildHttpServer)({
|
|
153
|
+
mcpPort: 0,
|
|
154
|
+
screenpipePort: 3030,
|
|
155
|
+
host: "127.0.0.1",
|
|
156
|
+
apiKey: "secret",
|
|
157
|
+
});
|
|
158
|
+
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
159
|
+
const address = server.address();
|
|
160
|
+
if (!address || typeof address === "string") {
|
|
161
|
+
throw new Error("expected server.address() to return a bound port");
|
|
162
|
+
}
|
|
163
|
+
const baseUrl = `http://127.0.0.1:${address.port}`;
|
|
164
|
+
try {
|
|
165
|
+
const initResponse = await fetch(`${baseUrl}/mcp`, {
|
|
166
|
+
method: "POST",
|
|
167
|
+
headers: {
|
|
168
|
+
authorization: "Bearer secret",
|
|
169
|
+
"content-type": "application/json",
|
|
170
|
+
accept: "application/json, text/event-stream",
|
|
171
|
+
},
|
|
172
|
+
body: JSON.stringify({
|
|
173
|
+
jsonrpc: "2.0",
|
|
174
|
+
id: 1,
|
|
175
|
+
method: "initialize",
|
|
176
|
+
params: {
|
|
177
|
+
protocolVersion: "2024-11-05",
|
|
178
|
+
capabilities: {},
|
|
179
|
+
clientInfo: { name: "vitest", version: "1.0.0" },
|
|
180
|
+
},
|
|
181
|
+
}),
|
|
182
|
+
});
|
|
183
|
+
(0, vitest_1.expect)(initResponse.status).toBe(200);
|
|
184
|
+
const sessionId = initResponse.headers.get("mcp-session-id");
|
|
185
|
+
(0, vitest_1.expect)(sessionId).toBeTruthy();
|
|
186
|
+
await initResponse.text();
|
|
187
|
+
const healthResponse = await fetch(`${baseUrl}/health`);
|
|
188
|
+
(0, vitest_1.expect)(healthResponse.status).toBe(200);
|
|
189
|
+
(0, vitest_1.expect)(await healthResponse.json()).toEqual({ status: "ok", sessions: 1 });
|
|
190
|
+
const toolsResponse = await fetch(`${baseUrl}/mcp`, {
|
|
191
|
+
method: "POST",
|
|
192
|
+
headers: {
|
|
193
|
+
authorization: "Bearer secret",
|
|
194
|
+
"content-type": "application/json",
|
|
195
|
+
accept: "application/json, text/event-stream",
|
|
196
|
+
"mcp-session-id": sessionId,
|
|
197
|
+
"mcp-protocol-version": "2024-11-05",
|
|
198
|
+
},
|
|
199
|
+
body: JSON.stringify({
|
|
200
|
+
jsonrpc: "2.0",
|
|
201
|
+
id: 2,
|
|
202
|
+
method: "tools/list",
|
|
203
|
+
params: {},
|
|
204
|
+
}),
|
|
205
|
+
});
|
|
206
|
+
(0, vitest_1.expect)(toolsResponse.status).toBe(200);
|
|
207
|
+
(0, vitest_1.expect)(await toolsResponse.text()).toContain('"name":"search_content"');
|
|
208
|
+
}
|
|
209
|
+
finally {
|
|
210
|
+
await new Promise((resolve, reject) => {
|
|
211
|
+
server.close((err) => {
|
|
212
|
+
if (err)
|
|
213
|
+
reject(err);
|
|
214
|
+
else
|
|
215
|
+
resolve();
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
});
|
package/package.json
CHANGED
package/src/http-server.test.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { describe, it, expect } from "vitest";
|
|
6
6
|
import {
|
|
7
|
+
buildHttpServer,
|
|
7
8
|
CliError,
|
|
8
9
|
isAuthorized,
|
|
9
10
|
isLoopbackRequest,
|
|
@@ -178,3 +179,80 @@ describe("isAuthorized", () => {
|
|
|
178
179
|
expect(isAuthorized(lan("Bearer SECRET"), "secret")).toBe(false);
|
|
179
180
|
});
|
|
180
181
|
});
|
|
182
|
+
|
|
183
|
+
describe("buildHttpServer", () => {
|
|
184
|
+
it("persists initialized sessions so tools/list works on the next request", async () => {
|
|
185
|
+
const server = buildHttpServer({
|
|
186
|
+
mcpPort: 0,
|
|
187
|
+
screenpipePort: 3030,
|
|
188
|
+
host: "127.0.0.1",
|
|
189
|
+
apiKey: "secret",
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
await new Promise<void>((resolve) => server.listen(0, "127.0.0.1", resolve));
|
|
193
|
+
|
|
194
|
+
const address = server.address();
|
|
195
|
+
if (!address || typeof address === "string") {
|
|
196
|
+
throw new Error("expected server.address() to return a bound port");
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const baseUrl = `http://127.0.0.1:${address.port}`;
|
|
200
|
+
|
|
201
|
+
try {
|
|
202
|
+
const initResponse = await fetch(`${baseUrl}/mcp`, {
|
|
203
|
+
method: "POST",
|
|
204
|
+
headers: {
|
|
205
|
+
authorization: "Bearer secret",
|
|
206
|
+
"content-type": "application/json",
|
|
207
|
+
accept: "application/json, text/event-stream",
|
|
208
|
+
},
|
|
209
|
+
body: JSON.stringify({
|
|
210
|
+
jsonrpc: "2.0",
|
|
211
|
+
id: 1,
|
|
212
|
+
method: "initialize",
|
|
213
|
+
params: {
|
|
214
|
+
protocolVersion: "2024-11-05",
|
|
215
|
+
capabilities: {},
|
|
216
|
+
clientInfo: { name: "vitest", version: "1.0.0" },
|
|
217
|
+
},
|
|
218
|
+
}),
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
expect(initResponse.status).toBe(200);
|
|
222
|
+
const sessionId = initResponse.headers.get("mcp-session-id");
|
|
223
|
+
expect(sessionId).toBeTruthy();
|
|
224
|
+
await initResponse.text();
|
|
225
|
+
|
|
226
|
+
const healthResponse = await fetch(`${baseUrl}/health`);
|
|
227
|
+
expect(healthResponse.status).toBe(200);
|
|
228
|
+
expect(await healthResponse.json()).toEqual({ status: "ok", sessions: 1 });
|
|
229
|
+
|
|
230
|
+
const toolsResponse = await fetch(`${baseUrl}/mcp`, {
|
|
231
|
+
method: "POST",
|
|
232
|
+
headers: {
|
|
233
|
+
authorization: "Bearer secret",
|
|
234
|
+
"content-type": "application/json",
|
|
235
|
+
accept: "application/json, text/event-stream",
|
|
236
|
+
"mcp-session-id": sessionId!,
|
|
237
|
+
"mcp-protocol-version": "2024-11-05",
|
|
238
|
+
},
|
|
239
|
+
body: JSON.stringify({
|
|
240
|
+
jsonrpc: "2.0",
|
|
241
|
+
id: 2,
|
|
242
|
+
method: "tools/list",
|
|
243
|
+
params: {},
|
|
244
|
+
}),
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
expect(toolsResponse.status).toBe(200);
|
|
248
|
+
expect(await toolsResponse.text()).toContain('"name":"search_content"');
|
|
249
|
+
} finally {
|
|
250
|
+
await new Promise<void>((resolve, reject) => {
|
|
251
|
+
server.close((err) => {
|
|
252
|
+
if (err) reject(err);
|
|
253
|
+
else resolve();
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
});
|
package/src/http-server.ts
CHANGED
|
@@ -337,13 +337,15 @@ export function buildHttpServer(config: CliConfig) {
|
|
|
337
337
|
const server = createMcpServer(fetchAPI);
|
|
338
338
|
const transport = new StreamableHTTPServerTransport({
|
|
339
339
|
sessionIdGenerator: () => crypto.randomUUID(),
|
|
340
|
+
onsessioninitialized: (newSessionId) => {
|
|
341
|
+
sessions.set(newSessionId, { server, transport });
|
|
342
|
+
},
|
|
343
|
+
onsessionclosed: (closedSessionId) => {
|
|
344
|
+
sessions.delete(closedSessionId);
|
|
345
|
+
},
|
|
340
346
|
});
|
|
341
347
|
|
|
342
348
|
await server.connect(transport);
|
|
343
|
-
|
|
344
|
-
if (transport.sessionId) {
|
|
345
|
-
sessions.set(transport.sessionId, { server, transport });
|
|
346
|
-
}
|
|
347
349
|
session = { server, transport };
|
|
348
350
|
}
|
|
349
351
|
|