Skip to content

Networks and proxies

You set your machine’s proxy and its trusted certificates once for each tool, through that tool’s standard mechanism. CORA honors what you set for the requests its own code makes. The other tools it runs, such as npm, git and Chrome, follow their own settings, as What CORA connects to shows.

cora and cora-mcp reach the CORA service through the proxy the environment names, as most command-line tools do:

  • HTTPS_PROXY names the proxy, as an http:// or https:// URL, such as http://proxy.example.com:8080.
  • HTTP_PROXY names it when HTTPS_PROXY is unset.
  • NO_PROXY lists the hosts to reach without the proxy, separated by commas or spaces.

The service is on HTTPS, so each request reaches it through the proxy’s CONNECT tunnel. Set the variable in the shell that runs cora:

Terminal window
export HTTPS_PROXY=http://proxy.example.com:8080
npx cora auth login

To keep it for every shell, set it in your shell’s profile, or in your Windows user environment variables. The environment variable reference lists each variable under the network kind. These rules apply to all three:

  • Each variable is also read in lower case, such as https_proxy. Outside Windows, the lower-case one wins when both are set. On Windows, variable names ignore case, so the two are one variable.
  • An empty variable counts as unset.
  • A NO_PROXY entry covers its host and the host’s subdomains, with or without a leading . or *.. So vispero.com covers cora.vispero.com.
  • A NO_PROXY entry with a port, such as cora.vispero.com:443, covers that port alone. NO_PROXY=* covers every host.
  • A proxy that asks for credentials takes them in its URL, percent-encoded, such as http://user:p%40ss@proxy.example.com:8080. cora and cora-mcp replace the credentials in any URL they write with REDACTED.
  • A value that is not an http:// or https:// URL without a path fails with config.invalid-environment, such as proxy.example.com:8080 without its scheme. The error names the variable, never its value.

Each request to the service, its answer included, must finish within service.requestTimeout. A request that takes longer fails with service.unreachable, and its message names the setting and its value.

On a network whose proxy or VPN is slow, raise it in your user config, in milliseconds:

config.json
{ "service": { "requestTimeout": 60000 } }

For one run, set CORA_SERVICE_REQUEST_TIMEOUT instead. The setting’s reference entry gives its default.

cora and cora-mcp trust the operating system’s certificate store, as well as Node.js’s own root certificates. That covers the common case of a TLS-inspecting proxy, such as Cloudflare WARP, Zscaler or Netskope. Such a proxy opens each HTTPS connection and signs it again with a root certificate your organization installs in the store. Once the root is there, requests to the service work with nothing to set.

They read the store where the operating system keeps it:

Platform Store
Windows The trusted root certificates of the machine’s and your user’s certificate stores
macOS The certificates the default and system keychains trust for SSL
Linux OpenSSL’s certificate file and directory, such as /etc/ssl/certs, or those SSL_CERT_FILE and SSL_CERT_DIR name

Where the root is not in the store, save it as a PEM file, and name the file in NODE_EXTRA_CA_CERTS. Node.js reads the variable as it starts, so set it before you start cora, or the coding agent that starts cora-mcp:

Terminal window
export NODE_EXTRA_CA_CERTS=/path/to/proxy-root.pem
npx cora auth login

A coding agent starts cora-mcp, and decides which of its environment variables cora-mcp gets. The two agents differ:

  • Codex starts a server with only a few of its own variables, such as PATH and HOME. It passes each other one only when the entry names it in env_vars.
  • Claude Code sets the variables an entry’s env names. Its docs do not say whether a server also gets the rest of Claude Code’s environment. The project agent’s server does: it starts with the environment Claude Code runs in.

CORA’s plugin names these in both agents’ entries, each taken from the environment the agent runs in:

  • the proxy variables, in upper and lower case;
  • NODE_EXTRA_CA_CERTS;
  • NODE_TLS_REJECT_UNAUTHORIZED.

Set them where the agent starts, such as the shell you start claude or codex from.

The plugin’s entries do not name the following. Under Codex, they never reach the plugin’s cora-mcp. Under Claude Code, they reach it only if Claude Code passes its whole environment on.

  • SSL_CERT_FILE and SSL_CERT_DIR. Claude Code’s entry gives each variable it names an empty value when it is unset, and on Linux Node.js reads an empty one as a store with no roots. So where a root is only in a file they name, name that file in NODE_EXTRA_CA_CERTS too, which reaches cora-mcp under both agents.
  • CORA_SERVICE_REQUEST_TIMEOUT. Set service.requestTimeout in your user config, which every cora-mcp reads.

An entry you write yourself passes on what you name in it:

Set each variable in the entry’s env, so it reaches cora-mcp whether or not Claude Code passes its whole environment on. Give it only a variable you set: an empty SSL_CERT_FILE or SSL_CERT_DIR empties the store on Linux.

.mcp.json
{
"mcpServers": {
"cora": {
"type": "stdio",
"command": "npx",
"args": [
"--yes",
"--prefer-offline=false",
"--fetch-retries=0",
"--fetch-timeout=3000",
"@vispero/cora-mcp@<version>"
],
"env": { "NODE_EXTRA_CA_CERTS": "/path/to/proxy-root.pem" }
}
}
}

