testmcpy 0.9.2__tar.gz → 0.10.3__tar.gz
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.
- {testmcpy-0.9.2/testmcpy.egg-info → testmcpy-0.10.3}/PKG-INFO +29 -10
- {testmcpy-0.9.2 → testmcpy-0.10.3}/README.md +28 -9
- {testmcpy-0.9.2 → testmcpy-0.10.3}/pyproject.toml +1 -1
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/wizard.py +18 -26
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/mcp_profiles.py +55 -1
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/tools.py +30 -10
- testmcpy-0.9.2/testmcpy/ui/dist/assets/index-BXP9_Odn.js → testmcpy-0.10.3/testmcpy/ui/dist/assets/index-C2CLSwMl.js +66 -66
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/dist/index.html +1 -1
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/MCPProfileSelector.jsx +2 -1
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/Reports.jsx +16 -0
- testmcpy-0.10.3/testmcpy/ui/src/pages/__tests__/Reports.test.jsx +104 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3/testmcpy.egg-info}/PKG-INFO +29 -10
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy.egg-info/SOURCES.txt +2 -1
- {testmcpy-0.9.2 → testmcpy-0.10.3}/LICENSE +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/MANIFEST.in +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/NOTICE +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/setup.cfg +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/__main__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/agent/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/agent/hooks.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/agent/models.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/agent/orchestrator.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/agent/prompts.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/agent/tools.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/analytics.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/auth_debugger.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/auth_flow_recorder.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/app.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/agent.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/analytics.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/badge.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/baseline.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/bench.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/conformance.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/export_db.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/mcp.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/metamorphic.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/multi_env.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/mutate.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/push.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/run.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/scan.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/score.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/server.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/tools.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/cli/commands/tui.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/config.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/core/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/core/chat_session.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/core/docs_optimizer.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/core/mcp_manager.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/core/tool_comparison.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/core/tool_discovery.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/db.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/error_handlers.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/evals/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/evals/auth_evaluators.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/evals/base_evaluators.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/evals/evaluator_packs.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/evals/security_evaluators.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/base.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/curl.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/graphql.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/javascript_client.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/json_yaml.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/protobuf.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/python.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/python_client.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/thrift.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/typescript.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/formatters/typescript_client.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/llm_profiles.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/mcp_profiles.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/migrate_json.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/models.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/research/claude_sdk_detailed_exploration.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/research/claude_sdk_poc.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/research/claude_sdk_working_poc.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/research/test_ollama_tools.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/security/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/security/rules.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/security/scanner.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/api.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/auth_middleware.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/helpers/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/helpers/mcp_config.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/models.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/agent.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/analytics.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/auth.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/compare.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/compatibility.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/generation_logs.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/health.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/llm.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/metrics.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/results.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/runs.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/search.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/security.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/smoke_reports.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/test_profiles.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/routers/tests.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/run_persistence.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/run_registry.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/state.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/server/websocket.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/smoke_test.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/__init__.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/baseline.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/ci_gate.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/comparison_runner.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/coverage_analyzer.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/emitters.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/html_report.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/llm_integration.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/mcp_client.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/metamorphic.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/model_registry.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/models.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/multi_env.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/oauth_flows.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/prompt_mutation.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/report_generator.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/runner_tools.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/schema_diff.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/test_runner.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/token_manager.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/src/usability_score.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/storage.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/test_profiles.py +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/README.md +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/dist/assets/index-D35cfDhp.css +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/index.html +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/package-lock.json +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/package.json +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/postcss.config.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/App.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/BackgroundRunsIndicator.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/Badge.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/CommandPalette.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/CompareToolsTab.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/ConfirmDialog.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/EditorStatusBar.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/EditorTabStrip.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/ErrorAlert.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/ErrorBoundary.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/LLMProfileSelector.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/LoadingSpinner.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/NotificationProvider.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/OptimizeDocsModal.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/OutputDiff.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/ParameterCard.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/SchemaCodeViewer.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/SkeletonLoader.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/StreamingLogViewer.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/TestGenerationModal.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/TestProfileSelector.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/TestResultPanel.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/TestStatusIndicator.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/ToolCallTimeline.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/ToolComparison.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/ToolDebugModal.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/TraceView.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/TypeBadge.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/Wizard.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/components/__tests__/OutputDiff.test.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/contexts/TestRunContext.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/contexts/ThemeContext.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/hooks/useEditorTheme.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/hooks/useKeyboardShortcuts.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/hooks/useSafeFetch.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/index.css +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/main.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/AuthDebugger.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/ChatInterface.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/Configuration.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/GenerationHistory.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/LLMProfiles.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/MCPExplorer.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/MCPProfiles.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/Performance.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/ProfilesManager.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/SecurityDashboard.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/Servers.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/TestManager.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/__tests__/ChatInterface.test.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/pages/__tests__/Performance.test.jsx +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/test-setup.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/utils/__tests__/formatConverters.test.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/utils/formatConverters.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/src/utils/formatters.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/tailwind.config.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/vite.config.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy/ui/vitest.config.js +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy.egg-info/dependency_links.txt +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy.egg-info/entry_points.txt +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy.egg-info/requires.txt +0 -0
- {testmcpy-0.9.2 → testmcpy-0.10.3}/testmcpy.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: testmcpy
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.10.3
|
|
4
4
|
Summary: A comprehensive testing framework for validating LLM tool calling capabilities with MCP services
|
|
5
5
|
Author: Amin Ghadersohi
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -94,13 +94,14 @@ Dynamic: license-file
|
|
|
94
94
|
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="Python 3.10+"></a>
|
|
95
95
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License"></a>
|
|
96
96
|
<a href="https://pypi.org/project/testmcpy/"><img src="https://img.shields.io/badge/pypi-testmcpy-blue" alt="PyPI"></a>
|
|
97
|
+
<a href="https://preset-io.github.io/testmcpy"><img src="https://img.shields.io/badge/docs-preset--io.github.io-7aa2f7" alt="Documentation"></a>
|
|
97
98
|
</p>
|
|
98
99
|
|
|
99
100
|

