@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/index.d.ts
CHANGED
|
@@ -18,3 +18,14 @@
|
|
|
18
18
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
19
19
|
import { AxonityClient } from "./client.js";
|
|
20
20
|
export declare function buildServer(client: AxonityClient): McpServer;
|
|
21
|
+
/**
|
|
22
|
+
* True when this module is the process entry point.
|
|
23
|
+
*
|
|
24
|
+
* `import.meta.url` is realpath-resolved and percent-encoded, so it can't be
|
|
25
|
+
* compared against a hand-built `file://${argv[1]}` string: npm installs the bin
|
|
26
|
+
* as a symlink (`node_modules/.bin/axonity-mcp`), which is how `npx` runs it, and
|
|
27
|
+
* paths with spaces encode differently. Both mismatches used to leave the server
|
|
28
|
+
* silently unstarted. Resolve argv[1] the same way before comparing.
|
|
29
|
+
*/
|
|
30
|
+
export declare function isEntryPoint(moduleUrl: string, argv1: string | undefined): boolean;
|
|
31
|
+
export declare function assertNoExtraArguments(argv: string[]): void;
|
package/dist/index.js
CHANGED
|
@@ -15,13 +15,20 @@
|
|
|
15
15
|
* tenant + scope on every call. Publishing is human-approved and lands in a
|
|
16
16
|
* later slice (C3) — this connector never publishes directly.
|
|
17
17
|
*/
|
|
18
|
+
import { realpathSync } from "node:fs";
|
|
19
|
+
import { pathToFileURL } from "node:url";
|
|
18
20
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
19
21
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
20
22
|
import { AxonityClient } from "./client.js";
|
|
21
23
|
import { loadConfig } from "./config.js";
|
|
22
24
|
import { registerConventions } from "./tools/conventions.js";
|
|
23
|
-
import {
|
|
25
|
+
import { assertPlaceholderCredentials } from "./tools/credentials.js";
|
|
26
|
+
import { registerAttachTools, registerCatalogTools, registerConnectorTools, registerPersonaTools, } from "./tools/extras.js";
|
|
24
27
|
import { registerEntityTools } from "./tools/register.js";
|
|
28
|
+
import { registerRunTools } from "./tools/runs.js";
|
|
29
|
+
import { registerTriggerTools } from "./tools/triggers.js";
|
|
30
|
+
import { registerApprovalTools, registerExecutionTools, registerValidationTools, } from "./tools/validation.js";
|
|
31
|
+
import { registerVersionTools } from "./tools/versions.js";
|
|
25
32
|
import { registerWorkflowMutations } from "./tools/workflowMutations.js";
|
|
26
33
|
/**
|
|
27
34
|
* The entities the connector covers. Core entities (C4) plus memory
|
|
@@ -34,51 +41,132 @@ const ENTITIES = [
|
|
|
34
41
|
basePath: "/api/v1/workflows",
|
|
35
42
|
updateMethod: "PATCH",
|
|
36
43
|
label: "workflows (business processes)",
|
|
44
|
+
deleteVersionParam: "expectedVersion",
|
|
37
45
|
},
|
|
38
46
|
{
|
|
39
47
|
singular: "agent",
|
|
40
48
|
basePath: "/api/v1/agents",
|
|
41
49
|
updateMethod: "PUT",
|
|
42
50
|
label: "agents",
|
|
51
|
+
deleteVersionParam: "expectedVersion",
|
|
43
52
|
},
|
|
44
53
|
{
|
|
45
54
|
singular: "tool",
|
|
46
55
|
basePath: "/api/v1/tools",
|
|
47
56
|
updateMethod: "PUT",
|
|
48
57
|
label: "tools (functions, connectors, validators, evaluators)",
|
|
58
|
+
// A connector is just a tool, so create_tool/update_tool can carry an
|
|
59
|
+
// authConfig too — they get the same credential guard as create_connector.
|
|
60
|
+
guardFields: assertPlaceholderCredentials,
|
|
61
|
+
deleteVersionParam: "expectedVersion",
|
|
49
62
|
},
|
|
50
63
|
{
|
|
51
64
|
singular: "skill",
|
|
52
65
|
basePath: "/api/v1/skills",
|
|
53
66
|
updateMethod: "PUT",
|
|
54
67
|
label: "skills (reusable know-how for agents)",
|
|
68
|
+
deleteVersionParam: "expected_version",
|
|
55
69
|
},
|
|
56
70
|
{
|
|
57
71
|
singular: "policy",
|
|
58
72
|
basePath: "/api/v1/policies",
|
|
59
73
|
updateMethod: "PUT",
|
|
60
74
|
label: "policies (rules and guardrails for agents)",
|
|
75
|
+
plural: "policies",
|
|
76
|
+
deleteVersionParam: "expected_version",
|
|
61
77
|
},
|
|
62
78
|
{
|
|
63
79
|
singular: "reference_doc",
|
|
64
80
|
basePath: "/api/v1/reference-docs",
|
|
65
81
|
updateMethod: "PUT",
|
|
66
82
|
label: "reference docs (background knowledge for agents)",
|
|
83
|
+
deleteVersionParam: "expected_version",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
singular: "output_schema",
|
|
87
|
+
basePath: "/api/v1/output-schemas",
|
|
88
|
+
updateMethod: "PUT",
|
|
89
|
+
label: "output schemas (reusable step/agent output contracts)",
|
|
90
|
+
// Now fully version-controlled and in the publish-approval gateway
|
|
91
|
+
// alongside the memory entities — no longer live-on-write.
|
|
92
|
+
deleteVersionParam: "expected_version",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
singular: "persona",
|
|
96
|
+
basePath: "/api/v1/personas",
|
|
97
|
+
updateMethod: "PUT",
|
|
98
|
+
label: "personas (an agent's character, 1:1 with the agent)",
|
|
99
|
+
// Created only through its agent (create_agent_persona) — there is no
|
|
100
|
+
// standalone POST /api/v1/personas.
|
|
101
|
+
creatable: false,
|
|
102
|
+
deleteVersionParam: "expected_version",
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
singular: "prompt_snippet",
|
|
106
|
+
basePath: "/api/v1/prompt-snippets",
|
|
107
|
+
updateMethod: "PATCH",
|
|
108
|
+
label: "prompt snippets (reusable prompt fragments)",
|
|
109
|
+
deleteVersionParam: "expectedVersion",
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
singular: "flow",
|
|
113
|
+
basePath: "/api/v1/flows",
|
|
114
|
+
updateMethod: "PATCH",
|
|
115
|
+
label: "flows (reusable workflow fragments)",
|
|
116
|
+
deleteVersionParam: "expectedVersion",
|
|
67
117
|
},
|
|
68
118
|
];
|
|
119
|
+
/**
|
|
120
|
+
* Entities with version history. Not the same list as ENTITIES: `flow` has no
|
|
121
|
+
* `/versions*` routes at all, so it is excluded here.
|
|
122
|
+
*/
|
|
123
|
+
const VERSIONED = [
|
|
124
|
+
{ singular: "workflow", basePath: "/api/v1/workflows", publishedPath: "entity" },
|
|
125
|
+
{ singular: "agent", basePath: "/api/v1/agents", publishedPath: "entity" },
|
|
126
|
+
{ singular: "tool", basePath: "/api/v1/tools", publishedPath: "entity" },
|
|
127
|
+
{ singular: "skill", basePath: "/api/v1/skills", publishedPath: "versions" },
|
|
128
|
+
{ singular: "policy", basePath: "/api/v1/policies", publishedPath: "versions" },
|
|
129
|
+
{
|
|
130
|
+
singular: "reference_doc",
|
|
131
|
+
basePath: "/api/v1/reference-docs",
|
|
132
|
+
publishedPath: "versions",
|
|
133
|
+
},
|
|
134
|
+
{ singular: "persona", basePath: "/api/v1/personas", publishedPath: "versions" },
|
|
135
|
+
{
|
|
136
|
+
singular: "output_schema",
|
|
137
|
+
basePath: "/api/v1/output-schemas",
|
|
138
|
+
publishedPath: "versions",
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
singular: "prompt_snippet",
|
|
142
|
+
basePath: "/api/v1/prompt-snippets",
|
|
143
|
+
publishedPath: "versions",
|
|
144
|
+
},
|
|
145
|
+
{ singular: "flow", basePath: "/api/v1/flows", publishedPath: "entity" },
|
|
146
|
+
];
|
|
69
147
|
export function buildServer(client) {
|
|
70
148
|
const server = new McpServer({ name: "axonity", version: "0.1.0" });
|
|
71
149
|
registerConventions(server);
|
|
72
150
|
for (const def of ENTITIES) {
|
|
73
151
|
registerEntityTools(server, client, def);
|
|
74
152
|
}
|
|
153
|
+
for (const def of VERSIONED) {
|
|
154
|
+
registerVersionTools(server, client, def);
|
|
155
|
+
}
|
|
75
156
|
registerWorkflowMutations(server, client);
|
|
157
|
+
registerValidationTools(server, client);
|
|
158
|
+
registerExecutionTools(server, client);
|
|
159
|
+
registerApprovalTools(server, client);
|
|
160
|
+
registerTriggerTools(server, client);
|
|
161
|
+
registerRunTools(server, client);
|
|
76
162
|
registerPersonaTools(server, client);
|
|
77
163
|
registerConnectorTools(server, client);
|
|
78
164
|
registerAttachTools(server, client);
|
|
165
|
+
registerCatalogTools(server, client);
|
|
79
166
|
return server;
|
|
80
167
|
}
|
|
81
168
|
async function main() {
|
|
169
|
+
assertNoExtraArguments(process.argv.slice(2));
|
|
82
170
|
const config = loadConfig();
|
|
83
171
|
const client = new AxonityClient(config);
|
|
84
172
|
const server = buildServer(client);
|
|
@@ -87,8 +175,43 @@ async function main() {
|
|
|
87
175
|
// Log to stderr — stdout is the MCP channel and must stay clean.
|
|
88
176
|
console.error(`Axonity MCP connector ready (${config.apiUrl}).`);
|
|
89
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* True when this module is the process entry point.
|
|
180
|
+
*
|
|
181
|
+
* `import.meta.url` is realpath-resolved and percent-encoded, so it can't be
|
|
182
|
+
* compared against a hand-built `file://${argv[1]}` string: npm installs the bin
|
|
183
|
+
* as a symlink (`node_modules/.bin/axonity-mcp`), which is how `npx` runs it, and
|
|
184
|
+
* paths with spaces encode differently. Both mismatches used to leave the server
|
|
185
|
+
* silently unstarted. Resolve argv[1] the same way before comparing.
|
|
186
|
+
*/
|
|
187
|
+
export function isEntryPoint(moduleUrl, argv1) {
|
|
188
|
+
if (!argv1)
|
|
189
|
+
return false;
|
|
190
|
+
try {
|
|
191
|
+
return moduleUrl === pathToFileURL(realpathSync(argv1)).href;
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
// argv[1] isn't a readable path (e.g. `node --eval`); not our entry point.
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
export function assertNoExtraArguments(argv) {
|
|
199
|
+
if (argv.length === 0)
|
|
200
|
+
return;
|
|
201
|
+
throw new Error([
|
|
202
|
+
"This MCP server does not accept command-line arguments.",
|
|
203
|
+
"Usage:",
|
|
204
|
+
" axonity-mcp",
|
|
205
|
+
"",
|
|
206
|
+
"Pass configuration through environment variables instead:",
|
|
207
|
+
" AXONITY_TOKEN (required): the service token.",
|
|
208
|
+
" AXONITY_API_URL (optional): API base URL.",
|
|
209
|
+
"",
|
|
210
|
+
`Received arguments: ${argv.join(" ")}`,
|
|
211
|
+
].join("\n"));
|
|
212
|
+
}
|
|
90
213
|
// Only run when executed directly (not when imported by tests).
|
|
91
|
-
if (import.meta.url
|
|
214
|
+
if (isEntryPoint(import.meta.url, process.argv[1])) {
|
|
92
215
|
main().catch((err) => {
|
|
93
216
|
console.error("Axonity MCP connector failed to start:", err);
|
|
94
217
|
process.exit(1);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EACL,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAkB,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEzE;;;;GAIG;AACH,MAAM,QAAQ,GAAgB;IAC5B;QACE,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,mBAAmB;QAC7B,YAAY,EAAE,OAAO;QACrB,KAAK,EAAE,gCAAgC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AAEjF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EACL,mBAAmB,EACnB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAkB,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAwB,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACjF,OAAO,EAAE,yBAAyB,EAAE,MAAM,8BAA8B,CAAC;AAEzE;;;;GAIG;AACH,MAAM,QAAQ,GAAgB;IAC5B;QACE,QAAQ,EAAE,UAAU;QACpB,QAAQ,EAAE,mBAAmB;QAC7B,YAAY,EAAE,OAAO;QACrB,KAAK,EAAE,gCAAgC;QACvC,kBAAkB,EAAE,iBAAiB;KACtC;IACD;QACE,QAAQ,EAAE,OAAO;QACjB,QAAQ,EAAE,gBAAgB;QAC1B,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,QAAQ;QACf,kBAAkB,EAAE,iBAAiB;KACtC;IACD;QACE,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,eAAe;QACzB,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,uDAAuD;QAC9D,sEAAsE;QACtE,2EAA2E;QAC3E,WAAW,EAAE,4BAA4B;QACzC,kBAAkB,EAAE,iBAAiB;KACtC;IACD;QACE,QAAQ,EAAE,OAAO;QACjB,QAAQ,EAAE,gBAAgB;QAC1B,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,uCAAuC;QAC9C,kBAAkB,EAAE,kBAAkB;KACvC;IACD;QACE,QAAQ,EAAE,QAAQ;QAClB,QAAQ,EAAE,kBAAkB;QAC5B,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,4CAA4C;QACnD,MAAM,EAAE,UAAU;QAClB,kBAAkB,EAAE,kBAAkB;KACvC;IACD;QACE,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,wBAAwB;QAClC,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,kDAAkD;QACzD,kBAAkB,EAAE,kBAAkB;KACvC;IACD;QACE,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,wBAAwB;QAClC,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,uDAAuD;QAC9D,mEAAmE;QACnE,2DAA2D;QAC3D,kBAAkB,EAAE,kBAAkB;KACvC;IACD;QACE,QAAQ,EAAE,SAAS;QACnB,QAAQ,EAAE,kBAAkB;QAC5B,YAAY,EAAE,KAAK;QACnB,KAAK,EAAE,qDAAqD;QAC5D,sEAAsE;QACtE,oCAAoC;QACpC,SAAS,EAAE,KAAK;QAChB,kBAAkB,EAAE,kBAAkB;KACvC;IACD;QACE,QAAQ,EAAE,gBAAgB;QAC1B,QAAQ,EAAE,yBAAyB;QACnC,YAAY,EAAE,OAAO;QACrB,KAAK,EAAE,6CAA6C;QACpD,kBAAkB,EAAE,iBAAiB;KACtC;IACD;QACE,QAAQ,EAAE,MAAM;QAChB,QAAQ,EAAE,eAAe;QACzB,YAAY,EAAE,OAAO;QACrB,KAAK,EAAE,qCAAqC;QAC5C,kBAAkB,EAAE,iBAAiB;KACtC;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,SAAS,GAAsB;IACnC,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,mBAAmB,EAAE,aAAa,EAAE,QAAQ,EAAE;IAChF,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,QAAQ,EAAE;IAC1E,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,EAAE;IACxE,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,aAAa,EAAE,UAAU,EAAE;IAC5E,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,kBAAkB,EAAE,aAAa,EAAE,UAAU,EAAE;IAC/E;QACE,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,wBAAwB;QAClC,aAAa,EAAE,UAAU;KAC1B;IACD,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,kBAAkB,EAAE,aAAa,EAAE,UAAU,EAAE;IAChF;QACE,QAAQ,EAAE,eAAe;QACzB,QAAQ,EAAE,wBAAwB;QAClC,aAAa,EAAE,UAAU;KAC1B;IACD;QACE,QAAQ,EAAE,gBAAgB;QAC1B,QAAQ,EAAE,yBAAyB;QACnC,aAAa,EAAE,UAAU;KAC1B;IACD,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,eAAe,EAAE,aAAa,EAAE,QAAQ,EAAE;CACzE,CAAC;AAEF,MAAM,UAAU,WAAW,CAAC,MAAqB;IAC/C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IACpE,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC5B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IAC3C,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5C,CAAC;IACD,yBAAyB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,uBAAuB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,sBAAsB,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,iEAAiE;IACjE,OAAO,CAAC,KAAK,CAAC,gCAAgC,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;AACnE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,SAAiB,EAAE,KAAyB;IACvE,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IACzB,IAAI,CAAC;QACH,OAAO,SAAS,KAAK,aAAa,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,2EAA2E;QAC3E,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,IAAc;IACnD,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAC9B,MAAM,IAAI,KAAK,CACb;QACE,yDAAyD;QACzD,QAAQ;QACR,eAAe;QACf,EAAE;QACF,2DAA2D;QAC3D,gDAAgD;QAChD,6CAA6C;QAC7C,EAAE;QACF,uBAAuB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;KACxC,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;AACJ,CAAC;AAED,gEAAgE;AAChE,IAAI,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnD,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACnB,OAAO,CAAC,KAAK,CAAC,wCAAwC,EAAE,GAAG,CAAC,CAAC;QAC7D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -11,35 +11,174 @@ const CONVENTIONS = `# Authoring conventions for Axonity entities
|
|
|
11
11
|
|
|
12
12
|
Read this before creating or updating anything.
|
|
13
13
|
|
|
14
|
+
## What this connector is for
|
|
15
|
+
- AUTHORING: composing an entity from intent — drafting a workflow, an agent, a
|
|
16
|
+
tool, and wiring them together. That is what these tools are good at.
|
|
17
|
+
- NOT bulk migration. Do not use this to move many entities verbatim from
|
|
18
|
+
somewhere else; Axonity's config import/export moves bytes without a model in
|
|
19
|
+
the path. Content can be subtly altered in transit through an agent, which is
|
|
20
|
+
exactly what you cannot afford in a fidelity migration.
|
|
21
|
+
|
|
22
|
+
## The authoring loop
|
|
23
|
+
1. \`read_*\` the entity (and \`read_*_published\` if you need to see what is live).
|
|
24
|
+
2. Edit the DRAFT: \`update_*\`, or workflow-edit tools for workflow structure.
|
|
25
|
+
3. Validate before publish: \`validate_workflow\` / \`analyze_workflow_reachable_outputs\` /
|
|
26
|
+
\`validate_tool_code\` / \`format_tool_code\`. These four are stateless and work with
|
|
27
|
+
read-only tokens.
|
|
28
|
+
4. Re-read and verify with a saved tool command: \`execute_tool\` / \`execute_stored_connector\`.
|
|
29
|
+
5. Fix any issues and re-read again.
|
|
30
|
+
6. \`request_publish_*\` — this only QUEUES a human approval.
|
|
31
|
+
7. \`list_publish_approvals\` / \`get_publish_approval\` to see whether it was
|
|
32
|
+
approved or rejected.
|
|
33
|
+
8. If something went wrong:
|
|
34
|
+
- Bad edit, entity still exists → \`list_*_versions\` then \`restore_*_version\`
|
|
35
|
+
to roll the draft back to an earlier version.
|
|
36
|
+
- Never published, want a clean slate → \`discard_*_draft\` resets the draft to
|
|
37
|
+
the last published state (fails if it was never published — there's nothing
|
|
38
|
+
to fall back to).
|
|
39
|
+
- Deleted by mistake → \`restore_*\` (see "Delete is recoverable" below).
|
|
40
|
+
|
|
14
41
|
## Drafts, not live
|
|
15
42
|
- \`create_*\` and \`update_*\` produce a DRAFT. The live runtime is unaffected
|
|
16
|
-
until a human publishes it in Axonity.
|
|
43
|
+
until a human publishes it in Axonity. \`flow\` has the same rule: runtime uses
|
|
44
|
+
the published snapshot from \`read_flow_published\` until \`request_publish_flow\`
|
|
45
|
+
is approved.
|
|
46
|
+
- You cannot publish directly — the backend refuses a direct publish from a service
|
|
47
|
+
token with a 403, so there is no tool for it and no way around it.
|
|
48
|
+
- A read-only token can only read: any write returns 403. If you see that, ask
|
|
49
|
+
your human for a write-scoped token rather than retrying.
|
|
17
50
|
- \`request_publish_*\` does NOT publish — it creates a pending approval a human
|
|
18
51
|
approves in Axonity. Use it when a draft is ready; then tell the user to
|
|
19
52
|
approve it in their Axonity approvals inbox.
|
|
20
53
|
|
|
21
54
|
## Optimistic locking (always read-then-write)
|
|
22
55
|
- Before \`update_*\`, call \`read_*\` and use the \`version\` you get as
|
|
23
|
-
\`expectedVersion
|
|
24
|
-
it — read again and re-apply your change onto
|
|
56
|
+
\`expectedVersion\` — in the request BODY. If the update returns a 409
|
|
57
|
+
conflict, someone else changed it — read again and re-apply your change onto
|
|
58
|
+
the new version.
|
|
59
|
+
- \`delete_*\` also takes \`expectedVersion\`, but as an argument on the tool call
|
|
60
|
+
only — the connector maps it to whatever query-parameter spelling that
|
|
61
|
+
entity's route actually expects (it differs per entity on the wire; you never
|
|
62
|
+
need to know which).
|
|
63
|
+
- \`restore_*\` and \`restore_deleted_*_version\` take NO version at all — a
|
|
64
|
+
restore must never lose to a stale-version guard.
|
|
65
|
+
|
|
66
|
+
## Errors: branch on the failure, not the words
|
|
67
|
+
- Every error names what went wrong as plainly as the backend allows. For a 409
|
|
68
|
+
specifically, two different problems share that status code and need
|
|
69
|
+
different responses:
|
|
70
|
+
- **Version conflict** — you had a stale read. Re-read, re-apply, retry.
|
|
71
|
+
- **Reference conflict** — the entity is referenced by something published or
|
|
72
|
+
live. Retrying will never help. Detach the reference or unpublish the
|
|
73
|
+
referencing entity first.
|
|
74
|
+
The error message tells you which one you hit — read it, don't assume 409
|
|
75
|
+
always means "retry."
|
|
76
|
+
- A 403 on any write means the token is read-only, or (for a direct publish
|
|
77
|
+
attempt, which no tool makes) that publishing must go through
|
|
78
|
+
\`request_publish_*\`. Either way: stop, don't retry, tell your human.
|
|
79
|
+
- A 401 means the service token is dead — missing, wrong, expired, or revoked.
|
|
80
|
+
**The backend deliberately returns the identical message for all four
|
|
81
|
+
causes** so it doesn't leak which applies; you have no way to tell them
|
|
82
|
+
apart and no way to check a token's remaining lifetime in advance (every
|
|
83
|
+
token now expires — 7, 15, 30, 60 or 90 days, chosen when it was minted;
|
|
84
|
+
there is no "never"). On any 401: stop, do not retry, and tell your human
|
|
85
|
+
plainly that the configured token is no longer valid and a new one must be
|
|
86
|
+
minted from Axonity → Settings → API tokens. Do not guess or imply the cause.
|
|
25
87
|
|
|
26
88
|
## Field shape
|
|
27
89
|
- All fields are camelCase JSON (e.g. \`capabilityTier\`, not \`capability_tier\`).
|
|
28
90
|
- \`update_*\` is a partial change for agents/tools and a partial patch for
|
|
29
91
|
workflows: send only the fields you are changing.
|
|
30
|
-
- The backend validates fields; a 422 error
|
|
92
|
+
- The backend validates fields; a 422 error names the offending field and why
|
|
93
|
+
(e.g. \`body.capabilityTier: Input should be 'standard' or 'advanced'\`). Fix
|
|
94
|
+
that field and retry — do not guess at the whole shape.
|
|
95
|
+
- \`agent.tags\` is not cosmetic: it drives which policies apply to the agent at
|
|
96
|
+
runtime. An untagged agent looks correct everywhere in the UI and silently
|
|
97
|
+
skips policies scoped to those tags. If you create or update an agent that
|
|
98
|
+
should be governed by a policy, check its tags match what the policy expects.
|
|
99
|
+
|
|
100
|
+
## After you write, verify
|
|
101
|
+
- A 200 means the request was accepted, NOT that it did what you meant. Re-read
|
|
102
|
+
the entity after a mutation and diff it against your intent — unknown fields
|
|
103
|
+
can be dropped silently, and a partial update only changes what you sent.
|
|
104
|
+
|
|
105
|
+
## Delete is recoverable — but not everything is
|
|
106
|
+
- \`delete_*\` soft-deletes: the entity disappears from \`list_*\` but is not gone.
|
|
107
|
+
\`restore_*\` brings it back; \`list_deleted_*\` shows what's waiting. This
|
|
108
|
+
applies uniformly to workflow, agent, tool, skill, policy, reference_doc,
|
|
109
|
+
persona, output_schema, prompt_snippet, and flow.
|
|
110
|
+
- The same applies one level down, to version HISTORY:
|
|
111
|
+
\`delete_*_version\` removes one entry from history (the current draft and
|
|
112
|
+
published version are protected and can't be targeted this way);
|
|
113
|
+
\`list_deleted_*_versions\` / \`restore_deleted_*_version\` undo it. Deleted
|
|
114
|
+
version numbers stay reserved rather than reused, so gaps in the numbering
|
|
115
|
+
are normal, not a sign of corruption.
|
|
116
|
+
- \`restore_*\` can itself 409 if a live entity now holds the same name/slot —
|
|
117
|
+
the error names the conflicting one.
|
|
118
|
+
- There is no "archive" state for these ten entities — delete + restore IS the
|
|
119
|
+
lifecycle. Runs are the one exception with a true archive/unarchive (see below).
|
|
31
120
|
|
|
32
121
|
## Per entity
|
|
33
|
-
- **workflow**: \`create_workflow\` makes a stub (name, description).
|
|
34
|
-
|
|
35
|
-
|
|
122
|
+
- **workflow**: \`create_workflow\` makes a stub (name, description). Edit its
|
|
123
|
+
document with either
|
|
124
|
+
- \`apply_workflow_mutations\` (LIST of command mutations, preserved order), or
|
|
125
|
+
- \`replace_workflow_document\` (full-document atomic PUT).
|
|
36
126
|
- **agent**: fields include name, avatar, capabilityTier, creativityTier,
|
|
37
|
-
learningMode, permissions, delegationTargetIds, toolIds, systemToolIds,
|
|
127
|
+
learningMode, permissions, delegationTargetIds, toolIds, systemToolIds, tags,
|
|
128
|
+
status. \`list_system_tools\` shows what can go in \`systemToolIds\` — there is
|
|
129
|
+
no separate grant/revoke tool, you set it via \`update_agent\`.
|
|
38
130
|
- **tool**: fields include name, description, type
|
|
39
131
|
("function" | "connector" | "validator" | "evaluator"), inputSchema,
|
|
40
132
|
outputSchema, implementation, authConfig, status. For a connector, set
|
|
41
133
|
\`type: "connector"\`; NEVER put real credentials in authConfig — use
|
|
42
|
-
placeholders and let a human fill secrets in the Axonity tool editor.
|
|
134
|
+
placeholders and let a human fill secrets in the Axonity tool editor. Test it
|
|
135
|
+
with \`execute_tool\` (runs code you supply) or \`execute_stored_connector\`
|
|
136
|
+
(runs an already-saved connector using its real, server-side-decrypted
|
|
137
|
+
secret — you never see the secret, only the result).
|
|
138
|
+
- **persona**: an agent's character — 1:1 with an agent. Created only through
|
|
139
|
+
its agent (\`create_agent_persona\`); once created it's a normal entity
|
|
140
|
+
(\`list_personas\`, \`read_persona\`, \`update_persona\`, delete/restore/versions).
|
|
141
|
+
- **prompt_snippet**: reusable prompt fragments. A normal entity in every
|
|
142
|
+
respect now (\`read_prompt_snippet\`, \`discard_prompt_snippet_draft\`,
|
|
143
|
+
everything else). Only wire-level oddity: \`list_deleted_prompt_snippets\`
|
|
144
|
+
uses a dedicated deleted collection and returns the backend \`items\` envelope.
|
|
145
|
+
- **output_schema**: a reusable output contract, fully version-controlled and
|
|
146
|
+
publishable like the other memory entities. A tool's \`outputValidators\` (or
|
|
147
|
+
an agent's \`permissions.expected_output_schema_id\`) references one by id —
|
|
148
|
+
create it before you need to point something at it.
|
|
149
|
+
- **flow**: a reusable workflow fragment in the authored-entity lifecycle.
|
|
150
|
+
\`create_flow\` and \`update_flow\` write draft state; execution uses
|
|
151
|
+
\`read_flow_published\` until approval completes. Use
|
|
152
|
+
\`request_publish_flow\` to request publish approval, and \`discard_flow_draft\`
|
|
153
|
+
when you need to reset the draft to last published state.
|
|
154
|
+
|
|
155
|
+
## Structural workflow edits
|
|
156
|
+
- \`apply_workflow_mutations\` takes a LIST of commands and applies them in order,
|
|
157
|
+
threading the version for you — pass the version you read, not one per command.
|
|
158
|
+
- It is NOT transactional. If command N fails, the ones before it stay applied;
|
|
159
|
+
the error tells you how many landed and which index failed. Re-read and resume
|
|
160
|
+
from that index rather than replaying the whole list.
|
|
161
|
+
|
|
162
|
+
## Triggers
|
|
163
|
+
- A published workflow still does nothing until it has a trigger. Add one with
|
|
164
|
+
\`create_cron_schedule\`, \`create_webhook_trigger\`, or
|
|
165
|
+
\`create_conditional_trigger\`.
|
|
166
|
+
- Trigger deletes are HARD deletes — no restore. Webhook tokens are shown once
|
|
167
|
+
at create/rotate and are never retrievable; hand them straight to your human
|
|
168
|
+
and never store one in an entity field.
|
|
169
|
+
|
|
170
|
+
## Evaluating what you built
|
|
171
|
+
- There is no findings endpoint and no evaluator entity. To judge a run, read it:
|
|
172
|
+
\`read_run\` (its \`validatorVerdicts\` and \`agentInvocations\`) and
|
|
173
|
+
\`read_run_trace\` (the step-by-step tool calls).
|
|
174
|
+
- Runs are the only thing with a real archive state — \`archive_run\` is
|
|
175
|
+
reversible, \`bulk_delete_runs\` is not.
|
|
176
|
+
|
|
177
|
+
## Secrets
|
|
178
|
+
- Never handle a real credential. A connector's \`authConfig\` takes placeholders
|
|
179
|
+
only ("{{ MY_SECRET }}" or ""); a human fills the real value in Axonity. This
|
|
180
|
+
is enforced — a write carrying something that looks like a real secret is
|
|
181
|
+
rejected before it leaves this connector.
|
|
43
182
|
|
|
44
183
|
## Tenant
|
|
45
184
|
- Your token fixes the tenant. You cannot act across tenants; never send a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conventions.js","sourceRoot":"","sources":["../../src/tools/conventions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,GAAG
|
|
1
|
+
{"version":3,"file":"conventions.js","sourceRoot":"","sources":["../../src/tools/conventions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgLnB,CAAC;AAEF,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,IAAI,CACT,qBAAqB,EACrB,4EAA4E;QAC1E,qEAAqE,EACvE,EAAE,EACF,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAC1E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The connector credential guard.
|
|
3
|
+
*
|
|
4
|
+
* A connector's `authConfig` must carry PLACEHOLDERS only — a human fills the
|
|
5
|
+
* real secret in Axonity, and the value never passes through an agent. This
|
|
6
|
+
* module enforces that on every path that can write a connector.
|
|
7
|
+
*
|
|
8
|
+
* Two independent defences, mirroring the backend's `secret_scrub` module:
|
|
9
|
+
*
|
|
10
|
+
* 1. **Structural** — credential-ish leaves (`clientSecret`, `apiKey`, …) must
|
|
11
|
+
* be a placeholder. Applied only to keys that actually name a credential, so
|
|
12
|
+
* legitimate neighbours (`authType: "bearer"`, `tokenUrl: "https://…"`)
|
|
13
|
+
* are left alone. The earlier guard required EVERY value to be a placeholder,
|
|
14
|
+
* which rejected correct connectors while missing nested ones entirely.
|
|
15
|
+
* 2. **Shape scan** — every string leaf, at any depth, is swept for known secret
|
|
16
|
+
* formats, catching a credential parked in a field nobody thought to name.
|
|
17
|
+
*
|
|
18
|
+
* Findings name WHERE and WHAT KIND, never the matched value — an error message
|
|
19
|
+
* is not a safe place to echo a secret.
|
|
20
|
+
*/
|
|
21
|
+
/** Empty, or a `{{ … }}` template the human replaces in Axonity. */
|
|
22
|
+
export declare function isPlaceholder(value: unknown): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Walk `value` depth-first and collect every violation as `path: reason`.
|
|
25
|
+
* Exported for testing; `assertPlaceholderCredentials` is the enforcement point.
|
|
26
|
+
*/
|
|
27
|
+
export declare function findCredentialViolations(value: unknown, path?: string): string[];
|
|
28
|
+
/**
|
|
29
|
+
* Throw if a connector's fields carry anything that looks like a real
|
|
30
|
+
* credential. Safe to call with any tool's fields — it is a no-op when there is
|
|
31
|
+
* no `authConfig`, which is what makes it cheap to apply to `create_tool` and
|
|
32
|
+
* `update_tool` as well as the connector-specific verbs.
|
|
33
|
+
*/
|
|
34
|
+
export declare function assertPlaceholderCredentials(fields: Record<string, unknown>): void;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The connector credential guard.
|
|
3
|
+
*
|
|
4
|
+
* A connector's `authConfig` must carry PLACEHOLDERS only — a human fills the
|
|
5
|
+
* real secret in Axonity, and the value never passes through an agent. This
|
|
6
|
+
* module enforces that on every path that can write a connector.
|
|
7
|
+
*
|
|
8
|
+
* Two independent defences, mirroring the backend's `secret_scrub` module:
|
|
9
|
+
*
|
|
10
|
+
* 1. **Structural** — credential-ish leaves (`clientSecret`, `apiKey`, …) must
|
|
11
|
+
* be a placeholder. Applied only to keys that actually name a credential, so
|
|
12
|
+
* legitimate neighbours (`authType: "bearer"`, `tokenUrl: "https://…"`)
|
|
13
|
+
* are left alone. The earlier guard required EVERY value to be a placeholder,
|
|
14
|
+
* which rejected correct connectors while missing nested ones entirely.
|
|
15
|
+
* 2. **Shape scan** — every string leaf, at any depth, is swept for known secret
|
|
16
|
+
* formats, catching a credential parked in a field nobody thought to name.
|
|
17
|
+
*
|
|
18
|
+
* Findings name WHERE and WHAT KIND, never the matched value — an error message
|
|
19
|
+
* is not a safe place to echo a secret.
|
|
20
|
+
*/
|
|
21
|
+
/** Keys whose value is a credential. Matched case- and separator-insensitively. */
|
|
22
|
+
const CREDENTIAL_KEY = /(secret|password|passphrase|token|credential|apikey|privatekey|signingkey|authorization|clientkey)/;
|
|
23
|
+
/**
|
|
24
|
+
* Suffixes that make a credential-ish key a LOCATOR rather than the secret
|
|
25
|
+
* itself — `tokenUrl` is an OAuth endpoint, `apiKeyName` is a header name.
|
|
26
|
+
* Without this, correct configs are rejected, which is what pushes an agent to
|
|
27
|
+
* work around the guard. The shape scan still covers these fields, so a real
|
|
28
|
+
* credential parked in one is caught anyway.
|
|
29
|
+
*/
|
|
30
|
+
const LOCATOR_SUFFIX = /(url|uri|endpoint|name|type|id|path|method|location|scope|expiresin|ttl)$/;
|
|
31
|
+
/** Known secret shapes, mirroring the backend's `_SECRET_PATTERNS`. */
|
|
32
|
+
const SECRET_PATTERNS = [
|
|
33
|
+
["private key block", /-----BEGIN [A-Z ]*PRIVATE KEY-----/],
|
|
34
|
+
["aws access key id", /\bAKIA[0-9A-Z]{16}\b/],
|
|
35
|
+
["github token", /\bgh[pousr]_[A-Za-z0-9]{36,}\b/],
|
|
36
|
+
["slack token", /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/],
|
|
37
|
+
["google api key", /\bAIza[0-9A-Za-z_-]{35}\b/],
|
|
38
|
+
["stripe secret key", /\bsk_(?:live|test)_[A-Za-z0-9]{16,}\b/],
|
|
39
|
+
["jwt", /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/],
|
|
40
|
+
["credentials in url", /:\/\/[^/\s:@]+:[^/\s:@]+@/],
|
|
41
|
+
];
|
|
42
|
+
/** Empty, or a `{{ … }}` template the human replaces in Axonity. */
|
|
43
|
+
export function isPlaceholder(value) {
|
|
44
|
+
if (value === "" || value === null || value === undefined)
|
|
45
|
+
return true;
|
|
46
|
+
return typeof value === "string" && /^\s*\{\{.*\}\}\s*$/.test(value);
|
|
47
|
+
}
|
|
48
|
+
function isCredentialKey(key) {
|
|
49
|
+
const normalized = key.replace(/[_\-\s]/g, "").toLowerCase();
|
|
50
|
+
if (LOCATOR_SUFFIX.test(normalized))
|
|
51
|
+
return false;
|
|
52
|
+
return CREDENTIAL_KEY.test(normalized);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Walk `value` depth-first and collect every violation as `path: reason`.
|
|
56
|
+
* Exported for testing; `assertPlaceholderCredentials` is the enforcement point.
|
|
57
|
+
*/
|
|
58
|
+
export function findCredentialViolations(value, path = "authConfig") {
|
|
59
|
+
const findings = [];
|
|
60
|
+
const walk = (node, at, keyIsCredential) => {
|
|
61
|
+
if (Array.isArray(node)) {
|
|
62
|
+
node.forEach((item, i) => walk(item, `${at}[${i}]`, keyIsCredential));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (node !== null && typeof node === "object") {
|
|
66
|
+
for (const [key, child] of Object.entries(node)) {
|
|
67
|
+
walk(child, `${at}.${key}`, isCredentialKey(key));
|
|
68
|
+
}
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (typeof node === "string") {
|
|
72
|
+
for (const [label, pattern] of SECRET_PATTERNS) {
|
|
73
|
+
if (pattern.test(node)) {
|
|
74
|
+
findings.push(`${at}: looks like a real ${label}`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// A credential-named leaf must be a placeholder whatever its type.
|
|
80
|
+
if (keyIsCredential && !isPlaceholder(node)) {
|
|
81
|
+
findings.push(`${at}: must be a placeholder, not a real value`);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
walk(value, path, false);
|
|
85
|
+
return findings;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Throw if a connector's fields carry anything that looks like a real
|
|
89
|
+
* credential. Safe to call with any tool's fields — it is a no-op when there is
|
|
90
|
+
* no `authConfig`, which is what makes it cheap to apply to `create_tool` and
|
|
91
|
+
* `update_tool` as well as the connector-specific verbs.
|
|
92
|
+
*/
|
|
93
|
+
export function assertPlaceholderCredentials(fields) {
|
|
94
|
+
const authConfig = fields.authConfig;
|
|
95
|
+
if (authConfig === undefined || authConfig === null)
|
|
96
|
+
return;
|
|
97
|
+
const findings = findCredentialViolations(authConfig);
|
|
98
|
+
if (findings.length === 0)
|
|
99
|
+
return;
|
|
100
|
+
throw new Error("authConfig must contain placeholders only — a human fills real secrets in " +
|
|
101
|
+
"the Axonity tool editor, and a credential must never pass through an " +
|
|
102
|
+
`agent. Use "{{ MY_SECRET }}" or "" instead.\n\n${findings
|
|
103
|
+
.map((f) => ` - ${f}`)
|
|
104
|
+
.join("\n")}`);
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/tools/credentials.ts"],"names":[],"mappings":"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"}
|
package/dist/tools/extras.d.ts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
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 type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
11
13
|
import type { AxonityClient } from "../client.js";
|
|
12
14
|
export declare function registerPersonaTools(server: McpServer, client: AxonityClient): void;
|
|
13
15
|
export declare function registerConnectorTools(server: McpServer, client: AxonityClient): void;
|
|
14
16
|
export declare function registerAttachTools(server: McpServer, client: AxonityClient): void;
|
|
17
|
+
/**
|
|
18
|
+
* Small standalone tools that don't fit any of the other groupings: the
|
|
19
|
+
* system-tools catalog (read-only — there is no grant/revoke route; enabling
|
|
20
|
+
* one for an agent means writing `systemToolIds` via `update_agent`), and
|
|
21
|
+
* cloning a flow/prompt-snippet into a tenant-owned copy.
|
|
22
|
+
*/
|
|
23
|
+
export declare function registerCatalogTools(server: McpServer, client: AxonityClient): void;
|