openzoo 0.34.11 → 0.35.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.
Files changed (2) hide show
  1. package/lib/mcp.js +86 -0
  2. package/package.json +1 -1
package/lib/mcp.js CHANGED
@@ -7,6 +7,7 @@ import { PayClient, QuoteTooHighError, UnderfundedError } from './pay.js';
7
7
  import { tokenBalance } from './x402.js';
8
8
  import { askWithContext, contextCacheDisabled, BIND_MIN_CHARS } from './hrr.js';
9
9
  import { listContexts } from './contexts.js';
10
+ import { withNamespace } from './namespace.js';
10
11
 
11
12
  const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
12
13
  // The model zoo_ask uses when the caller does not name one. Opus 5 by default:
@@ -291,6 +292,47 @@ export function buildMcpServer() {
291
292
  }
292
293
  });
293
294
 
295
+ // leCore's own catalog — leCore docs/ZOO.md §1. Rule-0 for the model: ask the
296
+ // engine whether a faculty exists BEFORE writing the algorithm yourself.
297
+ // 3,214 capabilities; a curated tools/list would hide almost all of them, so
298
+ // discovery is a search and execution is one generic tool, exactly as leCore
299
+ // ships it over its own MCP.
300
+ server.registerTool('zoo_lecore_find', {
301
+ description:
302
+ 'BEFORE implementing any algorithm, search leCore for it — 3,214 verified capabilities '
303
+ + '(nearest-neighbour search, float compression, mesh ops, certified image operators, physics '
304
+ + 'stepping, forecasting, corpus QA, bootstrap CIs, void/discovery, program-to-weights). '
305
+ + 'Hand-rolling what this returns is wasted tokens and worse code. Free, no payment.',
306
+ inputSchema: {
307
+ query: z.string().describe('What you are trying to do, in plain words: "nearest neighbour search", "compress floats".'),
308
+ top: z.number().int().positive().optional().describe('How many hits. Default 8.'),
309
+ },
310
+ }, async ({ query, top }) => {
311
+ const r = await fetch(`${config.apiBase}/v1/lecore/find`, {
312
+ method: 'POST', headers: withNamespace({ 'content-type': 'application/json' }),
313
+ body: JSON.stringify({ query, top: top ?? 8 }),
314
+ });
315
+ return text(await r.json());
316
+ });
317
+
318
+ server.registerTool('zoo_lecore_invoke', {
319
+ description:
320
+ 'Run any leCore capability by name (find it first with zoo_lecore_find). Returns the result plus '
321
+ + 'measured cost {elapsed_ms, payload_bytes} and a determinism receipt {input_sha256, output_sha256} — '
322
+ + 'the same call with the same args always produces the same output hash, so results are verifiable '
323
+ + 'and cacheable. Free, no payment.',
324
+ inputSchema: {
325
+ name: z.string().describe('Capability name exactly as zoo_lecore_find returned it.'),
326
+ args: z.record(z.any()).optional().describe('Arguments object for the capability.'),
327
+ },
328
+ }, async ({ name, args }) => {
329
+ const r = await fetch(`${config.apiBase}/v1/lecore/invoke`, {
330
+ method: 'POST', headers: withNamespace({ 'content-type': 'application/json' }),
331
+ body: JSON.stringify({ name, args: args || {} }),
332
+ });
333
+ return text(await r.json());
334
+ });
335
+
294
336
  server.registerTool('zoo_contexts', {
295
337
  description: 'List corpora already bound to the zoo\'s holographic memory (local manifest). A listed corpus is never re-uploaded — asks against it are near-free.',
296
338
  inputSchema: {},
@@ -301,6 +343,50 @@ export function buildMcpServer() {
301
343
  })),
302
344
  }));
303
345
 
346
+ // OUROBOROS — the model's durable external memory, managed server-side by
347
+ // leCore (docs/ZOO.md §7-8). memory_write stores a fact into a per-wallet
348
+ // partition; memory_search recalls ranked, best first, across sessions. The
349
+ // namespace header keys the partition to THIS wallet. Free (infrastructure),
350
+ // and every response carries a deterministic lecore.receipt.
351
+ const memHeaders = () => withNamespace({ 'content-type': 'application/json' });
352
+
353
+ server.registerTool('zoo_remember', {
354
+ description: 'OUROBOROS: store a fact/decision into your durable external memory (leCore, server-side). Findable later by zoo_recall across sessions — you HAVE persistent memory; write to it instead of losing context.',
355
+ inputSchema: {
356
+ text: z.string().describe('the fact, decision, or note to remember'),
357
+ tags: z.array(z.string()).optional().describe('optional tags to group/filter later'),
358
+ },
359
+ }, async ({ text: t, tags }) => {
360
+ try {
361
+ const r = await fetch(`${config.apiBase}/v1/memory/write`, {
362
+ method: 'POST', headers: memHeaders(),
363
+ body: JSON.stringify({ text: t, tags: tags || [] }),
364
+ });
365
+ const d = await r.json();
366
+ if (!r.ok) return text({ error: d?.error || `memory_write HTTP ${r.status}` });
367
+ return text({ stored: d.stored, id: d.id, total_memories: d.entries, receipt: d._meta?.['lecore.receipt']?.output_sha256?.slice(0, 16) });
368
+ } catch (e) { return text({ error: `zoo_remember failed: ${e.message}` }); }
369
+ });
370
+
371
+ server.registerTool('zoo_recall', {
372
+ description: 'OUROBOROS: recall from your durable external memory — ranked results, best first, across all past sessions. Check here BEFORE claiming you do not remember something.',
373
+ inputSchema: {
374
+ query: z.string().describe('what to recall'),
375
+ top: z.number().int().min(1).max(50).optional().describe('how many results (default 4)'),
376
+ tags: z.array(z.string()).optional().describe('restrict to these tags'),
377
+ },
378
+ }, async ({ query, top, tags }) => {
379
+ try {
380
+ const r = await fetch(`${config.apiBase}/v1/memory/search`, {
381
+ method: 'POST', headers: memHeaders(),
382
+ body: JSON.stringify({ query, top: top || 4, ...(tags ? { tags } : {}) }),
383
+ });
384
+ const d = await r.json();
385
+ if (!r.ok) return text({ error: d?.error || `memory_search HTTP ${r.status}` });
386
+ return text({ hits: (d.hits || []).map((h) => ({ id: h.id, text: h.text, tags: h.tags, score: h.score })), searched: d.searched });
387
+ } catch (e) { return text({ error: `zoo_recall failed: ${e.message}` }); }
388
+ });
389
+
304
390
  return { server, client };
305
391
  }
306
392
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzoo",
3
- "version": "0.34.11",
3
+ "version": "0.35.1",
4
4
  "description": "Local x402-paying proxy + MCP server for openzoo.fun — point any OpenAI-compatible harness (Cursor, Claude Code, aider, SDKs) at localhost and it pays per call from a local burner wallet. Solana and Base rails live; Robinhood experimental.",
5
5
  "license": "MIT",
6
6
  "type": "module",