testmcpy 0.2.6__tar.gz → 0.2.8__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.
Files changed (127) hide show
  1. {testmcpy-0.2.6/testmcpy.egg-info → testmcpy-0.2.8}/PKG-INFO +1 -1
  2. {testmcpy-0.2.6 → testmcpy-0.2.8}/pyproject.toml +1 -1
  3. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/auth_flow_recorder.py +18 -14
  4. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/routers/mcp_profiles.py +42 -7
  5. {testmcpy-0.2.6 → testmcpy-0.2.8/testmcpy.egg-info}/PKG-INFO +1 -1
  6. {testmcpy-0.2.6 → testmcpy-0.2.8}/LICENSE +0 -0
  7. {testmcpy-0.2.6 → testmcpy-0.2.8}/MANIFEST.in +0 -0
  8. {testmcpy-0.2.6 → testmcpy-0.2.8}/NOTICE +0 -0
  9. {testmcpy-0.2.6 → testmcpy-0.2.8}/README.md +0 -0
  10. {testmcpy-0.2.6 → testmcpy-0.2.8}/setup.cfg +0 -0
  11. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/__init__.py +0 -0
  12. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/auth_debugger.py +0 -0
  13. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/cli/__init__.py +0 -0
  14. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/cli/app.py +0 -0
  15. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/cli/commands/__init__.py +0 -0
  16. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/cli/commands/mcp.py +0 -0
  17. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/cli/commands/run.py +0 -0
  18. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/cli/commands/server.py +0 -0
  19. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/cli/commands/tools.py +0 -0
  20. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/cli/commands/tui.py +0 -0
  21. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/config.py +0 -0
  22. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/core/__init__.py +0 -0
  23. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/core/chat_session.py +0 -0
  24. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/core/docs_optimizer.py +0 -0
  25. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/core/mcp_manager.py +0 -0
  26. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/core/tool_comparison.py +0 -0
  27. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/core/tool_discovery.py +0 -0
  28. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/error_handlers.py +0 -0
  29. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/evals/__init__.py +0 -0
  30. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/evals/auth_evaluators.py +0 -0
  31. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/evals/base_evaluators.py +0 -0
  32. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/__init__.py +0 -0
  33. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/base.py +0 -0
  34. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/curl.py +0 -0
  35. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/graphql.py +0 -0
  36. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/javascript_client.py +0 -0
  37. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/json_yaml.py +0 -0
  38. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/protobuf.py +0 -0
  39. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/python.py +0 -0
  40. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/python_client.py +0 -0
  41. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/thrift.py +0 -0
  42. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/typescript.py +0 -0
  43. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/formatters/typescript_client.py +0 -0
  44. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/llm_profiles.py +0 -0
  45. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/mcp_profiles.py +0 -0
  46. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/research/claude_sdk_detailed_exploration.py +0 -0
  47. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/research/claude_sdk_poc.py +0 -0
  48. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/research/claude_sdk_working_poc.py +0 -0
  49. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/research/test_ollama_tools.py +0 -0
  50. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/__init__.py +0 -0
  51. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/api.py +0 -0
  52. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/api.py.bak +0 -0
  53. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/helpers/__init__.py +0 -0
  54. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/helpers/mcp_config.py +0 -0
  55. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/models.py +0 -0
  56. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/routers/__init__.py +0 -0
  57. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/routers/auth.py +0 -0
  58. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/routers/generation_logs.py +0 -0
  59. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/routers/llm.py +0 -0
  60. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/routers/results.py +0 -0
  61. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/routers/smoke_reports.py +0 -0
  62. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/routers/test_profiles.py +0 -0
  63. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/routers/tests.py +0 -0
  64. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/routers/tools.py +0 -0
  65. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/state.py +0 -0
  66. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/tool_compare_endpoint.py +0 -0
  67. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/server/websocket.py +0 -0
  68. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/smoke_test.py +0 -0
  69. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/src/__init__.py +0 -0
  70. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/src/llm_integration.py +0 -0
  71. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/src/mcp_client.py +0 -0
  72. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/src/model_registry.py +0 -0
  73. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/src/models.py +0 -0
  74. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/src/runner_tools.py +0 -0
  75. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/src/test_runner.py +0 -0
  76. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/storage.py +0 -0
  77. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/test_profiles.py +0 -0
  78. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/README.md +0 -0
  79. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/dist/assets/index-CaEBvXci.css +0 -0
  80. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/dist/assets/index-DbhZ0GnU.js +0 -0
  81. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/dist/index.html +0 -0
  82. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/index.html +0 -0
  83. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/package-lock.json +0 -0
  84. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/package.json +0 -0
  85. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/postcss.config.js +0 -0
  86. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/App.jsx +0 -0
  87. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/CompareToolsTab.jsx +0 -0
  88. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/ErrorAlert.jsx +0 -0
  89. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/ErrorBoundary.jsx +0 -0
  90. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/LLMProfileSelector.jsx +0 -0
  91. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/LoadingSpinner.jsx +0 -0
  92. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/MCPProfileSelector.jsx +0 -0
  93. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/OptimizeDocsModal.jsx +0 -0
  94. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/ParameterCard.jsx +0 -0
  95. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/SchemaCodeViewer.jsx +0 -0
  96. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/SkeletonLoader.jsx +0 -0
  97. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/TestGenerationModal.jsx +0 -0
  98. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/TestProfileSelector.jsx +0 -0
  99. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/TestResultPanel.jsx +0 -0
  100. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/TestStatusIndicator.jsx +0 -0
  101. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/ToolComparison.jsx +0 -0
  102. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/ToolDebugModal.jsx +0 -0
  103. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/components/TypeBadge.jsx +0 -0
  104. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/contexts/TestRunContext.jsx +0 -0
  105. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/hooks/useKeyboardShortcuts.js +0 -0
  106. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/hooks/useSafeFetch.js +0 -0
  107. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/index.css +0 -0
  108. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/main.jsx +0 -0
  109. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/pages/AuthDebugger.jsx +0 -0
  110. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/pages/ChatInterface.jsx +0 -0
  111. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/pages/Configuration.jsx +0 -0
  112. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/pages/GenerationHistory.jsx +0 -0
  113. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/pages/LLMProfiles.jsx +0 -0
  114. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/pages/MCPExplorer.jsx +0 -0
  115. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/pages/MCPProfiles.jsx +0 -0
  116. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/pages/ProfilesManager.jsx +0 -0
  117. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/pages/Reports.jsx +0 -0
  118. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/pages/TestManager.jsx +0 -0
  119. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/utils/__tests__/formatConverters.test.js +0 -0
  120. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/src/utils/formatConverters.js +0 -0
  121. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/tailwind.config.js +0 -0
  122. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy/ui/vite.config.js +0 -0
  123. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy.egg-info/SOURCES.txt +0 -0
  124. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy.egg-info/dependency_links.txt +0 -0
  125. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy.egg-info/entry_points.txt +0 -0
  126. {testmcpy-0.2.6 → testmcpy-0.2.8}/testmcpy.egg-info/requires.txt +0 -0
  127. {testmcpy-0.2.6 → testmcpy-0.2.8}/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.2.6
3
+ Version: 0.2.8
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
@@ -88,7 +88,7 @@ testmcpy = [
88
88
 
89
89
  [project]
90
90
  name = "testmcpy"
91
- version = "0.2.6"
91
+ version = "0.2.8"
92
92
  description = "A comprehensive testing framework for validating LLM tool calling capabilities with MCP services"
93
93
  authors = [{name = "Amin Ghadersohi"}]
94
94
  license = "Apache-2.0"
@@ -235,7 +235,19 @@ class AuthFlowRecorder:
235
235
  if storage_dir is None:
236
236
  storage_dir = Path.home() / ".testmcpy" / "auth_flows"
237
237
  self.storage_dir = Path(storage_dir)
238
- self.storage_dir.mkdir(parents=True, exist_ok=True)
238
+ try:
239
+ # Check if parent path exists as a file (not directory)
240
+ testmcpy_dir = Path.home() / ".testmcpy"
241
+ if testmcpy_dir.exists() and not testmcpy_dir.is_dir():
242
+ # Remove the file and create directory instead
243
+ testmcpy_dir.unlink()
244
+ self.storage_dir.mkdir(parents=True, exist_ok=True)
245
+ except OSError as e:
246
+ # Fall back to temp directory if home directory fails
247
+ import tempfile
248
+
249
+ self.storage_dir = Path(tempfile.gettempdir()) / "testmcpy" / "auth_flows"
250
+ self.storage_dir.mkdir(parents=True, exist_ok=True)
239
251
  self.console = Console()
240
252
  self.current_recording: AuthFlowRecording | None = None
241
253
 
@@ -328,9 +340,7 @@ class AuthFlowRecorder:
328
340
  self.current_recording = None
329
341
  return recording
330
342
 
331
- def save_recording(
332
- self, recording: AuthFlowRecording, filename: str | None = None
333
- ) -> Path:
343
+ def save_recording(self, recording: AuthFlowRecording, filename: str | None = None) -> Path:
334
344
  """Save a recording to a JSON file.
335
345
 
336
346
  Args:
@@ -341,9 +351,7 @@ class AuthFlowRecorder:
341
351
  Path to the saved file
342
352
  """
343
353
  if filename is None:
344
- timestamp = datetime.fromtimestamp(recording.start_time).strftime(
345
- "%Y%m%d_%H%M%S"
346
- )
354
+ timestamp = datetime.fromtimestamp(recording.start_time).strftime("%Y%m%d_%H%M%S")
347
355
  filename = f"{recording.auth_type}_{recording.flow_name}_{timestamp}.json"
348
356
 
349
357
  # Sanitize filename
@@ -451,8 +459,7 @@ class AuthFlowRecorder:
451
459
  },
452
460
  "differences": {
453
461
  "success_changed": recording1.success != recording2.success,
454
- "step_count_delta": recording2.get_step_count()
455
- - recording1.get_step_count(),
462
+ "step_count_delta": recording2.get_step_count() - recording1.get_step_count(),
456
463
  "duration_delta": recording2.get_duration() - recording1.get_duration(),
457
464
  "step_differences": [],
458
465
  },
@@ -525,8 +532,7 @@ class AuthFlowRecorder:
525
532
  icon = "✓" if step.success else "✗"
526
533
  color = "green" if step.success else "red"
527
534
  branch = tree.add(
528
- f"[{color}]{i}. {icon} {step.step_name}[/{color}] "
529
- f"[dim]({step.duration:.2f}s)[/dim]"
535
+ f"[{color}]{i}. {icon} {step.step_name}[/{color}] [dim]({step.duration:.2f}s)[/dim]"
530
536
  )
531
537
 
532
538
  # Add step details
@@ -625,9 +631,7 @@ class AuthFlowRecorder:
625
631
  else:
626
632
  self.console.print("\n[green]No step differences found[/green]")
627
633
 
628
- def export_to_json(
629
- self, recording: AuthFlowRecording, filepath: str | Path
630
- ) -> Path:
634
+ def export_to_json(self, recording: AuthFlowRecording, filepath: str | Path) -> Path:
631
635
  """Export a recording to a JSON file.
632
636
 
633
637
  Args:
@@ -97,10 +97,9 @@ def get_mcp_clients() -> dict[str, MCPClient]:
97
97
 
98
98
  @router.post("/profiles/create-config")
99
99
  async def create_mcp_config():
100
- """Create .mcp_services.yaml from the example file."""
100
+ """Create .mcp_services.yaml with a default template."""
101
101
  try:
102
- example_file = Path(".mcp_services.yaml.example")
103
- config_file = Path(".mcp_services.yaml")
102
+ config_file = Path.cwd() / ".mcp_services.yaml"
104
103
 
105
104
  if config_file.exists():
106
105
  return {
@@ -108,14 +107,50 @@ async def create_mcp_config():
108
107
  "error": "Configuration file already exists at .mcp_services.yaml",
109
108
  }
110
109
 
111
- if not example_file.exists():
112
- return {"success": False, "error": "Example file .mcp_services.yaml.example not found"}
110
+ # Default template
111
+ default_template = """# MCP Services Configuration
112
+ # Documentation: https://github.com/preset-io/testmcpy
113
113
 
114
- shutil.copy(example_file, config_file)
114
+ # Default profile to use when none specified
115
+ default: my-profile
116
+
117
+ # Profile definitions
118
+ profiles:
119
+ my-profile:
120
+ # Display name for the profile
121
+ name: My MCP Server
122
+
123
+ # MCP servers in this profile
124
+ mcps:
125
+ my-server:
126
+ # Server name (displayed in UI)
127
+ name: My Server
128
+
129
+ # How to start the server
130
+ # Option 1: Command to run
131
+ command: npx
132
+ args:
133
+ - -y
134
+ - "@my-org/my-mcp-server"
135
+
136
+ # Option 2: URL for remote server
137
+ # url: http://localhost:3000/mcp
138
+
139
+ # Environment variables (optional)
140
+ # env:
141
+ # API_KEY: your-api-key
142
+
143
+ # Authentication (optional)
144
+ # auth:
145
+ # type: bearer
146
+ # token_env: MY_API_TOKEN
147
+ """
148
+
149
+ config_file.write_text(default_template)
115
150
 
116
151
  return {
117
152
  "success": True,
118
- "message": "Created .mcp_services.yaml from example template",
153
+ "message": "Created .mcp_services.yaml with default template",
119
154
  "path": str(config_file.absolute()),
120
155
  }
121
156
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: testmcpy
3
- Version: 0.2.6
3
+ Version: 0.2.8
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
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes