Skip to content

npm launcher cannot start on Windows behind restricted networks: win32 has no npm fast path, GitHub release download fails (ECONNRESET/ETIMEDOUT) #597

Description

@wordgao

Summary

On Windows, npx crw-mcp (v0.37.1) cannot start at all behind a restricted network. The npm package is a JS launcher that resolves the native binary in three steps; on win32 the first two always fail, so it must download from GitHub Releases — and that download is exactly what gets blocked.

The launcher's own stderr:

crw-mcp: could not locate or download the win32-x64 binary.
  could not fetch SHA256SUMS for v0.37.1: read ECONNRESET
  (retry) could not fetch SHA256SUMS for v0.37.1: connect ETIMEDOUT 20.205.243.166:443
  Set CRW_MCP_BINARY=/path/to/crw-mcp to use a local build, or install
  from https://github.com/fastcrw/crw/releases.

The MCP client then hangs waiting for initialize (no stdout at all), so the server just looks "broken" rather than "offline".

Environment

  • crw-mcp@0.37.1 from npm, started via npx crw-mcp
  • OS: Windows 11 x64
  • Network: github.com reachable at TCP level for some endpoints but release downloads blocked / intermittent (ECONNRESET, ETIMEDOUT 20.205.243.166:443). api.github.com works fine (REST queries and releases/assets/{id} downloads both succeed).

Why Windows always takes the download path

Reading bin/crw-mcp.js, resolveBinary() is:

return fromEnv() || fromPackage() || (await fromDownload());
  1. fromEnv() — CRW_MCP_BINARY / CRW_BINARY, only if the user already has a binary.
  2. fromPackage() — require.resolve("crw-mcp-win32-x64/package.json"), the npm fast path.
  3. fromDownload() — GitHub Releases, verified against SHA256SUMS.

Step 2 is unavailable on Windows today: optionalDependencies lists only the four darwin/linux packages, and the reason is legitimate — crw-mcp-win32-x64 on npm is a security-held placeholder (0.0.1-security), so the real platform package cannot be published under that name. The code comment even calls this out ("robust to a missing/unpublishable platform package (e.g. npm security-held names)").

The consequence is that every Windows user falls through to GitHub Releases on first run, which is the one channel that is commonly blocked or flaky.

Suggested fixes (in preference order)

1. Publish the Windows platform package under a scoped name → real npm fast path

Scoped names can't be squatted the way bare names can:

@fastcrw/crw-mcp-win32-x64
@fastcrw/crw-mcp-win32-arm64

Add them to optionalDependencies and keep the old bare names as a secondary lookup. npm (and npm mirrors such as registry.npmmirror.com, which is reachable in this environment) would then deliver the binary the same way darwin/linux already get it — no GitHub dependency at all.

2. Fall back to api.github.com before giving up

fromDownload() uses https://github.com/{repo}/releases/download/.... In the environment tested here, that host timed out while api.github.com worked:

GET https://api.github.com/repos/fastcrw/crw/releases/assets/{id}
  Accept: application/octet-stream        → success (10 MB asset)
GET https://github.com/fastcrw/crw/releases/download/v0.37.1/... → ETIMEDOUT

The asset id is already obtainable from GET /repos/{repo}/releases/tags/v{VERSION}. Trying the API host before failing would likely fix this case with a few lines.

3. Honor proxy settings

https.get() is called with no agent, so HTTPS_PROXY / HTTP_PROXY are ignored. Many restricted environments only allow egress through a proxy. Node's undici/HttpsProxyAgent, or simply documenting CRW_MCP_BINARY, would help.

4. Make the manual-install error message actionable

The current message says "Set CRW_MCP_BINARY=... or install from the releases page", but doesn't say where to put the file. The launcher already knows its own cache path:

path.join(process.env.LOCALAPPDATA, "crw-mcp", `v${VERSION}`, "crw-mcp.exe")

Printing that exact path would have saved a lot of guesswork. Suggested wording:

crw-mcp: could not download win32-x64 binary (network unreachable).
  Manual install:
    1. download  https://github.com/fastcrw/crw/releases/download/v0.37.1/crw-mcp-win32-x64.zip
    2. verify    sha256 must equal 69a26ccbed6383ec8d6a61bd53f5d7b78927c03f62886be2e5c69280dc43df2c
                 (from .../v0.37.1/SHA256SUMS, line: crw-mcp-win32-x64.zip)
    3. extract crw-mcp.exe to:
       %LOCALAPPDATA%\crw-mcp\v0.37.1\crw-mcp.exe

A crw-mcp doctor / --binary-path subcommand that prints the resolved path and whether it exists would also be useful for support.

Reproduction

npx crw-mcp@0.37.1
# stderr as above, then the client waits forever for `initialize`

Workaround that worked (verified)

  1. Fetch SHA256SUMS and crw-mcp-win32-x64.zip through api.github.com/releases/assets/{id} (that route was reachable).
  2. Verify the zip against SHA256SUMS — matched:
    69a26ccbed6383ec8d6a61bd53f5d7b78927c03f62886be2e5c69280dc43df2c
  3. Extract crw-mcp.exe (26,555,904 bytes) to %LOCALAPPDATA%\crw-mcp\v0.37.1\.

After that the server started cleanly:

INFO crw_mcp: Starting crw-mcp v0.37.1 (embedded mode)
initialize → server: crw-mcp 0.37.1, protocol 2025-06-18
tools/list → 8 tools

No credentials, usernames or tokens are reproduced anywhere in this report; all paths are shown in env-var form.

Aside: the --user-data-dir fix in this release works perfectly — profiles now go to %LOCALAPPDATA%\crw\chrome-profiles\ and are removed on exit (0 leftover dirs, 0 orphaned processes). Thanks for that; this report is only about the launcher's ability to obtain the binary in the first place.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions