@axonity-ai/mcp 0.6.0 → 0.7.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.
Files changed (50) hide show
  1. package/README.md +176 -14
  2. package/dist/client.d.ts +15 -2
  3. package/dist/client.js +8 -1
  4. package/dist/client.js.map +1 -1
  5. package/dist/contract.d.ts +88 -0
  6. package/dist/contract.js +227 -0
  7. package/dist/contract.js.map +1 -0
  8. package/dist/errors.d.ts +15 -3
  9. package/dist/errors.js +27 -3
  10. package/dist/errors.js.map +1 -1
  11. package/dist/generated/listFilters.d.ts +19 -0
  12. package/dist/generated/listFilters.js +78 -0
  13. package/dist/generated/listFilters.js.map +1 -0
  14. package/dist/index.js +25 -2
  15. package/dist/index.js.map +1 -1
  16. package/dist/tools/authoringSpec.d.ts +76 -0
  17. package/dist/tools/authoringSpec.js +169 -0
  18. package/dist/tools/authoringSpec.js.map +1 -0
  19. package/dist/tools/company.d.ts +5 -2
  20. package/dist/tools/company.js +56 -2
  21. package/dist/tools/company.js.map +1 -1
  22. package/dist/tools/conventions.d.ts +16 -0
  23. package/dist/tools/conventions.js +191 -19
  24. package/dist/tools/conventions.js.map +1 -1
  25. package/dist/tools/credentials.d.ts +20 -0
  26. package/dist/tools/credentials.js +41 -0
  27. package/dist/tools/credentials.js.map +1 -1
  28. package/dist/tools/extras.d.ts +17 -0
  29. package/dist/tools/extras.js +139 -9
  30. package/dist/tools/extras.js.map +1 -1
  31. package/dist/tools/register.d.ts +27 -0
  32. package/dist/tools/register.js +19 -1
  33. package/dist/tools/register.js.map +1 -1
  34. package/dist/tools/runs.d.ts +11 -0
  35. package/dist/tools/runs.js +169 -26
  36. package/dist/tools/runs.js.map +1 -1
  37. package/dist/tools/secrets.d.ts +33 -0
  38. package/dist/tools/secrets.js +69 -0
  39. package/dist/tools/secrets.js.map +1 -0
  40. package/dist/tools/subworkflows.d.ts +20 -0
  41. package/dist/tools/subworkflows.js +42 -0
  42. package/dist/tools/subworkflows.js.map +1 -0
  43. package/dist/tools/validation.js +74 -4
  44. package/dist/tools/validation.js.map +1 -1
  45. package/dist/tools/versions.d.ts +9 -0
  46. package/dist/tools/versions.js +36 -0
  47. package/dist/tools/versions.js.map +1 -1
  48. package/dist/tools/workflowMutations.js +44 -12
  49. package/dist/tools/workflowMutations.js.map +1 -1
  50. package/package.json +3 -1
@@ -111,9 +111,10 @@ export function registerAttachTools(server, client) {
111
111
  */
112
112
  const link = (subject, target, path, firstArg, secondArg,
113
113
  /**
114
- * The read-back tool for this link, when one exists. A 200 here does not
115
- * prove the link resolved, so the description points at the tool that does —
116
- * agent-scoped links have one, `skill → workflow` has no list route.
114
+ * The read-back tool for this link. A 200 here does not prove the link
115
+ * resolved, so the description points at the tool that does. Every link
116
+ * has one since axonity-flow#961 S8 gave the workflow-scoped variant its
117
+ * list route; the parameter stays optional for a future link that does not.
117
118
  */
118
119
  readBack) => {
119
120
  const shape = { [firstArg]: z.string(), [secondArg]: z.string() };
@@ -135,9 +136,12 @@ export function registerAttachTools(server, client) {
135
136
  })));
136
137
  };
137
138
  link("skill", "agent", (agentId, skillId) => `/api/v1/agents/${agentId}/skills-v2/${skillId}`, "agentId", "skillId", "list_agent_skills");
138
- // No read-back for the workflow-scoped variant: the backend has no
139
- // GET /workflows/{id}/skills-v2, so there is nothing to point at.
140
- link("skill", "workflow", (workflowId, skillId) => `/api/v1/workflows/${workflowId}/skills-v2/${skillId}`, "workflowId", "skillId");
139
+ // The workflow-scoped variant HAS a read-back now (axonity-flow#961 S8).
140
+ // Attaching and detaching both had a route while reading back did not, so
141
+ // nothing distinguished a link that landed from one that silently did
142
+ // nothing — the shape of axonity-flow#778, where 27 detaches all reported
143
+ // `detached: true` and not one link had ever existed.
144
+ link("skill", "workflow", (workflowId, skillId) => `/api/v1/workflows/${workflowId}/skills-v2/${skillId}`, "workflowId", "skillId", "list_workflow_skills");
141
145
  link("policy", "agent", (agentId, policyId) => `/api/v1/agents/${agentId}/policies/${policyId}`, "agentId", "policyId", "list_agent_policies");
142
146
  // Reference docs attach to agents only — there is no workflow-scoped
143
147
  // reference-doc route on the backend, so no `*_to_workflow` pair here.
