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,703 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Metrics - Performance tracking and telemetry
|
|
3
|
+
* @copyright 2024-2026 nirholas
|
|
4
|
+
* @license MIT
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Metric Types
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Counter metric - tracks cumulative values
|
|
13
|
+
*/
|
|
14
|
+
export interface Counter {
|
|
15
|
+
readonly name: string;
|
|
16
|
+
readonly value: number;
|
|
17
|
+
readonly labels: Readonly<Record<string, string>>;
|
|
18
|
+
increment(amount?: number): void;
|
|
19
|
+
reset(): void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Gauge metric - tracks current values that can go up or down
|
|
24
|
+
*/
|
|
25
|
+
export interface Gauge {
|
|
26
|
+
readonly name: string;
|
|
27
|
+
readonly value: number;
|
|
28
|
+
readonly labels: Readonly<Record<string, string>>;
|
|
29
|
+
set(value: number): void;
|
|
30
|
+
increment(amount?: number): void;
|
|
31
|
+
decrement(amount?: number): void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Histogram metric - tracks distribution of values
|
|
36
|
+
*/
|
|
37
|
+
export interface Histogram {
|
|
38
|
+
readonly name: string;
|
|
39
|
+
readonly count: number;
|
|
40
|
+
readonly sum: number;
|
|
41
|
+
readonly min: number;
|
|
42
|
+
readonly max: number;
|
|
43
|
+
readonly mean: number;
|
|
44
|
+
readonly p50: number;
|
|
45
|
+
readonly p90: number;
|
|
46
|
+
readonly p95: number;
|
|
47
|
+
readonly p99: number;
|
|
48
|
+
readonly labels: Readonly<Record<string, string>>;
|
|
49
|
+
observe(value: number): void;
|
|
50
|
+
reset(): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Timer metric - specialized histogram for timing operations
|
|
55
|
+
*/
|
|
56
|
+
export interface Timer extends Histogram {
|
|
57
|
+
/** Start a timing observation */
|
|
58
|
+
start(): TimerObservation;
|
|
59
|
+
/** Time an async operation */
|
|
60
|
+
time<T>(operation: () => Promise<T>): Promise<T>;
|
|
61
|
+
/** Time a sync operation */
|
|
62
|
+
timeSync<T>(operation: () => T): T;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Active timer observation
|
|
67
|
+
*/
|
|
68
|
+
export interface TimerObservation {
|
|
69
|
+
/** End the observation and record the duration */
|
|
70
|
+
end(): number;
|
|
71
|
+
/** Cancel the observation without recording */
|
|
72
|
+
cancel(): void;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ============================================================================
|
|
76
|
+
// Metrics Snapshot
|
|
77
|
+
// ============================================================================
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Point-in-time snapshot of all metrics
|
|
81
|
+
*/
|
|
82
|
+
export interface MetricsSnapshot {
|
|
83
|
+
readonly timestamp: Date;
|
|
84
|
+
readonly counters: Readonly<Record<string, number>>;
|
|
85
|
+
readonly gauges: Readonly<Record<string, number>>;
|
|
86
|
+
readonly histograms: Readonly<Record<string, HistogramSnapshot>>;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Histogram snapshot data
|
|
91
|
+
*/
|
|
92
|
+
export interface HistogramSnapshot {
|
|
93
|
+
readonly count: number;
|
|
94
|
+
readonly sum: number;
|
|
95
|
+
readonly min: number;
|
|
96
|
+
readonly max: number;
|
|
97
|
+
readonly mean: number;
|
|
98
|
+
readonly p50: number;
|
|
99
|
+
readonly p90: number;
|
|
100
|
+
readonly p95: number;
|
|
101
|
+
readonly p99: number;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ============================================================================
|
|
105
|
+
// MCP-Specific Metrics
|
|
106
|
+
// ============================================================================
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* MCP client metrics
|
|
110
|
+
*/
|
|
111
|
+
export interface McpClientMetrics {
|
|
112
|
+
// Connection metrics
|
|
113
|
+
readonly connectionAttempts: Counter;
|
|
114
|
+
readonly connectionSuccesses: Counter;
|
|
115
|
+
readonly connectionFailures: Counter;
|
|
116
|
+
readonly connectionDuration: Timer;
|
|
117
|
+
readonly activeConnections: Gauge;
|
|
118
|
+
readonly reconnectionAttempts: Counter;
|
|
119
|
+
|
|
120
|
+
// Request metrics
|
|
121
|
+
readonly requestsTotal: Counter;
|
|
122
|
+
readonly requestsSuccess: Counter;
|
|
123
|
+
readonly requestsFailure: Counter;
|
|
124
|
+
readonly requestDuration: Timer;
|
|
125
|
+
readonly requestsInFlight: Gauge;
|
|
126
|
+
readonly requestTimeouts: Counter;
|
|
127
|
+
readonly requestsCancelled: Counter;
|
|
128
|
+
|
|
129
|
+
// Tool metrics
|
|
130
|
+
readonly toolCalls: Counter;
|
|
131
|
+
readonly toolCallDuration: Timer;
|
|
132
|
+
readonly toolCallErrors: Counter;
|
|
133
|
+
|
|
134
|
+
// Resource metrics
|
|
135
|
+
readonly resourceReads: Counter;
|
|
136
|
+
readonly resourceReadDuration: Timer;
|
|
137
|
+
readonly resourceReadErrors: Counter;
|
|
138
|
+
|
|
139
|
+
// Prompt metrics
|
|
140
|
+
readonly promptGets: Counter;
|
|
141
|
+
readonly promptGetDuration: Timer;
|
|
142
|
+
readonly promptGetErrors: Counter;
|
|
143
|
+
|
|
144
|
+
// Get snapshot of all metrics
|
|
145
|
+
snapshot(): MetricsSnapshot;
|
|
146
|
+
|
|
147
|
+
// Reset all metrics
|
|
148
|
+
reset(): void;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Session manager metrics
|
|
153
|
+
*/
|
|
154
|
+
export interface SessionManagerMetrics {
|
|
155
|
+
readonly sessionsCreated: Counter;
|
|
156
|
+
readonly sessionsDestroyed: Counter;
|
|
157
|
+
readonly sessionsActive: Gauge;
|
|
158
|
+
readonly sessionsEvicted: Counter;
|
|
159
|
+
readonly sessionsTimedOut: Counter;
|
|
160
|
+
readonly sessionDuration: Timer;
|
|
161
|
+
readonly sessionCreationDuration: Timer;
|
|
162
|
+
|
|
163
|
+
snapshot(): MetricsSnapshot;
|
|
164
|
+
reset(): void;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ============================================================================
|
|
168
|
+
// Implementations
|
|
169
|
+
// ============================================================================
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Simple counter implementation
|
|
173
|
+
*/
|
|
174
|
+
class SimpleCounter implements Counter {
|
|
175
|
+
readonly name: string;
|
|
176
|
+
readonly labels: Readonly<Record<string, string>>;
|
|
177
|
+
private _value = 0;
|
|
178
|
+
|
|
179
|
+
constructor(name: string, labels: Record<string, string> = {}) {
|
|
180
|
+
this.name = name;
|
|
181
|
+
this.labels = Object.freeze({ ...labels });
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
get value(): number {
|
|
185
|
+
return this._value;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
increment(amount = 1): void {
|
|
189
|
+
if (amount < 0) {
|
|
190
|
+
throw new Error('Counter can only be incremented by non-negative values');
|
|
191
|
+
}
|
|
192
|
+
this._value += amount;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
reset(): void {
|
|
196
|
+
this._value = 0;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Simple gauge implementation
|
|
202
|
+
*/
|
|
203
|
+
class SimpleGauge implements Gauge {
|
|
204
|
+
readonly name: string;
|
|
205
|
+
readonly labels: Readonly<Record<string, string>>;
|
|
206
|
+
private _value = 0;
|
|
207
|
+
|
|
208
|
+
constructor(name: string, labels: Record<string, string> = {}) {
|
|
209
|
+
this.name = name;
|
|
210
|
+
this.labels = Object.freeze({ ...labels });
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
get value(): number {
|
|
214
|
+
return this._value;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
set(value: number): void {
|
|
218
|
+
this._value = value;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
increment(amount = 1): void {
|
|
222
|
+
this._value += amount;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
decrement(amount = 1): void {
|
|
226
|
+
this._value -= amount;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Simple histogram implementation using reservoir sampling
|
|
232
|
+
*/
|
|
233
|
+
class SimpleHistogram implements Histogram {
|
|
234
|
+
readonly name: string;
|
|
235
|
+
readonly labels: Readonly<Record<string, string>>;
|
|
236
|
+
private _values: number[] = [];
|
|
237
|
+
private _count = 0;
|
|
238
|
+
private _sum = 0;
|
|
239
|
+
private _min = Infinity;
|
|
240
|
+
private _max = -Infinity;
|
|
241
|
+
private readonly _maxSamples: number;
|
|
242
|
+
|
|
243
|
+
constructor(name: string, labels: Record<string, string> = {}, maxSamples = 1000) {
|
|
244
|
+
this.name = name;
|
|
245
|
+
this.labels = Object.freeze({ ...labels });
|
|
246
|
+
this._maxSamples = maxSamples;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
get count(): number {
|
|
250
|
+
return this._count;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
get sum(): number {
|
|
254
|
+
return this._sum;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
get min(): number {
|
|
258
|
+
return this._count === 0 ? 0 : this._min;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
get max(): number {
|
|
262
|
+
return this._count === 0 ? 0 : this._max;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
get mean(): number {
|
|
266
|
+
return this._count === 0 ? 0 : this._sum / this._count;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
get p50(): number {
|
|
270
|
+
return this._percentile(0.5);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
get p90(): number {
|
|
274
|
+
return this._percentile(0.9);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
get p95(): number {
|
|
278
|
+
return this._percentile(0.95);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
get p99(): number {
|
|
282
|
+
return this._percentile(0.99);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
observe(value: number): void {
|
|
286
|
+
this._count++;
|
|
287
|
+
this._sum += value;
|
|
288
|
+
this._min = Math.min(this._min, value);
|
|
289
|
+
this._max = Math.max(this._max, value);
|
|
290
|
+
|
|
291
|
+
// Reservoir sampling to keep memory bounded
|
|
292
|
+
if (this._values.length < this._maxSamples) {
|
|
293
|
+
this._values.push(value);
|
|
294
|
+
} else {
|
|
295
|
+
// Random replacement
|
|
296
|
+
const index = Math.floor(Math.random() * this._count);
|
|
297
|
+
if (index < this._maxSamples) {
|
|
298
|
+
this._values[index] = value;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
reset(): void {
|
|
304
|
+
this._values = [];
|
|
305
|
+
this._count = 0;
|
|
306
|
+
this._sum = 0;
|
|
307
|
+
this._min = Infinity;
|
|
308
|
+
this._max = -Infinity;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
private _percentile(p: number): number {
|
|
312
|
+
if (this._values.length === 0) return 0;
|
|
313
|
+
|
|
314
|
+
const sorted = [...this._values].sort((a, b) => a - b);
|
|
315
|
+
const index = Math.ceil(p * sorted.length) - 1;
|
|
316
|
+
return sorted[Math.max(0, index)];
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Timer implementation wrapping histogram
|
|
322
|
+
*/
|
|
323
|
+
class SimpleTimer implements Timer {
|
|
324
|
+
private readonly _histogram: SimpleHistogram;
|
|
325
|
+
|
|
326
|
+
constructor(name: string, labels: Record<string, string> = {}) {
|
|
327
|
+
this._histogram = new SimpleHistogram(name, labels);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
get name(): string {
|
|
331
|
+
return this._histogram.name;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
get labels(): Readonly<Record<string, string>> {
|
|
335
|
+
return this._histogram.labels;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
get count(): number {
|
|
339
|
+
return this._histogram.count;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
get sum(): number {
|
|
343
|
+
return this._histogram.sum;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
get min(): number {
|
|
347
|
+
return this._histogram.min;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
get max(): number {
|
|
351
|
+
return this._histogram.max;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
get mean(): number {
|
|
355
|
+
return this._histogram.mean;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
get p50(): number {
|
|
359
|
+
return this._histogram.p50;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
get p90(): number {
|
|
363
|
+
return this._histogram.p90;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
get p95(): number {
|
|
367
|
+
return this._histogram.p95;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
get p99(): number {
|
|
371
|
+
return this._histogram.p99;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
observe(value: number): void {
|
|
375
|
+
this._histogram.observe(value);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
reset(): void {
|
|
379
|
+
this._histogram.reset();
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
start(): TimerObservation {
|
|
383
|
+
const startTime = performance.now();
|
|
384
|
+
let ended = false;
|
|
385
|
+
|
|
386
|
+
return {
|
|
387
|
+
end: () => {
|
|
388
|
+
if (ended) {
|
|
389
|
+
throw new Error('Timer observation already ended');
|
|
390
|
+
}
|
|
391
|
+
ended = true;
|
|
392
|
+
const duration = performance.now() - startTime;
|
|
393
|
+
this._histogram.observe(duration);
|
|
394
|
+
return duration;
|
|
395
|
+
},
|
|
396
|
+
cancel: () => {
|
|
397
|
+
ended = true;
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
async time<T>(operation: () => Promise<T>): Promise<T> {
|
|
403
|
+
const observation = this.start();
|
|
404
|
+
try {
|
|
405
|
+
return await operation();
|
|
406
|
+
} finally {
|
|
407
|
+
observation.end();
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
timeSync<T>(operation: () => T): T {
|
|
412
|
+
const observation = this.start();
|
|
413
|
+
try {
|
|
414
|
+
return operation();
|
|
415
|
+
} finally {
|
|
416
|
+
observation.end();
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
// ============================================================================
|
|
422
|
+
// MCP Client Metrics Implementation
|
|
423
|
+
// ============================================================================
|
|
424
|
+
|
|
425
|
+
/**
|
|
426
|
+
* Create MCP client metrics instance
|
|
427
|
+
*/
|
|
428
|
+
export function createClientMetrics(): McpClientMetrics {
|
|
429
|
+
const counters: Map<string, SimpleCounter> = new Map();
|
|
430
|
+
const gauges: Map<string, SimpleGauge> = new Map();
|
|
431
|
+
const timers: Map<string, SimpleTimer> = new Map();
|
|
432
|
+
|
|
433
|
+
const getCounter = (name: string): SimpleCounter => {
|
|
434
|
+
let counter = counters.get(name);
|
|
435
|
+
if (!counter) {
|
|
436
|
+
counter = new SimpleCounter(name);
|
|
437
|
+
counters.set(name, counter);
|
|
438
|
+
}
|
|
439
|
+
return counter;
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
const getGauge = (name: string): SimpleGauge => {
|
|
443
|
+
let gauge = gauges.get(name);
|
|
444
|
+
if (!gauge) {
|
|
445
|
+
gauge = new SimpleGauge(name);
|
|
446
|
+
gauges.set(name, gauge);
|
|
447
|
+
}
|
|
448
|
+
return gauge;
|
|
449
|
+
};
|
|
450
|
+
|
|
451
|
+
const getTimer = (name: string): SimpleTimer => {
|
|
452
|
+
let timer = timers.get(name);
|
|
453
|
+
if (!timer) {
|
|
454
|
+
timer = new SimpleTimer(name);
|
|
455
|
+
timers.set(name, timer);
|
|
456
|
+
}
|
|
457
|
+
return timer;
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
return {
|
|
461
|
+
// Connection metrics
|
|
462
|
+
connectionAttempts: getCounter('mcp_connection_attempts_total'),
|
|
463
|
+
connectionSuccesses: getCounter('mcp_connection_successes_total'),
|
|
464
|
+
connectionFailures: getCounter('mcp_connection_failures_total'),
|
|
465
|
+
connectionDuration: getTimer('mcp_connection_duration_ms'),
|
|
466
|
+
activeConnections: getGauge('mcp_active_connections'),
|
|
467
|
+
reconnectionAttempts: getCounter('mcp_reconnection_attempts_total'),
|
|
468
|
+
|
|
469
|
+
// Request metrics
|
|
470
|
+
requestsTotal: getCounter('mcp_requests_total'),
|
|
471
|
+
requestsSuccess: getCounter('mcp_requests_success_total'),
|
|
472
|
+
requestsFailure: getCounter('mcp_requests_failure_total'),
|
|
473
|
+
requestDuration: getTimer('mcp_request_duration_ms'),
|
|
474
|
+
requestsInFlight: getGauge('mcp_requests_in_flight'),
|
|
475
|
+
requestTimeouts: getCounter('mcp_request_timeouts_total'),
|
|
476
|
+
requestsCancelled: getCounter('mcp_requests_cancelled_total'),
|
|
477
|
+
|
|
478
|
+
// Tool metrics
|
|
479
|
+
toolCalls: getCounter('mcp_tool_calls_total'),
|
|
480
|
+
toolCallDuration: getTimer('mcp_tool_call_duration_ms'),
|
|
481
|
+
toolCallErrors: getCounter('mcp_tool_call_errors_total'),
|
|
482
|
+
|
|
483
|
+
// Resource metrics
|
|
484
|
+
resourceReads: getCounter('mcp_resource_reads_total'),
|
|
485
|
+
resourceReadDuration: getTimer('mcp_resource_read_duration_ms'),
|
|
486
|
+
resourceReadErrors: getCounter('mcp_resource_read_errors_total'),
|
|
487
|
+
|
|
488
|
+
// Prompt metrics
|
|
489
|
+
promptGets: getCounter('mcp_prompt_gets_total'),
|
|
490
|
+
promptGetDuration: getTimer('mcp_prompt_get_duration_ms'),
|
|
491
|
+
promptGetErrors: getCounter('mcp_prompt_get_errors_total'),
|
|
492
|
+
|
|
493
|
+
snapshot(): MetricsSnapshot {
|
|
494
|
+
const counterSnapshot: Record<string, number> = {};
|
|
495
|
+
const gaugeSnapshot: Record<string, number> = {};
|
|
496
|
+
const histogramSnapshot: Record<string, HistogramSnapshot> = {};
|
|
497
|
+
|
|
498
|
+
for (const [name, counter] of counters) {
|
|
499
|
+
counterSnapshot[name] = counter.value;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
for (const [name, gauge] of gauges) {
|
|
503
|
+
gaugeSnapshot[name] = gauge.value;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
for (const [name, timer] of timers) {
|
|
507
|
+
histogramSnapshot[name] = {
|
|
508
|
+
count: timer.count,
|
|
509
|
+
sum: timer.sum,
|
|
510
|
+
min: timer.min,
|
|
511
|
+
max: timer.max,
|
|
512
|
+
mean: timer.mean,
|
|
513
|
+
p50: timer.p50,
|
|
514
|
+
p90: timer.p90,
|
|
515
|
+
p95: timer.p95,
|
|
516
|
+
p99: timer.p99,
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
return {
|
|
521
|
+
timestamp: new Date(),
|
|
522
|
+
counters: counterSnapshot,
|
|
523
|
+
gauges: gaugeSnapshot,
|
|
524
|
+
histograms: histogramSnapshot,
|
|
525
|
+
};
|
|
526
|
+
},
|
|
527
|
+
|
|
528
|
+
reset(): void {
|
|
529
|
+
for (const counter of counters.values()) {
|
|
530
|
+
counter.reset();
|
|
531
|
+
}
|
|
532
|
+
for (const gauge of gauges.values()) {
|
|
533
|
+
gauge.set(0);
|
|
534
|
+
}
|
|
535
|
+
for (const timer of timers.values()) {
|
|
536
|
+
timer.reset();
|
|
537
|
+
}
|
|
538
|
+
},
|
|
539
|
+
};
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
// ============================================================================
|
|
543
|
+
// Session Manager Metrics Implementation
|
|
544
|
+
// ============================================================================
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Create session manager metrics instance
|
|
548
|
+
*/
|
|
549
|
+
export function createSessionManagerMetrics(): SessionManagerMetrics {
|
|
550
|
+
const counters: Map<string, SimpleCounter> = new Map();
|
|
551
|
+
const gauges: Map<string, SimpleGauge> = new Map();
|
|
552
|
+
const timers: Map<string, SimpleTimer> = new Map();
|
|
553
|
+
|
|
554
|
+
const getCounter = (name: string): SimpleCounter => {
|
|
555
|
+
let counter = counters.get(name);
|
|
556
|
+
if (!counter) {
|
|
557
|
+
counter = new SimpleCounter(name);
|
|
558
|
+
counters.set(name, counter);
|
|
559
|
+
}
|
|
560
|
+
return counter;
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
const getGauge = (name: string): SimpleGauge => {
|
|
564
|
+
let gauge = gauges.get(name);
|
|
565
|
+
if (!gauge) {
|
|
566
|
+
gauge = new SimpleGauge(name);
|
|
567
|
+
gauges.set(name, gauge);
|
|
568
|
+
}
|
|
569
|
+
return gauge;
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
const getTimer = (name: string): SimpleTimer => {
|
|
573
|
+
let timer = timers.get(name);
|
|
574
|
+
if (!timer) {
|
|
575
|
+
timer = new SimpleTimer(name);
|
|
576
|
+
timers.set(name, timer);
|
|
577
|
+
}
|
|
578
|
+
return timer;
|
|
579
|
+
};
|
|
580
|
+
|
|
581
|
+
return {
|
|
582
|
+
sessionsCreated: getCounter('mcp_sessions_created_total'),
|
|
583
|
+
sessionsDestroyed: getCounter('mcp_sessions_destroyed_total'),
|
|
584
|
+
sessionsActive: getGauge('mcp_sessions_active'),
|
|
585
|
+
sessionsEvicted: getCounter('mcp_sessions_evicted_total'),
|
|
586
|
+
sessionsTimedOut: getCounter('mcp_sessions_timed_out_total'),
|
|
587
|
+
sessionDuration: getTimer('mcp_session_duration_ms'),
|
|
588
|
+
sessionCreationDuration: getTimer('mcp_session_creation_duration_ms'),
|
|
589
|
+
|
|
590
|
+
snapshot(): MetricsSnapshot {
|
|
591
|
+
const counterSnapshot: Record<string, number> = {};
|
|
592
|
+
const gaugeSnapshot: Record<string, number> = {};
|
|
593
|
+
const histogramSnapshot: Record<string, HistogramSnapshot> = {};
|
|
594
|
+
|
|
595
|
+
for (const [name, counter] of counters) {
|
|
596
|
+
counterSnapshot[name] = counter.value;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
for (const [name, gauge] of gauges) {
|
|
600
|
+
gaugeSnapshot[name] = gauge.value;
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
for (const [name, timer] of timers) {
|
|
604
|
+
histogramSnapshot[name] = {
|
|
605
|
+
count: timer.count,
|
|
606
|
+
sum: timer.sum,
|
|
607
|
+
min: timer.min,
|
|
608
|
+
max: timer.max,
|
|
609
|
+
mean: timer.mean,
|
|
610
|
+
p50: timer.p50,
|
|
611
|
+
p90: timer.p90,
|
|
612
|
+
p95: timer.p95,
|
|
613
|
+
p99: timer.p99,
|
|
614
|
+
};
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
return {
|
|
618
|
+
timestamp: new Date(),
|
|
619
|
+
counters: counterSnapshot,
|
|
620
|
+
gauges: gaugeSnapshot,
|
|
621
|
+
histograms: histogramSnapshot,
|
|
622
|
+
};
|
|
623
|
+
},
|
|
624
|
+
|
|
625
|
+
reset(): void {
|
|
626
|
+
for (const counter of counters.values()) {
|
|
627
|
+
counter.reset();
|
|
628
|
+
}
|
|
629
|
+
for (const gauge of gauges.values()) {
|
|
630
|
+
gauge.set(0);
|
|
631
|
+
}
|
|
632
|
+
for (const timer of timers.values()) {
|
|
633
|
+
timer.reset();
|
|
634
|
+
}
|
|
635
|
+
},
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// ============================================================================
|
|
640
|
+
// Metrics Registry
|
|
641
|
+
// ============================================================================
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* Global metrics registry for centralized metric management
|
|
645
|
+
*/
|
|
646
|
+
export class MetricsRegistry {
|
|
647
|
+
private static _instance: MetricsRegistry | null = null;
|
|
648
|
+
private _clientMetrics: McpClientMetrics | null = null;
|
|
649
|
+
private _sessionMetrics: SessionManagerMetrics | null = null;
|
|
650
|
+
|
|
651
|
+
private constructor() {}
|
|
652
|
+
|
|
653
|
+
static getInstance(): MetricsRegistry {
|
|
654
|
+
if (!MetricsRegistry._instance) {
|
|
655
|
+
MetricsRegistry._instance = new MetricsRegistry();
|
|
656
|
+
}
|
|
657
|
+
return MetricsRegistry._instance;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
get clientMetrics(): McpClientMetrics {
|
|
661
|
+
if (!this._clientMetrics) {
|
|
662
|
+
this._clientMetrics = createClientMetrics();
|
|
663
|
+
}
|
|
664
|
+
return this._clientMetrics;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
get sessionMetrics(): SessionManagerMetrics {
|
|
668
|
+
if (!this._sessionMetrics) {
|
|
669
|
+
this._sessionMetrics = createSessionManagerMetrics();
|
|
670
|
+
}
|
|
671
|
+
return this._sessionMetrics;
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Get combined snapshot of all metrics
|
|
676
|
+
*/
|
|
677
|
+
snapshot(): {
|
|
678
|
+
client: MetricsSnapshot;
|
|
679
|
+
session: MetricsSnapshot;
|
|
680
|
+
timestamp: Date;
|
|
681
|
+
} {
|
|
682
|
+
return {
|
|
683
|
+
client: this.clientMetrics.snapshot(),
|
|
684
|
+
session: this.sessionMetrics.snapshot(),
|
|
685
|
+
timestamp: new Date(),
|
|
686
|
+
};
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
/**
|
|
690
|
+
* Reset all metrics
|
|
691
|
+
*/
|
|
692
|
+
reset(): void {
|
|
693
|
+
this._clientMetrics?.reset();
|
|
694
|
+
this._sessionMetrics?.reset();
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Get the global metrics registry
|
|
700
|
+
*/
|
|
701
|
+
export function getMetricsRegistry(): MetricsRegistry {
|
|
702
|
+
return MetricsRegistry.getInstance();
|
|
703
|
+
}
|