Skip to content

Commit a743270

Browse files
authored
Merge pull request #1043 from blublinsky/noop-with-token
Adding noop-with-token to allow k8 authentication for MCP servers
2 parents 6de3909 + 27b16a1 commit a743270

5 files changed

Lines changed: 39 additions & 14 deletions

File tree

src/app/endpoints/mcp_auth.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
from fastapi import APIRouter, Depends, Request
77

8+
import constants
89
from authentication import get_auth_dependency
910
from authentication.interface import AuthTuple
1011
from authorization.middleware import authorize
@@ -77,7 +78,7 @@ async def get_mcp_client_auth_options(
7778
client_headers = [
7879
header_name
7980
for header_name, header_value in mcp_server.authorization_headers.items()
80-
if header_value.strip() == "client"
81+
if header_value.strip() == constants.MCP_AUTH_CLIENT
8182
]
8283

8384
if client_headers:

src/app/endpoints/query_v2.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
)
2121
from llama_stack_client import AsyncLlamaStackClient
2222

23+
import constants
2324
import metrics
2425
from app.endpoints.query import (
2526
query_endpoint_handler_base,
@@ -782,12 +783,12 @@ def get_mcp_tools(
782783
def _get_token_value(original: str, header: str) -> str | None:
783784
"""Convert to header value."""
784785
match original:
785-
case "kubernetes":
786+
case constants.MCP_AUTH_KUBERNETES:
786787
# use k8s token
787788
if token is None or token == "":
788789
return None
789790
return f"Bearer {token}"
790-
case "client":
791+
case constants.MCP_AUTH_CLIENT:
791792
# use client provided token
792793
if mcp_headers is None:
793794
return None

src/constants.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@
122122
DEFAULT_JWT_UID_CLAIM = "user_id"
123123
DEFAULT_JWT_USER_NAME_CLAIM = "username"
124124

125+
# MCP authorization header special values
126+
MCP_AUTH_KUBERNETES = "kubernetes"
127+
MCP_AUTH_CLIENT = "client"
128+
125129
# default RAG tool value
126130
DEFAULT_RAG_TOOL = "knowledge_search"
127131

src/models/config.py

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,8 +1665,12 @@ def validate_mcp_auth_headers(self) -> Self:
16651665
Validate MCP server authorization headers against authentication module.
16661666
16671667
Removes any MCP server with authorization_headers="kubernetes" when the
1668-
authentication module is not "k8s". This prevents sending wrong credential
1669-
types to MCP servers.
1668+
authentication module is not "k8s" or "noop-with-token". This prevents sending
1669+
wrong credential types to MCP servers.
1670+
1671+
Note: "noop-with-token" should only be used for testing/development purposes.
1672+
When using "noop-with-token" with kubernetes authorization headers, a real
1673+
Kubernetes token must still be passed in the request headers.
16701674
16711675
Returns:
16721676
Self: The model instance after validation.
@@ -1680,15 +1684,28 @@ def validate_mcp_auth_headers(self) -> Self:
16801684
is_valid = True
16811685
if mcp_server.authorization_headers:
16821686
for value in mcp_server.authorization_headers.values():
1683-
if value.strip() == "kubernetes" and auth_module != "k8s":
1687+
if (
1688+
value.strip() == constants.MCP_AUTH_KUBERNETES
1689+
and auth_module
1690+
not in [
1691+
constants.AUTH_MOD_K8S,
1692+
constants.AUTH_MOD_NOOP_WITH_TOKEN,
1693+
]
1694+
):
16841695
logger.warning(
16851696
"Removing MCP server '%s': has authorization_headers with "
1686-
"value 'kubernetes' but authentication module is '%s' "
1687-
"(not 'k8s'). Either change authentication.module to 'k8s' "
1688-
"or update the MCP server's authorization_headers to use a "
1689-
"file path or 'client'.",
1697+
"value '%s' but authentication module is '%s' "
1698+
"(not '%s' or '%s'). Either change authentication.module to "
1699+
"'%s' or '%s' or update the MCP server's authorization_headers "
1700+
"to use a file path or '%s'.",
16901701
mcp_server.name,
1702+
constants.MCP_AUTH_KUBERNETES,
16911703
auth_module,
1704+
constants.AUTH_MOD_K8S,
1705+
constants.AUTH_MOD_NOOP_WITH_TOKEN,
1706+
constants.AUTH_MOD_K8S,
1707+
constants.AUTH_MOD_NOOP_WITH_TOKEN,
1708+
constants.MCP_AUTH_CLIENT,
16921709
)
16931710
is_valid = False
16941711
break

src/utils/mcp_auth_headers.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import logging
44
from pathlib import Path
55

6+
import constants
7+
68
logger = logging.getLogger(__name__)
79

810

@@ -39,16 +41,16 @@ def resolve_authorization_headers(
3941
for header_name, value in authorization_headers.items():
4042
value = value.strip()
4143
try:
42-
if value == "kubernetes":
44+
if value == constants.MCP_AUTH_KUBERNETES:
4345
# Special case: Keep kubernetes keyword for later substitution
44-
resolved[header_name] = "kubernetes"
46+
resolved[header_name] = constants.MCP_AUTH_KUBERNETES
4547
logger.debug(
4648
"Header %s will use Kubernetes token (resolved at request time)",
4749
header_name,
4850
)
49-
elif value == "client":
51+
elif value == constants.MCP_AUTH_CLIENT:
5052
# Special case: Keep client keyword for later substitution
51-
resolved[header_name] = "client"
53+
resolved[header_name] = constants.MCP_AUTH_CLIENT
5254
logger.debug(
5355
"Header %s will use client-provided token (resolved at request time)",
5456
header_name,

0 commit comments

Comments
 (0)