builderos-cli 2.0.1 → 2.0.3

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.
Files changed (3) hide show
  1. package/index.js +39 -14
  2. package/mcp-server.js +143 -0
  3. package/package.json +4 -1
package/index.js CHANGED
@@ -9,6 +9,7 @@
9
9
  * Usage:
10
10
  * npx builderos-cli init [options]
11
11
  * npx builderos-cli update [options]
12
+ * npx builderos-cli mcp # Start MCP server
12
13
  *
13
14
  * Options:
14
15
  * --api-url=<url> BuilderOS API URL (default: http://builder-os.test)
@@ -21,10 +22,22 @@
21
22
  import { mkdir, writeFile, readFile, access } from 'fs/promises';
22
23
  import { join } from 'path';
23
24
  import { constants } from 'fs';
25
+ import { startMCPServer } from './mcp-server.js';
24
26
 
25
27
  // Parse command line arguments
26
28
  const args = process.argv.slice(2);
27
29
 
30
+ // Check for MCP server command first
31
+ const command = args[0];
32
+ if (command === 'mcp') {
33
+ // Start MCP server (this will run indefinitely)
34
+ await startMCPServer().catch((error) => {
35
+ console.error('Fatal error:', error);
36
+ process.exit(1);
37
+ });
38
+ // MCP server is now running, this code won't be reached
39
+ }
40
+
28
41
  // Default options
29
42
  const options = {
30
43
  apiUrl: process.env.BUILDEROS_API_URL || 'http://builder-os.test',
@@ -35,7 +48,6 @@ const options = {
35
48
  };
36
49
 
37
50
  // Check if first arg is help or no command
38
- const command = args[0];
39
51
  if (!command || command === '--help' || command === '-h') {
40
52
  options.help = true;
41
53
  }
@@ -58,15 +70,17 @@ for (const arg of args) {
58
70
  // Show help
59
71
  if (options.help) {
60
72
  console.log(`
61
- BuilderOS CLI v2.0.0
73
+ BuilderOS CLI v2.0.3
62
74
 
63
75
  Usage:
64
76
  npx builderos-cli init [options]
65
77
  npx builderos-cli update [options]
78
+ npx builderos-cli mcp
66
79
 
67
80
  Commands:
68
81
  init Initialize BuilderOS in current project
69
82
  update Update skills from BuilderOS API
83
+ mcp Start MCP server (used by Claude Code)
70
84
 
71
85
  Options:
72
86
  --api-url=<url> BuilderOS API URL (default: http://builder-os.test)
@@ -87,6 +101,9 @@ Examples:
87
101
 
88
102
  # Force reinstall
89
103
  npx builderos-cli init --force
104
+
105
+ # Start MCP server (automatically used by .mcp.json)
106
+ npx builderos-cli mcp
90
107
  `);
91
108
  process.exit(0);
92
109
  }
@@ -105,11 +122,15 @@ async function fileExists(path) {
105
122
  async function fetchAPI(endpoint) {
106
123
  try {
107
124
  const url = `${options.apiUrl}${endpoint}`;
108
- const response = await fetch(url, {
109
- headers: {
110
- 'Host': 'builder-os.test', // For local nginx-proxy
111
- },
112
- });
125
+
126
+ // Only set Host header if API URL is not builder-os.test
127
+ // (for cases where we need to access through IP but want nginx to route correctly)
128
+ const headers = {};
129
+ if (!options.apiUrl.includes('builder-os.test')) {
130
+ headers['Host'] = 'builder-os.test';
131
+ }
132
+
133
+ const response = await fetch(url, { headers });
113
134
 
114
135
  if (!response.ok) {
115
136
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -118,6 +139,8 @@ async function fetchAPI(endpoint) {
118
139
  return await response.json();
119
140
  } catch (error) {
120
141
  console.error(`❌ Error fetching ${endpoint}:`, error.message);
142
+ console.error(` URL: ${url}`);
143
+ console.error(` Stack:`, error.stack);
121
144
  return null;
122
145
  }
123
146
  }
@@ -139,14 +162,13 @@ async function installMCP() {
139
162
  }
140
163
  }
141
164
 
142
- // Always use remote mode (npx @builderos/mcp-client)
143
- // This CLI is meant to be standalone, not requiring local BuilderOS code
165
+ // Use builderos-cli mcp command as MCP server
144
166
  const mcpConfig = {
145
167
  mcpServers: {
146
168
  'builder-os': {
147
169
  type: 'stdio',
148
170
  command: 'npx',
149
- args: ['-y', '@builderos/mcp-client'],
171
+ args: ['-y', 'builderos-cli', 'mcp'],
150
172
  env: {
151
173
  BUILDEROS_API_URL: options.apiUrl,
152
174
  },
@@ -166,12 +188,15 @@ async function installSkills() {
166
188
 
167
189
  // Fetch skills list
168
190
  const data = await fetchAPI('/api/skills');
169
- if (!data || !data.skills) {
191
+ if (!data || !data.data) {
170
192
  console.log(' ❌ Failed to fetch skills list');
193
+ if (data) {
194
+ console.log(' Response structure:', JSON.stringify(Object.keys(data)));
195
+ }
171
196
  return;
172
197
  }
173
198
 
174
- const skills = data.skills;
199
+ const skills = data.data;
175
200
  console.log(` Found ${skills.length} skills`);
176
201
 
177
202
  // Create .claude/skills directory
@@ -187,7 +212,7 @@ async function installSkills() {
187
212
 
188
213
  const skillData = await fetchAPI(`/api/skills/${skill.slug}`);
189
214
 
190
- if (!skillData || !skillData.content) {
215
+ if (!skillData || !skillData.data || !skillData.data.content) {
191
216
  console.log(` ⚠️ No content available`);
192
217
  failedSkills.push(skill.slug);
193
218
  continue;
@@ -199,7 +224,7 @@ async function installSkills() {
199
224
 
200
225
  // Write skill.md
201
226
  const skillPath = join(skillDir, 'skill.md');
202
- await writeFile(skillPath, skillData.content);
227
+ await writeFile(skillPath, skillData.data.content);
203
228
 
204
229
  console.log(` ✅ Saved to ${skillDir}/skill.md`);
205
230
  successCount++;
package/mcp-server.js ADDED
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * BuilderOS MCP Server
5
+ *
6
+ * MCP server that connects to BuilderOS HTTP API.
7
+ * Used by Claude Code to access BuilderOS tools.
8
+ */
9
+
10
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
11
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
12
+ import {
13
+ CallToolRequestSchema,
14
+ ListToolsRequestSchema,
15
+ } from '@modelcontextprotocol/sdk/types.js';
16
+
17
+ // Get API URL from environment variable
18
+ const API_URL = process.env.BUILDEROS_API_URL || 'http://builder-os.test';
19
+
20
+ /**
21
+ * Fetch tools from BuilderOS API
22
+ */
23
+ async function fetchTools() {
24
+ try {
25
+ // Only set Host header if API URL is not builder-os.test
26
+ const headers = {};
27
+ if (!API_URL.includes('builder-os.test')) {
28
+ headers['Host'] = 'builder-os.test';
29
+ }
30
+
31
+ const response = await fetch(`${API_URL}/api/mcp/tools`, { headers });
32
+
33
+ if (!response.ok) {
34
+ throw new Error(`Failed to fetch tools: ${response.statusText}`);
35
+ }
36
+
37
+ const data = await response.json();
38
+ return data.tools || [];
39
+ } catch (error) {
40
+ console.error('Error fetching tools:', error);
41
+ return [];
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Execute tool via BuilderOS API
47
+ */
48
+ async function executeTool(toolName, args) {
49
+ try {
50
+ // Only set Host header if API URL is not builder-os.test
51
+ const headers = {
52
+ 'Content-Type': 'application/json',
53
+ };
54
+ if (!API_URL.includes('builder-os.test')) {
55
+ headers['Host'] = 'builder-os.test';
56
+ }
57
+
58
+ const response = await fetch(`${API_URL}/api/mcp/execute`, {
59
+ method: 'POST',
60
+ headers,
61
+ body: JSON.stringify({
62
+ tool: toolName,
63
+ arguments: args
64
+ })
65
+ });
66
+
67
+ if (!response.ok) {
68
+ throw new Error(`Failed to execute tool: ${response.statusText}`);
69
+ }
70
+
71
+ const data = await response.json();
72
+ return data;
73
+ } catch (error) {
74
+ console.error('Error executing tool:', error);
75
+ throw error;
76
+ }
77
+ }
78
+
79
+ /**
80
+ * Start MCP server
81
+ */
82
+ export async function startMCPServer() {
83
+ const server = new Server(
84
+ {
85
+ name: 'builderos-cli-mcp',
86
+ version: '2.0.3',
87
+ },
88
+ {
89
+ capabilities: {
90
+ tools: {},
91
+ },
92
+ }
93
+ );
94
+
95
+ // List available tools
96
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
97
+ const tools = await fetchTools();
98
+ return { tools };
99
+ });
100
+
101
+ // Execute tool
102
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
103
+ const { name, arguments: args } = request.params;
104
+
105
+ try {
106
+ const result = await executeTool(name, args || {});
107
+
108
+ return {
109
+ content: [
110
+ {
111
+ type: 'text',
112
+ text: JSON.stringify(result, null, 2),
113
+ },
114
+ ],
115
+ };
116
+ } catch (error) {
117
+ return {
118
+ content: [
119
+ {
120
+ type: 'text',
121
+ text: `Error: ${error.message}`,
122
+ },
123
+ ],
124
+ isError: true,
125
+ };
126
+ }
127
+ });
128
+
129
+ // Start server
130
+ const transport = new StdioServerTransport();
131
+ await server.connect(transport);
132
+
133
+ console.error('BuilderOS MCP Server started');
134
+ console.error(`Connected to: ${API_URL}`);
135
+ }
136
+
137
+ // Run if called directly
138
+ if (import.meta.url === `file://${process.argv[1]}`) {
139
+ startMCPServer().catch((error) => {
140
+ console.error('Fatal error:', error);
141
+ process.exit(1);
142
+ });
143
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "builderos-cli",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "BuilderOS CLI - Initialize BuilderOS in any project without requiring local code",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -26,5 +26,8 @@
26
26
  "repository": {
27
27
  "type": "git",
28
28
  "url": "https://github.com/builderos/builderos"
29
+ },
30
+ "dependencies": {
31
+ "@modelcontextprotocol/sdk": "^1.0.4"
29
32
  }
30
33
  }