mcp-proxy-adapter 6.1.1__py3-none-any.whl → 6.2.0__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 (145) hide show
  1. mcp_proxy_adapter/__main__.py +27 -7
  2. mcp_proxy_adapter/api/app.py +18 -7
  3. mcp_proxy_adapter/commands/ssl_setup_command.py +234 -351
  4. mcp_proxy_adapter/core/app_factory.py +87 -3
  5. mcp_proxy_adapter/core/app_runner.py +272 -0
  6. mcp_proxy_adapter/core/certificate_utils.py +291 -73
  7. mcp_proxy_adapter/core/client.py +574 -0
  8. mcp_proxy_adapter/core/client_manager.py +284 -0
  9. mcp_proxy_adapter/core/server_adapter.py +17 -80
  10. mcp_proxy_adapter/core/server_engine.py +5 -99
  11. mcp_proxy_adapter/core/ssl_utils.py +13 -12
  12. mcp_proxy_adapter/core/transport_manager.py +5 -5
  13. mcp_proxy_adapter/examples/__init__.py +16 -0
  14. mcp_proxy_adapter/examples/basic_framework/__init__.py +7 -0
  15. mcp_proxy_adapter/examples/basic_framework/commands/__init__.py +4 -0
  16. mcp_proxy_adapter/examples/basic_framework/hooks/__init__.py +4 -0
  17. mcp_proxy_adapter/examples/basic_framework/main.py +21 -40
  18. mcp_proxy_adapter/examples/commands/__init__.py +5 -1
  19. mcp_proxy_adapter/examples/create_certificates_simple.py +260 -75
  20. mcp_proxy_adapter/examples/debug_request_state.py +4 -36
  21. mcp_proxy_adapter/examples/debug_role_chain.py +2 -49
  22. mcp_proxy_adapter/examples/demo_client.py +0 -66
  23. mcp_proxy_adapter/examples/full_application/__init__.py +11 -0
  24. mcp_proxy_adapter/examples/full_application/commands/__init__.py +7 -0
  25. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +0 -19
  26. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +0 -16
  27. mcp_proxy_adapter/examples/full_application/hooks/__init__.py +7 -0
  28. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +0 -22
  29. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +0 -24
  30. mcp_proxy_adapter/examples/full_application/main.py +65 -44
  31. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +154 -0
  32. mcp_proxy_adapter/examples/generate_all_certificates.py +0 -67
  33. mcp_proxy_adapter/examples/generate_certificates.py +0 -15
  34. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +369 -0
  35. mcp_proxy_adapter/examples/generate_test_configs.py +204 -0
  36. mcp_proxy_adapter/examples/proxy_registration_example.py +3 -70
  37. mcp_proxy_adapter/examples/run_example.py +1 -23
  38. mcp_proxy_adapter/examples/run_security_tests.py +2 -60
  39. mcp_proxy_adapter/examples/run_security_tests_fixed.py +0 -53
  40. mcp_proxy_adapter/examples/security_test_client.py +18 -123
  41. mcp_proxy_adapter/examples/setup_test_environment.py +179 -0
  42. mcp_proxy_adapter/examples/test_config.py +148 -0
  43. mcp_proxy_adapter/examples/test_config_generator.py +1 -25
  44. mcp_proxy_adapter/examples/test_examples.py +4 -67
  45. mcp_proxy_adapter/examples/universal_client.py +154 -162
  46. mcp_proxy_adapter/main.py +51 -161
  47. mcp_proxy_adapter/version.py +1 -1
  48. mcp_proxy_adapter-6.2.0.dist-info/METADATA +687 -0
  49. mcp_proxy_adapter-6.2.0.dist-info/RECORD +122 -0
  50. mcp_proxy_adapter/docs/EN/TROUBLESHOOTING.md +0 -285
  51. mcp_proxy_adapter/docs/RU/TROUBLESHOOTING.md +0 -285
  52. mcp_proxy_adapter/examples/README.md +0 -257
  53. mcp_proxy_adapter/examples/README_EN.md +0 -258
  54. mcp_proxy_adapter/examples/SECURITY_TESTING.md +0 -455
  55. mcp_proxy_adapter/examples/basic_framework/configs/http_auth.json +0 -37
  56. mcp_proxy_adapter/examples/basic_framework/configs/http_simple.json +0 -23
  57. mcp_proxy_adapter/examples/basic_framework/configs/https_auth.json +0 -43
  58. mcp_proxy_adapter/examples/basic_framework/configs/https_no_protocol_middleware.json +0 -36
  59. mcp_proxy_adapter/examples/basic_framework/configs/https_simple.json +0 -29
  60. mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_protocol_middleware.json +0 -34
  61. mcp_proxy_adapter/examples/basic_framework/configs/mtls_no_roles.json +0 -39
  62. mcp_proxy_adapter/examples/basic_framework/configs/mtls_simple.json +0 -35
  63. mcp_proxy_adapter/examples/basic_framework/configs/mtls_with_roles.json +0 -45
  64. mcp_proxy_adapter/examples/basic_framework/roles.json +0 -21
  65. mcp_proxy_adapter/examples/cert_config.json +0 -9
  66. mcp_proxy_adapter/examples/certs/admin.crt +0 -32
  67. mcp_proxy_adapter/examples/certs/admin.key +0 -52
  68. mcp_proxy_adapter/examples/certs/admin_cert.pem +0 -21
  69. mcp_proxy_adapter/examples/certs/admin_key.pem +0 -28
  70. mcp_proxy_adapter/examples/certs/ca_cert.pem +0 -23
  71. mcp_proxy_adapter/examples/certs/ca_cert.srl +0 -1
  72. mcp_proxy_adapter/examples/certs/ca_key.pem +0 -28
  73. mcp_proxy_adapter/examples/certs/cert_config.json +0 -9
  74. mcp_proxy_adapter/examples/certs/client.crt +0 -32
  75. mcp_proxy_adapter/examples/certs/client.key +0 -52
  76. mcp_proxy_adapter/examples/certs/client_admin.crt +0 -32
  77. mcp_proxy_adapter/examples/certs/client_admin.key +0 -52
  78. mcp_proxy_adapter/examples/certs/client_user.crt +0 -32
  79. mcp_proxy_adapter/examples/certs/client_user.key +0 -52
  80. mcp_proxy_adapter/examples/certs/guest_cert.pem +0 -21
  81. mcp_proxy_adapter/examples/certs/guest_key.pem +0 -28
  82. mcp_proxy_adapter/examples/certs/mcp_proxy_adapter_ca_ca.crt +0 -23
  83. mcp_proxy_adapter/examples/certs/proxy_cert.pem +0 -21
  84. mcp_proxy_adapter/examples/certs/proxy_key.pem +0 -28
  85. mcp_proxy_adapter/examples/certs/readonly.crt +0 -32
  86. mcp_proxy_adapter/examples/certs/readonly.key +0 -52
  87. mcp_proxy_adapter/examples/certs/readonly_cert.pem +0 -21
  88. mcp_proxy_adapter/examples/certs/readonly_key.pem +0 -28
  89. mcp_proxy_adapter/examples/certs/server.crt +0 -32
  90. mcp_proxy_adapter/examples/certs/server.key +0 -52
  91. mcp_proxy_adapter/examples/certs/server_cert.pem +0 -32
  92. mcp_proxy_adapter/examples/certs/server_key.pem +0 -52
  93. mcp_proxy_adapter/examples/certs/test_ca_ca.crt +0 -20
  94. mcp_proxy_adapter/examples/certs/user.crt +0 -32
  95. mcp_proxy_adapter/examples/certs/user.key +0 -52
  96. mcp_proxy_adapter/examples/certs/user_cert.pem +0 -21
  97. mcp_proxy_adapter/examples/certs/user_key.pem +0 -28
  98. mcp_proxy_adapter/examples/client_configs/api_key_client.json +0 -13
  99. mcp_proxy_adapter/examples/client_configs/basic_auth_client.json +0 -13
  100. mcp_proxy_adapter/examples/client_configs/certificate_client.json +0 -22
  101. mcp_proxy_adapter/examples/client_configs/jwt_client.json +0 -15
  102. mcp_proxy_adapter/examples/client_configs/no_auth_client.json +0 -9
  103. mcp_proxy_adapter/examples/full_application/configs/http_auth.json +0 -37
  104. mcp_proxy_adapter/examples/full_application/configs/http_simple.json +0 -23
  105. mcp_proxy_adapter/examples/full_application/configs/https_auth.json +0 -39
  106. mcp_proxy_adapter/examples/full_application/configs/https_simple.json +0 -25
  107. mcp_proxy_adapter/examples/full_application/configs/mtls_no_roles.json +0 -39
  108. mcp_proxy_adapter/examples/full_application/configs/mtls_with_roles.json +0 -45
  109. mcp_proxy_adapter/examples/full_application/roles.json +0 -21
  110. mcp_proxy_adapter/examples/keys/ca_key.pem +0 -28
  111. mcp_proxy_adapter/examples/keys/mcp_proxy_adapter_ca_ca.key +0 -28
  112. mcp_proxy_adapter/examples/keys/test_ca_ca.key +0 -28
  113. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log +0 -220
  114. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.1 +0 -1
  115. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.2 +0 -1
  116. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.3 +0 -1
  117. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.4 +0 -1
  118. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter.log.5 +0 -1
  119. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log +0 -220
  120. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.1 +0 -1
  121. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.2 +0 -1
  122. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.3 +0 -1
  123. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.4 +0 -1
  124. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_access.log.5 +0 -1
  125. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log +0 -2
  126. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.1 +0 -1
  127. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.2 +0 -1
  128. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.3 +0 -1
  129. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.4 +0 -1
  130. mcp_proxy_adapter/examples/logs/mcp_proxy_adapter_error.log.5 +0 -1
  131. mcp_proxy_adapter/examples/roles.json +0 -38
  132. mcp_proxy_adapter/examples/server_configs/config_basic_http.json +0 -204
  133. mcp_proxy_adapter/examples/server_configs/config_http_token.json +0 -238
  134. mcp_proxy_adapter/examples/server_configs/config_https.json +0 -215
  135. mcp_proxy_adapter/examples/server_configs/config_https_token.json +0 -231
  136. mcp_proxy_adapter/examples/server_configs/config_mtls.json +0 -215
  137. mcp_proxy_adapter/examples/server_configs/config_proxy_registration.json +0 -250
  138. mcp_proxy_adapter/examples/server_configs/config_simple.json +0 -46
  139. mcp_proxy_adapter/examples/server_configs/roles.json +0 -38
  140. mcp_proxy_adapter-6.1.1.dist-info/METADATA +0 -205
  141. mcp_proxy_adapter-6.1.1.dist-info/RECORD +0 -197
  142. {mcp_proxy_adapter-6.1.1.dist-info → mcp_proxy_adapter-6.2.0.dist-info}/WHEEL +0 -0
  143. {mcp_proxy_adapter-6.1.1.dist-info → mcp_proxy_adapter-6.2.0.dist-info}/entry_points.txt +0 -0
  144. {mcp_proxy_adapter-6.1.1.dist-info → mcp_proxy_adapter-6.2.0.dist-info}/licenses/LICENSE +0 -0
  145. {mcp_proxy_adapter-6.1.1.dist-info → mcp_proxy_adapter-6.2.0.dist-info}/top_level.txt +0 -0
@@ -1,49 +1,35 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
3
  Debug Request State - Проверка request.state
4
-
5
4
  Этот скрипт проверяет, как middleware устанавливает информацию о пользователе в request.state.
6
-
7
5
  Author: Vasiliy Zdanovskiy
8
6
  email: vasilyvz@gmail.com
9
7
  """
10
-
11
8
  import asyncio
12
9
  import json
13
10
  import sys
14
11
  from pathlib import Path
15
-
16
12
  # Add project root to path
17
13
  project_root = Path(__file__).parent.parent.parent
18
14
  sys.path.insert(0, str(project_root))
19
-
20
15
  from fastapi import FastAPI, Request
21
16
  from fastapi.testclient import TestClient
22
17
  from mcp_proxy_adapter.api.app import create_app
23
-
24
-
25
18
  async def debug_request_state():
26
19
  """Debug request state handling."""
27
-
28
20
  print("🔍 ОТЛАДКА REQUEST.STATE")
29
21
  print("=" * 50)
30
-
31
22
  # Create test app with proper configuration
32
23
  config_path = project_root / "mcp_proxy_adapter" / "examples" / "server_configs" / "config_http_token.json"
33
-
34
24
  with open(config_path) as f:
35
25
  config = json.load(f)
36
-
37
26
  # Override global config for testing
38
27
  import mcp_proxy_adapter.config
39
28
  mcp_proxy_adapter.config.config = config
40
-
41
29
  app = create_app(config)
42
30
  client = TestClient(app)
43
-
44
31
  print("📋 1. ТЕСТИРОВАНИЕ БЕЗ АУТЕНТИФИКАЦИИ")
45
32
  print("-" * 30)
46
-
47
33
  # Test without authentication
48
34
  response = client.post("/cmd", json={
49
35
  "jsonrpc": "2.0",
@@ -51,15 +37,12 @@ async def debug_request_state():
51
37
  "params": {"message": "test"},
52
38
  "id": 1
53
39
  })
54
-
55
40
  print(f"Status: {response.status_code}")
56
41
  print(f"Response: {response.json()}")
57
-
58
42
  print("\n📋 2. ТЕСТИРОВАНИЕ С ADMIN ТОКЕНОМ")
59
43
  print("-" * 30)
60
-
61
44
  # Test with admin token
62
- response = client.post("/cmd",
45
+ response = client.post("/cmd",
63
46
  json={
64
47
  "jsonrpc": "2.0",
65
48
  "method": "echo",
@@ -68,15 +51,12 @@ async def debug_request_state():
68
51
  },
69
52
  headers={"X-API-Key": "test-token-123"}
70
53
  )
71
-
72
54
  print(f"Status: {response.status_code}")
73
55
  print(f"Response: {response.json()}")
74
-
75
56
  print("\n📋 3. ТЕСТИРОВАНИЕ С USER ТОКЕНОМ")
76
57
  print("-" * 30)
77
-
78
58
  # Test with user token
79
- response = client.post("/cmd",
59
+ response = client.post("/cmd",
80
60
  json={
81
61
  "jsonrpc": "2.0",
82
62
  "method": "echo",
@@ -85,15 +65,12 @@ async def debug_request_state():
85
65
  },
86
66
  headers={"X-API-Key": "user-token-456"}
87
67
  )
88
-
89
68
  print(f"Status: {response.status_code}")
90
69
  print(f"Response: {response.json()}")
91
-
92
70
  print("\n📋 4. ТЕСТИРОВАНИЕ С READONLY ТОКЕНОМ")
93
71
  print("-" * 30)
94
-
95
72
  # Test with readonly token
96
- response = client.post("/cmd",
73
+ response = client.post("/cmd",
97
74
  json={
98
75
  "jsonrpc": "2.0",
99
76
  "method": "echo",
@@ -102,15 +79,12 @@ async def debug_request_state():
102
79
  },
103
80
  headers={"X-API-Key": "readonly-token-123"}
104
81
  )
105
-
106
82
  print(f"Status: {response.status_code}")
107
83
  print(f"Response: {response.json()}")
108
-
109
84
  print("\n📋 5. ТЕСТИРОВАНИЕ ROLE_TEST КОМАНДЫ")
110
85
  print("-" * 30)
111
-
112
86
  # Test role_test command with readonly token
113
- response = client.post("/cmd",
87
+ response = client.post("/cmd",
114
88
  json={
115
89
  "jsonrpc": "2.0",
116
90
  "method": "role_test",
@@ -119,26 +93,20 @@ async def debug_request_state():
119
93
  },
120
94
  headers={"X-API-Key": "readonly-token-123"}
121
95
  )
122
-
123
96
  print(f"Status: {response.status_code}")
124
97
  print(f"Response: {response.json()}")
125
-
126
98
  print("\n📋 6. АНАЛИЗ ПРОБЛЕМЫ")
127
99
  print("-" * 30)
128
-
129
100
  print("🔍 ПРОБЛЕМА: Readonly роль получает доступ к командам")
130
101
  print("\n📋 ВОЗМОЖНЫЕ ПРИЧИНЫ:")
131
102
  print("1. Framework middleware не устанавливает user info в request.state")
132
103
  print("2. Нет проверки прав на уровне middleware")
133
104
  print("3. Команды не проверяют права доступа")
134
105
  print("4. Интеграция между middleware и командами не работает")
135
-
136
106
  print("\n📋 РЕКОМЕНДАЦИИ:")
137
107
  print("1. Добавить CommandPermissionMiddleware")
138
108
  print("2. Убедиться, что framework middleware устанавливает user info")
139
109
  print("3. Добавить проверку прав в команды")
140
110
  print("4. Проверить интеграцию middleware")
141
-
142
-
143
111
  if __name__ == "__main__":
144
112
  asyncio.run(debug_request_state())
@@ -1,55 +1,40 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
3
  Debug Role Chain - Анализ цепочки блокировки ролей
4
-
5
4
  Этот скрипт анализирует всю цепочку от аутентификации до блокировки доступа.
6
-
7
5
  Author: Vasiliy Zdanovskiy
8
6
  email: vasilyvz@gmail.com
9
7
  """
10
-
11
8
  import asyncio
12
9
  import json
13
10
  import sys
14
11
  from pathlib import Path
15
-
16
12
  # Add project root to path
17
13
  project_root = Path(__file__).parent.parent.parent
18
14
  sys.path.insert(0, str(project_root))
19
-
20
15
  from mcp_security_framework import SecurityManager, AuthManager, PermissionManager
21
16
  from mcp_security_framework.schemas.config import SecurityConfig, AuthConfig, PermissionConfig
22
-
23
-
24
17
  async def debug_role_chain():
25
18
  """Debug the complete role chain from authentication to blocking."""
26
-
27
19
  print("🔍 АНАЛИЗ ЦЕПОЧКИ БЛОКИРОВКИ РОЛЕЙ")
28
20
  print("=" * 60)
29
-
30
21
  # Load configuration
31
22
  config_path = project_root / "mcp_proxy_adapter" / "examples" / "server_configs" / "config_http_token.json"
32
-
33
23
  with open(config_path) as f:
34
24
  config = json.load(f)
35
-
36
25
  security_config = config.get("security", {})
37
-
38
26
  print("📋 1. КОНФИГУРАЦИЯ API КЛЮЧЕЙ")
39
27
  print("-" * 30)
40
28
  api_keys = security_config.get("auth", {}).get("api_keys", {})
41
29
  for key, value in api_keys.items():
42
30
  print(f" {key}: {value}")
43
-
44
31
  print("\n📋 2. КОНФИГУРАЦИЯ РОЛЕЙ")
45
32
  print("-" * 30)
46
33
  roles_config = security_config.get("permissions", {}).get("roles", {})
47
34
  for role, permissions in roles_config.items():
48
35
  print(f" {role}: {permissions}")
49
-
50
36
  print("\n📋 3. СОЗДАНИЕ КОМПОНЕНТОВ БЕЗОПАСНОСТИ")
51
37
  print("-" * 30)
52
-
53
38
  # Create permission config
54
39
  perm_config = PermissionConfig(
55
40
  roles_file=str(project_root / "mcp_proxy_adapter" / "examples" / "server_configs" / "roles.json"),
@@ -62,7 +47,6 @@ async def debug_role_chain():
62
47
  strict_mode=True,
63
48
  roles=roles_config
64
49
  )
65
-
66
50
  # Create auth config
67
51
  auth_config = AuthConfig(
68
52
  enabled=security_config.get("auth", {}).get("enabled", True),
@@ -79,45 +63,34 @@ async def debug_role_chain():
79
63
  oauth2_config=security_config.get("auth", {}).get("oauth2_config"),
80
64
  public_paths=security_config.get("auth", {}).get("public_paths", [])
81
65
  )
