Skip to content

fix(mcp-server): let a deployed standalone server know its public url - #1832

Merged
Scra3 merged 1 commit into
mainfrom
fix/mcp-standalone-public-url
Aug 18, 2026
Merged

fix(mcp-server): let a deployed standalone server know its public url#1832
Scra3 merged 1 commit into
mainfrom
fix/mcp-standalone-public-url

Conversation

@Scra3

@Scra3 Scra3 commented Aug 17, 2026

Copy link
Copy Markdown
Member

Follow-up to #1815, which shipped in @forestadmin/mcp-server@1.22.0.

run() hardcodes baseUrl = 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 today:

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_URL is 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 global fetch is the Forest mock, so the test reaches it with the kept originalFetch.

🤖 Generated with Claude Code

Note

Let a deployed MCP server advertise its public URL via FOREST_MCP_SERVER_URL

  • Adds a new FOREST_MCP_SERVER_URL env var to server.ts that sets the public http(s) origin used for OAuth metadata and file upload URLs; defaults to http://localhost:<port> when unset.
  • Validates that FOREST_MCP_SERVER_URL is a bare origin (no path, query, fragment, or credentials), failing startup with a clear error on invalid input.
  • Tightens MCP_SERVER_PORT parsing to require an integer in [0, 65535]; rejects MCP_SERVER_PORT=0 unless FOREST_MCP_SERVER_URL is set, since the ephemeral port can't be advertised without a known public URL.
  • Logs the advertised URL at startup and warns when advertising a localhost URL because FOREST_MCP_SERVER_URL is unset.
  • Behavioral Change: servers deployed behind a public URL must now set FOREST_MCP_SERVER_URL; omitting it causes advertised endpoints to resolve to localhost.

Macroscope summarized 059365a.

Comment thread packages/mcp-server/src/server.ts Outdated
@Scra3
Scra3 force-pushed the fix/mcp-standalone-public-url branch from b68627b to e59196d Compare August 17, 2026 13:26
@qltysh

qltysh Bot commented Aug 17, 2026

Copy link
Copy Markdown

Qlty


Coverage Impact

This PR will not change total coverage.

Modified Files with Diff Coverage (1)

RatingFile% DiffUncovered Line #s
Coverage rating: A Coverage rating: A
packages/mcp-server/src/server.ts100.0%
Total100.0%
🚦 See full report on Qlty Cloud »

🛟 Help
  • Diff Coverage: Coverage for added or modified lines of code (excludes deleted files). Learn more.

  • Total Coverage: Coverage for the whole repository, calculated as the sum of all File Coverage. Learn more.

  • File Coverage: Covered Lines divided by Covered Lines plus Missed Lines. (Excludes non-executable lines including blank lines and comments.)

    • Indirect Changes: Changes to File Coverage for files that were not modified in this PR. Learn more.

@Scra3
Scra3 force-pushed the fix/mcp-standalone-public-url branch 2 times, most recently from 3d38b02 to 029f626 Compare August 17, 2026 13:35
@qltysh

qltysh Bot commented Aug 17, 2026

Copy link
Copy Markdown

1 new issue

Tool Category Rule Count
qlty Structure Function with high complexity (count = 13): run 1

Comment thread packages/mcp-server/src/server.ts
@Scra3
Scra3 force-pushed the fix/mcp-standalone-public-url branch 3 times, most recently from e6b0a5b to 4d627f5 Compare August 17, 2026 14:24
@Scra3
Scra3 force-pushed the fix/mcp-standalone-public-url branch from 4d627f5 to 61dd1d9 Compare August 17, 2026 14:49
Comment thread packages/mcp-server/src/server.ts
Comment thread packages/mcp-server/src/server.ts Outdated
Comment thread packages/mcp-server/src/server.ts Outdated
@Scra3
Scra3 force-pushed the fix/mcp-standalone-public-url branch 3 times, most recently from f8225f8 to 4edd242 Compare August 18, 2026 08:03
Comment thread packages/mcp-server/src/server.ts Outdated
@Scra3
Scra3 force-pushed the fix/mcp-standalone-public-url branch from 4edd242 to a2e357d Compare August 18, 2026 08:08
Comment thread packages/mcp-server/src/server.ts Outdated
@Scra3
Scra3 force-pushed the fix/mcp-standalone-public-url branch from a2e357d to beda2fb Compare August 18, 2026 08:14
run() 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.
@Scra3
Scra3 force-pushed the fix/mcp-standalone-public-url branch from beda2fb to 059365a Compare August 18, 2026 08:15
@Scra3
Scra3 merged commit e83a3f4 into main Aug 18, 2026
32 checks passed
@Scra3
Scra3 deleted the fix/mcp-standalone-public-url branch August 18, 2026 08:24
forest-bot added a commit that referenced this pull request Aug 18, 2026
## @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))
christophebrun-forest added a commit that referenced this pull request Aug 18, 2026
…-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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants