mcp-proxy-adapter 6.3.3__py3-none-any.whl → 6.3.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (129) hide show
  1. mcp_proxy_adapter/__init__.py +9 -5
  2. mcp_proxy_adapter/__main__.py +1 -1
  3. mcp_proxy_adapter/api/app.py +227 -176
  4. mcp_proxy_adapter/api/handlers.py +68 -60
  5. mcp_proxy_adapter/api/middleware/__init__.py +7 -5
  6. mcp_proxy_adapter/api/middleware/base.py +19 -16
  7. mcp_proxy_adapter/api/middleware/command_permission_middleware.py +44 -34
  8. mcp_proxy_adapter/api/middleware/error_handling.py +57 -67
  9. mcp_proxy_adapter/api/middleware/factory.py +50 -52
  10. mcp_proxy_adapter/api/middleware/logging.py +46 -30
  11. mcp_proxy_adapter/api/middleware/performance.py +19 -16
  12. mcp_proxy_adapter/api/middleware/protocol_middleware.py +80 -50
  13. mcp_proxy_adapter/api/middleware/transport_middleware.py +26 -24
  14. mcp_proxy_adapter/api/middleware/unified_security.py +70 -51
  15. mcp_proxy_adapter/api/middleware/user_info_middleware.py +43 -34
  16. mcp_proxy_adapter/api/schemas.py +69 -43
  17. mcp_proxy_adapter/api/tool_integration.py +83 -63
  18. mcp_proxy_adapter/api/tools.py +60 -50
  19. mcp_proxy_adapter/commands/__init__.py +15 -6
  20. mcp_proxy_adapter/commands/auth_validation_command.py +107 -110
  21. mcp_proxy_adapter/commands/base.py +108 -112
  22. mcp_proxy_adapter/commands/builtin_commands.py +28 -18
  23. mcp_proxy_adapter/commands/catalog_manager.py +394 -265
  24. mcp_proxy_adapter/commands/cert_monitor_command.py +222 -204
  25. mcp_proxy_adapter/commands/certificate_management_command.py +210 -213
  26. mcp_proxy_adapter/commands/command_registry.py +275 -226
  27. mcp_proxy_adapter/commands/config_command.py +48 -33
  28. mcp_proxy_adapter/commands/dependency_container.py +22 -23
  29. mcp_proxy_adapter/commands/dependency_manager.py +65 -56
  30. mcp_proxy_adapter/commands/echo_command.py +15 -15
  31. mcp_proxy_adapter/commands/health_command.py +31 -29
  32. mcp_proxy_adapter/commands/help_command.py +97 -61
  33. mcp_proxy_adapter/commands/hooks.py +65 -49
  34. mcp_proxy_adapter/commands/key_management_command.py +148 -147
  35. mcp_proxy_adapter/commands/load_command.py +58 -40
  36. mcp_proxy_adapter/commands/plugins_command.py +80 -54
  37. mcp_proxy_adapter/commands/protocol_management_command.py +60 -48
  38. mcp_proxy_adapter/commands/proxy_registration_command.py +107 -115
  39. mcp_proxy_adapter/commands/reload_command.py +43 -37
  40. mcp_proxy_adapter/commands/result.py +26 -33
  41. mcp_proxy_adapter/commands/role_test_command.py +26 -26
  42. mcp_proxy_adapter/commands/roles_management_command.py +176 -173
  43. mcp_proxy_adapter/commands/security_command.py +134 -122
  44. mcp_proxy_adapter/commands/settings_command.py +47 -56
  45. mcp_proxy_adapter/commands/ssl_setup_command.py +109 -129
  46. mcp_proxy_adapter/commands/token_management_command.py +129 -158
  47. mcp_proxy_adapter/commands/transport_management_command.py +41 -36
  48. mcp_proxy_adapter/commands/unload_command.py +42 -37
  49. mcp_proxy_adapter/config.py +36 -35
  50. mcp_proxy_adapter/core/__init__.py +19 -21
  51. mcp_proxy_adapter/core/app_factory.py +30 -9
  52. mcp_proxy_adapter/core/app_runner.py +81 -64
  53. mcp_proxy_adapter/core/auth_validator.py +176 -182
  54. mcp_proxy_adapter/core/certificate_utils.py +469 -426
  55. mcp_proxy_adapter/core/client.py +155 -126
  56. mcp_proxy_adapter/core/client_manager.py +60 -54
  57. mcp_proxy_adapter/core/client_security.py +108 -88
  58. mcp_proxy_adapter/core/config_converter.py +176 -143
  59. mcp_proxy_adapter/core/config_validator.py +12 -4
  60. mcp_proxy_adapter/core/crl_utils.py +21 -7
  61. mcp_proxy_adapter/core/errors.py +64 -20
  62. mcp_proxy_adapter/core/logging.py +34 -29
  63. mcp_proxy_adapter/core/mtls_asgi.py +29 -25
  64. mcp_proxy_adapter/core/mtls_asgi_app.py +66 -54
  65. mcp_proxy_adapter/core/protocol_manager.py +154 -104
  66. mcp_proxy_adapter/core/proxy_client.py +202 -144
  67. mcp_proxy_adapter/core/proxy_registration.py +12 -2
  68. mcp_proxy_adapter/core/role_utils.py +139 -125
  69. mcp_proxy_adapter/core/security_adapter.py +88 -77
  70. mcp_proxy_adapter/core/security_factory.py +50 -44
  71. mcp_proxy_adapter/core/security_integration.py +72 -24
  72. mcp_proxy_adapter/core/server_adapter.py +68 -64
  73. mcp_proxy_adapter/core/server_engine.py +71 -53
  74. mcp_proxy_adapter/core/settings.py +68 -58
  75. mcp_proxy_adapter/core/ssl_utils.py +69 -56
  76. mcp_proxy_adapter/core/transport_manager.py +72 -60
  77. mcp_proxy_adapter/core/unified_config_adapter.py +201 -150
  78. mcp_proxy_adapter/core/utils.py +4 -2
  79. mcp_proxy_adapter/custom_openapi.py +107 -99
  80. mcp_proxy_adapter/examples/basic_framework/main.py +9 -2
  81. mcp_proxy_adapter/examples/commands/__init__.py +1 -1
  82. mcp_proxy_adapter/examples/create_certificates_simple.py +182 -71
  83. mcp_proxy_adapter/examples/debug_request_state.py +38 -19
  84. mcp_proxy_adapter/examples/debug_role_chain.py +53 -20
  85. mcp_proxy_adapter/examples/demo_client.py +48 -36
  86. mcp_proxy_adapter/examples/examples/basic_framework/main.py +9 -2
  87. mcp_proxy_adapter/examples/examples/full_application/__init__.py +1 -0
  88. mcp_proxy_adapter/examples/examples/full_application/commands/custom_echo_command.py +22 -10
  89. mcp_proxy_adapter/examples/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  90. mcp_proxy_adapter/examples/examples/full_application/hooks/application_hooks.py +16 -3
  91. mcp_proxy_adapter/examples/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  92. mcp_proxy_adapter/examples/examples/full_application/main.py +27 -2
  93. mcp_proxy_adapter/examples/examples/full_application/proxy_endpoints.py +48 -14
  94. mcp_proxy_adapter/examples/full_application/__init__.py +1 -0
  95. mcp_proxy_adapter/examples/full_application/commands/custom_echo_command.py +22 -10
  96. mcp_proxy_adapter/examples/full_application/commands/dynamic_calculator_command.py +24 -17
  97. mcp_proxy_adapter/examples/full_application/hooks/application_hooks.py +16 -3
  98. mcp_proxy_adapter/examples/full_application/hooks/builtin_command_hooks.py +13 -3
  99. mcp_proxy_adapter/examples/full_application/main.py +27 -2
  100. mcp_proxy_adapter/examples/full_application/proxy_endpoints.py +48 -14
  101. mcp_proxy_adapter/examples/generate_all_certificates.py +198 -73
  102. mcp_proxy_adapter/examples/generate_certificates.py +31 -16
  103. mcp_proxy_adapter/examples/generate_certificates_and_tokens.py +220 -74
  104. mcp_proxy_adapter/examples/generate_test_configs.py +68 -91
  105. mcp_proxy_adapter/examples/proxy_registration_example.py +76 -75
  106. mcp_proxy_adapter/examples/run_example.py +23 -5
  107. mcp_proxy_adapter/examples/run_full_test_suite.py +109 -71
  108. mcp_proxy_adapter/examples/run_proxy_server.py +22 -9
  109. mcp_proxy_adapter/examples/run_security_tests.py +103 -41
  110. mcp_proxy_adapter/examples/run_security_tests_fixed.py +72 -36
  111. mcp_proxy_adapter/examples/scripts/config_generator.py +288 -187
  112. mcp_proxy_adapter/examples/scripts/create_certificates_simple.py +185 -72
  113. mcp_proxy_adapter/examples/scripts/generate_certificates_and_tokens.py +220 -74
  114. mcp_proxy_adapter/examples/security_test_client.py +196 -127
  115. mcp_proxy_adapter/examples/setup_test_environment.py +17 -29
  116. mcp_proxy_adapter/examples/test_config.py +19 -4
  117. mcp_proxy_adapter/examples/test_config_generator.py +23 -7
  118. mcp_proxy_adapter/examples/test_examples.py +84 -56
  119. mcp_proxy_adapter/examples/universal_client.py +119 -62
  120. mcp_proxy_adapter/openapi.py +108 -115
  121. mcp_proxy_adapter/utils/config_generator.py +429 -274
  122. mcp_proxy_adapter/version.py +1 -2
  123. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/METADATA +1 -1
  124. mcp_proxy_adapter-6.3.5.dist-info/RECORD +143 -0
  125. mcp_proxy_adapter-6.3.3.dist-info/RECORD +0 -143
  126. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/WHEEL +0 -0
  127. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/entry_points.txt +0 -0
  128. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/licenses/LICENSE +0 -0
  129. {mcp_proxy_adapter-6.3.3.dist-info → mcp_proxy_adapter-6.3.5.dist-info}/top_level.txt +0 -0
