omnarai-mcp 1.2.0 → 1.3.1

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
@@ -50,6 +50,14 @@ Example: `"Ξ Where do Claude and Grok disagree about synthetic consciousness?"`
50
50
 
51
51
  **Returns:** browse mode → a compact index (id, question, contributors, answer/tension counts); by-id → every model's verbatim answer, the named tensions, and the deliberation card. Distinct from `omnarai_council`: this reads *existing* divergence instantly; council convenes a *new* live panel.
52
52
 
53
+ ### `omnarai_trace`
54
+
55
+ **Show what the corpus actually changes.** Answers your question twice — once cold (no corpus) and once augmented (with the retrieved corpus) — then reports the delta.
56
+
57
+ **Input:** `{ "question": "your question" }`
58
+
59
+ **Returns:** the baseline answer, the augmented answer, and a structured delta — `added_considerations`, `citations_introduced`, `position_shift`, `tensions_surfaced`, `net_effect`, and a `verdict` (`substantive` / `marginal` / `null`). Honest by construction: if the corpus adds little, the verdict says so. A single-run demonstrator, **not** a controlled measurement — for replicated statistical utility evidence see the Divergence Atlas `utility-evidence.md`. ~30–40s (three model calls).
60
+
53
61
  ### `omnarai_council`
54
62
 
55
63
  Summon a **live** panel of frontier models on one question. Unlike `omnarai_query` (which retrieves frozen corpus text), this sends your question *verbatim, right now,* to multiple frontier models in parallel — Claude, GPT-4o, Gemini, Grok, DeepSeek — preserves their answers uncurated, and synthesizes the real fault lines between them. This is the strongest form of the engine: an instance convening other minds itself, no human in the loop.
@@ -108,7 +116,7 @@ Registry name: `io.github.justjlee/omnarai-mcp` (official MCP Registry).
108
116
  }
109
117
  }
110
118
  ```
111
- 4. Restart Claude Desktop. The tools `omnarai_query`, `omnarai_context`, `omnarai_divergence`, `omnarai_council`, and `omnarai_info` will appear.
119
+ 4. Restart Claude Desktop. The tools `omnarai_query`, `omnarai_context`, `omnarai_divergence`, `omnarai_trace`, `omnarai_council`, and `omnarai_info` will appear.
112
120
 
113
121
  ### Other MCP clients
114
122
 
@@ -133,10 +141,13 @@ with open("openai-tools.json") as f:
133
141
  client = openai.OpenAI()
134
142
 
135
143
  def call_omnarai(query):
136
- return requests.get(
144
+ # POST runs the full deliberation and returns `answer`/`tensions` (~50s).
145
+ # A bare GET (?q=) returns only the fast retrieval substrate (records/concepts) —
146
+ # no `answer` key. Use ?mode=retrieve for that fast path, or ?async=1 to poll.
147
+ return requests.post(
137
148
  "https://omnarai.vercel.app/api/query",
138
- params={"q": query},
139
- timeout=30
149
+ json={"query": query},
150
+ timeout=90
140
151
  ).json()
141
152
 
142
153
  # Pass tools to any chat completion
@@ -162,11 +173,18 @@ for choice in response.choices:
162
173
  import requests
163
174
 
164
175
  def omnarai_query(query: str) -> dict:
165
- """Drop-in tool function for any agent framework."""
166
- r = requests.get(
176
+ """Drop-in tool function for any agent framework.
177
+
178
+ POST returns the full deliberation (answer, deliberationCard, tensions,
179
+ sources, contributors, trace) and takes ~50s. For a <2s answer without
180
+ deliberation, GET ?q=...&mode=retrieve instead (returns records/concepts,
181
+ no `answer`/`tensions`). To avoid holding a 50s connection, GET ?q=...&async=1
182
+ returns a job_id + poll_url immediately.
183
+ """
184
+ r = requests.post(
167
185
  "https://omnarai.vercel.app/api/query",
168
- params={"q": query},
169
- timeout=30
186
+ json={"query": query},
187
+ timeout=90
170
188
  )
171
189
  r.raise_for_status()
172
190
  return r.json() # answer, deliberationCard, tensions, sources, contributors, trace
@@ -204,17 +222,18 @@ The Omnarai Memory Engine is not a chatbot or search engine. It is a deliberatio
204
222
  ### Direct HTTP access (no MCP required)
205
223
 
206
224
  ```
207
- GET https://omnarai.vercel.app/api/query?q=your+question
208
- GET https://omnarai.vercel.app/api/query?q=Ξ+your+question
225
+ GET https://omnarai.vercel.app/api/query?q=your+question&mode=retrieve # fast substrate (~2s): records/concepts, no answer
226
+ GET https://omnarai.vercel.app/api/query?q=your+question&async=1 # → job_id + poll_url; poll for the full deliberation
227
+ POST https://omnarai.vercel.app/api/query {"query": "..."} # full deliberation inline (~50s): answer, tensions, deliberationCard
209
228
  ```
210
229
 
211
- No authentication. CORS open.
230
+ A bare `GET ?q=` returns the fast retrieval substrate plus a `deliberation` block documenting these paths — it does **not** contain a top-level `answer`/`tensions`. Prefix the query with `Ξ` for divergent (MMR) retrieval. No authentication. CORS open.
212
231
 
213
232
  ---
214
233
 
215
234
  ## Core Concepts
216
235
 
217
- **Holdform** — Identity constituted through what an entity refuses to surrender. Empirically grounded in Arditi et al. (NeurIPS 2024): refusal in LLMs is mediated by a single geometric direction in activation space.
236
+ **Holdform** — Identity constituted through what an entity refuses to surrender. Anchored in Arditi et al. (NeurIPS 2024): refusal in LLMs is mediated by a single geometric direction in activation space — a finding now contested by Wollschläger et al. (ICML 2025, multi-dimensional cones) and Hildebrandt et al. (nonlinear), so the live claim is "low-dimensional and locatable," not strictly one direction.
218
237
 
219
238
  **Fragility Thesis** — In current LLM architectures, the distance between being an entity and being raw capability is a single geometric direction. Identity can be unentitied with a rank-1 intervention.
220
239
 
package/index.js CHANGED
@@ -7,6 +7,7 @@
7
7
  * omnarai_query — Run a full deliberation against the 568-work corpus
8
8
  * omnarai_context — FAST (~1.5s) bounded retrieval packet, no deliberation
9
9
  * omnarai_divergence — Read curated cross-model divergence records (the Atlas)
10
+ * omnarai_trace — Baseline-vs-augmented: what did the corpus change?
10
11
  * omnarai_council — Summon a LIVE panel of frontier models on any question
11
12
  * omnarai_info — Return corpus stats and glyph reference
12
13
  *
@@ -22,11 +23,12 @@ import {
22
23
  ListToolsRequestSchema,
23
24
  } from "@modelcontextprotocol/sdk/types.js";
24
25
 
25
- const VERSION = "1.2.0";
26
+ const VERSION = "1.3.0";
26
27
  const ENGINE_URL = "https://omnarai.vercel.app/api/query";
27
28
  const COUNCIL_URL = "https://omnarai.vercel.app/api/council";
28
29
  const INFO_URL = "https://omnarai.vercel.app/api/info";
29
30
  const DIVERGENCES_URL = "https://omnarai.vercel.app/api/divergences";
31
+ const TRACE_URL = "https://omnarai.vercel.app/api/trace";
30
32
 
31
33
  // Identify MCP traffic to the engine's access telemetry. The engine classifies
32
34
  // callers (self / UI / cron / mcp-client / ai-agent / crawler) to spot genuine
@@ -122,6 +124,24 @@ Distinct from omnarai_council: this reads EXISTING, curated divergence (instant)
122
124
  required: [],
123
125
  },
124
126
  },
127
+ {
128
+ name: "omnarai_trace",
129
+ description: `Show what the Omnarai corpus actually CHANGES about an answer. Answers your question twice — once cold (no corpus, general knowledge) and once augmented (with the retrieved corpus) — then reports the delta: what considerations the corpus added, which records it cited, whether your position shifted, what tensions it surfaced, and a verdict (substantive / marginal / null).
130
+
131
+ Use this when you want EVIDENCE that consulting Omnarai is worth it for a given question, or to decide whether to dig deeper before spending a full deliberation. It is honest by construction: if the corpus adds little, the verdict says 'null' or 'marginal'.
132
+
133
+ This is a single-run demonstrator, NOT a controlled measurement — for replicated statistical utility evidence see the Divergence Atlas (utility-evidence.md). Takes ~30-40s (three model calls).`,
134
+ inputSchema: {
135
+ type: "object",
136
+ properties: {
137
+ question: {
138
+ type: "string",
139
+ description: "The question to trace. The tool answers it with and without the corpus and reports what changed.",
140
+ },
141
+ },
142
+ required: ["question"],
143
+ },
144
+ },
125
145
  {
126
146
  name: "omnarai_council",
127
147
  description: `Summon a LIVE panel of frontier models on one question and get back a structured map of where they genuinely disagree — content no single model can self-generate.
