mcpmake 0.1.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.
Files changed (344) hide show
  1. package/README.md +691 -0
  2. package/bin/mcpmake.mjs +2 -0
  3. package/dist/analyzer/auth-detector.d.ts +12 -0
  4. package/dist/analyzer/auth-detector.js +142 -0
  5. package/dist/analyzer/dom-parser.d.ts +10 -0
  6. package/dist/analyzer/dom-parser.js +259 -0
  7. package/dist/analyzer/goal-crawler.d.ts +25 -0
  8. package/dist/analyzer/goal-crawler.js +177 -0
  9. package/dist/analyzer/hybrid-detector.d.ts +28 -0
  10. package/dist/analyzer/hybrid-detector.js +96 -0
  11. package/dist/analyzer/index.d.ts +12 -0
  12. package/dist/analyzer/index.js +8 -0
  13. package/dist/analyzer/screenshot-capture.d.ts +29 -0
  14. package/dist/analyzer/screenshot-capture.js +42 -0
  15. package/dist/analyzer/selector-builder.d.ts +19 -0
  16. package/dist/analyzer/selector-builder.js +199 -0
  17. package/dist/analyzer/semantic-analyzer.d.ts +13 -0
  18. package/dist/analyzer/semantic-analyzer.js +145 -0
  19. package/dist/analyzer/site-crawler.d.ts +38 -0
  20. package/dist/analyzer/site-crawler.js +235 -0
  21. package/dist/cloud/billing/billing-engine.d.ts +44 -0
  22. package/dist/cloud/billing/billing-engine.js +81 -0
  23. package/dist/cloud/billing/credit-store.d.ts +64 -0
  24. package/dist/cloud/billing/credit-store.js +168 -0
  25. package/dist/cloud/billing/index.d.ts +4 -0
  26. package/dist/cloud/billing/index.js +2 -0
  27. package/dist/cloud/billing/usage-store.d.ts +42 -0
  28. package/dist/cloud/billing/usage-store.js +85 -0
  29. package/dist/cloud/billing/usage-tracker.d.ts +38 -0
  30. package/dist/cloud/billing/usage-tracker.js +95 -0
  31. package/dist/cloud/build-pipeline.d.ts +39 -0
  32. package/dist/cloud/build-pipeline.js +310 -0
  33. package/dist/cloud/build-queue.d.ts +30 -0
  34. package/dist/cloud/build-queue.js +70 -0
  35. package/dist/cloud/caddy-manager.d.ts +18 -0
  36. package/dist/cloud/caddy-manager.js +97 -0
  37. package/dist/cloud/container-backend.d.ts +62 -0
  38. package/dist/cloud/container-backend.js +59 -0
  39. package/dist/cloud/container-manager.d.ts +64 -0
  40. package/dist/cloud/container-manager.js +301 -0
  41. package/dist/cloud/crypto.d.ts +27 -0
  42. package/dist/cloud/crypto.js +63 -0
  43. package/dist/cloud/db/index.d.ts +27 -0
  44. package/dist/cloud/db/index.js +53 -0
  45. package/dist/cloud/db/migrations.d.ts +12 -0
  46. package/dist/cloud/db/migrations.js +329 -0
  47. package/dist/cloud/db/pg-store.d.ts +45 -0
  48. package/dist/cloud/db/pg-store.js +336 -0
  49. package/dist/cloud/failure-tracker.d.ts +51 -0
  50. package/dist/cloud/failure-tracker.js +102 -0
  51. package/dist/cloud/idle-monitor.d.ts +30 -0
  52. package/dist/cloud/idle-monitor.js +70 -0
  53. package/dist/cloud/mailer.d.ts +21 -0
  54. package/dist/cloud/mailer.js +193 -0
  55. package/dist/cloud/mcp-proxy.d.ts +58 -0
  56. package/dist/cloud/mcp-proxy.js +203 -0
  57. package/dist/cloud/metric-samples.d.ts +43 -0
  58. package/dist/cloud/metric-samples.js +85 -0
  59. package/dist/cloud/metrics.d.ts +26 -0
  60. package/dist/cloud/metrics.js +59 -0
  61. package/dist/cloud/multipart.d.ts +26 -0
  62. package/dist/cloud/multipart.js +132 -0
  63. package/dist/cloud/observability.d.ts +27 -0
  64. package/dist/cloud/observability.js +98 -0
  65. package/dist/cloud/rate-limiter.d.ts +31 -0
  66. package/dist/cloud/rate-limiter.js +58 -0
  67. package/dist/cloud/request-security.d.ts +5 -0
  68. package/dist/cloud/request-security.js +74 -0
  69. package/dist/cloud/resource-monitor.d.ts +69 -0
  70. package/dist/cloud/resource-monitor.js +130 -0
  71. package/dist/cloud/secret-store.d.ts +38 -0
  72. package/dist/cloud/secret-store.js +103 -0
  73. package/dist/cloud/security.d.ts +26 -0
  74. package/dist/cloud/security.js +142 -0
  75. package/dist/cloud/server.d.ts +21 -0
  76. package/dist/cloud/server.js +1079 -0
  77. package/dist/cloud/shared-state.d.ts +72 -0
  78. package/dist/cloud/shared-state.js +159 -0
  79. package/dist/cloud/ssrf.d.ts +43 -0
  80. package/dist/cloud/ssrf.js +150 -0
  81. package/dist/cloud/store.d.ts +41 -0
  82. package/dist/cloud/store.js +75 -0
  83. package/dist/cloud/stripe.d.ts +78 -0
  84. package/dist/cloud/stripe.js +317 -0
  85. package/dist/cloud/telemetry-store.d.ts +53 -0
  86. package/dist/cloud/telemetry-store.js +108 -0
  87. package/dist/cloud/web/auth.d.ts +225 -0
  88. package/dist/cloud/web/auth.js +555 -0
  89. package/dist/cloud/web/charts.d.ts +70 -0
  90. package/dist/cloud/web/charts.js +178 -0
  91. package/dist/cloud/web/csrf.d.ts +14 -0
  92. package/dist/cloud/web/csrf.js +22 -0
  93. package/dist/cloud/web/docs.d.ts +40 -0
  94. package/dist/cloud/web/docs.js +174 -0
  95. package/dist/cloud/web/router.d.ts +25 -0
  96. package/dist/cloud/web/router.js +1921 -0
  97. package/dist/cloud/web/static/alpine.min.js +5 -0
  98. package/dist/cloud/web/static/favicon.svg +4 -0
  99. package/dist/cloud/web/static/htmx-sse.js +290 -0
  100. package/dist/cloud/web/static/htmx.min.js +1 -0
  101. package/dist/cloud/web/static/style.css +2683 -0
  102. package/dist/cloud/web/static-server.d.ts +13 -0
  103. package/dist/cloud/web/static-server.js +73 -0
  104. package/dist/cloud/web/template-engine.d.ts +27 -0
  105. package/dist/cloud/web/template-engine.js +146 -0
  106. package/dist/cloud/web/templates/layouts/admin.hbs +57 -0
  107. package/dist/cloud/web/templates/layouts/auth.hbs +138 -0
  108. package/dist/cloud/web/templates/layouts/base.hbs +16 -0
  109. package/dist/cloud/web/templates/layouts/dashboard.hbs +39 -0
  110. package/dist/cloud/web/templates/layouts/landing.hbs +82 -0
  111. package/dist/cloud/web/templates/pages/admin/overview.hbs +123 -0
  112. package/dist/cloud/web/templates/pages/admin/servers.hbs +129 -0
  113. package/dist/cloud/web/templates/pages/admin/telemetry.hbs +39 -0
  114. package/dist/cloud/web/templates/pages/admin/user-edit.hbs +91 -0
  115. package/dist/cloud/web/templates/pages/admin/users.hbs +179 -0
  116. package/dist/cloud/web/templates/pages/auth/forgot-password.hbs +25 -0
  117. package/dist/cloud/web/templates/pages/auth/login.hbs +33 -0
  118. package/dist/cloud/web/templates/pages/auth/register.hbs +32 -0
  119. package/dist/cloud/web/templates/pages/auth/reset-password.hbs +34 -0
  120. package/dist/cloud/web/templates/pages/dashboard/billing.hbs +140 -0
  121. package/dist/cloud/web/templates/pages/dashboard/create.hbs +173 -0
  122. package/dist/cloud/web/templates/pages/dashboard/index.hbs +8 -0
  123. package/dist/cloud/web/templates/pages/dashboard/server-detail.hbs +280 -0
  124. package/dist/cloud/web/templates/pages/dashboard/server-logs.hbs +35 -0
  125. package/dist/cloud/web/templates/pages/dashboard/server-metrics.hbs +63 -0
  126. package/dist/cloud/web/templates/pages/dashboard/servers-partial.hbs +21 -0
  127. package/dist/cloud/web/templates/pages/dashboard/servers.hbs +44 -0
  128. package/dist/cloud/web/templates/pages/docs/show.hbs +16 -0
  129. package/dist/cloud/web/templates/pages/errors/404.hbs +9 -0
  130. package/dist/cloud/web/templates/pages/errors/500.hbs +8 -0
  131. package/dist/cloud/web/templates/pages/landing/index.hbs +223 -0
  132. package/dist/cloud/web/templates/pages/legal/privacy.hbs +71 -0
  133. package/dist/cloud/web/templates/pages/legal/terms.hbs +73 -0
  134. package/dist/cloud/web/templates/partials/admin-stats.hbs +52 -0
  135. package/dist/cloud/web/templates/partials/flash-message.hbs +6 -0
  136. package/dist/cloud/web/templates/partials/pricing-table.hbs +103 -0
  137. package/dist/cloud/web/templates/partials/server-card.hbs +19 -0
  138. package/dist/cloud/web/templates/partials/status-badge.hbs +1 -0
  139. package/dist/commands/bundle.d.ts +18 -0
  140. package/dist/commands/bundle.js +82 -0
  141. package/dist/commands/ci.d.ts +25 -0
  142. package/dist/commands/ci.js +149 -0
  143. package/dist/commands/deploy.d.ts +24 -0
  144. package/dist/commands/deploy.js +145 -0
  145. package/dist/commands/diff.d.ts +18 -0
  146. package/dist/commands/diff.js +185 -0
  147. package/dist/commands/from/describe.d.ts +65 -0
  148. package/dist/commands/from/describe.js +173 -0
  149. package/dist/commands/from/har.d.ts +81 -0
  150. package/dist/commands/from/har.js +255 -0
  151. package/dist/commands/from/openapi.d.ts +105 -0
  152. package/dist/commands/from/openapi.js +302 -0
  153. package/dist/commands/from/postman.d.ts +51 -0
  154. package/dist/commands/from/postman.js +146 -0
  155. package/dist/commands/from/target-support.d.ts +11 -0
  156. package/dist/commands/from/target-support.js +33 -0
  157. package/dist/commands/from/url.d.ts +75 -0
  158. package/dist/commands/from/url.js +244 -0
  159. package/dist/commands/from/website.d.ts +75 -0
  160. package/dist/commands/from/website.js +284 -0
  161. package/dist/commands/lint.d.ts +24 -0
  162. package/dist/commands/lint.js +184 -0
  163. package/dist/commands/merge.d.ts +18 -0
  164. package/dist/commands/merge.js +161 -0
  165. package/dist/commands/publish.d.ts +27 -0
  166. package/dist/commands/publish.js +334 -0
  167. package/dist/commands/rescan.d.ts +40 -0
  168. package/dist/commands/rescan.js +255 -0
  169. package/dist/commands/update.d.ts +14 -0
  170. package/dist/commands/update.js +87 -0
  171. package/dist/commands/verify.d.ts +14 -0
  172. package/dist/commands/verify.js +71 -0
  173. package/dist/config/configurable-command.d.ts +13 -0
  174. package/dist/config/configurable-command.js +70 -0
  175. package/dist/config/mcpmake-config.d.ts +68 -0
  176. package/dist/config/mcpmake-config.js +207 -0
  177. package/dist/docs/cli.md +400 -0
  178. package/dist/docs/mcp-2026-07-28-migration.md +78 -0
  179. package/dist/docs/migrate-from-stainless.md +94 -0
  180. package/dist/docs/quickstart.md +166 -0
  181. package/dist/docs/show-hn.md +26 -0
  182. package/dist/docs/website-servers.md +169 -0
  183. package/dist/emitter/code-writer.d.ts +8 -0
  184. package/dist/emitter/code-writer.js +25 -0
  185. package/dist/emitter/index.d.ts +32 -0
  186. package/dist/emitter/index.js +280 -0
  187. package/dist/emitter/mcpb-bundler.d.ts +31 -0
  188. package/dist/emitter/mcpb-bundler.js +172 -0
  189. package/dist/emitter/project-scaffolder.d.ts +4 -0
  190. package/dist/emitter/project-scaffolder.js +89 -0
  191. package/dist/emitter/python-template-loader.d.ts +4 -0
  192. package/dist/emitter/python-template-loader.js +30 -0
  193. package/dist/emitter/python-templates/dockerfile.hbs +14 -0
  194. package/dist/emitter/python-templates/env.example.hbs +6 -0
  195. package/dist/emitter/python-templates/requirements.txt.hbs +4 -0
  196. package/dist/emitter/python-templates/server.py.hbs +77 -0
  197. package/dist/emitter/site-scaffolder.d.ts +13 -0
  198. package/dist/emitter/site-scaffolder.js +70 -0
  199. package/dist/emitter/site-template-loader.d.ts +5 -0
  200. package/dist/emitter/site-template-loader.js +47 -0
  201. package/dist/emitter/site-templates/browser-manager.ts.hbs +233 -0
  202. package/dist/emitter/site-templates/config.ts.hbs +28 -0
  203. package/dist/emitter/site-templates/dockerfile.hbs +31 -0
  204. package/dist/emitter/site-templates/env.example.hbs +19 -0
  205. package/dist/emitter/site-templates/package.json.hbs +26 -0
  206. package/dist/emitter/site-templates/server-main-http.ts.hbs +108 -0
  207. package/dist/emitter/site-templates/server-main.ts.hbs +23 -0
  208. package/dist/emitter/site-templates/tool-handler-action.ts.hbs +86 -0
  209. package/dist/emitter/site-templates/tool-handler-form.ts.hbs +116 -0
  210. package/dist/emitter/site-templates/tool-handler-lifecycle.ts.hbs +146 -0
  211. package/dist/emitter/site-templates/tool-index.ts.hbs +11 -0
  212. package/dist/emitter/template-loader.d.ts +1 -0
  213. package/dist/emitter/template-loader.js +27 -0
  214. package/dist/emitter/templates/auth-provider.ts.hbs +57 -0
  215. package/dist/emitter/templates/config.ts.hbs +63 -0
  216. package/dist/emitter/templates/discovery.ts.hbs +301 -0
  217. package/dist/emitter/templates/dockerfile.hbs +34 -0
  218. package/dist/emitter/templates/env.example.hbs +28 -0
  219. package/dist/emitter/templates/gitignore.hbs +5 -0
  220. package/dist/emitter/templates/http-executor.ts.hbs +117 -0
  221. package/dist/emitter/templates/oauth.ts.hbs +188 -0
  222. package/dist/emitter/templates/package.json.hbs +25 -0
  223. package/dist/emitter/templates/prompts.ts.hbs +22 -0
  224. package/dist/emitter/templates/readme.md.hbs +123 -0
  225. package/dist/emitter/templates/resources.ts.hbs +63 -0
  226. package/dist/emitter/templates/server-main-http.ts.hbs +407 -0
  227. package/dist/emitter/templates/server-main.ts.hbs +40 -0
  228. package/dist/emitter/templates/task-handlers.ts.hbs +189 -0
  229. package/dist/emitter/templates/task-manager.ts.hbs +139 -0
  230. package/dist/emitter/templates/task-sse.ts.hbs +105 -0
  231. package/dist/emitter/templates/tool-handler.ts.hbs +124 -0
  232. package/dist/emitter/templates/tool-index.ts.hbs +11 -0
  233. package/dist/emitter/templates/tool-test.ts.hbs +57 -0
  234. package/dist/emitter/templates/trace.ts.hbs +79 -0
  235. package/dist/emitter/templates/tsconfig.json.hbs +16 -0
  236. package/dist/emitter/templates/types.ts.hbs +5 -0
  237. package/dist/emitter/worker-template-loader.d.ts +5 -0
  238. package/dist/emitter/worker-template-loader.js +33 -0
  239. package/dist/emitter/worker-templates/config.ts.hbs +54 -0
  240. package/dist/emitter/worker-templates/dev-vars.example.hbs +10 -0
  241. package/dist/emitter/worker-templates/gitignore.hbs +6 -0
  242. package/dist/emitter/worker-templates/package.json.hbs +24 -0
  243. package/dist/emitter/worker-templates/readme.md.hbs +53 -0
  244. package/dist/emitter/worker-templates/server.test.ts.hbs +20 -0
  245. package/dist/emitter/worker-templates/tool-handler.ts.hbs +85 -0
  246. package/dist/emitter/worker-templates/tool-index.ts.hbs +28 -0
  247. package/dist/emitter/worker-templates/tsconfig.json.hbs +17 -0
  248. package/dist/emitter/worker-templates/worker.ts.hbs +242 -0
  249. package/dist/emitter/worker-templates/wrangler.toml.hbs +19 -0
  250. package/dist/generator/spec-generator.d.ts +6 -0
  251. package/dist/generator/spec-generator.js +50 -0
  252. package/dist/index.d.ts +1 -0
  253. package/dist/index.js +64 -0
  254. package/dist/parser/har-filter.d.ts +8 -0
  255. package/dist/parser/har-filter.js +71 -0
  256. package/dist/parser/har-loader.d.ts +2 -0
  257. package/dist/parser/har-loader.js +14 -0
  258. package/dist/parser/har-normalizer.d.ts +20 -0
  259. package/dist/parser/har-normalizer.js +78 -0
  260. package/dist/parser/index.d.ts +10 -0
  261. package/dist/parser/index.js +6 -0
  262. package/dist/parser/openapi-loader.d.ts +6 -0
  263. package/dist/parser/openapi-loader.js +308 -0
  264. package/dist/parser/operation-extractor.d.ts +13 -0
  265. package/dist/parser/operation-extractor.js +155 -0
  266. package/dist/parser/overlay-loader.d.ts +10 -0
  267. package/dist/parser/overlay-loader.js +184 -0
  268. package/dist/parser/postman-loader.d.ts +9 -0
  269. package/dist/parser/postman-loader.js +106 -0
  270. package/dist/parser/schema-converter.d.ts +12 -0
  271. package/dist/parser/schema-converter.js +117 -0
  272. package/dist/plugins/adapter.d.ts +40 -0
  273. package/dist/plugins/adapter.js +15 -0
  274. package/dist/plugins/loader.d.ts +25 -0
  275. package/dist/plugins/loader.js +58 -0
  276. package/dist/pricing.d.ts +55 -0
  277. package/dist/pricing.js +133 -0
  278. package/dist/providers/index.d.ts +15 -0
  279. package/dist/providers/index.js +56 -0
  280. package/dist/recorder/browser-recorder.d.ts +22 -0
  281. package/dist/recorder/browser-recorder.js +205 -0
  282. package/dist/registry/official-registry.d.ts +90 -0
  283. package/dist/registry/official-registry.js +129 -0
  284. package/dist/rescan/diff-engine.d.ts +5 -0
  285. package/dist/rescan/diff-engine.js +312 -0
  286. package/dist/rescan/index.d.ts +3 -0
  287. package/dist/rescan/index.js +2 -0
  288. package/dist/rescan/rescan-runner.d.ts +42 -0
  289. package/dist/rescan/rescan-runner.js +69 -0
  290. package/dist/rescan/rescan-scheduler.d.ts +41 -0
  291. package/dist/rescan/rescan-scheduler.js +179 -0
  292. package/dist/site-transformer/browser-tools.d.ts +10 -0
  293. package/dist/site-transformer/browser-tools.js +59 -0
  294. package/dist/site-transformer/index.d.ts +2 -0
  295. package/dist/site-transformer/index.js +2 -0
  296. package/dist/site-transformer/selector-healer.d.ts +8 -0
  297. package/dist/site-transformer/selector-healer.js +106 -0
  298. package/dist/site-transformer/tool-generator.d.ts +13 -0
  299. package/dist/site-transformer/tool-generator.js +245 -0
  300. package/dist/transformer/auth-detector.d.ts +13 -0
  301. package/dist/transformer/auth-detector.js +90 -0
  302. package/dist/transformer/catalog-builder.d.ts +18 -0
  303. package/dist/transformer/catalog-builder.js +56 -0
  304. package/dist/transformer/client-compat.d.ts +6 -0
  305. package/dist/transformer/client-compat.js +44 -0
  306. package/dist/transformer/har-clusterer.d.ts +9 -0
  307. package/dist/transformer/har-clusterer.js +27 -0
  308. package/dist/transformer/har-dedup.d.ts +10 -0
  309. package/dist/transformer/har-dedup.js +81 -0
  310. package/dist/transformer/har-schema-inferrer.d.ts +15 -0
  311. package/dist/transformer/har-schema-inferrer.js +90 -0
  312. package/dist/transformer/har-to-operations.d.ts +13 -0
  313. package/dist/transformer/har-to-operations.js +192 -0
  314. package/dist/transformer/index.d.ts +8 -0
  315. package/dist/transformer/index.js +6 -0
  316. package/dist/transformer/llm-namer.d.ts +6 -0
  317. package/dist/transformer/llm-namer.js +59 -0
  318. package/dist/transformer/naming.d.ts +4 -0
  319. package/dist/transformer/naming.js +30 -0
  320. package/dist/transformer/operation-filter.d.ts +13 -0
  321. package/dist/transformer/operation-filter.js +52 -0
  322. package/dist/transformer/resource-builder.d.ts +12 -0
  323. package/dist/transformer/resource-builder.js +80 -0
  324. package/dist/transformer/schema-merger.d.ts +14 -0
  325. package/dist/transformer/schema-merger.js +65 -0
  326. package/dist/transformer/tool-builder.d.ts +3 -0
  327. package/dist/transformer/tool-builder.js +114 -0
  328. package/dist/types/index.d.ts +131 -0
  329. package/dist/types/index.js +1 -0
  330. package/dist/types/site.d.ts +284 -0
  331. package/dist/types/site.js +8 -0
  332. package/dist/utils/fail.d.ts +48 -0
  333. package/dist/utils/fail.js +204 -0
  334. package/dist/utils/fs.d.ts +5 -0
  335. package/dist/utils/fs.js +28 -0
  336. package/dist/utils/interactive.d.ts +6 -0
  337. package/dist/utils/interactive.js +30 -0
  338. package/dist/utils/logger.d.ts +1 -0
  339. package/dist/utils/logger.js +2 -0
  340. package/dist/utils/sanitize.d.ts +28 -0
  341. package/dist/utils/sanitize.js +44 -0
  342. package/dist/utils/watcher.d.ts +11 -0
  343. package/dist/utils/watcher.js +36 -0
  344. package/package.json +65 -0
