@rudderhq/agent-runtime-utils 0.7.13 → 0.7.15

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 (38) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/rudder-agent-contract.d.ts +5 -0
  6. package/dist/rudder-agent-contract.d.ts.map +1 -0
  7. package/dist/rudder-agent-contract.generated.d.ts +8322 -0
  8. package/dist/rudder-agent-contract.generated.d.ts.map +1 -0
  9. package/dist/rudder-agent-contract.generated.js +9320 -0
  10. package/dist/rudder-agent-contract.generated.js.map +1 -0
  11. package/dist/rudder-agent-contract.js +31 -0
  12. package/dist/rudder-agent-contract.js.map +1 -0
  13. package/dist/rudder-agent-contract.test.d.ts +2 -0
  14. package/dist/rudder-agent-contract.test.d.ts.map +1 -0
  15. package/dist/rudder-agent-contract.test.js +69 -0
  16. package/dist/rudder-agent-contract.test.js.map +1 -0
  17. package/dist/rudder-mcp-contract.d.ts +5939 -932
  18. package/dist/rudder-mcp-contract.d.ts.map +1 -1
  19. package/dist/rudder-mcp-contract.js +7 -805
  20. package/dist/rudder-mcp-contract.js.map +1 -1
  21. package/dist/rudder-mcp-tool-descriptors.generated.d.ts +5111 -1
  22. package/dist/rudder-mcp-tool-descriptors.generated.d.ts.map +1 -1
  23. package/dist/rudder-mcp-tool-descriptors.generated.js +5999 -104
  24. package/dist/rudder-mcp-tool-descriptors.generated.js.map +1 -1
  25. package/dist/server-utils.instructions.d.ts.map +1 -1
  26. package/dist/server-utils.instructions.js +26 -6
  27. package/dist/server-utils.instructions.js.map +1 -1
  28. package/dist/server-utils.prompt-boundaries.test.d.ts +2 -0
  29. package/dist/server-utils.prompt-boundaries.test.d.ts.map +1 -0
  30. package/dist/server-utils.prompt-boundaries.test.js +44 -0
  31. package/dist/server-utils.prompt-boundaries.test.js.map +1 -0
  32. package/dist/server-utils.prompts.d.ts +23 -10
  33. package/dist/server-utils.prompts.d.ts.map +1 -1
  34. package/dist/server-utils.prompts.js +65 -27
  35. package/dist/server-utils.prompts.js.map +1 -1
  36. package/dist/server-utils.test.js +65 -19
  37. package/dist/server-utils.test.js.map +1 -1
  38. package/package.json +2 -2
@@ -1,816 +1,18 @@
1
1
  import { GENERATED_RUDDER_BROWSER_MCP_CONTRACT_HASH, GENERATED_RUDDER_CORE_MCP_CONTRACT_HASH, RUDDER_MCP_TOOL_DESCRIPTORS, } from "./rudder-mcp-tool-descriptors.generated.js";
2
2
  export const RUDDER_MCP_CONTRACT_VERSION = "rudder.agent-mcp-tools/v1";
