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.
- package/.env.example +8 -0
- package/.github/CODEOWNERS +6 -0
- package/.husky/pre-commit +1 -0
- package/.nvmrc +1 -0
- package/.prettierignore +5 -0
- package/.prettierrc +7 -0
- package/.vscode/settings.json +4 -0
- package/ARCHITECTURE.md +1429 -0
- package/CHANGELOG.md +167 -0
- package/CONTRIBUTING.md +327 -0
- package/LICENSE +201 -0
- package/README.md +1028 -0
- package/SECURITY.md +248 -0
- package/VISUAL_GUIDE.md +437 -0
- package/apps/vscode/IMPLEMENTATION.md +480 -0
- package/apps/vscode/README.md +248 -0
- package/apps/vscode/package.json +381 -0
- package/apps/vscode/resources/icon.png +0 -0
- package/apps/vscode/resources/icon.svg +5 -0
- package/apps/vscode/src/commands/browseRegistry.ts +211 -0
- package/apps/vscode/src/commands/configureClaudeDesktop.ts +332 -0
- package/apps/vscode/src/commands/convert.ts +82 -0
- package/apps/vscode/src/commands/convertCurrentRepo.ts +109 -0
- package/apps/vscode/src/commands/convertFromUrl.ts +138 -0
- package/apps/vscode/src/commands/index.ts +121 -0
- package/apps/vscode/src/commands/validate.ts +197 -0
- package/apps/vscode/src/extension.ts +464 -0
- package/apps/vscode/src/global.d.ts +36 -0
- package/apps/vscode/src/test/extension.test.ts +73 -0
- package/apps/vscode/src/utils/file-generator.ts +529 -0
- package/apps/vscode/src/utils/github-api.ts +335 -0
- package/apps/vscode/src/utils/index.ts +29 -0
- package/apps/vscode/src/utils/mcp-config.ts +334 -0
- package/apps/vscode/src/utils/storage.ts +87 -0
- package/apps/vscode/src/views/McpServersTreeView.ts +160 -0
- package/apps/vscode/src/views/OutputChannelView.ts +195 -0
- package/apps/vscode/src/views/StatusBarItem.ts +251 -0
- package/apps/vscode/src/views/ToolsExplorerView.ts +314 -0
- package/apps/vscode/src/views/historyProvider.ts +75 -0
- package/apps/vscode/src/views/index.ts +12 -0
- package/apps/vscode/src/views/resultsPanel.ts +330 -0
- package/apps/vscode/src/webviews/ConversionPanel.ts +350 -0
- package/apps/vscode/src/webviews/ToolDetailsPanel.ts +448 -0
- package/apps/vscode/src/webviews/index.ts +9 -0
- package/apps/vscode/src/webviews/webview-ui/styles.ts +492 -0
- package/apps/vscode/tsconfig.json +20 -0
- package/apps/web/PLAYGROUND_GUIDE.md +499 -0
- package/apps/web/README.md +505 -0
- package/apps/web/app/api/convert/route.ts +100 -0
- package/apps/web/app/api/convert/stream/route.ts +198 -0
- package/apps/web/app/api/deploy/route.ts +157 -0
- package/apps/web/app/api/edge/route.ts +308 -0
- package/apps/web/app/api/export-docker/route.ts +284 -0
- package/apps/web/app/api/generate-openapi/route.ts +119 -0
- package/apps/web/app/api/mcp/[serverId]/route.ts +263 -0
- package/apps/web/app/api/playground/connect/route.ts +143 -0
- package/apps/web/app/api/playground/disconnect/route.ts +78 -0
- package/apps/web/app/api/playground/execute/route.ts +135 -0
- package/apps/web/app/api/playground/sessions/route.ts +103 -0
- package/apps/web/app/api/playground/tools/route.ts +117 -0
- package/apps/web/app/api/playground/v2/connect/route.ts +96 -0
- package/apps/web/app/api/playground/v2/disconnect/route.ts +88 -0
- package/apps/web/app/api/playground/v2/health/route.ts +80 -0
- package/apps/web/app/api/playground/v2/prompts/route.ts +160 -0
- package/apps/web/app/api/playground/v2/resources/route.ts +159 -0
- package/apps/web/app/api/playground/v2/sessions/route.ts +184 -0
- package/apps/web/app/api/playground/v2/tools/route.ts +167 -0
- package/apps/web/app/api/stream/route.ts +232 -0
- package/apps/web/app/batch/BatchConvertClient.tsx +190 -0
- package/apps/web/app/batch/page.tsx +37 -0
- package/apps/web/app/convert/page.tsx +269 -0
- package/apps/web/app/dashboard/page.tsx +380 -0
- package/apps/web/app/globals.css +622 -0
- package/apps/web/app/layout.tsx +120 -0
- package/apps/web/app/manifest.ts +31 -0
- package/apps/web/app/opengraph-image.tsx +112 -0
- package/apps/web/app/page.old.tsx +924 -0
- package/apps/web/app/page.tsx +77 -0
- package/apps/web/app/playground/page.tsx +306 -0
- package/apps/web/app/playground/v2/error.tsx +163 -0
- package/apps/web/app/playground/v2/layout.tsx +58 -0
- package/apps/web/app/playground/v2/loading.tsx +152 -0
- package/apps/web/app/playground/v2/page.tsx +644 -0
- package/apps/web/app/playground/v2/providers.tsx +214 -0
- package/apps/web/app/playground/v2/use-shortcuts.ts +209 -0
- package/apps/web/app/playground/v2/use-url-state.ts +296 -0
- package/apps/web/app/providers.tsx +22 -0
- package/apps/web/app/sitemap.ts +32 -0
- package/apps/web/app/twitter-image.tsx +112 -0
- package/apps/web/components/BranchSelector.tsx +401 -0
- package/apps/web/components/ClaudeConfigExport.tsx +226 -0
- package/apps/web/components/Features.tsx +84 -0
- package/apps/web/components/Footer.tsx +119 -0
- package/apps/web/components/GenerationProgress.tsx +248 -0
- package/apps/web/components/GithubUrlInput.tsx +483 -0
- package/apps/web/components/Header.tsx +175 -0
- package/apps/web/components/Hero.tsx +117 -0
- package/apps/web/components/HowItWorks.tsx +119 -0
- package/apps/web/components/InstallBanner.tsx +158 -0
- package/apps/web/components/Logo.tsx +116 -0
- package/apps/web/components/ParticleBackground.tsx +105 -0
- package/apps/web/components/Playground.tsx +472 -0
- package/apps/web/components/PlaygroundToolTester.tsx +410 -0
- package/apps/web/components/ProductCards.tsx +179 -0
- package/apps/web/components/SplitView.tsx +194 -0
- package/apps/web/components/ToolFilter.tsx +260 -0
- package/apps/web/components/ToolList.tsx +325 -0
- package/apps/web/components/batch/BatchConvert.tsx +785 -0
- package/apps/web/components/batch/index.ts +7 -0
- package/apps/web/components/convert/ConfigTabs.tsx +230 -0
- package/apps/web/components/convert/ConversionResult.tsx +482 -0
- package/apps/web/components/convert/InlinePlayground.tsx +259 -0
- package/apps/web/components/convert/LoadingSteps.tsx +311 -0
- package/apps/web/components/convert/OneClickInstall.tsx +224 -0
- package/apps/web/components/convert/ToolCard.tsx +189 -0
- package/apps/web/components/convert/TryInPlayground.tsx +242 -0
- package/apps/web/components/convert/index.ts +12 -0
- package/apps/web/components/deploy/DeployButton.tsx +369 -0
- package/apps/web/components/deploy/index.ts +7 -0
- package/apps/web/components/docker/DockerExport.tsx +690 -0
- package/apps/web/components/docker/index.ts +7 -0
- package/apps/web/components/install/OneClickInstall.tsx +676 -0
- package/apps/web/components/install/index.ts +7 -0
- package/apps/web/components/playground/CapabilityTabs.tsx +150 -0
- package/apps/web/components/playground/ConnectionStatusV2.tsx +322 -0
- package/apps/web/components/playground/EmptyStates.tsx +305 -0
- package/apps/web/components/playground/ExecutionLog.tsx +260 -0
- package/apps/web/components/playground/ExecutionLogV2.tsx +378 -0
- package/apps/web/components/playground/JsonViewer.tsx +388 -0
- package/apps/web/components/playground/PlaygroundLayout.tsx +244 -0
- package/apps/web/components/playground/PromptsPanel.tsx +385 -0
- package/apps/web/components/playground/ResourcesPanel.tsx +378 -0
- package/apps/web/components/playground/SchemaForm.tsx +477 -0
- package/apps/web/components/playground/ServerStatus.tsx +151 -0
- package/apps/web/components/playground/ShareButton.tsx +239 -0
- package/apps/web/components/playground/ToolsPanel.tsx +309 -0
- package/apps/web/components/playground/TransportConfigurator.tsx +563 -0
- package/apps/web/components/playground/index.ts +74 -0
- package/apps/web/components/playground/types.ts +202 -0
- package/apps/web/components/streaming/StreamingProgress.tsx +441 -0
- package/apps/web/components/streaming/index.ts +7 -0
- package/apps/web/components/ui/badge.tsx +42 -0
- package/apps/web/components/ui/button.tsx +88 -0
- package/apps/web/components/ui/card.tsx +75 -0
- package/apps/web/components/ui/code-block.tsx +122 -0
- package/apps/web/components/ui/index.ts +12 -0
- package/apps/web/components/ui/input.tsx +55 -0
- package/apps/web/components/ui/tabs.tsx +61 -0
- package/apps/web/hooks/index.ts +85 -0
- package/apps/web/hooks/types.ts +1173 -0
- package/apps/web/hooks/use-conversion.ts +133 -0
- package/apps/web/hooks/use-execution-history.ts +376 -0
- package/apps/web/hooks/use-generation-progress.ts +147 -0
- package/apps/web/hooks/use-local-storage.ts +88 -0
- package/apps/web/hooks/use-mcp-client.ts +623 -0
- package/apps/web/hooks/use-mcp-connection.ts +500 -0
- package/apps/web/hooks/use-mcp-execution.ts +282 -0
- package/apps/web/hooks/use-mcp-prompts.ts +441 -0
- package/apps/web/hooks/use-mcp-resources.ts +430 -0
- package/apps/web/hooks/use-mcp-tools.ts +540 -0
- package/apps/web/hooks/use-playground-store.ts +299 -0
- package/apps/web/hooks/use-playground.ts +184 -0
- package/apps/web/hooks/use-streaming-conversion.ts +227 -0
- package/apps/web/hooks/useBatchConversion.ts +271 -0
- package/apps/web/hooks/useDockerConfig.ts +161 -0
- package/apps/web/hooks/usePlatformDetection.ts +80 -0
- package/apps/web/hooks/useStreaming.ts +199 -0
- package/apps/web/lib/api/errors.ts +386 -0
- package/apps/web/lib/api/index.ts +137 -0
- package/apps/web/lib/api/logger.ts +187 -0
- package/apps/web/lib/api/middleware.ts +364 -0
- package/apps/web/lib/api/openapi.ts +977 -0
- package/apps/web/lib/api/session-manager.ts +594 -0
- package/apps/web/lib/api/types.ts +433 -0
- package/apps/web/lib/api/validation.ts +523 -0
- package/apps/web/lib/constants.ts +114 -0
- package/apps/web/lib/mcp/client.ts +1137 -0
- package/apps/web/lib/mcp/events.ts +651 -0
- package/apps/web/lib/mcp/index.ts +347 -0
- package/apps/web/lib/mcp/logger.ts +428 -0
- package/apps/web/lib/mcp/metrics.ts +703 -0
- package/apps/web/lib/mcp/retry.ts +616 -0
- package/apps/web/lib/mcp/session-manager.ts +779 -0
- package/apps/web/lib/mcp/transports.ts +988 -0
- package/apps/web/lib/mcp/types.ts +594 -0
- package/apps/web/lib/mcp-client-enhanced.ts +871 -0
- package/apps/web/lib/mcp-client.ts +778 -0
- package/apps/web/lib/mcp-errors.ts +489 -0
- package/apps/web/lib/mcp-sandbox.ts +593 -0
- package/apps/web/lib/mcp-testing.ts +428 -0
- package/apps/web/lib/mcp-types.ts +448 -0
- package/apps/web/lib/playground-store.tsx +1147 -0
- package/apps/web/lib/utils.ts +439 -0
- package/apps/web/next-env.d.ts +5 -0
- package/apps/web/next.config.js +23 -0
- package/apps/web/package.json +55 -0
- package/apps/web/postcss.config.js +6 -0
- package/apps/web/public/.well-known/ai-plugin.json +17 -0
- package/apps/web/public/logo.svg +6 -0
- package/apps/web/public/robots.txt +22 -0
- package/apps/web/public/schema.json +27 -0
- package/apps/web/tailwind.config.js +26 -0
- package/apps/web/tailwind.config.ts +123 -0
- package/apps/web/tsconfig.json +20 -0
- package/apps/web/types/deploy.ts +139 -0
- package/apps/web/types/index.ts +247 -0
- package/apps/web/vercel.json +39 -0
- package/eslint.config.mjs +23 -0
- package/llms.txt +102 -0
- package/mkdocs/docs/api/core.md +318 -0
- package/mkdocs/docs/api/index.md +128 -0
- package/mkdocs/docs/api/mcp-server.md +301 -0
- package/mkdocs/docs/api/openapi-parser.md +254 -0
- package/mkdocs/docs/assets/logo.svg +7 -0
- package/mkdocs/docs/changelog.md +118 -0
- package/mkdocs/docs/cli/generate.md +148 -0
- package/mkdocs/docs/cli/index.md +52 -0
- package/mkdocs/docs/cli/inspect.md +164 -0
- package/mkdocs/docs/cli/serve.md +136 -0
- package/mkdocs/docs/concepts/classification.md +254 -0
- package/mkdocs/docs/concepts/how-it-works.md +299 -0
- package/mkdocs/docs/concepts/index.md +77 -0
- package/mkdocs/docs/concepts/mcp-protocol.md +362 -0
- package/mkdocs/docs/concepts/tool-types.md +382 -0
- package/mkdocs/docs/contributing/architecture.md +262 -0
- package/mkdocs/docs/contributing/development.md +245 -0
- package/mkdocs/docs/contributing/index.md +73 -0
- package/mkdocs/docs/contributing/testing.md +320 -0
- package/mkdocs/docs/getting-started/configuration.md +235 -0
- package/mkdocs/docs/getting-started/index.md +54 -0
- package/mkdocs/docs/getting-started/installation.md +145 -0
- package/mkdocs/docs/getting-started/quickstart.md +160 -0
- package/mkdocs/docs/guides/batch.md +375 -0
- package/mkdocs/docs/guides/claude-desktop.md +227 -0
- package/mkdocs/docs/guides/cursor.md +188 -0
- package/mkdocs/docs/guides/custom-tools.md +367 -0
- package/mkdocs/docs/guides/index.md +78 -0
- package/mkdocs/docs/guides/private-repos.md +221 -0
- package/mkdocs/docs/guides/vscode.md +247 -0
- package/mkdocs/docs/index.md +175 -0
- package/mkdocs/docs/reference/config.md +223 -0
- package/mkdocs/docs/reference/env.md +192 -0
- package/mkdocs/docs/reference/index.md +102 -0
- package/mkdocs/docs/reference/tools.md +309 -0
- package/mkdocs/docs/stylesheets/extra.css +231 -0
- package/mkdocs/mkdocs.yml +204 -0
- package/mkdocs/overrides/.gitkeep +1 -0
- package/mkdocs/overrides/main.html +7 -0
- package/mkdocs/python-deps.txt +7 -0
- package/mkdocs/vercel.json +11 -0
- package/package.json +63 -0
- package/packages/core/package.json +61 -0
- package/packages/core/src/__tests__/bitbucket-client.test.ts +366 -0
- package/packages/core/src/__tests__/cli.test.ts +235 -0
- package/packages/core/src/__tests__/code-extractor.test.ts +378 -0
- package/packages/core/src/__tests__/docker-generator.test.ts +255 -0
- package/packages/core/src/__tests__/github-client.test.ts +390 -0
- package/packages/core/src/__tests__/gitlab-client.test.ts +319 -0
- package/packages/core/src/__tests__/go-extractor.test.ts +351 -0
- package/packages/core/src/__tests__/graphql-extractor.test.ts +330 -0
- package/packages/core/src/__tests__/java-extractor.test.ts +497 -0
- package/packages/core/src/__tests__/plugins.test.ts +467 -0
- package/packages/core/src/__tests__/readme-extractor.test.ts +258 -0
- package/packages/core/src/__tests__/redis-cache.test.ts +307 -0
- package/packages/core/src/__tests__/rust-extractor.test.ts +252 -0
- package/packages/core/src/__tests__/streaming.test.ts +251 -0
- package/packages/core/src/additional-extractors.ts +333 -0
- package/packages/core/src/cache/cache-interface.ts +179 -0
- package/packages/core/src/cache/index.ts +210 -0
- package/packages/core/src/cache/redis-cache.ts +291 -0
- package/packages/core/src/cache/upstash-cache.ts +379 -0
- package/packages/core/src/cache.ts +251 -0
- package/packages/core/src/cli.ts +822 -0
- package/packages/core/src/code-extractor.ts +696 -0
- package/packages/core/src/docker-generator.ts +470 -0
- package/packages/core/src/edge-compatible.ts +491 -0
- package/packages/core/src/extractors/go-extractor.ts +791 -0
- package/packages/core/src/extractors/index.ts +9 -0
- package/packages/core/src/extractors/java-extractor.ts +937 -0
- package/packages/core/src/extractors/rust-extractor.ts +744 -0
- package/packages/core/src/github-client.ts +319 -0
- package/packages/core/src/go-generator.ts +356 -0
- package/packages/core/src/graphql-extractor.ts +358 -0
- package/packages/core/src/index.ts +797 -0
- package/packages/core/src/langchain-exporter.ts +617 -0
- package/packages/core/src/language-parsers.ts +1114 -0
- package/packages/core/src/mcp-introspector.ts +279 -0
- package/packages/core/src/monorepo-detector.ts +378 -0
- package/packages/core/src/plugins/index.ts +370 -0
- package/packages/core/src/plugins/registry.ts +404 -0
- package/packages/core/src/plugins/types.ts +215 -0
- package/packages/core/src/providers/base-provider.ts +246 -0
- package/packages/core/src/providers/bitbucket-client.ts +464 -0
- package/packages/core/src/providers/gitlab-client.ts +388 -0
- package/packages/core/src/providers/index.ts +176 -0
- package/packages/core/src/python-generator.ts +260 -0
- package/packages/core/src/queue/index.ts +100 -0
- package/packages/core/src/queue/memory-queue.ts +445 -0
- package/packages/core/src/queue/redis-queue.ts +578 -0
- package/packages/core/src/queue/types.ts +251 -0
- package/packages/core/src/readme-extractor.ts +409 -0
- package/packages/core/src/schema-generator.ts +638 -0
- package/packages/core/src/streaming.ts +999 -0
- package/packages/core/src/types.ts +289 -0
- package/packages/core/tsconfig.json +9 -0
- package/packages/core/tsup.config.ts +25 -0
- package/packages/mcp-server/README.md +297 -0
- package/packages/mcp-server/package.json +55 -0
- package/packages/mcp-server/src/__tests__/mcp-server.test.ts +177 -0
- package/packages/mcp-server/src/__tests__/tools.test.ts +217 -0
- package/packages/mcp-server/src/index.ts +1206 -0
- package/packages/mcp-server/src/prompts/index.ts +601 -0
- package/packages/mcp-server/src/tools/export-docker.ts +362 -0
- package/packages/mcp-server/src/tools/generate-openapi.ts +162 -0
- package/packages/mcp-server/src/tools/monitor-mcp-server.ts +448 -0
- package/packages/mcp-server/src/tools/stream-convert.ts +398 -0
- package/packages/mcp-server/src/tools/test-mcp-tool.ts +531 -0
- package/packages/mcp-server/tsconfig.json +12 -0
- package/packages/mcp-server/tsup.config.ts +14 -0
- package/packages/openapi-parser/package-lock.json +3028 -0
- package/packages/openapi-parser/package.json +41 -0
- package/packages/openapi-parser/src/analyzer.ts +700 -0
- package/packages/openapi-parser/src/asyncapi-parser.ts +475 -0
- package/packages/openapi-parser/src/cli.ts +302 -0
- package/packages/openapi-parser/src/generator.ts +570 -0
- package/packages/openapi-parser/src/generators/express-analyzer.ts +649 -0
- package/packages/openapi-parser/src/generators/fastapi-analyzer.ts +960 -0
- package/packages/openapi-parser/src/generators/index.ts +200 -0
- package/packages/openapi-parser/src/generators/nextjs-analyzer.ts +768 -0
- package/packages/openapi-parser/src/generators/openapi-builder.ts +527 -0
- package/packages/openapi-parser/src/generators/types.ts +298 -0
- package/packages/openapi-parser/src/graphql-parser.ts +462 -0
- package/packages/openapi-parser/src/grpc-parser.ts +649 -0
- package/packages/openapi-parser/src/har-parser.ts +723 -0
- package/packages/openapi-parser/src/index.ts +635 -0
- package/packages/openapi-parser/src/insomnia-parser.ts +614 -0
- package/packages/openapi-parser/src/parser.ts +231 -0
- package/packages/openapi-parser/src/postman-parser.ts +611 -0
- package/packages/openapi-parser/src/ref-resolver.ts +313 -0
- package/packages/openapi-parser/src/transformer.ts +459 -0
- package/packages/openapi-parser/tests/generators/express.test.ts +209 -0
- package/packages/openapi-parser/tests/generators/fastapi.test.ts +236 -0
- package/packages/openapi-parser/tests/generators/nextjs.test.ts +273 -0
- package/packages/openapi-parser/tests/parsers.test.ts +847 -0
- package/packages/openapi-parser/tsconfig.json +9 -0
- package/packages/openapi-parser/tsup.config.ts +11 -0
- package/packages/registry/package.json +59 -0
- package/packages/registry/src/cli.ts +456 -0
- package/packages/registry/src/index.ts +44 -0
- package/packages/registry/src/popular/github.json +47 -0
- package/packages/registry/src/popular/index.ts +55 -0
- package/packages/registry/src/popular/linear.json +42 -0
- package/packages/registry/src/popular/notion.json +42 -0
- package/packages/registry/src/popular/openai.json +40 -0
- package/packages/registry/src/popular/resend.json +38 -0
- package/packages/registry/src/popular/slack.json +42 -0
- package/packages/registry/src/popular/stripe.json +163 -0
- package/packages/registry/src/popular/supabase.json +42 -0
- package/packages/registry/src/popular/twilio.json +40 -0
- package/packages/registry/src/popular/vercel.json +40 -0
- package/packages/registry/src/registry.ts +492 -0
- package/packages/registry/src/storage.ts +334 -0
- package/packages/registry/src/types.ts +275 -0
- package/packages/registry/src/updater.ts +208 -0
- package/packages/registry/tsconfig.json +10 -0
- package/packages/registry/tsup.config.ts +11 -0
- package/pnpm-workspace.yaml +3 -0
- package/scripts/build-docs.sh +16 -0
- package/server.json +9 -0
- package/templates/Dockerfile.python.template +60 -0
- package/templates/Dockerfile.typescript.template +60 -0
- package/templates/docker-compose.template.yml +68 -0
- package/tests/fixtures/express-app/index.js +34 -0
- package/tests/fixtures/express-app/routes/posts.js +43 -0
- package/tests/fixtures/express-app/routes/users.js +58 -0
- package/tests/fixtures/fastapi-app/main.py +125 -0
- package/tests/fixtures/fastapi-app/routes/admin.py +42 -0
- package/tests/fixtures/graphql/simple-schema.graphql +65 -0
- package/tests/fixtures/mocks/github-api-responses.json +63 -0
- package/tests/fixtures/nextjs-app/app/api/posts/route.ts +55 -0
- package/tests/fixtures/nextjs-app/app/api/users/[id]/route.ts +63 -0
- package/tests/fixtures/nextjs-app/app/api/users/route.ts +44 -0
- package/tests/fixtures/nextjs-app/pages/api/health.ts +28 -0
- package/tests/fixtures/openapi/petstore.yaml +179 -0
- package/tests/integration/langchain-export.test.ts +405 -0
- package/tests/integration/openapi-conversion.test.ts +221 -0
- package/tsconfig.json +18 -0
- package/vitest.config.ts +32 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "twilio-mcp",
|
|
3
|
+
"name": "Twilio",
|
|
4
|
+
"description": "Twilio API - send SMS, make calls, and manage communication services",
|
|
5
|
+
"sourceRepo": "twilio/twilio-node",
|
|
6
|
+
"sourceUrl": "https://github.com/twilio/twilio-node",
|
|
7
|
+
"version": "1.0.0",
|
|
8
|
+
"sourceVersion": "v5.0.0",
|
|
9
|
+
"toolCount": 8,
|
|
10
|
+
"tools": [
|
|
11
|
+
{ "name": "send_sms", "description": "Send an SMS message", "source": "openapi", "paramCount": 4, "requiresAuth": true },
|
|
12
|
+
{ "name": "list_messages", "description": "List sent/received messages", "source": "openapi", "paramCount": 4, "requiresAuth": true },
|
|
13
|
+
{ "name": "get_message", "description": "Get a message by SID", "source": "openapi", "paramCount": 1, "requiresAuth": true },
|
|
14
|
+
{ "name": "make_call", "description": "Initiate a phone call", "source": "openapi", "paramCount": 4, "requiresAuth": true },
|
|
15
|
+
{ "name": "list_calls", "description": "List call records", "source": "openapi", "paramCount": 4, "requiresAuth": true },
|
|
16
|
+
{ "name": "list_phone_numbers", "description": "List available phone numbers", "source": "openapi", "paramCount": 3, "requiresAuth": true },
|
|
17
|
+
{ "name": "lookup_phone_number", "description": "Lookup phone number details", "source": "openapi", "paramCount": 2, "requiresAuth": true },
|
|
18
|
+
{ "name": "send_whatsapp", "description": "Send a WhatsApp message", "source": "openapi", "paramCount": 3, "requiresAuth": true }
|
|
19
|
+
],
|
|
20
|
+
"categories": ["communication", "sms", "api"],
|
|
21
|
+
"tags": ["twilio", "sms", "voice", "calls", "whatsapp", "messaging"],
|
|
22
|
+
"popularity": 9840,
|
|
23
|
+
"lastUpdated": "2026-01-15T00:00:00.000Z",
|
|
24
|
+
"createdAt": "2025-06-01T00:00:00.000Z",
|
|
25
|
+
"generatedCode": {
|
|
26
|
+
"typescript": "import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\n\nconst TWILIO_ACCOUNT_SID = process.env.TWILIO_ACCOUNT_SID;\nconst TWILIO_AUTH_TOKEN = process.env.TWILIO_AUTH_TOKEN;\n\nif (!TWILIO_ACCOUNT_SID || !TWILIO_AUTH_TOKEN) {\n console.error('Error: TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN environment variables are required');\n process.exit(1);\n}\n\nconst server = new Server({ name: 'twilio-mcp', version: '1.0.0' }, { capabilities: { tools: {} } });\n\nasync function twilioRequest(endpoint: string, method: string = 'GET', body?: Record<string, string>) {\n const auth = Buffer.from(`${TWILIO_ACCOUNT_SID}:${TWILIO_AUTH_TOKEN}`).toString('base64');\n const response = await fetch(`https://api.twilio.com/2010-04-01/Accounts/${TWILIO_ACCOUNT_SID}${endpoint}`, {\n method,\n headers: {\n 'Authorization': `Basic ${auth}`,\n 'Content-Type': 'application/x-www-form-urlencoded',\n },\n body: body ? new URLSearchParams(body).toString() : undefined,\n });\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.message || 'Twilio API error');\n }\n return response.json();\n}\n\nconst tools = [\n { name: 'send_sms', description: 'Send an SMS', inputSchema: { type: 'object', properties: { to: { type: 'string' }, from: { type: 'string' }, body: { type: 'string' }, status_callback: { type: 'string' } }, required: ['to', 'from', 'body'] } },\n { name: 'list_messages', description: 'List messages', inputSchema: { type: 'object', properties: { to: { type: 'string' }, from: { type: 'string' }, date_sent: { type: 'string' }, page_size: { type: 'number' } } } },\n { name: 'get_message', description: 'Get a message', inputSchema: { type: 'object', properties: { message_sid: { type: 'string' } }, required: ['message_sid'] } },\n { name: 'make_call', description: 'Make a call', inputSchema: { type: 'object', properties: { to: { type: 'string' }, from: { type: 'string' }, url: { type: 'string' }, twiml: { type: 'string' } }, required: ['to', 'from'] } },\n { name: 'list_calls', description: 'List calls', inputSchema: { type: 'object', properties: { to: { type: 'string' }, from: { type: 'string' }, status: { type: 'string' }, page_size: { type: 'number' } } } },\n { name: 'list_phone_numbers', description: 'List phone numbers', inputSchema: { type: 'object', properties: { country_code: { type: 'string' }, type: { type: 'string' }, page_size: { type: 'number' } } } },\n { name: 'send_whatsapp', description: 'Send WhatsApp message', inputSchema: { type: 'object', properties: { to: { type: 'string', description: 'WhatsApp number with whatsapp: prefix' }, from: { type: 'string' }, body: { type: 'string' } }, required: ['to', 'from', 'body'] } },\n];\n\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n try {\n let result;\n const a = args as Record<string, string>;\n switch (name) {\n case 'send_sms': result = await twilioRequest('/Messages.json', 'POST', { To: a.to, From: a.from, Body: a.body }); break;\n case 'list_messages': result = await twilioRequest('/Messages.json'); break;\n case 'get_message': result = await twilioRequest(`/Messages/${a.message_sid}.json`); break;\n case 'make_call': result = await twilioRequest('/Calls.json', 'POST', { To: a.to, From: a.from, Url: a.url || '', Twiml: a.twiml || '' }); break;\n case 'list_calls': result = await twilioRequest('/Calls.json'); break;\n case 'list_phone_numbers': result = await twilioRequest('/IncomingPhoneNumbers.json'); break;\n case 'send_whatsapp': result = await twilioRequest('/Messages.json', 'POST', { To: a.to, From: a.from, Body: a.body }); break;\n default: throw new Error(`Unknown tool: ${name}`);\n }\n return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };\n } catch (error) {\n return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true };\n }\n});\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch(console.error);\n"
|
|
27
|
+
},
|
|
28
|
+
"configs": {
|
|
29
|
+
"claude": { "mcpServers": { "twilio": { "command": "npx", "args": ["tsx", "index.ts"], "env": { "TWILIO_ACCOUNT_SID": "${TWILIO_ACCOUNT_SID}", "TWILIO_AUTH_TOKEN": "${TWILIO_AUTH_TOKEN}" } } } },
|
|
30
|
+
"cursor": { "mcpServers": { "twilio": { "command": "npx", "args": ["tsx", "index.ts"], "env": { "TWILIO_ACCOUNT_SID": "${TWILIO_ACCOUNT_SID}", "TWILIO_AUTH_TOKEN": "${TWILIO_AUTH_TOKEN}" } } } },
|
|
31
|
+
"vscode": { "mcpServers": { "twilio": { "command": "npx", "args": ["tsx", "index.ts"], "env": { "TWILIO_ACCOUNT_SID": "${TWILIO_ACCOUNT_SID}", "TWILIO_AUTH_TOKEN": "${TWILIO_AUTH_TOKEN}" } } } }
|
|
32
|
+
},
|
|
33
|
+
"quality": { "overall": 85, "schemaCompleteness": 86, "documentation": 84, "examples": 82, "authHandling": 88, "parameterTypes": 85 },
|
|
34
|
+
"auth": [{ "type": "http", "scheme": "basic", "envVar": "TWILIO_ACCOUNT_SID", "instructions": "Get your credentials from https://console.twilio.com" }],
|
|
35
|
+
"docsUrl": "https://www.twilio.com/docs",
|
|
36
|
+
"apiDocsUrl": "https://www.twilio.com/docs/api",
|
|
37
|
+
"iconUrl": "https://www.twilio.com/favicon.ico",
|
|
38
|
+
"verified": true,
|
|
39
|
+
"author": "github-to-mcp"
|
|
40
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "vercel-mcp",
|
|
3
|
+
"name": "Vercel",
|
|
4
|
+
"description": "Vercel API - manage deployments, domains, projects, and serverless functions",
|
|
5
|
+
"sourceRepo": "vercel/vercel",
|
|
6
|
+
"sourceUrl": "https://github.com/vercel/vercel",
|
|
7
|
+
"version": "1.0.0",
|
|
8
|
+
"sourceVersion": "v33.0.0",
|
|
9
|
+
"toolCount": 8,
|
|
10
|
+
"tools": [
|
|
11
|
+
{ "name": "list_deployments", "description": "List all deployments", "source": "openapi", "paramCount": 4, "requiresAuth": true },
|
|
12
|
+
{ "name": "get_deployment", "description": "Get deployment details", "source": "openapi", "paramCount": 1, "requiresAuth": true },
|
|
13
|
+
{ "name": "create_deployment", "description": "Create a new deployment", "source": "openapi", "paramCount": 4, "requiresAuth": true },
|
|
14
|
+
{ "name": "list_projects", "description": "List all projects", "source": "openapi", "paramCount": 2, "requiresAuth": true },
|
|
15
|
+
{ "name": "get_project", "description": "Get project details", "source": "openapi", "paramCount": 1, "requiresAuth": true },
|
|
16
|
+
{ "name": "list_domains", "description": "List all domains", "source": "openapi", "paramCount": 2, "requiresAuth": true },
|
|
17
|
+
{ "name": "add_domain", "description": "Add a domain to a project", "source": "openapi", "paramCount": 2, "requiresAuth": true },
|
|
18
|
+
{ "name": "get_env_vars", "description": "Get environment variables", "source": "openapi", "paramCount": 1, "requiresAuth": true }
|
|
19
|
+
],
|
|
20
|
+
"categories": ["deployment", "hosting", "api"],
|
|
21
|
+
"tags": ["vercel", "deployment", "serverless", "hosting", "nextjs"],
|
|
22
|
+
"popularity": 8920,
|
|
23
|
+
"lastUpdated": "2026-01-15T00:00:00.000Z",
|
|
24
|
+
"createdAt": "2025-06-01T00:00:00.000Z",
|
|
25
|
+
"generatedCode": {
|
|
26
|
+
"typescript": "import { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';\n\nconst VERCEL_TOKEN = process.env.VERCEL_TOKEN;\nconst VERCEL_BASE_URL = 'https://api.vercel.com';\n\nif (!VERCEL_TOKEN) {\n console.error('Error: VERCEL_TOKEN environment variable is required');\n process.exit(1);\n}\n\nconst server = new Server({ name: 'vercel-mcp', version: '1.0.0' }, { capabilities: { tools: {} } });\n\nasync function vercelRequest(endpoint: string, method: string = 'GET', body?: unknown) {\n const response = await fetch(`${VERCEL_BASE_URL}${endpoint}`, {\n method,\n headers: {\n 'Authorization': `Bearer ${VERCEL_TOKEN}`,\n 'Content-Type': 'application/json',\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n if (!response.ok) {\n const error = await response.json();\n throw new Error(error.error?.message || 'Vercel API error');\n }\n return response.json();\n}\n\nconst tools = [\n { name: 'list_deployments', description: 'List deployments', inputSchema: { type: 'object', properties: { projectId: { type: 'string' }, limit: { type: 'number' }, state: { type: 'string' }, target: { type: 'string' } } } },\n { name: 'get_deployment', description: 'Get deployment', inputSchema: { type: 'object', properties: { deploymentId: { type: 'string' } }, required: ['deploymentId'] } },\n { name: 'list_projects', description: 'List projects', inputSchema: { type: 'object', properties: { limit: { type: 'number' }, search: { type: 'string' } } } },\n { name: 'get_project', description: 'Get project', inputSchema: { type: 'object', properties: { projectId: { type: 'string' } }, required: ['projectId'] } },\n { name: 'list_domains', description: 'List domains', inputSchema: { type: 'object', properties: { projectId: { type: 'string' }, limit: { type: 'number' } } } },\n { name: 'add_domain', description: 'Add domain', inputSchema: { type: 'object', properties: { projectId: { type: 'string' }, domain: { type: 'string' } }, required: ['projectId', 'domain'] } },\n { name: 'get_env_vars', description: 'Get env vars', inputSchema: { type: 'object', properties: { projectId: { type: 'string' } }, required: ['projectId'] } },\n];\n\nserver.setRequestHandler(ListToolsRequestSchema, async () => ({ tools }));\n\nserver.setRequestHandler(CallToolRequestSchema, async (request) => {\n const { name, arguments: args } = request.params;\n try {\n let result;\n const a = args as Record<string, unknown>;\n switch (name) {\n case 'list_deployments': result = await vercelRequest(`/v6/deployments${a.projectId ? `?projectId=${a.projectId}` : ''}`); break;\n case 'get_deployment': result = await vercelRequest(`/v13/deployments/${a.deploymentId}`); break;\n case 'list_projects': result = await vercelRequest('/v9/projects'); break;\n case 'get_project': result = await vercelRequest(`/v9/projects/${a.projectId}`); break;\n case 'list_domains': result = await vercelRequest(`/v5/projects/${a.projectId}/domains`); break;\n case 'add_domain': result = await vercelRequest(`/v10/projects/${a.projectId}/domains`, 'POST', { name: a.domain }); break;\n case 'get_env_vars': result = await vercelRequest(`/v9/projects/${a.projectId}/env`); break;\n default: throw new Error(`Unknown tool: ${name}`);\n }\n return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };\n } catch (error) {\n return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }], isError: true };\n }\n});\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch(console.error);\n"
|
|
27
|
+
},
|
|
28
|
+
"configs": {
|
|
29
|
+
"claude": { "mcpServers": { "vercel": { "command": "npx", "args": ["tsx", "index.ts"], "env": { "VERCEL_TOKEN": "${VERCEL_TOKEN}" } } } },
|
|
30
|
+
"cursor": { "mcpServers": { "vercel": { "command": "npx", "args": ["tsx", "index.ts"], "env": { "VERCEL_TOKEN": "${VERCEL_TOKEN}" } } } },
|
|
31
|
+
"vscode": { "mcpServers": { "vercel": { "command": "npx", "args": ["tsx", "index.ts"], "env": { "VERCEL_TOKEN": "${VERCEL_TOKEN}" } } } }
|
|
32
|
+
},
|
|
33
|
+
"quality": { "overall": 84, "schemaCompleteness": 85, "documentation": 82, "examples": 80, "authHandling": 88, "parameterTypes": 85 },
|
|
34
|
+
"auth": [{ "type": "http", "scheme": "bearer", "envVar": "VERCEL_TOKEN", "instructions": "Create a token at https://vercel.com/account/tokens" }],
|
|
35
|
+
"docsUrl": "https://vercel.com/docs",
|
|
36
|
+
"apiDocsUrl": "https://vercel.com/docs/rest-api",
|
|
37
|
+
"iconUrl": "https://vercel.com/favicon.ico",
|
|
38
|
+
"verified": true,
|
|
39
|
+
"author": "github-to-mcp"
|
|
40
|
+
}
|
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Main MCP Registry class
|
|
3
|
+
* @copyright Copyright (c) 2024-2026 nirholas
|
|
4
|
+
* @license Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import * as fs from 'fs/promises';
|
|
8
|
+
import * as path from 'path';
|
|
9
|
+
import * as os from 'os';
|
|
10
|
+
import type {
|
|
11
|
+
RegistryEntry,
|
|
12
|
+
RegistryEntrySummary,
|
|
13
|
+
ListOptions,
|
|
14
|
+
ListResult,
|
|
15
|
+
InstallOptions,
|
|
16
|
+
InstallResult,
|
|
17
|
+
UpdateInfo,
|
|
18
|
+
StorageAdapter,
|
|
19
|
+
RegistryStats,
|
|
20
|
+
} from './types';
|
|
21
|
+
import { FileStorage } from './storage';
|
|
22
|
+
import { RegistryUpdater } from './updater';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Options for the MCP Registry
|
|
26
|
+
*/
|
|
27
|
+
export interface McpRegistryOptions {
|
|
28
|
+
/** Custom storage adapter */
|
|
29
|
+
storage?: StorageAdapter;
|
|
30
|
+
/** GitHub token for updates */
|
|
31
|
+
githubToken?: string;
|
|
32
|
+
/** Custom data directory */
|
|
33
|
+
dataDir?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* MCP Registry - manage pre-converted MCP servers
|
|
38
|
+
*/
|
|
39
|
+
export class McpRegistry {
|
|
40
|
+
private storage: StorageAdapter;
|
|
41
|
+
private updater: RegistryUpdater;
|
|
42
|
+
private options: McpRegistryOptions;
|
|
43
|
+
|
|
44
|
+
constructor(options: McpRegistryOptions = {}) {
|
|
45
|
+
this.options = options;
|
|
46
|
+
this.storage = options.storage || new FileStorage(options.dataDir);
|
|
47
|
+
this.updater = new RegistryUpdater(this.storage, {
|
|
48
|
+
githubToken: options.githubToken,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* List all available MCP servers
|
|
54
|
+
*/
|
|
55
|
+
async list(options?: ListOptions): Promise<ListResult> {
|
|
56
|
+
return this.storage.list(options);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get a specific registry entry by ID
|
|
61
|
+
*/
|
|
62
|
+
async get(id: string): Promise<RegistryEntry | null> {
|
|
63
|
+
return this.storage.get(id);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Search registry entries
|
|
68
|
+
*/
|
|
69
|
+
async search(query: string): Promise<RegistryEntrySummary[]> {
|
|
70
|
+
return this.storage.search(query);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Get all available categories
|
|
75
|
+
*/
|
|
76
|
+
async getCategories(): Promise<string[]> {
|
|
77
|
+
return this.storage.getCategories();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Install an MCP server to a target IDE/tool
|
|
82
|
+
*/
|
|
83
|
+
async install(id: string, options: InstallOptions): Promise<InstallResult> {
|
|
84
|
+
const entry = await this.storage.get(id);
|
|
85
|
+
|
|
86
|
+
if (!entry) {
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
error: `Registry entry '${id}' not found`,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
switch (options.target) {
|
|
95
|
+
case 'claude':
|
|
96
|
+
return await this.installToClaude(entry, options);
|
|
97
|
+
case 'cursor':
|
|
98
|
+
return await this.installToCursor(entry, options);
|
|
99
|
+
case 'vscode':
|
|
100
|
+
return await this.installToVSCode(entry, options);
|
|
101
|
+
case 'file':
|
|
102
|
+
return await this.installToFile(entry, options);
|
|
103
|
+
default:
|
|
104
|
+
return {
|
|
105
|
+
success: false,
|
|
106
|
+
error: `Unknown target: ${options.target}`,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
return {
|
|
111
|
+
success: false,
|
|
112
|
+
error: error instanceof Error ? error.message : 'Installation failed',
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Install to Claude Desktop
|
|
119
|
+
*/
|
|
120
|
+
private async installToClaude(entry: RegistryEntry, options: InstallOptions): Promise<InstallResult> {
|
|
121
|
+
const configPath = this.getClaudeConfigPath();
|
|
122
|
+
|
|
123
|
+
if (!configPath) {
|
|
124
|
+
return {
|
|
125
|
+
success: false,
|
|
126
|
+
error: 'Could not determine Claude Desktop config path',
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// Read existing config
|
|
131
|
+
let config: { mcpServers?: Record<string, unknown> } = {};
|
|
132
|
+
try {
|
|
133
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
134
|
+
config = JSON.parse(content);
|
|
135
|
+
} catch {
|
|
136
|
+
// Config doesn't exist yet
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Check if already installed
|
|
140
|
+
if (config.mcpServers?.[entry.id] && !options.overwrite) {
|
|
141
|
+
return {
|
|
142
|
+
success: false,
|
|
143
|
+
error: `${entry.name} is already installed. Use --overwrite to replace.`,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Create server directory
|
|
148
|
+
const serverDir = path.join(path.dirname(configPath), 'mcp-servers', entry.id);
|
|
149
|
+
await fs.mkdir(serverDir, { recursive: true });
|
|
150
|
+
|
|
151
|
+
// Write server code
|
|
152
|
+
const language = options.language || 'typescript';
|
|
153
|
+
const code = language === 'python' && entry.generatedCode.python
|
|
154
|
+
? entry.generatedCode.python
|
|
155
|
+
: entry.generatedCode.typescript;
|
|
156
|
+
|
|
157
|
+
const ext = language === 'python' ? 'py' : 'ts';
|
|
158
|
+
const serverFile = path.join(serverDir, `index.${ext}`);
|
|
159
|
+
await fs.writeFile(serverFile, code, 'utf-8');
|
|
160
|
+
|
|
161
|
+
// Update config
|
|
162
|
+
config.mcpServers = config.mcpServers || {};
|
|
163
|
+
config.mcpServers[entry.id] = {
|
|
164
|
+
...entry.configs.claude.mcpServers[Object.keys(entry.configs.claude.mcpServers)[0]],
|
|
165
|
+
...(options.env && { env: { ...entry.configs.claude.mcpServers[Object.keys(entry.configs.claude.mcpServers)[0]]?.env, ...options.env } }),
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// Write updated config
|
|
169
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
170
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
171
|
+
|
|
172
|
+
// Increment popularity
|
|
173
|
+
await this.incrementPopularity(entry.id);
|
|
174
|
+
|
|
175
|
+
return {
|
|
176
|
+
success: true,
|
|
177
|
+
path: serverDir,
|
|
178
|
+
instructions: [
|
|
179
|
+
`Installed ${entry.name} MCP server to ${serverDir}`,
|
|
180
|
+
'Restart Claude Desktop to activate the new server',
|
|
181
|
+
entry.auth.length > 0
|
|
182
|
+
? `Set environment variable: ${entry.auth[0].envVar || 'API_KEY'}`
|
|
183
|
+
: '',
|
|
184
|
+
].filter(Boolean),
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Install to Cursor
|
|
190
|
+
*/
|
|
191
|
+
private async installToCursor(entry: RegistryEntry, options: InstallOptions): Promise<InstallResult> {
|
|
192
|
+
const configPath = this.getCursorConfigPath();
|
|
193
|
+
|
|
194
|
+
if (!configPath) {
|
|
195
|
+
return {
|
|
196
|
+
success: false,
|
|
197
|
+
error: 'Could not determine Cursor config path',
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Similar to Claude installation
|
|
202
|
+
let config: { mcpServers?: Record<string, unknown> } = {};
|
|
203
|
+
try {
|
|
204
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
205
|
+
config = JSON.parse(content);
|
|
206
|
+
} catch {
|
|
207
|
+
// Config doesn't exist yet
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (config.mcpServers?.[entry.id] && !options.overwrite) {
|
|
211
|
+
return {
|
|
212
|
+
success: false,
|
|
213
|
+
error: `${entry.name} is already installed. Use --overwrite to replace.`,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const serverDir = path.join(path.dirname(configPath), 'mcp-servers', entry.id);
|
|
218
|
+
await fs.mkdir(serverDir, { recursive: true });
|
|
219
|
+
|
|
220
|
+
const language = options.language || 'typescript';
|
|
221
|
+
const code = language === 'python' && entry.generatedCode.python
|
|
222
|
+
? entry.generatedCode.python
|
|
223
|
+
: entry.generatedCode.typescript;
|
|
224
|
+
|
|
225
|
+
const ext = language === 'python' ? 'py' : 'ts';
|
|
226
|
+
const serverFile = path.join(serverDir, `index.${ext}`);
|
|
227
|
+
await fs.writeFile(serverFile, code, 'utf-8');
|
|
228
|
+
|
|
229
|
+
config.mcpServers = config.mcpServers || {};
|
|
230
|
+
config.mcpServers[entry.id] = {
|
|
231
|
+
...entry.configs.cursor.mcpServers[Object.keys(entry.configs.cursor.mcpServers)[0]],
|
|
232
|
+
...(options.env && { env: { ...entry.configs.cursor.mcpServers[Object.keys(entry.configs.cursor.mcpServers)[0]]?.env, ...options.env } }),
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
236
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
237
|
+
|
|
238
|
+
await this.incrementPopularity(entry.id);
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
success: true,
|
|
242
|
+
path: serverDir,
|
|
243
|
+
instructions: [
|
|
244
|
+
`Installed ${entry.name} MCP server to ${serverDir}`,
|
|
245
|
+
'Restart Cursor to activate the new server',
|
|
246
|
+
],
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Install to VS Code
|
|
252
|
+
*/
|
|
253
|
+
private async installToVSCode(entry: RegistryEntry, options: InstallOptions): Promise<InstallResult> {
|
|
254
|
+
// VS Code uses workspace-level .vscode/mcp.json
|
|
255
|
+
const workspaceDir = process.cwd();
|
|
256
|
+
const configPath = path.join(workspaceDir, '.vscode', 'mcp.json');
|
|
257
|
+
|
|
258
|
+
let config: { servers?: Record<string, unknown> } = {};
|
|
259
|
+
try {
|
|
260
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
261
|
+
config = JSON.parse(content);
|
|
262
|
+
} catch {
|
|
263
|
+
// Config doesn't exist yet
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (config.servers?.[entry.id] && !options.overwrite) {
|
|
267
|
+
return {
|
|
268
|
+
success: false,
|
|
269
|
+
error: `${entry.name} is already installed. Use --overwrite to replace.`,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
const serverDir = path.join(workspaceDir, '.mcp-servers', entry.id);
|
|
274
|
+
await fs.mkdir(serverDir, { recursive: true });
|
|
275
|
+
|
|
276
|
+
const language = options.language || 'typescript';
|
|
277
|
+
const code = language === 'python' && entry.generatedCode.python
|
|
278
|
+
? entry.generatedCode.python
|
|
279
|
+
: entry.generatedCode.typescript;
|
|
280
|
+
|
|
281
|
+
const ext = language === 'python' ? 'py' : 'ts';
|
|
282
|
+
const serverFile = path.join(serverDir, `index.${ext}`);
|
|
283
|
+
await fs.writeFile(serverFile, code, 'utf-8');
|
|
284
|
+
|
|
285
|
+
config.servers = config.servers || {};
|
|
286
|
+
config.servers[entry.id] = entry.configs.vscode.mcpServers[Object.keys(entry.configs.vscode.mcpServers)[0]];
|
|
287
|
+
|
|
288
|
+
await fs.mkdir(path.dirname(configPath), { recursive: true });
|
|
289
|
+
await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8');
|
|
290
|
+
|
|
291
|
+
await this.incrementPopularity(entry.id);
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
success: true,
|
|
295
|
+
path: serverDir,
|
|
296
|
+
instructions: [
|
|
297
|
+
`Installed ${entry.name} MCP server to ${serverDir}`,
|
|
298
|
+
'Reload VS Code window to activate',
|
|
299
|
+
],
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Install to a file (for manual setup)
|
|
305
|
+
*/
|
|
306
|
+
private async installToFile(entry: RegistryEntry, options: InstallOptions): Promise<InstallResult> {
|
|
307
|
+
const outputDir = options.outputDir || path.join(process.cwd(), entry.id);
|
|
308
|
+
await fs.mkdir(outputDir, { recursive: true });
|
|
309
|
+
|
|
310
|
+
const language = options.language || 'typescript';
|
|
311
|
+
const code = language === 'python' && entry.generatedCode.python
|
|
312
|
+
? entry.generatedCode.python
|
|
313
|
+
: entry.generatedCode.typescript;
|
|
314
|
+
|
|
315
|
+
const ext = language === 'python' ? 'py' : 'ts';
|
|
316
|
+
const serverFile = path.join(outputDir, `index.${ext}`);
|
|
317
|
+
await fs.writeFile(serverFile, code, 'utf-8');
|
|
318
|
+
|
|
319
|
+
// Write package.json for TypeScript
|
|
320
|
+
if (language === 'typescript') {
|
|
321
|
+
const packageJson = {
|
|
322
|
+
name: entry.id,
|
|
323
|
+
version: '1.0.0',
|
|
324
|
+
description: `MCP server for ${entry.name}`,
|
|
325
|
+
type: 'module',
|
|
326
|
+
main: 'index.ts',
|
|
327
|
+
scripts: {
|
|
328
|
+
start: 'npx tsx index.ts',
|
|
329
|
+
build: 'npx tsc',
|
|
330
|
+
},
|
|
331
|
+
dependencies: {
|
|
332
|
+
'@modelcontextprotocol/sdk': '^1.0.0',
|
|
333
|
+
},
|
|
334
|
+
devDependencies: {
|
|
335
|
+
typescript: '^5.0.0',
|
|
336
|
+
tsx: '^4.0.0',
|
|
337
|
+
},
|
|
338
|
+
};
|
|
339
|
+
await fs.writeFile(
|
|
340
|
+
path.join(outputDir, 'package.json'),
|
|
341
|
+
JSON.stringify(packageJson, null, 2),
|
|
342
|
+
'utf-8'
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Write config examples
|
|
347
|
+
await fs.writeFile(
|
|
348
|
+
path.join(outputDir, 'claude-config.json'),
|
|
349
|
+
JSON.stringify(entry.configs.claude, null, 2),
|
|
350
|
+
'utf-8'
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
await this.incrementPopularity(entry.id);
|
|
354
|
+
|
|
355
|
+
return {
|
|
356
|
+
success: true,
|
|
357
|
+
path: outputDir,
|
|
358
|
+
instructions: [
|
|
359
|
+
`Generated ${entry.name} MCP server at ${outputDir}`,
|
|
360
|
+
language === 'typescript' ? 'Run: npm install && npm start' : `Run: python ${serverFile}`,
|
|
361
|
+
'Copy config from claude-config.json to your IDE config',
|
|
362
|
+
],
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Check for updates
|
|
368
|
+
*/
|
|
369
|
+
async checkUpdates(): Promise<UpdateInfo[]> {
|
|
370
|
+
return this.updater.checkAllForUpdates();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Check if a specific entry has updates
|
|
375
|
+
*/
|
|
376
|
+
async checkUpdate(id: string): Promise<UpdateInfo | null> {
|
|
377
|
+
return this.updater.checkForUpdates(id);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Publish a new entry to the registry
|
|
382
|
+
*/
|
|
383
|
+
async publish(entry: RegistryEntry): Promise<void> {
|
|
384
|
+
// Validate entry
|
|
385
|
+
this.validateEntry(entry);
|
|
386
|
+
|
|
387
|
+
// Set timestamps
|
|
388
|
+
const now = new Date().toISOString();
|
|
389
|
+
entry.createdAt = entry.createdAt || now;
|
|
390
|
+
entry.lastUpdated = now;
|
|
391
|
+
|
|
392
|
+
await this.storage.save(entry);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* Get registry statistics
|
|
397
|
+
*/
|
|
398
|
+
async getStats(): Promise<RegistryStats> {
|
|
399
|
+
const result = await this.storage.list({ limit: 1000 });
|
|
400
|
+
const categories = await this.storage.getCategories();
|
|
401
|
+
|
|
402
|
+
const categoryCount = new Map<string, number>();
|
|
403
|
+
let totalTools = 0;
|
|
404
|
+
let totalDownloads = 0;
|
|
405
|
+
|
|
406
|
+
for (const entry of result.entries) {
|
|
407
|
+
totalTools += entry.toolCount;
|
|
408
|
+
totalDownloads += entry.popularity;
|
|
409
|
+
for (const cat of entry.categories) {
|
|
410
|
+
categoryCount.set(cat, (categoryCount.get(cat) || 0) + 1);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
const sorted = [...result.entries].sort((a, b) => b.popularity - a.popularity);
|
|
415
|
+
const recent = [...result.entries].sort(
|
|
416
|
+
(a, b) => new Date(b.lastUpdated).getTime() - new Date(a.lastUpdated).getTime()
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
return {
|
|
420
|
+
totalEntries: result.total,
|
|
421
|
+
totalTools,
|
|
422
|
+
totalDownloads,
|
|
423
|
+
categories: categories.map(name => ({
|
|
424
|
+
name,
|
|
425
|
+
count: categoryCount.get(name) || 0,
|
|
426
|
+
})),
|
|
427
|
+
topEntries: sorted.slice(0, 10),
|
|
428
|
+
recentlyUpdated: recent.slice(0, 10),
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Validate a registry entry
|
|
434
|
+
*/
|
|
435
|
+
private validateEntry(entry: RegistryEntry): void {
|
|
436
|
+
if (!entry.id || !/^[a-z0-9-]+$/.test(entry.id)) {
|
|
437
|
+
throw new Error('Invalid entry ID (must be lowercase alphanumeric with dashes)');
|
|
438
|
+
}
|
|
439
|
+
if (!entry.name) throw new Error('Entry name is required');
|
|
440
|
+
if (!entry.sourceRepo) throw new Error('Source repo is required');
|
|
441
|
+
if (!entry.generatedCode?.typescript) throw new Error('TypeScript code is required');
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* Increment popularity counter
|
|
446
|
+
*/
|
|
447
|
+
private async incrementPopularity(id: string): Promise<void> {
|
|
448
|
+
const entry = await this.storage.get(id);
|
|
449
|
+
if (entry) {
|
|
450
|
+
entry.popularity += 1;
|
|
451
|
+
await this.storage.save(entry);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Get Claude Desktop config path
|
|
457
|
+
*/
|
|
458
|
+
private getClaudeConfigPath(): string | null {
|
|
459
|
+
const platform = os.platform();
|
|
460
|
+
const home = os.homedir();
|
|
461
|
+
|
|
462
|
+
switch (platform) {
|
|
463
|
+
case 'darwin':
|
|
464
|
+
return path.join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
465
|
+
case 'win32':
|
|
466
|
+
return path.join(home, 'AppData', 'Roaming', 'Claude', 'claude_desktop_config.json');
|
|
467
|
+
case 'linux':
|
|
468
|
+
return path.join(home, '.config', 'claude', 'claude_desktop_config.json');
|
|
469
|
+
default:
|
|
470
|
+
return null;
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* Get Cursor config path
|
|
476
|
+
*/
|
|
477
|
+
private getCursorConfigPath(): string | null {
|
|
478
|
+
const platform = os.platform();
|
|
479
|
+
const home = os.homedir();
|
|
480
|
+
|
|
481
|
+
switch (platform) {
|
|
482
|
+
case 'darwin':
|
|
483
|
+
return path.join(home, 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage', 'mcp.json');
|
|
484
|
+
case 'win32':
|
|
485
|
+
return path.join(home, 'AppData', 'Roaming', 'Cursor', 'User', 'globalStorage', 'mcp.json');
|
|
486
|
+
case 'linux':
|
|
487
|
+
return path.join(home, '.config', 'Cursor', 'User', 'globalStorage', 'mcp.json');
|
|
488
|
+
default:
|
|
489
|
+
return null;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
}
|