From 8953d2b3f1d596a2418ab78d369b956a52ee229f Mon Sep 17 00:00:00 2001 From: TZZheng Date: Sun, 12 Jul 2026 15:49:23 -0500 Subject: [PATCH] fix(mcp): expand placeholders for HTTP connections (#761) --- src/lingtai/agent.py | 7 ++++ tests/test_mcp_capability.py | 71 ++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+) diff --git a/src/lingtai/agent.py b/src/lingtai/agent.py index 6ab2e21f..87c0d587 100644 --- a/src/lingtai/agent.py +++ b/src/lingtai/agent.py @@ -965,6 +965,13 @@ def connect_mcp_http( """ from .services.mcp import HTTPMCPClient + url = self._expand_agent_placeholders(url) + if headers: + headers = { + name: self._expand_agent_placeholders(value) + for name, value in headers.items() + } + client = HTTPMCPClient(url=url, headers=headers) client.start() diff --git a/tests/test_mcp_capability.py b/tests/test_mcp_capability.py index 41b53007..f6e54085 100644 --- a/tests/test_mcp_capability.py +++ b/tests/test_mcp_capability.py @@ -185,6 +185,77 @@ def test_expand_agent_placeholders_scopes_workbench_root(tmp_path): assert agent._expand_agent_placeholders(None) is None +class _FakeConnectionClient: + """Capture transport inputs without opening a subprocess or connection.""" + + instances = [] + + def __init__(self, **kwargs): + self.kwargs = kwargs + self.started = False + type(self).instances.append(self) + + def start(self): + self.started = True + + def list_tools(self): + return [] + + +def test_connect_mcp_http_expands_url_and_header_values(tmp_path, monkeypatch): + from lingtai.services import mcp + + class FakeHTTPMCPClient(_FakeConnectionClient): + instances = [] + + monkeypatch.setattr(mcp, "HTTPMCPClient", FakeHTTPMCPClient) + agent, workdir = _mk_agent(tmp_path) + + agent.connect_mcp_http( + "https://example.test/agents/{agent_id}/mcp", + { + "X-Agent-Dir": "{agent_dir}", + "X-{agent_id}": "unchanged", + "X-Literal": "no-placeholders", + }, + ) + + client = FakeHTTPMCPClient.instances[-1] + assert client.started + assert client.kwargs == { + "url": "https://example.test/agents/agent/mcp", + "headers": { + "X-Agent-Dir": str(workdir), + "X-{agent_id}": "unchanged", + "X-Literal": "no-placeholders", + }, + } + + +def test_connect_mcp_stdio_placeholder_expansion_is_unchanged(tmp_path, monkeypatch): + from lingtai.services import mcp + + class FakeMCPClient(_FakeConnectionClient): + instances = [] + + monkeypatch.setattr(mcp, "MCPClient", FakeMCPClient) + agent, workdir = _mk_agent(tmp_path) + + agent.connect_mcp( + "bin/{agent_id}", + args=["--root", "{agent_dir}", "literal"], + env={"AGENT": "{agent_id}", "LITERAL": "unchanged"}, + ) + + client = FakeMCPClient.instances[-1] + assert client.started + assert client.kwargs == { + "command": "bin/agent", + "args": ["--root", str(workdir), "literal"], + "env": {"AGENT": "agent", "LITERAL": "unchanged"}, + } + + # --------------------------------------------------------------------------- # Decompression # ---------------------------------------------------------------------------