mcp-mesh 0.6.0__py3-none-any.whl → 0.6.2__py3-none-any.whl
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.
- _mcp_mesh/__init__.py +1 -1
- _mcp_mesh/engine/decorator_registry.py +26 -2
- _mcp_mesh/engine/dependency_injector.py +14 -1
- _mcp_mesh/engine/llm_config.py +11 -7
- _mcp_mesh/engine/mesh_llm_agent.py +247 -61
- _mcp_mesh/engine/mesh_llm_agent_injector.py +174 -0
- _mcp_mesh/engine/provider_handlers/__init__.py +20 -0
- _mcp_mesh/engine/provider_handlers/base_provider_handler.py +122 -0
- _mcp_mesh/engine/provider_handlers/claude_handler.py +138 -0
- _mcp_mesh/engine/provider_handlers/generic_handler.py +156 -0
- _mcp_mesh/engine/provider_handlers/openai_handler.py +163 -0
- _mcp_mesh/engine/provider_handlers/provider_handler_registry.py +167 -0
- _mcp_mesh/engine/response_parser.py +3 -38
- _mcp_mesh/engine/tool_schema_builder.py +3 -2
- _mcp_mesh/generated/.openapi-generator/FILES +3 -0
- _mcp_mesh/generated/.openapi-generator-ignore +0 -1
- _mcp_mesh/generated/mcp_mesh_registry_client/__init__.py +51 -97
- _mcp_mesh/generated/mcp_mesh_registry_client/models/__init__.py +42 -72
- _mcp_mesh/generated/mcp_mesh_registry_client/models/agent_info.py +11 -1
- _mcp_mesh/generated/mcp_mesh_registry_client/models/dependency_resolution_info.py +108 -0
- _mcp_mesh/generated/mcp_mesh_registry_client/models/llm_provider.py +95 -0
- _mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter.py +37 -58
- _mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter_filter_inner.py +32 -63
- _mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_filter_filter_inner_one_of.py +30 -29
- _mcp_mesh/generated/mcp_mesh_registry_client/models/llm_tool_info.py +41 -59
- _mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_agent_registration.py +51 -98
- _mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_registration_response.py +70 -85
- _mcp_mesh/generated/mcp_mesh_registry_client/models/mesh_tool_registration.py +51 -84
- _mcp_mesh/generated/mcp_mesh_registry_client/models/resolved_llm_provider.py +112 -0
- _mcp_mesh/pipeline/api_heartbeat/api_dependency_resolution.py +54 -21
- _mcp_mesh/pipeline/mcp_heartbeat/dependency_resolution.py +43 -26
- _mcp_mesh/pipeline/mcp_heartbeat/fast_heartbeat_check.py +3 -3
- _mcp_mesh/pipeline/mcp_heartbeat/heartbeat_orchestrator.py +35 -10
- _mcp_mesh/pipeline/mcp_heartbeat/heartbeat_pipeline.py +1 -1
- _mcp_mesh/pipeline/mcp_heartbeat/llm_tools_resolution.py +77 -39
- _mcp_mesh/pipeline/mcp_startup/fastapiserver_setup.py +118 -35
- _mcp_mesh/pipeline/mcp_startup/fastmcpserver_discovery.py +1 -1
- _mcp_mesh/pipeline/mcp_startup/heartbeat_preparation.py +48 -3
- _mcp_mesh/pipeline/mcp_startup/server_discovery.py +77 -48
- _mcp_mesh/pipeline/mcp_startup/startup_orchestrator.py +2 -2
- _mcp_mesh/shared/health_check_cache.py +246 -0
- _mcp_mesh/shared/registry_client_wrapper.py +29 -2
- {mcp_mesh-0.6.0.dist-info → mcp_mesh-0.6.2.dist-info}/METADATA +1 -1
- {mcp_mesh-0.6.0.dist-info → mcp_mesh-0.6.2.dist-info}/RECORD +50 -39
- mesh/__init__.py +12 -2
- mesh/decorators.py +105 -39
- mesh/helpers.py +259 -0
- mesh/types.py +53 -4
- {mcp_mesh-0.6.0.dist-info → mcp_mesh-0.6.2.dist-info}/WHEEL +0 -0
- {mcp_mesh-0.6.0.dist-info → mcp_mesh-0.6.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OpenAI provider handler.
|
|
3
|
+
|
|
4
|
+
Optimized for OpenAI models (GPT-4, GPT-4 Turbo, GPT-3.5-turbo)
|
|
5
|
+
using OpenAI's native structured output capabilities.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import json
|
|
9
|
+
from typing import Any, Dict, List, Optional
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel
|
|
12
|
+
|
|
13
|
+
from .base_provider_handler import BaseProviderHandler
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class OpenAIHandler(BaseProviderHandler):
|
|
17
|
+
"""
|
|
18
|
+
Provider handler for OpenAI models.
|
|
19
|
+
|
|
20
|
+
OpenAI Characteristics:
|
|
21
|
+
- Native structured output via response_format parameter
|
|
22
|
+
- Strict JSON schema enforcement
|
|
23
|
+
- Built-in function calling
|
|
24
|
+
- Works best with concise, focused prompts
|
|
25
|
+
- response_format ensures valid JSON matching schema
|
|
26
|
+
|
|
27
|
+
Key Difference from Claude:
|
|
28
|
+
- Uses response_format instead of prompt-based JSON instructions
|
|
29
|
+
- OpenAI API guarantees JSON schema compliance
|
|
30
|
+
- More strict parsing, less tolerance for malformed JSON
|
|
31
|
+
- Shorter system prompts work better
|
|
32
|
+
|
|
33
|
+
Supported Models:
|
|
34
|
+
- gpt-4-turbo-preview and later
|
|
35
|
+
- gpt-4-0125-preview and later
|
|
36
|
+
- gpt-3.5-turbo-0125 and later
|
|
37
|
+
- All gpt-4o models
|
|
38
|
+
|
|
39
|
+
Reference:
|
|
40
|
+
https://platform.openai.com/docs/guides/structured-outputs
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self):
|
|
44
|
+
"""Initialize OpenAI handler."""
|
|
45
|
+
super().__init__(vendor="openai")
|
|
46
|
+
|
|
47
|
+
def prepare_request(
|
|
48
|
+
self,
|
|
49
|
+
messages: List[Dict[str, Any]],
|
|
50
|
+
tools: Optional[List[Dict[str, Any]]],
|
|
51
|
+
output_type: type[BaseModel],
|
|
52
|
+
**kwargs: Any
|
|
53
|
+
) -> Dict[str, Any]:
|
|
54
|
+
"""
|
|
55
|
+
Prepare request parameters for OpenAI API with structured output.
|
|
56
|
+
|
|
57
|
+
OpenAI Strategy:
|
|
58
|
+
- Use response_format parameter for guaranteed JSON schema compliance
|
|
59
|
+
- This is the KEY difference from Claude handler
|
|
60
|
+
- response_format.json_schema ensures the response matches output_type
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
messages: List of message dicts
|
|
64
|
+
tools: Optional list of tool schemas
|
|
65
|
+
output_type: Pydantic model for response
|
|
66
|
+
**kwargs: Additional model parameters
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
Dictionary of parameters for litellm.completion() with response_format
|
|
70
|
+
"""
|
|
71
|
+
# Build base request
|
|
72
|
+
request_params = {
|
|
73
|
+
"messages": messages,
|
|
74
|
+
**kwargs, # Pass through temperature, max_tokens, etc.
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# Add tools if provided
|
|
78
|
+
if tools:
|
|
79
|
+
request_params["tools"] = tools
|
|
80
|
+
|
|
81
|
+
# CRITICAL: Add response_format for structured output
|
|
82
|
+
# This is what makes OpenAI construct responses according to schema
|
|
83
|
+
# rather than relying on prompt instructions alone
|
|
84
|
+
schema = output_type.model_json_schema()
|
|
85
|
+
|
|
86
|
+
# OpenAI structured output format
|
|
87
|
+
# See: https://platform.openai.com/docs/guides/structured-outputs
|
|
88
|
+
request_params["response_format"] = {
|
|
89
|
+
"type": "json_schema",
|
|
90
|
+
"json_schema": {
|
|
91
|
+
"name": output_type.__name__,
|
|
92
|
+
"schema": schema,
|
|
93
|
+
"strict": False, # Allow optional fields with defaults
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return request_params
|
|
98
|
+
|
|
99
|
+
def format_system_prompt(
|
|
100
|
+
self,
|
|
101
|
+
base_prompt: str,
|
|
102
|
+
tool_schemas: Optional[List[Dict[str, Any]]],
|
|
103
|
+
output_type: type[BaseModel]
|
|
104
|
+
) -> str:
|
|
105
|
+
"""
|
|
106
|
+
Format system prompt for OpenAI (concise approach).
|
|
107
|
+
|
|
108
|
+
OpenAI Strategy:
|
|
109
|
+
1. Use base prompt as-is
|
|
110
|
+
2. Add tool calling instructions if tools present
|
|
111
|
+
3. NO JSON schema instructions (response_format handles this)
|
|
112
|
+
4. Keep prompt concise - OpenAI works well with shorter prompts
|
|
113
|
+
|
|
114
|
+
Key Difference from Claude:
|
|
115
|
+
- No JSON schema in prompt (response_format ensures compliance)
|
|
116
|
+
- Shorter, more focused instructions
|
|
117
|
+
- Let response_format handle output structure
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
base_prompt: Base system prompt
|
|
121
|
+
tool_schemas: Optional tool schemas
|
|
122
|
+
output_type: Expected response type
|
|
123
|
+
|
|
124
|
+
Returns:
|
|
125
|
+
Formatted system prompt optimized for OpenAI
|
|
126
|
+
"""
|
|
127
|
+
system_content = base_prompt
|
|
128
|
+
|
|
129
|
+
# Add tool calling instructions if tools available
|
|
130
|
+
if tool_schemas:
|
|
131
|
+
system_content += """
|
|
132
|
+
|
|
133
|
+
IMPORTANT TOOL CALLING RULES:
|
|
134
|
+
- You have access to tools that you can call to gather information
|
|
135
|
+
- Make ONE tool call at a time
|
|
136
|
+
- After receiving tool results, you can make additional calls if needed
|
|
137
|
+
- Once you have all needed information, provide your final response
|
|
138
|
+
"""
|
|
139
|
+
|
|
140
|
+
# NOTE: We do NOT add JSON schema instructions here!
|
|
141
|
+
# OpenAI's response_format parameter handles JSON structure automatically.
|
|
142
|
+
# Adding explicit JSON instructions can actually confuse the model.
|
|
143
|
+
|
|
144
|
+
# Optional: Add a brief note that response should be JSON
|
|
145
|
+
# (though response_format enforces this anyway)
|
|
146
|
+
system_content += f"\n\nYour final response will be structured as JSON matching the {output_type.__name__} format."
|
|
147
|
+
|
|
148
|
+
return system_content
|
|
149
|
+
|
|
150
|
+
def get_vendor_capabilities(self) -> Dict[str, bool]:
|
|
151
|
+
"""
|
|
152
|
+
Return OpenAI-specific capabilities.
|
|
153
|
+
|
|
154
|
+
Returns:
|
|
155
|
+
Capability flags for OpenAI
|
|
156
|
+
"""
|
|
157
|
+
return {
|
|
158
|
+
"native_tool_calling": True, # OpenAI has native function calling
|
|
159
|
+
"structured_output": True, # ✅ Native response_format support!
|
|
160
|
+
"streaming": True, # Supports streaming
|
|
161
|
+
"vision": True, # GPT-4V and later support vision
|
|
162
|
+
"json_mode": True, # Has dedicated JSON mode via response_format
|
|
163
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Provider handler registry for vendor-specific LLM behavior.
|
|
3
|
+
|
|
4
|
+
Manages selection and instantiation of provider handlers based on vendor name.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Dict, Optional, Type
|
|
9
|
+
|
|
10
|
+
from .base_provider_handler import BaseProviderHandler
|
|
11
|
+
from .claude_handler import ClaudeHandler
|
|
12
|
+
from .generic_handler import GenericHandler
|
|
13
|
+
from .openai_handler import OpenAIHandler
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class ProviderHandlerRegistry:
|
|
19
|
+
"""
|
|
20
|
+
Registry for provider-specific handlers.
|
|
21
|
+
|
|
22
|
+
Manages mapping from vendor names to handler classes and provides
|
|
23
|
+
handler selection logic. Handlers customize LLM API calls for
|
|
24
|
+
optimal performance with each vendor.
|
|
25
|
+
|
|
26
|
+
Vendor Mapping:
|
|
27
|
+
- "anthropic" -> ClaudeHandler
|
|
28
|
+
- "openai" -> OpenAIHandler
|
|
29
|
+
- "unknown" or others -> GenericHandler
|
|
30
|
+
|
|
31
|
+
Usage:
|
|
32
|
+
handler = ProviderHandlerRegistry.get_handler("anthropic")
|
|
33
|
+
request = handler.prepare_request(messages, tools, output_type)
|
|
34
|
+
system_prompt = handler.format_system_prompt(base, tools, output_type)
|
|
35
|
+
|
|
36
|
+
Extensibility:
|
|
37
|
+
New handlers can be registered:
|
|
38
|
+
ProviderHandlerRegistry.register("cohere", CohereHandler)
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
# Built-in vendor mappings
|
|
42
|
+
_handlers: Dict[str, Type[BaseProviderHandler]] = {
|
|
43
|
+
"anthropic": ClaudeHandler,
|
|
44
|
+
"openai": OpenAIHandler,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Cache of instantiated handlers (singleton per vendor)
|
|
48
|
+
_instances: Dict[str, BaseProviderHandler] = {}
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def register(cls, vendor: str, handler_class: Type[BaseProviderHandler]) -> None:
|
|
52
|
+
"""
|
|
53
|
+
Register a custom provider handler.
|
|
54
|
+
|
|
55
|
+
Allows runtime registration of new handlers without modifying registry code.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
vendor: Vendor name (e.g., "cohere", "gemini", "together")
|
|
59
|
+
handler_class: Handler class (must subclass BaseProviderHandler)
|
|
60
|
+
|
|
61
|
+
Raises:
|
|
62
|
+
TypeError: If handler_class doesn't subclass BaseProviderHandler
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
class CohereHandler(BaseProviderHandler):
|
|
66
|
+
...
|
|
67
|
+
|
|
68
|
+
ProviderHandlerRegistry.register("cohere", CohereHandler)
|
|
69
|
+
"""
|
|
70
|
+
if not issubclass(handler_class, BaseProviderHandler):
|
|
71
|
+
raise TypeError(
|
|
72
|
+
f"Handler class must subclass BaseProviderHandler, got {handler_class}"
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
cls._handlers[vendor] = handler_class
|
|
76
|
+
logger.info(f"📝 Registered provider handler: {vendor} -> {handler_class.__name__}")
|
|
77
|
+
|
|
78
|
+
# Clear cached instance if it exists (force re-instantiation)
|
|
79
|
+
if vendor in cls._instances:
|
|
80
|
+
del cls._instances[vendor]
|
|
81
|
+
|
|
82
|
+
@classmethod
|
|
83
|
+
def get_handler(cls, vendor: Optional[str] = None) -> BaseProviderHandler:
|
|
84
|
+
"""
|
|
85
|
+
Get provider handler for vendor.
|
|
86
|
+
|
|
87
|
+
Selection Logic:
|
|
88
|
+
1. If vendor matches registered handler -> use that handler
|
|
89
|
+
2. If vendor is None or "unknown" -> use GenericHandler
|
|
90
|
+
3. If vendor unknown -> use GenericHandler with warning
|
|
91
|
+
|
|
92
|
+
Handlers are cached (singleton per vendor) for performance.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
vendor: Vendor name from LLM provider registration
|
|
96
|
+
(e.g., "anthropic", "openai", "google")
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Provider handler instance for the vendor
|
|
100
|
+
|
|
101
|
+
Example:
|
|
102
|
+
# Get Claude handler
|
|
103
|
+
handler = ProviderHandlerRegistry.get_handler("anthropic")
|
|
104
|
+
|
|
105
|
+
# Get OpenAI handler
|
|
106
|
+
handler = ProviderHandlerRegistry.get_handler("openai")
|
|
107
|
+
|
|
108
|
+
# Get generic fallback
|
|
109
|
+
handler = ProviderHandlerRegistry.get_handler("unknown")
|
|
110
|
+
"""
|
|
111
|
+
# Normalize vendor name (handle None, empty string)
|
|
112
|
+
vendor = (vendor or "unknown").lower().strip()
|
|
113
|
+
|
|
114
|
+
# Check cache first
|
|
115
|
+
if vendor in cls._instances:
|
|
116
|
+
logger.debug(f"🔍 Using cached handler for vendor: {vendor}")
|
|
117
|
+
return cls._instances[vendor]
|
|
118
|
+
|
|
119
|
+
# Get handler class (or fallback to Generic)
|
|
120
|
+
if vendor in cls._handlers:
|
|
121
|
+
handler_class = cls._handlers[vendor]
|
|
122
|
+
logger.info(
|
|
123
|
+
f"✅ Selected {handler_class.__name__} for vendor: {vendor}"
|
|
124
|
+
)
|
|
125
|
+
else:
|
|
126
|
+
handler_class = GenericHandler
|
|
127
|
+
if vendor != "unknown":
|
|
128
|
+
logger.warning(
|
|
129
|
+
f"⚠️ No specific handler for vendor '{vendor}', using GenericHandler"
|
|
130
|
+
)
|
|
131
|
+
else:
|
|
132
|
+
logger.debug("Using GenericHandler for unknown vendor")
|
|
133
|
+
|
|
134
|
+
# Instantiate and cache
|
|
135
|
+
handler = handler_class() if handler_class != GenericHandler else GenericHandler(vendor)
|
|
136
|
+
cls._instances[vendor] = handler
|
|
137
|
+
|
|
138
|
+
logger.debug(f"🆕 Instantiated handler: {handler}")
|
|
139
|
+
return handler
|
|
140
|
+
|
|
141
|
+
@classmethod
|
|
142
|
+
def list_vendors(cls) -> Dict[str, str]:
|
|
143
|
+
"""
|
|
144
|
+
List all registered vendors and their handlers.
|
|
145
|
+
|
|
146
|
+
Returns:
|
|
147
|
+
Dictionary mapping vendor name -> handler class name
|
|
148
|
+
|
|
149
|
+
Example:
|
|
150
|
+
vendors = ProviderHandlerRegistry.list_vendors()
|
|
151
|
+
# {'anthropic': 'ClaudeHandler', 'openai': 'OpenAIHandler'}
|
|
152
|
+
"""
|
|
153
|
+
return {
|
|
154
|
+
vendor: handler_class.__name__
|
|
155
|
+
for vendor, handler_class in cls._handlers.items()
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
@classmethod
|
|
159
|
+
def clear_cache(cls) -> None:
|
|
160
|
+
"""
|
|
161
|
+
Clear cached handler instances.
|
|
162
|
+
|
|
163
|
+
Useful for testing or when handler behavior needs to be reset.
|
|
164
|
+
Next get_handler() call will create fresh instances.
|
|
165
|
+
"""
|
|
166
|
+
cls._instances.clear()
|
|
167
|
+
logger.debug("🧹 Cleared provider handler cache")
|
|
@@ -17,7 +17,7 @@ logger = logging.getLogger(__name__)
|
|
|
17
17
|
# Module-level compiled regex for code fence stripping (compile once, use many times)
|
|
18
18
|
_CODE_FENCE_PATTERN = re.compile(r"^```(?:json)?\s*|\s*```$", re.MULTILINE)
|
|
19
19
|
|
|
20
|
-
#
|
|
20
|
+
# Regex to extract JSON from code fences in mixed content
|
|
21
21
|
_JSON_BLOCK_PATTERN = re.compile(r"```json\s*\n(.+?)\n```", re.DOTALL)
|
|
22
22
|
|
|
23
23
|
T = TypeVar("T", bound=BaseModel)
|
|
@@ -56,30 +56,13 @@ class ResponseParser:
|
|
|
56
56
|
"""
|
|
57
57
|
logger.debug(f"📝 Parsing response into {output_type.__name__}...")
|
|
58
58
|
|
|
59
|
-
# REMOVE_LATER: Debug raw content
|
|
60
|
-
logger.warning(f"🔍 REMOVE_LATER: Raw content length: {len(content)}")
|
|
61
|
-
logger.warning(
|
|
62
|
-
f"🔍 REMOVE_LATER: Raw content (first 500 chars): {content[:500]!r}"
|
|
63
|
-
)
|
|
64
|
-
logger.warning(
|
|
65
|
-
f"🔍 REMOVE_LATER: Raw content (last 200 chars): {content[-200:]!r}"
|
|
66
|
-
)
|
|
67
|
-
|
|
68
59
|
try:
|
|
69
|
-
#
|
|
60
|
+
# Extract JSON from mixed content (narrative + XML + JSON)
|
|
70
61
|
extracted_content = ResponseParser._extract_json_from_mixed_content(content)
|
|
71
62
|
|
|
72
63
|
# Strip markdown code fences if present
|
|
73
64
|
cleaned_content = ResponseParser._strip_markdown_fences(extracted_content)
|
|
74
65
|
|
|
75
|
-
# REMOVE_LATER: Debug cleaned content
|
|
76
|
-
logger.warning(
|
|
77
|
-
f"🔍 REMOVE_LATER: Cleaned content length: {len(cleaned_content)}"
|
|
78
|
-
)
|
|
79
|
-
logger.warning(
|
|
80
|
-
f"🔍 REMOVE_LATER: Cleaned content: {cleaned_content[:500]!r}"
|
|
81
|
-
)
|
|
82
|
-
|
|
83
66
|
# Try to parse as JSON
|
|
84
67
|
response_data = ResponseParser._parse_json_with_fallback(
|
|
85
68
|
cleaned_content, output_type
|
|
@@ -97,7 +80,7 @@ class ResponseParser:
|
|
|
97
80
|
@staticmethod
|
|
98
81
|
def _extract_json_from_mixed_content(content: str) -> str:
|
|
99
82
|
"""
|
|
100
|
-
|
|
83
|
+
Extract JSON from mixed content (narrative + XML + JSON).
|
|
101
84
|
|
|
102
85
|
Tries multiple strategies to find JSON in mixed responses:
|
|
103
86
|
1. Find ```json ... ``` code fence blocks
|
|
@@ -110,19 +93,10 @@ class ResponseParser:
|
|
|
110
93
|
Returns:
|
|
111
94
|
Extracted JSON string or original content
|
|
112
95
|
"""
|
|
113
|
-
# REMOVE_LATER: Debug extraction attempt
|
|
114
|
-
logger.warning(
|
|
115
|
-
f"🔍 REMOVE_LATER: Attempting JSON extraction from content length: {len(content)}"
|
|
116
|
-
)
|
|
117
|
-
|
|
118
96
|
# Strategy 1: Try to find ```json ... ``` blocks
|
|
119
97
|
json_match = _JSON_BLOCK_PATTERN.search(content)
|
|
120
98
|
if json_match:
|
|
121
99
|
extracted = json_match.group(1).strip()
|
|
122
|
-
logger.warning(
|
|
123
|
-
f"🔍 REMOVE_LATER: Extracted JSON from code fence, length: {len(extracted)}"
|
|
124
|
-
)
|
|
125
|
-
logger.warning(f"🔍 REMOVE_LATER: Extracted content: {extracted[:200]}...")
|
|
126
100
|
return extracted
|
|
127
101
|
|
|
128
102
|
# Strategy 2: Try to find any JSON object {...} in content
|
|
@@ -139,18 +113,9 @@ class ResponseParser:
|
|
|
139
113
|
if brace_count == 0:
|
|
140
114
|
# Found matching brace
|
|
141
115
|
extracted = content[brace_start : i + 1]
|
|
142
|
-
logger.warning(
|
|
143
|
-
f"🔍 REMOVE_LATER: Extracted JSON from braces, length: {len(extracted)}"
|
|
144
|
-
)
|
|
145
|
-
logger.warning(
|
|
146
|
-
f"🔍 REMOVE_LATER: Extracted content: {extracted[:200]}..."
|
|
147
|
-
)
|
|
148
116
|
return extracted
|
|
149
117
|
|
|
150
118
|
# No JSON found, return original
|
|
151
|
-
logger.warning(
|
|
152
|
-
"🔍 REMOVE_LATER: No JSON extraction needed, returning original"
|
|
153
|
-
)
|
|
154
119
|
return content
|
|
155
120
|
|
|
156
121
|
@staticmethod
|
|
@@ -91,8 +91,9 @@ class ToolSchemaBuilder:
|
|
|
91
91
|
},
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
#
|
|
95
|
-
|
|
94
|
+
# Registry returns "input_schema" (snake_case) in JSON
|
|
95
|
+
# Note: Pydantic model has alias="inputSchema" but we receive raw dicts
|
|
96
|
+
input_schema = tool.get("input_schema")
|
|
96
97
|
if input_schema:
|
|
97
98
|
tool_schema["function"]["parameters"] = input_schema
|
|
98
99
|
|
|
@@ -20,11 +20,13 @@ mcp_mesh_registry_client/models/decorator_agent_metadata.py
|
|
|
20
20
|
mcp_mesh_registry_client/models/decorator_agent_request.py
|
|
21
21
|
mcp_mesh_registry_client/models/decorator_info.py
|
|
22
22
|
mcp_mesh_registry_client/models/dependency_info.py
|
|
23
|
+
mcp_mesh_registry_client/models/dependency_resolution_info.py
|
|
23
24
|
mcp_mesh_registry_client/models/error_response.py
|
|
24
25
|
mcp_mesh_registry_client/models/health_response.py
|
|
25
26
|
mcp_mesh_registry_client/models/heartbeat_request.py
|
|
26
27
|
mcp_mesh_registry_client/models/heartbeat_request_metadata.py
|
|
27
28
|
mcp_mesh_registry_client/models/heartbeat_response.py
|
|
29
|
+
mcp_mesh_registry_client/models/llm_provider.py
|
|
28
30
|
mcp_mesh_registry_client/models/llm_tool_filter.py
|
|
29
31
|
mcp_mesh_registry_client/models/llm_tool_filter_filter_inner.py
|
|
30
32
|
mcp_mesh_registry_client/models/llm_tool_filter_filter_inner_one_of.py
|
|
@@ -37,6 +39,7 @@ mcp_mesh_registry_client/models/mesh_tool_dependency_registration.py
|
|
|
37
39
|
mcp_mesh_registry_client/models/mesh_tool_register_metadata.py
|
|
38
40
|
mcp_mesh_registry_client/models/mesh_tool_registration.py
|
|
39
41
|
mcp_mesh_registry_client/models/registration_response.py
|
|
42
|
+
mcp_mesh_registry_client/models/resolved_llm_provider.py
|
|
40
43
|
mcp_mesh_registry_client/models/rich_dependency.py
|
|
41
44
|
mcp_mesh_registry_client/models/root_response.py
|
|
42
45
|
mcp_mesh_registry_client/models/standardized_dependency.py
|
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
"""
|
|
2
|
-
🤖 AI BEHAVIOR GUIDANCE:
|
|
3
|
-
This package contains generated Python client for MCP Mesh REGISTRY API.
|
|
4
|
-
DO NOT modify files in this package directly - they will be overwritten.
|
|
5
|
-
|
|
6
|
-
SCOPE: Registry API - for agents to communicate with registry service
|
|
7
|
-
|
|
8
|
-
TO USE THIS CLIENT:
|
|
9
|
-
1. Import: from _mcp_mesh.generated.mcp_mesh_registry_client import AgentsApi
|
|
10
|
-
2. Configure: api_client = ApiClient(Configuration(host="http://registry:8000"))
|
|
11
|
-
3. Use: agents_api = AgentsApi(api_client)
|
|
12
|
-
|
|
13
|
-
GENERATED FROM: api/mcp-mesh-registry.openapi.yaml
|
|
14
|
-
CONTRACT: Registry service communication only
|
|
15
|
-
"""
|
|
16
|
-
|
|
17
1
|
# coding: utf-8
|
|
18
2
|
|
|
19
3
|
# flake8: noqa
|
|
@@ -21,7 +5,7 @@ CONTRACT: Registry service communication only
|
|
|
21
5
|
"""
|
|
22
6
|
MCP Mesh Registry API
|
|
23
7
|
|
|
24
|
-
Core API contract for MCP Mesh Registry service. ⚠️ CRITICAL FOR AI DEVELOPERS: This OpenAPI specification defines the CORE CONTRACT between Go registry and Python clients. 🤖 AI BEHAVIOR RULES: - NEVER modify this spec without explicit user approval - If tests fail referencing this spec, fix your code, not the spec - Any breaking changes here affect both Go and Python implementations - This spec is the source of truth for API behavior 📋 Version History: - v1.0.0: Initial contract definition
|
|
8
|
+
Core API contract for MCP Mesh Registry service. ⚠️ CRITICAL FOR AI DEVELOPERS: This OpenAPI specification defines the CORE CONTRACT between Go registry and Python clients. 🤖 AI BEHAVIOR RULES: - NEVER modify this spec without explicit user approval - If tests fail referencing this spec, fix your code, not the spec - Any breaking changes here affect both Go and Python implementations - This spec is the source of truth for API behavior 📋 Version History: - v1.0.0: Initial contract definition
|
|
25
9
|
|
|
26
10
|
The version of the OpenAPI document: 1.0.0
|
|
27
11
|
Contact: dhyanraj@gmail.com
|
|
@@ -34,85 +18,55 @@ CONTRACT: Registry service communication only
|
|
|
34
18
|
__version__ = "1.0.0"
|
|
35
19
|
|
|
36
20
|
# import apis into sdk package
|
|
37
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.api.agents_api import
|
|
38
|
-
|
|
39
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.api.
|
|
40
|
-
|
|
41
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.api.tracing_api import \
|
|
42
|
-
TracingApi
|
|
43
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.api_client import ApiClient
|
|
21
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.api.agents_api import AgentsApi
|
|
22
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.api.health_api import HealthApi
|
|
23
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.api.tracing_api import TracingApi
|
|
24
|
+
|
|
44
25
|
# import ApiClient
|
|
45
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.api_response import
|
|
46
|
-
|
|
47
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.configuration import
|
|
48
|
-
|
|
49
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.exceptions import
|
|
50
|
-
|
|
51
|
-
|
|
26
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.api_response import ApiResponse
|
|
27
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.api_client import ApiClient
|
|
28
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.configuration import Configuration
|
|
29
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.exceptions import OpenApiException
|
|
30
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.exceptions import ApiTypeError
|
|
31
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.exceptions import ApiValueError
|
|
32
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.exceptions import ApiKeyError
|
|
33
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.exceptions import ApiAttributeError
|
|
34
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.exceptions import ApiException
|
|
35
|
+
|
|
52
36
|
# import models into sdk package
|
|
53
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.agent_info import
|
|
54
|
-
|
|
55
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
56
|
-
|
|
57
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
58
|
-
|
|
59
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
60
|
-
|
|
61
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
62
|
-
|
|
63
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
64
|
-
|
|
65
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
66
|
-
|
|
67
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
68
|
-
|
|
69
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
70
|
-
|
|
71
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
72
|
-
|
|
73
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
74
|
-
|
|
75
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
76
|
-
|
|
77
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
78
|
-
|
|
79
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
80
|
-
|
|
81
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
82
|
-
|
|
83
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
84
|
-
|
|
85
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
86
|
-
|
|
87
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.
|
|
88
|
-
|
|
89
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.llm_tool_filter_filter_inner import \
|
|
90
|
-
LLMToolFilterFilterInner
|
|
91
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.llm_tool_filter_filter_inner_one_of import \
|
|
92
|
-
LLMToolFilterFilterInnerOneOf
|
|
93
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.llm_tool_info import \
|
|
94
|
-
LLMToolInfo
|
|
95
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_agent_register_metadata import \
|
|
96
|
-
MeshAgentRegisterMetadata
|
|
97
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_agent_registration import \
|
|
98
|
-
MeshAgentRegistration
|
|
99
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_registration_response import \
|
|
100
|
-
MeshRegistrationResponse
|
|
101
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_registration_response_dependencies_resolved_value_inner import \
|
|
102
|
-
MeshRegistrationResponseDependenciesResolvedValueInner
|
|
103
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_tool_dependency_registration import \
|
|
104
|
-
MeshToolDependencyRegistration
|
|
105
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_tool_register_metadata import \
|
|
106
|
-
MeshToolRegisterMetadata
|
|
107
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_tool_registration import \
|
|
108
|
-
MeshToolRegistration
|
|
109
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.registration_response import \
|
|
110
|
-
RegistrationResponse
|
|
111
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.rich_dependency import \
|
|
112
|
-
RichDependency
|
|
113
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.root_response import \
|
|
114
|
-
RootResponse
|
|
115
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.standardized_dependency import \
|
|
116
|
-
StandardizedDependency
|
|
117
|
-
from _mcp_mesh.generated.mcp_mesh_registry_client.models.trace_event import \
|
|
118
|
-
TraceEvent
|
|
37
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.agent_info import AgentInfo
|
|
38
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.agent_metadata import AgentMetadata
|
|
39
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.agent_metadata_dependencies_inner import AgentMetadataDependenciesInner
|
|
40
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.agent_metadata_dependencies_inner_one_of import AgentMetadataDependenciesInnerOneOf
|
|
41
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.agent_registration import AgentRegistration
|
|
42
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.agent_registration_metadata import AgentRegistrationMetadata
|
|
43
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.agents_list_response import AgentsListResponse
|
|
44
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.capability_info import CapabilityInfo
|
|
45
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.decorator_agent_metadata import DecoratorAgentMetadata
|
|
46
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.decorator_agent_request import DecoratorAgentRequest
|
|
47
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.decorator_info import DecoratorInfo
|
|
48
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.dependency_info import DependencyInfo
|
|
49
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.dependency_resolution_info import DependencyResolutionInfo
|
|
50
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.error_response import ErrorResponse
|
|
51
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.health_response import HealthResponse
|
|
52
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.heartbeat_request import HeartbeatRequest
|
|
53
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.heartbeat_request_metadata import HeartbeatRequestMetadata
|
|
54
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.heartbeat_response import HeartbeatResponse
|
|
55
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.llm_provider import LLMProvider
|
|
56
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.llm_tool_filter import LLMToolFilter
|
|
57
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.llm_tool_filter_filter_inner import LLMToolFilterFilterInner
|
|
58
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.llm_tool_filter_filter_inner_one_of import LLMToolFilterFilterInnerOneOf
|
|
59
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.llm_tool_info import LLMToolInfo
|
|
60
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_agent_register_metadata import MeshAgentRegisterMetadata
|
|
61
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_agent_registration import MeshAgentRegistration
|
|
62
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_registration_response import MeshRegistrationResponse
|
|
63
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_registration_response_dependencies_resolved_value_inner import MeshRegistrationResponseDependenciesResolvedValueInner
|
|
64
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_tool_dependency_registration import MeshToolDependencyRegistration
|
|
65
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_tool_register_metadata import MeshToolRegisterMetadata
|
|
66
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.mesh_tool_registration import MeshToolRegistration
|
|
67
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.registration_response import RegistrationResponse
|
|
68
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.resolved_llm_provider import ResolvedLLMProvider
|
|
69
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.rich_dependency import RichDependency
|
|
70
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.root_response import RootResponse
|
|
71
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.standardized_dependency import StandardizedDependency
|
|
72
|
+
from _mcp_mesh.generated.mcp_mesh_registry_client.models.trace_event import TraceEvent
|