@cencori/mcp 0.4.0 → 0.5.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
@@ -42,6 +42,7 @@ Docs + `how_to_*` guidance tools work with **no API key**. Add `CENCORI_API_KEY`
42
42
  | Tool | Description |
43
43
  |------|-------------|
44
44
  | `search_docs` / `get_doc` / `list_docs` | Search / fetch / list Cencori documentation |
45
+ | `get_integration_guide` | Fetch the full `llm.txt` integration contract — the authoritative "how to set up Cencori in a codebase" guide |
45
46
  | `how_to_create_api_key`, `how_to_edit_api_key`, `how_to_revoke_api_key` | Guidance: API-key lifecycle (manual) |
46
47
  | `how_to_activate_policy`, `how_to_respond_to_change_request` | Guidance: governance checker steps (manual) |
47
48
  | `how_to_change_plan`, `how_to_manage_billing` | Guidance: billing / plan / credits (manual) |
package/dist/index.js CHANGED
@@ -200,6 +200,16 @@ var DocsClient = class {
200
200
  }
201
201
  return response.json();
202
202
  }
203
+ /** Fetch the raw `llm.txt` integration contract (public, no auth). */
204
+ async getIntegrationGuide() {
205
+ const url = new URL("/llm.txt", this.baseUrl);
206
+ const response = await fetch(url, { signal: fetchSignal() });
207
+ if (!response.ok) {
208
+ const message = await readHttpErrorMessage(response);
209
+ throw new Error(`Integration guide fetch failed (${response.status}): ${message}`);
210
+ }
211
+ return response.text();
212
+ }
203
213
  };
204
214
 
205
215
  // src/tools/docs.ts
@@ -288,6 +298,28 @@ function registerDocsTools(server, docs, docsBaseUrl) {
288
298
  return jsonResult(navigation);
289
299
  }
290
300
  );
301
+ server.registerTool(
302
+ "get_integration_guide",
303
+ {
304
+ title: "Get the Cencori integration guide (llm.txt)",
305
+ description: 'Fetch the full Cencori "Integration Contract for Code Agents" (llm.txt) \u2014 the authoritative, always-current guide for setting up Cencori in a codebase: package names, import paths, env vars, base URLs, SDK usage, request/response shapes, and step-by-step setup. Call this FIRST when asked to add, integrate, or set up Cencori in a project.',
306
+ inputSchema: {},
307
+ annotations: READ_ONLY_ANNOTATIONS
308
+ },
309
+ async () => {
310
+ const guide = await docs.getIntegrationGuide();
311
+ return {
312
+ content: [
313
+ {
314
+ type: "text",
315
+ text: `Source: ${docsBaseUrl}/llm.txt
316
+
317
+ ${guide}`
318
+ }
319
+ ]
320
+ };
321
+ }
322
+ );
291
323
  }
292
324
 
293
325
  // src/tools/gateway.ts