82
-
83
66
  # Create security config
84
67
  security_config_obj = SecurityConfig(
85
68
  auth=auth_config,
86
69
  permissions=perm_config
87
70
  )
88
-
89
71
  print("✅ Конфигурации созданы")
90
-
91
72
  print("\n📋 4. ИНИЦИАЛИЗАЦИЯ МЕНЕДЖЕРОВ")
92
73
  print("-" * 30)
93
-
94
74
  # Initialize managers
95
75
  permission_manager = PermissionManager(perm_config)
96
76
  auth_manager = AuthManager(auth_config, permission_manager)
97
77
  security_manager = SecurityManager(security_config_obj)
98
-
99
78
  print("✅ Менеджеры инициализированы")
100
-
101
79
  print("\n📋 5. ТЕСТИРОВАНИЕ АУТЕНТИФИКАЦИИ")
102
80
  print("-" * 30)
103
-
104
81
  # Test authentication with different tokens
105
82
  test_tokens = {
106
83
  "admin": "test-token-123",
107
- "user": "user-token-456",
84
+ "user": "user-token-456",
108
85
  "readonly": "readonly-token-123",
109
86
  "invalid": "invalid-token-999"
110
87
  }
111
-
112
88
  auth_results = {}
113
-
114
89
  for role, token in test_tokens.items():
115
90
  print(f"\n🔐 Тестирование токена для роли '{role}': {token}")
116
-
117
91
  try:
118
92
  result = auth_manager.authenticate_api_key(token)
119
93
  auth_results[role] = result
120
-
121
94
  print(f" ✅ Аутентификация: {'УСПЕШНА' if result.is_valid else 'НЕУДАЧНА'}")
122
95
  if result.is_valid:
123
96
  print(f" 👤 Пользователь: {result.username}")
@@ -125,81 +98,61 @@ async def debug_role_chain():
125
98
  print(f" 🔑 Метод: {result.auth_method}")
126
99
  else:
127
100
  print(f" ❌ Ошибка: {result.error_message}")
128
-
129
101
  except Exception as e:
130
102
  print(f" ❌ Исключение: {e}")
131
103
  auth_results[role] = None
132
-
133
104
  print("\n📋 6. ТЕСТИРОВАНИЕ ПРАВ ДОСТУПА")
134
105
  print("-" * 30)
135
-
136
106
  # Test permissions for different actions
137
107
  test_actions = ["read", "write", "manage", "delete"]
138
-
139
108
  for role, auth_result in auth_results.items():
140
109
  if auth_result and auth_result.is_valid:
141
110
  print(f"\n🔒 Тестирование прав для роли '{role}' (роли: {auth_result.roles})")
142
-
143
111
  for action in test_actions:
