prism-mcp-server 2.3.5 → 2.3.7

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
@@ -54,6 +54,7 @@
54
54
 
55
55
  | Feature | **Prism MCP** | [MCP Memory](https://github.com/modelcontextprotocol/servers/tree/main/src/memory) | [Mem0](https://github.com/mem0ai/mem0) | [Mnemory](https://github.com/fpytloun/mnemory) | [Basic Memory](https://github.com/basicmachines-co/basic-memory) |
56
56
  |---|---|---|---|---|---|
57
+ | **Pricing** | ✅ Free & open source (MIT) | ✅ Free & open source (MIT) | Freemium (free 10K memories; paid Pro) | ✅ Free & open source | Freemium (OSS core free; paid Pro) |
57
58
  | **Storage** | SQLite (local) + Supabase (cloud) | JSON file | Postgres + Qdrant (hosted or self-hosted) | Qdrant + S3/MinIO | Markdown files |
58
59
  | **Zero Config** | ✅ `npx -y prism-mcp-server` | ✅ | ❌ Requires Qdrant/Postgres | ✅ `uvx mnemory` | ✅ `pip install basic-memory` |
59
60
  | **Semantic Search** | ✅ F32_BLOB vectors + FTS5 | ❌ | ✅ pgvector | ✅ Qdrant vectors | ❌ Text search only |
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.4",
25
+ version: "2.3.7",
26
26
  };
27
27
  // ─── Required: Brave Search API Key ───────────────────────────
28
28
  export const BRAVE_API_KEY = process.env.BRAVE_API_KEY;
package/dist/server.js CHANGED
@@ -61,12 +61,13 @@ SubscribeRequestSchema, UnsubscribeRequestSchema, } from "@modelcontextprotocol/
61
61
  import { SERVER_CONFIG, SESSION_MEMORY_ENABLED, PRISM_USER_ID } from "./config.js";
62
62
  import { getSyncBus } from "./sync/factory.js";
63
63
  import { startDashboardServer } from "./dashboard/server.js";
64
- // ─── v0.4.0: Supabase API imports for Prompts/Resources handlers ───
65
- // REVIEWER NOTE: The prompt and resource handlers need direct access
66
- // to supabaseRpc and supabaseGet to fetch context. In v0.3.0, only
67
- // the handler files imported from supabaseApi. Now server.ts needs
68
- // them too for the prompt/resource request handlers.
69
- import { supabaseRpc, supabaseGet } from "./utils/supabaseApi.js";
64
+ // ─── v2.3.6 FIX: Use Storage Abstraction for Prompts/Resources ───
65
+ // CRITICAL FIX: Previously imported supabaseRpc/supabaseGet directly,
66
+ // which bypassed the storage abstraction layer and caused the server
67
+ // to crash (EOF) when the Supabase REST call failed without a proper
68
+ // error wrapper. Now uses getStorage() which routes through the
69
+ // correct backend (Supabase or SQLite) with proper error handling.
70
+ import { getStorage } from "./storage/index.js";
70
71
  // ─── Import Tool Definitions (schemas) and Handlers (implementations) ─────
71
72
  import { WEB_SEARCH_TOOL, BRAVE_WEB_SEARCH_CODE_MODE_TOOL, LOCAL_SEARCH_TOOL, BRAVE_LOCAL_SEARCH_CODE_MODE_TOOL, CODE_MODE_TRANSFORM_TOOL, BRAVE_ANSWERS_TOOL, RESEARCH_PAPER_ANALYSIS_TOOL, webSearchHandler, braveWebSearchCodeModeHandler, localSearchHandler, braveLocalSearchCodeModeHandler, codeModeTransformHandler, braveAnswersHandler, researchPaperAnalysisHandler, } from "./tools/index.js";
72
73
  // Session memory tools — only used if Supabase is configured
@@ -271,14 +272,10 @@ export function createServer() {
271
272
  const project = promptArgs?.project || "default";
272
273
  const level = promptArgs?.level || "standard";
273
274
  console.error(`[prompt:resume_session] Loading ${level} context for "${project}"`);
274
- // Fetch context using the same RPC as session_load_context
275
- // v1.5.0: Pass p_user_id for multi-tenant isolation
276
- const result = await supabaseRpc("get_session_context", {
277
- p_project: project,
278
- p_level: level,
279
- p_user_id: PRISM_USER_ID,
280
- });
281
- const data = Array.isArray(result) ? result[0] : result;
275
+ // v2.3.6 FIX: Use storage abstraction instead of direct supabaseRpc
276
+ const storage = await getStorage();
277
+ const result = await storage.loadContext(project, level, PRISM_USER_ID);
278
+ const data = result;
282
279
  // REVIEWER NOTE: We include the version in the prompt text so
283
280
  // the LLM knows to pass it back when saving. This is critical
284
281
  // for OCC (Enhancement #5) to work even when context is loaded
@@ -343,28 +340,25 @@ export function createServer() {
343
340
  }));