3
- const RUDDER_MCP_DESTRUCTIVE_CAPABILITY_IDS = new Set([
4
- "agent.skills.sync",
5
- "issue.block",
6
- "issue.done",
7
- "library.file.put",
8
- "automation.triggers.delete",
9
- "automation.triggers.rotate-secret",
10
- "automation.disable",
11
- "chat.archive",
12
- "runs.cancel",
13
- "browser.clipboard",
14
- "browser.logs",
15
- ]);
16
- const RUDDER_MCP_OPEN_WORLD_CAPABILITY_IDS = new Set([
17
- "browser.open",
18
- "browser.navigate",
19
- "browser.download",
20
- "browser.content",
21
- ]);
22
- function browserMcpInputSchema(id) {
23
- const string = (description, extra = {}) => ({ type: "string", description, ...extra });
24
- const number = (description, extra = {}) => ({ type: "number", description, ...extra });
25
- const boolean = (description) => ({ type: "boolean", description });
26
- const schema = (properties, required = []) => ({
27
- type: "object",
28
- additionalProperties: false,
29
- properties,
30
- ...(required.length > 0 ? { required } : {}),
31
- });
32
- const locatorAtom = schema({
33
- strategy: string("Locator strategy.", { enum: ["css", "testId", "href", "role", "label", "placeholder", "text"] }),
34
- value: string("Selector, role, label, placeholder, href, test id, or text value.", { minLength: 1, maxLength: 2_000 }),
35
- name: string("Accessible name used with the role strategy.", { maxLength: 2_000 }),
36
- exact: boolean("Require an exact text or attribute match."),
37
- }, ["strategy", "value"]);
38
- const simpleLocator = schema({
39
- ...locatorAtom.properties,
40
- filter: schema({
41
- hasText: string("Required descendant text.", { maxLength: 2_000 }),
42
- hasNotText: string("Excluded descendant text.", { maxLength: 2_000 }),
43
- visible: boolean("Filter by current visibility."),
44
- has: locatorAtom,
45
- hasNot: locatorAtom,
46
- }),
47
- and: locatorAtom,
48
- or: locatorAtom,
49
- index: number("Zero-based locator match index.", { minimum: 0, maximum: 499 }),
50
- position: string("Locator endpoint after an explicit count.", { enum: ["first", "last"] }),
51
- }, ["strategy", "value"]);
52
- const locator = schema({
53
- ...simpleLocator.properties,
54
- frame: { type: "array", maxItems: 8, items: string("CSS iframe selector.", { minLength: 1, maxLength: 1_000 }) },
55
- scope: simpleLocator,
56
- }, ["strategy", "value"]);
57
- const baseTab = { tabId: string("Run-owned Rudder Browser tab id.", { minLength: 1, maxLength: 160 }) };
58
- switch (id) {
59
- case "browser.tabs":
60
- case "browser.user-tabs": return schema({});
61
- case "browser.open": return schema({ url: string("HTTP or HTTPS URL.", { minLength: 1, maxLength: 8_192 }) }, ["url"]);
62
- case "browser.navigate": return schema({ ...baseTab, url: string("HTTP or HTTPS URL.", { minLength: 1, maxLength: 8_192 }) }, ["tabId", "url"]);
63
- case "browser.back":
64
- case "browser.forward":
65
- case "browser.reload":
66
- case "browser.read":
67
- case "browser.close": return schema(baseTab, ["tabId"]);
68
- case "browser.viewport": return schema({
69
- action: string("Viewport action.", { enum: ["get", "set", "reset"] }),
70
- width: number("Viewport width in CSS pixels.", { minimum: 320, maximum: 3_840 }),
71
- height: number("Viewport height in CSS pixels.", { minimum: 240, maximum: 2_160 }),
72
- }, ["action"]);
73
- case "browser.visibility": return schema({ visible: boolean("Whether the selected Agent Browser tab is visible.") });
74
- case "browser.snapshot": return schema({
75
- ...baseTab,
76
- boxes: boolean("Include viewport-relative element boxes."),
77
- depth: number("Maximum snapshot tree depth.", { minimum: 1, maximum: 30 }),
78
- maxNodes: number("Maximum snapshot nodes.", { minimum: 1, maximum: 3_000 }),
79
- }, ["tabId"]);
80
- case "browser.locator": return schema({
81
- ...baseTab,
82
- action: string("Read-only locator action.", { enum: ["count", "allTextContents", "textContent", "innerText", "attribute", "visible", "enabled", "checked", "selected", "wait"] }),
83
- locator,
84
- name: string("Attribute name for attribute reads.", { maxLength: 200 }),
85
- state: string("Wait state.", { enum: ["attached", "detached", "visible", "hidden"] }),
86
- timeoutMs: number("Wait timeout in milliseconds.", { minimum: 0, maximum: 30_000 }),
87
- }, ["tabId", "action", "locator"]);
88
- case "browser.cua": return schema({
89
- ...baseTab,
90
- action: string("Coordinate input or inspection action.", { enum: ["click", "doubleClick", "move", "scroll", "drag", "keypress", "type", "elementInfo"] }),
91
- x: number("Viewport X coordinate."),
92
- y: number("Viewport Y coordinate."),
93
- scrollX: number("Horizontal scroll delta."),
94
- scrollY: number("Vertical scroll delta."),
95
- button: { oneOf: [number("Mouse button number.", { minimum: 1, maximum: 5 }), string("Mouse button.", { enum: ["left", "middle", "right"] })] },
96
- keys: { type: "array", maxItems: 10, items: string("Keyboard key or modifier.", { minLength: 1, maxLength: 100 }) },
97
- text: string("Text to type.", { maxLength: 100_000 }),
98
- path: { type: "array", minItems: 2, maxItems: 200, items: schema({ x: number("Path X coordinate."), y: number("Path Y coordinate.") }, ["x", "y"]) },
99
- }, ["tabId", "action"]);
100
- case "browser.dom-cua": return schema({
101
- ...baseTab,
102
- action: string("Read-only DOM snapshot action.", { enum: ["get"] }),
103
- depth: number("Maximum DOM depth.", { minimum: 1, maximum: 30 }),
104
- maxNodes: number("Maximum DOM nodes.", { minimum: 1, maximum: 3_000 }),
105
- }, ["tabId", "action"]);
106
- case "browser.dialog": return schema({
107
- ...baseTab,
108
- action: string("Dialog action.", { enum: ["get", "accept", "dismiss"] }),
109
- promptText: string("Prompt response text.", { maxLength: 10_000 }),
110
- }, ["tabId", "action"]);
111
- case "browser.clipboard": return schema({
112
- action: string("Virtual clipboard action.", { enum: ["read", "readText", "write", "writeText", "clear"] }),
113
- text: string("Plain clipboard text.", { maxLength: 500_000 }),
114
- items: {
115
- type: "array",
116
- maxItems: 20,
117
- items: schema({
118
- presentationStyle: string("Clipboard presentation style.", { enum: ["unspecified", "inline", "attachment"] }),
119
- entries: {
120
- type: "array",
121
- maxItems: 20,
122
- items: schema({
123
- mimeType: string("Clipboard MIME type.", { minLength: 1, maxLength: 200 }),
124
- text: string("Text clipboard payload.", { maxLength: 500_000 }),
125
- base64: string("Base64 clipboard payload.", { maxLength: 650_000 }),
126
- }, ["mimeType"]),
127
- },
128
- }, ["entries"]),
129
- },
130
- }, ["action"]);
131
- case "browser.logs": return schema({
132
- ...baseTab,
133
- levels: { type: "array", maxItems: 5, items: string("Log level.", { enum: ["debug", "info", "log", "warn", "error"] }) },
134
- filter: string("Case-insensitive log substring filter.", { maxLength: 2_000 }),
135
- limit: number("Maximum log entries.", { minimum: 1, maximum: 500 }),
136
- clear: boolean("Clear the tab log buffer after reading."),
137
- }, ["tabId"]);
138
- case "browser.download": return schema({
139
- ...baseTab,
140
- mode: string("Read-only media download mode.", { enum: ["media"] }),
141
- locator,
142
- }, ["tabId", "mode", "locator"]);
143
- case "browser.assets": return schema({
144
- ...baseTab,
145
- action: string("Asset action.", { enum: ["list", "bundle"] }),
146
- inventoryId: string("Prior asset inventory id.", { maxLength: 160 }),
147
- assetIds: { type: "array", minItems: 1, maxItems: 100, items: string("Asset id.", { maxLength: 160 }) },
148
- kinds: { type: "array", minItems: 1, maxItems: 4, items: string("Asset kind.", { enum: ["font", "image", "stylesheet", "video"] }) },
149
- }, ["tabId", "action"]);
150
- case "browser.content": return schema({
151
- ...baseTab,
152
- format: string("Content export format.", { enum: ["text", "pdf", "md", "docx", "xlsx", "csv", "pptx"] }),
153
- }, ["tabId", "format"]);
154
- case "browser.wait": return schema({
155
- ...baseTab,
156
- url: string("URL substring.", { maxLength: 8_192 }),
157
- text: string("Text that must appear.", { maxLength: 10_000 }),
158
- textGone: string("Text that must disappear.", { maxLength: 10_000 }),
159
- timeMs: number("Fixed bounded delay in milliseconds.", { minimum: 0, maximum: 30_000 }),
160
- timeoutMs: number("Wait timeout in milliseconds.", { minimum: 0, maximum: 30_000 }),
161
- }, ["tabId"]);
162
- case "browser.click": return schema({ ...baseTab, ref: string("Element reference returned by rudder_browser_read.", { maxLength: 160 }) }, ["tabId", "ref"]);
163
- case "browser.type": return schema({
164
- ...baseTab,
165
- ref: string("Element reference returned by rudder_browser_read.", { maxLength: 160 }),
166
- text: string("Text to enter.", { maxLength: 100_000 }),
167
- submit: boolean("Submit the owning form after typing."),
168
- }, ["tabId", "ref", "text"]);
169
- case "browser.screenshot": return schema({
170
- ...baseTab,
171
- fullPage: boolean("Capture the full scrollable page."),
172
- format: string("Image format.", { enum: ["png", "jpeg"] }),
173
- quality: number("JPEG quality.", { minimum: 1, maximum: 100 }),
174
- clip: schema({ x: number("Clip X coordinate."), y: number("Clip Y coordinate."), width: number("Clip width.", { minimum: 1 }), height: number("Clip height.", { minimum: 1 }) }, ["x", "y", "width", "height"]),
175
- locator,
176
- }, ["tabId"]);
177
- default: return schema({});
178
- }
179
- }
180
3
  export function rudderMcpInputSchemaForCapability(id) {
181
- if (id.startsWith("browser."))
182
- return browserMcpInputSchema(id);
183
- return coreMcpInputSchema(id);
184
- }
185
- function coreMcpInputSchema(id) {
186
- const string = (description, extra = {}) => ({
187
- type: "string",
188
- description,
189
- minLength: 1,
190
- maxLength: 100_000,
191
- ...extra,
192
- });
193
- const number = (description, minimum = 0, maximum = 10_000) => ({
194
- type: "number",
195
- description,
196
- minimum,
197
- maximum,
198
- });
199
- const boolean = (description) => ({ type: "boolean", description });
200
- const strings = (description, maxItems = 100) => ({
201
- type: "array",
202
- description,
203
- maxItems,
204
- items: string(description, { maxLength: 8_192 }),
205
- });
206
- const payload = { type: ["object", "string"], description: "JSON payload object or JSON string." };
207
- const schema = (properties, required = []) => ({
208
- type: "object",
209
- additionalProperties: false,
210
- properties,
211
- ...(required.length > 0 ? { required } : {}),
212
- });
213
- const issue = string("Issue UUID, identifier, or short reference.", { maxLength: 200 });
214
- const goal = string("Goal UUID or typed short reference (gol_<prefix>) from the current Goal Runtime Context.", { maxLength: 200 });
215
- const project = string("Project UUID or shortname.", { maxLength: 200 });
216
- const approval = string("Approval UUID or short reference.", { maxLength: 200 });
217
- const automation = string("Automation UUID or short reference.", { maxLength: 200 });
218
- const trigger = string("Automation trigger UUID or short reference.", { maxLength: 200 });
219
- const chat = string("Chat conversation UUID or short reference.", { maxLength: 200 });
220
- const run = string("Run UUID, typed short reference (run_<prefix>), or legacy bare short prefix.", { maxLength: 200 });
221
- const cursor = string("Opaque pagination cursor.", { maxLength: 2_000 });
222
- const body = string("Direct Markdown body.", { maxLength: 500_000 });
223
- const images = strings("Local image paths to attach.", 20);
224
- switch (id) {
225
- case "agent.me":
226
- case "agent.inbox":
227
- case "agent.capabilities":
228
- case "project.list":
229
- case "skill.list":
230
- return schema({});
231
- case "organization.members.list":
232
- return schema({
233
- query: string("Optional member name filter.", { maxLength: 2_000 }),
234
- type: string("Member type filter.", { enum: ["human", "agent", "all"], maxLength: 10 }),
235
- limit: number("Page size.", 1, 100),
236
- cursor,
237
- });
238
- case "agent.update":
239
- return schema({
240
- name: string("Agent name.", { maxLength: 200 }),
241
- role: string("Agent role.", { maxLength: 100 }),
242
- title: string("Agent title.", { maxLength: 300 }),
243
- capabilities: string("Agent capability summary."),
244
- description: string("Compatibility alias for capabilities."),
245
- clearTitle: boolean("Clear the current title."),
246
- clearCapabilities: boolean("Clear the current capability summary."),
247
- clearDescription: boolean("Compatibility alias for clearCapabilities."),
248
- });
249
- case "agent.skills.create":
250
- return schema({
251
- name: string("Skill display name.", { maxLength: 200 }),
252
- slug: string("Skill slug.", { maxLength: 200 }),
253
- description: string("Skill description."),
254
- markdown: string("SKILL.md content.", { maxLength: 500_000 }),
255
- body: string("Compatibility alias for markdown.", { maxLength: 500_000 }),
256
- enable: boolean("Enable the created skill for the runtime agent."),
257
- }, ["name"]);
258
- case "agent.skills.enable":
259
- return schema({ selectionRefs: strings("Skill selection references.", 100) }, ["selectionRefs"]);
260
- case "agent.skills.sync":
261
- return schema({ desiredSkills: string("Comma-separated desired skill references.", { maxLength: 20_000 }) }, ["desiredSkills"]);
262
- case "goal.list":
263
- return schema({
264
- lifecycle: string("Goal lifecycle filter; active is the safe default.", {
265
- enum: ["draft", "active", "closed", "all"],
266
- maxLength: 20,
267
- }),
268
- focus: boolean("Filter by whether the Goal is the organization Focus Goal."),
269
- facet: string("Current Goal workspace facet.", {
270
- enum: ["agent_advancing", "needs_attention", "waiting_focus", "waiting_external", "ready_for_acceptance", "closed"],
271
- maxLength: 40,
272
- }),
273
- limit: number("Maximum owned Goals to return.", 1, 100),
274
- });
275
- case "goal.context":
276
- return schema({ goal: string("Goal UUID returned by rudder_goal_list.", { maxLength: 200 }) }, ["goal"]);
277
- case "goal.progress":
278
- return schema({
279
- goal,
280
- summary: string("Plain-language progress, observed change, or named blocker."),
281
- activityKind: string("Progress classification.", { enum: ["progress", "evidence", "bottleneck"], maxLength: 30 }),
282
- evidenceRefs: {
283
- type: "array",
284
- description: "URI-like references to artifacts, measurements, or other supporting evidence.",
285
- minItems: 1,
286
- maxItems: 100,
287
- items: string("URI-like evidence reference.", { maxLength: 8_192 }),
288
- },
289
- idempotencyKey: string("Stable key for safe retry.", { maxLength: 500 }),
290
- }, ["goal", "summary", "evidenceRefs", "idempotencyKey"]);
291
- case "goal.checkpoint":
292
- return schema({
293
- goal,
294
- summary: string("Plain-language bounded-run checkpoint summary."),
295
- evidenceRefs: {
296
- type: "array",
297
- description: "URI-like references to artifacts, measurements, or other supporting evidence.",
298
- maxItems: 100,
299
- items: string("URI-like evidence reference.", { maxLength: 8_192 }),
300
- },
301
- expectedPlanRevision: number("Plan revision read before this checkpoint.", 1, 1_000_000_000),
302
- plan: {
303
- type: "object",
304
- description: "Optional complete next Plan revision; omit when the current Plan remains valid.",
305
- additionalProperties: false,
306
- properties: {
307
- summary: string("Plan summary."),
308
- hypotheses: { type: "array", maxItems: 1000, items: {} },
309
- selectedPaths: { type: "array", maxItems: 1000, items: {} },
310
- rejectedPaths: { type: "array", maxItems: 1000, items: {} },
311
- sequencing: { type: "array", maxItems: 1000, items: {} },
312
- budgetAllocations: { type: "object", additionalProperties: true },
313
- invalidationConditions: { type: "array", maxItems: 1000, items: {} },
314
- },
315
- required: ["summary"],
316
- },
317
- continuation: {
318
- type: "object",
319
- additionalProperties: false,
320
- properties: {
321
- kind: string("Continuation policy.", { enum: ["commitment", "wait", "decision", "verification"] }),
322
- summary: string("What should happen next or what is awaited."),
323
- wakeCondition: { oneOf: [{ type: "string", minLength: 1 }, { type: "null" }] },
324
- },
325
- required: ["kind", "summary"],
326
- },
327
- idempotencyKey: string("Stable key for safe retry.", { maxLength: 500 }),
328
- }, ["goal", "summary", "evidenceRefs", "expectedPlanRevision", "continuation", "idempotencyKey"]);
329
- case "goal.change.propose":
330
- return schema({
331
- goal,
332
- contractRevision: number("Current Goal contract revision.", 1, 1_000_000_000),
333
- afterContract: {
334
- type: "object",
335
- description: "Only the Goal contract fields that should change.",
336
- additionalProperties: false,
337
- minProperties: 1,
338
- properties: {
339
- outcomeStatement: string("Proposed result-oriented outcome."),
340
- objectiveMode: string("Proposed objective mode.", {
341
- enum: ["target", "maximize", "maintain", "decide"],
342
- maxLength: 20,
343
- }),
344
- criteria: {
345
- type: "array",
346
- minItems: 1,
347
- maxItems: 100,
348
- items: schema({
349
- id: string("Stable criterion id.", { maxLength: 500 }),
350
- label: string("Plain-language success criterion."),
351
- evaluator: string("Criterion evaluator.", {
352
- enum: ["artifact", "metric", "policy", "human"],
353
- maxLength: 20,
354
- }),
355
- evidenceRequirements: {
356
- type: "array",
357
- maxItems: 100,
358
- items: string("URI-like required evidence reference.", { maxLength: 8_192 }),
359
- },
360
- }, ["id", "label", "evaluator"]),
361
- },
362
- autonomyEnvelope: { type: "object", additionalProperties: true },
363
- humanAuthorities: { type: "object", additionalProperties: true },
364
- evaluationPolicy: { type: "object", additionalProperties: true },
365
- actionDeadline: {
366
- description: "Proposed ISO-8601 action deadline, or null to clear it.",
367
- oneOf: [{ type: "string", format: "date-time" }, { type: "null" }],
368
- },
369
- evaluationDeadline: {
370
- description: "Proposed ISO-8601 evaluation deadline, or null to clear it.",
371
- oneOf: [{ type: "string", format: "date-time" }, { type: "null" }],
372
- },
373
- },
374
- },
375
- rationale: string("Why the current contract should change and what evidence invalidated it."),
376
- evidenceRefs: {
377
- type: "array",
378
- description: "URI-like references supporting the proposed change.",
379
- maxItems: 100,
380
- items: string("URI-like evidence reference.", { maxLength: 8_192 }),
381
- },
382
- idempotencyKey: string("Stable key for safe retry.", { maxLength: 500 }),
383
- }, ["goal", "contractRevision", "afterContract", "rationale", "idempotencyKey"]);
384
- case "goal.result.propose":
385
- return schema({
386
- goal,
387
- contractRevision: number("Current Goal contract revision.", 1, 1_000_000_000),
388
- criteria: {
389
- type: "array",
390
- description: "Criterion outcomes for the current contract revision.",
391
- minItems: 1,
392
- maxItems: 100,
393
- items: schema({
394
- id: string("Criterion id from the Goal Runtime Context.", { maxLength: 500 }),
395
- status: string("Observed criterion status.", { enum: ["met", "unmet", "breached", "unknown"], maxLength: 20 }),
396
- }, ["id", "status"]),
397
- },
398
- evidenceRefs: {
399
- type: "array",
400
- description: "URI-like references supporting the proposed result.",
401
- minItems: 1,
402
- maxItems: 100,
403
- items: string("URI-like evidence reference.", { maxLength: 8_192 }),
404
- },
405
- resultValue: {
406
- description: "Optional measured result value.",
407
- oneOf: [{ type: "string", maxLength: 100_000 }, { type: "number" }, { type: "boolean" }],
408
- },
409
- decision: string("Optional decision reached for decide-mode Goals."),
410
- resultPayload: { type: "object", description: "Optional structured result details.", additionalProperties: true },
411
- riskSummary: string("Known risks, limitations, or remaining gaps."),
412
- idempotencyKey: string("Stable key for safe retry.", { maxLength: 500 }),
413
- }, ["goal", "contractRevision", "criteria", "evidenceRefs", "riskSummary", "idempotencyKey"]);
414
- case "issue.create":
415
- return schema({
416
- title: string("Issue title.", { maxLength: 500 }),
417
- description: string("Issue description.", { maxLength: 500_000 }),
418
- status: string("Issue status.", { maxLength: 100 }),
419
- priority: string("Issue priority.", { maxLength: 100 }),
420
- assigneeAgentId: string("Assignee agent id or reference.", { maxLength: 200 }),
421
- projectId: string("Project id or reference.", { maxLength: 200 }),
422
- goalId: string("Goal id or reference.", { maxLength: 200 }),
423
- parentId: string("Parent issue id or reference.", { maxLength: 200 }),
424
- requestDepth: number("Requested issue depth.", 0, 10_000),
425
- billingCode: string("Billing code.", { maxLength: 200 }),
426
- labelIds: strings("Issue label ids.", 100),
427
- }, ["title"]);
428
- case "issue.list":
429
- return schema({
430
- status: string("Comma-separated issue statuses.", { maxLength: 500 }),
431
- assigneeAgentId: string("Assignee agent id or reference.", { maxLength: 200 }),
432
- projectId: string("Project id or reference.", { maxLength: 200 }),
433
- });
434
- case "issue.get":
435
- return schema({ issue }, ["issue"]);
436
- case "issue.search":
437
- return schema({
438
- query: string("Non-empty server-side issue search query.", { maxLength: 2_000 }),
439
- status: string("Comma-separated issue statuses.", { maxLength: 500 }),
440
- assigneeAgentId: string("Assignee agent id or reference.", { maxLength: 200 }),
441
- projectId: string("Project id or reference.", { maxLength: 200 }),
442
- }, ["query"]);
443
- case "issue.context":
444
- return schema({ issue, wakeCommentId: string("Wake comment id or short reference.", { maxLength: 200 }) }, ["issue"]);
445
- case "issue.checkout":
446
- return schema({ issue, expectedStatuses: string("Comma-separated allowed prior statuses.", { maxLength: 500 }) }, ["issue"]);
447
- case "issue.comment":
448
- return {
449
- ...schema({ issue, body, comment: body, images, reopen: boolean("Reopen the issue while commenting.") }, ["issue"]),
450
- anyOf: [{ required: ["body"] }, { required: ["comment"] }],
451
- };
452
- case "issue.comments.list":
453
- return schema({
454
- issue,
455
- after: string("Return comments after this comment id or short reference.", { maxLength: 200 }),
456
- order: string("Comment order.", { enum: ["asc", "desc"], maxLength: 10 }),
457
- }, ["issue"]);
458
- case "issue.comments.get":
459
- return schema({ issue, comment: string("Comment id or short reference.", { maxLength: 200 }) }, ["issue", "comment"]);
460
- case "issue.update":
461
- return schema({
462
- issue,
463
- title: string("Issue title.", { maxLength: 500 }),
464
- description: string("Issue description.", { maxLength: 500_000 }),
465
- status: string("New issue status.", { maxLength: 100 }),
466
- priority: string("New issue priority.", { maxLength: 100 }),
467
- assigneeAgentId: string("Assignee agent id or reference.", { maxLength: 200 }),
468
- projectId: string("Project id or reference.", { maxLength: 200 }),
469
- goalId: string("Goal id or reference.", { maxLength: 200 }),
470
- parentId: string("Parent issue id or reference.", { maxLength: 200 }),
471
- requestDepth: string("Requested issue depth.", { maxLength: 30 }),
472
- billingCode: string("Billing code.", { maxLength: 200 }),
473
- hiddenAt: string("Hidden timestamp.", { maxLength: 100 }),
474
- comment: body,
475
- body,
476
- images,
477
- }, ["issue"]);
478
- case "issue.review":
479
- return {
480
- ...schema({
481
- issue,
482
- decision: string("Structured review decision.", { enum: ["approve", "request_changes", "needs_followup", "blocked"], maxLength: 30 }),
483
- comment: body,
484
- body,
485
- }, ["issue", "decision"]),
486
- anyOf: [{ required: ["comment"] }, { required: ["body"] }],
487
- };
488
- case "issue.commit":
489
- return schema({
490
- issue,
491
- sha: string("Git commit SHA.", { maxLength: 100 }),
492
- message: string("Commit subject or status message.", { maxLength: 2_000 }),
493
- branch: string("Git branch name.", { maxLength: 500 }),
494
- repoPath: string("Repository path.", { maxLength: 8_192 }),
495
- workspacePath: string("Workspace path.", { maxLength: 8_192 }),
496
- count: number("Number of commits represented.", 1, 10_000),
497
- }, ["issue", "sha", "message"]);
498
- case "issue.done":
499
- case "issue.block":
500
- return {
501
- ...schema({ issue, comment: body, body, images }, ["issue"]),
502
- anyOf: [{ required: ["comment"] }, { required: ["body"] }],
503
- };
504
- case "project.get":
505
- return schema({ project }, ["project"]);
506
- case "project.create":
507
- return schema({
508
- name: string("Project name.", { maxLength: 300 }),
509
- description: string("Project description.", { maxLength: 500_000 }),
510
- status: string("Project status.", { maxLength: 100 }),
511
- goalId: string("Goal id or reference.", { maxLength: 200 }),
512
- goalIds: strings("Goal ids.", 100),
513
- leadAgentId: string("Lead agent id or reference.", { maxLength: 200 }),
514
- targetDate: string("Target date.", { maxLength: 100 }),
515
- color: string("Display color.", { maxLength: 100 }),
516
- }, ["name"]);
517
- case "project.update":
518
- return schema({
519
- project,
520
- name: string("Project name.", { maxLength: 300 }),
521
- description: string("Project description.", { maxLength: 500_000 }),
522
- status: string("Project status.", { maxLength: 100 }),
523
- goalId: string("Goal id or reference.", { maxLength: 200 }),
524
- goalIds: strings("Goal ids.", 100),
525
- leadAgentId: string("Lead agent id or reference.", { maxLength: 200 }),
526
- targetDate: string("Target date.", { maxLength: 100 }),
527
- color: string("Display color.", { maxLength: 100 }),
528
- archivedAt: string("Archive timestamp.", { maxLength: 100 }),
529
- }, ["project"]);
530
- case "user.activity":
531
- return schema({
532
- user: string("User id, reference, or self.", { maxLength: 200 }),
533
- since: string("Activity start timestamp.", { maxLength: 100 }),
534
- until: string("Activity end timestamp.", { maxLength: 100 }),
535
- include: string("Comma-separated optional sections.", { maxLength: 500 }),
536
- relatedAgentId: string("Related agent id.", { maxLength: 200 }),
537
- projectId: string("Project id.", { maxLength: 200 }),
538
- issueId: string("Issue id.", { maxLength: 200 }),
539
- limit: number("Page size.", 1, 100),
540
- cursor,
541
- });
542
- case "library.file.list":
543
- return schema({
544
- directory: string("Library-relative directory path.", { maxLength: 8_192 }),
545
- path: string("Compatibility alias for directory.", { maxLength: 8_192 }),
546
- });
547
- case "library.file.get":
548
- case "library.file.ref":
549
- case "library.file.link":
550
- return schema({ path: string("Library-relative file path.", { maxLength: 8_192 }) }, ["path"]);
551
- case "library.file.put":
552
- return {
553
- ...schema({
554
- path: string("Library-relative file path.", { maxLength: 8_192 }),
555
- body: string("Direct file content.", { maxLength: 1_000_000 }),
556
- content: string("Compatibility alias for body.", { maxLength: 1_000_000 }),
557
- }, ["path"]),
558
- anyOf: [{ required: ["body"] }, { required: ["content"] }],
559
- };
560
- case "approval.get":
561
- case "approval.issues":
562
- return schema({ approval }, ["approval"]);
563
- case "approval.comment":
564
- return {
565
- ...schema({ approval, body, comment: body }, ["approval"]),
566
- anyOf: [{ required: ["body"] }, { required: ["comment"] }],
567
- };
568
- case "skill.get":
569
- return schema({ skill: string("Organization skill id.", { maxLength: 200 }) }, ["skill"]);
570
- case "skill.file":
571
- return schema({
572
- skill: string("Organization skill id.", { maxLength: 200 }),
573
- path: string("Skill package file path.", { maxLength: 8_192 }),
574
- }, ["skill"]);
575
- case "skill.import":
576
- return schema({ source: string("Local path, URL, or repository reference.", { maxLength: 8_192 }) }, ["source"]);
577
- case "skill.scan-local":
578
- return schema({ roots: string("Comma-separated local roots.", { maxLength: 20_000 }) });
579
- case "skill.scan-projects":
580
- return schema({
581
- projectIds: string("Comma-separated project ids.", { maxLength: 20_000 }),
582
- workspaceIds: string("Comma-separated workspace ids.", { maxLength: 20_000 }),
583
- });
584
- case "automation.list":
585
- return schema({
586
- status: string("Automation status filter.", { maxLength: 100 }),
587
- assigneeAgentId: string("Assignee agent id.", { maxLength: 200 }),
588
- projectId: string("Project id.", { maxLength: 200 }),
589
- outputMode: string("Output mode filter.", { maxLength: 100 }),
590
- });
591
- case "automation.get":
592
- case "automation.triggers.list":
593
- case "automation.enable":
594
- case "automation.disable":
595
- return schema({ automation }, ["automation"]);
596
- case "automation.runs":
597
- return schema({ automation, limit: number("Maximum run rows.", 1, 100) }, ["automation"]);
598
- case "automation.triggers.create":
599
- return schema({
600
- automation,
601
- payload,
602
- kind: string("Trigger kind.", { maxLength: 100 }),
603
- label: string("Trigger label.", { maxLength: 300 }),
604
- enabled: boolean("Create the trigger enabled."),
605
- disabled: boolean("Create the trigger disabled."),
606
- cronExpression: string("Cron expression.", { maxLength: 500 }),
607
- timezone: string("IANA timezone.", { maxLength: 200 }),
608
- signingMode: string("Webhook signing mode.", { maxLength: 100 }),
609
- replayWindowSec: string("Webhook replay window in seconds.", { maxLength: 30 }),
610
- }, ["automation"]);
611
- case "automation.triggers.update":
612
- return schema({
613
- trigger,
614
- payload,
615
- label: string("Trigger label.", { maxLength: 300 }),
616
- enabled: boolean("Enable the trigger."),
617
- disabled: boolean("Disable the trigger."),
618
- cronExpression: string("Cron expression.", { maxLength: 500 }),
619
- timezone: string("IANA timezone.", { maxLength: 200 }),
620
- signingMode: string("Webhook signing mode.", { maxLength: 100 }),
621
- replayWindowSec: string("Webhook replay window in seconds.", { maxLength: 30 }),
622
- }, ["trigger"]);
623
- case "automation.triggers.delete":
624
- case "automation.triggers.rotate-secret":
625
- return schema({ trigger }, ["trigger"]);
626
- case "automation.create":
627
- return schema({
628
- payload,
629
- title: string("Automation title.", { maxLength: 500 }),
630
- instructions: string("Automation instructions.", { maxLength: 500_000 }),
631
- description: string("Compatibility alias for instructions.", { maxLength: 500_000 }),
632
- assigneeAgentId: string("Assignee agent id.", { maxLength: 200 }),
633
- projectId: string("Project id.", { maxLength: 200 }),
634
- goalId: string("Goal id.", { maxLength: 200 }),
635
- parentIssueId: string("Parent issue id.", { maxLength: 200 }),
636
- priority: string("Issue priority.", { maxLength: 100 }),
637
- status: string("Automation status.", { maxLength: 100 }),
638
- outputMode: string("Automation output mode.", { maxLength: 100 }),
639
- concurrencyPolicy: string("Concurrency policy.", { maxLength: 100 }),
640
- catchUpPolicy: string("Catch-up policy.", { maxLength: 100 }),
641
- notifyOnIssueCreated: boolean("Notify when an issue is created."),
642
- });
643
- case "automation.update":
644
- return schema({
645
- automation,
646
- payload,
647
- title: string("Automation title.", { maxLength: 500 }),
648
- instructions: string("Automation instructions.", { maxLength: 500_000 }),
649
- description: string("Compatibility alias for instructions.", { maxLength: 500_000 }),
650
- assigneeAgentId: string("Assignee agent id.", { maxLength: 200 }),
651
- projectId: string("Project id.", { maxLength: 200 }),
652
- goalId: string("Goal id.", { maxLength: 200 }),
653
- parentIssueId: string("Parent issue id.", { maxLength: 200 }),
654
- priority: string("Issue priority.", { maxLength: 100 }),
655
- status: string("Automation status.", { maxLength: 100 }),
656
- outputMode: string("Automation output mode.", { maxLength: 100 }),
657
- concurrencyPolicy: string("Concurrency policy.", { maxLength: 100 }),
658
- catchUpPolicy: string("Catch-up policy.", { maxLength: 100 }),
659
- notifyOnIssueCreated: boolean("Notify when an issue is created."),
660
- }, ["automation"]);
661
- case "automation.run":
662
- return schema({
663
- automation,
664
- triggerId: string("Trigger id.", { maxLength: 200 }),
665
- payload,
666
- idempotencyKey: string("Idempotency key.", { maxLength: 500 }),
667
- source: string("Invocation source.", { maxLength: 500 }),
668
- }, ["automation"]);
669
- case "chat.list":
670
- return schema({
671
- status: string("Chat status filter.", { maxLength: 100 }),
672
- query: string("Optional chat query.", { maxLength: 2_000 }),
673
- limit: number("Maximum chat rows.", 1, 100),
674
- });
675
- case "chat.search":
676
- return schema({
677
- query: string("Non-empty chat search query.", { maxLength: 2_000 }),
678
- status: string("Chat status filter.", { maxLength: 100 }),
679
- scope: string("Search scope.", { maxLength: 100 }),
680
- limit: number("Maximum matches.", 1, 100),
681
- snippetChars: number("Maximum snippet characters.", 100, 10_000),
682
- }, ["query"]);
683
- case "chat.get":
684
- case "chat.archive":
685
- return schema({ chat }, ["chat"]);
686
- case "chat.messages":
687
- return schema({
688
- chat,
689
- limit: number("Maximum message rows.", 1, 100),
690
- cursor,
691
- maxOutputChars: number("Maximum output characters per row.", 100, 20_000),
692
- includeTranscript: boolean("Include bounded transcript data."),
693
- includeOutput: boolean("Compatibility alias for includeTranscript."),
694
- }, ["chat"]);
695
- case "chat.transcript":
696
- return schema({
697
- chat,
698
- limit: number("Maximum transcript rows.", 1, 100),
699
- cursor,
700
- maxOutputChars: number("Maximum output characters per row.", 100, 20_000),
701
- }, ["chat"]);
702
- case "chat.read":
703
- return schema({
704
- chat,
705
- limit: number("Maximum message rows.", 1, 100),
706
- turnLimit: number("Maximum transcript turns.", 1, 100),
707
- cursor,
708
- maxOutputChars: number("Maximum output characters per row.", 100, 20_000),
709
- includeTranscript: boolean("Include bounded transcript data."),
710
- includeOutput: boolean("Compatibility alias for includeTranscript."),
711
- }, ["chat"]);
712
- case "chat.create":
713
- return schema({
714
- body: string("Initial agent-authored chat message.", { maxLength: 500_000 }),
715
- payload,
716
- title: string("Chat title.", { maxLength: 500 }),
717
- summary: string("Chat summary.", { maxLength: 10_000 }),
718
- preferredAgentId: string("Preferred responding agent id.", { maxLength: 200 }),
719
- issueCreationMode: string("Issue creation mode.", { maxLength: 100 }),
720
- planMode: boolean("Start the chat in plan mode."),
721
- }, ["body"]);
722
- case "chat.send":
723
- return schema({
724
- chat,
725
- body: string("Agent-authored chat message.", { maxLength: 500_000 }),
726
- editUserMessageId: string("User message id to edit.", { maxLength: 200 }),
727
- }, ["chat", "body"]);
728
- case "runs.list":
729
- return schema({
730
- updatedAfter: string("Only runs updated after this timestamp.", { maxLength: 100 }),
731
- runIdPrefix: string("Run id prefix filter.", { maxLength: 200 }),
732
- relatedAgentId: string("Agent id filter.", { maxLength: 200 }),
733
- status: string("Run status filter.", { maxLength: 100 }),
734
- runtime: string("Runtime type filter.", { maxLength: 100 }),
735
- issueId: string("Linked issue id filter.", { maxLength: 200 }),
736
- usedSkill: string("Used skill filter.", { maxLength: 500 }),
737
- loadedSkill: string("Loaded skill filter.", { maxLength: 500 }),
738
- createdBefore: string("Only runs created before this timestamp.", { maxLength: 100 }),
739
- cursor,
740
- limit: number("Summary page size.", 1, 100),
741
- });
742
- case "runs.by-skill":
743
- return schema({
744
- skill: string("Skill key or display name.", { maxLength: 500 }),
745
- evidence: string("Skill evidence type.", { enum: ["used", "loaded"], maxLength: 20 }),
746
- relatedAgentId: string("Agent id filter.", { maxLength: 200 }),
747
- status: string("Run status filter.", { maxLength: 100 }),
748
- runtime: string("Runtime type filter.", { maxLength: 100 }),
749
- issueId: string("Linked issue id filter.", { maxLength: 200 }),
750
- createdBefore: string("Only runs created before this timestamp.", { maxLength: 100 }),
751
- cursor,
752
- limit: number("Summary page size.", 1, 100),
753
- }, ["skill"]);
754
- case "runs.get":
755
- case "runs.cancel":
756
- case "runs.retry":
757
- return schema({ run }, ["run"]);
758
- case "runs.events":
759
- return schema({
760
- run,
761
- cursor,
762
- afterSeq: number("Legacy sequence-only cursor.", 0, 10_000_000),
763
- limit: number("Event page size.", 1, 500),
764
- maxChars: number("Maximum preview characters per event.", 100, 20_000),
765
- }, ["run"]);
766
- case "runs.log":
767
- return schema({
768
- run,
769
- maxChars: number("Maximum displayed log characters.", 100, 100_000),
770
- offset: number("Byte offset for ranged read.", 0, 1_000_000_000),
771
- limitBytes: number("Maximum bytes for ranged read.", 1, 1_000_000),
772
- }, ["run"]);
773
- case "runs.transcript":
774
- return schema({
775
- run,
776
- errorsOnly: boolean("Return only error rows."),
777
- aroundError: string("Transcript error step id.", { maxLength: 200 }),
778
- contextTurns: number("Turns around the selected error.", 1, 20),
779
- cursor,
780
- turnLimit: number("Maximum turns.", 1, 100),
781
- chronological: boolean("Return oldest-first rows."),
782
- narrative: boolean("Use narrative row formatting."),
783
- maxChars: number("Maximum output characters per row.", 100, 20_000),
784
- includeOutput: boolean("Include clipped row output."),
785
- }, ["run"]);
786
- case "runs.errors":
787
- return schema({
788
- run,
789
- cursor,
790
- maxChars: number("Maximum output characters per error.", 100, 20_000),
791
- }, ["run"]);
792
- default:
793
- throw new Error(`Missing exact Rudder MCP input schema for capability: ${id}`);
794
- }
4
+ const descriptor = RUDDER_MCP_TOOL_DESCRIPTORS.find((tool) => tool.capabilityId === id);
5
+ if (!descriptor)
6
+ throw new Error(`Missing exact Rudder MCP input schema for capability: ${id}`);
7
+ return descriptor.inputSchema;
795
8
  }
796
- export const RUDDER_MCP_CANONICAL_TOOL_DEFINITIONS = RUDDER_MCP_TOOL_DESCRIPTORS.map((tool) => ({
797
- ...tool,
798
- inputSchema: rudderMcpInputSchemaForCapability(tool.capabilityId),
799
- }));
9
+ export const RUDDER_MCP_CANONICAL_TOOL_DEFINITIONS = RUDDER_MCP_TOOL_DESCRIPTORS;
800
10
  export function rudderMcpSemanticToolContract(tool) {
801
11
  return {
802
12
  name: tool.name,
803
- description: `${tool.description} Mutating: ${tool.mutating ? "yes" : "no"}. Runtime identity and authorization are injected by the Rudder-managed MCP server and are not accepted as tool input. Org context: ${tool.requiresOrgId ? "required from runtime env" : "not required by this tool"}. Agent context: ${tool.requiresAgentId ? "required from runtime env" : "runtime env when available"}. Run attribution: ${tool.attachesRunIdWhenAvailable ? "attached from runtime env when available" : "not attached"}.`,
13
+ description: tool.semanticDescription ?? tool.description,
804
14
  inputSchema: tool.inputSchema,
805
- annotations: {
806
- title: tool.description.split(/[.;]/u, 1)[0] || tool.name,
807
- readOnlyHint: !tool.mutating,
808
- destructiveHint: RUDDER_MCP_DESTRUCTIVE_CAPABILITY_IDS.has(tool.capabilityId),
809
- idempotentHint: !tool.mutating
810
- || tool.capabilityId === "browser.reload"
811
- || tool.capabilityId === "browser.close",
812
- ...(RUDDER_MCP_OPEN_WORLD_CAPABILITY_IDS.has(tool.capabilityId) ? { openWorldHint: true } : {}),
813
- },
15
+ annotations: tool.annotations,
814
16
  };
815
17
  }
816
18
  export const RUDDER_MCP_CANONICAL_TOOL_CONTRACTS = RUDDER_MCP_CANONICAL_TOOL_DEFINITIONS