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,50 @@
1
+ import Anthropic from '@anthropic-ai/sdk';
2
+ import { logger } from '../utils/logger.js';
3
+ const SYSTEM_PROMPT = `You are an API architect. Given a description of an API or service, generate a valid OpenAPI 3.0 specification in JSON format.
4
+
5
+ Rules:
6
+ - Output ONLY valid JSON (no markdown fences, no explanation)
7
+ - Include realistic endpoints with proper HTTP methods
8
+ - Use descriptive operationIds in camelCase
9
+ - Include request/response schemas with realistic field types
10
+ - Add path parameters, query parameters, and request bodies where appropriate
11
+ - Include at least one security scheme if auth is likely needed
12
+ - Include a servers array with a base URL
13
+ - Keep it practical — 3-10 operations is typical`;
14
+ export async function generateSpecFromDescription(options) {
15
+ const apiKey = process.env.ANTHROPIC_API_KEY;
16
+ if (!apiKey) {
17
+ throw new Error('ANTHROPIC_API_KEY environment variable is required for describe mode.\n' +
18
+ 'Set it with: export ANTHROPIC_API_KEY=your-key-here');
19
+ }
20
+ const client = new Anthropic({ apiKey });
21
+ const model = options.model ?? 'claude-sonnet-4-20250514';
22
+ let userPrompt = `Generate an OpenAPI 3.0 spec for: ${options.description}`;
23
+ if (options.baseUrl) {
24
+ userPrompt += `\n\nUse this base URL: ${options.baseUrl}`;
25
+ }
26
+ logger.info('Generating OpenAPI spec from description...');
27
+ const message = await client.messages.create({
28
+ model,
29
+ max_tokens: 4096,
30
+ system: SYSTEM_PROMPT,
31
+ messages: [{ role: 'user', content: userPrompt }],
32
+ });
33
+ const content = message.content[0];
34
+ if (content.type !== 'text') {
35
+ throw new Error('Unexpected response format from Claude');
36
+ }
37
+ // Extract JSON — strip markdown fences if present
38
+ let json = content.text.trim();
39
+ if (json.startsWith('```')) {
40
+ json = json.replace(/^```(?:json)?\n?/, '').replace(/\n?```$/, '');
41
+ }
42
+ // Validate it's parseable JSON
43
+ try {
44
+ JSON.parse(json);
45
+ }
46
+ catch {
47
+ throw new Error('Claude returned invalid JSON. Try again or refine your description.');
48
+ }
49
+ return json;
50
+ }
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,64 @@
1
+ import { defineCommand, runMain } from 'citty';
2
+ import { logger } from './utils/logger.js';
3
+ import openapiCommand from './commands/from/openapi.js';
4
+ import harCommand from './commands/from/har.js';
5
+ import urlCommand from './commands/from/url.js';
6
+ import describeCommand from './commands/from/describe.js';
7
+ import postmanCommand from './commands/from/postman.js';
8
+ import websiteCommand from './commands/from/website.js';
9
+ import verifyCommand from './commands/verify.js';
10
+ import updateCommand from './commands/update.js';
11
+ import deployCommand from './commands/deploy.js';
12
+ import publishCommand from './commands/publish.js';
13
+ import mergeCommand from './commands/merge.js';
14
+ import lintCommand from './commands/lint.js';
15
+ import diffCommand from './commands/diff.js';
16
+ import bundleCommand from './commands/bundle.js';
17
+ import ciCommand from './commands/ci.js';
18
+ import rescanCommand from './commands/rescan.js';
19
+ const fromCommand = defineCommand({
20
+ meta: {
21
+ name: 'from',
22
+ description: 'Generate an MCP server from a source',
23
+ },
24
+ subCommands: {
25
+ openapi: openapiCommand,
26
+ har: harCommand,
27
+ url: urlCommand,
28
+ describe: describeCommand,
29
+ postman: postmanCommand,
30
+ website: websiteCommand,
31
+ },
32
+ });
33
+ const main = defineCommand({
34
+ meta: {
35
+ name: 'mcpmake',
36
+ version: '0.1.0',
37
+ description: 'Generate MCP servers from API specifications',
38
+ },
39
+ subCommands: {
40
+ from: fromCommand,
41
+ merge: mergeCommand,
42
+ verify: verifyCommand,
43
+ update: updateCommand,
44
+ deploy: deployCommand,
45
+ publish: publishCommand,
46
+ lint: lintCommand,
47
+ diff: diffCommand,
48
+ bundle: bundleCommand,
49
+ ci: ciCommand,
50
+ rescan: rescanCommand,
51
+ },
52
+ });
53
+ // Last-resort handlers for *unexpected* throws (the command failure sites use
54
+ // `fail()` instead). These fire too late to reliably await a network POST — the
55
+ // process is already tearing down — so we only log and signal a failed exit.
56
+ process.on('uncaughtException', (err) => {
57
+ logger.error(`Unexpected error: ${err instanceof Error ? err.message : String(err)}`);
58
+ process.exitCode = 1;
59
+ });
60
+ process.on('unhandledRejection', (reason) => {
61
+ logger.error(`Unhandled rejection: ${reason instanceof Error ? reason.message : String(reason)}`);
62
+ process.exitCode = 1;
63
+ });
64
+ runMain(main);
@@ -0,0 +1,8 @@
1
+ import type { Entry } from 'har-format';
2
+ export interface FilterOptions {
3
+ /** Only include entries from these domains. If empty, include all. */
4
+ allowedDomains?: string[];
5
+ /** Include requests that returned errors (4xx/5xx). Default: false */
6
+ includeErrors?: boolean;
7
+ }
8
+ export declare function filterHarEntries(entries: Entry[], options?: FilterOptions): Entry[];
@@ -0,0 +1,71 @@
1
+ const NOISE_EXTENSIONS = /\.(js|css|png|jpg|jpeg|gif|svg|ico|woff|woff2|ttf|eot|map|webp|avif)(\?|$)/i;
2
+ const ANALYTICS_DOMAINS = [
3
+ 'google-analytics.com',
4
+ 'googletagmanager.com',
5
+ 'analytics.',
6
+ 'mixpanel.com',
7
+ 'segment.io',
8
+ 'segment.com',
9
+ 'hotjar.com',
10
+ 'doubleclick.net',
11
+ 'facebook.net',
12
+ 'fbcdn.net',
13
+ 'sentry.io',
14
+ 'newrelic.com',
15
+ 'datadoghq.com',
16
+ 'clarity.ms',
17
+ ];
18
+ const SKIP_MIME_TYPES = [
19
+ 'text/html',
20
+ 'text/css',
21
+ 'application/javascript',
22
+ 'text/javascript',
23
+ 'image/',
24
+ 'font/',
25
+ 'audio/',
26
+ 'video/',
27
+ ];
28
+ export function filterHarEntries(entries, options = {}) {
29
+ return entries.filter((entry) => {
30
+ const url = entry.request.url;
31
+ let hostname;
32
+ try {
33
+ hostname = new URL(url).hostname;
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ // Skip non-HTTP methods
39
+ const method = entry.request.method.toUpperCase();
40
+ if (method === 'CONNECT' || method === 'OPTIONS')
41
+ return false;
42
+ // Skip static assets by extension
43
+ const pathname = new URL(url).pathname;
44
+ if (NOISE_EXTENSIONS.test(pathname))
45
+ return false;
46
+ // Skip analytics/tracking domains
47
+ if (ANALYTICS_DOMAINS.some((d) => hostname.includes(d)))
48
+ return false;
49
+ // Domain allowlist
50
+ if (options.allowedDomains?.length) {
51
+ if (!options.allowedDomains.some((d) => hostname.includes(d)))
52
+ return false;
53
+ }
54
+ // Skip error responses unless requested
55
+ if (!options.includeErrors && entry.response.status >= 400)
56
+ return false;
57
+ // Skip non-API content types in response
58
+ const responseMime = entry.response.content?.mimeType ?? '';
59
+ if (SKIP_MIME_TYPES.some((m) => responseMime.startsWith(m))) {
60
+ // Exception: text/html that's actually an API response (rare but possible)
61
+ // Keep if response body looks like JSON
62
+ if (responseMime.startsWith('text/html') && !entry.response.content?.text?.startsWith('{')) {
63
+ return false;
64
+ }
65
+ if (!responseMime.includes('json') && !responseMime.includes('xml')) {
66
+ return false;
67
+ }
68
+ }
69
+ return true;
70
+ });
71
+ }
@@ -0,0 +1,2 @@
1
+ import type { Har } from 'har-format';
2
+ export declare function loadHarFile(filePath: string): Promise<Har>;
@@ -0,0 +1,14 @@
1
+ import { readFile, stat } from 'node:fs/promises';
2
+ const MAX_HAR_SIZE_BYTES = 50 * 1024 * 1024; // 50 MB
3
+ export async function loadHarFile(filePath) {
4
+ const fileInfo = await stat(filePath);
5
+ if (fileInfo.size > MAX_HAR_SIZE_BYTES) {
6
+ throw new Error(`HAR file is too large (${Math.round(fileInfo.size / 1024 / 1024)} MB). Maximum is 50 MB.`);
7
+ }
8
+ const raw = await readFile(filePath, 'utf-8');
9
+ const har = JSON.parse(raw);
10
+ if (!har.log?.entries || !Array.isArray(har.log.entries)) {
11
+ throw new Error('Invalid HAR file: missing log.entries array');
12
+ }
13
+ return har;
14
+ }
@@ -0,0 +1,20 @@
1
+ import type { Entry } from 'har-format';
2
+ export interface NormalizedEntry {
3
+ entry: Entry;
4
+ normalizedPath: string;
5
+ baseUrl: string;
6
+ pathParams: PathParam[];
7
+ queryParams: QueryParam[];
8
+ }
9
+ export interface PathParam {
10
+ name: string;
11
+ position: number;
12
+ exampleValue: string;
13
+ inferredType: 'uuid' | 'integer' | 'string';
14
+ }
15
+ export interface QueryParam {
16
+ name: string;
17
+ exampleValue: string;
18
+ inferredType: 'integer' | 'boolean' | 'string';
19
+ }
20
+ export declare function normalizeEntry(entry: Entry): NormalizedEntry;
@@ -0,0 +1,78 @@
1
+ const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
2
+ const NUMERIC_ID_PATTERN = /^\d+$/;
3
+ const MONGO_ID_PATTERN = /^[0-9a-f]{24}$/i;
4
+ const SHORT_ID_PATTERN = /^[a-zA-Z0-9]{8,22}$/;
5
+ export function normalizeEntry(entry) {
6
+ const url = new URL(entry.request.url);
7
+ const baseUrl = `${url.protocol}//${url.host}`;
8
+ const segments = url.pathname.split('/').filter(Boolean);
9
+ const pathParams = [];
10
+ let paramCounter = 0;
11
+ const normalizedSegments = segments.map((segment, i) => {
12
+ if (UUID_PATTERN.test(segment)) {
13
+ const name = deriveParamName(segments, i, paramCounter++);
14
+ pathParams.push({ name, position: i, exampleValue: segment, inferredType: 'uuid' });
15
+ return `{${name}}`;
16
+ }
17
+ if (NUMERIC_ID_PATTERN.test(segment) && segment.length < 15) {
18
+ const name = deriveParamName(segments, i, paramCounter++);
19
+ pathParams.push({ name, position: i, exampleValue: segment, inferredType: 'integer' });
20
+ return `{${name}}`;
21
+ }
22
+ if (MONGO_ID_PATTERN.test(segment)) {
23
+ const name = deriveParamName(segments, i, paramCounter++);
24
+ pathParams.push({ name, position: i, exampleValue: segment, inferredType: 'string' });
25
+ return `{${name}}`;
26
+ }
27
+ // Heuristic: if previous segment is a known collection name and this looks like an ID
28
+ if (i > 0 && isCollectionName(segments[i - 1]) && SHORT_ID_PATTERN.test(segment)) {
29
+ const prevSegment = segments[i - 1];
30
+ // Only treat as ID if short enough and not a known sub-resource
31
+ if (segment.length <= 22 && !isCollectionName(segment)) {
32
+ const name = singularize(prevSegment) + 'Id';
33
+ pathParams.push({ name, position: i, exampleValue: segment, inferredType: 'string' });
34
+ return `{${name}}`;
35
+ }
36
+ }
37
+ return segment;
38
+ });
39
+ const normalizedPath = '/' + normalizedSegments.join('/');
40
+ const queryParams = [];
41
+ for (const qs of entry.request.queryString) {
42
+ queryParams.push({
43
+ name: qs.name,
44
+ exampleValue: qs.value,
45
+ inferredType: inferQueryParamType(qs.value),
46
+ });
47
+ }
48
+ return { entry, normalizedPath, baseUrl, pathParams, queryParams };
49
+ }
50
+ function deriveParamName(segments, currentIndex, counter) {
51
+ if (currentIndex > 0) {
52
+ const prev = segments[currentIndex - 1];
53
+ if (isCollectionName(prev)) {
54
+ return singularize(prev) + 'Id';
55
+ }
56
+ }
57
+ return counter === 0 ? 'id' : `id${counter + 1}`;
58
+ }
59
+ function isCollectionName(segment) {
60
+ // Common REST patterns: plurals, known resource names
61
+ return (/^[a-z][a-z0-9_-]*s$/i.test(segment) || ['api', 'v1', 'v2', 'v3'].includes(segment) === false);
62
+ }
63
+ function singularize(word) {
64
+ if (word.endsWith('ies'))
65
+ return word.slice(0, -3) + 'y';
66
+ if (word.endsWith('ses') || word.endsWith('xes') || word.endsWith('zes'))
67
+ return word.slice(0, -2);
68
+ if (word.endsWith('s') && !word.endsWith('ss'))
69
+ return word.slice(0, -1);
70
+ return word;
71
+ }
72
+ function inferQueryParamType(value) {
73
+ if (NUMERIC_ID_PATTERN.test(value))
74
+ return 'integer';
75
+ if (value === 'true' || value === 'false')
76
+ return 'boolean';
77
+ return 'string';
78
+ }
@@ -0,0 +1,10 @@
1
+ export { loadOpenApiSpec } from './openapi-loader.js';
2
+ export type { LoadResult } from './openapi-loader.js';
3
+ export { extractOperations } from './operation-extractor.js';
4
+ export type { ExtractionResult } from './operation-extractor.js';
5
+ export { jsonSchemaToZodCode, buildOperationInputSchema } from './schema-converter.js';
6
+ export { loadHarFile } from './har-loader.js';
7
+ export { filterHarEntries } from './har-filter.js';
8
+ export type { FilterOptions } from './har-filter.js';
9
+ export { normalizeEntry } from './har-normalizer.js';
10
+ export type { NormalizedEntry, PathParam, QueryParam } from './har-normalizer.js';
@@ -0,0 +1,6 @@
1
+ export { loadOpenApiSpec } from './openapi-loader.js';
2
+ export { extractOperations } from './operation-extractor.js';
3
+ export { jsonSchemaToZodCode, buildOperationInputSchema } from './schema-converter.js';
4
+ export { loadHarFile } from './har-loader.js';
5
+ export { filterHarEntries } from './har-filter.js';
6
+ export { normalizeEntry } from './har-normalizer.js';
@@ -0,0 +1,6 @@
1
+ import type { OpenAPI } from 'openapi-types';
2
+ export interface LoadResult {
3
+ api: OpenAPI.Document;
4
+ specPath: string;
5
+ }
6
+ export declare function loadOpenApiSpec(input: string): Promise<LoadResult>;
@@ -0,0 +1,308 @@
1
+ import SwaggerParser from '@apidevtools/swagger-parser';
2
+ import { logger } from '../utils/logger.js';
3
+ /**
4
+ * Detects if a parsed document is Swagger 2.0 and converts it to OpenAPI 3.0.
5
+ */
6
+ function isSwagger2(doc) {
7
+ return typeof doc.swagger === 'string' && doc.swagger.startsWith('2.');
8
+ }
9
+ function convertSwagger2ToOpenApi3(doc) {
10
+ logger.warn('Converting Swagger 2.0 to OpenAPI 3.0');
11
+ const scheme = doc.schemes?.[0] ?? 'https';
12
+ const host = doc.host ?? 'localhost';
13
+ const basePath = doc.basePath ?? '/';
14
+ const serverUrl = `${scheme}://${host}${basePath === '/' ? '' : basePath}`;
15
+ const globalConsumes = doc.consumes ?? ['application/json'];
16
+ const globalProduces = doc.produces ?? ['application/json'];
17
+ const components = {};
18
+ // Map definitions -> components.schemas
19
+ if (doc.definitions) {
20
+ components.schemas = doc.definitions;
21
+ }
22
+ // Map parameters -> components.parameters
23
+ if (doc.parameters) {
24
+ components.parameters = convertParameterDefinitions(doc.parameters);
25
+ }
26
+ // Map securityDefinitions -> components.securitySchemes
27
+ if (doc.securityDefinitions) {
28
+ components.securitySchemes = convertSecurityDefinitions(doc.securityDefinitions);
29
+ }
30
+ // Convert paths
31
+ const convertedPaths = {};
32
+ if (doc.paths) {
33
+ for (const [path, pathItem] of Object.entries(doc.paths)) {
34
+ convertedPaths[path] = convertPathItem(pathItem, globalConsumes, globalProduces);
35
+ }
36
+ }
37
+ const result = {
38
+ openapi: '3.0.0',
39
+ info: doc.info,
40
+ servers: [{ url: serverUrl }],
41
+ paths: convertedPaths,
42
+ };
43
+ if (Object.keys(components).length > 0) {
44
+ result.components = components;
45
+ }
46
+ if (doc.security) {
47
+ result.security = doc.security;
48
+ }
49
+ if (doc.tags) {
50
+ result.tags = doc.tags;
51
+ }
52
+ if (doc.externalDocs) {
53
+ result.externalDocs = doc.externalDocs;
54
+ }
55
+ return result;
56
+ }
57
+ function convertPathItem(pathItem, globalConsumes, globalProduces) {
58
+ const methods = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options'];
59
+ const result = {};
60
+ // Preserve path-level parameters
61
+ if (pathItem.parameters) {
62
+ result.parameters = convertParameters(pathItem.parameters);
63
+ }
64
+ for (const method of methods) {
65
+ const operation = pathItem[method];
66
+ if (!operation)
67
+ continue;
68
+ result[method] = convertOperation(operation, globalConsumes, globalProduces);
69
+ }
70
+ return result;
71
+ }
72
+ function convertOperation(operation, globalConsumes, globalProduces) {
73
+ const consumes = operation.consumes ?? globalConsumes;
74
+ const produces = operation.produces ?? globalProduces;
75
+ const converted = {};
76
+ // Copy simple fields
77
+ for (const key of ['operationId', 'summary', 'description', 'tags', 'deprecated', 'security']) {
78
+ if (operation[key] !== undefined) {
79
+ converted[key] = operation[key];
80
+ }
81
+ }
82
+ // Copy x- extension fields
83
+ for (const key of Object.keys(operation)) {
84
+ if (key.startsWith('x-')) {
85
+ converted[key] = operation[key];
86
+ }
87
+ }
88
+ // Separate body/formData params from regular params
89
+ const params = (operation.parameters ?? []);
90
+ const regularParams = [];
91
+ let bodyParam;
92
+ const formDataParams = [];
93
+ for (const p of params) {
94
+ if (p.in === 'body') {
95
+ bodyParam = p;
96
+ }
97
+ else if (p.in === 'formData') {
98
+ formDataParams.push(p);
99
+ }
100
+ else {
101
+ regularParams.push(p);
102
+ }
103
+ }
104
+ if (regularParams.length > 0) {
105
+ converted.parameters = convertParameters(regularParams);
106
+ }
107
+ // Build requestBody from body param or formData params
108
+ if (bodyParam) {
109
+ const contentType = consumes[0] ?? 'application/json';
110
+ converted.requestBody = {
111
+ description: bodyParam.description,
112
+ required: bodyParam.required ?? false,
113
+ content: {
114
+ [contentType]: {
115
+ schema: convertSchemaRef(bodyParam.schema),
116
+ },
117
+ },
118
+ };
119
+ }
120
+ else if (formDataParams.length > 0) {
121
+ const hasFile = formDataParams.some((p) => p.type === 'file');
122
+ const contentType = hasFile ? 'multipart/form-data' : 'application/x-www-form-urlencoded';
123
+ const properties = {};
124
+ const required = [];
125
+ for (const p of formDataParams) {
126
+ const name = p.name;
127
+ if (p.type === 'file') {
128
+ properties[name] = { type: 'string', format: 'binary' };
129
+ }
130
+ else {
131
+ properties[name] = { type: p.type ?? 'string' };
132
+ if (p.description) {
133
+ properties[name].description = p.description;
134
+ }
135
+ }
136
+ if (p.required) {
137
+ required.push(name);
138
+ }
139
+ }
140
+ converted.requestBody = {
141
+ content: {
142
+ [contentType]: {
143
+ schema: {
144
+ type: 'object',
145
+ properties,
146
+ ...(required.length > 0 ? { required } : {}),
147
+ },
148
+ },
149
+ },
150
+ };
151
+ }
152
+ // Convert responses
153
+ const responses = (operation.responses ?? {});
154
+ const convertedResponses = {};
155
+ for (const [status, response] of Object.entries(responses)) {
156
+ const convertedResponse = {
157
+ description: response.description ?? '',
158
+ };
159
+ if (response.schema) {
160
+ const contentType = produces[0] ?? 'application/json';
161
+ convertedResponse.content = {
162
+ [contentType]: {
163
+ schema: convertSchemaRef(response.schema),
164
+ },
165
+ };
166
+ }
167
+ if (response.headers) {
168
+ convertedResponse.headers = response.headers;
169
+ }
170
+ convertedResponses[status] = convertedResponse;
171
+ }
172
+ converted.responses = convertedResponses;
173
+ return converted;
174
+ }
175
+ function convertParameters(params) {
176
+ return params.map((p) => {
177
+ const converted = {
178
+ name: p.name,
179
+ in: p.in,
180
+ };
181
+ if (p.required !== undefined)
182
+ converted.required = p.required;
183
+ if (p.description !== undefined)
184
+ converted.description = p.description;
185
+ // Build schema from Swagger 2.0 parameter type fields
186
+ const schema = {};
187
+ if (p.type)
188
+ schema.type = p.type;
189
+ if (p.format)
190
+ schema.format = p.format;
191
+ if (p.enum)
192
+ schema.enum = p.enum;
193
+ if (p.default !== undefined)
194
+ schema.default = p.default;
195
+ if (p.items)
196
+ schema.items = p.items;
197
+ if (p.minimum !== undefined)
198
+ schema.minimum = p.minimum;
199
+ if (p.maximum !== undefined)
200
+ schema.maximum = p.maximum;
201
+ converted.schema = Object.keys(schema).length > 0 ? schema : { type: 'string' };
202
+ return converted;
203
+ });
204
+ }
205
+ function convertParameterDefinitions(params) {
206
+ const result = {};
207
+ for (const [name, param] of Object.entries(params)) {
208
+ const p = param;
209
+ if (p.in === 'body') {
210
+ // Body parameters in definitions are unusual; skip them for components.parameters
211
+ continue;
212
+ }
213
+ const converted = {
214
+ name: p.name ?? name,
215
+ in: p.in,
216
+ };
217
+ if (p.required !== undefined)
218
+ converted.required = p.required;
219
+ if (p.description !== undefined)
220
+ converted.description = p.description;
221
+ const schema = {};
222
+ if (p.type)
223
+ schema.type = p.type;
224
+ if (p.format)
225
+ schema.format = p.format;
226
+ if (p.enum)
227
+ schema.enum = p.enum;
228
+ converted.schema = Object.keys(schema).length > 0 ? schema : { type: 'string' };
229
+ result[name] = converted;
230
+ }
231
+ return result;
232
+ }
233
+ function convertSecurityDefinitions(defs) {
234
+ const result = {};
235
+ for (const [name, def] of Object.entries(defs)) {
236
+ const d = def;
237
+ switch (d.type) {
238
+ case 'basic':
239
+ result[name] = { type: 'http', scheme: 'basic' };
240
+ break;
241
+ case 'apiKey':
242
+ result[name] = { type: 'apiKey', name: d.name, in: d.in };
243
+ break;
244
+ case 'oauth2': {
245
+ const scheme = { type: 'oauth2', flows: {} };
246
+ const flows = scheme.flows;
247
+ const scopes = (d.scopes ?? {});
248
+ switch (d.flow) {
249
+ case 'implicit':
250
+ flows.implicit = { authorizationUrl: d.authorizationUrl, scopes };
251
+ break;
252
+ case 'password':
253
+ flows.password = { tokenUrl: d.tokenUrl, scopes };
254
+ break;
255
+ case 'application':
256
+ flows.clientCredentials = { tokenUrl: d.tokenUrl, scopes };
257
+ break;
258
+ case 'accessCode':
259
+ flows.authorizationCode = {
260
+ authorizationUrl: d.authorizationUrl,
261
+ tokenUrl: d.tokenUrl,
262
+ scopes,
263
+ };
264
+ break;
265
+ }
266
+ result[name] = scheme;
267
+ break;
268
+ }
269
+ default:
270
+ result[name] = d;
271
+ }
272
+ }
273
+ return result;
274
+ }
275
+ function convertSchemaRef(schema) {
276
+ if (!schema)
277
+ return {};
278
+ // Swagger 2.0 uses #/definitions/Foo, OpenAPI 3.0 uses #/components/schemas/Foo
279
+ // Since we move definitions -> components.schemas, update $ref paths
280
+ const result = {};
281
+ for (const [key, value] of Object.entries(schema)) {
282
+ if (key === '$ref' && typeof value === 'string') {
283
+ result.$ref = value.replace('#/definitions/', '#/components/schemas/');
284
+ }
285
+ else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
286
+ result[key] = convertSchemaRef(value);
287
+ }
288
+ else if (Array.isArray(value)) {
289
+ result[key] = value.map((item) => typeof item === 'object' && item !== null
290
+ ? convertSchemaRef(item)
291
+ : item);
292
+ }
293
+ else {
294
+ result[key] = value;
295
+ }
296
+ }
297
+ return result;
298
+ }
299
+ export async function loadOpenApiSpec(input) {
300
+ // First, parse without dereferencing to check for Swagger 2.0
301
+ const raw = (await SwaggerParser.parse(input));
302
+ let specToParse = input;
303
+ if (isSwagger2(raw)) {
304
+ specToParse = convertSwagger2ToOpenApi3(raw);
305
+ }
306
+ const api = (await SwaggerParser.dereference(specToParse));
307
+ return { api, specPath: input };
308
+ }
@@ -0,0 +1,13 @@
1
+ import type { OpenAPIV3 } from 'openapi-types';
2
+ import type { OperationDescriptor } from '../types/index.js';
3
+ export interface ExtractionResult {
4
+ operations: OperationDescriptor[];
5
+ baseUrl: string;
6
+ securitySchemes: Record<string, OpenAPIV3.SecuritySchemeObject>;
7
+ info: {
8
+ title: string;
9
+ version: string;
10
+ description?: string;
11
+ };
12
+ }
13
+ export declare function extractOperations(api: OpenAPIV3.Document): ExtractionResult;