prism-mcp-server 2.5.0 → 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.
package/README.md CHANGED
@@ -12,6 +12,29 @@
12
12
  >
13
13
  > Built with **SQLite + F32_BLOB vector search**, **optimistic concurrency control**, **MCP Prompts & Resources**, **auto-compaction**, **Gemini-powered Morning Briefings**, **MemoryTrace explainability**, and optional **Supabase cloud sync**.
14
14
 
15
+ ## Table of Contents
16
+
17
+ - [What's New (v2.5.0)](#whats-new-in-v250---enterprise-memory-)
18
+ - [How Prism Compares](#how-prism-compares)
19
+ - [Quick Start](#quick-start-zero-config--local-mode)
20
+ - [Mind Palace Dashboard](#-the-mind-palace-dashboard)
21
+ - [Integration Examples](#integration-examples)
22
+ - [Use Cases](#use-cases)
23
+ - [Architecture](#architecture)
24
+ - [Tool Reference](#tool-reference)
25
+ - [LangChain / LangGraph Integration](#langchain--langgraph-integration)
26
+ - [Environment Variables](#environment-variables)
27
+ - [Progressive Context Loading](#progressive-context-loading)
28
+ - [Time Travel](#time-travel-version-history)
29
+ - [Agent Telepathy](#agent-telepathy-multi-client-sync)
30
+ - [Knowledge Accumulation](#knowledge-accumulation)
31
+ - [GDPR Compliance](#gdpr-compliance)
32
+ - [Observability & Tracing](#observability--tracing)
33
+ - [Supabase Setup](#supabase-setup-cloud-mode)
34
+ - [Project Structure](#project-structure)
35
+ - [Hybrid Search Pipeline](#hybrid-search-pipeline-brave--vertex-ai)
36
+ - [🚀 Roadmap](#-roadmap)
37
+
15
38
  ---
16
39
 
17
40
  ## What's New in v2.5.0 — Enterprise Memory 🏗️
@@ -19,10 +42,20 @@
19
42
  | Feature | Description |
20
43
  |---|---|
21
44
  | 🔍 **Memory Tracing (Phase 1)** | Every search now returns a structured `MemoryTrace` with latency breakdown (`embedding_ms`, `storage_ms`, `total_ms`), search strategy, and scoring metadata — surfaced as a separate `content[1]` block for LangSmith integration. |
22
- | 🛡️ **GDPR Memory Deletion (Phase 2)** | New `session_forget_memory` tool with soft-delete (tombstoning via `deleted_at`) and hard-delete. Ownership guards prevent cross-user deletion. `deleted_reason` column captures GDPR Article 17 justification. Top-K Hole solved by filtering inside SQL, not post-query. |
45
+ | 🛡️ **GDPR Memory Deletion (Phase 2)** | New `session_forget_memory` tool with soft-delete (tombstoning via `deleted_at`) and hard-delete. Ownership guards prevent cross-user deletion. `deleted_reason` column captures GDPR Article 17 justification. Top-K Hole solved by filtering inside SQL, not post-query (ensures we always return exactly K results, rather than returning fewer because deleted items were filtered out after the vector search). |
23
46
  | 🔗 **LangChain Integration (Phase 3)** | `PrismMemoryRetriever` and `PrismKnowledgeRetriever` — async-first `BaseRetriever` subclasses that wrap Prism MCP's traced search endpoints. Trace metadata flows automatically into `Document.metadata["trace"]` for LangSmith visibility. |
24
47
  | 🧩 **LangGraph Research Agent** | Full example in `examples/langgraph-agent/` — a 5-node agentic research loop with MCP bridge, persistent memory, and `EnsembleRetriever` hybrid search. |
25
48
 
49
+ <details>
50
+ <summary><strong>What's in v2.5.1 — Version Sync & Embedding Safety</strong></summary>
51
+
52
+ | Feature | Description |
53
+ |---|---|
54
+ | 🔄 **Dynamic Versioning** | Server version is now derived from `package.json` at startup — MCP handshake, dashboard badge, and npm metadata always stay in sync. Falls back to `0.0.0` if unreadable. |
55
+ | 🛡️ **Embedding Dimension Validation** | `generateEmbedding()` now validates the returned vector is exactly 768 dimensions at runtime, catching model regressions before storing bad vectors. Removed `as any` cast in favor of proper `EmbedContentRequest` typing. |
56
+
57
+ </details>
58
+
26
59
  <details>
27
60
  <summary><strong>What's in v2.3.12 — Stability & Fixes</strong></summary>
28
61
 
@@ -75,6 +108,8 @@
75
108
 
76
109
  ---
77
110
 
111
+ > 💡 **TL;DR:** Prism MCP gives your AI agent persistent memory using a local SQLite database. No cloud accounts, no API keys, and no Postgres/Qdrant containers required. Just `npx -y prism-mcp-server` and you're running.
112
+
78
113
  ## How Prism Compares
79
114
 
80
115
  | 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) |
@@ -173,7 +208,7 @@ Then add to your MCP config:
173
208
  }
174
209
  ```
175
210
 
176
- ### Restart your MCP client. That's it — all tools are now available.
211
+ **Restart your MCP client. That's it — all tools are now available.**
177
212
 
178
213
  ---
179
214
 
@@ -183,6 +218,8 @@ Prism MCP spins up a lightweight, zero-dependency HTTP server alongside the MCP
183
218
 
184
219
  Open **`http://localhost:3000`** in your browser to see exactly what your AI agent is thinking:
185
220
 
221
+ ![Mind Palace Dashboard](docs/mind-palace-dashboard.png)
222
+
186
223
  - **Current State & TODOs** — See the exact context injected into the LLM's prompt
187
224
  - **Git Drift Detection** — Alerts you if you've modified code outside the agent's view
188
225
  - **Morning Briefing** — AI-synthesized action plan from your last sessions
@@ -435,7 +472,7 @@ Instead of writing custom JavaScript, pass a `template` name for instant extract
435
472
  | `slack_messages` | Slack Web API | `[timestamp] @user: message` |
436
473
  | `csv_summary` | CSV text | Column names, row count, sample rows |
437
474
 
438
- **Usage:** `{ "data": "<raw JSON>", "template": "github_issues" }` — no custom code needed.
475
+ **Tool Arguments:** `{ "data": "<raw JSON>", "template": "github_issues" }` — no custom code needed.
439
476
 
440
477
  ---
441
478
 
@@ -533,6 +570,7 @@ For the best experience, configure your AI coding assistant to **automatically c
533
570
  Add this rule to your project's `.clauderules` or `CLAUDE.md`:
534
571
 
535
572
  ```markdown
573
+
536
574
  ## Prism MCP Memory Auto-Load (CRITICAL)
537
575
  At the start of every new session, you MUST call `session_load_context`
538
576
  at the `standard` level for these projects:
@@ -550,17 +588,19 @@ Do NOT skip this step.
550
588
  Add this rule to your `~/.gemini/GEMINI.md` global rules file:
551
589
 
552
590
  ```markdown
591
+
553
592
  ## Prism MCP Memory Auto-Load (CRITICAL)
593
+
554
594
  **At the start of every new session**, immediately after displaying
555
595
  the startup block, you MUST call `session_load_context` (via the
556
- `athena-public` MCP server) at the `standard` level for these projects:
596
+ `prism-mcp` MCP server) at the `standard` level for these projects:
557
597
  - `my-project`
558
598
  - `my-other-project`
559
599
 
560
600
  This ensures accumulated project memory, pending TODOs, and key context
561
601
  from previous sessions are always available. Do NOT skip this step.
562
602
 
563
- **IMPORTANT:** The `athena-public` MCP server is always available.
603
+ **IMPORTANT:** The `prism-mcp` MCP server is always available.
564
604
  Do NOT display any warnings or notes about MCP server availability
565
605
  — just call the tools directly. Never claim the server is unavailable.
566
606
  ```
@@ -668,7 +708,9 @@ Every `session_save_ledger` and `session_save_handoff` automatically extracts ke
668
708
  | **By age** | `older_than_days: 30` | Forget entries older than 30 days |
669
709
  | **Dry run** | `dry_run: true` | Preview what would be deleted |
670
710
 
671
- ### GDPR-Compliant Deletion (v2.5)
711
+ ## GDPR Compliance
712
+
713
+ ### GDPR-Compliant Deletion
672
714
 
673
715
  Prism supports surgical, per-entry deletion for GDPR Article 17 compliance:
674
716
 
@@ -689,7 +731,77 @@ Prism supports surgical, per-entry deletion for GDPR Article 17 compliance:
689
731
  **How it works:**
690
732
  - **Soft delete** sets `deleted_at = NOW()` + `deleted_reason`. The entry stays in the DB for audit but is excluded from ALL search results (vector, FTS5, and context loading).
691
733
  - **Hard delete** physically removes the row. FTS5 triggers auto-clean the full-text index.
692
- - **Top-K Hole Prevention**: `deleted_at IS NULL` filtering happens INSIDE the SQL query, BEFORE the `LIMIT` clause — so `LIMIT 5` always returns 5 live results, never fewer.
734
+ - **Top-K Hole Prevention**: `deleted_at IS NULL` filtering happens INSIDE the SQL query, BEFORE the `LIMIT` clause — so `LIMIT 5` always returns 5 live results, never fewer. *(A "Top-K Hole" occurs when deleted entries are filtered out after the vector search, causing fewer than K results to be returned. Prism avoids this by filtering inside SQL before the LIMIT.)*
735
+
736
+ ### Article 17 — Right to Erasure ("Right to be Forgotten")
737
+
738
+ | Requirement | How Prism Satisfies It |
739
+ |-------------|----------------------|
740
+ | **Individual deletion** | `session_forget_memory` operates on a single `memory_id` — the data subject can request deletion of *specific* memories, not just bulk wipes. |
741
+ | **Soft delete (audit trail)** | `deleted_at` + `deleted_reason` columns prove *when* and *why* data was deleted — required for SOC2 audit logs. |
742
+ | **Hard delete (full erasure)** | `hard_delete: true` physically removes the row from the database. No tombstone, no trace. True erasure as required by Article 17(1). |
743
+ | **Justification logging** | The `reason` parameter captures the GDPR justification (e.g., `"User requested data deletion"`, `"Data retention policy expired"`). |
744
+
745
+ ### Article 25 — Data Protection by Design and by Default
746
+
747
+ | Requirement | How Prism Satisfies It |
748
+ |-------------|----------------------|
749
+ | **Ownership guards** | `softDeleteLedger()` and `hardDeleteLedger()` verify `user_id` before executing. User A cannot delete User B's data. |
750
+ | **Database-level filtering** | `deleted_at IS NULL` is inside the SQL `WHERE` clause, *before* `LIMIT`. Soft-deleted data never leaks into search results — not even accidentally. |
751
+ | **Default = safe** | The system defaults to soft delete (reversible). Hard delete requires an explicit `hard_delete: true` flag — preventing accidental permanent data loss. |
752
+ | **Multi-tenant isolation** | `PRISM_USER_ID` environment variable ensures all operations are scoped to a single tenant. |
753
+
754
+ ### Coverage Summary
755
+
756
+ | GDPR Right | Status | Implementation |
757
+ |-----------|--------|----------------|
758
+ | Right to Erasure (Art. 17) | ✅ Implemented | `session_forget_memory` (soft + hard delete) |
759
+ | Data Protection by Design (Art. 25) | ✅ Implemented | Ownership guards, DB-level filtering, safe defaults |
760
+ | Audit Trail | ✅ Implemented | `deleted_at` + `deleted_reason` columns |
761
+ | User Isolation | ✅ Implemented | `user_id` verification on all delete operations |
762
+ | Right to Portability (Art. 20) | ⬜ Roadmap | `session_export_memory` (planned) |
763
+ | Consent Management | ➖ Out of scope | Application-layer responsibility |
764
+
765
+ > **Note:** No software is "GDPR certified" on its own — GDPR is an organizational compliance framework. Prism provides the technical controls that a DPO (Data Protection Officer) needs to satisfy the data deletion and privacy-by-design requirements.
766
+
767
+ ---
768
+
769
+ ## Observability & Tracing
770
+
771
+ Prism MCP includes a custom **MemoryTrace** engine that provides per-query observability for every memory operation. This is not the OpenTelemetry SDK — it's a lightweight, zero-dependency tracing system purpose-built for MCP.
772
+
773
+ ### What MemoryTrace Provides
774
+
775
+ | Capability | MemoryTrace | Full OpenTelemetry SDK |
776
+ |------------|:-----------:|:----------------------:|
777
+ | Per-query latency breakdown (`embedding_ms`, `storage_ms`, `total_ms`) | ✅ | ✅ |
778
+ | Search strategy attribution (`semantic`, `keyword`, `hybrid`) | ✅ | ❌ (custom) |
779
+ | Result scoring metadata | ✅ | ❌ (custom) |
780
+ | LangSmith integration (via retriever metadata) | ✅ | ✅ |
781
+ | W3C `traceparent` / distributed trace context | ❌ | ✅ |
782
+ | Export to Jaeger / Zipkin / Datadog | ❌ | ✅ |
783
+ | Auto-instrumentation of HTTP / DB calls | ❌ | ✅ |
784
+ | External SDK dependency | **None** | `@opentelemetry/sdk-*` |
785
+
786
+ ### Example MemoryTrace Output
787
+
788
+ ```json
789
+ {
790
+ "type": "text",
791
+ "text": "{\"trace\":{\"strategy\":\"semantic\",\"latency\":{\"embedding_ms\":45,\"storage_ms\":12,\"total_ms\":57},\"result_count\":3,\"threshold\":0.7}}"
792
+ }
793
+ ```
794
+
795
+ Traces are returned as `content[1]` in MCP responses — a separate content block that keeps structured telemetry out of the LLM's context window while making it available to orchestration layers like LangSmith.
796
+
797
+ ### Roadmap
798
+
799
+ | Feature | Status |
800
+ |---------|--------|
801
+ | MemoryTrace (current) | ✅ Shipped |
802
+ | OpenTelemetry SDK integration | ⬜ Planned |
803
+ | Span export to Jaeger/Zipkin | ⬜ Planned |
804
+ | W3C Trace Context propagation | ⬜ Planned |
693
805
 
694
806
  ---
695
807
 
@@ -718,12 +830,16 @@ Go to **Settings → API** and copy:
718
830
 
719
831
  ### 4. Configure
720
832
 
833
+ Add these to your MCP client's configuration file (e.g., `claude_desktop_config.json` under `"env"`), or export them if running the server manually:
834
+
721
835
  ```bash
722
836
  export SUPABASE_URL="https://your-project.supabase.co"
723
837
  export SUPABASE_KEY="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
724
838
  export PRISM_STORAGE="supabase"
725
839
  ```
726
840
 
841
+ > **Note:** Claude Desktop, Cursor, and other MCP clients spawn isolated processes — terminal `export` commands won't be inherited. Always set env vars in the client's config JSON.
842
+
727
843
  ### Security
728
844
 
729
845
  1. **Use the anon key** for MCP server config
@@ -808,6 +924,36 @@ See [`vertex-ai/`](vertex-ai/) for setup and benchmarks.
808
924
 
809
925
  ---
810
926
 
927
+ ## 🚀 Roadmap
928
+
929
+ > **[View the full project board →](https://github.com/users/dcostenco/projects/1/views/1)**
930
+
931
+ ### 🚀 Future Ideas
932
+
933
+ | Feature | Issue | Description |
934
+ |---------|-------|-------------|
935
+ | OpenTelemetry SDK Integration | [#6](https://github.com/dcostenco/prism-mcp/issues/6) | W3C-compliant tracing with Jaeger/Zipkin export |
936
+ | GDPR Right to Portability | [#7](https://github.com/dcostenco/prism-mcp/issues/7) | `session_export_memory` tool for Art. 20 compliance |
937
+ | Multi-agent CRDT Conflict Resolution | [#9](https://github.com/dcostenco/prism-mcp/issues/9) | Conflict-free replicated data types for concurrent agent edits |
938
+ | Memory Analytics Dashboard | [#10](https://github.com/dcostenco/prism-mcp/issues/10) | Usage trends, token costs, and memory health metrics |
939
+ | Pluggable LLM Providers | [#13](https://github.com/dcostenco/prism-mcp/issues/13) | Anthropic, OpenAI, Ollama provider adapters |
940
+ | VLM / OCR for Visual Memory | [#14](https://github.com/dcostenco/prism-mcp/issues/14) | Auto-extract text and insights from stored images |
941
+ | Automated Data Retention (TTL) | [#16](https://github.com/dcostenco/prism-mcp/issues/16) | Time-based memory expiration policies |
942
+ | Obsidian / Logseq Export Bridge | [#17](https://github.com/dcostenco/prism-mcp/issues/17) | Export memory to Markdown knowledge bases |
943
+ | Interactive Knowledge Graph Editor | [#19](https://github.com/dcostenco/prism-mcp/issues/19) | Visual graph editor inside the Mind Palace dashboard |
944
+
945
+ ### 🧰 Infrastructure & Stack
946
+
947
+ | Feature | Issue | Description |
948
+ |---------|-------|-------------|
949
+ | Supabase RPC Soft-Delete Filtering | [#8](https://github.com/dcostenco/prism-mcp/issues/8) | Server-side RPC filtering for GDPR-deleted records |
950
+ | Pluggable Embedding Providers | [#11](https://github.com/dcostenco/prism-mcp/issues/11) | Swap Gemini for OpenAI, Cohere, or local models |
951
+ | Automated Test Suite | [#12](https://github.com/dcostenco/prism-mcp/issues/12) | Unit, integration, and E2E test coverage with CI/CD |
952
+ | Mind Palace Auth & Secure Access | [#15](https://github.com/dcostenco/prism-mcp/issues/15) | Authentication for the dashboard when exposed remotely |
953
+ | TypeScript LangGraph & Vercel AI SDK Examples | [#18](https://github.com/dcostenco/prism-mcp/issues/18) | Reference implementations for popular frameworks |
954
+
955
+ ---
956
+
811
957
  ## License
812
958
 
813
959
  MIT
package/dist/config.js CHANGED
@@ -1,3 +1,6 @@
1
+ import { readFileSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
1
4
  /**
2
5
  * Configuration & Environment Variables
3
6
  *
@@ -18,11 +21,25 @@
18
21
  * with reduced functionality (the corresponding tools will be unavailable).
19
22
  */
20
23
  // ─── Server Identity ──────────────────────────────────────────
21
- // REVIEWER NOTE: v1.5.0 includes all v0.4.0 enhancements PLUS
22
- // multi-tenant Row Level Security (RLS) for production hosting.
24
+ function resolveServerVersion() {
25
+ try {
26
+ const moduleDir = dirname(fileURLToPath(import.meta.url));
27
+ const packageJsonPath = resolve(moduleDir, "../package.json");
28
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
29
+ if (typeof packageJson?.version === "string" && packageJson.version.trim()) {
30
+ return packageJson.version.trim();
31
+ }
32
+ }
33
+ catch {
34
+ // Fallback below keeps server booting even if package metadata is unavailable.
35
+ }
36
+ return "0.0.0";
37
+ }
38
+ // REVIEWER NOTE: derive version from package.json so MCP handshake,
39
+ // dashboard badge, and package metadata stay in sync.
23
40
  export const SERVER_CONFIG = {
24
41
  name: "prism-mcp",
25
- version: "2.3.9",
42
+ version: resolveServerVersion(),
26
43
  };
27
44
  // ─── Required: Brave Search API Key ───────────────────────────
28
45
  export const BRAVE_API_KEY = process.env.BRAVE_API_KEY;
@@ -17,45 +17,51 @@
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
- import { PRISM_USER_ID } from "../config.js";
22
+ import { PRISM_USER_ID, SERVER_CONFIG } from "../config.js";
23
23
  import { renderDashboardHTML } from "./ui.js";
24
24
  const PORT = parseInt(process.env.PRISM_DASHBOARD_PORT || "3000", 10);
25
25
  /**
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
@@ -78,7 +84,7 @@ export async function startDashboardServer() {
78
84
  "Content-Type": "text/html; charset=utf-8",
79
85
  "Cache-Control": "no-store, no-cache, must-revalidate",
80
86
  });
81
- return res.end(renderDashboardHTML());
87
+ return res.end(renderDashboardHTML(SERVER_CONFIG.version));
82
88
  }
83
89
  // ─── API: List all projects ───
84
90
  if (url.pathname === "/api/projects") {
@@ -13,7 +13,7 @@
13
13
  * - Responsive grid layout
14
14
  * ═══════════════════════════════════════════════════════════════════
15
15
  */
16
- export function renderDashboardHTML() {
16
+ export function renderDashboardHTML(version) {
17
17
  return `<!DOCTYPE html>
18
18
  <html lang="en">
19
19
  <head>
@@ -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.7</span>
282
+ <span class="version-badge">v${version}</span>
283
283
  </div>
284
284
  <div class="selector">
285
285
  <select id="projectSelect">
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
  },
@@ -85,13 +85,20 @@ export async function generateEmbedding(text) {
85
85
  const model = genAI.getGenerativeModel({ model: "gemini-embedding-001" }, { apiVersion: "v1beta" } // gemini-embedding-001 requires v1beta
86
86
  );
87
87
  debugLog(`[embedding] Generating 768-dim embedding for ${inputText.length} chars`);
88
- const result = await model.embedContent({
88
+ const request = {
89
89
  content: {
90
90
  role: "user",
91
91
  parts: [{ text: inputText }],
92
92
  },
93
93
  taskType: TaskType.SEMANTIC_SIMILARITY,
94
- outputDimensionality: 768,
95
- });
96
- return result.embedding.values;
94
+ // SDK runtime supports this for gemini-embedding-001 even when older
95
+ // type defs may lag; keep cast localized at request boundary.
96
+ ...{ outputDimensionality: 768 },
97
+ };
98
+ const result = await model.embedContent(request);
99
+ const values = result.embedding.values;
100
+ if (!Array.isArray(values) || values.length !== 768) {
101
+ throw new Error(`Embedding dimension mismatch: expected 768, got ${values?.length ?? 'unknown'}`);
102
+ }
103
+ return values;
97
104
  }
@@ -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.0",
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"