Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions aider/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,13 @@ def get_parser(default_config_files, git_root):
help="Specify a file path with MCP server configurations",
default=None,
)
group.add_argument(
"--mcp-transport",
metavar="MCP_TRANSPORT",
help="Specify the transport for MCP servers (default: stdio)",
default="stdio",
choices=["stdio", "http"],
)
group.add_argument(
"-c",
"--config",
Expand Down
4 changes: 3 additions & 1 deletion aider/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -972,7 +972,9 @@ def get_io(pretty):

try:
# Load MCP servers from config string or file
mcp_servers = load_mcp_servers(args.mcp_servers, args.mcp_servers_file, io, args.verbose)
mcp_servers = load_mcp_servers(
args.mcp_servers, args.mcp_servers_file, io, args.verbose, args.mcp_transport
)

if not mcp_servers:
mcp_servers = []
Expand Down
24 changes: 16 additions & 8 deletions aider/mcp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import json

from aider.mcp.server import McpServer
from aider.mcp.server import McpServer, HttpStreamingServer


def _parse_mcp_servers_from_json_string(json_string, io, verbose=False):
def _parse_mcp_servers_from_json_string(json_string, io, verbose=False, mcp_transport="stdio"):
"""Parse MCP servers from a JSON string."""
servers = []

Expand All @@ -19,7 +19,11 @@ def _parse_mcp_servers_from_json_string(json_string, io, verbose=False):

# Create a server config with name included
server_config["name"] = name
servers.append(McpServer(server_config))
transport = server_config.get("transport", mcp_transport)
if transport == "stdio":
servers.append(McpServer(server_config))
elif transport == "http":
servers.append(HttpStreamingServer(server_config))

if verbose:
io.tool_output(f"Loaded {len(servers)} MCP servers from JSON string")
Expand All @@ -34,7 +38,7 @@ def _parse_mcp_servers_from_json_string(json_string, io, verbose=False):
return servers


def _parse_mcp_servers_from_file(file_path, io, verbose=False):
def _parse_mcp_servers_from_file(file_path, io, verbose=False, mcp_transport="stdio"):
"""Parse MCP servers from a JSON file."""
servers = []

Expand All @@ -52,7 +56,11 @@ def _parse_mcp_servers_from_file(file_path, io, verbose=False):

# Create a server config with name included
server_config["name"] = name
servers.append(McpServer(server_config))
transport = server_config.get("transport", mcp_transport)
if transport == "stdio":
servers.append(McpServer(server_config))
elif transport == "http":
servers.append(HttpStreamingServer(server_config))

if verbose:
io.tool_output(f"Loaded {len(servers)} MCP servers from {file_path}")
Expand All @@ -69,18 +77,18 @@ def _parse_mcp_servers_from_file(file_path, io, verbose=False):
return servers


def load_mcp_servers(mcp_servers, mcp_servers_file, io, verbose=False):
def load_mcp_servers(mcp_servers, mcp_servers_file, io, verbose=False, mcp_transport="stdio"):
"""Load MCP servers from a JSON string or file."""
servers = []

# First try to load from the JSON string (preferred)
if mcp_servers:
servers = _parse_mcp_servers_from_json_string(mcp_servers, io, verbose)
servers = _parse_mcp_servers_from_json_string(mcp_servers, io, verbose, mcp_transport)
if servers:
return servers

# If JSON string failed or wasn't provided, try the file
if mcp_servers_file:
servers = _parse_mcp_servers_from_file(mcp_servers_file, io, verbose)
servers = _parse_mcp_servers_from_file(mcp_servers_file, io, verbose, mcp_transport)

return servers
23 changes: 23 additions & 0 deletions aider/mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from mcp.client.streamable_http import streamablehttp_client


class McpServer:
Expand Down Expand Up @@ -74,3 +75,25 @@ async def disconnect(self):
self.stdio_context = None
except Exception as e:
logging.error(f"Error during cleanup of server {self.name}: {e}")

class HttpStreamingServer(McpServer):
async def connect(self):
if self.session is not None:
logging.info(f"Using existing session for MCP server: {self.name}")
return self.session

logging.info(f"Establishing new connection to MCP server: {self.name}")
try:
url = self.config["url"]
http_transport = await self.exit_stack.enter_async_context(streamablehttp_client(url))
read, write, _ = http_transport

session = await self.exit_stack.enter_async_context(ClientSession(read, write))
await session.initialize()
self.session = session
return session
except Exception as e:
logging.error(f"Error initializing server {self.name}: {e}")
await self.disconnect()
raise

17 changes: 13 additions & 4 deletions aider/website/docs/config/mcp.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ for more information.
You have two ways of sharing your MCP server configuration with Aider.

{: .note }
Today, Aider only supports connecting to MCP servers using the stdio transport

> Today, Aider supports connecting to MCP servers using stdio and http transports.

### Config Files

Expand All @@ -28,8 +29,8 @@ mcp-servers: |
{
"mcpServers": {
"git": {
"command": "uvx",
"args": ["mcp-server-git"]
"transport": "http",
"url": "http://localhost:8000"
}
}
}
Expand All @@ -50,7 +51,7 @@ You can specify MCP servers directly on the command line using the `--mcp-server
#### Using a JSON String

```bash
aider --mcp-servers '{"mcpServers":{"git":{"command":"uvx","args":["mcp-server-git"]}}}'
aider --mcp-servers '{"mcpServers":{"git":{"transport":"http","url":"http://localhost:8000"}}}'
```

#### Using a configuration file
Expand All @@ -61,6 +62,14 @@ Alternatively, you can store your MCP server configurations in a JSON file and r
aider --mcp-servers-file mcp.json
```

#### Specifying the transport

You can use the `--mcp-transport` flag to specify the transport for all configured MCP servers that do not have a transport specified.

```bash
aider --mcp-transport http
```

### Environment Variables

You can also configure MCP servers using environment variables in your `.env` file:
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ mccabe==0.7.0
# via
# -c requirements/common-constraints.txt
# flake8
mcp==1.6.0
mcp==1.12.3
# via
# -c requirements/common-constraints.txt
# -r requirements/requirements.in
Expand Down
2 changes: 1 addition & 1 deletion requirements/common-constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ matplotlib==3.10.3
# via -r requirements/requirements-dev.in
mccabe==0.7.0
# via flake8
mcp==1.6.0
mcp==1.12.3
# via -r requirements/requirements.in
mdurl==0.1.2
# via markdown-it-py
Expand Down
2 changes: 1 addition & 1 deletion requirements/requirements.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pillow
shtab
oslex
google-generativeai
mcp>=1.0.0
mcp==1.12.3

# The proper dependency is networkx[default], but this brings
# in matplotlib and a bunch of other deps
Expand Down
Loading