@axonity-ai/mcp 0.1.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +142 -24
- package/dist/client.d.ts +11 -2
- package/dist/client.js +28 -10
- package/dist/client.js.map +1 -1
- package/dist/errors.d.ts +53 -10
- package/dist/errors.js +163 -19
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +11 -0
- package/dist/index.js +125 -2
- package/dist/index.js.map +1 -1
- package/dist/tools/conventions.js +148 -9
- package/dist/tools/conventions.js.map +1 -1
- package/dist/tools/credentials.d.ts +34 -0
- package/dist/tools/credentials.js +106 -0
- package/dist/tools/credentials.js.map +1 -0
- package/dist/tools/extras.d.ts +14 -5
- package/dist/tools/extras.js +57 -40
- package/dist/tools/extras.js.map +1 -1
- package/dist/tools/register.d.ts +59 -10
- package/dist/tools/register.js +77 -22
- package/dist/tools/register.js.map +1 -1
- package/dist/tools/runs.d.ts +14 -0
- package/dist/tools/runs.js +73 -0
- package/dist/tools/runs.js.map +1 -0
- package/dist/tools/triggers.d.ts +13 -0
- package/dist/tools/triggers.js +128 -0
- package/dist/tools/triggers.js.map +1 -0
- package/dist/tools/validation.d.ts +13 -0
- package/dist/tools/validation.js +116 -0
- package/dist/tools/validation.js.map +1 -0
- package/dist/tools/versions.d.ts +37 -0
- package/dist/tools/versions.js +93 -0
- package/dist/tools/versions.js.map +1 -0
- package/dist/tools/workflowMutations.d.ts +22 -0
- package/dist/tools/workflowMutations.js +95 -23
- package/dist/tools/workflowMutations.js.map +1 -1
- package/package.json +1 -1
package/dist/tools/extras.js
CHANGED
|
@@ -1,20 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Secondary MCP tools
|
|
3
|
-
*
|
|
2
|
+
* Secondary MCP tools: the agent-scoped persona create/read (personas
|
|
3
|
+
* themselves are a full generic entity — see index.ts — but creation and the
|
|
4
|
+
* by-agent read have no equivalent generic route), connectors (a tool
|
|
5
|
+
* subtype), attaching memory to a target, and a few standalone one-offs.
|
|
4
6
|
*
|
|
5
7
|
* These use routes with shapes that don't fit the generic entity registrar:
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* path-only link.
|
|
8
|
+
* a persona is created only through its agent, connectors are a tool with
|
|
9
|
+
* `type: "connector"` and MUST NOT carry real credentials, and attach/detach
|
|
10
|
+
* is a path-only link.
|
|
9
11
|
*/
|
|
10
12
|
import { z } from "zod";
|
|
13
|
+
import { assertPlaceholderCredentials } from "./credentials.js";
|
|
11
14
|
import { guard, jsonResult } from "./result.js";
|
|
12
|
-
/** A value is a safe placeholder if it's empty or a `{{ … }}` template. */
|
|
13
|
-
function isPlaceholder(value) {
|
|
14
|
-
if (value === "" || value === null || value === undefined)
|
|
15
|
-
return true;
|
|
16
|
-
return typeof value === "string" && /^\s*\{\{.*\}\}\s*$/.test(value);
|
|
17
|
-
}
|
|
18
15
|
export function registerPersonaTools(server, client) {
|
|
19
16
|
server.tool("read_agent_persona", "Read an agent's persona (voice/character). A persona is 1:1 with an agent — " +
|
|
20
17
|
"there is no standalone persona list.", { agentId: z.string().describe("The agent's id.") }, async ({ agentId }) => guard(async () => jsonResult(await client.get(`/api/v1/agents/${agentId}/persona`))));
|
|
@@ -24,34 +21,20 @@ export function registerPersonaTools(server, client) {
|
|
|
24
21
|
.record(z.unknown())
|
|
25
22
|
.describe('Persona fields, e.g. { "name": "…", "characterText": "…" }.'),
|
|
26
23
|
}, async ({ agentId, fields }) => guard(async () => jsonResult(await client.post(`/api/v1/agents/${agentId}/persona`, fields))));
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
.describe("The version you last read — 409 if stale."),
|
|
33
|
-
fields: z.record(z.unknown()).describe("The fields to change (camelCase)."),
|
|
34
|
-
}, async ({ personaId, expectedVersion, fields }) => guard(async () => jsonResult(await client.put(`/api/v1/personas/${personaId}`, {
|
|
35
|
-
expectedVersion,
|
|
36
|
-
...fields,
|
|
37
|
-
}))));
|
|
24
|
+
// Reading/updating a persona by its OWN id (list_personas, read_persona,
|
|
25
|
+
// update_persona, delete_persona, restore_persona, …) is generated generically
|
|
26
|
+
// from the "persona" EntityDef in index.ts — identical PUT semantics to what
|
|
27
|
+
// used to be hand-written here. Only the agent-scoped create/read above are
|
|
28
|
+
// bespoke, because personas have no standalone create route.
|
|
38
29
|
}
|
|
39
30
|
export function registerConnectorTools(server, client) {
|
|
40
|
-
const authGuard = (fields) => {
|
|
41
|
-
const authConfig = fields.authConfig;
|
|
42
|
-
if (authConfig && !Object.values(authConfig).every(isPlaceholder)) {
|
|
43
|
-
throw new Error("authConfig must contain only placeholders (empty or {{ … }}). Never put " +
|
|
44
|
-
"real credentials in a connector — a human fills secrets in the Axonity " +
|
|
45
|
-
"tool editor.");
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
31
|
server.tool("create_connector", "Create a connector draft (a tool of type 'connector'). Do NOT put real " +
|
|
49
32
|
"credentials in authConfig — use placeholders; a human fills secrets in Axonity.", {
|
|
50
33
|
fields: z
|
|
51
34
|
.record(z.unknown())
|
|
52
35
|
.describe("Connector fields (name, description, implementation, authConfig)."),
|
|
53
36
|
}, async ({ fields }) => guard(async () => {
|
|
54
|
-
|
|
37
|
+
assertPlaceholderCredentials(fields);
|
|
55
38
|
return jsonResult(await client.post("/api/v1/tools", { type: "connector", ...fields }));
|
|
56
39
|
}));
|
|
57
40
|
server.tool("update_connector", "Update a connector draft (a tool of type 'connector'). Read it first for its " +
|
|
@@ -60,7 +43,7 @@ export function registerConnectorTools(server, client) {
|
|
|
60
43
|
expectedVersion: z.number().int().describe("Version last read — 409 if stale."),
|
|
61
44
|
fields: z.record(z.unknown()).describe("Fields to change (camelCase)."),
|
|
62
45
|
}, async ({ id, expectedVersion, fields }) => guard(async () => {
|
|
63
|
-
|
|
46
|
+
assertPlaceholderCredentials(fields);
|
|
64
47
|
return jsonResult(await client.put(`/api/v1/tools/${id}`, {
|
|
65
48
|
expectedVersion,
|
|
66
49
|
type: "connector",
|
|
@@ -69,13 +52,47 @@ export function registerConnectorTools(server, client) {
|
|
|
69
52
|
}));
|
|
70
53
|
}
|
|
71
54
|
export function registerAttachTools(server, client) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Attach and detach are the same path with POST vs DELETE, so both verbs are
|
|
57
|
+
* generated from one definition — that is what keeps them from drifting apart
|
|
58
|
+
* again (only attach existed before, so nothing could be unwired).
|
|
59
|
+
*/
|
|
60
|
+
const link = (subject, target, path, firstArg, secondArg) => {
|
|
61
|
+
const shape = { [firstArg]: z.string(), [secondArg]: z.string() };
|
|
62
|
+
server.tool(`attach_${subject}_to_${target}`, `Scope a ${subject.replace("_", " ")} to a ${target} so the ${target} uses it.`, shape, async (args) => guard(async () => jsonResult(await client.post(path(args[firstArg], args[secondArg])))));
|
|
63
|
+
server.tool(`detach_${subject}_from_${target}`, `Unscope a ${subject.replace("_", " ")} from a ${target}. This only ` +
|
|
64
|
+
`removes the link — the ${subject.replace("_", " ")} itself is not deleted ` +
|
|
65
|
+
`and stays available to attach elsewhere.`, shape, async (args) => guard(async () => {
|
|
66
|
+
await client.del(path(args[firstArg], args[secondArg]));
|
|
67
|
+
return jsonResult({
|
|
68
|
+
detached: true,
|
|
69
|
+
[firstArg]: args[firstArg],
|
|
70
|
+
[secondArg]: args[secondArg],
|
|
71
|
+
});
|
|
72
|
+
}));
|
|
73
|
+
};
|
|
74
|
+
link("skill", "agent", (agentId, skillId) => `/api/v1/agents/${agentId}/skills-v2/${skillId}`, "agentId", "skillId");
|
|
75
|
+
link("skill", "workflow", (workflowId, skillId) => `/api/v1/workflows/${workflowId}/skills-v2/${skillId}`, "workflowId", "skillId");
|
|
76
|
+
link("policy", "agent", (agentId, policyId) => `/api/v1/agents/${agentId}/policies/${policyId}`, "agentId", "policyId");
|
|
77
|
+
// Reference docs attach to agents only — there is no workflow-scoped
|
|
78
|
+
// reference-doc route on the backend, so no `*_to_workflow` pair here.
|
|
79
|
+
link("reference", "agent", (agentId, refId) => `/api/v1/agents/${agentId}/reference-docs/${refId}`, "agentId", "refId");
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Small standalone tools that don't fit any of the other groupings: the
|
|
83
|
+
* system-tools catalog (read-only — there is no grant/revoke route; enabling
|
|
84
|
+
* one for an agent means writing `systemToolIds` via `update_agent`), and
|
|
85
|
+
* cloning a flow/prompt-snippet into a tenant-owned copy.
|
|
86
|
+
*/
|
|
87
|
+
export function registerCatalogTools(server, client) {
|
|
88
|
+
server.tool("list_system_tools", "List the tenant's system-tool catalog (id, label, description, category). " +
|
|
89
|
+
"There is no grant/revoke tool — enable one for an agent by adding its id " +
|
|
90
|
+
"to `systemToolIds` via update_agent.", {}, async () => guard(async () => jsonResult(await client.get("/api/v1/system-tools"))));
|
|
91
|
+
server.tool("clone_flow", "Fork a flow into a new, independent, tenant-owned copy — including a " +
|
|
92
|
+
"framework-provided one. Prefer this over editing a framework flow " +
|
|
93
|
+
"directly: it is visible and NOT actually protected from update_flow/ " +
|
|
94
|
+
"delete_flow (a backend gap, despite what its docstrings claim), so " +
|
|
95
|
+
"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`))));
|
|
96
|
+
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`))));
|
|
80
97
|
}
|
|
81
98
|
//# sourceMappingURL=extras.js.map
|
package/dist/tools/extras.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extras.js","sourceRoot":"","sources":["../../src/tools/extras.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"extras.js","sourceRoot":"","sources":["../../src/tools/extras.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/register.d.ts
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Registers the read/draft/update MCP tools for one Axonity entity type.
|
|
2
|
+
* Registers the read/draft/update/lifecycle MCP tools for one Axonity entity type.
|
|
3
3
|
*
|
|
4
|
-
* Every entity
|
|
5
|
-
*
|
|
6
|
-
* list_<
|
|
7
|
-
* read_<entity>
|
|
8
|
-
* create_<entity>
|
|
9
|
-
* update_<entity>
|
|
4
|
+
* Every entity gets the same verbs the internal Builder team has, minus direct
|
|
5
|
+
* publish:
|
|
6
|
+
* list_<plural> — GET <basePath>
|
|
7
|
+
* read_<entity> — GET <basePath>/{id}
|
|
8
|
+
* create_<entity> — POST <basePath> (a new draft)
|
|
9
|
+
* update_<entity> — PUT|PATCH <basePath>/{id} (read-then-write)
|
|
10
|
+
* delete_<entity> — DELETE <basePath>/{id} (soft-delete, recoverable)
|
|
11
|
+
* restore_<entity> — POST <basePath>/{id}/restore (undo a delete)
|
|
12
|
+
* list_deleted_<plural> — restore candidates
|
|
13
|
+
* discard_<entity>_draft — reset the draft to the last published state
|
|
10
14
|
*
|
|
11
15
|
* The connector stays thin: entity fields pass through as JSON and the backend
|
|
12
|
-
* validates them (
|
|
13
|
-
* so a stale write 409s rather than
|
|
16
|
+
* validates them (a structured error names the offending field — see errors.ts).
|
|
17
|
+
* Updates carry `expectedVersion` in the body so a stale write 409s rather than
|
|
18
|
+
* clobbering. Deletes carry it as a QUERY param instead, and the key's spelling
|
|
19
|
+
* is not uniform across entities (`deleteVersionParam` on `EntityDef` says which).
|
|
14
20
|
*
|
|
15
21
|
* `request_publish_*` never publishes — it creates a pending approval a human
|
|
16
|
-
* decides in Axonity
|
|
22
|
+
* decides in Axonity.
|
|
17
23
|
*/
|
|
18
24
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
19
25
|
import type { AxonityClient } from "../client.js";
|
|
@@ -26,5 +32,48 @@ export interface EntityDef {
|
|
|
26
32
|
updateMethod: "PUT" | "PATCH";
|
|
27
33
|
/** One-line human description of the entity, for the tool docs. */
|
|
28
34
|
label: string;
|
|
35
|
+
/**
|
|
36
|
+
* Optional pre-write check on the caller's fields, applied to `create_*` and
|
|
37
|
+
* `update_*`. Throws to reject. Used to run the connector credential guard on
|
|
38
|
+
* plain tool writes, which would otherwise bypass it.
|
|
39
|
+
*/
|
|
40
|
+
guardFields?: (fields: Record<string, unknown>) => void;
|
|
41
|
+
/**
|
|
42
|
+
* Whether this entity can be published. Default true. `flow` has no publish
|
|
43
|
+
* route and is not a valid `entityType` for a publish approval, so generating
|
|
44
|
+
* this tool is suppressed there.
|
|
45
|
+
*/
|
|
46
|
+
publishable?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* The plural noun for `list_<plural>` / `list_deleted_<plural>`. Defaults to
|
|
49
|
+
* `${singular}s`, which is wrong for at least "policy" — set it explicitly
|
|
50
|
+
* rather than shipping `list_policys`.
|
|
51
|
+
*/
|
|
52
|
+
plural?: string;
|
|
53
|
+
/** Whether `create_<entity>` is generated. Default true. False for `persona`, whose create is agent-scoped (`create_agent_persona`). */
|
|
54
|
+
creatable?: boolean;
|
|
55
|
+
/** Whether `read_<entity>` is generated. Default true. False for `prompt_snippet`, which has no single-read route. */
|
|
56
|
+
readable?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* The query-string key DELETE expects for the optimistic lock. Its presence
|
|
59
|
+
* is what turns on `delete_/restore_/list_deleted_/discard_*` — omit it for
|
|
60
|
+
* an entity with no lifecycle routes. The two spellings are a real backend
|
|
61
|
+
* inconsistency, not a typo: `expectedVersion` (workflow, agent, tool,
|
|
62
|
+
* prompt_snippet, flow) vs `expected_version` (skill, policy, reference_doc,
|
|
63
|
+
* output_schema, persona).
|
|
64
|
+
*/
|
|
65
|
+
deleteVersionParam?: "expectedVersion" | "expected_version";
|
|
66
|
+
/**
|
|
67
|
+
* Whether `discard_<entity>_draft` is generated. Default true when the
|
|
68
|
+
* entity is deletable. False for `flow` and `prompt_snippet`, neither of
|
|
69
|
+
* which has a discard-draft route.
|
|
70
|
+
*/
|
|
71
|
+
hasDiscardDraft?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* How to list soft-deleted rows. `"collection"` (default) is `GET
|
|
74
|
+
* <basePath>/deleted`, used by every entity except `prompt_snippet`, which
|
|
75
|
+
* instead takes `?deleted=true` on the main list route (`"query"`).
|
|
76
|
+
*/
|
|
77
|
+
deletedListPath?: "collection" | "query";
|
|
29
78
|
}
|
|
30
79
|
export declare function registerEntityTools(server: McpServer, client: AxonityClient, def: EntityDef): void;
|
package/dist/tools/register.js
CHANGED
|
@@ -1,35 +1,56 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Registers the read/draft/update MCP tools for one Axonity entity type.
|
|
2
|
+
* Registers the read/draft/update/lifecycle MCP tools for one Axonity entity type.
|
|
3
3
|
*
|
|
4
|
-
* Every entity
|
|
5
|
-
*
|
|
6
|
-
* list_<
|
|
7
|
-
* read_<entity>
|
|
8
|
-
* create_<entity>
|
|
9
|
-
* update_<entity>
|
|
4
|
+
* Every entity gets the same verbs the internal Builder team has, minus direct
|
|
5
|
+
* publish:
|
|
6
|
+
* list_<plural> — GET <basePath>
|
|
7
|
+
* read_<entity> — GET <basePath>/{id}
|
|
8
|
+
* create_<entity> — POST <basePath> (a new draft)
|
|
9
|
+
* update_<entity> — PUT|PATCH <basePath>/{id} (read-then-write)
|
|
10
|
+
* delete_<entity> — DELETE <basePath>/{id} (soft-delete, recoverable)
|
|
11
|
+
* restore_<entity> — POST <basePath>/{id}/restore (undo a delete)
|
|
12
|
+
* list_deleted_<plural> — restore candidates
|
|
13
|
+
* discard_<entity>_draft — reset the draft to the last published state
|
|
10
14
|
*
|
|
11
15
|
* The connector stays thin: entity fields pass through as JSON and the backend
|
|
12
|
-
* validates them (
|
|
13
|
-
* so a stale write 409s rather than
|
|
16
|
+
* validates them (a structured error names the offending field — see errors.ts).
|
|
17
|
+
* Updates carry `expectedVersion` in the body so a stale write 409s rather than
|
|
18
|
+
* clobbering. Deletes carry it as a QUERY param instead, and the key's spelling
|
|
19
|
+
* is not uniform across entities (`deleteVersionParam` on `EntityDef` says which).
|
|
14
20
|
*
|
|
15
21
|
* `request_publish_*` never publishes — it creates a pending approval a human
|
|
16
|
-
* decides in Axonity
|
|
22
|
+
* decides in Axonity.
|
|
17
23
|
*/
|
|
18
24
|
import { z } from "zod";
|
|
19
25
|
import { guard, jsonResult } from "./result.js";
|
|
26
|
+
/** A required literal — an agent cannot satisfy it by filling in a default. */
|
|
27
|
+
const CONFIRM = z
|
|
28
|
+
.literal(true)
|
|
29
|
+
.describe("Must be true. Acknowledges you understand this is destructive.");
|
|
20
30
|
export function registerEntityTools(server, client, def) {
|
|
21
|
-
const { singular, basePath, updateMethod, label } = def;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
const { singular, basePath, updateMethod, label, guardFields } = def;
|
|
32
|
+
const plural = def.plural ?? `${singular}s`;
|
|
33
|
+
const publishable = def.publishable !== false;
|
|
34
|
+
const creatable = def.creatable !== false;
|
|
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))));
|
|
37
|
+
if (readable) {
|
|
38
|
+
server.tool(`read_${singular}`, `Read one ${singular} by id, including its current draft and version. ` +
|
|
39
|
+
`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}`))));
|
|
40
|
+
}
|
|
41
|
+
if (creatable) {
|
|
42
|
+
server.tool(`create_${singular}`, `Create a new ${singular} draft. Pass the entity's fields (camelCase) in ` +
|
|
43
|
+
`\`fields\`; the backend validates them. Returns the created ${singular} ` +
|
|
44
|
+
`with its id and version.`, {
|
|
45
|
+
fields: z
|
|
46
|
+
.record(z.unknown())
|
|
47
|
+
.describe(`The ${singular}'s fields as a JSON object (camelCase keys), e.g. ` +
|
|
48
|
+
`{ "name": "…", "description": "…" }.`),
|
|
49
|
+
}, async ({ fields }) => guard(async () => {
|
|
50
|
+
guardFields?.(fields);
|
|
51
|
+
return jsonResult(await client.post(basePath, fields));
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
33
54
|
server.tool(`update_${singular}`, `Update a ${singular} draft. Read it first to get \`expectedVersion\`; on a ` +
|
|
34
55
|
`409 conflict, read again and retry. Pass only the fields you are ` +
|
|
35
56
|
`changing (camelCase) in \`fields\`.`, {
|
|
@@ -42,6 +63,7 @@ export function registerEntityTools(server, client, def) {
|
|
|
42
63
|
.record(z.unknown())
|
|
43
64
|
.describe(`The fields to change, as a JSON object (camelCase keys).`),
|
|
44
65
|
}, async ({ id, expectedVersion, fields }) => guard(async () => {
|
|
66
|
+
guardFields?.(fields);
|
|
45
67
|
const body = { expectedVersion, ...fields };
|
|
46
68
|
const path = `${basePath}/${id}`;
|
|
47
69
|
const data = updateMethod === "PUT"
|
|
@@ -49,6 +71,39 @@ export function registerEntityTools(server, client, def) {
|
|
|
49
71
|
: await client.patch(path, body);
|
|
50
72
|
return jsonResult(data);
|
|
51
73
|
}));
|
|
74
|
+
if (def.deleteVersionParam) {
|
|
75
|
+
const deleteVersionParam = def.deleteVersionParam;
|
|
76
|
+
const hasDiscardDraft = def.hasDiscardDraft !== false;
|
|
77
|
+
server.tool(`delete_${singular}`, `Delete a ${singular}. Destructive, but RECOVERABLE — it is soft-deleted ` +
|
|
78
|
+
`and can be brought back with restore_${singular} (it will not appear in ` +
|
|
79
|
+
`list_${plural} until then). Read it first for its version. A 409 here ` +
|
|
80
|
+
`may be a stale version (re-read and retry) or a reference conflict ` +
|
|
81
|
+
`(something published still uses it — re-reading will not help; the ` +
|
|
82
|
+
`error tells you which).`, {
|
|
83
|
+
id: z.string().describe(`The ${singular}'s id.`),
|
|
84
|
+
expectedVersion: z
|
|
85
|
+
.number()
|
|
86
|
+
.int()
|
|
87
|
+
.describe("The version you last read — rejected with 409 if stale."),
|
|
88
|
+
confirm: CONFIRM,
|
|
89
|
+
}, async ({ id, expectedVersion }) => guard(async () => {
|
|
90
|
+
await client.del(`${basePath}/${id}`, { [deleteVersionParam]: expectedVersion });
|
|
91
|
+
return jsonResult({ deleted: true, id });
|
|
92
|
+
}));
|
|
93
|
+
server.tool(`restore_${singular}`, `Undo delete_${singular} — bring a soft-deleted ${singular} back. Takes no ` +
|
|
94
|
+
`version check (a restore must never lose to a stale-version guard). Can ` +
|
|
95
|
+
`409 if a live ${singular} now holds a name/slot this one also claims.`, { id: z.string().describe(`The ${singular}'s id.`) }, async ({ id }) => guard(async () => jsonResult(await client.post(`${basePath}/${id}/restore`))));
|
|
96
|
+
server.tool(`list_deleted_${plural}`, `List soft-deleted ${label} — the restore candidates for restore_${singular}.`, {}, async () => guard(async () => jsonResult(def.deletedListPath === "query"
|
|
97
|
+
? await client.get(basePath, { deleted: true })
|
|
98
|
+
: await client.get(`${basePath}/deleted`))));
|
|
99
|
+
if (hasDiscardDraft) {
|
|
100
|
+
server.tool(`discard_${singular}_draft`, `Discard uncommitted draft edits on a ${singular}, resetting it to its ` +
|
|
101
|
+
`last published state. Fails if it has never been published — there is ` +
|
|
102
|
+
`no published state to fall back to.`, { id: z.string().describe(`The ${singular}'s id.`) }, async ({ id }) => guard(async () => jsonResult(await client.post(`${basePath}/${id}/discard-draft`))));
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (!publishable)
|
|
106
|
+
return;
|
|
52
107
|
server.tool(`request_publish_${singular}`, `Request that a ${singular} be published. This does NOT publish it — it ` +
|
|
53
108
|
`creates a pending approval a human approves in Axonity. Returns the ` +
|
|
54
109
|
`pending approval (with its readiness).`, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/tools/register.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run observability — how an agent evaluates what it built.
|
|
3
|
+
*
|
|
4
|
+
* There is no "findings" endpoint and no evaluator entity. Evaluation means
|
|
5
|
+
* reading runs: the run detail carries `validatorVerdicts` and
|
|
6
|
+
* `agentInvocations`, and the trace carries the step-by-step tool calls. Those
|
|
7
|
+
* are the evidence an agent reasons over.
|
|
8
|
+
*
|
|
9
|
+
* Runs are also the only thing in the product with a real archive state —
|
|
10
|
+
* entities have soft-delete, runs have archive/unarchive.
|
|
11
|
+
*/
|
|
12
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
13
|
+
import type { AxonityClient } from "../client.js";
|
|
14
|
+
export declare function registerRunTools(server: McpServer, client: AxonityClient): void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run observability — how an agent evaluates what it built.
|
|
3
|
+
*
|
|
4
|
+
* There is no "findings" endpoint and no evaluator entity. Evaluation means
|
|
5
|
+
* reading runs: the run detail carries `validatorVerdicts` and
|
|
6
|
+
* `agentInvocations`, and the trace carries the step-by-step tool calls. Those
|
|
7
|
+
* are the evidence an agent reasons over.
|
|
8
|
+
*
|
|
9
|
+
* Runs are also the only thing in the product with a real archive state —
|
|
10
|
+
* entities have soft-delete, runs have archive/unarchive.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { guard, jsonResult } from "./result.js";
|
|
14
|
+
const CONFIRM = z
|
|
15
|
+
.literal(true)
|
|
16
|
+
.describe("Must be true. Destructive and irreversible — ask your human first.");
|
|
17
|
+
export function registerRunTools(server, client) {
|
|
18
|
+
server.tool("list_runs", "List workflow runs across the tenant, newest first. Archived runs are " +
|
|
19
|
+
"excluded unless includeArchived is true. To list runs of ONE workflow, " +
|
|
20
|
+
"use list_workflow_runs instead — this route has no workflow filter.", {
|
|
21
|
+
status: z
|
|
22
|
+
.string()
|
|
23
|
+
.optional()
|
|
24
|
+
.describe('Comma-separated statuses, e.g. "running,failed". Omit for all.'),
|
|
25
|
+
createdAfter: z.string().optional().describe("ISO date lower bound."),
|
|
26
|
+
createdBefore: z.string().optional().describe("ISO date upper bound."),
|
|
27
|
+
includeArchived: z.boolean().optional().describe("Defaults to false."),
|
|
28
|
+
limit: z.number().int().optional().describe("Default 50, capped at 200."),
|
|
29
|
+
offset: z.number().int().optional().describe("Default 0."),
|
|
30
|
+
}, async ({ status, createdAfter, createdBefore, includeArchived, limit, offset }) => guard(async () => jsonResult(await client.get("/api/v1/runs", {
|
|
31
|
+
status,
|
|
32
|
+
created_after: createdAfter,
|
|
33
|
+
created_before: createdBefore,
|
|
34
|
+
include_archived: includeArchived,
|
|
35
|
+
limit,
|
|
36
|
+
offset,
|
|
37
|
+
}))));
|
|
38
|
+
server.tool("list_workflow_runs", "List the runs of one workflow. Note this route takes archivedOnly (show " +
|
|
39
|
+
"ONLY archived runs), which is not the same as list_runs' includeArchived.", {
|
|
40
|
+
workflowId: z.string().describe("The workflow's id."),
|
|
41
|
+
archivedOnly: z
|
|
42
|
+
.boolean()
|
|
43
|
+
.optional()
|
|
44
|
+
.describe("True to list only archived runs. Defaults to false."),
|
|
45
|
+
}, async ({ workflowId, archivedOnly }) => guard(async () => jsonResult(await client.get(`/api/v1/workflows/${workflowId}/runs`, {
|
|
46
|
+
archived_only: archivedOnly,
|
|
47
|
+
}))));
|
|
48
|
+
server.tool("read_run", "Read one run in full: status, per-step state, the workflow snapshot it " +
|
|
49
|
+
"ran against, trigger input, agent invocations, and validator verdicts. " +
|
|
50
|
+
"The verdicts are the closest thing to evaluator findings — there is no " +
|
|
51
|
+
"separate findings endpoint.", { runId: z.string().describe("The run's id.") }, async ({ runId }) => guard(async () => jsonResult(await client.get(`/api/v1/runs/${runId}`))));
|
|
52
|
+
server.tool("read_run_trace", "Read a run's chronological tool-call trace — each entry has the step, the " +
|
|
53
|
+
"tool, its arguments, its output, and any error. This is what you read to " +
|
|
54
|
+
"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`))));
|
|
55
|
+
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`))));
|
|
56
|
+
server.tool("read_runs_summary", "Counts of runs by state across the tenant (running, waiting, completed, " +
|
|
57
|
+
"failed, expired, total).", {}, async () => guard(async () => jsonResult(await client.get("/api/v1/runs/summary"))));
|
|
58
|
+
server.tool("archive_run", "Archive a run — hides it from the default run list without deleting it. " +
|
|
59
|
+
"Reversible with unarchive_run.", { runId: z.string().describe("The run's id.") }, async ({ runId }) => guard(async () => jsonResult(await client.post(`/api/v1/runs/${runId}/archive`))));
|
|
60
|
+
server.tool("unarchive_run", "Restore an archived run to the default run list.", { runId: z.string().describe("The run's id.") }, async ({ runId }) => guard(async () => jsonResult(await client.post(`/api/v1/runs/${runId}/unarchive`))));
|
|
61
|
+
server.tool("bulk_archive_runs", "Archive up to 500 runs at once. Reversible — archived runs can be " +
|
|
62
|
+
"unarchived individually. Returns counts of succeeded and failed.", {
|
|
63
|
+
runIds: z.array(z.string()).min(1).max(500).describe("The run ids to archive."),
|
|
64
|
+
}, async ({ runIds }) => guard(async () => jsonResult(await client.post("/api/v1/runs/bulk/archive", { runIds }))));
|
|
65
|
+
server.tool("bulk_delete_runs", "Delete up to 500 runs at once. IRREVERSIBLE — unlike archiving, deleted " +
|
|
66
|
+
"runs do not come back, and their traces and cost history go with them. " +
|
|
67
|
+
"Prefer bulk_archive_runs unless a human has explicitly asked for deletion. " +
|
|
68
|
+
"Returns counts of succeeded and failed; a partial failure is possible.", {
|
|
69
|
+
runIds: z.array(z.string()).min(1).max(500).describe("The run ids to delete."),
|
|
70
|
+
confirm: CONFIRM,
|
|
71
|
+
}, async ({ runIds }) => guard(async () => jsonResult(await client.post("/api/v1/runs/bulk/delete", { runIds }))));
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=runs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runs.js","sourceRoot":"","sources":["../../src/tools/runs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trigger management — what makes a published workflow actually run.
|
|
3
|
+
*
|
|
4
|
+
* Three trigger kinds, all member-accessible despite living in `*_admin.py` on
|
|
5
|
+
* the backend. Note the asymmetry the routes impose: creating and listing are
|
|
6
|
+
* workflow-scoped, while rotate/update/delete address the trigger directly.
|
|
7
|
+
*
|
|
8
|
+
* Trigger deletes are HARD deletes — the row is removed, not soft-deleted, and
|
|
9
|
+
* there is no restore. Hence the `confirm` guard on each.
|
|
10
|
+
*/
|
|
11
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
12
|
+
import type { AxonityClient } from "../client.js";
|
|
13
|
+
export declare function registerTriggerTools(server: McpServer, client: AxonityClient): void;
|