Skip to content

Commit b2077c5

Browse files
authored
Merge pull request #279 from GitHubSecurityLab/anticomputer/streamable-url-env
Resolve env templates in remote MCP server urls
2 parents f306663 + 143d839 commit b2077c5

2 files changed

Lines changed: 33 additions & 2 deletions

File tree

src/seclab_taskflow_agent/mcp_utils.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,13 +238,13 @@ def mcp_client_params(
238238

239239
case "sse":
240240
headers = _resolve_headers(sp.headers, sp.optional_headers)
241-
server_params["url"] = sp.url
241+
server_params["url"] = swap_env(sp.url) if sp.url is not None else None
242242
server_params["headers"] = headers
243243
server_params["timeout"] = sp.timeout
244244

245245
case "streamable":
246246
headers = _resolve_headers(sp.headers, sp.optional_headers)
247-
server_params["url"] = sp.url
247+
server_params["url"] = swap_env(sp.url) if sp.url is not None else None
248248
server_params["headers"] = headers
249249
server_params["timeout"] = sp.timeout
250250

tests/test_mcp_utils.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,34 @@ def test_env_names_returns_sorted_names_or_none():
196196
assert _env_names({"B_VAR": "x", "A_VAR": "{{ env('A') }}"}) == ["A_VAR", "B_VAR"]
197197
assert _env_names({}) == []
198198
assert _env_names(None) is None
199+
200+
201+
@pytest.mark.parametrize("kind", ["streamable", "sse"])
202+
def test_mcp_client_params_resolves_remote_url_env(monkeypatch, kind):
203+
# A remote toolbox sources its endpoint from the environment. The url must
204+
# be env-templated the same way stdio args/env and headers already are, so
205+
# `url: "{{ env('CONTAINER_SHELL_URL') }}"` reaches the client resolved.
206+
monkeypatch.setenv("CONTAINER_SHELL_URL", "http://host.docker.internal:8765/mcp/")
207+
server_params = SimpleNamespace(
208+
kind=kind,
209+
reconnecting=False,
210+
url="{{ env('CONTAINER_SHELL_URL') }}",
211+
headers=None,
212+
optional_headers=None,
213+
timeout=None,
214+
command=None,
215+
env=None,
216+
args=None,
217+
)
218+
toolbox = SimpleNamespace(
219+
server_params=server_params,
220+
confirm=["container_shell_exec"],
221+
server_prompt=None,
222+
client_session_timeout=None,
223+
)
224+
available_tools = MagicMock()
225+
available_tools.get_toolbox.return_value = toolbox
226+
227+
params = mcp_client_params(available_tools, ["pkg.remote"])
228+
229+
assert params["pkg.remote"][0]["url"] == "http://host.docker.internal:8765/mcp/"

0 commit comments

Comments
 (0)