Skip to main content
Lesson 8 of 12 · Remote MCP: Connect External Tools

Multi-server configuration

Lesson 8 of 12 Updated July 29, 2026 Developer
On this page
  1. Multiple sources, single agent
  2. Syntax: nothing new, just multiple entries
  3. Labels become structural
  4. How Grok selects a server
  5. An end-to-end support agent
  6. Key takeaways

Multiple sources, single agent

Remote MCP reaches its full potential when you connect Grok to multiple servers at once. Each brings its own tools, and the model arbitrates between them based on the incoming request. This is what separates an agent that can do one thing from an agent that can conduct an investigation: checking a service status, then a customer history, then a troubleshooting article, without you writing a single line of orchestration code.

Syntax: nothing new, just multiple entries

There is no multi-server mode to enable. You simply add multiple MCP objects to the tools list.

from xai_sdk.tools import mcp

tools = [
    mcp(server_url="https://mcp.deepwiki.com/mcp", server_label="deepwiki"),
    mcp(server_url="https://your-custom-tools.com/mcp", server_label="custom"),
    mcp(server_url="https://api.example.com/tools", server_label="api-tools"),
]

The same principle applies to the Responses API in OpenAI format, where each server becomes a dictionary in the list. This version adds descriptions, which you will see are no longer optional as soon as you use more than one server.

tools = [
    {
        "type": "mcp",
        "server_url": "https://mcp.deepwiki.com/mcp",
        "server_label": "deepwiki",
        "server_description": "Documentation for GitHub open-source projects"
    },
    {
        "type": "mcp",
        "server_url": "https://your-custom-tools.com/mcp",
        "server_label": "custom",
        "server_description": "Internal company tools"
    },
    {
        "type": "mcp",
        "server_url": "https://api.example.com/tools",
        "server_label": "api-tools",
        "server_description": "Data and analytics API"
    },
]

Labels become structural

The server_label, until now a readability aid, becomes essential here. Take a very common scenario: you connect your internal documentation and DeepWiki, and both expose a tool named search. Without distinct labels, two tools bear the same name and Grok has no way to decide. With labels, deepwiki__search queries the GitHub documentation while internal-docs__search searches your knowledge base—two clearly separated tools that the model chooses based on descriptions and the conversation flow.

Three rules are enough to never encounter a problem. Each label must be unique in the configuration. It must reflect the data source rather than the technical function, because provenance distinguishes servers from each other, not what they do. And it must remain short without becoming interchangeable. The contrast below illustrates the gap between the two approaches:

# Good: descriptive and distinct labels
server_label="deepwiki"
server_label="crm"
server_label="jira"

# Bad: ambiguous labels
server_label="server1"
server_label="server2"
server_label="tools"

The labels in the second series are a latent trap. They work the day you write them, because you know what server1 contains. Six months later, when rereading an incident log, no one knows anymore—and the model, for its part, never knew.

How Grok selects a server

Faced with multiple servers, the model cross-references four sources of information to decide. It starts with the user request, meaning what is actually asked. It then consults the server_description of each server, which tells it what each one is for overall. It goes down one level to the names and descriptions of the tools themselves, each tool carrying its own. And it takes into account the conversation context, since previous messages influence the selection: if the client already gave you their account number three turns earlier, Grok knows it can call crm__get_customer without asking again.

Of these four sources, the second is the one you have the most control over, and that is precisely why descriptions become critical in multi-server mode. Without descriptions, Grok falls back on tool names alone—a search facing another search, with no indication of what they index. The selection errors that result are all the more confusing because they seem random: the model chooses correctly half the time, by luck.

An end-to-end support agent

This configuration brings together everything above in a complete use case.

tools = [
    mcp(
        server_url="https://kb.monentreprise.com/mcp",
        server_label="knowledge",
        server_description="Product knowledge base. Help articles, FAQ, troubleshooting guides.",
        allowed_tool_names=["search_articles", "get_article"]
    ),
    mcp(
        server_url="https://crm.monentreprise.com/mcp",
        server_label="crm",
        server_description="CRM. Customer history, previous tickets, account information.",
        authorization=f"Bearer {os.getenv('CRM_TOKEN')}",
        allowed_tool_names=["get_customer", "search_tickets", "get_ticket"]
    ),
    mcp(
        server_url="https://status.monentreprise.com/mcp",
        server_label="status",
        server_description="Service status. Ongoing incidents, scheduled maintenance.",
        allowed_tool_names=["get_current_status", "list_incidents"]
    ),
]

A customer writes “my service is no longer working”. Grok first checks if there is an ongoing incident via status__get_current_status, consults the customer’s account with crm__get_customer to know which service it is, then searches for a troubleshooting article via knowledge__search_articles. This sequence is written nowhere in your code: it stems from the descriptions and the question asked. Note also that each server remains restricted to its read operations—the power of multi-server never eliminates the need for an allowlist.

Key takeaways

  • Pass multiple MCP objects in the tools list for multi-server
  • Each server must have a unique and descriptive server_label
  • server_description values are essential to guide Grok to the right server
  • Grok automatically selects the appropriate server based on the request and context
  • Restrict each server’s tools with allowed_tool_names to limit noise