@agilemonster/mcp-server 0.0.0-stage → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -2
- package/bin/mcp.js +30 -0
- package/bin/orchestrator.js +92 -0
- package/bin/worker.js +69 -0
- package/dist/client.d.ts +48 -0
- package/dist/client.js +245 -0
- package/dist/guidelines.d.ts +1 -0
- package/dist/guidelines.js +51 -0
- package/dist/orchestrator.d.ts +27 -0
- package/dist/orchestrator.js +306 -0
- package/dist/server.d.ts +37 -0
- package/dist/server.js +680 -0
- package/dist/types.d.ts +47 -0
- package/dist/types.js +1 -0
- package/dist/worker.d.ts +40 -0
- package/dist/worker.js +227 -0
- package/package.json +47 -4
package/dist/server.js
ADDED
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import { AgileMonsterClient } from './client.js';
|
|
7
|
+
import { AGENT_GUIDELINES_MARKDOWN } from './guidelines.js';
|
|
8
|
+
export function createServer(client = new AgileMonsterClient()) {
|
|
9
|
+
const server = new Server({
|
|
10
|
+
name: 'agilemonster-mcp-server',
|
|
11
|
+
version: '1.0.0',
|
|
12
|
+
}, {
|
|
13
|
+
capabilities: {
|
|
14
|
+
tools: {},
|
|
15
|
+
prompts: {},
|
|
16
|
+
resources: {},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
// -------------------------------------------------------------------------
|
|
20
|
+
// 1. Prompts for Autonomous Agents
|
|
21
|
+
// -------------------------------------------------------------------------
|
|
22
|
+
const prompts = [
|
|
23
|
+
{
|
|
24
|
+
name: 'agilemonster_agent_protocol',
|
|
25
|
+
description: 'Official operational guidelines and lifecycle protocol for AI agents working on Agile Monster boards.',
|
|
26
|
+
arguments: [],
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'agilemonster_work_on_task',
|
|
30
|
+
description: 'Workflow prompt for an AI agent to claim, investigate, implement, test, and submit an Agile Monster task for review.',
|
|
31
|
+
arguments: [
|
|
32
|
+
{
|
|
33
|
+
name: 'card_id',
|
|
34
|
+
description: 'The UUID of the Agile Monster card to work on.',
|
|
35
|
+
required: true,
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'task_title',
|
|
39
|
+
description: 'Optional task title for context.',
|
|
40
|
+
required: false,
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
46
|
+
return { prompts };
|
|
47
|
+
});
|
|
48
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
49
|
+
const { name, arguments: args } = request.params;
|
|
50
|
+
if (name === 'agilemonster_agent_protocol') {
|
|
51
|
+
return {
|
|
52
|
+
description: 'Agile Monster Task Lifecycle Protocol for AI Agents',
|
|
53
|
+
messages: [
|
|
54
|
+
{
|
|
55
|
+
role: 'user',
|
|
56
|
+
content: {
|
|
57
|
+
type: 'text',
|
|
58
|
+
text: AGENT_GUIDELINES_MARKDOWN,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
if (name === 'agilemonster_work_on_task') {
|
|
65
|
+
const cardId = args?.card_id || 'UNKNOWN_CARD_ID';
|
|
66
|
+
const taskTitle = args?.task_title ? `"${args.task_title}"` : 'assigned task';
|
|
67
|
+
return {
|
|
68
|
+
description: `Operational task workflow for card ${cardId}`,
|
|
69
|
+
messages: [
|
|
70
|
+
{
|
|
71
|
+
role: 'user',
|
|
72
|
+
content: {
|
|
73
|
+
type: 'text',
|
|
74
|
+
text: `You are an autonomous AI coding assistant working on the Agile Monster card ${taskTitle} (ID: ${cardId}).
|
|
75
|
+
|
|
76
|
+
Please strictly follow the Agile Monster Task Lifecycle Protocol:
|
|
77
|
+
1. **Claim the Task**: Call agilemonster_claim_task({ card_id: "${cardId}" }) to mark it "in_progress".
|
|
78
|
+
2. **Context & Exploration**: Read relevant files, check git history, and understand requirements.
|
|
79
|
+
3. **Handle Ambiguity**: If anything is unclear, call agilemonster_ask_question({ card_id: "${cardId}", question: "..." }) to set status to "waiting_for_input" and wait for the user.
|
|
80
|
+
4. **Log Progress**: If you complete a major milestone, call agilemonster_add_progress({ card_id: "${cardId}", update: "..." }).
|
|
81
|
+
5. **Implement & Test**: Write clean code and verify with automated unit/integration tests or build commands.
|
|
82
|
+
6. **Submit for Human Review**: NEVER mark this task as Done directly. Call agilemonster_submit_for_review({ card_id: "${cardId}", summary: "...", verification_steps: "..." }) to reassign to the user for testing.
|
|
83
|
+
7. **Suggest Follow-Ups**: Call agilemonster_create_followup_tasks({ card_id: "${cardId}", tasks: [...] }) to propose staging/production deployment or further testing.`,
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
throw new Error(`Unknown prompt: ${name}`);
|
|
90
|
+
});
|
|
91
|
+
// -------------------------------------------------------------------------
|
|
92
|
+
// 2. Resources for Autonomous Agents
|
|
93
|
+
// -------------------------------------------------------------------------
|
|
94
|
+
const resources = [
|
|
95
|
+
{
|
|
96
|
+
uri: 'agilemonster://guidelines/agents',
|
|
97
|
+
name: 'Agile Monster Agent Operational Protocol',
|
|
98
|
+
description: 'Standard lifecycle and operating procedures for AI agents using Agile Monster.',
|
|
99
|
+
mimeType: 'text/markdown',
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
uri: 'agilemonster://project/context',
|
|
103
|
+
name: 'Current Repository Board Context',
|
|
104
|
+
description: 'Active Agile Monster board ID, columns, and assigned tasks for this repository.',
|
|
105
|
+
mimeType: 'application/json',
|
|
106
|
+
},
|
|
107
|
+
];
|
|
108
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
109
|
+
return { resources };
|
|
110
|
+
});
|
|
111
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
112
|
+
const { uri } = request.params;
|
|
113
|
+
if (uri === 'agilemonster://guidelines/agents') {
|
|
114
|
+
return {
|
|
115
|
+
contents: [
|
|
116
|
+
{
|
|
117
|
+
uri,
|
|
118
|
+
mimeType: 'text/markdown',
|
|
119
|
+
text: AGENT_GUIDELINES_MARKDOWN,
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
if (uri === 'agilemonster://project/context') {
|
|
125
|
+
const projectConfig = client.loadProjectConfig();
|
|
126
|
+
const projectName = projectConfig?.board_name || path.basename(process.cwd());
|
|
127
|
+
const boardId = projectConfig?.board_id;
|
|
128
|
+
const context = await client.getContext(projectName, boardId);
|
|
129
|
+
return {
|
|
130
|
+
contents: [
|
|
131
|
+
{
|
|
132
|
+
uri,
|
|
133
|
+
mimeType: 'application/json',
|
|
134
|
+
text: JSON.stringify({
|
|
135
|
+
config_source: projectConfig ? '.agilemonster.json' : 'auto_matched',
|
|
136
|
+
project_config: projectConfig,
|
|
137
|
+
...context,
|
|
138
|
+
}, null, 2),
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
throw new Error(`Resource not found: ${uri}`);
|
|
144
|
+
});
|
|
145
|
+
// -------------------------------------------------------------------------
|
|
146
|
+
// 3. Tools for Autonomous Agents
|
|
147
|
+
// -------------------------------------------------------------------------
|
|
148
|
+
const tools = [
|
|
149
|
+
{
|
|
150
|
+
name: 'agilemonster_get_context',
|
|
151
|
+
description: 'Inspect Agile Monster board and project context for this repository. Automatically reads .agilemonster.json if present or finds matching board.',
|
|
152
|
+
inputSchema: {
|
|
153
|
+
type: 'object',
|
|
154
|
+
properties: {
|
|
155
|
+
project_name: {
|
|
156
|
+
type: 'string',
|
|
157
|
+
description: 'Optional project or repository name to match against board names.',
|
|
158
|
+
},
|
|
159
|
+
board_id: {
|
|
160
|
+
type: 'string',
|
|
161
|
+
description: 'Optional explicit board ID.',
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
name: 'agilemonster_init_project',
|
|
168
|
+
description: 'Bind the current repository to an Agile Monster workspace and board by creating a .agilemonster.json file and generating AGENTS.md.',
|
|
169
|
+
inputSchema: {
|
|
170
|
+
type: 'object',
|
|
171
|
+
properties: {
|
|
172
|
+
workspace_id: {
|
|
173
|
+
type: 'string',
|
|
174
|
+
description: 'The Agile Monster workspace UUID.',
|
|
175
|
+
},
|
|
176
|
+
board_id: {
|
|
177
|
+
type: 'string',
|
|
178
|
+
description: 'The Agile Monster board UUID.',
|
|
179
|
+
},
|
|
180
|
+
provider: {
|
|
181
|
+
type: 'string',
|
|
182
|
+
description: 'Default agent provider for this repo (e.g. antigravity, cursor, claude_code, hermes).',
|
|
183
|
+
},
|
|
184
|
+
review_list: {
|
|
185
|
+
type: 'string',
|
|
186
|
+
description: 'Optional name of list to move cards to upon review (default: "Review" or "Testing").',
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
required: ['workspace_id', 'board_id'],
|
|
190
|
+
},
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
name: 'agilemonster_list_my_tasks',
|
|
194
|
+
description: 'List tasks assigned to the AI agent on Agile Monster boards (queued, in_progress, waiting_for_input, review).',
|
|
195
|
+
inputSchema: {
|
|
196
|
+
type: 'object',
|
|
197
|
+
properties: {
|
|
198
|
+
provider: {
|
|
199
|
+
type: 'string',
|
|
200
|
+
description: 'Agent provider name (e.g. antigravity, cursor, claude_code, codex, hermes, windsurf). Defaults to repo config or "any".',
|
|
201
|
+
},
|
|
202
|
+
status: {
|
|
203
|
+
type: 'string',
|
|
204
|
+
description: 'Filter by status: "queued", "in_progress", "waiting_for_input", "review", or "all".',
|
|
205
|
+
},
|
|
206
|
+
board_id: {
|
|
207
|
+
type: 'string',
|
|
208
|
+
description: 'Optional filter by board ID (defaults to repo config if present).',
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
name: 'agilemonster_claim_task',
|
|
215
|
+
description: 'Claim a task assigned to this agent to begin working on it. Marks card as "in_progress" in Agile Monster.',
|
|
216
|
+
inputSchema: {
|
|
217
|
+
type: 'object',
|
|
218
|
+
properties: {
|
|
219
|
+
card_id: {
|
|
220
|
+
type: 'string',
|
|
221
|
+
description: 'The card UUID to claim.',
|
|
222
|
+
},
|
|
223
|
+
provider: {
|
|
224
|
+
type: 'string',
|
|
225
|
+
description: 'Agent provider name (e.g. antigravity, cursor, claude_code, hermes).',
|
|
226
|
+
},
|
|
227
|
+
run_ref: {
|
|
228
|
+
type: 'string',
|
|
229
|
+
description: 'Optional execution/session reference ID.',
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
required: ['card_id', 'provider'],
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
name: 'agilemonster_ask_question',
|
|
237
|
+
description: 'Ask the user a clarifying question about the task. Posts a tagged comment on the card and updates status to "waiting_for_input".',
|
|
238
|
+
inputSchema: {
|
|
239
|
+
type: 'object',
|
|
240
|
+
properties: {
|
|
241
|
+
card_id: {
|
|
242
|
+
type: 'string',
|
|
243
|
+
description: 'The card UUID.',
|
|
244
|
+
},
|
|
245
|
+
provider: {
|
|
246
|
+
type: 'string',
|
|
247
|
+
description: 'Agent provider name.',
|
|
248
|
+
},
|
|
249
|
+
question: {
|
|
250
|
+
type: 'string',
|
|
251
|
+
description: 'The question for the user.',
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
required: ['card_id', 'provider', 'question'],
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
name: 'agilemonster_add_progress',
|
|
259
|
+
description: 'Post a progress update or implementation notes to the Agile Monster task activity/comments.',
|
|
260
|
+
inputSchema: {
|
|
261
|
+
type: 'object',
|
|
262
|
+
properties: {
|
|
263
|
+
card_id: {
|
|
264
|
+
type: 'string',
|
|
265
|
+
description: 'The card UUID.',
|
|
266
|
+
},
|
|
267
|
+
provider: {
|
|
268
|
+
type: 'string',
|
|
269
|
+
description: 'Agent provider name.',
|
|
270
|
+
},
|
|
271
|
+
update: {
|
|
272
|
+
type: 'string',
|
|
273
|
+
description: 'Summary of progress made so far.',
|
|
274
|
+
},
|
|
275
|
+
tokens_used: {
|
|
276
|
+
type: 'number',
|
|
277
|
+
description: 'Optional count of LLM tokens consumed in this step.',
|
|
278
|
+
},
|
|
279
|
+
cost_usd: {
|
|
280
|
+
type: 'number',
|
|
281
|
+
description: 'Optional USD cost consumed in this step (e.g. 0.0150).',
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
required: ['card_id', 'provider', 'update'],
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
name: 'agilemonster_record_spend',
|
|
289
|
+
description: 'Record LLM token and cost consumption on a card to enforce circuit breakers against runaway billing.',
|
|
290
|
+
inputSchema: {
|
|
291
|
+
type: 'object',
|
|
292
|
+
properties: {
|
|
293
|
+
card_id: {
|
|
294
|
+
type: 'string',
|
|
295
|
+
description: 'The card UUID.',
|
|
296
|
+
},
|
|
297
|
+
provider: {
|
|
298
|
+
type: 'string',
|
|
299
|
+
description: 'Agent provider name.',
|
|
300
|
+
},
|
|
301
|
+
tokens: {
|
|
302
|
+
type: 'number',
|
|
303
|
+
description: 'Number of tokens consumed.',
|
|
304
|
+
},
|
|
305
|
+
cost_usd: {
|
|
306
|
+
type: 'number',
|
|
307
|
+
description: 'Estimated USD cost.',
|
|
308
|
+
},
|
|
309
|
+
note: {
|
|
310
|
+
type: 'string',
|
|
311
|
+
description: 'Optional note describing what the spend was used for.',
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
required: ['card_id', 'provider', 'tokens', 'cost_usd'],
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
name: 'agilemonster_set_budget',
|
|
319
|
+
description: 'Configure spend and token circuit-breaker limits for an Agile Monster task to protect against infinite loops.',
|
|
320
|
+
inputSchema: {
|
|
321
|
+
type: 'object',
|
|
322
|
+
properties: {
|
|
323
|
+
card_id: {
|
|
324
|
+
type: 'string',
|
|
325
|
+
description: 'The card UUID.',
|
|
326
|
+
},
|
|
327
|
+
max_budget_usd: {
|
|
328
|
+
type: 'number',
|
|
329
|
+
description: 'Maximum dollar budget allowed for this task (e.g. 5.00).',
|
|
330
|
+
},
|
|
331
|
+
max_tokens: {
|
|
332
|
+
type: 'number',
|
|
333
|
+
description: 'Maximum token budget allowed for this task (e.g. 150000).',
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
required: ['card_id'],
|
|
337
|
+
},
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
name: 'agilemonster_submit_for_review',
|
|
341
|
+
description: 'Handoff task to human: moves card to Testing/QA/Review column, reassigns the card to the human who requested it, sets status to "review", and posts step-by-step verification instructions.',
|
|
342
|
+
inputSchema: {
|
|
343
|
+
type: 'object',
|
|
344
|
+
properties: {
|
|
345
|
+
card_id: {
|
|
346
|
+
type: 'string',
|
|
347
|
+
description: 'The card UUID.',
|
|
348
|
+
},
|
|
349
|
+
provider: {
|
|
350
|
+
type: 'string',
|
|
351
|
+
description: 'Agent provider name.',
|
|
352
|
+
},
|
|
353
|
+
summary: {
|
|
354
|
+
type: 'string',
|
|
355
|
+
description: 'Summary of the work completed and files changed.',
|
|
356
|
+
},
|
|
357
|
+
verification_steps: {
|
|
358
|
+
type: 'string',
|
|
359
|
+
description: 'Step-by-step instructions for the user to test and verify the changes.',
|
|
360
|
+
},
|
|
361
|
+
target_list: {
|
|
362
|
+
type: 'string',
|
|
363
|
+
description: 'Optional name or ID of the testing/review column (e.g. "Testing", "QA", "In Review"). Auto-detected if omitted.',
|
|
364
|
+
},
|
|
365
|
+
target_list_id: {
|
|
366
|
+
type: 'string',
|
|
367
|
+
description: 'Optional ID of the review/testing column (legacy alias).',
|
|
368
|
+
},
|
|
369
|
+
assign_to_user_id: {
|
|
370
|
+
type: 'string',
|
|
371
|
+
description: 'Optional user UUID to assign to. Defaults to the human who created/requested the task.',
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
required: ['card_id', 'provider', 'summary'],
|
|
375
|
+
},
|
|
376
|
+
},
|
|
377
|
+
{
|
|
378
|
+
name: 'agilemonster_create_followup_tasks',
|
|
379
|
+
description: 'Suggest and create follow-up tasks on the board (e.g., "Deploy to Test", "Deploy to Production", "Write integration tests").',
|
|
380
|
+
inputSchema: {
|
|
381
|
+
type: 'object',
|
|
382
|
+
properties: {
|
|
383
|
+
card_id: {
|
|
384
|
+
type: 'string',
|
|
385
|
+
description: 'The parent card UUID.',
|
|
386
|
+
},
|
|
387
|
+
provider: {
|
|
388
|
+
type: 'string',
|
|
389
|
+
description: 'Agent provider name.',
|
|
390
|
+
},
|
|
391
|
+
tasks: {
|
|
392
|
+
type: 'array',
|
|
393
|
+
description: 'List of follow-up tasks to create.',
|
|
394
|
+
items: {
|
|
395
|
+
type: 'object',
|
|
396
|
+
properties: {
|
|
397
|
+
title: { type: 'string', description: 'Title of the follow-up task' },
|
|
398
|
+
description: { type: 'string', description: 'Details or instructions' },
|
|
399
|
+
list_id: { type: 'string', description: 'Target column list ID' },
|
|
400
|
+
agent_provider: { type: 'string', description: 'Optional agent worker to pre-assign' },
|
|
401
|
+
},
|
|
402
|
+
required: ['title'],
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
required: ['card_id', 'provider', 'tasks'],
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
name: 'agilemonster_block_task',
|
|
411
|
+
description: 'Block a task and reassign back to human user with a reason (e.g. missing credentials, ambiguous requirements, or upstream blockers). Sets status to blocked / waiting_for_input.',
|
|
412
|
+
inputSchema: {
|
|
413
|
+
type: 'object',
|
|
414
|
+
properties: {
|
|
415
|
+
card_id: {
|
|
416
|
+
type: 'string',
|
|
417
|
+
description: 'The card UUID to block.',
|
|
418
|
+
},
|
|
419
|
+
provider: {
|
|
420
|
+
type: 'string',
|
|
421
|
+
description: 'Agent provider name (e.g. antigravity, cursor, claude_code, windsurf).',
|
|
422
|
+
},
|
|
423
|
+
comment: {
|
|
424
|
+
type: 'string',
|
|
425
|
+
description: 'Detailed explanation of why the task is blocked and what is needed from the user to proceed.',
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
required: ['card_id'],
|
|
429
|
+
},
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
name: 'agilemonster_complete_task',
|
|
433
|
+
description: 'Mark task as complete and advance to the board Done list after testing and verification pass. Adds structured completion comment detailing deployment status (automated CI/CD run or user-controlled trigger instructions).',
|
|
434
|
+
inputSchema: {
|
|
435
|
+
type: 'object',
|
|
436
|
+
properties: {
|
|
437
|
+
card_id: {
|
|
438
|
+
type: 'string',
|
|
439
|
+
description: 'The card UUID to mark as completed.',
|
|
440
|
+
},
|
|
441
|
+
provider: {
|
|
442
|
+
type: 'string',
|
|
443
|
+
description: 'Agent provider name (e.g. antigravity, cursor, claude_code, windsurf).',
|
|
444
|
+
},
|
|
445
|
+
comment: {
|
|
446
|
+
type: 'string',
|
|
447
|
+
description: 'Detailed completion notes including test results and deployment details (auto-deployed CI/CD run ID/commit or manual trigger instructions).',
|
|
448
|
+
},
|
|
449
|
+
},
|
|
450
|
+
required: ['card_id'],
|
|
451
|
+
},
|
|
452
|
+
},
|
|
453
|
+
];
|
|
454
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
455
|
+
return { tools };
|
|
456
|
+
});
|
|
457
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
458
|
+
const { name, arguments: args = {} } = request.params;
|
|
459
|
+
const projectConfig = client.loadProjectConfig();
|
|
460
|
+
try {
|
|
461
|
+
switch (name) {
|
|
462
|
+
case 'agilemonster_get_context': {
|
|
463
|
+
const projectName = args.project_name ||
|
|
464
|
+
projectConfig?.board_name ||
|
|
465
|
+
path.basename(process.cwd());
|
|
466
|
+
const boardId = args.board_id || projectConfig?.board_id;
|
|
467
|
+
const context = await client.getContext(projectName, boardId);
|
|
468
|
+
return {
|
|
469
|
+
content: [
|
|
470
|
+
{
|
|
471
|
+
type: 'text',
|
|
472
|
+
text: JSON.stringify({
|
|
473
|
+
config_source: projectConfig ? '.agilemonster.json' : 'auto_matched',
|
|
474
|
+
project_config: projectConfig,
|
|
475
|
+
...context,
|
|
476
|
+
}, null, 2),
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
case 'agilemonster_init_project': {
|
|
482
|
+
const workspaceId = args.workspace_id;
|
|
483
|
+
const boardId = args.board_id;
|
|
484
|
+
const provider = args.provider || projectConfig?.provider || 'antigravity';
|
|
485
|
+
const reviewList = args.review_list || projectConfig?.review_list;
|
|
486
|
+
const savedPath = client.saveProjectConfig({
|
|
487
|
+
workspace_id: workspaceId,
|
|
488
|
+
board_id: boardId,
|
|
489
|
+
provider,
|
|
490
|
+
review_list: reviewList,
|
|
491
|
+
});
|
|
492
|
+
// Ensure AGENTS.md exists in the project root
|
|
493
|
+
const agentsMdPath = path.resolve(process.cwd(), 'AGENTS.md');
|
|
494
|
+
let agentsMdCreated = false;
|
|
495
|
+
if (!fs.existsSync(agentsMdPath)) {
|
|
496
|
+
fs.writeFileSync(agentsMdPath, AGENT_GUIDELINES_MARKDOWN, 'utf-8');
|
|
497
|
+
agentsMdCreated = true;
|
|
498
|
+
}
|
|
499
|
+
return {
|
|
500
|
+
content: [
|
|
501
|
+
{
|
|
502
|
+
type: 'text',
|
|
503
|
+
text: `Successfully initialized Agile Monster project config at ${savedPath}:\n` +
|
|
504
|
+
JSON.stringify({ workspace_id: workspaceId, board_id: boardId, provider }, null, 2) +
|
|
505
|
+
(agentsMdCreated ? `\n• Generated AGENTS.md with AI agent operational protocols.` : `\n• AGENTS.md already present.`),
|
|
506
|
+
},
|
|
507
|
+
],
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
case 'agilemonster_list_my_tasks': {
|
|
511
|
+
const provider = args.provider || projectConfig?.provider || 'any';
|
|
512
|
+
const status = args.status;
|
|
513
|
+
const boardId = args.board_id || projectConfig?.board_id;
|
|
514
|
+
const workspaceId = projectConfig?.workspace_id;
|
|
515
|
+
const result = await client.listAssigned(provider, status, boardId, workspaceId);
|
|
516
|
+
return {
|
|
517
|
+
content: [
|
|
518
|
+
{
|
|
519
|
+
type: 'text',
|
|
520
|
+
text: JSON.stringify(result, null, 2),
|
|
521
|
+
},
|
|
522
|
+
],
|
|
523
|
+
};
|
|
524
|
+
}
|
|
525
|
+
case 'agilemonster_claim_task': {
|
|
526
|
+
const cardId = args.card_id;
|
|
527
|
+
const provider = args.provider || projectConfig?.provider || 'antigravity';
|
|
528
|
+
const runRef = args.run_ref;
|
|
529
|
+
const card = await client.claimTask(cardId, provider, runRef);
|
|
530
|
+
return {
|
|
531
|
+
content: [
|
|
532
|
+
{
|
|
533
|
+
type: 'text',
|
|
534
|
+
text: `Task claimed successfully. Status is now "in_progress".\n${JSON.stringify(card, null, 2)}`,
|
|
535
|
+
},
|
|
536
|
+
],
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
case 'agilemonster_ask_question': {
|
|
540
|
+
const cardId = args.card_id;
|
|
541
|
+
const provider = args.provider || projectConfig?.provider || 'antigravity';
|
|
542
|
+
const question = args.question;
|
|
543
|
+
const card = await client.askQuestion(cardId, provider, question);
|
|
544
|
+
return {
|
|
545
|
+
content: [
|
|
546
|
+
{
|
|
547
|
+
type: 'text',
|
|
548
|
+
text: `Question posted on task ${cardId}. Status set to "waiting_for_input".\n${JSON.stringify(card, null, 2)}`,
|
|
549
|
+
},
|
|
550
|
+
],
|
|
551
|
+
};
|
|
552
|
+
}
|
|
553
|
+
case 'agilemonster_add_progress': {
|
|
554
|
+
const cardId = args.card_id;
|
|
555
|
+
const provider = args.provider || projectConfig?.provider || 'antigravity';
|
|
556
|
+
const update = args.update;
|
|
557
|
+
const tokensUsed = args.tokens_used;
|
|
558
|
+
const costUsd = args.cost_usd;
|
|
559
|
+
const card = await client.addProgress(cardId, provider, update, tokensUsed, costUsd);
|
|
560
|
+
return {
|
|
561
|
+
content: [
|
|
562
|
+
{
|
|
563
|
+
type: 'text',
|
|
564
|
+
text: `Progress update posted to task ${cardId}.\n${JSON.stringify(card, null, 2)}`,
|
|
565
|
+
},
|
|
566
|
+
],
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
case 'agilemonster_record_spend': {
|
|
570
|
+
const cardId = args.card_id;
|
|
571
|
+
const provider = args.provider || projectConfig?.provider || 'antigravity';
|
|
572
|
+
const tokens = args.tokens || 0;
|
|
573
|
+
const costUsd = args.cost_usd || 0;
|
|
574
|
+
const note = args.note;
|
|
575
|
+
const card = await client.recordSpend(cardId, provider, tokens, costUsd, note);
|
|
576
|
+
return {
|
|
577
|
+
content: [
|
|
578
|
+
{
|
|
579
|
+
type: 'text',
|
|
580
|
+
text: `LLM Spend recorded for task ${cardId}: +${tokens} tokens, +$${costUsd}.\n${JSON.stringify(card, null, 2)}`,
|
|
581
|
+
},
|
|
582
|
+
],
|
|
583
|
+
};
|
|
584
|
+
}
|
|
585
|
+
case 'agilemonster_set_budget': {
|
|
586
|
+
const cardId = args.card_id;
|
|
587
|
+
const maxBudgetUsd = args.max_budget_usd !== undefined ? args.max_budget_usd : null;
|
|
588
|
+
const maxTokens = args.max_tokens !== undefined ? args.max_tokens : null;
|
|
589
|
+
const card = await client.setBudget(cardId, maxBudgetUsd, maxTokens);
|
|
590
|
+
return {
|
|
591
|
+
content: [
|
|
592
|
+
{
|
|
593
|
+
type: 'text',
|
|
594
|
+
text: `Circuit-breaker budget configured for task ${cardId}.\n${JSON.stringify(card, null, 2)}`,
|
|
595
|
+
},
|
|
596
|
+
],
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
case 'agilemonster_submit_for_review': {
|
|
600
|
+
const cardId = args.card_id;
|
|
601
|
+
const provider = args.provider || projectConfig?.provider || 'antigravity';
|
|
602
|
+
const summary = args.summary;
|
|
603
|
+
const verificationSteps = args.verification_steps;
|
|
604
|
+
const targetList = args.target_list || args.target_list_id || undefined;
|
|
605
|
+
const assignToUserId = args.assign_to_user_id;
|
|
606
|
+
const card = await client.submitReview(cardId, provider, summary, verificationSteps, targetList, assignToUserId);
|
|
607
|
+
return {
|
|
608
|
+
content: [
|
|
609
|
+
{
|
|
610
|
+
type: 'text',
|
|
611
|
+
text: `Task ${cardId} moved to testing/review and reassigned back to human requester for confirmation.\n${JSON.stringify(card, null, 2)}`,
|
|
612
|
+
},
|
|
613
|
+
],
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
case 'agilemonster_create_followup_tasks': {
|
|
617
|
+
const cardId = args.card_id;
|
|
618
|
+
const provider = args.provider || projectConfig?.provider || 'antigravity';
|
|
619
|
+
const tasks = args.tasks;
|
|
620
|
+
const result = await client.createFollowupTasks(cardId, provider, tasks);
|
|
621
|
+
return {
|
|
622
|
+
content: [
|
|
623
|
+
{
|
|
624
|
+
type: 'text',
|
|
625
|
+
text: `Created ${result.tasks.length} follow-up task(s) on the board:\n${JSON.stringify(result.tasks, null, 2)}`,
|
|
626
|
+
},
|
|
627
|
+
],
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
case 'agilemonster_block_task': {
|
|
631
|
+
const cardId = args.card_id;
|
|
632
|
+
const provider = args.provider || projectConfig?.provider || 'antigravity';
|
|
633
|
+
const comment = args.comment;
|
|
634
|
+
const card = await client.blockTask(cardId, provider, comment);
|
|
635
|
+
return {
|
|
636
|
+
content: [
|
|
637
|
+
{
|
|
638
|
+
type: 'text',
|
|
639
|
+
text: `Task ${cardId} marked as blocked and reassigned back to human teammate.\n${JSON.stringify(card, null, 2)}`,
|
|
640
|
+
},
|
|
641
|
+
],
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
case 'agilemonster_complete_task': {
|
|
645
|
+
const cardId = args.card_id;
|
|
646
|
+
const provider = args.provider || projectConfig?.provider || 'antigravity';
|
|
647
|
+
const comment = args.comment;
|
|
648
|
+
const card = await client.completeTask(cardId, provider, comment);
|
|
649
|
+
return {
|
|
650
|
+
content: [
|
|
651
|
+
{
|
|
652
|
+
type: 'text',
|
|
653
|
+
text: `Task ${cardId} marked as Done and completed successfully.\n${JSON.stringify(card, null, 2)}`,
|
|
654
|
+
},
|
|
655
|
+
],
|
|
656
|
+
};
|
|
657
|
+
}
|
|
658
|
+
default:
|
|
659
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
catch (error) {
|
|
663
|
+
return {
|
|
664
|
+
isError: true,
|
|
665
|
+
content: [
|
|
666
|
+
{
|
|
667
|
+
type: 'text',
|
|
668
|
+
text: `Error executing ${name}: ${error?.message || String(error)}`,
|
|
669
|
+
},
|
|
670
|
+
],
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
});
|
|
674
|
+
return server;
|
|
675
|
+
}
|
|
676
|
+
export async function runStdioServer() {
|
|
677
|
+
const server = createServer();
|
|
678
|
+
const transport = new StdioServerTransport();
|
|
679
|
+
await server.connect(transport);
|
|
680
|
+
}
|