144
112
  try:
145
113
  # Check permissions using permission manager
146
114
  validation_result = permission_manager.validate_access(
147
- auth_result.roles,
115
+ auth_result.roles,
148
116
  [action]
149
117
  )
150
-
151
118
  status = "✅ РАЗРЕШЕНО" if validation_result.is_valid else "❌ ЗАБЛОКИРОВАНО"
152
119
  print(f" {action}: {status}")
153
-
154
120
  if not validation_result.is_valid:
155
121
  print(f" 📝 Причина: {validation_result.error_message}")
156
122
  print(f" 🎯 Эффективные права: {validation_result.effective_permissions}")
157
123
  print(f" ❌ Отсутствующие права: {validation_result.missing_permissions}")
158
-
159
124
  except Exception as e:
160
125
  print(f" {action}: ❌ ОШИБКА - {e}")
161
-
162
126
  print("\n📋 7. ТЕСТИРОВАНИЕ ПОЛНОЙ ЦЕПОЧКИ")
163
127
  print("-" * 30)
164
-
165
128
  # Test complete request validation
166
129
  for role, token in test_tokens.items():
167
130
  print(f"\n🔄 Полная цепочка для роли '{role}'")
168
-
169
131
  request_data = {
170
132
  "api_key": token,
171
133
  "required_permissions": ["write"],
172
134
  "client_ip": "127.0.0.1"
173
135
  }
174
-
175
136
  try:
176
137
  result = security_manager.validate_request(request_data)
177
-
178
138
  status = "✅ УСПЕШНО" if result.is_valid else "❌ ЗАБЛОКИРОВАНО"
179
139
  print(f" Результат: {status}")
180
-
181
140
  if not result.is_valid:
182
141
  print(f" 📝 Причина: {result.error_message}")
183
-
184
142
  except Exception as e:
185
143
  print(f" ❌ ОШИБКА: {e}")
186
-
187
144
  print("\n📋 8. АНАЛИЗ ПРОБЛЕМЫ")
188
145
  print("-" * 30)
189
-
190
146
  print("🔍 ПРОБЛЕМА: Readonly роль получает доступ к write операциям")
191
147
  print("\n📋 ВОЗМОЖНЫЕ ПРИЧИНЫ:")
192
148
  print("1. Middleware не передает информацию о пользователе в request.state")
193
149
  print("2. Framework middleware не блокирует доступ на уровне middleware")
194
150
  print("3. Команда role_test не получает правильный контекст пользователя")
195
151
  print("4. Интеграция между middleware и командами не работает")
196
-
197
152
  print("\n📋 РЕКОМЕНДАЦИИ:")
198
153
  print("1. Проверить, как framework middleware устанавливает user info")
199
154
  print("2. Добавить проверку прав на уровне middleware")
200
155
  print("3. Убедиться, что request.state содержит user info")
201
156
  print("4. Проверить интеграцию между middleware и командами")
202
-
203
-
204
157
  if __name__ == "__main__":
205
158
  asyncio.run(debug_role_chain())
@@ -1,88 +1,68 @@
1
1
  """
2
2
  Demo Client Script
3
-
4
3
  This script demonstrates how to use the UniversalClient with different
5
4
  authentication methods and connection types.
6
-
7
5
  Author: Vasiliy Zdanovskiy
8
6
  email: vasilyvz@gmail.com
9
7
  """
10
-
11
8
  import asyncio
12
9
  import json
13
10
  import sys
14
11
  from pathlib import Path
15
-
16
12
  # Add project root to path
17
13
  sys.path.insert(0, str(Path(__file__).parent.parent))
18
-
19
14
  from examples.universal_client import UniversalClient, create_client_config
20
-
21
-
22
15
  async def demo_from_config_file(config_file: str):
23
16
  """
24
17
  Demo client using configuration from file.
25
-
26
18
  Args:
27
19
  config_file: Path to configuration file
28
20
  """
29
21
  print(f"🚀 Demo from config file: {config_file}")
30
22
  print("=" * 50)
31
-
32
23
  try:
33
24
  # Load configuration
34
25
  with open(config_file, 'r') as f:
35
26
  config = json.load(f)
36
-
37
27
  print(f"Configuration loaded: {config.get('security', {}).get('auth_method', 'none')} auth")
38
-
39
28
  # Create and use client
40
29
  async with UniversalClient(config) as client:
41
30
  # Test connection
42
31
  success = await client.test_connection()
43
-
44
32
  if success:
45
33
  print("✅ Connection successful!")
46
-
47
34
  # Test security features
48
35
  security_results = await client.test_security_features()
49
36
  print("\nSecurity Features:")
