@nordsym/apiclaw 1.5.17 → 1.5.19

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 (228) hide show
  1. package/convex/http.js.map +1 -1
  2. package/convex/http.ts +516 -0
  3. package/dist/analytics.d.ts +0 -4
  4. package/dist/analytics.d.ts.map +1 -1
  5. package/dist/analytics.js +0 -1
  6. package/dist/analytics.js.map +1 -1
  7. package/dist/bin.js +1 -1
  8. package/dist/cli/commands/mcp-install.d.ts.map +1 -1
  9. package/dist/cli/commands/mcp-install.js +8 -87
  10. package/dist/cli/commands/mcp-install.js.map +1 -1
  11. package/dist/cli/index.js +0 -7
  12. package/dist/credentials.d.ts.map +1 -1
  13. package/dist/credentials.js +38 -43
  14. package/dist/credentials.js.map +1 -1
  15. package/dist/discovery.d.ts.map +1 -1
  16. package/dist/discovery.js +82 -191
  17. package/dist/discovery.js.map +1 -1
  18. package/dist/http-api.d.ts.map +1 -1
  19. package/dist/http-api.js +33 -17
  20. package/dist/http-api.js.map +1 -1
  21. package/dist/proxy.js +1 -1
  22. package/dist/proxy.js.map +1 -1
  23. package/landing/next-env.d.ts +0 -1
  24. package/landing/src/app/api/auth/magic-link/route.ts +1 -1
  25. package/landing/src/app/auth/verify/page.tsx +0 -6
  26. package/landing/src/app/dashboard/verify/page.tsx +0 -6
  27. package/landing/src/app/join/page.tsx +0 -6
  28. package/landing/src/app/layout.tsx +2 -2
  29. package/landing/src/app/login/page.tsx +1 -1
  30. package/landing/src/app/mou/[partnerId]/page.tsx +0 -6
  31. package/landing/src/app/page.tsx +18 -39
  32. package/landing/src/app/providers/dashboard/[apiId]/actions/[actionId]/edit/page.tsx +0 -6
  33. package/landing/src/app/providers/dashboard/[apiId]/actions/new/page.tsx +0 -5
  34. package/landing/src/app/providers/dashboard/[apiId]/actions/page.tsx +0 -5
  35. package/landing/src/app/providers/dashboard/[apiId]/direct-call/page.tsx +1 -6
  36. package/landing/src/app/providers/dashboard/[apiId]/page.tsx +0 -5
  37. package/landing/src/app/providers/dashboard/[apiId]/test/page.tsx +0 -5
  38. package/landing/src/app/providers/dashboard/layout.tsx +6 -6
  39. package/landing/src/app/providers/dashboard/login/page.tsx +1 -1
  40. package/landing/src/app/providers/dashboard/page.tsx +1 -1
  41. package/landing/src/app/providers/dashboard/verify/page.tsx +0 -6
  42. package/landing/src/app/providers/layout.tsx +1 -1
  43. package/landing/src/app/upgrade/page.tsx +0 -6
  44. package/landing/src/app/workspace/page.tsx +0 -6
  45. package/landing/src/components/HeroTabs.tsx +2 -2
  46. package/landing/src/components/{Workspace.tsx → ProviderDashboard.tsx} +2 -2
  47. package/landing/src/components/VideoDemo.tsx +10 -21
  48. package/landing/src/lib/mock-data.ts +1 -1
  49. package/landing/src/lib/stats.json +1 -1
  50. package/package.json +3 -8
  51. package/src/analytics.ts +0 -5
  52. package/src/bin.ts +1 -1
  53. package/src/cli/commands/mcp-install.ts +8 -90
  54. package/src/cli/index.ts +0 -8
  55. package/src/credentials.ts +39 -44
  56. package/src/discovery.ts +82 -191
  57. package/src/http-api.ts +34 -18
  58. package/src/proxy.ts +1 -1
  59. package/APILAYER_STATUS_2026-03-24.md +0 -38
  60. package/CHANGELOG-WHITELIST-V2.md +0 -269
  61. package/HIVR-WHITELIST-STATUS.md +0 -205
  62. package/HIVR-WHITELIST.md +0 -148
  63. package/TERMINOLOGY-AUDIT.md +0 -99
  64. package/TERMINOLOGY-FIXED.md +0 -74
  65. package/VIDEO-DEMO-GUIDE.md +0 -82
  66. package/WHITELIST-ARCHITECTURE.md +0 -379
  67. package/api/discover.ts +0 -71
  68. package/api/health.ts +0 -20
  69. package/convex/adminActivate.d.ts +0 -3
  70. package/convex/adminActivate.js +0 -47
  71. package/convex/adminStats.d.ts +0 -3
  72. package/convex/adminStats.js +0 -42
  73. package/convex/agents.d.ts +0 -54
  74. package/convex/agents.js +0 -499
  75. package/convex/analytics.d.ts +0 -5
  76. package/convex/analytics.js +0 -166
  77. package/convex/billing.d.ts +0 -88
  78. package/convex/billing.js +0 -655
  79. package/convex/capabilities.d.ts +0 -9
  80. package/convex/capabilities.js +0 -145
  81. package/convex/chains.d.ts +0 -67
  82. package/convex/chains.js +0 -1042
  83. package/convex/credits.d.ts +0 -25
  84. package/convex/credits.js +0 -186
  85. package/convex/crons.d.ts +0 -3
  86. package/convex/crons.js +0 -17
  87. package/convex/directCall.d.ts +0 -72
  88. package/convex/directCall.js +0 -627
  89. package/convex/earnProgress.d.ts +0 -58
  90. package/convex/earnProgress.js +0 -649
  91. package/convex/email.d.ts +0 -14
  92. package/convex/email.js +0 -300
  93. package/convex/feedback.d.ts +0 -7
  94. package/convex/feedback.js +0 -227
  95. package/convex/http.d.ts +0 -3
  96. package/convex/http.js +0 -910
  97. package/convex/logs.d.ts +0 -38
  98. package/convex/logs.js +0 -487
  99. package/convex/mou.d.ts +0 -6
  100. package/convex/mou.js +0 -82
  101. package/convex/providerKeys.d.ts +0 -31
  102. package/convex/providerKeys.js +0 -257
  103. package/convex/providers.d.ts +0 -29
  104. package/convex/providers.js +0 -756
  105. package/convex/purchases.d.ts +0 -7
  106. package/convex/purchases.js +0 -157
  107. package/convex/ratelimit.d.ts +0 -4
  108. package/convex/ratelimit.js +0 -91
  109. package/convex/searchLogs.d.ts +0 -4
  110. package/convex/searchLogs.js +0 -129
  111. package/convex/spendAlerts.d.ts +0 -36
  112. package/convex/spendAlerts.js +0 -380
  113. package/convex/stripeActions.d.ts +0 -19
  114. package/convex/stripeActions.js +0 -411
  115. package/convex/teams.d.ts +0 -21
  116. package/convex/teams.js +0 -215
  117. package/convex/telemetry.d.ts +0 -4
  118. package/convex/telemetry.js +0 -74
  119. package/convex/usage.d.ts +0 -27
  120. package/convex/usage.js +0 -229
  121. package/convex/waitlist.d.ts +0 -4
  122. package/convex/waitlist.js +0 -49
  123. package/convex/webhooks.d.ts +0 -12
  124. package/convex/webhooks.js +0 -410
  125. package/convex/workspaces.d.ts +0 -29
  126. package/convex/workspaces.js +0 -880
  127. package/direct-test.mjs +0 -51
  128. package/dist/access-control.d.ts +0 -45
  129. package/dist/access-control.d.ts.map +0 -1
  130. package/dist/access-control.js +0 -142
  131. package/dist/access-control.js.map +0 -1
  132. package/dist/chain-types.d.ts +0 -187
  133. package/dist/chain-types.d.ts.map +0 -1
  134. package/dist/chain-types.js +0 -33
  135. package/dist/chain-types.js.map +0 -1
  136. package/dist/convex/adminActivate.js +0 -46
  137. package/dist/convex/adminStats.js +0 -41
  138. package/dist/convex/agents.js +0 -498
  139. package/dist/convex/analytics.js +0 -165
  140. package/dist/convex/billing.js +0 -654
  141. package/dist/convex/capabilities.js +0 -144
  142. package/dist/convex/chains.js +0 -1041
  143. package/dist/convex/credits.js +0 -185
  144. package/dist/convex/crons.js +0 -16
  145. package/dist/convex/directCall.js +0 -626
  146. package/dist/convex/earnProgress.js +0 -648
  147. package/dist/convex/email.js +0 -299
  148. package/dist/convex/feedback.js +0 -226
  149. package/dist/convex/http.js +0 -909
  150. package/dist/convex/logs.js +0 -486
  151. package/dist/convex/mou.js +0 -81
  152. package/dist/convex/providerKeys.js +0 -256
  153. package/dist/convex/providers.js +0 -755
  154. package/dist/convex/purchases.js +0 -156
  155. package/dist/convex/ratelimit.js +0 -90
  156. package/dist/convex/schema.js +0 -709
  157. package/dist/convex/searchLogs.js +0 -128
  158. package/dist/convex/spendAlerts.js +0 -379
  159. package/dist/convex/stripeActions.js +0 -410
  160. package/dist/convex/teams.js +0 -214
  161. package/dist/convex/telemetry.js +0 -73
  162. package/dist/convex/usage.js +0 -228
  163. package/dist/convex/waitlist.js +0 -48
  164. package/dist/convex/webhooks.js +0 -409
  165. package/dist/convex/workspaces.js +0 -879
  166. package/dist/hivr-whitelist.d.ts +0 -18
  167. package/dist/hivr-whitelist.d.ts.map +0 -1
  168. package/dist/hivr-whitelist.js +0 -95
  169. package/dist/hivr-whitelist.js.map +0 -1
  170. package/dist/http-server-minimal.d.ts +0 -7
  171. package/dist/http-server-minimal.d.ts.map +0 -1
  172. package/dist/http-server-minimal.js +0 -126
  173. package/dist/http-server-minimal.js.map +0 -1
  174. package/dist/product-whitelist.d.ts +0 -37
  175. package/dist/product-whitelist.d.ts.map +0 -1
  176. package/dist/product-whitelist.js +0 -203
  177. package/dist/product-whitelist.js.map +0 -1
  178. package/dist/src/analytics.js +0 -129
  179. package/dist/src/bin.js +0 -17
  180. package/dist/src/capability-router.js +0 -240
  181. package/dist/src/chainExecutor.js +0 -451
  182. package/dist/src/chainResolver.js +0 -518
  183. package/dist/src/cli/commands/doctor.js +0 -324
  184. package/dist/src/cli/commands/mcp-install.js +0 -255
  185. package/dist/src/cli/commands/restore.js +0 -259
  186. package/dist/src/cli/commands/setup.js +0 -205
  187. package/dist/src/cli/commands/uninstall.js +0 -188
  188. package/dist/src/cli/index.js +0 -111
  189. package/dist/src/cli.js +0 -302
  190. package/dist/src/confirmation.js +0 -240
  191. package/dist/src/credentials.js +0 -357
  192. package/dist/src/credits.js +0 -260
  193. package/dist/src/crypto.js +0 -66
  194. package/dist/src/discovery.js +0 -504
  195. package/dist/src/enterprise/env.js +0 -123
  196. package/dist/src/enterprise/script-generator.js +0 -460
  197. package/dist/src/execute-dynamic.js +0 -473
  198. package/dist/src/execute.js +0 -1727
  199. package/dist/src/index.js +0 -2062
  200. package/dist/src/metered.js +0 -80
  201. package/dist/src/open-apis.js +0 -276
  202. package/dist/src/proxy.js +0 -28
  203. package/dist/src/session.js +0 -86
  204. package/dist/src/stripe.js +0 -407
  205. package/dist/src/telemetry.js +0 -49
  206. package/dist/src/types.js +0 -2
  207. package/dist/src/utils/backup.js +0 -181
  208. package/dist/src/utils/config.js +0 -220
  209. package/dist/src/utils/os.js +0 -105
  210. package/dist/src/utils/paths.js +0 -159
  211. package/landing/pages/api/discover.ts +0 -43
  212. package/landing/pages/api/health.ts +0 -20
  213. package/scripts/test-whitelist-v2.sh +0 -128
  214. package/src/access-control.ts +0 -174
  215. package/src/hivr-whitelist.ts +0 -110
  216. package/src/http-server-minimal.ts +0 -154
  217. package/src/product-whitelist.ts +0 -246
  218. package/test-actual-handlers.ts +0 -92
  219. package/test-apilayer-all-14.ts +0 -249
  220. package/test-apilayer-fixed.ts +0 -248
  221. package/test-direct-endpoints.ts +0 -174
  222. package/test-exact-endpoints.ts +0 -144
  223. package/test-final.ts +0 -83
  224. package/test-full-routing.ts +0 -100
  225. package/test-handlers-correct.ts +0 -217
  226. package/test-numverify-key.ts +0 -41
  227. package/test-via-handlers.ts +0 -92
  228. package/test-worldnews.mjs +0 -26
@@ -1,324 +0,0 @@
1
- /**
2
- * Doctor Command
3
- * Health check for APIClaw installation and MCP client configurations
4
- */
5
- import { existsSync } from 'fs';
6
- import { execSync } from 'child_process';
7
- import { getAllClients, getClientConfig } from '../../utils/paths.js';
8
- import { readConfig, hasApiclawConfig } from '../../utils/config.js';
9
- import { getApiUrl, readEnvConfig, ENV_VARS } from '../../enterprise/env.js';
10
- /**
11
- * Check Node.js availability and version
12
- */
13
- function checkNode() {
14
- try {
15
- const version = execSync('node --version', { encoding: 'utf-8' }).trim();
16
- const major = parseInt(version.replace('v', '').split('.')[0], 10);
17
- if (major < 18) {
18
- return {
19
- category: 'System',
20
- name: 'Node.js',
21
- status: 'warn',
22
- message: `${version} (recommend v18+)`,
23
- };
24
- }
25
- return {
26
- category: 'System',
27
- name: 'Node.js',
28
- status: 'pass',
29
- message: version,
30
- };
31
- }
32
- catch {
33
- return {
34
- category: 'System',
35
- name: 'Node.js',
36
- status: 'fail',
37
- message: 'Not found',
38
- details: 'Node.js is required. Install from https://nodejs.org',
39
- };
40
- }
41
- }
42
- /**
43
- * Check npm availability
44
- */
45
- function checkNpm() {
46
- try {
47
- const version = execSync('npm --version', { encoding: 'utf-8' }).trim();
48
- return {
49
- category: 'System',
50
- name: 'npm',
51
- status: 'pass',
52
- message: `v${version}`,
53
- };
54
- }
55
- catch {
56
- return {
57
- category: 'System',
58
- name: 'npm',
59
- status: 'fail',
60
- message: 'Not found',
61
- details: 'npm is required for npx to work',
62
- };
63
- }
64
- }
65
- /**
66
- * Check npx availability
67
- */
68
- function checkNpx() {
69
- try {
70
- execSync('npx --version', { encoding: 'utf-8', stdio: 'pipe' });
71
- return {
72
- category: 'System',
73
- name: 'npx',
74
- status: 'pass',
75
- message: 'Available',
76
- };
77
- }
78
- catch {
79
- return {
80
- category: 'System',
81
- name: 'npx',
82
- status: 'fail',
83
- message: 'Not found',
84
- details: 'npx is required for MCP server execution',
85
- };
86
- }
87
- }
88
- /**
89
- * Check MCP client configuration
90
- */
91
- function checkClient(client, serverName = 'apiclaw') {
92
- const config = getClientConfig(client);
93
- const configPath = config.configPath;
94
- // Check if config file exists
95
- if (!existsSync(configPath)) {
96
- // Check if config directory exists (client might be installed but not configured)
97
- const dirExists = existsSync(config.configDir);
98
- if (dirExists) {
99
- return {
100
- category: 'MCP Clients',
101
- name: config.displayName,
102
- status: 'warn',
103
- message: 'Installed but not configured',
104
- details: `Config file: ${configPath}`,
105
- };
106
- }
107
- return {
108
- category: 'MCP Clients',
109
- name: config.displayName,
110
- status: 'skip',
111
- message: 'Not installed',
112
- };
113
- }
114
- // Read and check config
115
- const readResult = readConfig(configPath);
116
- if (!readResult.success) {
117
- return {
118
- category: 'MCP Clients',
119
- name: config.displayName,
120
- status: 'fail',
121
- message: 'Invalid config',
122
- details: readResult.error,
123
- };
124
- }
125
- // Check if APIClaw is configured
126
- if (readResult.config && hasApiclawConfig(readResult.config, serverName)) {
127
- return {
128
- category: 'MCP Clients',
129
- name: config.displayName,
130
- status: 'pass',
131
- message: 'Configured',
132
- };
133
- }
134
- return {
135
- category: 'MCP Clients',
136
- name: config.displayName,
137
- status: 'warn',
138
- message: 'APIClaw not configured',
139
- details: `Run: npx @nordsym/apiclaw setup --client ${client}`,
140
- };
141
- }
142
- /**
143
- * Check API connectivity
144
- */
145
- async function checkConnectivity() {
146
- const apiUrl = getApiUrl();
147
- const convexUrl = process.env.CONVEX_URL || 'https://brilliant-puffin-712.eu-west-1.convex.cloud';
148
- const candidates = [
149
- `${apiUrl}/health`,
150
- 'https://apiclaw.nordsym.com',
151
- `${convexUrl.replace('.cloud', '.site')}/workspace/poll`,
152
- ];
153
- const failures = [];
154
- for (const testUrl of candidates) {
155
- try {
156
- const controller = new AbortController();
157
- const timeout = setTimeout(() => controller.abort(), 5000);
158
- const response = await fetch(testUrl, {
159
- method: 'GET',
160
- signal: controller.signal,
161
- });
162
- clearTimeout(timeout);
163
- // Any HTTP response proves network + host reachability.
164
- if (response.ok) {
165
- return {
166
- category: 'Connectivity',
167
- name: 'API Server',
168
- status: 'pass',
169
- message: `${testUrl} reachable`,
170
- };
171
- }
172
- if (testUrl.includes('/workspace/poll') && response.status === 400) {
173
- return {
174
- category: 'Connectivity',
175
- name: 'API Server',
176
- status: 'pass',
177
- message: `${testUrl} reachable (auth endpoint responding)`,
178
- };
179
- }
180
- failures.push(`${testUrl} -> HTTP ${response.status}`);
181
- }
182
- catch (error) {
183
- const reason = error instanceof Error ? error.message : 'Unknown error';
184
- failures.push(`${testUrl} -> ${reason}`);
185
- }
186
- }
187
- return {
188
- category: 'Connectivity',
189
- name: 'API Server',
190
- status: 'skip',
191
- message: 'Could not reach API (offline or DNS/TLS issue?)',
192
- details: failures.join(' | '),
193
- };
194
- }
195
- /**
196
- * Check environment variables
197
- */
198
- function checkEnvVars() {
199
- const envConfig = readEnvConfig();
200
- const results = [];
201
- if (envConfig.workspace) {
202
- results.push({
203
- category: 'Environment',
204
- name: ENV_VARS.WORKSPACE,
205
- status: 'pass',
206
- message: envConfig.workspace,
207
- });
208
- }
209
- if (envConfig.apiUrl) {
210
- results.push({
211
- category: 'Environment',
212
- name: ENV_VARS.API_URL,
213
- status: 'pass',
214
- message: envConfig.apiUrl,
215
- });
216
- }
217
- if (envConfig.disableTelemetry) {
218
- results.push({
219
- category: 'Environment',
220
- name: ENV_VARS.DISABLE_TELEMETRY,
221
- status: 'pass',
222
- message: 'true',
223
- });
224
- }
225
- return results;
226
- }
227
- /**
228
- * Run all health checks
229
- */
230
- export async function runDoctor(options = {}) {
231
- const checks = [];
232
- const serverName = options.serverName || 'apiclaw';
233
- // System checks
234
- checks.push(checkNode());
235
- checks.push(checkNpm());
236
- checks.push(checkNpx());
237
- // Client checks
238
- for (const client of getAllClients()) {
239
- checks.push(checkClient(client, serverName));
240
- }
241
- // Connectivity check
242
- checks.push(await checkConnectivity());
243
- // Environment checks
244
- checks.push(...checkEnvVars());
245
- // Calculate health status
246
- const failures = checks.filter(c => c.status === 'fail');
247
- const warnings = checks.filter(c => c.status === 'warn');
248
- const passes = checks.filter(c => c.status === 'pass');
249
- let healthy = failures.length === 0;
250
- let summary;
251
- if (failures.length > 0) {
252
- summary = `${failures.length} issue(s) found`;
253
- }
254
- else if (warnings.length > 0) {
255
- summary = `All systems operational (${warnings.length} warning(s))`;
256
- }
257
- else {
258
- summary = 'All systems operational āœ“';
259
- }
260
- return { healthy, checks, summary };
261
- }
262
- /**
263
- * Format doctor results for display
264
- */
265
- export function formatDoctorOutput(result) {
266
- const lines = [];
267
- lines.push('');
268
- lines.push('šŸ” APIClaw Health Check');
269
- lines.push('========================');
270
- lines.push('');
271
- // Group checks by category
272
- const categories = new Map();
273
- for (const check of result.checks) {
274
- const existing = categories.get(check.category) || [];
275
- existing.push(check);
276
- categories.set(check.category, existing);
277
- }
278
- // Format each category
279
- for (const [category, checks] of categories) {
280
- // Skip empty categories
281
- if (checks.length === 0)
282
- continue;
283
- lines.push(`${category}:`);
284
- for (const check of checks) {
285
- const icon = getStatusIcon(check.status);
286
- lines.push(` ${icon} ${check.name} - ${check.message}`);
287
- if (check.details && (check.status === 'fail' || check.status === 'warn')) {
288
- lines.push(` ${check.details}`);
289
- }
290
- }
291
- lines.push('');
292
- }
293
- // Summary
294
- lines.push(`Status: ${result.summary}`);
295
- lines.push('');
296
- return lines.join('\n');
297
- }
298
- /**
299
- * Get icon for status
300
- */
301
- function getStatusIcon(status) {
302
- switch (status) {
303
- case 'pass': return 'āœ“';
304
- case 'fail': return 'āœ—';
305
- case 'warn': return '⚠';
306
- case 'skip': return 'ā—‹';
307
- }
308
- }
309
- /**
310
- * Doctor command handler
311
- */
312
- export async function doctorCommand(options = {}) {
313
- const result = await runDoctor(options);
314
- if (options.json) {
315
- console.log(JSON.stringify(result, null, 2));
316
- }
317
- else {
318
- console.log(formatDoctorOutput(result));
319
- }
320
- // Exit with error code if unhealthy
321
- if (!result.healthy) {
322
- process.exit(1);
323
- }
324
- }
@@ -1,255 +0,0 @@
1
- /**
2
- * MCP Install Command
3
- * Simple, focused command to install APIClaw into MCP config files
4
- * Supports Claude Desktop and Claude Code
5
- */
6
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
7
- import { dirname, join } from 'path';
8
- import { platform, homedir } from 'os';
9
- import chalk from 'chalk';
10
- /**
11
- * Detect operating system
12
- */
13
- function detectOS() {
14
- const os = platform();
15
- switch (os) {
16
- case 'darwin': return 'mac';
17
- case 'win32': return 'win';
18
- default: return 'linux';
19
- }
20
- }
21
- /**
22
- * Get home directory
23
- */
24
- function getHome() {
25
- return homedir();
26
- }
27
- /**
28
- * Get config paths for supported clients
29
- */
30
- function getClientConfigs() {
31
- const os = detectOS();
32
- const home = getHome();
33
- const clients = [
34
- {
35
- name: 'claude-desktop',
36
- displayName: 'Claude Desktop',
37
- configKey: 'mcpServers',
38
- getConfigPath: () => {
39
- switch (os) {
40
- case 'mac':
41
- return join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
42
- case 'win':
43
- return join(process.env.APPDATA || join(home, 'AppData', 'Roaming'), 'Claude', 'claude_desktop_config.json');
44
- case 'linux':
45
- return join(home, '.config', 'Claude', 'claude_desktop_config.json');
46
- }
47
- },
48
- },
49
- {
50
- name: 'claude-code',
51
- displayName: 'Claude Code',
52
- configKey: 'mcpServers',
53
- getConfigPath: () => {
54
- // Claude Code uses ~/.claude.json on all platforms
55
- return join(home, '.claude.json');
56
- },
57
- },
58
- ];
59
- return clients;
60
- }
61
- /**
62
- * APIClaw MCP server configuration
63
- */
64
- const APICLAW_CONFIG = {
65
- command: 'npx',
66
- args: ['-y', '@nordsym/apiclaw', 'serve'],
67
- };
68
- /**
69
- * Read JSON config file
70
- */
71
- function readConfig(path) {
72
- try {
73
- if (!existsSync(path)) {
74
- return { success: true, config: {}, isNew: true };
75
- }
76
- const content = readFileSync(path, 'utf-8');
77
- if (!content.trim()) {
78
- return { success: true, config: {}, isNew: true };
79
- }
80
- return { success: true, config: JSON.parse(content), isNew: false };
81
- }
82
- catch (error) {
83
- return {
84
- success: false,
85
- config: null,
86
- error: error instanceof Error ? error.message : 'Unknown error'
87
- };
88
- }
89
- }
90
- /**
91
- * Write JSON config file with backup
92
- */
93
- function writeConfig(path, config, createBackup = true) {
94
- try {
95
- const dir = dirname(path);
96
- if (!existsSync(dir)) {
97
- mkdirSync(dir, { recursive: true });
98
- }
99
- // Create backup if file exists
100
- if (createBackup && existsSync(path)) {
101
- const backupPath = `${path}.backup.${Date.now()}.json`;
102
- const existing = readFileSync(path, 'utf-8');
103
- writeFileSync(backupPath, existing, 'utf-8');
104
- }
105
- writeFileSync(path, JSON.stringify(config, null, 2), 'utf-8');
106
- return { success: true };
107
- }
108
- catch (error) {
109
- return {
110
- success: false,
111
- error: error instanceof Error ? error.message : 'Unknown error'
112
- };
113
- }
114
- }
115
- /**
116
- * Install APIClaw into a client config
117
- */
118
- function installToClient(client, dryRun) {
119
- const configPath = client.getConfigPath();
120
- // Read existing config
121
- const readResult = readConfig(configPath);
122
- if (!readResult.success) {
123
- return { success: false, message: `Failed to read config: ${readResult.error}` };
124
- }
125
- const config = readResult.config;
126
- // Initialize mcpServers if not present
127
- if (!config.mcpServers) {
128
- config.mcpServers = {};
129
- }
130
- // Check if already installed
131
- if (config.mcpServers.apiclaw) {
132
- return { success: true, message: 'Already installed', skipped: true };
133
- }
134
- // Add APIClaw config
135
- config.mcpServers.apiclaw = APICLAW_CONFIG;
136
- if (dryRun) {
137
- console.log(chalk.cyan(`\n Would add to ${configPath}:`));
138
- console.log(chalk.gray(JSON.stringify({ apiclaw: APICLAW_CONFIG }, null, 4)));
139
- return { success: true, message: 'Dry run - no changes made', skipped: true };
140
- }
141
- // Write config
142
- const writeResult = writeConfig(configPath, config);
143
- if (!writeResult.success) {
144
- return { success: false, message: `Failed to write config: ${writeResult.error}` };
145
- }
146
- return {
147
- success: true,
148
- message: readResult.isNew ? 'Created new config' : 'Updated config'
149
- };
150
- }
151
- /**
152
- * Main mcp-install command handler
153
- */
154
- export async function mcpInstallCommand(options) {
155
- const os = detectOS();
156
- const osName = os === 'mac' ? 'macOS' : os === 'win' ? 'Windows' : 'Linux';
157
- console.log(chalk.bold('\nšŸ¦ž APIClaw MCP Install\n'));
158
- console.log(`Platform: ${osName}\n`);
159
- const clients = getClientConfigs();
160
- let targetClients = clients;
161
- // Filter to specific client if requested
162
- if (options.client) {
163
- const normalizedClient = options.client.toLowerCase().replace(/[_\s]/g, '-');
164
- const aliases = {
165
- 'claude': 'claude-desktop',
166
- 'claude-desktop': 'claude-desktop',
167
- 'claudedesktop': 'claude-desktop',
168
- 'desktop': 'claude-desktop',
169
- 'code': 'claude-code',
170
- 'claude-code': 'claude-code',
171
- 'claudecode': 'claude-code',
172
- };
173
- const targetName = aliases[normalizedClient];
174
- if (!targetName) {
175
- console.log(chalk.red(`āŒ Unknown client: ${options.client}`));
176
- console.log(' Supported: claude-desktop, claude-code');
177
- process.exit(1);
178
- }
179
- targetClients = clients.filter(c => c.name === targetName);
180
- }
181
- // Detect which clients exist
182
- console.log('šŸ” Detecting MCP clients...\n');
183
- const detectedClients = [];
184
- for (const client of targetClients) {
185
- const configPath = client.getConfigPath();
186
- const configDir = dirname(configPath);
187
- const exists = existsSync(configPath) || existsSync(configDir);
188
- const icon = exists ? chalk.green('āœ“') : chalk.gray('āœ—');
189
- const status = exists ? 'found' : 'not found';
190
- console.log(` ${icon} ${client.displayName} ${status}`);
191
- if (exists) {
192
- detectedClients.push(client);
193
- }
194
- }
195
- console.log('');
196
- if (detectedClients.length === 0) {
197
- console.log(chalk.yellow('āš ļø No MCP clients detected.'));
198
- console.log(' Install Claude Desktop or Claude Code first.\n');
199
- process.exit(0);
200
- }
201
- // Install to each detected client
202
- let successCount = 0;
203
- let skipCount = 0;
204
- let failCount = 0;
205
- for (const client of detectedClients) {
206
- const result = installToClient(client, options.dryRun || false);
207
- if (result.success) {
208
- if (result.skipped) {
209
- skipCount++;
210
- console.log(chalk.yellow(`ā­ļø ${client.displayName}: ${result.message}`));
211
- }
212
- else {
213
- successCount++;
214
- console.log(chalk.green(`āœ“ ${client.displayName}: ${result.message}`));
215
- }
216
- }
217
- else {
218
- failCount++;
219
- console.log(chalk.red(`āœ— ${client.displayName}: ${result.message}`));
220
- }
221
- }
222
- // Summary
223
- console.log('\n' + '═'.repeat(50));
224
- if (failCount === 0) {
225
- if (options.dryRun) {
226
- console.log(chalk.cyan('\nāœ… Dry run complete! Run without --dry-run to apply changes.\n'));
227
- }
228
- else if (successCount > 0) {
229
- console.log(chalk.green('\nāœ… APIClaw installed successfully!\n'));
230
- console.log(chalk.bold('What you get:\n'));
231
- console.log(chalk.cyan(' šŸ” Search') + ' 22,000+ APIs to discover');
232
- console.log(chalk.cyan(' 🌐 Open APIs') + ' 1,600 free APIs');
233
- console.log(chalk.cyan(' šŸ”‘ Direct Call') + ' 1,500+ premium (APIClaw manages keys)');
234
- console.log('');
235
- console.log('Next:');
236
- console.log(' 1. Restart your MCP client');
237
- console.log(' 2. Try: "Find weather APIs"');
238
- console.log('');
239
- console.log('Docs: https://apiclaw.com/docs\n');
240
- }
241
- else {
242
- console.log(chalk.yellow('\nāœ… APIClaw already installed in all clients.\n'));
243
- console.log(chalk.bold('What you have:\n'));
244
- console.log(chalk.cyan(' šŸ” Search') + ' 22,000+ APIs to discover');
245
- console.log(chalk.cyan(' 🌐 Open APIs') + ' 1,600 free APIs');
246
- console.log(chalk.cyan(' šŸ”‘ Direct Call') + ' 1,500+ premium (APIClaw manages keys)');
247
- console.log('');
248
- console.log('Run with --force to reinstall (coming soon).\n');
249
- }
250
- }
251
- else {
252
- console.log(chalk.red(`\nāš ļø Installation completed with ${failCount} error(s).\n`));
253
- process.exit(1);
254
- }
255
- }