mcp-proxy-adapter 6.0.0__py3-none-any.whl → 6.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.
- mcp_proxy_adapter/__main__.py +27 -7
- mcp_proxy_adapter/api/app.py +209 -79
- mcp_proxy_adapter/api/handlers.py +16 -5
- mcp_proxy_adapter/api/middleware/__init__.py +14 -9
- mcp_proxy_adapter/api/middleware/command_permission_middleware.py +148 -0
- mcp_proxy_adapter/api/middleware/factory.py +36 -12
- mcp_proxy_adapter/api/middleware/protocol_middleware.py +84 -18
- mcp_proxy_adapter/api/middleware/unified_security.py +197 -0
- mcp_proxy_adapter/api/middleware/user_info_middleware.py +158 -0
- mcp_proxy_adapter/commands/__init__.py +7 -1
- mcp_proxy_adapter/commands/base.py +7 -4
- mcp_proxy_adapter/commands/builtin_commands.py +8 -2
- mcp_proxy_adapter/commands/command_registry.py +8 -0
- mcp_proxy_adapter/commands/echo_command.py +81 -0
- mcp_proxy_adapter/commands/health_command.py +1 -1
- mcp_proxy_adapter/commands/help_command.py +21 -14
- mcp_proxy_adapter/commands/proxy_registration_command.py +326 -185
- mcp_proxy_adapter/commands/role_test_command.py +141 -0
- mcp_proxy_adapter/commands/security_command.py +488 -0
- mcp_proxy_adapter/commands/ssl_setup_command.py +234 -351
- mcp_proxy_adapter/commands/token_management_command.py +1 -1
- mcp_proxy_adapter/config.py +323 -40
- mcp_proxy_adapter/core/app_factory.py +410 -0
- mcp_proxy_adapter/core/app_runner.py +272 -0
- mcp_proxy_adapter/core/certificate_utils.py +291 -73
- mcp_proxy_adapter/core/client.py +574 -0
- mcp_proxy_adapter/core/client_manager.py +284 -0
- mcp_proxy_adapter/core/client_security.py +384 -0
- mcp_proxy_adapter/core/logging.py +8 -3
- mcp_proxy_adapter/core/mtls_asgi.py +156 -0
- mcp_proxy_adapter/core/mtls_asgi_app.py +187 -0
- mcp_proxy_adapter/core/protocol_manager.py +169 -10
- mcp_proxy_adapter/core/proxy_client.py +602 -0
- mcp_proxy_adapter/core/proxy_registration.py +299 -47
- mcp_proxy_adapter/core/security_adapter.py +12 -15
- mcp_proxy_adapter/core/security_integration.py +286 -0
- mcp_proxy_adapter/core/server_adapter.py +282 -0
- mcp_proxy_adapter/core/server_engine.py +270 -0
- mcp_proxy_adapter/core/ssl_utils.py +13 -12
- mcp_proxy_adapter/core/transport_manager.py +5 -5
- mcp_proxy_adapter/core/unified_config_adapter.py +579 -0
- mcp_proxy_adapter/examples/__init__.py +13 -4
- mcp_proxy_adapter/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/basic_framework/main.py +44 -0
- mcp_proxy_adapter/examples/commands/__init__.py +5 -0
- mcp_proxy_adapter/examples/create_certificates_simple.py +550 -0
- mcp_proxy_adapter/examples/debug_request_state.py +112 -0
- mcp_proxy_adapter/examples/debug_role_chain.py +158 -0
- mcp_proxy_adapter/examples/demo_client.py +275 -0
- mcp_proxy_adapter/examples/examples/basic_framework/__init__.py +9 -0
- mcp_proxy_adapter/examples/examples/basic_framework/commands/__init__.py +4 -0
- mcp_proxy_adapter/examples/examples/basic_framework/hooks/__init__.py +4 -0
- mcp_proxy_adapter/examples/examples/basic_framework/main.py +44 -0
- mcp_proxy_adapter/examples/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/__init__.py +7 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +80 -0
- mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +90 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/__init__.py +7 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +75 -0
- mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +71 -0
- mcp_proxy_adapter/examples/examples/full_application/main.py +173 -0
- mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +154 -0
- mcp_proxy_adapter/examples/full_application/__init__.py +12 -0
- mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
- mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +80 -0
- mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +90 -0
- mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
- mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +75 -0
- mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +71 -0
- mcp_proxy_adapter/examples/full_application/main.py +173 -0
- mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
- mcp_proxy_adapter/examples/generate_all_certificates.py +362 -0
- mcp_proxy_adapter/examples/generate_certificates.py +177 -0
- mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
- mcp_proxy_adapter/examples/generate_test_configs.py +331 -0
- mcp_proxy_adapter/examples/proxy_registration_example.py +334 -0
- mcp_proxy_adapter/examples/run_example.py +59 -0
- mcp_proxy_adapter/examples/run_full_test_suite.py +318 -0
- mcp_proxy_adapter/examples/run_proxy_server.py +146 -0
- mcp_proxy_adapter/examples/run_security_tests.py +544 -0
- mcp_proxy_adapter/examples/run_security_tests_fixed.py +247 -0
- mcp_proxy_adapter/examples/scripts/config_generator.py +740 -0
- mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +560 -0
- mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +369 -0
- mcp_proxy_adapter/examples/security_test_client.py +782 -0
- mcp_proxy_adapter/examples/setup_test_environment.py +328 -0
- mcp_proxy_adapter/examples/test_config.py +148 -0
- mcp_proxy_adapter/examples/test_config_generator.py +86 -0
- mcp_proxy_adapter/examples/test_examples.py +281 -0
- mcp_proxy_adapter/examples/universal_client.py +620 -0
- mcp_proxy_adapter/main.py +66 -148
- mcp_proxy_adapter/utils/config_generator.py +1008 -0
- mcp_proxy_adapter/version.py +5 -2
- mcp_proxy_adapter-6.0.1.dist-info/METADATA +679 -0
- mcp_proxy_adapter-6.0.1.dist-info/RECORD +140 -0
- mcp_proxy_adapter-6.0.1.dist-info/entry_points.txt +2 -0
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/licenses/LICENSE +2 -2
- mcp_proxy_adapter/api/middleware/auth.py +0 -146
- mcp_proxy_adapter/api/middleware/auth_adapter.py +0 -235
- mcp_proxy_adapter/api/middleware/mtls_adapter.py +0 -305
- mcp_proxy_adapter/api/middleware/mtls_middleware.py +0 -296
- mcp_proxy_adapter/api/middleware/rate_limit.py +0 -152
- mcp_proxy_adapter/api/middleware/rate_limit_adapter.py +0 -241
- mcp_proxy_adapter/api/middleware/roles_adapter.py +0 -365
- mcp_proxy_adapter/api/middleware/roles_middleware.py +0 -381
- mcp_proxy_adapter/api/middleware/security.py +0 -376
- mcp_proxy_adapter/api/middleware/token_auth_middleware.py +0 -261
- mcp_proxy_adapter/examples/README.md +0 -124
- mcp_proxy_adapter/examples/basic_server/README.md +0 -60
- mcp_proxy_adapter/examples/basic_server/__init__.py +0 -7
- mcp_proxy_adapter/examples/basic_server/basic_custom_settings.json +0 -39
- mcp_proxy_adapter/examples/basic_server/config.json +0 -70
- mcp_proxy_adapter/examples/basic_server/config_all_protocols.json +0 -54
- mcp_proxy_adapter/examples/basic_server/config_http.json +0 -70
- mcp_proxy_adapter/examples/basic_server/config_http_only.json +0 -52
- mcp_proxy_adapter/examples/basic_server/config_https.json +0 -58
- mcp_proxy_adapter/examples/basic_server/config_mtls.json +0 -58
- mcp_proxy_adapter/examples/basic_server/config_ssl.json +0 -46
- mcp_proxy_adapter/examples/basic_server/custom_settings_example.py +0 -238
- mcp_proxy_adapter/examples/basic_server/server.py +0 -114
- mcp_proxy_adapter/examples/custom_commands/README.md +0 -127
- mcp_proxy_adapter/examples/custom_commands/__init__.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/advanced_hooks.py +0 -566
- mcp_proxy_adapter/examples/custom_commands/auto_commands/__init__.py +0 -6
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/auto_commands/auto_info_command.py +0 -111
- mcp_proxy_adapter/examples/custom_commands/auto_commands/test_command.py +0 -105
- mcp_proxy_adapter/examples/custom_commands/catalog/commands/test_command.py +0 -129
- mcp_proxy_adapter/examples/custom_commands/config.json +0 -118
- mcp_proxy_adapter/examples/custom_commands/config_all_protocols.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_https_only.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_https_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/config_mtls_only.json +0 -46
- mcp_proxy_adapter/examples/custom_commands/config_mtls_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/config_single_transport.json +0 -33
- mcp_proxy_adapter/examples/custom_commands/custom_health_command.py +0 -169
- mcp_proxy_adapter/examples/custom_commands/custom_help_command.py +0 -215
- mcp_proxy_adapter/examples/custom_commands/custom_openapi_generator.py +0 -76
- mcp_proxy_adapter/examples/custom_commands/custom_settings.json +0 -96
- mcp_proxy_adapter/examples/custom_commands/custom_settings_manager.py +0 -241
- mcp_proxy_adapter/examples/custom_commands/data_transform_command.py +0 -135
- mcp_proxy_adapter/examples/custom_commands/echo_command.py +0 -122
- mcp_proxy_adapter/examples/custom_commands/full_help_response.json +0 -1
- mcp_proxy_adapter/examples/custom_commands/generated_openapi.json +0 -629
- mcp_proxy_adapter/examples/custom_commands/get_openapi.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/hooks.py +0 -230
- mcp_proxy_adapter/examples/custom_commands/intercept_command.py +0 -123
- mcp_proxy_adapter/examples/custom_commands/loadable_commands/test_ignored.py +0 -129
- mcp_proxy_adapter/examples/custom_commands/manual_echo_command.py +0 -103
- mcp_proxy_adapter/examples/custom_commands/proxy_connection_manager.py +0 -278
- mcp_proxy_adapter/examples/custom_commands/server.py +0 -252
- mcp_proxy_adapter/examples/custom_commands/simple_openapi_server.py +0 -75
- mcp_proxy_adapter/examples/custom_commands/start_server_with_proxy_manager.py +0 -299
- mcp_proxy_adapter/examples/custom_commands/start_server_with_registration.py +0 -278
- mcp_proxy_adapter/examples/custom_commands/test_hooks.py +0 -176
- mcp_proxy_adapter/examples/custom_commands/test_openapi.py +0 -27
- mcp_proxy_adapter/examples/custom_commands/test_registry.py +0 -23
- mcp_proxy_adapter/examples/custom_commands/test_simple.py +0 -19
- mcp_proxy_adapter/examples/custom_project_example/README.md +0 -103
- mcp_proxy_adapter/examples/custom_project_example/README_EN.md +0 -103
- mcp_proxy_adapter/examples/deployment/README.md +0 -49
- mcp_proxy_adapter/examples/deployment/__init__.py +0 -7
- mcp_proxy_adapter/examples/deployment/config.development.json +0 -8
- mcp_proxy_adapter/examples/deployment/config.json +0 -29
- mcp_proxy_adapter/examples/deployment/config.production.json +0 -12
- mcp_proxy_adapter/examples/deployment/config.staging.json +0 -11
- mcp_proxy_adapter/examples/deployment/docker-compose.yml +0 -31
- mcp_proxy_adapter/examples/deployment/run.sh +0 -43
- mcp_proxy_adapter/examples/deployment/run_docker.sh +0 -84
- mcp_proxy_adapter/examples/simple_custom_commands/README.md +0 -149
- mcp_proxy_adapter/examples/simple_custom_commands/README_EN.md +0 -149
- mcp_proxy_adapter/schemas/base_schema.json +0 -114
- mcp_proxy_adapter/schemas/openapi_schema.json +0 -314
- mcp_proxy_adapter/schemas/roles_schema.json +0 -162
- mcp_proxy_adapter/tests/__init__.py +0 -0
- mcp_proxy_adapter/tests/api/__init__.py +0 -3
- mcp_proxy_adapter/tests/api/test_cmd_endpoint.py +0 -115
- mcp_proxy_adapter/tests/api/test_custom_openapi.py +0 -617
- mcp_proxy_adapter/tests/api/test_handlers.py +0 -522
- mcp_proxy_adapter/tests/api/test_middleware.py +0 -340
- mcp_proxy_adapter/tests/api/test_schemas.py +0 -546
- mcp_proxy_adapter/tests/api/test_tool_integration.py +0 -531
- mcp_proxy_adapter/tests/commands/__init__.py +0 -3
- mcp_proxy_adapter/tests/commands/test_config_command.py +0 -211
- mcp_proxy_adapter/tests/commands/test_echo_command.py +0 -127
- mcp_proxy_adapter/tests/commands/test_help_command.py +0 -136
- mcp_proxy_adapter/tests/conftest.py +0 -131
- mcp_proxy_adapter/tests/functional/__init__.py +0 -3
- mcp_proxy_adapter/tests/functional/test_api.py +0 -253
- mcp_proxy_adapter/tests/integration/__init__.py +0 -3
- mcp_proxy_adapter/tests/integration/test_cmd_integration.py +0 -129
- mcp_proxy_adapter/tests/integration/test_integration.py +0 -255
- mcp_proxy_adapter/tests/performance/__init__.py +0 -3
- mcp_proxy_adapter/tests/performance/test_performance.py +0 -189
- mcp_proxy_adapter/tests/stubs/__init__.py +0 -10
- mcp_proxy_adapter/tests/stubs/echo_command.py +0 -104
- mcp_proxy_adapter/tests/test_api_endpoints.py +0 -271
- mcp_proxy_adapter/tests/test_api_handlers.py +0 -289
- mcp_proxy_adapter/tests/test_base_command.py +0 -123
- mcp_proxy_adapter/tests/test_batch_requests.py +0 -117
- mcp_proxy_adapter/tests/test_command_registry.py +0 -281
- mcp_proxy_adapter/tests/test_config.py +0 -127
- mcp_proxy_adapter/tests/test_utils.py +0 -65
- mcp_proxy_adapter/tests/unit/__init__.py +0 -3
- mcp_proxy_adapter/tests/unit/test_base_command.py +0 -436
- mcp_proxy_adapter/tests/unit/test_config.py +0 -270
- mcp_proxy_adapter-6.0.0.dist-info/METADATA +0 -201
- mcp_proxy_adapter-6.0.0.dist-info/RECORD +0 -179
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/WHEEL +0 -0
- {mcp_proxy_adapter-6.0.0.dist-info → mcp_proxy_adapter-6.0.1.dist-info}/top_level.txt +0 -0
@@ -1,103 +0,0 @@
|
|
1
|
-
#!/usr/bin/env python3
|
2
|
-
"""
|
3
|
-
Script to get OpenAPI schema directly from the code.
|
4
|
-
"""
|
5
|
-
|
6
|
-
import json
|
7
|
-
import asyncio
|
8
|
-
import sys
|
9
|
-
import os
|
10
|
-
from pathlib import Path
|
11
|
-
|
12
|
-
# Add current directory to path for imports
|
13
|
-
sys.path.insert(0, os.getcwd())
|
14
|
-
|
15
|
-
from mcp_proxy_adapter.custom_openapi import CustomOpenAPIGenerator
|
16
|
-
from mcp_proxy_adapter.commands.command_registry import registry
|
17
|
-
|
18
|
-
async def main():
|
19
|
-
"""Generate and save OpenAPI schema."""
|
20
|
-
try:
|
21
|
-
# Initialize commands first
|
22
|
-
print("🔄 Initializing commands...")
|
23
|
-
result = await registry.reload_system()
|
24
|
-
print(f"✅ Commands initialized: {result}")
|
25
|
-
|
26
|
-
# Load custom commands manually
|
27
|
-
print("🔄 Loading custom commands...")
|
28
|
-
custom_commands = [
|
29
|
-
"echo_command",
|
30
|
-
"custom_help_command",
|
31
|
-
"custom_health_command",
|
32
|
-
"manual_echo_command"
|
33
|
-
]
|
34
|
-
|
35
|
-
for cmd_name in custom_commands:
|
36
|
-
try:
|
37
|
-
# Import the command module
|
38
|
-
module = __import__(cmd_name)
|
39
|
-
print(f"✅ Loaded custom command: {cmd_name}")
|
40
|
-
|
41
|
-
# Try to register the command if it has a command class
|
42
|
-
if hasattr(module, 'EchoCommand'):
|
43
|
-
registry.register_custom(module.EchoCommand())
|
44
|
-
print(f"✅ Registered EchoCommand")
|
45
|
-
elif hasattr(module, 'CustomHelpCommand'):
|
46
|
-
registry.register_custom(module.CustomHelpCommand())
|
47
|
-
print(f"✅ Registered CustomHelpCommand")
|
48
|
-
elif hasattr(module, 'CustomHealthCommand'):
|
49
|
-
registry.register_custom(module.CustomHealthCommand())
|
50
|
-
print(f"✅ Registered CustomHealthCommand")
|
51
|
-
elif hasattr(module, 'ManualEchoCommand'):
|
52
|
-
registry.register_custom(module.ManualEchoCommand())
|
53
|
-
print(f"✅ Registered ManualEchoCommand")
|
54
|
-
|
55
|
-
except Exception as e:
|
56
|
-
print(f"⚠️ Failed to load {cmd_name}: {e}")
|
57
|
-
|
58
|
-
# Get commands after registration
|
59
|
-
print("📋 Getting commands after registration...")
|
60
|
-
commands = registry.get_all_commands()
|
61
|
-
print(f" Total commands: {len(commands)}")
|
62
|
-
print(f" Command names: {list(commands.keys())}")
|
63
|
-
|
64
|
-
# Create generator
|
65
|
-
generator = CustomOpenAPIGenerator()
|
66
|
-
|
67
|
-
# Generate schema
|
68
|
-
schema = generator.generate(
|
69
|
-
title="Extended MCP Proxy Server",
|
70
|
-
description="Advanced MCP Proxy Adapter server with custom commands and hooks",
|
71
|
-
version="2.1.0"
|
72
|
-
)
|
73
|
-
|
74
|
-
# Save to file
|
75
|
-
with open("generated_openapi.json", "w", encoding="utf-8") as f:
|
76
|
-
json.dump(schema, f, indent=2, ensure_ascii=False)
|
77
|
-
|
78
|
-
print("✅ OpenAPI schema generated successfully!")
|
79
|
-
print(f"📄 Saved to: generated_openapi.json")
|
80
|
-
print(f"📊 Schema size: {len(json.dumps(schema))} characters")
|
81
|
-
|
82
|
-
# Show basic info
|
83
|
-
print(f"\n📋 Schema info:")
|
84
|
-
print(f" Title: {schema['info']['title']}")
|
85
|
-
print(f" Version: {schema['info']['version']}")
|
86
|
-
|
87
|
-
# Get commands info
|
88
|
-
commands = registry.get_all_commands()
|
89
|
-
print(f" Commands: {len(commands)}")
|
90
|
-
print(f" Command names: {list(commands.keys())}")
|
91
|
-
|
92
|
-
# Check CommandRequest enum
|
93
|
-
command_enum = schema['components']['schemas'].get('CommandRequest', {}).get('properties', {}).get('command', {}).get('enum', [])
|
94
|
-
print(f" Commands in schema: {len(command_enum)}")
|
95
|
-
print(f" Schema commands: {command_enum}")
|
96
|
-
|
97
|
-
except Exception as e:
|
98
|
-
print(f"❌ Error generating schema: {e}")
|
99
|
-
import traceback
|
100
|
-
traceback.print_exc()
|
101
|
-
|
102
|
-
if __name__ == "__main__":
|
103
|
-
asyncio.run(main())
|
@@ -1,230 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Custom Hooks Example
|
3
|
-
|
4
|
-
This module demonstrates how to use hooks in the MCP Proxy Adapter framework.
|
5
|
-
Hooks allow you to intercept command execution before and after processing.
|
6
|
-
"""
|
7
|
-
|
8
|
-
import time
|
9
|
-
import logging
|
10
|
-
from typing import Dict, Any
|
11
|
-
from datetime import datetime
|
12
|
-
|
13
|
-
from mcp_proxy_adapter.commands.hooks import HookContext, HookType
|
14
|
-
|
15
|
-
|
16
|
-
# Setup logging for hooks
|
17
|
-
logger = logging.getLogger("mcp_proxy_adapter.examples.hooks")
|
18
|
-
|
19
|
-
|
20
|
-
def echo_before_hook(context: HookContext) -> None:
|
21
|
-
"""
|
22
|
-
Before hook for echo command.
|
23
|
-
|
24
|
-
Args:
|
25
|
-
context: Hook context with command information
|
26
|
-
"""
|
27
|
-
logger.info(f"🔔 Echo command will be executed with params: {context.params}")
|
28
|
-
|
29
|
-
# Add timestamp to params
|
30
|
-
context.params["hook_timestamp"] = datetime.now().isoformat()
|
31
|
-
|
32
|
-
# Log the message that will be echoed
|
33
|
-
message = context.params.get("message", context.params.get("text", "Hello, World!"))
|
34
|
-
logger.info(f"📢 Will echo message: '{message}'")
|
35
|
-
|
36
|
-
|
37
|
-
def echo_after_hook(context: HookContext) -> None:
|
38
|
-
"""
|
39
|
-
After hook for echo command.
|
40
|
-
|
41
|
-
Args:
|
42
|
-
context: Hook context with command information
|
43
|
-
"""
|
44
|
-
logger.info(f"✅ Echo command completed successfully")
|
45
|
-
|
46
|
-
# Log the result
|
47
|
-
if context.result and hasattr(context.result, 'data'):
|
48
|
-
echoed_message = context.result.data.get("message", "Unknown")
|
49
|
-
timestamp = context.result.data.get("timestamp", "Unknown")
|
50
|
-
logger.info(f"📤 Echoed: '{echoed_message}' at {timestamp}")
|
51
|
-
|
52
|
-
|
53
|
-
def help_before_hook(context: HookContext) -> None:
|
54
|
-
"""
|
55
|
-
Before hook for help command.
|
56
|
-
|
57
|
-
Args:
|
58
|
-
context: Hook context with command information
|
59
|
-
"""
|
60
|
-
logger.info(f"🔔 Help command will be executed")
|
61
|
-
|
62
|
-
# Add request tracking
|
63
|
-
context.params["request_id"] = f"help_{int(time.time())}"
|
64
|
-
context.params["hook_processed"] = True
|
65
|
-
|
66
|
-
cmdname = context.params.get("cmdname")
|
67
|
-
if cmdname:
|
68
|
-
logger.info(f"📖 Will get help for command: {cmdname}")
|
69
|
-
else:
|
70
|
-
logger.info(f"📖 Will get help for all commands")
|
71
|
-
|
72
|
-
|
73
|
-
def help_after_hook(context: HookContext) -> None:
|
74
|
-
"""
|
75
|
-
After hook for help command.
|
76
|
-
|
77
|
-
Args:
|
78
|
-
context: Hook context with command information
|
79
|
-
"""
|
80
|
-
logger.info(f"✅ Help command completed successfully")
|
81
|
-
|
82
|
-
# Log the result summary
|
83
|
-
if context.result and hasattr(context.result, 'to_dict'):
|
84
|
-
result_dict = context.result.to_dict()
|
85
|
-
total_commands = result_dict.get("total", 0)
|
86
|
-
logger.info(f"📚 Help returned {total_commands} commands")
|
87
|
-
|
88
|
-
|
89
|
-
def health_before_hook(context: HookContext) -> None:
|
90
|
-
"""
|
91
|
-
Before hook for health command.
|
92
|
-
|
93
|
-
Args:
|
94
|
-
context: Hook context with command information
|
95
|
-
"""
|
96
|
-
logger.info(f"🔔 Health command will be executed")
|
97
|
-
|
98
|
-
# Add health check metadata
|
99
|
-
context.params["health_check_id"] = f"health_{int(time.time())}"
|
100
|
-
context.params["hook_enhanced"] = True
|
101
|
-
|
102
|
-
logger.info(f"🏥 Starting enhanced health check")
|
103
|
-
|
104
|
-
|
105
|
-
def health_after_hook(context: HookContext) -> None:
|
106
|
-
"""
|
107
|
-
After hook for health command.
|
108
|
-
|
109
|
-
Args:
|
110
|
-
context: Hook context with command information
|
111
|
-
"""
|
112
|
-
logger.info(f"✅ Health command completed successfully")
|
113
|
-
|
114
|
-
# Log health status
|
115
|
-
if context.result and hasattr(context.result, 'data'):
|
116
|
-
status = context.result.data.get("status", "unknown")
|
117
|
-
uptime = context.result.data.get("uptime", 0)
|
118
|
-
logger.info(f"🏥 Health status: {status}, Uptime: {uptime:.2f}s")
|
119
|
-
|
120
|
-
|
121
|
-
def global_before_hook(context: HookContext) -> None:
|
122
|
-
"""
|
123
|
-
Global before hook for all commands.
|
124
|
-
|
125
|
-
Args:
|
126
|
-
context: Hook context with command information
|
127
|
-
"""
|
128
|
-
logger.info(f"🌐 Global before hook: {context.command_name}")
|
129
|
-
|
130
|
-
# Add global tracking
|
131
|
-
context.params["global_hook_processed"] = True
|
132
|
-
context.params["execution_start_time"] = time.time()
|
133
|
-
|
134
|
-
logger.info(f"🚀 Starting execution of '{context.command_name}'")
|
135
|
-
|
136
|
-
|
137
|
-
def global_after_hook(context: HookContext) -> None:
|
138
|
-
"""
|
139
|
-
Global after hook for all commands.
|
140
|
-
|
141
|
-
Args:
|
142
|
-
context: Hook context with command information
|
143
|
-
"""
|
144
|
-
start_time = context.params.get("execution_start_time", time.time())
|
145
|
-
execution_time = time.time() - start_time
|
146
|
-
|
147
|
-
logger.info(f"🌐 Global after hook: {context.command_name}")
|
148
|
-
logger.info(f"⏱️ Execution time: {execution_time:.3f}s")
|
149
|
-
|
150
|
-
# Log success/failure
|
151
|
-
if context.result:
|
152
|
-
logger.info(f"✅ Command '{context.command_name}' completed successfully")
|
153
|
-
else:
|
154
|
-
logger.warning(f"⚠️ Command '{context.command_name}' completed with issues")
|
155
|
-
|
156
|
-
|
157
|
-
def performance_hook(context: HookContext) -> None:
|
158
|
-
"""
|
159
|
-
Performance monitoring hook.
|
160
|
-
|
161
|
-
Args:
|
162
|
-
context: Hook context with command information
|
163
|
-
"""
|
164
|
-
if context.hook_type == HookType.BEFORE_EXECUTION:
|
165
|
-
# Store start time
|
166
|
-
context.params["_performance_start"] = time.time()
|
167
|
-
logger.debug(f"⏱️ Performance monitoring started for {context.command_name}")
|
168
|
-
|
169
|
-
elif context.hook_type == HookType.AFTER_EXECUTION:
|
170
|
-
# Calculate execution time
|
171
|
-
start_time = context.params.get("_performance_start", time.time())
|
172
|
-
execution_time = time.time() - start_time
|
173
|
-
|
174
|
-
logger.info(f"📊 Performance: {context.command_name} took {execution_time:.3f}s")
|
175
|
-
|
176
|
-
# Log slow commands
|
177
|
-
if execution_time > 1.0:
|
178
|
-
logger.warning(f"🐌 Slow command detected: {context.command_name} ({execution_time:.3f}s)")
|
179
|
-
|
180
|
-
|
181
|
-
def security_hook(context: HookContext) -> None:
|
182
|
-
"""
|
183
|
-
Security monitoring hook.
|
184
|
-
|
185
|
-
Args:
|
186
|
-
context: Hook context with command information
|
187
|
-
"""
|
188
|
-
if context.hook_type == HookType.BEFORE_EXECUTION:
|
189
|
-
# Check for sensitive data in params
|
190
|
-
sensitive_keys = ["password", "token", "secret", "key"]
|
191
|
-
found_sensitive = [key for key in context.params.keys() if any(s in key.lower() for s in sensitive_keys)]
|
192
|
-
|
193
|
-
if found_sensitive:
|
194
|
-
logger.warning(f"🔒 Security: Sensitive parameters detected in {context.command_name}: {found_sensitive}")
|
195
|
-
|
196
|
-
# Add security metadata
|
197
|
-
context.params["_security_checked"] = True
|
198
|
-
logger.debug(f"🔒 Security check completed for {context.command_name}")
|
199
|
-
|
200
|
-
|
201
|
-
def register_all_hooks(hooks_manager) -> None:
|
202
|
-
"""
|
203
|
-
Register all hooks with the hooks manager.
|
204
|
-
|
205
|
-
Args:
|
206
|
-
hooks_manager: The hooks manager instance
|
207
|
-
"""
|
208
|
-
logger.info("🔧 Registering custom hooks...")
|
209
|
-
|
210
|
-
# Register command-specific hooks
|
211
|
-
hooks_manager.register_before_hook("echo", echo_before_hook)
|
212
|
-
hooks_manager.register_after_hook("echo", echo_after_hook)
|
213
|
-
|
214
|
-
hooks_manager.register_before_hook("help", help_before_hook)
|
215
|
-
hooks_manager.register_after_hook("help", help_after_hook)
|
216
|
-
|
217
|
-
hooks_manager.register_before_hook("health", health_before_hook)
|
218
|
-
hooks_manager.register_after_hook("health", health_after_hook)
|
219
|
-
|
220
|
-
# Register global hooks
|
221
|
-
hooks_manager.register_global_before_hook(global_before_hook)
|
222
|
-
hooks_manager.register_global_after_hook(global_after_hook)
|
223
|
-
|
224
|
-
# Register utility hooks
|
225
|
-
hooks_manager.register_global_before_hook(performance_hook)
|
226
|
-
hooks_manager.register_global_after_hook(performance_hook)
|
227
|
-
|
228
|
-
hooks_manager.register_global_before_hook(security_hook)
|
229
|
-
|
230
|
-
logger.info("✅ All hooks registered successfully")
|
@@ -1,123 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Intercept Command Example
|
3
|
-
|
4
|
-
A command that can be completely intercepted by hooks based on conditions.
|
5
|
-
"""
|
6
|
-
|
7
|
-
from typing import Dict, Any, Optional
|
8
|
-
from mcp_proxy_adapter.commands.base import Command
|
9
|
-
from mcp_proxy_adapter.commands.result import CommandResult
|
10
|
-
|
11
|
-
|
12
|
-
class InterceptResult(CommandResult):
|
13
|
-
"""
|
14
|
-
Result of the intercept command execution.
|
15
|
-
"""
|
16
|
-
|
17
|
-
def __init__(self, message: str, executed: bool, intercept_reason: Optional[str] = None,
|
18
|
-
hook_data: Optional[Dict[str, Any]] = None):
|
19
|
-
"""
|
20
|
-
Initialize intercept command result.
|
21
|
-
|
22
|
-
Args:
|
23
|
-
message: Result message
|
24
|
-
executed: Whether the command was actually executed
|
25
|
-
intercept_reason: Reason for interception (if any)
|
26
|
-
hook_data: Data from hooks
|
27
|
-
"""
|
28
|
-
self.message = message
|
29
|
-
self.executed = executed
|
30
|
-
self.intercept_reason = intercept_reason
|
31
|
-
self.hook_data = hook_data or {}
|
32
|
-
|
33
|
-
def to_dict(self) -> Dict[str, Any]:
|
34
|
-
"""
|
35
|
-
Convert result to dictionary.
|
36
|
-
|
37
|
-
Returns:
|
38
|
-
Dict[str, Any]: Result as dictionary
|
39
|
-
"""
|
40
|
-
return {
|
41
|
-
"message": self.message,
|
42
|
-
"executed": self.executed,
|
43
|
-
"intercept_reason": self.intercept_reason,
|
44
|
-
"hook_data": self.hook_data,
|
45
|
-
"command_type": "intercept"
|
46
|
-
}
|
47
|
-
|
48
|
-
@classmethod
|
49
|
-
def get_schema(cls) -> Dict[str, Any]:
|
50
|
-
"""
|
51
|
-
Get JSON schema for the result.
|
52
|
-
|
53
|
-
Returns:
|
54
|
-
Dict[str, Any]: JSON schema
|
55
|
-
"""
|
56
|
-
return {
|
57
|
-
"type": "object",
|
58
|
-
"properties": {
|
59
|
-
"message": {"type": "string"},
|
60
|
-
"executed": {"type": "boolean"},
|
61
|
-
"intercept_reason": {"type": "string"},
|
62
|
-
"hook_data": {"type": "object"},
|
63
|
-
"command_type": {"type": "string"}
|
64
|
-
}
|
65
|
-
}
|
66
|
-
|
67
|
-
|
68
|
-
class InterceptCommand(Command):
|
69
|
-
"""
|
70
|
-
Intercept command for demonstrating hook interception.
|
71
|
-
"""
|
72
|
-
|
73
|
-
name = "intercept"
|
74
|
-
result_class = InterceptResult
|
75
|
-
|
76
|
-
async def execute(self, action: Optional[str] = None,
|
77
|
-
bypass_flag: Optional[int] = None, **kwargs) -> InterceptResult:
|
78
|
-
"""
|
79
|
-
Execute intercept command.
|
80
|
-
|
81
|
-
Args:
|
82
|
-
action: Action to perform
|
83
|
-
bypass_flag: Flag to determine if command should be bypassed (0 = bypass, 1 = execute)
|
84
|
-
**kwargs: Additional parameters
|
85
|
-
|
86
|
-
Returns:
|
87
|
-
InterceptResult: Intercept command result
|
88
|
-
"""
|
89
|
-
action = action or "default"
|
90
|
-
bypass_flag = bypass_flag if bypass_flag is not None else 1
|
91
|
-
|
92
|
-
# This should only execute if bypass_flag == 1
|
93
|
-
# If bypass_flag == 0, hooks should intercept and return result
|
94
|
-
|
95
|
-
return InterceptResult(
|
96
|
-
message=f"Command executed with action: {action}",
|
97
|
-
executed=True,
|
98
|
-
intercept_reason=None,
|
99
|
-
hook_data=kwargs
|
100
|
-
)
|
101
|
-
|
102
|
-
@classmethod
|
103
|
-
def get_schema(cls) -> Dict[str, Any]:
|
104
|
-
"""
|
105
|
-
Get JSON schema for command parameters.
|
106
|
-
|
107
|
-
Returns:
|
108
|
-
Dict[str, Any]: JSON schema
|
109
|
-
"""
|
110
|
-
return {
|
111
|
-
"type": "object",
|
112
|
-
"properties": {
|
113
|
-
"action": {
|
114
|
-
"type": "string",
|
115
|
-
"description": "Action to perform"
|
116
|
-
},
|
117
|
-
"bypass_flag": {
|
118
|
-
"type": "integer",
|
119
|
-
"enum": [0, 1],
|
120
|
-
"description": "Flag to determine execution (0 = bypass, 1 = execute)"
|
121
|
-
}
|
122
|
-
}
|
123
|
-
}
|
@@ -1,129 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Test command for loadable commands testing.
|
3
|
-
|
4
|
-
This command demonstrates the loadable commands functionality.
|
5
|
-
"""
|
6
|
-
|
7
|
-
from typing import Any, Dict
|
8
|
-
|
9
|
-
from mcp_proxy_adapter.commands.base import Command
|
10
|
-
from mcp_proxy_adapter.commands.result import SuccessResult
|
11
|
-
|
12
|
-
|
13
|
-
class TestCommandResult:
|
14
|
-
"""
|
15
|
-
Result of test command execution.
|
16
|
-
"""
|
17
|
-
|
18
|
-
def __init__(self, message: str, test_data: Dict[str, Any]):
|
19
|
-
"""
|
20
|
-
Initialize test command result.
|
21
|
-
|
22
|
-
Args:
|
23
|
-
message: Result message
|
24
|
-
test_data: Test data
|
25
|
-
"""
|
26
|
-
self.message = message
|
27
|
-
self.test_data = test_data
|
28
|
-
|
29
|
-
def to_dict(self) -> Dict[str, Any]:
|
30
|
-
"""
|
31
|
-
Convert result to dictionary.
|
32
|
-
|
33
|
-
Returns:
|
34
|
-
Dictionary representation of the result.
|
35
|
-
"""
|
36
|
-
return {
|
37
|
-
"success": True,
|
38
|
-
"message": self.message,
|
39
|
-
"test_data": self.test_data
|
40
|
-
}
|
41
|
-
|
42
|
-
@classmethod
|
43
|
-
def get_schema(cls) -> Dict[str, Any]:
|
44
|
-
"""
|
45
|
-
Get JSON schema for the result.
|
46
|
-
|
47
|
-
Returns:
|
48
|
-
JSON schema dictionary.
|
49
|
-
"""
|
50
|
-
return {
|
51
|
-
"type": "object",
|
52
|
-
"properties": {
|
53
|
-
"success": {
|
54
|
-
"type": "boolean",
|
55
|
-
"description": "Whether command was successful"
|
56
|
-
},
|
57
|
-
"message": {
|
58
|
-
"type": "string",
|
59
|
-
"description": "Result message"
|
60
|
-
},
|
61
|
-
"test_data": {
|
62
|
-
"type": "object",
|
63
|
-
"description": "Test data"
|
64
|
-
}
|
65
|
-
},
|
66
|
-
"required": ["success", "message", "test_data"]
|
67
|
-
}
|
68
|
-
|
69
|
-
|
70
|
-
class TestCommand(Command):
|
71
|
-
"""
|
72
|
-
Test command for loadable commands testing.
|
73
|
-
"""
|
74
|
-
|
75
|
-
name = "test"
|
76
|
-
result_class = TestCommandResult
|
77
|
-
|
78
|
-
async def execute(self, **kwargs) -> TestCommandResult:
|
79
|
-
"""
|
80
|
-
Execute test command.
|
81
|
-
|
82
|
-
Args:
|
83
|
-
**kwargs: Command parameters
|
84
|
-
|
85
|
-
Returns:
|
86
|
-
TestCommandResult with test information
|
87
|
-
"""
|
88
|
-
# Get parameters
|
89
|
-
test_param = kwargs.get("test_param", "default_value")
|
90
|
-
echo_text = kwargs.get("echo_text", "Hello from loadable command!")
|
91
|
-
|
92
|
-
# Create test data
|
93
|
-
test_data = {
|
94
|
-
"command_type": "loadable",
|
95
|
-
"test_param": test_param,
|
96
|
-
"echo_text": echo_text,
|
97
|
-
"timestamp": "2025-08-12T09:45:00Z",
|
98
|
-
"status": "working"
|
99
|
-
}
|
100
|
-
|
101
|
-
return TestCommandResult(
|
102
|
-
message=f"Test command executed successfully with param: {test_param}",
|
103
|
-
test_data=test_data
|
104
|
-
)
|
105
|
-
|
106
|
-
@classmethod
|
107
|
-
def get_schema(cls) -> Dict[str, Any]:
|
108
|
-
"""
|
109
|
-
Get JSON schema for command parameters.
|
110
|
-
|
111
|
-
Returns:
|
112
|
-
JSON schema dictionary.
|
113
|
-
"""
|
114
|
-
return {
|
115
|
-
"type": "object",
|
116
|
-
"properties": {
|
117
|
-
"test_param": {
|
118
|
-
"type": "string",
|
119
|
-
"description": "Test parameter",
|
120
|
-
"default": "default_value"
|
121
|
-
},
|
122
|
-
"echo_text": {
|
123
|
-
"type": "string",
|
124
|
-
"description": "Text to echo",
|
125
|
-
"default": "Hello from loadable command!"
|
126
|
-
}
|
127
|
-
},
|
128
|
-
"additionalProperties": False
|
129
|
-
}
|
@@ -1,103 +0,0 @@
|
|
1
|
-
"""
|
2
|
-
Manually registered Echo Command
|
3
|
-
|
4
|
-
This command must be manually registered in the server code.
|
5
|
-
"""
|
6
|
-
|
7
|
-
from typing import Dict, Any, Optional
|
8
|
-
from mcp_proxy_adapter.commands.base import Command
|
9
|
-
from mcp_proxy_adapter.commands.result import CommandResult
|
10
|
-
|
11
|
-
|
12
|
-
class ManualEchoResult(CommandResult):
|
13
|
-
"""
|
14
|
-
Result of the manually registered echo command execution.
|
15
|
-
"""
|
16
|
-
|
17
|
-
def __init__(self, message: str, manually_registered: bool = True):
|
18
|
-
"""
|
19
|
-
Initialize manual echo command result.
|
20
|
-
|
21
|
-
Args:
|
22
|
-
message: Echoed message
|
23
|
-
manually_registered: Flag indicating this was manually registered
|
24
|
-
"""
|
25
|
-
self.message = message
|
26
|
-
self.manually_registered = manually_registered
|
27
|
-
|
28
|
-
def to_dict(self) -> Dict[str, Any]:
|
29
|
-
"""
|
30
|
-
Convert result to dictionary.
|
31
|
-
|
32
|
-
Returns:
|
33
|
-
Dict[str, Any]: Result as dictionary
|
34
|
-
"""
|
35
|
-
return {
|
36
|
-
"message": self.message,
|
37
|
-
"manually_registered": self.manually_registered,
|
38
|
-
"command_type": "manual_echo"
|
39
|
-
}
|
40
|
-
|
41
|
-
@classmethod
|
42
|
-
def get_schema(cls) -> Dict[str, Any]:
|
43
|
-
"""
|
44
|
-
Get JSON schema for the result.
|
45
|
-
|
46
|
-
Returns:
|
47
|
-
Dict[str, Any]: JSON schema
|
48
|
-
"""
|
49
|
-
return {
|
50
|
-
"type": "object",
|
51
|
-
"properties": {
|
52
|
-
"message": {"type": "string"},
|
53
|
-
"manually_registered": {"type": "boolean"},
|
54
|
-
"command_type": {"type": "string"}
|
55
|
-
}
|
56
|
-
}
|
57
|
-
|
58
|
-
|
59
|
-
class ManualEchoCommand(Command):
|
60
|
-
"""
|
61
|
-
Manually registered echo command.
|
62
|
-
"""
|
63
|
-
|
64
|
-
name = "manual_echo"
|
65
|
-
result_class = ManualEchoResult
|
66
|
-
|
67
|
-
async def execute(self, message: Optional[str] = None, **kwargs) -> ManualEchoResult:
|
68
|
-
"""
|
69
|
-
Execute manually registered echo command.
|
70
|
-
|
71
|
-
Args:
|
72
|
-
message: Message to echo
|
73
|
-
**kwargs: Additional parameters
|
74
|
-
|
75
|
-
Returns:
|
76
|
-
ManualEchoResult: Manual echo command result
|
77
|
-
"""
|
78
|
-
if message is None:
|
79
|
-
message = "Hello from manually registered command!"
|
80
|
-
|
81
|
-
return ManualEchoResult(
|
82
|
-
message=message,
|
83
|
-
manually_registered=True
|
84
|
-
)
|
85
|
-
|
86
|
-
@classmethod
|
87
|
-
def get_schema(cls) -> Dict[str, Any]:
|
88
|
-
"""
|
89
|
-
Get JSON schema for command parameters.
|
90
|
-
|
91
|
-
Returns:
|
92
|
-
Dict[str, Any]: JSON schema
|
93
|
-
"""
|
94
|
-
return {
|
95
|
-
"type": "object",
|
96
|
-
"properties": {
|
97
|
-
"message": {
|
98
|
-
"type": "string",
|
99
|
-
"description": "Message to echo",
|
100
|
-
"default": "Hello from manually registered command!"
|
101
|
-
}
|
102
|
-
}
|
103
|
-
}
|