feat(mcp-server): agentUrl option to route MCP tool calls internally#1740
Open
Scra3 wants to merge 2 commits into
Open
feat(mcp-server): agentUrl option to route MCP tool calls internally#1740Scra3 wants to merge 2 commits into
Scra3 wants to merge 2 commits into
Conversation
MCP tools call back into the agent's data layer over HTTP. By default the URL is the environment's public api_endpoint, so tool calls leave over the public internet even when the MCP server is mounted inside the agent. Add an opt-in agentUrl option (mountAiMcpServer, ForestMCPServerOptions, FOREST_AGENT_URL for the CLI) that overrides only the internal tool->agent channel — the advertised OAuth discovery URLs stay public so external MCP clients still authenticate. Requested by a self-hosted customer (Swaive) who wants MCP callbacks to stay on their private network. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Coverage Impact This PR will not change total coverage. Modified Files with Diff Coverage (3)
🛟 Help
|
Review follow-ups on the agentUrl option:
- normalizeAgentUrl now parses once, rejects non-http(s) schemes and URLs with
a query string or fragment (which would swallow the request path in
agent-client's `${url}${path}` join), and returns the parsed, whitespace-
normalized form instead of the raw string. Previously such inputs passed
validation and silently misrouted every tool call.
- Add an end-to-end test proving a `tools/call` actually targets agentUrl and
not the environment's public api_endpoint.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.

Context
MCP tools don't touch the datasource directly — each tool call (
list,create,executeAction…) calls back into the agent's data layer over HTTP viaagent-client. The URL used is the environment's publicapi_endpoint(as registered in Forest), read fromAuthInfo.extra.environmentApiEndpoint.Consequence: even when the MCP server is mounted inside the agent (same process), every tool call leaves over the public internet and comes back. A self-hosted customer (Swaive, KYB prod use case with n8n) asked to keep this traffic on their private network.
Change
Opt-in
agentUrloption that overrides only the internal tool→agent channel:forest-oauth-provider.ts— newagentUrl(validated as an absolute URL, trailing slash stripped);verifyAccessTokenputsagentUrl ?? environmentApiEndpointintoextra.environmentApiEndpoint(the single consumer, inagent-caller.ts).getBaseUrl()untouched.server.ts—ForestMCPServerOptions.agentUrl, threaded to the provider.cli.ts—FOREST_AGENT_URLenv var for the standalone binary.agent.ts—mountAiMcpServer({ agentUrl })threading.The advertised OAuth URLs (issuer,
.well-knownmetadata, authorize/token) stay public — external MCP clients (n8n) still authenticate from outside.agentUrlonly changes where tools reach the agent.Same concept and name as
addWorkflowExecutor({ agentUrl }). Default unchanged (publicapi_endpoint), so zero impact on existing deployments.Tests
forest-oauth-provider.test.ts—extra.environmentApiEndpoint=agentUrlwhen set (fallback toapi_endpointotherwise), trailing slash stripped, invalid URL throws.server.test.ts— withagentUrlset, advertised OAuth metadata URLs stay public.agent.test.ts—mountAiMcpServer({ agentUrl })reachesForestMCPServer.mcp-server: 608 tests pass, lint clean.
Definition of Done
General
Security
agentUrlis validated; default behavior unchanged; the option improves security posture (keeps tool traffic off the public internet).🤖 Generated with Claude Code
Note
Add
agentUrloption toForestMCPServerto route MCP tool calls to a self-hosted agentagentUrltoForestMCPServerOptionsandForestOAuthProviderthat, when set, overrides the publicapi_endpointembedded in OAuth tokens as the tool callback base URL.Agent.mountAiMcpServer(stored and forwarded onAgent.start) and through the CLI via theFOREST_AGENT_URLenvironment variable.ForestOAuthProvider.normalizeAgentUrlvalidates that the value is an absolutehttp/httpsURL with no query string or fragment, and strips trailing slashes; invalid values throw at construction time.agentUrl— only the per-tokenenvironmentApiEndpointchanges.agentUrlnow throws duringForestOAuthProviderconstruction, which is a new failure mode for existing callers that forward arbitrary user input.Macroscope summarized c476514.