@defai.digital/mcp-server 13.0.3

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 (178) hide show
  1. package/LICENSE +214 -0
  2. package/dist/bin.d.ts +3 -0
  3. package/dist/bin.d.ts.map +1 -0
  4. package/dist/bin.js +7 -0
  5. package/dist/bin.js.map +1 -0
  6. package/dist/bootstrap.d.ts +89 -0
  7. package/dist/bootstrap.d.ts.map +1 -0
  8. package/dist/bootstrap.js +161 -0
  9. package/dist/bootstrap.js.map +1 -0
  10. package/dist/index.d.ts +10 -0
  11. package/dist/index.d.ts.map +1 -0
  12. package/dist/index.js +17 -0
  13. package/dist/index.js.map +1 -0
  14. package/dist/middleware/rate-limiter.d.ts +136 -0
  15. package/dist/middleware/rate-limiter.d.ts.map +1 -0
  16. package/dist/middleware/rate-limiter.js +262 -0
  17. package/dist/middleware/rate-limiter.js.map +1 -0
  18. package/dist/prompts/agent-guide.d.ts +16 -0
  19. package/dist/prompts/agent-guide.d.ts.map +1 -0
  20. package/dist/prompts/agent-guide.js +391 -0
  21. package/dist/prompts/agent-guide.js.map +1 -0
  22. package/dist/prompts/explain-workflow.d.ts +15 -0
  23. package/dist/prompts/explain-workflow.d.ts.map +1 -0
  24. package/dist/prompts/explain-workflow.js +157 -0
  25. package/dist/prompts/explain-workflow.js.map +1 -0
  26. package/dist/prompts/index.d.ts +39 -0
  27. package/dist/prompts/index.d.ts.map +1 -0
  28. package/dist/prompts/index.js +83 -0
  29. package/dist/prompts/index.js.map +1 -0
  30. package/dist/prompts/review-changes.d.ts +15 -0
  31. package/dist/prompts/review-changes.d.ts.map +1 -0
  32. package/dist/prompts/review-changes.js +102 -0
  33. package/dist/prompts/review-changes.js.map +1 -0
  34. package/dist/prompts/troubleshoot-session.d.ts +15 -0
  35. package/dist/prompts/troubleshoot-session.d.ts.map +1 -0
  36. package/dist/prompts/troubleshoot-session.js +156 -0
  37. package/dist/prompts/troubleshoot-session.js.map +1 -0
  38. package/dist/registry-accessor.d.ts +83 -0
  39. package/dist/registry-accessor.d.ts.map +1 -0
  40. package/dist/registry-accessor.js +153 -0
  41. package/dist/registry-accessor.js.map +1 -0
  42. package/dist/resources/agents.d.ts +40 -0
  43. package/dist/resources/agents.d.ts.map +1 -0
  44. package/dist/resources/agents.js +123 -0
  45. package/dist/resources/agents.js.map +1 -0
  46. package/dist/resources/config.d.ts +57 -0
  47. package/dist/resources/config.d.ts.map +1 -0
  48. package/dist/resources/config.js +222 -0
  49. package/dist/resources/config.js.map +1 -0
  50. package/dist/resources/index.d.ts +38 -0
  51. package/dist/resources/index.d.ts.map +1 -0
  52. package/dist/resources/index.js +132 -0
  53. package/dist/resources/index.js.map +1 -0
  54. package/dist/resources/policies.d.ts +40 -0
  55. package/dist/resources/policies.d.ts.map +1 -0
  56. package/dist/resources/policies.js +122 -0
  57. package/dist/resources/policies.js.map +1 -0
  58. package/dist/resources/sessions.d.ts +30 -0
  59. package/dist/resources/sessions.d.ts.map +1 -0
  60. package/dist/resources/sessions.js +64 -0
  61. package/dist/resources/sessions.js.map +1 -0
  62. package/dist/resources/workflows.d.ts +40 -0
  63. package/dist/resources/workflows.d.ts.map +1 -0
  64. package/dist/resources/workflows.js +143 -0
  65. package/dist/resources/workflows.js.map +1 -0
  66. package/dist/schema-registry.d.ts +23 -0
  67. package/dist/schema-registry.d.ts.map +1 -0
  68. package/dist/schema-registry.js +225 -0
  69. package/dist/schema-registry.js.map +1 -0
  70. package/dist/server.d.ts +63 -0
  71. package/dist/server.d.ts.map +1 -0
  72. package/dist/server.js +393 -0
  73. package/dist/server.js.map +1 -0
  74. package/dist/session-accessor.d.ts +23 -0
  75. package/dist/session-accessor.d.ts.map +1 -0
  76. package/dist/session-accessor.js +39 -0
  77. package/dist/session-accessor.js.map +1 -0
  78. package/dist/shared-registry.d.ts +23 -0
  79. package/dist/shared-registry.d.ts.map +1 -0
  80. package/dist/shared-registry.js +235 -0
  81. package/dist/shared-registry.js.map +1 -0
  82. package/dist/stdio.d.ts +6 -0
  83. package/dist/stdio.d.ts.map +1 -0
  84. package/dist/stdio.js +152 -0
  85. package/dist/stdio.js.map +1 -0
  86. package/dist/tool-namespacing.d.ts +28 -0
  87. package/dist/tool-namespacing.d.ts.map +1 -0
  88. package/dist/tool-namespacing.js +80 -0
  89. package/dist/tool-namespacing.js.map +1 -0
  90. package/dist/tools/ability.d.ts +55 -0
  91. package/dist/tools/ability.d.ts.map +1 -0
  92. package/dist/tools/ability.js +560 -0
  93. package/dist/tools/ability.js.map +1 -0
  94. package/dist/tools/agent.d.ts +73 -0
  95. package/dist/tools/agent.d.ts.map +1 -0
  96. package/dist/tools/agent.js +895 -0
  97. package/dist/tools/agent.js.map +1 -0
  98. package/dist/tools/config.d.ts +36 -0
  99. package/dist/tools/config.d.ts.map +1 -0
  100. package/dist/tools/config.js +265 -0
  101. package/dist/tools/config.js.map +1 -0
  102. package/dist/tools/design.d.ts +42 -0
  103. package/dist/tools/design.d.ts.map +1 -0
  104. package/dist/tools/design.js +736 -0
  105. package/dist/tools/design.js.map +1 -0
  106. package/dist/tools/discuss.d.ts +40 -0
  107. package/dist/tools/discuss.d.ts.map +1 -0
  108. package/dist/tools/discuss.js +331 -0
  109. package/dist/tools/discuss.js.map +1 -0
  110. package/dist/tools/file-system.d.ts +63 -0
  111. package/dist/tools/file-system.d.ts.map +1 -0
  112. package/dist/tools/file-system.js +513 -0
  113. package/dist/tools/file-system.js.map +1 -0
  114. package/dist/tools/guard.d.ts +29 -0
  115. package/dist/tools/guard.d.ts.map +1 -0
  116. package/dist/tools/guard.js +311 -0
  117. package/dist/tools/guard.js.map +1 -0
  118. package/dist/tools/index.d.ts +35 -0
  119. package/dist/tools/index.d.ts.map +1 -0
  120. package/dist/tools/index.js +178 -0
  121. package/dist/tools/index.js.map +1 -0
  122. package/dist/tools/memory.d.ts +101 -0
  123. package/dist/tools/memory.d.ts.map +1 -0
  124. package/dist/tools/memory.js +704 -0
  125. package/dist/tools/memory.js.map +1 -0
  126. package/dist/tools/orchestration.d.ts +58 -0
  127. package/dist/tools/orchestration.d.ts.map +1 -0
  128. package/dist/tools/orchestration.js +714 -0
  129. package/dist/tools/orchestration.js.map +1 -0
  130. package/dist/tools/review.d.ts +40 -0
  131. package/dist/tools/review.d.ts.map +1 -0
  132. package/dist/tools/review.js +319 -0
  133. package/dist/tools/review.js.map +1 -0
  134. package/dist/tools/scaffold.d.ts +27 -0
  135. package/dist/tools/scaffold.d.ts.map +1 -0
  136. package/dist/tools/scaffold.js +495 -0
  137. package/dist/tools/scaffold.js.map +1 -0
  138. package/dist/tools/session.d.ts +75 -0
  139. package/dist/tools/session.d.ts.map +1 -0
  140. package/dist/tools/session.js +749 -0
  141. package/dist/tools/session.js.map +1 -0
  142. package/dist/tools/telemetry.d.ts +58 -0
  143. package/dist/tools/telemetry.d.ts.map +1 -0
  144. package/dist/tools/telemetry.js +638 -0
  145. package/dist/tools/telemetry.js.map +1 -0
  146. package/dist/tools/trace.d.ts +29 -0
  147. package/dist/tools/trace.d.ts.map +1 -0
  148. package/dist/tools/trace.js +191 -0
  149. package/dist/tools/trace.js.map +1 -0
  150. package/dist/tools/workflow.d.ts +26 -0
  151. package/dist/tools/workflow.d.ts.map +1 -0
  152. package/dist/tools/workflow.js +269 -0
  153. package/dist/tools/workflow.js.map +1 -0
  154. package/dist/trace-wrapper.d.ts +79 -0
  155. package/dist/trace-wrapper.d.ts.map +1 -0
  156. package/dist/trace-wrapper.js +151 -0
  157. package/dist/trace-wrapper.js.map +1 -0
  158. package/dist/types.d.ts +185 -0
  159. package/dist/types.d.ts.map +1 -0
  160. package/dist/types.js +11 -0
  161. package/dist/types.js.map +1 -0
  162. package/dist/utils/artifact-store.d.ts +49 -0
  163. package/dist/utils/artifact-store.d.ts.map +1 -0
  164. package/dist/utils/artifact-store.js +102 -0
  165. package/dist/utils/artifact-store.js.map +1 -0
  166. package/dist/utils/index.d.ts +6 -0
  167. package/dist/utils/index.d.ts.map +1 -0
  168. package/dist/utils/index.js +10 -0
  169. package/dist/utils/index.js.map +1 -0
  170. package/dist/utils/response.d.ts +139 -0
  171. package/dist/utils/response.d.ts.map +1 -0
  172. package/dist/utils/response.js +293 -0
  173. package/dist/utils/response.js.map +1 -0
  174. package/dist/validation.d.ts +223 -0
  175. package/dist/validation.d.ts.map +1 -0
  176. package/dist/validation.js +372 -0
  177. package/dist/validation.js.map +1 -0
  178. package/package.json +67 -0