@@ -28,29 +28,30 @@ from ..core.auth_validator import AuthValidator
28
28
  class TokenManagementCommand(Command):
29
29
  """
30
30
  Token management commands.
31
-
31
+
32
32
  Provides commands for creating, validating, revoking, listing, and refreshing tokens.
33
33
  Supports both JWT and API tokens.
34
34
  """
35
-
35
+
36
36
  def __init__(self):
37
37
  """Initialize token management command."""
38
38
  super().__init__()
39
39
  self.auth_validator = AuthValidator()
40
40
  self.logger = logging.getLogger(__name__)
41
-
41
+
42
42
  # Load configuration
43
43
  from ...config import config
44
+
44
45
  self.token_config = config.get("ssl", {}).get("token_auth", {})
45
46
  self.tokens_file = self.token_config.get("tokens_file", "tokens.json")
46
47
  self.token_expiry = self.token_config.get("token_expiry", 3600)
47
48
  self.jwt_secret = self.token_config.get("jwt_secret", "")
48
49
  self.jwt_algorithm = self.token_config.get("jwt_algorithm", "HS256")
49
-
50
+
50
51
  async def execute(self, **kwargs) -> CommandResult:
51
52
  """
52
53
  Execute token management command.
53
-
54
+
54
55
  Args:
55
56
  **kwargs: Command parameters containing:
56
57
  - method: Command method (token_create, token_validate, token_revoke, token_list, token_refresh)
@@ -58,13 +59,13 @@ class TokenManagementCommand(Command):
58
59
  - token_data: Token data for creation
59
60
  - token: Token string for validation/revocation/refresh
60
61
  - active_only: Boolean for token listing
61
-
62
+
62
63
  Returns:
63
64
  CommandResult with operation result
64
65
  """
