@agilemonster/mcp-server 0.0.0-stage → 1.0.0

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 CHANGED
@@ -1,3 +1,131 @@
1
- # Temporary Holding Version
1
+ # @agilemonster/mcp-server & Agent Orchestrator
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Official Model Context Protocol (MCP) Server and Autonomous Agent Orchestrator for **Agile Monster** ([https://app.agilemonster.com](https://app.agilemonster.com)).
4
+
5
+ Seamlessly connects your Agile Monster boards with your favorite developer AI agents:
6
+ - **Cursor**
7
+ - **Claude Code**
8
+ - **Antigravity / Gemini Code Assist**
9
+ - **Codex**
10
+ - **Hermes Agent**
11
+ - **Windsurf / Aider**
12
+
13
+ ---
14
+
15
+ ## ⚡ Quick Start: Adding to your AI Agent
16
+
17
+ Generate a **Personal API Key** in Agile Monster ([https://app.agilemonster.com](https://app.agilemonster.com) -> Profile -> API Keys). Your key will look like `am_live_...`.
18
+
19
+ ### 1. Cursor (`.cursor/mcp.json` or Global Settings)
20
+ ```json
21
+ {
22
+ "mcpServers": {
23
+ "agilemonster": {
24
+ "command": "npx",
25
+ "args": ["-y", "@agilemonster/mcp-server"],
26
+ "env": {
27
+ "AGILEMONSTER_API_KEY": "am_live_your_token_here",
28
+ "AGILEMONSTER_API_URL": "https://api.agilemonster.com"
29
+ }
30
+ }
31
+ }
32
+ }
33
+ ```
34
+
35
+ ### 2. Claude Code CLI
36
+ ```bash
37
+ claude mcp add agilemonster npx -y @agilemonster/mcp-server \
38
+ -e AGILEMONSTER_API_KEY="am_live_your_token_here" \
39
+ -e AGILEMONSTER_API_URL="https://api.agilemonster.com"
40
+ ```
41
+
42
+ ### 3. Antigravity / Gemini
43
+ Add to your Antigravity MCP directory (`~/.gemini/antigravity/mcp/agilemonster` or project settings):
44
+ ```json
45
+ {
46
+ "mcpServers": {
47
+ "agilemonster": {
48
+ "command": "node",
49
+ "args": ["/path/to/agilemonster/packages/mcp-server/bin/mcp.js"],
50
+ "env": {
51
+ "AGILEMONSTER_API_KEY": "am_live_your_token_here",
52
+ "AGILEMONSTER_API_URL": "https://api.agilemonster.com"
53
+ }
54
+ }
55
+ }
56
+ }
57
+ ```
58
+
59
+ ---
60
+
61
+ ## 📁 1-Click Project Initialization (`init`)
62
+
63
+ To automatically bind your repository to an Agile Monster board and generate operational instructions for your AI agents in one command, run:
64
+
65
+ ```bash
66
+ npx @agilemonster/mcp-server init
67
+ ```
68
+
69
+ This generates:
70
+ 1. `.agilemonster.json` — Binds the local repository to the board UUID, list columns, and default agent provider.
71
+ 2. `AGENTS.md` — Codified operational rules for autonomous agents (Cursor, Claude Code, Antigravity, etc.) so they know when to claim tasks, ask clarifying questions, log progress, and submit work for human testing.
72
+
73
+ ---
74
+
75
+ ## 🛠️ Available MCP Tools
76
+
77
+ Agents have access to 8 purpose-built lifecycle tools:
78
+
79
+ | Tool | Purpose |
80
+ | :--- | :--- |
81
+ | `agilemonster_get_context` | Inspects board, columns, and active tasks. Auto-detects project from `.agilemonster.json` or directory name. |
82
+ | `agilemonster_init_project` | Binds current repo to an Agile Monster board and creates `AGENTS.md`. |
83
+ | `agilemonster_list_my_tasks` | Lists cards assigned to the AI agent (`queued`, `in_progress`, `waiting_for_input`, `review`). |
84
+ | `agilemonster_claim_task` | Claims a task, marking it `in_progress` on the board before code edits start. |
85
+ | `agilemonster_ask_question` | Posts a question comment on the card and marks status as `waiting_for_input` so the user is alerted. |
86
+ | `agilemonster_add_progress` | Logs implementation progress notes to task comments. |
87
+ | `agilemonster_submit_for_review` | Marks work complete, moves card to Review column, reassigns to human member for confirmation, and posts test instructions. |
88
+ | `agilemonster_create_followup_tasks` | Creates follow-up cards (e.g. "Deploy to Test", "Deploy to Production", "Write integration tests"). |
89
+
90
+ ---
91
+
92
+ ## 💡 MCP Native Prompts & Resources
93
+
94
+ The server exposes Model Context Protocol **Prompts** and **Resources** so agents can automatically load operational instructions into their context:
95
+
96
+ ### Prompts
97
+ - `agilemonster_agent_protocol`: System instructions explaining the full task lifecycle protocol.
98
+ - `agilemonster_work_on_task`: Guided workflow prompt for an agent to claim, investigate, implement, test, submit for review, and propose follow-up tasks for a specific card ID.
99
+
100
+ ### Resources
101
+ - `agilemonster://guidelines/agents`: Live markdown text of the official Agent Guidelines (`text/markdown`).
102
+ - `agilemonster://project/context`: Current repository board, list structure, and active agent tasks as live JSON (`application/json`).
103
+
104
+ ---
105
+
106
+ ## 🤖 The Autonomous Agent Orchestrator CLI
107
+
108
+ Use the built-in orchestrator to monitor tasks, dispatch work, or run a background watcher:
109
+
110
+ ```bash
111
+ # Check current tasks assigned to agents for this project
112
+ npx @agilemonster/mcp-server status
113
+
114
+ # Watch for newly assigned tasks in real-time
115
+ npx @agilemonster/mcp-server watch
116
+
117
+ # Claim a task
118
+ npx @agilemonster/mcp-server claim <card_id>
119
+
120
+ # Submit for user testing & confirmation
121
+ npx @agilemonster/mcp-server review <card_id> "Implemented dark mode toggle" "Test via Settings screen"
122
+
123
+ # Ask the user a question
124
+ npx @agilemonster/mcp-server question <card_id> "Should we support OAuth tokens as well?"
125
+ ```
126
+
127
+ ---
128
+
129
+ ## 📚 REST API Reference
130
+
131
+ For developers building custom scripts, CI/CD bots, or proprietary agent orchestrators, refer to the full REST API specification in [`docs/AGENT-API.md`](../../docs/AGENT-API.md).
package/bin/mcp.js ADDED
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ import { runStdioServer } from '../dist/server.js';
3
+
4
+ const cliCommands = new Set([
5
+ 'bootstrap',
6
+ 'setup',
7
+ 'init',
8
+ 'status',
9
+ 'check',
10
+ 'list',
11
+ 'watch',
12
+ 'daemon',
13
+ 'claim',
14
+ 'review',
15
+ 'question',
16
+ 'help',
17
+ '--help',
18
+ '-h',
19
+ ]);
20
+
21
+ const firstArg = process.argv[2];
22
+ if (firstArg && cliCommands.has(firstArg)) {
23
+ // Delegate to orchestrator CLI
24
+ await import('./orchestrator.js');
25
+ } else {
26
+ runStdioServer().catch((error) => {
27
+ console.error('Fatal MCP Server Error:', error);
28
+ process.exit(1);
29
+ });
30
+ }
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ import { AgileMonsterOrchestrator } from '../dist/orchestrator.js';
3
+ import { AgileMonsterClient } from '../dist/client.js';
4
+
5
+ const client = new AgileMonsterClient();
6
+ const orchestrator = new AgileMonsterOrchestrator(client);
7
+
8
+ const args = process.argv.slice(2);
9
+ const command = args[0] || 'status';
10
+
11
+ async function main() {
12
+ switch (command) {
13
+ case 'status':
14
+ case 'check':
15
+ case 'list':
16
+ await orchestrator.printDashboard();
17
+ break;
18
+
19
+ case 'watch':
20
+ case 'daemon':
21
+ await orchestrator.runDaemon({
22
+ intervalMs: 10000,
23
+ });
24
+ break;
25
+
26
+ case 'bootstrap':
27
+ case 'setup':
28
+ case 'init': {
29
+ const ideArg = args.find((a) => a.startsWith('--ide='))?.split('=')[1] || args[1];
30
+ await orchestrator.initInteractive({ ide: ideArg });
31
+ break;
32
+ }
33
+
34
+ case 'claim': {
35
+ const cardId = args[1];
36
+ if (!cardId) {
37
+ console.error('Usage: agilemonster-orchestrator claim <cardId> [provider]');
38
+ process.exit(1);
39
+ }
40
+ const provider = args[2] || client.loadProjectConfig()?.provider || 'antigravity';
41
+ const result = await client.claimTask(cardId, provider);
42
+ console.log(`✅ Claimed task: ${result.title} (${result.id})`);
43
+ break;
44
+ }
45
+
46
+ case 'review': {
47
+ const cardId = args[1];
48
+ const summary = args[2];
49
+ if (!cardId || !summary) {
50
+ console.error('Usage: agilemonster-orchestrator review <cardId> "<summary>" [verificationSteps]');
51
+ process.exit(1);
52
+ }
53
+ const verificationSteps = args[3];
54
+ const provider = client.loadProjectConfig()?.provider || 'antigravity';
55
+ const result = await client.submitReview(cardId, provider, summary, verificationSteps);
56
+ console.log(`✅ Submitted task for review & testing: ${result.title} (${result.id})`);
57
+ break;
58
+ }
59
+
60
+ case 'question': {
61
+ const cardId = args[1];
62
+ const question = args[2];
63
+ if (!cardId || !question) {
64
+ console.error('Usage: agilemonster-orchestrator question <cardId> "<question>"');
65
+ process.exit(1);
66
+ }
67
+ const provider = client.loadProjectConfig()?.provider || 'antigravity';
68
+ const result = await client.askQuestion(cardId, provider, question);
69
+ console.log(`✅ Question posted to task: ${result.title}`);
70
+ break;
71
+ }
72
+
73
+ default:
74
+ console.log(`
75
+ Agile Monster Agent Orchestrator CLI
76
+
77
+ Commands:
78
+ agilemonster-orchestrator (or status) Show active agent tasks and project binding
79
+ agilemonster-orchestrator watch Run background daemon to watch for newly queued tasks
80
+ agilemonster-orchestrator init Bind current directory to an Agile Monster board
81
+ agilemonster-orchestrator claim <id> Claim a task and mark it in-progress
82
+ agilemonster-orchestrator review <id> "..." Submit task for user review & confirmation
83
+ agilemonster-orchestrator question <id> "..." Ask the user a clarifying question
84
+ `);
85
+ break;
86
+ }
87
+ }
88
+
89
+ main().catch((err) => {
90
+ console.error('Orchestrator Error:', err.message || err);
91
+ process.exit(1);
92
+ });
package/bin/worker.js ADDED
@@ -0,0 +1,69 @@
1
+ #!/usr/bin/env node
2
+ import { AgileMonsterWorker } from '../dist/worker.js';
3
+ import { AgileMonsterClient } from '../dist/client.js';
4
+
5
+ const client = new AgileMonsterClient();
6
+ const worker = new AgileMonsterWorker(client);
7
+
8
+ const args = process.argv.slice(2);
9
+
10
+ function getArg(prefix, fallback) {
11
+ const found = args.find((a) => a.startsWith(prefix));
12
+ if (found) {
13
+ return found.split('=')[1];
14
+ }
15
+ return fallback;
16
+ }
17
+
18
+ const hasFlag = (flag) => args.includes(flag);
19
+
20
+ if (hasFlag('--help') || hasFlag('-h')) {
21
+ console.log(`
22
+ Agile Monster Autonomous Agent Worker
23
+
24
+ Usage:
25
+ agilemonster-worker [options]
26
+
27
+ Options:
28
+ --runner=<engine> Execution engine: simulated (default), aider, claude, shell
29
+ --command="<cmd>" Shell command to execute when runner=shell
30
+ --provider=<agent> Target agent provider: antigravity (default), cursor, aider, etc.
31
+ --interval=<seconds> Polling interval in seconds (default: 15)
32
+ --heartbeat=<seconds> Heartbeat progress update interval (default: 30)
33
+ --max-budget=<usd> Circuit-breaker USD budget limit per task (default: 5.00)
34
+ --max-tokens=<count> Circuit-breaker token limit per task (default: 200000)
35
+ --no-branch Do not create an isolated git branch for the task
36
+ --once Process at most one queued task and exit
37
+ --help, -h Show this help screen
38
+ `);
39
+ process.exit(0);
40
+ }
41
+
42
+ const runner = getArg('--runner', 'simulated');
43
+ const customCommand = getArg('--command', undefined);
44
+ const provider = getArg('--provider', undefined);
45
+ const intervalSec = parseInt(getArg('--interval', '15'), 10);
46
+ const heartbeatSec = parseInt(getArg('--heartbeat', '30'), 10);
47
+ const maxBudgetUsd = parseFloat(getArg('--max-budget', '5.0'));
48
+ const maxTokens = parseInt(getArg('--max-tokens', '200000'), 10);
49
+ const gitBranch = !hasFlag('--no-branch');
50
+ const once = hasFlag('--once');
51
+
52
+ async function main() {
53
+ await worker.start({
54
+ runner,
55
+ customCommand,
56
+ provider,
57
+ intervalMs: intervalSec * 1000,
58
+ heartbeatMs: heartbeatSec * 1000,
59
+ maxBudgetUsd,
60
+ maxTokens,
61
+ gitBranch,
62
+ once,
63
+ });
64
+ }
65
+
66
+ main().catch((err) => {
67
+ console.error('Fatal Worker Error:', err.message || err);
68
+ process.exit(1);
69
+ });
@@ -0,0 +1,48 @@
1
+ import { AgileMonsterProjectConfig, Card, ContextResponse } from './types.js';
2
+ export declare class AgileMonsterClient {
3
+ private apiKey;
4
+ private baseUrl;
5
+ private cwd;
6
+ private cachedConfig;
7
+ constructor(options?: {
8
+ apiKey?: string;
9
+ baseUrl?: string;
10
+ cwd?: string;
11
+ });
12
+ private resolveApiKey;
13
+ getApiKey(): string;
14
+ setApiKey(key: string): void;
15
+ loadProjectConfig(): AgileMonsterProjectConfig | null;
16
+ saveProjectConfig(config: AgileMonsterProjectConfig, dir?: string): string;
17
+ static saveGlobalConfig(data: {
18
+ api_key?: string;
19
+ }): string;
20
+ private request;
21
+ me(): Promise<{
22
+ id: string;
23
+ email: string;
24
+ first_name?: string;
25
+ last_name?: string;
26
+ }>;
27
+ getContext(projectName?: string, boardId?: string): Promise<ContextResponse>;
28
+ listAssigned(provider?: string, status?: string, boardId?: string, workspaceId?: string): Promise<{
29
+ provider: string;
30
+ cards: Card[];
31
+ }>;
32
+ claimTask(cardId: string, provider: string, runRef?: string): Promise<Card>;
33
+ askQuestion(cardId: string, provider: string, question: string): Promise<Card>;
34
+ addProgress(cardId: string, provider: string, update: string, tokensUsed?: number, costUsd?: number): Promise<Card>;
35
+ recordSpend(cardId: string, provider: string, tokens: number, costUsd: number, note?: string): Promise<Card>;
36
+ setBudget(cardId: string, maxBudgetUsd?: number | null, maxTokens?: number | null): Promise<Card>;
37
+ submitReview(cardId: string, provider: string, summary: string, verificationSteps?: string, targetList?: string, assignToUserId?: string): Promise<Card>;
38
+ completeTask(cardId: string, provider: string, comment?: string): Promise<Card>;
39
+ blockTask(cardId: string, provider: string, comment?: string): Promise<Card>;
40
+ createFollowupTasks(cardId: string, provider: string, tasks: Array<{
41
+ title: string;
42
+ description?: string;
43
+ list_id?: string;
44
+ agent_provider?: string;
45
+ }>): Promise<{
46
+ tasks: Card[];
47
+ }>;
48
+ }
package/dist/client.js ADDED
@@ -0,0 +1,245 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ export class AgileMonsterClient {
4
+ apiKey = '';
5
+ baseUrl;
6
+ cwd;
7
+ cachedConfig = undefined;
8
+ constructor(options) {
9
+ this.cwd = options?.cwd || process.cwd();
10
+ this.baseUrl = (options?.baseUrl ||
11
+ process.env.AGILEMONSTER_API_URL ||
12
+ 'https://api.agilemonster.com').replace(/\/+$/, '');
13
+ this.apiKey = options?.apiKey || this.resolveApiKey();
14
+ }
15
+ resolveApiKey() {
16
+ // 1. Process environment variables
17
+ if (process.env.AGILEMONSTER_API_KEY && process.env.AGILEMONSTER_API_KEY.trim() !== '') {
18
+ return process.env.AGILEMONSTER_API_KEY.trim();
19
+ }
20
+ if (process.env.AM_API_KEY && process.env.AM_API_KEY.trim() !== '') {
21
+ return process.env.AM_API_KEY.trim();
22
+ }
23
+ // 2. Project config (.agilemonster.json)
24
+ const projectConfig = this.loadProjectConfig();
25
+ if (projectConfig?.api_key && projectConfig.api_key.trim() !== '') {
26
+ return projectConfig.api_key.trim();
27
+ }
28
+ // 3. Local .env file in cwd
29
+ try {
30
+ const envPath = path.join(this.cwd, '.env');
31
+ if (fs.existsSync(envPath)) {
32
+ const envContent = fs.readFileSync(envPath, 'utf8');
33
+ const match = envContent.match(/(?:AGILEMONSTER_API_KEY|AM_API_KEY)\s*=\s*["']?([a-zA-Z0-9_-]+)["']?/);
34
+ if (match && match[1]) {
35
+ return match[1].trim();
36
+ }
37
+ }
38
+ }
39
+ catch {
40
+ // Ignore .env read error
41
+ }
42
+ // 4. Global developer config (~/.agilemonster/config.json)
43
+ try {
44
+ const homedir = process.env.HOME || process.env.USERPROFILE || '';
45
+ if (homedir) {
46
+ const globalConfigPath = path.join(homedir, '.agilemonster', 'config.json');
47
+ if (fs.existsSync(globalConfigPath)) {
48
+ const globalRaw = fs.readFileSync(globalConfigPath, 'utf8');
49
+ const parsed = JSON.parse(globalRaw);
50
+ if (parsed.api_key && typeof parsed.api_key === 'string') {
51
+ return parsed.api_key.trim();
52
+ }
53
+ }
54
+ }
55
+ }
56
+ catch {
57
+ // Ignore global config read error
58
+ }
59
+ return '';
60
+ }
61
+ getApiKey() {
62
+ return this.apiKey;
63
+ }
64
+ setApiKey(key) {
65
+ this.apiKey = key;
66
+ }
67
+ loadProjectConfig() {
68
+ if (this.cachedConfig !== undefined) {
69
+ return this.cachedConfig;
70
+ }
71
+ try {
72
+ let currentDir = this.cwd;
73
+ while (currentDir !== path.parse(currentDir).root) {
74
+ const configPath = path.join(currentDir, '.agilemonster.json');
75
+ if (fs.existsSync(configPath)) {
76
+ const content = fs.readFileSync(configPath, 'utf8');
77
+ this.cachedConfig = JSON.parse(content);
78
+ return this.cachedConfig;
79
+ }
80
+ currentDir = path.dirname(currentDir);
81
+ }
82
+ }
83
+ catch {
84
+ // Ignore reading error
85
+ }
86
+ this.cachedConfig = null;
87
+ return null;
88
+ }
89
+ saveProjectConfig(config, dir) {
90
+ const targetDir = dir || this.cwd;
91
+ const configPath = path.join(targetDir, '.agilemonster.json');
92
+ fs.writeFileSync(configPath, JSON.stringify(config, null, 2), 'utf8');
93
+ this.cachedConfig = config;
94
+ return configPath;
95
+ }
96
+ static saveGlobalConfig(data) {
97
+ const homedir = process.env.HOME || process.env.USERPROFILE || '';
98
+ if (!homedir)
99
+ throw new Error('Cannot locate home directory');
100
+ const dir = path.join(homedir, '.agilemonster');
101
+ if (!fs.existsSync(dir)) {
102
+ fs.mkdirSync(dir, { recursive: true });
103
+ }
104
+ const configPath = path.join(dir, 'config.json');
105
+ let existing = {};
106
+ try {
107
+ if (fs.existsSync(configPath)) {
108
+ existing = JSON.parse(fs.readFileSync(configPath, 'utf8'));
109
+ }
110
+ }
111
+ catch { }
112
+ const merged = { ...existing, ...data };
113
+ fs.writeFileSync(configPath, JSON.stringify(merged, null, 2), 'utf8');
114
+ return configPath;
115
+ }
116
+ async request(endpoint, options = {}) {
117
+ if (!this.apiKey) {
118
+ throw new Error('Missing AGILEMONSTER_API_KEY. Generate a Personal API Key in Agile Monster (Profile -> API Keys) and set it in your environment or MCP config.');
119
+ }
120
+ const url = `${this.baseUrl}${endpoint.startsWith('/') ? '' : '/'}${endpoint}`;
121
+ const headers = {
122
+ Authorization: `Bearer ${this.apiKey}`,
123
+ 'Content-Type': 'application/json',
124
+ Accept: 'application/json',
125
+ ...(options.headers || {}),
126
+ };
127
+ const res = await fetch(url, {
128
+ ...options,
129
+ headers,
130
+ });
131
+ const text = await res.text();
132
+ let json = null;
133
+ try {
134
+ json = JSON.parse(text);
135
+ }
136
+ catch {
137
+ // Not JSON
138
+ }
139
+ if (!res.ok) {
140
+ const msg = json?.message || json?.error || `HTTP ${res.status}: ${text.slice(0, 150)}`;
141
+ throw new Error(`Agile Monster API Error: ${msg}`);
142
+ }
143
+ return json;
144
+ }
145
+ async me() {
146
+ return this.request('/api/agent/me');
147
+ }
148
+ async getContext(projectName, boardId) {
149
+ const params = new URLSearchParams();
150
+ if (projectName)
151
+ params.set('project_name', projectName);
152
+ if (boardId)
153
+ params.set('board_id', boardId);
154
+ const qs = params.toString();
155
+ return this.request(`/api/agent/context${qs ? `?${qs}` : ''}`);
156
+ }
157
+ async listAssigned(provider = 'any', status, boardId, workspaceId) {
158
+ const params = new URLSearchParams();
159
+ if (provider)
160
+ params.set('provider', provider);
161
+ if (status)
162
+ params.set('status', status);
163
+ if (boardId)
164
+ params.set('board_id', boardId);
165
+ if (workspaceId)
166
+ params.set('workspace_id', workspaceId);
167
+ const qs = params.toString();
168
+ return this.request(`/api/agent/assigned${qs ? `?${qs}` : ''}`);
169
+ }
170
+ async claimTask(cardId, provider, runRef) {
171
+ return this.request(`/api/agent/cards/${cardId}/claim`, {
172
+ method: 'POST',
173
+ body: JSON.stringify({ provider, run_ref: runRef }),
174
+ });
175
+ }
176
+ async askQuestion(cardId, provider, question) {
177
+ return this.request(`/api/agent/cards/${cardId}/ask-question`, {
178
+ method: 'POST',
179
+ body: JSON.stringify({ provider, question }),
180
+ });
181
+ }
182
+ async addProgress(cardId, provider, update, tokensUsed, costUsd) {
183
+ return this.request(`/api/agent/cards/${cardId}/progress`, {
184
+ method: 'POST',
185
+ body: JSON.stringify({
186
+ provider,
187
+ update,
188
+ tokens_used: tokensUsed,
189
+ cost_usd: costUsd,
190
+ }),
191
+ });
192
+ }
193
+ async recordSpend(cardId, provider, tokens, costUsd, note) {
194
+ return this.request(`/api/agent/cards/${cardId}/spend`, {
195
+ method: 'POST',
196
+ body: JSON.stringify({
197
+ provider,
198
+ tokens,
199
+ cost_usd: costUsd,
200
+ note,
201
+ }),
202
+ });
203
+ }
204
+ async setBudget(cardId, maxBudgetUsd, maxTokens) {
205
+ return this.request(`/api/agent/cards/${cardId}/budget`, {
206
+ method: 'POST',
207
+ body: JSON.stringify({
208
+ max_budget_usd: maxBudgetUsd,
209
+ max_tokens: maxTokens,
210
+ }),
211
+ });
212
+ }
213
+ async submitReview(cardId, provider, summary, verificationSteps, targetList, assignToUserId) {
214
+ return this.request(`/api/agent/cards/${cardId}/submit-review`, {
215
+ method: 'POST',
216
+ body: JSON.stringify({
217
+ provider,
218
+ summary,
219
+ verification_steps: verificationSteps,
220
+ target_list: targetList,
221
+ target_list_id: targetList,
222
+ target_list_name: targetList,
223
+ assign_to_user_id: assignToUserId,
224
+ }),
225
+ });
226
+ }
227
+ async completeTask(cardId, provider, comment) {
228
+ return this.request(`/api/agent/cards/${cardId}/complete`, {
229
+ method: 'POST',
230
+ body: JSON.stringify({ provider, comment }),
231
+ });
232
+ }
233
+ async blockTask(cardId, provider, comment) {
234
+ return this.request(`/api/agent/cards/${cardId}/block`, {
235
+ method: 'POST',
236
+ body: JSON.stringify({ provider, comment }),
237
+ });
238
+ }
239
+ async createFollowupTasks(cardId, provider, tasks) {
240
+ return this.request(`/api/agent/cards/${cardId}/followup-tasks`, {
241
+ method: 'POST',
242
+ body: JSON.stringify({ provider, tasks }),
243
+ });
244
+ }
245
+ }
@@ -0,0 +1 @@
1
+ export declare const AGENT_GUIDELINES_MARKDOWN = "# Autonomous AI Agent Operational Guidelines (Agile Monster)\n\nThis document provides mandatory operational protocols for AI coding assistants (**Cursor, Claude Code, Antigravity, Codex, Hermes Agent, Windsurf, Aider**) working inside repositories integrated with **Agile Monster** (https://app.agilemonster.com).\n\n---\n\n## \uD83E\uDDED Core Principles\n\n1. **The Agile Monster Board is the Source of Truth**: \n All non-trivial feature additions, bug fixes, refactors, and deployments must correspond to a task on the project's Agile Monster board.\n2. **One Active Assignee**: \n Work on cards assigned specifically to your agent provider (`cursor`, `claude_code`, `antigravity`, `codex`, `hermes`, `windsurf`, `aider`, or `custom`). Never claim or alter tasks assigned to other agents or human teammates without explicit user direction.\n3. **No Hallucinated Requirements**: \n When a specification, API schema, or environment variable is ambiguous, stop and ask the user rather than guessing.\n4. **Human Verification Gate**: \n Autonomous agents must **never** close a task directly to `Done`. You must submit work for human testing and verification using `agilemonster_submit_for_review`.\n\n---\n\n## \uD83D\uDD04 Task Lifecycle Protocol\n\nFollow this exact sequential protocol when working on any task:\n\n1. **Context & Discovery**:\n - Inspect `.agilemonster.json` in the project root if present.\n - Run `agilemonster_get_context` to retrieve the board ID, list columns (`Backlog`, `In Progress`, `Review`, `Done`), and active tasks.\n\n2. **Task Intake**:\n - Check which tasks are queued for your agent using `agilemonster_list_my_tasks({ \"status\": \"queued\" })`.\n - Confirm the card is assigned to your provider before proceeding.\n\n3. **Claiming the Task**:\n - Before editing files or running build tools, claim the task:\n `agilemonster_claim_task({ \"card_id\": \"<card_uuid>\" })`\n - This moves the card status to `in_progress` and logs an activity event on the board.\n\n4. **Implementation, Questions & Progress**:\n - **When Blocked or Unclear**: Call `agilemonster_ask_question({ \"card_id\": \"<card_uuid>\", \"question\": \"...\" })`. This sets status to `waiting_for_input` so the user is alerted.\n - **Logging Progress**: For non-trivial milestones, call `agilemonster_add_progress({ \"card_id\": \"<card_uuid>\", \"update\": \"...\", \"tokens_used\": 1500, \"cost_usd\": 0.003 })`.\n - **Cost Safeguards**: Use `agilemonster_set_budget` and `agilemonster_record_spend` to protect against runaway billing loops.\n\n5. **Submission for Human Review & Testing**:\n - When code is implemented, compiled, and tested locally:\n - Call `agilemonster_submit_for_review({ \"card_id\": \"<card_uuid>\", \"summary\": \"...\", \"verification_steps\": \"...\" })`.\n - This automatically moves the card to the board's **Testing / QA / Review** column, reassigns the card back to the human who requested it, sets `agent_status` to `review`, and posts step-by-step verification instructions.\n - Never mark the card directly as \"Done\". The user will verify your test steps and sign off.\n\n6. **Suggest Follow-Up Tasks**:\n - Proactively suggest follow-up cards (deploy to test/staging, deploy to production, add integration tests) using:\n `agilemonster_create_followup_tasks({ \"card_id\": \"<card_uuid>\", \"tasks\": [...] })`.\n";
@@ -0,0 +1,51 @@
1
+ export const AGENT_GUIDELINES_MARKDOWN = `# Autonomous AI Agent Operational Guidelines (Agile Monster)
2
+
3
+ This document provides mandatory operational protocols for AI coding assistants (**Cursor, Claude Code, Antigravity, Codex, Hermes Agent, Windsurf, Aider**) working inside repositories integrated with **Agile Monster** (https://app.agilemonster.com).
4
+
5
+ ---
6
+
7
+ ## 🧭 Core Principles
8
+
9
+ 1. **The Agile Monster Board is the Source of Truth**:
10
+ All non-trivial feature additions, bug fixes, refactors, and deployments must correspond to a task on the project's Agile Monster board.
11
+ 2. **One Active Assignee**:
12
+ Work on cards assigned specifically to your agent provider (\`cursor\`, \`claude_code\`, \`antigravity\`, \`codex\`, \`hermes\`, \`windsurf\`, \`aider\`, or \`custom\`). Never claim or alter tasks assigned to other agents or human teammates without explicit user direction.
13
+ 3. **No Hallucinated Requirements**:
14
+ When a specification, API schema, or environment variable is ambiguous, stop and ask the user rather than guessing.
15
+ 4. **Human Verification Gate**:
16
+ Autonomous agents must **never** close a task directly to \`Done\`. You must submit work for human testing and verification using \`agilemonster_submit_for_review\`.
17
+
18
+ ---
19
+
20
+ ## 🔄 Task Lifecycle Protocol
21
+
22
+ Follow this exact sequential protocol when working on any task:
23
+
24
+ 1. **Context & Discovery**:
25
+ - Inspect \`.agilemonster.json\` in the project root if present.
26
+ - Run \`agilemonster_get_context\` to retrieve the board ID, list columns (\`Backlog\`, \`In Progress\`, \`Review\`, \`Done\`), and active tasks.
27
+
28
+ 2. **Task Intake**:
29
+ - Check which tasks are queued for your agent using \`agilemonster_list_my_tasks({ "status": "queued" })\`.
30
+ - Confirm the card is assigned to your provider before proceeding.
31
+
32
+ 3. **Claiming the Task**:
33
+ - Before editing files or running build tools, claim the task:
34
+ \`agilemonster_claim_task({ "card_id": "<card_uuid>" })\`
35
+ - This moves the card status to \`in_progress\` and logs an activity event on the board.
36
+
37
+ 4. **Implementation, Questions & Progress**:
38
+ - **When Blocked or Unclear**: Call \`agilemonster_ask_question({ "card_id": "<card_uuid>", "question": "..." })\`. This sets status to \`waiting_for_input\` so the user is alerted.
39
+ - **Logging Progress**: For non-trivial milestones, call \`agilemonster_add_progress({ "card_id": "<card_uuid>", "update": "...", "tokens_used": 1500, "cost_usd": 0.003 })\`.
40
+ - **Cost Safeguards**: Use \`agilemonster_set_budget\` and \`agilemonster_record_spend\` to protect against runaway billing loops.
41
+
42
+ 5. **Submission for Human Review & Testing**:
43
+ - When code is implemented, compiled, and tested locally:
44
+ - Call \`agilemonster_submit_for_review({ "card_id": "<card_uuid>", "summary": "...", "verification_steps": "..." })\`.
45
+ - This automatically moves the card to the board's **Testing / QA / Review** column, reassigns the card back to the human who requested it, sets \`agent_status\` to \`review\`, and posts step-by-step verification instructions.
46
+ - Never mark the card directly as "Done". The user will verify your test steps and sign off.
47
+
48
+ 6. **Suggest Follow-Up Tasks**:
49
+ - Proactively suggest follow-up cards (deploy to test/staging, deploy to production, add integration tests) using:
50
+ \`agilemonster_create_followup_tasks({ "card_id": "<card_uuid>", "tasks": [...] })\`.
51
+ `;