mcp-proxy-adapter 2.1.0__py3-none-any.whl → 2.1.1__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.
- docs/README.md +172 -0
- docs/README_ru.md +172 -0
- docs/architecture.md +251 -0
- docs/architecture_ru.md +343 -0
- docs/command_development.md +250 -0
- docs/command_development_ru.md +593 -0
- docs/deployment.md +251 -0
- docs/deployment_ru.md +1298 -0
- docs/examples.md +254 -0
- docs/examples_ru.md +401 -0
- docs/mcp_proxy_adapter.md +251 -0
- docs/mcp_proxy_adapter_ru.md +405 -0
- docs/quickstart.md +251 -0
- docs/quickstart_ru.md +397 -0
- docs/testing.md +255 -0
- docs/testing_ru.md +469 -0
- docs/validation_ru.md +287 -0
- examples/analyze_config.py +141 -0
- examples/basic_integration.py +161 -0
- examples/docstring_and_schema_example.py +60 -0
- examples/extension_example.py +60 -0
- examples/help_best_practices.py +67 -0
- examples/help_usage.py +64 -0
- examples/mcp_proxy_client.py +131 -0
- examples/mcp_proxy_config.json +175 -0
- examples/openapi_server.py +369 -0
- examples/project_structure_example.py +47 -0
- examples/testing_example.py +53 -0
- mcp_proxy_adapter/__init__.py +17 -0
- mcp_proxy_adapter/adapter.py +697 -0
- mcp_proxy_adapter/models.py +47 -0
- mcp_proxy_adapter/registry.py +439 -0
- mcp_proxy_adapter/schema.py +257 -0
- {mcp_proxy_adapter-2.1.0.dist-info → mcp_proxy_adapter-2.1.1.dist-info}/METADATA +2 -2
- mcp_proxy_adapter-2.1.1.dist-info/RECORD +61 -0
- mcp_proxy_adapter-2.1.1.dist-info/top_level.txt +5 -0
- scripts/code_analyzer/code_analyzer.py +328 -0
- scripts/code_analyzer/register_commands.py +446 -0
- scripts/publish.py +85 -0
- tests/conftest.py +12 -0
- tests/test_adapter.py +529 -0
- tests/test_adapter_coverage.py +274 -0
- tests/test_basic_dispatcher.py +169 -0
- tests/test_command_registry.py +328 -0
- tests/test_examples.py +32 -0
- tests/test_mcp_proxy_adapter.py +568 -0
- tests/test_mcp_proxy_adapter_basic.py +262 -0
- tests/test_part1.py +348 -0
- tests/test_part2.py +524 -0
- tests/test_schema.py +358 -0
- tests/test_simple_adapter.py +251 -0
- adapters/__init__.py +0 -16
- cli/__init__.py +0 -12
- cli/__main__.py +0 -79
- cli/command_runner.py +0 -233
- generators/__init__.py +0 -14
- generators/endpoint_generator.py +0 -172
- generators/openapi_generator.py +0 -254
- generators/rest_api_generator.py +0 -207
- mcp_proxy_adapter-2.1.0.dist-info/RECORD +0 -28
- mcp_proxy_adapter-2.1.0.dist-info/top_level.txt +0 -7
- openapi_schema/__init__.py +0 -38
- openapi_schema/command_registry.py +0 -312
- openapi_schema/rest_schema.py +0 -510
- openapi_schema/rpc_generator.py +0 -307
- openapi_schema/rpc_schema.py +0 -416
- validators/__init__.py +0 -14
- validators/base_validator.py +0 -23
- {analyzers → mcp_proxy_adapter/analyzers}/__init__.py +0 -0
- {analyzers → mcp_proxy_adapter/analyzers}/docstring_analyzer.py +0 -0
- {analyzers → mcp_proxy_adapter/analyzers}/type_analyzer.py +0 -0
- {dispatchers → mcp_proxy_adapter/dispatchers}/__init__.py +0 -0
- {dispatchers → mcp_proxy_adapter/dispatchers}/base_dispatcher.py +0 -0
- {dispatchers → mcp_proxy_adapter/dispatchers}/json_rpc_dispatcher.py +0 -0
- {validators → mcp_proxy_adapter/validators}/docstring_validator.py +0 -0
- {validators → mcp_proxy_adapter/validators}/metadata_validator.py +0 -0
- {mcp_proxy_adapter-2.1.0.dist-info → mcp_proxy_adapter-2.1.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-2.1.0.dist-info → mcp_proxy_adapter-2.1.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,312 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Command registry for automatic OpenAPI schema generation.
|
3
|
-
Describes all available API commands, their parameters and response formats.
|
4
|
-
"""
|
5
|
-
from typing import Dict, Any, List, Optional, Type, Union, get_type_hints
|
6
|
-
import inspect
|
7
|
-
import docstring_parser
|
8
|
-
from pydantic import BaseModel, Field, create_model
|
9
|
-
|
10
|
-
class CommandParameter:
|
11
|
-
"""Description of a command parameter"""
|
12
|
-
def __init__(self, name: str, type_hint: Type, default=None, description: str = None, required: bool = False):
|
13
|
-
self.name = name
|
14
|
-
self.type_hint = type_hint
|
15
|
-
self.default = default
|
16
|
-
self.description = description
|
17
|
-
self.required = required
|
18
|
-
|
19
|
-
def to_dict(self) -> Dict[str, Any]:
|
20
|
-
"""Converts parameter to dictionary for JSON Schema"""
|
21
|
-
result = {
|
22
|
-
"name": self.name,
|
23
|
-
"type": self._get_type_name(),
|
24
|
-
"description": self.description or f"Parameter {self.name}",
|
25
|
-
"required": self.required
|
26
|
-
}
|
27
|
-
|
28
|
-
if self.default is not None and self.default is not inspect.Parameter.empty:
|
29
|
-
result["default"] = self.default
|
30
|
-
|
31
|
-
return result
|
32
|
-
|
33
|
-
def _get_type_name(self) -> str:
|
34
|
-
"""Gets type name for JSON Schema"""
|
35
|
-
if self.type_hint == str:
|
36
|
-
return "string"
|
37
|
-
elif self.type_hint == int:
|
38
|
-
return "integer"
|
39
|
-
elif self.type_hint == float:
|
40
|
-
return "number"
|
41
|
-
elif self.type_hint == bool:
|
42
|
-
return "boolean"
|
43
|
-
elif self.type_hint == list or self.type_hint == List:
|
44
|
-
return "array"
|
45
|
-
elif self.type_hint == dict or self.type_hint == Dict:
|
46
|
-
return "object"
|
47
|
-
else:
|
48
|
-
return "object"
|
49
|
-
|
50
|
-
|
51
|
-
class CommandInfo:
|
52
|
-
"""Information about a command"""
|
53
|
-
def __init__(self, name: str, handler_func, description: str = None, summary: str = None):
|
54
|
-
self.name = name
|
55
|
-
self.handler_func = handler_func
|
56
|
-
self.description = description or ""
|
57
|
-
self.summary = summary or name.replace("_", " ").capitalize()
|
58
|
-
self.parameters: List[CommandParameter] = []
|
59
|
-
self._parse_parameters()
|
60
|
-
|
61
|
-
def _parse_parameters(self):
|
62
|
-
"""Extracts parameter information from function signature"""
|
63
|
-
sig = inspect.signature(self.handler_func)
|
64
|
-
type_hints = get_type_hints(self.handler_func)
|
65
|
-
docstring = docstring_parser.parse(self.handler_func.__doc__ or "")
|
66
|
-
|
67
|
-
# Create dictionary for finding parameter descriptions in docstring
|
68
|
-
param_descriptions = {param.arg_name: param.description for param in docstring.params}
|
69
|
-
|
70
|
-
for name, param in sig.parameters.items():
|
71
|
-
# Ignore self parameter for class methods
|
72
|
-
if name == 'self':
|
73
|
-
continue
|
74
|
-
|
75
|
-
# Determine parameter type
|
76
|
-
param_type = type_hints.get(name, Any)
|
77
|
-
|
78
|
-
# Determine if parameter is required
|
79
|
-
required = param.default == inspect.Parameter.empty
|
80
|
-
|
81
|
-
# Add parameter
|
82
|
-
self.parameters.append(CommandParameter(
|
83
|
-
name=name,
|
84
|
-
type_hint=param_type,
|
85
|
-
default=None if param.default == inspect.Parameter.empty else param.default,
|
86
|
-
description=param_descriptions.get(name),
|
87
|
-
required=required
|
88
|
-
))
|
89
|
-
|
90
|
-
def to_dict(self) -> Dict[str, Any]:
|
91
|
-
"""Converts command information to dictionary for OpenAPI schema"""
|
92
|
-
return {
|
93
|
-
"name": self.name,
|
94
|
-
"summary": self.summary,
|
95
|
-
"description": self.description,
|
96
|
-
"parameters": [param.to_dict() for param in self.parameters]
|
97
|
-
}
|
98
|
-
|
99
|
-
|
100
|
-
class CommandRegistry:
|
101
|
-
"""API command registry"""
|
102
|
-
def __init__(self):
|
103
|
-
self.commands: Dict[str, CommandInfo] = {}
|
104
|
-
|
105
|
-
def register(self, name: str, handler_func = None, description: str = None, summary: str = None):
|
106
|
-
"""
|
107
|
-
Registers a command in the registry.
|
108
|
-
Can be used as a decorator.
|
109
|
-
|
110
|
-
Args:
|
111
|
-
name: Command name
|
112
|
-
handler_func: Command handler function
|
113
|
-
description: Command description
|
114
|
-
summary: Brief command summary
|
115
|
-
"""
|
116
|
-
def decorator(func):
|
117
|
-
self.commands[name] = CommandInfo(
|
118
|
-
name=name,
|
119
|
-
handler_func=func,
|
120
|
-
description=description or func.__doc__,
|
121
|
-
summary=summary
|
122
|
-
)
|
123
|
-
return func
|
124
|
-
|
125
|
-
if handler_func is not None:
|
126
|
-
return decorator(handler_func)
|
127
|
-
return decorator
|
128
|
-
|
129
|
-
def get_command(self, name: str) -> Optional[CommandInfo]:
|
130
|
-
"""Gets information about a command by its name"""
|
131
|
-
return self.commands.get(name)
|
132
|
-
|
133
|
-
def get_all_commands(self) -> List[CommandInfo]:
|
134
|
-
"""Gets list of all registered commands"""
|
135
|
-
return list(self.commands.values())
|
136
|
-
|
137
|
-
def generate_openapi_components(self) -> Dict[str, Any]:
|
138
|
-
"""
|
139
|
-
Generates OpenAPI schema components based on registered commands.
|
140
|
-
|
141
|
-
Returns:
|
142
|
-
Dict[str, Any]: OpenAPI schema components
|
143
|
-
"""
|
144
|
-
components = {
|
145
|
-
"schemas": {}
|
146
|
-
}
|
147
|
-
|
148
|
-
# Add common schemas for CommandRequest and JsonRpcResponse
|
149
|
-
components["schemas"]["CommandRequest"] = {
|
150
|
-
"type": "object",
|
151
|
-
"required": ["command", "jsonrpc"],
|
152
|
-
"properties": {
|
153
|
-
"jsonrpc": {
|
154
|
-
"type": "string",
|
155
|
-
"description": "JSON-RPC protocol version",
|
156
|
-
"enum": ["2.0"],
|
157
|
-
"default": "2.0"
|
158
|
-
},
|
159
|
-
"id": {
|
160
|
-
"type": ["string", "number", "null"],
|
161
|
-
"description": "Request identifier, used to match requests and responses"
|
162
|
-
},
|
163
|
-
"command": {
|
164
|
-
"type": "string",
|
165
|
-
"title": "Command",
|
166
|
-
"description": "Command name to execute",
|
167
|
-
"enum": list(self.commands.keys())
|
168
|
-
},
|
169
|
-
"params": {
|
170
|
-
"title": "Params",
|
171
|
-
"description": "Command parameters",
|
172
|
-
"oneOf": []
|
173
|
-
}
|
174
|
-
}
|
175
|
-
}
|
176
|
-
|
177
|
-
components["schemas"]["JsonRpcResponse"] = {
|
178
|
-
"type": "object",
|
179
|
-
"required": ["jsonrpc", "success"],
|
180
|
-
"properties": {
|
181
|
-
"jsonrpc": {
|
182
|
-
"type": "string",
|
183
|
-
"description": "JSON-RPC protocol version",
|
184
|
-
"enum": ["2.0"],
|
185
|
-
"default": "2.0"
|
186
|
-
},
|
187
|
-
"success": {
|
188
|
-
"type": "boolean",
|
189
|
-
"description": "Operation success indicator",
|
190
|
-
"default": False
|
191
|
-
},
|
192
|
-
"result": {
|
193
|
-
"description": "Operation result. Present only on successful execution (success=True). Result format depends on the executed command."
|
194
|
-
},
|
195
|
-
"error": {
|
196
|
-
"description": "Error information. Present only when error occurs (success=false).",
|
197
|
-
"type": "object",
|
198
|
-
"required": ["code", "message"],
|
199
|
-
"properties": {
|
200
|
-
"code": {
|
201
|
-
"type": "integer",
|
202
|
-
"description": "Error code (internal code, not HTTP status)",
|
203
|
-
"example": 400
|
204
|
-
},
|
205
|
-
"message": {
|
206
|
-
"type": "string",
|
207
|
-
"description": "Error message description",
|
208
|
-
"example": "Record does not exist: ID 12345"
|
209
|
-
}
|
210
|
-
}
|
211
|
-
},
|
212
|
-
"id": {
|
213
|
-
"type": ["string", "number", "null"],
|
214
|
-
"description": "Request identifier (if specified in request)"
|
215
|
-
}
|
216
|
-
},
|
217
|
-
"example": {
|
218
|
-
"jsonrpc": "2.0",
|
219
|
-
"success": True,
|
220
|
-
"result": {"id": "550e8400-e29b-41d4-a716-446655440000"},
|
221
|
-
"id": "request-1"
|
222
|
-
}
|
223
|
-
}
|
224
|
-
|
225
|
-
# Create schemas for each command's parameters
|
226
|
-
for command_name, command_info in self.commands.items():
|
227
|
-
param_schema_name = f"{command_name.title().replace('_', '')}Params"
|
228
|
-
|
229
|
-
# Create command parameter schema
|
230
|
-
param_schema = {
|
231
|
-
"type": "object",
|
232
|
-
"title": param_schema_name,
|
233
|
-
"description": f"Parameters for command {command_name}",
|
234
|
-
"properties": {},
|
235
|
-
"required": []
|
236
|
-
}
|
237
|
-
|
238
|
-
# Add properties for each parameter
|
239
|
-
for param in command_info.parameters:
|
240
|
-
param_type = param._get_type_name()
|
241
|
-
param_schema["properties"][param.name] = {
|
242
|
-
"type": param_type,
|
243
|
-
"description": param.description or f"Parameter {param.name}"
|
244
|
-
}
|
245
|
-
|
246
|
-
if param.default is not None and param.default is not inspect.Parameter.empty:
|
247
|
-
param_schema["properties"][param.name]["default"] = param.default
|
248
|
-
|
249
|
-
if param.required:
|
250
|
-
param_schema["required"].append(param.name)
|
251
|
-
|
252
|
-
# Add parameter schema to components
|
253
|
-
components["schemas"][param_schema_name] = param_schema
|
254
|
-
|
255
|
-
# Add reference to parameter schema in oneOf list of CommandRequest
|
256
|
-
components["schemas"]["CommandRequest"]["properties"]["params"]["oneOf"].append({
|
257
|
-
"$ref": f"#/components/schemas/{param_schema_name}"
|
258
|
-
})
|
259
|
-
|
260
|
-
# Add null as possible value for parameters
|
261
|
-
components["schemas"]["CommandRequest"]["properties"]["params"]["oneOf"].append({
|
262
|
-
"type": "null"
|
263
|
-
})
|
264
|
-
|
265
|
-
return components
|
266
|
-
|
267
|
-
def generate_examples(self) -> Dict[str, Any]:
|
268
|
-
"""
|
269
|
-
Generates command usage examples for OpenAPI schema.
|
270
|
-
|
271
|
-
Returns:
|
272
|
-
Dict[str, Any]: Command usage examples
|
273
|
-
"""
|
274
|
-
examples = {}
|
275
|
-
|
276
|
-
for command_name, command_info in self.commands.items():
|
277
|
-
# Create base request example
|
278
|
-
example = {
|
279
|
-
"summary": command_info.summary,
|
280
|
-
"value": {
|
281
|
-
"jsonrpc": "2.0",
|
282
|
-
"command": command_name,
|
283
|
-
"params": {},
|
284
|
-
"id": command_name
|
285
|
-
}
|
286
|
-
}
|
287
|
-
|
288
|
-
# Fill example with default parameters or examples
|
289
|
-
for param in command_info.parameters:
|
290
|
-
if param.default is not None and param.default is not inspect.Parameter.empty:
|
291
|
-
example["value"]["params"][param.name] = param.default
|
292
|
-
elif param.type_hint == str:
|
293
|
-
example["value"]["params"][param.name] = f"example_{param.name}"
|
294
|
-
elif param.type_hint == int:
|
295
|
-
example["value"]["params"][param.name] = 1
|
296
|
-
elif param.type_hint == float:
|
297
|
-
example["value"]["params"][param.name] = 1.0
|
298
|
-
elif param.type_hint == bool:
|
299
|
-
example["value"]["params"][param.name] = True
|
300
|
-
elif param.type_hint == list or param.type_hint == List:
|
301
|
-
example["value"]["params"][param.name] = []
|
302
|
-
elif param.type_hint == dict or param.type_hint == Dict:
|
303
|
-
example["value"]["params"][param.name] = {}
|
304
|
-
|
305
|
-
# Add example to examples dictionary
|
306
|
-
examples[f"{command_name}_example"] = example
|
307
|
-
|
308
|
-
return examples
|
309
|
-
|
310
|
-
|
311
|
-
# Create global command registry instance
|
312
|
-
registry = CommandRegistry()
|