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:
yuneng-jiang 2026-03-10 09:57:21 -07:00 committed by GitHub
commit b02ecc7807
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 79 additions and 3 deletions

View file

@ -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)

View file

@ -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.
#

View file

@ -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,
]
]

View file

@ -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__])

View 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>

View file

@ -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>

View file

@ -9,6 +9,7 @@ export const AUTH_TYPE = {
NONE: "none",
API_KEY: "api_key",
BEARER_TOKEN: "bearer_token",
TOKEN: "token",
BASIC: "basic",
OAUTH2: "oauth2",
};