@@ -0,0 +1,255 @@
1
+ import { defineCommand } from 'citty';
2
+ import { loadHarFile } from '../../parser/har-loader.js';
3
+ import { filterHarEntries } from '../../parser/har-filter.js';
4
+ import { normalizeEntry } from '../../parser/har-normalizer.js';
5
+ import { clusterEntries } from '../../transformer/har-clusterer.js';
6
+ import { clustersToOperations } from '../../transformer/har-to-operations.js';
7
+ import { deduplicateEntries } from '../../transformer/har-dedup.js';
8
+ import { improveToolNames } from '../../transformer/llm-namer.js';
9
+ import { buildAllTools } from '../../transformer/tool-builder.js';
10
+ import { filterOperations } from '../../transformer/operation-filter.js';
11
+ import { emitProject, emitPythonProject } from '../../emitter/index.js';
12
+ import { targetArg, resolveTarget, resolveTransport, printWorkerNextSteps, } from './target-support.js';
13
+ import { logger } from '../../utils/logger.js';
14
+ import { fail } from '../../utils/fail.js';
15
+ import { confirmOperations } from '../../utils/interactive.js';
16
+ function toPackageName(name) {
17
+ return name
18
+ .toLowerCase()
19
+ .replace(/[^a-z0-9]+/g, '-')
20
+ .replace(/^-|-$/g, '');
21
+ }
22
+ export default defineCommand({
23
+ meta: {
24
+ name: 'har',
25
+ description: 'Generate an MCP server from a HAR (HTTP Archive) file',
26
+ },
27
+ args: {
28
+ file: {
29
+ type: 'positional',
30
+ description: 'Path to HAR file (exported from browser DevTools)',
31
+ required: true,
32
+ },
33
+ output: {
34
+ type: 'string',
35
+ alias: 'o',
36
+ description: 'Output directory for generated project',
37
+ required: true,
38
+ },
39
+ name: {
40
+ type: 'string',
41
+ alias: 'n',
42
+ description: 'Server name',
43
+ },
44
+ domain: {
45
+ type: 'string',
46
+ alias: 'd',
47
+ description: 'Only include requests to this domain (can repeat with commas)',
48
+ },
49
+ 'include-errors': {
50
+ type: 'boolean',
51
+ description: 'Include requests that returned HTTP errors',
52
+ default: false,
53
+ },
54
+ 'improve-names': {
55
+ type: 'boolean',
56
+ description: 'Use AI to generate better tool names (requires ANTHROPIC_API_KEY)',
57
+ default: false,
58
+ },
59
+ dedup: {
60
+ type: 'boolean',
61
+ description: 'Deduplicate pagination and retry requests',
62
+ default: true,
63
+ },
64
+ interactive: {
65
+ type: 'boolean',
66
+ description: 'Review and confirm detected tools before generation',
67
+ default: false,
68
+ },
69
+ force: {
70
+ type: 'boolean',
71
+ alias: 'f',
72
+ description: 'Overwrite existing output directory',
73
+ default: false,
74
+ },
75
+ transport: {
76
+ type: 'string',
77
+ alias: 't',
78
+ description: 'Transport mode: "stdio" (default) or "http"',
79
+ default: 'stdio',
80
+ },
81
+ include: {
82
+ type: 'string',
83
+ alias: 'i',
84
+ description: 'Only include operations matching these patterns (comma-separated)',
85
+ },
86
+ exclude: {
87
+ type: 'string',
88
+ alias: 'e',
89
+ description: 'Exclude operations matching these patterns (comma-separated)',
90
+ },
91
+ 'dry-run': {
92
+ type: 'boolean',
93
+ description: 'Preview generated files without writing',
94
+ default: false,
95
+ },
96
+ format: {
97
+ type: 'string',
98
+ description: 'Output format: "typescript" (default), "python"',
99
+ default: 'typescript',
100
+ },
101
+ target: targetArg,
102
+ },
103
+ async run({ args }) {
104
+ logger.info(`Loading HAR file: ${args.file}`);
105
+ const har = await loadHarFile(args.file);
106
+ logger.info(`Found ${har.log.entries.length} total entries`);
107
+ // Filter noise
108
+ const allowedDomains = args.domain?.split(',').map((d) => d.trim()) ?? [];
109
+ const filtered = filterHarEntries(har.log.entries, {
110
+ allowedDomains: allowedDomains.length > 0 ? allowedDomains : undefined,
111
+ includeErrors: args['include-errors'] ?? false,
112
+ });
113
+ logger.info(`${filtered.length} API entries after filtering`);
114
+ if (filtered.length === 0) {
115
+ await fail('No API requests found after filtering. Try --domain to specify the API host.');
116
+ }
117
+ // Normalize paths (detect IDs, UUIDs, etc.)
118
+ let normalized = filtered.map(normalizeEntry);
119
+ // Deduplicate pagination and retries
120
+ if (args.dedup !== false) {
121
+ const before = normalized.length;
122
+ normalized = deduplicateEntries(normalized);
123
+ if (normalized.length < before) {
124
+ logger.info(`Deduplicated: ${before} → ${normalized.length} entries`);
125
+ }
126
+ }
127
+ // Cluster into logical operations
128
+ const clusters = clusterEntries(normalized);
129
+ logger.info(`Clustered into ${clusters.length} operations`);
130
+ // Convert to OperationDescriptors (shared with OpenAPI pipeline)
131
+ let { operations: allOperations, baseUrl, detectedAuth } = clustersToOperations(clusters);
132
+ // LLM-assisted naming
133
+ if (args['improve-names']) {
134
+ allOperations = await improveToolNames(allOperations);
135
+ }
136
+ // Apply include/exclude filters
137
+ let operations = filterOperations(allOperations, {
138
+ include: args.include?.split(',').map((s) => s.trim()),
139
+ exclude: args.exclude?.split(',').map((s) => s.trim()),
140
+ });
141
+ if (operations.length === 0) {
142
+ await fail('No operations left after filtering.');
143
+ }
144
+ if (operations.length !== allOperations.length) {
145
+ logger.info(`${operations.length} operations after filtering`);
146
+ }
147
+ // Interactive confirmation
148
+ if (args.interactive) {
149
+ operations = await confirmOperations(operations);
150
+ if (operations.length === 0) {
151
+ await fail('No operations selected.');
152
+ }
153
+ }
154
+ // Convert detected auth to AuthSchemes
155
+ const authSchemes = [];
156
+ const envVars = [];
157
+ for (const auth of detectedAuth) {
158
+ if (auth.type === 'bearer') {
159
+ authSchemes.push({
160
+ type: 'http-bearer',
161
+ envVarName: 'BEARER_TOKEN',
162
+ description: 'Bearer token detected in HAR',
163
+ });
164
+ envVars.push({
165
+ name: 'BEARER_TOKEN',
166
+ description: 'Bearer authentication token',
167
+ required: true,
168
+ });
169
+ }
170
+ else if (auth.type === 'basic') {
171
+ authSchemes.push({
172
+ type: 'http-basic',
173
+ envVarName: 'BASIC_USERNAME',
174
+ description: 'Basic auth detected in HAR',
175
+ });
176
+ envVars.push({ name: 'BASIC_USERNAME', description: 'Basic auth username', required: true }, { name: 'BASIC_PASSWORD', description: 'Basic auth password', required: true });
177
+ }
178
+ else if (auth.type === 'apiKey') {
179
+ authSchemes.push({
180
+ type: 'apiKey',
181
+ envVarName: 'API_KEY',
182
+ headerName: auth.headerName,
183
+ in: 'header',
184
+ description: `API key header: ${auth.headerName}`,
185
+ });
186
+ envVars.push({
187
+ name: 'API_KEY',
188
+ description: `API key (sent as header "${auth.headerName}")`,
189
+ required: true,
190
+ });
191
+ }
192
+ }
193
+ // Dedupe env vars
194
+ const seen = new Set();
195
+ const uniqueEnvVars = envVars.filter((v) => {
196
+ if (seen.has(v.name))
197
+ return false;
198
+ seen.add(v.name);
199
+ return true;
200
+ });
201
+ // Build tools (reuses OpenAPI pipeline)
202
+ const tools = buildAllTools(operations);
203
+ const serverName = args.name ?? toPackageName(new URL(baseUrl).hostname);
204
+ const target = resolveTarget(args.target);
205
+ const transport = resolveTransport(target, args.transport);
206
+ const manifest = {
207
+ serverName,
208
+ serverVersion: '1.0.0',
209
+ baseUrl,
210
+ transport,
211
+ tools,
212
+ authSchemes,
213
+ envVars: [
214
+ { name: 'BASE_URL', description: 'API base URL', required: true, example: baseUrl },
215
+ ...uniqueEnvVars,
216
+ ],
217
+ target,
218
+ };
219
+ const emitOpts = {
220
+ outputDir: args.output,
221
+ force: args.force ?? false,
222
+ dryRun: args['dry-run'] ?? false,
223
+ };
224
+ const outputFormat = args.format ?? 'typescript';
225
+ if (target === 'cloudflare' && outputFormat === 'python') {
226
+ await fail('--target cloudflare is only available for TypeScript output (not --format python)');
227
+ }
228
+ logger.info(`Generating ${outputFormat} MCP server: ${serverName}` +
229
+ (target === 'cloudflare' ? ' (Cloudflare Workers)' : ''));
230
+ if (outputFormat === 'python') {
231
+ await emitPythonProject(manifest, emitOpts);
232
+ }
233
+ else {
234
+ await emitProject(manifest, emitOpts);
235
+ }
236
+ logger.success(`MCP server generated at: ${args.output}`);
237
+ logger.info('');
238
+ logger.info(`Tools generated: ${tools.length}`);
239
+ if (detectedAuth.length > 0) {
240
+ logger.info(`Auth detected: ${detectedAuth.map((a) => a.type).join(', ')}`);
241
+ }
242
+ if (target === 'cloudflare') {
243
+ printWorkerNextSteps(args.output);
244
+ }
245
+ else {
246
+ logger.info('');
247
+ logger.info('Next steps:');
248
+ logger.info(` cd ${args.output}`);
249
+ logger.info(' cp .env.example .env # fill in your credentials');
250
+ logger.info(' npm install');
251
+ logger.info(' npm run build');
252
+ logger.info(' npm start');
253
+ }
254
+ },
255
+ });
@@ -0,0 +1,105 @@
1
+ declare const _default: import("citty").CommandDef<{
2
+ spec: {
3
+ type: "positional";
4
+ description: string;
5
+ required: true;
6
+ };
7
+ output: {
8
+ type: "string";
9
+ alias: string;
10
+ description: string;
11
+ required: true;
12
+ };
13
+ name: {
14
+ type: "string";
15
+ alias: string;
16
+ description: string;
17
+ };
18
+ 'base-url': {
19
+ type: "string";
20
+ alias: string;
21
+ description: string;
22
+ };
23
+ force: {
24
+ type: "boolean";
25
+ alias: string;
26
+ description: string;
27
+ default: false;
28
+ };
29
+ transport: {
30
+ type: "string";
31
+ alias: string;
32
+ description: string;
33
+ default: string;
34
+ };
35
+ include: {
36
+ type: "string";
37
+ alias: string;
38
+ description: string;
39
+ };
40
+ exclude: {
41
+ type: "string";
42
+ alias: string;
43
+ description: string;
44
+ };
45
+ 'dry-run': {
46
+ type: "boolean";
47
+ description: string;
48
+ default: false;
49
+ };
50
+ client: {
51
+ type: "string";
52
+ alias: string;
53
+ description: string;
54
+ };
55
+ 'no-resources': {
56
+ type: "boolean";
57
+ description: string;
58
+ default: false;
59
+ };
60
+ 'no-prompts': {
61
+ type: "boolean";
62
+ description: string;
63
+ default: false;
64
+ };
65
+ 'dynamic-discovery': {
66
+ type: "boolean";
67
+ description: string;
68
+ default: false;
69
+ };
70
+ 'static-tools': {
71
+ type: "string";
72
+ description: string;
73
+ };
74
+ watch: {
75
+ type: "boolean";
76
+ alias: string;
77
+ description: string;
78
+ default: false;
79
+ };
80
+ 'improve-names': {
81
+ type: "boolean";
82
+ description: string;
83
+ default: false;
84
+ };
85
+ overlay: {
86
+ type: "string";
87
+ description: string;
88
+ };
89
+ format: {
90
+ type: "string";
91
+ description: string;
92
+ default: string;
93
+ };
94
+ target: {
95
+ type: "string";
96
+ description: string;
97
+ default: string;
98
+ };
99
+ mcpb: {
100
+ type: "boolean";
101
+ description: string;
102
+ default: false;
103
+ };
104
+ }>;
105
+ export default _default;
@@ -0,0 +1,302 @@
1
+ import { defineConfigurableCommand } from '../../config/configurable-command.js';
2
+ import { resolve } from 'node:path';
3
+ import { execFile as execFileCb } from 'node:child_process';
4
+ import { promisify } from 'node:util';
5
+ import { loadOpenApiSpec } from '../../parser/openapi-loader.js';
6
+ import { applyOverlay } from '../../parser/overlay-loader.js';
7
+ import { extractOperations } from '../../parser/operation-extractor.js';
8
+ import { detectAuthSchemes } from '../../transformer/auth-detector.js';
9
+ import { buildAllTools } from '../../transformer/tool-builder.js';
10
+ import { filterOperations } from '../../transformer/operation-filter.js';
11
+ import { improveToolNames } from '../../transformer/llm-namer.js';
12
+ import { buildResources, buildPrompts } from '../../transformer/resource-builder.js';
13
+ import { applyClientCompat } from '../../transformer/client-compat.js';
14
+ import { emitProject, emitPythonProject } from '../../emitter/index.js';
15
+ import { printWorkerNextSteps } from './target-support.js';
16
+ import { generateMcpb } from '../../emitter/mcpb-bundler.js';
17
+ import { getProvider, getProviderNames } from '../../providers/index.js';
18
+ import { logger } from '../../utils/logger.js';
19
+ import { fail } from '../../utils/fail.js';
20
+ import { watchFile } from '../../utils/watcher.js';
21
+ const execFile = promisify(execFileCb);
22
+ function toPackageName(title) {
23
+ return title
24
+ .toLowerCase()
25
+ .replace(/[^a-z0-9]+/g, '-')
26
+ .replace(/^-|-$/g, '');
27
+ }
28
+ export default defineConfigurableCommand('openapi', {
29
+ meta: {
30
+ name: 'openapi',
31
+ description: 'Generate an MCP server from an OpenAPI specification',
32
+ },
33
+ args: {
34
+ spec: {
35
+ type: 'positional',
36
+ description: `Path/URL to OpenAPI spec, or provider name (${getProviderNames().join(', ')})`,
37
+ required: true,
38
+ },
39
+ output: {
40
+ type: 'string',
41
+ alias: 'o',
42
+ description: 'Output directory for generated project',
43
+ required: true,
44
+ },
45
+ name: {
46
+ type: 'string',
47
+ alias: 'n',
48
+ description: 'Server name (defaults to API title from spec)',
49
+ },
50
+ 'base-url': {
51
+ type: 'string',
52
+ alias: 'b',
53
+ description: 'Base URL override (defaults to first server in spec)',
54
+ },
55
+ force: {
56
+ type: 'boolean',
57
+ alias: 'f',
58
+ description: 'Overwrite existing output directory',
59
+ default: false,
60
+ },
61
+ transport: {
62
+ type: 'string',
63
+ alias: 't',
64
+ description: 'Transport mode: "stdio" (default) or "http"',
65
+ default: 'stdio',
66
+ },
67
+ include: {
68
+ type: 'string',
69
+ alias: 'i',
70
+ description: 'Only include operations matching these patterns (comma-separated tags, paths, or operationIds)',
71
+ },
72
+ exclude: {
73
+ type: 'string',
74
+ alias: 'e',
75
+ description: 'Exclude operations matching these patterns (comma-separated)',
76
+ },
77
+ 'dry-run': {
78
+ type: 'boolean',
79
+ description: 'Preview generated files without writing',
80
+ default: false,
81
+ },
82
+ client: {
83
+ type: 'string',
84
+ alias: 'c',
85
+ description: 'Client compatibility mode: cursor, claude, openai',
86
+ },
87
+ 'no-resources': {
88
+ type: 'boolean',
89
+ description: 'Skip generating MCP resources',
90
+ default: false,
91
+ },
92
+ 'no-prompts': {
93
+ type: 'boolean',
94
+ description: 'Skip generating MCP prompts',
95
+ default: false,
96
+ },
97
+ 'dynamic-discovery': {
98
+ type: 'boolean',
99
+ description: 'Emit 4 meta-tools instead of N individual tools (for large APIs)',
100
+ default: false,
101
+ },
102
+ 'static-tools': {
103
+ type: 'string',
104
+ description: 'With --dynamic-discovery: also register first N tools statically',
105
+ },
106
+ watch: {
107
+ type: 'boolean',
108
+ alias: 'w',
109
+ description: 'Watch spec file for changes and regenerate',
110
+ default: false,
111
+ },
112
+ 'improve-names': {
113
+ type: 'boolean',
114
+ description: 'Use AI to generate better tool names (requires ANTHROPIC_API_KEY)',
115
+ default: false,
116
+ },
117
+ overlay: {
118
+ type: 'string',
119
+ description: 'Path to an OpenAPI Overlay file (YAML/JSON) to patch the spec before processing',
120
+ },
121
+ format: {
122
+ type: 'string',
123
+ description: 'Output format: "typescript" (default), "python"',
124
+ default: 'typescript',
125
+ },
126
+ target: {
127
+ type: 'string',
128
+ description: 'Deployment target: "node" (default) or "cloudflare" (Cloudflare Workers)',
129
+ default: 'node',
130
+ },
131
+ mcpb: {
132
+ type: 'boolean',
133
+ description: 'Also generate an .mcpb bundle for one-click Claude Desktop install',
134
+ default: false,
135
+ },
136
+ },
137
+ async run({ args }) {
138
+ // Resolve provider shortcut
139
+ const provider = getProvider(args.spec);
140
+ const specPath = provider?.specUrl ?? args.spec;
141
+ if (provider) {
142
+ logger.info(`Using provider template: ${provider.name} (${provider.description})`);
143
+ if (provider.suggestedIncludes && !args.include) {
144
+ logger.info(`Tip: use --include ${provider.suggestedIncludes.join(',')} to reduce tool count`);
145
+ }
146
+ }
147
+ logger.info(`Loading OpenAPI spec from: ${specPath}`);
148
+ const { api } = await loadOpenApiSpec(specPath);
149
+ // Apply overlay if specified (patches spec before extraction)
150
+ if (args.overlay) {
151
+ await applyOverlay(api, args.overlay);
152
+ }
153
+ let { operations, baseUrl, securitySchemes, info } = extractOperations(api);
154
+ if (operations.length === 0) {
155
+ await fail('No operations found in the spec.');
156
+ }
157
+ logger.info(`Found ${operations.length} operations`);
158
+ // LLM-assisted naming
159
+ if (args['improve-names']) {
160
+ operations = await improveToolNames(operations);
161
+ }
162
+ const filtered = filterOperations(operations, {
163
+ include: args.include?.split(',').map((s) => s.trim()),
164
+ exclude: args.exclude?.split(',').map((s) => s.trim()),
165
+ });
166
+ if (filtered.length === 0) {
167
+ await fail('No operations left after filtering. Check your --include/--exclude patterns.');
168
+ }
169
+ if (filtered.length !== operations.length) {
170
+ logger.info(`${filtered.length} operations after filtering`);
171
+ }
172
+ let tools = buildAllTools(filtered);
173
+ if (args.client) {
174
+ tools = applyClientCompat(tools, args.client);
175
+ }
176
+ const { authSchemes, envVars } = detectAuthSchemes(securitySchemes);
177
+ const serverName = args.name ?? (provider ? provider.name : toPackageName(info.title));
178
+ const resolvedBaseUrl = args['base-url'] ?? baseUrl ?? provider?.baseUrl;
179
+ if (!resolvedBaseUrl) {
180
+ await fail('No base URL found in spec. Use --base-url to provide one.');
181
+ }
182
+ const target = args.target === 'cloudflare' ? 'cloudflare' : 'node';
183
+ // Cloudflare Workers always run as a stateless HTTP fetch handler — there is
184
+ // no stdio there. Override transport so shared template data stays coherent.
185
+ const transport = target === 'cloudflare' ? 'http' : args.transport === 'http' ? 'http' : 'stdio';
186
+ const resources = args['no-resources'] ? [] : buildResources(filtered);
187
+ const prompts = args['no-prompts'] ? [] : buildPrompts(filtered);
188
+ const dynamicDiscovery = args['dynamic-discovery'] ?? false;
189
+ const staticToolCount = args['static-tools'] ? parseInt(args['static-tools'], 10) : undefined;
190
+ const manifest = {
191
+ serverName,
192
+ serverVersion: info.version ?? '1.0.0',
193
+ baseUrl: resolvedBaseUrl,
194
+ transport: transport,
195
+ tools,
196
+ resources,
197
+ prompts,
198
+ authSchemes,
199
+ envVars: [
200
+ {
201
+ name: 'BASE_URL',
202
+ description: 'API base URL',
203
+ required: true,
204
+ example: resolvedBaseUrl,
205
+ },
206
+ ...envVars,
207
+ ],
208
+ dynamicDiscovery,
209
+ staticToolCount,
210
+ target,
211
+ };
212
+ const emitOpts = {
213
+ outputDir: args.output,
214
+ force: args.force ?? false,
215
+ dryRun: args['dry-run'] ?? false,
216
+ };
217
+ const outputFormat = args.format ?? 'typescript';
218
+ if (target === 'cloudflare' && outputFormat === 'python') {
219
+ await fail('--target cloudflare is only available for TypeScript output (not --format python)');
220
+ }
221
+ logger.info(`Generating ${outputFormat} MCP server: ${serverName}` +
222
+ (target === 'cloudflare' ? ' (Cloudflare Workers)' : ''));
223
+ if (outputFormat === 'python') {
224
+ await emitPythonProject(manifest, emitOpts);
225
+ logger.success(`Python MCP server generated at: ${args.output}`);
226
+ logger.info('');
227
+ logger.info('Next steps:');
228
+ logger.info(` cd ${args.output}`);
229
+ logger.info(' cp .env.example .env # fill in your credentials');
230
+ logger.info(' pip install -r requirements.txt');
231
+ logger.info(' python server.py');
232
+ if (args.mcpb) {
233
+ logger.warn('MCPB bundling is only supported for TypeScript projects');
234
+ }
235
+ }
236
+ else {
237
+ await emitProject(manifest, emitOpts);
238
+ logger.success(`MCP server generated at: ${args.output}`);
239
+ if (target === 'cloudflare') {
240
+ if (args.mcpb) {
241
+ logger.warn('MCPB bundling is not applicable to the Cloudflare Workers target');
242
+ }
243
+ printWorkerNextSteps(args.output);
244
+ }
245
+ else if (args.mcpb && !args['dry-run']) {
246
+ const projectDir = resolve(args.output);
247
+ logger.info('Installing production dependencies...');
248
+ await execFile('npm', ['install', '--omit=dev'], {
249
+ cwd: projectDir,
250
+ timeout: 120_000,
251
+ });
252
+ logger.info('Building project...');
253
+ await execFile('npm', ['run', 'build'], {
254
+ cwd: projectDir,
255
+ timeout: 120_000,
256
+ });
257
+ logger.info('Creating .mcpb bundle...');
258
+ const mcpbPath = await generateMcpb({ projectDir });
259
+ logger.success(`MCPB bundle created: ${mcpbPath}`);
260
+ }
261
+ else {
262
+ logger.info('');
263
+ logger.info('Next steps:');
264
+ logger.info(` cd ${args.output}`);
265
+ logger.info(' cp .env.example .env # fill in your credentials');
266
+ logger.info(' npm install');
267
+ logger.info(' npm run build');
268
+ logger.info(' npm start');
269
+ }
270
+ }
271
+ // Watch mode — re-generate on spec file changes
272
+ if (args.watch && !provider) {
273
+ watchFile({
274
+ filePath: args.spec,
275
+ onChange: async () => {
276
+ const { api: freshApi } = await loadOpenApiSpec(specPath);
277
+ if (args.overlay) {
278
+ await applyOverlay(freshApi, args.overlay);
279
+ }
280
+ const fresh = extractOperations(freshApi);
281
+ const freshFiltered = filterOperations(fresh.operations, {
282
+ include: args.include?.split(',').map((s) => s.trim()),
283
+ exclude: args.exclude?.split(',').map((s) => s.trim()),
284
+ });
285
+ const freshTools = buildAllTools(freshFiltered);
286
+ const freshAuth = detectAuthSchemes(fresh.securitySchemes);
287
+ const freshResources = buildResources(freshFiltered);
288
+ const freshPrompts = buildPrompts(freshFiltered);
289
+ await emitProject({
290
+ ...manifest,
291
+ tools: freshTools,
292
+ resources: freshResources,
293
+ prompts: freshPrompts,
294
+ authSchemes: freshAuth.authSchemes,
295
+ }, { outputDir: args.output, force: true, dryRun: false });
296
+ },
297
+ });
298
+ // Keep the process alive
299
+ await new Promise(() => { });
300
+ }
301
+ },
302
+ });