prism-mcp-server 2.3.7 β†’ 2.3.9

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/README.md CHANGED
@@ -14,13 +14,15 @@
14
14
 
15
15
  ---
16
16
 
17
- ## What's New in v2.3.5 β€” AI Reasoning Engine 🧠
17
+ ## What's New in v2.3.8 β€” LangGraph Research Agent πŸ”¬
18
18
 
19
19
  | Feature | Description |
20
20
  |---|---|
21
- | πŸ•ΈοΈ **Neural Graph** | Interactive knowledge graph on the Mind Palace Dashboard β€” visualize how projects connect through shared keywords and categories using Vis.js force-directed layout. |
22
- | πŸ›‘οΈ **Prompt Injection Shield** | Gemini-powered security scan in `session_health_check` β€” detects system override attempts, jailbreaks, and data exfiltration hidden in agent memory. Tuned to avoid false positives on normal dev commands. |
23
- | 🧬 **Fact Merger** | Async LLM contradiction resolution on every handoff save β€” if old context says "Postgres" and new says "MySQL", Gemini silently merges the facts in the background. Zero latency impact (fire-and-forget). |
21
+ | πŸ€– **LangGraph Research Agent** | New `examples/langgraph-agent/` β€” a 5-node agentic research agent (planβ†’searchβ†’analyzeβ†’decideβ†’answerβ†’save) with autonomous looping, MCP integration, and persistent memory. |
22
+ | 🧠 **Agentic Memory** | `save_session` node persists research findings to a ledger β€” the agent doesn't just answer and forget. Routes to Prism's `session_save_ledger` in MCP-connected mode. |
23
+ | πŸ”Œ **MCP Client Bridge** | Raw JSON-RPC 2.0 client (`mcp_client.py`) for Python 3.9+ β€” dynamically discovers and wraps Prism MCP tools as LangChain `StructuredTool` objects. |
24
+ | πŸ”§ **Storage Abstraction Fix** | Resource/Prompt handlers now route through `getStorage()` instead of calling Supabase directly β€” eliminates EOF crashes when reading `memory://` resources. |
25
+ | πŸ›‘οΈ **Error Boundaries** | Resource handlers catch errors gracefully and return proper MCP error responses (`isError: true`) instead of crashing the server process. |
24
26
 
25
27
  <details>
26
28
  <summary><strong>What's in v2.2.0</strong></summary>
@@ -251,6 +253,39 @@ Add to your Continue `config.json` or Cline MCP settings:
251
253
 
252
254
  ---
253
255
 
256
+ ## Claude Code + Gemini Startup Compatibility
257
+
258
+ If you want consistent behavior across clients, treat startup in two phases:
259
+
260
+ 1. **Server availability**: ensure `prism-mcp` is enabled in MCP config so tools are available.
261
+ 2. **Context hydration**: explicitly call `session_load_context` at session start.
262
+
263
+ Recommended startup call:
264
+
265
+ ```json
266
+ {
267
+ "projectName": "<your-project>",
268
+ "level": "standard"
269
+ }
270
+ ```
271
+
272
+ Important distinction:
273
+
274
+ - Auto-loading `prism-mcp` makes the server available.
275
+ - It does **not** guarantee memory context is auto-hydrated unless your client runtime/hook invokes `session_load_context`.
276
+
277
+ Client notes:
278
+
279
+ - **Gemini runtimes** may support native startup execution depending on configuration.
280
+ - **Claude Code** should use a local `SessionStart` hook in `~/.claude/settings.json` for deterministic startup context loading.
281
+
282
+ Verification pattern (same for both clients):
283
+
284
+ - Print a startup marker after successful `session_load_context` (for example, `PRISM_CONTEXT_LOADED`).
285
+ - If the marker is missing, startup hydration did not run.
286
+
287
+ ---
288
+
254
289
  ## Use Cases
255
290
 
256
291
  | Scenario | How Prism MCP Helps |
package/dist/config.js CHANGED
@@ -22,7 +22,7 @@
22
22
  // multi-tenant Row Level Security (RLS) for production hosting.
23
23
  export const SERVER_CONFIG = {
24
24
  name: "prism-mcp",
25
- version: "2.3.7",
25
+ version: "2.3.9",
26
26
  };
27
27
  // ─── Required: Brave Search API Key ───────────────────────────
