-
Notifications
You must be signed in to change notification settings - Fork 76
Description
Bug Description
I'm running the server from master and it seem like lightspeed-stack is not sending the Authorization header to llama-stack.
This is my MCP configuration in lightspeed-stack.yaml:
mcp_servers:
- name: rhos-osp-tools
url: http://127.0.0.1:8901/openstack/
authorization_headers:
Authorization: "${env.PWD}/lightspeed-stack/mcp-auth-token"
- name: rhos-ocp-tools
url: http://127.0.0.1:8901/openshift/
authorization_headers:
Authorization: "${env.PWD}/lightspeed-stack/mcp-auth-token"In llama-stack I have:
tool_runtime:
- config: {} # Enable the RAG tool
provider_id: rag-runtime
provider_type: inline::rag-runtime
- provider_id: model-context-protocol
provider_type: remote::model-context-protocol
config: {}On the client I see this:
$ curl -s -X POST http://localhost:8080/v1/query -H "Content-Type: application/json" -d '{"query": "How do I launch an instance in OpenStack?"}'
{"detail":{"response":"Internal server error","cause":"An unexpected error occurred while processing the request."}}
On lighspeed-stack I see:
[18:46:28] INFO HTTP Request: POST http://localhost:8321/v1/responses "HTTP/1.1 401 Unauthorized" _client.py:1740
INFO: 127.0.0.1:53008 - "POST /v1/query HTTP/1.1" 500 Internal Server Error
On the llama-stack side we can see the MCP call to list the tools fails with:
AuthenticationRequiredError: Client error '401 Unauthorized' for url 'http://127.0.0.1:8901/openstack/'
For more information check: https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401
INFO 2026-03-04 18:46:28,298 uvicorn.access:480 uncategorized: ::1:55450 - "POST /v1/responses HTTP/1.1" 401
I don't know what was different the other day, but it was working.
My debugging
If we debug what llama-stack is going to send to the MCP server we can see there are no headers:
> /home/geguileo/work/lightspeed/lightspeed-stack/.venv/lib64/python3.13/site-packages/llama_stack/providers/utils/tools/mcp.py(143)get_session()
-> import pdb; pdb.set_trace()
(Pdb) l
138 if key in self._sessions:
139 session, _, _ = self._sessions[key]
140 return session
141
142 # Create new session
143 -> import pdb; pdb.set_trace()
144 session, client_ctx, session_ctx = await self._create_session(endpoint, headers)
145 self._sessions[key] = (session, client_ctx, session_ctx)
146 logger.debug(f"Created new MCP session for {endpoint} (key: {key[:32]}...)")
147 return session
148
(Pdb) pp headers
{}
On the lighspeed stack side we can see in src/app/endpoints/query.py in method retrieve_response we have:
303 response = await client.responses.create(
304 **responses_params.model_dump(exclude_none=True)
305 )
But if we check what the dump returns we can see that the authorization is missing:
(Pdb) pp responses_params.model_dump(exclude_none=True)
< blah blah blah >
'tools': [{'max_num_results': 10,
'type': 'file_search',
'vector_store_ids': ['rhoso_18.0']},
{'require_approval': 'never',
'server_label': 'rhos-osp-tools',
'server_url': 'http://127.0.0.1:8901/openstack/',
'type': 'mcp'},
{'require_approval': 'never',
'server_label': 'rhos-ocp-tools',
'server_url': 'http://127.0.0.1:8901/openshift/',
'type': 'mcp'}]}
We can see in llama-stack's src/llama_stack_api/openai_responses.py the caseu: authorization field is explicitly excluded from the dump:
@json_schema_type
class OpenAIResponseInputToolMCP(BaseModel):
authorization: str | None = Field(default=None, exclude=True)
Potential fix
I tried to forcefully include the authorization in the dump, and it worked.
In file src/utils/types.py I modify the ResponsesApiParams class:
class ResponsesApiParams(BaseModel):
def model_dump(self, *args, **kwargs):
result = super().model_dump(*args, **kwargs)
if self.tools:
for i, tool in enumerate(self.tools):
if getattr(tool, "authorization", None):
result["tools"][i]["authorization"] = tool.authorization
return result