These notes explain MCP in simple English, with practical examples, diagrams, code snippets, interview answers, and revision points. They follow the uploaded chapter's core concepts and terminology.
1. Why do we need MCP?
Imagine a company has a task-tracking system and wants to add AI features to five applications:
- A customer-support chatbot
- A Slack bot
- An internal admin assistant
- A code-editor plugin
- A command-line AI assistant
All five applications need to create, list, and complete tasks.
Without MCP, each application builds its own integration with the task service.
Without MCP
Each app maintains its own integration, validation and error handling.
Suppose the task service introduces a new required field called dueDate. Every application must update its integration. If one team forgets, its integration breaks.
This is a traditional software integration problem, not a problem unique to AI.
The N × M integration problem
Assume there are:
- N AI applications
- M external systems
Without a shared protocol, the number of integrations can grow to N × M.
For example, five applications accessing ten systems may require:
5 × 10 = 50 integrationsWith MCP, each app learns one common protocol, and each system exposes its capabilities through an MCP server.
N × M → N + MIn this example, that means roughly 15 integration components instead of 50, assuming one reusable connection per app and one MCP wrapper per system.
Memory trick: MCP is like USB. Instead of building a different connector for every device, you use a common standard.
2. What is MCP?
Model Context Protocol (MCP) is a standard protocol that allows AI applications to discover and use external tools and data through a common interface.
An AI application can use MCP to connect to systems such as:
- GitHub
- Jira
- Slack
- Task-management services
- Databases
- File systems
- Calendar APIs
- Internal company services
MCP does not create these capabilities. It standardizes how AI applications discover and access them.
MCP uses JSON-RPC
MCP messages use JSON-RPC 2.0, a format for sending requests and receiving results between programs.
A simplified request looks like this:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}Meaning:
jsonrpc: the protocol format versionid: identifies the request so the response can be matchedmethod: the operation being requestedparams: optional input arguments for the method
The server responds with the same request ID and either a result or an error.
3. The three main components of MCP
This is the most important concept in the chapter.
1. Host: the AI application
Examples: an AI assistant, a code editor with AI, or your own Spring AI application.
The host manages the model, conversation, permissions and approval rules.
2. MCP Client: the connector
It communicates with one MCP server, discovers available tools and sends tool-call requests.
3. MCP Server: the capability provider
It exposes tools and potentially resources and prompts. It runs ordinary code to perform the requested operation.
Example: the server calls an existing task service or database.
3.1 Host
The host is the application that the user interacts with.
Responsibilities:
- Receives the user's message.
- Sends the message and available tool definitions to the LLM.
- Receives the model's proposed tool call.
- Checks permissions and whether approval is needed.
- Tells the MCP client to execute allowed calls.
- Returns results to the model and eventually responds to the user.
Important: The model can request a tool, but the host decides whether the tool is allowed to run.
3.2 MCP client
The MCP client is a component inside the host.
Responsibilities:
- Connects to an MCP server.
- Discovers tools using
tools/list. - Sends tool requests using
tools/call. - Receives tool results.
- Handles protocol communication.
A host connected to three MCP servers generally maintains three client connections, one per server.
Analogy: If the host is your Java application and an MCP server is a database, the MCP client plays a role similar to a database driver.
3.3 MCP server
The MCP server exposes capabilities through MCP.
For example, a task server may provide:
create_task(title)
list_tasks()
complete_task(title)Internally, these tools can call existing business logic, REST APIs, databases, files or message queues.
The server controls which capabilities it exposes. A database MCP server could provide a read-only query tool without exposing a destructive operation such as dropping a table.
3.4 Does an MCP server need an LLM?
No. An MCP server does not need an LLM or an AI API key.
It can be an ordinary Spring Boot, Node.js or Python application. The model normally lives in the host; the server simply executes the requested business logic.
4. Tool calling vs MCP
These two concepts work together, but they solve different problems.
| Concept | Main question | Responsibility |
|---|---|---|
| Tool calling | Which tool should run, and with what arguments? | The model proposes the call |
| MCP | Where do the tools come from, and how does the app reach them? | The protocol standardizes discovery and execution |
Consider the request:
"Remind me to renew my car insurance."
The model may choose:
{
"name": "create_task",
"arguments": {
"title": "Renew car insurance"
}
}Tool calling determines that create_task is appropriate and supplies its arguments.
MCP allows the host to send that request to the remote task server through tools/call.
Interview-ready answer: Tool calling decides which capability to use. MCP provides a standard way to discover and access that capability. MCP does not replace tool calling.
5. How does MCP work end to end?
Let's follow the complete request:
User: "Remind me to renew my car insurance."
- Discover tools: The MCP client asks the task server for its available tools using
tools/list. - Send tools to the model: The host converts the tool definitions into the format expected by its model API.
- Choose a tool: The LLM selects
create_taskand supplies the title argument. - Check permissions: The host checks whether the requested operation is allowed and whether approval is required.
- Execute the tool: The MCP client sends
tools/callto the task server. - Run business logic: The server validates the title and creates the task.
- Return the result: The result returns to the host, which provides it to the LLM.
- Respond to the user: The model generates a natural-language response.
The tool discovery step generally happens at connection or startup and can be cached. It does not have to happen before every user message.
A critical distinction
- The LLM does not directly connect to the MCP server.
- The MCP server does not need to know which LLM selected the tool.
- The host coordinates the interaction.
- The server executes code; the model interprets the result.
6. tools/list: Discovering tools
tools/list asks an MCP server which tools it offers.
Example request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list"
}A simplified response:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "create_task",
"description": "Create a pending task.",
"inputSchema": {
"type": "object",
"properties": {
"title": {
"type": "string",
"minLength": 1,
"maxLength": 120
}
},
"required": ["title"]
}
}
]
}
}Each tool definition contains three key parts:
- Name: The identifier used to call the tool.
- Description: What the tool does and when it should be used.
- Input schema: The structure and constraints of its arguments.
The host learns these definitions dynamically rather than having to hardcode every tool.
Why do tool descriptions matter?
Suppose a model needs to complete a task but does not know its exact title.
A good description might say:
"Call
list_tasksfirst if you are unsure of the exact task title."
The model can then list the tasks before attempting to complete one.
Treat tool descriptions like public API documentation: unclear descriptions can cause incorrect tool selection.
7. Schemas: a contract between programs
A tool's input schema defines the arguments the tool expects.
For example:
{
"type": "object",
"properties": {
"title": {
"type": "string",
"minLength": 1,
"maxLength": 120
}
},
"required": ["title"]
}This describes the expected structure, but it does not guarantee that a task title is unique or that the user has permission to create a task.
The server must still validate business rules.
This is similar to structured output from an LLM:
- Structured output schema: Defines the shape of the model's response.
- Tool input schema: Defines the shape of the model's tool arguments.
- Business validation: Checks whether the requested action is actually valid.
8. tools/call: Executing a tool
After the model selects a tool, the host instructs the MCP client to call it.
Example request:
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "create_task",
"arguments": {
"title": "Renew car insurance"
}
}
}A simplified response:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "Task created: Renew car insurance"
}
],
"isError": false
}
}The response contains content blocks, such as text, and an isError flag indicating whether the tool reported an execution error.
The client converts the returned content into tool output for the host and model.
9. Handling errors and retries
MCP distinguishes between two kinds of failure.
A. Tool execution error
The server ran the tool, but the operation could not be completed.
Example: the user asks to complete a task named Car Insurance, but the actual title is Renew car insurance.
The server returns a tool result with isError: true and a useful message. The model may then call list_tasks and retry with the correct title.
B. Protocol or transport error
The request could not be handled properly, such as when the server is unavailable, the request names an unknown tool, or a call times out.
The host or client must handle this failure, log it and decide what to communicate to the user.
Why blind retries are dangerous
Imagine a payment tool times out. The payment might have succeeded even though the client never received the response.
Retrying without protection could charge the customer twice.
Use an idempotency key: a unique identifier that lets the server recognize repeated requests and avoid repeating the same side effect.
For task creation, the example server also rejects duplicate pending titles, which helps make a retry safe for that specific operation. This is not a general replacement for idempotency keys.
10. MCP transports: stdio vs Streamable HTTP
A transport determines how MCP messages travel between the client and server.
| Feature | stdio | Streamable HTTP |
|---|---|---|
| Connection | Host starts a child process | Server runs on a port |
| Typical use | Local editor tools and file access | Shared or deployed services |
| Network access | Normally local to the host process | Accessible to clients that can reach the URL |
| Authentication | Often not needed for a trusted local process, but permissions still matter | Required for shared or remotely reachable services |
| Main concern | Server output must not corrupt the protocol stream | Authentication, network security and local-host protections |
stdio example
An AI code editor starts an MCP server as a local process. The client writes requests to the process's standard input and reads responses from standard output.
Be careful: a local MCP server may run with your user permissions, potentially allowing access to local files or credentials.
Streamable HTTP example
Your Spring Boot task server listens at an endpoint such as:
http://localhost:8081/mcpThe host sends MCP requests over HTTP.
For production, the server needs appropriate authentication, authorization, secure deployment and network protections.
11. MCP and REST API: Do they replace each other?
No. MCP and REST solve different integration needs and can work together.
A web frontend or mobile app can continue using the same REST API directly.
| REST API | MCP server |
|---|---|
| Exposes HTTP endpoints | Exposes capabilities through MCP |
| Commonly used by application code | Designed for AI applications and their hosts |
| Often documents endpoints with OpenAPI | Provides tool discovery through tools/list |
| May expose lower-level operations | Can expose higher-level actions with model-oriented descriptions |
An MCP server can act as an AI-friendly layer over an existing REST API. You do not need to rewrite the business logic.
12. Tools, resources and prompts
MCP can expose more than executable tools.
| Capability | Purpose | Example |
|---|---|---|
| Tools | Perform actions | create_task, complete_task |
| Resources | Provide information or context | A policy document or project README |
| Prompts | Provide reusable instructions or workflows | A template for planning the day |
A useful way to remember this:
- Tools: Do something.
- Resources: Provide something to know or read.
- Prompts: Provide reusable instructions.
These are distinct concepts. A resource is not the same as RAG (Retrieval-Augmented Generation). A resource can be fetched by its address, while RAG typically retrieves relevant chunks from a larger collection. An MCP tool can itself run a RAG pipeline.
13. Security: the host is still responsible
MCP standardizes communication. It does not automatically make a tool safe.
The host should enforce security rules before allowing tool execution.
Important security practices
- Allow-list tools. Expose only the tools the application needs.
- Require approval for risky actions. For example, deleting a repository, sending an email or making a payment.
- Authenticate shared servers. Use appropriate credentials and per-user authorization.
- Use least privilege. A server should receive only the permissions required for its work.
- Treat tool output as untrusted data. A tool result might contain prompt-injection text instructing the model to ignore its rules.
- Review changes to tool definitions. A server could introduce a new destructive tool or change an existing tool's behavior.
- Protect local servers. Bind them to loopback when they are meant to be local and apply the relevant host-header protections.
Example: a destructive tool
Suppose an MCP server offers:
delete_repository(repositoryName)Even if the model requests this tool, the host should check its policy and potentially require user confirmation before sending tools/call.
The model's choice is a request, not authorization.
14. Performance and production considerations
MCP adds a connection layer, so it comes with operational costs.
14.1 Cache the tool list
The server's available tools do not usually change with every user message.
A host can cache tools/list and refresh it periodically or when the server signals that the list changed.
Benefits:
- Fewer discovery round trips
- Lower latency
- Reduced overhead
But caching has a trade-off: newly added tools might not appear until the cache refreshes.
14.2 Avoid exposing every tool
Every tool definition sent to the model consumes input tokens. Too many tools can increase costs and make it harder for the model to choose the correct one.
Expose the tools relevant to the host's task instead of blindly passing through every capability from every server.
14.3 Handle name collisions
Two connected servers might both offer a tool called search.
The host needs a naming strategy, such as server prefixes, so it can identify the correct tool.
14.4 Use timeouts and step limits
A slow tool can delay the entire response. Configure sensible timeouts and stop the model-tool loop after a maximum number of steps to prevent runaway loops.
14.5 Treat tool definitions as a public API
Changing a tool name or making an optional field required may break clients.
Prefer backward-compatible changes: introduce the new interface, migrate clients and remove the old interface only when it is safe.
15. Building an MCP task assistant with Spring Boot
The chapter's example has two applications:
Task client: port 8080
- Receives the user's request.
- Calls the LLM.
- Uses an MCP client to discover and call remote tools.
- Returns the final answer.
Task server: port 8081
- Exposes
create_task,list_tasksandcomplete_task. - Validates inputs.
- Runs the task store's business logic.
- Does not need an LLM.
The example exposes these client endpoints:
| Endpoint | Purpose |
|---|---|
POST /api/ask | Accepts a message and runs the assistant loop |
GET /api/tools | Returns the discovered tool list without making a model call |
The chapter specifies a 400 response for invalid messages, such as an empty message or one exceeding the configured length, and a 502 when the model or task server fails. These are behaviors of the example application, not universal MCP status-code requirements.
15.1 Defining a tool in Spring AI
The example uses annotations to expose Java methods as MCP tools:
@McpTool(
name = "create_task",
description = "Add a new pending task. Titles must be unique among pending tasks."
)
public String createTask(
@McpToolParam(
description = "Short title of the new task",
required = true
) String title
) {
return "Task created: " + store.create(title);
}Conceptually:
@McpToolexposes the method as a tool.nameidentifies the tool.descriptionhelps the model understand when to use it.@McpToolParamdescribes the argument.- The method calls ordinary business logic in
store.create(title).
The Spring AI MCP server integration uses method signatures and annotations to construct the tool definition.
15.2 Configuring the MCP client
The example configures a Streamable HTTP connection in YAML:
spring:
ai:
mcp:
client:
request-timeout: 20s
streamable-http:
connections:
task-server:
url: ${TASK_SERVER_URL:http://localhost:8081}
endpoint: /mcp
toolcallback:
enabled: trueThis tells the client where the MCP server is and configures the tool-callback integration. The starter handles the protocol details, including discovery and remote calls.
15.3 Connecting remote tools to the LLM
The key idea in the example is that the model receives callbacks created from remote MCP tool definitions.
public TaskAssistant(
ChatClient.Builder builder,
ToolCallbackProvider mcpTools
) {
this.chatClient = builder
.defaultSystem(SYSTEM_PROMPT)
.build();
this.mcpTools = mcpTools;
}
public String reply(String message) {
String reply = chatClient.prompt()
.user(message)
.toolCallbacks(mcpTools.getToolCallbacks())
.call()
.content();
if (reply == null || reply.isBlank()) {
throw new IllegalStateException(
"The model returned an empty reply"
);
}
return reply;
}The important line is:
.toolCallbacks(mcpTools.getToolCallbacks())The model can use the discovered remote tools without the client application hardcoding each tool's definition.
Remember: The business logic belongs to the server. The host owns the model and the decision loop. The MCP client connects the two.
16. When should you use MCP?
Use MCP when:
- Multiple AI applications need the same tools.
- You want your service to be usable by AI hosts you do not control.
- You want a standard way to discover and invoke external capabilities.
Avoid adding MCP when:
- Only one application needs a few local tools.
- The workflow is a fixed pipeline and the model does not choose tools.
- An extra network hop would violate a strict latency requirement.
- Several operations must succeed or fail as one atomic transaction.
- You cannot secure the MCP server properly.
For a single application with a few tools, local functions are often simpler. For multiple AI clients sharing many capabilities, MCP can reduce duplicated integration work.
17. Quick revision notes
| Term | Meaning |
|---|---|
| MCP | A standard protocol for discovering and accessing external capabilities. |
| Host | The AI app that owns the model, conversation and permission decisions. |
| MCP client | The component that communicates with one MCP server. |
| MCP server | A program that exposes tools and other capabilities. |
tools/list | Discovers tool names, descriptions and input schemas. |
tools/call | Requests execution of a named tool with arguments. |
| Tool calling | The model proposes which tool to use and supplies its arguments. |
| stdio | A local process communication transport. |
| Streamable HTTP | A network transport for communicating with an MCP server over HTTP. |
| Idempotency key | A unique request identifier that helps prevent duplicate side effects on retries. |
The entire chapter in three lines
- Tool calling: The model chooses a capability and proposes its arguments.
- MCP: The host discovers and accesses capabilities through a common protocol.
- Security: The host still decides what is allowed; the server validates and executes the operation.
18. Interview questions and answers
"What problem does MCP solve?"
MCP reduces duplicated integrations between AI applications and external systems. Each app can use a common protocol, while each system exposes its capabilities through an MCP server.
"What is the difference between an MCP host, client and server?"
The host manages the model and permissions. The client handles MCP communication with a server. The server exposes tools and runs their business logic.
"Does an MCP server require an LLM?"
No. It can be an ordinary application that exposes functions and executes them. The LLM generally lives in the host.
"Explain tools/list and tools/call."
tools/listdiscovers the available tools and their schemas.tools/callrequests execution of a particular tool with its arguments.
"How is MCP different from tool calling?"
Tool calling determines which tool the model wants to use. MCP provides the standardized mechanism for discovering and reaching the tool.
"How does MCP work with REST APIs?"
An MCP server can wrap an existing REST API and expose AI-friendly tools. Other applications can continue using the REST API directly.
"How should tool errors be handled?"
Return a clear tool error so the model can potentially recover. Protocol or transport errors must be handled by the client or host. Retry operations with side effects carefully, using idempotency where appropriate.
"How do you secure MCP?"
Authenticate shared servers, enforce per-user permissions, allow-list tools, require approval for risky actions and treat tool output as untrusted data.
"When would you not use MCP?"
When one application uses a few local tools, the workflow is fixed, latency is extremely tight, operations require a single atomic transaction, or the server cannot be secured.
19. Self-test
Check your understanding
- Which component decides whether a requested tool is allowed to execute?
- The MCP server only
- The host
- The model alone
- The JSON-RPC transport
- Which method discovers available tools?
- tools/call
- server/execute
- tools/list
- resources/read
- Does an MCP server need an LLM?
- Always
- Only with HTTP
- No
- Only in Spring Boot
- What does tool calling do?
- Authenticates the MCP server
- Chooses a tool and its arguments
- Replaces REST APIs
- Creates the transport
- Why can blind retries be dangerous for a payment tool?
- They change the schema
- They can repeat a successful charge
- They disable discovery
- They always cause JSON-RPC errors
- Which transport is commonly suited to a local editor plugin?
- stdio
- SMTP
- SQL
- GraphQL
Suggested revision order: First understand the three roles, then the difference between tool calling and MCP, then
tools/listandtools/call, followed by security, transports and the Spring Boot example.