feat: Add in-process SDK MCP server support (#142)

## Summary

Adds in-process SDK MCP server support to the Python SDK, building on
the control protocol from #139.

**Note: Targets `dickson/control` branch (PR #139), not `main`.**

## Key Changes

- Added `@tool` decorator and `create_sdk_mcp_server()` API for defining
in-process MCP servers
- SDK MCP servers run directly in the Python process (no subprocess
overhead)
- Moved SDK MCP handling from Transport to Query class for proper
architectural layering
- Added `McpSdkServerConfig` type and integrated with control protocol

## Example

```python
from claude_code_sdk import tool, create_sdk_mcp_server

@tool("greet", "Greet a user", {"name": str})
async def greet_user(args):
    return {"content": [{"type": "text", "text": f"Hello, {args['name']}!"}]}

server = create_sdk_mcp_server(name="my-tools", tools=[greet_user])

options = ClaudeCodeOptions(mcp_servers={"tools": server})
```

## Testing

- Added integration tests in `test_sdk_mcp_integration.py`
- Added example calculator server in `examples/mcp_calculator.py`

---------

Co-authored-by: Dickson Tsai <dickson@anthropic.com>
Co-authored-by: Ashwin Bhat <ashwin@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
kashyap murali
2025-09-03 08:29:32 -07:00
committed by GitHub
parent 22fa9f473e
commit 9ef57859af
11 changed files with 879 additions and 18 deletions

View File

@@ -14,7 +14,7 @@ bash commands, edit files, search the web, fetch web content) to accomplish.
# BASIC STREAMING
# ============================================================================
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
from claude_code_sdk import AssistantMessage, ClaudeSDKClient, ResultMessage, TextBlock
async with ClaudeSDKClient() as client:
print("User: What is 2+2?")
@@ -32,7 +32,8 @@ async with ClaudeSDKClient() as client:
# ============================================================================
import asyncio
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock
from claude_code_sdk import AssistantMessage, ClaudeSDKClient, TextBlock
async with ClaudeSDKClient() as client:
async def send_and_receive(prompt):
@@ -53,7 +54,7 @@ async with ClaudeSDKClient() as client:
# PERSISTENT CLIENT FOR MULTIPLE QUESTIONS
# ============================================================================
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock
from claude_code_sdk import AssistantMessage, ClaudeSDKClient, TextBlock
# Create client
client = ClaudeSDKClient()
@@ -88,8 +89,7 @@ await client.disconnect()
# IMPORTANT: Interrupts require active message consumption. You must be
# consuming messages from the client for the interrupt to be processed.
import asyncio
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
from claude_code_sdk import AssistantMessage, ClaudeSDKClient, TextBlock
async with ClaudeSDKClient() as client:
print("\n--- Sending initial message ---\n")
@@ -141,7 +141,7 @@ async with ClaudeSDKClient() as client:
# ERROR HANDLING PATTERN
# ============================================================================
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock
from claude_code_sdk import AssistantMessage, ClaudeSDKClient, TextBlock
try:
async with ClaudeSDKClient() as client:
@@ -168,7 +168,8 @@ except Exception as e:
# SENDING ASYNC ITERABLE OF MESSAGES
# ============================================================================
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock
from claude_code_sdk import AssistantMessage, ClaudeSDKClient, TextBlock
async def message_generator():
"""Generate multiple messages as an async iterable."""
@@ -209,7 +210,7 @@ async with ClaudeSDKClient() as client:
# COLLECTING ALL MESSAGES INTO A LIST
# ============================================================================
from claude_code_sdk import ClaudeSDKClient, AssistantMessage, TextBlock, ResultMessage
from claude_code_sdk import AssistantMessage, ClaudeSDKClient, TextBlock
async with ClaudeSDKClient() as client:
print("User: What are the primary colors?")