Skip to content

Commit 2cd7cab

Browse files
fix: add default values to Literal type fields in content types
Content types like TextContent and ImageContent have single-value Literal type fields (e.g., type: Literal["text"]) that now default automatically so users don't have to pass them explicitly. Before: TextContent(type="text", text="hello") After: TextContent(text="hello") Github-Issue: #1731
1 parent f2b89ec commit 2cd7cab

File tree

2 files changed

+68
-9
lines changed

2 files changed

+68
-9
lines changed

src/mcp/types.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ class GetPromptRequest(Request[GetPromptRequestParams, Literal["prompts/get"]]):
10161016
class TextContent(BaseModel):
10171017
"""Text content for a message."""
10181018

1019-
type: Literal["text"]
1019+
type: Literal["text"] = "text"
10201020
text: str
10211021
"""The text content of the message."""
10221022
annotations: Annotations | None = None
@@ -1031,7 +1031,7 @@ class TextContent(BaseModel):
10311031
class ImageContent(BaseModel):
10321032
"""Image content for a message."""
10331033

1034-
type: Literal["image"]
1034+
type: Literal["image"] = "image"
10351035
data: str
10361036
"""The base64-encoded image data."""
10371037
mimeType: str
@@ -1051,7 +1051,7 @@ class ImageContent(BaseModel):
10511051
class AudioContent(BaseModel):
10521052
"""Audio content for a message."""
10531053

1054-
type: Literal["audio"]
1054+
type: Literal["audio"] = "audio"
10551055
data: str
10561056
"""The base64-encoded audio data."""
10571057
mimeType: str
@@ -1077,7 +1077,7 @@ class ToolUseContent(BaseModel):
10771077
in the next user message.
10781078
"""
10791079

1080-
type: Literal["tool_use"]
1080+
type: Literal["tool_use"] = "tool_use"
10811081
"""Discriminator for tool use content."""
10821082

10831083
name: str
@@ -1105,7 +1105,7 @@ class ToolResultContent(BaseModel):
11051105
from the assistant. It contains the output of executing the requested tool.
11061106
"""
11071107

1108-
type: Literal["tool_result"]
1108+
type: Literal["tool_result"] = "tool_result"
11091109
"""Discriminator for tool result content."""
11101110

11111111
toolUseId: str
@@ -1172,7 +1172,7 @@ class EmbeddedResource(BaseModel):
11721172
of the LLM and/or the user.
11731173
"""
11741174

1175-
type: Literal["resource"]
1175+
type: Literal["resource"] = "resource"
11761176
resource: TextResourceContents | BlobResourceContents
11771177
annotations: Annotations | None = None
11781178
meta: dict[str, Any] | None = Field(alias="_meta", default=None)
@@ -1190,7 +1190,7 @@ class ResourceLink(Resource):
11901190
Note: resource links returned by tools are not guaranteed to appear in the results of `resources/list` requests.
11911191
"""
11921192

1193-
type: Literal["resource_link"]
1193+
type: Literal["resource_link"] = "resource_link"
11941194

11951195

11961196
ContentBlock = TextContent | ImageContent | AudioContent | ResourceLink | EmbeddedResource
@@ -1584,7 +1584,7 @@ def content_as_list(self) -> list[SamplingMessageContentBlock]:
15841584
class ResourceTemplateReference(BaseModel):
15851585
"""A reference to a resource or resource template definition."""
15861586

1587-
type: Literal["ref/resource"]
1587+
type: Literal["ref/resource"] = "ref/resource"
15881588
uri: str
15891589
"""The URI or URI template of the resource."""
15901590
model_config = ConfigDict(extra="allow")
@@ -1598,7 +1598,7 @@ class ResourceReference(ResourceTemplateReference):
15981598
class PromptReference(BaseModel):
15991599
"""Identifies a prompt."""
16001600

1601-
type: Literal["ref/prompt"]
1601+
type: Literal["ref/prompt"] = "ref/prompt"
16021602
name: str
16031603
"""The name of the prompt or prompt template"""
16041604
model_config = ConfigDict(extra="allow")

tests/test_types.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,3 +361,62 @@ def test_list_tools_result_preserves_json_schema_2020_12_fields():
361361
assert tool.inputSchema["$schema"] == "https://json-schema.org/draft/2020-12/schema"
362362
assert "$defs" in tool.inputSchema
363363
assert tool.inputSchema["additionalProperties"] is False
364+
365+
366+
def test_content_types_have_default_literal_type_fields():
367+
"""Test that content types default their Literal type fields.
368+
369+
Content types like TextContent have single-value Literal type fields
370+
(e.g., type: Literal["text"]) that should default automatically so users
371+
don't have to pass them explicitly.
372+
373+
Before fix: TextContent(type="text", text="hello") - type required
374+
After fix: TextContent(text="hello") - type defaults to "text"
375+
376+
See: https://github.com/modelcontextprotocol/python-sdk/issues/1731
377+
"""
378+
from mcp.types import (
379+
AudioContent,
380+
EmbeddedResource,
381+
ImageContent,
382+
PromptReference,
383+
ResourceLink,
384+
ResourceTemplateReference,
385+
TextResourceContents,
386+
)
387+
388+
# TextContent should default type to "text"
389+
text_content = TextContent(text="hello")
390+
assert text_content.type == "text"
391+
392+
# ImageContent should default type to "image"
393+
image_content = ImageContent(data="base64data", mimeType="image/png")
394+
assert image_content.type == "image"
395+
396+
# AudioContent should default type to "audio"
397+
audio_content = AudioContent(data="base64data", mimeType="audio/mp3")
398+
assert audio_content.type == "audio"
399+
400+
# ToolUseContent should default type to "tool_use"
401+
tool_use = ToolUseContent(name="my_tool", id="call_123", input={"arg": "value"})
402+
assert tool_use.type == "tool_use"
403+
404+
# ToolResultContent should default type to "tool_result"
405+
tool_result = ToolResultContent(toolUseId="call_123")
406+
assert tool_result.type == "tool_result"
407+
408+
# EmbeddedResource should default type to "resource"
409+
embedded = EmbeddedResource(resource=TextResourceContents(uri="file:///test.txt", text="content"))
410+
assert embedded.type == "resource"
411+
412+
# ResourceLink should default type to "resource_link"
413+
resource_link = ResourceLink(name="test", uri="file:///test.txt")
414+
assert resource_link.type == "resource_link"
415+
416+
# ResourceTemplateReference should default type to "ref/resource"
417+
resource_ref = ResourceTemplateReference(uri="file:///test.txt")
418+
assert resource_ref.type == "ref/resource"
419+
420+
# PromptReference should default type to "ref/prompt"
421+
prompt_ref = PromptReference(name="my_prompt")
422+
assert prompt_ref.type == "ref/prompt"

0 commit comments

Comments
 (0)