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,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert Page - GitHub to MCP Conversion Interface
|
|
3
|
+
* @copyright 2024-2026 nirholas
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use client';
|
|
8
|
+
|
|
9
|
+
import { useEffect, Suspense, useState } from 'react';
|
|
10
|
+
import { useSearchParams, useRouter } from 'next/navigation';
|
|
11
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
12
|
+
import { ArrowLeft, Github, Zap } from 'lucide-react';
|
|
13
|
+
import Link from 'next/link';
|
|
14
|
+
|
|
15
|
+
import Header from '@/components/Header';
|
|
16
|
+
import Footer from '@/components/Footer';
|
|
17
|
+
import ParticleBackground from '@/components/ParticleBackground';
|
|
18
|
+
import GithubUrlInput from '@/components/GithubUrlInput';
|
|
19
|
+
import ConversionResult from '@/components/convert/ConversionResult';
|
|
20
|
+
import LoadingSteps from '@/components/convert/LoadingSteps';
|
|
21
|
+
import GenerationProgress from '@/components/GenerationProgress';
|
|
22
|
+
import { useConversion } from '@/hooks/use-conversion';
|
|
23
|
+
import { useStreamingConversion } from '@/hooks/use-streaming-conversion';
|
|
24
|
+
import { useGenerationProgress } from '@/hooks/use-generation-progress';
|
|
25
|
+
import type { GitRef } from '@/components/BranchSelector';
|
|
26
|
+
|
|
27
|
+
function ConvertContent() {
|
|
28
|
+
const searchParams = useSearchParams();
|
|
29
|
+
const router = useRouter();
|
|
30
|
+
const urlParam = searchParams.get('url');
|
|
31
|
+
const [useStreaming, setUseStreaming] = useState(true);
|
|
32
|
+
|
|
33
|
+
// Regular conversion hook (fallback)
|
|
34
|
+
const regularConversion = useConversion();
|
|
35
|
+
|
|
36
|
+
// Streaming conversion hook (enhanced experience)
|
|
37
|
+
const streamingConversion = useStreamingConversion();
|
|
38
|
+
|
|
39
|
+
// Use streaming by default, fallback to regular if needed
|
|
40
|
+
const {
|
|
41
|
+
status,
|
|
42
|
+
result,
|
|
43
|
+
error,
|
|
44
|
+
convert: convertFn,
|
|
45
|
+
reset,
|
|
46
|
+
} = useStreaming ? streamingConversion : regularConversion;
|
|
47
|
+
|
|
48
|
+
// Get history from regular conversion hook (not available in streaming)
|
|
49
|
+
const { history } = regularConversion;
|
|
50
|
+
|
|
51
|
+
// Streaming-specific state
|
|
52
|
+
const { steps, currentStep, progress } = streamingConversion;
|
|
53
|
+
|
|
54
|
+
// Auto-convert if URL is provided in query params
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (urlParam && status === 'idle') {
|
|
57
|
+
convertFn(urlParam);
|
|
58
|
+
}
|
|
59
|
+
}, [urlParam, status, convertFn]);
|
|
60
|
+
|
|
61
|
+
const handleSubmit = (url: string, ref?: GitRef | null) => {
|
|
62
|
+
// Build URL with optional ref parameter
|
|
63
|
+
let convertUrl = url;
|
|
64
|
+
if (ref && !ref.isDefault) {
|
|
65
|
+
// Append ref to URL for the conversion
|
|
66
|
+
const urlObj = new URL(url.startsWith('http') ? url : `https://${url}`);
|
|
67
|
+
// GitHub URL format: /owner/repo/tree/branch for browsing
|
|
68
|
+
// But for API, we'll pass as query param
|
|
69
|
+
convertUrl = `${url}${url.includes('?') ? '&' : '?'}ref=${encodeURIComponent(ref.sha || ref.name)}`;
|
|
70
|
+
}
|
|
71
|
+
router.push(`/convert?url=${encodeURIComponent(url)}${ref && !ref.isDefault ? `&ref=${encodeURIComponent(ref.sha || ref.name)}` : ''}`);
|
|
72
|
+
convertFn(convertUrl);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const handleReset = () => {
|
|
76
|
+
reset();
|
|
77
|
+
router.push('/convert');
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<main id="main-content" className="relative min-h-screen">
|
|
82
|
+
<ParticleBackground />
|
|
83
|
+
<Header />
|
|
84
|
+
|
|
85
|
+
<div className="container mx-auto px-4 pt-24 pb-16">
|
|
86
|
+
{/* Back link */}
|
|
87
|
+
<motion.div
|
|
88
|
+
initial={{ opacity: 0, x: -20 }}
|
|
89
|
+
animate={{ opacity: 1, x: 0 }}
|
|
90
|
+
className="mb-8"
|
|
91
|
+
>
|
|
92
|
+
<Link
|
|
93
|
+
href="/"
|
|
94
|
+
className="inline-flex items-center gap-2 text-sm text-neutral-400 hover:text-white transition-colors"
|
|
95
|
+
>
|
|
96
|
+
<ArrowLeft className="w-4 h-4" />
|
|
97
|
+
Back to Home
|
|
98
|
+
</Link>
|
|
99
|
+
</motion.div>
|
|
100
|
+
|
|
101
|
+
{/* Page header */}
|
|
102
|
+
<motion.div
|
|
103
|
+
initial={{ opacity: 0, y: 20 }}
|
|
104
|
+
animate={{ opacity: 1, y: 0 }}
|
|
105
|
+
className="text-center mb-12"
|
|
106
|
+
>
|
|
107
|
+
<div className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-white/5 border border-neutral-800 mb-6">
|
|
108
|
+
<Github className="w-4 h-4 text-white" />
|
|
109
|
+
<span className="text-sm font-medium text-neutral-400">
|
|
110
|
+
GitHub to <span className="text-white font-semibold">MCP Server</span>
|
|
111
|
+
</span>
|
|
112
|
+
{useStreaming && (
|
|
113
|
+
<span className="ml-2 px-2 py-0.5 text-xs bg-green-500/20 text-green-400 rounded-full flex items-center gap-1">
|
|
114
|
+
<Zap className="w-3 h-3" />
|
|
115
|
+
Live
|
|
116
|
+
</span>
|
|
117
|
+
)}
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<h1 className="text-4xl md:text-5xl font-bold text-white mb-4">
|
|
121
|
+
Convert Repository
|
|
122
|
+
</h1>
|
|
123
|
+
<p className="text-lg text-neutral-400 max-w-2xl mx-auto">
|
|
124
|
+
Enter a GitHub repository URL to generate a ready-to-use MCP server
|
|
125
|
+
</p>
|
|
126
|
+
</motion.div>
|
|
127
|
+
|
|
128
|
+
{/* Input section - always visible */}
|
|
129
|
+
<motion.div
|
|
130
|
+
initial={{ opacity: 0, y: 20 }}
|
|
131
|
+
animate={{ opacity: 1, y: 0 }}
|
|
132
|
+
transition={{ delay: 0.1 }}
|
|
133
|
+
className="max-w-2xl mx-auto mb-12"
|
|
134
|
+
>
|
|
135
|
+
<GithubUrlInput
|
|
136
|
+
onSubmit={handleSubmit}
|
|
137
|
+
disabled={status === 'loading'}
|
|
138
|
+
initialValue={urlParam || ''}
|
|
139
|
+
showBranchSelector={true}
|
|
140
|
+
/>
|
|
141
|
+
</motion.div>
|
|
142
|
+
|
|
143
|
+
{/* Content area */}
|
|
144
|
+
<AnimatePresence mode="wait">
|
|
145
|
+
{status === 'loading' && (
|
|
146
|
+
<motion.div
|
|
147
|
+
key="loading"
|
|
148
|
+
initial={{ opacity: 0, y: 20 }}
|
|
149
|
+
animate={{ opacity: 1, y: 0 }}
|
|
150
|
+
exit={{ opacity: 0, y: -20 }}
|
|
151
|
+
>
|
|
152
|
+
<LoadingSteps
|
|
153
|
+
steps={useStreaming ? steps : undefined}
|
|
154
|
+
currentStep={useStreaming ? currentStep : undefined}
|
|
155
|
+
progress={useStreaming ? progress : undefined}
|
|
156
|
+
isStreaming={useStreaming}
|
|
157
|
+
/>
|
|
158
|
+
</motion.div>
|
|
159
|
+
)}
|
|
160
|
+
|
|
161
|
+
{status === 'error' && error && (
|
|
162
|
+
<motion.div
|
|
163
|
+
key="error"
|
|
164
|
+
initial={{ opacity: 0, y: 20 }}
|
|
165
|
+
animate={{ opacity: 1, y: 0 }}
|
|
166
|
+
exit={{ opacity: 0, y: -20 }}
|
|
167
|
+
className="max-w-2xl mx-auto"
|
|
168
|
+
>
|
|
169
|
+
<div className="rounded-xl border border-red-500/30 bg-red-500/10 p-6">
|
|
170
|
+
<div className="flex items-start gap-4">
|
|
171
|
+
<div className="w-10 h-10 rounded-lg bg-red-500/20 flex items-center justify-center flex-shrink-0">
|
|
172
|
+
<span className="text-red-400 text-xl">!</span>
|
|
173
|
+
</div>
|
|
174
|
+
<div className="flex-1">
|
|
175
|
+
<h3 className="text-lg font-semibold text-red-400 mb-2">
|
|
176
|
+
Conversion Failed
|
|
177
|
+
</h3>
|
|
178
|
+
<p className="text-neutral-300 mb-4">{error.error}</p>
|
|
179
|
+
{error.details && (
|
|
180
|
+
<p className="text-sm text-neutral-500 mb-4">{error.details}</p>
|
|
181
|
+
)}
|
|
182
|
+
{error.retryAfter && (
|
|
183
|
+
<p className="text-sm text-neutral-500">
|
|
184
|
+
Please try again in {error.retryAfter} seconds
|
|
185
|
+
</p>
|
|
186
|
+
)}
|
|
187
|
+
<button
|
|
188
|
+
onClick={handleReset}
|
|
189
|
+
className="mt-4 px-4 py-2 bg-white/10 border border-neutral-700 rounded-lg text-white hover:bg-white/20 transition-colors"
|
|
190
|
+
>
|
|
191
|
+
Try Again
|
|
192
|
+
</button>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
</motion.div>
|
|
197
|
+
)}
|
|
198
|
+
|
|
199
|
+
{status === 'success' && result && (
|
|
200
|
+
<motion.div
|
|
201
|
+
key="success"
|
|
202
|
+
initial={{ opacity: 0, y: 20 }}
|
|
203
|
+
animate={{ opacity: 1, y: 0 }}
|
|
204
|
+
exit={{ opacity: 0, y: -20 }}
|
|
205
|
+
>
|
|
206
|
+
<ConversionResult result={result} onReset={handleReset} />
|
|
207
|
+
</motion.div>
|
|
208
|
+
)}
|
|
209
|
+
|
|
210
|
+
{status === 'idle' && !urlParam && (
|
|
211
|
+
<motion.div
|
|
212
|
+
key="idle"
|
|
213
|
+
initial={{ opacity: 0, y: 20 }}
|
|
214
|
+
animate={{ opacity: 1, y: 0 }}
|
|
215
|
+
exit={{ opacity: 0, y: -20 }}
|
|
216
|
+
>
|
|
217
|
+
{/* Recent history */}
|
|
218
|
+
{history.length > 0 && (
|
|
219
|
+
<div className="max-w-3xl mx-auto">
|
|
220
|
+
<h2 className="text-xl font-semibold text-white mb-6">Recent Conversions</h2>
|
|
221
|
+
<div className="grid gap-4">
|
|
222
|
+
{history.slice(0, 5).map((item) => (
|
|
223
|
+
<button
|
|
224
|
+
key={item.id}
|
|
225
|
+
onClick={() => handleSubmit(item.url)}
|
|
226
|
+
className="group flex items-center justify-between p-4 rounded-xl border border-neutral-800 bg-neutral-900/50 hover:border-neutral-600 hover:bg-neutral-900/80 transition-all text-left"
|
|
227
|
+
>
|
|
228
|
+
<div className="flex items-center gap-4">
|
|
229
|
+
<div className="w-10 h-10 rounded-lg bg-white/5 border border-neutral-800 flex items-center justify-center">
|
|
230
|
+
<Github className="w-5 h-5 text-white" />
|
|
231
|
+
</div>
|
|
232
|
+
<div>
|
|
233
|
+
<div className="font-medium text-white group-hover:text-white transition-colors">
|
|
234
|
+
{item.name}
|
|
235
|
+
</div>
|
|
236
|
+
<div className="text-sm text-neutral-500">
|
|
237
|
+
{item.toolCount} tools • {item.classification}
|
|
238
|
+
</div>
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
<div className="text-xs text-neutral-600">
|
|
242
|
+
{new Date(item.convertedAt).toLocaleDateString()}
|
|
243
|
+
</div>
|
|
244
|
+
</button>
|
|
245
|
+
))}
|
|
246
|
+
</div>
|
|
247
|
+
</div>
|
|
248
|
+
)}
|
|
249
|
+
</motion.div>
|
|
250
|
+
)}
|
|
251
|
+
</AnimatePresence>
|
|
252
|
+
</div>
|
|
253
|
+
|
|
254
|
+
<Footer />
|
|
255
|
+
</main>
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export default function ConvertPage() {
|
|
260
|
+
return (
|
|
261
|
+
<Suspense fallback={
|
|
262
|
+
<div className="min-h-screen bg-black flex items-center justify-center">
|
|
263
|
+
<div className="animate-spin w-8 h-8 border-2 border-white border-t-transparent rounded-full" />
|
|
264
|
+
</div>
|
|
265
|
+
}>
|
|
266
|
+
<ConvertContent />
|
|
267
|
+
</Suspense>
|
|
268
|
+
);
|
|
269
|
+
}
|
|
@@ -0,0 +1,380 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dashboard Page - Manage deployed MCP servers
|
|
3
|
+
* @copyright 2024-2026 nirholas
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use client';
|
|
8
|
+
|
|
9
|
+
import { useState, useEffect, useCallback, useMemo } from 'react';
|
|
10
|
+
import { motion, AnimatePresence } from 'framer-motion';
|
|
11
|
+
import {
|
|
12
|
+
Cloud,
|
|
13
|
+
Server,
|
|
14
|
+
Activity,
|
|
15
|
+
BarChart3,
|
|
16
|
+
Clock,
|
|
17
|
+
Zap,
|
|
18
|
+
Settings,
|
|
19
|
+
Trash2,
|
|
20
|
+
Copy,
|
|
21
|
+
Check,
|
|
22
|
+
ExternalLink,
|
|
23
|
+
AlertCircle,
|
|
24
|
+
RefreshCw,
|
|
25
|
+
Play,
|
|
26
|
+
Pause,
|
|
27
|
+
ChevronRight,
|
|
28
|
+
TrendingUp,
|
|
29
|
+
Globe,
|
|
30
|
+
Shield,
|
|
31
|
+
} from 'lucide-react';
|
|
32
|
+
import Header from '@/components/Header';
|
|
33
|
+
import Footer from '@/components/Footer';
|
|
34
|
+
import ParticleBackground from '@/components/ParticleBackground';
|
|
35
|
+
import { Button } from '@/components/ui/button';
|
|
36
|
+
import { copyToClipboard } from '@/lib/utils';
|
|
37
|
+
import type { DeployedServer } from '@/types/deploy';
|
|
38
|
+
import Link from 'next/link';
|
|
39
|
+
|
|
40
|
+
export default function DashboardPage() {
|
|
41
|
+
const [servers, setServers] = useState<DeployedServer[]>([]);
|
|
42
|
+
const [selectedServer, setSelectedServer] = useState<DeployedServer | null>(null);
|
|
43
|
+
const [loading, setLoading] = useState(true);
|
|
44
|
+
const [copied, setCopied] = useState<string | null>(null);
|
|
45
|
+
|
|
46
|
+
// Load servers from localStorage
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
const stored = localStorage.getItem('deployed-servers');
|
|
49
|
+
if (stored) {
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(stored);
|
|
52
|
+
setServers(parsed);
|
|
53
|
+
if (parsed.length > 0) {
|
|
54
|
+
setSelectedServer(parsed[0]);
|
|
55
|
+
}
|
|
56
|
+
} catch (e) {
|
|
57
|
+
console.error('Failed to parse stored servers:', e);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
setLoading(false);
|
|
61
|
+
}, []);
|
|
62
|
+
|
|
63
|
+
const handleCopy = useCallback(async (text: string, id: string) => {
|
|
64
|
+
const success = await copyToClipboard(text);
|
|
65
|
+
if (success) {
|
|
66
|
+
setCopied(id);
|
|
67
|
+
setTimeout(() => setCopied(null), 2000);
|
|
68
|
+
}
|
|
69
|
+
}, []);
|
|
70
|
+
|
|
71
|
+
const handleDelete = useCallback((serverId: string) => {
|
|
72
|
+
if (!confirm('Are you sure you want to delete this server?')) return;
|
|
73
|
+
|
|
74
|
+
const updated = servers.filter(s => s.id !== serverId);
|
|
75
|
+
setServers(updated);
|
|
76
|
+
localStorage.setItem('deployed-servers', JSON.stringify(updated));
|
|
77
|
+
|
|
78
|
+
if (selectedServer?.id === serverId) {
|
|
79
|
+
setSelectedServer(updated[0] || null);
|
|
80
|
+
}
|
|
81
|
+
}, [servers, selectedServer]);
|
|
82
|
+
|
|
83
|
+
const handleToggleStatus = useCallback((serverId: string) => {
|
|
84
|
+
const updated = servers.map(s => {
|
|
85
|
+
if (s.id === serverId) {
|
|
86
|
+
return { ...s, status: s.status === 'active' ? 'paused' as const : 'active' as const };
|
|
87
|
+
}
|
|
88
|
+
return s;
|
|
89
|
+
});
|
|
90
|
+
setServers(updated);
|
|
91
|
+
localStorage.setItem('deployed-servers', JSON.stringify(updated));
|
|
92
|
+
|
|
93
|
+
if (selectedServer?.id === serverId) {
|
|
94
|
+
setSelectedServer(updated.find(s => s.id === serverId) || null);
|
|
95
|
+
}
|
|
96
|
+
}, [servers, selectedServer]);
|
|
97
|
+
|
|
98
|
+
// Calculate overall stats
|
|
99
|
+
const stats = useMemo(() => {
|
|
100
|
+
return {
|
|
101
|
+
totalServers: servers.length,
|
|
102
|
+
activeServers: servers.filter(s => s.status === 'active').length,
|
|
103
|
+
totalTools: servers.reduce((sum, s) => sum + s.tools.length, 0),
|
|
104
|
+
totalCalls: servers.reduce((sum, s) => sum + s.usage.totalCalls, 0),
|
|
105
|
+
};
|
|
106
|
+
}, [servers]);
|
|
107
|
+
|
|
108
|
+
if (loading) {
|
|
109
|
+
return (
|
|
110
|
+
<main className="relative min-h-screen">
|
|
111
|
+
<ParticleBackground />
|
|
112
|
+
<Header />
|
|
113
|
+
<div className="container mx-auto px-4 pt-24 pb-16 flex items-center justify-center min-h-[60vh]">
|
|
114
|
+
<div className="flex flex-col items-center gap-4">
|
|
115
|
+
<RefreshCw className="w-8 h-8 text-white animate-spin" />
|
|
116
|
+
<div className="text-neutral-400">Loading dashboard...</div>
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
<Footer />
|
|
120
|
+
</main>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<main className="relative min-h-screen">
|
|
126
|
+
<ParticleBackground />
|
|
127
|
+
<Header />
|
|
128
|
+
|
|
129
|
+
<div className="container mx-auto px-4 pt-24 pb-16">
|
|
130
|
+
{/* Page Header */}
|
|
131
|
+
<motion.div
|
|
132
|
+
initial={{ opacity: 0, y: 20 }}
|
|
133
|
+
animate={{ opacity: 1, y: 0 }}
|
|
134
|
+
className="mb-8"
|
|
135
|
+
>
|
|
136
|
+
<div className="flex items-center gap-3 mb-2">
|
|
137
|
+
<div className="w-10 h-10 rounded-xl bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center">
|
|
138
|
+
<Cloud className="w-5 h-5 text-white" />
|
|
139
|
+
</div>
|
|
140
|
+
<div>
|
|
141
|
+
<h1 className="text-3xl font-bold text-white">Dashboard</h1>
|
|
142
|
+
<p className="text-neutral-400">Manage your deployed MCP servers</p>
|
|
143
|
+
</div>
|
|
144
|
+
</div>
|
|
145
|
+
</motion.div>
|
|
146
|
+
|
|
147
|
+
{/* Stats Grid */}
|
|
148
|
+
<motion.div
|
|
149
|
+
initial={{ opacity: 0, y: 20 }}
|
|
150
|
+
animate={{ opacity: 1, y: 0 }}
|
|
151
|
+
transition={{ delay: 0.1 }}
|
|
152
|
+
className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-8"
|
|
153
|
+
>
|
|
154
|
+
{[
|
|
155
|
+
{ label: 'Deployed Servers', value: stats.totalServers, icon: Server, color: 'blue' },
|
|
156
|
+
{ label: 'Active', value: stats.activeServers, icon: Zap, color: 'green' },
|
|
157
|
+
{ label: 'Total Tools', value: stats.totalTools, icon: Settings, color: 'purple' },
|
|
158
|
+
{ label: 'API Calls', value: stats.totalCalls.toLocaleString(), icon: Activity, color: 'orange' },
|
|
159
|
+
].map(({ label, value, icon: Icon, color }) => (
|
|
160
|
+
<div
|
|
161
|
+
key={label}
|
|
162
|
+
className="p-4 rounded-xl border border-neutral-800 bg-neutral-900/50 backdrop-blur-sm"
|
|
163
|
+
>
|
|
164
|
+
<div className="flex items-center gap-2 mb-2">
|
|
165
|
+
<Icon className={`w-4 h-4 text-${color}-400`} />
|
|
166
|
+
<span className="text-xs text-neutral-500">{label}</span>
|
|
167
|
+
</div>
|
|
168
|
+
<div className="text-2xl font-bold text-white">{value}</div>
|
|
169
|
+
</div>
|
|
170
|
+
))}
|
|
171
|
+
</motion.div>
|
|
172
|
+
|
|
173
|
+
{servers.length === 0 ? (
|
|
174
|
+
/* Empty State */
|
|
175
|
+
<motion.div
|
|
176
|
+
initial={{ opacity: 0, y: 20 }}
|
|
177
|
+
animate={{ opacity: 1, y: 0 }}
|
|
178
|
+
transition={{ delay: 0.2 }}
|
|
179
|
+
className="text-center py-16"
|
|
180
|
+
>
|
|
181
|
+
<div className="w-20 h-20 mx-auto rounded-full bg-neutral-800 flex items-center justify-center mb-6">
|
|
182
|
+
<Cloud className="w-10 h-10 text-neutral-600" />
|
|
183
|
+
</div>
|
|
184
|
+
<h2 className="text-xl font-bold text-white mb-2">No deployed servers yet</h2>
|
|
185
|
+
<p className="text-neutral-400 mb-6 max-w-md mx-auto">
|
|
186
|
+
Convert a GitHub repository and deploy it to the cloud to see it here.
|
|
187
|
+
</p>
|
|
188
|
+
<Link href="/convert">
|
|
189
|
+
<Button className="bg-white text-black hover:bg-neutral-200">
|
|
190
|
+
Convert a Repository
|
|
191
|
+
<ChevronRight className="w-4 h-4 ml-1" />
|
|
192
|
+
</Button>
|
|
193
|
+
</Link>
|
|
194
|
+
</motion.div>
|
|
195
|
+
) : (
|
|
196
|
+
/* Server List & Details */
|
|
197
|
+
<div className="grid md:grid-cols-3 gap-6">
|
|
198
|
+
{/* Server List */}
|
|
199
|
+
<motion.div
|
|
200
|
+
initial={{ opacity: 0, x: -20 }}
|
|
201
|
+
animate={{ opacity: 1, x: 0 }}
|
|
202
|
+
transition={{ delay: 0.2 }}
|
|
203
|
+
className="md:col-span-1 space-y-3"
|
|
204
|
+
>
|
|
205
|
+
<h2 className="text-sm font-medium text-neutral-400 mb-4">Your Servers</h2>
|
|
206
|
+
{servers.map((server) => (
|
|
207
|
+
<button
|
|
208
|
+
key={server.id}
|
|
209
|
+
onClick={() => setSelectedServer(server)}
|
|
210
|
+
className={`w-full p-4 rounded-xl border text-left transition-all ${
|
|
211
|
+
selectedServer?.id === server.id
|
|
212
|
+
? 'border-blue-500 bg-blue-500/10'
|
|
213
|
+
: 'border-neutral-800 bg-neutral-900/50 hover:border-neutral-700'
|
|
214
|
+
}`}
|
|
215
|
+
>
|
|
216
|
+
<div className="flex items-start justify-between mb-2">
|
|
217
|
+
<div className="font-medium text-white truncate pr-2">{server.name}</div>
|
|
218
|
+
<span
|
|
219
|
+
className={`px-2 py-0.5 text-xs rounded-full ${
|
|
220
|
+
server.status === 'active'
|
|
221
|
+
? 'bg-green-500/20 text-green-400'
|
|
222
|
+
: 'bg-neutral-500/20 text-neutral-400'
|
|
223
|
+
}`}
|
|
224
|
+
>
|
|
225
|
+
{server.status}
|
|
226
|
+
</span>
|
|
227
|
+
</div>
|
|
228
|
+
<div className="text-xs text-neutral-500 flex items-center gap-3">
|
|
229
|
+
<span>{server.tools.length} tools</span>
|
|
230
|
+
<span>•</span>
|
|
231
|
+
<span>{server.usage.totalCalls} calls</span>
|
|
232
|
+
</div>
|
|
233
|
+
</button>
|
|
234
|
+
))}
|
|
235
|
+
</motion.div>
|
|
236
|
+
|
|
237
|
+
{/* Server Details */}
|
|
238
|
+
<motion.div
|
|
239
|
+
initial={{ opacity: 0, x: 20 }}
|
|
240
|
+
animate={{ opacity: 1, x: 0 }}
|
|
241
|
+
transition={{ delay: 0.3 }}
|
|
242
|
+
className="md:col-span-2"
|
|
243
|
+
>
|
|
244
|
+
{selectedServer && (
|
|
245
|
+
<div className="rounded-xl border border-neutral-800 bg-neutral-900/50 backdrop-blur-sm overflow-hidden">
|
|
246
|
+
{/* Server Header */}
|
|
247
|
+
<div className="p-6 border-b border-neutral-800">
|
|
248
|
+
<div className="flex items-start justify-between">
|
|
249
|
+
<div>
|
|
250
|
+
<h2 className="text-xl font-bold text-white mb-1">{selectedServer.name}</h2>
|
|
251
|
+
<p className="text-sm text-neutral-400">{selectedServer.description}</p>
|
|
252
|
+
</div>
|
|
253
|
+
<div className="flex items-center gap-2">
|
|
254
|
+
<button
|
|
255
|
+
onClick={() => handleToggleStatus(selectedServer.id)}
|
|
256
|
+
className="p-2 text-neutral-400 hover:text-white rounded-lg hover:bg-white/5 transition-colors"
|
|
257
|
+
title={selectedServer.status === 'active' ? 'Pause server' : 'Resume server'}
|
|
258
|
+
>
|
|
259
|
+
{selectedServer.status === 'active' ? <Pause className="w-4 h-4" /> : <Play className="w-4 h-4" />}
|
|
260
|
+
</button>
|
|
261
|
+
<button
|
|
262
|
+
onClick={() => handleDelete(selectedServer.id)}
|
|
263
|
+
className="p-2 text-neutral-400 hover:text-red-400 rounded-lg hover:bg-red-500/10 transition-colors"
|
|
264
|
+
title="Delete server"
|
|
265
|
+
>
|
|
266
|
+
<Trash2 className="w-4 h-4" />
|
|
267
|
+
</button>
|
|
268
|
+
</div>
|
|
269
|
+
</div>
|
|
270
|
+
</div>
|
|
271
|
+
|
|
272
|
+
{/* Endpoint */}
|
|
273
|
+
<div className="p-6 border-b border-neutral-800">
|
|
274
|
+
<div className="text-xs text-neutral-500 mb-2">Endpoint URL</div>
|
|
275
|
+
<div className="flex items-center gap-2 p-3 bg-black/30 rounded-lg">
|
|
276
|
+
<Globe className="w-4 h-4 text-blue-400 flex-shrink-0" />
|
|
277
|
+
<code className="flex-1 text-sm text-green-400 font-mono truncate">
|
|
278
|
+
{selectedServer.endpoint}
|
|
279
|
+
</code>
|
|
280
|
+
<button
|
|
281
|
+
onClick={() => handleCopy(selectedServer.endpoint, `endpoint-${selectedServer.id}`)}
|
|
282
|
+
className="p-1.5 text-neutral-400 hover:text-white rounded hover:bg-white/5"
|
|
283
|
+
>
|
|
284
|
+
{copied === `endpoint-${selectedServer.id}` ? (
|
|
285
|
+
<Check className="w-4 h-4 text-green-400" />
|
|
286
|
+
) : (
|
|
287
|
+
<Copy className="w-4 h-4" />
|
|
288
|
+
)}
|
|
289
|
+
</button>
|
|
290
|
+
</div>
|
|
291
|
+
</div>
|
|
292
|
+
|
|
293
|
+
{/* Usage Stats */}
|
|
294
|
+
<div className="p-6 border-b border-neutral-800">
|
|
295
|
+
<h3 className="text-sm font-medium text-neutral-400 mb-4 flex items-center gap-2">
|
|
296
|
+
<BarChart3 className="w-4 h-4" />
|
|
297
|
+
Usage Statistics
|
|
298
|
+
</h3>
|
|
299
|
+
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
300
|
+
{[
|
|
301
|
+
{ label: 'Total Calls', value: selectedServer.usage.totalCalls, trend: '+12%' },
|
|
302
|
+
{ label: 'Today', value: selectedServer.usage.totalCallsToday },
|
|
303
|
+
{ label: 'Success Rate', value: `${selectedServer.usage.successRate}%`, good: true },
|
|
304
|
+
{ label: 'Avg Latency', value: `${selectedServer.usage.avgLatencyMs}ms` },
|
|
305
|
+
].map(({ label, value, trend, good }) => (
|
|
306
|
+
<div key={label} className="p-3 bg-black/30 rounded-lg">
|
|
307
|
+
<div className="text-xs text-neutral-500 mb-1">{label}</div>
|
|
308
|
+
<div className="flex items-center gap-2">
|
|
309
|
+
<div className="text-lg font-bold text-white">{value}</div>
|
|
310
|
+
{trend && (
|
|
311
|
+
<span className="text-xs text-green-400 flex items-center">
|
|
312
|
+
<TrendingUp className="w-3 h-3 mr-0.5" />
|
|
313
|
+
{trend}
|
|
314
|
+
</span>
|
|
315
|
+
)}
|
|
316
|
+
</div>
|
|
317
|
+
</div>
|
|
318
|
+
))}
|
|
319
|
+
</div>
|
|
320
|
+
</div>
|
|
321
|
+
|
|
322
|
+
{/* Tools */}
|
|
323
|
+
<div className="p-6">
|
|
324
|
+
<h3 className="text-sm font-medium text-neutral-400 mb-4 flex items-center gap-2">
|
|
325
|
+
<Settings className="w-4 h-4" />
|
|
326
|
+
Deployed Tools ({selectedServer.tools.length})
|
|
327
|
+
</h3>
|
|
328
|
+
<div className="space-y-2">
|
|
329
|
+
{selectedServer.tools.map((tool) => (
|
|
330
|
+
<div
|
|
331
|
+
key={tool.name}
|
|
332
|
+
className="flex items-center justify-between p-3 bg-black/30 rounded-lg"
|
|
333
|
+
>
|
|
334
|
+
<div className="flex items-center gap-3">
|
|
335
|
+
<div className={`w-2 h-2 rounded-full ${tool.enabled ? 'bg-green-400' : 'bg-neutral-500'}`} />
|
|
336
|
+
<div>
|
|
337
|
+
<div className="text-sm font-medium text-white">{tool.name}</div>
|
|
338
|
+
<div className="text-xs text-neutral-500 truncate max-w-[300px]">
|
|
339
|
+
{tool.description}
|
|
340
|
+
</div>
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
<div className="text-xs text-neutral-400">
|
|
344
|
+
{tool.callCount} calls
|
|
345
|
+
</div>
|
|
346
|
+
</div>
|
|
347
|
+
))}
|
|
348
|
+
</div>
|
|
349
|
+
</div>
|
|
350
|
+
|
|
351
|
+
{/* Metadata */}
|
|
352
|
+
<div className="px-6 pb-6">
|
|
353
|
+
<div className="flex items-center gap-4 text-xs text-neutral-500">
|
|
354
|
+
<span className="flex items-center gap-1">
|
|
355
|
+
<Clock className="w-3 h-3" />
|
|
356
|
+
Created {new Date(selectedServer.createdAt).toLocaleDateString()}
|
|
357
|
+
</span>
|
|
358
|
+
<span className="flex items-center gap-1">
|
|
359
|
+
<Globe className="w-3 h-3" />
|
|
360
|
+
{selectedServer.region}
|
|
361
|
+
</span>
|
|
362
|
+
{selectedServer.sourceRepo && (
|
|
363
|
+
<span className="flex items-center gap-1">
|
|
364
|
+
<ExternalLink className="w-3 h-3" />
|
|
365
|
+
{selectedServer.sourceRepo}
|
|
366
|
+
</span>
|
|
367
|
+
)}
|
|
368
|
+
</div>
|
|
369
|
+
</div>
|
|
370
|
+
</div>
|
|
371
|
+
)}
|
|
372
|
+
</motion.div>
|
|
373
|
+
</div>
|
|
374
|
+
)}
|
|
375
|
+
</div>
|
|
376
|
+
|
|
377
|
+
<Footer />
|
|
378
|
+
</main>
|
|
379
|
+
);
|
|
380
|
+
}
|