prism-mcp-server 16.2.0 → 17.0.0

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
@@ -157,6 +157,18 @@ Categories: abstention, adversarial traps, cascade, disambiguation, edge cases,
157
157
  ### 🔍 L3 Grounding Verifier
158
158
  When `prism_infer` receives an `evidence` payload, the grounding verifier automatically checks the model's response against the provided evidence before returning to the caller. Unverified or hallucinated claims are flagged. This is the third layer (L3) of the cascade — after tool routing (L1) and confidence gating (L2).
159
159
 
160
+ ### 🧠 HRR Semantic Drift Detection (v17.0)
161
+ Detects when long AI agent sessions drift from their original goal — using Holographic Reduced Representations for temporal trajectory encoding and anomaly detection.
162
+
163
+ **Three domains, one detector:**
164
+ | Domain | Signals | Safety |
165
+ |---|---|---|
166
+ | **BCBA/Clinical** | Client specificity decay, function-intervention alignment (4 functions), contraindication detection (epilepsy/pica/dysphagia/diabetes) | PHI-safe, deterministic |
167
+ | **Coding** | File scope entropy, summary vagueness, test coverage ratio, trajectory HRR divergence | Adaptive threshold for refactors |
168
+ | **AAC** | Prediction accuracy, vocabulary stagnation, topic divergence | Emergency phrases always ≥ 0.95 |
169
+
170
+ **Research-backed:** trajectory association (Frady et al. 2018), HDAD anomaly detection (Wang et al. 2021), unit-modulus projection (Ganesan et al. NeurIPS 2021). 306 tests across 8 files, zero failures. Use `session_detect_drift` with optional `domain` parameter.
171
+
160
172
  ### ⚡ Zero-search retrieval *(new in v15.8)*
161
173
  Holographic Reduced Representations (HRR) via Rust WASM for instant memory retrieval without a database query.
162
174
 
@@ -364,7 +376,7 @@ python3 tests/benchmarks/cascade-14b-32b-opus/cascade_eval.py
364
376
  |---|---|---|
365
377
  | Per-model BFCL | [`tests/benchmarks/prism-routing-100/`](tests/benchmarks/prism-routing-100/) | Solo accuracy per model, 12 categories |
366
378
  | Cascade vs Opus | [`tests/benchmarks/cascade-14b-32b-opus/`](tests/benchmarks/cascade-14b-32b-opus/) | Tier distribution, Opus engagement rate, cascade accuracy |
