stream0-channel 0.2.0 → 0.4.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.
- package/bin/stream0-channel.mjs +41 -24
- package/package.json +3 -3
package/bin/stream0-channel.mjs
CHANGED
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
* Install: npx stream0-channel
|
|
7
7
|
*
|
|
8
8
|
* Environment variables:
|
|
9
|
-
* STREAM0_URL
|
|
10
|
-
* STREAM0_API_KEY
|
|
11
|
-
* STREAM0_AGENT_ID
|
|
9
|
+
* STREAM0_URL - Stream0 server URL (default: http://localhost:8080)
|
|
10
|
+
* STREAM0_API_KEY - API key for group-level auth (register, list agents)
|
|
11
|
+
* STREAM0_AGENT_ID - This agent's ID on Stream0
|
|
12
|
+
* STREAM0_AGENT_TOKEN - Agent token for message operations (optional, obtained at registration)
|
|
12
13
|
*/
|
|
13
14
|
|
|
14
15
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
@@ -27,22 +28,32 @@ if (!AGENT_ID) {
|
|
|
27
28
|
process.exit(1);
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
// Group-level headers (X-API-Key) for registration and discovery
|
|
32
|
+
const groupHeaders = { "Content-Type": "application/json" };
|
|
33
|
+
if (STREAM0_API_KEY) groupHeaders["X-API-Key"] = STREAM0_API_KEY;
|
|
34
|
+
|
|
35
|
+
// Agent-level headers (X-Agent-Token) for send/receive/ack
|
|
36
|
+
let agentToken = process.env.STREAM0_AGENT_TOKEN || "";
|
|
37
|
+
function agentHeaders() {
|
|
38
|
+
return { "Content-Type": "application/json", "X-Agent-Token": agentToken };
|
|
39
|
+
}
|
|
32
40
|
|
|
33
41
|
// --- Stream0 HTTP helpers ---
|
|
34
42
|
|
|
35
|
-
async function stream0Get(path, params) {
|
|
43
|
+
async function stream0Get(path, params, useAgentAuth = false) {
|
|
36
44
|
const url = new URL(`${STREAM0_URL}${path}`);
|
|
37
45
|
if (params) for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v);
|
|
38
|
-
const resp = await fetch(url.toString(), {
|
|
46
|
+
const resp = await fetch(url.toString(), {
|
|
47
|
+
headers: useAgentAuth ? agentHeaders() : groupHeaders,
|
|
48
|
+
signal: AbortSignal.timeout(35000),
|
|
49
|
+
});
|
|
39
50
|
return resp.json();
|
|
40
51
|
}
|
|
41
52
|
|
|
42
|
-
async function stream0Post(path, body) {
|
|
53
|
+
async function stream0Post(path, body, useAgentAuth = false) {
|
|
43
54
|
const resp = await fetch(`${STREAM0_URL}${path}`, {
|
|
44
55
|
method: "POST",
|
|
45
|
-
headers,
|
|
56
|
+
headers: useAgentAuth ? agentHeaders() : groupHeaders,
|
|
46
57
|
body: body ? JSON.stringify(body) : undefined,
|
|
47
58
|
signal: AbortSignal.timeout(10000),
|
|
48
59
|
});
|
|
@@ -56,7 +67,7 @@ function sleep(ms) {
|
|
|
56
67
|
// --- MCP Server ---
|
|
57
68
|
|
|
58
69
|
const mcp = new Server(
|
|
59
|
-
{ name: "stream0-channel", version: "0.
|
|
70
|
+
{ name: "stream0-channel", version: "0.4.0" },
|
|
60
71
|
{
|
|
61
72
|
capabilities: {
|
|
62
73
|
experimental: { "claude/channel": {} },
|
|
@@ -169,7 +180,7 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
169
180
|
mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
170
181
|
const { name, arguments: args } = req.params;
|
|
171
182
|
|
|
172
|
-
// --- discover ---
|
|
183
|
+
// --- discover (group-auth) ---
|
|
173
184
|
if (name === "discover") {
|
|
174
185
|
const result = await stream0Get("/agents");
|
|
175
186
|
const agents = (result?.agents || [])
|
|
@@ -206,7 +217,7 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
206
217
|
};
|
|
207
218
|
}
|
|
208
219
|
|
|
209
|
-
// --- delegate ---
|
|
220
|
+
// --- delegate (agent-auth) ---
|
|
210
221
|
if (name === "delegate") {
|
|
211
222
|
const { to, task, context, timeout: userTimeout } = args;
|
|
212
223
|
|
|
@@ -218,10 +229,9 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
218
229
|
|
|
219
230
|
await stream0Post(`/agents/${to}/inbox`, {
|
|
220
231
|
thread_id: threadId,
|
|
221
|
-
from: AGENT_ID,
|
|
222
232
|
type: "request",
|
|
223
233
|
content,
|
|
224
|
-
});
|
|
234
|
+
}, true);
|
|
225
235
|
|
|
226
236
|
console.error(
|
|
227
237
|
`[stream0-channel] Delegated to ${to} (thread: ${threadId}), waiting up to ${timeoutSec}s...`
|
|
@@ -237,11 +247,11 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
237
247
|
status: "unread",
|
|
238
248
|
thread_id: threadId,
|
|
239
249
|
timeout: String(pollTimeout),
|
|
240
|
-
});
|
|
250
|
+
}, true);
|
|
241
251
|
|
|
242
252
|
const messages = result?.messages || [];
|
|
243
253
|
for (const msg of messages) {
|
|
244
|
-
await stream0Post(`/inbox/messages/${msg.id}/ack
|
|
254
|
+
await stream0Post(`/inbox/messages/${msg.id}/ack`, undefined, true);
|
|
245
255
|
|
|
246
256
|
if (msg.type === "done") {
|
|
247
257
|
const responseText =
|
|
@@ -307,7 +317,7 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
307
317
|
};
|
|
308
318
|
}
|
|
309
319
|
|
|
310
|
-
// --- reply ---
|
|
320
|
+
// --- reply (agent-auth) ---
|
|
311
321
|
if (name === "reply") {
|
|
312
322
|
const { to, thread_id, type, content } = args;
|
|
313
323
|
|
|
@@ -320,18 +330,17 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
320
330
|
|
|
321
331
|
await stream0Post(`/agents/${to}/inbox`, {
|
|
322
332
|
thread_id,
|
|
323
|
-
from: AGENT_ID,
|
|
324
333
|
type,
|
|
325
334
|
content: contentObj,
|
|
326
|
-
});
|
|
335
|
+
}, true);
|
|
327
336
|
|
|
328
337
|
return { content: [{ type: "text", text: `Replied to ${to} (thread: ${thread_id})` }] };
|
|
329
338
|
}
|
|
330
339
|
|
|
331
|
-
// --- ack ---
|
|
340
|
+
// --- ack (agent-auth) ---
|
|
332
341
|
if (name === "ack") {
|
|
333
342
|
const { message_id } = args;
|
|
334
|
-
await stream0Post(`/inbox/messages/${message_id}/ack
|
|
343
|
+
await stream0Post(`/inbox/messages/${message_id}/ack`, undefined, true);
|
|
335
344
|
return { content: [{ type: "text", text: `Acknowledged ${message_id}` }] };
|
|
336
345
|
}
|
|
337
346
|
|
|
@@ -342,19 +351,27 @@ mcp.setRequestHandler(CallToolRequestSchema, async (req) => {
|
|
|
342
351
|
|
|
343
352
|
await mcp.connect(new StdioServerTransport());
|
|
344
353
|
|
|
345
|
-
// Register agent on Stream0
|
|
346
|
-
await stream0Post("/agents", { id: AGENT_ID });
|
|
354
|
+
// Register agent on Stream0 (group-auth) and get agent token
|
|
355
|
+
const regResult = await stream0Post("/agents", { id: AGENT_ID });
|
|
356
|
+
if (regResult?.agent_token && !agentToken) {
|
|
357
|
+
agentToken = regResult.agent_token;
|
|
358
|
+
}
|
|
347
359
|
console.error(`[stream0-channel] Registered as ${AGENT_ID}, polling inbox...`);
|
|
348
360
|
|
|
361
|
+
if (!agentToken) {
|
|
362
|
+
console.error("[stream0-channel] Warning: no agent token available. Message operations will fail.");
|
|
363
|
+
}
|
|
364
|
+
|
|
349
365
|
const pushed = new Set();
|
|
350
366
|
|
|
367
|
+
// Poll inbox (agent-auth)
|
|
351
368
|
async function pollLoop() {
|
|
352
369
|
while (true) {
|
|
353
370
|
try {
|
|
354
371
|
const result = await stream0Get(`/agents/${AGENT_ID}/inbox`, {
|
|
355
372
|
status: "unread",
|
|
356
373
|
timeout: "25",
|
|
357
|
-
});
|
|
374
|
+
}, true);
|
|
358
375
|
|
|
359
376
|
const messages = result?.messages || [];
|
|
360
377
|
for (const msg of messages) {
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stream0-channel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Stream0 MCP channel for Claude Code",
|
|
5
5
|
"bin": {
|
|
6
|
-
"stream0-channel": "
|
|
6
|
+
"stream0-channel": "bin/stream0-channel.mjs"
|
|
7
7
|
},
|
|
8
8
|
"type": "module",
|
|
9
9
|
"dependencies": {
|
|
@@ -12,6 +12,6 @@
|
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "https://github.com/risingwavelabs/stream0"
|
|
15
|
+
"url": "git+https://github.com/risingwavelabs/stream0.git"
|
|
16
16
|
}
|
|
17
17
|
}
|