Skip to content

Commit 152c562

Browse files
Add dedicated 'Parsing Tool Results' section to documentation
- Add new section under Advanced Usage for parsing CallToolResult objects - Create comprehensive example showing all content types (text, structured, embedded resources, images, errors) - Move parsing documentation to a dedicated section instead of inline examples - Improve discoverability and clarity of tool result parsing patterns
1 parent e896ce2 commit 152c562

File tree

2 files changed

+149
-6
lines changed

2 files changed

+149
-6
lines changed

README.md

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
- [Advanced Usage](#advanced-usage)
4242
- [Low-Level Server](#low-level-server)
4343
- [Writing MCP Clients](#writing-mcp-clients)
44+
- [Parsing Tool Results](#parsing-tool-results)
4445
- [MCP Primitives](#mcp-primitives)
4546
- [Server Capabilities](#server-capabilities)
4647
- [Documentation](#documentation)
@@ -787,12 +788,18 @@ async def run():
787788
elif isinstance(item, types.EmbeddedResource):
788789
# Check if the embedded resource contains text
789790
if isinstance(item.resource, types.TextResourceContents):
790-
print(f"Tool output (EmbeddedResource - Text): {item.resource.text}")
791+
print(
792+
f"Tool output (EmbeddedResource - Text): {item.resource.text}"
793+
)
791794
elif isinstance(item.resource, types.BlobResourceContents):
792-
print(f"Tool output (EmbeddedResource - Blob): URI {item.resource.uri}, MIME Type {item.resource.mimeType}")
795+
print(
796+
f"Tool output (EmbeddedResource - Blob): URI {item.resource.uri}, MIME Type {item.resource.mimeType}"
797+
)
793798
elif isinstance(item, types.ImageContent):
794799
# Showing only a snippet of image data
795-
print(f"Tool output (ImageContent): MIME Type {item.mimeType}, Data (base64): {item.data[:30]}...")
800+
print(
801+
f"Tool output (ImageContent): MIME Type {item.mimeType}, Data (base64): {item.data[:30]}..."
802+
)
796803
else:
797804
print(f"Tool output (Unknown Content Type): {type(item)}")
798805

@@ -831,12 +838,18 @@ async def main():
831838
elif isinstance(item, types.EmbeddedResource):
832839
# Check if the embedded resource contains text
833840
if isinstance(item.resource, types.TextResourceContents):
834-
print(f"Tool output (EmbeddedResource - Text): {item.resource.text}")
841+
print(
842+
f"Tool output (EmbeddedResource - Text): {item.resource.text}"
843+
)
835844
elif isinstance(item.resource, types.BlobResourceContents):
836-
print(f"Tool output (EmbeddedResource - Blob): URI {item.resource.uri}, MIME Type {item.resource.mimeType}")
845+
print(
846+
f"Tool output (EmbeddedResource - Blob): URI {item.resource.uri}, MIME Type {item.resource.mimeType}"
847+
)
837848
elif isinstance(item, types.ImageContent):
838849
# Showing only a snippet of image data
839-
print(f"Tool output (ImageContent): MIME Type {item.mimeType}, Data (base64): {item.data[:30]}...")
850+
print(
851+
f"Tool output (ImageContent): MIME Type {item.mimeType}, Data (base64): {item.data[:30]}..."
852+
)
840853
else:
841854
print(f"Tool output (Unknown Content Type): {type(item)}")
842855
```
@@ -894,6 +907,74 @@ async def main():
894907

895908
For a complete working example, see [`examples/clients/simple-auth-client/`](examples/clients/simple-auth-client/).
896909

910+
### Parsing Tool Results
911+
912+
When calling tools through MCP, the `CallToolResult` object contains the tool's response in a structured format. Understanding how to parse this result is essential for properly handling tool outputs.
913+
914+
```python
915+
"""examples/snippets/clients/parsing_tool_results.py"""
916+
917+
import asyncio
918+
919+
from mcp import ClientSession, StdioServerParameters, types
920+
from mcp.client.stdio import stdio_client
921+
922+
923+
async def parse_tool_results():
924+
"""Demonstrates how to parse different types of content in CallToolResult."""
925+
server_params = StdioServerParameters(
926+
command="python", args=["path/to/mcp_server.py"]
927+
)
928+
929+
async with stdio_client(server_params) as (read, write):
930+
async with ClientSession(read, write) as session:
931+
await session.initialize()
932+
933+
# Example 1: Parsing text content
934+
result = await session.call_tool("get_data", {"format": "text"})
935+
for content in result.content:
936+
if isinstance(content, types.TextContent):
937+
print(f"Text: {content.text}")
938+
939+
# Example 2: Parsing structured content from JSON tools
940+
result = await session.call_tool("get_user", {"id": "123"})
941+
if hasattr(result, "structuredContent") and result.structuredContent:
942+
# Access structured data directly
943+
user_data = result.structuredContent
944+
print(f"User: {user_data.get('name')}, Age: {user_data.get('age')}")
945+
946+
# Example 3: Parsing embedded resources
947+
result = await session.call_tool("read_config", {})
948+
for content in result.content:
949+
if isinstance(content, types.EmbeddedResource):
950+
resource = content.resource
951+
if isinstance(resource, types.TextResourceContents):
952+
print(f"Config from {resource.uri}: {resource.text}")
953+
elif isinstance(resource, types.BlobResourceContents):
954+
print(f"Binary data from {resource.uri}")
955+
956+
# Example 4: Parsing image content
957+
result = await session.call_tool("generate_chart", {"data": [1, 2, 3]})
958+
for content in result.content:
959+
if isinstance(content, types.ImageContent):
960+
print(f"Image ({content.mimeType}): {len(content.data)} bytes")
961+
962+
# Example 5: Handling errors
963+
result = await session.call_tool("failing_tool", {})
964+
if result.isError:
965+
print("Tool execution failed!")
966+
for content in result.content:
967+
if isinstance(content, types.TextContent):
968+
print(f"Error: {content.text}")
969+
970+
971+
async def main():
972+
await parse_tool_results()
973+
974+
975+
if __name__ == "__main__":
976+
asyncio.run(main())
977+
```
897978

898979
### MCP Primitives
899980

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
"""examples/snippets/clients/parsing_tool_results.py"""
2+
3+
import asyncio
4+
5+
from mcp import ClientSession, StdioServerParameters, types
6+
from mcp.client.stdio import stdio_client
7+
8+
9+
async def parse_tool_results():
10+
"""Demonstrates how to parse different types of content in CallToolResult."""
11+
server_params = StdioServerParameters(
12+
command="python", args=["path/to/mcp_server.py"]
13+
)
14+
15+
async with stdio_client(server_params) as (read, write):
16+
async with ClientSession(read, write) as session:
17+
await session.initialize()
18+
19+
# Example 1: Parsing text content
20+
result = await session.call_tool("get_data", {"format": "text"})
21+
for content in result.content:
22+
if isinstance(content, types.TextContent):
23+
print(f"Text: {content.text}")
24+
25+
# Example 2: Parsing structured content from JSON tools
26+
result = await session.call_tool("get_user", {"id": "123"})
27+
if hasattr(result, "structuredContent") and result.structuredContent:
28+
# Access structured data directly
29+
user_data = result.structuredContent
30+
print(f"User: {user_data.get('name')}, Age: {user_data.get('age')}")
31+
32+
# Example 3: Parsing embedded resources
33+
result = await session.call_tool("read_config", {})
34+
for content in result.content:
35+
if isinstance(content, types.EmbeddedResource):
36+
resource = content.resource
37+
if isinstance(resource, types.TextResourceContents):
38+
print(f"Config from {resource.uri}: {resource.text}")
39+
elif isinstance(resource, types.BlobResourceContents):
40+
print(f"Binary data from {resource.uri}")
41+
42+
# Example 4: Parsing image content
43+
result = await session.call_tool("generate_chart", {"data": [1, 2, 3]})
44+
for content in result.content:
45+
if isinstance(content, types.ImageContent):
46+
print(f"Image ({content.mimeType}): {len(content.data)} bytes")
47+
48+
# Example 5: Handling errors
49+
result = await session.call_tool("failing_tool", {})
50+
if result.isError:
51+
print("Tool execution failed!")
52+
for content in result.content:
53+
if isinstance(content, types.TextContent):
54+
print(f"Error: {content.text}")
55+
56+
57+
async def main():
58+
await parse_tool_results()
59+
60+
61+
if __name__ == "__main__":
62+
asyncio.run(main())

0 commit comments

Comments
 (0)