How to Configure MCP Servers in ML Intern for Extended Tool Capabilities

ML Intern uses MCP (Multi-Channel Protocol) servers to expose additional tool back-ends via JSON configuration in configs/main_agent_config.json, loading them through Pydantic models in agent/config.py and routing calls via ToolRouter in agent/core/tools.py.

The ML Intern agent framework from Hugging Face leverages the FastMCP protocol to connect with remote and local tool providers. This architecture allows the agent to execute tools hosted on external servers or local subprocesses without hard-coding credentials into your repository. By configuring the mcpServers map in the main configuration file, you enable the agent to discover and invoke specialized capabilities ranging from Hugging Face repository operations to custom local utilities.

Understanding the MCP Configuration Architecture

The MCP integration in ML Intern follows a strict validation pipeline that ensures type safety and secure credential handling.

The Configuration Schema

In agent/config.py, the codebase defines a Pydantic Config model containing the field mcpServers: dict[str, MCPServerConfig]. Each entry in this dictionary must conform to either the RemoteMCPServer or StdioMCPServer schema imported from fastmcp.mcp_config.

  • RemoteMCPServer: Uses HTTP transport for external endpoints
  • StdioMCPServer: Uses standard input/output for local subprocess communication

Environment Variable Substitution

Security-critical values like API tokens must never reside in version control. The substitute_env_vars() function in agent/config.py processes the JSON configuration before validation, replacing ${VAR} placeholders with values from a .env file or system environment. This substitution occurs inside the load_config() helper, which reads configs/main_agent_config.json and returns a validated Config instance.

Step-by-Step MCP Server Configuration

1. Define Servers in the JSON Config

Edit configs/main_agent_config.json to add entries under the mcpServers key. Each server requires a logical name and transport-specific parameters.

{
  "model_name": "bedrock/us.anthropic.claude-opus-4-6-v1",
  "save_sessions": true,
  "auto_file_upload": true,
  "mcpServers": {
    "hf-mcp-server": {
      "transport": "http",
      "url": "https://huggingface.co/mcp?login",
      "headers": {
        "Authorization": "Bearer ${HF_MCP_TOKEN}"
      }
    },
    "local-stdio": {
      "transport": "stdio",
      "command": "python -m fastmcp.server"
    }
  }
}

The hf-mcp-server entry demonstrates remote configuration with header-based authentication, while local-stdio shows a local Python module invocation.

2. Secure Secrets with Environment Variables

Create a .env file at the repository root (ensure this is gitignored) to store sensitive tokens:

HF_MCP_TOKEN=hf_XXXXXXXXXXXXXXXXXXXX

When load_config() executes, it automatically interpolates ${HF_MCP_TOKEN} with the actual value before Pydantic validation occurs.

3. Load and Validate the Configuration

The configuration loading happens programmatically through the agent/config.py module:

from pathlib import Path
from agent.config import load_config

config_path = Path(__file__).parent.parent / "configs" / "main_agent_config.json"
config = load_config(config_path)          # Validates & substitutes env vars

print(config.mcpServers)                  # Parsed server dictionary

This instantiation validates the schema and confirms that all referenced environment variables exist.

4. Initialize the Tool Router

In agent/main.py, the application constructs the ToolRouter by passing the parsed server configuration:

from agent.core.tools import ToolRouter

tool_router = ToolRouter(config.mcpServers, hf_token=hf_token, local_mode=True)

This initialization creates internal fastmcp.Client instances for each configured MCP server, establishing the communication channels before the agent loop begins.

Routing Tool Calls Through MCP

Once configured, tool execution flows through the router transparently. When the LLM requests an MCP-registered tool, ToolRouter.execute_tool() in agent/core/tools.py forwards the request to the appropriate client.

await tool_router.execute_tool(
    tool_name="hf_repo_files",
    args={"repo_id": "my-org/my-repo", "path": "/data"}
)

The router detects that hf_repo_files resides on the remote MCP server, serializes the request, waits for the HTTP response, and injects the returned file list back into the agent context. This implementation spans lines 147-170 in agent/core/tools.py, handling both transport types uniformly.

Summary

  • Configure MCP servers in configs/main_agent_config.json using RemoteMCPServer or StdioMCPServer schemas from fastmcp
  • Secure credentials via ${VAR} placeholders processed by substitute_env_vars() in agent/config.py using .env files
  • Validate configurations through the Pydantic Config model loaded by load_config() in agent/config.py
  • Route tool calls through ToolRouter initialized in agent/main.py, which manages fastmcp.Client instances in agent/core/tools.py

Frequently Asked Questions

What is the difference between RemoteMCPServer and StdioMCPServer in ML Intern?

RemoteMCPServer configures HTTP-based connections to external services, requiring a url and optional headers for authentication, while StdioMCPServer launches local subprocesses using a command string and communicates over standard input/output. The agent/config.py module imports both schemas from fastmcp.mcp_config and validates them through the Pydantic MCPServerConfig union type.

How does ML Intern handle sensitive API keys for MCP servers?

ML Intern processes the JSON configuration through substitute_env_vars() in agent/config.py, which replaces ${VAR} syntax with values from the environment or .env file before Pydantic validation. This ensures tokens like HF_MCP_TOKEN remain outside version control while being available to the fastmcp.Client at runtime.

Where is the MCP client instantiated in the ML Intern codebase?

The fastmcp.Client instantiation occurs inside agent/core/tools.py when ToolRouter initializes. The router receives the config.mcpServers dictionary from agent/main.py and creates dedicated client instances for each configured server, managing their lifecycle and connection pooling throughout the agent session.

Can I add multiple MCP servers to a single ML Intern configuration?

Yes. The mcpServers field in configs/main_agent_config.json accepts a dictionary mapping logical names to server configurations. You can define any number of remote HTTP servers and local stdio processes simultaneously; ToolRouter maintains separate client connections for each entry and routes tool calls to the appropriate endpoint based on the tool name registration.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →