Skip to content

Transport is resolved before environment variable expansion in mcp.json #10654

Description

@digregoriovalerio

What happened?

If you use:

{
"mcpServers": {
"example": {"url": "${MY_VAR}"}
}
}

Doesn't resolve the transport correctly. If I use "http://${MY_VAR_WITHOUT_SCHEMA}" then it works.

The url should be resolved with the same logic used for headers and env values.

I believe mcp-servers.ts in validateMcpServerConfig() should use the url after environment variable expansion. Same issue in runtime.ts in createDefaultTransport(). Same issue in McpServerConnection.oauthUrl.

Steps to reproduce

use:

{
"mcpServers": {
"example": {"url": "${MY_VAR}"}
}
}

In mcp.json

Expected behavior

This mcp.json:

{
"mcpServers": {
"example": {"url": "${MY_VAR}"}
}
}

Should be able to connect as streamable-http.

Version

1.0.4

Activity

  1. github-actions commented on Oct 8, 2026

    @github-actions
    Contributor

    This issue was auto-closed. All issues from new contributors are auto-closed by default.

    Maintainers review auto-closed issues daily and reopen worthwhile ones. Issues that do not meet the quality bar in CONTRIBUTING.md will not be reopened or receive a reply.

    If a maintainer replies lgtmi on one of your issues, your future issues will stay open. If a maintainer replies lgtm, your future issues and PRs will stay open. The command must be at the start of the reply (optionally after one or more @username mentions) or at the end.

    See CONTRIBUTING.md.

  2. added
    untriagedThis issue has been auto closed and has not been triaged
    on Oct 8, 2026
  3. added
    mcpIssues related to built in mcp extension
    on Oct 8, 2026
  4. removed
    untriagedThis issue has been auto closed and has not been triaged
    on Oct 8, 2026
  5. digregoriovalerio commented on Oct 8, 2026

    @digregoriovalerio
    Author

    Figured out that http://${MY_VAR_WITHOUT_SCHEMA} makes the transport work but actually connection doesn't come up. Seems like env vars are not working in URL.

  6. BaaRai commented on Oct 8, 2026

    @BaaRai

    Confirmed, and there is a fourth place the raw url leaks into: the auth guard.

    • validateMcpServerConfig rejects ${VAR} urls before expansion ever runs.
    • createDefaultTransport passes config.url to StreamableHttpTransport unexpanded (headers and env values next to it go through resolveConfigValueOrThrow).
    • McpServerConnection.oauthUrl hands the raw url to OAuth discovery.
    • validation is also what enforces "auth requires https or loopback", so simply skipping the url check for expandable values would make the credential guard bypassable through an env var. The expanded value needs the same check.

    I have a fix that follows the headers pattern: urls may reference ${NAME} or !cmd (new isExpandableConfigValue helper), validation defers the url checks when the value is expandable, and createDefaultTransport expands with resolveConfigValueOrThrow and enforces the http(s) and auth-https constraints on the expanded value (shared httpServerUrlError helper, so both sites use the same rules). oauthUrl expands the same way but stays non-throwing since it runs in the constructor. A missing variable fails the connection with the resolver's error naming the variable.

    Regression test at test/suite/regressions/10654-mcp-url-env-expansion.test.ts covers: expandable urls pass validation, literal garbage still fails, transport gets the expanded url, non-http expansions are rejected, missing variable is named, and the auth guard holds on expanded urls. npm run check passes.

    Happy to send the PR. lgtm?

  7. digregoriovalerio commented on Oct 8, 2026

    @digregoriovalerio
    Author

    I'd really appreciate such a quick fix. I'm integrating PI and this is a blocker for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingmcpIssues related to built in mcp extension

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions