wolfpack-mcp 1.0.47 → 1.0.49
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/dist/agentBuilderTools.js +797 -0
- package/dist/client.js +155 -0
- package/dist/index.js +132 -31
- package/package.json +1 -1
|
@@ -0,0 +1,797 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent builder MCP tool definitions and handlers.
|
|
3
|
+
* Registered only when the API key has the `agent_builder` capability.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
export const AGENT_BUILDER_TOOLS = [
|
|
7
|
+
// ─── Group 1: Agent CRUD ─────────────────────────────────────────────────
|
|
8
|
+
{
|
|
9
|
+
name: 'list_agents',
|
|
10
|
+
description: 'List all agents in the organisation. Returns name, status, template, and assigned projects.',
|
|
11
|
+
inputSchema: { type: 'object', properties: {} },
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
name: 'get_agent',
|
|
15
|
+
description: 'Get full details for an agent including config, instructions, LLM model, and linked skills.',
|
|
16
|
+
inputSchema: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
20
|
+
},
|
|
21
|
+
required: ['agent_id'],
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
name: 'create_agent',
|
|
26
|
+
description: 'Create a new agent from a template. Use list_agent_templates to see available templates.',
|
|
27
|
+
inputSchema: {
|
|
28
|
+
type: 'object',
|
|
29
|
+
properties: {
|
|
30
|
+
template_id: { type: 'string', description: 'Template ID to create the agent from' },
|
|
31
|
+
name: { type: 'string', description: 'Display name for the agent' },
|
|
32
|
+
config: { type: 'object', description: 'Optional agent-specific configuration' },
|
|
33
|
+
},
|
|
34
|
+
required: ['template_id', 'name'],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'update_agent',
|
|
39
|
+
description: "Update an agent's config, instructions, or LLM model. Omit fields to leave them unchanged.",
|
|
40
|
+
inputSchema: {
|
|
41
|
+
type: 'object',
|
|
42
|
+
properties: {
|
|
43
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
44
|
+
name: { type: 'string', description: 'Updated display name' },
|
|
45
|
+
instructions: {
|
|
46
|
+
type: 'string',
|
|
47
|
+
description: 'Agent-specific instructions (supplements template instructions). Set to null to clear.',
|
|
48
|
+
},
|
|
49
|
+
llm_provider: {
|
|
50
|
+
type: 'string',
|
|
51
|
+
description: 'LLM provider ID (e.g. "anthropic"). Set to null for default.',
|
|
52
|
+
},
|
|
53
|
+
llm_model: {
|
|
54
|
+
type: 'string',
|
|
55
|
+
description: 'LLM model ID (e.g. "claude-sonnet-4-6"). Set to null for family auto-select.',
|
|
56
|
+
},
|
|
57
|
+
llm_family: {
|
|
58
|
+
type: 'string',
|
|
59
|
+
description: 'LLM model family (e.g. "sonnet"). Agent auto-upgrades to latest in family.',
|
|
60
|
+
},
|
|
61
|
+
scheduling_enabled: { type: 'boolean', description: 'Whether scheduled tasks are enabled' },
|
|
62
|
+
},
|
|
63
|
+
required: ['agent_id'],
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
// ─── Group 2: Project Assignment ─────────────────────────────────────────
|
|
67
|
+
{
|
|
68
|
+
name: 'list_agent_projects',
|
|
69
|
+
description: 'List projects assigned to an agent.',
|
|
70
|
+
inputSchema: {
|
|
71
|
+
type: 'object',
|
|
72
|
+
properties: {
|
|
73
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
74
|
+
},
|
|
75
|
+
required: ['agent_id'],
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
name: 'assign_agent_to_project',
|
|
80
|
+
description: 'Assign an agent to a project by slug.',
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: 'object',
|
|
83
|
+
properties: {
|
|
84
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
85
|
+
project_slug: { type: 'string', description: 'Project slug to assign the agent to' },
|
|
86
|
+
},
|
|
87
|
+
required: ['agent_id', 'project_slug'],
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
name: 'remove_agent_from_project',
|
|
92
|
+
description: 'Remove an agent from a project.',
|
|
93
|
+
inputSchema: {
|
|
94
|
+
type: 'object',
|
|
95
|
+
properties: {
|
|
96
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
97
|
+
project_slug: { type: 'string', description: 'Project slug to remove the agent from' },
|
|
98
|
+
},
|
|
99
|
+
required: ['agent_id', 'project_slug'],
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
// ─── Group 3: Sessions ────────────────────────────────────────────────────
|
|
103
|
+
{
|
|
104
|
+
name: 'list_agent_sessions',
|
|
105
|
+
description: 'List sessions for an agent. Filter by status: running, stopped, failed.',
|
|
106
|
+
inputSchema: {
|
|
107
|
+
type: 'object',
|
|
108
|
+
properties: {
|
|
109
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
110
|
+
status: {
|
|
111
|
+
type: 'string',
|
|
112
|
+
enum: ['pending', 'starting', 'running', 'stopping', 'stopped', 'failed'],
|
|
113
|
+
description: 'Filter by session status',
|
|
114
|
+
},
|
|
115
|
+
limit: { type: 'number', description: 'Maximum sessions to return' },
|
|
116
|
+
offset: { type: 'number', description: 'Sessions to skip for pagination' },
|
|
117
|
+
},
|
|
118
|
+
required: ['agent_id'],
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
name: 'get_agent_session',
|
|
123
|
+
description: 'Get session metadata and recent events (last 20). Does NOT include full conversation — use get_agent_session_conversation for that.',
|
|
124
|
+
inputSchema: {
|
|
125
|
+
type: 'object',
|
|
126
|
+
properties: {
|
|
127
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
128
|
+
session_id: { type: 'string', description: 'Session ID' },
|
|
129
|
+
},
|
|
130
|
+
required: ['agent_id', 'session_id'],
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: 'get_agent_session_conversation',
|
|
135
|
+
description: 'Get the full conversation history for a session (paginated). Can be large for long-running sessions.',
|
|
136
|
+
inputSchema: {
|
|
137
|
+
type: 'object',
|
|
138
|
+
properties: {
|
|
139
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
140
|
+
session_id: { type: 'string', description: 'Session ID' },
|
|
141
|
+
limit: { type: 'number', description: 'Turns to return' },
|
|
142
|
+
offset: { type: 'number', description: 'Turns to skip' },
|
|
143
|
+
},
|
|
144
|
+
required: ['agent_id', 'session_id'],
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
name: 'run_agent',
|
|
149
|
+
description: 'Queue an ad-hoc session with an inline prompt. This is async — it returns a queue entry ID immediately. ' +
|
|
150
|
+
'Use list_agent_queue or list_agent_sessions to track progress.',
|
|
151
|
+
inputSchema: {
|
|
152
|
+
type: 'object',
|
|
153
|
+
properties: {
|
|
154
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
155
|
+
prompt: { type: 'string', description: 'What the agent should do' },
|
|
156
|
+
project_slug: { type: 'string', description: 'Project to scope the session to (optional)' },
|
|
157
|
+
},
|
|
158
|
+
required: ['agent_id', 'prompt'],
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: 'stop_agent_session',
|
|
163
|
+
description: 'Stop a running agent session.',
|
|
164
|
+
inputSchema: {
|
|
165
|
+
type: 'object',
|
|
166
|
+
properties: {
|
|
167
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
168
|
+
session_id: { type: 'string', description: 'Session ID to stop' },
|
|
169
|
+
},
|
|
170
|
+
required: ['agent_id', 'session_id'],
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
name: 'resume_agent_session',
|
|
175
|
+
description: 'Resume a completed session with a follow-up prompt. The agent continues with full prior context.',
|
|
176
|
+
inputSchema: {
|
|
177
|
+
type: 'object',
|
|
178
|
+
properties: {
|
|
179
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
180
|
+
session_id: { type: 'string', description: 'Completed session ID to resume' },
|
|
181
|
+
prompt: { type: 'string', description: 'Follow-up prompt for the agent' },
|
|
182
|
+
},
|
|
183
|
+
required: ['agent_id', 'session_id', 'prompt'],
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
// ─── Group 4: Tasks & Queue ───────────────────────────────────────────────
|
|
187
|
+
{
|
|
188
|
+
name: 'list_agent_tasks',
|
|
189
|
+
description: 'List defined tasks for an agent.',
|
|
190
|
+
inputSchema: {
|
|
191
|
+
type: 'object',
|
|
192
|
+
properties: {
|
|
193
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
194
|
+
},
|
|
195
|
+
required: ['agent_id'],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
name: 'get_agent_task',
|
|
200
|
+
description: 'Get details of a specific agent task.',
|
|
201
|
+
inputSchema: {
|
|
202
|
+
type: 'object',
|
|
203
|
+
properties: {
|
|
204
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
205
|
+
task_id: { type: 'string', description: 'Task ID' },
|
|
206
|
+
},
|
|
207
|
+
required: ['agent_id', 'task_id'],
|
|
208
|
+
},
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
name: 'create_agent_task',
|
|
212
|
+
description: 'Create a new task for an agent.',
|
|
213
|
+
inputSchema: {
|
|
214
|
+
type: 'object',
|
|
215
|
+
properties: {
|
|
216
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
217
|
+
name: { type: 'string', description: 'Task name' },
|
|
218
|
+
prompt: { type: 'string', description: 'What the agent should do when this task runs' },
|
|
219
|
+
scheduled_enabled: {
|
|
220
|
+
type: 'boolean',
|
|
221
|
+
description: 'Whether this task is included in scheduled runs (default false)',
|
|
222
|
+
},
|
|
223
|
+
sort_order: {
|
|
224
|
+
type: 'number',
|
|
225
|
+
description: 'Order within scheduled batch (lower = first)',
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
required: ['agent_id', 'name', 'prompt'],
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: 'update_agent_task',
|
|
233
|
+
description: "Update a task's prompt or schedule settings.",
|
|
234
|
+
inputSchema: {
|
|
235
|
+
type: 'object',
|
|
236
|
+
properties: {
|
|
237
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
238
|
+
task_id: { type: 'string', description: 'Task ID' },
|
|
239
|
+
name: { type: 'string', description: 'Updated task name' },
|
|
240
|
+
prompt: { type: 'string', description: 'Updated prompt' },
|
|
241
|
+
scheduled_enabled: { type: 'boolean', description: 'Include in scheduled runs' },
|
|
242
|
+
sort_order: { type: 'number', description: 'Order within scheduled batch' },
|
|
243
|
+
is_active: { type: 'boolean', description: 'Whether this task is active' },
|
|
244
|
+
},
|
|
245
|
+
required: ['agent_id', 'task_id'],
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: 'run_agent_task',
|
|
250
|
+
description: 'Queue a saved task for immediate execution. Async — returns a queue entry ID. ' +
|
|
251
|
+
'Use list_agent_queue to track progress.',
|
|
252
|
+
inputSchema: {
|
|
253
|
+
type: 'object',
|
|
254
|
+
properties: {
|
|
255
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
256
|
+
task_id: { type: 'string', description: 'Task ID to run' },
|
|
257
|
+
project_slug: { type: 'string', description: 'Project to scope the session to (optional)' },
|
|
258
|
+
},
|
|
259
|
+
required: ['agent_id', 'task_id'],
|
|
260
|
+
},
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
name: 'list_agent_queue',
|
|
264
|
+
description: 'List queue entries for an agent. Use this to track progress after run_agent or run_agent_task.',
|
|
265
|
+
inputSchema: {
|
|
266
|
+
type: 'object',
|
|
267
|
+
properties: {
|
|
268
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
269
|
+
status: {
|
|
270
|
+
type: 'string',
|
|
271
|
+
enum: ['queued', 'running', 'completed', 'failed', 'cancelled'],
|
|
272
|
+
description: 'Filter by queue entry status',
|
|
273
|
+
},
|
|
274
|
+
},
|
|
275
|
+
required: ['agent_id'],
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'cancel_queue_entry',
|
|
280
|
+
description: 'Cancel a queued (not yet running) queue entry.',
|
|
281
|
+
inputSchema: {
|
|
282
|
+
type: 'object',
|
|
283
|
+
properties: {
|
|
284
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
285
|
+
entry_id: { type: 'string', description: 'Queue entry ID to cancel' },
|
|
286
|
+
},
|
|
287
|
+
required: ['agent_id', 'entry_id'],
|
|
288
|
+
},
|
|
289
|
+
},
|
|
290
|
+
// ─── Group 5: Skills (authoring) ─────────────────────────────────────────
|
|
291
|
+
{
|
|
292
|
+
name: 'create_skill',
|
|
293
|
+
description: 'Create a new org-level skill. Skills are reusable capability packs agents can load on demand.',
|
|
294
|
+
inputSchema: {
|
|
295
|
+
type: 'object',
|
|
296
|
+
properties: {
|
|
297
|
+
name: {
|
|
298
|
+
type: 'string',
|
|
299
|
+
description: 'Skill name (lowercase letters, numbers, hyphens only, e.g. "deploy-app")',
|
|
300
|
+
},
|
|
301
|
+
description: {
|
|
302
|
+
type: 'string',
|
|
303
|
+
description: 'What the skill does and when to use it (max 1024 chars)',
|
|
304
|
+
},
|
|
305
|
+
content: {
|
|
306
|
+
type: 'string',
|
|
307
|
+
description: 'Instruction body in markdown',
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
required: ['name', 'description', 'content'],
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
{
|
|
314
|
+
name: 'update_skill',
|
|
315
|
+
description: "Update a skill's instructions or description.",
|
|
316
|
+
inputSchema: {
|
|
317
|
+
type: 'object',
|
|
318
|
+
properties: {
|
|
319
|
+
skill_id: { type: 'string', description: 'Skill ID (UUID)' },
|
|
320
|
+
name: { type: 'string', description: 'Updated skill name' },
|
|
321
|
+
description: { type: 'string', description: 'Updated description' },
|
|
322
|
+
content: { type: 'string', description: 'Updated instruction body' },
|
|
323
|
+
},
|
|
324
|
+
required: ['skill_id'],
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
name: 'create_skill_resource',
|
|
329
|
+
description: 'Add a text resource to a skill (script, reference, or asset).',
|
|
330
|
+
inputSchema: {
|
|
331
|
+
type: 'object',
|
|
332
|
+
properties: {
|
|
333
|
+
skill_id: { type: 'string', description: 'Skill ID (UUID)' },
|
|
334
|
+
type: {
|
|
335
|
+
type: 'string',
|
|
336
|
+
enum: ['script', 'reference', 'asset'],
|
|
337
|
+
description: 'Resource type',
|
|
338
|
+
},
|
|
339
|
+
name: { type: 'string', description: 'Resource filename' },
|
|
340
|
+
content: { type: 'string', description: 'Resource text content' },
|
|
341
|
+
mime_type: { type: 'string', description: 'MIME type (optional)' },
|
|
342
|
+
},
|
|
343
|
+
required: ['skill_id', 'type', 'name', 'content'],
|
|
344
|
+
},
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
name: 'update_skill_resource',
|
|
348
|
+
description: "Update a skill resource's content.",
|
|
349
|
+
inputSchema: {
|
|
350
|
+
type: 'object',
|
|
351
|
+
properties: {
|
|
352
|
+
skill_id: { type: 'string', description: 'Skill ID (UUID)' },
|
|
353
|
+
resource_id: { type: 'string', description: 'Resource ID (UUID)' },
|
|
354
|
+
name: { type: 'string', description: 'Updated filename' },
|
|
355
|
+
content: { type: 'string', description: 'Updated text content' },
|
|
356
|
+
mime_type: { type: 'string', description: 'Updated MIME type' },
|
|
357
|
+
},
|
|
358
|
+
required: ['skill_id', 'resource_id'],
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
name: 'set_agent_skills',
|
|
363
|
+
description: 'Replace the full set of skills assigned to an agent. ' +
|
|
364
|
+
'Use list_org_skills to find skill IDs, then pass all desired skill IDs here.',
|
|
365
|
+
inputSchema: {
|
|
366
|
+
type: 'object',
|
|
367
|
+
properties: {
|
|
368
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
369
|
+
skill_ids: {
|
|
370
|
+
type: 'array',
|
|
371
|
+
items: { type: 'string' },
|
|
372
|
+
description: 'Array of skill IDs to assign (replaces all current assignments)',
|
|
373
|
+
},
|
|
374
|
+
},
|
|
375
|
+
required: ['agent_id', 'skill_ids'],
|
|
376
|
+
},
|
|
377
|
+
},
|
|
378
|
+
// ─── Group 5b: Skills (reading org library) ──────────────────────────────
|
|
379
|
+
{
|
|
380
|
+
name: 'list_org_skills',
|
|
381
|
+
description: 'List all skills in the org skill library (org-level + system-level). ' +
|
|
382
|
+
'Returns ID, name, description, and whether the skill is built-in. ' +
|
|
383
|
+
'Use skill IDs with set_agent_skills to assign skills to an agent.',
|
|
384
|
+
inputSchema: { type: 'object', properties: {} },
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
name: 'get_org_skill',
|
|
388
|
+
description: 'Get the full content of an org-level skill by name. ' +
|
|
389
|
+
'Returns instructions, metadata, and a list of attached resources.',
|
|
390
|
+
inputSchema: {
|
|
391
|
+
type: 'object',
|
|
392
|
+
properties: {
|
|
393
|
+
skill_name: {
|
|
394
|
+
type: 'string',
|
|
395
|
+
description: 'The name of the skill to load (e.g. "deploy-app")',
|
|
396
|
+
},
|
|
397
|
+
},
|
|
398
|
+
required: ['skill_name'],
|
|
399
|
+
},
|
|
400
|
+
},
|
|
401
|
+
// ─── Group 6: Secrets ─────────────────────────────────────────────────────
|
|
402
|
+
{
|
|
403
|
+
name: 'list_agent_secrets',
|
|
404
|
+
description: 'List secret names for an agent. Values are never returned.',
|
|
405
|
+
inputSchema: {
|
|
406
|
+
type: 'object',
|
|
407
|
+
properties: {
|
|
408
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
409
|
+
},
|
|
410
|
+
required: ['agent_id'],
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
name: 'set_agent_secret',
|
|
415
|
+
description: 'Create or update a secret for an agent. ' +
|
|
416
|
+
'Name must be uppercase letters, digits, and underscores (e.g. MY_API_KEY).',
|
|
417
|
+
inputSchema: {
|
|
418
|
+
type: 'object',
|
|
419
|
+
properties: {
|
|
420
|
+
agent_id: { type: 'string', description: 'Agent profile ID' },
|
|
421
|
+
name: { type: 'string', description: 'Secret name (e.g. MY_API_KEY)' },
|
|
422
|
+
value: { type: 'string', description: 'Secret value (encrypted at rest)' },
|
|
423
|
+
},
|
|
424
|
+
required: ['agent_id', 'name', 'value'],
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
// ─── Group 7: Discovery ───────────────────────────────────────────────────
|
|
428
|
+
{
|
|
429
|
+
name: 'list_agent_templates',
|
|
430
|
+
description: 'List agent templates available to the organisation. Use template IDs when calling create_agent.',
|
|
431
|
+
inputSchema: { type: 'object', properties: {} },
|
|
432
|
+
},
|
|
433
|
+
{
|
|
434
|
+
name: 'list_llm_models',
|
|
435
|
+
description: 'List LLM providers and models available to the organisation. ' +
|
|
436
|
+
'Use provider and model IDs when calling create_agent or update_agent.',
|
|
437
|
+
inputSchema: { type: 'object', properties: {} },
|
|
438
|
+
},
|
|
439
|
+
];
|
|
440
|
+
// Zod schemas for argument parsing
|
|
441
|
+
const AgentIdSchema = z.object({ agent_id: z.string() });
|
|
442
|
+
const AgentSessionSchema = z.object({ agent_id: z.string(), session_id: z.string() });
|
|
443
|
+
const AgentTaskSchema = z.object({ agent_id: z.string(), task_id: z.string() });
|
|
444
|
+
const SkillIdSchema = z.object({ skill_id: z.string() });
|
|
445
|
+
export async function handleAgentBuilderTool(name, args, client) {
|
|
446
|
+
const text = (t) => JSON.stringify(t, null, 2);
|
|
447
|
+
switch (name) {
|
|
448
|
+
// ─── Agent CRUD ────────────────────────────────────────────────────────
|
|
449
|
+
case 'list_agents': {
|
|
450
|
+
const agents = await client.listAgents();
|
|
451
|
+
return { content: [{ type: 'text', text: text(agents) }] };
|
|
452
|
+
}
|
|
453
|
+
case 'get_agent': {
|
|
454
|
+
const { agent_id } = AgentIdSchema.parse(args);
|
|
455
|
+
const agent = await client.getAgent(agent_id);
|
|
456
|
+
if (!agent)
|
|
457
|
+
return { content: [{ type: 'text', text: 'Agent not found' }] };
|
|
458
|
+
return { content: [{ type: 'text', text: text(agent) }] };
|
|
459
|
+
}
|
|
460
|
+
case 'create_agent': {
|
|
461
|
+
const parsed = z
|
|
462
|
+
.object({
|
|
463
|
+
template_id: z.string(),
|
|
464
|
+
name: z.string(),
|
|
465
|
+
config: z.record(z.unknown()).optional(),
|
|
466
|
+
})
|
|
467
|
+
.parse(args);
|
|
468
|
+
const agent = await client.createAgent({
|
|
469
|
+
templateId: parsed.template_id,
|
|
470
|
+
name: parsed.name,
|
|
471
|
+
config: parsed.config,
|
|
472
|
+
});
|
|
473
|
+
return {
|
|
474
|
+
content: [
|
|
475
|
+
{
|
|
476
|
+
type: 'text',
|
|
477
|
+
text: `Created agent "${agent.user?.comment || agent.userId}"\n\n${text(agent)}`,
|
|
478
|
+
},
|
|
479
|
+
],
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
case 'update_agent': {
|
|
483
|
+
const parsed = z
|
|
484
|
+
.object({
|
|
485
|
+
agent_id: z.string(),
|
|
486
|
+
name: z.string().optional(),
|
|
487
|
+
instructions: z.string().nullable().optional(),
|
|
488
|
+
llm_provider: z.string().nullable().optional(),
|
|
489
|
+
llm_model: z.string().nullable().optional(),
|
|
490
|
+
llm_family: z.string().nullable().optional(),
|
|
491
|
+
scheduling_enabled: z.boolean().optional(),
|
|
492
|
+
})
|
|
493
|
+
.parse(args);
|
|
494
|
+
const { agent_id, ...rest } = parsed;
|
|
495
|
+
const fields = {};
|
|
496
|
+
if (rest.name !== undefined)
|
|
497
|
+
fields.name = rest.name;
|
|
498
|
+
if (rest.instructions !== undefined)
|
|
499
|
+
fields.instructions = rest.instructions;
|
|
500
|
+
if (rest.llm_provider !== undefined)
|
|
501
|
+
fields.llmProvider = rest.llm_provider;
|
|
502
|
+
if (rest.llm_model !== undefined)
|
|
503
|
+
fields.llmModel = rest.llm_model;
|
|
504
|
+
if (rest.llm_family !== undefined)
|
|
505
|
+
fields.llmFamily = rest.llm_family;
|
|
506
|
+
if (rest.scheduling_enabled !== undefined)
|
|
507
|
+
fields.schedulingEnabled = rest.scheduling_enabled;
|
|
508
|
+
const agent = await client.updateAgent(agent_id, fields);
|
|
509
|
+
return { content: [{ type: 'text', text: `Updated agent\n\n${text(agent)}` }] };
|
|
510
|
+
}
|
|
511
|
+
// ─── Project Assignment ─────────────────────────────────────────────────
|
|
512
|
+
case 'list_agent_projects': {
|
|
513
|
+
const { agent_id } = AgentIdSchema.parse(args);
|
|
514
|
+
const projects = await client.listAgentProjects(agent_id);
|
|
515
|
+
return { content: [{ type: 'text', text: text(projects) }] };
|
|
516
|
+
}
|
|
517
|
+
case 'assign_agent_to_project': {
|
|
518
|
+
const parsed = z.object({ agent_id: z.string(), project_slug: z.string() }).parse(args);
|
|
519
|
+
await client.assignAgentToProject(parsed.agent_id, parsed.project_slug);
|
|
520
|
+
return {
|
|
521
|
+
content: [{ type: 'text', text: `Assigned agent to project "${parsed.project_slug}"` }],
|
|
522
|
+
};
|
|
523
|
+
}
|
|
524
|
+
case 'remove_agent_from_project': {
|
|
525
|
+
const parsed = z.object({ agent_id: z.string(), project_slug: z.string() }).parse(args);
|
|
526
|
+
await client.removeAgentFromProject(parsed.agent_id, parsed.project_slug);
|
|
527
|
+
return {
|
|
528
|
+
content: [{ type: 'text', text: `Removed agent from project "${parsed.project_slug}"` }],
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
// ─── Sessions ───────────────────────────────────────────────────────────
|
|
532
|
+
case 'list_agent_sessions': {
|
|
533
|
+
const parsed = z
|
|
534
|
+
.object({
|
|
535
|
+
agent_id: z.string(),
|
|
536
|
+
status: z.string().optional(),
|
|
537
|
+
limit: z.number().optional(),
|
|
538
|
+
offset: z.number().optional(),
|
|
539
|
+
})
|
|
540
|
+
.parse(args);
|
|
541
|
+
const sessions = await client.listAgentSessions(parsed.agent_id, {
|
|
542
|
+
status: parsed.status,
|
|
543
|
+
limit: parsed.limit,
|
|
544
|
+
offset: parsed.offset,
|
|
545
|
+
});
|
|
546
|
+
return { content: [{ type: 'text', text: text(sessions) }] };
|
|
547
|
+
}
|
|
548
|
+
case 'get_agent_session': {
|
|
549
|
+
const { agent_id, session_id } = AgentSessionSchema.parse(args);
|
|
550
|
+
const session = await client.getAgentSession(agent_id, session_id);
|
|
551
|
+
if (!session)
|
|
552
|
+
return { content: [{ type: 'text', text: 'Session not found' }] };
|
|
553
|
+
return { content: [{ type: 'text', text: text(session) }] };
|
|
554
|
+
}
|
|
555
|
+
case 'get_agent_session_conversation': {
|
|
556
|
+
const parsed = z
|
|
557
|
+
.object({
|
|
558
|
+
agent_id: z.string(),
|
|
559
|
+
session_id: z.string(),
|
|
560
|
+
limit: z.number().optional(),
|
|
561
|
+
offset: z.number().optional(),
|
|
562
|
+
})
|
|
563
|
+
.parse(args);
|
|
564
|
+
const conv = await client.getAgentSessionConversation(parsed.agent_id, parsed.session_id, {
|
|
565
|
+
limit: parsed.limit,
|
|
566
|
+
offset: parsed.offset,
|
|
567
|
+
});
|
|
568
|
+
return { content: [{ type: 'text', text: text(conv) }] };
|
|
569
|
+
}
|
|
570
|
+
case 'run_agent': {
|
|
571
|
+
const parsed = z
|
|
572
|
+
.object({ agent_id: z.string(), prompt: z.string(), project_slug: z.string().optional() })
|
|
573
|
+
.parse(args);
|
|
574
|
+
const result = await client.runAgent(parsed.agent_id, parsed.prompt, parsed.project_slug);
|
|
575
|
+
return {
|
|
576
|
+
content: [
|
|
577
|
+
{
|
|
578
|
+
type: 'text',
|
|
579
|
+
text: `Queued session (entry ID: ${result.entryId}, position: ${result.position}, executing: ${result.executing})\n\nUse list_agent_queue or list_agent_sessions to track progress.`,
|
|
580
|
+
},
|
|
581
|
+
],
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
case 'stop_agent_session': {
|
|
585
|
+
const { agent_id, session_id } = AgentSessionSchema.parse(args);
|
|
586
|
+
const session = await client.stopAgentSession(agent_id, session_id);
|
|
587
|
+
return {
|
|
588
|
+
content: [
|
|
589
|
+
{ type: 'text', text: `Stopped session (status: ${session.status})\n\n${text(session)}` },
|
|
590
|
+
],
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
case 'resume_agent_session': {
|
|
594
|
+
const parsed = z
|
|
595
|
+
.object({ agent_id: z.string(), session_id: z.string(), prompt: z.string() })
|
|
596
|
+
.parse(args);
|
|
597
|
+
const session = await client.resumeAgentSession(parsed.agent_id, parsed.session_id, parsed.prompt);
|
|
598
|
+
return { content: [{ type: 'text', text: `Resumed session\n\n${text(session)}` }] };
|
|
599
|
+
}
|
|
600
|
+
// ─── Tasks ──────────────────────────────────────────────────────────────
|
|
601
|
+
case 'list_agent_tasks': {
|
|
602
|
+
const { agent_id } = AgentIdSchema.parse(args);
|
|
603
|
+
const tasks = await client.listAgentTasks(agent_id);
|
|
604
|
+
return { content: [{ type: 'text', text: text(tasks) }] };
|
|
605
|
+
}
|
|
606
|
+
case 'get_agent_task': {
|
|
607
|
+
const { agent_id, task_id } = AgentTaskSchema.parse(args);
|
|
608
|
+
const task = await client.getAgentTask(agent_id, task_id);
|
|
609
|
+
if (!task)
|
|
610
|
+
return { content: [{ type: 'text', text: 'Task not found' }] };
|
|
611
|
+
return { content: [{ type: 'text', text: text(task) }] };
|
|
612
|
+
}
|
|
613
|
+
case 'create_agent_task': {
|
|
614
|
+
const parsed = z
|
|
615
|
+
.object({
|
|
616
|
+
agent_id: z.string(),
|
|
617
|
+
name: z.string(),
|
|
618
|
+
prompt: z.string(),
|
|
619
|
+
scheduled_enabled: z.boolean().optional(),
|
|
620
|
+
sort_order: z.number().optional(),
|
|
621
|
+
})
|
|
622
|
+
.parse(args);
|
|
623
|
+
const task = await client.createAgentTask(parsed.agent_id, {
|
|
624
|
+
name: parsed.name,
|
|
625
|
+
prompt: parsed.prompt,
|
|
626
|
+
scheduledEnabled: parsed.scheduled_enabled,
|
|
627
|
+
sortOrder: parsed.sort_order,
|
|
628
|
+
});
|
|
629
|
+
return { content: [{ type: 'text', text: `Created task "${task.name}"\n\n${text(task)}` }] };
|
|
630
|
+
}
|
|
631
|
+
case 'update_agent_task': {
|
|
632
|
+
const parsed = z
|
|
633
|
+
.object({
|
|
634
|
+
agent_id: z.string(),
|
|
635
|
+
task_id: z.string(),
|
|
636
|
+
name: z.string().optional(),
|
|
637
|
+
prompt: z.string().optional(),
|
|
638
|
+
scheduled_enabled: z.boolean().optional(),
|
|
639
|
+
sort_order: z.number().optional(),
|
|
640
|
+
is_active: z.boolean().optional(),
|
|
641
|
+
})
|
|
642
|
+
.parse(args);
|
|
643
|
+
const fields = {};
|
|
644
|
+
if (parsed.name !== undefined)
|
|
645
|
+
fields.name = parsed.name;
|
|
646
|
+
if (parsed.prompt !== undefined)
|
|
647
|
+
fields.prompt = parsed.prompt;
|
|
648
|
+
if (parsed.scheduled_enabled !== undefined)
|
|
649
|
+
fields.scheduledEnabled = parsed.scheduled_enabled;
|
|
650
|
+
if (parsed.sort_order !== undefined)
|
|
651
|
+
fields.sortOrder = parsed.sort_order;
|
|
652
|
+
if (parsed.is_active !== undefined)
|
|
653
|
+
fields.isActive = parsed.is_active;
|
|
654
|
+
const task = await client.updateAgentTask(parsed.agent_id, parsed.task_id, fields);
|
|
655
|
+
return { content: [{ type: 'text', text: `Updated task\n\n${text(task)}` }] };
|
|
656
|
+
}
|
|
657
|
+
case 'run_agent_task': {
|
|
658
|
+
const parsed = z
|
|
659
|
+
.object({ agent_id: z.string(), task_id: z.string(), project_slug: z.string().optional() })
|
|
660
|
+
.parse(args);
|
|
661
|
+
const result = await client.runAgentTask(parsed.agent_id, parsed.task_id, parsed.project_slug);
|
|
662
|
+
return {
|
|
663
|
+
content: [
|
|
664
|
+
{
|
|
665
|
+
type: 'text',
|
|
666
|
+
text: `Queued task (entry ID: ${result.entryId}, position: ${result.position}, executing: ${result.executing})\n\nUse list_agent_queue to track progress.`,
|
|
667
|
+
},
|
|
668
|
+
],
|
|
669
|
+
};
|
|
670
|
+
}
|
|
671
|
+
case 'list_agent_queue': {
|
|
672
|
+
const parsed = z.object({ agent_id: z.string(), status: z.string().optional() }).parse(args);
|
|
673
|
+
const entries = await client.listAgentQueue(parsed.agent_id, parsed.status);
|
|
674
|
+
return { content: [{ type: 'text', text: text(entries) }] };
|
|
675
|
+
}
|
|
676
|
+
case 'cancel_queue_entry': {
|
|
677
|
+
const parsed = z.object({ agent_id: z.string(), entry_id: z.string() }).parse(args);
|
|
678
|
+
await client.cancelQueueEntry(parsed.agent_id, parsed.entry_id);
|
|
679
|
+
return { content: [{ type: 'text', text: `Cancelled queue entry ${parsed.entry_id}` }] };
|
|
680
|
+
}
|
|
681
|
+
// ─── Skills ─────────────────────────────────────────────────────────────
|
|
682
|
+
case 'create_skill': {
|
|
683
|
+
const parsed = z
|
|
684
|
+
.object({ name: z.string(), description: z.string(), content: z.string() })
|
|
685
|
+
.parse(args);
|
|
686
|
+
const skill = await client.createSkill(parsed);
|
|
687
|
+
return {
|
|
688
|
+
content: [{ type: 'text', text: `Created skill "${parsed.name}"\n\n${text(skill)}` }],
|
|
689
|
+
};
|
|
690
|
+
}
|
|
691
|
+
case 'update_skill': {
|
|
692
|
+
const parsed = z
|
|
693
|
+
.object({
|
|
694
|
+
skill_id: z.string(),
|
|
695
|
+
name: z.string().optional(),
|
|
696
|
+
description: z.string().optional(),
|
|
697
|
+
content: z.string().optional(),
|
|
698
|
+
})
|
|
699
|
+
.parse(args);
|
|
700
|
+
const { skill_id, ...fields } = parsed;
|
|
701
|
+
const skill = await client.updateSkill(skill_id, fields);
|
|
702
|
+
return { content: [{ type: 'text', text: `Updated skill\n\n${text(skill)}` }] };
|
|
703
|
+
}
|
|
704
|
+
case 'create_skill_resource': {
|
|
705
|
+
const parsed = z
|
|
706
|
+
.object({
|
|
707
|
+
skill_id: z.string(),
|
|
708
|
+
type: z.enum(['script', 'reference', 'asset']),
|
|
709
|
+
name: z.string(),
|
|
710
|
+
content: z.string(),
|
|
711
|
+
mime_type: z.string().optional(),
|
|
712
|
+
})
|
|
713
|
+
.parse(args);
|
|
714
|
+
const { skill_id, mime_type, ...rest } = parsed;
|
|
715
|
+
const resource = await client.createSkillResource(skill_id, { ...rest, mimeType: mime_type });
|
|
716
|
+
return {
|
|
717
|
+
content: [{ type: 'text', text: `Created resource "${parsed.name}"\n\n${text(resource)}` }],
|
|
718
|
+
};
|
|
719
|
+
}
|
|
720
|
+
case 'update_skill_resource': {
|
|
721
|
+
const parsed = z
|
|
722
|
+
.object({
|
|
723
|
+
skill_id: z.string(),
|
|
724
|
+
resource_id: z.string(),
|
|
725
|
+
name: z.string().optional(),
|
|
726
|
+
content: z.string().optional(),
|
|
727
|
+
mime_type: z.string().optional(),
|
|
728
|
+
})
|
|
729
|
+
.parse(args);
|
|
730
|
+
const { skill_id, resource_id, mime_type, ...rest } = parsed;
|
|
731
|
+
const resource = await client.updateSkillResource(skill_id, resource_id, {
|
|
732
|
+
...rest,
|
|
733
|
+
mimeType: mime_type,
|
|
734
|
+
});
|
|
735
|
+
return { content: [{ type: 'text', text: `Updated resource\n\n${text(resource)}` }] };
|
|
736
|
+
}
|
|
737
|
+
case 'set_agent_skills': {
|
|
738
|
+
const parsed = z.object({ agent_id: z.string(), skill_ids: z.array(z.string()) }).parse(args);
|
|
739
|
+
await client.setAgentSkills(parsed.agent_id, parsed.skill_ids);
|
|
740
|
+
return {
|
|
741
|
+
content: [
|
|
742
|
+
{
|
|
743
|
+
type: 'text',
|
|
744
|
+
text: `Set ${parsed.skill_ids.length} skill(s) on agent ${parsed.agent_id}`,
|
|
745
|
+
},
|
|
746
|
+
],
|
|
747
|
+
};
|
|
748
|
+
}
|
|
749
|
+
// ─── Skills (reading org library) ────────────────────────────────────────
|
|
750
|
+
case 'list_org_skills': {
|
|
751
|
+
const skills = await client.listOrgSkills();
|
|
752
|
+
return { content: [{ type: 'text', text: text(skills) }] };
|
|
753
|
+
}
|
|
754
|
+
case 'get_org_skill': {
|
|
755
|
+
const parsed = z.object({ skill_name: z.string() }).parse(args);
|
|
756
|
+
const skill = await client.getOrgSkill(parsed.skill_name);
|
|
757
|
+
if (!skill) {
|
|
758
|
+
return {
|
|
759
|
+
content: [
|
|
760
|
+
{
|
|
761
|
+
type: 'text',
|
|
762
|
+
text: `Skill '${parsed.skill_name}' not found. Use list_org_skills to see available skills.`,
|
|
763
|
+
},
|
|
764
|
+
],
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
return { content: [{ type: 'text', text: text(skill) }] };
|
|
768
|
+
}
|
|
769
|
+
// ─── Secrets ─────────────────────────────────────────────────────────────
|
|
770
|
+
case 'list_agent_secrets': {
|
|
771
|
+
const { agent_id } = AgentIdSchema.parse(args);
|
|
772
|
+
const secrets = await client.listAgentSecrets(agent_id);
|
|
773
|
+
return { content: [{ type: 'text', text: text(secrets) }] };
|
|
774
|
+
}
|
|
775
|
+
case 'set_agent_secret': {
|
|
776
|
+
const parsed = z
|
|
777
|
+
.object({ agent_id: z.string(), name: z.string(), value: z.string() })
|
|
778
|
+
.parse(args);
|
|
779
|
+
const secret = await client.setAgentSecret(parsed.agent_id, parsed.name, parsed.value);
|
|
780
|
+
return { content: [{ type: 'text', text: `Set secret "${secret.name}"` }] };
|
|
781
|
+
}
|
|
782
|
+
// ─── Discovery ────────────────────────────────────────────────────────────
|
|
783
|
+
case 'list_agent_templates': {
|
|
784
|
+
const templates = await client.listAgentTemplates();
|
|
785
|
+
return { content: [{ type: 'text', text: text(templates) }] };
|
|
786
|
+
}
|
|
787
|
+
case 'list_llm_models': {
|
|
788
|
+
const models = await client.listLlmModels();
|
|
789
|
+
return { content: [{ type: 'text', text: text(models) }] };
|
|
790
|
+
}
|
|
791
|
+
default:
|
|
792
|
+
return {
|
|
793
|
+
content: [{ type: 'text', text: `Unknown agent builder tool: ${name}` }],
|
|
794
|
+
isError: true,
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
}
|
package/dist/client.js
CHANGED
|
@@ -568,6 +568,161 @@ export class WolfpackClient {
|
|
|
568
568
|
parentCommentId,
|
|
569
569
|
});
|
|
570
570
|
}
|
|
571
|
+
// ─── Capabilities ─────────────────────────────────────────────────────────
|
|
572
|
+
async getCapabilities() {
|
|
573
|
+
return this.api.get('/capabilities');
|
|
574
|
+
}
|
|
575
|
+
// ─── Agent Builder: Agent CRUD ─────────────────────────────────────────────
|
|
576
|
+
async listAgents() {
|
|
577
|
+
return this.api.get('/agents');
|
|
578
|
+
}
|
|
579
|
+
async getAgent(agentId) {
|
|
580
|
+
try {
|
|
581
|
+
return await this.api.get(`/agents/${agentId}`);
|
|
582
|
+
}
|
|
583
|
+
catch (error) {
|
|
584
|
+
if (error && typeof error === 'object' && 'status' in error && error.status === 404)
|
|
585
|
+
return null;
|
|
586
|
+
throw error;
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
async createAgent(body) {
|
|
590
|
+
return this.api.post('/agents', body);
|
|
591
|
+
}
|
|
592
|
+
async updateAgent(agentId, body) {
|
|
593
|
+
return this.api.patch(`/agents/${agentId}`, body);
|
|
594
|
+
}
|
|
595
|
+
// ─── Agent Builder: Project Assignment ────────────────────────────────────
|
|
596
|
+
async listAgentProjects(agentId) {
|
|
597
|
+
return this.api.get(`/agents/${agentId}/projects`);
|
|
598
|
+
}
|
|
599
|
+
async assignAgentToProject(agentId, teamSlug) {
|
|
600
|
+
return this.api.post(`/agents/${agentId}/projects/${encodeURIComponent(teamSlug)}`, {});
|
|
601
|
+
}
|
|
602
|
+
async removeAgentFromProject(agentId, teamSlug) {
|
|
603
|
+
return this.api
|
|
604
|
+
.delete(`/agents/${agentId}/projects/${encodeURIComponent(teamSlug)}`)
|
|
605
|
+
.then(() => ({ success: true }));
|
|
606
|
+
}
|
|
607
|
+
// ─── Agent Builder: Sessions ───────────────────────────────────────────────
|
|
608
|
+
async listAgentSessions(agentId, options) {
|
|
609
|
+
const params = new URLSearchParams();
|
|
610
|
+
if (options?.status)
|
|
611
|
+
params.append('status', options.status);
|
|
612
|
+
if (options?.limit !== undefined)
|
|
613
|
+
params.append('limit', options.limit.toString());
|
|
614
|
+
if (options?.offset !== undefined)
|
|
615
|
+
params.append('offset', options.offset.toString());
|
|
616
|
+
const q = params.toString();
|
|
617
|
+
return this.api.get(`/agents/${agentId}/sessions${q ? `?${q}` : ''}`);
|
|
618
|
+
}
|
|
619
|
+
async getAgentSession(agentId, sessionId) {
|
|
620
|
+
try {
|
|
621
|
+
return await this.api.get(`/agents/${agentId}/sessions/${sessionId}`);
|
|
622
|
+
}
|
|
623
|
+
catch (error) {
|
|
624
|
+
if (error && typeof error === 'object' && 'status' in error && error.status === 404)
|
|
625
|
+
return null;
|
|
626
|
+
throw error;
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
async getAgentSessionConversation(agentId, sessionId, options) {
|
|
630
|
+
const params = new URLSearchParams();
|
|
631
|
+
if (options?.limit !== undefined)
|
|
632
|
+
params.append('limit', options.limit.toString());
|
|
633
|
+
if (options?.offset !== undefined)
|
|
634
|
+
params.append('offset', options.offset.toString());
|
|
635
|
+
const q = params.toString();
|
|
636
|
+
return this.api.get(`/agents/${agentId}/sessions/${sessionId}/conversation${q ? `?${q}` : ''}`);
|
|
637
|
+
}
|
|
638
|
+
async runAgent(agentId, prompt, teamSlug) {
|
|
639
|
+
return this.api.post(`/agents/${agentId}/run`, { prompt, teamSlug });
|
|
640
|
+
}
|
|
641
|
+
async stopAgentSession(agentId, sessionId) {
|
|
642
|
+
return this.api.post(`/agents/${agentId}/sessions/${sessionId}/stop`, {});
|
|
643
|
+
}
|
|
644
|
+
async resumeAgentSession(agentId, sessionId, prompt) {
|
|
645
|
+
return this.api.post(`/agents/${agentId}/sessions/${sessionId}/resume`, {
|
|
646
|
+
prompt,
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
// ─── Agent Builder: Tasks ──────────────────────────────────────────────────
|
|
650
|
+
async listAgentTasks(agentId) {
|
|
651
|
+
return this.api.get(`/agents/${agentId}/tasks`);
|
|
652
|
+
}
|
|
653
|
+
async getAgentTask(agentId, taskId) {
|
|
654
|
+
try {
|
|
655
|
+
return await this.api.get(`/agents/${agentId}/tasks/${taskId}`);
|
|
656
|
+
}
|
|
657
|
+
catch (error) {
|
|
658
|
+
if (error && typeof error === 'object' && 'status' in error && error.status === 404)
|
|
659
|
+
return null;
|
|
660
|
+
throw error;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
async createAgentTask(agentId, body) {
|
|
664
|
+
return this.api.post(`/agents/${agentId}/tasks`, body);
|
|
665
|
+
}
|
|
666
|
+
async updateAgentTask(agentId, taskId, body) {
|
|
667
|
+
return this.api.patch(`/agents/${agentId}/tasks/${taskId}`, body);
|
|
668
|
+
}
|
|
669
|
+
async runAgentTask(agentId, taskId, teamSlug) {
|
|
670
|
+
return this.api.post(`/agents/${agentId}/tasks/${taskId}/run`, { teamSlug });
|
|
671
|
+
}
|
|
672
|
+
// ─── Agent Builder: Queue ──────────────────────────────────────────────────
|
|
673
|
+
async listAgentQueue(agentId, status) {
|
|
674
|
+
const q = status ? `?status=${encodeURIComponent(status)}` : '';
|
|
675
|
+
return this.api.get(`/agents/${agentId}/queue${q}`);
|
|
676
|
+
}
|
|
677
|
+
async cancelQueueEntry(agentId, entryId) {
|
|
678
|
+
return this.api.delete(`/agents/${agentId}/queue/${entryId}`).then(() => ({ success: true }));
|
|
679
|
+
}
|
|
680
|
+
// ─── Agent Builder: Secrets ────────────────────────────────────────────────
|
|
681
|
+
async listAgentSecrets(agentId) {
|
|
682
|
+
return this.api.get(`/agents/${agentId}/secrets`);
|
|
683
|
+
}
|
|
684
|
+
async setAgentSecret(agentId, name, value) {
|
|
685
|
+
return this.api.post(`/agents/${agentId}/secrets`, { name, value });
|
|
686
|
+
}
|
|
687
|
+
// ─── Agent Builder: Skills (write) ────────────────────────────────────────
|
|
688
|
+
async createSkill(body) {
|
|
689
|
+
return this.api.post('/skills', body);
|
|
690
|
+
}
|
|
691
|
+
async updateSkill(skillId, body) {
|
|
692
|
+
return this.api.patch(`/skills/${skillId}`, body);
|
|
693
|
+
}
|
|
694
|
+
async createSkillResource(skillId, body) {
|
|
695
|
+
return this.api.post(`/skills/${skillId}/resources`, body);
|
|
696
|
+
}
|
|
697
|
+
async updateSkillResource(skillId, resourceId, body) {
|
|
698
|
+
return this.api.patch(`/skills/${skillId}/resources/${resourceId}`, body);
|
|
699
|
+
}
|
|
700
|
+
async setAgentSkills(agentId, skillIds) {
|
|
701
|
+
return this.api.post(`/skills/agent-assignments/${agentId}`, {
|
|
702
|
+
skillIds,
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
// ─── Agent Builder: Skills (read) ──────────────────────────────────────────
|
|
706
|
+
async listOrgSkills() {
|
|
707
|
+
return this.api.get('/skills/org');
|
|
708
|
+
}
|
|
709
|
+
async getOrgSkill(name) {
|
|
710
|
+
try {
|
|
711
|
+
return await this.api.get(`/skills/org/${encodeURIComponent(name)}`);
|
|
712
|
+
}
|
|
713
|
+
catch (error) {
|
|
714
|
+
if (error && typeof error === 'object' && 'status' in error && error.status === 404)
|
|
715
|
+
return null;
|
|
716
|
+
throw error;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
// ─── Agent Builder: Discovery ──────────────────────────────────────────────
|
|
720
|
+
async listAgentTemplates() {
|
|
721
|
+
return this.api.get('/agent-builder/templates');
|
|
722
|
+
}
|
|
723
|
+
async listLlmModels() {
|
|
724
|
+
return this.api.get('/agent-builder/llm-models');
|
|
725
|
+
}
|
|
571
726
|
close() {
|
|
572
727
|
// No cleanup needed for API client
|
|
573
728
|
}
|
package/dist/index.js
CHANGED
|
@@ -8,6 +8,7 @@ import { readFile, stat } from 'fs/promises';
|
|
|
8
8
|
import { basename, extname, resolve } from 'path';
|
|
9
9
|
import { WolfpackClient } from './client.js';
|
|
10
10
|
import { validateConfig, config } from './config.js';
|
|
11
|
+
import { AGENT_BUILDER_TOOLS, handleAgentBuilderTool } from './agentBuilderTools.js';
|
|
11
12
|
// Get current package version
|
|
12
13
|
const require = createRequire(import.meta.url);
|
|
13
14
|
const packageJson = require('../package.json');
|
|
@@ -115,6 +116,10 @@ const VALID_STATUSES = [
|
|
|
115
116
|
const UpdateWorkItemSchema = z.object({
|
|
116
117
|
work_item_id: z.string().describe('The ID of the work item'),
|
|
117
118
|
title: z.string().optional().describe('New title for the work item'),
|
|
119
|
+
description: z
|
|
120
|
+
.string()
|
|
121
|
+
.optional()
|
|
122
|
+
.describe('Updated description (supports Markdown and @mentions)'),
|
|
118
123
|
status: z.enum(VALID_STATUSES).optional().describe('New status'),
|
|
119
124
|
leading_user_id: z
|
|
120
125
|
.string()
|
|
@@ -137,6 +142,27 @@ const UpdateWorkItemSchema = z.object({
|
|
|
137
142
|
.nullable()
|
|
138
143
|
.optional()
|
|
139
144
|
.describe('Size estimate: "S" (small), "M" (medium), "L" (large), or null to remove'),
|
|
145
|
+
assisting_user1_id: z
|
|
146
|
+
.string()
|
|
147
|
+
.nullable()
|
|
148
|
+
.optional()
|
|
149
|
+
.describe('User ID for first assisting user, or null to remove'),
|
|
150
|
+
assisting_user2_id: z
|
|
151
|
+
.string()
|
|
152
|
+
.nullable()
|
|
153
|
+
.optional()
|
|
154
|
+
.describe('User ID for second assisting user, or null to remove'),
|
|
155
|
+
assisting_user3_id: z
|
|
156
|
+
.string()
|
|
157
|
+
.nullable()
|
|
158
|
+
.optional()
|
|
159
|
+
.describe('User ID for third assisting user, or null to remove'),
|
|
160
|
+
tag_ids: z.array(z.string()).optional().describe('Tag IDs to apply (replaces existing tags)'),
|
|
161
|
+
closing_comment: z
|
|
162
|
+
.string()
|
|
163
|
+
.nullable()
|
|
164
|
+
.optional()
|
|
165
|
+
.describe('Comment explaining closure/completion'),
|
|
140
166
|
project_slug: z
|
|
141
167
|
.string()
|
|
142
168
|
.optional()
|
|
@@ -590,6 +616,7 @@ function hasPlan(description) {
|
|
|
590
616
|
class WolfpackMCPServer {
|
|
591
617
|
server;
|
|
592
618
|
client;
|
|
619
|
+
capabilities = [];
|
|
593
620
|
constructor() {
|
|
594
621
|
this.client = new WolfpackClient();
|
|
595
622
|
this.server = new Server({
|
|
@@ -737,8 +764,8 @@ class WolfpackMCPServer {
|
|
|
737
764
|
{
|
|
738
765
|
name: 'update_work_item',
|
|
739
766
|
description: 'Update one or more fields on a work item. Only provide the fields you want to change. ' +
|
|
740
|
-
'Supports: title, status, leading_user_id (assignee),
|
|
741
|
-
'category_id, priority (0-4),
|
|
767
|
+
'Supports: title, description, status, leading_user_id (assignee), assisting_user1/2/3_id, ' +
|
|
768
|
+
'radar_item_id (initiative), category_id, priority (0-4), size (S/M/L), tag_ids, and closing_comment. ' +
|
|
742
769
|
'STATUS WORKFLOW: "pending" (backlog) → "new" (to do) → "doing" (in progress) → "review" (work done) → "ready" (awaiting deployment) → "completed" (deployed). ' +
|
|
743
770
|
'Use "blocked" when work cannot proceed. For "pending" items use pull_work_item first. ' +
|
|
744
771
|
'When moving to "review", add a completion comment. When moving to "blocked", add a comment explaining the blocker.',
|
|
@@ -753,6 +780,10 @@ class WolfpackMCPServer {
|
|
|
753
780
|
type: 'string',
|
|
754
781
|
description: 'New title for the work item',
|
|
755
782
|
},
|
|
783
|
+
description: {
|
|
784
|
+
type: 'string',
|
|
785
|
+
description: 'Updated description (supports Markdown and @mentions)',
|
|
786
|
+
},
|
|
756
787
|
status: {
|
|
757
788
|
type: 'string',
|
|
758
789
|
enum: [
|
|
@@ -789,6 +820,27 @@ class WolfpackMCPServer {
|
|
|
789
820
|
enum: ['S', 'M', 'L', null],
|
|
790
821
|
description: 'Size estimate: "S" (small), "M" (medium), "L" (large), or null to remove',
|
|
791
822
|
},
|
|
823
|
+
assisting_user1_id: {
|
|
824
|
+
type: ['string', 'null'],
|
|
825
|
+
description: 'User ID for first assisting user, or null to remove',
|
|
826
|
+
},
|
|
827
|
+
assisting_user2_id: {
|
|
828
|
+
type: ['string', 'null'],
|
|
829
|
+
description: 'User ID for second assisting user, or null to remove',
|
|
830
|
+
},
|
|
831
|
+
assisting_user3_id: {
|
|
832
|
+
type: ['string', 'null'],
|
|
833
|
+
description: 'User ID for third assisting user, or null to remove',
|
|
834
|
+
},
|
|
835
|
+
tag_ids: {
|
|
836
|
+
type: 'array',
|
|
837
|
+
items: { type: 'string' },
|
|
838
|
+
description: 'Tag IDs to apply (replaces existing tags)',
|
|
839
|
+
},
|
|
840
|
+
closing_comment: {
|
|
841
|
+
type: ['string', 'null'],
|
|
842
|
+
description: 'Comment explaining closure/completion',
|
|
843
|
+
},
|
|
792
844
|
project_slug: {
|
|
793
845
|
type: 'string',
|
|
794
846
|
description: 'Project slug (required for multi-project users, use list_projects to get slugs)',
|
|
@@ -1811,6 +1863,7 @@ class WolfpackMCPServer {
|
|
|
1811
1863
|
required: ['discussion_id', 'content'],
|
|
1812
1864
|
},
|
|
1813
1865
|
},
|
|
1866
|
+
...(this.capabilities.includes('agent_builder') ? AGENT_BUILDER_TOOLS : []),
|
|
1814
1867
|
],
|
|
1815
1868
|
}));
|
|
1816
1869
|
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -1908,6 +1961,8 @@ class WolfpackMCPServer {
|
|
|
1908
1961
|
const fields = {};
|
|
1909
1962
|
if (parsed.title !== undefined)
|
|
1910
1963
|
fields.title = parsed.title;
|
|
1964
|
+
if (parsed.description !== undefined)
|
|
1965
|
+
fields.description = parsed.description;
|
|
1911
1966
|
if (parsed.status !== undefined)
|
|
1912
1967
|
fields.status = parsed.status;
|
|
1913
1968
|
if (parsed.leading_user_id !== undefined)
|
|
@@ -1920,6 +1975,16 @@ class WolfpackMCPServer {
|
|
|
1920
1975
|
fields.priority = parsed.priority;
|
|
1921
1976
|
if (parsed.size !== undefined)
|
|
1922
1977
|
fields.size = parsed.size;
|
|
1978
|
+
if (parsed.assisting_user1_id !== undefined)
|
|
1979
|
+
fields.assistingUser1Id = parsed.assisting_user1_id;
|
|
1980
|
+
if (parsed.assisting_user2_id !== undefined)
|
|
1981
|
+
fields.assistingUser2Id = parsed.assisting_user2_id;
|
|
1982
|
+
if (parsed.assisting_user3_id !== undefined)
|
|
1983
|
+
fields.assistingUser3Id = parsed.assisting_user3_id;
|
|
1984
|
+
if (parsed.tag_ids !== undefined)
|
|
1985
|
+
fields.tagIds = parsed.tag_ids;
|
|
1986
|
+
if (parsed.closing_comment !== undefined)
|
|
1987
|
+
fields.closingComment = parsed.closing_comment;
|
|
1923
1988
|
const workItem = await this.client.updateWorkItem(parsed.work_item_id, fields, teamSlug);
|
|
1924
1989
|
if (workItem) {
|
|
1925
1990
|
// Build a summary of what changed
|
|
@@ -1928,6 +1993,8 @@ class WolfpackMCPServer {
|
|
|
1928
1993
|
changes.push(`status → ${parsed.status}`);
|
|
1929
1994
|
if (parsed.title !== undefined)
|
|
1930
1995
|
changes.push(`title → "${parsed.title}"`);
|
|
1996
|
+
if (parsed.description !== undefined)
|
|
1997
|
+
changes.push('description updated');
|
|
1931
1998
|
if (parsed.leading_user_id !== undefined)
|
|
1932
1999
|
changes.push(parsed.leading_user_id
|
|
1933
2000
|
? `assigned to ${workItem.leadingUser?.name || parsed.leading_user_id}`
|
|
@@ -1950,6 +2017,22 @@ class WolfpackMCPServer {
|
|
|
1950
2017
|
}
|
|
1951
2018
|
if (parsed.size !== undefined)
|
|
1952
2019
|
changes.push(parsed.size ? `size → ${parsed.size}` : 'size removed');
|
|
2020
|
+
if (parsed.assisting_user1_id !== undefined)
|
|
2021
|
+
changes.push(parsed.assisting_user1_id
|
|
2022
|
+
? `assisting user 1 updated`
|
|
2023
|
+
: 'assisting user 1 removed');
|
|
2024
|
+
if (parsed.assisting_user2_id !== undefined)
|
|
2025
|
+
changes.push(parsed.assisting_user2_id
|
|
2026
|
+
? `assisting user 2 updated`
|
|
2027
|
+
: 'assisting user 2 removed');
|
|
2028
|
+
if (parsed.assisting_user3_id !== undefined)
|
|
2029
|
+
changes.push(parsed.assisting_user3_id
|
|
2030
|
+
? `assisting user 3 updated`
|
|
2031
|
+
: 'assisting user 3 removed');
|
|
2032
|
+
if (parsed.tag_ids !== undefined)
|
|
2033
|
+
changes.push('tags updated');
|
|
2034
|
+
if (parsed.closing_comment !== undefined)
|
|
2035
|
+
changes.push('closing comment set');
|
|
1953
2036
|
const summary = changes.length > 0 ? changes.join(', ') : 'no changes';
|
|
1954
2037
|
return {
|
|
1955
2038
|
content: [
|
|
@@ -2618,8 +2701,12 @@ class WolfpackMCPServer {
|
|
|
2618
2701
|
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
2619
2702
|
};
|
|
2620
2703
|
}
|
|
2621
|
-
default:
|
|
2704
|
+
default: {
|
|
2705
|
+
if (this.capabilities.includes('agent_builder')) {
|
|
2706
|
+
return handleAgentBuilderTool(name, args, this.client);
|
|
2707
|
+
}
|
|
2622
2708
|
throw new Error(`Unknown tool: ${name}`);
|
|
2709
|
+
}
|
|
2623
2710
|
}
|
|
2624
2711
|
}
|
|
2625
2712
|
catch (error) {
|
|
@@ -2657,41 +2744,55 @@ class WolfpackMCPServer {
|
|
|
2657
2744
|
return false;
|
|
2658
2745
|
}
|
|
2659
2746
|
async start() {
|
|
2747
|
+
// Fetch capabilities to determine which tools to register
|
|
2748
|
+
try {
|
|
2749
|
+
const caps = await this.client.getCapabilities();
|
|
2750
|
+
this.capabilities = caps.capabilities;
|
|
2751
|
+
if (this.capabilities.length > 0) {
|
|
2752
|
+
console.error(`Capabilities: ${this.capabilities.join(', ')}`);
|
|
2753
|
+
}
|
|
2754
|
+
}
|
|
2755
|
+
catch (error) {
|
|
2756
|
+
console.error(`Warning: Could not fetch capabilities: ${error instanceof Error ? error.message : String(error)}`);
|
|
2757
|
+
// Proceed with project tools only (backward compat)
|
|
2758
|
+
}
|
|
2660
2759
|
// Connect stdio transport FIRST so MCP clients don't deadlock waiting for initialize
|
|
2661
2760
|
const transport = new StdioServerTransport();
|
|
2662
2761
|
await this.server.connect(transport);
|
|
2663
2762
|
console.error(`Wolfpack MCP Server v${CURRENT_VERSION} started`);
|
|
2664
|
-
// Resolve project
|
|
2665
|
-
if (
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
catch (error) {
|
|
2672
|
-
console.error(`Failed to resolve project slug: ${error instanceof Error ? error.message : String(error)}`);
|
|
2673
|
-
// Don't exit - project can be specified per tool call
|
|
2674
|
-
}
|
|
2675
|
-
}
|
|
2676
|
-
else {
|
|
2677
|
-
// No project slug configured - try to auto-detect
|
|
2678
|
-
try {
|
|
2679
|
-
const teams = await this.client.listProjects();
|
|
2680
|
-
if (teams.length === 1) {
|
|
2681
|
-
// Auto-select the only project
|
|
2682
|
-
this.client.setProjectSlug(teams[0].slug);
|
|
2683
|
-
console.error(`Auto-selected project: ${teams[0].name} (${teams[0].slug})`);
|
|
2684
|
-
}
|
|
2685
|
-
else if (teams.length === 0) {
|
|
2686
|
-
console.error('Warning: No projects found for this API key');
|
|
2763
|
+
// Resolve project for project-capable keys
|
|
2764
|
+
if (this.capabilities.includes('project') || this.capabilities.length === 0) {
|
|
2765
|
+
if (config.projectSlug) {
|
|
2766
|
+
// Explicit project slug configured - use it
|
|
2767
|
+
try {
|
|
2768
|
+
await this.client.resolveProjectSlug(config.projectSlug);
|
|
2769
|
+
console.error(`Resolved project: "${config.projectSlug}"`);
|
|
2687
2770
|
}
|
|
2688
|
-
|
|
2689
|
-
console.error(`
|
|
2771
|
+
catch (error) {
|
|
2772
|
+
console.error(`Failed to resolve project slug: ${error instanceof Error ? error.message : String(error)}`);
|
|
2773
|
+
// Don't exit - project can be specified per tool call
|
|
2690
2774
|
}
|
|
2691
2775
|
}
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2776
|
+
else {
|
|
2777
|
+
// No project slug configured - try to auto-detect
|
|
2778
|
+
try {
|
|
2779
|
+
const teams = await this.client.listProjects();
|
|
2780
|
+
if (teams.length === 1) {
|
|
2781
|
+
// Auto-select the only project
|
|
2782
|
+
this.client.setProjectSlug(teams[0].slug);
|
|
2783
|
+
console.error(`Auto-selected project: ${teams[0].name} (${teams[0].slug})`);
|
|
2784
|
+
}
|
|
2785
|
+
else if (teams.length === 0) {
|
|
2786
|
+
console.error('Warning: No projects found for this API key');
|
|
2787
|
+
}
|
|
2788
|
+
else {
|
|
2789
|
+
console.error(`Multiple projects available (${teams.length}). Use list_projects tool to see them, then specify project_slug in tool calls.`);
|
|
2790
|
+
}
|
|
2791
|
+
}
|
|
2792
|
+
catch (error) {
|
|
2793
|
+
console.error(`Warning: Could not fetch projects: ${error instanceof Error ? error.message : String(error)}`);
|
|
2794
|
+
// Don't exit - let the user use list_projects tool manually
|
|
2795
|
+
}
|
|
2695
2796
|
}
|
|
2696
2797
|
}
|
|
2697
2798
|
// Check for updates (non-blocking)
|