@@ -450,39 +482,50 @@ function registerAgentsTools(server, client, caps) {
450
482
  var import_zod4 = require("zod");
451
483
  var scopeShape = {
452
484
  namespace: import_zod4.z.string().optional().describe("Memory namespace to scope to."),
453
- scope: import_zod4.z.string().optional().describe("Memory scope (e.g. project, user, session)."),
454
- user_id: import_zod4.z.string().optional().describe("Scope to a specific end-user id."),
455
- session_id: import_zod4.z.string().optional().describe("Scope to a specific session id.")
485
+ scope: import_zod4.z.enum(["user", "session"]).optional().describe('Memory scope. Defaults to "user".'),
486
+ user_id: import_zod4.z.string().optional().describe("End-user id. REQUIRED for user scope (the default)."),
487
+ session_id: import_zod4.z.string().optional().describe("Session id. REQUIRED for session scope.")
456
488
  };
489
+ function missingScopeKey({ scope, user_id, session_id }) {
490
+ if ((scope ?? "user") === "session") {
491
+ return session_id || user_id ? null : "session_id (or user_id) is required for session scope.";
492
+ }
493
+ return user_id ? null : 'user_id is required for user scope (the default). Pass user_id, or use scope="session" with session_id.';
494
+ }
495
+ var scopeErr = (msg) => jsonResult({ error: "missing_scope", message: msg });
457
496
  function registerMemoryTools(server, client, caps) {
458
497
  server.registerTool(
459
498
  "list_memories",
460
499
  {
461
500
  title: "List memories",
462
- description: "List stored memories for the project, optionally scoped by namespace/user/session.",
501
+ description: "List stored memories for a user or session. Requires user_id (or session_id for session scope).",
463
502
  inputSchema: {
464
503
  ...scopeShape,
465
- limit: import_zod4.z.number().int().positive().max(200).optional(),
504
+ limit: import_zod4.z.number().int().positive().max(100).optional(),
466
505
  cursor: import_zod4.z.string().optional().describe("Pagination cursor from a previous response.")
467
506
  },
468
507
  annotations: READ_ONLY_ANNOTATIONS
469
508
  },
470
- async ({ namespace, scope, user_id, session_id, limit, cursor }) => jsonResult(
471
- await client.get("/v1/memory/list", {
472
- namespace,
473
- scope,
474
- userId: user_id,
475
- sessionId: session_id,
476
- limit: limit?.toString(),
477
- cursor
478
- })
479
- )
509
+ async ({ namespace, scope, user_id, session_id, limit, cursor }) => {
510
+ const err = missingScopeKey({ scope, user_id, session_id });
511
+ if (err) return scopeErr(err);
512
+ return jsonResult(
513
+ await client.get("/v1/memory/list", {
514
+ namespace,
515
+ scope,
516
+ userId: user_id,
517
+ sessionId: session_id,
518
+ limit: limit?.toString(),
519
+ cursor
520
+ })
521
+ );
522
+ }
480
523
  );
481
524
  server.registerTool(
482
525
  "search_memory",
483
526
  {
484
527
  title: "Search memory (semantic)",
485
- description: "Semantically search stored memories by query.",
528
+ description: "Semantically search a user\u2019s or session\u2019s memories. Requires user_id (or session_id for session scope).",
486
529
  inputSchema: {
487
530
  query: import_zod4.z.string().min(1).describe("Natural-language search query."),
488
531
  ...scopeShape,
@@ -491,17 +534,21 @@ function registerMemoryTools(server, client, caps) {
491
534
  },
492
535
  annotations: READ_ONLY_ANNOTATIONS
493
536
  },
494
- async ({ query, namespace, scope, user_id, session_id, top_k, threshold }) => jsonResult(
495
- await client.post("/v1/memory/search", {
496
- query,
497
- namespace,
498
- scope,
499
- userId: user_id,
500
- sessionId: session_id,
501
- topK: top_k,
502
- threshold
503
- })
504
- )
537
+ async ({ query, namespace, scope, user_id, session_id, top_k, threshold }) => {
538
+ const err = missingScopeKey({ scope, user_id, session_id });
539
+ if (err) return scopeErr(err);
540
+ return jsonResult(
541
+ await client.post("/v1/memory/search", {
542
+ query,
543
+ namespace,
544
+ scope,
545
+ userId: user_id,
546
+ sessionId: session_id,
547
+ topK: top_k,
548
+ threshold
549
+ })
550
+ );
551
+ }
505
552
  );
506
553
  server.registerTool(
507
554
  "get_memory",
@@ -517,24 +564,23 @@ function registerMemoryTools(server, client, caps) {
517
564
  "list_memory_entities",
518
565
  {
519
566
  title: "List memory entities",
520
- description: "List entities resolved from the memory graph.",
567
+ description: "List entities resolved from a user\u2019s or session\u2019s memory graph. Requires user_id (or session_id).",
521
568
  inputSchema: scopeShape,
522
569
  annotations: READ_ONLY_ANNOTATIONS
523
570
  },
524
- async ({ namespace, scope, user_id, session_id }) => jsonResult(
525
- await client.get("/v1/memory/entities", {
526
- namespace,
527
- scope,
528
- userId: user_id,
529
- sessionId: session_id
530
- })
531
- )
571
+ async ({ namespace, scope, user_id, session_id }) => {
572
+ const err = missingScopeKey({ scope, user_id, session_id });
573
+ if (err) return scopeErr(err);
574
+ return jsonResult(
575
+ await client.get("/v1/memory/entities", { namespace, scope, userId: user_id, sessionId: session_id })
576
+ );
577
+ }
532
578
  );
533
579
  server.registerTool(
534
580
  "get_memory_graph",
535
581
  {
536
582
  title: "Get memory entity graph",
537
- description: "Traverse the memory entity graph from an optional starting entity.",
583
+ description: "Traverse a user\u2019s or session\u2019s memory entity graph. Requires user_id (or session_id).",
538
584
  inputSchema: {
539
585
  ...scopeShape,
540
586
  entity: import_zod4.z.string().optional().describe("Entity to start traversal from."),
@@ -542,40 +588,48 @@ function registerMemoryTools(server, client, caps) {
542
588
  },
543
589
  annotations: READ_ONLY_ANNOTATIONS
544
590
  },
545
- async ({ namespace, scope, user_id, session_id, entity, hops }) => jsonResult(
546
- await client.get("/v1/memory/graph", {
547
- namespace,
548
- scope,
549
- userId: user_id,
550
- sessionId: session_id,
551
- entity,
552
- hops: hops?.toString()
553
- })
554
- )
591
+ async ({ namespace, scope, user_id, session_id, entity, hops }) => {
592
+ const err = missingScopeKey({ scope, user_id, session_id });
593
+ if (err) return scopeErr(err);
594
+ return jsonResult(
595
+ await client.get("/v1/memory/graph", {
596
+ namespace,
597
+ scope,
598
+ userId: user_id,
599
+ sessionId: session_id,
600
+ entity,
601
+ hops: hops?.toString()
602
+ })
603
+ );
604
+ }
555
605
  );
556
606
  server.registerTool(
557
607
  "get_forget_suggestions",
558
608
  {
559
609
  title: "Get forget suggestions",
560
- description: "List memories the system suggests forgetting (stale/superseded).",
610
+ description: "List memories the system suggests forgetting for a user or session. Requires user_id (or session_id).",
561
611
  inputSchema: scopeShape,
562
612
  annotations: READ_ONLY_ANNOTATIONS
563
613
  },
564
- async ({ namespace, scope, user_id, session_id }) => jsonResult(
565
- await client.get("/v1/memory/forget-suggestions", {
566
- namespace,
567
- scope,
568
- userId: user_id,
569
- sessionId: session_id
570
- })
571
- )
614
+ async ({ namespace, scope, user_id, session_id }) => {
615
+ const err = missingScopeKey({ scope, user_id, session_id });
616
+ if (err) return scopeErr(err);
617
+ return jsonResult(
618
+ await client.get("/v1/memory/forget-suggestions", {
619
+ namespace,
620
+ scope,
621
+ userId: user_id,
622
+ sessionId: session_id
623
+ })
624
+ );
625
+ }
572
626
  );
573
627
  if (caps.write) {
574
628
  server.registerTool(
575
629
  "remember_memory",
576
630
  {
577
631
  title: "Remember a conversation turn",
578
- description: "Store a user/assistant exchange as memory for later retrieval.",
632
+ description: "Store a user/assistant exchange as memory. Requires user_id (or session_id for session scope).",
579
633
  inputSchema: {
580
634
  user: import_zod4.z.string().min(1).describe("The user message."),
581
635
  assistant: import_zod4.z.string().min(1).describe("The assistant response."),
@@ -583,22 +637,26 @@ function registerMemoryTools(server, client, caps) {
583
637
  },
584
638
  annotations: WRITE_ANNOTATIONS
585
639
  },
586
- async ({ user, assistant, namespace, scope, user_id, session_id }) => jsonResult(
587
- await client.post("/v1/memory/remember", {
588
- user,
589
- assistant,
590
- namespace,
591
- scope,
592
- userId: user_id,
593
- sessionId: session_id
594
- })
595
- )
640
+ async ({ user, assistant, namespace, scope, user_id, session_id }) => {
641
+ const err = missingScopeKey({ scope, user_id, session_id });
642
+ if (err) return scopeErr(err);
643
+ return jsonResult(
644
+ await client.post("/v1/memory/remember", {
645
+ user,
646
+ assistant,
647
+ namespace,
648
+ scope,
649
+ userId: user_id,
650
+ sessionId: session_id
651
+ })
652
+ );
653
+ }
596
654
  );
597
655
  server.registerTool(
598
656
  "write_memory",
599
657
  {
600
658
  title: "Write a memory",
601
- description: "Store a single memory (a fact/note) directly.",
659
+ description: "Store a single memory (a fact/note). Requires user_id (or session_id for session scope).",
602
660
  inputSchema: {
603
661
  content: import_zod4.z.string().min(1).describe("The memory content to store."),
604
662
  importance: import_zod4.z.number().min(0).max(1).optional().describe("Importance weight 0\u20131."),
@@ -606,16 +664,20 @@ function registerMemoryTools(server, client, caps) {
606
664
  },
607
665
  annotations: WRITE_ANNOTATIONS
608
666
  },
609
- async ({ content, importance, namespace, scope, user_id, session_id }) => jsonResult(
610
- await client.post("/v1/memory/write", {
611
- content,
612
- importance,
613
- namespace,
614
- scope,
615
- userId: user_id,
616
- sessionId: session_id
617
- })
618
- )
667
+ async ({ content, importance, namespace, scope, user_id, session_id }) => {
668
+ const err = missingScopeKey({ scope, user_id, session_id });
669
+ if (err) return scopeErr(err);
670
+ return jsonResult(
671
+ await client.post("/v1/memory/write", {
672
+ content,
673
+ importance,
674
+ namespace,
675
+ scope,
676
+ userId: user_id,
677
+ sessionId: session_id
678
+ })
679
+ );
680
+ }
619
681
  );
620
682
  server.registerTool(
621
683
  "create_namespace",
@@ -1152,7 +1214,7 @@ function registerGuidanceTools(server, baseUrl) {
1152
1214
 
1153
1215
  // src/server.ts
1154
1216
  var SERVER_NAME = "cencori";
1155
- var SERVER_VERSION = "0.4.0";
1217
+ var SERVER_VERSION = "0.5.0";
1156
1218
  function createServer(config) {
1157
1219
  const server = new import_mcp.McpServer(
1158
1220
  {