Unified MCP Server
Installation & Usage
OpenAI · Anthropic · Gemini · Cohere · Grok & Groq · Claude.ai · Claude desktop · Cursor
The samples below use the US host. Swap it for your workspace's region — mcp-api-eu.unified.to or api-au.unified.to — since a credential only resolves on its own region's host. See Endpoints.
OpenAI API:
OpenAI's Responses API supports remote MCP directly. Enter in our Streamable HTTP URL.
resp = client.responses.create(
model="gpt-4.1",
tools=[{
"type": "mcp",
"server_label": "unifiedMCP",
"server_url": "https://mcp-api.unified.to/mcp?connection=YYYYYYY",
"headers": {"Authorization": "Bearer XXXXXXXX"},
"require_approval": "never",
}],
input="list the candidates and then analyse the resumes from their applications",
)
OpenAI also supports sending in a list of tools and having their API request that you call a specific tool with specific parameters. You would first call our GET /tools?type=openai endpoint, then take the output and include it in your prompt API call:
resp = client.responses.create(
model="gpt-4.1",
tools=$TOOLS,
input="list the candidates and then analyse the resumes from their applications",
)
Once you call that tool (using our POST /tools/{id}/call endpoint, with the function call's name as {id} and its parsed arguments as the body), you would create a new prompt and reference the original response with a previous_response_id value.
Please see this article for more information.
Anthropic API:
Claude's Messages API connects to the Unified MCP server directly through Anthropic's MCP connector, so you don't write a tool-call loop. Anthropic lists our tools, lets Claude call them, and returns the results in the same response.
Declare the server in mcp_servers, reference it from tools with an mcp_toolset entry (a server that no toolset references is rejected), and send the mcp-client-2025-11-20 beta header. Put your workspace API key in authorization_token, which Anthropic sends as the Authorization: Bearer header, and keep only the connection in the URL:
import anthropic
client = anthropic.Anthropic()
response = client.beta.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
messages=[{"role": "user", "content": "list the candidates and then analyse the resumes from their applications"}],
mcp_servers=[
{
"type": "url",
"url": "https://mcp-api.unified.to/mcp?connection=YYYYYYY",
"name": "unifiedMCP",
"authorization_token": "XXXXXXXX", # your workspace API key
}
],
tools=[{"type": "mcp_toolset", "mcp_server_name": "unifiedMCP"}],
betas=["mcp-client-2025-11-20"],
)
const response = await anthropic.beta.messages.create({
model: 'claude-opus-5-5',
max_tokens: 1024,
messages: [{ role: 'user', content: message }],
mcp_servers: [
{
type: 'url',
url: 'https://mcp-api.unified.to/mcp?connection=YYYYYYY',
name: 'unifiedMCP',
authorization_token: process.env.UNIFIED_API_KEY,
},
],
tools: [{ type: 'mcp_toolset', mcp_server_name: 'unifiedMCP' }],
betas: ['mcp-client-2025-11-20'],
});
The response contains mcp_tool_use and mcp_tool_result blocks for each tool Claude called, followed by Claude's answer:
[
{
"type": "mcp_tool_use",
"id": "mcptoolu_014Q35RayjACSWkSj4X2yov1",
"name": "list_candidates",
"server_name": "unifiedMCP",
"input": { "limit": "100" }
},
{
"type": "mcp_tool_result",
"tool_use_id": "mcptoolu_014Q35RayjACSWkSj4X2yov1",
"is_error": false,
"content": [{ "type": "text", "text": "..." }]
},
{ "type": "text", "text": "..." }
]
To expose only some tools, allowlist them in the mcp_toolset entry with default_config and configs. This is an alternative to our own tools parameter:
{
"type": "mcp_toolset",
"mcp_server_name": "unifiedMCP",
"default_config": { "enabled": false },
"configs": {
"list_candidates": { "enabled": true }
}
}
The MCP connector supports tool calls only. It isn't available on Amazon Bedrock or Google Cloud Vertex AI, and it isn't eligible for zero data retention. See Anthropic's MCP connector documentation for details.
Calling the tools yourself
On Amazon Bedrock or Vertex AI, or when your code must run each tool call itself (for example, to log or approve it), use standard tool use instead. Fetch the tools from our GET /tools?type=openai endpoint and rename parameters to input_schema, which is the key Anthropic expects:
import requests
unified_tools = requests.get(
"https://mcp-api.unified.to/tools",
params={"type": "openai", "connection": "YYYYYYY"},
headers={"Authorization": "Bearer XXXXXXXX"},
).json()
tools = [
{"name": t["name"], "description": t["description"], "input_schema": t["parameters"]}
for t in unified_tools
]
resp = client.messages.create(
model="claude-opus-5-5",
max_tokens=1024,
tools=tools,
messages=[{"role": "user", "content": "list the candidates and then analyse the resumes from their applications"}],
)
Claude returns tool_use content blocks:
[
{
"type": "tool_use",
"id": "toolu_01D7FLrfh4GYq7yT1ULFeyMV",
"name": "list_candidates",
"input": { "limit": "100" }
}
]
Call that tool with our POST /tools/{name}/call endpoint, sending its input as the JSON body, then return the result to Claude in the next user message:
[
{
"type": "tool_result",
"tool_use_id": "toolu_01D7FLrfh4GYq7yT1ULFeyMV",
"content": "..."
}
]
See Anthropic's tool use documentation for more information.
Google Gemini API:
Google Gemini uses a similar concept that Anthropic use for tools, but they call it functionDeclarations.
First you will request a list of function declarations with a GET /tools?type=gemini, and then give them to the generateContent request inside a functionDeclarations entry:
const completion = await gemini.models.generateContent({
model: latestModel,
contents: message,
config: {
tools: [{ functionDeclarations: $TOOLS }]
},
});
Please see this article for more information.
Gemini will return a request for you to call that specific tool:
content {
role: "model"
parts {
function_call {
name: "list_candidates"
args {
fields {
key: "limit"
value {
string_value: "100"
}
}
}
}
}
}
Call that tool with our POST /tools/{name}/call endpoint, sending its args as the JSON body. When you respond back with another message creation, you can include the result in the content array:
{
"role": "user",
"parts": [
{
"functionResponse": {
"name": "list_candidates",
"response": {
...
}
}
}
]
}
Cohere:
Cohere's chat API uses the same concept as Anthropic and Google Gemini. First get a list of tools from our GET /tools?type=cohere endpoint, then add that result to your chat API command:
response = co.chat(
model="command-a-03-2025", messages=messages, tools=tools
)
When Cohere's response asks you to call a tool, call our POST /tools/{name}/call endpoint with the tool call's function.name as {name} and its parsed function.arguments as the JSON body.
Grok & Groq:
Both x.ai's Grok and Groq (different company) work the same way, which is similar to Anthropic and Google Gemini.
First get a list of tools from our GET /tools?type=grok or GET /tools?type=groq endpoint, then add that result to your chat API command:
response = client.chat.completions.create({
// ...
tools: tools,
tool_choice: 'auto',
});
Respond to tool_calls in the Grok/Groq response:
const response_message = response.choices[0].message;
const tool_calls = response_message.tool_calls;
for (const tool_call of tool_calls) {
const function_name = tool_call.function.name;
const function_args = JSON.parse(tool_call.function.arguments);
// call our POST /tools/${function_name}/call with function_args as the JSON body
const result_content = await callUnifiedTool(function_name, function_args);
const messages = [
{
tool_call_id: tool_call.id,
role: 'tool',
name: function_name,
content: result_content,
},
];
const second_message = client.chat.completions.create({
// ...
messages,
});
}
Claude.ai (online):
Go to claude.ai, then navigate to Customize > Connectors and click Add custom connector. On a Team or Enterprise plan, an Owner adds it under Organization settings > Connectors instead.
Your workspace (Core Unified API tools): enter https://mcp-api.unified.to/mcp with no credential. Claude takes you through OAuth sign-in to pick a workspace.
One connection: send a connection-scoped token as a request header:
- For MCP server URL, enter
https://mcp-api.unified.to/mcp. - For Authentication, choose No sign-in.
- Under Request headers, choose the
authorizationheader and enterBearer {connectionID}-{nonce}-{signature}as its value. IncludeBearerand the space; Claude sends the value exactly as entered. - Click Add.
Claude stores the header value and doesn't show it again. To change the token later, remove the connector and add it again.
Request headers are a beta that Anthropic offers to a limited set of organizations (see Anthropic's custom connector docs). If your Add custom connector dialog has no Request headers section, put the token in the URL instead: https://mcp-api.unified.to/mcp?token={connectionID}-{nonce}-{signature}. That form still works, but it is deprecated.
Make sure to provide your end-customer the appropriate token value. Generate it with get_unified_connection_mcp_url in user mode: recommended.headers holds the header value, and mcp_url holds the URL form.
Claude (desktop client):
Edit the claude_desktop_config.json file:
{
"mcpServers": {
"unified-mcp": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp-api.unified.to/mcp?connection=YYYYYYY",
"--header",
"Authorization:${AUTH_HEADER}"
],
"env": {
"AUTH_HEADER": "Bearer XXXXXXXX"
}
}
}
}
Make sure to provide your end-customer the appropriate token value.
Cursor:
Navigate to Cursor > Settings > Cursor Settings > MCP and edit the MCP configuration. Replace unified-mcp with the name of your own application and then make sure to provide your end-customer the appropriate token value.
{
"mcpServers": {
"unified-mcp": {
"url": "https://mcp-api.unified.to/mcp?connection=YYYYYYY",
"headers": {
"Authorization": "Bearer XXXXXXXX"
}
}
}
}
MCP is a new protocol and it is moving fast. We expect more LLM & agent clients to support its newer Streamable HTTP transport protocol. We also expect that the MCP protocol will continue to expand quickly. Stay tuned as we also keep up.