Creating Requests
Build a function to create valid JSON-RPC 2.0 requests.
In this lesson:
- Filename in header (e.g.,
jsonrpc.py) = Write this code to that file - "Add after X" = Append this code to your existing file
- bash blocks = Commands to run in your terminal
- "Expected Output" = What you should see (don't write this)
Create: jsonrpc.py
Create a new file called jsonrpc.py. This will be your JSON-RPC utility
module that you'll build up throughout this lesson.
"""
jsonrpc.py - JSON-RPC 2.0 utilities for MCP.
This module provides functions for creating and handling JSON-RPC messages.
"""
import json
from typing import Any
def create_request(
method: str,
params: dict | None = None,
request_id: int | None = None
) -> dict:
"""
Create a JSON-RPC 2.0 request.
Args:
method: The method name to call (e.g., "tools/list")
params: Optional parameters for the method
request_id: Unique identifier for matching responses
Returns:
A properly formatted JSON-RPC request dict
"""
request: dict[str, Any] = {
"jsonrpc": "2.0",
"method": method,
}
if request_id is not None:
request["id"] = request_id
if params is not None:
request["params"] = params
return request
# =============================================================================
# Try it out
# =============================================================================
if __name__ == "__main__":
# Create a simple request
req1 = create_request("tools/list", request_id=1)
print("Request 1 (tools/list):")
print(json.dumps(req1, indent=2))
print()
# Create a request with parameters
req2 = create_request(
method="tools/call",
params={"name": "calculator", "arguments": {"expression": "2 + 2"}},
request_id=2
)
print("Request 2 (tools/call with params):")
print(json.dumps(req2, indent=2))
Try It
Run your new module:
python jsonrpc.py
Expected Output
Request 1 (tools/list):
{
"jsonrpc": "2.0",
"method": "tools/list",
"id": 1
}
Request 2 (tools/call with params):
{
"jsonrpc": "2.0",
"method": "tools/call",
"id": 2,
"params": {
"name": "calculator",
"arguments": {
"expression": "2 + 2"
}
}
}
Understanding the Code
The Four Fields
A JSON-RPC 2.0 request has four possible fields:
| Field | Required? | Description |
|---|---|---|
jsonrpc |
Yes | Must be exactly "2.0" |
method |
Yes | The method name to call |
id |
For requests | Unique identifier (string or int) |
params |
No | Parameters for the method |
Type Annotations
Notice the type hints use dict | None syntax. This tells Python
(and your IDE) that the parameter can be either a dict or None:
# This is the modern Python 3.10+ syntax
params: dict | None = None
# Equivalent to the older typing.Optional syntax:
# from typing import Optional
# params: Optional[dict] = None
The id field lets you match responses to requests. When you send
multiple requests concurrently, responses might arrive out of order. The ID
tells you which response belongs to which request.
What's Next
Your module can create requests, but what about responses? In the next step, you'll add functions to create success responses, error responses, and handle JSON-RPC error codes.