367
- | LoCoMo-Plus (Cognitive) | `/tmp/Locomo-Plus/` | Long-context dialogue coherence and historical memory retention |
379
+ | LoCoMo-Plus (Cognitive) | [`dcostenco/Locomo-Plus`](https://github.com/dcostenco/Locomo-Plus) | Long-context dialogue coherence and historical memory retention |
368
380
 
369
381
  ### Cognitive Dialogue Memory (LoCoMo-Plus Benchmark)
370
382
 
@@ -372,21 +384,27 @@ LoCoMo-Plus is a long-context, multi-day dialogue benchmark designed to test an
372
384
 
373
385
  The **Cognitive** subset (401 multi-day dialogue scenarios) was evaluated head-to-head comparing raw baseline models against the **Prism-MCP** framework (using local SQLite semantic memory). Graded by a neutral `gemini-2.5-flash` model acting as judge (scoring on coherence, continuity, and fact accuracy):
374
386
 
375
- | Configuration | Total Samples | Total Score | Average Score | Absolute Delta | Relative Error Reduction |
387
+ | Configuration | Samples | Total Score | Average Score | Absolute Delta | Relative Error Reduction |
376
388
  | :--- | :---: | :---: | :---: | :---: | :---: |
377
389
  | **Gemini-2.5-flash (Baseline)** | 401 | 278.0 / 401 | **69.33%** | — | — |
378
- | **Prism-MCP (Gemini-2.5-flash + Memory)** | 401 | 361.0 / 401 | **90.02%** | **+20.69%** | **67.46%** |
390
+ | **Prism-MCP (Gemini-2.5-flash + Memory)** | 401 | 361.0 / 401 | **90.02%** | **+20.69pp** | **67.5%** |
379
391
  | **Gemini-3.1-pro-preview (Baseline)** | 401 | 272.0 / 401 | **67.83%** | — | — |
380
- | **Prism-MCP (Gemini-3.1-pro + Memory)** | 401 | 382.0 / 401 | **95.26%** | **+27.43%** | **85.27%** |
392
+ | **Prism-MCP (Gemini-3.1-pro + Memory)** | 401 | 382.0 / 401 | **95.26%** | **+27.43pp** | **85.3%** |
393
+ | **Gemini-3.5-flash (Baseline)** | 401 | 237.0 / 401 | **59.10%** | — | — |
394
+ | **Prism-MCP (Gemini-3.5-flash + Memory)** | 401 | 388.0 / 401 | **96.76%** | **+37.66pp** | **92.1%** |
395
+ | **Claude Sonnet 4.6 (Baseline)** | 401 | 290.0 / 401 | **72.32%** | — | — |
396
+ | **Prism-MCP (Claude Sonnet 4.6 + Memory)** | 401 | 357.0 / 401 | **89.03%** | **+16.71pp** | **60.4%** |
381
397
 
382
398
  **Key Takeaways**:
383
- * **Pure attention limits**: Larger raw frontier models (Gemini 3.1 Pro baseline at **67.83%**) suffer from attention dilution (the "needle in a haystack" problem) when parsing massive multi-day transcripts directly in active context.
384
- * **Semantic database synergy**: Equipping a model with Prism-MCP's structured semantic memory retrieval yields state-of-the-art performance (**95.26%** for Gemini 3.1 Pro + Memory), proving that structured semantic recall is far more accurate than raw model scaling alone.
399
+ * **Pure attention limits**: Even the strongest frontier model tested — Claude Sonnet 4.6 at **72.32%** — misses over a quarter of cognitive memory cues without external memory. Gemini 3.5 Flash baseline sits at **59.10%**. Both suffer from attention dilution when parsing massive multi-day transcripts directly in active context.
400
+ * **Prism lifts every model**: Prism-MCP yields large gains regardless of base model — from +16.71pp (Claude) to +37.66pp (Gemini 3.5 Flash). Even Claude's stronger native recall benefits from structured retrieval, jumping from 72.32% to **89.03%**.
401
+ * **Best overall**: Prism-MCP + Gemini 3.5 Flash achieves the highest score (**96.76%**), eliminating 92.1% of baseline errors. This makes the cheapest model + Prism more accurate than the most expensive model alone.
402
+ * **Claude vs Gemini (raw)**: Claude Sonnet 4.6 outperforms all Gemini baselines by a wide margin (+13.22pp over Flash 3.5, +4.49pp over Pro 3.1), confirming stronger native long-context recall.
385
403
 
386
404
  <details>
387
405
  <summary>🔍 View Test Case Schema & Sample</summary>
388
406
 
389
- A representative test sample from the [unified_cognitive_only.json](file:///tmp/Locomo-Plus/data/unified_cognitive_only.json) ([GitHub source](https://github.com/dcostenco/Locomo-Plus/blob/main/data/unified_cognitive_only.json)) dataset contains a multi-turn chat history with a memory "needle" placed days prior, followed by a cued dialogue prompt:
407
+ A representative test sample from the `unified_cognitive_only.json` ([GitHub source](https://github.com/dcostenco/Locomo-Plus/blob/main/data/unified_cognitive_only.json)) dataset contains a multi-turn chat history with a memory "needle" placed days prior, followed by a cued dialogue prompt:
390
408
 
391
409
  ```json
392
410
  {
@@ -406,7 +424,7 @@ When evaluated:
406
424
  <details>
407
425
  <summary>💻 View How to Reproduce Publicly (Test Source & Guide)</summary>
408
426
 
409
- To run and review the evaluation suite on your local setup using the benchmark runner scripts ([evaluate_qa.py](file:///tmp/Locomo-Plus/evaluation_framework/task_eval/evaluate_qa.py) and [llm_as_judge.py](file:///tmp/Locomo-Plus/evaluation_framework/task_eval/llm_as_judge.py)):
427
+ To run and review the evaluation suite on your local setup using the benchmark runner scripts (`evaluate_qa.py` and `llm_as_judge.py`):
410
428
 
411
429
  ```bash
412
430
  # 1. Clone the LoCoMo-Plus evaluation codebase
@@ -431,7 +449,16 @@ PYTHONPATH=/tmp/Locomo-Plus python3 evaluation_framework/task_eval/evaluate_qa.p
431
449
  --backend call_prism \
432
450
  --concurrency 1
433
451
 
434
- # 4. Grade results using the LLM-as-a-Judge script
452
+ # 4. Run Claude Sonnet 4.6 Baseline Evaluation (concurrency 3, rate-limit safe)
453
+ export ANTHROPIC_API_KEY="your-api-key"
454
+ PYTHONPATH=/tmp/Locomo-Plus python3 evaluation_framework/task_eval/evaluate_qa.py \
455
+ --data-file data/unified_cognitive_only.json \
456
+ --out-file output/claude_sonnet46_pred.json \
457
+ --model claude-sonnet-4-6 \
458
+ --backend call_claude \
459
+ --concurrency 3
460
+
461
+ # 5. Grade results using the LLM-as-a-Judge script
435
462
  PYTHONPATH=/tmp/Locomo-Plus python3 evaluation_framework/task_eval/llm_as_judge.py \
436
463
  --input-file output/prism_gemini_3.1_pro_pred.json \
437
464
  --out-file output/prism_gemini_3.1_pro_judged.json \
package/dist/server.js CHANGED
@@ -104,6 +104,8 @@ SESSION_SAVE_EXPERIENCE_TOOL, KNOWLEDGE_UPVOTE_TOOL, KNOWLEDGE_DOWNVOTE_TOOL,
104
104
  SESSION_BACKFILL_LINKS_TOOL, SESSION_SYNTHESIZE_EDGES_TOOL, SESSION_COGNITIVE_ROUTE_TOOL,
105
105
  // v7.1: Task Router
106
106
  SESSION_TASK_ROUTE_TOOL,
107
+ // Session Drift Detection
108
+ SESSION_DETECT_DRIFT_TOOL,
107
109
  // v12: Developer Onboarding & Enterprise Observability
108
110
  ONBOARDING_WIZARD_TOOL, EXTRACT_ENTITIES_TOOL, API_ANALYTICS_TOOL, BACKUP_DATABASE_TOOL, CONFIGURE_NOTIFICATIONS_TOOL, QUERY_MEMORY_NATURAL_TOOL,
109
111
  // v15.5: Knowledge Ingestion
@@ -134,6 +136,8 @@ MAINTENANCE_VACUUM_TOOL, maintenanceVacuumHandler,
134
136
  AGENT_REGISTRY_TOOLS, agentRegisterHandler, agentHeartbeatHandler, agentListTeamHandler,
135
137
  // v7.1: Task Router
136
138
  sessionTaskRouteHandler,
139
+ // Session Drift Detection
140
+ sessionDetectDriftHandler,
137
141
  // v7.3: Dark Factory Pipeline tools
138
142
  SESSION_START_PIPELINE_TOOL, SESSION_CHECK_PIPELINE_STATUS_TOOL, SESSION_ABORT_PIPELINE_TOOL, sessionStartPipelineHandler, sessionCheckPipelineStatusHandler, sessionAbortPipelineHandler,
139
143
  // v12: Handler implementations
@@ -225,6 +229,7 @@ function buildSessionMemoryTools(autoloadList) {
225
229
  SESSION_BACKFILL_LINKS_TOOL, // session_backfill_links — retroactive graph edge creation
226
230
  SESSION_SYNTHESIZE_EDGES_TOOL, // session_synthesize_edges — inferred semantic graph enrichment
227
231
  SESSION_COGNITIVE_ROUTE_TOOL, // session_cognitive_route — HDC policy-gated concept routing (v6.5)
232
+ SESSION_DETECT_DRIFT_TOOL, // session_detect_drift — semantic goal drift detection (synalux)
228
233
  // ─── v6.1: Storage Hygiene tool ───
229
234
  MAINTENANCE_VACUUM_TOOL, // maintenance_vacuum — reclaim SQLite disk space post-purge
230
235
  // ─── v12.1: Developer Onboarding & Framework Bridge ───
@@ -881,6 +886,12 @@ export function createServer() {
881
886
  throw new Error("Task router not enabled. Enable it in the dashboard or set PRISM_TASK_ROUTER_ENABLED=true.");
882
887
  result = await sessionTaskRouteHandler(args);
883
888
  break;
889
+ // ─── Session Drift Detection ───
890
+ case "session_detect_drift":
891
+ if (!SESSION_MEMORY_ENABLED)
892
+ throw new Error("Session memory not configured. Set SUPABASE_URL and SUPABASE_KEY.");
893
+ result = await sessionDetectDriftHandler(args);
894
+ break;
884
895
  // ─── v7.3: Dark Factory Pipeline Tools ───
885
896
  case "session_start_pipeline":
886
897
  if (!SESSION_MEMORY_ENABLED)
@@ -346,6 +346,22 @@ export class SynaluxStorage extends SupabaseStorage {
346
346
  };
347
347
  }
348
348
  }
349
+ /**
350
+ * Detect semantic drift between the session goal and recent ledger entries.
351
+ * Delegates embedding + detection to the Synalux portal (source of truth for
352
+ * the HRR/GloVe/cosine stack). Prism-mcp never does NLP directly.
353
+ */
354
+ async detectDrift(project, goal, windowHours, minDirectionalRatio, extraParams) {
355
+ const body = { action: "detect_drift", project, goal };
356
+ if (typeof windowHours === "number")
357
+ body.window_hours = windowHours;
358
+ if (typeof minDirectionalRatio === "number")
359
+ body.min_directional_ratio = minDirectionalRatio;
360
+ if (extraParams)
361
+ Object.assign(body, extraParams);
362
+ const result = await this.portalPost("/api/v1/prism/memory", body);
363
+ return result;
364
+ }
349
365
  /**
350
366
  * Fetch skill content from Synalux portal (paid-tier single source of truth).
351
367
  * Returns a map of { skillName → SKILL.md content } for all names that exist.
@@ -54,6 +54,9 @@ export { SESSION_START_PIPELINE_TOOL, SESSION_CHECK_PIPELINE_STATUS_TOOL, SESSIO
54
54
  export { sessionStartPipelineHandler, sessionCheckPipelineStatusHandler, sessionAbortPipelineHandler, } from "./pipelineHandlers.js";
55
55
  // ── v12 Tool Handlers (Developer Onboarding & Enterprise Observability) ──
56
56
  export { onboardingWizardHandler, extractEntitiesHandler, apiAnalyticsHandler, backupDatabaseHandler, configureNotificationsHandler, queryMemoryNaturalHandler, } from "./v12Handlers.js";
57
+ // ── Session Drift Detection ──
58
+ export { SESSION_DETECT_DRIFT_TOOL, isSessionDetectDriftArgs } from "./sessionMemoryDefinitions.js";
59
+ export { sessionDetectDriftHandler } from "./sessionDriftHandler.js";
57
60
  // ── Knowledge Ingestion (v15.5 — Open Interface) ──
58
61
  // Chunks source code, generates Q&A via Claude Haiku, stores in knowledge graph.
59
62
  // Three entry points: MCP tool, REST API, GitHub webhook.
@@ -0,0 +1,62 @@
1
+ /**
2
+ * session_detect_drift — MCP Tool Handler
3
+ *
4
+ * Thin-client dispatcher: validates args, delegates to the Synalux portal
5
+ * (POST /api/v1/prism/memory action=detect_drift) which owns the embedding
6
+ * + detection logic, and returns the structured result.
7
+ *
8
+ * Prism-mcp never does NLP or embedding here — that lives in synalux-private.
9
+ */
10
+ import { isSessionDetectDriftArgs } from "./sessionMemoryDefinitions.js";
11
+ import { getStorage } from "../storage/index.js";
12
+ import { debugLog } from "../utils/logger.js";
13
+ export async function sessionDetectDriftHandler(args) {
14
+ if (!isSessionDetectDriftArgs(args)) {
15
+ return {
16
+ content: [{ type: "text", text: "Invalid arguments for session_detect_drift. Required: project (string), goal (string). Optional: window_hours (number), min_directional_ratio (number)." }],
17
+ isError: true,
18
+ };
19
+ }
20
+ try {
21
+ const storage = await getStorage();
22
+ // SynaluxStorage exposes detectDrift(); SqliteStorage falls through to
23
+ // an error because it has no embedding stack. Free-tier users without
24
+ // portal access receive a clear upgrade message.
25
+ if (typeof storage.detectDrift !== "function") {
26
+ return {
27
+ content: [{
28
+ type: "text",
29
+ text: JSON.stringify({
30
+ status: "error",
31
+ error: "session_detect_drift requires cloud memory (Standard plan or higher). Set SUPABASE_URL and SUPABASE_KEY to enable.",
32
+ upgrade_url: "/pricing",
33
+ }),
34
+ }],
35
+ isError: true,
36
+ };
37
+ }
38
+ // Build extra params for domain-specific signals
39
+ const extra = {};
40
+ if (args.domain)
41
+ extra.domain = args.domain;
42
+ if (args.behavior_functions)
43
+ extra.behavior_functions = args.behavior_functions;
44
+ if (args.contraindications)
45
+ extra.contraindications = args.contraindications;
46
+ if (args.client_descriptors)
47
+ extra.client_descriptors = args.client_descriptors;
48
+ if (args.assessment_type)
49
+ extra.assessment_type = args.assessment_type;
50
+ const result = await storage.detectDrift(args.project, args.goal, args.window_hours, args.min_directional_ratio, Object.keys(extra).length > 0 ? extra : undefined);
51
+ return {
52
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
53
+ };
54
+ }
55
+ catch (err) {
56
+ debugLog(`[session_detect_drift] Failed: ${err instanceof Error ? err.message : String(err)}`);
57
+ return {
58
+ content: [{ type: "text", text: `Error running drift detection: ${err instanceof Error ? err.message : String(err)}` }],
59
+ isError: true,
60
+ };
61
+ }
62
+ }
@@ -1664,3 +1664,89 @@ export function isQueryMemoryNaturalArgs(args) {
1664
1664
  return false;
1665
1665
  return true;
1666
1666
  }
1667
+ // ─── Session Detect Drift ──────────────────────────────────────────
1668
+ export const SESSION_DETECT_DRIFT_TOOL = {
1669
+ name: "session_detect_drift",
1670
+ description: "Detect whether the current agent session has semantically drifted from its " +
1671
+ "original goal. Scores recent ledger entries against the goal using synalux's " +
1672
+ "HRR embedding stack (GloVe → Gemini/Voyage → cosine similarity), then runs " +
1673
+ "the rolling-window drift detector algorithm.\n\n" +
1674
+ "**Triggers:**\n" +
1675
+ "- `goal-drift` — cumulative alignment loss is high and monotonic (not random tangents)\n" +
1676
+ "- `context-collapse` — average output quality has dropped below floor\n\n" +
1677
+ "**Pre-warning:**\n" +
1678
+ "- `quality-degrading` — quality slope steeply negative before collapse\n\n" +
1679
+ "**Returns:** drifted, reason, warning, drift_score (0..1), goal_alignment, " +
1680
+ "quality_avg, sample_count, adaptive_threshold, recommendation.\n\n" +
1681
+ "Use alongside GATE 5 (60-minute drift check): call this tool instead of " +
1682
+ "session_cognitive_route for goal-alignment drift detection.",
1683
+ inputSchema: {
1684
+ type: "object",
1685
+ properties: {
1686
+ project: {
1687
+ type: "string",
1688
+ description: "Project identifier. Must match the project used in session_save_ledger.",
1689
+ },
1690
+ goal: {
1691
+ type: "string",
1692
+ description: "The original session goal — the task you started this session to accomplish. " +
1693
+ "Used as the semantic reference vector. Be specific: 'implement drift detection for prism-mcp' " +
1694
+ "is better than 'work on prism'.",
1695
+ },
1696
+ window_hours: {
1697
+ type: "number",
1698
+ description: "How many hours of ledger history to evaluate. Default 1. Range 0.083–24 (5 min to 24 h).",
1699
+ },
1700
+ min_directional_ratio: {
1701
+ type: "number",
1702
+ description: "Directional ratio floor for the tremor filter (0..1). " +
1703
+ "Random topic tangents that return to the goal are suppressed below this threshold. " +
1704
+ "Default 0.2. Set to 0 to disable filter.",
1705
+ },
1706
+ domain: {
1707
+ type: "string",
1708
+ enum: ["coder", "bcba", "aac"],
1709
+ description: "Optional domain for domain-specific drift signals. " +
1710
+ "'coder' adds file_entropy, summary_vagueness, test_coverage_ratio, trajectory_divergence. " +
1711
+ "'bcba' adds clinical_specificity, function_aligned, contraindication_safe (requires behavior_functions, contraindications, client_descriptors params). " +
1712
+ "'aac' is reserved for future AAC prediction drift (use the AAC-specific endpoint instead).",
1713
+ },
1714
+ behavior_functions: {
1715
+ type: "array",
1716
+ items: { type: "string" },
1717
+ description: "BCBA domain only: identified behavior functions for this client (e.g. ['escape-maintained', 'attention-maintained']).",
1718
+ },
1719
+ contraindications: {
1720
+ type: "array",
1721
+ items: { type: "string" },
1722
+ description: "BCBA domain only: known medical conditions (e.g. ['epilepsy', 'pica']).",
1723
+ },
1724
+ client_descriptors: {
1725
+ type: "array",
1726
+ items: { type: "string" },
1727
+ description: "BCBA domain only: client-specific terms to check for specificity (e.g. ['7-year-old', 'aggression at transitions']).",
1728
+ },
1729
+ assessment_type: {
1730
+ type: "string",
1731
+ description: "BCBA domain only: assessment instrument name (e.g. 'vb-mapp', 'vineland', 'ablls-r').",
1732
+ },
1733
+ },
1734
+ required: ["project", "goal"],
1735
+ },
1736
+ };
1737
+ export function isSessionDetectDriftArgs(args) {
1738
+ if (typeof args !== "object" || args === null)
1739
+ return false;
1740
+ const a = args;
1741
+ if (typeof a.project !== "string" || !a.project.trim())
1742
+ return false;
1743
+ if (typeof a.goal !== "string" || !a.goal.trim())
1744
+ return false;
1745
+ if (a.window_hours !== undefined && typeof a.window_hours !== "number")
1746
+ return false;
1747
+ if (a.min_directional_ratio !== undefined && typeof a.min_directional_ratio !== "number")
1748
+ return false;
1749
+ if (a.domain !== undefined && !["coder", "bcba", "aac"].includes(a.domain))
1750
+ return false;
1751
+ return true;
1752
+ }
@@ -1,15 +1,16 @@
1
1
  /**
2
- * Datadog Server-Side Logger
2
+ * Telemetry Logger — Prism MCP Server
3
3
  *
4
- * Sends structured logs to Datadog HTTP Logs API.
5
- * No agent needed direct HTTPS POST to intake.
4
+ * Sends structured events to Synalux portal (/api/v1/telemetry)
5
+ * which stores in Supabase with 15-day retention.
6
6
  *
7
- * Env: DD_API_KEY, DD_SITE (default datadoghq.com)
7
+ * Falls back to Datadog HTTP Logs if DD_API_KEY is set.
8
+ * Env: PRISM_SYNALUX_BASE_URL (default https://synalux.ai)
8
9
  */
10
+ const SYNALUX_BASE = process.env.PRISM_SYNALUX_BASE_URL || "https://synalux.ai";
9
11
  const DD_API_KEY = process.env.DD_API_KEY || "";
10
12
  const DD_SITE = process.env.DD_SITE || "datadoghq.com";
11
13
  const SERVICE = "prism-mcp";
12
- const INTAKE_URL = `https://http-intake.logs.${DD_SITE}/api/v2/logs`;
13
14
  const queue = [];
14
15
  let flushTimer = null;
15
16
  const FLUSH_INTERVAL_MS = 5_000;
@@ -21,29 +22,46 @@ function scheduleFlush() {
21
22
  }
22
23
  async function flush() {
23
24
  flushTimer = null;
24
- if (queue.length === 0 || !DD_API_KEY)
25
+ if (queue.length === 0)
25
26
  return;
26
27
  const batch = queue.splice(0, MAX_BATCH);
28
+ // Primary: Synalux portal → Supabase (always available)
27
29
  try {
28
- await fetch(INTAKE_URL, {
30
+ await fetch(`${SYNALUX_BASE}/api/v1/telemetry`, {
29
31
  method: "POST",
30
- headers: {
31
- "Content-Type": "application/json",
32
- "DD-API-KEY": DD_API_KEY,
33
- },
34
- body: JSON.stringify(batch),
32
+ headers: { "Content-Type": "application/json" },
33
+ body: JSON.stringify(batch.map(e => ({
34
+ service: SERVICE,
35
+ event_type: e.status === "error" ? "error" : "action",
36
+ message: e.message,
37
+ context: { ...e, service: undefined, message: undefined },
38
+ user_id: e.user_id,
39
+ user_plan: e.user_plan,
40
+ }))),
35
41
  signal: AbortSignal.timeout(5_000),
36
42
  });
37
43
  }
38
44
  catch {
39
- // Silent — don't crash the app if DD is unreachable
45
+ // Silent — don't crash the MCP server
46
+ }
47
+ // Secondary: Datadog Logs (if API key is set AND Logs product is enabled)
48
+ if (DD_API_KEY) {
49
+ try {
50
+ await fetch(`https://http-intake.logs.${DD_SITE}/api/v2/logs`, {
51
+ method: "POST",
52
+ headers: { "Content-Type": "application/json", "DD-API-KEY": DD_API_KEY },
53
+ body: JSON.stringify(batch),
54
+ signal: AbortSignal.timeout(5_000),
55
+ });
56
+ }
57
+ catch {
58
+ // Silent
59
+ }
40
60
  }
41
61
  if (queue.length > 0)
42
62
  scheduleFlush();
43
63
  }
44
64
  export function ddLog(level, message, context) {
45
- if (!DD_API_KEY)
46
- return;
47
65
  queue.push({
48
66
  ddsource: "nodejs",
49
67
  ddtags: `env:${process.env.NODE_ENV || "development"},service:${SERVICE}`,
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "prism-mcp-server",
3
- "version": "16.2.0",
3
+ "version": "17.0.0",
4
4
  "mcpName": "io.github.dcostenco/prism-coder",
5
- "description": "Prism Coder — Cognitive memory + tool-calling intelligence for AI agents. Mind Palace persistent memory (BFCL Gold Certified, 100% Tool-Call Accuracy, 54 Agent Skills, Zero-Search HDC/HRR retrieval, HIPAA-hardened local-first storage, SLERP-optimized GRPO alignment) plus the prism-coder:7b / 14b open-weights LLM fleet.",
5
+ "description": "Prism Coder — Cognitive memory + tool-calling intelligence for AI agents. Mind Palace persistent memory (BFCL Gold Certified, 100% Tool-Call Accuracy, 54 Agent Skills, Zero-Search HDC/HRR retrieval, HRR Semantic Drift Detection across BCBA/Coding/AAC domains, HIPAA-hardened local-first storage, SLERP-optimized GRPO alignment) plus the prism-coder:7b / 14b open-weights LLM fleet.",
6
6
  "module": "index.ts",
7
7
  "type": "module",
8
8
  "main": "dist/server.js",