Tool calling and MCP
Anthropic-compatible tool calling on the Radium Messages API, with the full tool_use and tool_result round trip, and where MCP fits alongside it.
Tool calling and MCP
Radium supports Anthropic-compatible tool calling on the Messages API. MCP is handled by the client application, and when that client is pointed at Radium it can expose MCP-provided tools to the model through the ordinary tool-calling flow.
These two things arrive together in most conversations, and they sit at different levels of the stack, so this page covers tool calling first and then places MCP against it.
Two different layers
Tool calling — API feature
Your client sends tool definitions with the request, the model returns a tool_use block asking for one, your client runs it, and your client sends the output back as tool_result. This happens between your application and Radium.
MCP — client-side protocol The Model Context Protocol connects an application such as Claude Code to external tool servers. Those servers expose tools, and the client decides how to present them to the model. This happens on your side, before any request reaches Radium.
┌─────────────────────── runs on your side ──────────────────────────┐
│ │
│ ┌────────────────┐ MCP ┌─────────────────────┐ │
│ │ MCP server │◄─────────────────►│ Your client │ │
│ │ yours, exposing │ │ application or │ │
│ │ tools │ │ Claude Code │ │
│ └────────────────┘ └──────────┬──────────┘ │
│ │ │
└────────────────────────────────────────────────────┼───────────────┘
│ tools
│ tool_use
│ tool_result
▼
┌─────────────────────┐
│ Radium │
│ POST /v1/messages │
└─────────────────────┘
MCP runs horizontally, on your infrastructure, between your client and your tool servers. Tool calling runs vertically, between your client and Radium. Radium answers the model half and never talks to your MCP server.
What is supported
- Tool definitions in the
toolsrequest field - JSON Schema-style
input_schemadefinitions - Model responses containing
tool_usecontent blocks - Returning tool outputs with
tool_resultcontent blocks - Multiple available tools in a single request
- Streaming responses with tools
All of it on the same endpoint you are already calling.
The round trip
Three turns. Your client does two of them.
Turn one — send the request with your tool definitions
curl -s https://api.radium.cloud/v1/messages \
-H "content-type: application/json" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $RADIUM_API_KEY" \
-d '{
"model": "hal-1.0",
"max_tokens": 2048,
"tools": [
{
"name": "get_weather",
"description": "Get current weather for a city",
"input_schema": {
"type": "object",
"properties": {
"city": { "type": "string" }
},
"required": ["city"]
}
}
],
"messages": [
{ "role": "user", "content": "What is the weather in Tokyo?" }
]
}'
Turn two — the model asks for the tool
If it decides to call get_weather, the response carries a tool_use block:
{
"type": "tool_use",
"id": "toolu_...",
"name": "get_weather",
"input": {
"city": "Tokyo"
}
}
Radium has no idea what get_weather does and does not run it. That part is yours.
Turn three — run the tool and send the output back
Append the assistant turn containing the tool_use block, then a user turn containing the matching tool_result:
curl -s https://api.radium.cloud/v1/messages \
-H "content-type: application/json" \
-H "anthropic-version: 2023-06-01" \
-H "x-api-key: $RADIUM_API_KEY" \
-d '{
"model": "hal-1.0",
"max_tokens": 2048,
"tools": [
{
"name": "get_weather",
"description": "Get current weather for a city",
"input_schema": {
"type": "object",
"properties": {
"city": { "type": "string" }
},
"required": ["city"]
}
}
],
"messages": [
{ "role": "user", "content": "What is the weather in Tokyo?" },
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_123",
"name": "get_weather",
"input": { "city": "Tokyo" }
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_123",
"content": "Tokyo is 24 C and clear."
}
]
}
]
}'
The one to get right The
tool_use_idon your result has to match theidthe model issued. Send the tool definitions again with the follow-up, because the conversation is stateless and the model needs them on every turn.
The loop repeats for as long as the model keeps asking.
Several tools at once
Put as many definitions in the tools array as the work needs, and the model picks. Each one needs a name, a description the model can reason about, and an input_schema. The description carries more weight than people expect, because it is the only thing telling the model when a tool applies.
Streaming
Streaming works with tools on the same endpoint, so an agent loop can render output while it runs. Behaviour under streaming is worth checking against your own client before you depend on it, since every framework assembles the stream a little differently.
Where MCP sits
There is no separate Radium MCP endpoint to call, and there is nothing to configure on our side. MCP servers run on your infrastructure, your client connects to them and discovers what they expose, and the resulting tool definitions travel to Radium through the Messages API as ordinary tools.
From the model's position, a tool that arrived over MCP and a tool you hard-coded look the same. That is the point of the design, and it is why MCP support is a property of your client rather than a property of your inference provider.
MCP with Claude Code
Claude Code connects to MCP servers, discovers their tools, and passes the definitions through the model API. Radium answers the model half of that exchange. So:
- Configure Radium as the model provider with
ANTHROPIC_BASE_URL,ANTHROPIC_MODEL, and your key. The full steps are on Run Claude Code on Radium. - Configure MCP servers in Claude Code exactly as you already do. Nothing about that changes.
- Treat MCP tools as client-managed. The server is yours, the execution is yours, and Radium receives the definitions and the conversation turns.
Before production
Every MCP server exposes its own schemas and its own permissions, and models differ in how they handle an unfamiliar tool surface. Run a small smoke test of the specific workflow you intend to rely on, with the model you intend to use, before you put it in front of anyone.
Compatibility gets the request through. The smoke test tells you it works.