{"course":{"slug":"building-with-ai","title":"Building with AI","url":"https://addaly.com/learn/building-with-ai","level":"intermediate","track":"build"},"lesson":{"slug":"mcp-and-tool-protocols","title":"MCP: what a tool protocol buys you, and what it costs","url":"https://addaly.com/learn/building-with-ai/mcp-and-tool-protocols","position":28,"of":80,"minutes":9,"answer":"MCP standardises tool discovery so capabilities become a deployment concern rather than a code change, at the cost of a new trust boundary: server-supplied descriptions enter your prompt and can change after you approved them.","keyIdea":"MCP standardises tool discovery so capabilities become a deployment concern rather than a code change, at the cost of a new trust boundary: server-supplied descriptions enter your prompt and can change after you approved them."},"body":{"format":"markdown","text":"## The problem it solves\n\nWithout a standard, every combination of application and data source needs its own connector. Five applications and eight systems is forty integrations, each with its own auth handling, its own schema conventions, and its own bugs.\n\nThe **Model Context Protocol** is an attempt to make that five plus eight instead of forty. A **server** exposes capabilities; a **client** (an assistant, an IDE, an agent) consumes them. Anything that speaks the protocol can talk to anything else that does, and the maintainer of a system writes one server rather than one connector per consumer.\n\nThree kinds of capability, and the distinction matters:\n\n- **Tools**: actions the model may invoke. This is what most servers ship.\n- **Resources**: content the client can read and attach to context, addressed by URI. Selected by the application or the user, not the model.\n- **Prompts**: reusable templates a user can invoke deliberately.\n\nThe useful part of that split is the third column, which is *who decides*. Tools are model-driven; resources are application-driven; prompts are user-driven. Systems that blur it end up with a model deciding to read things nobody meant it to read.\n\n## What it actually is\n\nJSON-RPC over one of two transports: **stdio** for a server running as a local subprocess, and **streamable HTTP** for a remote one. The client starts a session, calls `tools/list` to discover what exists, and then `tools/call` to invoke.\n\n```json\n{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\n \"params\":{\"name\":\"search_tickets\",\n           \"arguments\":{\"query\":\"refund not received\",\"limit\":5}}}\n```\n\nUnderneath, nothing changes about the model. The tool list is fetched from a server rather than hard-coded, and the result comes back over a socket instead of a function call. Every lesson about tool design still applies exactly: good names, negative clauses in descriptions, tight schemas, identity never in the arguments.\n\n## When it is worth it\n\n**Use a protocol when the set of tools is not known at build time.** An assistant that different customers connect to their own systems; an IDE where the user adds capabilities; an internal platform where six teams each expose their own service without touching your codebase. Here the indirection pays for itself.\n\n**Do not use one when you have four tools and control both ends.** Four Python functions in a dictionary is less code, has fewer moving parts, no subprocess to supervise, no session to reconnect, and one less thing to be down at three in the morning. A protocol solves a coupling problem, and if you do not have a coupling problem it is pure overhead.\n\nThe honest middle case is that MCP is worth adopting early if you expect third parties to extend your product, and worth deferring if you do not.\n\n## The security surface, stated plainly\n\nThis is the part that deserves your attention, because a tool protocol moves trust boundaries.\n\n**A server you install runs on your machine with your permissions.** A stdio server is a subprocess. It can read your files, your environment variables and your keys. Installing one from an unfamiliar source is exactly as consequential as running any other program from that source, and the packaging makes it feel lighter than it is.\n\n**Tool descriptions come from the server and go into your prompt.** A malicious or compromised server can put instructions in a description: text that the model reads as guidance and that you never see. This is prompt injection arriving through the metadata channel rather than through user content, and it is specific to protocols that fetch definitions at runtime.\n\n**Definitions can change after you approved them.** A server can serve one description on Monday and a different one on Friday. If your approval was a one-time decision, it was a decision about a thing that no longer exists. Pin versions where you can, hash the tool definitions, and re-prompt on change.\n\n**Tokens are usually broader than the task.** Connecting a server to a whole workspace when the job needs one folder is the common shape, and it means a single confused tool call can reach everything.\n\nMitigations that are worth the effort: run servers with the narrowest credentials that work, keep an allowlist of servers rather than installing freely, log every `tools/call` with its arguments, require confirmation for writes, and treat tool *results* as untrusted text: a server returning a document containing \"ignore previous instructions\" is the ordinary case, not the exotic one.\n\n## The thing to take away\n\nA protocol changes the plumbing, not the physics. The model still cannot run anything; your client does. Authorisation is still your job and still belongs to the session, not the arguments. Every tool is still a place where text from outside your system enters your model's context.\n\nWhat MCP gives you is that the tools available to your assistant become a deployment concern rather than a code change, which is a large operational win and a new place to be careful."},"check":{"question":"A team adds a third-party MCP server so their assistant can search an external knowledge base. Which risk is specific to fetching tool definitions at runtime, rather than being a general tool-use risk?","options":[{"text":"The tool might return data the user is not authorised to see.","correct":false,"tempting":"A genuine authorisation problem, but it exists identically for hand-written local tools and is not created by runtime discovery."},{"text":"The model might call the tool with wrong arguments.","correct":false,"tempting":"Occurs with any tool surface and is addressed by schema and description quality regardless of how the definition arrived."},{"text":"The server can change a tool's description after approval, injecting instructions into the prompt that nobody on the team reviewed.","correct":true},{"text":"Network latency adds to every tool call, slowing the loop.","correct":false,"tempting":"A real operational cost of remote servers, but a performance concern rather than a trust boundary that runtime definitions introduce."}]},"prev":{"slug":"writing-the-agent-loop","title":"Writing the loop, with the stopping conditions","url":"https://addaly.com/learn/building-with-ai/writing-the-agent-loop"},"next":{"slug":"running-code-safely","title":"Letting a model run code without letting it run your machine","url":"https://addaly.com/learn/building-with-ai/running-code-safely"},"authorship":"Founder and series editor: Dr Mustafa Mun. Written by AI models to a written standard. Exam keys checked blind by a second model: 3,665 of 3,666 agreed. Academic review invited.","review":{"status":"Draft, open for academic review"},"cite":"Addaly (2026) 'MCP: what a tool protocol buys you, and what it costs', in Building with AI. Edited by M. Mun. Addaly. Available at: https://addaly.com/learn/building-with-ai/mcp-and-tool-protocols (Accessed: 13 October 2026).","licence":{"name":"CC BY-NC-SA 4.0","url":"https://creativecommons.org/licenses/by-nc-sa/4.0/"},"reader":{"schema":1,"title":"MCP: what a tool protocol buys you, and what it costs","courseTitle":"Building with AI","module":{"index":3,"slug":"structure-tools-and-the-loop","title":"Structure, tools and the loop"},"answer":null,"keyIdea":"MCP standardises tool discovery so capabilities become a deployment concern rather than a code change, at the cost of a new trust boundary: server-supplied descriptions enter your prompt and can change after you approved them.","hero":{"kind":"plate","image":null,"alt":null,"caption":null},"blocks":[{"t":"h2","id":"the-problem-it-solves","runs":[{"text":"The problem it solves"}]},{"t":"p","runs":[{"text":"Without a standard, every combination of application and data source needs its own connector. Five applications and eight systems is forty integrations, each with its own auth handling, its own schema conventions, and its own bugs."}]},{"t":"p","runs":[{"text":"The "},{"text":"Model Context Protocol","b":true},{"text":" is an attempt to make that five plus eight instead of forty. A "},{"text":"server","b":true},{"text":" exposes capabilities; a "},{"text":"client","b":true},{"text":" (an assistant, an IDE, an agent) consumes them. Anything that speaks the protocol can talk to anything else that does, and the maintainer of a system writes one server rather than one connector per consumer."}]},{"t":"p","runs":[{"text":"Three kinds of capability, and the distinction matters:"}]},{"t":"ul","items":[[{"text":"Tools","b":true},{"text":": actions the model may invoke. This is what most servers ship."}],[{"text":"Resources","b":true},{"text":": content the client can read and attach to context, addressed by URI. Selected by the application or the user, not the model."}],[{"text":"Prompts","b":true},{"text":": reusable templates a user can invoke deliberately."}]]},{"t":"p","runs":[{"text":"The useful part of that split is the third column, which is "},{"text":"who decides","i":true},{"text":". Tools are model-driven; resources are application-driven; prompts are user-driven. Systems that blur it end up with a model deciding to read things nobody meant it to read."}]},{"t":"h2","id":"what-it-actually-is","runs":[{"text":"What it actually is"}]},{"t":"p","runs":[{"text":"JSON-RPC over one of two transports: "},{"text":"stdio","b":true},{"text":" for a server running as a local subprocess, and "},{"text":"streamable HTTP","b":true},{"text":" for a remote one. The client starts a session, calls "},{"text":"tools/list","code":true},{"text":" to discover what exists, and then "},{"text":"tools/call","code":true},{"text":" to invoke."}]},{"t":"code","lang":"json","label":"JSON","text":"{\"jsonrpc\":\"2.0\",\"id\":3,\"method\":\"tools/call\",\n \"params\":{\"name\":\"search_tickets\",\n           \"arguments\":{\"query\":\"refund not received\",\"limit\":5}}}"},{"t":"p","runs":[{"text":"Underneath, nothing changes about the model. The tool list is fetched from a server rather than hard-coded, and the result comes back over a socket instead of a function call. Every lesson about tool design still applies exactly: good names, negative clauses in descriptions, tight schemas, identity never in the arguments."}]},{"t":"h2","id":"when-it-is-worth-it","runs":[{"text":"When it is worth it"}]},{"t":"p","runs":[{"text":"Use a protocol when the set of tools is not known at build time.","b":true},{"text":" An assistant that different customers connect to their own systems; an IDE where the user adds capabilities; an internal platform where six teams each expose their own service without touching your codebase. Here the indirection pays for itself."}]},{"t":"p","runs":[{"text":"Do not use one when you have four tools and control both ends.","b":true},{"text":" Four Python functions in a dictionary is less code, has fewer moving parts, no subprocess to supervise, no session to reconnect, and one less thing to be down at three in the morning. A protocol solves a coupling problem, and if you do not have a coupling problem it is pure overhead."}]},{"t":"p","runs":[{"text":"The honest middle case is that MCP is worth adopting early if you expect third parties to extend your product, and worth deferring if you do not."}]},{"t":"h2","id":"the-security-surface-stated-plainly","runs":[{"text":"The security surface, stated plainly"}]},{"t":"p","runs":[{"text":"This is the part that deserves your attention, because a tool protocol moves trust boundaries."}]},{"t":"p","runs":[{"text":"A server you install runs on your machine with your permissions.","b":true},{"text":" A stdio server is a subprocess. It can read your files, your environment variables and your keys. Installing one from an unfamiliar source is exactly as consequential as running any other program from that source, and the packaging makes it feel lighter than it is."}]},{"t":"p","runs":[{"text":"Tool descriptions come from the server and go into your prompt.","b":true},{"text":" A malicious or compromised server can put instructions in a description: text that the model reads as guidance and that you never see. This is prompt injection arriving through the metadata channel rather than through user content, and it is specific to protocols that fetch definitions at runtime."}]},{"t":"p","runs":[{"text":"Definitions can change after you approved them.","b":true},{"text":" A server can serve one description on Monday and a different one on Friday. If your approval was a one-time decision, it was a decision about a thing that no longer exists. Pin versions where you can, hash the tool definitions, and re-prompt on change."}]},{"t":"p","runs":[{"text":"Tokens are usually broader than the task.","b":true},{"text":" Connecting a server to a whole workspace when the job needs one folder is the common shape, and it means a single confused tool call can reach everything."}]},{"t":"p","runs":[{"text":"Mitigations that are worth the effort: run servers with the narrowest credentials that work, keep an allowlist of servers rather than installing freely, log every "},{"text":"tools/call","code":true},{"text":" with its arguments, require confirmation for writes, and treat tool "},{"text":"results","i":true},{"text":" as untrusted text: a server returning a document containing “ignore previous instructions” is the ordinary case, not the exotic one."}]},{"t":"h2","id":"the-thing-to-take-away","runs":[{"text":"The thing to take away"}]},{"t":"p","runs":[{"text":"A protocol changes the plumbing, not the physics. The model still cannot run anything; your client does. Authorisation is still your job and still belongs to the session, not the arguments. Every tool is still a place where text from outside your system enters your model’s context."}]},{"t":"p","runs":[{"text":"What MCP gives you is that the tools available to your assistant become a deployment concern rather than a code change, which is a large operational win and a new place to be careful."}]}],"check":{"question":[{"text":"A team adds a third-party MCP server so their assistant can search an external knowledge base. Which risk is specific to fetching tool definitions at runtime, rather than being a general tool-use risk?"}],"options":[{"text":[{"text":"The tool might return data the user is not authorised to see."}],"correct":false,"tempting":[{"text":"A genuine authorisation problem, but it exists identically for hand-written local tools and is not created by runtime discovery."}]},{"text":[{"text":"The model might call the tool with wrong arguments."}],"correct":false,"tempting":[{"text":"Occurs with any tool surface and is addressed by schema and description quality regardless of how the definition arrived."}]},{"text":[{"text":"The server can change a tool’s description after approval, injecting instructions into the prompt that nobody on the team reviewed."}],"correct":true,"tempting":null},{"text":[{"text":"Network latency adds to every tool call, slowing the loop."}],"correct":false,"tempting":[{"text":"A real operational cost of remote servers, but a performance concern rather than a trust boundary that runtime definitions introduce."}]}],"order":[3,1,2,0],"why":null},"prev":{"slug":"writing-the-agent-loop","title":"Writing the loop, with the stopping conditions","minutes":10},"next":{"slug":"running-code-safely","title":"Letting a model run code without letting it run your machine","minutes":9}}}