At the heart of the Model Context Protocol (MCP) lies a structured and predictable communication system built on top of JSON-RPC 2.0. Every interaction between clients and servers, whether it’s triggering an action, returning a result, or sending updates follows a well-defined message format.
MCP defines three core message types:
· Requests: Used to initiate operations, always carrying a unique non-null ID to track execution.
· Responses: Returned for every request, containing either a successful result or a structured error, always mapped back to the original request ID.
· Notifications: Lightweight, one-way messages that do not expect any response, enabling asynchronous updates without overhead.
By enforcing strict rules like unique request IDs, consistent response mapping, and clear separation between request-response and fire-and-forget communication, MCP ensures reliability, traceability, and simplicity in distributed AI systems.
This messaging foundation is what enables MCP to scale across multiple clients and servers while maintaining clarity and control in every interaction.
1. Understanding Requests in MCP
A Request in the Model Context Protocol (MCP) is used to initiate an action between a client and a server. Either side can send a request depending on who needs something done.
Think of it like this "Hey, can you do this for me?" and you expect a response back.
Key Characteristics
· Every request strictly adheres to the JSON-RPC 2.0 structure.
· Every request must associate with an unique identifier, this identifier must be unique within the session. This ensures traceability, especially when multiple requests are happening in parallel.
Request Structure looks like below.
{
"jsonrpc": "2.0",
"id": "req-123",
"method": "some.method",
"params": {
"key": "value"
}
}
· jsonrpc: Always "2.0"
· id: Unique identifier (string or number)
· method: Tool/action name to execute
· params: Optional input data for the method
Example 1: Fetch Available Tools
Client asks server what tools are available.
{
"jsonrpc": "2.0",
"id": "tools-001",
"method": "tools/list"
}
No params needed here. Server will respond with a list of tools.
Example 2: Execute a Tool
Client asks server to summarize text.
{
"jsonrpc": "2.0",
"id": "tool-exec-45",
"method": "tools/execute",
"params": {
"toolName": "summarize",
"input": {
"text": "MCP is a protocol designed to..."
}
}
}
This is a command-style request. Requires structured input.
Example 3: Fetch a Resource
{
"jsonrpc": "2.0",
"id": "resource-22",
"method": "resources/get",
"params": {
"uri": "file://reports/sales-q1.txt"
}
}
Example 4: Server Requesting Client Capability
MCP is bidirectional, so servers can also send requests.
{
"jsonrpc": "2.0",
"id": "client-cap-9",
"method": "client/getCapabilities"
}
Server asks, What can you (client) support?.
Common Mistakes to Avoid
· Reusing the same request ID
· Setting "id": null
· Missing "jsonrpc": "2.0"
· Sending invalid or inconsistent params
A request in MCP is a uniquely identifiable, structured instruction sent between client and server to perform an action, always expecting a corresponding response.
2. Understanding Responses in MCP
A Response in the Model Context Protocol (MCP) is sent as a direct reply to a Request. Every request expects exactly one response, which is either:
· A successful result, or
· An error describing what went wrong
Think of it like this :Here’s what you asked for" or "Here’s why I couldn’t do it"
Key Principles
· Every request must receive exactly one response.
· The response must include the same id as the request. This ensures proper request-response matching, especially in async systems.
· A response contains either a result or an error, never both
2.1 Result Responses (Success Case)
When an operation succeeds, the response includes a result field.
{
"jsonrpc": "2.0",
"id": "req-123",
"result": {
"data": "some value"
}
}
Response must include
"jsonrpc": "2.0"
"id" (same as request)
"result" (can be any JSON structure)
Example 1: Tools List Response
{
"jsonrpc": "2.0",
"id": "tools-001",
"result": {
"tools": [
{ "name": "summarize" },
{ "name": "translate" }
]
}
}
Example 2: Tool Execution Result
{
"jsonrpc": "2.0",
"id": "tool-exec-45",
"result": {
"output": "MCP enables structured communication..."
}
}
2.2 Error Responses (Failure Case)
When something goes wrong, MCP uses a structured error format.
{
"jsonrpc": "2.0",
"id": "req-123",
"error": {
"code": 400,
"message": "Invalid parameters",
"data": {
"details": "Missing 'text' field"
}
}
}
Error object must include:
· "error" object
o code (integer)
o message (human-readable)
· data is optional (used for debugging details)
· id may be omitted only if request parsing failed.
Example 1: Invalid Tool Input
{
"jsonrpc": "2.0",
"id": "tool-exec-45",
"error": {
"code": 422,
"message": "Invalid input",
"data": {
"reason": "Text cannot be empty"
}
}
}
Example 2: Unknown Method
{
"jsonrpc": "2.0",
"id": "req-999",
"error": {
"code": 404,
"message": "Method not found"
}
}
Example 3: Malformed Request (No ID Available)
{
"jsonrpc": "2.0",
"error": {
"code": 400,
"message": "Malformed JSON"
}
}
No id because server couldn’t parse it.
Result vs Error (Quick Comparison)
|
Feature |
Result Response |
Error Response |
|
Indicates |
Success |
Failure |
|
Required Field |
result |
error |
|
ID Required |
Yes |
Yes (usually) |
|
Extra Info |
Flexible Data |
code, message, optional data |
Common Mistakes
· Sending both result and error
· Mismatched request/response IDs
· Using non-integer error codes
· Missing error message
A response in MCP is a structured reply tied to a request ID, delivering either a successful result or a well-defined error, never both
3. Understanding Notifications in MCP
A Notification in the Model Context Protocol (MCP) is a one-way message sent between a client and a server.
Unlike requests:
· It does not expect a response
· It does not include an id
Think of it like this, "Just letting you know…", no reply needed
Key Characteristics
· Notifications are sent without waiting for acknowledgment.
· No Request Tracking, no id field, no response will ever come back
· It is perfect for status updates, event signalling and progress tracking
Structure:
{
"jsonrpc": "2.0",
"method": "some.event",
"params": {
"key": "value"
}
}
· jsonrpc: Always "2.0"
· method: Event/action name
· params: Optional data payload
Example 1: Progress Update
Server notifies client about task progress:
{
"jsonrpc": "2.0",
"method": "task/progress",
"params": {
"taskId": "123",
"progress": 75
}
}
No response expected, client can update UI progress bar.
Example 2: Resource Updated Event
{
"jsonrpc": "2.0",
"method": "resources/updated",
"params": {
"uri": "file://reports/sales-q1.txt"
}
}
Used for event-driven updates, client may choose to refresh data.
Example 3: Logging / Debug Info
{
"jsonrpc": "2.0",
"method": "log/message",
"params": {
"level": "info",
"message": "Tool execution started"
}
}
Helpful for observability, no need to interrupt execution flow.
Example 4: Client-Side Signal
Client notifying server about cancellation.
{
"jsonrpc": "2.0",
"method": "task/cancel",
"params": {
"taskId": "123"
}
}
Server may act on it, but does not send a response.
Important Rules
· Do NOT include id
· Do NOT expect any response
· Do NOT retry assuming failure (no acknowledgment mechanism)
Requests Vs Notifications
|
Feature |
Request |
Notification |
|
Has ID |
Yes |
No |
|
Expects Response |
Yes |
No |
|
Use Case |
Actions / Queries |
Events / Updates |
Use notifications when:
· You don’t need confirmation
· You’re sending events or signals
· You want non-blocking communication
Avoid them when:
· You need guaranteed delivery
· You need a result or acknowledgment
In summary, Notifications in MCP are lightweight, one-way messages used for events and updates, sent without an ID and without expecting any response.
Previous Next Home
No comments:
Post a Comment