@agilemonster/mcp-server 1.0.5 ā 1.0.6
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/client.d.ts +1 -1
- package/dist/client.js +3 -2
- package/dist/orchestrator.js +33 -13
- package/dist/server.js +34 -3
- package/dist/types.d.ts +2 -0
- package/dist/worker.js +5 -1
- package/package.json +1 -1
package/dist/client.d.ts
CHANGED
|
@@ -33,7 +33,7 @@ export declare class AgileMonsterClient {
|
|
|
33
33
|
provider: string;
|
|
34
34
|
cards: Card[];
|
|
35
35
|
}>;
|
|
36
|
-
claimTask(cardId: string, provider: string, runRef?: string): Promise<Card>;
|
|
36
|
+
claimTask(cardId: string, provider: string, runRef?: string, expectedBoardId?: string): Promise<Card>;
|
|
37
37
|
askQuestion(cardId: string, provider: string, question: string): Promise<Card>;
|
|
38
38
|
addProgress(cardId: string, provider: string, update: string, tokensUsed?: number, costUsd?: number): Promise<Card>;
|
|
39
39
|
recordSpend(cardId: string, provider: string, tokens: number, costUsd: number, note?: string): Promise<Card>;
|
package/dist/client.js
CHANGED
|
@@ -195,10 +195,11 @@ export class AgileMonsterClient {
|
|
|
195
195
|
const qs = params.toString();
|
|
196
196
|
return this.request(`/api/agent/assigned${qs ? `?${qs}` : ''}`);
|
|
197
197
|
}
|
|
198
|
-
async claimTask(cardId, provider, runRef) {
|
|
198
|
+
async claimTask(cardId, provider, runRef, expectedBoardId) {
|
|
199
|
+
const boardId = expectedBoardId || this.loadProjectConfig()?.board_id;
|
|
199
200
|
return this.request(`/api/agent/cards/${cardId}/claim`, {
|
|
200
201
|
method: 'POST',
|
|
201
|
-
body: JSON.stringify({ provider, run_ref: runRef }),
|
|
202
|
+
body: JSON.stringify({ provider, run_ref: runRef, board_id: boardId }),
|
|
202
203
|
});
|
|
203
204
|
}
|
|
204
205
|
async askQuestion(cardId, provider, question) {
|
package/dist/orchestrator.js
CHANGED
|
@@ -12,6 +12,10 @@ export class AgileMonsterOrchestrator {
|
|
|
12
12
|
const projectConfig = this.client.loadProjectConfig();
|
|
13
13
|
const provider = options?.provider || projectConfig?.provider || 'any';
|
|
14
14
|
const boardId = options?.boardId || projectConfig?.board_id;
|
|
15
|
+
// STRICT BOARD SCOPE GUARD: Never poll across all boards when current folder is unbound!
|
|
16
|
+
if (!boardId) {
|
|
17
|
+
return [];
|
|
18
|
+
}
|
|
15
19
|
const result = await this.client.listAssigned(provider, undefined, boardId);
|
|
16
20
|
return result.cards || [];
|
|
17
21
|
}
|
|
@@ -34,8 +38,10 @@ export class AgileMonsterOrchestrator {
|
|
|
34
38
|
console.log(`š¤ Default Provider: ${config.provider || 'any'}`);
|
|
35
39
|
}
|
|
36
40
|
else {
|
|
37
|
-
console.log(
|
|
38
|
-
console.log('
|
|
41
|
+
console.log(`ā ļø [UNBOUND REPOSITORY] No .agilemonster.json found in "${cwdName}".`);
|
|
42
|
+
console.log(' To prevent agents from picking up tasks from the wrong board and burning tokens:');
|
|
43
|
+
console.log(' Run "npx -y @agilemonster/mcp-server bootstrap" in this folder first!\n');
|
|
44
|
+
return;
|
|
39
45
|
}
|
|
40
46
|
console.log('\nš Checking for assigned agent tasks...');
|
|
41
47
|
const tasks = await this.checkTasks();
|
|
@@ -217,13 +223,24 @@ export class AgileMonsterOrchestrator {
|
|
|
217
223
|
else {
|
|
218
224
|
const num = parseInt(choice, 10);
|
|
219
225
|
if (!Number.isNaN(num) && num >= 1 && num <= boards.length) {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
226
|
+
const candidate = boards[num - 1];
|
|
227
|
+
// Safety confirmation if user picks an existing board that AI said didn't match this folder
|
|
228
|
+
if (aiMatch &&
|
|
229
|
+
aiMatch.matched_board_id !== candidate.id &&
|
|
230
|
+
candidate.name.toLowerCase() !== folderName.toLowerCase()) {
|
|
231
|
+
const confirm = (await rl.question(`ā ļø Safety Check: Folder is "${folderName}" but board is "${candidate.name}". Are you sure they are the same project? [y/N]: `))
|
|
232
|
+
.trim()
|
|
233
|
+
.toLowerCase();
|
|
234
|
+
if (confirm !== 'y' && confirm !== 'yes') {
|
|
235
|
+
console.log('ā Cancelled to prevent connecting the wrong board.');
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
targetBoard = candidate;
|
|
224
240
|
}
|
|
225
241
|
else {
|
|
226
|
-
|
|
242
|
+
console.error(`ā Invalid selection "${choice}". Aborting so we never bind the wrong board.`);
|
|
243
|
+
return;
|
|
227
244
|
}
|
|
228
245
|
}
|
|
229
246
|
}
|
|
@@ -232,14 +249,15 @@ export class AgileMonsterOrchestrator {
|
|
|
232
249
|
}
|
|
233
250
|
}
|
|
234
251
|
else {
|
|
235
|
-
// Non-interactive
|
|
236
|
-
if
|
|
252
|
+
// Non-interactive mode: ONLY auto-bind if AI matched with high confidence OR --board was explicitly passed.
|
|
253
|
+
// NEVER auto-pick a board or create a board silently if ambiguous!
|
|
254
|
+
if (context.matched_board && aiMatch?.confidence === 'high') {
|
|
237
255
|
targetBoard = context.matched_board;
|
|
238
256
|
}
|
|
239
|
-
else
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
257
|
+
else {
|
|
258
|
+
console.error(`ā Ambiguous board match for folder "${folderName}" in non-interactive mode.`);
|
|
259
|
+
console.error(` Please run interactively in your terminal or pass --board="<Board Name>" explicitly so we never connect the wrong board.`);
|
|
260
|
+
return;
|
|
243
261
|
}
|
|
244
262
|
}
|
|
245
263
|
}
|
|
@@ -288,6 +306,8 @@ export class AgileMonsterOrchestrator {
|
|
|
288
306
|
workspace_id: targetBoard.workspace_id,
|
|
289
307
|
board_id: targetBoard.id,
|
|
290
308
|
board_name: targetBoard.name,
|
|
309
|
+
project_name: folderName,
|
|
310
|
+
project_path: process.cwd(),
|
|
291
311
|
provider: options?.provider || 'antigravity',
|
|
292
312
|
review_list: 'In Review',
|
|
293
313
|
done_list: 'Done',
|
package/dist/server.js
CHANGED
|
@@ -512,12 +512,30 @@ Please strictly follow the Agile Monster Task Lifecycle Protocol:
|
|
|
512
512
|
const status = args.status;
|
|
513
513
|
const boardId = args.board_id || projectConfig?.board_id;
|
|
514
514
|
const workspaceId = projectConfig?.workspace_id;
|
|
515
|
+
if (!boardId) {
|
|
516
|
+
return {
|
|
517
|
+
isError: true,
|
|
518
|
+
content: [
|
|
519
|
+
{
|
|
520
|
+
type: 'text',
|
|
521
|
+
text: `ā ļø [BOARD SCOPE GUARD] Current project folder "${path.basename(process.cwd())}" is not bound to an Agile Monster board (.agilemonster.json is missing).\n` +
|
|
522
|
+
`Refusing to list tasks across all boards so you never accidentally pick up a task from the wrong project and burn tokens.\n` +
|
|
523
|
+
`Please run "npx -y @agilemonster/mcp-server bootstrap" in this folder or call agilemonster_get_context first to bind the right board.`,
|
|
524
|
+
},
|
|
525
|
+
],
|
|
526
|
+
};
|
|
527
|
+
}
|
|
515
528
|
const result = await client.listAssigned(provider, status, boardId, workspaceId);
|
|
516
529
|
return {
|
|
517
530
|
content: [
|
|
518
531
|
{
|
|
519
532
|
type: 'text',
|
|
520
|
-
text: JSON.stringify(
|
|
533
|
+
text: JSON.stringify({
|
|
534
|
+
bound_board_id: boardId,
|
|
535
|
+
bound_board_name: projectConfig?.board_name,
|
|
536
|
+
bound_project_name: projectConfig?.project_name || path.basename(process.cwd()),
|
|
537
|
+
...result,
|
|
538
|
+
}, null, 2),
|
|
521
539
|
},
|
|
522
540
|
],
|
|
523
541
|
};
|
|
@@ -526,12 +544,25 @@ Please strictly follow the Agile Monster Task Lifecycle Protocol:
|
|
|
526
544
|
const cardId = args.card_id;
|
|
527
545
|
const provider = args.provider || projectConfig?.provider || 'antigravity';
|
|
528
546
|
const runRef = args.run_ref;
|
|
529
|
-
const
|
|
547
|
+
const expectedBoardId = projectConfig?.board_id;
|
|
548
|
+
if (!expectedBoardId) {
|
|
549
|
+
return {
|
|
550
|
+
isError: true,
|
|
551
|
+
content: [
|
|
552
|
+
{
|
|
553
|
+
type: 'text',
|
|
554
|
+
text: `ā ļø [BOARD SCOPE GUARD] Cannot claim card ${cardId} because this repository folder ("${path.basename(process.cwd())}") has no .agilemonster.json board binding.\n` +
|
|
555
|
+
`Run "npx -y @agilemonster/mcp-server bootstrap" first so we verify this folder matches the card's board.`,
|
|
556
|
+
},
|
|
557
|
+
],
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
const card = await client.claimTask(cardId, provider, runRef, expectedBoardId);
|
|
530
561
|
return {
|
|
531
562
|
content: [
|
|
532
563
|
{
|
|
533
564
|
type: 'text',
|
|
534
|
-
text: `Task claimed successfully. Status is now "in_progress".\n${JSON.stringify(card, null, 2)}`,
|
|
565
|
+
text: `Task claimed successfully on board "${card.board_name || expectedBoardId}". Status is now "in_progress".\n${JSON.stringify(card, null, 2)}`,
|
|
535
566
|
},
|
|
536
567
|
],
|
|
537
568
|
};
|
package/dist/types.d.ts
CHANGED
package/dist/worker.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { spawn } from 'node:child_process';
|
|
2
|
+
import path from 'node:path';
|
|
2
3
|
import { AgileMonsterClient } from './client.js';
|
|
3
4
|
export class AgileMonsterWorker {
|
|
4
5
|
client;
|
|
@@ -59,8 +60,11 @@ export class AgileMonsterWorker {
|
|
|
59
60
|
const projectConfig = this.client.loadProjectConfig();
|
|
60
61
|
const provider = options.provider || projectConfig?.provider || 'antigravity';
|
|
61
62
|
const boardId = options.boardId || projectConfig?.board_id;
|
|
63
|
+
if (!boardId) {
|
|
64
|
+
throw new Error(`[Board Scope Guard] No .agilemonster.json board binding found in "${path.basename(process.cwd())}". Refusing to poll tasks without an explicit board binding.`);
|
|
65
|
+
}
|
|
62
66
|
const res = await this.client.listAssigned(provider, 'queued', boardId);
|
|
63
|
-
const tasks = res.cards || [];
|
|
67
|
+
const tasks = (res.cards || []).filter((c) => !c.board_id || c.board_id === boardId);
|
|
64
68
|
if (tasks.length === 0) {
|
|
65
69
|
return;
|
|
66
70
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agilemonster/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Official Model Context Protocol (MCP) server & Orchestrator for Agile Monster (Cursor, Claude Code, Antigravity, Codex, Hermes, Windsurf)",
|
|
6
6
|
"main": "dist/server.js",
|