feat: adding tool annotation used by MCP

This commit is contained in:
Lance Galletti 2025-06-23 10:56:08 -04:00
parent 51b179e1c5
commit 7123e9723c
9 changed files with 168 additions and 0 deletions

View file

@ -5588,6 +5588,28 @@
"additionalProperties": { "additionalProperties": {
"$ref": "#/components/schemas/ToolParamDefinition" "$ref": "#/components/schemas/ToolParamDefinition"
} }
},
"annotations": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"read_only_hint": {
"type": "boolean"
},
"destructive_hint": {
"type": "boolean"
},
"idempotent_hint": {
"type": "boolean"
},
"open_world_hint": {
"type": "boolean"
}
},
"additionalProperties": false,
"title": "ToolAnnotations"
} }
}, },
"additionalProperties": false, "additionalProperties": false,
@ -6488,6 +6510,28 @@
} }
] ]
} }
},
"annotations": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"read_only_hint": {
"type": "boolean"
},
"destructive_hint": {
"type": "boolean"
},
"idempotent_hint": {
"type": "boolean"
},
"open_world_hint": {
"type": "boolean"
}
},
"additionalProperties": false,
"title": "ToolAnnotations"
} }
}, },
"additionalProperties": false, "additionalProperties": false,
@ -8502,6 +8546,28 @@
}, },
"description": { "description": {
"type": "string" "type": "string"
},
"annotations": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"read_only_hint": {
"type": "boolean"
},
"destructive_hint": {
"type": "boolean"
},
"idempotent_hint": {
"type": "boolean"
},
"open_world_hint": {
"type": "boolean"
}
},
"additionalProperties": false,
"title": "ToolAnnotations"
} }
}, },
"additionalProperties": false, "additionalProperties": false,
@ -11027,6 +11093,28 @@
} }
] ]
} }
},
"annotations": {
"type": "object",
"properties": {
"title": {
"type": "string"
},
"read_only_hint": {
"type": "boolean"
},
"destructive_hint": {
"type": "boolean"
},
"idempotent_hint": {
"type": "boolean"
},
"open_world_hint": {
"type": "boolean"
}
},
"additionalProperties": false,
"title": "ToolAnnotations"
} }
}, },
"additionalProperties": false, "additionalProperties": false,

View file

@ -3940,6 +3940,21 @@ components:
type: object type: object
additionalProperties: additionalProperties:
$ref: '#/components/schemas/ToolParamDefinition' $ref: '#/components/schemas/ToolParamDefinition'
annotations:
type: object
properties:
title:
type: string
read_only_hint:
type: boolean
destructive_hint:
type: boolean
idempotent_hint:
type: boolean
open_world_hint:
type: boolean
additionalProperties: false
title: ToolAnnotations
additionalProperties: false additionalProperties: false
required: required:
- tool_name - tool_name
@ -4638,6 +4653,21 @@ components:
- type: string - type: string
- type: array - type: array
- type: object - type: object
annotations:
type: object
properties:
title:
type: string
read_only_hint:
type: boolean
destructive_hint:
type: boolean
idempotent_hint:
type: boolean
open_world_hint:
type: boolean
additionalProperties: false
title: ToolAnnotations
additionalProperties: false additionalProperties: false
required: required:
- name - name
@ -5990,6 +6020,21 @@ components:
type: string type: string
description: description:
type: string type: string
annotations:
type: object
properties:
title:
type: string
read_only_hint:
type: boolean
destructive_hint:
type: boolean
idempotent_hint:
type: boolean
open_world_hint:
type: boolean
additionalProperties: false
title: ToolAnnotations
additionalProperties: false additionalProperties: false
required: required:
- input_schema - input_schema
@ -7768,6 +7813,21 @@ components:
- type: string - type: string
- type: array - type: array
- type: object - type: object
annotations:
type: object
properties:
title:
type: string
read_only_hint:
type: boolean
destructive_hint:
type: boolean
idempotent_hint:
type: boolean
open_world_hint:
type: boolean
additionalProperties: false
title: ToolAnnotations
additionalProperties: false additionalProperties: false
required: required:
- identifier - identifier

View file

@ -10,6 +10,7 @@ from pydantic import BaseModel, Field
from typing_extensions import TypedDict from typing_extensions import TypedDict
from llama_stack.apis.vector_io import SearchRankingOptions as FileSearchRankingOptions from llama_stack.apis.vector_io import SearchRankingOptions as FileSearchRankingOptions
from llama_stack.models.llama.datatypes import ToolAnnotations
from llama_stack.schema_utils import json_schema_type, register_schema from llama_stack.schema_utils import json_schema_type, register_schema
# NOTE(ashwin): this file is literally a copy of the OpenAI responses API schema. We should probably # NOTE(ashwin): this file is literally a copy of the OpenAI responses API schema. We should probably
@ -161,6 +162,7 @@ class MCPListToolsTool(BaseModel):
input_schema: dict[str, Any] input_schema: dict[str, Any]
name: str name: str
description: str | None = None description: str | None = None
annotations: ToolAnnotations | None = None
@json_schema_type @json_schema_type

View file

@ -12,6 +12,7 @@ from typing_extensions import runtime_checkable
from llama_stack.apis.common.content_types import URL, InterleavedContent from llama_stack.apis.common.content_types import URL, InterleavedContent
from llama_stack.apis.resource import Resource, ResourceType from llama_stack.apis.resource import Resource, ResourceType
from llama_stack.models.llama.datatypes import ToolAnnotations
from llama_stack.providers.utils.telemetry.trace_protocol import trace_protocol from llama_stack.providers.utils.telemetry.trace_protocol import trace_protocol
from llama_stack.schema_utils import json_schema_type, webmethod from llama_stack.schema_utils import json_schema_type, webmethod
@ -34,6 +35,7 @@ class Tool(Resource):
description: str description: str
parameters: list[ToolParameter] parameters: list[ToolParameter]
metadata: dict[str, Any] | None = None metadata: dict[str, Any] | None = None
annotations: ToolAnnotations | None = None
@json_schema_type @json_schema_type
@ -42,6 +44,7 @@ class ToolDef(BaseModel):
description: str | None = None description: str | None = None
parameters: list[ToolParameter] | None = None parameters: list[ToolParameter] | None = None
metadata: dict[str, Any] | None = None metadata: dict[str, Any] | None = None
annotations: ToolAnnotations | None = None
@json_schema_type @json_schema_type

View file

@ -74,6 +74,7 @@ class ToolGroupsRoutingTable(CommonRoutingTableImpl, ToolGroups):
parameters=t.parameters or [], parameters=t.parameters or [],
metadata=t.metadata, metadata=t.metadata,
provider_id=toolgroup.provider_id, provider_id=toolgroup.provider_id,
annotations=t.annotations,
) )
) )

View file

@ -95,10 +95,19 @@ class ToolParamDefinition(BaseModel):
default: Any | None = None default: Any | None = None
class ToolAnnotations(BaseModel):
title: str | None = None
read_only_hint: bool | None = Field(default=None, alias="readOnlyHint")
destructive_hint: bool | None = Field(default=None, alias="destructiveHint")
idempotent_hint: bool | None = Field(default=None, alias="idempotentHint")
open_world_hint: bool | None = Field(default=None, alias="openWorldHint")
class ToolDefinition(BaseModel): class ToolDefinition(BaseModel):
tool_name: BuiltinTool | str tool_name: BuiltinTool | str
description: str | None = None description: str | None = None
parameters: dict[str, ToolParamDefinition] | None = None parameters: dict[str, ToolParamDefinition] | None = None
annotations: ToolAnnotations | None = None
@field_validator("tool_name", mode="before") @field_validator("tool_name", mode="before")
@classmethod @classmethod

View file

@ -800,6 +800,7 @@ class ChatAgent(ShieldRunnerMixin):
) )
for param in tool_def.parameters for param in tool_def.parameters
}, },
annotations=tool_def.annotations,
) )
for toolgroup_name_with_maybe_tool_name in agent_config_toolgroups: for toolgroup_name_with_maybe_tool_name in agent_config_toolgroups:
toolgroup_name, input_tool_name = self._parse_toolgroup_name(toolgroup_name_with_maybe_tool_name) toolgroup_name, input_tool_name = self._parse_toolgroup_name(toolgroup_name_with_maybe_tool_name)
@ -843,6 +844,7 @@ class ChatAgent(ShieldRunnerMixin):
) )
for param in tool_def.parameters for param in tool_def.parameters
}, },
annotations=tool_def.annotations,
) )
tool_name_to_args[tool_def.identifier] = toolgroup_to_args.get(toolgroup_name, {}) tool_name_to_args[tool_def.identifier] = toolgroup_to_args.get(toolgroup_name, {})

View file

@ -671,6 +671,7 @@ class OpenAIResponsesImpl:
}, },
"required": [p.name for p in t.parameters if p.required], "required": [p.name for p in t.parameters if p.required],
}, },
annotations=t.annotations,
) )
) )
else: else:

View file

@ -57,6 +57,7 @@ async def list_mcp_tools(endpoint: str, headers: dict[str, str]) -> ListToolDefs
description=param_schema.get("description", ""), description=param_schema.get("description", ""),
) )
) )
annotations = getattr(tool, "annotations", None)
tools.append( tools.append(
ToolDef( ToolDef(
name=tool.name, name=tool.name,
@ -65,6 +66,7 @@ async def list_mcp_tools(endpoint: str, headers: dict[str, str]) -> ListToolDefs
metadata={ metadata={
"endpoint": endpoint, "endpoint": endpoint,
}, },
annotations=annotations,
) )
) )
return ListToolDefsResponse(data=tools) return ListToolDefsResponse(data=tools)