mcp-proxy-adapter 2.1.1__py3-none-any.whl → 2.1.3__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.
Files changed (50) hide show
  1. {mcp_proxy_adapter-2.1.1.dist-info → mcp_proxy_adapter-2.1.3.dist-info}/METADATA +1 -1
  2. mcp_proxy_adapter-2.1.3.dist-info/RECORD +18 -0
  3. mcp_proxy_adapter-2.1.3.dist-info/top_level.txt +1 -0
  4. docs/README.md +0 -172
  5. docs/README_ru.md +0 -172
  6. docs/architecture.md +0 -251
  7. docs/architecture_ru.md +0 -343
  8. docs/command_development.md +0 -250
  9. docs/command_development_ru.md +0 -593
  10. docs/deployment.md +0 -251
  11. docs/deployment_ru.md +0 -1298
  12. docs/examples.md +0 -254
  13. docs/examples_ru.md +0 -401
  14. docs/mcp_proxy_adapter.md +0 -251
  15. docs/mcp_proxy_adapter_ru.md +0 -405
  16. docs/quickstart.md +0 -251
  17. docs/quickstart_ru.md +0 -397
  18. docs/testing.md +0 -255
  19. docs/testing_ru.md +0 -469
  20. docs/validation_ru.md +0 -287
  21. examples/analyze_config.py +0 -141
  22. examples/basic_integration.py +0 -161
  23. examples/docstring_and_schema_example.py +0 -60
  24. examples/extension_example.py +0 -60
  25. examples/help_best_practices.py +0 -67
  26. examples/help_usage.py +0 -64
  27. examples/mcp_proxy_client.py +0 -131
  28. examples/mcp_proxy_config.json +0 -175
  29. examples/openapi_server.py +0 -369
  30. examples/project_structure_example.py +0 -47
  31. examples/testing_example.py +0 -53
  32. mcp_proxy_adapter-2.1.1.dist-info/RECORD +0 -61
  33. mcp_proxy_adapter-2.1.1.dist-info/top_level.txt +0 -5
  34. scripts/code_analyzer/code_analyzer.py +0 -328
  35. scripts/code_analyzer/register_commands.py +0 -446
  36. scripts/publish.py +0 -85
  37. tests/conftest.py +0 -12
  38. tests/test_adapter.py +0 -529
  39. tests/test_adapter_coverage.py +0 -274
  40. tests/test_basic_dispatcher.py +0 -169
  41. tests/test_command_registry.py +0 -328
  42. tests/test_examples.py +0 -32
  43. tests/test_mcp_proxy_adapter.py +0 -568
  44. tests/test_mcp_proxy_adapter_basic.py +0 -262
  45. tests/test_part1.py +0 -348
  46. tests/test_part2.py +0 -524
  47. tests/test_schema.py +0 -358
  48. tests/test_simple_adapter.py +0 -251
  49. {mcp_proxy_adapter-2.1.1.dist-info → mcp_proxy_adapter-2.1.3.dist-info}/WHEEL +0 -0
  50. {mcp_proxy_adapter-2.1.1.dist-info → mcp_proxy_adapter-2.1.3.dist-info}/licenses/LICENSE +0 -0
docs/validation_ru.md DELETED
@@ -1,287 +0,0 @@
1
- # Валидация команд и обработка ошибок
2
-
3
- В этом документе описаны процессы валидации команд в Command Registry и способы обработки ошибок.
4
-
5
- ## Содержание
6
-
7
- - [Процесс валидации](#процесс-валидации)
8
- - [Типы валидаторов](#типы-валидаторов)
9
- - [Режимы работы](#режимы-работы)
10
- - [Типы ошибок](#типы-ошибок)
11
- - [Обработка ошибок](#обработка-ошибок)
12
- - [Автоматическое исправление](#автоматическое-исправление)
13
-
14
- ## Процесс валидации
15
-
16
- Валидация команд выполняется перед их регистрацией в диспетчере. Процесс включает следующие шаги:
17
-
18
- 1. **Анализ исходного кода**: извлечение метаданных из докстрингов и аннотаций типов
19
- 2. **Проверка соответствия**: сравнение метаданных с формальными параметрами функции
20
- 3. **Принятие решения**: регистрация команды или вывод ошибок в зависимости от режима работы
21
-
22
- ```python
23
- # Основной процесс валидации в методе register_command
24
- def register_command(self, command_name: str, handler: Callable) -> bool:
25
- # Анализ обработчика
26
- metadata = self.analyze_handler(command_name, handler)
27
-
28
- # Валидация метаданных
29
- is_valid, errors = self.validate_handler(command_name, handler, metadata)
30
-
31
- # Вывод ошибок, если они есть
32
- if not is_valid:
33
- for error in errors:
34
- logger.error(f"{command_name}: {error}")
35
-
36
- # В строгом режиме прерываем регистрацию
37
- if self.strict and not self.auto_fix:
38
- return False
39
-
40
- # Регистрация команды
41
- self.dispatcher.register_handler(
42
- command=command_name,
43
- handler=handler,
44
- description=metadata["description"],
45
- summary=metadata["summary"],
46
- params=metadata["parameters"]
47
- )
48
-
49
- return True
50
- ```
51
-
52
- ## Типы валидаторов
53
-
54
- Command Registry включает несколько типов валидаторов для разных аспектов проверки:
55
-
56
- ### 1. DocstringValidator
57
-
58
- Проверяет соответствие докстрингов формальным параметрам функции:
59
-
60
- - Наличие описания функции
61
- - Описание всех параметров в секции Args
62
- - Наличие секции Returns
63
- - Соответствие имен параметров в докстринге и сигнатуре функции
64
-
65
- ```python
66
- class DocstringValidator:
67
- def validate(self, handler: Callable, command_name: str, metadata: Dict[str, Any]) -> Tuple[bool, List[str]]:
68
- errors = []
69
-
70
- # Получаем формальные параметры функции
71
- sig = inspect.signature(handler)
72
- formal_params = list(sig.parameters.keys())
73
-
74
- # Парсим докстринг
75
- docstring = handler.__doc__ or ""
76
- parsed_doc = docstring_parser.parse(docstring)
77
-
78
- # Проверяем наличие описания функции
79
- if not parsed_doc.short_description and not parsed_doc.long_description:
80
- errors.append(f"Отсутствует описание функции")
81
-
82
- # Получаем параметры из докстринга
83
- doc_params = {param.arg_name: param for param in parsed_doc.params}
84
-
85
- # Проверяем, что все формальные параметры описаны в докстринге
86
- for param in formal_params:
87
- if param not in doc_params and param != 'params':
88
- errors.append(f"Параметр '{param}' не описан в докстринге функции")
89
-
90
- # Проверяем наличие returns в докстринге
91
- if not parsed_doc.returns:
92
- errors.append(f"Отсутствует описание возвращаемого значения в докстринге функции")
93
-
94
- return len(errors) == 0, errors
95
- ```
96
-
97
- ### 2. MetadataValidator
98
-
99
- Проверяет соответствие метаданных команды её сигнатуре:
100
-
101
- - Наличие всех обязательных параметров в метаданных
102
- - Соответствие типов параметров в метаданных и аннотациях
103
- - Отсутствие лишних параметров в метаданных
104
-
105
- ```python
106
- class MetadataValidator:
107
- def validate(self, handler: Callable, command_name: str, metadata: Dict[str, Any]) -> Tuple[bool, List[str]]:
108
- errors = []
109
-
110
- # Получаем формальные параметры функции
111
- sig = inspect.signature(handler)
112
-
113
- # Проверяем соответствие метаданных и формальных параметров
114
- if "parameters" in metadata:
115
- for param_name, param_info in metadata["parameters"].items():
116
- # Проверяем наличие параметра в сигнатуре функции
117
- if param_name not in sig.parameters:
118
- errors.append(f"Параметр '{param_name}' указан в метаданных, но отсутствует в сигнатуре функции")
119
-
120
- # Проверяем, что все обязательные параметры указаны в метаданных
121
- for param_name, param in sig.parameters.items():
122
- if param.default == inspect.Parameter.empty and param_name != 'self':
123
- if param_name not in metadata["parameters"]:
124
- errors.append(f"Обязательный параметр '{param_name}' не указан в метаданных")
125
-
126
- return len(errors) == 0, errors
127
- ```
128
-
129
- ## Режимы работы
130
-
131
- Command Registry поддерживает несколько режимов валидации, которые определяют поведение при обнаружении ошибок:
132
-
133
- ### 1. Строгий режим (strict=True)
134
-
135
- В строгом режиме система отказывается регистрировать команды с ошибками в документации:
136
-
137
- - При обнаружении любой ошибки в документации команда не регистрируется
138
- - Выводятся подробные сообщения об ошибках для каждой команды
139
- - Рекомендуется использовать в CI/CD и продакшене для обеспечения качества кода
140
-
141
- ```python
142
- # Пример использования строгого режима
143
- registry = CommandRegistry(strict=True, auto_fix=False)
144
- registry.register_all_commands() # Команды с ошибками не будут зарегистрированы
145
- ```
146
-
147
- ### 2. Нестрогий режим (strict=False)
148
-
149
- В нестрогом режиме система регистрирует все команды, даже с ошибками:
150
-
151
- - При обнаружении ошибок выводятся предупреждения, но команда регистрируется
152
- - Может привести к неточностям в документации API
153
- - Полезен для быстрого прототипирования и отладки
154
-
155
- ```python
156
- # Пример использования нестрогого режима
157
- registry = CommandRegistry(strict=False, auto_fix=False)
158
- registry.register_all_commands() # Все команды будут зарегистрированы
159
- ```
160
-
161
- ### 3. Режим автоисправления (auto_fix=True)
162
-
163
- В режиме автоисправления система пытается автоматически исправить ошибки:
164
-
165
- - Недостающие метаданные извлекаются из аннотаций типов
166
- - Улучшается документация на основе имеющейся информации
167
- - Полезен при разработке, когда документация еще не полностью оформлена
168
-
169
- ```python
170
- # Пример использования режима автоисправления
171
- registry = CommandRegistry(strict=True, auto_fix=True)
172
- registry.register_all_commands() # Система попытается исправить ошибки
173
- ```
174
-
175
- ## Типы ошибок
176
-
177
- Валидаторы могут обнаруживать различные типы ошибок:
178
-
179
- ### 1. Ошибки докстрингов
180
-
181
- - **Отсутствие описания функции**: докстринг пуст или содержит только код
182
- - **Отсутствие описания параметра**: параметр функции не описан в докстринге
183
- - **Отсутствие описания возвращаемого значения**: нет секции Returns
184
- - **Лишние параметры в докстринге**: в докстринге описаны параметры, которых нет в функции
185
-
186
- ### 2. Ошибки метаданных
187
-
188
- - **Несоответствие типов**: тип в метаданных не соответствует аннотации типа
189
- - **Отсутствие обязательного параметра**: обязательный параметр не описан в метаданных
190
- - **Лишние параметры в метаданных**: в метаданных указаны параметры, которых нет в функции
191
- - **Некорректное описание**: отсутствует или неполное описание команды или параметра
192
-
193
- ### 3. Ошибки аннотаций типов
194
-
195
- - **Отсутствие аннотации типа**: параметр не имеет аннотации типа
196
- - **Отсутствие аннотации возвращаемого значения**: функция не имеет аннотации возвращаемого значения
197
- - **Несоответствие типов в аннотациях и метаданных**: тип в аннотации не соответствует типу в метаданных
198
-
199
- ## Обработка ошибок
200
-
201
- При обнаружении ошибок Command Registry предоставляет подробную информацию для их исправления:
202
-
203
- ```
204
- 🚫 Ошибки в команде 'search_by_vector':
205
- - Параметр 'top_k' не описан в докстринге функции
206
- - Отсутствует описание возвращаемого значения в докстринге функции
207
- - Обязательный параметр 'vector' не указан в метаданных команды
208
- ```
209
-
210
- В зависимости от режима работы, система может:
211
-
212
- 1. **Отказаться регистрировать команду** (strict=True, auto_fix=False)
213
- 2. **Зарегистрировать команду с предупреждениями** (strict=False)
214
- 3. **Попытаться исправить ошибки автоматически** (auto_fix=True)
215
-
216
- ### Рекомендуемый подход к обработке ошибок
217
-
218
- 1. **В разработке**:
219
- - Использовать auto_fix=True для автоматического исправления ошибок
220
- - Регулярно запускать валидацию в строгом режиме для выявления проблем
221
-
222
- 2. **В CI/CD**:
223
- - Использовать strict=True для блокирования PR с ошибками в документации
224
- - Добавить проверку валидации команд в процесс тестирования
225
-
226
- 3. **В продакшене**:
227
- - Всегда использовать strict=True для гарантии качества документации
228
- - Никогда не использовать auto_fix=True в продакшен-среде
229
-
230
- ## Автоматическое исправление
231
-
232
- Когда включен режим auto_fix=True, система пытается исправить ошибки автоматически:
233
-
234
- ### 1. Дополнение метаданных
235
-
236
- Если метаданные неполные, система дополняет их на основе:
237
-
238
- - Аннотаций типов для определения типов параметров
239
- - Сигнатуры функции для определения обязательных параметров
240
- - Значений по умолчанию для определения default значений
241
-
242
- ```python
243
- # Дополнение метаданных на основе аннотаций типов
244
- type_hints = get_type_hints(handler)
245
- for param_name, param_type in type_hints.items():
246
- if param_name == 'return':
247
- continue
248
-
249
- if param_name not in metadata["parameters"]:
250
- metadata["parameters"][param_name] = {
251
- "type": map_type_to_openapi(param_type),
252
- "description": f"Параметр {param_name}",
253
- "required": param_name in required_params
254
- }
255
- ```
256
-
257
- ### 2. Извлечение описаний из докстрингов
258
-
259
- Если докстринги есть, но метаданные неполные, система извлекает описания из докстрингов:
260
-
261
- ```python
262
- # Извлечение описаний из докстрингов
263
- parsed_doc = docstring_parser.parse(handler.__doc__ or "")
264
- for param in parsed_doc.params:
265
- param_name = param.arg_name
266
- if param_name in metadata["parameters"]:
267
- metadata["parameters"][param_name]["description"] = param.description
268
- ```
269
-
270
- ### 3. Генерация базовых описаний
271
-
272
- Если описания отсутствуют, система генерирует базовые описания:
273
-
274
- ```python
275
- # Генерация базовых описаний
276
- if not metadata.get("description"):
277
- metadata["description"] = f"Команда {command_name}"
278
-
279
- if not metadata.get("summary"):
280
- metadata["summary"] = command_name.replace("_", " ").title()
281
- ```
282
-
283
- ## Заключение
284
-
285
- Система валидации Command Registry помогает обеспечить высокое качество документации API за счет строгой проверки соответствия докстрингов, метаданных и сигнатур функций.
286
-
287
- Рекомендуется использовать строгий режим валидации (strict=True) для гарантии качества документации, особенно в процессе CI/CD и в продакшен-среде. Режим автоисправления (auto_fix=True) полезен на ранних этапах разработки, когда документация еще не полностью оформлена.
@@ -1,141 +0,0 @@
1
- """
2
- Analysis of MCP Proxy configuration generated by the adapter.
3
-
4
- This script loads and analyzes the MCP Proxy configuration file
5
- that was created by MCPProxyAdapter, and outputs structured
6
- information about routes and tools.
7
-
8
- Usage:
9
- python examples/analyze_config.py
10
- """
11
- import os
12
- import json
13
- import sys
14
- from typing import Dict, Any, List
15
-
16
-
17
- def load_config_file(config_path: str) -> Dict[str, Any]:
18
- """
19
- Loads MCP Proxy configuration file.
20
-
21
- Args:
22
- config_path (str): Path to configuration file
23
-
24
- Returns:
25
- Dict[str, Any]: Loaded configuration
26
-
27
- Raises:
28
- FileNotFoundError: If file is not found
29
- json.JSONDecodeError: If file is not valid JSON
30
- """
31
- try:
32
- with open(config_path, 'r', encoding='utf-8') as f:
33
- return json.load(f)
34
- except FileNotFoundError:
35
- print(f"Error: Configuration file not found: {config_path}")
36
- sys.exit(1)
37
- except json.JSONDecodeError as e:
38
- print(f"Error: File is not valid JSON: {e}")
39
- sys.exit(1)
40
-
41
-
42
- def print_routes(config: Dict[str, Any]) -> None:
43
- """
44
- Prints route information from configuration.
45
-
46
- Args:
47
- config (Dict[str, Any]): MCP Proxy configuration
48
- """
49
- if "routes" not in config:
50
- print("No routes in configuration")
51
- return
52
-
53
- routes = config["routes"]
54
- print(f"=== Routes ({len(routes)}) ===")
55
-
56
- for i, route in enumerate(routes, 1):
57
- print(f"\n{i}. Route:")
58
- print(f" Endpoint: {route.get('endpoint', 'Not specified')}")
59
- print(f" Method: {route.get('method', 'Not specified')}")
60
-
61
- if "json_rpc" in route:
62
- print(" Type: JSON-RPC")
63
- if "params" in route["json_rpc"]:
64
- print(f" Parameters: {route['json_rpc'].get('params', 'Not specified')}")
65
- else:
66
- print(" Type: Regular HTTP")
67
-
68
-
69
- def print_tools(config: Dict[str, Any]) -> None:
70
- """
71
- Prints tool information from configuration.
72
-
73
- Args:
74
- config (Dict[str, Any]): MCP Proxy configuration
75
- """
76
- if "tools" not in config:
77
- print("No tools in configuration")
78
- return
79
-
80
- tools = config["tools"]
81
- print(f"\n=== Tools ({len(tools)}) ===")
82
-
83
- for i, tool in enumerate(tools, 1):
84
- print(f"\n{i}. Tool:")
85
- print(f" Name: {tool.get('name', 'Not specified')}")
86
- print(f" Description: {tool.get('description', 'Not specified')}")
87
-
88
- if "parameters" in tool:
89
- params = tool["parameters"]
90
- required_params = params.get("required", [])
91
- properties = params.get("properties", {})
92
-
93
- print(f" Parameters ({len(properties)}):")
94
- for param_name, param_info in properties.items():
95
- required = "Required" if param_name in required_params else "Optional"
96
- param_type = param_info.get("type", "Not specified")
97
- description = param_info.get("description", "Not specified")
98
-
99
- print(f" - {param_name} ({param_type}, {required}):")
100
- print(f" {description}")
101
-
102
-
103
- def analyze_config(config_path: str) -> None:
104
- """
105
- Analyzes MCP Proxy configuration.
106
-
107
- Args:
108
- config_path (str): Path to configuration file
109
- """
110
- config = load_config_file(config_path)
111
-
112
- print("\n=== MCP Proxy Configuration Analysis ===")
113
- print(f"File: {config_path}")
114
- print(f"Version: {config.get('version', 'Not specified')}")
115
-
116
- print_routes(config)
117
- print_tools(config)
118
-
119
- print("\n=== Summary ===")
120
- num_routes = len(config.get("routes", []))
121
- num_tools = len(config.get("tools", []))
122
-
123
- print(f"Configuration contains {num_routes} routes and {num_tools} tools.")
124
-
125
- if num_tools > 0 and num_routes > 0:
126
- print("MCP Proxy is configured correctly and ready to use.")
127
- else:
128
- print("WARNING: Configuration may be incomplete or incorrect.")
129
-
130
-
131
- def main():
132
- """Main script function."""
133
- # Define path to configuration file
134
- config_path = os.path.join(os.path.dirname(__file__), "mcp_proxy_config.json")
135
-
136
- # Analyze configuration
137
- analyze_config(config_path)
138
-
139
-
140
- if __name__ == "__main__":
141
- main()
@@ -1,161 +0,0 @@
1
- """
2
- Example of basic MCPProxyAdapter integration with an existing FastAPI application.
3
- """
4
- import logging
5
- import os
6
- import sys
7
- from typing import Dict, Any, List, Optional
8
-
9
- # Add parent directory to import path
10
- current_dir = os.path.dirname(os.path.abspath(__file__))
11
- parent_dir = os.path.dirname(current_dir)
12
- if parent_dir not in sys.path:
13
- sys.path.insert(0, parent_dir)
14
-
15
- from fastapi import FastAPI, HTTPException, APIRouter
16
- from pydantic import BaseModel
17
-
18
- # Import from installed package or local file
19
- try:
20
- from mcp_proxy_adapter.adapter import MCPProxyAdapter, configure_logger
21
- from mcp_proxy_adapter.registry import CommandRegistry
22
- except ImportError:
23
- from src.adapter import MCPProxyAdapter, configure_logger
24
- from src.registry import CommandRegistry
25
-
26
- # Configure project logging
27
- logging.basicConfig(
28
- level=logging.INFO,
29
- format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
30
- )
31
-
32
- # Create project logger
33
- project_logger = logging.getLogger("my_project")
34
- project_logger.setLevel(logging.DEBUG)
35
-
36
- # Configure adapter logger using project logger
37
- adapter_logger = configure_logger(project_logger)
38
-
39
- # Create FastAPI application
40
- app = FastAPI(
41
- title="My API with MCP Proxy Integration",
42
- description="API with Command Registry integration, supporting MCP Proxy",
43
- version="1.0.0"
44
- )
45
-
46
- # Define existing endpoints
47
- router = APIRouter()
48
-
49
- class Item(BaseModel):
50
- name: str
51
- price: float
52
- is_active: bool = True
53
-
54
- @router.get("/items", response_model=List[Item])
55
- async def get_items():
56
- """Returns list of items."""
57
- return [
58
- {"name": "Item 1", "price": 10.5, "is_active": True},
59
- {"name": "Item 2", "price": 20.0, "is_active": False},
60
- {"name": "Item 3", "price": 30.0, "is_active": True},
61
- ]
62
-
63
- @router.get("/items/{item_id}", response_model=Item)
64
- async def get_item(item_id: int):
65
- """Returns item information by ID."""
66
- items = [
67
- {"name": "Item 1", "price": 10.5, "is_active": True},
68
- {"name": "Item 2", "price": 20.0, "is_active": False},
69
- {"name": "Item 3", "price": 30.0, "is_active": True},
70
- ]
71
-
72
- if item_id < 1 or item_id > len(items):
73
- raise HTTPException(status_code=404, detail="Item not found")
74
-
75
- return items[item_id - 1]
76
-
77
- # Add existing endpoints to application
78
- app.include_router(router)
79
-
80
- # Define commands for Command Registry
81
- def list_items() -> List[Dict[str, Any]]:
82
- """
83
- Returns list of all items.
84
-
85
- Returns:
86
- List[Dict[str, Any]]: List of items
87
- """
88
- return [
89
- {"name": "Item 1", "price": 10.5, "is_active": True},
90
- {"name": "Item 2", "price": 20.0, "is_active": False},
91
- {"name": "Item 3", "price": 30.0, "is_active": True},
92
- ]
93
-
94
- def get_item_by_id(item_id: int) -> Dict[str, Any]:
95
- """
96
- Returns item information by ID.
97
-
98
- Args:
99
- item_id: Item ID
100
-
101
- Returns:
102
- Dict[str, Any]: Item information
103
-
104
- Raises:
105
- ValueError: If item is not found
106
- """
107
- items = list_items()
108
-
109
- if item_id < 1 or item_id > len(items):
110
- raise ValueError(f"Item with ID {item_id} not found")
111
-
112
- return items[item_id - 1]
113
-
114
- def search_items(query: str, min_price: Optional[float] = None, max_price: Optional[float] = None) -> List[Dict[str, Any]]:
115
- """
116
- Searches for items by name and price range.
117
-
118
- Args:
119
- query: Search query for name
120
- min_price: Minimum price (optional)
121
- max_price: Maximum price (optional)
122
-
123
- Returns:
124
- List[Dict[str, Any]]: List of found items
125
- """
126
- items = list_items()
127
-
128
- # Filter by name
129
- filtered_items = [item for item in items if query.lower() in item["name"].lower()]
130
-
131
- # Filter by minimum price
132
- if min_price is not None:
133
- filtered_items = [item for item in filtered_items if item["price"] >= min_price]
134
-
135
- # Filter by maximum price
136
- if max_price is not None:
137
- filtered_items = [item for item in filtered_items if item["price"] <= max_price]
138
-
139
- return filtered_items
140
-
141
- # Create CommandRegistry instance
142
- registry = CommandRegistry()
143
-
144
- # Register commands
145
- registry.register_command("list_items", list_items)
146
- registry.register_command("get_item", get_item_by_id)
147
- registry.register_command("search_items", search_items)
148
-
149
- # Create MCP Proxy adapter
150
- adapter = MCPProxyAdapter(registry)
151
-
152
- # Register endpoints in existing application
153
- adapter.register_endpoints(app)
154
-
155
- # Save configuration for MCP Proxy
156
- adapter.save_config_to_file("mcp_proxy_config.json")
157
-
158
- # Entry point for running the application
159
- if __name__ == "__main__":
160
- import uvicorn
161
- uvicorn.run(app, host="0.0.0.0", port=8000)
@@ -1,60 +0,0 @@
1
- """
2
- Docstring and Schema Example for MCPProxyAdapter
3
-
4
- - How to write docstrings for commands
5
- - How docstrings are used in OpenAPI/schema
6
- - Best practices for documenting parameters and return values
7
-
8
- Run:
9
- python examples/docstring_and_schema_example.py
10
- """
11
- import os
12
- import sys
13
- sys.path.insert(0, os.path.abspath(os.path.dirname(os.path.dirname(__file__))))
14
- from mcp_proxy_adapter.adapter import MCPProxyAdapter
15
-
16
- class MyRegistry:
17
- def __init__(self):
18
- self.dispatcher = self
19
- self.commands = {"sum": self.sum_numbers}
20
- self.commands_info = {
21
- "sum": {
22
- "description": self.sum_numbers.__doc__,
23
- "params": {
24
- "a": {"type": "integer", "description": "First number", "required": True},
25
- "b": {"type": "integer", "description": "Second number", "required": True}
26
- }
27
- }
28
- }
29
- def get_valid_commands(self):
30
- return list(self.commands.keys())
31
- def get_command_info(self, command):
32
- return self.commands_info.get(command)
33
- def get_commands_info(self):
34
- return self.commands_info
35
- def execute(self, command, **params):
36
- if command == "sum":
37
- return self.sum_numbers(**params)
38
- raise KeyError(f"Unknown command: {command}")
39
- def add_generator(self, generator):
40
- pass
41
- def sum_numbers(self, a: int, b: int) -> int:
42
- """
43
- Returns the sum of two numbers.
44
-
45
- Args:
46
- a (int): First number
47
- b (int): Second number
48
-
49
- Returns:
50
- int: The sum of a and b
51
- """
52
- return a + b
53
-
54
- if __name__ == "__main__":
55
- registry = MyRegistry()
56
- adapter = MCPProxyAdapter(registry)
57
- # Print OpenAPI schema (simulated)
58
- schema = adapter.generate_mcp_proxy_config()
59
- print("=== Tool description from docstring ===")
60
- print(schema.tools[0].description)