create-multicast 0.1.2 → 0.2.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-multicast",
3
- "version": "0.1.2",
3
+ "version": "0.2.0",
4
4
  "description": "Create a Multicast MCP gateway — one command to scaffold, configure, and deploy your parallel MCP server.",
5
5
  "type": "module",
6
6
  "bin": "./dist/cli.js",
@@ -67,16 +67,53 @@ async function callMcpServer(
67
67
  const timer = setTimeout(() => controller.abort(), timeoutMs);
68
68
 
69
69
  try {
70
- const headers: Record<string, string> = {
70
+ const baseHeaders: Record<string, string> = {
71
71
  "Content-Type": "application/json",
72
+ "Accept": "application/json, text/event-stream",
72
73
  };
73
74
  if (server.auth) {
74
- headers["Authorization"] = server.auth;
75
+ baseHeaders["Authorization"] = server.auth;
76
+ }
77
+
78
+ // Step 1: Initialize MCP session
79
+ const initResponse = await fetch(server.url, {
80
+ method: "POST",
81
+ headers: baseHeaders,
82
+ body: JSON.stringify({
83
+ jsonrpc: "2.0",
84
+ method: "initialize",
85
+ params: {
86
+ protocolVersion: "2024-11-05",
87
+ capabilities: {},
88
+ clientInfo: { name: "multicast", version: "0.1.0" },
89
+ },
90
+ id: "init-" + crypto.randomUUID(),
91
+ }),
92
+ signal: controller.signal,
93
+ });
94
+
95
+ const sessionId = initResponse.headers.get("mcp-session-id");
96
+
97
+ // Step 2: Send initialized notification (required by spec)
98
+ const callHeaders = { ...baseHeaders };
99
+ if (sessionId) {
100
+ callHeaders["mcp-session-id"] = sessionId;
75
101
  }
76
102
 
103
+ await fetch(server.url, {
104
+ method: "POST",
105
+ headers: callHeaders,
106
+ body: JSON.stringify({
107
+ jsonrpc: "2.0",
108
+ method: "notifications/initialized",
109
+ }),
110
+ signal: controller.signal,
111
+ });
112
+
113
+ // Step 3: Call the tool with the session
77
114
  const response = await fetch(server.url, {
78
115
  method: "POST",
79
- headers,
116
+ headers: callHeaders,
80
117
  body: JSON.stringify({
81
118
  jsonrpc: "2.0",
82
119
  method: "tools/call",
@@ -148,6 +185,7 @@ async function discoverServerTools(
148
185
  try {
149
186
  const headers: Record<string, string> = {
150
187
  "Content-Type": "application/json",
188
+ "Accept": "application/json, text/event-stream",
151
189
  };
152
190
  if (server.auth) {
153
191
  headers["Authorization"] = server.auth;
@@ -222,6 +260,15 @@ async function discoverServerTools(
222
260
 
223
261
  const tools = data.result?.tools || [];
224
262
 
263
+ // Upsert server row FIRST (tools table has FK reference to servers)
264
+ await db
265
+ .prepare(
266
+ `INSERT OR REPLACE INTO servers (name, url, description, tool_count, status, last_error, last_discovered_at, updated_at)
267
+ VALUES (?, ?, '', ?, 'active', NULL, datetime('now'), datetime('now'))`
268
+ )
269
+ .bind(server.name, server.url, tools.length)
270
+ .run();
271
+
225
272
  // Clear old tools for this server
226
273
  await db
227
274
  .prepare("DELETE FROM tools WHERE server_name = ?")
@@ -244,15 +291,6 @@ async function discoverServerTools(
244
291
  .run();
245
292
  }
246
293
 
247
- // Update server metadata
248
- await db
249
- .prepare(
250
- `INSERT OR REPLACE INTO servers (name, url, description, tool_count, status, last_error, last_discovered_at, updated_at)
251
- VALUES (?, ?, '', ?, 'active', NULL, datetime('now'), datetime('now'))`
252
- )
253
- .bind(server.name, server.url, tools.length)
254
- .run();
255
-
256
294
  return { tool_count: tools.length };
257
295
  } catch (err: unknown) {
258
296
  const message = err instanceof Error ? err.message : "discovery failed";