// progression-milestone-set — advance one milestone date on one chain link. // MATCH + SET, account-scoped. Optionally stamps the source (e.g. the email // message id) for audit. import { z } from "zod"; import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { lifelineTool } from "../../../../../../../platform/lib/mcp-lifeline/dist/index.js"; import { getSession } from "../lib/neo4j.js"; import { setMilestone, MILESTONE_STAGE_NAMES, type MilestoneStage } from "../lib/chain-graph.js"; export function registerMilestoneSet(server: McpServer, accountId: string): void { lifelineTool( server, "progression-milestone-set", "Set one milestone date on one chain link (e.g. searches-received on the priority-2 link). Advances only that date. Pass source (an email message id) to record what evidenced the change.", { chainId: z.string(), priority: z.number().int().describe("The chain link to update."), stage: z.enum(MILESTONE_STAGE_NAMES as [MilestoneStage, ...MilestoneStage[]]).describe( "Which milestone: one of the ten progression stages.", ), date: z.string().describe("ISO-8601 date the milestone was reached."), source: z.string().optional().describe("Optional provenance, e.g. the email message id."), }, async (params: Record) => { const { chainId, priority, stage, date, source } = params as { chainId: string; priority: number; stage: MilestoneStage; date: string; source?: string; }; const session = getSession(); try { const r = await setMilestone(session, accountId, chainId, priority, stage, date, source); console.error( `[progression] op=milestone-set chainId=${chainId} link=${priority} stage=${stage} date=${date} source=${source ?? "none"} updated=${r.updated}`, ); return { content: [ { type: "text" as const, text: JSON.stringify({ ok: r.updated > 0, chainId, priority, stage, date, updated: r.updated }, null, 2), }, ], }; } catch (err) { const msg = err instanceof Error ? err.message : String(err); console.error(`[progression] op=milestone-set chainId=${chainId} rejected=${msg}`); return { content: [{ type: "text" as const, text: `Error: ${msg}` }], isError: true }; } finally { await session.close(); } }, ); }