Uh oh!
There was an error while loading. Please reload this page.
fix(mcp-server): let a deployed standalone server know its public url - #1832
Conversation
Uh oh!
There was an error while loading. Please reload this page.
b68627b to
e59196dCompareCoverage Impact This PR will not change total coverage. Modified Files with Diff Coverage (1)
🛟 Help
|
3d38b02 to
029f626Compare1 new issue
|
Uh oh!
There was an error while loading. Please reload this page.
e6b0a5b to
4d627f5Compare4d627f5 to
61dd1d9CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
f8225f8 to
4edd242CompareUh oh!
There was an error while loading. Please reload this page.
4edd242 to
a2e357dCompareUh oh!
There was an error while loading. Please reload this page.
a2e357d to
beda2fbComparerun() hardcoded baseUrl to http://localhost:<port>, and that explicit value wins over the environment's api_endpoint. A process cannot derive its own public url — dns, proxy and tls termination live outside it — so a deployed standalone server advertised localhost as its OAuth issuer, and on the in-memory store minted localhost upload urls no remote client can reach. FOREST_MCP_SERVER_URL, when set, becomes the base url and fixes both at once. Unset, nothing changes. The value must be an http(s) origin with no path, query, fragment or credentials, enforced at startup: the OAuth endpoints are concatenated onto the href and the uploads base resolves against the origin, so anything else advertises broken urls that only fail once a client follows them. The rejection reports the parsed origin rather than the raw value, so credentials this check exists to withhold do not end up in the logs instead. MCP_SERVER_PORT is validated on its own rather than as a side effect of parsing the default url, which a configured FOREST_MCP_SERVER_URL replaces: listen() would otherwise reject a bad port with a bare RangeError, after the schema fetch and the OAuth initialization, and not at all in the configuration this option adds. The startup line reports both facts now that they can differ — the port the socket bound, and the url clients are told — and warns when a server is left on the localhost default, which is the only runtime chance to catch it.
beda2fb to
059365aCompareUh oh!
There was an error while loading. Please reload this page.
## @forestadmin/mcp-server [1.22.1](https://github.com/ForestAdmin/agent-nodejs/compare/@forestadmin/mcp-server@1.22.0...@forestadmin/mcp-server@1.22.1) (2026-08-18) ### Bug Fixes * **mcp-server:** let a deployed standalone server know its public url ([#1832](#1832)) ([e83a3f4](e83a3f4))
…-workflow-tools-in-forest-mcp-server #1832 added requestActionFileUpload to the same four tool lists this branch extends with the workflow tools, so every conflict was additive: both sides are kept. The workflow tools stay unconditional and the file upload tool keeps its fileUploads gate; the imports keep import/order. Without this the PR could not be checked at all - GitHub skips pull_request workflows on a conflicting PR, so no run was triggered. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Follow-up to #1815, which shipped in
@forestadmin/mcp-server@1.22.0.run()hardcodesbaseUrl = http://localhost:<port>, and that explicit value wins over the environment'sapi_endpoint. A process cannot derive its own public URL — DNS, proxy and TLS termination live outside it — so a deployed standalone server today:localhostas its OAuth issuer and endpoints (pre-existing, not introduced by feat: upload files through the MCP server for action File fields #1815),localhostupload URLs no remote client can reach.Nobody had seen it because every standalone test so far ran locally. A standalone deployment with a configured storage backend is unaffected — the upload URL comes from the backend.
FOREST_MCP_SERVER_URLis the public URL the server is reachable at. Set, it becomes the base URL, fixing the issuer and the upload URLs in one move; unset, behavior is unchanged. A value that does not parse as a URL fails at startup, like every other option.Verified by test through the real HTTP server
run()starts: the advertised issuer is the configured URL. The suite's globalfetchis the Forest mock, so the test reaches it with the keptoriginalFetch.🤖 Generated with Claude Code
Note
Let a deployed MCP server advertise its public URL via
FOREST_MCP_SERVER_URLFOREST_MCP_SERVER_URLenv var to server.ts that sets the public http(s) origin used for OAuth metadata and file upload URLs; defaults tohttp://localhost:<port>when unset.FOREST_MCP_SERVER_URLis a bare origin (no path, query, fragment, or credentials), failing startup with a clear error on invalid input.MCP_SERVER_PORTparsing to require an integer in [0, 65535]; rejectsMCP_SERVER_PORT=0unlessFOREST_MCP_SERVER_URLis set, since the ephemeral port can't be advertised without a known public URL.FOREST_MCP_SERVER_URLis unset.FOREST_MCP_SERVER_URL; omitting it causes advertised endpoints to resolve to localhost.Macroscope summarized 059365a.