agent-planner-mcp 0.3.0 → 0.5.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025-2026 Talking Agents Oy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -112,6 +112,45 @@ NODE_ENV=production
112
112
  npm start
113
113
  ```
114
114
 
115
+ ## Transport Modes
116
+
117
+ The Planning System MCP Server supports two transport modes:
118
+
119
+ ### 🖥️ stdio Mode (Default)
120
+ For **local use** with Claude Desktop, Claude Code, and other local MCP clients:
121
+ - Default transport when running `npm start`
122
+ - Communication via stdin/stdout
123
+ - Best for development and personal use
124
+ - See sections below for Claude Desktop configuration
125
+
126
+ ### 🌐 HTTP/SSE Mode
127
+ For **remote access** via Anthropic's MCP Connector and cloud deployments:
128
+ - Implements MCP Streamable HTTP specification (2025-06-18)
129
+ - RESTful JSON-RPC API over HTTP
130
+ - Production-ready for Cloud Run deployment
131
+ - Supports session management and concurrent connections
132
+ - **Documentation**: See [HTTP_MODE.md](./HTTP_MODE.md)
133
+ - **Deployment**: See [MCP_REGISTRY.md](./MCP_REGISTRY.md)
134
+
135
+ **Quick Start (HTTP Mode):**
136
+ ```bash
137
+ # Local development
138
+ npm run start:http
139
+ # Server runs on http://127.0.0.1:3100
140
+
141
+ # Production deployment
142
+ ./deploy.sh
143
+ # Deploys to Google Cloud Run (europe-north1)
144
+ ```
145
+
146
+ **Use Cases:**
147
+ - ✅ **Anthropic Messages API**: Use with Claude via MCP Connector
148
+ - ✅ **Multi-Agent Systems**: agent-runtime integration
149
+ - ✅ **Cloud Deployment**: Scalable, always-available service
150
+ - ✅ **MCP Registry**: Discoverable via registry lookup
151
+
152
+ For detailed HTTP mode documentation, see [HTTP_MODE.md](./HTTP_MODE.md).
153
+
115
154
  ## Using with Claude Desktop
116
155
 
117
156
  ### Option 1: Using npx (Recommended - Simplest Setup)
package/package.json CHANGED
@@ -1,14 +1,16 @@
1
1
  {
2
2
  "name": "agent-planner-mcp",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "MCP server interface for the Planning System API",
5
5
  "main": "src/index.js",
6
6
  "bin": {
7
- "agent-planner-mcp": "src/index.js"
7
+ "agent-planner-mcp": "src/cli.js"
8
8
  },
9
9
  "scripts": {
10
10
  "start": "node src/index.js",
11
+ "start:http": "MCP_TRANSPORT=http node src/index.js",
11
12
  "dev": "nodemon src/index.js",
13
+ "dev:http": "MCP_TRANSPORT=http nodemon src/index.js",
12
14
  "test": "jest",
13
15
  "test:tools": "node test-tools.js",
14
16
  "setup": "node src/setup.js",
@@ -27,7 +29,7 @@
27
29
  "license": "MIT",
28
30
  "repository": {
29
31
  "type": "git",
30
- "url": "https://github.com/talkingagents/agent-planner-mcp.git"
32
+ "url": "git+https://github.com/TAgents/agent-planner-mcp.git"
31
33
  },
32
34
  "homepage": "https://agentplanner.io",
33
35
  "bugs": {
@@ -37,12 +39,16 @@
37
39
  "@modelcontextprotocol/sdk": "^1.8.0",
38
40
  "axios": "^1.6.2",
39
41
  "dotenv": "^16.3.1",
42
+ "express": "^4.18.2",
40
43
  "ignore": "^7.0.3"
41
44
  },
42
45
  "devDependencies": {
43
46
  "jest": "^29.7.0",
44
47
  "nodemon": "^3.0.1"
45
48
  },
49
+ "publishConfig": {
50
+ "access": "public"
51
+ },
46
52
  "engines": {
47
53
  "node": ">=16.0.0"
48
54
  },
package/src/api-client.js CHANGED
@@ -26,23 +26,28 @@ const apiClient = axios.create({
26
26
  }
27
27
  });
28
28
 
29
- // Log API requests in debug mode
30
- apiClient.interceptors.request.use(request => {
31
- console.error(`API Request: ${request.method.toUpperCase()} ${request.url}`);
32
- return request;
33
- });
34
-
35
- // Log API responses in debug mode
29
+ // Log API requests only in development mode
30
+ if (process.env.NODE_ENV === 'development') {
31
+ apiClient.interceptors.request.use(request => {
32
+ console.error(`API Request: ${request.method.toUpperCase()} ${request.url}`);
33
+ return request;
34
+ });
35
+ }
36
+
37
+ // Handle API responses - log details only in development, always handle auth errors helpfully
36
38
  apiClient.interceptors.response.use(
37
39
  response => {
38
- console.error(`API Response: ${response.status} ${response.statusText}`);
40
+ if (process.env.NODE_ENV === 'development') {
41
+ console.error(`API Response: ${response.status} ${response.statusText}`);
42
+ }
39
43
  return response;
40
44
  },
41
45
  error => {
46
+ // Always log auth errors helpfully (but not the token itself)
42
47
  if (error.response && error.response.status === 401) {
43
- console.error('API Error: Authentication failed (401). Please check that your USER_API_TOKEN is correct, valid, and not revoked.');
44
- console.error('If you are still using the old API_TOKEN, please generate a USER_API_TOKEN from the agent-planner UI.');
45
- } else {
48
+ console.error('API Error: Authentication failed (401). Please check that your USER_API_TOKEN is correct and not revoked.');
49
+ } else if (process.env.NODE_ENV === 'development') {
50
+ // Only log other errors in development
46
51
  console.error('API Error:', error.response ? error.response.data : error.message);
47
52
  }
48
53
  return Promise.reject(error);
@@ -100,6 +105,30 @@ const plans = {
100
105
  */
101
106
  deletePlan: async (planId) => {
102
107
  await apiClient.delete(`/plans/${planId}`);
108
+ },
109
+
110
+ /**
111
+ * Update plan visibility (make public or private)
112
+ * @param {string} planId - Plan ID
113
+ * @param {Object} visibilityData - Visibility settings
114
+ * @param {string} visibilityData.visibility - 'public' or 'private'
115
+ * @param {string} [visibilityData.github_repo_owner] - GitHub repo owner (for public plans)
116
+ * @param {string} [visibilityData.github_repo_name] - GitHub repo name (for public plans)
117
+ * @returns {Promise<Object>} - Updated plan with visibility info
118
+ */
119
+ updateVisibility: async (planId, visibilityData) => {
120
+ const response = await apiClient.put(`/plans/${planId}/visibility`, visibilityData);
121
+ return response.data;
122
+ },
123
+
124
+ /**
125
+ * Get a public plan (no authentication required in browser, but API token needed for MCP)
126
+ * @param {string} planId - Plan ID
127
+ * @returns {Promise<Object>} - Public plan details
128
+ */
129
+ getPublicPlan: async (planId) => {
130
+ const response = await apiClient.get(`/plans/${planId}/public`);
131
+ return response.data;
103
132
  }
104
133
  };
105
134
 
@@ -110,10 +139,18 @@ const nodes = {
110
139
  /**
111
140
  * Get nodes for a plan
112
141
  * @param {string} planId - Plan ID
142
+ * @param {Object} options - Optional query parameters
143
+ * @param {boolean} options.include_details - Include full node details (default: false)
113
144
  * @returns {Promise<Array>} - List of nodes
114
145
  */
115
- getNodes: async (planId) => {
116
- const response = await apiClient.get(`/plans/${planId}/nodes`);
146
+ getNodes: async (planId, options = {}) => {
147
+ const params = new URLSearchParams();
148
+ if (options.include_details) {
149
+ params.append('include_details', 'true');
150
+ }
151
+
152
+ const queryString = params.toString() ? `?${params.toString()}` : '';
153
+ const response = await apiClient.get(`/plans/${planId}/nodes${queryString}`);
117
154
  return response.data;
118
155
  },
119
156
 
@@ -230,101 +267,6 @@ const logs = {
230
267
  }
231
268
  };
232
269
 
233
- /**
234
- * Artifact-related API functions
235
- */
236
- const artifacts = {
237
- /**
238
- * Get artifacts for a node
239
- * @param {string} planId - Plan ID
240
- * @param {string} nodeId - Node ID
241
- * @returns {Promise<Array>} - List of artifacts
242
- */
243
- getArtifacts: async (planId, nodeId) => {
244
- const response = await apiClient.get(`/plans/${planId}/nodes/${nodeId}/artifacts`);
245
- return response.data;
246
- },
247
-
248
- /**
249
- * Get a specific artifact by ID
250
- * @param {string} planId - Plan ID
251
- * @param {string} nodeId - Node ID
252
- * @param {string} artifactId - Artifact ID
253
- * @returns {Promise<Object>} - Artifact details
254
- */
255
- getArtifact: async (planId, nodeId, artifactId) => {
256
- const response = await apiClient.get(`/plans/${planId}/nodes/${nodeId}/artifacts/${artifactId}`);
257
- return response.data;
258
- },
259
-
260
- /**
261
- * Get the content of an artifact
262
- * @param {string} planId - Plan ID
263
- * @param {string} nodeId - Node ID
264
- * @param {string} artifactId - Artifact ID
265
- * @returns {Promise<string>} - Artifact content
266
- */
267
- getArtifactContent: async (planId, nodeId, artifactId) => {
268
- try {
269
- // First, get artifact details to check the URL
270
- const artifact = await artifacts.getArtifact(planId, nodeId, artifactId);
271
-
272
- // If the artifact has a URL, fetch the content
273
- if (artifact.url) {
274
- try {
275
- // For local file paths, use fs instead of HTTP request
276
- if (artifact.url.startsWith('/') && !artifact.url.startsWith('/api/')) {
277
- const fs = require('fs').promises;
278
- try {
279
- // Read the file directly from the filesystem
280
- const content = await fs.readFile(artifact.url, 'utf8');
281
- return content;
282
- } catch (fsError) {
283
- console.error('Error reading artifact file:', fsError);
284
- throw new Error(`Cannot read file at ${artifact.url}: ${fsError.message}`);
285
- }
286
- } else {
287
- // For internal URLs (API routes), append to base URL
288
- const contentUrl = artifact.url.startsWith('/api/')
289
- ? `${apiClient.defaults.baseURL}${artifact.url}`
290
- : artifact.url;
291
-
292
- const contentResponse = await axios.get(contentUrl, {
293
- headers: {
294
- 'Authorization': apiClient.defaults.headers['Authorization'],
295
- 'Accept': artifact.content_type || 'text/plain'
296
- },
297
- responseType: 'text'
298
- });
299
-
300
- return contentResponse.data;
301
- }
302
- } catch (fetchError) {
303
- console.error('Error fetching artifact content:', fetchError);
304
- throw new Error(`Failed to fetch artifact content: ${fetchError.message}`);
305
- }
306
- } else {
307
- throw new Error('Artifact does not have a content URL');
308
- }
309
- } catch (error) {
310
- console.error('Error fetching artifact content:', error);
311
- throw error;
312
- }
313
- },
314
-
315
- /**
316
- * Add an artifact to a node
317
- * @param {string} planId - Plan ID
318
- * @param {string} nodeId - Node ID
319
- * @param {Object} artifactData - Artifact data
320
- * @returns {Promise<Object>} - Created artifact
321
- */
322
- addArtifact: async (planId, nodeId, artifactData) => {
323
- const response = await apiClient.post(`/plans/${planId}/nodes/${nodeId}/artifacts`, artifactData);
324
- return response.data;
325
- }
326
- };
327
-
328
270
  /**
329
271
  * Activity-related API functions
330
272
  */
@@ -335,7 +277,7 @@ const activity = {
335
277
  * @returns {Promise<Array>} - Activity feed
336
278
  */
337
279
  getPlanActivity: async (planId) => {
338
- const response = await apiClient.get(`/activity/plan/${planId}`);
280
+ const response = await apiClient.get(`/activity/plans/${planId}/activity`);
339
281
  return response.data;
340
282
  },
341
283
 
@@ -344,7 +286,7 @@ const activity = {
344
286
  * @returns {Promise<Array>} - Activity feed
345
287
  */
346
288
  getGlobalActivity: async () => {
347
- const response = await apiClient.get('/activity');
289
+ const response = await apiClient.get('/activity/feed');
348
290
  return response.data;
349
291
  }
350
292
  };
@@ -499,7 +441,7 @@ const tokens = {
499
441
  * @returns {Promise<Array>} - List of API tokens
500
442
  */
501
443
  getTokens: async () => {
502
- const response = await apiClient.get('/tokens');
444
+ const response = await apiClient.get('/auth/token');
503
445
  return response.data;
504
446
  },
505
447
 
@@ -509,7 +451,7 @@ const tokens = {
509
451
  * @returns {Promise<Object>} - Created token
510
452
  */
511
453
  createToken: async (tokenData) => {
512
- const response = await apiClient.post('/tokens', tokenData);
454
+ const response = await apiClient.post('/auth/token', tokenData);
513
455
  return response.data;
514
456
  },
515
457
 
@@ -519,7 +461,221 @@ const tokens = {
519
461
  * @returns {Promise<void>}
520
462
  */
521
463
  revokeToken: async (tokenId) => {
522
- await apiClient.delete(`/tokens/${tokenId}`);
464
+ await apiClient.delete(`/auth/token/${tokenId}`);
465
+ }
466
+ };
467
+
468
+ /**
469
+ * Organization API functions
470
+ */
471
+ const organizations = {
472
+ list: async () => {
473
+ const response = await apiClient.get('/organizations');
474
+ return response.data.organizations || response.data;
475
+ },
476
+
477
+ get: async (orgId) => {
478
+ const response = await apiClient.get(`/organizations/${orgId}`);
479
+ return response.data;
480
+ },
481
+
482
+ create: async (data) => {
483
+ const response = await apiClient.post('/organizations', data);
484
+ return response.data;
485
+ },
486
+
487
+ update: async (orgId, data) => {
488
+ const response = await apiClient.put(`/organizations/${orgId}`, data);
489
+ return response.data;
490
+ },
491
+
492
+ delete: async (orgId) => {
493
+ const response = await apiClient.delete(`/organizations/${orgId}`);
494
+ return response.data;
495
+ },
496
+
497
+ listMembers: async (orgId) => {
498
+ const response = await apiClient.get(`/organizations/${orgId}/members`);
499
+ return response.data.members || response.data;
500
+ },
501
+
502
+ addMember: async (orgId, data) => {
503
+ const response = await apiClient.post(`/organizations/${orgId}/members`, data);
504
+ return response.data;
505
+ },
506
+
507
+ removeMember: async (orgId, memberId) => {
508
+ const response = await apiClient.delete(`/organizations/${orgId}/members/${memberId}`);
509
+ return response.data;
510
+ }
511
+ };
512
+
513
+ /**
514
+ * Goals API functions
515
+ */
516
+ const goals = {
517
+ list: async (filters = {}) => {
518
+ const params = new URLSearchParams();
519
+ if (filters.organization_id) params.append('organization_id', filters.organization_id);
520
+ if (filters.status) params.append('status', filters.status);
521
+ const response = await apiClient.get(`/goals?${params.toString()}`);
522
+ return response.data.goals || response.data;
523
+ },
524
+
525
+ get: async (goalId) => {
526
+ const response = await apiClient.get(`/goals/${goalId}`);
527
+ return response.data;
528
+ },
529
+
530
+ create: async (data) => {
531
+ const response = await apiClient.post('/goals', data);
532
+ return response.data;
533
+ },
534
+
535
+ update: async (goalId, data) => {
536
+ const response = await apiClient.put(`/goals/${goalId}`, data);
537
+ return response.data;
538
+ },
539
+
540
+ updateMetrics: async (goalId, metrics) => {
541
+ const response = await apiClient.put(`/goals/${goalId}/metrics`, { metrics });
542
+ return response.data;
543
+ },
544
+
545
+ delete: async (goalId) => {
546
+ const response = await apiClient.delete(`/goals/${goalId}`);
547
+ return response.data;
548
+ },
549
+
550
+ linkPlan: async (goalId, planId) => {
551
+ const response = await apiClient.post(`/goals/${goalId}/plans/${planId}`);
552
+ return response.data;
553
+ },
554
+
555
+ unlinkPlan: async (goalId, planId) => {
556
+ const response = await apiClient.delete(`/goals/${goalId}/plans/${planId}`);
557
+ return response.data;
558
+ }
559
+ };
560
+
561
+ /**
562
+ * Knowledge Store API functions
563
+ */
564
+ const knowledge = {
565
+ /**
566
+ * List knowledge entries with optional filters
567
+ * GET /knowledge
568
+ */
569
+ listEntries: async (storeIdOrFilters, filters = {}) => {
570
+ const params = new URLSearchParams();
571
+ // Support both (storeId, filters) and (filters) calling patterns
572
+ if (typeof storeIdOrFilters === 'string') {
573
+ params.append('scopeId', storeIdOrFilters);
574
+ if (filters.entry_type) params.append('entryType', filters.entry_type);
575
+ if (filters.tags) params.append('tags', filters.tags);
576
+ if (filters.limit) params.append('limit', filters.limit);
577
+ if (filters.offset) params.append('offset', filters.offset);
578
+ } else if (typeof storeIdOrFilters === 'object') {
579
+ const f = storeIdOrFilters;
580
+ if (f.scope) params.append('scope', f.scope);
581
+ if (f.scope_id) params.append('scopeId', f.scope_id);
582
+ if (f.entry_type) params.append('entryType', f.entry_type);
583
+ if (f.limit) params.append('limit', f.limit);
584
+ if (f.offset) params.append('offset', f.offset);
585
+ }
586
+ const response = await apiClient.get(`/knowledge?${params.toString()}`);
587
+ return response.data;
588
+ },
589
+
590
+ /**
591
+ * Alias for listEntries — used by get_context and understand_context tools
592
+ */
593
+ getEntries: async (filters = {}) => {
594
+ return knowledge.listEntries(filters);
595
+ },
596
+
597
+ /**
598
+ * Get a single knowledge entry
599
+ * GET /knowledge/:id
600
+ */
601
+ getEntry: async (entryId) => {
602
+ const response = await apiClient.get(`/knowledge/${entryId}`);
603
+ return response.data;
604
+ },
605
+
606
+ /**
607
+ * Create a knowledge entry
608
+ * POST /knowledge
609
+ */
610
+ createEntry: async (data) => {
611
+ const response = await apiClient.post('/knowledge', data);
612
+ return response.data;
613
+ },
614
+
615
+ /**
616
+ * Update a knowledge entry
617
+ * PUT /knowledge/:id
618
+ */
619
+ updateEntry: async (entryId, data) => {
620
+ const response = await apiClient.put(`/knowledge/${entryId}`, data);
621
+ return response.data;
622
+ },
623
+
624
+ /**
625
+ * Delete a knowledge entry
626
+ * DELETE /knowledge/:id
627
+ */
628
+ deleteEntry: async (entryId) => {
629
+ const response = await apiClient.delete(`/knowledge/${entryId}`);
630
+ return response.data;
631
+ },
632
+
633
+ /**
634
+ * Semantic search across knowledge entries
635
+ * POST /knowledge/search
636
+ */
637
+ search: async (data) => {
638
+ const response = await apiClient.post('/knowledge/search', data);
639
+ return response.data;
640
+ }
641
+ };
642
+
643
+ /**
644
+ * Agent Context API functions (leaf-up context loading)
645
+ */
646
+ const context = {
647
+ /**
648
+ * Get focused context for a specific node (task/phase)
649
+ * Traverses from node up to root, including goals, org, and knowledge
650
+ * @param {string} nodeId - Node ID
651
+ * @param {Object} options - Options (include_knowledge, include_siblings)
652
+ * @returns {Promise<Object>} - Agent context
653
+ */
654
+ getNodeContext: async (nodeId, options = {}) => {
655
+ const params = new URLSearchParams({ node_id: nodeId });
656
+ if (options.include_knowledge !== undefined) {
657
+ params.append('include_knowledge', options.include_knowledge);
658
+ }
659
+ if (options.include_siblings !== undefined) {
660
+ params.append('include_siblings', options.include_siblings);
661
+ }
662
+ const response = await apiClient.get(`/context?${params.toString()}`);
663
+ return response.data;
664
+ },
665
+
666
+ /**
667
+ * Get plan-level context (overview, not full tree)
668
+ * @param {string} planId - Plan ID
669
+ * @param {Object} options - Options (include_knowledge)
670
+ * @returns {Promise<Object>} - Plan context
671
+ */
672
+ getPlanContext: async (planId, options = {}) => {
673
+ const params = new URLSearchParams({ plan_id: planId });
674
+ if (options.include_knowledge !== undefined) {
675
+ params.append('include_knowledge', options.include_knowledge);
676
+ }
677
+ const response = await apiClient.get(`/context/plan?${params.toString()}`);
678
+ return response.data;
523
679
  }
524
680
  };
525
681
 
@@ -532,9 +688,12 @@ module.exports = {
532
688
  nodes,
533
689
  comments,
534
690
  logs,
535
- artifacts,
536
691
  activity,
537
692
  search,
538
693
  tokens,
694
+ organizations,
695
+ goals,
696
+ knowledge,
697
+ context,
539
698
  axiosInstance // Export for direct API calls
540
699
  };
package/src/cli.js ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * CLI Entry Point for agent-planner-mcp
5
+ * Routes to different commands or starts the MCP server
6
+ */
7
+
8
+ const path = require('path');
9
+
10
+ const args = process.argv.slice(2);
11
+ const command = args[0];
12
+
13
+ // Route to different commands
14
+ switch (command) {
15
+ case 'setup-claude-code':
16
+ // Run the setup-claude-code script
17
+ const setupClaudeCode = require('./setup-claude-code.js');
18
+ setupClaudeCode.main();
19
+ break;
20
+
21
+ case 'setup':
22
+ // Run the interactive setup wizard
23
+ require('./setup.js');
24
+ break;
25
+
26
+ case '--help':
27
+ case '-h':
28
+ case 'help':
29
+ console.log(`
30
+ Agent Planner MCP - Model Context Protocol Server
31
+
32
+ Usage:
33
+ npx agent-planner-mcp Start MCP server (requires USER_API_TOKEN)
34
+ npx agent-planner-mcp setup-claude-code Install orchestration commands to .claude/
35
+ npx agent-planner-mcp setup Interactive setup wizard
36
+ npx agent-planner-mcp --help Show this help message
37
+
38
+ Environment Variables:
39
+ API_URL - Agent Planner API URL (default: http://localhost:3000)
40
+ USER_API_TOKEN - API token from Agent Planner UI (required for server)
41
+ MCP_SERVER_NAME - Server name (default: planning-system-mcp)
42
+ NODE_ENV - Environment (development/production)
43
+
44
+ Documentation:
45
+ https://github.com/talkingagents/agent-planner-mcp
46
+ `);
47
+ break;
48
+
49
+ case '--version':
50
+ case '-v':
51
+ const pkg = require('../package.json');
52
+ console.log(`agent-planner-mcp v${pkg.version}`);
53
+ break;
54
+
55
+ default:
56
+ // No command or unknown command - start MCP server
57
+ if (command && !command.startsWith('-')) {
58
+ console.error(`Unknown command: ${command}`);
59
+ console.error('Run "npx agent-planner-mcp --help" for usage information.');
60
+ process.exit(1);
61
+ }
62
+ // Start the MCP server
63
+ require('./index.js');
64
+ }