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,937 @@
1
+ /**
2
+ * @fileoverview Java code extractor for extracting tools from Java codebases
3
+ * @copyright Copyright (c) 2024-2026 nirholas
4
+ * @license MIT
5
+ */
6
+
7
+ import { ExtractedTool, ParsedDocumentation } from '../types';
8
+
9
+ /**
10
+ * Extracted Java method information
11
+ */
12
+ interface JavaMethod {
13
+ name: string;
14
+ className: string;
15
+ visibility: 'public' | 'protected' | 'private' | 'package';
16
+ isStatic: boolean;
17
+ returnType: string;
18
+ params: Array<{
19
+ name: string;
20
+ type: string;
21
+ annotations: string[];
22
+ }>;
23
+ annotations: string[];
24
+ documentation: ParsedDocumentation | null;
25
+ line: number;
26
+ }
27
+
28
+ /**
29
+ * Java endpoint info (for Spring/JAX-RS)
30
+ */
31
+ interface JavaEndpoint {
32
+ method: string;
33
+ path: string;
34
+ handler: JavaMethod | null;
35
+ produces?: string[];
36
+ consumes?: string[];
37
+ }
38
+
39
+ /**
40
+ * JavaExtractor extracts tools from Java codebases
41
+ * Supports:
42
+ * - Spring Boot @RequestMapping, @GetMapping, etc.
43
+ * - JAX-RS @Path, @GET, @POST, etc.
44
+ * - Micronaut @Controller routes
45
+ * - Public methods with Javadoc
46
+ */
47
+ export class JavaExtractor {
48
+ /**
49
+ * Extract tools from Java code
50
+ */
51
+ async extract(code: string, filename: string): Promise<ExtractedTool[]> {
52
+ const tools: ExtractedTool[] = [];
53
+
54
+ // Extract from web framework annotations
55
+ const springTools = this.extractSpringEndpoints(code, filename);
56
+ const jaxrsTools = this.extractJaxRsEndpoints(code, filename);
57
+ const micronautTools = this.extractMicronautEndpoints(code, filename);
58
+
59
+ tools.push(...springTools, ...jaxrsTools, ...micronautTools);
60
+
61
+ // Extract from public methods with Javadoc
62
+ const publicMethods = this.extractPublicMethods(code, filename);
63
+ tools.push(...publicMethods);
64
+
65
+ return tools;
66
+ }
67
+
68
+ /**
69
+ * Extract Spring Boot endpoints
70
+ * Annotations:
71
+ * - @RequestMapping
72
+ * - @GetMapping, @PostMapping, @PutMapping, @DeleteMapping, @PatchMapping
73
+ * - @RestController, @Controller
74
+ */
75
+ private extractSpringEndpoints(code: string, filename: string): ExtractedTool[] {
76
+ const tools: ExtractedTool[] = [];
77
+ const lines = code.split('\n');
78
+
79
+ // Find class-level @RequestMapping for base path
80
+ let basePath = '';
81
+ const classRequestMapping = code.match(/@RequestMapping\s*\(\s*(?:value\s*=\s*)?"([^"]+)"/);
82
+ if (classRequestMapping) {
83
+ basePath = classRequestMapping[1];
84
+ }
85
+
86
+ // Method-level mapping annotations
87
+ const mappingAnnotations = [
88
+ { pattern: /@GetMapping\s*\(\s*(?:value\s*=\s*)?"([^"]+)"/, method: 'GET' },
89
+ { pattern: /@PostMapping\s*\(\s*(?:value\s*=\s*)?"([^"]+)"/, method: 'POST' },
90
+ { pattern: /@PutMapping\s*\(\s*(?:value\s*=\s*)?"([^"]+)"/, method: 'PUT' },
91
+ { pattern: /@DeleteMapping\s*\(\s*(?:value\s*=\s*)?"([^"]+)"/, method: 'DELETE' },
92
+ { pattern: /@PatchMapping\s*\(\s*(?:value\s*=\s*)?"([^"]+)"/, method: 'PATCH' },
93
+ { pattern: /@GetMapping\s*(?:\(\s*\))?(?!\s*\()/, method: 'GET', noPath: true },
94
+ { pattern: /@PostMapping\s*(?:\(\s*\))?(?!\s*\()/, method: 'POST', noPath: true },
95
+ { pattern: /@PutMapping\s*(?:\(\s*\))?(?!\s*\()/, method: 'PUT', noPath: true },
96
+ { pattern: /@DeleteMapping\s*(?:\(\s*\))?(?!\s*\()/, method: 'DELETE', noPath: true },
97
+ { pattern: /@PatchMapping\s*(?:\(\s*\))?(?!\s*\()/, method: 'PATCH', noPath: true },
98
+ ];
99
+
100
+ // Also handle @RequestMapping with method attribute
101
+ const requestMappingPattern = /@RequestMapping\s*\(\s*(?:value\s*=\s*)?"([^"]+)"(?:\s*,\s*method\s*=\s*RequestMethod\.(\w+))?/g;
102
+
103
+ for (let i = 0; i < lines.length; i++) {
104
+ const line = lines[i];
105
+
106
+ // Check for specific mapping annotations
107
+ for (const { pattern, method, noPath } of mappingAnnotations) {
108
+ const match = line.match(pattern);
109
+ if (match) {
110
+ const path = noPath ? '' : (match[1] || '');
111
+ const fullPath = this.joinPaths(basePath, path);
112
+
113
+ // Find the method definition
114
+ const methodInfo = this.findNextMethod(lines, i + 1);
115
+
116
+ if (methodInfo) {
117
+ tools.push({
118
+ name: this.generateToolName(method, fullPath, methodInfo.name),
119
+ description: methodInfo.documentation?.description || `${method} ${fullPath}`,
120
+ inputSchema: this.buildSpringInputSchema(methodInfo, fullPath),
121
+ source: {
122
+ type: 'code',
123
+ file: filename,
124
+ line: i + 1
125
+ },
126
+ confidence: 0.85
127
+ });
128
+ }
129
+ }
130
+ }
131
+
132
+ // Check for @RequestMapping
133
+ requestMappingPattern.lastIndex = 0;
134
+ const rmMatch = requestMappingPattern.exec(line);
135
+ if (rmMatch && !line.includes('@interface') && !this.isClassLevel(lines, i)) {
136
+ const path = rmMatch[1] || '';
137
+ const method = rmMatch[2] || 'GET';
138
+ const fullPath = this.joinPaths(basePath, path);
139
+
140
+ const methodInfo = this.findNextMethod(lines, i + 1);
141
+
142
+ if (methodInfo) {
143
+ tools.push({
144
+ name: this.generateToolName(method, fullPath, methodInfo.name),
145
+ description: methodInfo.documentation?.description || `${method} ${fullPath}`,
146
+ inputSchema: this.buildSpringInputSchema(methodInfo, fullPath),
147
+ source: {
148
+ type: 'code',
149
+ file: filename,
150
+ line: i + 1
151
+ },
152
+ confidence: 0.85
153
+ });
154
+ }
155
+ }
156
+ }
157
+
158
+ return tools;
159
+ }
160
+
161
+ /**
162
+ * Extract JAX-RS endpoints
163
+ * Annotations:
164
+ * - @Path
165
+ * - @GET, @POST, @PUT, @DELETE, @PATCH, @HEAD, @OPTIONS
166
+ * - @Produces, @Consumes
167
+ */
168
+ private extractJaxRsEndpoints(code: string, filename: string): ExtractedTool[] {
169
+ const tools: ExtractedTool[] = [];
170
+ const lines = code.split('\n');
171
+
172
+ // Find class-level @Path
173
+ let basePath = '';
174
+ const classPath = code.match(/@Path\s*\(\s*"([^"]+)"\s*\)/);
175
+ if (classPath) {
176
+ basePath = classPath[1];
177
+ }
178
+
179
+ // Check if this is a JAX-RS file
180
+ if (!code.includes('@Path') && !code.includes('@GET') && !code.includes('@POST')) {
181
+ return tools;
182
+ }
183
+
184
+ const httpMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'];
185
+
186
+ for (let i = 0; i < lines.length; i++) {
187
+ const line = lines[i];
188
+
189
+ // Look for HTTP method annotations
190
+ for (const httpMethod of httpMethods) {
191
+ if (line.includes(`@${httpMethod}`)) {
192
+ // Find @Path annotation near this line
193
+ let methodPath = '';
194
+ for (let j = Math.max(0, i - 3); j <= Math.min(lines.length - 1, i + 3); j++) {
195
+ const pathMatch = lines[j].match(/@Path\s*\(\s*"([^"]+)"\s*\)/);
196
+ if (pathMatch && j !== this.getClassPathLine(lines)) {
197
+ methodPath = pathMatch[1];
198
+ break;
199
+ }
200
+ }
201
+
202
+ const fullPath = this.joinPaths(basePath, methodPath);
203
+ const methodInfo = this.findNextMethod(lines, i + 1);
204
+
205
+ if (methodInfo) {
206
+ tools.push({
207
+ name: this.generateToolName(httpMethod, fullPath, methodInfo.name),
208
+ description: methodInfo.documentation?.description || `${httpMethod} ${fullPath}`,
209
+ inputSchema: this.buildJaxRsInputSchema(methodInfo, fullPath),
210
+ source: {
211
+ type: 'code',
212
+ file: filename,
213
+ line: i + 1
214
+ },
215
+ confidence: 0.85
216
+ });
217
+ }
218
+ break;
219
+ }
220
+ }
221
+ }
222
+
223
+ return tools;
224
+ }
225
+
226
+ /**
227
+ * Extract Micronaut endpoints
228
+ * Annotations:
229
+ * - @Controller
230
+ * - @Get, @Post, @Put, @Delete, @Patch
231
+ */
232
+ private extractMicronautEndpoints(code: string, filename: string): ExtractedTool[] {
233
+ const tools: ExtractedTool[] = [];
234
+ const lines = code.split('\n');
235
+
236
+ // Check if this is a Micronaut file
237
+ if (!code.includes('@Controller') && !code.includes('io.micronaut')) {
238
+ return tools;
239
+ }
240
+
241
+ // Find class-level @Controller path
242
+ let basePath = '';
243
+ const controllerMatch = code.match(/@Controller\s*\(\s*"([^"]+)"\s*\)/);
244
+ if (controllerMatch) {
245
+ basePath = controllerMatch[1];
246
+ }
247
+
248
+ const mappingAnnotations = [
249
+ { pattern: /@Get\s*\(\s*"([^"]+)"\s*\)/, method: 'GET' },
250
+ { pattern: /@Post\s*\(\s*"([^"]+)"\s*\)/, method: 'POST' },
251
+ { pattern: /@Put\s*\(\s*"([^"]+)"\s*\)/, method: 'PUT' },
252
+ { pattern: /@Delete\s*\(\s*"([^"]+)"\s*\)/, method: 'DELETE' },
253
+ { pattern: /@Patch\s*\(\s*"([^"]+)"\s*\)/, method: 'PATCH' },
254
+ { pattern: /@Get\s*(?:\(\s*\))?(?!\s*\()/, method: 'GET', noPath: true },
255
+ { pattern: /@Post\s*(?:\(\s*\))?(?!\s*\()/, method: 'POST', noPath: true },
256
+ ];
257
+
258
+ for (let i = 0; i < lines.length; i++) {
259
+ const line = lines[i];
260
+
261
+ for (const { pattern, method, noPath } of mappingAnnotations) {
262
+ const match = line.match(pattern);
263
+ if (match) {
264
+ const path = noPath ? '' : (match[1] || '');
265
+ const fullPath = this.joinPaths(basePath, path);
266
+
267
+ const methodInfo = this.findNextMethod(lines, i + 1);
268
+
269
+ if (methodInfo) {
270
+ tools.push({
271
+ name: this.generateToolName(method, fullPath, methodInfo.name),
272
+ description: methodInfo.documentation?.description || `${method} ${fullPath}`,
273
+ inputSchema: this.buildMicronautInputSchema(methodInfo, fullPath),
274
+ source: {
275
+ type: 'code',
276
+ file: filename,
277
+ line: i + 1
278
+ },
279
+ confidence: 0.8
280
+ });
281
+ }
282
+ }
283
+ }
284
+ }
285
+
286
+ return tools;
287
+ }
288
+
289
+ /**
290
+ * Extract public methods with Javadoc
291
+ */
292
+ private extractPublicMethods(code: string, filename: string): ExtractedTool[] {
293
+ const tools: ExtractedTool[] = [];
294
+ const lines = code.split('\n');
295
+
296
+ for (let i = 0; i < lines.length; i++) {
297
+ const line = lines[i];
298
+
299
+ // Look for public method declarations
300
+ if (/^\s*public\s+(?:static\s+)?(?!class|interface|enum)[\w<>\[\],\s]+\s+\w+\s*\(/.test(line)) {
301
+ // Skip if it has web framework annotations (already processed)
302
+ let hasWebAnnotation = false;
303
+ for (let j = Math.max(0, i - 5); j < i; j++) {
304
+ if (/@(Get|Post|Put|Delete|Patch|RequestMapping|Path|GET|POST|PUT|DELETE)/.test(lines[j])) {
305
+ hasWebAnnotation = true;
306
+ break;
307
+ }
308
+ }
309
+
310
+ if (hasWebAnnotation) continue;
311
+
312
+ const methodInfo = this.parseMethod(lines, i);
313
+
314
+ if (methodInfo && methodInfo.documentation && methodInfo.visibility === 'public') {
315
+ tools.push({
316
+ name: methodInfo.name,
317
+ description: methodInfo.documentation.description || methodInfo.name,
318
+ inputSchema: this.buildMethodInputSchema(methodInfo),
319
+ source: {
320
+ type: 'code',
321
+ file: filename,
322
+ line: i + 1
323
+ },
324
+ confidence: 0.6,
325
+ confidenceFactors: {
326
+ documentation: 0.8,
327
+ types: 0.9,
328
+ examples: methodInfo.documentation.examples?.length ? 0.7 : 0.2,
329
+ source: 0.7
330
+ }
331
+ });
332
+ }
333
+ }
334
+ }
335
+
336
+ return tools;
337
+ }
338
+
339
+ /**
340
+ * Find the next method definition
341
+ */
342
+ private findNextMethod(lines: string[], startLine: number): JavaMethod | null {
343
+ for (let i = startLine; i < Math.min(startLine + 10, lines.length); i++) {
344
+ const line = lines[i];
345
+ // Look for method signature (not class/interface declaration)
346
+ if (/^\s*(public|protected|private)?\s*(static\s+)?[\w<>\[\],\s]+\s+\w+\s*\(/.test(line) &&
347
+ !line.includes('class ') && !line.includes('interface ') && !line.includes('enum ')) {
348
+ return this.parseMethod(lines, i);
349
+ }
350
+ }
351
+ return null;
352
+ }
353
+
354
+ /**
355
+ * Parse a Java method definition
356
+ */
357
+ private parseMethod(lines: string[], lineIndex: number): JavaMethod | null {
358
+ let methodLine = lines[lineIndex];
359
+
360
+ // Handle multi-line signatures
361
+ let parenDepth = 0;
362
+ let i = lineIndex;
363
+ while (i < lines.length) {
364
+ for (const char of lines[i]) {
365
+ if (char === '(') parenDepth++;
366
+ if (char === ')') parenDepth--;
367
+ }
368
+ if (parenDepth === 0 && i > lineIndex) {
369
+ methodLine = lines.slice(lineIndex, i + 1).join(' ');
370
+ break;
371
+ }
372
+ if (parenDepth === 0) break;
373
+ i++;
374
+ }
375
+
376
+ // Parse method signature - but need to handle params with nested parens
377
+ // First, extract the header part (before opening paren)
378
+ const headerMatch = methodLine.match(
379
+ /^\s*(public|protected|private)?\s*(static\s+)?([\w<>\[\],\s]+)\s+(\w+)\s*\(/
380
+ );
381
+
382
+ if (!headerMatch) return null;
383
+
384
+ const [headerPart, visibility, isStatic, returnType, name] = headerMatch;
385
+
386
+ // Extract parameters by finding the matching closing paren
387
+ let paramsStart = headerPart.length;
388
+ let depth = 1;
389
+ let paramsEnd = paramsStart;
390
+
391
+ for (let idx = paramsStart; idx < methodLine.length; idx++) {
392
+ const char = methodLine[idx];
393
+ if (char === '(') depth++;
394
+ else if (char === ')') {
395
+ depth--;
396
+ if (depth === 0) {
397
+ paramsEnd = idx;
398
+ break;
399
+ }
400
+ }
401
+ }
402
+
403
+ const paramsStr = methodLine.substring(paramsStart, paramsEnd);
404
+
405
+ // Parse parameters
406
+ const params = this.parseParameters(paramsStr, lines, lineIndex);
407
+
408
+ // Get class name from file
409
+ const classMatch = lines.join('\n').match(/class\s+(\w+)/);
410
+ const className = classMatch ? classMatch[1] : 'Unknown';
411
+
412
+ // Get annotations
413
+ const annotations = this.getAnnotations(lines, lineIndex);
414
+
415
+ // Get Javadoc
416
+ const documentation = this.parseJavadoc(lines, lineIndex);
417
+
418
+ return {
419
+ name,
420
+ className,
421
+ visibility: (visibility as JavaMethod['visibility']) || 'package',
422
+ isStatic: !!isStatic,
423
+ returnType: returnType.trim(),
424
+ params,
425
+ annotations,
426
+ documentation,
427
+ line: lineIndex + 1
428
+ };
429
+ }
430
+
431
+ /**
432
+ * Parse method parameters
433
+ */
434
+ private parseParameters(
435
+ paramsStr: string,
436
+ lines: string[],
437
+ methodLine: number
438
+ ): JavaMethod['params'] {
439
+ const params: JavaMethod['params'] = [];
440
+ if (!paramsStr.trim()) return params;
441
+
442
+ // Split by comma, handling generics
443
+ const paramParts = this.splitParams(paramsStr);
444
+
445
+ for (const part of paramParts) {
446
+ const trimmed = part.trim();
447
+ if (!trimmed) continue;
448
+
449
+ // Extract annotations
450
+ const annotations: string[] = [];
451
+ let cleanPart = trimmed;
452
+
453
+ const annotationMatches = trimmed.matchAll(/@(\w+)(?:\([^)]*\))?\s*/g);
454
+ for (const match of annotationMatches) {
455
+ annotations.push(match[0].trim());
456
+ cleanPart = cleanPart.replace(match[0], '');
457
+ }
458
+
459
+ // Parse type and name
460
+ const paramMatch = cleanPart.trim().match(/^([\w<>\[\],\s.]+)\s+(\w+)$/);
461
+ if (paramMatch) {
462
+ params.push({
463
+ type: paramMatch[1].trim(),
464
+ name: paramMatch[2],
465
+ annotations
466
+ });
467
+ }
468
+ }
469
+
470
+ return params;
471
+ }
472
+
473
+ /**
474
+ * Split parameters handling generics
475
+ */
476
+ private splitParams(paramsStr: string): string[] {
477
+ const params: string[] = [];
478
+ let current = '';
479
+ let depth = 0;
480
+
481
+ for (const char of paramsStr) {
482
+ if (char === '<' || char === '(' || char === '[') {
483
+ depth++;
484
+ current += char;
485
+ } else if (char === '>' || char === ')' || char === ']') {
486
+ depth--;
487
+ current += char;
488
+ } else if (char === ',' && depth === 0) {
489
+ params.push(current.trim());
490
+ current = '';
491
+ } else {
492
+ current += char;
493
+ }
494
+ }
495
+
496
+ if (current.trim()) {
497
+ params.push(current.trim());
498
+ }
499
+
500
+ return params;
501
+ }
502
+
503
+ /**
504
+ * Get annotations above a method
505
+ */
506
+ private getAnnotations(lines: string[], methodLine: number): string[] {
507
+ const annotations: string[] = [];
508
+ let i = methodLine - 1;
509
+
510
+ while (i >= 0) {
511
+ const line = lines[i].trim();
512
+ if (line.startsWith('@')) {
513
+ annotations.unshift(line);
514
+ i--;
515
+ } else if (line === '' || line.startsWith('*') || line.startsWith('/*') || line.startsWith('//')) {
516
+ i--;
517
+ } else {
518
+ break;
519
+ }
520
+ }
521
+
522
+ return annotations;
523
+ }
524
+
525
+ /**
526
+ * Parse Javadoc comments
527
+ */
528
+ private parseJavadoc(lines: string[], methodLine: number): ParsedDocumentation | null {
529
+ // Find start of Javadoc
530
+ let javadocEnd = -1;
531
+ let i = methodLine - 1;
532
+
533
+ // Skip annotations
534
+ while (i >= 0 && (lines[i].trim().startsWith('@') || lines[i].trim() === '')) {
535
+ i--;
536
+ }
537
+
538
+ // Look for */
539
+ while (i >= 0) {
540
+ if (lines[i].includes('*/')) {
541
+ javadocEnd = i;
542
+ break;
543
+ }
544
+ if (!lines[i].trim().startsWith('*') && !lines[i].trim().startsWith('@') && lines[i].trim() !== '') {
545
+ return null; // No Javadoc
546
+ }
547
+ i--;
548
+ }
549
+
550
+ if (javadocEnd === -1) return null;
551
+
552
+ // Find start /**
553
+ let javadocStart = javadocEnd;
554
+ while (javadocStart >= 0) {
555
+ if (lines[javadocStart].includes('/**')) {
556
+ break;
557
+ }
558
+ javadocStart--;
559
+ }
560
+
561
+ if (javadocStart < 0) return null;
562
+
563
+ // Parse Javadoc content
564
+ const javadocLines: string[] = [];
565
+ for (let j = javadocStart; j <= javadocEnd; j++) {
566
+ let line = lines[j]
567
+ .replace(/\/\*\*/, '')
568
+ .replace(/\*\//, '')
569
+ .replace(/^\s*\*\s?/, '')
570
+ .trim();
571
+ if (line) {
572
+ javadocLines.push(line);
573
+ }
574
+ }
575
+
576
+ return this.parseDocumentation(javadocLines);
577
+ }
578
+
579
+ /**
580
+ * Parse documentation content
581
+ */
582
+ private parseDocumentation(docLines: string[]): ParsedDocumentation {
583
+ const doc: ParsedDocumentation = {
584
+ params: [],
585
+ examples: []
586
+ };
587
+
588
+ let description = '';
589
+ let inDescription = true;
590
+
591
+ for (const line of docLines) {
592
+ // @param tag
593
+ const paramMatch = line.match(/^@param\s+(\w+)\s+(.*)/);
594
+ if (paramMatch) {
595
+ inDescription = false;
596
+ doc.params.push({
597
+ name: paramMatch[1],
598
+ description: paramMatch[2]
599
+ });
600
+ continue;
601
+ }
602
+
603
+ // @return tag
604
+ const returnMatch = line.match(/^@returns?\s+(.*)/);
605
+ if (returnMatch) {
606
+ inDescription = false;
607
+ doc.returns = { description: returnMatch[1] };
608
+ continue;
609
+ }
610
+
611
+ // @throws/@exception tag
612
+ const throwsMatch = line.match(/^@(?:throws|exception)\s+(.*)/);
613
+ if (throwsMatch) {
614
+ inDescription = false;
615
+ if (!doc.throws) doc.throws = [];
616
+ doc.throws.push(throwsMatch[1]);
617
+ continue;
618
+ }
619
+
620
+ // @deprecated tag
621
+ if (line.startsWith('@deprecated')) {
622
+ inDescription = false;
623
+ doc.deprecated = true;
624
+ continue;
625
+ }
626
+
627
+ // @since tag
628
+ const sinceMatch = line.match(/^@since\s+(.*)/);
629
+ if (sinceMatch) {
630
+ inDescription = false;
631
+ doc.since = sinceMatch[1];
632
+ continue;
633
+ }
634
+
635
+ // Skip other @ tags
636
+ if (line.startsWith('@')) {
637
+ inDescription = false;
638
+ continue;
639
+ }
640
+
641
+ // Add to description
642
+ if (inDescription) {
643
+ description += (description ? ' ' : '') + line;
644
+ }
645
+ }
646
+
647
+ doc.description = description.trim() || undefined;
648
+ return doc;
649
+ }
650
+
651
+ /**
652
+ * Check if current line is class-level (not method-level)
653
+ */
654
+ private isClassLevel(lines: string[], lineIndex: number): boolean {
655
+ // Look ahead for class keyword before next method
656
+ for (let i = lineIndex + 1; i < Math.min(lineIndex + 10, lines.length); i++) {
657
+ if (/^\s*public\s+class\s+/.test(lines[i])) {
658
+ return true;
659
+ }
660
+ if (/^\s*(public|protected|private)?\s*(static\s+)?[\w<>\[\],\s]+\s+\w+\s*\(/.test(lines[i])) {
661
+ return false;
662
+ }
663
+ }
664
+ return false;
665
+ }
666
+
667
+ /**
668
+ * Get line number of class-level @Path annotation
669
+ */
670
+ private getClassPathLine(lines: string[]): number {
671
+ for (let i = 0; i < lines.length; i++) {
672
+ if (lines[i].includes('@Path') && this.isClassLevel(lines, i)) {
673
+ return i;
674
+ }
675
+ }
676
+ return -1;
677
+ }
678
+
679
+ /**
680
+ * Join path segments
681
+ */
682
+ private joinPaths(base: string, path: string): string {
683
+ if (!base && !path) return '/';
684
+ if (!base) return path.startsWith('/') ? path : '/' + path;
685
+ if (!path) return base.startsWith('/') ? base : '/' + base;
686
+
687
+ const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base;
688
+ const normalizedPath = path.startsWith('/') ? path : '/' + path;
689
+
690
+ return (normalizedBase.startsWith('/') ? '' : '/') + normalizedBase + normalizedPath;
691
+ }
692
+
693
+ /**
694
+ * Generate tool name
695
+ */
696
+ private generateToolName(method: string, path: string, handlerName: string): string {
697
+ const pathParts = path
698
+ .split('/')
699
+ .filter(p => p && !p.startsWith('{') && !p.startsWith(':'))
700
+ .map(p => p.replace(/-/g, '_').toLowerCase());
701
+
702
+ if (pathParts.length > 0) {
703
+ return `${method.toLowerCase()}_${pathParts.join('_')}`;
704
+ }
705
+
706
+ // Convert method name from camelCase to snake_case
707
+ return handlerName.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '');
708
+ }
709
+
710
+ /**
711
+ * Build input schema for Spring endpoints
712
+ */
713
+ private buildSpringInputSchema(
714
+ methodInfo: JavaMethod,
715
+ path: string
716
+ ): { type: 'object'; properties: Record<string, any>; required: string[] } {
717
+ const properties: Record<string, any> = {};
718
+ const required: string[] = [];
719
+
720
+ // Extract path parameters
721
+ const pathParams = path.match(/\{(\w+)\}/g) || [];
722
+ for (const param of pathParams) {
723
+ const name = param.slice(1, -1);
724
+ properties[name] = {
725
+ type: 'string',
726
+ description: `Path parameter: ${name}`
727
+ };
728
+ required.push(name);
729
+ }
730
+
731
+ // Add method parameters
732
+ for (const param of methodInfo.params) {
733
+ // Skip framework types
734
+ if (this.isSpringFrameworkType(param.type)) continue;
735
+
736
+ // Check for @RequestBody, @RequestParam, @PathVariable annotations
737
+ const isPathVariable = param.annotations.some(a => a.includes('@PathVariable'));
738
+ const isRequestBody = param.annotations.some(a => a.includes('@RequestBody'));
739
+ const isRequestParam = param.annotations.some(a => a.includes('@RequestParam'));
740
+
741
+ if (isPathVariable) continue; // Already handled
742
+
743
+ const paramDescription = methodInfo.documentation?.params.find(p => p.name === param.name)?.description;
744
+
745
+ if (isRequestBody) {
746
+ properties[param.name] = {
747
+ type: 'object',
748
+ description: paramDescription || `Request body: ${param.name}`
749
+ };
750
+ required.push(param.name);
751
+ } else if (isRequestParam) {
752
+ // Check if required
753
+ const reqMatch = param.annotations.find(a => a.includes('@RequestParam'))?.match(/required\s*=\s*(true|false)/);
754
+ const isRequired = !reqMatch || reqMatch[1] === 'true';
755
+
756
+ properties[param.name] = {
757
+ type: this.javaTypeToJsonSchema(param.type),
758
+ description: paramDescription || param.name
759
+ };
760
+
761
+ if (isRequired) {
762
+ required.push(param.name);
763
+ }
764
+ }
765
+ }
766
+
767
+ return { type: 'object', properties, required };
768
+ }
769
+
770
+ /**
771
+ * Build input schema for JAX-RS endpoints
772
+ */
773
+ private buildJaxRsInputSchema(
774
+ methodInfo: JavaMethod,
775
+ path: string
776
+ ): { type: 'object'; properties: Record<string, any>; required: string[] } {
777
+ const properties: Record<string, any> = {};
778
+ const required: string[] = [];
779
+
780
+ // Extract path parameters
781
+ const pathParams = path.match(/\{(\w+)\}/g) || [];
782
+ for (const param of pathParams) {
783
+ const name = param.slice(1, -1);
784
+ properties[name] = {
785
+ type: 'string',
786
+ description: `Path parameter: ${name}`
787
+ };
788
+ required.push(name);
789
+ }
790
+
791
+ // Add method parameters
792
+ for (const param of methodInfo.params) {
793
+ const isPathParam = param.annotations.some(a => a.includes('@PathParam'));
794
+ const isQueryParam = param.annotations.some(a => a.includes('@QueryParam'));
795
+ const isFormParam = param.annotations.some(a => a.includes('@FormParam'));
796
+
797
+ if (isPathParam) continue;
798
+
799
+ const paramDescription = methodInfo.documentation?.params.find(p => p.name === param.name)?.description;
800
+
801
+ if (isQueryParam || isFormParam) {
802
+ properties[param.name] = {
803
+ type: this.javaTypeToJsonSchema(param.type),
804
+ description: paramDescription || param.name
805
+ };
806
+ } else if (!this.isJaxRsFrameworkType(param.type)) {
807
+ // Assume it's a request body
808
+ properties[param.name] = {
809
+ type: 'object',
810
+ description: paramDescription || `Request body: ${param.name}`
811
+ };
812
+ required.push(param.name);
813
+ }
814
+ }
815
+
816
+ return { type: 'object', properties, required };
817
+ }
818
+
819
+ /**
820
+ * Build input schema for Micronaut endpoints
821
+ */
822
+ private buildMicronautInputSchema(
823
+ methodInfo: JavaMethod,
824
+ path: string
825
+ ): { type: 'object'; properties: Record<string, any>; required: string[] } {
826
+ // Micronaut is similar to Spring
827
+ return this.buildSpringInputSchema(methodInfo, path);
828
+ }
829
+
830
+ /**
831
+ * Build input schema from method parameters
832
+ */
833
+ private buildMethodInputSchema(
834
+ methodInfo: JavaMethod
835
+ ): { type: 'object'; properties: Record<string, any>; required: string[] } {
836
+ const properties: Record<string, any> = {};
837
+ const required: string[] = [];
838
+
839
+ for (const param of methodInfo.params) {
840
+ const paramDescription = methodInfo.documentation?.params.find(p => p.name === param.name)?.description;
841
+
842
+ properties[param.name] = {
843
+ type: this.javaTypeToJsonSchema(param.type),
844
+ description: paramDescription || param.name
845
+ };
846
+
847
+ // Primitive types are required, objects are optional
848
+ if (!param.type.includes('.') && !param.type.startsWith('Optional')) {
849
+ required.push(param.name);
850
+ }
851
+ }
852
+
853
+ return { type: 'object', properties, required };
854
+ }
855
+
856
+ /**
857
+ * Check if type is a Spring framework type
858
+ */
859
+ private isSpringFrameworkType(type: string): boolean {
860
+ const frameworkTypes = [
861
+ 'HttpServletRequest', 'HttpServletResponse',
862
+ 'Model', 'ModelMap', 'ModelAndView',
863
+ 'BindingResult', 'Errors',
864
+ 'RedirectAttributes', 'SessionStatus',
865
+ 'Principal', 'Authentication',
866
+ 'UriComponentsBuilder', 'HttpEntity',
867
+ 'MultipartFile'
868
+ ];
869
+ return frameworkTypes.some(ft => type.includes(ft));
870
+ }
871
+
872
+ /**
873
+ * Check if type is a JAX-RS framework type
874
+ */
875
+ private isJaxRsFrameworkType(type: string): boolean {
876
+ const frameworkTypes = [
877
+ 'HttpServletRequest', 'HttpServletResponse',
878
+ 'UriInfo', 'HttpHeaders', 'SecurityContext',
879
+ 'Request', 'Response', 'ContainerRequestContext'
880
+ ];
881
+ return frameworkTypes.some(ft => type.includes(ft));
882
+ }
883
+
884
+ /**
885
+ * Convert Java type to JSON Schema type
886
+ */
887
+ private javaTypeToJsonSchema(javaType: string): string {
888
+ const type = javaType.trim();
889
+
890
+ // Handle arrays
891
+ if (type.endsWith('[]') || type.startsWith('List<') || type.startsWith('Set<') || type.startsWith('Collection<')) {
892
+ return 'array';
893
+ }
894
+
895
+ // Handle maps
896
+ if (type.startsWith('Map<') || type.startsWith('HashMap<')) {
897
+ return 'object';
898
+ }
899
+
900
+ // Handle Optional
901
+ if (type.startsWith('Optional<')) {
902
+ const inner = type.match(/Optional<(.+)>/);
903
+ if (inner) return this.javaTypeToJsonSchema(inner[1]);
904
+ }
905
+
906
+ // Primitive and wrapper type mapping
907
+ const typeMap: Record<string, string> = {
908
+ 'String': 'string',
909
+ 'CharSequence': 'string',
910
+ 'int': 'integer',
911
+ 'Integer': 'integer',
912
+ 'long': 'integer',
913
+ 'Long': 'integer',
914
+ 'short': 'integer',
915
+ 'Short': 'integer',
916
+ 'byte': 'integer',
917
+ 'Byte': 'integer',
918
+ 'BigInteger': 'integer',
919
+ 'float': 'number',
920
+ 'Float': 'number',
921
+ 'double': 'number',
922
+ 'Double': 'number',
923
+ 'BigDecimal': 'number',
924
+ 'boolean': 'boolean',
925
+ 'Boolean': 'boolean',
926
+ 'char': 'string',
927
+ 'Character': 'string'
928
+ };
929
+
930
+ if (typeMap[type]) {
931
+ return typeMap[type];
932
+ }
933
+
934
+ // Default to object for complex types
935
+ return 'object';
936
+ }
937
+ }