@@ -160,16 +164,29 @@ export function registerAttachTools(server, client) {
160
164
  `every agent and a single playbook can run to 15 KB. Read one body ` +
161
165
  `deliberately with read_${subject === "reference_doc" ? "reference_doc" : subject} ` +
162
166
  `when you actually intend to read it. Pass verbosity: "full" only when ` +
163
- `you need every field of every row.`, {
167
+ `you need every field of every row.` +
168
+ `\n\nPass workflowId to see the agent as it is composed INSIDE that ` +
169
+ `workflow — the runtime view, including anything scoped to the workflow ` +
170
+ `rather than to the agent. Without it you see the agent on its own, ` +
171
+ `which is not what a run of that workflow assembles.`, {
164
172
  agentId: z.string().describe("The agent's id."),
173
+ workflowId: z
174
+ .string()
175
+ .optional()
176
+ .describe("Compose the runtime view for this workflow. Omit for the agent's " +
177
+ "own scope only."),
165
178
  verbosity: z
166
179
  .enum(["identity", "full"])
167
180
  .optional()
168
181
  .describe('How much of each row to return. "identity" (default) is id, name, ' +
169
182
  'description, status and linkSource. "full" is the entire entity, ' +
170
183
  "bodies included — expensive, and rarely what an audit needs."),
171
- }, async ({ agentId, verbosity }) => guard(async () => {
172
- const response = await client.get(path(agentId));
184
+ }, async ({ agentId, workflowId, verbosity, }) => guard(async () => {
185
+ const response = workflowId
186
+ ? await client.get(path(agentId), {
187
+ workflow_id: workflowId,
188
+ })
189
+ : await client.get(path(agentId));
173
190
  if (verbosity === "full")
174
191
  return jsonResult(response);
175
192
  return jsonResult(projectLinkRows(response, rowsKey));
@@ -178,6 +195,92 @@ export function registerAttachTools(server, client) {
178
195
  listLinks("skill", "skills", (id) => `/api/v1/agents/${id}/skills-v2`, "skills");
179
196
  listLinks("policy", "policies", (id) => `/api/v1/agents/${id}/policies`, "policies");
180
197
  listLinks("reference_doc", "reference_docs", (id) => `/api/v1/agents/${id}/reference-docs`, "references");
198
+ /**
199
+ * The workflow-scoped read-back (axonity-flow#961 S8).
200
+ *
201
+ * Deliberately without `linkSource`: unlike the agent view there is only one
202
+ * way a skill reaches a workflow — an explicit link — so a field that always
203
+ * says the same thing would train a reader to skip it. Live links only, for
204
+ * the reason `list_agent_skills` gives: detaching closes the interval rather
205
+ * than deleting the row, and a stale dependency list is worse than none.
206
+ */
207
+ server.tool("list_workflow_skills", "List the skills currently scoped to a WORKFLOW — the read-back for " +
208
+ "attach_skill_to_workflow. A 200 from an attach does not prove the link " +
209
+ "resolved, and the link lives outside the workflow document, so " +
210
+ "read_workflow will never show it: this is the only way to tell an attach " +
211
+ "that landed from one that silently did nothing. Read-only. " +
212
+ "\n\nReturns IDENTITY by default; pass verbosity: \"full\" for whole " +
213
+ "bodies, which a skill's playbook makes expensive.", {
214
+ workflowId: z.string().describe("The workflow's id."),
215
+ verbosity: z
216
+ .enum(["identity", "full"])
217
+ .optional()
218
+ .describe('How much of each row to return. "identity" (default) is id, name, ' +
219
+ 'description and status. "full" is the entire skill, body included.'),
220
+ }, async ({ workflowId, verbosity }) => guard(async () => {
221
+ const response = await client.get(`/api/v1/workflows/${workflowId}/skills-v2`);
222
+ if (verbosity === "full")
223
+ return jsonResult(response);
224
+ return jsonResult(projectLinkRows(response, "skills"));
225
+ }));
226
+ }
227
+ /**
228
+ * "What breaks if I change this" — the reverse look-up, for both halves of the
229
+ * catalogue (axonity-flow#845 S5 and #961 S8).
230
+ *
231
+ * A shared library item is edited on the assumption that someone knows what
232
+ * uses it. Three items could answer that agent-first; the rest of the catalogue
233
+ * could not answer it at all, and there a broken reference stops a RUN rather
234
+ * than merely thinning a prompt. The only way to find out was to validate every
235
+ * workflow in the tenant and see where it went wrong.
236
+ *
237
+ * It was never queryable because these are not rows in a join table: they are
238
+ * keys inside a JSON document, and per entity in more than one place — an agent
239
+ * is a step OWNER and the `ownerAgentId` of a subprocess step; a tool appears in
240
+ * a step contract, in a plan activity, and on an automation step's config. The
241
+ * backend answers through one reader for exactly that reason.
242
+ */
243
+ export function registerDependencyTools(server, client) {
244
+ server.tool("list_workflows_using", "Which workflows reference an entity, and IN WHICH STEPS. Ask this BEFORE " +
245
+ "editing or deleting anything shared — it is the answer to \"what breaks " +
246
+ "if I change this\", and the alternative is validating every workflow in " +
247
+ "the tenant. Read-only. " +
248
+ "\n\nEach hit carries the workflow's id and name, the author's own names " +
249
+ "for the steps that name it (somewhere to look, not just a yes), and a " +
250
+ "`state`: `published` is a dependency that is LIVE right now and must not " +
251
+ "break; `draft` is one someone is still building. The same workflow can " +
252
+ "appear twice, once per state, and the difference is the point. " +
253
+ "\n\nThis reads workflow documents. For the agents that depend on a " +
254
+ "skill, policy or reference doc — a prompt-level dependency, not a " +
255
+ "document one — use list_dependent_agents.", {
256
+ entityKind: z
257
+ .enum(["tool", "agent", "flow", "output_schema", "workflow"])
258
+ .describe("What kind of thing you are about to change. `workflow` answers " +
259
+ "which workflows CALL this one as a sub-process."),
260
+ entityId: z.string().describe("That entity's id."),
261
+ }, async ({ entityKind, entityId }) => guard(async () => jsonResult(await client.get(`/api/v1/workflows/using/${entityKind}/${entityId}`))));
262
+ server.tool("list_dependent_agents", "Which agents currently depend on a skill, policy or reference doc — the " +
263
+ "reverse of list_agent_skills / list_agent_policies / " +
264
+ "list_agent_reference_docs. Read it before editing or deleting a shared " +
265
+ "library item: changing one silently changes every prompt it is in. " +
266
+ "Read-only. " +
267
+ "\n\nLIVE links only. Detaching closes the link's interval rather than " +
268
+ "deleting the row, so a list that included closed ones would name agents " +
269
+ "that no longer use it — worse than no list at all. " +
270
+ "\n\nFor workflow documents that reference a tool, agent, flow, output " +
271
+ "schema or workflow, use list_workflows_using instead.", {
272
+ entityKind: z
273
+ .enum(["skill", "policy", "reference_doc"])
274
+ .describe("Which library item you are about to change."),
275
+ entityId: z.string().describe("That item's id."),
276
+ }, async ({ entityKind, entityId }) => guard(async () => {
277
+ const base = {
278
+ skill: "/api/v1/skills",
279
+ policy: "/api/v1/policies",
280
+ reference_doc: "/api/v1/reference-docs",
281
+ }[entityKind];
282
+ return jsonResult(await client.get(`${base}/${entityId}/dependent-agents`));
283
+ }));
181
284
  }
182
285
  /**
183
286
  * Small standalone tools that don't fit any of the other groupings: the
@@ -195,5 +298,32 @@ export function registerCatalogTools(server, client) {
195
298
  "delete_flow (a backend gap, despite what its docstrings claim), so " +
196
299
  "editing one in place risks changing something other tenants share.", { flowId: z.string().describe("The flow's id.") }, async ({ flowId }) => guard(async () => jsonResult(await client.post(`/api/v1/flows/${flowId}/clone`))));
197
300
  server.tool("clone_prompt_snippet", "Duplicate a prompt snippet into a new, independent copy.", { snippetId: z.string().describe("The prompt snippet's id.") }, async ({ snippetId }) => guard(async () => jsonResult(await client.post(`/api/v1/prompt-snippets/${snippetId}/clone`))));
301
+ server.tool("list_tool_packages", "The Python packages a tool's code may import on THIS deploy, with their " +
302
+ "metadata. This is the allowlist `validate_tool_code` judges against, so " +
303
+ "reading it beats discovering the boundary through a rejected import. " +
304
+ "Read-only.", {}, async () => guard(async () => jsonResult(await client.get("/api/v1/tools/packages"))));
305
+ /**
306
+ * The template catalogues. Four routes, one tool: they are the same question
307
+ * asked about four things, and four near-identical tools on a surface this
308
+ * size is how a reader stops reading tool names.
309
+ */
310
+ server.tool("list_templates", "List the starting points this deploy ships: agent, tool and workflow " +
311
+ "templates, or the general template catalogue. A template is a shape to " +
312
+ "author FROM — read one for its fields, then create a fresh entity with " +
313
+ "those values. It is not something you reference by id from a workflow. " +
314
+ "Read-only.", {
315
+ kind: z
316
+ .enum(["all", "agent", "tool", "workflow"])
317
+ .optional()
318
+ .describe('Which catalogue. "all" (default) is the general template list; the ' +
319
+ "others are the per-entity catalogues."),
320
+ }, async ({ kind }) => guard(async () => jsonResult(await client.get({
321
+ all: "/api/v1/templates",
322
+ agent: "/api/v1/agent-templates",
323
+ tool: "/api/v1/tool-templates",
324
+ workflow: "/api/v1/workflow-templates",
325
+ }[kind ?? "all"]))));
326
+ server.tool("read_template", "Read one template from the general catalogue by id — its full definition, " +
327
+ "which is what you author a new entity from. Read-only.", { templateId: z.string().describe("The template's id, from list_templates.") }, async ({ templateId }) => guard(async () => jsonResult(await client.get(`/api/v1/templates/${templateId}`))));
198
328
  }
199
329
  //# sourceMappingURL=extras.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"extras.js","sourceRoot":"","sources":["../../src/tools/extras.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"extras.js","sourceRoot":"","sources":["../../src/tools/extras.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,EAAE,4BAA4B,EAAE,MAAM,kBAAkB,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9D,MAAM,UAAU,oBAAoB,CAClC,MAAiB,EACjB,MAAqB;IAErB,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,8EAA8E;QAC5E,sCAAsC,EACxC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,EACnD,KAAK,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,CACpB,KAAK,CAAC,KAAK,IAAI,EAAE,CACf,UAAU,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,kBAAkB,OAAO,UAAU,CAAC,CAAC,CAClE,CACJ,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,0EAA0E,EAC1E;QACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;QAC/C,MAAM,EAAE,CAAC;aACN,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;aACnB,QAAQ,CAAC,6DAA6D,CAAC;KAC3E,EACD,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,CAC5B,KAAK,CAAC,KAAK,IAAI,EAAE,CACf,UAAU,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,kBAAkB,OAAO,UAAU,EAAE,MAAM,CAAC,CAAC,CAC3E,CACJ,CAAC;IAEF,yEAAyE;IACzE,+EAA+E;IAC/E,6EAA6E;IAC7E,4EAA4E;IAC5E,6DAA6D;AAC/D,CAAC;AAED,MAAM,UAAU,sBAAsB,CACpC,MAAiB,EACjB,MAAqB;IAErB,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,yEAAyE;QACvE,iFAAiF,EACnF;QACE,MAAM,EAAE,CAAC;aACN,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC;aACnB,QAAQ,CAAC,mEAAmE,CAAC;KACjF,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CACnB,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,4BAA4B,CAAC,MAAM,CAAC,CAAC;QACrC,OAAO,UAAU,CACf,MAAM,MAAM,CAAC,IAAI,CAAC,eAAe,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,MAAM,EAAE,CAAC,CACrE,CAAC;IACJ,CAAC,CAAC,CACL,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,+EAA+E;QAC7E,gDAAgD,EAClD;QACE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QACnD,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,mCAAmC,CAAC;QAC/E,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,+BAA+B,CAAC;KACxE,EACD,KAAK,EAAE,EAAE,EAAE,EAAE,eAAe,EAAE,MAAM,EAAE,EAAE,EAAE,CACxC,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,4BAA4B,CAAC,MAAM,CAAC,CAAC;QACrC,OAAO,UAAU,CACf,MAAM,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,EAAE,EAAE;YACtC,eAAe;YACf,IAAI,EAAE,WAAW;YACjB,GAAG,MAAM;SACV,CAAC,CACH,CAAC;IACJ,CAAC,CAAC,CACL,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,eAAe,GAAG;IACtB,IAAI;IACJ,MAAM;IACN,OAAO;IACP,aAAa;IACb,SAAS;IACT,QAAQ;IACR,QAAQ;IACR,YAAY;IACZ,OAAO;CACC,CAAC;AAEX,4DAA4D;AAC5D,MAAM,UAAU,eAAe,CAC7B,QAAiC,EACjC,OAAe;IAEf,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;IAC/B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,QAAQ,CAAC;IAE1C,OAAO;QACL,GAAG,QAAQ;QACX,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;YAC1B,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO,GAAG,CAAC;YACxD,MAAM,MAAM,GAAG,GAA8B,CAAC;YAC9C,MAAM,IAAI,GAA4B,EAAE,CAAC;YACzC,KAAK,MAAM,KAAK,IAAI,eAAe,EAAE,CAAC;gBACpC,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,SAAS;oBAAE,IAAI,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC/D,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC,CAAC;QACF,yEAAyE;QACzE,+CAA+C;QAC/C,aAAa,EACX,yEAAyE;YACzE,sDAAsD;KACzD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,MAAiB,EACjB,MAAqB;IAErB;;;;OAIG;IACH,MAAM,IAAI,GAAG,CACX,OAAe,EACf,MAAc,EACd,IAAsC,EACtC,QAAgB,EAChB,SAAiB;IACjB;;;;;OAKG;IACH,QAAiB,EACjB,EAAE;QACF,MAAM,KAAK,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QAElE,MAAM,CAAC,IAAI,CACT,UAAU,OAAO,OAAO,MAAM,EAAE,EAChC,WAAW,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,SAAS,MAAM,WAAW,MAAM,WAAW;YAC7E,CAAC,QAAQ;gBACP,CAAC,CAAC,4BAA4B,QAAQ,6BAA6B,MAAM,KAAK;oBAC5E,6DAA6D,MAAM,QAAQ;oBAC3E,cAAc;gBAChB,CAAC,CAAC,EAAE,CAAC,EACT,KAAK,EACL,KAAK,EAAE,IAA4B,EAAE,EAAE,CACrC,KAAK,CAAC,KAAK,IAAI,EAAE,CACf,UAAU,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CACrE,CACJ,CAAC;QAEF,MAAM,CAAC,IAAI,CACT,UAAU,OAAO,SAAS,MAAM,EAAE,EAClC,aAAa,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,WAAW,MAAM,cAAc;YACnE,0BAA0B,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,yBAAyB;YAC5E,wEAAwE;YACxE,2EAA2E;YAC3E,0EAA0E;YAC1E,4BAA4B;YAC5B,CAAC,QAAQ,CAAC,CAAC,CAAC,gCAAgC,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EACjE,KAAK,EACL,KAAK,EAAE,IAA4B,EAAE,EAAE,CACrC,KAAK,CAAC,KAAK,IAAI,EAAE,CACf,YAAY,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;YACpE,QAAQ;YACR,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE;SACtE,CAAC,CACH,CACJ,CAAC;IACJ,CAAC,CAAC;IAEF,IAAI,CACF,OAAO,EACP,OAAO,EACP,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,kBAAkB,OAAO,cAAc,OAAO,EAAE,EACtE,SAAS,EACT,SAAS,EACT,mBAAmB,CACpB,CAAC;IACF,yEAAyE;IACzE,0EAA0E;IAC1E,sEAAsE;IACtE,0EAA0E;IAC1E,sDAAsD;IACtD,IAAI,CACF,OAAO,EACP,UAAU,EACV,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC,qBAAqB,UAAU,cAAc,OAAO,EAAE,EAC/E,YAAY,EACZ,SAAS,EACT,sBAAsB,CACvB,CAAC;IACF,IAAI,CACF,QAAQ,EACR,OAAO,EACP,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,kBAAkB,OAAO,aAAa,QAAQ,EAAE,EACvE,SAAS,EACT,UAAU,EACV,qBAAqB,CACtB,CAAC;IACF,qEAAqE;IACrE,uEAAuE;IACvE,IAAI,CACF,WAAW,EACX,OAAO,EACP,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,CAAC,kBAAkB,OAAO,mBAAmB,KAAK,EAAE,EACvE,SAAS,EACT,OAAO,EACP,2BAA2B,CAC5B,CAAC;IAEF;;;;;OAKG;IACH,MAAM,SAAS,GAAG,CAChB,OAAe,EACf,MAAc,EACd,IAAiC;IACjC,uFAAuF;IACvF,OAAe,EACf,EAAE;QACF,MAAM,CAAC,IAAI,CACT,cAAc,MAAM,EAAE,EACtB,YAAY,OAAO,oDAAoD;YACrE,UAAU,OAAO,yDAAyD;YAC1E,yDAAyD;YACzD,qEAAqE;YACrE,sEAAsE;YACtE,sEAAsE;YACtE,oEAAoE;YACpE,0BAA0B,OAAO,KAAK,eAAe,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,OAAO,GAAG;YACpF,wEAAwE;YACxE,oCAAoC;YACpC,qEAAqE;YACrE,yEAAyE;YACzE,qEAAqE;YACrE,qDAAqD,EACvD;YACE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;YAC/C,UAAU,EAAE,CAAC;iBACV,MAAM,EAAE;iBACR,QAAQ,EAAE;iBACV,QAAQ,CACP,mEAAmE;gBACjE,iBAAiB,CACpB;YACH,SAAS,EAAE,CAAC;iBACT,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;iBAC1B,QAAQ,EAAE;iBACV,QAAQ,CACP,oEAAoE;gBAClE,mEAAmE;gBACnE,8DAA8D,CACjE;SACJ,EACD,KAAK,EAAE,EACL,OAAO,EACP,UAAU,EACV,SAAS,GAKV,EAAE,EAAE,CACH,KAAK,CAAC,KAAK,IAAI,EAAE;YACf,MAAM,QAAQ,GAAG,UAAU;gBACzB,CAAC,CAAC,MAAM,MAAM,CAAC,GAAG,CAA0B,IAAI,CAAC,OAAO,CAAC,EAAE;oBACvD,WAAW,EAAE,UAAU;iBACxB,CAAC;gBACJ,CAAC,CAAC,MAAM,MAAM,CAAC,GAAG,CAA0B,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;YAC7D,IAAI,SAAS,KAAK,MAAM;gBAAE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;YACtD,OAAO,UAAU,CAAC,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;QACxD,CAAC,CAAC,CACL,CAAC;IACJ,CAAC,CAAC;IAEF,SAAS,CAAC,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,kBAAkB,EAAE,YAAY,EAAE,QAAQ,CAAC,CAAC;IACjF,SAAS,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,kBAAkB,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;IACrF,SAAS,CACP,eAAe,EACf,gBAAgB,EAChB,CAAC,EAAE,EAAE,EAAE,CAAC,kBAAkB,EAAE,iBAAiB,EAC7C,YAAY,CACb,CAAC;IAEF;;;;;;;;OAQG;IACH,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,qEAAqE;QACnE,yEAAyE;QACzE,iEAAiE;QACjE,2EAA2E;QAC3E,6DAA6D;QAC7D,sEAAsE;QACtE,mDAAmD,EACrD;QACE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;QACrD,SAAS,EAAE,CAAC;aACT,IAAI,CAAC,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;aAC1B,QAAQ,EAAE;aACV,QAAQ,CACP,oEAAoE;YAClE,oEAAoE,CACvE;KACJ,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,EAAE,CAClC,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,GAAG,CAC/B,qBAAqB,UAAU,YAAY,CAC5C,CAAC;QACF,IAAI,SAAS,KAAK,MAAM;YAAE,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC;QACtD,OAAO,UAAU,CAAC,eAAe,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CACL,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAiB,EACjB,MAAqB;IAErB,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,2EAA2E;QACzE,0EAA0E;QAC1E,0EAA0E;QAC1E,yBAAyB;QACzB,0EAA0E;QAC1E,wEAAwE;QACxE,2EAA2E;QAC3E,yEAAyE;QACzE,iEAAiE;QACjE,qEAAqE;QACrE,oEAAoE;QACpE,2CAA2C,EAC7C;QACE,UAAU,EAAE,CAAC;aACV,IAAI,CAAC,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;aAC5D,QAAQ,CACP,iEAAiE;YAC/D,iDAAiD,CACpD;QACH,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;KACnD,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE,CACjC,KAAK,CAAC,KAAK,IAAI,EAAE,CACf,UAAU,CACR,MAAM,MAAM,CAAC,GAAG,CAAC,2BAA2B,UAAU,IAAI,QAAQ,EAAE,CAAC,CACtE,CACF,CACJ,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,uBAAuB,EACvB,0EAA0E;QACxE,uDAAuD;QACvD,yEAAyE;QACzE,qEAAqE;QACrE,aAAa;QACb,wEAAwE;QACxE,0EAA0E;QAC1E,qDAAqD;QACrD,wEAAwE;QACxE,uDAAuD,EACzD;QACE,UAAU,EAAE,CAAC;aACV,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;aAC1C,QAAQ,CAAC,6CAA6C,CAAC;QAC1D,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC;KACjD,EACD,KAAK,EAAE,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,EAAE,CACjC,KAAK,CAAC,KAAK,IAAI,EAAE;QACf,MAAM,IAAI,GAAG;YACX,KAAK,EAAE,gBAAgB;YACvB,MAAM,EAAE,kBAAkB;YAC1B,aAAa,EAAE,wBAAwB;SACxC,CAAC,UAAU,CAAC,CAAC;QACd,OAAO,UAAU,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,QAAQ,mBAAmB,CAAC,CAAC,CAAC;IAC9E,CAAC,CAAC,CACL,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,MAAqB;IAC3E,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,4EAA4E;QAC1E,2EAA2E;QAC3E,sCAAsC,EACxC,EAAE,EACF,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC,CACpF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,YAAY,EACZ,uEAAuE;QACrE,oEAAoE;QACpE,uEAAuE;QACvE,qEAAqE;QACrE,oEAAoE,EACtE,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,EACjD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CACnB,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,iBAAiB,MAAM,QAAQ,CAAC,CAAC,CAAC,CACpF,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,0DAA0D,EAC1D,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,EAC9D,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,CACtB,KAAK,CAAC,KAAK,IAAI,EAAE,CACf,UAAU,CAAC,MAAM,MAAM,CAAC,IAAI,CAAC,2BAA2B,SAAS,QAAQ,CAAC,CAAC,CAC5E,CACJ,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,0EAA0E;QACxE,0EAA0E;QAC1E,uEAAuE;QACvE,YAAY,EACd,EAAE,EACF,KAAK,IAAI,EAAE,CACT,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAC5E,CAAC;IAEF;;;;OAIG;IACH,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,uEAAuE;QACrE,yEAAyE;QACzE,yEAAyE;QACzE,yEAAyE;QACzE,YAAY,EACd;QACE,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC;aAC1C,QAAQ,EAAE;aACV,QAAQ,CACP,qEAAqE;YACnE,uCAAuC,CAC1C;KACJ,EACD,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CACjB,KAAK,CAAC,KAAK,IAAI,EAAE,CACf,UAAU,CACR,MAAM,MAAM,CAAC,GAAG,CACd;QACE,GAAG,EAAE,mBAAmB;QACxB,KAAK,EAAE,yBAAyB;QAChC,IAAI,EAAE,wBAAwB;QAC9B,QAAQ,EAAE,4BAA4B;KACvC,CAAC,IAAI,IAAI,KAAK,CAAC,CACjB,CACF,CACF,CACJ,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,eAAe,EACf,4EAA4E;QAC1E,wDAAwD,EAC1D,EAAE,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,yCAAyC,CAAC,EAAE,EAC9E,KAAK,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,CACvB,KAAK,CAAC,KAAK,IAAI,EAAE,CACf,UAAU,CAAC,MAAM,MAAM,CAAC,GAAG,CAAC,qBAAqB,UAAU,EAAE,CAAC,CAAC,CAChE,CACJ,CAAC;AACJ,CAAC"}
@@ -23,6 +23,28 @@
23
23
  */
24
24
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
25
25
  import type { AxonityClient } from "../client.js";
26
+ /**
27
+ * One narrowing a `list_<plural>` route accepts.
28
+ *
29
+ * Filtering in the QUERY is not the same as filtering the answer: the backend
30
+ * applies it before the rows come back, so "which policies are tenant-scoped"
31
+ * is one call rather than a fetch-everything-and-sift — and on the paged routes
32
+ * it is the difference between an answer and page one of an answer.
33
+ *
34
+ * `arg` is the camelCase name the tool takes; `query` is the spelling the route
35
+ * declares, which is snake_case on some routes and camelCase on others. That
36
+ * inconsistency is real and is exactly what a caller should not have to know.
37
+ */
38
+ export interface ListFilter {
39
+ /** The tool argument's name (camelCase). */
40
+ arg: string;
41
+ /** The query-string key the route expects. */
42
+ query: string;
43
+ /** What kind of value it takes. */
44
+ type: "string" | "boolean";
45
+ /** Agent-facing description of what the filter does. */
46
+ description: string;
47
+ }
26
48
  export interface EntityDef {
27
49
  /** Singular tool noun, e.g. "workflow". */
28
50
  singular: string;
@@ -83,5 +105,10 @@ export interface EntityDef {
83
105
  * on the main list) is retained for a future entity that needs it.
84
106
  */
85
107
  deletedListPath?: "collection" | "query";
108
+ /**
109
+ * Query-string narrowings `list_<plural>` accepts, when the route declares
110
+ * any. Omit for an entity whose list route takes no parameters.
111
+ */
112
+ listFilters?: ListFilter[];
86
113
  }
87
114
  export declare function registerEntityTools(server: McpServer, client: AxonityClient, def: EntityDef): void;
@@ -33,7 +33,25 @@ export function registerEntityTools(server, client, def) {
33
33
  const publishable = def.publishable !== false;
34
34
  const creatable = def.creatable !== false;
35
35
  const readable = def.readable !== false;
36
- server.tool(`list_${plural}`, `List all ${label} in your Axonity tenant (id, name, status, version).`, {}, async () => guard(async () => jsonResult(await client.get(basePath))));
36
+ const listFilters = def.listFilters ?? [];
37
+ server.tool(`list_${plural}`, `List all ${label} in your Axonity tenant (id, name, status, version).` +
38
+ (listFilters.length > 0
39
+ ? ` Narrow it with ${listFilters
40
+ .map((f) => `\`${f.arg}\``)
41
+ .join(" / ")} — the filter is applied by the backend, so it answers ` +
42
+ `the narrower question rather than handing you everything to sift.`
43
+ : ""), Object.fromEntries(listFilters.map((filter) => [
44
+ filter.arg,
45
+ (filter.type === "boolean" ? z.boolean() : z.string())
46
+ .optional()
47
+ .describe(filter.description),
48
+ ])), async (args) => guard(async () => {
49
+ // No filters declared → call the route exactly as before, with no query
50
+ // argument at all rather than an empty one.
51
+ if (listFilters.length === 0)
52
+ return jsonResult(await client.get(basePath));
53
+ return jsonResult(await client.get(basePath, Object.fromEntries(listFilters.map((filter) => [filter.query, args[filter.arg]]))));
54
+ }));
37
55
  if (readable) {
38
56
  server.tool(`read_${singular}`, `Read one ${singular} by id, including its current draft and version. ` +
39
57
  `Read before you update — you need the current version.`, { id: z.string().describe(`The ${singular}'s id.`) }, async ({ id }) => guard(async () => jsonResult(await client.get(`${basePath}/${id}`))));
@@ -1 +1 @@
1
- {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,17 @@
8
8
  *
9
9
  * Runs are also the only thing in the product with a real archive state —
10
10
  * entities have soft-delete, runs have archive/unarchive.
11
+ *
12
+ * A RUN THAT ASKS A QUESTION CAN BE ANSWERED (#45 M9). `axonity_conventions`
13
+ * tells an agent to `start_workflow_run` to test a workflow end to end. A run
14
+ * that reaches an `ask_user` step parks there and waits — so, without a way to
15
+ * answer, the guide prescribed a loop the connector could not finish. The two
16
+ * tools that unpark a run supply the INPUT it is waiting for, which is not the
17
+ * same act as deciding a review:
18
+ * - `answer_run_question` / `send_run_message` are here.
19
+ * - `POST /runs/{id}/steps/{id}/plan-approval` is NOT, and
20
+ * `POST /runs/{id}/restart` cannot be. Both are recorded, with the reason,
21
+ * in `test/exclusions.test.ts` — as a decision rather than an omission.
11
22
  */
12
23
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
13
24
  import type { AxonityClient } from "../client.js";
@@ -8,6 +8,17 @@
8
8
  *
9
9
  * Runs are also the only thing in the product with a real archive state —
10
10
  * entities have soft-delete, runs have archive/unarchive.
11
+ *
12
+ * A RUN THAT ASKS A QUESTION CAN BE ANSWERED (#45 M9). `axonity_conventions`
13
+ * tells an agent to `start_workflow_run` to test a workflow end to end. A run
14
+ * that reaches an `ask_user` step parks there and waits — so, without a way to
15
+ * answer, the guide prescribed a loop the connector could not finish. The two
16
+ * tools that unpark a run supply the INPUT it is waiting for, which is not the
17
+ * same act as deciding a review:
18
+ * - `answer_run_question` / `send_run_message` are here.
19
+ * - `POST /runs/{id}/steps/{id}/plan-approval` is NOT, and
20
+ * `POST /runs/{id}/restart` cannot be. Both are recorded, with the reason,
21
+ * in `test/exclusions.test.ts` — as a decision rather than an omission.
11
22
  */
12
23
  import { z } from "zod";
13
24
  import { guard, jsonResult } from "./result.js";
@@ -19,18 +30,37 @@ export function registerRunTools(server, client) {
19
30
  "authored. This EXECUTES: it runs the PUBLISHED workflow against live " +
20
31
  "infrastructure (models, connectors), so it can incur cost and cause real " +
21
32
  "side effects. It does not run your unpublished draft. After starting, " +
22
- "follow it with read_run / read_run_trace / read_run_cost. Optionally pass " +
23
- "triggerInput to feed the workflow's trigger.", {
33
+ "follow it with read_run / read_run_trace / read_run_cost. " +
34
+ "\n\nA workflow can have MORE THAN ONE start (a button and a schedule, " +
35
+ "say), and each start declares its own fields. Read " +
36
+ "read_workflow_trigger_parameters first, then name the one you mean with " +
37
+ "triggerId and build triggerInput from THAT start's parameters — a " +
38
+ "triggerId that does not exist is a 422 listing the ones that do, never a " +
39
+ "quiet fallback to a different start. " +
40
+ "\n\nA run may PARK on a step that asks a question instead of finishing. " +
41
+ "read_run_waiting_on says what it is parked on; answer_run_question and " +
42
+ "send_run_message are how it moves again.", {
24
43
  workflowId: z.string().describe("The workflow's id."),
44
+ triggerId: z
45
+ .string()
46
+ .optional()
47
+ .describe("Which start to fire, from read_workflow_trigger_parameters' " +
48
+ "`triggers[].id`. Omit and the workflow's FIRST trigger is used — " +
49
+ "the historical behaviour, and an arbitrary choice on a workflow " +
50
+ "with several starts, so name one whenever more than one exists."),
25
51
  triggerInput: z
26
52
  .record(z.unknown())
27
53
  .optional()
28
- .describe("Input payload for the workflow's trigger. Omit for none."),
54
+ .describe("Input payload for the start you are firing, keyed by each " +
55
+ "parameter's `name`. Omit for none. Do NOT send a parameter marked " +
56
+ "`pinned` — the author owns that value and it is overwritten on " +
57
+ "every run regardless of what you send."),
29
58
  manualPhases: z
30
59
  .boolean()
31
60
  .optional()
32
61
  .describe("Run with manual phase gating. Defaults to false."),
33
- }, async ({ workflowId, triggerInput, manualPhases }) => guard(async () => jsonResult(await client.post(`/api/v1/workflows/${workflowId}/runs`, {
62
+ }, async ({ workflowId, triggerId, triggerInput, manualPhases }) => guard(async () => jsonResult(await client.post(`/api/v1/workflows/${workflowId}/runs`, {
63
+ ...(triggerId ? { triggerId } : {}),
34
64
  ...(triggerInput ? { triggerInput } : {}),
35
65
  ...(manualPhases === undefined ? {} : { manualPhases }),
36
66
  }))));
@@ -48,13 +78,19 @@ export function registerRunTools(server, client) {
48
78
  server.tool("list_runs", "List workflow runs across the tenant, newest first. Archived runs are " +
49
79
  "excluded unless includeArchived is true. To list runs of ONE workflow, " +
50
80
  "use list_workflow_runs instead — this route has no workflow filter." +
51
- "\n\nTHIS ONE IS NOT PAGED THE SAME WAY: it answers with a BARE ARRAY, " +
52
- "no envelope, no total and no cursor. You get at most limit rows (default " +
53
- "50, and a larger value is silently clamped to 200), so a result whose " +
54
- "length equals the limit you asked for is the signal that MORE MAY EXIST " +
55
- "— nothing in the response says so. Walk it with offset until you get a " +
56
- "short page. Unlike list_workflow_runs, this route does list per-item " +
57
- "FOR EACH runs alongside their launches.", {
81
+ "\n\nTHE RESPONSE IS ONE PAGE, NOT THE FULL LIST: " +
82
+ "{ items, nextCursor, pageSize, hasMore }. Default page size is 20, max " +
83
+ "200. While hasMore is true you have NOT seen every run — pass the " +
84
+ "response's nextCursor back as cursor to get the next page, and repeat " +
85
+ "until nextCursor is null. Counting or concluding anything (\"how many " +
86
+ "failed?\") from a single page with hasMore: true gives a confidently " +
87
+ "wrong answer. " +
88
+ "\n\nRuns arrive at ~78/min during a fan-out, which is why the position " +
89
+ "is a cursor and not an offset: an offset window under that rate skips " +
90
+ "and repeats rows between pages. Never build a cursor — echo back the " +
91
+ "one you were given. " +
92
+ "\n\nUnlike list_workflow_runs, this route does list per-item FOR EACH " +
93
+ "runs alongside their launches.", {
58
94
  status: z
59
95
  .string()
60
96
  .optional()
@@ -66,21 +102,20 @@ export function registerRunTools(server, client) {
66
102
  .number()
67
103
  .int()
68
104
  .optional()
69
- .describe("Rows to return. Defaults to 50, silently clamped to 200 — asking " +
70
- "for more does not fail, it just returns 200."),
71
- offset: z
72
- .number()
73
- .int()
105
+ .describe("Page size. Defaults to 20, silently clamped to 200 — asking for " +
106
+ "more does not fail, it just returns 200."),
107
+ cursor: z
108
+ .string()
74
109
  .optional()
75
- .describe("Rows to skip. Defaults to 0. Advance it by the page size to walk " +
76
- "the whole list; stop when a page comes back short."),
77
- }, async ({ status, createdAfter, createdBefore, includeArchived, limit, offset }) => guard(async () => jsonResult(await client.get("/api/v1/runs", {
110
+ .describe("Opaque continuation cursor from the previous response's nextCursor. " +
111
+ "Omit for the first page. Do not parse or construct one."),
112
+ }, async ({ status, createdAfter, createdBefore, includeArchived, limit, cursor }) => guard(async () => jsonResult(await client.get("/api/v1/runs", {
78
113
  status,
79
114
  created_after: createdAfter,
80
115
  created_before: createdBefore,
81
116
  include_archived: includeArchived,
82
117
  limit,
83
- offset,
118
+ cursor,
84
119
  }))));
85
120
  server.tool("list_workflow_runs", "List one workflow's LAUNCHES, newest first. Note this route takes " +
86
121
  "archivedOnly (show ONLY archived launches), which is not the same as " +
@@ -98,8 +133,18 @@ export function registerRunTools(server, client) {
98
133
  "entry — not 4,415. That entry carries forEachProgress " +
99
134
  "({ total, pending, inProgress, succeeded, failed, … }), which is where " +
100
135
  "per-item counts come from. Do not read the number of items on a page as " +
101
- "a number of runs.", {
136
+ "a number of runs." +
137
+ "\n\nFilter with status BEFORE paging, not after: the filter is applied " +
138
+ "in the query, so \"which launches failed?\" is one page rather than a " +
139
+ "walk through every page keeping the failures. A status this backend " +
140
+ "does not know is a 422 naming the ones it does — this connector " +
141
+ "deliberately keeps no copy of that list.", {
102
142
  workflowId: z.string().describe("The workflow's id."),
143
+ status: z
144
+ .array(z.string())
145
+ .optional()
146
+ .describe('Restrict to these launch statuses, e.g. ["failed", "cancelled"]. ' +
147
+ "Several are a union. Omit for every status."),
103
148
  archivedOnly: z
104
149
  .boolean()
105
150
  .optional()
@@ -117,23 +162,121 @@ export function registerRunTools(server, client) {
117
162
  "nextCursor verbatim. Omit for the first page. It marks a POSITION, " +
118
163
  "not an offset, so it stays correct while new runs are being " +
119
164
  "inserted. A token you built or edited yourself is a 400."),
120
- }, async ({ workflowId, archivedOnly, limit, cursor }) => guard(async () =>
165
+ }, async ({ workflowId, status, archivedOnly, limit, cursor }) => guard(async () =>
121
166
  // The page envelope is forwarded WHOLE. Unwrapping to items would drop
122
167
  // hasMore/nextCursor and recreate, one layer up, exactly the silent
123
168
  // truncation this tool exists to make visible (#37).
124
169
  jsonResult(await client.get(`/api/v1/workflows/${workflowId}/runs`, {
170
+ // This route reads a REPEATED key (?status=a&status=b); the
171
+ // tenant-wide `list_runs` reads one comma-separated string. A real
172
+ // backend difference, so each tool sends what its route declares.
173
+ status,
125
174
  archived_only: archivedOnly,
126
175
  limit,
127
176
  cursor,
128
177
  }))));
129
- server.tool("read_run", "Read one run in full: status, per-step state, the workflow snapshot it " +
130
- "ran against, trigger input, agent invocations, and validator verdicts. " +
131
- "The verdicts are the closest thing to evaluator findings — there is no " +
132
- "separate findings endpoint.", { runId: z.string().describe("The run's id.") }, async ({ runId }) => guard(async () => jsonResult(await client.get(`/api/v1/runs/${runId}`))));
178
+ server.tool("read_run", "Read one run: status, per-step state, trigger input, agent invocations, " +
179
+ "and validator verdicts. The verdicts are the closest thing to evaluator " +
180
+ "findings — there is no separate findings endpoint. " +
181
+ "\n\nThe WORKFLOW SNAPSHOT is omitted by default. It is the immutable " +
182
+ "copy of the document the run executed, and it measured 23,809 of 29,414 " +
183
+ "bytes — 81% — of one real response, none of which says anything about " +
184
+ "how the run went. An oversized response turns a call that SUCCEEDED into " +
185
+ "an error, which is the same trap apply_workflow_mutations avoids by not " +
186
+ "forwarding a document either. Pass includeSnapshot: true when you " +
187
+ "actually need to see what the run executed (e.g. it behaved unlike the " +
188
+ "current draft and you want to know which document it ran).", {
189
+ runId: z.string().describe("The run's id."),
190
+ includeSnapshot: z
191
+ .boolean()
192
+ .optional()
193
+ .describe("Include `workflowSnapshot`, the document this run executed. " +
194
+ "Defaults to FALSE here — the backend's own default is true, and " +
195
+ "this tool overrides it because the snapshot is typically most of " +
196
+ "the response and never the answer to a question about the run."),
197
+ }, async ({ runId, includeSnapshot }) => guard(async () => jsonResult(await client.get(`/api/v1/runs/${runId}`, {
198
+ includeSnapshot: includeSnapshot === true,
199
+ }))));
133
200
  server.tool("read_run_trace", "Read a run's chronological tool-call trace — each entry has the step, the " +
134
201
  "tool, its arguments, its output, and any error. This is what you read to " +
135
202
  "work out WHY a run behaved as it did.", { runId: z.string().describe("The run's id.") }, async ({ runId }) => guard(async () => jsonResult(await client.get(`/api/v1/runs/${runId}/trace`))));
136
203
  server.tool("read_run_cost", "Read a run's token and cost breakdown, per agent and model.", { runId: z.string().describe("The run's id.") }, async ({ runId }) => guard(async () => jsonResult(await client.get(`/api/v1/runs/${runId}/cost`))));
204
+ // ---- Why a run is parked, and what it did ------------------------------
205
+ server.tool("read_run_waiting_on", "Why a run is PARKED. A run in `waiting` or `input_required` is not stuck " +
206
+ "and not slow — it is holding for something, and this lists every pending " +
207
+ "wake-task targeting it: a question asked of a person, a timer, a callback " +
208
+ "that has not arrived. Read this before concluding a test run failed. " +
209
+ "\n\nAn EMPTY list is a real answer, not an error: the run may have every " +
210
+ "wake already resolved and be about to resume. " +
211
+ "\n\nWhen the answer is a question, answer_run_question is what unparks it.", {
212
+ runId: z.string().describe("The run's id."),
213
+ limit: z.number().int().optional().describe("How many to return. Default 50."),
214
+ }, async ({ runId, limit }) => guard(async () => jsonResult(await client.get(`/api/v1/runs/${runId}/waiting-on`, { limit }))));
215
+ server.tool("list_run_items", "One page of the ITEM RESULTS inside a launch — the rows a FOR EACH " +
216
+ "produced. This is what list_workflow_runs does NOT show: a launch over " +
217
+ "4,415 people is one entry there and 4,415 rows here. Each row's `id` is " +
218
+ "a real run you can read_run for that one item's detail. " +
219
+ "\n\nTHE RESPONSE IS ONE PAGE: { items, nextCursor, pageSize, hasMore }, " +
220
+ "20 by default and max 200. Follow nextCursor until it is null. " +
221
+ "\n\nFILTER WITH `outcome`, DO NOT FILTER THE PAGE. It is applied in the " +
222
+ "database: on a 4,415-item launch the twelve failures are scattered " +
223
+ "through the middle, so keeping the failed rows out of page one shows you " +
224
+ "none and reads as \"no failures\". For the totals alone use " +
225
+ "read_run_items_summary — it is one call instead of a walk.", {
226
+ runId: z.string().describe("The launch's run id."),
227
+ outcome: z
228
+ .enum(["all", "failed", "skipped"])
229
+ .optional()
230
+ .describe('Which items to return. "failed" covers items that never produced a ' +
231
+ 'result; "skipped" covers items a gate deliberately declined. ' +
232
+ 'Defaults to "all".'),
233
+ limit: z.number().int().optional().describe("Page size. Default 20, max 200."),
234
+ cursor: z
235
+ .string()
236
+ .optional()
237
+ .describe("Opaque continuation cursor from the previous response's nextCursor. " +
238
+ "Omit for the first page. Do not parse or construct one."),
239
+ }, async ({ runId, outcome, limit, cursor }) => guard(async () => jsonResult(await client.get(`/api/v1/runs/${runId}/items`, { outcome, limit, cursor }))));
240
+ server.tool("read_run_items_summary", "The roll-up over a launch's items — \"4,415 processed · 12 failed\" — in " +
241
+ "ONE call, with no paging. Ask this before list_run_items: it answers " +
242
+ "\"did anything fail?\" outright, where counting a page answers it wrongly. " +
243
+ "A launch that never fanned out reports zeroes.", { runId: z.string().describe("The launch's run id.") }, async ({ runId }) => guard(async () => jsonResult(await client.get(`/api/v1/runs/${runId}/items/summary`))));
244
+ server.tool("list_run_tasks", "Every task and child run descending from this run: for-each iterations " +
245
+ "still queued, delegated agent tasks, callback wake-tasks, and the " +
246
+ "iterations already promoted to runs of their own. Use it to see what a " +
247
+ "run set in motion beyond its own steps — a run can look idle while its " +
248
+ "children are doing all the work.", {
249
+ runId: z.string().describe("The run's id."),
250
+ limit: z.number().int().optional().describe("How many to return. Default 200."),
251
+ }, async ({ runId, limit }) => guard(async () => jsonResult(await client.get(`/api/v1/runs/${runId}/tasks`, { limit }))));
252
+ server.tool("read_run_for_each_progress", "Per-state counts for ONE fan-out batch on a run: total, pending, " +
253
+ "inProgress, succeeded, failed, deadLetter. This is how you watch a FOR " +
254
+ "EACH step advance while it is still running, instead of re-reading the " +
255
+ "whole run. Get the batchId from list_run_tasks or the step's state in " +
256
+ "read_run.", {
257
+ runId: z.string().describe("The run's id."),
258
+ batchId: z.string().describe("The FOR EACH batch's id."),
259
+ }, async ({ runId, batchId }) => guard(async () => jsonResult(await client.get(`/api/v1/runs/${runId}/for-each/${batchId}/progress`))));
260
+ // ---- Unparking a run ---------------------------------------------------
261
+ server.tool("answer_run_question", "Answer an `ask_user` step a run is parked on, so the run resumes. This is " +
262
+ "what makes \"start a run and see what it does\" finishable: without it a " +
263
+ "workflow that asks anything waits forever and a test never returns a " +
264
+ "verdict. Find the parked step with read_run_waiting_on or read_run. " +
265
+ "\n\nThe answer is recorded as the ANSWER A PERSON WOULD HAVE GIVEN and " +
266
+ "the run proceeds on it. On a run a human is depending on, that is their " +
267
+ "decision to make, not yours — answer your own test runs, and ask before " +
268
+ "answering someone else's. Returns the run's updated detail.", {
269
+ runId: z.string().describe("The run's id."),
270
+ stepId: z.string().describe("The suspended step's id, from read_run_waiting_on."),
271
+ answer: z.string().describe("The answer text the step is waiting for."),
272
+ }, async ({ runId, stepId, answer }) => guard(async () => jsonResult(await client.post(`/api/v1/runs/${runId}/steps/${stepId}/answer`, { answer }))));
273
+ server.tool("send_run_message", "Send a user turn to a CONVERSATION run that is waiting on one. The server " +
274
+ "resolves which step is parked, so unlike answer_run_question this takes " +
275
+ "no stepId. Same caution: the turn is recorded as a person's, so use it " +
276
+ "on runs you started. Returns the run's updated detail.", {
277
+ runId: z.string().describe("The conversation run's id."),
278
+ message: z.string().min(1).describe("The user turn to submit."),
279
+ }, async ({ runId, message }) => guard(async () => jsonResult(await client.post(`/api/v1/runs/${runId}/message`, { message }))));
137
280
  server.tool("read_runs_summary", "Counts of runs by state across the tenant (running, waiting, completed, " +
138
281
  "failed, expired, total).", {}, async () => guard(async () => jsonResult(await client.get("/api/v1/runs/summary"))));
139
282
  server.tool("archive_run", "Archive a run — hides it from the default run list without deleting it. " +