1177 words Slides

17.8 MCP in the SDK

Course: Claude Code - Enterprise Development

Section: Claude Agent SDK

Video Length: 3-4 minutes

Presenter: Daniel Treasure


Opening Hook

"You've built MCPs (16.5), and you've built custom tools (17.7). What if you want both? Register MCP servers as tools in your agent so Claude can access all your connected services programmatically."


Key Talking Points

What to say:

  • "MCP servers in the SDK work the same as in CLI—Claude sees them as tools to call."
  • "Difference: in SDK, you manage MCP connections programmatically, not through CLI config."
  • "Register MCPs when creating agent, Claude can invoke operations seamlessly."
  • "Credentials are managed outside Claude—secure and auditable."

What to show on screen:

  • MCP server starting in background
  • Agent initialized with MCP connections
  • Claude calling MCP operation
  • Result flowing back to agent
  • Multiple MCPs working together

Demo Plan

[00:00 - 00:45] MCP Setup in SDK 1. Start MCP server (your custom user service from 16.5) 2. Configure SDK to connect to MCP transport 3. Agent registration: point agent to MCP server 4. Verify connection is live

[00:45 - 01:45] Claude Using MCP Tools 1. Ask Claude: "Get user details for user 42" 2. Show Claude's tool selection: sees MCP operation 3. Claude calls MCP tool (get_user) 4. MCP server receives request, validates, calls internal API 5. Result returns to Claude, agent uses it

[01:45 - 02:45] Multiple MCPs 1. Show agent with two MCPs registered: user service + internal API 2. Ask Claude task requiring both: "Get user 42 and their recent API calls" 3. Claude chains MCP calls intelligently 4. Show results consolidated

[02:45 - 03:30] Credential Management 1. Discuss: credentials are in MCP server, not exposed to Claude 2. Show environment config: MCP server has token/credentials 3. Emphasize: Claude never sees raw credentials 4. Explain: audit logging in MCP server


Code Examples & Commands

Python SDK with MCP:

import asyncio
import subprocess
from claude_code import Agent, MCPConnection

async def agent_with_mcp():
    # Start MCP server (e.g., your custom user service)
    mcp_process = subprocess.Popen([
        "python", "/path/to/mcp_user_service.py"
    ])

    # Create agent with MCP connection
    mcp_connection = MCPConnection(
        name="user-service",
        transport_type="stdio",
        transport_args={
            "command": "python",
            "args": ["/path/to/mcp_user_service.py"]
        }
    )

    agent = Agent(
        model="claude-sonnet-4-5-20250929",
        system_prompt="You are a user management assistant.",
        mcp_connections=[mcp_connection]
    )

    # Claude can now use MCP tools
    result = await agent.run("Get details for user 123")
    print(f"Result:\n{result.output}")

    # Cleanup
    mcp_process.terminate()

asyncio.run(agent_with_mcp())

Multiple MCPs in Agent:

import asyncio
from claude_code import Agent, MCPConnection

async def multi_mcp_agent():
    # Define two MCP connections
    user_service = MCPConnection(
        name="user-service",
        transport_type="stdio",
        transport_args={"command": "python", "args": ["/path/to/users.py"]}
    )

    api_service = MCPConnection(
        name="api-logs",
        transport_type="stdio",
        transport_args={"command": "python", "args": ["/path/to/logs.py"]}
    )

    # Create agent with both MCPs
    agent = Agent(
        model="claude-sonnet-4-5-20250929",
        mcp_connections=[user_service, api_service]
    )

    # Claude can use either/both MCPs
    task = """
    1. Get user 42 (use user-service MCP)
    2. Get their recent API logs (use api-logs MCP)
    3. Summarize activity
    """

    result = await agent.run(task)
    print(f"Summary:\n{result.output}")

asyncio.run(multi_mcp_agent())

HTTP Transport MCP (e.g., Sentry, Slack):

import asyncio
from claude_code import Agent, MCPConnection
import os

async def agent_with_external_mcp():
    # Connect to remote MCP server (e.g., Sentry)
    sentry_mcp = MCPConnection(
        name="sentry",
        transport_type="http",
        transport_args={
            "url": "https://mcp.sentry.dev/mcp",
            "headers": {
                "Authorization": f"Bearer {os.getenv('SENTRY_TOKEN')}"
            }
        }
    )

    agent = Agent(
        model="claude-sonnet-4-5-20250929",
        mcp_connections=[sentry_mcp]
    )

    # Claude accesses Sentry
    result = await agent.run(
        "What are the top 5 errors in our production system today?"
    )
    print(result.output)

