MCP Server Development
MCP Server Development is 2.1% of the CCDV-F blueprint, about one question. It tests what a server actually declares, why diagnostic output breaks a subprocess connection, and what changes when the same server is hosted for other people.
Written by Kiran Manne
2.1% of the CCDV-F blueprint, which is roughly 1 question of 53. It sits inside Tools and MCPs, worth 10.6% in total.
MCP Server Development sits at 2.1%, which on a 53-question paper is about one mark, and it is the smallest of the three sub-skills in its domain for a good reason: most developers consume servers rather than write them. Study it accordingly. Aim to describe a server's structure and its two deployment shapes rather than to recite the protocol.
What a server actually is: a process that advertises a set of capabilities during connection setup and then answers requests against them. You declare a tool by giving it a name, a description and an input schema and registering a handler; the software development kit turns that declaration into the listing and invocation responses on the wire, so you rarely touch a protocol frame yourself. Resources and prompts follow the same pattern in different shapes.
The interesting engineering is not in the message format. It is in the two things a server author gets wrong. A locally launched server shares its output stream with the protocol, so ordinary debugging output corrupts the connection. And a server that works perfectly for one developer on their own machine has none of the authentication, tenancy or authorization it needs the moment it is hosted for other people. Those two ideas carry the sub-skill.
What the exam tests here
- What a server declares for a tool, and how that declaration becomes listing and invocation behaviour
- Capability advertisement at connection time, and why a client should not call what was never advertised
- Why a locally launched server must keep diagnostic output off the protocol stream
- What changes about the trust model when the same server is hosted over a network
- Evolving a server's surface without breaking the hosts and agents depending on it
What you actually write
A server declaration is small. For a tool you supply a stable name, a description written for a model choosing between yours and everything else available, an input schema, and a function receiving validated arguments and returning content. The library handles enumeration and dispatch.
Resources are addressed rather than invoked: register a URI, or a template with parameters in it, along with a reader producing the content for a given address. Prompts are named, parameterised message templates a person selects deliberately. The authoring decision is which of the three a given piece of functionality is, and the reliable test is who ought to initiate it. Deciding that badly is the most common structural mistake in a first server.
Advertise, then respect the advertisement
Connection setup includes an exchange in which each side states what it supports. A server offering no prompts says so, and a client should not then request them; a client unable to handle a given feature likewise declares its absence. Building against an assumption rather than the declaration produces integrations that work with one counterpart and fail against another, which is exactly the interoperability the protocol exists to provide.
A related affordance matters if your surface is dynamic. Where the available tools can change mid-session, because somebody connected an account or switched workspace, there is a notification for telling the client the listing has changed. Without it the host keeps offering a stale set and calls start failing for reasons neither side can see.
The standard output stream belongs to the protocol
When a host launches a server as a subprocess, the two exchange messages over that process's standard input and output. Anything else written to standard output is injected into the middle of that stream, and the connection then breaks in a way that looks nothing like its cause: a parse failure, a hung client, a server that disconnects on the first request.
The bug is universal because printing is how everyone debugs. A stray print statement, a library logging to standard output by default, a framework's startup banner: any one of them is enough. Send diagnostics to the error stream or through the protocol's own logging facility, and configure third-party libraries explicitly rather than trusting their defaults.
Local and hosted are different products
A subprocess server runs as one person, on their machine, with their environment and their filesystem. Authentication is implicit because the operating system already did it, and there is exactly one tenant. Take the same code and put it behind a network endpoint and none of that holds: requests arrive from many people, the credentials in the environment belong to whoever deployed it rather than to the caller, and every handler that trusted an identifier because there was only ever one user is now an access-control defect.
Porting therefore means adding real authentication, deriving authority per request from the caller rather than from process configuration, and treating every parameter as attacker-supplied. The transport change rewrites the trust assumptions.
Where candidates go wrong
Trap 1: exposing the whole underlying system
A server generated mechanically from a database schema or an interface specification produces dozens of tools, all of which occupy the model's context whenever the server is connected and most of which will never be called. That cost is paid on every request by every user of that host.
A server is a curated surface. Expose the handful of operations corresponding to things people actually ask for, phrase them in the language of the task rather than of the underlying tables, and leave the remainder unexported.
Trap 2: renaming a tool because the new name reads better
Names are the interface. Host configurations reference them, permission rules match on them, agent instructions mention them, and saved workflows invoke them. Changing one is a breaking change that fails at run time rather than at build time, with an error the user cannot act on.
Where the surface genuinely must change, add the replacement, mark the old one clearly, and remove it after a deprecation period. The same applies to tightening a schema: making an optional parameter required breaks every caller that omitted it.
Trap 3: testing only through a model
If the sole check on a server is whether an agent completed a task with it, every failure is ambiguous. The handler may be broken, the schema may be wrong, or the description may simply have failed to persuade the model to call it.
Drive the server directly first, with the reference inspector or a plain client, so listing, invocation, argument validation and error paths are verified on their own. Then evaluate the model-facing half separately by watching which tools get chosen. Two questions deserve two tests.
Common questions
How much of the CCDV-F exam is MCP Server Development?
2.1%, so roughly one question of 53 and the lightest sub-skill in its domain. Being able to describe what a server declares, how it is launched, and how the security picture changes when it is hosted will cover almost anything reasonably askable.
Why does my locally launched server disconnect immediately?
Look for something writing to standard output. That stream carries the protocol messages when a host runs the server as a subprocess, so a print statement, a logging default or a framework banner corrupts the conversation. Route every diagnostic to the error stream and configure your libraries so they cannot do otherwise.
Do I have to construct protocol messages by hand?
No, and you should not. The software development kits accept declarations (a name, a description, a schema, a handler) and generate the listing and invocation behaviour for you. Your effort belongs in deciding what to expose, writing descriptions a model can act on, and getting the trust model right.
How many tools should one server expose?
As few as will do the job. Every tool a connected server publishes occupies context for every request in that host, so a mechanically generated surface of fifty operations taxes users who need three of them. Curate down to task-shaped operations and leave the rest of the underlying system unexported.
The rest of Tools and MCPs
- Tool Implementation (4.4%)
- Agentic Customization (4.1%)
Practise this
The CCDV-F bank covers every sub-skill in the blueprint, weighted the way the real paper is. Free sample questions need no account.
Free CCDV-F questions