mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-10 22:41:41 +00:00
Merge pull request #23260 from milan-berri/feat/mcp-token-auth-support
feat(mcp): add token authentication support for MCP servers
This commit is contained in:
commit
b02ecc7807
7 changed files with 79 additions and 3 deletions
|
|
@ -212,6 +212,8 @@ class MCPClient:
|
|||
headers["Authorization"] = self._mcp_auth_value
|
||||
elif self.auth_type == MCPAuth.oauth2:
|
||||
headers["Authorization"] = f"Bearer {self._mcp_auth_value}"
|
||||
elif self.auth_type == MCPAuth.token:
|
||||
headers["Authorization"] = f"token {self._mcp_auth_value}"
|
||||
elif isinstance(self._mcp_auth_value, dict):
|
||||
headers.update(self._mcp_auth_value)
|
||||
|
||||
|
|
|
|||
|
|
@ -418,6 +418,8 @@ class MCPServerManager:
|
|||
headers["Authorization"] = f"ApiKey {server.authentication_token}"
|
||||
elif server.auth_type == MCPAuth.basic:
|
||||
headers["Authorization"] = f"Basic {server.authentication_token}"
|
||||
elif server.auth_type == MCPAuth.token:
|
||||
headers["Authorization"] = f"token {server.authentication_token}"
|
||||
|
||||
# Add any static headers from server config.
|
||||
#
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ class MCPAuth(str, enum.Enum):
|
|||
basic = "basic"
|
||||
authorization = "authorization"
|
||||
oauth2 = "oauth2"
|
||||
token = "token"
|
||||
|
||||
|
||||
# MCP Literals
|
||||
|
|
@ -50,6 +51,7 @@ MCPAuthType = Optional[
|
|||
MCPAuth.basic,
|
||||
MCPAuth.authorization,
|
||||
MCPAuth.oauth2,
|
||||
MCPAuth.token,
|
||||
]
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ sys.path.insert(0, "../../../")
|
|||
|
||||
import litellm.experimental_mcp_client.client as mcp_client_module
|
||||
from litellm.experimental_mcp_client.client import MCPClient
|
||||
from litellm.types.mcp import MCPStdioConfig, MCPTransport
|
||||
from litellm.types.mcp import MCPAuth, MCPStdioConfig, MCPTransport
|
||||
|
||||
|
||||
class TestMCPClient:
|
||||
|
|
@ -245,6 +245,72 @@ class TestMCPClient:
|
|||
assert test_client.headers is not None
|
||||
await test_client.aclose()
|
||||
|
||||
def test_token_auth_header_generation(self):
|
||||
"""Test that token auth generates correct Authorization header"""
|
||||
client = MCPClient(
|
||||
server_url="http://example.com/sse",
|
||||
transport_type="sse",
|
||||
auth_type=MCPAuth.token,
|
||||
auth_value="my-secret-token"
|
||||
)
|
||||
|
||||
headers = client._get_auth_headers()
|
||||
|
||||
assert "Authorization" in headers
|
||||
assert headers["Authorization"] == "token my-secret-token"
|
||||
|
||||
def test_token_auth_compatibility_with_existing_auth_types(self):
|
||||
"""Verify existing auth types are not affected by token auth addition"""
|
||||
# Test bearer token
|
||||
client = MCPClient(
|
||||
server_url="http://example.com/sse",
|
||||
transport_type="sse",
|
||||
auth_type=MCPAuth.bearer_token,
|
||||
auth_value="bearer-token"
|
||||
)
|
||||
headers = client._get_auth_headers()
|
||||
assert headers["Authorization"] == "Bearer bearer-token"
|
||||
|
||||
# Test API key
|
||||
client = MCPClient(
|
||||
server_url="http://example.com/sse",
|
||||
transport_type="sse",
|
||||
auth_type=MCPAuth.api_key,
|
||||
auth_value="api-key"
|
||||
)
|
||||
headers = client._get_auth_headers()
|
||||
assert headers["X-API-Key"] == "api-key"
|
||||
|
||||
# Test basic auth (gets base64 encoded)
|
||||
client = MCPClient(
|
||||
server_url="http://example.com/sse",
|
||||
transport_type="sse",
|
||||
auth_type=MCPAuth.basic,
|
||||
auth_value="user:pass"
|
||||
)
|
||||
headers = client._get_auth_headers()
|
||||
assert headers["Authorization"].startswith("Basic ")
|
||||
|
||||
def test_token_auth_with_extra_headers(self):
|
||||
"""Test that token auth works alongside extra headers"""
|
||||
client = MCPClient(
|
||||
server_url="http://example.com/sse",
|
||||
transport_type="sse",
|
||||
auth_type=MCPAuth.token,
|
||||
auth_value="my-token",
|
||||
extra_headers={"X-Custom-Header": "custom-value"}
|
||||
)
|
||||
|
||||
headers = client._get_auth_headers()
|
||||
|
||||
assert headers["Authorization"] == "token my-token"
|
||||
assert headers["X-Custom-Header"] == "custom-value"
|
||||
|
||||
def test_token_auth_enum_value(self):
|
||||
"""Test that MCPAuth.token enum exists and has correct value"""
|
||||
assert hasattr(MCPAuth, "token")
|
||||
assert MCPAuth.token.value == "token"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__])
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ interface CreateMCPServerProps {
|
|||
onBackToDiscovery?: () => void;
|
||||
}
|
||||
|
||||
const AUTH_TYPES_REQUIRING_AUTH_VALUE = [AUTH_TYPE.API_KEY, AUTH_TYPE.BEARER_TOKEN, AUTH_TYPE.BASIC];
|
||||
const AUTH_TYPES_REQUIRING_AUTH_VALUE = [AUTH_TYPE.API_KEY, AUTH_TYPE.BEARER_TOKEN, AUTH_TYPE.TOKEN, AUTH_TYPE.BASIC];
|
||||
const AUTH_TYPES_REQUIRING_CREDENTIALS = [...AUTH_TYPES_REQUIRING_AUTH_VALUE, AUTH_TYPE.OAUTH2];
|
||||
const CREATE_OAUTH_UI_STATE_KEY = "litellm-mcp-oauth-create-state";
|
||||
|
||||
|
|
@ -654,6 +654,7 @@ const CreateMCPServer: React.FC<CreateMCPServerProps> = ({
|
|||
User keys will be sent as:{" "}
|
||||
<code className="font-mono bg-blue-100 px-1 rounded">
|
||||
{getFieldValue("auth_type") === "bearer_token" && "Authorization: Bearer {key}"}
|
||||
{getFieldValue("auth_type") === "token" && "Authorization: token {key}"}
|
||||
{getFieldValue("auth_type") === "api_key" && "x-api-key: {key}"}
|
||||
{getFieldValue("auth_type") === "basic" && "Authorization: Basic {key}"}
|
||||
{getFieldValue("auth_type") === "authorization" && "Authorization: {key}"}
|
||||
|
|
@ -718,6 +719,7 @@ const CreateMCPServer: React.FC<CreateMCPServerProps> = ({
|
|||
<Select.Option value="none">None</Select.Option>
|
||||
<Select.Option value="api_key">API Key</Select.Option>
|
||||
<Select.Option value="bearer_token">Bearer Token</Select.Option>
|
||||
<Select.Option value="token">Token</Select.Option>
|
||||
<Select.Option value="basic">Basic Auth</Select.Option>
|
||||
<Select.Option value="oauth2">OAuth</Select.Option>
|
||||
</Select>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ interface MCPServerEditProps {
|
|||
availableAccessGroups: string[];
|
||||
}
|
||||
|
||||
const AUTH_TYPES_REQUIRING_AUTH_VALUE = [AUTH_TYPE.API_KEY, AUTH_TYPE.BEARER_TOKEN, AUTH_TYPE.BASIC];
|
||||
const AUTH_TYPES_REQUIRING_AUTH_VALUE = [AUTH_TYPE.API_KEY, AUTH_TYPE.BEARER_TOKEN, AUTH_TYPE.TOKEN, AUTH_TYPE.BASIC];
|
||||
const AUTH_TYPES_REQUIRING_CREDENTIALS = [...AUTH_TYPES_REQUIRING_AUTH_VALUE, AUTH_TYPE.OAUTH2];
|
||||
const EDIT_OAUTH_UI_STATE_KEY = "litellm-mcp-oauth-edit-state";
|
||||
|
||||
|
|
@ -658,6 +658,7 @@ const MCPServerEdit: React.FC<MCPServerEditProps> = ({
|
|||
<Select.Option value="none">None</Select.Option>
|
||||
<Select.Option value="api_key">API Key</Select.Option>
|
||||
<Select.Option value="bearer_token">Bearer Token</Select.Option>
|
||||
<Select.Option value="token">Token</Select.Option>
|
||||
<Select.Option value="basic">Basic Auth</Select.Option>
|
||||
<Select.Option value="oauth2">OAuth</Select.Option>
|
||||
</Select>
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ export const AUTH_TYPE = {
|
|||
NONE: "none",
|
||||
API_KEY: "api_key",
|
||||
BEARER_TOKEN: "bearer_token",
|
||||
TOKEN: "token",
|
||||
BASIC: "basic",
|
||||
OAUTH2: "oauth2",
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue