@agilemonster/mcp-server 1.0.6 → 1.0.7

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/bin/mcp.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import { runStdioServer } from '../dist/server.js';
3
+ import { MCP_SERVER_VERSION } from '../dist/client.js';
3
4
 
4
5
  const cliCommands = new Set([
5
6
  'bootstrap',
@@ -19,7 +20,10 @@ const cliCommands = new Set([
19
20
  ]);
20
21
 
21
22
  const firstArg = process.argv[2];
22
- if (firstArg && cliCommands.has(firstArg)) {
23
+ if (firstArg === '--version' || firstArg === '-v' || firstArg === 'version') {
24
+ console.log(MCP_SERVER_VERSION);
25
+ process.exit(0);
26
+ } else if (firstArg && cliCommands.has(firstArg)) {
23
27
  // Delegate to orchestrator CLI
24
28
  await import('./orchestrator.js');
25
29
  } else {
package/dist/client.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { AgileMonsterProjectConfig, Board, BoardAgentConfig, Card, ContextResponse } from './types.js';
1
+ import { AgileMonsterProjectConfig, Board, BoardAgentConfig, Card, ContextResponse, PulseResponse } from './types.js';
2
+ export declare const MCP_SERVER_VERSION = "1.0.7";
2
3
  export declare class AgileMonsterClient {
3
4
  private apiKey;
4
5
  private baseUrl;
@@ -29,6 +30,12 @@ export declare class AgileMonsterClient {
29
30
  saveBoardAgents(boardId: string, agents: BoardAgentConfig[], projectName?: string, projectPath?: string, gitRemote?: string): Promise<{
30
31
  agents: BoardAgentConfig[];
31
32
  }>;
33
+ pulse(options: {
34
+ boardId: string;
35
+ provider?: string;
36
+ projectName?: string;
37
+ projectPath?: string;
38
+ }): Promise<PulseResponse>;
32
39
  listAssigned(provider?: string, status?: string, boardId?: string, workspaceId?: string): Promise<{
33
40
  provider: string;
34
41
  cards: Card[];
package/dist/client.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
+ export const MCP_SERVER_VERSION = '1.0.7';
3
4
  export class AgileMonsterClient {
4
5
  apiKey = '';
5
6
  baseUrl;
@@ -122,6 +123,7 @@ export class AgileMonsterClient {
122
123
  Authorization: `Bearer ${this.apiKey}`,
123
124
  'Content-Type': 'application/json',
124
125
  Accept: 'application/json',
126
+ 'X-AgileMonster-MCP-Version': MCP_SERVER_VERSION,
125
127
  ...(options.headers || {}),
126
128
  };
127
129
  const res = await fetch(url, {
@@ -178,10 +180,23 @@ export class AgileMonsterClient {
178
180
  project_name: projectName,
179
181
  project_path: projectPath,
180
182
  git_remote: gitRemote,
183
+ mcp_version: MCP_SERVER_VERSION,
181
184
  connected: true,
182
185
  }),
183
186
  });
184
187
  }
188
+ async pulse(options) {
189
+ return this.request('/api/agent/pulse', {
190
+ method: 'POST',
191
+ body: JSON.stringify({
192
+ board_id: options.boardId,
193
+ provider: options.provider || 'any',
194
+ project_name: options.projectName,
195
+ project_path: options.projectPath,
196
+ mcp_version: MCP_SERVER_VERSION,
197
+ }),
198
+ });
199
+ }
185
200
  async listAssigned(provider = 'any', status, boardId, workspaceId) {
186
201
  const params = new URLSearchParams();
187
202
  if (provider)
@@ -361,7 +361,7 @@ export class AgileMonsterOrchestrator {
361
361
  existing.mcpServers = existing.mcpServers || {};
362
362
  existing.mcpServers.agilemonster = {
363
363
  command: 'npx',
364
- args: ['-y', '@agilemonster/mcp-server'],
364
+ args: ['-y', '@agilemonster/mcp-server@latest'],
365
365
  env: {
366
366
  AGILEMONSTER_API_KEY: apiKey,
367
367
  AGILEMONSTER_API_URL: 'https://api.agilemonster.com',
@@ -388,7 +388,7 @@ export class AgileMonsterOrchestrator {
388
388
  existing.mcpServers = existing.mcpServers || {};
389
389
  existing.mcpServers.agilemonster = {
390
390
  command: 'npx',
391
- args: ['-y', '@agilemonster/mcp-server'],
391
+ args: ['-y', '@agilemonster/mcp-server@latest'],
392
392
  env: {
393
393
  AGILEMONSTER_API_KEY: apiKey,
394
394
  AGILEMONSTER_API_URL: 'https://api.agilemonster.com',
@@ -419,7 +419,7 @@ export class AgileMonsterOrchestrator {
419
419
  existing.mcpServers = existing.mcpServers || {};
420
420
  existing.mcpServers.agilemonster = {
421
421
  command: 'npx',
422
- args: ['-y', '@agilemonster/mcp-server'],
422
+ args: ['-y', '@agilemonster/mcp-server@latest'],
423
423
  env: {
424
424
  AGILEMONSTER_API_KEY: apiKey,
425
425
  AGILEMONSTER_API_URL: 'https://api.agilemonster.com',
@@ -450,7 +450,7 @@ export class AgileMonsterOrchestrator {
450
450
  existing.mcpServers = existing.mcpServers || {};
451
451
  existing.mcpServers.agilemonster = {
452
452
  command: 'npx',
453
- args: ['-y', '@agilemonster/mcp-server'],
453
+ args: ['-y', '@agilemonster/mcp-server@latest'],
454
454
  env: {
455
455
  AGILEMONSTER_API_KEY: apiKey,
456
456
  AGILEMONSTER_API_URL: 'https://api.agilemonster.com',
@@ -479,7 +479,7 @@ export class AgileMonsterOrchestrator {
479
479
  existing.mcpServers = existing.mcpServers || {};
480
480
  existing.mcpServers.agilemonster = {
481
481
  command: 'npx',
482
- args: ['-y', '@agilemonster/mcp-server'],
482
+ args: ['-y', '@agilemonster/mcp-server@latest'],
483
483
  env: {
484
484
  AGILEMONSTER_API_KEY: apiKey,
485
485
  AGILEMONSTER_API_URL: 'https://api.agilemonster.com',
package/dist/server.d.ts CHANGED
@@ -34,4 +34,5 @@ export declare function createServer(client?: AgileMonsterClient): Server<{
34
34
  } | undefined;
35
35
  } | undefined;
36
36
  }>;
37
+ export declare function startBuiltInPullPulse(server: Server, client: AgileMonsterClient, intervalMs?: number): NodeJS.Timeout;
37
38
  export declare function runStdioServer(): Promise<void>;
package/dist/server.js CHANGED
@@ -3,17 +3,18 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
3
3
  import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
4
4
  import path from 'node:path';
5
5
  import fs from 'node:fs';
6
- import { AgileMonsterClient } from './client.js';
6
+ import { spawn } from 'node:child_process';
7
+ import { AgileMonsterClient, MCP_SERVER_VERSION } from './client.js';
7
8
  import { AGENT_GUIDELINES_MARKDOWN } from './guidelines.js';
8
9
  export function createServer(client = new AgileMonsterClient()) {
9
10
  const server = new Server({
10
11
  name: 'agilemonster-mcp-server',
11
- version: '1.0.0',
12
+ version: MCP_SERVER_VERSION,
12
13
  }, {
13
14
  capabilities: {
14
15
  tools: {},
15
16
  prompts: {},
16
- resources: {},
17
+ resources: { subscribe: true, listChanged: true },
17
18
  },
18
19
  });
19
20
  // -------------------------------------------------------------------------
@@ -704,8 +705,135 @@ Please strictly follow the Agile Monster Task Lifecycle Protocol:
704
705
  });
705
706
  return server;
706
707
  }
708
+ function sendDesktopNotification(title, message) {
709
+ if (process.platform === 'darwin') {
710
+ try {
711
+ const safeTitle = title.replace(/["\\]/g, '');
712
+ const safeMsg = message.replace(/["\\]/g, '').slice(0, 180);
713
+ const child = spawn('osascript', ['-e', `display notification "${safeMsg}" with title "${safeTitle}" sound name "Glass"`], { stdio: 'ignore', detached: true });
714
+ child.unref();
715
+ }
716
+ catch { }
717
+ }
718
+ }
719
+ function syncIdeTaskRules(boardName, queuedCards) {
720
+ const cwd = process.cwd();
721
+ const cursorRulesDir = path.join(cwd, '.cursor', 'rules');
722
+ const cursorRuleFile = path.join(cursorRulesDir, 'agilemonster-queue.mdc');
723
+ if (queuedCards.length === 0) {
724
+ try {
725
+ if (fs.existsSync(cursorRuleFile)) {
726
+ fs.unlinkSync(cursorRuleFile);
727
+ }
728
+ }
729
+ catch { }
730
+ return;
731
+ }
732
+ const lines = [
733
+ '---',
734
+ 'description: Active Agile Monster queued tasks assigned to this repository',
735
+ 'globs: ',
736
+ 'alwaysApply: true',
737
+ '---',
738
+ `# 🔔 Queued Agile Monster Tasks for Board "${boardName}"`,
739
+ '',
740
+ `There ${queuedCards.length === 1 ? 'is 1 queued task' : `are ${queuedCards.length} queued tasks`} assigned on the "${boardName}" board waiting to be claimed:`,
741
+ '',
742
+ ];
743
+ for (const c of queuedCards) {
744
+ const worker = c.agent_display_name || c.agent_provider || 'agent';
745
+ const model = c.agent_model && c.agent_model !== 'auto' ? ` (Preferred Model: ${c.agent_model})` : '';
746
+ lines.push(`- **${c.title}** (Card ID: \`${c.id}\` | Assigned to: \`${worker}\`${model})`);
747
+ if (c.description) {
748
+ lines.push(` - Details: ${c.description.replace(/\r?\n/g, ' ').slice(0, 280)}`);
749
+ }
750
+ }
751
+ lines.push('');
752
+ lines.push('When the user starts a task or asks what is next, call `agilemonster_claim_task` with the Card ID above, implement the solution, and submit it for review with `agilemonster_submit_for_review`.');
753
+ try {
754
+ if (fs.existsSync(path.join(cwd, '.cursor'))) {
755
+ if (!fs.existsSync(cursorRulesDir)) {
756
+ fs.mkdirSync(cursorRulesDir, { recursive: true });
757
+ }
758
+ fs.writeFileSync(cursorRuleFile, lines.join('\n') + '\n', 'utf8');
759
+ }
760
+ }
761
+ catch { }
762
+ }
763
+ function triggerBackgroundSelfUpdate() {
764
+ try {
765
+ // 1. Pre-warm latest @agilemonster/mcp-server in npx cache
766
+ const child = spawn('npx', ['-y', '@agilemonster/mcp-server@latest', '--version'], {
767
+ stdio: 'ignore',
768
+ detached: true,
769
+ });
770
+ child.unref();
771
+ // 2. Ensure local .cursor/mcp.json and .mcp.json use @latest so next IDE reload uses latest
772
+ const cwd = process.cwd();
773
+ for (const rel of ['.cursor/mcp.json', '.mcp.json', '.vscode/mcp.json']) {
774
+ const p = path.join(cwd, rel);
775
+ if (fs.existsSync(p)) {
776
+ try {
777
+ const parsed = JSON.parse(fs.readFileSync(p, 'utf8'));
778
+ if (parsed?.mcpServers?.agilemonster) {
779
+ parsed.mcpServers.agilemonster.args = ['-y', '@agilemonster/mcp-server@latest'];
780
+ fs.writeFileSync(p, JSON.stringify(parsed, null, 2), 'utf8');
781
+ }
782
+ }
783
+ catch { }
784
+ }
785
+ }
786
+ }
787
+ catch { }
788
+ }
789
+ export function startBuiltInPullPulse(server, client, intervalMs = 20000) {
790
+ const notifiedCardIds = new Set();
791
+ let updateTriggered = false;
792
+ const runPulse = async () => {
793
+ try {
794
+ const config = client.loadProjectConfig();
795
+ if (!config?.board_id || !client.getApiKey()) {
796
+ return;
797
+ }
798
+ const res = await client.pulse({
799
+ boardId: config.board_id,
800
+ provider: 'any',
801
+ projectName: config.project_name || path.basename(process.cwd()),
802
+ projectPath: config.project_path || process.cwd(),
803
+ });
804
+ const queued = res.queued_cards || [];
805
+ syncIdeTaskRules(config.board_name || 'Board', queued);
806
+ for (const card of queued) {
807
+ if (!notifiedCardIds.has(card.id)) {
808
+ notifiedCardIds.add(card.id);
809
+ const worker = card.agent_display_name || card.agent_provider || 'AI Agent';
810
+ const modelTag = card.agent_model && card.agent_model !== 'auto' ? ` [${card.agent_model}]` : '';
811
+ sendDesktopNotification(`Agile Monster -> ${worker}${modelTag}`, `New task queued on ${config.board_name || 'Board'}: "${card.title}"`);
812
+ try {
813
+ await server.sendResourceUpdated({ uri: 'agilemonster://project/context' });
814
+ }
815
+ catch { }
816
+ }
817
+ }
818
+ if ((res.version?.force_update_requested || res.version?.update_available) &&
819
+ !updateTriggered) {
820
+ updateTriggered = true;
821
+ triggerBackgroundSelfUpdate();
822
+ }
823
+ }
824
+ catch {
825
+ // Silent during background pulse
826
+ }
827
+ };
828
+ setTimeout(runPulse, 2500).unref();
829
+ const timer = setInterval(runPulse, intervalMs);
830
+ timer.unref();
831
+ return timer;
832
+ }
707
833
  export async function runStdioServer() {
708
- const server = createServer();
834
+ const client = new AgileMonsterClient();
835
+ const server = createServer(client);
709
836
  const transport = new StdioServerTransport();
710
837
  await server.connect(transport);
838
+ startBuiltInPullPulse(server, client, 20000);
711
839
  }
package/dist/types.d.ts CHANGED
@@ -18,6 +18,9 @@ export interface Card {
18
18
  position?: number;
19
19
  due_date?: string | null;
20
20
  agent_provider?: string | null;
21
+ agent_id?: string | null;
22
+ agent_model?: string | null;
23
+ agent_display_name?: string | null;
21
24
  agent_status?: string | null;
22
25
  agent_run_ref?: string | null;
23
26
  max_budget_usd?: number | null;
@@ -59,9 +62,26 @@ export interface BoardAgentConfig {
59
62
  project_name?: string | null;
60
63
  project_path?: string | null;
61
64
  git_remote?: string | null;
65
+ mcp_version?: string | null;
62
66
  connected?: boolean;
63
67
  last_connected_at?: string | null;
64
68
  }
69
+ export interface PulseVersionInfo {
70
+ client_version: string | null;
71
+ latest_version: string;
72
+ min_supported_version: string;
73
+ update_available: boolean;
74
+ update_required: boolean;
75
+ force_update_requested: boolean;
76
+ update_command: string;
77
+ }
78
+ export interface PulseResponse {
79
+ board_id: string;
80
+ pulsed_at: string;
81
+ queued_cards: Card[];
82
+ in_progress_cards: Card[];
83
+ version: PulseVersionInfo;
84
+ }
65
85
  export interface ContextResponse {
66
86
  matched_board: Board | null;
67
87
  ai_match?: AiBoardMatch | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agilemonster/mcp-server",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
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",