344
341
  // List concrete resources — one per known project
345
342
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
346
- // REVIEWER NOTE: We query Supabase for all projects that have
347
- // a handoff entry. This gives Claude Desktop a browsable list
348
- // of all projects with saved state. The select fields are
349
- // minimal to keep the response lightweight.
350
- const handoffs = await supabaseGet("session_handoffs", {
351
- select: "project,last_summary,updated_at",
352
- });
353
- return {
354
- resources: (Array.isArray(handoffs) ? handoffs : []).map((h) => ({
355
- uri: `memory://${h.project}/handoff`,
356
- name: `${h.project} — Session State`,
357
- description: h.last_summary
358
- ? h.last_summary.substring(0, 200)
359
- : "No summary available",
360
- mimeType: "application/json",
361
- })),
362
- };
343
+ // v2.3.6 FIX: Use storage abstraction instead of direct supabaseGet
344
+ try {
345
+ const storage = await getStorage();
346
+ const projects = await storage.listProjects();
347
+ return {
348
+ resources: projects.map((p) => ({
349
+ uri: `memory://${p}/handoff`,
350
+ name: `${p} — Session State`,
351
+ mimeType: "application/json",
352
+ })),
353
+ };
354
+ }
355
+ catch (error) {
356
+ console.error(`[resource:list] Error listing resources: ${error}`);
357
+ return { resources: [] };
358
+ }
363
359
  });
364
360
  // Read a specific project's handoff as a resource
365
361
  server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
366
- // REVIEWER NOTE: Parse the project name from the URI.
367
- // URI format: memory://{project}/handoff
368
362
  const uri = request.params.uri;
369
363
  const match = uri.match(/^memory:\/\/(.+)\/handoff$/);
370
364
  if (!match) {
@@ -372,32 +366,35 @@ export function createServer() {
372
366
  }
373
367
  const project = decodeURIComponent(match[1]);
374
368
  console.error(`[resource:read] Fetching handoff for "${project}"`);
375
- // Reuse the same RPC as session_load_context — standard level
376
- // gives a good balance of info without being too large.
377
- // REVIEWER NOTE: The RPC response includes `version` (added in
378
- // migration 019), which the LLM needs for OCC when saving later.
379
- // v1.5.0: Pass p_user_id for multi-tenant isolation
380
- const result = await supabaseRpc("get_session_context", {
381
- p_project: project,
382
- p_level: "standard",
383
- p_user_id: PRISM_USER_ID,
384
- });
385
- const data = Array.isArray(result) ? result[0] : result;
386
- // REVIEWER NOTE: Inject explicit OCC instructions into the
387
- // resource text so the LLM knows to pass version on save.
388
- const resourceData = data || { status: "no_session_found", project };
389
- if (data?.version) {
390
- resourceData._occ_instruction =
391
- `When saving handoff state, you MUST pass expected_version: ${data.version} ` +
392
- `to prevent state collisions with other sessions.`;
369
+ try {
370
+ // v2.3.6 FIX: Use storage abstraction instead of direct supabaseRpc
371
+ const storage = await getStorage();
372
+ const data = await storage.loadContext(project, "standard", PRISM_USER_ID);
373
+ const resourceData = data || { status: "no_session_found", project };
374
+ if (data?.version) {
375
+ resourceData._occ_instruction =
376
+ `When saving handoff state, you MUST pass expected_version: ${data.version} ` +
377
+ `to prevent state collisions with other sessions.`;
378
+ }
379
+ return {
380
+ contents: [{
381
+ uri: uri,
382
+ mimeType: "application/json",
383
+ text: JSON.stringify(resourceData, null, 2),
384
+ }],
385
+ };
386
+ }
387
+ catch (error) {
388
+ console.error(`[resource:read] Error reading resource ${uri}: ${error}`);
389
+ return {
390
+ isError: true,
391
+ contents: [{
392
+ uri: uri,
393
+ mimeType: "text/plain",
394
+ text: `Error reading resource: ${error instanceof Error ? error.message : String(error)}`,
395
+ }],
396
+ };
393
397
  }
394
- return {
395
- contents: [{
396
- uri: uri,
397
- mimeType: "application/json",
398
- text: JSON.stringify(resourceData, null, 2),
399
- }],
400
- };
401
398
  });
402
399
  // ─── Resource Subscriptions: subscribe/unsubscribe ───
403
400
  // REVIEWER NOTE: These handlers track which resource URIs the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prism-mcp-server",
3
- "version": "2.3.5",
3
+ "version": "2.3.7",
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",