asyncio.run(agent_with_external_mcp())

With Custom Tools + MCPs:

import asyncio
from claude_code import Agent, MCPConnection, Tool

async def combined_tools_and_mcps():
    # Custom tool
    def get_team_members(team: str) -> str:
        """Get team members from internal directory."""
        teams = {
            "eng": "Alice, Bob, Charlie",
            "product": "Diana, Eve",
            "sales": "Frank"
        }
        return teams.get(team, "Team not found")

    # MCP connection
    jira_mcp = MCPConnection(
        name="jira",
        transport_type="http",
        transport_args={"url": "https://company.atlassian.net/mcp"}
    )

    # Create agent with both
    agent = Agent(
        model="claude-sonnet-4-5-20250929",
        custom_tools=[
            Tool(
                name="get_team_members",
                description="Get list of team members",
                input_schema={
                    "type": "object",
                    "properties": {
                        "team": {
                            "type": "string",
                            "enum": ["eng", "product", "sales"]
                        }
                    },
                    "required": ["team"]
                },
                execute=get_team_members
            )
        ],
        mcp_connections=[jira_mcp]
    )

    # Claude uses both custom tools and MCPs
    result = await agent.run(
        "Get the engineering team and assign the top 5 Jira bugs to them"
    )
    print(result.output)

asyncio.run(combined_tools_and_mcps())

TypeScript with MCP:

import Anthropic from "@anthropic-ai/sdk";

interface MCPConfig {
  name: string;
  transport: "stdio" | "http";
  url?: string;
  command?: string;
  args?: string[];
}

async function agentWithMCP(): Promise<void> {
  const client = new Anthropic();

  const mcp: MCPConfig = {
    name: "user-service",
    transport: "stdio",
    command: "python",
    args: ["/path/to/mcp_service.py"],
  };

  console.log(`Connecting to MCP: ${mcp.name}`);
  console.log("Agent ready to use MCP tools");

  // Detailed implementation depends on SDK
}

agentWithMCP().catch(console.error);

Gotchas & Tips

Gotcha 1: MCP Server Lifecycle - MCP server must be running for agent to use it - If server crashes, agent operations fail - Solution: Health checks, automatic restart, fallback

Gotcha 2: Slow MCP Operations - If MCP is slow to respond, agent waits - User sees delay - Solution: Optimize MCP server performance, add timeouts, queue operations

Gotcha 3: Credential Isolation - Credentials should be in MCP server, not shared with Claude - If you leak credentials to Claude prompt, they're exposed - Solution: Never put credentials in agent system prompt; keep in MCP

Gotcha 4: Tool Name Conflicts - If two MCPs have same tool name, confusion may arise - Solution: Use namespacing: "sentry_list_errors", "jira_list_issues" - Or: MCP scopes in agent config

Gotcha 5: Authorization Boundary - MCP operations may check: "Is Claude allowed to call this?" - Example: read-only user can't create issues - Solution: MCP server enforces permissions; Claude respects boundary

Tip 1: MCP Health Check - Periodically verify MCP is reachable before agent task - Fast fail if unavailable

Tip 2: Error Handling - MCP operations may fail (timeout, rate limit, auth error) - Claude should handle gracefully: "Sentry is temporarily unavailable"

Tip 3: Audit All MCP Calls - Log every MCP operation: what, who, when, result - Useful for security and debugging

Tip 4: Timeout Settings - Set reasonable timeouts for MCP calls - Prevent agent from waiting forever

Tip 5: Cache MCP Results - If same MCP query repeated, cache result - Reduces load, improves speed


Lead-out

"You've integrated MCPs into agent SDK workflows. Next: subagents. For complex problems, one agent isn't always enough. We'll show how to create hierarchies of agents that coordinate and delegate."


Reference URLs

  • Claude Code MCP SDK Integration: [check official docs]
  • MCP Server Examples: https://github.com/anthropics/mcp-servers
  • MCP Protocol: https://modelcontextprotocol.io/

Prep Reading

  • Review MCPs you've created or plan to use (5 min)
  • Ensure MCP server is running and tested (10 min)
  • Design agent workflow involving MCPs (5 min)

Notes for Daniel

  • Bridge concept: This video connects CLI (where MCPs are easy) to SDK (where MCPs are integrated).
  • Credential security: Emphasize repeatedly that credentials stay in MCP server, never leak to Claude.
  • Practical value: Position MCPs in SDK as the way to safely integrate production systems with agents.
  • Coordination: Mention that with multiple MCPs, Claude coordinates across systems automatically.