mcp-proxy-adapter 6.3.4__py3-none-any.whl → 6.3.5__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_proxy_adapter/__init__.py +9 -5
- mcp_proxy_adapter/__main__.py +1 -1
- mcp_proxy_adapter/api/app.py +227 -176
- mcp_proxy_adapter/api/handlers.py +68 -60
- mcp_proxy_adapter/api/middleware/__init__.py +7 -5
- mcp_proxy_adapter/api/middleware/base.py +19 -16
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
- mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
- mcp_proxy_adapter/api/middleware/factory.py +50 -52
- mcp_proxy_adapter/api/middleware/logging.py +46 -30
- mcp_proxy_adapter/api/middleware/performance.py +19 -16
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
- mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
- mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
- mcp_proxy_adapter/api/schemas.py +69 -43
- mcp_proxy_adapter/api/tool_integration.py +83 -63
- mcp_proxy_adapter/api/tools.py +60 -50
- mcp_proxy_adapter/commands/__init__.py +15 -6
- mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
- mcp_proxy_adapter/commands/base.py +108 -112
- mcp_proxy_adapter/commands/builtin_commands.py +28 -18
- mcp_proxy_adapter/commands/catalog_manager.py +394 -265
- mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
- mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
- mcp_proxy_adapter/commands/command_registry.py +275 -226
- mcp_proxy_adapter/commands/config_command.py +48 -33
- mcp_proxy_adapter/commands/dependency_container.py +22 -23
- mcp_proxy_adapter/commands/dependency_manager.py +65 -56
- mcp_proxy_adapter/commands/echo_command.py +15 -15
- mcp_proxy_adapter/commands/health_command.py +31 -29
- mcp_proxy_adapter/commands/help_command.py +97 -61
- mcp_proxy_adapter/commands/hooks.py +65 -49
- mcp_proxy_adapter/commands/key_management_command.py +148 -147
- mcp_proxy_adapter/commands/load_command.py +58 -40
- mcp_proxy_adapter/commands/plugins_command.py +80 -54
- mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
- mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
- mcp_proxy_adapter/commands/reload_command.py +43 -37
- mcp_proxy_adapter/commands/result.py +26 -33
- mcp_proxy_adapter/commands/role_test_command.py +26 -26
- mcp_proxy_adapter/commands/roles_management_command.py +176 -173
- mcp_proxy_adapter/commands/security_command.py +134 -122
- mcp_proxy_adapter/commands/settings_command.py +47 -56
- mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
- mcp_proxy_adapter/commands/token_management_command.py +129 -158
- mcp_proxy_adapter/commands/transport_management_command.py +41 -36
- mcp_proxy_adapter/commands/unload_command.py +42 -37
- mcp_proxy_adapter/config.py +36 -35
- mcp_proxy_adapter/core/__init__.py +19 -21
- mcp_proxy_adapter/core/app_factory.py +30 -9
- mcp_proxy_adapter/core/app_runner.py +81 -64
- mcp_proxy_adapter/core/auth_validator.py +176 -182
- mcp_proxy_adapter/core/certificate_utils.py +469 -426
- mcp_proxy_adapter/core/client.py +155 -126
- mcp_proxy_adapter/core/client_manager.py +60 -54
- mcp_proxy_adapter/core/client_security.py +108 -88
- mcp_proxy_adapter/core/config_converter.py +176 -143
- mcp_proxy_adapter/core/config_validator.py +12 -4
- mcp_proxy_adapter/core/crl_utils.py +21 -7
- mcp_proxy_adapter/core/errors.py +64 -20
- mcp_proxy_adapter/core/logging.py +34 -29
- mcp_proxy_adapter/core/mtls_asgi.py +29 -25
- mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
- mcp_proxy_adapter/core/protocol_manager.py +154 -104
- mcp_proxy_adapter/core/proxy_client.py +202 -144
- mcp_proxy_adapter/core/proxy_registration.py +7 -3
- mcp_proxy_adapter/core/role_utils.py +139 -125
- mcp_proxy_adapter/core/security_adapter.py +88 -77
- mcp_proxy_adapter/core/security_factory.py +50 -44
- mcp_proxy_adapter/core/security_integration.py +72 -24
- mcp_proxy_adapter/core/server_adapter.py +68 -64
- mcp_proxy_adapter/core/server_engine.py +71 -53
- mcp_proxy_adapter/core/settings.py +68 -58
- mcp_proxy_adapter/core/ssl_utils.py +69 -56
- mcp_proxy_adapter/core/transport_manager.py +72 -60
- mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
- mcp_proxy_adapter/core/utils.py +4 -2
- mcp_proxy_adapter/custom_openapi.py +107 -99
- mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/commands/__init__.py +1 -1
- mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
- mcp_proxy_adapter/examples/debug_request_state.py +38 -19
- mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
- mcp_proxy_adapter/examples/demo_client.py +48 -36
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
- mcp_proxy_adapter/examples/full_application/main.py +27 -2
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
- mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
- mcp_proxy_adapter/examples/generate_certificates.py +31 -16
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
- mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
- mcp_proxy_adapter/examples/run_example.py +23 -5
- mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
- mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
- mcp_proxy_adapter/examples/run_security_tests.py +103 -41
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
- mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
- mcp_proxy_adapter/examples/security_test_client.py +196 -127
- mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
- mcp_proxy_adapter/examples/test_config.py +19 -4
- mcp_proxy_adapter/examples/test_config_generator.py +23 -7
- mcp_proxy_adapter/examples/test_examples.py +84 -56
- mcp_proxy_adapter/examples/universal_client.py +119 -62
- mcp_proxy_adapter/openapi.py +108 -115
- mcp_proxy_adapter/utils/config_generator.py +429 -274
- mcp_proxy_adapter/version.py +1 -2
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
- mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
- mcp_proxy_adapter-6.3.4.dist-info/RECORD +0 -143
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
- {mcp_proxy_adapter-6.3.4.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
mcp_proxy_adapter/api/schemas.py
CHANGED
@@ -11,15 +11,19 @@ class ErrorResponse(BaseModel):
|
|
11
11
|
"""
|
12
12
|
Error response model.
|
13
13
|
"""
|
14
|
+
|
14
15
|
code: int = Field(..., description="Error code")
|
15
16
|
message: str = Field(..., description="Error message")
|
16
|
-
details: Optional[Dict[str, Any]] = Field(
|
17
|
+
details: Optional[Dict[str, Any]] = Field(
|
18
|
+
None, description="Additional error details"
|
19
|
+
)
|
17
20
|
|
18
21
|
|
19
22
|
class ErrorWrapper(BaseModel):
|
20
23
|
"""
|
21
24
|
Wrapper for error response.
|
22
25
|
"""
|
26
|
+
|
23
27
|
error: ErrorResponse
|
24
28
|
|
25
29
|
|
@@ -27,9 +31,12 @@ class JsonRpcRequest(BaseModel):
|
|
27
31
|
"""
|
28
32
|
JSON-RPC request model.
|
29
33
|
"""
|
34
|
+
|
30
35
|
jsonrpc: Literal["2.0"] = Field("2.0", description="JSON-RPC version")
|
31
36
|
method: str = Field(..., description="Method name")
|
32
|
-
params: Optional[Union[Dict[str, Any], List[Any]]] = Field(
|
37
|
+
params: Optional[Union[Dict[str, Any], List[Any]]] = Field(
|
38
|
+
None, description="Method parameters"
|
39
|
+
)
|
33
40
|
id: Optional[Union[str, int]] = Field(None, description="Request ID")
|
34
41
|
|
35
42
|
|
@@ -37,6 +44,7 @@ class JsonRpcError(BaseModel):
|
|
37
44
|
"""
|
38
45
|
JSON-RPC error model.
|
39
46
|
"""
|
47
|
+
|
40
48
|
code: int = Field(..., description="Error code")
|
41
49
|
message: str = Field(..., description="Error message")
|
42
50
|
data: Optional[Dict[str, Any]] = Field(None, description="Additional error data")
|
@@ -46,6 +54,7 @@ class JsonRpcSuccessResponse(BaseModel):
|
|
46
54
|
"""
|
47
55
|
JSON-RPC success response model.
|
48
56
|
"""
|
57
|
+
|
49
58
|
jsonrpc: Literal["2.0"] = Field("2.0", description="JSON-RPC version")
|
50
59
|
result: Dict[str, Any] = Field(..., description="Method result")
|
51
60
|
id: Optional[Union[str, int]] = Field(None, description="Request ID")
|
@@ -55,6 +64,7 @@ class JsonRpcErrorResponse(BaseModel):
|
|
55
64
|
"""
|
56
65
|
JSON-RPC error response model.
|
57
66
|
"""
|
67
|
+
|
58
68
|
jsonrpc: Literal["2.0"] = Field("2.0", description="JSON-RPC version")
|
59
69
|
error: JsonRpcError = Field(..., description="Error information")
|
60
70
|
id: Optional[Union[str, int]] = Field(None, description="Request ID")
|
@@ -64,6 +74,7 @@ class CommandResponse(BaseModel):
|
|
64
74
|
"""
|
65
75
|
Command response model.
|
66
76
|
"""
|
77
|
+
|
67
78
|
success: bool = Field(..., description="Command execution success flag")
|
68
79
|
data: Optional[Dict[str, Any]] = Field(None, description="Result data")
|
69
80
|
message: Optional[str] = Field(None, description="Result message")
|
@@ -74,6 +85,7 @@ class HealthResponse(BaseModel):
|
|
74
85
|
"""
|
75
86
|
Health response model.
|
76
87
|
"""
|
88
|
+
|
77
89
|
status: str = Field(..., description="Server status")
|
78
90
|
version: str = Field(..., description="Server version")
|
79
91
|
uptime: float = Field(..., description="Server uptime in seconds")
|
@@ -84,6 +96,7 @@ class CommandListResponse(BaseModel):
|
|
84
96
|
"""
|
85
97
|
Command list response model.
|
86
98
|
"""
|
99
|
+
|
87
100
|
commands: Dict[str, Dict[str, Any]] = Field(..., description="Available commands")
|
88
101
|
|
89
102
|
|
@@ -91,6 +104,7 @@ class CommandRequest(BaseModel):
|
|
91
104
|
"""
|
92
105
|
Command request model for /cmd endpoint.
|
93
106
|
"""
|
107
|
+
|
94
108
|
command: str = Field(..., description="Command name to execute")
|
95
109
|
params: Optional[Dict[str, Any]] = Field({}, description="Command parameters")
|
96
110
|
|
@@ -99,6 +113,7 @@ class CommandSuccessResponse(BaseModel):
|
|
99
113
|
"""
|
100
114
|
Command success response model for /cmd endpoint.
|
101
115
|
"""
|
116
|
+
|
102
117
|
result: Dict[str, Any] = Field(..., description="Command execution result")
|
103
118
|
|
104
119
|
|
@@ -106,113 +121,124 @@ class CommandErrorResponse(BaseModel):
|
|
106
121
|
"""
|
107
122
|
Command error response model for /cmd endpoint.
|
108
123
|
"""
|
124
|
+
|
109
125
|
error: JsonRpcError = Field(..., description="Error information")
|
110
126
|
|
111
127
|
|
112
128
|
class APIToolDescription:
|
113
129
|
"""
|
114
130
|
Генератор описаний для инструментов API на основе метаданных команд.
|
115
|
-
|
131
|
+
|
116
132
|
Класс предоставляет функциональность для создания подробных и понятных
|
117
133
|
описаний инструментов API, которые помогают пользователям сразу понять
|
118
134
|
как использовать API.
|
119
135
|
"""
|
120
|
-
|
136
|
+
|
121
137
|
@classmethod
|
122
138
|
def generate_tool_description(cls, name: str, registry) -> Dict[str, Any]:
|
123
139
|
"""
|
124
140
|
Генерирует подробное описание инструмента API на основе имени и реестра команд.
|
125
|
-
|
141
|
+
|
126
142
|
Args:
|
127
143
|
name: Имя инструмента API
|
128
144
|
registry: Реестр команд
|
129
|
-
|
145
|
+
|
130
146
|
Returns:
|
131
147
|
Словарь с полным описанием инструмента
|
132
148
|
"""
|
133
149
|
# Получаем все метаданные из реестра команд
|
134
150
|
all_metadata = registry.get_all_metadata()
|
135
|
-
|
151
|
+
|
136
152
|
# Базовое описание инструмента
|
137
153
|
description = {
|
138
154
|
"name": name,
|
139
155
|
"description": f"Выполняет команды через JSON-RPC протокол на сервере проекта.",
|
140
156
|
"supported_commands": {},
|
141
|
-
"examples": []
|
157
|
+
"examples": [],
|
142
158
|
}
|
143
|
-
|
159
|
+
|
144
160
|
# Добавляем информацию о поддерживаемых командах
|
145
161
|
for cmd_name, metadata in all_metadata.items():
|
146
162
|
command_info = {
|
147
163
|
"summary": metadata["summary"],
|
148
164
|
"description": metadata["description"],
|
149
165
|
"params": {},
|
150
|
-
"required_params": []
|
166
|
+
"required_params": [],
|
151
167
|
}
|
152
|
-
|
168
|
+
|
153
169
|
# Добавляем информацию о параметрах
|
154
170
|
for param_name, param_info in metadata["params"].items():
|
155
171
|
param_type = param_info.get("type", "any").replace("typing.", "")
|
156
|
-
|
172
|
+
|
157
173
|
# Определяем тип параметра для документации
|
158
174
|
simple_type = cls._simplify_type(param_type)
|
159
|
-
|
175
|
+
|
160
176
|
command_info["params"][param_name] = {
|
161
177
|
"type": simple_type,
|
162
|
-
"description": cls._extract_param_description(
|
163
|
-
|
178
|
+
"description": cls._extract_param_description(
|
179
|
+
metadata["description"], param_name
|
180
|
+
),
|
181
|
+
"required": param_info.get("required", False),
|
164
182
|
}
|
165
|
-
|
183
|
+
|
166
184
|
# Если параметр обязательный, добавляем его в список обязательных
|
167
185
|
if param_info.get("required", False):
|
168
186
|
command_info["required_params"].append(param_name)
|
169
|
-
|
187
|
+
|
170
188
|
description["supported_commands"][cmd_name] = command_info
|
171
|
-
|
189
|
+
|
172
190
|
# Добавляем примеры из метаданных команды
|
173
191
|
for example in metadata.get("examples", []):
|
174
|
-
description["examples"].append(
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
192
|
+
description["examples"].append(
|
193
|
+
{
|
194
|
+
"command": example.get("command", cmd_name),
|
195
|
+
"params": example.get("params", {}),
|
196
|
+
"description": example.get(
|
197
|
+
"description", f"Пример использования команды {cmd_name}"
|
198
|
+
),
|
199
|
+
}
|
200
|
+
)
|
201
|
+
|
180
202
|
return description
|
181
|
-
|
203
|
+
|
182
204
|
@classmethod
|
183
205
|
def generate_tool_description_text(cls, name: str, registry) -> str:
|
184
206
|
"""
|
185
207
|
Генерирует текстовое описание инструмента API для документации.
|
186
|
-
|
208
|
+
|
187
209
|
Args:
|
188
210
|
name: Имя инструмента API
|
189
211
|
registry: Реестр команд
|
190
|
-
|
212
|
+
|
191
213
|
Returns:
|
192
214
|
Текстовое описание инструмента в формате markdown
|
193
215
|
"""
|
194
216
|
tool_data = cls.generate_tool_description(name, registry)
|
195
|
-
|
217
|
+
|
196
218
|
# Формируем заголовок и базовое описание
|
197
219
|
text = f"# Инструмент {tool_data['name']}\n\n"
|
198
220
|
text += f"{tool_data['description']}\n\n"
|
199
|
-
|
221
|
+
|
200
222
|
# Список доступных команд
|
201
223
|
text += "## Доступные команды\n\n"
|
202
224
|
for cmd_name, cmd_info in tool_data["supported_commands"].items():
|
203
225
|
text += f"### {cmd_name}\n\n"
|
204
226
|
text += f"{cmd_info['description']}\n\n"
|
205
|
-
|
227
|
+
|
206
228
|
# Информация о параметрах
|
207
229
|
if cmd_info["params"]:
|
208
230
|
text += "#### Параметры:\n\n"
|
209
231
|
for param_name, param_info in cmd_info["params"].items():
|
210
|
-
required_mark =
|
232
|
+
required_mark = (
|
233
|
+
"**обязательный**" if param_info["required"] else "опциональный"
|
234
|
+
)
|
211
235
|
text += f"- `{param_name}` ({param_info['type']}, {required_mark}): {param_info['description']}\n"
|
212
236
|
text += "\n"
|
213
|
-
|
237
|
+
|
214
238
|
# Примеры использования
|
215
|
-
cmd_examples = [
|
239
|
+
cmd_examples = [
|
240
|
+
ex for ex in tool_data["examples"] if ex["command"] == cmd_name
|
241
|
+
]
|
216
242
|
if cmd_examples:
|
217
243
|
text += "#### Примеры:\n\n"
|
218
244
|
for i, example in enumerate(cmd_examples):
|
@@ -235,23 +261,23 @@ class APIToolDescription:
|
|
235
261
|
text += ' "params": {}\n'
|
236
262
|
text += "}\n"
|
237
263
|
text += "```\n\n"
|
238
|
-
|
264
|
+
|
239
265
|
return text
|
240
|
-
|
266
|
+
|
241
267
|
@classmethod
|
242
268
|
def _simplify_type(cls, type_str: str) -> str:
|
243
269
|
"""
|
244
270
|
Упрощает строковое представление типа для документации.
|
245
|
-
|
271
|
+
|
246
272
|
Args:
|
247
273
|
type_str: Строковое представление типа
|
248
|
-
|
274
|
+
|
249
275
|
Returns:
|
250
276
|
Упрощенное строковое представление типа
|
251
277
|
"""
|
252
278
|
# Удаляем префиксы из строки типа
|
253
279
|
type_str = type_str.replace("<class '", "").replace("'>", "")
|
254
|
-
|
280
|
+
|
255
281
|
# Преобразование стандартных типов
|
256
282
|
if "str" in type_str:
|
257
283
|
return "строка"
|
@@ -271,16 +297,16 @@ class APIToolDescription:
|
|
271
297
|
return cls._simplify_type(inner_type)
|
272
298
|
else:
|
273
299
|
return "значение"
|
274
|
-
|
300
|
+
|
275
301
|
@classmethod
|
276
302
|
def _extract_param_description(cls, doc_string: str, param_name: str) -> str:
|
277
303
|
"""
|
278
304
|
Извлекает описание параметра из строки документации.
|
279
|
-
|
305
|
+
|
280
306
|
Args:
|
281
307
|
doc_string: Строка документации
|
282
308
|
param_name: Имя параметра
|
283
|
-
|
309
|
+
|
284
310
|
Returns:
|
285
311
|
Описание параметра или пустая строка, если описание не найдено
|
286
312
|
"""
|
@@ -291,13 +317,13 @@ class APIToolDescription:
|
|
291
317
|
args_section = doc_string.split("Parameters:")[1].split("\n\n")[0]
|
292
318
|
else:
|
293
319
|
return ""
|
294
|
-
|
320
|
+
|
295
321
|
# Ищем описание параметра
|
296
322
|
for line in args_section.split("\n"):
|
297
323
|
line = line.strip()
|
298
324
|
if line.startswith(param_name + ":") or line.startswith(param_name + " :"):
|
299
325
|
return line.split(":", 1)[1].strip()
|
300
|
-
|
326
|
+
|
301
327
|
return ""
|
302
328
|
|
303
329
|
|
@@ -19,31 +19,39 @@ logger = logging.getLogger(__name__)
|
|
19
19
|
class ToolIntegration:
|
20
20
|
"""
|
21
21
|
Класс для интеграции метаданных команд с внешними инструментами API.
|
22
|
-
|
22
|
+
|
23
23
|
Обеспечивает генерацию описаний инструментов API для различных систем
|
24
24
|
на основе метаданных команд микросервиса.
|
25
25
|
"""
|
26
|
-
|
26
|
+
|
27
27
|
@classmethod
|
28
|
-
def generate_tool_schema(
|
29
|
-
|
28
|
+
def generate_tool_schema(
|
29
|
+
cls,
|
30
|
+
tool_name: str,
|
31
|
+
registry: CommandRegistry,
|
32
|
+
description: Optional[str] = None,
|
33
|
+
) -> Dict[str, Any]:
|
30
34
|
"""
|
31
35
|
Генерирует схему инструмента API для использования в OpenAPI и других системах.
|
32
|
-
|
36
|
+
|
33
37
|
Args:
|
34
38
|
tool_name: Имя инструмента API
|
35
39
|
registry: Реестр команд
|
36
40
|
description: Дополнительное описание инструмента (опционально)
|
37
|
-
|
41
|
+
|
38
42
|
Returns:
|
39
43
|
Словарь с описанием инструмента в формате OpenAPI
|
40
44
|
"""
|
41
45
|
# Получаем базовое описание инструмента
|
42
|
-
base_description = APIToolDescription.generate_tool_description(
|
43
|
-
|
46
|
+
base_description = APIToolDescription.generate_tool_description(
|
47
|
+
tool_name, registry
|
48
|
+
)
|
49
|
+
|
44
50
|
# Получаем типы параметров
|
45
|
-
parameter_types = cls._extract_parameter_types(
|
46
|
-
|
51
|
+
parameter_types = cls._extract_parameter_types(
|
52
|
+
base_description["supported_commands"]
|
53
|
+
)
|
54
|
+
|
47
55
|
# Формируем схему инструмента
|
48
56
|
schema = {
|
49
57
|
"name": tool_name,
|
@@ -53,100 +61,105 @@ class ToolIntegration:
|
|
53
61
|
"command": {
|
54
62
|
"description": "Команда для выполнения",
|
55
63
|
"type": "string",
|
56
|
-
"enum": list(base_description["supported_commands"].keys())
|
64
|
+
"enum": list(base_description["supported_commands"].keys()),
|
57
65
|
},
|
58
66
|
"params": {
|
59
67
|
"description": "Параметры команды",
|
60
68
|
"type": "object",
|
61
69
|
"additionalProperties": True,
|
62
|
-
"properties": parameter_types
|
63
|
-
}
|
70
|
+
"properties": parameter_types,
|
71
|
+
},
|
64
72
|
},
|
65
73
|
"required": ["command"],
|
66
|
-
"type": "object"
|
67
|
-
}
|
74
|
+
"type": "object",
|
75
|
+
},
|
68
76
|
}
|
69
|
-
|
77
|
+
|
70
78
|
return schema
|
71
|
-
|
79
|
+
|
72
80
|
@classmethod
|
73
|
-
def generate_tool_documentation(
|
74
|
-
|
81
|
+
def generate_tool_documentation(
|
82
|
+
cls, tool_name: str, registry: CommandRegistry, format: str = "markdown"
|
83
|
+
) -> str:
|
75
84
|
"""
|
76
85
|
Генерирует документацию по инструменту API в заданном формате.
|
77
|
-
|
86
|
+
|
78
87
|
Args:
|
79
88
|
tool_name: Имя инструмента API
|
80
89
|
registry: Реестр команд
|
81
90
|
format: Формат документации (markdown, html)
|
82
|
-
|
91
|
+
|
83
92
|
Returns:
|
84
93
|
Строка с документацией в заданном формате
|
85
94
|
"""
|
86
95
|
if format.lower() == "markdown":
|
87
|
-
return APIToolDescription.generate_tool_description_text(
|
96
|
+
return APIToolDescription.generate_tool_description_text(
|
97
|
+
tool_name, registry
|
98
|
+
)
|
88
99
|
elif format.lower() == "html":
|
89
|
-
# Преобразуем markdown в HTML (в реальном проекте здесь будет
|
100
|
+
# Преобразуем markdown в HTML (в реальном проекте здесь будет
|
90
101
|
# использоваться библиотека для конвертации markdown в HTML)
|
91
|
-
markdown = APIToolDescription.generate_tool_description_text(
|
102
|
+
markdown = APIToolDescription.generate_tool_description_text(
|
103
|
+
tool_name, registry
|
104
|
+
)
|
92
105
|
# Простая конвертация для примера
|
93
|
-
body = markdown.replace(
|
106
|
+
body = markdown.replace("#", "<h1>").replace("\n\n", "</p><p>")
|
94
107
|
html = f"<html><body>{body}</body></html>"
|
95
108
|
return html
|
96
109
|
else:
|
97
110
|
# По умолчанию возвращаем markdown
|
98
|
-
return APIToolDescription.generate_tool_description_text(
|
99
|
-
|
111
|
+
return APIToolDescription.generate_tool_description_text(
|
112
|
+
tool_name, registry
|
113
|
+
)
|
114
|
+
|
100
115
|
@classmethod
|
101
|
-
def register_external_tools(
|
116
|
+
def register_external_tools(
|
117
|
+
cls, registry: CommandRegistry, tool_names: List[str]
|
118
|
+
) -> Dict[str, Dict[str, Any]]:
|
102
119
|
"""
|
103
120
|
Регистрирует инструменты API во внешних системах.
|
104
|
-
|
121
|
+
|
105
122
|
Args:
|
106
123
|
registry: Реестр команд
|
107
124
|
tool_names: Список имен инструментов API для регистрации
|
108
|
-
|
125
|
+
|
109
126
|
Returns:
|
110
127
|
Словарь с результатами регистрации инструментов
|
111
128
|
"""
|
112
129
|
results = {}
|
113
|
-
|
130
|
+
|
114
131
|
for tool_name in tool_names:
|
115
132
|
try:
|
116
133
|
# Генерируем схему инструмента
|
117
134
|
schema = cls.generate_tool_schema(tool_name, registry)
|
118
|
-
|
135
|
+
|
119
136
|
# Здесь будет код для регистрации инструмента во внешней системе
|
120
137
|
# Например, отправка схемы в API регистрации инструментов
|
121
|
-
|
122
|
-
results[tool_name] = {
|
123
|
-
|
124
|
-
"schema": schema
|
125
|
-
}
|
126
|
-
|
138
|
+
|
139
|
+
results[tool_name] = {"status": "success", "schema": schema}
|
140
|
+
|
127
141
|
logger.info(f"Successfully registered tool: {tool_name}")
|
128
142
|
except Exception as e:
|
129
143
|
logger.debug(f"Error registering tool {tool_name}: {e}")
|
130
|
-
results[tool_name] = {
|
131
|
-
|
132
|
-
"error": str(e)
|
133
|
-
}
|
134
|
-
|
144
|
+
results[tool_name] = {"status": "error", "error": str(e)}
|
145
|
+
|
135
146
|
return results
|
136
|
-
|
147
|
+
|
137
148
|
@classmethod
|
138
|
-
def _extract_parameter_types(
|
149
|
+
def _extract_parameter_types(
|
150
|
+
cls, commands: Dict[str, Dict[str, Any]]
|
151
|
+
) -> Dict[str, Dict[str, Any]]:
|
139
152
|
"""
|
140
153
|
Извлекает типы параметров из описания команд для формирования схемы.
|
141
|
-
|
154
|
+
|
142
155
|
Args:
|
143
156
|
commands: Словарь с описанием команд
|
144
|
-
|
157
|
+
|
145
158
|
Returns:
|
146
159
|
Словарь с типами параметров для схемы OpenAPI
|
147
160
|
"""
|
148
161
|
parameter_types = {}
|
149
|
-
|
162
|
+
|
150
163
|
# Формируем словарь типов для всех параметров всех команд
|
151
164
|
for cmd_name, cmd_info in commands.items():
|
152
165
|
params = cmd_info.get("params", {})
|
@@ -154,7 +167,7 @@ class ToolIntegration:
|
|
154
167
|
continue
|
155
168
|
for param_name, param_info in params.items():
|
156
169
|
param_type = param_info.get("type", "значение")
|
157
|
-
|
170
|
+
|
158
171
|
# Преобразуем русские типы в типы JSON Schema
|
159
172
|
if param_type == "строка":
|
160
173
|
json_type = "string"
|
@@ -170,58 +183,65 @@ class ToolIntegration:
|
|
170
183
|
json_type = "object"
|
171
184
|
else:
|
172
185
|
json_type = "string"
|
173
|
-
|
186
|
+
|
174
187
|
# Добавляем тип в общий словарь
|
175
188
|
parameter_types[param_name] = {
|
176
189
|
"type": json_type,
|
177
|
-
"description": param_info.get("description", "")
|
190
|
+
"description": param_info.get("description", ""),
|
178
191
|
}
|
179
|
-
|
192
|
+
|
180
193
|
return parameter_types
|
181
194
|
|
182
195
|
|
183
196
|
def generate_tool_help(tool_name: str, registry: CommandRegistry) -> str:
|
184
197
|
"""
|
185
198
|
Генерирует справочную информацию по инструменту API.
|
186
|
-
|
199
|
+
|
187
200
|
Args:
|
188
201
|
tool_name: Имя инструмента API
|
189
202
|
registry: Реестр команд
|
190
|
-
|
203
|
+
|
191
204
|
Returns:
|
192
205
|
Строка с описанием инструмента и доступных команд
|
193
206
|
"""
|
194
207
|
# Получаем метаданные всех команд
|
195
208
|
all_metadata = registry.get_all_metadata()
|
196
|
-
|
209
|
+
|
197
210
|
# Формируем текст справки
|
198
211
|
help_text = f"# Инструмент {tool_name}\n\n"
|
199
212
|
help_text += "Позволяет выполнять команды через JSON-RPC протокол.\n\n"
|
200
213
|
help_text += "## Доступные команды:\n\n"
|
201
|
-
|
214
|
+
|
202
215
|
# Добавляем информацию о каждой команде
|
203
216
|
for cmd_name, metadata in all_metadata.items():
|
204
217
|
help_text += f"### {cmd_name}\n"
|
205
218
|
help_text += f"{metadata['summary']}\n\n"
|
206
|
-
|
219
|
+
|
207
220
|
# Добавляем информацию о параметрах команды
|
208
221
|
if metadata["params"]:
|
209
222
|
help_text += "Параметры:\n"
|
210
223
|
for param_name, param_info in metadata["params"].items():
|
211
|
-
required =
|
224
|
+
required = (
|
225
|
+
"обязательный"
|
226
|
+
if param_info.get("required", False)
|
227
|
+
else "опциональный"
|
228
|
+
)
|
212
229
|
help_text += f"- {param_name}: {required}\n"
|
213
230
|
help_text += "\n"
|
214
|
-
|
231
|
+
|
215
232
|
# Добавляем пример использования команды
|
216
233
|
if metadata.get("examples"):
|
217
234
|
example = metadata["examples"][0]
|
218
235
|
help_text += "Пример:\n"
|
219
236
|
help_text += "```json\n"
|
220
237
|
help_text += json.dumps(
|
221
|
-
{
|
238
|
+
{
|
239
|
+
"command": example.get("command", cmd_name),
|
240
|
+
"params": example.get("params", {}),
|
241
|
+
},
|
222
242
|
indent=2,
|
223
|
-
ensure_ascii=False
|
243
|
+
ensure_ascii=False,
|
224
244
|
)
|
225
245
|
help_text += "\n```\n\n"
|
226
|
-
|
227
|
-
return help_text
|
246
|
+
|
247
|
+
return help_text
|