Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 101 additions & 101 deletions docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -13506,6 +13506,105 @@
}
]
},
"InputToolMCP": {
"properties": {
"type": {
"type": "string",
"const": "mcp",
"title": "Type",
"default": "mcp"
},
"server_label": {
"type": "string",
"title": "Server Label"
},
"connector_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Connector Id"
},
"server_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Server Url"
},
"headers": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"title": "Headers"
},
"authorization": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Authorization"
},
"require_approval": {
"anyOf": [
{
"type": "string",
"const": "always"
},
{
"type": "string",
"const": "never"
},
{
"$ref": "#/components/schemas/ApprovalFilter"
}
],
"title": "Require Approval",
"default": "never"
},
"allowed_tools": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"$ref": "#/components/schemas/AllowedToolsFilter"
},
{
"type": "null"
}
],
"title": "Allowed Tools"
}
},
"type": "object",
"required": [
"server_label"
],
"title": "InputToolMCP",
"description": "MCP input tool with authorization included when serializing request bodies."
},
"InternalServerErrorResponse": {
"properties": {
"status_code": {
Expand Down Expand Up @@ -15201,105 +15300,6 @@
"title": "OpenAIResponseInputToolFunction",
"description": "Function tool configuration for OpenAI response inputs.\n\n:param type: Tool type identifier, always \"function\"\n:param name: Name of the function that can be called\n:param description: (Optional) Description of what the function does\n:param parameters: (Optional) JSON schema defining the function's parameters\n:param strict: (Optional) Whether to enforce strict parameter validation"
},
"OpenAIResponseInputToolMCP": {
"properties": {
"type": {
"type": "string",
"const": "mcp",
"title": "Type",
"default": "mcp"
},
"server_label": {
"type": "string",
"title": "Server Label"
},
"connector_id": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Connector Id"
},
"server_url": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Server Url"
},
"headers": {
"anyOf": [
{
"additionalProperties": true,
"type": "object"
},
{
"type": "null"
}
],
"title": "Headers"
},
"authorization": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"title": "Authorization"
},
"require_approval": {
"anyOf": [
{
"type": "string",
"const": "always"
},
{
"type": "string",
"const": "never"
},
{
"$ref": "#/components/schemas/ApprovalFilter"
}
],
"title": "Require Approval",
"default": "never"
},
"allowed_tools": {
"anyOf": [
{
"items": {
"type": "string"
},
"type": "array"
},
{
"$ref": "#/components/schemas/AllowedToolsFilter"
},
{
"type": "null"
}
],
"title": "Allowed Tools"
}
},
"type": "object",
"required": [
"server_label"
],
"title": "OpenAIResponseInputToolMCP",
"description": "Model Context Protocol (MCP) tool configuration for OpenAI response inputs.\n\n:param type: Tool type identifier, always \"mcp\"\n:param server_label: Label to identify this MCP server\n:param connector_id: (Optional) ID of the connector to use for this MCP server\n:param server_url: (Optional) URL endpoint of the MCP server\n:param headers: (Optional) HTTP headers to include when connecting to the server\n:param authorization: (Optional) OAuth access token for authenticating with the MCP server\n:param require_approval: Approval requirement for tool calls (\"always\", \"never\", or filter)\n:param allowed_tools: (Optional) Restriction on which tools can be used from this server"
},
"OpenAIResponseInputToolWebSearch": {
"properties": {
"type": {
Expand Down Expand Up @@ -18082,15 +18082,15 @@
"$ref": "#/components/schemas/OpenAIResponseInputToolFunction"
},
{
"$ref": "#/components/schemas/OpenAIResponseInputToolMCP"
"$ref": "#/components/schemas/InputToolMCP"
}
],
"discriminator": {
"propertyName": "type",
"mapping": {
"file_search": "#/components/schemas/OpenAIResponseInputToolFileSearch",
"function": "#/components/schemas/OpenAIResponseInputToolFunction",
"mcp": "#/components/schemas/OpenAIResponseInputToolMCP",
"mcp": "#/components/schemas/InputToolMCP",
"web_search": "#/components/schemas/OpenAIResponseInputToolWebSearch",
"web_search_2025_08_26": "#/components/schemas/OpenAIResponseInputToolWebSearch",
"web_search_preview": "#/components/schemas/OpenAIResponseInputToolWebSearch",
Expand Down
7 changes: 1 addition & 6 deletions src/app/endpoints/responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -455,12 +455,7 @@ async def responses_endpoint_handler(
original_request.input, inline_rag_context.context_text
)

api_params = ResponsesApiParams.model_validate(
{
**updated_request.model_dump(exclude={"tools"}),
"tools": updated_request.tools,
}
)
api_params = ResponsesApiParams.model_validate(updated_request.model_dump())
context = ResponsesContext(
client=client,
auth=auth,
Expand Down
5 changes: 1 addition & 4 deletions src/models/api/requests/responses_openai.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
import json
from typing import Any, Optional, Self

from llama_stack_api.openai_responses import (
OpenAIResponseInputTool as InputTool,
)
from llama_stack_api.openai_responses import (
OpenAIResponseInputToolChoice as ToolChoice,
)
Expand All @@ -22,7 +19,7 @@

from constants import RESPONSES_REQUEST_MAX_SIZE
from models.common.query import SolrVectorSearchRequest
from models.common.responses.types import IncludeParameter, ResponseInput
from models.common.responses.types import IncludeParameter, InputTool, ResponseInput
from utils import suid


Expand Down
4 changes: 4 additions & 0 deletions src/models/common/responses/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
)
from models.common.responses.types import (
IncludeParameter,
InputTool,
InputToolMCP,
ResponseInput,
ResponseItem,
)
Expand All @@ -15,6 +17,8 @@
"ResponseInput",
"ResponseItem",
"IncludeParameter",
"InputTool",
"InputToolMCP",
"ResponsesApiParams",
"ResponsesContext",
"ResponsesConversationContext",
Expand Down
27 changes: 6 additions & 21 deletions src/models/common/responses/responses_api_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
from collections.abc import Mapping
from typing import Any, Final, Optional

from llama_stack_api.openai_responses import (
OpenAIResponseInputTool as InputTool,
)
from llama_stack_api.openai_responses import (
OpenAIResponseInputToolChoice as ToolChoice,
)
Expand All @@ -23,7 +20,7 @@
)
from pydantic import BaseModel, Field

from models.common.responses.types import IncludeParameter, ResponseInput
from models.common.responses.types import IncludeParameter, InputTool, ResponseInput
from utils.tool_formatter import translate_vector_store_ids_to_user_facing

# Attribute names that are echoed back in the response.
Expand Down Expand Up @@ -126,28 +123,16 @@ class ResponsesApiParams(BaseModel):
)

def model_dump(self, *args: Any, **kwargs: Any) -> dict[str, Any]:
"""Serialize params, re-injecting MCP authorization stripped by exclude=True.
"""Serialize to a request body dict.

llama-stack-api marks ``InputToolMCP.authorization`` with
``Field(exclude=True)`` to prevent token leakage in API responses.
The base ``model_dump()`` therefore strips the field, but we need it
in the request payload so llama-stack server can authenticate with
MCP servers. See LCORE-1414 / GitHub issue #1269.
Omits conversation when previous_response_id is set.

Returns:
Serializable dict for the Responses API request body.
"""
result = super().model_dump(*args, **kwargs)
# Only one context option is allowed, previous_response_id has priority
# Turn is added to conversation manually if previous_response_id is used
if self.previous_response_id:
result.pop("conversation", None)
dumped_tools = result.get("tools")
if not self.tools or not isinstance(dumped_tools, list):
return result
if len(dumped_tools) != len(self.tools):
return result
for tool, dumped_tool in zip(self.tools, dumped_tools):
authorization = getattr(tool, "authorization", None)
if authorization is not None and isinstance(dumped_tool, dict):
dumped_tool["authorization"] = authorization
Copy link
Copy Markdown
Contributor Author

@asimurka asimurka May 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessary as we override authorization attribute locally so that it is not dropped anymore.

return result

def echoed_params(self, rag_id_mapping: Mapping[str, str]) -> dict[str, Any]:
Expand Down
25 changes: 24 additions & 1 deletion src/models/common/responses/types.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
"""Type aliases for OpenAI-compatible Responses API input shapes."""

from typing import Literal
from typing import Annotated, Literal

from llama_stack_api.openai_responses import (
OpenAIResponseInputFunctionToolCallOutput as FunctionToolCallOutput,
)
from llama_stack_api.openai_responses import (
OpenAIResponseInputToolFileSearch as InputToolFileSearch,
)
from llama_stack_api.openai_responses import (
OpenAIResponseInputToolFunction as InputToolFunction,
)
from llama_stack_api.openai_responses import OpenAIResponseInputToolMCP
from llama_stack_api.openai_responses import (
OpenAIResponseInputToolWebSearch as InputToolWebSearch,
)
from llama_stack_api.openai_responses import (
OpenAIResponseMCPApprovalRequest as McpApprovalRequest,
)
Expand All @@ -29,6 +39,19 @@
from llama_stack_api.openai_responses import (
OpenAIResponseOutputMessageWebSearchToolCall as WebSearchToolCall,
)
from pydantic import Field


class InputToolMCP(OpenAIResponseInputToolMCP):
"""MCP input tool with authorization included when serializing request bodies."""

authorization: str | None = None
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Override locally so that the attribute is not dropped when model is dumped



InputTool = Annotated[
InputToolWebSearch | InputToolFileSearch | InputToolFunction | InputToolMCP,
Field(discriminator="type"),
]

type IncludeParameter = Literal[
"web_search_call.action.sources",
Expand Down
Loading
Loading