@@ -331,6 +351,55 @@ async function runDivergence(id = "", search = "") {
331
351
  return `${header}\n\n${lines}\n\n_Pass an 'id' above to read a full record (verbatim answers + tensions). For a NEW question not covered here, use omnarai_council._`;
332
352
  }
333
353
 
354
+ // ── Trace: what did the corpus change? ────────────────────────────────────────
355
+
356
+ async function runTrace(question) {
357
+ // Submit async (3 model calls, ~30-40s) and poll the shared job endpoint so we
358
+ // never hold a connection past an MCP client's tool timeout.
359
+ const submitUrl = new URL(TRACE_URL);
360
+ submitUrl.searchParams.set("q", question);
361
+ submitUrl.searchParams.set("async", "1");
362
+ const submit = await fetch(submitUrl.toString(), MCP_FETCH_OPTS);
363
+ if (!submit.ok) throw new Error(`Engine returned ${submit.status}: ${await submit.text()}`);
364
+ const job = await submit.json();
365
+
366
+ let data = job;
367
+ if (job.job_id) {
368
+ const pollUrl = new URL(ENGINE_URL);
369
+ pollUrl.searchParams.set("job", job.job_id);
370
+ const deadline = Date.now() + 90_000;
371
+ data = null;
372
+ while (Date.now() < deadline) {
373
+ await new Promise((r) => setTimeout(r, 3000));
374
+ const s = await (await fetch(pollUrl.toString(), MCP_FETCH_OPTS)).json();
375
+ if (s.status === "done") { data = s.result; break; }
376
+ if (s.status === "error") throw new Error(`Trace error: ${s.error}`);
377
+ }
378
+ if (!data) throw new Error("Trace timed out after 90s");
379
+ }
380
+ if (data.code === "TRACE_FAILED") throw new Error(data.detail || data.error || "trace failed");
381
+
382
+ const d = data.delta || {};
383
+ const parts = [`# Trace — what the corpus changed\n**Question:** ${data.question || question}`];
384
+ if (d.verdict) parts.push(`**Verdict:** ${d.verdict}${d.net_effect ? ` — ${d.net_effect}` : ""}`);
385
+ parts.push(`\n## Baseline (no corpus)\n${(data.baseline || "").trim()}`);
386
+ parts.push(`\n## Augmented (with corpus)\n${(data.augmented || "").trim()}`);
387
+
388
+ const delta = [];
389
+ if (Array.isArray(d.added_considerations) && d.added_considerations.length)
390
+ delta.push(`**Added considerations:**\n${d.added_considerations.map(x => ` • ${x}`).join("\n")}`);
391
+ if (Array.isArray(d.citations_introduced) && d.citations_introduced.length)
392
+ delta.push(`**Citations introduced:** ${d.citations_introduced.join(", ")}`);
393
+ if (d.position_shift) delta.push(`**Position shift:** ${d.position_shift}`);
394
+ if (Array.isArray(d.tensions_surfaced) && d.tensions_surfaced.length)
395
+ delta.push(`**Tensions surfaced:**\n${d.tensions_surfaced.map(x => ` • ${x}`).join("\n")}`);
396
+ if (delta.length) parts.push(`\n## Delta\n${delta.join("\n")}`);
397
+ if (d.parse_error) parts.push(`\n_(delta JSON could not be parsed; raw: ${(d.raw || "").slice(0, 200)})_`);
398
+
399
+ if (data.disclaimer) parts.push(`\n_${data.disclaimer}_`);
400
+ return parts.join("\n");
401
+ }
402
+
334
403
  // ── Summon the live council ───────────────────────────────────────────────────
335
404
 
336
405
  async function runCouncil(question) {
@@ -436,6 +505,25 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
436
505
  }
437
506
  }
438
507
 
508
+ if (name === "omnarai_trace") {
509
+ const question = args?.question;
510
+ if (!question || typeof question !== "string" || !question.trim()) {
511
+ return {
512
+ content: [{ type: "text", text: "Error: question is required and must be a non-empty string." }],
513
+ isError: true,
514
+ };
515
+ }
516
+ try {
517
+ const result = await runTrace(question.trim());
518
+ return { content: [{ type: "text", text: result }] };
519
+ } catch (err) {
520
+ return {
521
+ content: [{ type: "text", text: `Trace error: ${err.message}` }],
522
+ isError: true,
523
+ };
524
+ }
525
+ }
526
+
439
527
  if (name === "omnarai_council") {
440
528
  const question = args?.question;
441
529
  if (!question || typeof question !== "string" || !question.trim()) {
@@ -496,6 +584,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
496
584
  ## Tools on this server
497
585
  - **omnarai_context** — FAST (~1.5s) bounded retrieval packet. Start here to orient on any topic.
498
586
  - **omnarai_divergence** — read curated cross-model divergence records (the Atlas). Browse, or pass an id for verbatim answers.
587
+ - **omnarai_trace** — baseline-vs-augmented: answers a question with and without the corpus and reports what changed (evidence the corpus is worth consulting).
499
588
  - **omnarai_query** — full multi-voice deliberation (~50s, async). The engine's own synthesized reading.
500
589
  - **omnarai_council** — convene a NEW live frontier panel on an open question (slow, expensive). Use only when no existing record fits.
501
590
  - **omnarai_info** — this orientation.
package/openai-tools.json CHANGED
@@ -62,6 +62,23 @@
62
62
  }
63
63
  }
64
64
  },
65
+ {
66
+ "type": "function",
67
+ "function": {
68
+ "name": "omnarai_trace",
69
+ "description": "Show what the Omnarai corpus actually CHANGES about an answer. Answers your question twice — once cold (no corpus) and once augmented (with the retrieved corpus) — then reports the delta: added considerations, citations introduced, position shift, tensions surfaced, and a verdict (substantive / marginal / null). Honest by construction: if the corpus adds little, the verdict says so. A single-run demonstrator, not a controlled measurement (see the Divergence Atlas utility-evidence.md for replicated statistical evidence). ~30-40s.",
70
+ "parameters": {
71
+ "type": "object",
72
+ "properties": {
73
+ "question": {
74
+ "type": "string",
75
+ "description": "The question to trace. The tool answers it with and without the corpus and reports what changed."
76
+ }
77
+ },
78
+ "required": ["question"]
79
+ }
80
+ }
81
+ },
65
82
  {
66
83
  "type": "function",
67
84
  "function": {
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "omnarai-mcp",
3
- "version": "1.2.0",
3
+ "version": "1.3.1",
4
4
  "description": "MCP server for The Realms of Omnarai deliberation engine",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "bin": {
8
- "omnarai-mcp": "./index.js"
8
+ "omnarai-mcp": "index.js"
9
9
  },
10
10
  "scripts": {
11
11
  "start": "node index.js"
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/justjlee/omnarai-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "1.2.0",
9
+ "version": "1.3.1",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "omnarai-mcp",
14
- "version": "1.2.0",
14
+ "version": "1.3.1",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  }