MCP explained: tools, resources, prompts and the current hype gap
MCP gives teams a standard way to let models discover and call tools, read resources, and use prompt templates — all over JSON-RPC. The hype gap appears when people assume a protocol automatically solves integration, safety or product design problems that still need to be handled explicitly. A standard interface is helpful. A standard interface is not the same as a complete product.
Quick answer
Understand MCP as a transport and description layer for model-connected capabilities. Then check permissions, stability and operational control before you assume it is production-ready. If you only need one model calling one known API, a custom function-calling wrapper is probably simpler than running an MCP server.
What this means: tools, resources and prompts — concretely
MCP organises what a model can do into three primitives. Here is what each looks like on the wire.
Tools
A tool is a function the model can invoke. The server advertises tools via tools/list, and the client calls them via tools/call. Each tool has a name, description, and JSON Schema input definition.
Minimal tool definition (what the server returns in tools/list):
{
"name": "read_file",
"description": "Read the contents of a file at a given path",
"inputSchema": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Absolute path to the file"
}
},
"required": ["path"]
}
}
The model sees the name, description and schema — it does not execute the call directly. The model proposes arguments ({"path": "/home/user/config.json"}), the client sends a tools/call request, and the server returns the result.
Spec ref: Tool interface (§tools/list), CallToolRequest (§tools/call) — MCP specification v2025-11-25.
Resources
A resource is data the server can serve — a file, a database row, an API response. Resources are identified by URI. The server advertises them via resources/list, and the client reads them via resources/read.
Resource URI examples:
file:///home/user/project/config.json— file system contentpostgres://orders/recent?limit=10— database query resulthttps://api.example.com/v2/status— HTTP resource (proxied)
A resources/read request returns the content:
{
"contents": [{
"uri": "file:///home/user/project/config.json",
"mimeType": "application/json",
"text": "{\"port\": 3000, \"debug\": false}"
}]
}
Spec ref: Resource interface, ReadResourceRequest (§resources/read) — MCP specification v2025-11-25.
Prompts
A prompt is a pre-written template the server provides. Unlike tools (which execute) or resources (which serve data), prompts give the model structured instructions. They can include argument slots for templating.
Prompt template example:
{
"name": "code_review",
"description": "Review a pull request for common issues",
"arguments": [
{
"name": "pr_number",
"description": "The PR number to review",
"required": true
}
]
}
A client calls prompts/get with {"name": "code_review", "arguments": {"pr_number": "42"}} and receives a PromptMessage containing the rendered instructions.
Spec ref: Prompt interface, GetPromptRequest (§prompts/get) — MCP specification v2025-11-25.
How they fit together
| Primitive | Model discovers via | Client action | Server returns |
|---|---|---|---|
| Tool | tools/list | tools/call with arguments | CallToolResult (content + optional structured data) |
| Resource | resources/list | resources/read with URI | ReadResourceResult (text or blob contents) |
| Prompt | prompts/list | prompts/get with name + args | GetPromptResult (rendered message) |
All of this runs over JSON-RPC 2.0, either over stdio (local subprocess) or SSE (remote server). The transport is separate from the capability — a design choice that keeps the protocol flexible but means the two sides can disagree on implementation details.
Where teams get it wrong — with real scenarios
Mistake 1: Treating MCP as if it were a magic agent framework.
A team wires MCP file-system tools into a coding agent with no tool-call approval step. The agent spots what it thinks is a stale config file and deletes it. The fix: every tool call needs an explicit approval gate, the same as any other automation that can modify state. MCP gives you the plumbing, not the safety policy.
Mistake 2: Exposing tools without access control or audit logging.
A developer spins up a filesystem MCP server on a staging VPS with no auth, connected to a public endpoint. Any model that discovers the server can read every file the process has access to. The fix: put MCP servers behind authentication, scope tool permissions to the minimum needed, and log every tools/call invocation. The spec does not mandate auth — you have to add it yourself.
Mistake 3: Assuming every client and server implementation will match perfectly.
Two MCP servers both expose a write_file tool, but one expects an absolute path and one expects a path relative to a working directory. The model has no way to tell the difference from the description alone. The fix: write tool descriptions precisely enough that a model can pick the right server, and test with the actual client you will use.
Mistake 4: Running MCP where a simpler integration would do.
If you are integrating one model with one known API (a single database, a single search endpoint), writing a thin HTTP wrapper is often faster than setting up an MCP server, writing the tool definitions, and running the server process. MCP earns its keep when you have multiple tools from multiple providers or want the model to dynamically discover what is available.
Practical decision check
-
Do you need a standard interface, or just a thin custom integration?
Scoring heuristic: If you need to expose fewer than three tools to one model, a custom function-calling wrapper is simpler than running an MCP server. If you have tools from multiple sources or want the model to discover them dynamically, MCP starts to pay for itself. -
Who controls what the model can call?
Everytools/callrequest should pass through an approval layer — human-in-the-loop for destructive operations, rate-limited automatic approval for read-only tools. MCP does not provide this. You do. -
What happens when a tool is missing or mis-described?
The model will either hallucinate a call that does not exist or misinterpret the arguments. Graceful failure handling — “tool not found” responses, clear error messages, and model training on what to do when discovery returns empty — is your responsibility, not the protocol’s.
What would change the advice
MCP is not always the right choice. Here is when the balance tips away from it:
- Single-model, single-API integration. If the model talks to one database or one API, a custom wrapper with function calling is less overhead. MCP adds a server process, schema definitions, and transport negotiation for zero benefit in this case.
- Latency-sensitive tool calls. stdio transport introduces subprocess overhead. SSE transport introduces network round-trips. If you need tool results in under 100ms, evaluate whether a direct function-call integration is faster, or whether you need an in-process transport.
- Teams that cannot maintain a server process. MCP servers need to be deployed, monitored and restarted. If your team does not have the operational capacity for one more daemon, MCP will become tech debt.
- Immature or rapidly changing tool surface. If your tool definitions change daily, the model’s understanding of available tools will lag behind. MCP’s
tools/list_changednotification helps, but rapid churn still degrades reliability.
Real MCP servers you can inspect today
These reference servers from the @modelcontextprotocol organisation are open-source and show real tool definitions:
- filesystem (
server-filesystem): exposesread_file,write_file,list_directory,search_filesand similar — useful for coding agents but dangerous without approval gates. - github (
server-github): exposes tools for PR review, issue management, file operations on repos — a good example of wrapping an external API behind MCP. - postgres (
server-postgres): exposes database schema and query tools — demonstrates resource URIs (postgres://...) and read-only vs. write tool patterns. - brave-search (
server-brave-search): exposes web search tools — a simple example of a tool that takes a query string and returns structured results.
Each of these servers is a working, inspectable example of MCP tool definitions in practice. Reading their source is the fastest way to understand what a good tool description looks like.
What this page cannot tell you
This page cannot tell you whether MCP is the right choice for your exact stack. It can only help you separate useful standardisation from protocol-shaped hype. If the advice above changes — particularly around transport options, auth requirements or tool-discovery guarantees — this page should be rechecked against the current spec.
Methodology and sources
Check date: 2026-05-25
What was checked: MCP specification v2025-11-25, protocol schema, reference server implementations, Anthropic MCP documentation, OpenAI function-calling documentation
What the sources were used for:
- MCP specification v2025-11-25 (§tools/list, §tools/call, §resources/read, §prompts/list, §prompts/get) — concrete tool/resource/prompt definitions and JSON-RPC structure
- Anthropic MCP documentation (docs.anthropic.com) — server implementation patterns and reference server descriptions
- OpenAI function-calling docs — comparison point for alternative approaches (used in the “What would change the advice” section)
- Reference server source code (@modelcontextprotocol/server-filesystem, server-github, server-postgres, server-brave-search) — real tool definitions and usage patterns
Assumptions and limits:
- MCP implementations continue to evolve; the examples above reflect the v2025-11-25 spec
- Tool description quality varies by server — the reference servers above represent best-practice examples
- This is integration guidance, not a blanket recommendation for or against MCP
- Auth, rate-limiting and audit-logging recommendations draw from OWASP Top 10 for LLM Applications (owasp.org), not from MCP specification requirements
What would need re-checking:
- If MCP adds built-in auth or permission primitives in a future spec version
- If transport options expand beyond stdio and SSE
- If the
tools/list_changednotification behaviour changes (particularly rate guarantees)
Related guides
- Function calling and tool use: where agents actually fail
- AI agents vs workflows: a plain-English difference for teams
- Prompt versioning: treating prompts like production code
Change log
- 2026-05-24: first draft built from the llm-editor-approved brief.
- 2026-05-25: revised per editorial review (LLM-0065). Added concrete tool/resource/prompt examples with JSON structures, real MCP server names, expanded scenarios, “what would change the advice” section, inline spec citations, fixed related-guide links to production routes, and rewrote source-use descriptions.
Source list
- Model Context Protocol specification v2025-11-25 — https://spec.modelcontextprotocol.io/ (schema: https://raw.githubusercontent.com/modelcontextprotocol/specification/main/schema/2025-11-25/schema.ts)
- Anthropic MCP documentation — https://docs.anthropic.com/en/docs/agents-and-tools/mcp
- OpenAI function calling — https://platform.openai.com/docs/guides/function-calling
- OWASP Top 10 for LLM Applications — https://owasp.org/www-project-top-10-for-large-language-model-applications/
- Reference MCP servers: server-filesystem, server-github, server-postgres, server-brave-search — https://github.com/modelcontextprotocol