@theronap/cortex-mcp 0.9.19 → 0.9.21

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/server.mjs +37 -3
  2. package/package.json +1 -1
package/lib/server.mjs CHANGED
@@ -464,6 +464,39 @@ export async function runServer(version) {
464
464
  },
465
465
  )
466
466
 
467
+ server.registerTool(
468
+ 'set_page_validity',
469
+ {
470
+ title: 'Mark a wiki page current / superseded / historical',
471
+ description: 'Set the CURRENCY of one of YOUR OWN authored pages so the brain can filter out stale info: "current" (reflects reality now — the default), "superseded" (replaced by a newer page — pass superseded_by with that page\'s name), or "historical" (kept for the record, no longer current). Optionally set modality: "reality" (as-built), "plan" (intended, not yet real), or "construction" (being built now). Call this the moment your understanding changes that a page is no longer the live truth — e.g. right after you author the new reality, mark the old page superseded. Owner-only.',
472
+ inputSchema: {
473
+ kind: z.enum(['project', 'person', 'org', 'user']).describe('the page kind'),
474
+ name: z.string().describe('the exact page name'),
475
+ validity: z.enum(['current', 'superseded', 'historical']).describe('the currency state'),
476
+ modality: z.enum(['reality', 'plan', 'construction']).optional().describe('what the page describes (optional)'),
477
+ superseded_by: z.string().optional().describe('for superseded: the name of the page that replaced it'),
478
+ },
479
+ },
480
+ async ({ kind, name, validity, modality, superseded_by }) => {
481
+ let res
482
+ try {
483
+ res = await fetchCortex(`${BASE}/api/brain/validity`, {
484
+ method: 'POST',
485
+ headers: { Authorization: `Bearer ${TOKEN}`, 'Content-Type': 'application/json' },
486
+ body: JSON.stringify({ kind, name, validity, modality, superseded_by }),
487
+ })
488
+ } catch (e) {
489
+ return { content: [{ type: 'text', text: `Could not set validity: ${e.message}` }] }
490
+ }
491
+ if (!res.ok) {
492
+ const d = classify(res.status, res.headers.get('content-type'), await res.text(), res.headers.get('x-vercel-id'))
493
+ return { content: [{ type: 'text', text: `Could not set validity: ${d.message}` }] }
494
+ }
495
+ const out = await res.json()
496
+ return { content: [{ type: 'text', text: `Done — "${out.name}" is now ${out.validity}${out.modality ? ` / ${out.modality}` : ''} (${out.docs_updated} tier-doc(s) updated).` }] }
497
+ },
498
+ )
499
+
467
500
  // ── File requests: ask the owner for a record's FULL original (lives on their machine) ──
468
501
  const fail = (verb, res) => async () =>
469
502
  ({ content: [{ type: 'text', text: `Could not ${verb}: ${classify(res.status, res.headers.get('content-type'), await res.text(), res.headers.get('x-vercel-id')).message}` }] })
@@ -626,10 +659,10 @@ export async function runServer(version) {
626
659
  {
627
660
  title: 'Author a wiki node (live, while it is hot)',
628
661
  description:
629
- 'Write your CURRENT understanding of a project/person/org/you into the org wiki as a maintained page. Call `authoring_context` FIRST. Author from your own synthesis of the session — the compiled mental model, not a transcript dump: what it IS, where it stands, dated decisions, open threads, key people. Weave inline [[links]] to other nodes (canonical names from the namespace; red-links for wanted-but-absent nodes). The server re-authorizes the tier and resolves links. Use this continuously whenever your understanding of a node meaningfully advanced, and at session end (/log).',
662
+ 'Write your CURRENT understanding of a project/person/org/you into the org wiki as a maintained page. Call `authoring_context` FIRST. Author from your own synthesis of the session — the compiled mental model, not a transcript dump: what it IS, where it stands, dated decisions, open threads, key people. Weave inline [[links]] to other nodes (canonical names from the namespace; red-links for wanted-but-absent nodes). The server re-authorizes the tier and resolves links. CREATES the node if it does not exist yet (project/person/org) — the conversation IS the evidence, so a brand-new entity that surfaced only in this session is authorable on the spot; you do NOT need prior records. Because such a node has nothing external to corroborate it, author it DELIBERATELY: only when you genuinely understand it is a real, distinct entity, and use its exact canonical name so it does not duplicate one already in the namespace (`user` nodes are never created). Use this continuously whenever your understanding of a node meaningfully advanced, and at session end (/log).',
630
663
  inputSchema: {
631
664
  kind: z.enum(['project', 'person', 'org', 'user']).describe('the node type'),
632
- name: z.string().describe('the EXACT canonical node name (from the namespace), e.g. "Cortex" or "Theron Peterson"'),
665
+ name: z.string().describe('the canonical node name — an EXACT existing name from the namespace to update it, or a new name to create the node (project/person/org). e.g. "Cortex" or "Theron Peterson"'),
633
666
  summary: z.string().describe('one-sentence summary of what this is and its current state (may contain [[links]])'),
634
667
  sections: z.array(z.object({
635
668
  heading: z.string().describe('e.g. Overview, Current state, Decisions, Open threads, People'),
@@ -658,7 +691,8 @@ export async function runServer(version) {
658
691
  const blue = out?.links?.blue ?? 0
659
692
  const red = out?.links?.red ?? 0
660
693
  const redList = Array.isArray(out?.redLinks) && out.redLinks.length ? `\nRed-links (wanted nodes): ${out.redLinks.map((r) => `[[${r}]]`).join(', ')}` : ''
661
- const note = out?.built ? `Authored "${name}" (${out.built} tier${out.built === 1 ? '' : 's'}). Links: ${blue} resolved, ${red} red.${redList}`
694
+ const verb = out?.created ? 'Created + authored' : 'Authored'
695
+ const note = out?.built ? `${verb} "${name}" (${out.built} tier${out.built === 1 ? '' : 's'}). Links: ${blue} resolved, ${red} red.${redList}`
662
696
  : `No change to "${name}"${out?.skipped?.length ? ` (${out.skipped.join(', ')})` : ''}.`
663
697
  return { content: [{ type: 'text', text: note }] }
664
698
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theronap/cortex-mcp",
3
- "version": "0.9.19",
3
+ "version": "0.9.21",
4
4
  "description": "Connect your AI assistant to Cortex — your org's projects, activity, gaps, and directives, scoped to you.",
5
5
  "type": "module",
6
6
  "bin": {