Each start of cora-mcp from the plugin’s entry, or from an entry like it that runs npx, asks npm’s registry for the release and its dependencies, even where your npm config sets prefer-offline, so a release newer than the versions npm has cached still starts. When the registry refuses the connection, or sends nothing for 3 seconds once connected, npx starts the release from npm’s cache, so a release that ran before starts without the network. npm’s offline setting still applies: with it, npx asks no registry, and starts only a release npm has cached.

The first start of a release npm hasn’t cached, such as after the plugin updates, gives up after those 3 seconds too. A registry mirror that fetches a package it lacks before it answers can take longer, and the start then fails, with ETARGET when it is cora-mcp’s version list that took longer. To get past it, fetch the release with npm’s own wait, then restart the server from your agent:

Terminal window
npx --yes --prefer-offline=false @vispero/cora-mcp@<version> --version

For a project’s first setup, cora init does this for the coding agents it sets up: its fetch waits 30 seconds for each answer, and leaves the project’s release cached for the agent’s start.

The connection counts as open once its TLS handshake completes and, through a proxy, once the proxy’s tunnel is open. Until then npm’s 3 seconds haven’t started, so a connection that never opens holds the start:

  • A proxy or registry whose network drops the connection, such as a corporate proxy while you’re off its VPN, holds it until the operating system gives up: about 20 seconds on Windows, over a minute on macOS, and over two minutes on Linux.
  • One that takes the connection and never completes the handshake or the tunnel holds it with no end.

Such a start can outlast your agent’s startup timeout, and the agent then shows CORA’s server as failed. A connection that is refused, or a host name your DNS server says doesn’t exist, falls back to the cache at once. For the registry, npm takes its proxy from its own https-proxy or proxy setting, or else from HTTPS_PROXY or https_proxy, so the variable you set for cora reaches it too.

cora mcp and cora init ask no registry for a release npm has cached, so on such a network only a release npm hasn’t cached holds them: cora mcp until the connection fails or your agent’s startup timeout passes, and cora init for up to 10 minutes, after which it goes on without it.

On such a network, turn on npm’s offline, so npx starts the release from its cache without asking the registry:

Terminal window
npm config set offline true

Once you’re on a network that reaches the registry again, turn it off:

Terminal window
npm config delete offline

offline is in your user .npmrc, so it applies to every npm command on the machine: while it’s on, an npm install that needs a package npm hasn’t cached fails, and npx starts only a release npm has cached. The first start of a release it hasn’t, such as after the plugin updates, fails within seconds: with ETARGET where npm’s list of cora-mcp’s versions predates the release, and otherwise with ENOTCACHED.

Where it’s a proxy that can’t be reached, you can instead remove it from npm’s settings, and remove HTTPS_PROXY and https_proxy from the agent’s environment.

npx cora info shows what cora reads in the shell it runs in:

  • Its Service section gives the service’s address and its request timeout, with their values.
  • Its Environment section lists each variable on this page that is set, never with its value, then the names of those that are not, after Unset:.

It reads its own shell, not what an agent passed to cora-mcp.

When a request fails, service.unreachable says what failed, with the network error’s code, such as the connection to 127.0.0.1:8080 was refused (`ECONNREFUSED`) for a proxy that is not running, or gives the timeout it reached. For a certificate the machine does not trust, its message says so and gives the TLS error’s code, and its hint names the fixes:

error[service.unreachable]: Could not reach https://cora.vispero.com: this machine does not trust the certificate it presented (`SELF_SIGNED_CERT_IN_CHAIN`)
hint: A TLS-inspecting proxy may sign this network's connections: install its root certificate in the operating system's store, or name a PEM file that holds it in `NODE_EXTRA_CA_CERTS`, then run the command again.

CORA’s own requests go only to the CORA service. Each other host is reached by another tool, which reads its own settings:

  • The CORA service, https://cora.vispero.com, for signing in, renewing a signed-in token, and fetching the service’s current signing keys: see What CORA sends to the service. CORA’s settings apply, as this page sets them.
  • npm’s registry, when npx starts cora-mcp for a coding agent, and when cora init, cora mcp and cora-mcp’s version alignment fetch a cora-mcp release. npm reads its own settings for it, such as https-proxy, noproxy and cafile, and where they’re unset, HTTPS_PROXY and NO_PROXY, as npm’s registry says.
  • GitHub, when Claude Code and Codex clone CORA’s plugin marketplace, Vispero/cora-plugins, with git. git’s settings apply, such as http.proxy and http.sslCAInfo in git config.
  • Your app, which Chrome loads for each page cora scan scans or an agent opens in cora-mcp’s browser. Chrome’s own settings apply: CORA gives Chrome no proxy.

cora scan also asks the config’s server.url whether your app’s server is ready, through no proxy. cora auth login opens its sign-in page in your browser where it can, and the browser follows its own settings.