mcp-proxy-adapter 2.1.17__py3-none-any.whl → 3.0.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.
- examples/__init__.py +19 -0
- examples/anti_patterns/README.md +51 -0
- examples/anti_patterns/__init__.py +9 -0
- examples/anti_patterns/bad_design/README.md +72 -0
- examples/anti_patterns/bad_design/global_state.py +170 -0
- examples/anti_patterns/bad_design/monolithic_command.py +272 -0
- examples/basic_example/README.md +245 -0
- examples/basic_example/__init__.py +8 -0
- examples/basic_example/commands/__init__.py +5 -0
- examples/basic_example/commands/echo_command.py +95 -0
- examples/basic_example/commands/math_command.py +151 -0
- examples/basic_example/commands/time_command.py +152 -0
- examples/basic_example/config.json +25 -0
- examples/basic_example/docs/EN/README.md +177 -0
- examples/basic_example/docs/RU/README.md +177 -0
- examples/basic_example/server.py +151 -0
- examples/basic_example/tests/conftest.py +243 -0
- examples/commands/echo_command.py +52 -0
- examples/commands/echo_result.py +65 -0
- examples/commands/get_date_command.py +98 -0
- examples/commands/new_uuid4_command.py +91 -0
- examples/complete_example/Dockerfile +24 -0
- examples/complete_example/README.md +92 -0
- examples/complete_example/__init__.py +8 -0
- examples/complete_example/commands/__init__.py +5 -0
- examples/complete_example/commands/system_command.py +328 -0
- examples/complete_example/config.json +41 -0
- examples/complete_example/configs/config.dev.yaml +40 -0
- examples/complete_example/configs/config.docker.yaml +40 -0
- examples/complete_example/docker-compose.yml +35 -0
- examples/complete_example/requirements.txt +20 -0
- examples/complete_example/server.py +139 -0
- examples/minimal_example/README.md +65 -0
- examples/minimal_example/__init__.py +8 -0
- examples/minimal_example/config.json +14 -0
- examples/minimal_example/main.py +136 -0
- examples/minimal_example/simple_server.py +163 -0
- examples/minimal_example/tests/conftest.py +171 -0
- examples/minimal_example/tests/test_hello_command.py +111 -0
- examples/minimal_example/tests/test_integration.py +181 -0
- examples/server.py +69 -0
- examples/simple_server.py +128 -0
- examples/test_server.py +134 -0
- examples/tool_description_example.py +82 -0
- mcp_proxy_adapter/__init__.py +33 -1
- mcp_proxy_adapter/api/__init__.py +0 -0
- mcp_proxy_adapter/api/app.py +391 -0
- mcp_proxy_adapter/api/handlers.py +229 -0
- mcp_proxy_adapter/api/middleware/__init__.py +49 -0
- mcp_proxy_adapter/api/middleware/auth.py +146 -0
- mcp_proxy_adapter/api/middleware/base.py +79 -0
- mcp_proxy_adapter/api/middleware/error_handling.py +198 -0
- mcp_proxy_adapter/api/middleware/logging.py +96 -0
- mcp_proxy_adapter/api/middleware/performance.py +83 -0
- mcp_proxy_adapter/api/middleware/rate_limit.py +152 -0
- mcp_proxy_adapter/api/schemas.py +305 -0
- mcp_proxy_adapter/api/tool_integration.py +223 -0
- mcp_proxy_adapter/api/tools.py +198 -0
- mcp_proxy_adapter/commands/__init__.py +19 -0
- mcp_proxy_adapter/commands/base.py +301 -0
- mcp_proxy_adapter/commands/command_registry.py +231 -0
- mcp_proxy_adapter/commands/config_command.py +113 -0
- mcp_proxy_adapter/commands/health_command.py +136 -0
- mcp_proxy_adapter/commands/help_command.py +193 -0
- mcp_proxy_adapter/commands/result.py +215 -0
- mcp_proxy_adapter/config.py +195 -0
- mcp_proxy_adapter/core/__init__.py +0 -0
- mcp_proxy_adapter/core/errors.py +173 -0
- mcp_proxy_adapter/core/logging.py +205 -0
- mcp_proxy_adapter/core/utils.py +138 -0
- mcp_proxy_adapter/custom_openapi.py +125 -0
- mcp_proxy_adapter/openapi.py +403 -0
- mcp_proxy_adapter/py.typed +0 -0
- mcp_proxy_adapter/schemas/base_schema.json +114 -0
- mcp_proxy_adapter/schemas/openapi_schema.json +314 -0
- mcp_proxy_adapter/tests/__init__.py +0 -0
- mcp_proxy_adapter/tests/api/__init__.py +3 -0
- mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +115 -0
- mcp_proxy_adapter/tests/api/test_middleware.py +336 -0
- mcp_proxy_adapter/tests/commands/__init__.py +3 -0
- mcp_proxy_adapter/tests/commands/test_config_command.py +211 -0
- mcp_proxy_adapter/tests/commands/test_echo_command.py +127 -0
- mcp_proxy_adapter/tests/commands/test_help_command.py +133 -0
- mcp_proxy_adapter/tests/conftest.py +131 -0
- mcp_proxy_adapter/tests/functional/__init__.py +3 -0
- mcp_proxy_adapter/tests/functional/test_api.py +235 -0
- mcp_proxy_adapter/tests/integration/__init__.py +3 -0
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +130 -0
- mcp_proxy_adapter/tests/integration/test_integration.py +255 -0
- mcp_proxy_adapter/tests/performance/__init__.py +3 -0
- mcp_proxy_adapter/tests/performance/test_performance.py +189 -0
- mcp_proxy_adapter/tests/stubs/__init__.py +10 -0
- mcp_proxy_adapter/tests/stubs/echo_command.py +104 -0
- mcp_proxy_adapter/tests/test_api_endpoints.py +271 -0
- mcp_proxy_adapter/tests/test_api_handlers.py +289 -0
- mcp_proxy_adapter/tests/test_base_command.py +123 -0
- mcp_proxy_adapter/tests/test_batch_requests.py +117 -0
- mcp_proxy_adapter/tests/test_command_registry.py +245 -0
- mcp_proxy_adapter/tests/test_config.py +127 -0
- mcp_proxy_adapter/tests/test_utils.py +65 -0
- mcp_proxy_adapter/tests/unit/__init__.py +3 -0
- mcp_proxy_adapter/tests/unit/test_base_command.py +130 -0
- mcp_proxy_adapter/tests/unit/test_config.py +217 -0
- mcp_proxy_adapter/version.py +3 -0
- mcp_proxy_adapter-3.0.1.dist-info/METADATA +200 -0
- mcp_proxy_adapter-3.0.1.dist-info/RECORD +109 -0
- {mcp_proxy_adapter-2.1.17.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/top_level.txt +1 -0
- mcp_proxy_adapter/adapter.py +0 -697
- mcp_proxy_adapter/analyzers/__init__.py +0 -1
- mcp_proxy_adapter/analyzers/docstring_analyzer.py +0 -199
- mcp_proxy_adapter/analyzers/type_analyzer.py +0 -151
- mcp_proxy_adapter/dispatchers/__init__.py +0 -1
- mcp_proxy_adapter/dispatchers/base_dispatcher.py +0 -85
- mcp_proxy_adapter/dispatchers/json_rpc_dispatcher.py +0 -262
- mcp_proxy_adapter/examples/analyze_config.py +0 -141
- mcp_proxy_adapter/examples/basic_integration.py +0 -155
- mcp_proxy_adapter/examples/docstring_and_schema_example.py +0 -69
- mcp_proxy_adapter/examples/extension_example.py +0 -72
- mcp_proxy_adapter/examples/help_best_practices.py +0 -67
- mcp_proxy_adapter/examples/help_usage.py +0 -64
- mcp_proxy_adapter/examples/mcp_proxy_client.py +0 -131
- mcp_proxy_adapter/examples/openapi_server.py +0 -383
- mcp_proxy_adapter/examples/project_structure_example.py +0 -47
- mcp_proxy_adapter/examples/testing_example.py +0 -64
- mcp_proxy_adapter/models.py +0 -47
- mcp_proxy_adapter/registry.py +0 -439
- mcp_proxy_adapter/schema.py +0 -257
- mcp_proxy_adapter/testing_utils.py +0 -112
- mcp_proxy_adapter/validators/__init__.py +0 -1
- mcp_proxy_adapter/validators/docstring_validator.py +0 -75
- mcp_proxy_adapter/validators/metadata_validator.py +0 -76
- mcp_proxy_adapter-2.1.17.dist-info/METADATA +0 -376
- mcp_proxy_adapter-2.1.17.dist-info/RECORD +0 -30
- {mcp_proxy_adapter-2.1.17.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-2.1.17.dist-info → mcp_proxy_adapter-3.0.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,328 @@
|
|
1
|
+
"""
|
2
|
+
System information command module.
|
3
|
+
|
4
|
+
This module contains a command that returns detailed information about the system.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import os
|
8
|
+
import sys
|
9
|
+
import socket
|
10
|
+
import platform
|
11
|
+
import datetime
|
12
|
+
from typing import Dict, Any, Optional, List
|
13
|
+
|
14
|
+
import psutil
|
15
|
+
import pytz
|
16
|
+
|
17
|
+
from mcp_proxy_adapter import Command, SuccessResult
|
18
|
+
|
19
|
+
|
20
|
+
class SystemInfoResult(SuccessResult):
|
21
|
+
"""
|
22
|
+
Result of system_info command.
|
23
|
+
|
24
|
+
Attributes:
|
25
|
+
system (dict): System information
|
26
|
+
cpu (dict): CPU information
|
27
|
+
memory (dict): Memory information
|
28
|
+
disk (dict): Disk information
|
29
|
+
python (dict): Python information
|
30
|
+
network (dict): Network information
|
31
|
+
time (dict): Time information
|
32
|
+
"""
|
33
|
+
|
34
|
+
def __init__(
|
35
|
+
self,
|
36
|
+
system: Dict[str, Any],
|
37
|
+
cpu: Dict[str, Any],
|
38
|
+
memory: Dict[str, Any],
|
39
|
+
disk: Dict[str, Any],
|
40
|
+
python: Dict[str, Any],
|
41
|
+
network: Dict[str, Any],
|
42
|
+
time: Dict[str, Any]
|
43
|
+
):
|
44
|
+
"""
|
45
|
+
Initialize result.
|
46
|
+
|
47
|
+
Args:
|
48
|
+
system: System information
|
49
|
+
cpu: CPU information
|
50
|
+
memory: Memory information
|
51
|
+
disk: Disk information
|
52
|
+
python: Python information
|
53
|
+
network: Network information
|
54
|
+
time: Time information
|
55
|
+
"""
|
56
|
+
self.system = system
|
57
|
+
self.cpu = cpu
|
58
|
+
self.memory = memory
|
59
|
+
self.disk = disk
|
60
|
+
self.python = python
|
61
|
+
self.network = network
|
62
|
+
self.time = time
|
63
|
+
|
64
|
+
def to_dict(self) -> Dict[str, Any]:
|
65
|
+
"""
|
66
|
+
Convert result to dictionary.
|
67
|
+
|
68
|
+
Returns:
|
69
|
+
Dictionary representation
|
70
|
+
"""
|
71
|
+
return {
|
72
|
+
"system": self.system,
|
73
|
+
"cpu": self.cpu,
|
74
|
+
"memory": self.memory,
|
75
|
+
"disk": self.disk,
|
76
|
+
"python": self.python,
|
77
|
+
"network": self.network,
|
78
|
+
"time": self.time
|
79
|
+
}
|
80
|
+
|
81
|
+
@classmethod
|
82
|
+
def get_schema(cls) -> Dict[str, Any]:
|
83
|
+
"""
|
84
|
+
Get JSON schema for result.
|
85
|
+
|
86
|
+
Returns:
|
87
|
+
JSON schema
|
88
|
+
"""
|
89
|
+
return {
|
90
|
+
"type": "object",
|
91
|
+
"properties": {
|
92
|
+
"system": {
|
93
|
+
"type": "object",
|
94
|
+
"description": "System information",
|
95
|
+
"properties": {
|
96
|
+
"platform": {"type": "string"},
|
97
|
+
"system": {"type": "string"},
|
98
|
+
"node": {"type": "string"},
|
99
|
+
"release": {"type": "string"},
|
100
|
+
"version": {"type": "string"},
|
101
|
+
"machine": {"type": "string"},
|
102
|
+
"processor": {"type": "string"},
|
103
|
+
"uptime": {"type": "number"}
|
104
|
+
}
|
105
|
+
},
|
106
|
+
"cpu": {
|
107
|
+
"type": "object",
|
108
|
+
"description": "CPU information",
|
109
|
+
"properties": {
|
110
|
+
"count_physical": {"type": "integer"},
|
111
|
+
"count_logical": {"type": "integer"},
|
112
|
+
"usage_percent": {"type": "number"},
|
113
|
+
"frequency": {"type": "object"}
|
114
|
+
}
|
115
|
+
},
|
116
|
+
"memory": {
|
117
|
+
"type": "object",
|
118
|
+
"description": "Memory information",
|
119
|
+
"properties": {
|
120
|
+
"total": {"type": "integer"},
|
121
|
+
"available": {"type": "integer"},
|
122
|
+
"used": {"type": "integer"},
|
123
|
+
"percent": {"type": "number"}
|
124
|
+
}
|
125
|
+
},
|
126
|
+
"disk": {
|
127
|
+
"type": "object",
|
128
|
+
"description": "Disk information",
|
129
|
+
"properties": {
|
130
|
+
"partitions": {"type": "array"},
|
131
|
+
"usage": {"type": "object"}
|
132
|
+
}
|
133
|
+
},
|
134
|
+
"python": {
|
135
|
+
"type": "object",
|
136
|
+
"description": "Python information",
|
137
|
+
"properties": {
|
138
|
+
"version": {"type": "string"},
|
139
|
+
"implementation": {"type": "string"},
|
140
|
+
"executable": {"type": "string"},
|
141
|
+
"packages": {"type": "array"}
|
142
|
+
}
|
143
|
+
},
|
144
|
+
"network": {
|
145
|
+
"type": "object",
|
146
|
+
"description": "Network information",
|
147
|
+
"properties": {
|
148
|
+
"interfaces": {"type": "array"},
|
149
|
+
"connections": {"type": "integer"}
|
150
|
+
}
|
151
|
+
},
|
152
|
+
"time": {
|
153
|
+
"type": "object",
|
154
|
+
"description": "Time information",
|
155
|
+
"properties": {
|
156
|
+
"current": {"type": "string"},
|
157
|
+
"utc": {"type": "string"},
|
158
|
+
"timezone": {"type": "string"},
|
159
|
+
"timestamp": {"type": "number"}
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
|
166
|
+
class SystemInfoCommand(Command):
|
167
|
+
"""
|
168
|
+
Command that returns detailed system information.
|
169
|
+
|
170
|
+
This command demonstrates gathering and formatting complex system data.
|
171
|
+
"""
|
172
|
+
|
173
|
+
name = "system_info"
|
174
|
+
result_class = SystemInfoResult
|
175
|
+
|
176
|
+
async def execute(
|
177
|
+
self,
|
178
|
+
include_python_packages: bool = False,
|
179
|
+
include_network_interfaces: bool = True
|
180
|
+
) -> SystemInfoResult:
|
181
|
+
"""
|
182
|
+
Execute command.
|
183
|
+
|
184
|
+
Args:
|
185
|
+
include_python_packages: Whether to include installed Python packages
|
186
|
+
include_network_interfaces: Whether to include network interfaces
|
187
|
+
|
188
|
+
Returns:
|
189
|
+
System information result
|
190
|
+
"""
|
191
|
+
# Gather system information
|
192
|
+
system_info = {
|
193
|
+
"platform": platform.platform(),
|
194
|
+
"system": platform.system(),
|
195
|
+
"node": platform.node(),
|
196
|
+
"release": platform.release(),
|
197
|
+
"version": platform.version(),
|
198
|
+
"machine": platform.machine(),
|
199
|
+
"processor": platform.processor(),
|
200
|
+
"uptime": psutil.boot_time()
|
201
|
+
}
|
202
|
+
|
203
|
+
# CPU information
|
204
|
+
cpu_info = {
|
205
|
+
"count_physical": psutil.cpu_count(logical=False),
|
206
|
+
"count_logical": psutil.cpu_count(logical=True),
|
207
|
+
"usage_percent": psutil.cpu_percent(interval=0.1),
|
208
|
+
"frequency": {
|
209
|
+
"current": psutil.cpu_freq().current if psutil.cpu_freq() else 0,
|
210
|
+
"min": psutil.cpu_freq().min if psutil.cpu_freq() and psutil.cpu_freq().min else 0,
|
211
|
+
"max": psutil.cpu_freq().max if psutil.cpu_freq() and psutil.cpu_freq().max else 0
|
212
|
+
}
|
213
|
+
}
|
214
|
+
|
215
|
+
# Memory information
|
216
|
+
memory = psutil.virtual_memory()
|
217
|
+
memory_info = {
|
218
|
+
"total": memory.total,
|
219
|
+
"available": memory.available,
|
220
|
+
"used": memory.used,
|
221
|
+
"percent": memory.percent
|
222
|
+
}
|
223
|
+
|
224
|
+
# Disk information
|
225
|
+
disk_info = {
|
226
|
+
"partitions": [],
|
227
|
+
"usage": {}
|
228
|
+
}
|
229
|
+
|
230
|
+
for partition in psutil.disk_partitions():
|
231
|
+
try:
|
232
|
+
usage = psutil.disk_usage(partition.mountpoint)
|
233
|
+
disk_info["partitions"].append({
|
234
|
+
"device": partition.device,
|
235
|
+
"mountpoint": partition.mountpoint,
|
236
|
+
"fstype": partition.fstype,
|
237
|
+
"opts": partition.opts
|
238
|
+
})
|
239
|
+
disk_info["usage"][partition.mountpoint] = {
|
240
|
+
"total": usage.total,
|
241
|
+
"used": usage.used,
|
242
|
+
"free": usage.free,
|
243
|
+
"percent": usage.percent
|
244
|
+
}
|
245
|
+
except (PermissionError, FileNotFoundError):
|
246
|
+
# Some mountpoints may not be accessible
|
247
|
+
pass
|
248
|
+
|
249
|
+
# Python information
|
250
|
+
python_info = {
|
251
|
+
"version": platform.python_version(),
|
252
|
+
"implementation": platform.python_implementation(),
|
253
|
+
"executable": sys.executable,
|
254
|
+
"packages": []
|
255
|
+
}
|
256
|
+
|
257
|
+
if include_python_packages:
|
258
|
+
try:
|
259
|
+
import pkg_resources
|
260
|
+
python_info["packages"] = [
|
261
|
+
{"name": pkg.key, "version": pkg.version}
|
262
|
+
for pkg in pkg_resources.working_set
|
263
|
+
]
|
264
|
+
except ImportError:
|
265
|
+
pass
|
266
|
+
|
267
|
+
# Network information
|
268
|
+
network_info = {
|
269
|
+
"interfaces": [],
|
270
|
+
"connections": len(psutil.net_connections())
|
271
|
+
}
|
272
|
+
|
273
|
+
if include_network_interfaces:
|
274
|
+
for interface, addresses in psutil.net_if_addrs().items():
|
275
|
+
for address in addresses:
|
276
|
+
if address.family == socket.AF_INET: # IPv4
|
277
|
+
network_info["interfaces"].append({
|
278
|
+
"interface": interface,
|
279
|
+
"address": address.address,
|
280
|
+
"netmask": address.netmask,
|
281
|
+
"broadcast": address.broadcast
|
282
|
+
})
|
283
|
+
|
284
|
+
# Time information
|
285
|
+
now = datetime.datetime.now()
|
286
|
+
utc_now = datetime.datetime.now(pytz.UTC)
|
287
|
+
|
288
|
+
time_info = {
|
289
|
+
"current": now.isoformat(),
|
290
|
+
"utc": utc_now.isoformat(),
|
291
|
+
"timezone": str(datetime.datetime.now().astimezone().tzinfo),
|
292
|
+
"timestamp": now.timestamp()
|
293
|
+
}
|
294
|
+
|
295
|
+
return SystemInfoResult(
|
296
|
+
system=system_info,
|
297
|
+
cpu=cpu_info,
|
298
|
+
memory=memory_info,
|
299
|
+
disk=disk_info,
|
300
|
+
python=python_info,
|
301
|
+
network=network_info,
|
302
|
+
time=time_info
|
303
|
+
)
|
304
|
+
|
305
|
+
@classmethod
|
306
|
+
def get_schema(cls) -> Dict[str, Any]:
|
307
|
+
"""
|
308
|
+
Get JSON schema for command parameters.
|
309
|
+
|
310
|
+
Returns:
|
311
|
+
JSON schema
|
312
|
+
"""
|
313
|
+
return {
|
314
|
+
"type": "object",
|
315
|
+
"properties": {
|
316
|
+
"include_python_packages": {
|
317
|
+
"type": "boolean",
|
318
|
+
"description": "Whether to include installed Python packages",
|
319
|
+
"default": False
|
320
|
+
},
|
321
|
+
"include_network_interfaces": {
|
322
|
+
"type": "boolean",
|
323
|
+
"description": "Whether to include network interfaces",
|
324
|
+
"default": True
|
325
|
+
}
|
326
|
+
},
|
327
|
+
"additionalProperties": False
|
328
|
+
}
|
@@ -0,0 +1,41 @@
|
|
1
|
+
{
|
2
|
+
"service": {
|
3
|
+
"name": "Complete Example",
|
4
|
+
"version": "1.0.0",
|
5
|
+
"description": "Полный пример MCP Proxy Adapter"
|
6
|
+
},
|
7
|
+
"server": {
|
8
|
+
"host": "0.0.0.0",
|
9
|
+
"port": 8000,
|
10
|
+
"debug": false,
|
11
|
+
"log_level": "info",
|
12
|
+
"workers": 4
|
13
|
+
},
|
14
|
+
"logging": {
|
15
|
+
"level": "INFO",
|
16
|
+
"file": "logs/complete_example.log",
|
17
|
+
"rotation": {
|
18
|
+
"type": "time",
|
19
|
+
"when": "D",
|
20
|
+
"interval": 1,
|
21
|
+
"backup_count": 30
|
22
|
+
}
|
23
|
+
},
|
24
|
+
"auth": {
|
25
|
+
"enabled": false,
|
26
|
+
"token_expiration": 3600,
|
27
|
+
"secret_key": "change_this_to_a_secure_key_in_production"
|
28
|
+
},
|
29
|
+
"database": {
|
30
|
+
"url": "sqlite:///./data/database.db",
|
31
|
+
"echo": false,
|
32
|
+
"pool_size": 5,
|
33
|
+
"max_overflow": 10
|
34
|
+
},
|
35
|
+
"cache": {
|
36
|
+
"enabled": true,
|
37
|
+
"ttl": 300,
|
38
|
+
"type": "memory",
|
39
|
+
"max_size": 1000
|
40
|
+
}
|
41
|
+
}
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Development configuration for complete MCP Microservice example
|
2
|
+
|
3
|
+
# Server settings
|
4
|
+
server:
|
5
|
+
host: "localhost" # Host to bind server
|
6
|
+
port: 8000 # Port to bind server
|
7
|
+
workers: 1 # Number of worker processes
|
8
|
+
debug: true # Enable debug mode
|
9
|
+
|
10
|
+
# Logging settings
|
11
|
+
logging:
|
12
|
+
level: "DEBUG" # Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
13
|
+
file: "logs/complete_example.log" # Log file path
|
14
|
+
rotation:
|
15
|
+
type: "size" # Log rotation type (size, time)
|
16
|
+
max_bytes: 10485760 # Maximum log file size (10 MB)
|
17
|
+
backup_count: 5 # Number of backup files
|
18
|
+
|
19
|
+
# Command discovery settings
|
20
|
+
discovery:
|
21
|
+
enabled: true
|
22
|
+
package: "commands" # Package to discover commands
|
23
|
+
|
24
|
+
# Cache settings
|
25
|
+
cache:
|
26
|
+
enabled: true
|
27
|
+
type: "file" # Cache type (file, memory, redis)
|
28
|
+
path: "cache" # Cache directory
|
29
|
+
ttl: 300 # Default TTL in seconds
|
30
|
+
|
31
|
+
# Database settings (for db_command)
|
32
|
+
database:
|
33
|
+
enabled: false # Database is disabled in development
|
34
|
+
type: "sqlite" # Database type
|
35
|
+
path: ":memory:" # Database path (in-memory SQLite)
|
36
|
+
|
37
|
+
# File operations settings (for file_command)
|
38
|
+
files:
|
39
|
+
base_path: "." # Base path for file operations
|
40
|
+
allowed_extensions: [".txt", ".log", ".json", ".yaml"] # Allowed file extensions
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# Docker configuration for complete MCP Microservice example
|
2
|
+
|
3
|
+
# Server settings
|
4
|
+
server:
|
5
|
+
host: "0.0.0.0" # Bind to all interfaces in Docker
|
6
|
+
port: 8000 # Port to bind server
|
7
|
+
workers: 2 # Number of worker processes
|
8
|
+
debug: false # Disable debug mode in production
|
9
|
+
|
10
|
+
# Logging settings
|
11
|
+
logging:
|
12
|
+
level: "INFO" # Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
|
13
|
+
file: "/app/logs/complete_example.log" # Log file path in Docker container
|
14
|
+
rotation:
|
15
|
+
type: "size" # Log rotation type (size, time)
|
16
|
+
max_bytes: 10485760 # Maximum log file size (10 MB)
|
17
|
+
backup_count: 10 # Number of backup files
|
18
|
+
|
19
|
+
# Command discovery settings
|
20
|
+
discovery:
|
21
|
+
enabled: true
|
22
|
+
package: "commands" # Package to discover commands
|
23
|
+
|
24
|
+
# Cache settings
|
25
|
+
cache:
|
26
|
+
enabled: true
|
27
|
+
type: "file" # Cache type (file, memory, redis)
|
28
|
+
path: "/app/cache" # Cache directory in Docker container
|
29
|
+
ttl: 3600 # Default TTL in seconds (1 hour)
|
30
|
+
|
31
|
+
# Database settings (for db_command)
|
32
|
+
database:
|
33
|
+
enabled: true # Enable database in Docker environment
|
34
|
+
type: "sqlite" # Database type
|
35
|
+
path: "/app/data/db.sqlite" # Database path in Docker container
|
36
|
+
|
37
|
+
# File operations settings (for file_command)
|
38
|
+
files:
|
39
|
+
base_path: "/app/data" # Base path for file operations in Docker
|
40
|
+
allowed_extensions: [".txt", ".log", ".json", ".yaml"] # Allowed file extensions
|
@@ -0,0 +1,35 @@
|
|
1
|
+
version: '3.8'
|
2
|
+
|
3
|
+
services:
|
4
|
+
mcp-proxy-adapter:
|
5
|
+
build:
|
6
|
+
context: .
|
7
|
+
dockerfile: Dockerfile
|
8
|
+
image: mcp-proxy-adapter-example:latest
|
9
|
+
container_name: mcp-proxy-adapter-example
|
10
|
+
restart: unless-stopped
|
11
|
+
ports:
|
12
|
+
- "8000:8000"
|
13
|
+
volumes:
|
14
|
+
# Mount configuration, logs, and cache from host
|
15
|
+
- ./configs:/app/configs:ro
|
16
|
+
- ./logs:/app/logs
|
17
|
+
- ./cache:/app/cache
|
18
|
+
- ./data:/app/data
|
19
|
+
environment:
|
20
|
+
- PYTHONUNBUFFERED=1
|
21
|
+
- CONFIG_PATH=/app/configs/config.docker.yaml
|
22
|
+
networks:
|
23
|
+
- smart-assistant
|
24
|
+
user: "${UID:-1000}:${GID:-1000}" # Use host user ID to avoid permission issues
|
25
|
+
healthcheck:
|
26
|
+
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
|
27
|
+
interval: 30s
|
28
|
+
timeout: 10s
|
29
|
+
retries: 3
|
30
|
+
start_period: 10s
|
31
|
+
|
32
|
+
networks:
|
33
|
+
smart-assistant:
|
34
|
+
# Use external network if it exists, otherwise create it
|
35
|
+
external: true
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Python dependencies for MCP Microservice complete example
|
2
|
+
|
3
|
+
# Core dependencies
|
4
|
+
fastapi>=0.95.0,<1.0.0
|
5
|
+
pydantic>=2.0.0,<3.0.0
|
6
|
+
uvicorn>=0.22.0,<1.0.0
|
7
|
+
docstring-parser>=0.15,<1.0.0
|
8
|
+
typing-extensions>=4.5.0,<5.0.0
|
9
|
+
jsonrpc>=1.2.0,<2.0.0
|
10
|
+
|
11
|
+
# For system_command
|
12
|
+
psutil>=5.9.0,<6.0.0
|
13
|
+
pytz>=2023.3
|
14
|
+
|
15
|
+
# For file_command
|
16
|
+
aiofiles>=23.1.0,<24.0.0
|
17
|
+
|
18
|
+
# For db_command
|
19
|
+
aiosqlite>=0.17.0,<1.0.0
|
20
|
+
SQLAlchemy>=2.0.0,<3.0.0
|
@@ -0,0 +1,139 @@
|
|
1
|
+
"""
|
2
|
+
Complete MCP Microservice example.
|
3
|
+
|
4
|
+
This example demonstrates a complete microservice application with Docker support,
|
5
|
+
environment-specific configuration, and multiple commands.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import os
|
9
|
+
import sys
|
10
|
+
import argparse
|
11
|
+
from typing import Dict, Any
|
12
|
+
from pathlib import Path
|
13
|
+
|
14
|
+
import mcp_proxy_adapter as mcp
|
15
|
+
from mcp_proxy_adapter import MicroService
|
16
|
+
from mcp_proxy_adapter.commands.command_registry import registry
|
17
|
+
from mcp_proxy_adapter.core.logging import logger
|
18
|
+
from mcp_proxy_adapter.config import config
|
19
|
+
|
20
|
+
# Add commands directory to path for local imports
|
21
|
+
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
22
|
+
|
23
|
+
|
24
|
+
def parse_args():
|
25
|
+
"""
|
26
|
+
Parse command line arguments.
|
27
|
+
|
28
|
+
Returns:
|
29
|
+
Parsed arguments
|
30
|
+
"""
|
31
|
+
parser = argparse.ArgumentParser(description="MCP Microservice Example")
|
32
|
+
parser.add_argument(
|
33
|
+
"--config",
|
34
|
+
default="configs/config.dev.yaml",
|
35
|
+
help="Path to configuration file"
|
36
|
+
)
|
37
|
+
return parser.parse_args()
|
38
|
+
|
39
|
+
|
40
|
+
def ensure_directories(config_path: str):
|
41
|
+
"""
|
42
|
+
Create necessary directories based on configuration.
|
43
|
+
|
44
|
+
Args:
|
45
|
+
config_path: Path to configuration file
|
46
|
+
"""
|
47
|
+
# Extract base directory
|
48
|
+
base_dir = os.path.dirname(os.path.abspath(__file__))
|
49
|
+
|
50
|
+
# Create logs directory
|
51
|
+
os.makedirs(os.path.join(base_dir, "logs"), exist_ok=True)
|
52
|
+
|
53
|
+
# Create cache directory
|
54
|
+
os.makedirs(os.path.join(base_dir, "cache"), exist_ok=True)
|
55
|
+
|
56
|
+
# Create data directory
|
57
|
+
os.makedirs(os.path.join(base_dir, "data"), exist_ok=True)
|
58
|
+
|
59
|
+
|
60
|
+
def setup_application(config_file=None):
|
61
|
+
"""
|
62
|
+
Setup and configure the microservice application.
|
63
|
+
|
64
|
+
Args:
|
65
|
+
config_file: Path to configuration file (optional)
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
Configured microservice object
|
69
|
+
"""
|
70
|
+
# Parse command line arguments if config_file not provided
|
71
|
+
if config_file is None:
|
72
|
+
args = parse_args()
|
73
|
+
config_file = args.config
|
74
|
+
|
75
|
+
# Get absolute path to config file
|
76
|
+
current_dir = Path(__file__).parent.absolute()
|
77
|
+
config_path = current_dir / config_file
|
78
|
+
|
79
|
+
# Fall back to config.json if specified file doesn't exist
|
80
|
+
if not config_path.exists():
|
81
|
+
config_path = current_dir / "config.json"
|
82
|
+
|
83
|
+
# Create necessary directories
|
84
|
+
ensure_directories(str(config_path))
|
85
|
+
|
86
|
+
# Load configuration if exists
|
87
|
+
if config_path.exists():
|
88
|
+
config.load_from_file(str(config_path))
|
89
|
+
logger.info(f"Loaded configuration from {config_path}")
|
90
|
+
else:
|
91
|
+
logger.warning(f"Configuration file {config_path} not found, using defaults")
|
92
|
+
|
93
|
+
# Create microservice
|
94
|
+
service = MicroService(
|
95
|
+
title="Complete MCP Microservice Example",
|
96
|
+
description="Full-featured microservice with Docker support",
|
97
|
+
version="1.0.0",
|
98
|
+
config_path=str(config_path) if config_path.exists() else None
|
99
|
+
)
|
100
|
+
|
101
|
+
# Safely register commands from package
|
102
|
+
try:
|
103
|
+
# Clear any existing registrations to prevent conflicts
|
104
|
+
package_path = "commands"
|
105
|
+
|
106
|
+
# Get currently registered commands
|
107
|
+
commands = registry.get_all_commands()
|
108
|
+
for cmd_name in list(commands.keys()):
|
109
|
+
try:
|
110
|
+
registry.unregister(cmd_name)
|
111
|
+
except Exception as e:
|
112
|
+
logger.debug(f"Error unregistering command {cmd_name}: {e}")
|
113
|
+
|
114
|
+
# Discover and register commands
|
115
|
+
service.discover_commands(package_path)
|
116
|
+
logger.info(f"Discovered and registered commands from package: {package_path}")
|
117
|
+
except Exception as e:
|
118
|
+
logger.error(f"Error discovering commands: {e}")
|
119
|
+
|
120
|
+
return service
|
121
|
+
|
122
|
+
|
123
|
+
def main():
|
124
|
+
"""Run microservice with command discovery."""
|
125
|
+
# Setup application
|
126
|
+
service = setup_application()
|
127
|
+
|
128
|
+
# Check if port is overridden by environment variable (for testing)
|
129
|
+
if "TEST_SERVER_PORT" in os.environ:
|
130
|
+
port = int(os.environ["TEST_SERVER_PORT"])
|
131
|
+
service.port = port
|
132
|
+
logger.info(f"Using test port from environment: {port}")
|
133
|
+
|
134
|
+
# Run server with parameters from configuration
|
135
|
+
service.run()
|
136
|
+
|
137
|
+
|
138
|
+
if __name__ == "__main__":
|
139
|
+
main()
|