@@ -0,0 +1,895 @@
1
+ import { LIMIT_AGENTS } from '@defai.digital/contracts';
2
+ import { getAvailableTemplates, createWorkflowFromTemplate, isValidTemplateName, createAgentSelectionService, } from '@defai.digital/agent-domain';
3
+ // Import from registry-accessor to avoid circular dependencies
4
+ import { getSharedRegistry, getSharedExecutor, } from '../registry-accessor.js';
5
+ /**
6
+ * Agent list tool definition
7
+ * INV-MCP-004: Idempotent - read-only operation
8
+ */
9
+ export const agentListTool = {
10
+ name: 'agent_list',
11
+ description: 'List available agents with optional filtering. Read-only, no side effects.',
12
+ inputSchema: {
13
+ type: 'object',
14
+ properties: {
15
+ team: {
16
+ type: 'string',
17
+ description: 'Filter by team name',
18
+ },
19
+ enabled: {
20
+ type: 'boolean',
21
+ description: 'Filter by enabled status',
22
+ },
23
+ limit: {
24
+ type: 'number',
25
+ description: 'Maximum number of agents to return',
26
+ default: LIMIT_AGENTS,
27
+ },
28
+ },
29
+ },
30
+ outputSchema: {
31
+ type: 'object',
32
+ properties: {
33
+ agents: {
34
+ type: 'array',
35
+ description: 'List of agent summaries',
36
+ items: {
37
+ type: 'object',
38
+ properties: {
39
+ agentId: { type: 'string' },
40
+ displayName: { type: 'string' },
41
+ description: { type: 'string' },
42
+ team: { type: 'string' },
43
+ enabled: { type: 'boolean' },
44
+ capabilities: { type: 'array', items: { type: 'string' } },
45
+ },
46
+ },
47
+ },
48
+ total: { type: 'number', description: 'Total number of agents' },
49
+ },
50
+ required: ['agents', 'total'],
51
+ },
52
+ idempotent: true,
53
+ };
54
+ /**
55
+ * Agent run tool definition
56
+ * INV-MCP-004: Non-idempotent - creates new execution each call
57
+ * INV-MCP-002: Side effects - executes agent workflow, may modify state
58
+ */
59
+ export const agentRunTool = {
60
+ name: 'agent_run',
61
+ description: 'Execute an agent with the given input. SIDE EFFECTS: Creates new agent execution, may modify session state and emit trace events.',
62
+ inputSchema: {
63
+ type: 'object',
64
+ properties: {
65
+ agentId: {
66
+ type: 'string',
67
+ description: 'The ID of the agent to run',
68
+ },
69
+ input: {
70
+ type: 'object',
71
+ description: 'Input data for the agent',
72
+ },
73
+ sessionId: {
74
+ type: 'string',
75
+ description: 'Optional session ID to associate with the run',
76
+ },
77
+ },
78
+ required: ['agentId'],
79
+ },
80
+ outputSchema: {
81
+ type: 'object',
82
+ properties: {
83
+ success: { type: 'boolean', description: 'Whether execution succeeded' },
84
+ agentId: { type: 'string', description: 'Agent that was executed' },
85
+ sessionId: { type: 'string', description: 'Session ID (if provided)' },
86
+ output: { type: 'object', description: 'Agent output data' },
87
+ stepResults: {
88
+ type: 'array',
89
+ description: 'Results from each step',
90
+ items: {
91
+ type: 'object',
92
+ properties: {
93
+ stepId: { type: 'string' },
94
+ success: { type: 'boolean' },
95
+ durationMs: { type: 'number' },
96
+ },
97
+ },
98
+ },
99
+ totalDurationMs: { type: 'number', description: 'Total execution time' },
100
+ error: { type: 'object', description: 'Error details if failed' },
101
+ },
102
+ required: ['success', 'agentId', 'totalDurationMs'],
103
+ },
104
+ idempotent: false,
105
+ retryableErrors: ['AGENT_EXECUTION_FAILED'],
106
+ };
107
+ /**
108
+ * Agent get tool definition
109
+ * INV-MCP-004: Idempotent - read-only operation
110
+ */
111
+ export const agentGetTool = {
112
+ name: 'agent_get',
113
+ description: 'Get detailed information about a specific agent. Read-only, no side effects.',
114
+ inputSchema: {
115
+ type: 'object',
116
+ properties: {
117
+ agentId: {
118
+ type: 'string',
119
+ description: 'The ID of the agent to retrieve',
120
+ },
121
+ },
122
+ required: ['agentId'],
123
+ },
124
+ outputSchema: {
125
+ type: 'object',
126
+ properties: {
127
+ agentId: { type: 'string' },
128
+ displayName: { type: 'string' },
129
+ version: { type: 'string' },
130
+ description: { type: 'string' },
131
+ role: { type: 'string' },
132
+ expertise: { type: 'string' },
133
+ capabilities: { type: 'array', items: { type: 'string' } },
134
+ team: { type: 'string' },
135
+ tags: { type: 'array', items: { type: 'string' } },
136
+ enabled: { type: 'boolean' },
137
+ workflow: {
138
+ type: 'array',
139
+ items: {
140
+ type: 'object',
141
+ properties: {
142
+ stepId: { type: 'string' },
143
+ name: { type: 'string' },
144
+ type: { type: 'string' },
145
+ },
146
+ },
147
+ },
148
+ orchestration: {
149
+ type: 'object',
150
+ properties: {
151
+ maxDelegationDepth: { type: 'number' },
152
+ canReadWorkspaces: { type: 'boolean' },
153
+ canWriteToShared: { type: 'boolean' },
154
+ },
155
+ },
156
+ },
157
+ required: ['agentId', 'description', 'enabled'],
158
+ },
159
+ idempotent: true,
160
+ };
161
+ /**
162
+ * Agent register tool definition
163
+ * INV-MCP-004: Non-idempotent - creates new agent profile
164
+ * INV-MCP-002: Side effects - modifies agent registry
165
+ */
166
+ export const agentRegisterTool = {
167
+ name: 'agent_register',
168
+ description: 'Register a new agent profile. SIDE EFFECTS: Creates new agent in registry. Fails if agent already exists.',
169
+ inputSchema: {
170
+ type: 'object',
171
+ properties: {
172
+ agentId: {
173
+ type: 'string',
174
+ description: 'Unique identifier for the agent (must start with letter, alphanumeric/dash/underscore only)',
175
+ },
176
+ description: {
177
+ type: 'string',
178
+ description: 'Description of the agent capabilities',
179
+ },
180
+ displayName: {
181
+ type: 'string',
182
+ description: 'Human-readable display name',
183
+ },
184
+ systemPrompt: {
185
+ type: 'string',
186
+ description: 'System prompt for the agent (instructions for how to behave)',
187
+ },
188
+ team: {
189
+ type: 'string',
190
+ description: 'Team the agent belongs to',
191
+ },
192
+ capabilities: {
193
+ type: 'array',
194
+ items: { type: 'string' },
195
+ description: 'List of agent capabilities',
196
+ },
197
+ tags: {
198
+ type: 'array',
199
+ items: { type: 'string' },
200
+ description: 'Tags for categorization',
201
+ },
202
+ workflowTemplate: {
203
+ type: 'string',
204
+ enum: ['prompt-response', 'research', 'code-review', 'multi-step', 'delegate-chain', 'agent-selection'],
205
+ description: 'Use a predefined workflow template instead of custom workflow steps',
206
+ },
207
+ workflow: {
208
+ type: 'array',
209
+ items: {
210
+ type: 'object',
211
+ properties: {
212
+ stepId: { type: 'string', description: 'Unique step identifier' },
213
+ name: { type: 'string', description: 'Step name' },
214
+ type: {
215
+ type: 'string',
216
+ enum: ['prompt', 'tool', 'conditional', 'loop', 'parallel', 'delegate'],
217
+ description: 'Step type'
218
+ },
219
+ config: { type: 'object', description: 'Step configuration' },
220
+ },
221
+ required: ['stepId', 'name', 'type'],
222
+ },
223
+ description: 'Workflow steps to execute when agent runs (ignored if workflowTemplate is provided)',
224
+ },
225
+ enabled: {
226
+ type: 'boolean',
227
+ description: 'Whether the agent is enabled',
228
+ default: true,
229
+ },
230
+ },
231
+ required: ['agentId', 'description'],
232
+ },
233
+ outputSchema: {
234
+ type: 'object',
235
+ properties: {
236
+ registered: { type: 'boolean', description: 'Whether registration succeeded' },
237
+ agentId: { type: 'string', description: 'Registered agent ID' },
238
+ message: { type: 'string', description: 'Result message' },
239
+ createdAt: { type: 'string', description: 'Creation timestamp' },
240
+ },
241
+ required: ['registered', 'agentId', 'message'],
242
+ },
243
+ idempotent: false,
244
+ };
245
+ /**
246
+ * Agent remove tool definition
247
+ * INV-MCP-004: Idempotent - removing non-existent agent returns removed=false
248
+ * INV-MCP-002: Side effects - deletes agent from registry
249
+ */
250
+ export const agentRemoveTool = {
251
+ name: 'agent_remove',
252
+ description: 'Remove an agent from the registry. SIDE EFFECTS: Deletes agent profile. Idempotent - removing non-existent agent returns removed=false.',
253
+ inputSchema: {
254
+ type: 'object',
255
+ properties: {
256
+ agentId: {
257
+ type: 'string',
258
+ description: 'The ID of the agent to remove',
259
+ },
260
+ },
261
+ required: ['agentId'],
262
+ },
263
+ outputSchema: {
264
+ type: 'object',
265
+ properties: {
266
+ removed: { type: 'boolean', description: 'Whether agent was removed' },
267
+ agentId: { type: 'string', description: 'Agent ID' },
268
+ message: { type: 'string', description: 'Result message' },
269
+ },
270
+ required: ['removed', 'agentId', 'message'],
271
+ },
272
+ idempotent: true,
273
+ };
274
+ /**
275
+ * Handler for agent_list tool
276
+ */
277
+ export const handleAgentList = async (args) => {
278
+ const team = args.team;
279
+ const enabled = args.enabled;
280
+ const limit = args.limit ?? 50;
281
+ try {
282
+ // Build filter only with defined properties
283
+ const filter = {};
284
+ if (team !== undefined) {
285
+ filter.team = team;
286
+ }
287
+ if (enabled !== undefined) {
288
+ filter.enabled = enabled;
289
+ }
290
+ const registry = await getSharedRegistry();
291
+ const agents = await registry.list(Object.keys(filter).length > 0 ? filter : undefined);
292
+ const agentSummaries = agents.slice(0, limit).map((a) => ({
293
+ agentId: a.agentId,
294
+ displayName: a.displayName,
295
+ description: a.description,
296
+ team: a.team,
297
+ enabled: a.enabled,
298
+ capabilities: a.capabilities,
299
+ }));
300
+ return {
301
+ content: [
302
+ {
303
+ type: 'text',
304
+ text: JSON.stringify({
305
+ agents: agentSummaries,
306
+ total: agents.length,
307
+ }, null, 2),
308
+ },
309
+ ],
310
+ };
311
+ }
312
+ catch (error) {
313
+ const message = error instanceof Error ? error.message : 'Unknown error';
314
+ return {
315
+ content: [
316
+ {
317
+ type: 'text',
318
+ text: JSON.stringify({
319
+ error: 'AGENT_LIST_FAILED',
320
+ message,
321
+ }),
322
+ },
323
+ ],
324
+ isError: true,
325
+ };
326
+ }
327
+ };
328
+ /**
329
+ * Handler for agent_run tool
330
+ */
331
+ export const handleAgentRun = async (args) => {
332
+ const agentId = args.agentId;
333
+ const input = args.input ?? {};
334
+ const sessionId = args.sessionId;
335
+ const startTime = Date.now();
336
+ try {
337
+ // Check if agent exists
338
+ const registry = await getSharedRegistry();
339
+ const agent = await registry.get(agentId);
340
+ if (agent === undefined) {
341
+ return {
342
+ content: [
343
+ {
344
+ type: 'text',
345
+ text: JSON.stringify({
346
+ success: false,
347
+ agentId,
348
+ error: {
349
+ code: 'AGENT_NOT_FOUND',
350
+ message: `Agent "${agentId}" not found`,
351
+ },
352
+ totalDurationMs: Date.now() - startTime,
353
+ }),
354
+ },
355
+ ],
356
+ isError: true,
357
+ };
358
+ }
359
+ // Execute agent - note: execute takes (agentId, input, options)
360
+ const executor = await getSharedExecutor();
361
+ const result = await executor.execute(agentId, input, {
362
+ sessionId,
363
+ });
364
+ return {
365
+ content: [
366
+ {
367
+ type: 'text',
368
+ text: JSON.stringify({
369
+ success: result.success,
370
+ agentId: result.agentId,
371
+ sessionId,
372
+ output: result.output,
373
+ stepResults: result.stepResults?.map((s) => ({
374
+ stepId: s.stepId,
375
+ success: s.success,
376
+ durationMs: s.durationMs,
377
+ })),
378
+ totalDurationMs: result.totalDurationMs,
379
+ error: result.error,
380
+ }, null, 2),
381
+ },
382
+ ],
383
+ isError: !result.success,
384
+ };
385
+ }
386
+ catch (error) {
387
+ const message = error instanceof Error ? error.message : 'Unknown error';
388
+ return {
389
+ content: [
390
+ {
391
+ type: 'text',
392
+ text: JSON.stringify({
393
+ success: false,
394
+ agentId,
395
+ error: {
396
+ code: 'AGENT_EXECUTION_FAILED',
397
+ message,
398
+ },
399
+ totalDurationMs: Date.now() - startTime,
400
+ }),
401
+ },
402
+ ],
403
+ isError: true,
404
+ };
405
+ }
406
+ };
407
+ /**
408
+ * Handler for agent_get tool
409
+ */
410
+ export const handleAgentGet = async (args) => {
411
+ const agentId = args.agentId;
412
+ try {
413
+ const registry = await getSharedRegistry();
414
+ const agent = await registry.get(agentId);
415
+ if (agent === undefined) {
416
+ return {
417
+ content: [
418
+ {
419
+ type: 'text',
420
+ text: JSON.stringify({
421
+ error: 'AGENT_NOT_FOUND',
422
+ message: `Agent "${agentId}" not found`,
423
+ }),
424
+ },
425
+ ],
426
+ isError: true,
427
+ };
428
+ }
429
+ return {
430
+ content: [
431
+ {
432
+ type: 'text',
433
+ text: JSON.stringify({
434
+ agentId: agent.agentId,
435
+ displayName: agent.displayName,
436
+ version: agent.version,
437
+ description: agent.description,
438
+ role: agent.role,
439
+ expertise: agent.expertise,
440
+ capabilities: agent.capabilities,
441
+ team: agent.team,
442
+ tags: agent.tags,
443
+ enabled: agent.enabled,
444
+ workflow: agent.workflow?.map((s) => ({
445
+ stepId: s.stepId,
446
+ name: s.name,
447
+ type: s.type,
448
+ })),
449
+ orchestration: agent.orchestration
450
+ ? {
451
+ maxDelegationDepth: agent.orchestration.maxDelegationDepth,
452
+ canReadWorkspaces: agent.orchestration.canReadWorkspaces,
453
+ canWriteToShared: agent.orchestration.canWriteToShared,
454
+ }
455
+ : undefined,
456
+ }, null, 2),
457
+ },
458
+ ],
459
+ };
460
+ }
461
+ catch (error) {
462
+ const message = error instanceof Error ? error.message : 'Unknown error';
463
+ return {
464
+ content: [
465
+ {
466
+ type: 'text',
467
+ text: JSON.stringify({
468
+ error: 'AGENT_GET_FAILED',
469
+ message,
470
+ }),
471
+ },
472
+ ],
473
+ isError: true,
474
+ };
475
+ }
476
+ };
477
+ /**
478
+ * Handler for agent_register tool
479
+ */
480
+ export const handleAgentRegister = async (args) => {
481
+ const agentId = args.agentId;
482
+ const description = args.description;
483
+ const displayName = args.displayName;
484
+ const systemPrompt = args.systemPrompt;
485
+ const team = args.team;
486
+ const capabilities = args.capabilities;
487
+ const tags = args.tags;
488
+ const workflowTemplate = args.workflowTemplate;
489
+ const workflow = args.workflow;
490
+ const enabled = args.enabled ?? true;
491
+ try {
492
+ const registry = await getSharedRegistry();
493
+ // Check if agent already exists
494
+ const existing = await registry.get(agentId);
495
+ if (existing !== undefined) {
496
+ return {
497
+ content: [
498
+ {
499
+ type: 'text',
500
+ text: JSON.stringify({
501
+ error: 'AGENT_ALREADY_EXISTS',
502
+ message: `Agent "${agentId}" already exists`,
503
+ }),
504
+ },
505
+ ],
506
+ isError: true,
507
+ };
508
+ }
509
+ // Validate agentId format
510
+ const agentIdPattern = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
511
+ if (!agentIdPattern.test(agentId)) {
512
+ return {
513
+ content: [
514
+ {
515
+ type: 'text',
516
+ text: JSON.stringify({
517
+ error: 'INVALID_AGENT_ID',
518
+ message: 'Agent ID must start with letter and contain only alphanumeric, dash, underscore',
519
+ }),
520
+ },
521
+ ],
522
+ isError: true,
523
+ };
524
+ }
525
+ // Resolve workflow: template takes precedence over custom workflow
526
+ let resolvedWorkflow;
527
+ if (workflowTemplate !== undefined) {
528
+ // Validate template name
529
+ if (!isValidTemplateName(workflowTemplate)) {
530
+ const availableTemplates = getAvailableTemplates();
531
+ return {
532
+ content: [
533
+ {
534
+ type: 'text',
535
+ text: JSON.stringify({
536
+ error: 'INVALID_WORKFLOW_TEMPLATE',
537
+ message: `Unknown workflow template "${workflowTemplate}". Available templates: ${availableTemplates.join(', ')}`,
538
+ }),
539
+ },
540
+ ],
541
+ isError: true,
542
+ };
543
+ }
544
+ // Create workflow from template
545
+ const templateWorkflow = createWorkflowFromTemplate(workflowTemplate);
546
+ if (templateWorkflow !== undefined) {
547
+ resolvedWorkflow = templateWorkflow.map(step => ({
548
+ stepId: step.stepId,
549
+ name: step.name,
550
+ type: step.type,
551
+ config: step.config ?? {},
552
+ }));
553
+ }
554
+ }
555
+ else if (workflow !== undefined && workflow.length > 0) {
556
+ // Use custom workflow
557
+ resolvedWorkflow = workflow.map(step => ({
558
+ stepId: step.stepId,
559
+ name: step.name,
560
+ type: step.type,
561
+ config: step.config ?? {},
562
+ }));
563
+ }
564
+ // Register the agent with resolved workflow
565
+ const profile = {
566
+ agentId,
567
+ description,
568
+ displayName,
569
+ systemPrompt,
570
+ team,
571
+ capabilities: capabilities ?? [],
572
+ tags: tags ?? [],
573
+ workflow: resolvedWorkflow,
574
+ enabled,
575
+ };
576
+ await registry.register(profile);
577
+ // Build response message
578
+ const responseMessage = workflowTemplate !== undefined
579
+ ? `Agent "${agentId}" registered successfully with "${workflowTemplate}" workflow template`
580
+ : resolvedWorkflow !== undefined
581
+ ? `Agent "${agentId}" registered successfully with ${resolvedWorkflow.length} workflow step(s)`
582
+ : `Agent "${agentId}" registered successfully`;
583
+ return {
584
+ content: [
585
+ {
586
+ type: 'text',
587
+ text: JSON.stringify({
588
+ registered: true,
589
+ agentId,
590
+ message: responseMessage,
591
+ workflowTemplate: workflowTemplate ?? null,
592
+ workflowSteps: resolvedWorkflow?.length ?? 0,
593
+ createdAt: new Date().toISOString(),
594
+ }, null, 2),
595
+ },
596
+ ],
597
+ };
598
+ }
599
+ catch (error) {
600
+ const message = error instanceof Error ? error.message : 'Unknown error';
601
+ return {
602
+ content: [
603
+ {
604
+ type: 'text',
605
+ text: JSON.stringify({
606
+ error: 'AGENT_REGISTER_FAILED',
607
+ message,
608
+ }),
609
+ },
610
+ ],
611
+ isError: true,
612
+ };
613
+ }
614
+ };
615
+ /**
616
+ * Handler for agent_remove tool
617
+ */
618
+ export const handleAgentRemove = async (args) => {
619
+ const agentId = args.agentId;
620
+ try {
621
+ const registry = await getSharedRegistry();
622
+ // Check if agent exists
623
+ const existing = await registry.get(agentId);
624
+ if (existing === undefined) {
625
+ return {
626
+ content: [
627
+ {
628
+ type: 'text',
629
+ text: JSON.stringify({
630
+ removed: false,
631
+ agentId,
632
+ message: `Agent "${agentId}" not found`,
633
+ }),
634
+ },
635
+ ],
636
+ };
637
+ }
638
+ // Remove the agent
639
+ await registry.remove(agentId);
640
+ return {
641
+ content: [
642
+ {
643
+ type: 'text',
644
+ text: JSON.stringify({
645
+ removed: true,
646
+ agentId,
647
+ message: `Agent "${agentId}" removed successfully`,
648
+ }, null, 2),
649
+ },
650
+ ],
651
+ };
652
+ }
653
+ catch (error) {
654
+ const message = error instanceof Error ? error.message : 'Unknown error';
655
+ return {
656
+ content: [
657
+ {
658
+ type: 'text',
659
+ text: JSON.stringify({
660
+ error: 'AGENT_REMOVE_FAILED',
661
+ message,
662
+ }),
663
+ },
664
+ ],
665
+ isError: true,
666
+ };
667
+ }
668
+ };
669
+ // ============================================================================
670
+ // Agent Recommendation Tool (INV-AGT-SEL-001 through INV-AGT-SEL-006)
671
+ // ============================================================================
672
+ /**
673
+ * Agent recommend tool definition
674
+ * INV-MCP-004: Idempotent - read-only operation
675
+ * INV-AGT-SEL-001: Selection is deterministic
676
+ * INV-AGT-SEL-004: Always returns at least one result
677
+ */
678
+ export const agentRecommendTool = {
679
+ name: 'agent_recommend',
680
+ description: 'Recommend the best agent for a given task. Returns ranked matches with confidence scores. Use this to auto-route tasks to appropriate agents. Read-only, no side effects.',
681
+ inputSchema: {
682
+ type: 'object',
683
+ properties: {
684
+ task: {
685
+ type: 'string',
686
+ description: 'Task description to match against agents (max 2000 chars)',
687
+ },
688
+ team: {
689
+ type: 'string',
690
+ description: 'Filter by team name',
691
+ },
692
+ requiredCapabilities: {
693
+ type: 'array',
694
+ items: { type: 'string' },
695
+ description: 'Required capabilities the agent must have',
696
+ },
697
+ excludeAgents: {
698
+ type: 'array',
699
+ items: { type: 'string' },
700
+ description: 'Agent IDs to exclude from matching',
701
+ },
702
+ maxResults: {
703
+ type: 'number',
704
+ description: 'Maximum number of recommendations (default 3)',
705
+ default: 3,
706
+ },
707
+ },
708
+ required: ['task'],
709
+ },
710
+ outputSchema: {
711
+ type: 'object',
712
+ properties: {
713
+ recommended: { type: 'string', description: 'Best matching agent ID' },
714
+ confidence: { type: 'number', description: 'Match confidence 0-1' },
715
+ reason: { type: 'string', description: 'Why this agent was selected' },
716
+ alternatives: {
717
+ type: 'array',
718
+ description: 'Alternative agent matches',
719
+ items: {
720
+ type: 'object',
721
+ properties: {
722
+ agentId: { type: 'string' },
723
+ confidence: { type: 'number' },
724
+ reason: { type: 'string' },
725
+ },
726
+ },
727
+ },
728
+ },
729
+ required: ['recommended', 'confidence', 'reason', 'alternatives'],
730
+ },
731
+ idempotent: true,
732
+ };
733
+ /**
734
+ * Handler for agent_recommend tool
735
+ * Implements INV-AGT-SEL-001 through INV-AGT-SEL-006
736
+ * Uses AgentSelectionService domain module for proper separation
737
+ */
738
+ export const handleAgentRecommend = async (args) => {
739
+ const task = args.task;
740
+ const team = args.team;
741
+ const requiredCapabilities = args.requiredCapabilities;
742
+ const excludeAgents = args.excludeAgents;
743
+ const maxResults = args.maxResults ?? 3;
744
+ try {
745
+ const registry = await getSharedRegistry();
746
+ // Use domain service for agent selection (INV-AGT-SEL-001 through INV-AGT-SEL-006)
747
+ const selectionService = createAgentSelectionService(registry);
748
+ // INV-AGT-SEL-001: Selection is deterministic (same input = same output)
749
+ const result = await selectionService.recommend({
750
+ task,
751
+ team,
752
+ requiredCapabilities,
753
+ excludeAgents,
754
+ maxResults,
755
+ });
756
+ // INV-AGT-SEL-004: Always returns at least one result (service handles fallback)
757
+ return {
758
+ content: [
759
+ {
760
+ type: 'text',
761
+ text: JSON.stringify({
762
+ recommended: result.recommended,
763
+ confidence: result.confidence,
764
+ reason: result.reason,
765
+ alternatives: result.alternatives.map(alt => ({
766
+ agentId: alt.agentId,
767
+ confidence: alt.confidence,
768
+ })),
769
+ }, null, 2),
770
+ },
771
+ ],
772
+ };
773
+ }
774
+ catch (error) {
775
+ const message = error instanceof Error ? error.message : 'Unknown error';
776
+ return {
777
+ content: [
778
+ {
779
+ type: 'text',
780
+ text: JSON.stringify({
781
+ error: 'AGENT_RECOMMEND_FAILED',
782
+ message,
783
+ }),
784
+ },
785
+ ],
786
+ isError: true,
787
+ };
788
+ }
789
+ };
790
+ // ============================================================================
791
+ // Agent Capabilities Tool
792
+ // ============================================================================
793
+ /**
794
+ * Agent capabilities tool definition
795
+ * INV-MCP-004: Idempotent - read-only operation
796
+ */
797
+ export const agentCapabilitiesTool = {
798
+ name: 'agent_capabilities',
799
+ description: 'List all unique capabilities across agents with mapping to agent IDs. Use for capability-based routing and discovery. Read-only, no side effects.',
800
+ inputSchema: {
801
+ type: 'object',
802
+ properties: {
803
+ category: {
804
+ type: 'string',
805
+ enum: ['orchestrator', 'implementer', 'reviewer', 'specialist', 'generalist'],
806
+ description: 'Filter by agent category',
807
+ },
808
+ includeDisabled: {
809
+ type: 'boolean',
810
+ description: 'Include disabled agents (default false)',
811
+ default: false,
812
+ },
813
+ },
814
+ },
815
+ outputSchema: {
816
+ type: 'object',
817
+ properties: {
818
+ capabilities: {
819
+ type: 'array',
820
+ items: { type: 'string' },
821
+ description: 'All unique capabilities',
822
+ },
823
+ agentsByCapability: {
824
+ type: 'object',
825
+ description: 'Capability → agent IDs mapping',
826
+ additionalProperties: {
827
+ type: 'array',
828
+ items: { type: 'string' },
829
+ },
830
+ },
831
+ capabilitiesByAgent: {
832
+ type: 'object',
833
+ description: 'Agent ID → capabilities mapping',
834
+ additionalProperties: {
835
+ type: 'array',
836
+ items: { type: 'string' },
837
+ },
838
+ },
839
+ categoriesByAgent: {
840
+ type: 'object',
841
+ description: 'Agent ID → category mapping',
842
+ additionalProperties: { type: 'string' },
843
+ },
844
+ },
845
+ required: ['capabilities', 'agentsByCapability', 'capabilitiesByAgent'],
846
+ },
847
+ idempotent: true,
848
+ };
849
+ /**
850
+ * Handler for agent_capabilities tool
851
+ * Uses AgentSelectionService domain module for proper separation
852
+ */
853
+ export const handleAgentCapabilities = async (args) => {
854
+ const category = args.category;
855
+ const includeDisabled = args.includeDisabled ?? false;
856
+ try {
857
+ const registry = await getSharedRegistry();
858
+ // Use domain service for capabilities discovery
859
+ const selectionService = createAgentSelectionService(registry);
860
+ // Delegate to domain service
861
+ const result = await selectionService.getCapabilities({
862
+ category,
863
+ includeDisabled,
864
+ });
865
+ return {
866
+ content: [
867
+ {
868
+ type: 'text',
869
+ text: JSON.stringify({
870
+ capabilities: result.capabilities,
871
+ agentsByCapability: result.agentsByCapability,
872
+ capabilitiesByAgent: result.capabilitiesByAgent,
873
+ categoriesByAgent: result.categoriesByAgent,
874
+ }, null, 2),
875
+ },
876
+ ],
877
+ };
878
+ }
879
+ catch (error) {
880
+ const message = error instanceof Error ? error.message : 'Unknown error';
881
+ return {
882
+ content: [
883
+ {
884
+ type: 'text',
885
+ text: JSON.stringify({
886
+ error: 'AGENT_CAPABILITIES_FAILED',
887
+ message,
888
+ }),
889
+ },
890
+ ],
891
+ isError: true,
892
+ };
893
+ }
894
+ };
895
+ //# sourceMappingURL=agent.js.map