50
37
  for feature, status in security_results.items():
51
38
  status_icon = "✅" if status else "❌"
52
39
  print(f" {status_icon} {feature}: {status}")
53
-
54
40
  # Make API calls
55
41
  await demo_api_calls(client)
56
42
  else:
57
43
  print("❌ Connection failed")
58
-
59
44
  except FileNotFoundError:
60
45
  print(f"❌ Configuration file not found: {config_file}")
61
46
  except json.JSONDecodeError:
62
47
  print(f"❌ Invalid JSON in configuration file: {config_file}")
63
48
  except Exception as e:
64
49
  print(f"❌ Demo failed: {e}")
65
-
66
-
67
50
  async def demo_api_calls(client: UniversalClient):
68
51
  """Demonstrate various API calls."""
69
52
  print("\n📡 API Calls Demo:")
70
53
  print("-" * 30)
71
-
72
54
  # Test health endpoint
73
55
  try:
74
56
  health = await client.get("/health")
75
57
  print(f"Health: {health}")
76
58
  except Exception as e:
77
59
  print(f"Health check failed: {e}")
78
-
79
60
  # Test status endpoint
80
61
  try:
81
62
  status = await client.get("/api/status")
82
63
  print(f"Status: {status}")
83
64
  except Exception as e:
84
65
  print(f"Status check failed: {e}")
85
-
86
66
  # Test JSON-RPC command
87
67
  try:
88
68
  command_data = {
@@ -94,12 +74,10 @@ async def demo_api_calls(client: UniversalClient):
94
74
  },
95
75
  "id": 1
96
76
  }
97
-
98
77
  result = await client.post("/api/jsonrpc", command_data)
99
78
  print(f"Command Result: {result}")
100
79
  except Exception as e:
101
80
  print(f"Command execution failed: {e}")
102
-
103
81
  # Test security command if available
104
82
  try:
105
83
  security_data = {
@@ -111,46 +89,33 @@ async def demo_api_calls(client: UniversalClient):
111
89
  },
112
90
  "id": 2
113
91
  }
114
-
115
92
  result = await client.post("/api/jsonrpc", security_data)
116
93
  print(f"Security Status: {result}")
117
94
  except Exception as e:
118
95
  print(f"Security command failed: {e}")
119
-
120
-
121
96
  async def demo_all_configs():
122
97
  """Demo all available client configurations."""
123
98
  print("🚀 Demo All Client Configurations")
124
99
  print("=" * 50)
125
-
126
100
  config_dir = Path(__file__).parent / "client_configs"
127
-
128
101
  if not config_dir.exists():
129
102
  print(f"❌ Config directory not found: {config_dir}")
130
103
  return
131
-
132
104
  config_files = list(config_dir.glob("*.json"))
133
-
134
105
  if not config_files:
135
106
  print(f"❌ No configuration files found in {config_dir}")
136
107
  return
137
-
138
108
  print(f"Found {len(config_files)} configuration files:")
139
109
  for config_file in config_files:
140
110
  print(f" - {config_file.name}")
141
-
142
111
  print("\n" + "=" * 50)
143
-
144
112
  for config_file in config_files:
145
113
  await demo_from_config_file(str(config_file))
146
114
  print("\n" + "-" * 50)
147
-
148
-
149
115
  async def demo_programmatic_config():
150
116
  """Demo client with programmatically created configuration."""
151
117
  print("🚀 Demo Programmatic Configuration")
152
118
  print("=" * 50)
153
-
154
119
  # Create different configurations programmatically
155
120
  configs = [
156
121
  {
@@ -191,40 +156,31 @@ async def demo_programmatic_config():
191
156
  )
192
157
  }
193
158
  ]
194
-
195
159
  for config_info in configs:
196
160
  print(f"\n📋 Testing: {config_info['name']}")
197
161
  print("-" * 30)
198
-
199
162
  try:
200
163
  async with UniversalClient(config_info["config"]) as client:
201
164
  success = await client.test_connection()
202
-
203
165
  if success:
204
166
  print("✅ Connection successful!")
205
167
  await demo_api_calls(client)
206
168
  else:
207
169
  print("❌ Connection failed")
208
-
209
170
  except Exception as e:
210
171
  print(f"❌ Test failed: {e}")
211
-
212
-
213
172
  async def interactive_demo():
214
173
  """Interactive demo with user input."""
215
174
  print("🚀 Interactive Client Demo")
216
175
  print("=" * 50)
217
-
218
176
  print("Available authentication methods:")
219
177
  print("1. No authentication")
220
178
  print("2. API Key")
221
179
  print("3. JWT Token")
222
180
  print("4. Certificate")