65
66
  try:
66
67
  method = kwargs.get("method")
67
-
68
+
68
69
  if method == "token_create":
69
70
  token_type = kwargs.get("token_type", "api")
70
71
  token_data = kwargs.get("token_data", {})
@@ -83,22 +84,20 @@ class TokenManagementCommand(Command):
83
84
  token = kwargs.get("token")
84
85
  return await self.token_refresh(token)
85
86
  else:
86
- return ErrorResult(
87
- message=f"Unknown method: {method}",
88
- code=-32601
89
- )
90
-
87
+ return ErrorResult(message=f"Unknown method: {method}", code=-32601)
88
+
91
89
  except Exception as e:
92
90
  self.logger.error(f"Token management command execution error: {e}")
93
91
  return ErrorResult(
94
- message=f"Token management command failed: {str(e)}",
95
- code=-32603
92
+ message=f"Token management command failed: {str(e)}", code=-32603
96
93
  )
97
-
98
- async def token_create(self, token_type: str, token_data: Dict[str, Any]) -> Union[SuccessResult, ErrorResult]:
94
+
95
+ async def token_create(
96
+ self, token_type: str, token_data: Dict[str, Any]
97
+ ) -> Union[SuccessResult, ErrorResult]:
99
98
  """
100
99
  Create a new token.
101
-
100
+
102
101
  Args:
103
102
  token_type: Type of token (jwt/api)
104
103
  token_data: Token data dictionary containing:
@@ -106,145 +105,133 @@ class TokenManagementCommand(Command):
106
105
  - expires_in: Token expiration time in seconds (optional)
107
106
  - description: Token description (optional)
108
107
  - user_id: User ID associated with token (optional)
109
-
108
+
110
109
  Returns:
111
110
  CommandResult with created token information
112
111
  """
113
112
  try:
114
113
  if token_type not in ["jwt", "api"]:
115
114
  return ErrorResult(
116
- message=f"Unsupported token type: {token_type}",
117
- code=-32602
115
+ message=f"Unsupported token type: {token_type}", code=-32602
118
116
  )
119
-
117
+
120
118
  if token_type == "jwt":
121
119
  return await self._create_jwt_token(token_data)
122
120
  else:
123
121
  return await self._create_api_token(token_data)
124
-
122
+
125
123
  except Exception as e:
126
124
  self.logger.error(f"Token creation error: {e}")
127
- return ErrorResult(
128
- message=f"Token creation failed: {str(e)}",
129
- code=-32603
130
- )
131
-
132
- async def token_validate(self, token: str, token_type: str = "auto") -> Union[SuccessResult, ErrorResult]:
125
+ return ErrorResult(message=f"Token creation failed: {str(e)}", code=-32603)
126
+
127
+ async def token_validate(
128
+ self, token: str, token_type: str = "auto"
129
+ ) -> Union[SuccessResult, ErrorResult]:
133
130
  """
134
131
  Validate a token.
135
-
132
+
136
133
  Args:
137
134
  token: Token string to validate
138
135
  token_type: Type of token (auto/jwt/api)
139
-
136
+
140
137
  Returns:
141
138
  CommandResult with validation status and token information
142
139
  """
143
140
  try:
144
141
  if not token:
145
- return ErrorResult(
146
- message="Token not provided",
147
- code=-32602
148
- )
149
-
142
+ return ErrorResult(message="Token not provided", code=-32602)
143
+
150
144
  # Auto-detect token type if not specified
151
145
  if token_type == "auto":
152
146
  token_type = "jwt" if self._is_jwt_token(token) else "api"
153
-
147
+
154
148
  # Use AuthValidator for validation
155
149
  result = self.auth_validator.validate_token(token, token_type)
156
-
150
+
157
151
  if result.is_valid:
158
152
  return SuccessResult(
159
153
  data={
160
154
  "valid": True,
161
155
  "token_type": token_type,
162
156
  "roles": result.roles,
163
- "expires_at": self._get_token_expiry(token, token_type)
157
+ "expires_at": self._get_token_expiry(token, token_type),
164
158
  }
165
159
  )
166
160
  else:
167
161
  error_data = result.to_json_rpc_error()
168
162
  return ErrorResult(
169
- message=error_data["message"],
170
- code=error_data["code"]
163
+ message=error_data["message"], code=error_data["code"]
171
164
  )
172
-
165
+
173
166
  except Exception as e:
174
167
  self.logger.error(f"Token validation error: {e}")
175
168
  return ErrorResult(
176
- message=f"Token validation failed: {str(e)}",
177
- code=-32603
169
+ message=f"Token validation failed: {str(e)}", code=-32603
178
170
  )
179
-
171
+
180
172
  async def token_revoke(self, token: str) -> Union[SuccessResult, ErrorResult]:
181
173
  """
182
174
  Revoke a token.
183
-
175
+
184
176
  Args:
185
177
  token: Token string to revoke
186
-
178
+
187
179
  Returns:
188
180
  CommandResult with revocation status
189
181
  """
190
182
  try:
191
183
  if not token:
192
- return ErrorResult(
193
- message="Token not provided",
194
- code=-32602
195
- )
196
-
184
+ return ErrorResult(message="Token not provided", code=-32602)
185
+
197
186
  # Load current tokens
198
187
  tokens = self._load_tokens()
199
-
188
+
200
189
  # Check if token exists
201
190
  if token not in tokens:
202
- return ErrorResult(
203
- message="Token not found",
204
- code=-32011
205
- )
206
-
191
+ return ErrorResult(message="Token not found", code=-32011)
192
+
207
193
  # Mark token as revoked
208
194
  tokens[token]["active"] = False
209
195
  tokens[token]["revoked_at"] = time.time()
210
196
  tokens[token]["revoked_by"] = "system"
211
-
197
+
212
198
  # Save updated tokens
213
199
  self._save_tokens(tokens)
214
-
200
+
215
201
  return SuccessResult(
216
202
  data={
217
203
  "revoked": True,
218
204
  "token": token,
219
- "revoked_at": datetime.now().isoformat()
205
+ "revoked_at": datetime.now().isoformat(),
220
206
  }
221
207
  )
222
-
208
+
223
209
  except Exception as e:
224
210
  self.logger.error(f"Token revocation error: {e}")
225
211
  return ErrorResult(
226
- message=f"Token revocation failed: {str(e)}",
227
- code=-32603
212
+ message=f"Token revocation failed: {str(e)}", code=-32603
228
213
  )
229
-
230
- async def token_list(self, active_only: bool = True) -> Union[SuccessResult, ErrorResult]:
214
+
215
+ async def token_list(
216
+ self, active_only: bool = True
217
+ ) -> Union[SuccessResult, ErrorResult]:
231
218
  """
232
219
  List all tokens.
233
-
220
+
234
221
  Args:
235
222
  active_only: If True, return only active tokens
236
-
223
+
237
224
  Returns:
238
225
  CommandResult with list of tokens
239
226
  """
240
227
  try:
241
228
  # Load tokens
242
229
  tokens = self._load_tokens()
243
-
230
+
244
231
  # Filter tokens if requested
245
232
  if active_only:
246
233
  tokens = {k: v for k, v in tokens.items() if v.get("active", True)}
247
-
234
+
248
235
  # Prepare token list (without sensitive data)
249
236
  token_list = []
250
237
  for token_id, token_data in tokens.items():
@@ -256,70 +243,55 @@ class TokenManagementCommand(Command):
256
243
  "created_at": token_data.get("created_at"),
257
244
  "expires_at": token_data.get("expires_at"),
258
245
  "description": token_data.get("description", ""),
259
- "user_id": token_data.get("user_id")
246
+ "user_id": token_data.get("user_id"),
260
247
  }
261
-
248
+
262
249
  if "revoked_at" in token_data:
263
250
  token_info["revoked_at"] = token_data["revoked_at"]
264
-
251
+
265
252
  token_list.append(token_info)
266
-
253
+
267
254
  return SuccessResult(
268
255
  data={
269
256
  "tokens": token_list,
270
257
  "count": len(token_list),
271
- "active_only": active_only
258
+ "active_only": active_only,
272
259
  }
273
260
  )
274
-
261
+
275
262
  except Exception as e:
276
263
  self.logger.error(f"Token listing error: {e}")
277
- return ErrorResult(
278
- message=f"Token listing failed: {str(e)}",
279
- code=-32603
280
- )
281
-
264
+ return ErrorResult(message=f"Token listing failed: {str(e)}", code=-32603)
265
+
282
266
  async def token_refresh(self, token: str) -> Union[SuccessResult, ErrorResult]:
283
267
  """
284
268
  Refresh a token.
285
-
269
+
286
270
  Args:
287
271
  token: Token string to refresh
288
-
272
+
289
273
  Returns:
290
274
  CommandResult with refreshed token information
291
275
  """
292
276
  try:
293
277
  if not token:
294
- return ErrorResult(
295
- message="Token not provided",
296
- code=-32602
297
- )
298
-
278
+ return ErrorResult(message="Token not provided", code=-32602)
279
+
299
280
  # Load current tokens
300
281
  tokens = self._load_tokens()
301
-
282
+
302
283
  # Check if token exists and is active
303
284
  if token not in tokens:
304
- return ErrorResult(
305
- message="Token not found",
306
- code=-32011
307
- )
308
-
285
+ return ErrorResult(message="Token not found", code=-32011)
286
+
309
287
  token_data = tokens[token]
310
288
  if not token_data.get("active", True):
311
- return ErrorResult(
312
- message="Token is revoked",
313
- code=-32011
314
- )
315
-
289
+ return ErrorResult(message="Token is revoked", code=-32011)
290
+
316
291
  # Check if token has expired
317
292
  if "expires_at" in token_data and time.time() > token_data["expires_at"]:
318
- return ErrorResult(
319
- message="Token has expired",
320
- code=-32010
321
- )
322
-
293
+ return ErrorResult(message="Token has expired", code=-32010)
294
+
323
295
  # Create new token with same data
324
296
  new_token_data = {
325
297
  "type": token_data.get("type", "api"),
@@ -329,64 +301,63 @@ class TokenManagementCommand(Command):
329
301
  "expires_at": time.time() + self.token_expiry,
330
302
  "description": token_data.get("description", ""),
331
303
  "user_id": token_data.get("user_id"),
332
- "refreshed_from": token
304
+ "refreshed_from": token,
333
305
  }
334
-
306
+
335
307
  # Generate new token ID
336
308
  new_token_id = str(uuid.uuid4())
337
309
  tokens[new_token_id] = new_token_data
338
-
310
+
339
311
  # Revoke old token
340
312
  tokens[token]["active"] = False
341
313
  tokens[token]["refreshed_to"] = new_token_id
342
314
  tokens[token]["refreshed_at"] = time.time()
343
-
315
+
344
316
  # Save updated tokens
345
317
  self._save_tokens(tokens)
346
-
318
+
347
319
  return SuccessResult(
348
320
  data={
349
321
  "refreshed": True,
350
322
  "old_token": token,
351
323
  "new_token": new_token_id,
352
- "expires_at": new_token_data["expires_at"]
324
+ "expires_at": new_token_data["expires_at"],
353
325
  }
354
326
  )
355
-
327
+
356
328
  except Exception as e:
357
329
  self.logger.error(f"Token refresh error: {e}")
358
- return ErrorResult(
359
- message=f"Token refresh failed: {str(e)}",
360
- code=-32603
361
- )
362
-
363
- async def _create_jwt_token(self, token_data: Dict[str, Any]) -> Union[SuccessResult, ErrorResult]:
330
+ return ErrorResult(message=f"Token refresh failed: {str(e)}", code=-32603)
331
+
332
+ async def _create_jwt_token(
333
+ self, token_data: Dict[str, Any]
334
+ ) -> Union[SuccessResult, ErrorResult]:
364
335
  """
365
336
  Create JWT token.
366
-
337
+
367
338
  Args:
368
339
  token_data: Token data dictionary
369
-
340
+
370
341
  Returns:
371
342
  CommandResult with JWT token
372
343
  """
373
344
  try:
374
345
  # This is a placeholder for JWT creation
375
346
  # In a real implementation, you would use a JWT library like PyJWT
376
-
347
+
377
348
  # For now, create a simple token structure
378
349
  token_id = str(uuid.uuid4())
379
350
  expires_in = token_data.get("expires_in", self.token_expiry)
380
-
351
+
381
352
  jwt_token_data = {
382
353
  "jti": token_id,
383
354
  "sub": token_data.get("user_id", "system"),
384
355
  "roles": token_data.get("roles", []),
385
356
  "exp": time.time() + expires_in,
386
357
  "iat": time.time(),
387
- "iss": "mcp_proxy_adapter"
358
+ "iss": "mcp_proxy_adapter",
388
359
  }
389
-
360
+
390
361
  # In a real implementation, you would encode this as JWT
391
362
  # For now, return the token data
392
363
  return SuccessResult(
@@ -395,24 +366,25 @@ class TokenManagementCommand(Command):
395
366
  "token_type": "jwt",
396
367
  "expires_at": jwt_token_data["exp"],
397
368
  "roles": jwt_token_data["roles"],
398
- "user_id": jwt_token_data["sub"]
369
+ "user_id": jwt_token_data["sub"],
399
370
  }
400
371
  )
401
-
372
+
402
373
  except Exception as e:
403
374
  self.logger.error(f"JWT token creation error: {e}")
404
375
  return ErrorResult(
405
- message=f"JWT token creation failed: {str(e)}",
406
- code=-32603
376
+ message=f"JWT token creation failed: {str(e)}", code=-32603
407
377
  )
408
-
409
- async def _create_api_token(self, token_data: Dict[str, Any]) -> Union[SuccessResult, ErrorResult]:
378
+
379
+ async def _create_api_token(
380
+ self, token_data: Dict[str, Any]
381
+ ) -> Union[SuccessResult, ErrorResult]:
410
382
  """
411
383
  Create API token.
412
-
384
+
413
385
  Args:
414
386
  token_data: Token data dictionary
415
-
387
+
416
388
  Returns:
417
389
  CommandResult with API token
418
390
  """
@@ -420,7 +392,7 @@ class TokenManagementCommand(Command):
420
392
  # Generate token ID
421
393
  token_id = str(uuid.uuid4())
422
394
  expires_in = token_data.get("expires_in", self.token_expiry)
423
-
395
+
424
396
  # Create token data
425
397
  api_token_data = {
426
398
  "type": "api",
@@ -429,52 +401,51 @@ class TokenManagementCommand(Command):
429
401
  "created_at": time.time(),
430
402
  "expires_at": time.time() + expires_in,
431
403
  "description": token_data.get("description", ""),
432
- "user_id": token_data.get("user_id")
404
+ "user_id": token_data.get("user_id"),
433
405
  }
434
-
406
+
435
407
  # Load current tokens and add new token
436
408
  tokens = self._load_tokens()
437
409
  tokens[token_id] = api_token_data
438
410
  self._save_tokens(tokens)
439
-
411
+
440
412
  return SuccessResult(
441
413
  data={
442
414
  "token": token_id,
443
415
  "token_type": "api",
444
416
  "expires_at": api_token_data["expires_at"],
445
417
  "roles": api_token_data["roles"],
446
- "user_id": api_token_data["user_id"]
418
+ "user_id": api_token_data["user_id"],
447
419
  }
448
420
  )
449
-
421
+
450
422
  except Exception as e:
451
423
  self.logger.error(f"API token creation error: {e}")
452
424
  return ErrorResult(
453
- message=f"API token creation failed: {str(e)}",
454
- code=-32603
425
+ message=f"API token creation failed: {str(e)}", code=-32603
455
426
  )
456
-
427
+
457
428
  def _is_jwt_token(self, token: str) -> bool:
458
429
  """
459
430
  Check if token is JWT format.
460
-
431
+
461
432
  Args:
462
433
  token: Token string
463
-
434
+
464
435
  Returns:
465
436
  True if token appears to be JWT, False otherwise
466
437
  """
467
- parts = token.split('.')
438
+ parts = token.split(".")
468
439
  return len(parts) == 3
469
-
440
+
470
441
  def _get_token_expiry(self, token: str, token_type: str) -> Optional[float]:
471
442
  """
472
443
  Get token expiry time.
473
-
444
+
474
445
  Args:
475
446
  token: Token string
476
447
  token_type: Type of token
477
-
448
+
478
449
  Returns:
479
450
  Expiry timestamp or None
480
451
  """
@@ -483,47 +454,47 @@ class TokenManagementCommand(Command):
483
454
  tokens = self._load_tokens()
484
455
  if token in tokens:
485
456
  return tokens[token].get("expires_at")
486
-
457
+
487
458
  # For JWT tokens, this would require decoding
488
459
  # For now, return None
489
460
  return None
490
-
461
+
491
462
  except Exception as e:
492
463
  self.logger.error(f"Failed to get token expiry: {e}")
493
464
  return None
494
-
465
+
495
466
  def _load_tokens(self) -> Dict[str, Any]:
496
467
  """
497
468
  Load tokens from file.
498
-
469
+
499
470
  Returns:
500
471
  Dictionary of tokens
501
472
  """
502
473
  try:
503
474
  if not self.tokens_file or not Path(self.tokens_file).exists():
504
475
  return {}
505
-
506
- with open(self.tokens_file, 'r', encoding='utf-8') as f:
476
+
477
+ with open(self.tokens_file, "r", encoding="utf-8") as f:
507
478
  return json.load(f)
508
-
479
+
509
480
  except Exception as e:
510
481
  self.logger.error(f"Failed to load tokens: {e}")
511
482
  return {}
512
-
483
+
513
484
  def _save_tokens(self, tokens: Dict[str, Any]) -> None:
514
485
  """
515
486
  Save tokens to file.
516
-
487
+
517
488
  Args:
518
489
  tokens: Dictionary of tokens to save
519
490
  """
520
491
  try:
521
492
  # Ensure directory exists
522
493
  Path(self.tokens_file).parent.mkdir(parents=True, exist_ok=True)
523
-
524
- with open(self.tokens_file, 'w', encoding='utf-8') as f:
494
+
495
+ with open(self.tokens_file, "w", encoding="utf-8") as f:
525
496
  json.dump(tokens, f, indent=2, ensure_ascii=False)
526
-
497
+
527
498
  except Exception as e:
528
499
  self.logger.error(f"Failed to save tokens: {e}")
529
- raise
500
+ raise