Skip to content

[FEATURE] Support for multiple MCP servers (and loading from config file) #482

@jer96

Description

@jer96

Overview

Add support for loading MCP server configurations from a JSON config file, allowing users to define multiple MCP servers declaratively instead of programmatically. This extends the existing experimental agent_config.py to support an mcp_servers field that creates and manages MCPClient instances automatically.

Note: Multiple MCP servers and automatic lifecycle management already work programmatically (see tests_integ/mcp/test_mcp_tool_provider.py::test_mcp_client_multiple_servers). This feature request is specifically about configuration file support.

Implementation Requirements

1. Extend Agent Config Schema (src/strands/experimental/agent_config.py)

Add mcp_servers to the existing AGENT_CONFIG_SCHEMA JSON schema. The configuration format should be compatible with the Claude Desktop / Cursor / VS Code mcpServers convention where possible.

Target config format:

{
  "name": "my_agent",
  "model": "us.anthropic.claude-3-5-sonnet-20241022-v2:0",
  "prompt": "You are a helpful assistant.",
  "tools": ["strands_tools.file_read"],
  "mcp_servers": {
    "aws_docs": {
      "command": "uvx",
      "args": ["awslabs.aws-documentation-mcp-server@latest"],
      "env": { "AWS_PROFILE": "default" },
      "prefix": "aws",
      "startup_timeout": 30,
      "tool_filters": {
        "allowed": ["search_.*"],
        "rejected": ["dangerous_tool"]
      }
    },
    "remote_service": {
      "transport": "sse",
      "url": "http://localhost:8000/sse",
      "headers": {
        "Authorization": "Bearer token123"
      },
      "prefix": "remote"
    },
    "http_service": {
      "transport": "streamable-http",
      "url": "http://localhost:8000/mcp",
      "headers": {},
      "prefix": "http"
    }
  }
}

2. Create MCP Config Module (src/strands/tools/mcp/mcp_config.py)

Create a new module that handles parsing MCP server configuration and creating MCPClient instances.

Key components:

  • Transport type detection: Infer transport from config (default to stdio if command is present, otherwise infer from url or explicit transport field)
  • Transport types to support:
    • stdio — uses mcp.client.stdio.stdio_client with StdioServerParameters
    • sse — uses mcp.client.sse.sse_client
    • streamable-http — uses mcp.client.streamable_http.streamablehttp_client
  • Config-to-MCPClient mapping: Convert each server config entry into an MCPClient instance with the appropriate transport callable

Per-server configuration options:

Field Type Required Description
command string For stdio Command to run the MCP server
args string[] No Arguments for the command
env object No Environment variables for the subprocess
cwd string No Working directory for stdio subprocess
transport string No Transport type: "stdio", "sse", "streamable-http" (auto-detected if omitted)
url string For sse/http URL of the remote MCP server
headers object No HTTP headers for sse/http transports
prefix string No Prefix for tool names to avoid collisions
startup_timeout int No Timeout for server initialization (default: 30)
tool_filters object No Tool filter config with allowed and rejected arrays of string/regex patterns

3. Integrate with config_to_agent

Update config_to_agent() in agent_config.py to:

  1. Parse the mcp_servers field from config
  2. Create MCPClient instances using the new config module
  3. Append MCPClient instances to the tools list passed to Agent()
  4. Let existing ToolProvider handling in ToolRegistry.process_tools() manage lifecycle

4. Also Provide Standalone Config Loading

In addition to config_to_agent integration, provide a standalone function to load MCP clients from config for users who want to use them independently:

from strands.tools.mcp import MCPClient
from strands.tools.mcp.mcp_config import load_mcp_clients_from_config

# Load from file
clients = load_mcp_clients_from_config("mcp_config.json")

# Or from dict
clients = load_mcp_clients_from_config({
    "aws_docs": {
        "command": "uvx",
        "args": ["awslabs.aws-documentation-mcp-server@latest"]
    }
})

# Use with agent
agent = Agent(tools=list(clients.values()))

5. Testing

Unit tests (tests/strands/tools/mcp/test_mcp_config.py):

  • Config parsing and validation for each transport type
  • Transport type auto-detection logic
  • Tool filter parsing (string literals → exact match, regex patterns)
  • Error handling for invalid configs
  • MCPClient creation with correct parameters

Unit tests (tests/strands/experimental/test_agent_config.py):

  • Extend existing tests for config_to_agent with mcp_servers field

Integration tests (tests_integ/mcp/test_mcp_config.py):

  • Load MCP servers from config file using existing echo_server.py
  • Verify tools are loaded and callable via agent
  • Multiple server config loading

Files to Create/Modify

File Action Description
src/strands/tools/mcp/mcp_config.py Create MCP config parsing and MCPClient factory
src/strands/tools/mcp/__init__.py Modify Export new config module
src/strands/experimental/agent_config.py Modify Add mcp_servers to schema and processing
tests/strands/tools/mcp/test_mcp_config.py Create Unit tests for config module
tests/strands/experimental/test_agent_config.py Modify Add tests for mcp_servers in agent config
tests_integ/mcp/test_mcp_config.py Create Integration tests
AGENTS.md Modify Update directory structure

Acceptance Criteria

  • Users can define multiple MCP servers in a JSON config file
  • Config supports stdio, SSE, and streamable-http transport types
  • Transport type is auto-detected when not explicitly specified
  • config_to_agent() correctly creates agents with MCP tools from config
  • Standalone load_mcp_clients_from_config() function works independently
  • Per-server options work: prefix, startup_timeout, tool_filters, env, headers
  • Tool filters support string literals and regex patterns in config
  • Invalid configurations produce clear error messages with JSON schema validation
  • Unit tests cover all config parsing paths and edge cases
  • Integration tests verify end-to-end MCP tool usage from config
  • Existing MCP programmatic usage (Agent(tools=[mcp_client])) is unaffected

Assumptions

  1. JSON only — No YAML/TOML support needed for now (per maintainer decision)
  2. Skip graceful failures[FEATURE] Graceful MCP server startup failures - fail open #1481 (fail-open strategy) is deferred; a single server failure will fail agent init as-is
  3. No environment variable interpolation — Config values are taken as-is (env passthrough via env field for stdio only)
  4. Experimental — This feature lives under experimental/agent_config.py and is subject to API changes
  5. No workflow changes — No GitHub Actions modifications required

Prior Art & References

Notes for Future Improvement

  • Consider adding YAML support in a follow-up
  • Consider environment variable interpolation (e.g., ${ENV_VAR}) for sensitive values
  • Consider fail_open option when [FEATURE] Graceful MCP server startup failures - fail open #1481 is implemented
  • The AGENTS.md directory structure should be updated to reflect the new mcp_config.py file
  • README.md MCP section could be updated with config file example

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions