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 +153 -7
- package/dist/config.js +20 -3
- package/dist/dashboard/server.js +38 -32
- package/dist/dashboard/ui.js +2 -2
- package/dist/server.js +9 -25
- package/dist/utils/embeddingApi.js +11 -4
- package/dist/utils/googleAi.js +1 -1
- package/package.json +2 -2
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
|
-
|
|
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
|
+

|
|
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
|
-
**
|
|
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
|
-
`
|
|
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 `
|
|
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
|
-
|
|
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
|
-
|
|
22
|
-
|
|
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:
|
|
42
|
+
version: resolveServerVersion(),
|
|
26
43
|
};
|
|
27
44
|
// ─── Required: Brave Search API Key ───────────────────────────
|
|
28
45
|
export const BRAVE_API_KEY = process.env.BRAVE_API_KEY;
|
package/dist/dashboard/server.js
CHANGED
|
@@ -17,45 +17,51 @@
|
|
|
17
17
|
* ═══════════════════════════════════════════════════════════════════
|
|
18
18
|
*/
|
|
19
19
|
import * as http from "http";
|
|
20
|
-
import {
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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") {
|
package/dist/dashboard/ui.js
CHANGED
|
@@ -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">
|
|
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,
|
|
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
|
-
//
|
|
200
|
-
//
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
|
|
88
|
+
const request = {
|
|
89
89
|
content: {
|
|
90
90
|
role: "user",
|
|
91
91
|
parts: [{ text: inputText }],
|
|
92
92
|
},
|
|
93
93
|
taskType: TaskType.SEMANTIC_SIMILARITY,
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
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
|
}
|
package/dist/utils/googleAi.js
CHANGED
|
@@ -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" }
|
|
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.
|
|
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.
|
|
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"
|