github-to-mcp-monorepo 1.0.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 (388) hide show
  1. package/.env.example +8 -0
  2. package/.github/CODEOWNERS +6 -0
  3. package/.husky/pre-commit +1 -0
  4. package/.nvmrc +1 -0
  5. package/.prettierignore +5 -0
  6. package/.prettierrc +7 -0
  7. package/.vscode/settings.json +4 -0
  8. package/ARCHITECTURE.md +1429 -0
  9. package/CHANGELOG.md +167 -0
  10. package/CONTRIBUTING.md +327 -0
  11. package/LICENSE +201 -0
  12. package/README.md +1028 -0
  13. package/SECURITY.md +248 -0
  14. package/VISUAL_GUIDE.md +437 -0
  15. package/apps/vscode/IMPLEMENTATION.md +480 -0
  16. package/apps/vscode/README.md +248 -0
  17. package/apps/vscode/package.json +381 -0
  18. package/apps/vscode/resources/icon.png +0 -0
  19. package/apps/vscode/resources/icon.svg +5 -0
  20. package/apps/vscode/src/commands/browseRegistry.ts +211 -0
  21. package/apps/vscode/src/commands/configureClaudeDesktop.ts +332 -0
  22. package/apps/vscode/src/commands/convert.ts +82 -0
  23. package/apps/vscode/src/commands/convertCurrentRepo.ts +109 -0
  24. package/apps/vscode/src/commands/convertFromUrl.ts +138 -0
  25. package/apps/vscode/src/commands/index.ts +121 -0
  26. package/apps/vscode/src/commands/validate.ts +197 -0
  27. package/apps/vscode/src/extension.ts +464 -0
  28. package/apps/vscode/src/global.d.ts +36 -0
  29. package/apps/vscode/src/test/extension.test.ts +73 -0
  30. package/apps/vscode/src/utils/file-generator.ts +529 -0
  31. package/apps/vscode/src/utils/github-api.ts +335 -0
  32. package/apps/vscode/src/utils/index.ts +29 -0
  33. package/apps/vscode/src/utils/mcp-config.ts +334 -0
  34. package/apps/vscode/src/utils/storage.ts +87 -0
  35. package/apps/vscode/src/views/McpServersTreeView.ts +160 -0
  36. package/apps/vscode/src/views/OutputChannelView.ts +195 -0
  37. package/apps/vscode/src/views/StatusBarItem.ts +251 -0
  38. package/apps/vscode/src/views/ToolsExplorerView.ts +314 -0
  39. package/apps/vscode/src/views/historyProvider.ts +75 -0
  40. package/apps/vscode/src/views/index.ts +12 -0
  41. package/apps/vscode/src/views/resultsPanel.ts +330 -0
  42. package/apps/vscode/src/webviews/ConversionPanel.ts +350 -0
  43. package/apps/vscode/src/webviews/ToolDetailsPanel.ts +448 -0
  44. package/apps/vscode/src/webviews/index.ts +9 -0
  45. package/apps/vscode/src/webviews/webview-ui/styles.ts +492 -0
  46. package/apps/vscode/tsconfig.json +20 -0
  47. package/apps/web/PLAYGROUND_GUIDE.md +499 -0
  48. package/apps/web/README.md +505 -0
  49. package/apps/web/app/api/convert/route.ts +100 -0
  50. package/apps/web/app/api/convert/stream/route.ts +198 -0
  51. package/apps/web/app/api/deploy/route.ts +157 -0
  52. package/apps/web/app/api/edge/route.ts +308 -0
  53. package/apps/web/app/api/export-docker/route.ts +284 -0
  54. package/apps/web/app/api/generate-openapi/route.ts +119 -0
  55. package/apps/web/app/api/mcp/[serverId]/route.ts +263 -0
  56. package/apps/web/app/api/playground/connect/route.ts +143 -0
  57. package/apps/web/app/api/playground/disconnect/route.ts +78 -0
  58. package/apps/web/app/api/playground/execute/route.ts +135 -0
  59. package/apps/web/app/api/playground/sessions/route.ts +103 -0
  60. package/apps/web/app/api/playground/tools/route.ts +117 -0
  61. package/apps/web/app/api/playground/v2/connect/route.ts +96 -0
  62. package/apps/web/app/api/playground/v2/disconnect/route.ts +88 -0
  63. package/apps/web/app/api/playground/v2/health/route.ts +80 -0
  64. package/apps/web/app/api/playground/v2/prompts/route.ts +160 -0
  65. package/apps/web/app/api/playground/v2/resources/route.ts +159 -0
  66. package/apps/web/app/api/playground/v2/sessions/route.ts +184 -0
  67. package/apps/web/app/api/playground/v2/tools/route.ts +167 -0
  68. package/apps/web/app/api/stream/route.ts +232 -0
  69. package/apps/web/app/batch/BatchConvertClient.tsx +190 -0
  70. package/apps/web/app/batch/page.tsx +37 -0
  71. package/apps/web/app/convert/page.tsx +269 -0
  72. package/apps/web/app/dashboard/page.tsx +380 -0
  73. package/apps/web/app/globals.css +622 -0
  74. package/apps/web/app/layout.tsx +120 -0
  75. package/apps/web/app/manifest.ts +31 -0
  76. package/apps/web/app/opengraph-image.tsx +112 -0
  77. package/apps/web/app/page.old.tsx +924 -0
  78. package/apps/web/app/page.tsx +77 -0
  79. package/apps/web/app/playground/page.tsx +306 -0
  80. package/apps/web/app/playground/v2/error.tsx +163 -0
  81. package/apps/web/app/playground/v2/layout.tsx +58 -0
  82. package/apps/web/app/playground/v2/loading.tsx +152 -0
  83. package/apps/web/app/playground/v2/page.tsx +644 -0
  84. package/apps/web/app/playground/v2/providers.tsx +214 -0
  85. package/apps/web/app/playground/v2/use-shortcuts.ts +209 -0
  86. package/apps/web/app/playground/v2/use-url-state.ts +296 -0
  87. package/apps/web/app/providers.tsx +22 -0
  88. package/apps/web/app/sitemap.ts +32 -0
  89. package/apps/web/app/twitter-image.tsx +112 -0
  90. package/apps/web/components/BranchSelector.tsx +401 -0
  91. package/apps/web/components/ClaudeConfigExport.tsx +226 -0
  92. package/apps/web/components/Features.tsx +84 -0
  93. package/apps/web/components/Footer.tsx +119 -0
  94. package/apps/web/components/GenerationProgress.tsx +248 -0
  95. package/apps/web/components/GithubUrlInput.tsx +483 -0
  96. package/apps/web/components/Header.tsx +175 -0
  97. package/apps/web/components/Hero.tsx +117 -0
  98. package/apps/web/components/HowItWorks.tsx +119 -0
  99. package/apps/web/components/InstallBanner.tsx +158 -0
  100. package/apps/web/components/Logo.tsx +116 -0
  101. package/apps/web/components/ParticleBackground.tsx +105 -0
  102. package/apps/web/components/Playground.tsx +472 -0
  103. package/apps/web/components/PlaygroundToolTester.tsx +410 -0
  104. package/apps/web/components/ProductCards.tsx +179 -0
  105. package/apps/web/components/SplitView.tsx +194 -0
  106. package/apps/web/components/ToolFilter.tsx +260 -0
  107. package/apps/web/components/ToolList.tsx +325 -0
  108. package/apps/web/components/batch/BatchConvert.tsx +785 -0
  109. package/apps/web/components/batch/index.ts +7 -0
  110. package/apps/web/components/convert/ConfigTabs.tsx +230 -0
  111. package/apps/web/components/convert/ConversionResult.tsx +482 -0
  112. package/apps/web/components/convert/InlinePlayground.tsx +259 -0
  113. package/apps/web/components/convert/LoadingSteps.tsx +311 -0
  114. package/apps/web/components/convert/OneClickInstall.tsx +224 -0
  115. package/apps/web/components/convert/ToolCard.tsx +189 -0
  116. package/apps/web/components/convert/TryInPlayground.tsx +242 -0
  117. package/apps/web/components/convert/index.ts +12 -0
  118. package/apps/web/components/deploy/DeployButton.tsx +369 -0
  119. package/apps/web/components/deploy/index.ts +7 -0
  120. package/apps/web/components/docker/DockerExport.tsx +690 -0
  121. package/apps/web/components/docker/index.ts +7 -0
  122. package/apps/web/components/install/OneClickInstall.tsx +676 -0
  123. package/apps/web/components/install/index.ts +7 -0
  124. package/apps/web/components/playground/CapabilityTabs.tsx +150 -0
  125. package/apps/web/components/playground/ConnectionStatusV2.tsx +322 -0
  126. package/apps/web/components/playground/EmptyStates.tsx +305 -0
  127. package/apps/web/components/playground/ExecutionLog.tsx +260 -0
  128. package/apps/web/components/playground/ExecutionLogV2.tsx +378 -0
  129. package/apps/web/components/playground/JsonViewer.tsx +388 -0
  130. package/apps/web/components/playground/PlaygroundLayout.tsx +244 -0
  131. package/apps/web/components/playground/PromptsPanel.tsx +385 -0
  132. package/apps/web/components/playground/ResourcesPanel.tsx +378 -0
  133. package/apps/web/components/playground/SchemaForm.tsx +477 -0
  134. package/apps/web/components/playground/ServerStatus.tsx +151 -0
  135. package/apps/web/components/playground/ShareButton.tsx +239 -0
  136. package/apps/web/components/playground/ToolsPanel.tsx +309 -0
  137. package/apps/web/components/playground/TransportConfigurator.tsx +563 -0
  138. package/apps/web/components/playground/index.ts +74 -0
  139. package/apps/web/components/playground/types.ts +202 -0
  140. package/apps/web/components/streaming/StreamingProgress.tsx +441 -0
  141. package/apps/web/components/streaming/index.ts +7 -0
  142. package/apps/web/components/ui/badge.tsx +42 -0
  143. package/apps/web/components/ui/button.tsx +88 -0
  144. package/apps/web/components/ui/card.tsx +75 -0
  145. package/apps/web/components/ui/code-block.tsx +122 -0
  146. package/apps/web/components/ui/index.ts +12 -0
  147. package/apps/web/components/ui/input.tsx +55 -0
  148. package/apps/web/components/ui/tabs.tsx +61 -0
  149. package/apps/web/hooks/index.ts +85 -0
  150. package/apps/web/hooks/types.ts +1173 -0
  151. package/apps/web/hooks/use-conversion.ts +133 -0
  152. package/apps/web/hooks/use-execution-history.ts +376 -0
  153. package/apps/web/hooks/use-generation-progress.ts +147 -0
  154. package/apps/web/hooks/use-local-storage.ts +88 -0
  155. package/apps/web/hooks/use-mcp-client.ts +623 -0
  156. package/apps/web/hooks/use-mcp-connection.ts +500 -0
  157. package/apps/web/hooks/use-mcp-execution.ts +282 -0
  158. package/apps/web/hooks/use-mcp-prompts.ts +441 -0
  159. package/apps/web/hooks/use-mcp-resources.ts +430 -0
  160. package/apps/web/hooks/use-mcp-tools.ts +540 -0
  161. package/apps/web/hooks/use-playground-store.ts +299 -0
  162. package/apps/web/hooks/use-playground.ts +184 -0
  163. package/apps/web/hooks/use-streaming-conversion.ts +227 -0
  164. package/apps/web/hooks/useBatchConversion.ts +271 -0
  165. package/apps/web/hooks/useDockerConfig.ts +161 -0
  166. package/apps/web/hooks/usePlatformDetection.ts +80 -0
  167. package/apps/web/hooks/useStreaming.ts +199 -0
  168. package/apps/web/lib/api/errors.ts +386 -0
  169. package/apps/web/lib/api/index.ts +137 -0
  170. package/apps/web/lib/api/logger.ts +187 -0
  171. package/apps/web/lib/api/middleware.ts +364 -0
  172. package/apps/web/lib/api/openapi.ts +977 -0
  173. package/apps/web/lib/api/session-manager.ts +594 -0
  174. package/apps/web/lib/api/types.ts +433 -0
  175. package/apps/web/lib/api/validation.ts +523 -0
  176. package/apps/web/lib/constants.ts +114 -0
  177. package/apps/web/lib/mcp/client.ts +1137 -0
  178. package/apps/web/lib/mcp/events.ts +651 -0
  179. package/apps/web/lib/mcp/index.ts +347 -0
  180. package/apps/web/lib/mcp/logger.ts +428 -0
  181. package/apps/web/lib/mcp/metrics.ts +703 -0
  182. package/apps/web/lib/mcp/retry.ts +616 -0
  183. package/apps/web/lib/mcp/session-manager.ts +779 -0
  184. package/apps/web/lib/mcp/transports.ts +988 -0
  185. package/apps/web/lib/mcp/types.ts +594 -0
  186. package/apps/web/lib/mcp-client-enhanced.ts +871 -0
  187. package/apps/web/lib/mcp-client.ts +778 -0
  188. package/apps/web/lib/mcp-errors.ts +489 -0
  189. package/apps/web/lib/mcp-sandbox.ts +593 -0
  190. package/apps/web/lib/mcp-testing.ts +428 -0
  191. package/apps/web/lib/mcp-types.ts +448 -0
  192. package/apps/web/lib/playground-store.tsx +1147 -0
  193. package/apps/web/lib/utils.ts +439 -0
  194. package/apps/web/next-env.d.ts +5 -0
  195. package/apps/web/next.config.js +23 -0
  196. package/apps/web/package.json +55 -0
  197. package/apps/web/postcss.config.js +6 -0
  198. package/apps/web/public/.well-known/ai-plugin.json +17 -0
  199. package/apps/web/public/logo.svg +6 -0
  200. package/apps/web/public/robots.txt +22 -0
  201. package/apps/web/public/schema.json +27 -0
  202. package/apps/web/tailwind.config.js +26 -0
  203. package/apps/web/tailwind.config.ts +123 -0
  204. package/apps/web/tsconfig.json +20 -0
  205. package/apps/web/types/deploy.ts +139 -0
  206. package/apps/web/types/index.ts +247 -0
  207. package/apps/web/vercel.json +39 -0
  208. package/eslint.config.mjs +23 -0
  209. package/llms.txt +102 -0
  210. package/mkdocs/docs/api/core.md +318 -0
  211. package/mkdocs/docs/api/index.md +128 -0
  212. package/mkdocs/docs/api/mcp-server.md +301 -0
  213. package/mkdocs/docs/api/openapi-parser.md +254 -0
  214. package/mkdocs/docs/assets/logo.svg +7 -0
  215. package/mkdocs/docs/changelog.md +118 -0
  216. package/mkdocs/docs/cli/generate.md +148 -0
  217. package/mkdocs/docs/cli/index.md +52 -0
  218. package/mkdocs/docs/cli/inspect.md +164 -0
  219. package/mkdocs/docs/cli/serve.md +136 -0
  220. package/mkdocs/docs/concepts/classification.md +254 -0
  221. package/mkdocs/docs/concepts/how-it-works.md +299 -0
  222. package/mkdocs/docs/concepts/index.md +77 -0
  223. package/mkdocs/docs/concepts/mcp-protocol.md +362 -0
  224. package/mkdocs/docs/concepts/tool-types.md +382 -0
  225. package/mkdocs/docs/contributing/architecture.md +262 -0
  226. package/mkdocs/docs/contributing/development.md +245 -0
  227. package/mkdocs/docs/contributing/index.md +73 -0
  228. package/mkdocs/docs/contributing/testing.md +320 -0
  229. package/mkdocs/docs/getting-started/configuration.md +235 -0
  230. package/mkdocs/docs/getting-started/index.md +54 -0
  231. package/mkdocs/docs/getting-started/installation.md +145 -0
  232. package/mkdocs/docs/getting-started/quickstart.md +160 -0
  233. package/mkdocs/docs/guides/batch.md +375 -0
  234. package/mkdocs/docs/guides/claude-desktop.md +227 -0
  235. package/mkdocs/docs/guides/cursor.md +188 -0
  236. package/mkdocs/docs/guides/custom-tools.md +367 -0
  237. package/mkdocs/docs/guides/index.md +78 -0
  238. package/mkdocs/docs/guides/private-repos.md +221 -0
  239. package/mkdocs/docs/guides/vscode.md +247 -0
  240. package/mkdocs/docs/index.md +175 -0
  241. package/mkdocs/docs/reference/config.md +223 -0
  242. package/mkdocs/docs/reference/env.md +192 -0
  243. package/mkdocs/docs/reference/index.md +102 -0
  244. package/mkdocs/docs/reference/tools.md +309 -0
  245. package/mkdocs/docs/stylesheets/extra.css +231 -0
  246. package/mkdocs/mkdocs.yml +204 -0
  247. package/mkdocs/overrides/.gitkeep +1 -0
  248. package/mkdocs/overrides/main.html +7 -0
  249. package/mkdocs/python-deps.txt +7 -0
  250. package/mkdocs/vercel.json +11 -0
  251. package/package.json +63 -0
  252. package/packages/core/package.json +61 -0
  253. package/packages/core/src/__tests__/bitbucket-client.test.ts +366 -0
  254. package/packages/core/src/__tests__/cli.test.ts +235 -0
  255. package/packages/core/src/__tests__/code-extractor.test.ts +378 -0
  256. package/packages/core/src/__tests__/docker-generator.test.ts +255 -0
  257. package/packages/core/src/__tests__/github-client.test.ts +390 -0
  258. package/packages/core/src/__tests__/gitlab-client.test.ts +319 -0
  259. package/packages/core/src/__tests__/go-extractor.test.ts +351 -0
  260. package/packages/core/src/__tests__/graphql-extractor.test.ts +330 -0
  261. package/packages/core/src/__tests__/java-extractor.test.ts +497 -0
  262. package/packages/core/src/__tests__/plugins.test.ts +467 -0
  263. package/packages/core/src/__tests__/readme-extractor.test.ts +258 -0
  264. package/packages/core/src/__tests__/redis-cache.test.ts +307 -0
  265. package/packages/core/src/__tests__/rust-extractor.test.ts +252 -0
  266. package/packages/core/src/__tests__/streaming.test.ts +251 -0
  267. package/packages/core/src/additional-extractors.ts +333 -0
  268. package/packages/core/src/cache/cache-interface.ts +179 -0
  269. package/packages/core/src/cache/index.ts +210 -0
  270. package/packages/core/src/cache/redis-cache.ts +291 -0
  271. package/packages/core/src/cache/upstash-cache.ts +379 -0
  272. package/packages/core/src/cache.ts +251 -0
  273. package/packages/core/src/cli.ts +822 -0
  274. package/packages/core/src/code-extractor.ts +696 -0
  275. package/packages/core/src/docker-generator.ts +470 -0
  276. package/packages/core/src/edge-compatible.ts +491 -0
  277. package/packages/core/src/extractors/go-extractor.ts +791 -0
  278. package/packages/core/src/extractors/index.ts +9 -0
  279. package/packages/core/src/extractors/java-extractor.ts +937 -0
  280. package/packages/core/src/extractors/rust-extractor.ts +744 -0
  281. package/packages/core/src/github-client.ts +319 -0
  282. package/packages/core/src/go-generator.ts +356 -0
  283. package/packages/core/src/graphql-extractor.ts +358 -0
  284. package/packages/core/src/index.ts +797 -0
  285. package/packages/core/src/langchain-exporter.ts +617 -0
  286. package/packages/core/src/language-parsers.ts +1114 -0
  287. package/packages/core/src/mcp-introspector.ts +279 -0
  288. package/packages/core/src/monorepo-detector.ts +378 -0
  289. package/packages/core/src/plugins/index.ts +370 -0
  290. package/packages/core/src/plugins/registry.ts +404 -0
  291. package/packages/core/src/plugins/types.ts +215 -0
  292. package/packages/core/src/providers/base-provider.ts +246 -0
  293. package/packages/core/src/providers/bitbucket-client.ts +464 -0
  294. package/packages/core/src/providers/gitlab-client.ts +388 -0
  295. package/packages/core/src/providers/index.ts +176 -0
  296. package/packages/core/src/python-generator.ts +260 -0
  297. package/packages/core/src/queue/index.ts +100 -0
  298. package/packages/core/src/queue/memory-queue.ts +445 -0
  299. package/packages/core/src/queue/redis-queue.ts +578 -0
  300. package/packages/core/src/queue/types.ts +251 -0
  301. package/packages/core/src/readme-extractor.ts +409 -0
  302. package/packages/core/src/schema-generator.ts +638 -0
  303. package/packages/core/src/streaming.ts +999 -0
  304. package/packages/core/src/types.ts +289 -0
  305. package/packages/core/tsconfig.json +9 -0
  306. package/packages/core/tsup.config.ts +25 -0
  307. package/packages/mcp-server/README.md +297 -0
  308. package/packages/mcp-server/package.json +55 -0
  309. package/packages/mcp-server/src/__tests__/mcp-server.test.ts +177 -0
  310. package/packages/mcp-server/src/__tests__/tools.test.ts +217 -0
  311. package/packages/mcp-server/src/index.ts +1206 -0
  312. package/packages/mcp-server/src/prompts/index.ts +601 -0
  313. package/packages/mcp-server/src/tools/export-docker.ts +362 -0
  314. package/packages/mcp-server/src/tools/generate-openapi.ts +162 -0
  315. package/packages/mcp-server/src/tools/monitor-mcp-server.ts +448 -0
  316. package/packages/mcp-server/src/tools/stream-convert.ts +398 -0
  317. package/packages/mcp-server/src/tools/test-mcp-tool.ts +531 -0
  318. package/packages/mcp-server/tsconfig.json +12 -0
  319. package/packages/mcp-server/tsup.config.ts +14 -0
  320. package/packages/openapi-parser/package-lock.json +3028 -0
  321. package/packages/openapi-parser/package.json +41 -0
  322. package/packages/openapi-parser/src/analyzer.ts +700 -0
  323. package/packages/openapi-parser/src/asyncapi-parser.ts +475 -0
  324. package/packages/openapi-parser/src/cli.ts +302 -0
  325. package/packages/openapi-parser/src/generator.ts +570 -0
  326. package/packages/openapi-parser/src/generators/express-analyzer.ts +649 -0
  327. package/packages/openapi-parser/src/generators/fastapi-analyzer.ts +960 -0
  328. package/packages/openapi-parser/src/generators/index.ts +200 -0
  329. package/packages/openapi-parser/src/generators/nextjs-analyzer.ts +768 -0
  330. package/packages/openapi-parser/src/generators/openapi-builder.ts +527 -0
  331. package/packages/openapi-parser/src/generators/types.ts +298 -0
  332. package/packages/openapi-parser/src/graphql-parser.ts +462 -0
  333. package/packages/openapi-parser/src/grpc-parser.ts +649 -0
  334. package/packages/openapi-parser/src/har-parser.ts +723 -0
  335. package/packages/openapi-parser/src/index.ts +635 -0
  336. package/packages/openapi-parser/src/insomnia-parser.ts +614 -0
  337. package/packages/openapi-parser/src/parser.ts +231 -0
  338. package/packages/openapi-parser/src/postman-parser.ts +611 -0
  339. package/packages/openapi-parser/src/ref-resolver.ts +313 -0
  340. package/packages/openapi-parser/src/transformer.ts +459 -0
  341. package/packages/openapi-parser/tests/generators/express.test.ts +209 -0
  342. package/packages/openapi-parser/tests/generators/fastapi.test.ts +236 -0
  343. package/packages/openapi-parser/tests/generators/nextjs.test.ts +273 -0
  344. package/packages/openapi-parser/tests/parsers.test.ts +847 -0
  345. package/packages/openapi-parser/tsconfig.json +9 -0
  346. package/packages/openapi-parser/tsup.config.ts +11 -0
  347. package/packages/registry/package.json +59 -0
  348. package/packages/registry/src/cli.ts +456 -0
  349. package/packages/registry/src/index.ts +44 -0
  350. package/packages/registry/src/popular/github.json +47 -0
  351. package/packages/registry/src/popular/index.ts +55 -0
  352. package/packages/registry/src/popular/linear.json +42 -0
  353. package/packages/registry/src/popular/notion.json +42 -0
  354. package/packages/registry/src/popular/openai.json +40 -0
  355. package/packages/registry/src/popular/resend.json +38 -0
  356. package/packages/registry/src/popular/slack.json +42 -0
  357. package/packages/registry/src/popular/stripe.json +163 -0
  358. package/packages/registry/src/popular/supabase.json +42 -0
  359. package/packages/registry/src/popular/twilio.json +40 -0
  360. package/packages/registry/src/popular/vercel.json +40 -0
  361. package/packages/registry/src/registry.ts +492 -0
  362. package/packages/registry/src/storage.ts +334 -0
  363. package/packages/registry/src/types.ts +275 -0
  364. package/packages/registry/src/updater.ts +208 -0
  365. package/packages/registry/tsconfig.json +10 -0
  366. package/packages/registry/tsup.config.ts +11 -0
  367. package/pnpm-workspace.yaml +3 -0
  368. package/scripts/build-docs.sh +16 -0
  369. package/server.json +9 -0
  370. package/templates/Dockerfile.python.template +60 -0
  371. package/templates/Dockerfile.typescript.template +60 -0
  372. package/templates/docker-compose.template.yml +68 -0
  373. package/tests/fixtures/express-app/index.js +34 -0
  374. package/tests/fixtures/express-app/routes/posts.js +43 -0
  375. package/tests/fixtures/express-app/routes/users.js +58 -0
  376. package/tests/fixtures/fastapi-app/main.py +125 -0
  377. package/tests/fixtures/fastapi-app/routes/admin.py +42 -0
  378. package/tests/fixtures/graphql/simple-schema.graphql +65 -0
  379. package/tests/fixtures/mocks/github-api-responses.json +63 -0
  380. package/tests/fixtures/nextjs-app/app/api/posts/route.ts +55 -0
  381. package/tests/fixtures/nextjs-app/app/api/users/[id]/route.ts +63 -0
  382. package/tests/fixtures/nextjs-app/app/api/users/route.ts +44 -0
  383. package/tests/fixtures/nextjs-app/pages/api/health.ts +28 -0
  384. package/tests/fixtures/openapi/petstore.yaml +179 -0
  385. package/tests/integration/langchain-export.test.ts +405 -0
  386. package/tests/integration/openapi-conversion.test.ts +221 -0
  387. package/tsconfig.json +18 -0
  388. package/vitest.config.ts +32 -0