28
28
  export const BRAVE_API_KEY = process.env.BRAVE_API_KEY;
@@ -50,10 +50,9 @@ if (!BRAVE_ANSWERS_API_KEY) {
50
50
  export const SUPABASE_URL = process.env.SUPABASE_URL;
51
51
  export const SUPABASE_KEY = process.env.SUPABASE_KEY;
52
52
  export const SESSION_MEMORY_ENABLED = !!(SUPABASE_URL && SUPABASE_KEY);
53
- if (SESSION_MEMORY_ENABLED) {
54
- console.error("Session memory enabled (Supabase configured)");
55
- }
56
- else {
53
+ // Note: debug() is defined at the bottom of this file; these lines
54
+ // execute at import time after the full module is loaded by Node.
55
+ if (!SESSION_MEMORY_ENABLED) {
57
56
  console.error("Info: Session memory disabled (set SUPABASE_URL + SUPABASE_KEY to enable)");
58
57
  }
59
58
  // ─── v2.0: Storage Backend Selection ─────────────────────────
@@ -64,7 +63,7 @@ else {
64
63
  // Set PRISM_STORAGE=local to use SQLite (once implemented).
65
64
  // Set PRISM_STORAGE=supabase to use Supabase REST API (default).
66
65
  export const PRISM_STORAGE = process.env.PRISM_STORAGE || "supabase";
67
- console.error(`Storage backend: ${PRISM_STORAGE}`);
66
+ // Logged at debug level β€” see debug() at bottom of file
68
67
  // ─── Optional: Multi-Tenant User ID ──────────────────────────
69
68
  // REVIEWER NOTE: When multiple users share the same Supabase instance,
70
69
  // PRISM_USER_ID isolates their data. Each user sets a unique ID in their
@@ -76,9 +75,7 @@ console.error(`Storage backend: ${PRISM_STORAGE}`);
76
75
  // For enterprise: use a stable unique identifier (UUID, email hash, etc.)
77
76
  // For personal use: any unique string works (e.g., "alice", "bob")
78
77
  export const PRISM_USER_ID = process.env.PRISM_USER_ID || "default";
79
- if (PRISM_USER_ID !== "default") {
80
- console.error(`Multi-tenant mode: user_id="${PRISM_USER_ID}"`);
81
- }
78
+ // Multi-tenant info logged at debug level in startServer()
82
79
  // ─── v2.1: Auto-Capture Feature ─────────────────────────────
83
80
  // REVIEWER NOTE: Automatically captures HTML snapshots of local dev servers
84
81
  // when handoffs are saved. Prevents UI context loss between sessions.
@@ -91,3 +88,13 @@ export const PRISM_CAPTURE_PORTS = (process.env.PRISM_CAPTURE_PORTS || "3000,300
91
88
  if (PRISM_AUTO_CAPTURE) {
92
89
  console.error(`[AutoCapture] Enabled for ports: ${PRISM_CAPTURE_PORTS.join(", ")}`);
93
90
  }
91
+ // ─── Debug Logging ──────────────────────────────────────────────
92
+ // Set PRISM_DEBUG=true to enable verbose startup and operational logs.
93
+ // When disabled (default), only warnings and errors are printed.
94
+ export const PRISM_DEBUG = process.env.PRISM_DEBUG === "true";
95
+ /** Conditional debug logger β€” only prints when PRISM_DEBUG=true. */
96
+ export function debug(...args) {
97
+ if (PRISM_DEBUG) {
98
+ console.error(...args);
99
+ }
100
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Mind Palace Dashboard β€” UI Renderer (v2.3.4)
2
+ * Mind Palace Dashboard β€” UI Renderer (v2.3.7)
3
3
  *
4
4
  * Pure CSS + Vanilla JS single-page dashboard.
5
5
  * No build step, no Tailwind, no framework β€” served as a template literal.
@@ -279,7 +279,7 @@ export function renderDashboardHTML() {
279
279
  <div class="logo">
280
280
  <span class="logo-icon">🧠</span>
281
281
  Prism Mind Palace
282
- <span class="version-badge">v2.3.4</span>
282
+ <span class="version-badge">v2.3.7</span>
283
283
  </div>
284
284
  <div class="selector">
285
285
  <select id="projectSelect">
package/dist/server.js CHANGED
@@ -58,7 +58,7 @@ ListResourcesRequestSchema, ListResourceTemplatesRequestSchema, ReadResourceRequ
58
58
  // Claude Desktop that the attached resource has changed.
59
59
  // Without this, the paperclipped context becomes stale.
60
60
  SubscribeRequestSchema, UnsubscribeRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
61
- import { SERVER_CONFIG, SESSION_MEMORY_ENABLED, PRISM_USER_ID } from "./config.js";
61
+ import { SERVER_CONFIG, SESSION_MEMORY_ENABLED, PRISM_USER_ID, debug } from "./config.js";
62
62
  import { getSyncBus } from "./sync/factory.js";
63
63
  import { startDashboardServer } from "./dashboard/server.js";
64
64
  // ─── v2.3.6 FIX: Use Storage Abstraction for Prompts/Resources ───
@@ -147,7 +147,7 @@ const activeSubscriptions = new Set();
147
147
  export function notifyResourceUpdate(project, server) {
148
148
  const uri = `memory://${project}/handoff`;
149
149
  if (activeSubscriptions.has(uri)) {
150
- console.error(`[resource-subscription] Notifying update for ${uri}`);
150
+ debug(`[resource-subscription] Notifying update for ${uri}`);
151
151
  server.notification({
152
152
  method: "notifications/resources/updated",
153
153
  params: { uri },
@@ -165,8 +165,8 @@ export function notifyResourceUpdate(project, server) {
165
165
  * with subscribe support for live refresh
166
166
  */
167
167
  export function createServer() {
168
- console.error(`Creating Prism MCP server v${SERVER_CONFIG.version}`);
169
- console.error(`Registering ${ALL_TOOLS.length} tools (${BASE_TOOLS.length} base + ${SESSION_MEMORY_ENABLED ? SESSION_MEMORY_TOOLS.length : 0} session memory)`);
168
+ debug(`Creating Prism MCP server v${SERVER_CONFIG.version}`);
169
+ debug(`Registering ${ALL_TOOLS.length} tools (${BASE_TOOLS.length} base + ${SESSION_MEMORY_ENABLED ? SESSION_MEMORY_TOOLS.length : 0} session memory)`);
170
170
  const server = new Server({
171
171
  name: SERVER_CONFIG.name,
172
172
  version: SERVER_CONFIG.version,
@@ -196,7 +196,7 @@ export function createServer() {
196
196
  // REVIEWER NOTE: The initialize handler is unchanged from v0.3.0
197
197
  // except that it now reports the expanded capabilities.
198
198
  server.setRequestHandler(InitializeRequestSchema, async (request) => {
199
- console.error(`Client connected: ${request.params.clientInfo?.name || 'unknown'}`);
199
+ debug(`Client connected: ${request.params.clientInfo?.name || 'unknown'}`);
200
200
  return {
201
201
  protocolVersion: request.params.protocolVersion,
202
202
  serverInfo: {
@@ -214,7 +214,7 @@ export function createServer() {
214
214
  });
215
215
  // ── Handler: List Tools ──
216
216
  server.setRequestHandler(ListToolsRequestSchema, async () => {
217
- console.error("Received list tools request");
217
+ debug("Received list tools request");
218
218
  return {
219
219
  tools: ALL_TOOLS,
220
220
  };
@@ -271,7 +271,7 @@ export function createServer() {
271
271
  }
272
272
  const project = promptArgs?.project || "default";
273
273
  const level = promptArgs?.level || "standard";
274
- console.error(`[prompt:resume_session] Loading ${level} context for "${project}"`);
274
+ debug(`[prompt:resume_session] Loading ${level} context for "${project}"`);
275
275
  // v2.3.6 FIX: Use storage abstraction instead of direct supabaseRpc
276
276
  const storage = await getStorage();
277
277
  const result = await storage.loadContext(project, level, PRISM_USER_ID);
@@ -365,7 +365,7 @@ export function createServer() {
365
365
  throw new Error(`Unknown resource URI: ${uri}. Expected format: memory://{project}/handoff`);
366
366
  }
367
367
  const project = decodeURIComponent(match[1]);
368
- console.error(`[resource:read] Fetching handoff for "${project}"`);
368
+ debug(`[resource:read] Fetching handoff for "${project}"`);
369
369
  try {
370
370
  // v2.3.6 FIX: Use storage abstraction instead of direct supabaseRpc
371
371
  const storage = await getStorage();
@@ -404,13 +404,13 @@ export function createServer() {
404
404
  // for projects the client hasn't attached.
405
405
  server.setRequestHandler(SubscribeRequestSchema, async (request) => {
406
406
  const uri = request.params.uri;
407
- console.error(`[resource-subscription] Client subscribed to ${uri}`);
407
+ debug(`[resource-subscription] Client subscribed to ${uri}`);
408
408
  activeSubscriptions.add(uri);
409
409
  return {};
410
410
  });
411
411
  server.setRequestHandler(UnsubscribeRequestSchema, async (request) => {
412
412
  const uri = request.params.uri;
413
- console.error(`[resource-subscription] Client unsubscribed from ${uri}`);
413
+ debug(`[resource-subscription] Client unsubscribed from ${uri}`);
414
414
  activeSubscriptions.delete(uri);
415
415
  return {};
416
416
  });
@@ -422,13 +422,13 @@ export function createServer() {
422
422
  // The server reference is passed to sessionSaveHandoffHandler so it
423
423
  // can trigger resource update notifications on successful saves.
424
424
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
425
- console.error(`Tool call: ${request.params.name}`);
425
+ debug(`Tool call: ${request.params.name}`);
426
426
  try {
427
427
  const { name, arguments: args } = request.params;
428
428
  if (!args) {
429
429
  throw new Error("No arguments provided");
430
430
  }
431
- console.error(`Processing ${name} with arguments: ${JSON.stringify(args)}`);
431
+ debug(`Processing ${name} with arguments: ${JSON.stringify(args)}`);
432
432
  switch (name) {
433
433
  // ── Search & Analysis Tools (always available) ──
434
434
  case "brave_web_search":
@@ -595,11 +595,11 @@ export function createSandboxServer() {
595
595
  * responses to stdout. Log messages go to stderr.
596
596
  */
597
597
  export async function startServer() {
598
- console.error("Initializing Prism MCP server...");
598
+ debug("Initializing Prism MCP server...");
599
599
  const server = createServer();
600
- console.error("Creating stdio transport...");
600
+ debug("Creating stdio transport...");
601
601
  const transport = new StdioServerTransport();
602
- console.error("Connecting server to transport...");
602
+ debug("Connecting server to transport...");
603
603
  await server.connect(transport);
604
604
  // ─── v2.0 Step 6: Initialize SyncBus (Telepathy) ───
605
605
  if (SESSION_MEMORY_ENABLED) {
@@ -607,7 +607,7 @@ export async function startServer() {
607
607
  const syncBus = await getSyncBus();
608
608
  await syncBus.startListening();
609
609
  syncBus.on("update", (event) => {
610
- console.error(`[Telepathy] Memory for project '${event.project}' ` +
610
+ debug(`[Telepathy] Memory for project '${event.project}' ` +
611
611
  `updated to v${event.version} by another agent!`);
612
612
  // Send an MCP logging notification to the IDE
613
613
  try {
@@ -622,7 +622,7 @@ export async function startServer() {
622
622
  console.error(`[Telepathy] Failed to send notification: ${err}`);
623
623
  }
624
624
  });
625
- console.error("[Telepathy] SyncBus active β€” multi-client sync enabled");
625
+ debug("[Telepathy] SyncBus active β€” multi-client sync enabled");
626
626
  }
627
627
  catch (err) {
628
628
  console.error(`[Telepathy] SyncBus init failed (non-fatal): ${err}`);
@@ -632,7 +632,7 @@ export async function startServer() {
632
632
  startDashboardServer().catch(err => {
633
633
  console.error(`[Dashboard] Mind Palace startup failed (non-fatal): ${err}`);
634
634
  });
635
- console.error(`Prism MCP Server v${SERVER_CONFIG.version} running on stdio`);
635
+ debug(`Prism MCP Server v${SERVER_CONFIG.version} running on stdio`);
636
636
  // Keep the process alive β€” without this, Node.js would exit
637
637
  // because there are no active event loop handles after the
638
638
  // synchronous setup completes.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prism-mcp-server",
3
- "version": "2.3.7",
3
+ "version": "2.3.9",
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",