223
181
  print("5. Basic Authentication")
224
-
225
182
  try:
226
183
  choice = input("\nSelect authentication method (1-5): ").strip()
227
-
228
184
  auth_methods = {
229
185
  "1": "none",
230
186
  "2": "api_key",
@@ -232,26 +188,20 @@ async def interactive_demo():
232
188
  "4": "certificate",
233
189
  "5": "basic"
234
190
  }
235
-
236
191
  if choice not in auth_methods:
237
192
  print("❌ Invalid choice")
238
193
  return
239
-
240
194
  auth_method = auth_methods[choice]
241
-
242
195
  # Get server URL
243
196
  server_url = input("Enter server URL (default: http://localhost:8000): ").strip()
244
197
  if not server_url:
245
198
  server_url = "http://localhost:8000"
246
-
247
199
  # Create configuration based on choice
248
200
  config_kwargs = {}
249
-
250
201
  if auth_method == "api_key":
251
202
  api_key = input("Enter API key: ").strip()
252
203
  if api_key:
253
204
  config_kwargs["api_key"] = api_key
254
-
255
205
  elif auth_method == "jwt":
256
206
  username = input("Enter username: ").strip()
257
207
  password = input("Enter password: ").strip()
@@ -262,7 +212,6 @@ async def interactive_demo():
262
212
  "password": password,
263
213
  "secret": secret
264
214
  })
265
-
266
215
  elif auth_method == "certificate":
267
216
  cert_file = input("Enter certificate file path: ").strip()
268
217
  key_file = input("Enter key file path: ").strip()
@@ -273,7 +222,6 @@ async def interactive_demo():
273
222
  "key_file": key_file,
274
223
  "ca_cert_file": ca_cert_file
275
224
  })
276
-
277
225
  elif auth_method == "basic":
278
226
  username = input("Enter username: ").strip()
279
227
  password = input("Enter password: ").strip()
@@ -282,50 +230,38 @@ async def interactive_demo():
282
230
  "username": username,
283
231
  "password": password
284
232
  })
285
-
286
233
  # Create configuration
287
234
  config = create_client_config(server_url, auth_method, **config_kwargs)
288
-
289
235
  print(f"\nConfiguration created for {auth_method} authentication")
290
236
  print(f"Server URL: {server_url}")
291
-
292
237
  # Test connection
293
238
  async with UniversalClient(config) as client:
294
239
  success = await client.test_connection()
295
-
296
240
  if success:
297
241
  print("✅ Connection successful!")
298
242
  await demo_api_calls(client)
299
243
  else:
300
244
  print("❌ Connection failed")
301
-
302
245
  except KeyboardInterrupt:
303
246
  print("\n\nDemo interrupted by user")
304
247
  except Exception as e:
305
248
  print(f"❌ Interactive demo failed: {e}")
306
-
307
-
308
249
  def main():
309
250
  """Main demo function."""
310
251
  if len(sys.argv) > 1:
311
252
  command = sys.argv[1]
312
-
313
253
  if command == "config":
314
254
  if len(sys.argv) > 2:
315
255
  config_file = sys.argv[2]
316
256
  asyncio.run(demo_from_config_file(config_file))
317
257
  else:
318
258
  print("Usage: python demo_client.py config <config_file>")
319
-
320
259
  elif command == "all":
321
260
  asyncio.run(demo_all_configs())
322
-
323
261
  elif command == "programmatic":
324
262
  asyncio.run(demo_programmatic_config())
325
-
326
263
  elif command == "interactive":
327
264
  asyncio.run(interactive_demo())
328
-
329
265
  else:
330
266
  print("Unknown command. Available commands:")
331
267
  print(" config <file> - Demo with config file")
@@ -335,7 +271,5 @@ def main():
335
271
  else:
336
272
  # Default: demo all configs
337
273
  asyncio.run(demo_all_configs())
338
-
339
-
340
274
  if __name__ == "__main__":
341
275
  main()
@@ -0,0 +1,11 @@
1
+ """Full Application Example.
2
+
3
+ This example demonstrates advanced usage of MCP Proxy Adapter including:
4
+ - Proxy registration endpoints
5
+ - Custom command hooks
6
+ - Advanced security configurations
7
+ - Role-based access control
8
+ """
9
+
10
+ from .main import app
11
+ from .proxy_endpoints import router as proxy_router
@@ -0,0 +1,7 @@
1
+ """Full Application Commands.
2
+
3
+ Custom command implementations for the full application example.
4
+ """
5
+
6
+ from .custom_echo_command import CustomEchoCommand
7
+ from .dynamic_calculator_command import DynamicCalculatorCommand