prism-mcp-server 2.5.1 → 2.5.2

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.
@@ -17,7 +17,7 @@
17
17
  * ═══════════════════════════════════════════════════════════════════
18
18
  */
19
19
  import * as http from "http";
20
- import { execSync } from "child_process";
20
+ import { exec } from "child_process";
21
21
  import { getStorage } from "../storage/index.js";
22
22
  import { PRISM_USER_ID, SERVER_CONFIG } from "../config.js";
23
23
  import { renderDashboardHTML } from "./ui.js";
@@ -26,36 +26,42 @@ const PORT = parseInt(process.env.PRISM_DASHBOARD_PORT || "3000", 10);
26
26
  * Kill any existing process holding the dashboard port.
27
27
  * This prevents zombie dashboard processes from surviving IDE restarts
28
28
  * and serving stale versions of the UI.
29
+ *
30
+ * CRITICAL: Uses async exec() instead of execSync() to avoid blocking
31
+ * the Node.js event loop. Blocking during startup prevents the MCP
32
+ * stdio transport from responding to the initialize handshake in time,
33
+ * causing Antigravity to report MCP_SERVER_INIT_ERROR.
29
34
  */
30
- function killPortHolder(port) {
31
- try {
32
- // lsof returns PIDs listening on the port; -t gives terse (PID-only) output
33
- const pids = execSync(`lsof -ti tcp:${port}`, { encoding: "utf-8" })
34
- .trim()
35
- .split("\n")
36
- .filter(Boolean);
37
- if (pids.length === 0)
38
- return;
39
- // Don't kill ourselves
40
- const myPid = String(process.pid);
41
- const stalePids = pids.filter(p => p !== myPid);
42
- if (stalePids.length > 0) {
43
- console.error(`[Dashboard] Killing stale process(es) on port ${port}: ${stalePids.join(", ")}`);
44
- execSync(`kill ${stalePids.join(" ")}`, { encoding: "utf-8" });
45
- // Brief pause to let the OS release the port
46
- execSync("sleep 0.3");
47
- }
48
- }
49
- catch (err) {
50
- // lsof exits with code 1 when no matches found — that's expected.
51
- // Any other failure (lsof missing, permission denied, etc.) gets a warning.
52
- const isNoMatch = err instanceof Error &&
53
- "status" in err &&
54
- err.status === 1;
55
- if (!isNoMatch) {
56
- console.error(`[Dashboard] killPortHolder: could not check port ${port} (lsof may not be installed) — skipping.`);
57
- }
58
- }
35
+ async function killPortHolder(port) {
36
+ return new Promise((resolve) => {
37
+ exec(`lsof -ti tcp:${port}`, { encoding: "utf-8" }, (err, stdout) => {
38
+ if (err) {
39
+ // lsof exits with code 1 when no matches found — that's expected.
40
+ // Any other failure (lsof missing, permission denied, etc.) gets a warning.
41
+ const isNoMatch = err.code === 1;
42
+ if (!isNoMatch) {
43
+ console.error(`[Dashboard] killPortHolder: could not check port ${port} (lsof may not be installed) — skipping.`);
44
+ }
45
+ return resolve();
46
+ }
47
+ const pids = stdout.trim().split("\n").filter(Boolean);
48
+ if (pids.length === 0)
49
+ return resolve();
50
+ // Don't kill ourselves
51
+ const myPid = String(process.pid);
52
+ const stalePids = pids.filter(p => p !== myPid);
53
+ if (stalePids.length > 0) {
54
+ console.error(`[Dashboard] Killing stale process(es) on port ${port}: ${stalePids.join(", ")}`);
55
+ exec(`kill ${stalePids.join(" ")}`, () => {
56
+ // Brief pause to let the OS release the port
57
+ setTimeout(resolve, 300);
58
+ });
59
+ }
60
+ else {
61
+ resolve();
62
+ }
63
+ });
64
+ });
59
65
  }
60
66
  export async function startDashboardServer() {
61
67
  // Clean up any zombie dashboard process from a previous session
package/dist/server.js CHANGED
@@ -39,7 +39,7 @@
39
39
  */
40
40
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
41
41
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
42
- import { CallToolRequestSchema, ListToolsRequestSchema, InitializeRequestSchema,
42
+ import { CallToolRequestSchema, ListToolsRequestSchema,
43
43
  // ─── v0.4.0: MCP Prompts support (Enhancement #1) ───
44
44
  // REVIEWER NOTE: These schemas enable the /resume_session
45
45
  // slash command in Claude Desktop. ListPrompts tells the
@@ -175,9 +175,7 @@ export function createServer() {
175
175
  version: SERVER_CONFIG.version,
176
176
  }, {
177
177
  capabilities: {
178
- tools: {
179
- tools: ALL_TOOLS,
180
- },
178
+ tools: {},
181
179
  // ─── v0.4.0: Prompt capability (Enhancement #1) ───
182
180
  // REVIEWER NOTE: Declaring `prompts: {}` tells Claude Desktop
183
181
  // that we support the prompts/list and prompts/get methods.
@@ -196,24 +194,12 @@ export function createServer() {
196
194
  },
197
195
  });
198
196
  // ── Handler: Initialize ──
199
- // REVIEWER NOTE: The initialize handler is unchanged from v0.3.0
200
- // except that it now reports the expanded capabilities.
201
- server.setRequestHandler(InitializeRequestSchema, async (request) => {
202
- return {
203
- protocolVersion: request.params.protocolVersion,
204
- serverInfo: {
205
- name: SERVER_CONFIG.name,
206
- version: SERVER_CONFIG.version,
207
- },
208
- capabilities: {
209
- tools: {
210
- tools: ALL_TOOLS,
211
- },
212
- ...(SESSION_MEMORY_ENABLED ? { prompts: {} } : {}),
213
- ...(SESSION_MEMORY_ENABLED ? { resources: { subscribe: true } } : {}),
214
- },
215
- };
216
- });
197
+ // NOTE: The SDK's built-in _oninitialize() handles the Initialize request.
198
+ // It stores _clientCapabilities, _clientVersion, negotiates protocol version,
199
+ // and returns capabilities from the Server constructor config.
200
+ // Do NOT override InitializeRequestSchema — doing so bypasses critical
201
+ // internal state management and can cause MCP clients (like Antigravity)
202
+ // to fail during the init handshake.
217
203
  // ── Handler: List Tools ──
218
204
  server.setRequestHandler(ListToolsRequestSchema, async () => {
219
205
  return {
@@ -537,9 +523,7 @@ export function createSandboxServer() {
537
523
  version: SERVER_CONFIG.version,
538
524
  }, {
539
525
  capabilities: {
540
- tools: {
541
- tools: [...BASE_TOOLS, ...SESSION_MEMORY_TOOLS],
542
- },
526
+ tools: {},
543
527
  prompts: {},
544
528
  resources: { subscribe: true },
545
529
  },
@@ -38,7 +38,7 @@ export async function createMcpClient() {
38
38
  command: "node",
39
39
  args: ["index.js"], // Server entry point
40
40
  });
41
- const client = new Client({ name: "gemini-mcp-client", version: "1.0.0" }, { capabilities: { tools: {} } });
41
+ const client = new Client({ name: "gemini-mcp-client", version: "1.0.0" });
42
42
  await client.connect(transport);
43
43
  return { client, transport };
44
44
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prism-mcp-server",
3
- "version": "2.5.1",
3
+ "version": "2.5.2",
4
4
  "mcpName": "io.github.dcostenco/prism-mcp",
5
5
  "description": "The Mind Palace for AI Agents — local-first MCP server with persistent memory (SQLite/Supabase), visual dashboard, time travel, multi-agent sync, Morning Briefings, reality drift detection, code mode templates, semantic vector search, and Brave Search + Gemini analysis. Zero-config local mode.",
6
6
  "module": "index.ts",
@@ -79,7 +79,7 @@
79
79
  "@google-cloud/discoveryengine": "^2.5.3",
80
80
  "@google/generative-ai": "^0.24.1",
81
81
  "@libsql/client": "^0.17.2",
82
- "@modelcontextprotocol/sdk": "^1.9.0",
82
+ "@modelcontextprotocol/sdk": "^1.27.1",
83
83
  "@supabase/supabase-js": "^2.99.3",
84
84
  "dotenv": "^16.5.0",
85
85
  "quickjs-emscripten": "^0.32.0"