@@ -0,0 +1,379 @@
1
+ /**
2
+ * @fileoverview Upstash Redis cache implementation for serverless environments
3
+ * @copyright Copyright (c) 2024-2026 nirholas
4
+ * @license MIT
5
+ */
6
+
7
+ import type {
8
+ CacheInterface,
9
+ CacheEntry,
10
+ CacheStats,
11
+ CacheConfig,
12
+ CacheSerializer
13
+ } from './cache-interface';
14
+ import { defaultSerializer } from './cache-interface';
15
+
16
+ /**
17
+ * Upstash REST API response
18
+ */
19
+ interface UpstashResponse<T = unknown> {
20
+ result: T;
21
+ error?: string;
22
+ }
23
+
24
+ /**
25
+ * Upstash cache configuration
26
+ */
27
+ export interface UpstashCacheConfig extends CacheConfig {
28
+ /** Upstash REST URL */
29
+ url: string;
30
+ /** Upstash REST token */
31
+ token: string;
32
+ /** Key prefix for namespacing */
33
+ keyPrefix?: string;
34
+ /** Request timeout in milliseconds */
35
+ timeout?: number;
36
+ }
37
+
38
+ /**
39
+ * Upstash Redis cache implementation
40
+ * Uses REST API for serverless/edge compatibility
41
+ */
42
+ export class UpstashCache implements CacheInterface {
43
+ private url: string;
44
+ private token: string;
45
+ private config: UpstashCacheConfig;
46
+ private serializer: CacheSerializer;
47
+ private stats: { hits: number; misses: number };
48
+
49
+ constructor(config: UpstashCacheConfig) {
50
+ this.url = config.url.replace(/\/$/, ''); // Remove trailing slash
51
+ this.token = config.token;
52
+ this.config = {
53
+ keyPrefix: 'mcp-cache',
54
+ defaultTTL: 3600,
55
+ timeout: 5000,
56
+ ...config
57
+ };
58
+ this.serializer = config.serializer || defaultSerializer;
59
+ this.stats = { hits: 0, misses: 0 };
60
+ }
61
+
62
+ /**
63
+ * Generate prefixed key
64
+ */
65
+ private prefixKey(key: string): string {
66
+ return this.config.keyPrefix ? `${this.config.keyPrefix}:${key}` : key;
67
+ }
68
+
69
+ /**
70
+ * Execute Upstash command via REST API
71
+ */
72
+ private async execute<T>(command: string[]): Promise<T> {
73
+ const controller = new AbortController();
74
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
75
+
76
+ try {
77
+ const response = await fetch(`${this.url}`, {
78
+ method: 'POST',
79
+ headers: {
80
+ Authorization: `Bearer ${this.token}`,
81
+ 'Content-Type': 'application/json'
82
+ },
83
+ body: JSON.stringify(command),
84
+ signal: controller.signal
85
+ });
86
+
87
+ if (!response.ok) {
88
+ throw new Error(`Upstash API error: ${response.status} ${response.statusText}`);
89
+ }
90
+
91
+ const data = await response.json() as UpstashResponse<T>;
92
+
93
+ if (data.error) {
94
+ throw new Error(`Upstash error: ${data.error}`);
95
+ }
96
+
97
+ return data.result;
98
+ } finally {
99
+ clearTimeout(timeoutId);
100
+ }
101
+ }
102
+
103
+ /**
104
+ * Execute pipeline of commands
105
+ */
106
+ private async pipeline<T>(commands: string[][]): Promise<T[]> {
107
+ const controller = new AbortController();
108
+ const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
109
+
110
+ try {
111
+ const response = await fetch(`${this.url}/pipeline`, {
112
+ method: 'POST',
113
+ headers: {
114
+ Authorization: `Bearer ${this.token}`,
115
+ 'Content-Type': 'application/json'
116
+ },
117
+ body: JSON.stringify(commands),
118
+ signal: controller.signal
119
+ });
120
+
121
+ if (!response.ok) {
122
+ throw new Error(`Upstash API error: ${response.status} ${response.statusText}`);
123
+ }
124
+
125
+ const data = await response.json() as UpstashResponse<T>[];
126
+ return data.map(d => d.result);
127
+ } finally {
128
+ clearTimeout(timeoutId);
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Get a cached value
134
+ */
135
+ async get<T>(key: string): Promise<CacheEntry<T> | null> {
136
+ const prefixedKey = this.prefixKey(key);
137
+
138
+ try {
139
+ const value = await this.execute<string | null>(['GET', prefixedKey]);
140
+
141
+ if (!value) {
142
+ this.stats.misses++;
143
+ return null;
144
+ }
145
+
146
+ const entry = this.serializer.deserialize<CacheEntry<T>>(value);
147
+
148
+ // Check if entry is expired
149
+ if (Date.now() - entry.timestamp > entry.ttl * 1000) {
150
+ this.stats.misses++;
151
+ // Delete expired entry asynchronously
152
+ this.delete(key).catch(() => {});
153
+ return null;
154
+ }
155
+
156
+ this.stats.hits++;
157
+ return entry;
158
+ } catch (error) {
159
+ this.stats.misses++;
160
+ return null;
161
+ }
162
+ }
163
+
164
+ /**
165
+ * Set a cached value
166
+ */
167
+ async set<T>(key: string, entry: CacheEntry<T>): Promise<void> {
168
+ const prefixedKey = this.prefixKey(key);
169
+ const serialized = this.serializer.serialize(entry);
170
+
171
+ // Calculate expiration time
172
+ const expirationSeconds = this.config.staleWhileRevalidate
173
+ ? Math.ceil(entry.ttl * (this.config.staleTolerance || 2))
174
+ : entry.ttl;
175
+
176
+ if (expirationSeconds > 0) {
177
+ await this.execute(['SET', prefixedKey, serialized, 'EX', String(expirationSeconds)]);
178
+ } else {
179
+ await this.execute(['SET', prefixedKey, serialized]);
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Delete a cached value
185
+ */
186
+ async delete(key: string): Promise<void> {
187
+ const prefixedKey = this.prefixKey(key);
188
+ await this.execute(['DEL', prefixedKey]);
189
+ }
190
+
191
+ /**
192
+ * Clear all cached values with the prefix
193
+ */
194
+ async clear(): Promise<void> {
195
+ const pattern = this.config.keyPrefix ? `${this.config.keyPrefix}:*` : '*';
196
+
197
+ // Get all keys matching the pattern
198
+ const keys = await this.execute<string[]>(['KEYS', pattern]);
199
+
200
+ if (keys && keys.length > 0) {
201
+ // Delete in batches
202
+ const batchSize = 100;
203
+ for (let i = 0; i < keys.length; i += batchSize) {
204
+ const batch = keys.slice(i, i + batchSize);
205
+ await this.execute(['DEL', ...batch]);
206
+ }
207
+ }
208
+
209
+ // Reset stats
210
+ this.stats = { hits: 0, misses: 0 };
211
+ }
212
+
213
+ /**
214
+ * Check if a key exists
215
+ */
216
+ async has(key: string): Promise<boolean> {
217
+ const prefixedKey = this.prefixKey(key);
218
+ const exists = await this.execute<number>(['EXISTS', prefixedKey]);
219
+ return exists > 0;
220
+ }
221
+
222
+ /**
223
+ * Get multiple values at once
224
+ */
225
+ async getMany<T>(keys: string[]): Promise<Map<string, CacheEntry<T> | null>> {
226
+ const result = new Map<string, CacheEntry<T> | null>();
227
+
228
+ if (keys.length === 0) {
229
+ return result;
230
+ }
231
+
232
+ const prefixedKeys = keys.map(k => this.prefixKey(k));
233
+ const values = await this.execute<(string | null)[]>(['MGET', ...prefixedKeys]);
234
+
235
+ keys.forEach((key, index) => {
236
+ const value = values[index];
237
+ if (value) {
238
+ try {
239
+ const entry = this.serializer.deserialize<CacheEntry<T>>(value);
240
+ if (Date.now() - entry.timestamp <= entry.ttl * 1000) {
241
+ this.stats.hits++;
242
+ result.set(key, entry);
243
+ } else {
244
+ this.stats.misses++;
245
+ result.set(key, null);
246
+ }
247
+ } catch {
248
+ this.stats.misses++;
249
+ result.set(key, null);
250
+ }
251
+ } else {
252
+ this.stats.misses++;
253
+ result.set(key, null);
254
+ }
255
+ });
256
+
257
+ return result;
258
+ }
259
+
260
+ /**
261
+ * Set multiple values at once
262
+ */
263
+ async setMany<T>(entries: Map<string, CacheEntry<T>>): Promise<void> {
264
+ if (entries.size === 0) {
265
+ return;
266
+ }
267
+
268
+ // Use pipeline for efficiency
269
+ const commands: string[][] = [];
270
+
271
+ entries.forEach((entry, key) => {
272
+ const prefixedKey = this.prefixKey(key);
273
+ const serialized = this.serializer.serialize(entry);
274
+
275
+ const expirationSeconds = this.config.staleWhileRevalidate
276
+ ? Math.ceil(entry.ttl * (this.config.staleTolerance || 2))
277
+ : entry.ttl;
278
+
279
+ if (expirationSeconds > 0) {
280
+ commands.push(['SET', prefixedKey, serialized, 'EX', String(expirationSeconds)]);
281
+ } else {
282
+ commands.push(['SET', prefixedKey, serialized]);
283
+ }
284
+ });
285
+
286
+ await this.pipeline(commands);
287
+ }
288
+
289
+ /**
290
+ * Get cache statistics
291
+ */
292
+ async getStats(): Promise<CacheStats> {
293
+ let size = 0;
294
+
295
+ try {
296
+ const dbSize = await this.execute<number>(['DBSIZE']);
297
+ size = dbSize || 0;
298
+ } catch {
299
+ // Ignore stats errors
300
+ }
301
+
302
+ const total = this.stats.hits + this.stats.misses;
303
+
304
+ return {
305
+ hits: this.stats.hits,
306
+ misses: this.stats.misses,
307
+ size,
308
+ hitRatio: total > 0 ? this.stats.hits / total : 0
309
+ };
310
+ }
311
+
312
+ /**
313
+ * Close method (no-op for REST-based client)
314
+ */
315
+ async close(): Promise<void> {
316
+ // No connection to close for REST API
317
+ }
318
+
319
+ /**
320
+ * Increment a counter (useful for rate limiting)
321
+ */
322
+ async incr(key: string, ttl?: number): Promise<number> {
323
+ const prefixedKey = this.prefixKey(key);
324
+
325
+ if (ttl) {
326
+ // Use pipeline to set expiration atomically
327
+ const results = await this.pipeline<number>([
328
+ ['INCR', prefixedKey],
329
+ ['EXPIRE', prefixedKey, String(ttl)]
330
+ ]);
331
+ return results[0];
332
+ }
333
+
334
+ return this.execute<number>(['INCR', prefixedKey]);
335
+ }
336
+
337
+ /**
338
+ * Set with NX (only if not exists) - useful for distributed locks
339
+ */
340
+ async setNX(key: string, value: string, ttl?: number): Promise<boolean> {
341
+ const prefixedKey = this.prefixKey(key);
342
+
343
+ if (ttl) {
344
+ const result = await this.execute<string | null>(['SET', prefixedKey, value, 'NX', 'EX', String(ttl)]);
345
+ return result === 'OK';
346
+ }
347
+
348
+ const result = await this.execute<number>(['SETNX', prefixedKey, value]);
349
+ return result === 1;
350
+ }
351
+ }
352
+
353
+ /**
354
+ * Create an Upstash cache instance
355
+ */
356
+ export function createUpstashCache(config: UpstashCacheConfig): UpstashCache {
357
+ return new UpstashCache(config);
358
+ }
359
+
360
+ /**
361
+ * Create Upstash cache from environment variables
362
+ */
363
+ export function createUpstashCacheFromEnv(options?: Omit<UpstashCacheConfig, 'url' | 'token'>): UpstashCache {
364
+ const url = process.env.UPSTASH_REDIS_REST_URL;
365
+ const token = process.env.UPSTASH_REDIS_REST_TOKEN;
366
+
367
+ if (!url || !token) {
368
+ throw new Error(
369
+ 'Missing Upstash environment variables. ' +
370
+ 'Please set UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN.'
371
+ );
372
+ }
373
+
374
+ return new UpstashCache({
375
+ url,
376
+ token,
377
+ ...options
378
+ });
379
+ }
@@ -0,0 +1,251 @@
1
+ /**
2
+ * @fileoverview GitHub API caching layer with stale-while-revalidate
3
+ * @copyright Copyright (c) 2024-2026 nirholas
4
+ * @license MIT
5
+ */
6
+
7
+ import type { CacheEntry, CacheAdapter } from './types';
8
+
9
+ /**
10
+ * In-memory cache adapter for serverless environments
11
+ */
12
+ export class MemoryCacheAdapter implements CacheAdapter {
13
+ private cache: Map<string, CacheEntry<any>> = new Map();
14
+
15
+ async get<T>(key: string): Promise<CacheEntry<T> | null> {
16
+ const entry = this.cache.get(key);
17
+ if (!entry) return null;
18
+ return entry as CacheEntry<T>;
19
+ }
20
+
21
+ async set<T>(key: string, entry: CacheEntry<T>): Promise<void> {
22
+ this.cache.set(key, entry);
23
+ }
24
+
25
+ async delete(key: string): Promise<void> {
26
+ this.cache.delete(key);
27
+ }
28
+
29
+ async clear(): Promise<void> {
30
+ this.cache.clear();
31
+ }
32
+
33
+ /**
34
+ * Get cache statistics
35
+ */
36
+ getStats(): { size: number; keys: string[] } {
37
+ return {
38
+ size: this.cache.size,
39
+ keys: Array.from(this.cache.keys())
40
+ };
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Default TTL values in seconds
46
+ */
47
+ export const DEFAULT_TTL = {
48
+ METADATA: 3600, // 1 hour for repo metadata
49
+ FILES: 900, // 15 minutes for file contents
50
+ SPECS: 1800, // 30 minutes for API specs
51
+ DIRECTORY: 600 // 10 minutes for directory listings
52
+ } as const;
53
+
54
+ /**
55
+ * GitHub API Cache with stale-while-revalidate support
56
+ */
57
+ export class GitHubCache {
58
+ private adapter: CacheAdapter;
59
+ private ttls: { metadata: number; files: number };
60
+ private verbose: boolean;
61
+ private revalidating: Set<string> = new Set();
62
+
63
+ constructor(
64
+ adapter?: CacheAdapter,
65
+ ttls?: { metadata?: number; files?: number },
66
+ verbose?: boolean
67
+ ) {
68
+ this.adapter = adapter || new MemoryCacheAdapter();
69
+ this.ttls = {
70
+ metadata: ttls?.metadata || DEFAULT_TTL.METADATA,
71
+ files: ttls?.files || DEFAULT_TTL.FILES
72
+ };
73
+ this.verbose = verbose || false;
74
+ }
75
+
76
+ /**
77
+ * Generate cache key from components
78
+ */
79
+ generateKey(owner: string, repo: string, type: string, path?: string, ref?: string): string {
80
+ const parts = [owner, repo, type];
81
+ if (ref) parts.push(ref);
82
+ if (path) parts.push(path);
83
+ return parts.join('/');
84
+ }
85
+
86
+ /**
87
+ * Check if an entry is fresh (not stale)
88
+ */
89
+ private isFresh(entry: CacheEntry<any>): boolean {
90
+ const age = Date.now() - entry.timestamp;
91
+ return age < entry.ttl * 1000;
92
+ }
93
+
94
+ /**
95
+ * Check if an entry is stale but usable (within 2x TTL)
96
+ */
97
+ private isStale(entry: CacheEntry<any>): boolean {
98
+ const age = Date.now() - entry.timestamp;
99
+ return age >= entry.ttl * 1000 && age < entry.ttl * 2000;
100
+ }
101
+
102
+ /**
103
+ * Get cached data with stale-while-revalidate pattern
104
+ * Returns cached data immediately if available (even if stale),
105
+ * and triggers background revalidation if stale
106
+ */
107
+ async get<T>(
108
+ key: string,
109
+ fetcher: () => Promise<T>,
110
+ ttl?: number
111
+ ): Promise<T> {
112
+ const entry = await this.adapter.get<T>(key);
113
+
114
+ if (entry) {
115
+ if (this.isFresh(entry)) {
116
+ if (this.verbose) {
117
+ console.log(`[Cache] HIT (fresh): ${key}`);
118
+ }
119
+ return entry.data;
120
+ }
121
+
122
+ if (this.isStale(entry)) {
123
+ if (this.verbose) {
124
+ console.log(`[Cache] HIT (stale, revalidating): ${key}`);
125
+ }
126
+ // Trigger background revalidation
127
+ this.revalidateInBackground(key, fetcher, ttl || entry.ttl);
128
+ return entry.data;
129
+ }
130
+ }
131
+
132
+ // Cache miss or expired beyond stale threshold
133
+ if (this.verbose) {
134
+ console.log(`[Cache] MISS: ${key}`);
135
+ }
136
+ return this.fetchAndCache(key, fetcher, ttl || this.ttls.files);
137
+ }
138
+
139
+ /**
140
+ * Fetch data and store in cache
141
+ */
142
+ private async fetchAndCache<T>(
143
+ key: string,
144
+ fetcher: () => Promise<T>,
145
+ ttl: number
146
+ ): Promise<T> {
147
+ const data = await fetcher();
148
+ await this.adapter.set(key, {
149
+ data,
150
+ timestamp: Date.now(),
151
+ ttl
152
+ });
153
+ return data;
154
+ }
155
+
156
+ /**
157
+ * Revalidate cache entry in background
158
+ */
159
+ private async revalidateInBackground<T>(
160
+ key: string,
161
+ fetcher: () => Promise<T>,
162
+ ttl: number
163
+ ): Promise<void> {
164
+ // Prevent multiple simultaneous revalidations
165
+ if (this.revalidating.has(key)) {
166
+ return;
167
+ }
168
+
169
+ this.revalidating.add(key);
170
+ try {
171
+ await this.fetchAndCache(key, fetcher, ttl);
172
+ if (this.verbose) {
173
+ console.log(`[Cache] Revalidated: ${key}`);
174
+ }
175
+ } catch (error) {
176
+ if (this.verbose) {
177
+ console.log(`[Cache] Revalidation failed: ${key}`, error);
178
+ }
179
+ // Keep stale data on revalidation failure
180
+ } finally {
181
+ this.revalidating.delete(key);
182
+ }
183
+ }
184
+
185
+ /**
186
+ * Force refresh a cache entry
187
+ */
188
+ async refresh<T>(
189
+ key: string,
190
+ fetcher: () => Promise<T>,
191
+ ttl?: number
192
+ ): Promise<T> {
193
+ if (this.verbose) {
194
+ console.log(`[Cache] FORCE REFRESH: ${key}`);
195
+ }
196
+ return this.fetchAndCache(key, fetcher, ttl || this.ttls.files);
197
+ }
198
+
199
+ /**
200
+ * Invalidate a specific cache entry
201
+ */
202
+ async invalidate(key: string): Promise<void> {
203
+ await this.adapter.delete(key);
204
+ if (this.verbose) {
205
+ console.log(`[Cache] INVALIDATED: ${key}`);
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Invalidate all entries for a repository
211
+ */
212
+ async invalidateRepo(owner: string, repo: string): Promise<void> {
213
+ const prefix = `${owner}/${repo}/`;
214
+ // For memory adapter, we can iterate
215
+ if (this.adapter instanceof MemoryCacheAdapter) {
216
+ const stats = this.adapter.getStats();
217
+ for (const key of stats.keys) {
218
+ if (key.startsWith(prefix)) {
219
+ await this.adapter.delete(key);
220
+ }
221
+ }
222
+ }
223
+ if (this.verbose) {
224
+ console.log(`[Cache] INVALIDATED REPO: ${owner}/${repo}`);
225
+ }
226
+ }
227
+
228
+ /**
229
+ * Clear entire cache
230
+ */
231
+ async clear(): Promise<void> {
232
+ await this.adapter.clear();
233
+ if (this.verbose) {
234
+ console.log(`[Cache] CLEARED`);
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Get TTL for metadata
240
+ */
241
+ get metadataTTL(): number {
242
+ return this.ttls.metadata;
243
+ }
244
+
245
+ /**
246
+ * Get TTL for files
247
+ */
248
+ get filesTTL(): number {
249
+ return this.ttls.files;
250
+ }
251
+ }