|
|
100
101
|
|
|
101
102
|
---
|
|
102
103
|
|
|
103
|
-
**[Documentation](
|
|
104
|
+
**[Documentation](https://preset-io.github.io/testmcpy)** | **[Getting Started](https://preset-io.github.io/testmcpy/getting-started)** | **[CLI Reference](https://preset-io.github.io/testmcpy/cli)** | **[Examples](examples/)** | **[Contributing](CONTRIBUTING.md)** | **[Discussions](https://github.com/preset-io/testmcpy/discussions)**
|
|
104
105
|
|
|
105
106
|
---
|
|
106
107
|
|
|
@@ -397,6 +398,8 @@ testmcpy run tests/ --model claude-haiku-4-5
|
|
|
397
398
|
|
|
398
399
|
## Commands Reference
|
|
399
400
|
|
|
401
|
+
The highlights are below — the full reference for all 38 commands lives at **[preset-io.github.io/testmcpy/cli](https://preset-io.github.io/testmcpy/cli)**.
|
|
402
|
+
|
|
400
403
|
| Command | Description |
|
|
401
404
|
|---------|-------------|
|
|
402
405
|
| **Setup** | |
|
|
@@ -412,6 +415,12 @@ testmcpy run tests/ --model claude-haiku-4-5
|
|
|
412
415
|
| `testmcpy research` | Test LLM tool-calling capabilities |
|
|
413
416
|
| `testmcpy chat` | Interactive chat with MCP tools |
|
|
414
417
|
| `testmcpy compare` | Multi-model comparison |
|
|
418
|
+
| **Quality & Benchmarking** | |
|
|
419
|
+
| `testmcpy bench` | Run a suite across models × profiles × repeats |
|
|
420
|
+
| `testmcpy conformance` | Run the official MCP spec conformance suite |
|
|
421
|
+
| `testmcpy score` | Grade tool surface for LLM usability (0-100, A-F) |
|
|
422
|
+
| `testmcpy scan` | Static security scan of tool metadata (SARIF output) |
|
|
423
|
+
| `testmcpy matrix` / `leaderboard` / `flaky` | Per-test × per-config analytics |
|
|
415
424
|
| **Advanced** | |
|
|
416
425
|
| `testmcpy baseline-save` | Save current test results as a named baseline |
|
|
417
426
|
| `testmcpy baseline-compare` | Compare a run against a saved baseline |
|
|
@@ -459,7 +468,7 @@ Environment variables are also supported: `MCP_AUTH_TOKEN`, `MCP_JWT_URL`, `MCP_
|
|
|
459
468
|
|
|
460
469
|
## Web Interface
|
|
461
470
|
|
|
462
|
-
Optional React-based UI
|
|
471
|
+
Optional React-based UI for visual testing and analytics — every page is documented at **[preset-io.github.io/testmcpy/web-ui](https://preset-io.github.io/testmcpy/web-ui)**:
|
|
463
472
|
|
|
464
473
|

|
|
465
474
|
|
|
@@ -477,11 +486,9 @@ testmcpy serve
|
|
|
477
486
|
| `/tests` | Test Manager | YAML test browser, execution, results |
|
|
478
487
|
| `/reports` | Reports | All test results, evaluations, cost analysis |
|
|
479
488
|
| `/chat` | Chat Interface | Multi-turn conversation with MCP tools |
|
|
480
|
-
| `/
|
|
481
|
-
| `/
|
|
482
|
-
| `/
|
|
483
|
-
| `/mcp-health` | MCP Health | Server health monitoring |
|
|
484
|
-
| `/security` | Security Dashboard | Security analysis |
|
|
489
|
+
| `/performance` | Performance | Per-test matrix and config leaderboard (also serves `/metrics`, `/compare`) |
|
|
490
|
+
| `/servers` | Servers | Health monitoring + cross-server schema compatibility (also serves `/mcp-health`, `/compatibility`) |
|
|
491
|
+
| `/security` | Security Dashboard | Security evaluator results and risk summary |
|
|
485
492
|
| `/generation-history` | Generation History | AI test generation logs |
|
|
486
493
|
| `/auth-debugger` | Auth Debugger | Auth flow debugging |
|
|
487
494
|
| `/config` | Configuration | Settings and environment |
|
|
@@ -498,7 +505,19 @@ Access at `http://localhost:8000`.
|
|
|
498
505
|
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/auth-debugger.png" alt="Auth Debugger page"><br><sub>Auth Debugger — step through OAuth / JWT / Bearer flows</sub></td>
|
|
499
506
|
</tr>
|
|
500
507
|
<tr>
|
|
508
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/metrics.png" alt="Performance matrix page"><br><sub>Performance — per-test results across model and MCP configurations</sub></td>
|
|
509
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/compare.png" alt="Leaderboard page"><br><sub>Leaderboard — configs ranked by pass rate, cost-per-pass, latency</sub></td>
|
|
510
|
+
</tr>
|
|
511
|
+
<tr>
|
|
512
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/security.png" alt="Security Dashboard page"><br><sub>Security Dashboard — security evaluator results and risk summary</sub></td>
|
|
513
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/compatibility.png" alt="Schema compatibility page"><br><sub>Schema Compat — cross-server tool schema compatibility matrix</sub></td>
|
|
514
|
+
</tr>
|
|
515
|
+
<tr>
|
|
516
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/mcp-health.png" alt="Server health page"><br><sub>Servers — MCP server health monitoring</sub></td>
|
|
501
517
|
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/mcp-profiles.png" alt="MCP Profiles page"><br><sub>MCP Profiles — manage MCP service connections</sub></td>
|
|
518
|
+
</tr>
|
|
519
|
+
<tr>
|
|
520
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/llm-profiles.png" alt="LLM Profiles page"><br><sub>LLM Profiles — provider configurations with model pricing</sub></td>
|
|
502
521
|
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/config.png" alt="Configuration page"><br><sub>Configuration — current settings and client snippets</sub></td>
|
|
503
522
|
</tr>
|
|
504
523
|
</table>
|
|
@@ -620,7 +639,7 @@ class MyEvaluator(BaseEvaluator):
|
|
|
620
639
|
)
|
|
621
640
|
```
|
|
622
641
|
|
|
623
|
-
See **[Evaluator Reference](
|
|
642
|
+
See the **[Evaluator Reference](https://preset-io.github.io/testmcpy/concepts/evaluators)** and the **[Custom Evaluators guide](https://preset-io.github.io/testmcpy/guides/custom-evaluators)** for complete documentation.
|
|
624
643
|
|
|
625
644
|
## Examples
|
|
626
645
|
|
|
@@ -641,7 +660,7 @@ We welcome contributions! Whether it's bug reports, feature requests, documentat
|
|
|
641
660
|
|
|
642
661
|
- **Issues**: [Report bugs or request features](https://github.com/preset-io/testmcpy/issues)
|
|
643
662
|
- **Discussions**: [Ask questions and share ideas](https://github.com/preset-io/testmcpy/discussions)
|
|
644
|
-
- **Documentation**:
|
|
663
|
+
- **Documentation**: [preset-io.github.io/testmcpy](https://preset-io.github.io/testmcpy) (agent-facing source docs live in [context/](context/))
|
|
645
664
|
- **Examples**: Explore [examples/](examples/) for sample code
|
|
646
665
|
|
|
647
666
|
## License
|
|
@@ -14,13 +14,14 @@
|
|
|
14
14
|
<a href="https://www.python.org/downloads/"><img src="https://img.shields.io/badge/python-3.10+-blue.svg" alt="Python 3.10+"></a>
|
|
15
15
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-Apache%202.0-blue.svg" alt="License"></a>
|
|
16
16
|
<a href="https://pypi.org/project/testmcpy/"><img src="https://img.shields.io/badge/pypi-testmcpy-blue" alt="PyPI"></a>
|
|
17
|
+
<a href="https://preset-io.github.io/testmcpy"><img src="https://img.shields.io/badge/docs-preset--io.github.io-7aa2f7" alt="Documentation"></a>
|
|
17
18
|
</p>
|
|
18
19
|
|
|
19
20
|

|
|
20
21
|
|
|
21
22
|
---
|
|
22
23
|
|
|
23
|
-
**[Documentation](
|
|
24
|
+
**[Documentation](https://preset-io.github.io/testmcpy)** | **[Getting Started](https://preset-io.github.io/testmcpy/getting-started)** | **[CLI Reference](https://preset-io.github.io/testmcpy/cli)** | **[Examples](examples/)** | **[Contributing](CONTRIBUTING.md)** | **[Discussions](https://github.com/preset-io/testmcpy/discussions)**
|
|
24
25
|
|
|
25
26
|
---
|
|
26
27
|
|
|
@@ -317,6 +318,8 @@ testmcpy run tests/ --model claude-haiku-4-5
|
|
|
317
318
|
|
|
318
319
|
## Commands Reference
|
|
319
320
|
|
|
321
|
+
The highlights are below — the full reference for all 38 commands lives at **[preset-io.github.io/testmcpy/cli](https://preset-io.github.io/testmcpy/cli)**.
|
|
322
|
+
|
|
320
323
|
| Command | Description |
|
|
321
324
|
|---------|-------------|
|
|
322
325
|
| **Setup** | |
|
|
@@ -332,6 +335,12 @@ testmcpy run tests/ --model claude-haiku-4-5
|
|
|
332
335
|
| `testmcpy research` | Test LLM tool-calling capabilities |
|
|
333
336
|
| `testmcpy chat` | Interactive chat with MCP tools |
|
|
334
337
|
| `testmcpy compare` | Multi-model comparison |
|
|
338
|
+
| **Quality & Benchmarking** | |
|
|
339
|
+
| `testmcpy bench` | Run a suite across models × profiles × repeats |
|
|
340
|
+
| `testmcpy conformance` | Run the official MCP spec conformance suite |
|
|
341
|
+
| `testmcpy score` | Grade tool surface for LLM usability (0-100, A-F) |
|
|
342
|
+
| `testmcpy scan` | Static security scan of tool metadata (SARIF output) |
|
|
343
|
+
| `testmcpy matrix` / `leaderboard` / `flaky` | Per-test × per-config analytics |
|
|
335
344
|
| **Advanced** | |
|
|
336
345
|
| `testmcpy baseline-save` | Save current test results as a named baseline |
|
|
337
346
|
| `testmcpy baseline-compare` | Compare a run against a saved baseline |
|
|
@@ -379,7 +388,7 @@ Environment variables are also supported: `MCP_AUTH_TOKEN`, `MCP_JWT_URL`, `MCP_
|
|
|
379
388
|
|
|
380
389
|
## Web Interface
|
|
381
390
|
|
|
382
|
-
Optional React-based UI
|
|
391
|
+
Optional React-based UI for visual testing and analytics — every page is documented at **[preset-io.github.io/testmcpy/web-ui](https://preset-io.github.io/testmcpy/web-ui)**:
|
|
383
392
|
|
|
384
393
|

|
|
385
394
|
|
|
@@ -397,11 +406,9 @@ testmcpy serve
|
|
|
397
406
|
| `/tests` | Test Manager | YAML test browser, execution, results |
|
|
398
407
|
| `/reports` | Reports | All test results, evaluations, cost analysis |
|
|
399
408
|
| `/chat` | Chat Interface | Multi-turn conversation with MCP tools |
|
|
400
|
-
| `/
|
|
401
|
-
| `/
|
|
402
|
-
| `/
|
|
403
|
-
| `/mcp-health` | MCP Health | Server health monitoring |
|
|
404
|
-
| `/security` | Security Dashboard | Security analysis |
|
|
409
|
+
| `/performance` | Performance | Per-test matrix and config leaderboard (also serves `/metrics`, `/compare`) |
|
|
410
|
+
| `/servers` | Servers | Health monitoring + cross-server schema compatibility (also serves `/mcp-health`, `/compatibility`) |
|
|
411
|
+
| `/security` | Security Dashboard | Security evaluator results and risk summary |
|
|
405
412
|
| `/generation-history` | Generation History | AI test generation logs |
|
|
406
413
|
| `/auth-debugger` | Auth Debugger | Auth flow debugging |
|
|
407
414
|
| `/config` | Configuration | Settings and environment |
|
|
@@ -418,7 +425,19 @@ Access at `http://localhost:8000`.
|
|
|
418
425
|
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/auth-debugger.png" alt="Auth Debugger page"><br><sub>Auth Debugger — step through OAuth / JWT / Bearer flows</sub></td>
|
|
419
426
|
</tr>
|
|
420
427
|
<tr>
|
|
428
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/metrics.png" alt="Performance matrix page"><br><sub>Performance — per-test results across model and MCP configurations</sub></td>
|
|
429
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/compare.png" alt="Leaderboard page"><br><sub>Leaderboard — configs ranked by pass rate, cost-per-pass, latency</sub></td>
|
|
430
|
+
</tr>
|
|
431
|
+
<tr>
|
|
432
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/security.png" alt="Security Dashboard page"><br><sub>Security Dashboard — security evaluator results and risk summary</sub></td>
|
|
433
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/compatibility.png" alt="Schema compatibility page"><br><sub>Schema Compat — cross-server tool schema compatibility matrix</sub></td>
|
|
434
|
+
</tr>
|
|
435
|
+
<tr>
|
|
436
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/mcp-health.png" alt="Server health page"><br><sub>Servers — MCP server health monitoring</sub></td>
|
|
421
437
|
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/mcp-profiles.png" alt="MCP Profiles page"><br><sub>MCP Profiles — manage MCP service connections</sub></td>
|
|
438
|
+
</tr>
|
|
439
|
+
<tr>
|
|
440
|
+
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/llm-profiles.png" alt="LLM Profiles page"><br><sub>LLM Profiles — provider configurations with model pricing</sub></td>
|
|
422
441
|
<td align="center"><img src="https://raw.githubusercontent.com/preset-io/testmcpy/main/docs/screenshots/config.png" alt="Configuration page"><br><sub>Configuration — current settings and client snippets</sub></td>
|
|
423
442
|
</tr>
|
|
424
443
|
</table>
|
|
@@ -540,7 +559,7 @@ class MyEvaluator(BaseEvaluator):
|
|
|
540
559
|
)
|
|
541
560
|
```
|
|
542
561
|
|
|
543
|
-
See **[Evaluator Reference](
|
|
562
|
+
See the **[Evaluator Reference](https://preset-io.github.io/testmcpy/concepts/evaluators)** and the **[Custom Evaluators guide](https://preset-io.github.io/testmcpy/guides/custom-evaluators)** for complete documentation.
|
|
544
563
|
|
|
545
564
|
## Examples
|
|
546
565
|
|
|
@@ -561,7 +580,7 @@ We welcome contributions! Whether it's bug reports, feature requests, documentat
|
|
|
561
580
|
|
|
562
581
|
- **Issues**: [Report bugs or request features](https://github.com/preset-io/testmcpy/issues)
|
|
563
582
|
- **Discussions**: [Ask questions and share ideas](https://github.com/preset-io/testmcpy/discussions)
|
|
564
|
-
- **Documentation**:
|
|
583
|
+
- **Documentation**: [preset-io.github.io/testmcpy](https://preset-io.github.io/testmcpy) (agent-facing source docs live in [context/](context/))
|
|
565
584
|
- **Examples**: Explore [examples/](examples/) for sample code
|
|
566
585
|
|
|
567
586
|
## License
|
|
@@ -93,7 +93,7 @@ testmcpy = [
|
|
|
93
93
|
|
|
94
94
|
[project]
|
|
95
95
|
name = "testmcpy"
|
|
96
|
-
version = "0.
|
|
96
|
+
version = "0.10.3"
|
|
97
97
|
description = "A comprehensive testing framework for validating LLM tool calling capabilities with MCP services"
|
|
98
98
|
authors = [{name = "Amin Ghadersohi"}]
|
|
99
99
|
license = "Apache-2.0"
|
|
@@ -104,40 +104,32 @@ def add_mcp():
|
|
|
104
104
|
# Step 5: Test Connection
|
|
105
105
|
console.print("\n[bold yellow]Step 5: Test Connection[/bold yellow]")
|
|
106
106
|
if Confirm.ask("Test connection now?", default=True):
|
|
107
|
-
from testmcpy.mcp_profiles import AuthConfig, MCPServer
|
|
108
|
-
|
|
109
|
-
test_url = mcp_url if transport == "sse" else f"stdio://{command}"
|
|
110
|
-
mcp_server = MCPServer(
|
|
111
|
-
name=name,
|
|
112
|
-
mcp_url=test_url,
|
|
113
|
-
auth=AuthConfig(auth_type=auth_config.get("type", "none")),
|
|
114
|
-
timeout=timeout,
|
|
115
|
-
rate_limit_rpm=rate_limit,
|
|
116
|
-
transport=transport,
|
|
117
|
-
command=command if transport == "stdio" else None,
|
|
118
|
-
args=args_str.split() if args_str else None,
|
|
119
|
-
)
|
|
120
|
-
|
|
121
107
|
console.print("[dim]Connecting...[/dim]")
|
|
122
108
|
try:
|
|
123
|
-
from testmcpy.src.mcp_client import MCPClient
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
)
|
|
133
|
-
|
|
109
|
+
from testmcpy.src.mcp_client import MCPClient, MCPError, StdioMCPClient
|
|
110
|
+
|
|
111
|
+
if transport == "stdio":
|
|
112
|
+
client: MCPClient | StdioMCPClient = StdioMCPClient(
|
|
113
|
+
command=command, args=args_str.split() if args_str else None
|
|
114
|
+
)
|
|
115
|
+
else:
|
|
116
|
+
client = MCPClient(mcp_url, auth=auth_config)
|
|
117
|
+
|
|
118
|
+
async def _test_connection():
|
|
119
|
+
try:
|
|
120
|
+
await client.initialize(timeout=float(timeout))
|
|
121
|
+
return await client.list_tools(timeout=float(timeout))
|
|
122
|
+
finally:
|
|
123
|
+
await client.close()
|
|
124
|
+
|
|
125
|
+
tools = asyncio.run(_test_connection())
|
|
134
126
|
console.print(f"[green]Connected! Found {len(tools)} tools.[/green]")
|
|
135
127
|
if tools:
|
|
136
128
|
tool_names = [t.name if hasattr(t, "name") else str(t) for t in tools[:5]]
|
|
137
129
|
console.print(
|
|
138
130
|
f"[dim] Tools: {', '.join(tool_names)}{'...' if len(tools) > 5 else ''}[/dim]"
|
|
139
131
|
)
|
|
140
|
-
except (ConnectionError, TimeoutError, OSError, RuntimeError, ValueError) as e:
|
|
132
|
+
except (MCPError, ConnectionError, TimeoutError, OSError, RuntimeError, ValueError) as e:
|
|
141
133
|
console.print(f"[red]Connection failed: {e}[/red]")
|
|
142
134
|
if not Confirm.ask("Continue anyway?", default=True):
|
|
143
135
|
raise typer.Abort()
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""MCP profile management endpoints."""
|
|
2
2
|
|
|
3
3
|
import copy
|
|
4
|
+
import logging
|
|
4
5
|
import re
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
|
|
@@ -14,7 +15,9 @@ from testmcpy.server.helpers import (
|
|
|
14
15
|
load_mcp_yaml,
|
|
15
16
|
save_mcp_yaml,
|
|
16
17
|
)
|
|
17
|
-
from testmcpy.src.mcp_client import MCPClient
|
|
18
|
+
from testmcpy.src.mcp_client import MCPClient, MCPError, StdioMCPClient
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
18
21
|
|
|
19
22
|
router = APIRouter(prefix="/api/mcp", tags=["mcp-profiles"])
|
|
20
23
|
|
|
@@ -87,6 +90,15 @@ class MCPReorderRequest(BaseModel):
|
|
|
87
90
|
to_index: int
|
|
88
91
|
|
|
89
92
|
|
|
93
|
+
class TestConnectionRequest(BaseModel):
|
|
94
|
+
mcp_url: str
|
|
95
|
+
transport: str = "sse"
|
|
96
|
+
command: str | None = None
|
|
97
|
+
args: list[str] | None = None
|
|
98
|
+
auth: AuthConfig | None = None
|
|
99
|
+
timeout: int | None = None
|
|
100
|
+
|
|
101
|
+
|
|
90
102
|
# Helper to get the mcp_clients dict from api module
|
|
91
103
|
def get_mcp_clients() -> dict[str, MCPClient]:
|
|
92
104
|
"""Get the global mcp_clients dict from api module."""
|
|
@@ -872,3 +884,45 @@ async def test_mcp_connection(profile_id: str, mcp_index: int):
|
|
|
872
884
|
raise
|
|
873
885
|
except Exception as e:
|
|
874
886
|
raise HTTPException(status_code=500, detail=str(e))
|
|
887
|
+
|
|
888
|
+
|
|
889
|
+
@router.post("/test-connection")
|
|
890
|
+
async def test_connection_standalone(request: TestConnectionRequest):
|
|
891
|
+
"""Test connection to an MCP server from an inline config.
|
|
892
|
+
|
|
893
|
+
Used by the Add MCP wizard to test a server before it is saved to any
|
|
894
|
+
profile (unlike /profiles/{id}/test-connection/{idx}, which tests a
|
|
895
|
+
saved MCP).
|
|
896
|
+
"""
|
|
897
|
+
timeout = float(request.timeout) if request.timeout else 30.0
|
|
898
|
+
|
|
899
|
+
if request.transport == "stdio":
|
|
900
|
+
command = request.command or request.mcp_url.removeprefix("stdio://")
|
|
901
|
+
if not command:
|
|
902
|
+
raise HTTPException(status_code=400, detail="command is required for stdio transport")
|
|
903
|
+
client: MCPClient | StdioMCPClient = StdioMCPClient(command=command, args=request.args)
|
|
904
|
+
else:
|
|
905
|
+
if not request.mcp_url:
|
|
906
|
+
raise HTTPException(status_code=400, detail="mcp_url is required")
|
|
907
|
+
# AuthConfig already matches the {type, token, ...} dict shape
|
|
908
|
+
# MCPClient._setup_auth() reads (it tolerates extra keys).
|
|
909
|
+
auth_dict = request.auth.model_dump(exclude_none=True) if request.auth else {"type": "none"}
|
|
910
|
+
client = MCPClient(request.mcp_url, auth=auth_dict)
|
|
911
|
+
|
|
912
|
+
try:
|
|
913
|
+
await client.initialize(timeout=timeout)
|
|
914
|
+
tools = await client.list_tools(timeout=timeout)
|
|
915
|
+
return {
|
|
916
|
+
"success": True,
|
|
917
|
+
"status": "connected",
|
|
918
|
+
"message": f"Successfully connected — found {len(tools)} tools",
|
|
919
|
+
"tool_count": len(tools),
|
|
920
|
+
"tools": [tool.name for tool in tools],
|
|
921
|
+
}
|
|
922
|
+
except (MCPError, ConnectionError, TimeoutError, OSError, RuntimeError, ValueError) as e:
|
|
923
|
+
return {"success": False, "status": "error", "message": f"Connection failed: {str(e)}"}
|
|
924
|
+
finally:
|
|
925
|
+
try:
|
|
926
|
+
await client.close()
|
|
927
|
+
except (MCPError, ConnectionError, OSError, RuntimeError) as e:
|
|
928
|
+
logger.warning("Failed to close test client: %s", e)
|
|
@@ -13,7 +13,7 @@ from testmcpy.config import get_config
|
|
|
13
13
|
from testmcpy.mcp_profiles import load_profile
|
|
14
14
|
from testmcpy.server.state import get_default_mcp_client, get_mcp_clients
|
|
15
15
|
from testmcpy.src.llm_integration import create_llm_provider
|
|
16
|
-
from testmcpy.src.mcp_client import MCPClient, MCPError
|
|
16
|
+
from testmcpy.src.mcp_client import MCPClient, MCPError, MCPToolCall
|
|
17
17
|
|
|
18
18
|
logger = logging.getLogger(__name__)
|
|
19
19
|
|
|
@@ -1010,16 +1010,25 @@ async def compare_tools(request: ToolCompareRequest):
|
|
|
1010
1010
|
start_time = time.time()
|
|
1011
1011
|
|
|
1012
1012
|
# Initialize client
|
|
1013
|
-
client = MCPClient(
|
|
1013
|
+
client = MCPClient(
|
|
1014
|
+
base_url=mcp_config.mcp_url,
|
|
1015
|
+
auth=mcp_config.auth.to_dict() if mcp_config.auth else None,
|
|
1016
|
+
)
|
|
1014
1017
|
await client.initialize()
|
|
1015
1018
|
|
|
1016
1019
|
# Call the tool
|
|
1017
1020
|
tool_result = await client.call_tool(
|
|
1018
|
-
name=request.tool_name, arguments=request.parameters
|
|
1021
|
+
MCPToolCall(name=request.tool_name, arguments=request.parameters)
|
|
1019
1022
|
)
|
|
1020
1023
|
|
|
1021
|
-
|
|
1022
|
-
|
|
1024
|
+
if tool_result.is_error:
|
|
1025
|
+
result["success"] = False
|
|
1026
|
+
result["error"] = tool_result.error_message or "Tool call failed"
|
|
1027
|
+
else:
|
|
1028
|
+
from testmcpy.server.api import _serialize_tool_content
|
|
1029
|
+
|
|
1030
|
+
result["success"] = True
|
|
1031
|
+
result["result"] = _serialize_tool_content(tool_result.content)
|
|
1023
1032
|
result["duration_ms"] = (time.time() - start_time) * 1000
|
|
1024
1033
|
|
|
1025
1034
|
except Exception as e:
|
|
@@ -1029,9 +1038,9 @@ async def compare_tools(request: ToolCompareRequest):
|
|
|
1029
1038
|
finally:
|
|
1030
1039
|
if client:
|
|
1031
1040
|
try:
|
|
1032
|
-
await client.
|
|
1033
|
-
except
|
|
1034
|
-
|
|
1041
|
+
await client.close()
|
|
1042
|
+
except (MCPError, ConnectionError, OSError, RuntimeError) as e:
|
|
1043
|
+
logger.warning("Failed to close comparison client: %s", e)
|
|
1035
1044
|
|
|
1036
1045
|
return result
|
|
1037
1046
|
|
|
@@ -1116,7 +1125,10 @@ async def debug_tool(tool_name: str, request: ToolDebugRequest):
|
|
|
1116
1125
|
profile_data = load_profile(request.profile)
|
|
1117
1126
|
if profile_data and profile_data.mcps:
|
|
1118
1127
|
mcp_config = profile_data.mcps[0]
|
|
1119
|
-
client = MCPClient(
|
|
1128
|
+
client = MCPClient(
|
|
1129
|
+
base_url=mcp_config.mcp_url,
|
|
1130
|
+
auth=mcp_config.auth.to_dict() if mcp_config.auth else None,
|
|
1131
|
+
)
|
|
1120
1132
|
await client.initialize()
|
|
1121
1133
|
mcp_clients[client_key] = client
|
|
1122
1134
|
except Exception as e:
|
|
@@ -1137,7 +1149,15 @@ async def debug_tool(tool_name: str, request: ToolDebugRequest):
|
|
|
1137
1149
|
|
|
1138
1150
|
# Step 2: Call tool
|
|
1139
1151
|
try:
|
|
1140
|
-
|
|
1152
|
+
tool_result = await client.call_tool(
|
|
1153
|
+
MCPToolCall(name=tool_name, arguments=request.parameters)
|
|
1154
|
+
)
|
|
1155
|
+
if tool_result.is_error:
|
|
1156
|
+
raise MCPError(tool_result.error_message or "Tool call failed")
|
|
1157
|
+
|
|
1158
|
+
from testmcpy.server.api import _serialize_tool_content
|
|
1159
|
+
|
|
1160
|
+
response = _serialize_tool_content(tool_result.content)
|
|
1141
1161
|
|
|
1142
1162
|
steps.append(
|
|
1143
1163
|
{
|