Initial commit

This commit is contained in:
Zhongwei Li
2025-11-29 18:00:18 +08:00
commit 765529cd13
69 changed files with 18291 additions and 0 deletions

View File

@@ -0,0 +1,193 @@
#!/usr/bin/env python3
"""Example: Calculator MCP Server.
This example demonstrates how to create an in-process MCP server with
calculator tools using the Claude Code Python SDK.
Unlike external MCP servers that require separate processes, this server
runs directly within your Python application, providing better performance
and simpler deployment.
"""
import asyncio
from typing import Any
from claude_agent_sdk import (
ClaudeAgentOptions,
create_sdk_mcp_server,
tool,
)
# Define calculator tools using the @tool decorator
@tool("add", "Add two numbers", {"a": float, "b": float})
async def add_numbers(args: dict[str, Any]) -> dict[str, Any]:
"""Add two numbers together."""
result = args["a"] + args["b"]
return {
"content": [{"type": "text", "text": f"{args['a']} + {args['b']} = {result}"}]
}
@tool("subtract", "Subtract one number from another", {"a": float, "b": float})
async def subtract_numbers(args: dict[str, Any]) -> dict[str, Any]:
"""Subtract b from a."""
result = args["a"] - args["b"]
return {
"content": [{"type": "text", "text": f"{args['a']} - {args['b']} = {result}"}]
}
@tool("multiply", "Multiply two numbers", {"a": float, "b": float})
async def multiply_numbers(args: dict[str, Any]) -> dict[str, Any]:
"""Multiply two numbers."""
result = args["a"] * args["b"]
return {
"content": [{"type": "text", "text": f"{args['a']} × {args['b']} = {result}"}]
}
@tool("divide", "Divide one number by another", {"a": float, "b": float})
async def divide_numbers(args: dict[str, Any]) -> dict[str, Any]:
"""Divide a by b."""
if args["b"] == 0:
return {
"content": [
{"type": "text", "text": "Error: Division by zero is not allowed"}
],
"is_error": True,
}
result = args["a"] / args["b"]
return {
"content": [{"type": "text", "text": f"{args['a']} ÷ {args['b']} = {result}"}]
}
@tool("sqrt", "Calculate square root", {"n": float})
async def square_root(args: dict[str, Any]) -> dict[str, Any]:
"""Calculate the square root of a number."""
n = args["n"]
if n < 0:
return {
"content": [
{
"type": "text",
"text": f"Error: Cannot calculate square root of negative number {n}",
}
],
"is_error": True,
}
import math
result = math.sqrt(n)
return {"content": [{"type": "text", "text": f"{n} = {result}"}]}
@tool("power", "Raise a number to a power", {"base": float, "exponent": float})
async def power(args: dict[str, Any]) -> dict[str, Any]:
"""Raise base to the exponent power."""
result = args["base"] ** args["exponent"]
return {
"content": [
{"type": "text", "text": f"{args['base']}^{args['exponent']} = {result}"}
]
}
def display_message(msg):
"""Display message content in a clean format."""
from claude_agent_sdk import (
AssistantMessage,
ResultMessage,
SystemMessage,
TextBlock,
ToolResultBlock,
ToolUseBlock,
UserMessage,
)
if isinstance(msg, UserMessage):
for block in msg.content:
if isinstance(block, TextBlock):
print(f"User: {block.text}")
elif isinstance(block, ToolResultBlock):
print(
f"Tool Result: {block.content[:100] if block.content else 'None'}..."
)
elif isinstance(msg, AssistantMessage):
for block in msg.content:
if isinstance(block, TextBlock):
print(f"Claude: {block.text}")
elif isinstance(block, ToolUseBlock):
print(f"Using tool: {block.name}")
# Show tool inputs for calculator
if block.input:
print(f" Input: {block.input}")
elif isinstance(msg, SystemMessage):
# Ignore system messages
pass
elif isinstance(msg, ResultMessage):
print("Result ended")
if msg.total_cost_usd:
print(f"Cost: ${msg.total_cost_usd:.6f}")
async def main():
"""Run example calculations using the SDK MCP server with streaming client."""
from claude_agent_sdk import ClaudeSDKClient
# Create the calculator server with all tools
calculator = create_sdk_mcp_server(
name="calculator",
version="2.0.0",
tools=[
add_numbers,
subtract_numbers,
multiply_numbers,
divide_numbers,
square_root,
power,
],
)
# Configure Claude to use the calculator server with allowed tools
# Pre-approve all calculator MCP tools so they can be used without permission prompts
options = ClaudeAgentOptions(
mcp_servers={"calc": calculator},
allowed_tools=[
"mcp__calc__add",
"mcp__calc__subtract",
"mcp__calc__multiply",
"mcp__calc__divide",
"mcp__calc__sqrt",
"mcp__calc__power",
],
)
# Example prompts to demonstrate calculator usage
prompts = [
"List your tools",
"Calculate 15 + 27",
"What is 100 divided by 7?",
"Calculate the square root of 144",
"What is 2 raised to the power of 8?",
"Calculate (12 + 8) * 3 - 10", # Complex calculation
]
for prompt in prompts:
print(f"\n{'=' * 50}")
print(f"Prompt: {prompt}")
print(f"{'=' * 50}")
async with ClaudeSDKClient(options=options) as client:
await client.query(prompt)
async for message in client.receive_response():
display_message(message)
if __name__ == "__main__":
asyncio.run(main())