Skip to content

Commit 92e082b

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 4b8f558 commit 92e082b

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
@@ -44,6 +44,7 @@
4444
- [Advanced Usage](#advanced-usage)
4545
- [Low-Level Server](#low-level-server)
4646
- [Writing MCP Clients](#writing-mcp-clients)
47+
- [Parsing Tool Results](#parsing-tool-results)
4748
- [MCP Primitives](#mcp-primitives)
4849
- [Server Capabilities](#server-capabilities)
4950
- [Documentation](#documentation)
@@ -1418,12 +1419,18 @@ async def run():
14181419
elif isinstance(item, types.EmbeddedResource):
14191420
# Check if the embedded resource contains text
14201421
if isinstance(item.resource, types.TextResourceContents):
1421-
print(f"Tool output (EmbeddedResource - Text): {item.resource.text}")
1422+
print(
1423+
f"Tool output (EmbeddedResource - Text): {item.resource.text}"
1424+
)
14221425
elif isinstance(item.resource, types.BlobResourceContents):
1423-
print(f"Tool output (EmbeddedResource - Blob): URI {item.resource.uri}, MIME Type {item.resource.mimeType}")
1426+
print(
1427+
f"Tool output (EmbeddedResource - Blob): URI {item.resource.uri}, MIME Type {item.resource.mimeType}"
1428+
)
14241429
elif isinstance(item, types.ImageContent):
14251430
# Showing only a snippet of image data
1426-
print(f"Tool output (ImageContent): MIME Type {item.mimeType}, Data (base64): {item.data[:30]}...")
1431+
print(
1432+
f"Tool output (ImageContent): MIME Type {item.mimeType}, Data (base64): {item.data[:30]}..."
1433+
)
14271434
else:
14281435
print(f"Tool output (Unknown Content Type): {type(item)}")
14291436

@@ -1480,12 +1487,18 @@ async def main():
14801487
elif isinstance(item, types.EmbeddedResource):
14811488
# Check if the embedded resource contains text
14821489
if isinstance(item.resource, types.TextResourceContents):
1483-
print(f"Tool output (EmbeddedResource - Text): {item.resource.text}")
1490+
print(
1491+
f"Tool output (EmbeddedResource - Text): {item.resource.text}"
1492+
)
14841493
elif isinstance(item.resource, types.BlobResourceContents):
1485-
print(f"Tool output (EmbeddedResource - Blob): URI {item.resource.uri}, MIME Type {item.resource.mimeType}")
1494+
print(
1495+
f"Tool output (EmbeddedResource - Blob): URI {item.resource.uri}, MIME Type {item.resource.mimeType}"
1496+
)
14861497
elif isinstance(item, types.ImageContent):
14871498
# Showing only a snippet of image data
1488-
print(f"Tool output (ImageContent): MIME Type {item.mimeType}, Data (base64): {item.data[:30]}...")
1499+
print(
1500+
f"Tool output (ImageContent): MIME Type {item.mimeType}, Data (base64): {item.data[:30]}..."
1501+
)
14891502
else:
14901503
print(f"Tool output (Unknown Content Type): {type(item)}")
14911504

@@ -1635,6 +1648,74 @@ async def main():
16351648

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

1651+
### Parsing Tool Results
1652+
1653+
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.
1654+
1655+
```python
1656+
"""examples/snippets/clients/parsing_tool_results.py"""
1657+
1658+
import asyncio
1659+
1660+
from mcp import ClientSession, StdioServerParameters, types
1661+
from mcp.client.stdio import stdio_client
1662+
1663+
1664+
async def parse_tool_results():
1665+
"""Demonstrates how to parse different types of content in CallToolResult."""
1666+
server_params = StdioServerParameters(
1667+
command="python", args=["path/to/mcp_server.py"]
1668+
)
1669+
1670+
async with stdio_client(server_params) as (read, write):
1671+
async with ClientSession(read, write) as session:
1672+
await session.initialize()
1673+
1674+
# Example 1: Parsing text content
1675+
result = await session.call_tool("get_data", {"format": "text"})
1676+
for content in result.content:
1677+
if isinstance(content, types.TextContent):
1678+
print(f"Text: {content.text}")
1679+
1680+
# Example 2: Parsing structured content from JSON tools
1681+
result = await session.call_tool("get_user", {"id": "123"})
1682+
if hasattr(result, "structuredContent") and result.structuredContent:
1683+
# Access structured data directly
1684+
user_data = result.structuredContent
1685+
print(f"User: {user_data.get('name')}, Age: {user_data.get('age')}")
1686+
1687+
# Example 3: Parsing embedded resources
1688+
result = await session.call_tool("read_config", {})
1689+
for content in result.content:
1690+
if isinstance(content, types.EmbeddedResource):
1691+
resource = content.resource
1692+
if isinstance(resource, types.TextResourceContents):
1693+
print(f"Config from {resource.uri}: {resource.text}")
1694+
elif isinstance(resource, types.BlobResourceContents):
1695+
print(f"Binary data from {resource.uri}")
1696+
1697+
# Example 4: Parsing image content
1698+
result = await session.call_tool("generate_chart", {"data": [1, 2, 3]})
1699+
for content in result.content:
1700+
if isinstance(content, types.ImageContent):
1701+
print(f"Image ({content.mimeType}): {len(content.data)} bytes")
1702+
1703+
# Example 5: Handling errors
1704+
result = await session.call_tool("failing_tool", {})
1705+
if result.isError:
1706+
print("Tool execution failed!")
1707+
for content in result.content:
1708+
if isinstance(content, types.TextContent):
1709+
print(f"Error: {content.text}")
1710+
1711+
1712+
async def main():
1713+
await parse_tool_results()
1714+
1715+
1716+
if __name__ == "__main__":
1717+
asyncio.run(main())
1718+
```
16381719
### MCP Primitives
16391720

16401721
The MCP protocol defines three core primitives that servers can implement:
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)