CertSafari
    Anthropic Claude Certified Developer – Foundations (CCDV-F)· Lessons

    Domain 8 · Lesson 24/25

    MCP Transports and Connecting Servers to Claude Code and the Agent SDK

    MCP Server Development

    13 min read
    3.53% of exam
    6 sources
    Published 4 Oct 2026
    Docs as of 30 Sep 2026

    What you will be able to do

    • Apply the stdio transport rules for stdout, stderr, and shutdown
    • Deploy a Streamable HTTP server securely, and recognise SSE and WebSocket endpoints
    • Use the official SDKs to author a server and to connect a client to Claude
    • Register stdio, HTTP, SSE, and WebSocket servers in Claude Code
    • Configure MCP servers and tool permissions in the Agent SDK, and reason about startup timeouts

    1.The stdio transport

    With stdio, the client launches the server as a child process. The server reads JSON-RPC messages from stdin and writes them to stdout. Each message is a single request, notification, or response, delimited by a newline, and a message must not contain embedded newlines. The server may write UTF-8 text to stderr for logging. The client may capture, forward, or ignore that output, and should not assume that stderr output means something went wrong.

    Shutdown is driven by the client. It closes the server's input stream, waits for the process to exit, and forcibly terminates the process if it does not exit within a reasonable time.

    Checkpoint 1 of 8· Put it in order

    Put the client's stdio shutdown steps in order

    1. 1.Wait for the server to exit
    2. 2.Close the input stream to the child process (the server)
    3. 3.Forcibly terminate the process if it has not exited within a reasonable time

    Sources1

    2.Streamable HTTP, sockets, and remote deployment

    A remote server uses Streamable HTTP. It exposes a single MCP endpoint that accepts POST, and the client sends every JSON-RPC request or notification as its own POST. The client's Accept header must list both application/json and text/event-stream. The server answers a request either with a single JSON object or with an SSE stream scoped to that request. That stream can carry related notifications, such as progress, before the final response. The server must not send independent requests on the stream. Instead, server-to-client interactions like sampling and elicitation are embedded in results as input requests. If the client posts a notification and the server accepts it, the server returns 202 Accepted with no body. Each POST also carries metadata headers: Mcp-Method on every request, and Mcp-Name on tools/call, resources/read, and prompts/get.

    Request headers for a tools/call over Streamable HTTPhttp
    POST /mcp HTTP/1.1
    Content-Type: application/json
    MCP-Protocol-Version: 2026-07-28
    Mcp-Method: tools/call
    Mcp-Name: get_weather

    For deployment, the sources give three security rules. Servers must validate the Origin header on every incoming connection, to prevent DNS rebinding, and must respond 403 Forbidden when it is present and invalid. A server running locally should bind to 127.0.0.1 rather than 0.0.0.0. And servers should authenticate all connections. Beyond HTTP, Claude Code can also connect to older SSE endpoints (--transport sse) and to WebSocket endpoints ("type":"ws" with a wss:// URL). The provided sources do not go further into hosting or scaling.

    Checkpoint 2 of 8· Check yourself

    A client POSTs a JSON-RPC notification to a Streamable HTTP server, and the server accepts it. What should the response be?

    Sources2

    3.Authoring with the official SDKs

    You rarely write JSON-RPC by hand. In Python, the mcp package provides FastMCP. In a sample server from the MCP tunnels quickstart, a function decorated with @mcp.tool(), with type hints and a docstring, becomes a tool, and mcp.run(transport="streamable-http") serves it over HTTP. The client side looks similar in TypeScript. With @modelcontextprotocol/sdk, you create a transport, create a Client, and connect. Anthropic's TypeScript SDK then provides helpers (mcpTools, mcpMessages, mcpResourceToContent) that convert the server's tools, prompts, and resources into Claude API types.

    An MCP client connecting to a local stdio server in TypeScripttypescript
    import { Client } from "@modelcontextprotocol/sdk/client/index.js";
    import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
    
    const anthropic = new Anthropic();
    
    // Connect to an MCP server
    const transport = new StdioClientTransport({ command: "mcp-server", args: [] });
    const mcpClient = new Client({ name: "my-client", version: "1.0.0" });
    await mcpClient.connect(transport);

    Checkpoint 3 of 8· Check yourself

    In the sample above, what does StdioClientTransport({ command: "mcp-server", args: [] }) do?

    Sources34

    4.Connecting a server to Claude Code

    How you register a server with claude mcp add depends on what you were given. A URL means a remote server, so use --transport http (or sse). A launch command means a local server, so use --transport stdio, put the command after --, and pass any secrets with --env. For anything else, such as a WebSocket endpoint, use claude mcp add-json with a JSON config.

    A local stdio server with an environment variablebash
    # Real example: Add Airtable server
    claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
      -- npx -y airtable-mcp-server
    A WebSocket server added through JSONbash
    claude mcp add-json events-server \
      '{"type":"ws","url":"wss://mcp.example.com/socket","headers":{"Authorization":"Bearer YOUR_TOKEN"}}'

    In JSON, a url entry needs an explicit type of http, sse, or ws. Claude Code treats an entry without a type as a stdio server, so the connection fails. Server names may contain only letters, numbers, hyphens, and underscores. To manage servers, use claude mcp list, claude mcp get <name>, and claude mcp remove <name>; inside a session, /mcp shows server status. Project-scoped servers from .mcp.json show as pending until you approve them in an interactive claude session. Claude Code also warns about hidden whitespace in config values and about the same server name being defined in more than one scope.

    Checkpoint 4 of 8· Fill the gap

    Which transport value connects Claude Code to Notion's remote endpoint?

    claude mcp add --transport  ?  notion https://mcp.notion.com/mcp

    Checkpoint 5 of 8· Exam question

    A platform engineer is integrating a new MCP server into an internal Claude Code agent. The vendor's documentation instructs users to run `npx internal-tools-mcp` as a local process on the same machine that hosts the agent, and gives no network endpoint. Which transport type should the engineer configure for this server?

    Sources5

    5.Connecting a server to the Agent SDK

    In the Agent SDK, you pass servers in the mcpServers option (mcp_servers in Python). These use the same shapes as before: type and url for a remote server, or command and args for a stdio server. The same JSON can live in a .mcp.json file. Configuring a server does not by itself give the agent permission to use its tools. You grant that in allowedTools, where each tool has the name mcp__<server>__<tool>, so a wildcard like mcp__claude-code-docs__* allows every tool on that server.

    Connecting the Agent SDK to a remote HTTP server and allowing its toolstypescript
    import { query } from "@anthropic-ai/claude-agent-sdk";
    
    for await (const message of query({
      prompt: "Use the docs MCP server to explain what hooks are in Claude Code",
      options: {
        mcpServers: {
          "claude-code-docs": {
            type: "http",
            url: "https://code.claude.com/docs/mcp"
          }
        },
        allowedTools: ["mcp__claude-code-docs__*"]
      }
    })) {
      if (message.type === "result" && message.subtype === "success") {
        console.log(message.result);
      }
    }

    How quickly servers connect at startup affects the first turn. With tool search, which is on by default, the first turn waits only for servers marked alwaysLoad: true, and the others keep connecting in the background.

    When an MCP server delays the agent's first turn
    Server typeDelays first turn?Timeout
    stdio server, or HTTP/SSE server without a cached tool listYes, until it connectsMCP_TIMEOUT, 30 seconds by default
    Remote server with a cached tool listNo; cached tools are available from the first turnNone at startup; its deferred connect has its own timeout
    In-process SDK serverYes, until it connects and lists its toolsMCP_TIMEOUT per connect attempt

    Checkpoint 6 of 8· Check yourself

    An agent configures a server named filesystem but Claude never calls its tools. Which allowedTools entry grants all of that server's tools?

    Checkpoint 7 of 8· Exam question

    A team wants to connect their agent to a third-party analytics MCP server. The provider's documentation gives a hosted endpoint URL, `https://analytics.example.com/mcp`, rather than a local command to run. Which configuration best matches this integration pattern?

    Checkpoint 8 of 8· Exam question

    A developer configures an MCP server named `github` that exposes a `list_issues` tool. To auto-approve only this specific tool, without granting access to any other tool on the server, which entry should be added to `allowedTools`?

    Sources6

    Exam traps

    Each one states something that sounds right. Open it to see what is actually true.

    1. 1.A stdio server can print debug output to stdout, and the client will filter it out.Why is that wrong?

      stdout may carry only valid MCP messages. Logging belongs on stderr, which clients should not treat as a sign of errors.

      Covered in The stdio transport

    2. 2.A JSON server entry with just a url is enough, because Claude Code infers HTTP from the URL.Why is that wrong?

      An entry without a type is read as stdio, so a url entry must set type to http, sse, or ws.

      Covered in Connecting a server to Claude Code

    3. 3.A locally running HTTP MCP server should bind to 0.0.0.0 so every client can reach it.Why is that wrong?

      Local servers should bind only to localhost, and must validate the Origin header to prevent DNS rebinding.

      Covered in Streamable HTTP, sockets, and remote deployment

    Practise it for real

    Register a local stdio MCP server in Claude Code, check that it connects, and remove it again.

    1. 1.Run: claude mcp add --transport stdio myserver -- npx server (replace npx server with the launch command of a server you have)

      Why: A launch command means the server runs on your machine, so it is registered as stdio with the command after --.

      You should see: Claude Code saves a server named myserver that will run your command.

    2. 2.Run: claude mcp list, then claude mcp get myserver

      Why: These commands show the configured servers along with their status and any warnings, such as hidden whitespace.

      You should see: myserver appears with its command and connection status.

    3. 3.Start claude and type /mcp

      Why: /mcp shows the status of each server from inside a session.

      You should see: myserver shows as connected, along with its tools.

    4. 4.Run: claude mcp remove myserver

      Why: This cleans up the test registration.

      You should see: myserver no longer appears in claude mcp list.

    Stuck? Get a nudge

    If the server shows as failed, check that the command after -- runs on its own in your shell, and that the server writes nothing but MCP messages to stdout.

    Sources

    Every claim above is drawn from one of these pages, quoted as it was written on the date shown.

    1. 1.
      “Messages are delimited by newlines, and MUST NOT contain embedded newlines.”
      ↩︎ The stdio transport
      “SHOULD NOT assume stderr output indicates error conditions”
      ↩︎ The stdio transport
      “The server MUST NOT write anything to its stdout that is not a valid MCP message.”
      ↩︎ Exam trap 1
      “If the server does not exit within a reasonable time, forcibly terminating the process”
      ↩︎ Checkpoint
      “The server reads JSON-RPC messages from stdin and writes JSON-RPC messages to stdout.”
      ↩︎ Checkpoint
    2. 2.
      “The server exposes a single HTTP endpoint (the MCP endpoint) that accepts POST.”
      ↩︎ Streamable HTTP, sockets, and remote deployment
      “Servers MUST validate the Origin header on all incoming connections to prevent DNS rebinding attacks.”
      ↩︎ Streamable HTTP, sockets, and remote deployment
      “The server MUST NOT send independent JSON-RPC requests on this stream.”
      ↩︎ Streamable HTTP, sockets, and remote deployment
      “When running locally, servers SHOULD bind only to localhost (127.0.0.1) rather than all network interfaces (0.0.0.0).”
      ↩︎ Exam trap 3
      “If the server accepts it, the server MUST return HTTP status code 202 Accepted with no body.”
      ↩︎ Checkpoint
    3. 4.
      “These helpers convert MCP types to Claude API types, reducing boilerplate when working with MCP tools, prompts, and resources.”
      ↩︎ Authoring with the official SDKs
    4. 5.
      “A launch command such as npx -y @example/mcp-server: the server runs on your machine.”
      ↩︎ Connecting a server to Claude Code
      “Run claude interactively to review and approve it.”
      ↩︎ Connecting a server to Claude Code
      “Claude Code reads an entry with no type as a stdio server, so a url entry without a type fails.”
      ↩︎ Exam trap 2
    5. 6.
      “Configure MCP servers to extend your agent with external tools.”
      ↩︎ Connecting a server to the Agent SDK
      “make its tools available at their full schemas on the first turn, exempt from tool search deferral”
      ↩︎ Connecting a server to the Agent SDK
      “MCP_TIMEOUT, 30 seconds by default; the connection fails at that deadline”
      ↩︎ Connecting a server to the Agent SDK
      “allowedTools: ["mcp__filesystem__*"]”
      ↩︎ Checkpoint

    Ready to test yourself?

    Practise the 20 questions on this subdomain.

    Spotted a mistake, or was something unclear? Tell us.