@minicor/mcp-server 4.10.0 → 4.12.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.
@@ -64,12 +64,31 @@ export class AgentServiceClient {
64
64
  async listTasks() {
65
65
  return this.request("GET", "/tasks");
66
66
  }
67
- async runTask(slug, workspaceId, input, region) {
68
- return this.request("POST", `/tasks/${encodeURIComponent(slug)}/runs`, {
69
- workspaceId,
70
- input,
71
- region,
67
+ async runTask(slug, workspaceId, input, region, extra) {
68
+ return this.request("POST", `/tasks/${encodeURIComponent(slug)}/runs`, { workspaceId, input, region, ...(extra ?? {}) });
69
+ }
70
+ // ── Harness verbs (engine runs + catalog) ──
71
+ async getAgentCatalog() { return this.request("GET", "/agent-catalog"); }
72
+ async getSessionRuntimes() { return this.request("GET", "/session-runtimes"); }
73
+ async runAgent(agentId, body) { return this.request("POST", `/agents/${encodeURIComponent(agentId)}/run`, body); }
74
+ async listRuns(query) { return this.request("GET", "/runs", undefined, query); }
75
+ async getRun(runId) { return this.request("GET", `/runs/${encodeURIComponent(runId)}`); }
76
+ // Answer a parked (needs_input) run. The success response is an SSE tail of the
77
+ // resumed execution; the resume is committed server-side before the tail
78
+ // starts, so detach immediately — await_agent is the blocking verb.
79
+ async answerRun(runId, answers, region) {
80
+ const controller = new AbortController();
81
+ const res = await fetch(`${this.platformBase}/api/agents/runs/${encodeURIComponent(runId)}/answers`, {
82
+ method: "POST",
83
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${this.token}` },
84
+ body: JSON.stringify({ answers, ...(region ? { region } : {}) }),
85
+ signal: controller.signal,
72
86
  });
87
+ if (!res.ok) {
88
+ const detail = await res.text().catch(() => "");
89
+ throw new Error(`Answer run ${runId} failed (${res.status}): ${detail.slice(0, 300)}`);
90
+ }
91
+ controller.abort();
73
92
  }
74
93
  async listTaskRuns(slug, workspaceId) {
75
94
  return this.request("GET", `/tasks/${encodeURIComponent(slug)}/runs`, undefined, workspaceId ? { workspace_id: workspaceId } : undefined);
@@ -1 +1 @@
1
- {"version":3,"file":"agent-service-client.js","sourceRoot":"","sources":["../src/agent-service-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"agent-service-client.js","sourceRoot":"","sources":["../src/agent-service-client.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"server-surface.d.ts","sourceRoot":"","sources":["../src/server-surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA0B3C,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB,gEAAgE;IAChE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA8FD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,CAI7D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,QAkCnE"}
1
+ {"version":3,"file":"server-surface.d.ts","sourceRoot":"","sources":["../src/server-surface.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AA2B3C,eAAO,MAAM,WAAW,YAAY,CAAC;AAErC,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,UAAU,EAAE,OAAO,CAAC;IACpB,gEAAgE;IAChE,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA4GD,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,OAAO,GAAG,MAAM,CAI7D;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,cAAc,QAmCnE"}
@@ -14,6 +14,7 @@ import { register as registerBlueprints } from "./tools/blueprints.js";
14
14
  import { register as registerRecording } from "./tools/recording.js";
15
15
  import { register as registerContext } from "./tools/context.js";
16
16
  import { register as registerTasks } from "./tools/tasks.js";
17
+ import { register as registerAgentHarness } from "./tools/agent-harness.js";
17
18
  import { register as registerSession } from "./tools/session.js";
18
19
  import { register as registerWorkflowGuide } from "./prompts/workflow-guide.js";
19
20
  import { register as registerDebugExecution } from "./prompts/debug-execution.js";
@@ -37,6 +38,10 @@ const BLUEPRINT_LOOP = `THE BLUEPRINT LOOP (the front door of the build loop):
37
38
  A Blueprint is the living spec + context library that OWNS a job. When a route
38
39
  is blueprint-linked, NEVER register_job / update_job / add_test_case directly
39
40
  on it - that trips job_ahead drift; drive changes through the spec instead.
41
+ Sanctioned escape hatch for intentional direct edits (e.g. bulk job edits):
42
+ pass acknowledgeJobAhead=true to update_job / add_test_case. The tool proceeds
43
+ and the response carries a job_ahead warning with the fold-back options
44
+ (blueprint_import_cases, or blueprint_build which overwrites direct edits).
40
45
  The loop: feed the library (blueprint_add_entry: SOPs, Looms, notes, VM
41
46
  walkthroughs) -> blueprint_synthesize (drafts a spec proposal - never applied
42
47
  silently) -> review + blueprint_apply_proposal -> if the applied spec carries
@@ -100,6 +105,15 @@ execute PUBLISHED workflows, not unpublished Dev Mode branches.
100
105
 
101
106
  For the microscope details, load get_skill("job-build-loop") and
102
107
  get_skill("rpa-testing-workflow").`;
108
+ const HARNESS_LOOP = `THE AGENT HARNESS (staff: spawn and drive platform agents from here):
109
+
110
+ list_agent_catalog -> spawn_agent (catalog agents run in the background; the
111
+ 'worker' task takes a freeform brief + toolProfile and converses via
112
+ send_task_message) -> agent_thread to observe -> answer_agent un-parks a
113
+ needs_input run -> await_agent blocks to the terminal result. Spawns are
114
+ staff-gated and spend-guarded server-side; per-run model / budgets /
115
+ promptAddendum overrides are clamped by the platform's caps.
116
+ `;
103
117
  const SESSION_PREAMBLE = `CRITICAL: If the current directory contains a minicor.json file, you are in a workspace clone.
104
118
  You MUST call session_start(directory) as your FIRST action. It returns the workspace rules
105
119
  (AGENTS.md), prior session state for resuming, and all context you need. Follow the phase loop
@@ -113,7 +127,7 @@ If you are NOT in a workspace clone, use the tools freely - list_workspaces, clo
113
127
  `;
114
128
  export function buildInstructions(localTools) {
115
129
  const header = "You are connected to the Minicor MCP server for RPA workflow automation.\n\n";
116
- return header + (localTools ? SESSION_PREAMBLE : "") + BLUEPRINT_LOOP + JOBS_LOOP;
130
+ return header + (localTools ? SESSION_PREAMBLE : "") + BLUEPRINT_LOOP + HARNESS_LOOP + JOBS_LOOP;
117
131
  }
118
132
  export function registerSurface(deps, opts) {
119
133
  const directVmTools = opts.directVmTools ?? true;
@@ -132,6 +146,7 @@ export function registerSurface(deps, opts) {
132
146
  registerRecording(deps);
133
147
  registerContext(deps);
134
148
  registerTasks(deps);
149
+ registerAgentHarness(deps);
135
150
  if (opts.localTools) {
136
151
  registerSyncTools(deps);
137
152
  registerSession(deps);
@@ -1 +1 @@
1
- {"version":3,"file":"server-surface.js","sourceRoot":"","sources":["../src/server-surface.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server-surface.js","sourceRoot":"","sources":["../src/server-surface.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ToolDeps } from "../types.js";
2
+ export declare function register(deps: ToolDeps): void;
3
+ //# sourceMappingURL=agent-harness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-harness.d.ts","sourceRoot":"","sources":["../../src/tools/agent-harness.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAuB5C,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,QAuItC"}
@@ -0,0 +1,143 @@
1
+ // The agent harness: staff spawn platform agents (catalog runs or the generic "worker"), read their
2
+ // threads, answer parked questions, and block on results. Wire shapes mirror agent-service's
3
+ // src/http/harness-contract.ts (node 1): overrides { model, budgets, promptAddendum } nested on both
4
+ // doors, source: "mcp" top-level, worker input { brief, toolProfile, budgets }, mcp:{uuid} idempotency.
5
+ import { randomUUID } from "node:crypto";
6
+ import { z } from "zod";
7
+ import { safe } from "../helpers.js";
8
+ import { AgentServiceClient } from "../agent-service-client.js";
9
+ const regionParam = z.enum(["us", "ca"]).optional().describe("Region (us or ca). Auto-detected from workspace if omitted.");
10
+ // Terminal engine-run statuses; needs_input is parked, not finished — the await/answer split hinges on that.
11
+ const RUN_TERMINAL = new Set(["succeeded", "failed", "gave_up", "budget_exhausted", "cancelled"]);
12
+ const POLL_MS = 5_000;
13
+ /** Strip undefined values so wire payloads carry only what the caller sent. */
14
+ function prune(obj) {
15
+ return Object.fromEntries(Object.entries(obj).filter(([, v]) => v !== undefined));
16
+ }
17
+ /** One compact chronology row from a run summary or full run record. */
18
+ function compactRun(run) {
19
+ let parkedQuestion = run.needs_input?.first_question ?? null;
20
+ if (!parkedQuestion && run.status === "needs_input" && typeof run.needs_input_json === "string") {
21
+ try {
22
+ parkedQuestion = JSON.parse(run.needs_input_json)?.questions?.[0] ?? null;
23
+ }
24
+ catch { /* questionless */ }
25
+ }
26
+ return {
27
+ runId: run.id, agent: run.agent_id, status: run.status, terminalReason: run.terminal_reason ?? null,
28
+ costUsd: run.cost_usd ?? null, createdAt: run.created_at ?? null, parentRunId: run.thread?.parent_run_id ?? null, parkedQuestion,
29
+ };
30
+ }
31
+ export function register(deps) {
32
+ const { server } = deps;
33
+ const getClient = (region) => new AgentServiceClient(deps.getApiBase(region), deps.getAuthToken?.(region) || "");
34
+ server.tool("spawn_agent", "Spawn a platform agent into a workspace (staff harness). Catalog agents (job-builder, job-debugger, build-supervisor...) start as background runs; the generic 'worker' and other session manifests start as task runs you converse with via send_task_message. Call list_agent_catalog first for ids and input shapes. Returns run/task ids + thread id; then agent_thread to observe, answer_agent to un-park, await_agent to block.", {
35
+ workspaceId: z.number().describe("Workspace the agent acts on"),
36
+ agentId: z.string().describe("Catalog agent id or task slug (e.g. 'worker') from list_agent_catalog"),
37
+ input: z.record(z.string(), z.unknown()).optional().describe("Input matching the agent's input schema (catalog agents)"),
38
+ brief: z.string().optional().describe("Freeform brief for the 'worker' agent (merged into its input)"),
39
+ toolProfile: z.enum(["readonly", "builder", "full"]).optional().describe("Worker tool allowlist profile"),
40
+ model: z.string().optional().describe("Per-run model override (validated server-side)"),
41
+ budgets: z.object({ maxSteps: z.number().int().positive().optional(), maxTokens: z.number().int().positive().optional(), maxCostUsd: z.number().positive().optional(), wallClockMs: z.number().int().positive().optional() })
42
+ .optional().describe("Per-run budget overrides, clamped server-side by the platform caps"),
43
+ promptAddendum: z.string().min(1).max(4_000).optional().describe("Operator instructions APPENDED to the resolved prompt (never replaces it; 4k cap)"),
44
+ thread: z.object({ threadId: z.string().optional().describe("Attach to an existing thread"), parentRunId: z.string().optional().describe("Lineage: the run that spawned this one") })
45
+ .optional().describe("Thread lineage stamp; omitted = server auto-stamps mcp:{userId}"),
46
+ region: regionParam,
47
+ }, async ({ workspaceId, agentId, input, brief, toolProfile, model, budgets, promptAddendum, thread, region }) => {
48
+ const r = region ?? deps.state.getWorkspaceRegion(workspaceId);
49
+ return safe(async () => {
50
+ const client = getClient(r);
51
+ const isWorker = agentId === "worker"; // the worker carries budgets inside its input (workerInputSchema)
52
+ const ovr = prune({ model, budgets: isWorker ? undefined : budgets, promptAddendum });
53
+ const overrides = Object.keys(ovr).length ? ovr : undefined;
54
+ const tasks = (await client.listTasks())?.tasks ?? [];
55
+ if (tasks.some((t) => t.slug === agentId)) {
56
+ const res = await client.runTask(agentId, workspaceId, prune({ ...(input ?? {}), brief, toolProfile, budgets: isWorker ? budgets : undefined }), r, prune({ source: "mcp", overrides }));
57
+ return { taskRunId: res.run_id, sessionId: res.session_id ?? null, threadId: res.run?.thread_id ?? null, status: res.run?.status ?? "running" };
58
+ }
59
+ const res = await client.runAgent(agentId, prune({
60
+ workspace_id: workspaceId, input, region: r, idempotency_key: `mcp:${randomUUID()}`, source: "mcp", overrides,
61
+ thread: thread ? prune({ thread_id: thread.threadId, parent_run_id: thread.parentRunId }) : undefined,
62
+ }));
63
+ const run = res.run ?? res;
64
+ return { runId: run.id, threadId: run.thread_id ?? run.thread?.thread_id ?? thread?.threadId ?? null, status: run.status };
65
+ });
66
+ });
67
+ server.tool("agent_thread", "Read a thread's chronology: every engine run stamped with this thread id, compact (agent, status, terminal reason, cost, parked question when needs_input). Pass taskRunId too when the thread includes a worker/task conversation — its activity is merged in.", {
68
+ workspaceId: z.number().describe("Workspace ID (region detection)"),
69
+ threadId: z.string().min(1).describe("Thread ID (from spawn_agent or the console)"),
70
+ taskRunId: z.string().optional().describe("Also include this task run's activity (worker conversations)"),
71
+ region: regionParam,
72
+ }, async ({ workspaceId, threadId, taskRunId, region }) => {
73
+ const r = region ?? deps.state.getWorkspaceRegion(workspaceId);
74
+ return safe(async () => {
75
+ const client = getClient(r);
76
+ const runs = ((await client.listRuns({ thread_id: threadId }))?.runs ?? []).map(compactRun).sort((a, b) => new Date(a.createdAt ?? 0).getTime() - new Date(b.createdAt ?? 0).getTime());
77
+ return { threadId, runs, ...(taskRunId ? { taskRun: (await client.getTaskRun(taskRunId))?.run ?? null } : {}) };
78
+ });
79
+ });
80
+ server.tool("answer_agent", "Answer a parked engine run (status needs_input). Answers are positional against the run's parked questions. The run resumes in the background — follow with await_agent. Session/task conversations use send_task_message instead.", {
81
+ runId: z.string().min(1).describe("Engine run ID (not a task run)"),
82
+ answers: z.array(z.string()).min(1).describe("Positional answers to the parked questions"),
83
+ region: regionParam,
84
+ }, async ({ runId, answers, region }) => safe(async () => {
85
+ const client = getClient(region);
86
+ await client.answerRun(runId, answers, region);
87
+ const run = (await client.getRun(runId))?.run;
88
+ return { answered: true, run: run ? compactRun(run) : null };
89
+ }));
90
+ server.tool("await_agent", "Block until an agent finishes: polls a run (or task run) to a terminal state and returns the compact result (status, terminal reason, result text, cost). Returns early when a run parks on needs_input — answer_agent is then the next verb. On timeout returns the current status with timedOut: true.", {
91
+ runId: z.string().optional().describe("Engine run ID (exactly one of runId/taskRunId)"),
92
+ taskRunId: z.string().optional().describe("Task run ID (worker/session spawns)"),
93
+ timeoutSeconds: z.number().int().min(1).max(1800).default(300).describe("Max seconds to wait (default 300, max 1800)"),
94
+ region: regionParam,
95
+ }, async ({ runId, taskRunId, timeoutSeconds, region }) => safe(async () => {
96
+ if (!runId === !taskRunId)
97
+ throw new Error("Pass exactly one of runId or taskRunId");
98
+ const client = getClient(region), deadline = Date.now() + timeoutSeconds * 1000;
99
+ for (;;) {
100
+ if (runId) {
101
+ const run = (await client.getRun(runId))?.run;
102
+ if (!run)
103
+ throw new Error(`Run ${runId} not found`);
104
+ if (RUN_TERMINAL.has(run.status) || run.status === "needs_input") {
105
+ return { ...compactRun(run), resultText: typeof run.result_text === "string" ? run.result_text.slice(0, 2000) : null };
106
+ }
107
+ if (Date.now() >= deadline)
108
+ return { ...compactRun(run), timedOut: true };
109
+ }
110
+ else {
111
+ const run = (await client.getTaskRun(taskRunId))?.run;
112
+ if (!run)
113
+ throw new Error(`Task run ${taskRunId} not found`);
114
+ // Task runs are conversational: idle = turn complete (their rest state).
115
+ if (run.status === "idle" || run.status === "error")
116
+ return { taskRunId, status: run.status, activity: (run.activity ?? []).slice(-5) };
117
+ if (Date.now() >= deadline)
118
+ return { taskRunId, status: run.status, timedOut: true };
119
+ }
120
+ await new Promise((resolve) => setTimeout(resolve, Math.min(POLL_MS, deadline - Date.now())));
121
+ }
122
+ }));
123
+ server.tool("list_agent_catalog", "Discover what the harness can spawn: registry catalog agents (with runMode + input schema), session task manifests like 'worker' (spawned through the task door), and the non-spawnable session runtimes for context. Call before spawn_agent.", { region: regionParam }, async ({ region }) => safe(async () => {
124
+ const client = getClient(region);
125
+ const [catalog, runtimes, tasks] = await Promise.all([client.getAgentCatalog(), client.getSessionRuntimes(), client.listTasks()]);
126
+ const taskList = tasks?.tasks ?? [];
127
+ const taskSlugs = new Set(taskList.map((t) => t.slug));
128
+ return {
129
+ spawnable: [
130
+ ...(catalog?.agents ?? []).filter((a) => !taskSlugs.has(a.id)).map((a) => ({
131
+ id: a.id, kind: "run", runMode: a.run_mode, name: a.name ?? null, description: a.description ?? null,
132
+ model: a.model ?? null, budgets: a.budgets ?? null, inputSchema: a.input_schema ?? null,
133
+ })),
134
+ ...taskList.map((t) => ({
135
+ id: t.slug, kind: "task", runMode: "session", name: t.name ?? null,
136
+ description: t.description ?? null, inputSchema: t.input_schema ?? null,
137
+ })),
138
+ ],
139
+ sessionRuntimes: runtimes?.runtimes ?? [],
140
+ };
141
+ }));
142
+ }
143
+ //# sourceMappingURL=agent-harness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-harness.js","sourceRoot":"","sources":["../../src/tools/agent-harness.ts"],"names":[],"mappings":"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"}
@@ -10,6 +10,10 @@
10
10
  * OWNERSHIP RULE: when a route is blueprint-linked, never register_job /
11
11
  * update_job / add_test_case directly on it — that trips reverse-drift
12
12
  * detection (state job_ahead). Drive changes through the spec instead.
13
+ * Sanctioned escape hatch: update_job / add_test_case accept
14
+ * acknowledgeJobAhead=true for intentional direct edits; the response then
15
+ * carries a job_ahead warning with the fold-back options
16
+ * (blueprint_import_cases or blueprint_build).
13
17
  *
14
18
  * Auth/transport is handled by MiddlewareServiceClient (same plumbing as the
15
19
  * jobs tools): the region's public middleware-service with the MCP's user
@@ -1 +1 @@
1
- {"version":3,"file":"blueprints.d.ts","sourceRoot":"","sources":["../../src/tools/blueprints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAaH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAmH5C,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,QAm0CtC"}
1
+ {"version":3,"file":"blueprints.d.ts","sourceRoot":"","sources":["../../src/tools/blueprints.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAaH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAgI5C,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,QAk0CtC"}
@@ -10,6 +10,10 @@
10
10
  * OWNERSHIP RULE: when a route is blueprint-linked, never register_job /
11
11
  * update_job / add_test_case directly on it — that trips reverse-drift
12
12
  * detection (state job_ahead). Drive changes through the spec instead.
13
+ * Sanctioned escape hatch: update_job / add_test_case accept
14
+ * acknowledgeJobAhead=true for intentional direct edits; the response then
15
+ * carries a job_ahead warning with the fold-back options
16
+ * (blueprint_import_cases or blueprint_build).
13
17
  *
14
18
  * Auth/transport is handled by MiddlewareServiceClient (same plumbing as the
15
19
  * jobs tools): the region's public middleware-service with the MCP's user
@@ -22,6 +26,17 @@ const regionParam = z
22
26
  .enum(["us", "ca"])
23
27
  .optional()
24
28
  .describe("Region (us or ca). Auto-detected from workspace if omitted.");
29
+ // Blueprint and entry ids are ALWAYS uuids server-side; a non-uuid reaches the
30
+ // Postgres uuid cast and dies as a 500. LLM callers have shipped hallucinated
31
+ // ids to prod (a literal integer, a splice of two real uuids), so reject them
32
+ // client-side with a pointer to the tool that returns real ids.
33
+ const blueprintIdParam = z
34
+ .string()
35
+ .uuid("blueprintId must be a uuid; call blueprint_list to get real ids")
36
+ .describe("Blueprint ID (uuid)");
37
+ const entryIdParam = z
38
+ .string()
39
+ .uuid("entryId must be a uuid; call blueprint_list_entries to get real ids");
25
40
  const entryKindParam = z
26
41
  .enum([
27
42
  "doc",
@@ -188,7 +203,7 @@ export function register(deps) {
188
203
  // ── blueprint_get ──────────────────────────────────────────
189
204
  server.tool("blueprint_get", "Get a blueprint: the full spec document, computed state, both drift summaries, and the inbox (document.openQuestions + pendingProposal). This is the raw read — headVersion here is the baseVersion for blueprint_update's CAS, and pendingProposal's baseVersion/basedOnSeq are the coordinates blueprint_apply_proposal requires. For 'what should I do next', prefer resolve_blueprint_state, which turns this state into concrete tool calls.", {
190
205
  workspaceId: z.number().describe("Workspace ID"),
191
- blueprintId: z.string().describe("Blueprint ID"),
206
+ blueprintId: blueprintIdParam,
192
207
  region: regionParam,
193
208
  }, async ({ workspaceId, blueprintId, region }) => {
194
209
  const r = resolveRegion(workspaceId, region);
@@ -216,7 +231,7 @@ export function register(deps) {
216
231
  // ── blueprint_update ───────────────────────────────────────
217
232
  server.tool("blueprint_update", "Edit the spec document directly: `document` replaces wholesale, `patch` is the section-level merge (goal/schemas/openQuestions replaced, environment shallow-merged, screens/steps upserted by id, credentials by key, exampleCases by name). ALWAYS pass baseVersion (headVersion from blueprint_get / resolve_blueprint_state) — it is compare-and-swap: a 409 means the blueprint moved past your read, so RE-READ with blueprint_get and re-author the edit against the new head; never retry blindly. Prefer the synthesize->apply path for library-derived changes; direct edits are for surgical fixes. A successful document change snapshots a version and makes the job stale (blueprint_build to re-sync).", {
218
233
  workspaceId: z.number().describe("Workspace ID"),
219
- blueprintId: z.string().describe("Blueprint ID"),
234
+ blueprintId: blueprintIdParam,
220
235
  name: z.string().optional().describe("Rename the blueprint"),
221
236
  document: z
222
237
  .record(z.string(), z.unknown())
@@ -289,9 +304,8 @@ export function register(deps) {
289
304
  // ── blueprint_add_entry ────────────────────────────────────
290
305
  server.tool("blueprint_add_entry", "Add (or, with entryId, update) a library entry — the way you feed a blueprint context. Context kinds (doc/video/url/note/transcript/data-source/walkthrough) feed synthesis; resource kinds (screen-map/anchor/screenshot) are runtime-referenceable as entry://<id>#<fragment>. Enrichable kinds (doc/video/url with a url or blobRef) start status=pending and are enriched to text by a worker — poll blueprint_list_entries before synthesizing. For file uploads: blueprint_entry_upload_url first, PUT the bytes, then pass the returned blobRef here. VM WALKTHROUGH MODE (get_skill 'blueprint-vm-walkthrough'): create the walkthrough entry IMMEDIATELY when the session starts and PATCH it (entryId + content) after EVERY step — crash resilience. Every write bumps librarySeq, so the spec becomes spec_stale until the next blueprint_synthesize.", {
291
306
  workspaceId: z.number().describe("Workspace ID"),
292
- blueprintId: z.string().describe("Blueprint ID"),
293
- entryId: z
294
- .string()
307
+ blueprintId: blueprintIdParam,
308
+ entryId: entryIdParam
295
309
  .optional()
296
310
  .describe("PATCH mode: update this existing entry (title/text/url/content only) instead of creating one. A new url re-queues enrichment."),
297
311
  kind: entryKindParam.optional().describe("Entry kind — required when creating, ignored in PATCH mode (kind is immutable)."),
@@ -355,8 +369,8 @@ export function register(deps) {
355
369
  // ── blueprint_list_entries ─────────────────────────────────
356
370
  server.tool("blueprint_list_entries", "List a blueprint's library entries (full rows: text, url, structured content, enrichment status/transcript/error), or one entry via entryId. status pending/processing means the enrichment worker is still on it — synthesize 409s until every entry is ready; status failed carries the reason in `error` (fix the source or delete the entry). With entryId: revisions=true adds the entry's immutable history (newest first), downloadUrl=true adds a signed read URL for the uploaded blob.", {
357
371
  workspaceId: z.number().describe("Workspace ID"),
358
- blueprintId: z.string().describe("Blueprint ID"),
359
- entryId: z.string().optional().describe("Fetch just this entry"),
372
+ blueprintId: blueprintIdParam,
373
+ entryId: entryIdParam.optional().describe("Fetch just this entry"),
360
374
  revisions: z
361
375
  .boolean()
362
376
  .optional()
@@ -409,7 +423,7 @@ export function register(deps) {
409
423
  // ── blueprint_entry_upload_url ─────────────────────────────
410
424
  server.tool("blueprint_entry_upload_url", "Get a short-lived signed upload URL for a file that will become a library entry. Handshake: (1) this tool -> { uploadUrl, blobRef, expiresOn }; (2) PUT the bytes to uploadUrl (plain PUT with the file's Content-Type; no extra headers needed — works from anywhere, including FROM INSIDE A VM via vm_execute_script with Python requests.put, the walkthrough screenshot path); (3) blueprint_add_entry with the returned blobRef. 409 means blob storage isn't configured on the service.", {
411
425
  workspaceId: z.number().describe("Workspace ID"),
412
- blueprintId: z.string().describe("Blueprint ID"),
426
+ blueprintId: blueprintIdParam,
413
427
  fileName: z.string().describe("Original file name, e.g. 'step-3-invoice-screen.png'"),
414
428
  region: regionParam,
415
429
  }, async ({ workspaceId, blueprintId, fileName, region }) => {
@@ -444,7 +458,7 @@ export function register(deps) {
444
458
  // ── blueprint_synthesize ───────────────────────────────────
445
459
  server.tool("blueprint_synthesize", "Synthesize a spec proposal from the library (LLM). Produces ONE pending proposal for review — it is NEVER applied silently; blueprint_apply_proposal is the gate. Call after feeding entries (state no_spec) or after the library moved past the spec (state spec_stale) — and answer ALL open questions FIRST so one synthesis folds every answer in (don't loop answer->synthesize per question). Synchronous and can take a while on large libraries; on timeout, poll blueprint_get — the proposal may have landed anyway. Blocked responses are structured: blocked.reason = proposal_pending (review or pass replace=true) | entries_enriching (poll blueprint_list_entries) | llm_unconfigured (escalate) | library_empty (blueprint_add_entry first).", {
446
460
  workspaceId: z.number().describe("Workspace ID"),
447
- blueprintId: z.string().describe("Blueprint ID"),
461
+ blueprintId: blueprintIdParam,
448
462
  instructions: z
449
463
  .string()
450
464
  .optional()
@@ -507,7 +521,7 @@ export function register(deps) {
507
521
  // ── blueprint_get_proposal ─────────────────────────────────
508
522
  server.tool("blueprint_get_proposal", "Read the pending synthesis proposal for review: the section-level patch, regenerated SOP, one-paragraph summary, and per-claim citations (entryId + provenance extracted|inferred|ambiguous — scrutinize 'inferred' and 'ambiguous' claims before applying). Returns the exact apply coordinates: blueprint_apply_proposal requires this proposal's baseVersion AND basedOnSeq, so a concurrent resynthesize can never swap a different proposal under your review.", {
509
523
  workspaceId: z.number().describe("Workspace ID"),
510
- blueprintId: z.string().describe("Blueprint ID"),
524
+ blueprintId: blueprintIdParam,
511
525
  region: regionParam,
512
526
  }, async ({ workspaceId, blueprintId, region }) => {
513
527
  const r = resolveRegion(workspaceId, region);
@@ -540,7 +554,7 @@ export function register(deps) {
540
554
  // ── blueprint_apply_proposal ───────────────────────────────
541
555
  server.tool("blueprint_apply_proposal", "Apply the pending proposal you reviewed: patch + SOP land as one validated, version-snapshotted document update, and specBasedOnSeq is stamped. Requires the reviewed proposal's coordinates (baseVersion + proposalBasedOnSeq from blueprint_get_proposal): the tool sends proposalBasedOnSeq with the apply so the service atomically REFUSES (409 proposal_mismatch) if the pending proposal is no longer the one you reviewed (a concurrent resynthesize swapped it); it also re-reads and checks before POSTing as defense in depth. After a successful apply the spec is ahead of the job (job_stale) — blueprint_build is the next verb, after answering any openQuestions the new spec carries.", {
542
556
  workspaceId: z.number().describe("Workspace ID"),
543
- blueprintId: z.string().describe("Blueprint ID"),
557
+ blueprintId: blueprintIdParam,
544
558
  baseVersion: z
545
559
  .number()
546
560
  .describe("The reviewed proposal's baseVersion (from blueprint_get_proposal.applyWith)"),
@@ -651,7 +665,7 @@ export function register(deps) {
651
665
  // ── blueprint_reject_proposal ──────────────────────────────
652
666
  server.tool("blueprint_reject_proposal", "Reject (discard) the pending proposal — use when the synthesis got it wrong or the spec moved underneath it. A 404 ('no pending proposal') is success-shaped: someone else already applied or rejected it, so the outcome you wanted (no pending proposal blocking synthesize) holds either way. Follow with blueprint_synthesize (optionally with steering `instructions`) to produce a better one.", {
653
667
  workspaceId: z.number().describe("Workspace ID"),
654
- blueprintId: z.string().describe("Blueprint ID"),
668
+ blueprintId: blueprintIdParam,
655
669
  region: regionParam,
656
670
  }, async ({ workspaceId, blueprintId, region }) => {
657
671
  const r = resolveRegion(workspaceId, region);
@@ -686,7 +700,7 @@ export function register(deps) {
686
700
  // ── blueprint_answer_question ──────────────────────────────
687
701
  server.tool("blueprint_answer_question", "Answer ONE open synthesis question atomically: the service removes it from document.openQuestions, stores the answer as a note entry, and snapshots a version in a single transaction. `question` must match the openQuestions text EXACTLY (from blueprint_get / resolve_blueprint_state). A 404 means another writer already answered it — that is CONVERGENCE, not failure; move to the next question. Builder questions (build run needs_input) are NOT answered here — use answer_build_question. DRIFT NOTE: each answer bumps librarySeq, so the spec goes spec_stale — answer ALL open questions first, then run blueprint_synthesize ONCE; never loop answer->synthesize per question.", {
688
702
  workspaceId: z.number().describe("Workspace ID"),
689
- blueprintId: z.string().describe("Blueprint ID"),
703
+ blueprintId: blueprintIdParam,
690
704
  question: z
691
705
  .string()
692
706
  .describe("The open question being answered — EXACT text from document.openQuestions"),
@@ -789,7 +803,7 @@ export function register(deps) {
789
803
  // ── blueprint_build ────────────────────────────────────────
790
804
  server.tool("blueprint_build", "Sync the spec into its Job (the primary build verb): validates the spec, ensures the router + route exist, upserts judge test cases from exampleCases (content-hash idempotent), attaches spec + library + resolved resource refs as the builder artifact, and queues/folds into a build run. RETURNS THE HANDOFF ARTIFACT: { middlewareId, routeId, buildId, testCaseIds } — the coordinates the whole jobs toolset (get_build_status, run_tests, resolve_job_state, publish_job) takes over with. Precondition enforced here: if the linked build run is needs_input, this returns blocked instead of syncing (the service would fold cases WITHOUT re-queueing the builder) — answer_build_question first. A 400 means the spec isn't syncable and carries the problem list.", {
791
805
  workspaceId: z.number().describe("Workspace ID"),
792
- blueprintId: z.string().describe("Blueprint ID"),
806
+ blueprintId: blueprintIdParam,
793
807
  instructions: z
794
808
  .string()
795
809
  .optional()
@@ -839,7 +853,7 @@ export function register(deps) {
839
853
  // ── blueprint_build_status ─────────────────────────────────
840
854
  server.tool("blueprint_build_status", "Blueprint-side view of the linked build: composes the blueprint's state with the stamped build run (status queued|running|green|failed|needs_input, summary, open questions). needs_input questions come back with answer_build_question coordinates prefilled — try to answer them from the library FIRST (blueprint_list_entries; cite what you find) before escalating to a human. For the full job-side picture (test cases, executions), use resolve_job_state with the same coordinates.", {
841
855
  workspaceId: z.number().describe("Workspace ID"),
842
- blueprintId: z.string().describe("Blueprint ID"),
856
+ blueprintId: blueprintIdParam,
843
857
  region: regionParam,
844
858
  }, async ({ workspaceId, blueprintId, region }) => {
845
859
  const r = resolveRegion(workspaceId, region);
@@ -902,7 +916,7 @@ export function register(deps) {
902
916
  // ── blueprint_import_cases ─────────────────────────────────
903
917
  server.tool("blueprint_import_cases", "Adopt the linked job's test cases into the spec's exampleCases (upsert by name) — the job_ahead FOLD-BACK arrow. Use when the job was edited directly (update_job / teach_job / Dev-Mode clones tripped reverse drift) and the direct edits should become spec truth, or right after blueprint_create linked an existing job. After importing, the spec is ahead of the job (job_stale): review it, then blueprint_build re-syncs and re-stamps the drift baseline. The alternative job_ahead exit is blueprint_build alone — rebuild from the spec and OVERWRITE the direct edits.", {
904
918
  workspaceId: z.number().describe("Workspace ID"),
905
- blueprintId: z.string().describe("Blueprint ID"),
919
+ blueprintId: blueprintIdParam,
906
920
  region: regionParam,
907
921
  }, async ({ workspaceId, blueprintId, region }) => {
908
922
  const r = resolveRegion(workspaceId, region);
@@ -932,7 +946,7 @@ export function register(deps) {
932
946
  // ── blueprint_list_versions ────────────────────────────────
933
947
  server.tool("blueprint_list_versions", "List a blueprint's spec version snapshots (newest first) — every document change (apply, direct update, answered question) snapshots one, with its note. Pass version to fetch one full snapshot (e.g. to diff what a proposal changed, or to recover a document to re-author against after a CAS 409). Entry-level history lives on blueprint_list_entries revisions=true instead.", {
934
948
  workspaceId: z.number().describe("Workspace ID"),
935
- blueprintId: z.string().describe("Blueprint ID"),
949
+ blueprintId: blueprintIdParam,
936
950
  version: z.number().optional().describe("Fetch one full version snapshot"),
937
951
  region: regionParam,
938
952
  }, async ({ workspaceId, blueprintId, version, region }) => {
@@ -953,7 +967,7 @@ export function register(deps) {
953
967
  // ── resolve_blueprint_state ────────────────────────────────
954
968
  server.tool("resolve_blueprint_state", "The 'where am I in the blueprint loop?' call — START HERE when working a blueprint (the sibling of resolve_job_state, one layer up). One call fetches the blueprint (state + drift + proposal + open questions), its library entries (enrichment status), and the linked build run, then returns an UNFOLDED state (no_context | enriching | no_spec | proposal_pending | needs_answers | building | needs_input | build_failed | job_ahead | spec_stale | job_stale | in_sync — every state maps to one verb), blockers[] (enrichment_failed / builder_stalled / question_needs_human — the escalation surface), and ordered nextActions with the concrete tool calls prefilled. The loop it drives: add entries -> synthesize -> answer questions -> apply proposal -> blueprint_build -> the jobs loop (resolve_job_state) takes over.", {
955
969
  workspaceId: z.number().describe("Workspace ID"),
956
- blueprintId: z.string().describe("Blueprint ID to resolve"),
970
+ blueprintId: blueprintIdParam.describe("Blueprint ID (uuid) to resolve"),
957
971
  region: regionParam,
958
972
  }, async ({ workspaceId, blueprintId, region }) => {
959
973
  const r = resolveRegion(workspaceId, region);