Anthropic's MCP Advanced Topics course: learn sampling and transports, then test against the spec
The course maps out what MCP looks like in production. The spec's mandatory rules, such as a clean stdout, Origin checks and a human approving sampling, are still yours to implement and test.
In brief
- Anthropic's course covers sampling, transports and production deployment for MCP; it assumes Python, async, JSON/HTTP and SSE.
- Sampling keeps model choice and permissions with the client; the server only sends preferences and hints.
- Stateless HTTP scales easily but has trade-offs, and the Python SDK still diverges from the spec in places, so test it yourself.
On 19 April 2026 an issue was opened on the MCP Python SDK repository. It was short: a Streamable HTTP server configured with stateless_http=True still accepted GET /mcp, contrary to the spec. The bug is minor, but it shows that even the official library does not always follow the spec.
That is also the right way to approach “Model Context Protocol: Advanced Topics”, Anthropic’s course on Anthropic Academy (hosted on Skilljar). It centres on server-client communication, transport mechanisms and what to watch for in production deployments. The course page says only © 2026; it gives no release date or duration.
For an FDE these are real questions at the customer site. Where does the MCP server run? Who holds the model key? What happens when you put it behind a load balancer? The course answers most of them. The rest you have to work out from the spec.
Who should take it, and in what order?
The course assumes Python, async programming, JSON/HTTP and the basics of SSE. If you are not yet comfortable writing async Python, learn that first. Otherwise the transport lessons will be hard going, because you will be learning the protocol and the syntax at the same time.
A sensible order is to finish the course, then read the Sampling and Transports pages of the 2025-06-18 spec, and only then open the SDK issue above. That way you move from concepts to the mandatory rules, and then to the place where real code still falls short of them. Three ideas are worth keeping.
The server borrows the client’s model
According to the course, sampling is the mechanism by which an MCP server asks for a language model call through the client it is connected to. The MCP spec spells out the benefit: the server gets AI capabilities without its own API key, while the client keeps control over access, model selection and permissions.
Nor does the server hard-code a model name. It tells the client how much it values cost, speed or model quality, along with a few model-name hints. The spec stresses that hints are advisory; the final decision belongs to the client.
Imagine building a server that summarises support tickets for a customer. With sampling you do not need to ask the customer for a separate key for the server, and their security team still decides which model to use.
But the spec comes with a recommendation: there should always be a human able to deny a sampling request. If you are writing the client, that approval step is your job.
stdout is for MCP messages only
The spec defines two standard transports, stdio and Streamable HTTP, and recommends that clients support stdio whenever possible. stdio has one mandatory rule: the server must not write anything to stdout that is not a valid MCP message. Logs go to stderr.
This is an easy mistake to make when writing your own server. A single debugging print pollutes the message stream, and the client receives data it cannot parse. So the first thing to do when setting up a server, before writing any tool, is to configure the logger:
import logging, sys
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
log = logging.getLogger("mcp-server")
log.info("server starting") # goes to stderr, never touches stdout
Expected result: every log line appears on stderr, and stdout carries only MCP messages. To be sure, deliberately add a print("debug") and watch how the client reacts, so you recognise the symptom next time.
State decides how you scale
The most valuable part of the course teaches you to choose a transport by deployment requirements, the features you need and scaling limits, including when to use stateless HTTP to scale horizontally behind a load balancer.
Under the spec, sessions in Streamable HTTP are optional. The server may assign an ID through the Mcp-Session-Id header at initialisation, after which the client must send that ID back on every request.
Imagine a customer running three instances behind a load balancer. Instance A issues a session and holds the state, but the next request lands on instance B, which knows nothing about that session. Running stateless avoids this, but it is not free.
The course points out that the configuration flags affect server-initiated requests and streaming. Sampling is exactly a server-initiated request, so you need to check that it still works in the configuration you choose.
Two more rules belong directly in your test suite, each in its own command, so that when a request is rejected you know exactly which rule blocked it. Replace the address below with your server’s.
The first command checks the divergence raised in the SDK issue: send a GET to a server running stateless_http=True, with no other headers.
curl -i -X GET http://localhost:8000/mcp
The issue proposes that a stateless server return 405 for this request. If your server still accepts it, record that and block it in your own layer rather than trusting the library to handle it.
The second command checks the mandatory rule on the Origin header, which a Streamable HTTP server must validate on every connection to prevent DNS rebinding attacks. Use POST so it does not get mixed up with the GET test above:
curl -i -X POST http://localhost:8000/mcp \
-H "Origin: http://evil.example" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"ping"}'
What you need to see is the request rejected. Then rerun the same command without the Origin line: if only the version with the foreign Origin is blocked, you know the Origin check is working and the request did not fail for some other reason.
Turn the course into evidence on your CV
Do not just list the completion certificate on your CV; attach a small repo that proves you did the work.
Build a server that runs over both stdio and Streamable HTTP, logs to stderr, has a test that rejects a foreign Origin, has a stateless configuration running behind two instances, and comes with a client that includes a sampling approval step.
In the README, write a short paragraph explaining why you chose stateful or stateless.
When an FDE job description mentions MCP, agent integration or production deployment, that paragraph is what to bring to the interview. Be ready to talk through the trade-offs, such as why session IDs complicate load balancing, rather than just listing the APIs you called.
Plenty of people will finish this course. Far fewer will have sent GET /mcp to their own server to see what comes back.
Was this article useful?
Thanks for the feedback!