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,617 @@
1
+ /**
2
+ * @fileoverview Langchain Exporter - Export MCP tools to Langchain format
3
+ * @author nich (x.com/nichxbt | github.com/nirholas)
4
+ * @copyright Copyright (c) 2024-2026 nich (nirholas)
5
+ * @license MIT
6
+ * @see https://github.com/nirholas/github-to-mcp
7
+ */
8
+
9
+ import { ExtractedTool } from './types';
10
+
11
+ /** Exporter metadata - nich (x.com/nichxbt | github.com/nirholas) */
12
+ const _LANGCHAIN_META = { author: 'nich', v: 1, project: 'github-to-mcp' } as const;
13
+
14
+ // ============================================================================
15
+ // Types
16
+ // ============================================================================
17
+
18
+ export interface LangchainExportOptions {
19
+ /** Name for the toolkit/tool collection */
20
+ toolkitName?: string;
21
+ /** Base URL for API calls */
22
+ baseUrl?: string;
23
+ /** Environment variable name for API key */
24
+ apiKeyEnvVar?: string;
25
+ /** Include JSDoc/docstrings */
26
+ includeComments?: boolean;
27
+ /** Add runtime validation */
28
+ includeValidation?: boolean;
29
+ /** Export format */
30
+ format?: 'tools' | 'toolkit' | 'agent';
31
+ }
32
+
33
+ export interface LangchainExportResult {
34
+ typescript: string;
35
+ python: string;
36
+ metadata: {
37
+ toolCount: number;
38
+ toolkitName: string;
39
+ generatedAt: string;
40
+ };
41
+ }
42
+
43
+ // ============================================================================
44
+ // Langchain Exporter Class
45
+ // ============================================================================
46
+
47
+ /**
48
+ * Export MCP tools to Langchain format
49
+ *
50
+ * Supports both TypeScript (@langchain/core) and Python (langchain) exports
51
+ * with proper type safety, validation, and documentation.
52
+ */
53
+ export class LangchainExporter {
54
+ private options: Required<LangchainExportOptions>;
55
+
56
+ constructor(options: LangchainExportOptions = {}) {
57
+ this.options = {
58
+ toolkitName: options.toolkitName ?? 'generatedTools',
59
+ baseUrl: options.baseUrl ?? 'https://api.example.com',
60
+ apiKeyEnvVar: options.apiKeyEnvVar ?? 'API_KEY',
61
+ includeComments: options.includeComments ?? true,
62
+ includeValidation: options.includeValidation ?? true,
63
+ format: options.format ?? 'tools',
64
+ };
65
+ }
66
+
67
+ /**
68
+ * Export tools to both TypeScript and Python Langchain format
69
+ */
70
+ export(tools: ExtractedTool[]): LangchainExportResult {
71
+ return {
72
+ typescript: this.exportTypeScript(tools),
73
+ python: this.exportPython(tools),
74
+ metadata: {
75
+ toolCount: tools.length,
76
+ toolkitName: this.options.toolkitName,
77
+ generatedAt: new Date().toISOString(),
78
+ },
79
+ };
80
+ }
81
+
82
+ /**
83
+ * Export as Langchain Tools for TypeScript
84
+ */
85
+ exportTypeScript(tools: ExtractedTool[]): string {
86
+ const { toolkitName, baseUrl, apiKeyEnvVar, includeComments, includeValidation } = this.options;
87
+
88
+ const imports = this.generateTypeScriptImports(includeValidation);
89
+ const schemas = includeValidation ? this.generateZodSchemas(tools) : '';
90
+ const toolDefinitions = tools.map(tool => this.generateTypeScriptTool(tool, includeValidation)).join('\n\n');
91
+
92
+ const code = `${this.generateFileHeader('TypeScript')}
93
+
94
+ ${imports}
95
+
96
+ ${includeComments ? '// ============================================================================\n// Configuration\n// ============================================================================\n\n' : ''}const API_BASE_URL = process.env.BASE_URL || '${baseUrl}';
97
+ const API_KEY = process.env.${apiKeyEnvVar};
98
+
99
+ if (!API_KEY) {
100
+ console.warn('Warning: ${apiKeyEnvVar} environment variable not set');
101
+ }
102
+
103
+ ${includeComments ? '// ============================================================================\n// Helper Functions\n// ============================================================================\n\n' : ''}async function makeApiRequest(
104
+ endpoint: string,
105
+ method: string = 'GET',
106
+ body?: Record<string, unknown>
107
+ ): Promise<unknown> {
108
+ const response = await fetch(\`\${API_BASE_URL}\${endpoint}\`, {
109
+ method,
110
+ headers: {
111
+ 'Authorization': \`Bearer \${API_KEY}\`,
112
+ 'Content-Type': 'application/json',
113
+ },
114
+ ...(body && { body: JSON.stringify(body) }),
115
+ });
116
+
117
+ if (!response.ok) {
118
+ throw new Error(\`API request failed: \${response.status} \${response.statusText}\`);
119
+ }
120
+
121
+ return response.json();
122
+ }
123
+
124
+ ${schemas ? `${includeComments ? '// ============================================================================\n// Zod Schemas for Validation\n// ============================================================================\n\n' : ''}${schemas}\n\n` : ''}${includeComments ? '// ============================================================================\n// Tool Definitions\n// ============================================================================\n\n' : ''}${toolDefinitions}
125
+
126
+ ${includeComments ? '// ============================================================================\n// Export\n// ============================================================================\n\n' : ''}export const ${toolkitName} = [
127
+ ${tools.map(t => ` ${this.toVariableName(t.name)}Tool,`).join('\n')}
128
+ ];
129
+
130
+ ${this.options.format === 'toolkit' ? this.generateTypeScriptToolkit(tools, toolkitName) : ''}
131
+ export default ${toolkitName};
132
+ `;
133
+
134
+ return code;
135
+ }
136
+
137
+ /**
138
+ * Export as Langchain Tools for Python
139
+ */
140
+ exportPython(tools: ExtractedTool[]): string {
141
+ const { toolkitName, baseUrl, apiKeyEnvVar, includeComments, includeValidation } = this.options;
142
+
143
+ const imports = this.generatePythonImports(includeValidation);
144
+ const pydanticModels = includeValidation ? this.generatePydanticModels(tools) : '';
145
+ const toolDefinitions = tools.map(tool => this.generatePythonTool(tool, includeValidation)).join('\n\n');
146
+
147
+ const code = `${this.generateFileHeader('Python', '#')}
148
+
149
+ ${imports}
150
+
151
+ ${includeComments ? '# ============================================================================\n# Configuration\n# ============================================================================\n\n' : ''}API_BASE_URL = os.getenv("BASE_URL", "${baseUrl}")
152
+ API_KEY = os.getenv("${apiKeyEnvVar}")
153
+
154
+ if not API_KEY:
155
+ logger.warning("${apiKeyEnvVar} environment variable not set")
156
+
157
+ ${includeComments ? '# ============================================================================\n# HTTP Client\n# ============================================================================\n\n' : ''}async def make_api_request(
158
+ endpoint: str,
159
+ method: str = "GET",
160
+ body: dict | None = None
161
+ ) -> dict:
162
+ """Make an authenticated API request."""
163
+ async with httpx.AsyncClient() as client:
164
+ response = await client.request(
165
+ method=method,
166
+ url=f"{API_BASE_URL}{endpoint}",
167
+ headers={
168
+ "Authorization": f"Bearer {API_KEY}",
169
+ "Content-Type": "application/json",
170
+ },
171
+ json=body,
172
+ )
173
+ response.raise_for_status()
174
+ return response.json()
175
+
176
+ ${pydanticModels ? `${includeComments ? '# ============================================================================\n# Pydantic Models for Validation\n# ============================================================================\n\n' : ''}${pydanticModels}\n\n` : ''}${includeComments ? '# ============================================================================\n# Tool Functions\n# ============================================================================\n\n' : ''}${toolDefinitions}
177
+
178
+ ${includeComments ? '# ============================================================================\n# Tool Collection\n# ============================================================================\n\n' : ''}${toolkitName} = [
179
+ ${tools.map(t => ` ${this.toSnakeCase(t.name)}_tool,`).join('\n')}
180
+ ]
181
+
182
+ ${this.options.format === 'toolkit' ? this.generatePythonToolkit(tools, toolkitName) : ''}
183
+ __all__ = ["${toolkitName}"${this.options.format === 'toolkit' ? `, "${this.toPascalCase(toolkitName)}Toolkit"` : ''}]
184
+ `;
185
+
186
+ return code;
187
+ }
188
+
189
+ // ============================================================================
190
+ // TypeScript Generation Helpers
191
+ // ============================================================================
192
+
193
+ private generateFileHeader(language: string, commentChar: string = '//'): string {
194
+ const border = commentChar === '#' ? '#' : '//';
195
+ return `${commentChar === '#' ? '"""' : '/**'}
196
+ ${commentChar === '#' ? '' : ' *'} Generated Langchain Tools
197
+ ${commentChar === '#' ? '' : ' *'}
198
+ ${commentChar === '#' ? '' : ' *'} Auto-generated from MCP tool definitions
199
+ ${commentChar === '#' ? '' : ' *'} Language: ${language}
200
+ ${commentChar === '#' ? '' : ' *'}
201
+ ${commentChar === '#' ? '' : ' *'} @author nich (x.com/nichxbt | github.com/nirholas)
202
+ ${commentChar === '#' ? '' : ' *'} @see https://github.com/nirholas/github-to-mcp
203
+ ${commentChar === '#' ? '"""' : ' */'}`;
204
+ }
205
+
206
+ private generateTypeScriptImports(includeValidation: boolean): string {
207
+ const imports = [
208
+ `import { DynamicStructuredTool } from '@langchain/core/tools';`,
209
+ ];
210
+
211
+ if (includeValidation) {
212
+ imports.push(`import { z } from 'zod';`);
213
+ }
214
+
215
+ return imports.join('\n');
216
+ }
217
+
218
+ private generateZodSchemas(tools: ExtractedTool[]): string {
219
+ return tools.map(tool => this.generateZodSchema(tool)).join('\n\n');
220
+ }
221
+
222
+ private generateZodSchema(tool: ExtractedTool): string {
223
+ const schemaName = `${this.toPascalCase(tool.name)}Schema`;
224
+ const properties = tool.inputSchema?.properties || {};
225
+ const required = tool.inputSchema?.required || [];
226
+
227
+ const fields = Object.entries(properties).map(([name, prop]: [string, any]) => {
228
+ const zodType = this.jsonSchemaToZod(prop, required.includes(name));
229
+ const description = prop.description ? `.describe('${this.escapeString(prop.description)}')` : '';
230
+ return ` ${name}: ${zodType}${description},`;
231
+ });
232
+
233
+ return `export const ${schemaName} = z.object({
234
+ ${fields.join('\n')}
235
+ });
236
+
237
+ export type ${this.toPascalCase(tool.name)}Input = z.infer<typeof ${schemaName}>;`;
238
+ }
239
+
240
+ private jsonSchemaToZod(prop: any, isRequired: boolean): string {
241
+ let zodType: string;
242
+
243
+ switch (prop.type) {
244
+ case 'string':
245
+ zodType = 'z.string()';
246
+ if (prop.format === 'email') zodType = 'z.string().email()';
247
+ if (prop.format === 'url' || prop.format === 'uri') zodType = 'z.string().url()';
248
+ if (prop.format === 'uuid') zodType = 'z.string().uuid()';
249
+ if (prop.minLength) zodType += `.min(${prop.minLength})`;
250
+ if (prop.maxLength) zodType += `.max(${prop.maxLength})`;
251
+ if (prop.pattern) zodType += `.regex(/${prop.pattern}/)`;
252
+ if (prop.enum) zodType = `z.enum([${prop.enum.map((e: string) => `'${e}'`).join(', ')}])`;
253
+ break;
254
+ case 'number':
255
+ case 'integer':
256
+ zodType = prop.type === 'integer' ? 'z.number().int()' : 'z.number()';
257
+ if (prop.minimum !== undefined) zodType += `.min(${prop.minimum})`;
258
+ if (prop.maximum !== undefined) zodType += `.max(${prop.maximum})`;
259
+ break;
260
+ case 'boolean':
261
+ zodType = 'z.boolean()';
262
+ break;
263
+ case 'array':
264
+ const itemType = prop.items ? this.jsonSchemaToZod(prop.items, true) : 'z.unknown()';
265
+ zodType = `z.array(${itemType})`;
266
+ break;
267
+ case 'object':
268
+ if (prop.properties) {
269
+ const nestedFields = Object.entries(prop.properties).map(([k, v]: [string, any]) => {
270
+ const nestedRequired = (prop.required || []).includes(k);
271
+ return `${k}: ${this.jsonSchemaToZod(v, nestedRequired)}`;
272
+ }).join(', ');
273
+ zodType = `z.object({ ${nestedFields} })`;
274
+ } else {
275
+ zodType = 'z.record(z.unknown())';
276
+ }
277
+ break;
278
+ default:
279
+ zodType = 'z.unknown()';
280
+ }
281
+
282
+ if (!isRequired) {
283
+ zodType += '.optional()';
284
+ }
285
+
286
+ return zodType;
287
+ }
288
+
289
+ private generateTypeScriptTool(tool: ExtractedTool, includeValidation: boolean): string {
290
+ const varName = this.toVariableName(tool.name);
291
+ const schemaName = `${this.toPascalCase(tool.name)}Schema`;
292
+ const description = this.escapeString(tool.description || `Execute ${tool.name}`);
293
+
294
+ const properties = tool.inputSchema?.properties || {};
295
+ const params = Object.keys(properties);
296
+ const destructure = params.length > 0 ? `{ ${params.join(', ')} }` : '{}';
297
+
298
+ // Generate inline schema if not using validation
299
+ const schemaCode = includeValidation
300
+ ? schemaName
301
+ : this.generateInlineZodSchema(tool);
302
+
303
+ // Generate implementation
304
+ const endpoint = this.guessEndpoint(tool.name);
305
+ const method = this.guessHttpMethod(tool.name);
306
+
307
+ return `export const ${varName}Tool = new DynamicStructuredTool({
308
+ name: '${tool.name}',
309
+ description: \`${description}\`,
310
+ schema: ${schemaCode},
311
+ func: async (${destructure}) => {
312
+ try {
313
+ const result = await makeApiRequest(
314
+ '${endpoint}',
315
+ '${method}',
316
+ ${params.length > 0 ? `{ ${params.join(', ')} }` : 'undefined'}
317
+ );
318
+ return JSON.stringify(result, null, 2);
319
+ } catch (error) {
320
+ return \`Error: \${error instanceof Error ? error.message : String(error)}\`;
321
+ }
322
+ },
323
+ });`;
324
+ }
325
+
326
+ private generateInlineZodSchema(tool: ExtractedTool): string {
327
+ const properties = tool.inputSchema?.properties || {};
328
+ const required = tool.inputSchema?.required || [];
329
+
330
+ const fields = Object.entries(properties).map(([name, prop]: [string, any]) => {
331
+ const zodType = this.jsonSchemaToZod(prop, required.includes(name));
332
+ const description = prop.description ? `.describe('${this.escapeString(prop.description)}')` : '';
333
+ return ` ${name}: ${zodType}${description},`;
334
+ });
335
+
336
+ return `z.object({
337
+ ${fields.join('\n')}
338
+ })`;
339
+ }
340
+
341
+ private generateTypeScriptToolkit(tools: ExtractedTool[], name: string): string {
342
+ const className = this.toPascalCase(name) + 'Toolkit';
343
+ return `
344
+ /**
345
+ * Toolkit class for grouping related tools
346
+ */
347
+ export class ${className} {
348
+ private tools: DynamicStructuredTool[];
349
+
350
+ constructor() {
351
+ this.tools = ${name};
352
+ }
353
+
354
+ getTools(): DynamicStructuredTool[] {
355
+ return this.tools;
356
+ }
357
+
358
+ getTool(name: string): DynamicStructuredTool | undefined {
359
+ return this.tools.find(t => t.name === name);
360
+ }
361
+ }
362
+ `;
363
+ }
364
+
365
+ // ============================================================================
366
+ // Python Generation Helpers
367
+ // ============================================================================
368
+
369
+ private generatePythonImports(includeValidation: boolean): string {
370
+ const imports = [
371
+ 'import os',
372
+ 'import logging',
373
+ 'from typing import Any',
374
+ '',
375
+ 'import httpx',
376
+ 'from langchain.tools import StructuredTool',
377
+ ];
378
+
379
+ if (includeValidation) {
380
+ imports.push('from pydantic import BaseModel, Field');
381
+ }
382
+
383
+ imports.push('', 'logger = logging.getLogger(__name__)');
384
+
385
+ return imports.join('\n');
386
+ }
387
+
388
+ private generatePydanticModels(tools: ExtractedTool[]): string {
389
+ return tools.map(tool => this.generatePydanticModel(tool)).join('\n\n');
390
+ }
391
+
392
+ private generatePydanticModel(tool: ExtractedTool): string {
393
+ const className = `${this.toPascalCase(tool.name)}Input`;
394
+ const properties = tool.inputSchema?.properties || {};
395
+ const required = tool.inputSchema?.required || [];
396
+
397
+ const fields = Object.entries(properties).map(([name, prop]: [string, any]) => {
398
+ const pythonType = this.jsonSchemaToPython(prop, required.includes(name));
399
+ const fieldArgs: string[] = [];
400
+
401
+ if (!required.includes(name)) {
402
+ fieldArgs.push('default=None');
403
+ }
404
+ if (prop.description) {
405
+ fieldArgs.push(`description="${this.escapeString(prop.description)}"`);
406
+ }
407
+
408
+ const fieldDef = fieldArgs.length > 0 ? `Field(${fieldArgs.join(', ')})` : '...';
409
+ return ` ${this.toSnakeCase(name)}: ${pythonType} = ${fieldDef}`;
410
+ });
411
+
412
+ const docstring = tool.description ? ` """${tool.description}"""\n` : '';
413
+
414
+ return `class ${className}(BaseModel):
415
+ ${docstring}${fields.join('\n')}`;
416
+ }
417
+
418
+ private jsonSchemaToPython(prop: any, isRequired: boolean): string {
419
+ let pythonType: string;
420
+
421
+ switch (prop.type) {
422
+ case 'string':
423
+ pythonType = 'str';
424
+ break;
425
+ case 'number':
426
+ pythonType = 'float';
427
+ break;
428
+ case 'integer':
429
+ pythonType = 'int';
430
+ break;
431
+ case 'boolean':
432
+ pythonType = 'bool';
433
+ break;
434
+ case 'array':
435
+ const itemType = prop.items ? this.jsonSchemaToPython(prop.items, true) : 'Any';
436
+ pythonType = `list[${itemType}]`;
437
+ break;
438
+ case 'object':
439
+ pythonType = 'dict[str, Any]';
440
+ break;
441
+ default:
442
+ pythonType = 'Any';
443
+ }
444
+
445
+ if (!isRequired) {
446
+ pythonType = `${pythonType} | None`;
447
+ }
448
+
449
+ return pythonType;
450
+ }
451
+
452
+ private generatePythonTool(tool: ExtractedTool, includeValidation: boolean): string {
453
+ const funcName = this.toSnakeCase(tool.name);
454
+ const className = `${this.toPascalCase(tool.name)}Input`;
455
+ const description = this.escapeString(tool.description || `Execute ${tool.name}`);
456
+
457
+ const properties = tool.inputSchema?.properties || {};
458
+ const required = tool.inputSchema?.required || [];
459
+
460
+ // Generate function parameters
461
+ const params = Object.entries(properties).map(([name, prop]: [string, any]) => {
462
+ const pythonType = this.jsonSchemaToPython(prop, required.includes(name));
463
+ const snakeName = this.toSnakeCase(name);
464
+ const defaultVal = required.includes(name) ? '' : ' = None';
465
+ return ` ${snakeName}: ${pythonType}${defaultVal}`;
466
+ });
467
+
468
+ const endpoint = this.guessEndpoint(tool.name);
469
+ const method = this.guessHttpMethod(tool.name);
470
+ const bodyParams = Object.keys(properties).map(p => `"${p}": ${this.toSnakeCase(p)}`).join(', ');
471
+
472
+ const functionDef = `async def ${funcName}(
473
+ ${params.join(',\n') || ' # No parameters'}
474
+ ) -> str:
475
+ """
476
+ ${description}
477
+ """
478
+ try:
479
+ result = await make_api_request(
480
+ "${endpoint}",
481
+ "${method}",
482
+ {${bodyParams}} if ${Object.keys(properties).length > 0} else None
483
+ )
484
+ return str(result)
485
+ except Exception as e:
486
+ return f"Error: {e}"`;
487
+
488
+ const toolDef = `${funcName}_tool = StructuredTool.from_function(
489
+ coroutine=${funcName},
490
+ name="${tool.name}",
491
+ description="${description}",${includeValidation ? `\n args_schema=${className},` : ''}
492
+ )`;
493
+
494
+ return `${functionDef}\n\n${toolDef}`;
495
+ }
496
+
497
+ private generatePythonToolkit(tools: ExtractedTool[], name: string): string {
498
+ const className = this.toPascalCase(name) + 'Toolkit';
499
+ return `
500
+
501
+ class ${className}:
502
+ """Toolkit class for grouping related tools."""
503
+
504
+ def __init__(self):
505
+ self.tools = ${name}
506
+
507
+ def get_tools(self) -> list[StructuredTool]:
508
+ """Get all tools in this toolkit."""
509
+ return self.tools
510
+
511
+ def get_tool(self, name: str) -> StructuredTool | None:
512
+ """Get a specific tool by name."""
513
+ return next((t for t in self.tools if t.name == name), None)
514
+ `;
515
+ }
516
+
517
+ // ============================================================================
518
+ // Utility Methods
519
+ // ============================================================================
520
+
521
+ private toVariableName(name: string): string {
522
+ // Convert to camelCase variable name
523
+ return name
524
+ .replace(/[-_](.)/g, (_, char) => char.toUpperCase())
525
+ .replace(/^(.)/, char => char.toLowerCase());
526
+ }
527
+
528
+ private toPascalCase(name: string): string {
529
+ return name
530
+ .replace(/[-_](.)/g, (_, char) => char.toUpperCase())
531
+ .replace(/^(.)/, char => char.toUpperCase());
532
+ }
533
+
534
+ private toSnakeCase(name: string): string {
535
+ return name
536
+ .replace(/([A-Z])/g, '_$1')
537
+ .replace(/[-\s]/g, '_')
538
+ .toLowerCase()
539
+ .replace(/^_/, '')
540
+ .replace(/_+/g, '_');
541
+ }
542
+
543
+ private escapeString(str: string): string {
544
+ return str
545
+ .replace(/\\/g, '\\\\')
546
+ .replace(/'/g, "\\'")
547
+ .replace(/"/g, '\\"')
548
+ .replace(/\n/g, '\\n')
549
+ .replace(/`/g, '\\`');
550
+ }
551
+
552
+ private guessEndpoint(toolName: string): string {
553
+ // Try to guess a RESTful endpoint from the tool name
554
+ const parts = toolName.split(/[-_]/);
555
+ const action = parts[0].toLowerCase();
556
+ const resource = parts.slice(1).join('/').toLowerCase() || 'resource';
557
+
558
+ switch (action) {
559
+ case 'get':
560
+ case 'list':
561
+ case 'fetch':
562
+ return `/${resource}`;
563
+ case 'create':
564
+ case 'add':
565
+ case 'post':
566
+ return `/${resource}`;
567
+ case 'update':
568
+ case 'edit':
569
+ case 'patch':
570
+ return `/${resource}/{id}`;
571
+ case 'delete':
572
+ case 'remove':
573
+ return `/${resource}/{id}`;
574
+ default:
575
+ return `/${toolName.replace(/[-_]/g, '/')}`;
576
+ }
577
+ }
578
+
579
+ private guessHttpMethod(toolName: string): string {
580
+ const name = toolName.toLowerCase();
581
+ if (name.startsWith('get') || name.startsWith('list') || name.startsWith('fetch') || name.startsWith('read')) {
582
+ return 'GET';
583
+ }
584
+ if (name.startsWith('create') || name.startsWith('add') || name.startsWith('post')) {
585
+ return 'POST';
586
+ }
587
+ if (name.startsWith('update') || name.startsWith('edit') || name.startsWith('patch')) {
588
+ return 'PATCH';
589
+ }
590
+ if (name.startsWith('delete') || name.startsWith('remove')) {
591
+ return 'DELETE';
592
+ }
593
+ return 'POST';
594
+ }
595
+ }
596
+
597
+ // ============================================================================
598
+ // Factory Functions
599
+ // ============================================================================
600
+
601
+ /**
602
+ * Create a new Langchain exporter with options
603
+ */
604
+ export function createLangchainExporter(options?: LangchainExportOptions): LangchainExporter {
605
+ return new LangchainExporter(options);
606
+ }
607
+
608
+ /**
609
+ * Quick export tools to Langchain format
610
+ */
611
+ export function exportToLangchain(
612
+ tools: ExtractedTool[],
613
+ options?: LangchainExportOptions
614
+ ): LangchainExportResult {
615
+ const exporter = new LangchainExporter(options);
616
+ return exporter.export(tools);
617
+ }