Skip to content

Commit a719bef

Browse files
Add support for disabling API key validation when api_key is set to None
1 parent f7bebc4 commit a719bef

File tree

5 files changed

+59
-1
lines changed

5 files changed

+59
-1
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,9 @@ router_config = {
180180
}
181181
router = MCPRouter(api_key="your-custom-api-key", router_config=router_config)
182182

183+
# Disable API key validation by setting api_key to None
184+
router = MCPRouter(api_key=None)
185+
183186
# Optionally, create a global config from the router's configuration
184187
router.create_global_config()
185188
```

src/mcpm/router/router.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ class MCPRouter:
5353
}
5454
router = MCPRouter(api_key="your-api-key", router_config=router_config)
5555
56+
# Disable API key validation by setting api_key to None
57+
router = MCPRouter(api_key=None)
58+
5659
# Create a global config from the router's configuration
5760
router.create_global_config()
5861
```
@@ -73,7 +76,7 @@ def __init__(
7376
:param profile_path: Path to the profile file
7477
:param strict: Whether to use strict mode for duplicated tool name.
7578
If True, raise error when duplicated tool name is found else auto resolve by adding server name prefix
76-
:param api_key: Optional API key to use for authentication
79+
:param api_key: Optional API key to use for authentication. Set to None to disable API key validation.
7780
:param router_config: Optional router configuration to use instead of the global config
7881
"""
7982
self.server_sessions: t.Dict[str, ServerConnection] = {}

src/mcpm/router/transport.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,11 @@ async def handle_post_message(self, scope: Scope, receive: Receive, send: Send):
239239
self._session_id_to_identifier.pop(session_id, None)
240240

241241
def _validate_api_key(self, scope: Scope, api_key: str | None) -> bool:
242+
# If api_key is explicitly set to None, disable API key validation
243+
if self.api_key is None:
244+
logger.debug("API key validation disabled")
245+
return True
246+
242247
# If we have a directly provided API key and it matches the request's API key, return True
243248
if self.api_key is not None and api_key == self.api_key:
244249
return True

tests/router/__init__.py

Whitespace-only changes.
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import unittest
2+
from unittest.mock import MagicMock, patch
3+
4+
from mcpm.router.transport import RouterSseTransport
5+
6+
7+
class TestApiKeyDisabled(unittest.TestCase):
8+
"""Test that API key validation is disabled when api_key is set to None."""
9+
10+
def test_api_key_disabled(self):
11+
"""Test that API key validation is disabled when api_key is set to None."""
12+
# Create a transport with api_key=None
13+
transport = RouterSseTransport("/messages/", api_key=None)
14+
15+
# Mock the scope
16+
scope = MagicMock()
17+
18+
# Test that _validate_api_key returns True regardless of the api_key parameter
19+
self.assertTrue(transport._validate_api_key(scope, api_key=None))
20+
self.assertTrue(transport._validate_api_key(scope, api_key="some-key"))
21+
self.assertTrue(transport._validate_api_key(scope, api_key="invalid-key"))
22+
23+
def test_api_key_enabled(self):
24+
"""Test that API key validation works when api_key is set."""
25+
# Create a transport with a specific api_key
26+
transport = RouterSseTransport("/messages/", api_key="test-key")
27+
28+
# Mock the scope
29+
scope = MagicMock()
30+
31+
# Test that _validate_api_key returns True only for the matching key
32+
self.assertTrue(transport._validate_api_key(scope, api_key="test-key"))
33+
self.assertFalse(transport._validate_api_key(scope, api_key="wrong-key"))
34+
35+
# When using the default validation logic, we need to mock the ConfigManager
36+
with patch("mcpm.router.transport.ConfigManager") as mock_config_manager:
37+
# Set up the mock to make the default validation logic fail
38+
mock_instance = mock_config_manager.return_value
39+
mock_instance.read_share_config.return_value = {"url": "http://example.com", "api_key": "share-key"}
40+
mock_instance.get_router_config.return_value = {"host": "localhost"}
41+
42+
# Test with a key that doesn't match the transport's key
43+
self.assertFalse(transport._validate_api_key(scope, api_key="wrong-key"))
44+
45+
46+
if __name__ == "__main__":
47+
unittest.main()

0 commit comments

Comments
 (0)