nostr-bray 1.28.0 → 1.28.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/dist/index.js +33 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -142,12 +142,10 @@ if (config.transport === 'stdio') {
|
|
|
142
142
|
else {
|
|
143
143
|
const { createServer } = await import('node:http');
|
|
144
144
|
const { StreamableHTTPServerTransport } = await import('@modelcontextprotocol/sdk/server/streamableHttp.js');
|
|
145
|
-
const {
|
|
145
|
+
const { isInitializeRequest } = await import('@modelcontextprotocol/sdk/types.js');
|
|
146
|
+
const { randomUUID, timingSafeEqual } = await import('node:crypto');
|
|
146
147
|
const token = process.env.BRAY_HTTP_TOKEN ?? randomUUID();
|
|
147
148
|
console.error(`nostr-bray HTTP auth token: ${token}`);
|
|
148
|
-
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => randomUUID() });
|
|
149
|
-
await server.connect(transport);
|
|
150
|
-
const { timingSafeEqual } = await import('node:crypto');
|
|
151
149
|
const expectedAuth = Buffer.from(`Bearer ${token}`);
|
|
152
150
|
// Sliding window rate limiter (per-IP)
|
|
153
151
|
const rateLimits = new Map();
|
|
@@ -163,6 +161,25 @@ else {
|
|
|
163
161
|
entry.count++;
|
|
164
162
|
return entry.count <= RATE_LIMIT;
|
|
165
163
|
}
|
|
164
|
+
// Session map — each MCP session gets its own transport.
|
|
165
|
+
// The underlying McpServer is reused across sessions: when a session ends its
|
|
166
|
+
// transport closes, which sets server._transport = undefined, allowing the next
|
|
167
|
+
// session to call server.connect(newTransport).
|
|
168
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
169
|
+
const sessions = new Map();
|
|
170
|
+
async function createSession() {
|
|
171
|
+
// Close the current server connection so it can be reconnected below.
|
|
172
|
+
if (server.isConnected())
|
|
173
|
+
await server.close();
|
|
174
|
+
const t = new StreamableHTTPServerTransport({
|
|
175
|
+
sessionIdGenerator: () => randomUUID(),
|
|
176
|
+
onsessioninitialized: (id) => { sessions.set(id, t); },
|
|
177
|
+
});
|
|
178
|
+
t.onclose = () => { if (t.sessionId)
|
|
179
|
+
sessions.delete(t.sessionId); };
|
|
180
|
+
await server.connect(t);
|
|
181
|
+
return t;
|
|
182
|
+
}
|
|
166
183
|
const httpServer = createServer(async (req, res) => {
|
|
167
184
|
const clientIp = req.socket.remoteAddress ?? 'unknown';
|
|
168
185
|
// Rate limiting
|
|
@@ -187,6 +204,7 @@ else {
|
|
|
187
204
|
return;
|
|
188
205
|
}
|
|
189
206
|
// Parse body for POST requests (1MB limit)
|
|
207
|
+
let body;
|
|
190
208
|
if (req.method === 'POST') {
|
|
191
209
|
const MAX_BODY = 1_048_576;
|
|
192
210
|
const chunks = [];
|
|
@@ -200,7 +218,6 @@ else {
|
|
|
200
218
|
}
|
|
201
219
|
chunks.push(chunk);
|
|
202
220
|
}
|
|
203
|
-
let body;
|
|
204
221
|
try {
|
|
205
222
|
body = JSON.parse(Buffer.concat(chunks).toString());
|
|
206
223
|
}
|
|
@@ -209,11 +226,19 @@ else {
|
|
|
209
226
|
res.end(JSON.stringify({ error: 'Invalid JSON' }));
|
|
210
227
|
return;
|
|
211
228
|
}
|
|
212
|
-
await transport.handleRequest(req, res, body);
|
|
213
229
|
}
|
|
214
|
-
|
|
215
|
-
|
|
230
|
+
// Route to existing session or create a new one for initialize requests
|
|
231
|
+
const sessionId = req.headers['mcp-session-id'];
|
|
232
|
+
let transport = sessionId ? sessions.get(sessionId) : undefined;
|
|
233
|
+
if (!transport) {
|
|
234
|
+
if (req.method !== 'POST' || !isInitializeRequest(body)) {
|
|
235
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
236
|
+
res.end(JSON.stringify({ jsonrpc: '2.0', error: { code: -32000, message: 'Bad Request: no active session' }, id: null }));
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
transport = await createSession();
|
|
216
240
|
}
|
|
241
|
+
await transport.handleRequest(req, res, body);
|
|
217
242
|
});
|
|
218
243
|
httpServer.listen(config.port, config.bindAddress, () => {
|
|
219
244
|
console.error(`nostr-bray HTTP on ${config.bindAddress}:${config.port}`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nostr-bray",
|
|
3
|
-
"version": "1.28.
|
|
3
|
+
"version": "1.28.1",
|
|
4
4
|
"mcpName": "dev.forgesworn/bray",
|
|
5
5
|
"description": "Trust-aware Nostr for AI and humans. Three dimensions of trust -- verification, proximity, and access -- woven into every interaction.",
|
|
6
6
|
"type": "module",
|