MCP server - HTTP transport
With the default stdio setup, your AI client launches the binary for you whenever it starts - you never run it yourself. With --http, you run the binary yourself as a long-lived server and leave it running, and clients connect to its local HTTP port. It's protected by loopback-only binding, Host/Origin allowlists, and a required bearer token (the Threat model below explains why that combination is safe).
Setup
Use the binary you installed in the MCP server - quick start — substitute its path for ./resilio-mcp-server in the commands below. On Windows that's the full path from your install section, e.g. "C:\Users\<YOUR-USERNAME>\AppData\Local\Programs\Resilio MCP Server\resilio-mcp-server.exe".
-
Generate a token:
This prints the token once to the terminal and writes only its SHA-256 hash to
RESILIO_HTTP_TOKEN_HASHin your.env(the plaintext is never stored). Copy the token somewhere safe for step 3. -
Start the server in HTTP mode, and leave it running:
The server listens on
http://localhost:3001— loopback only (use--port <n>to change the port). This process must stay alive; your client connects to it over HTTP. -
Point your AI client at it, with the token in an
Authorization: Bearerheader:-
Claude Code (native HTTP support):
claude mcp add --transport http resilio-http http://localhost:3001/ \ --header "Authorization: Bearer <token>"Verify with
claude mcp list(should show✓ Connected). -
Claude Desktop and other stdio-only clients have no native HTTP transport — they can't hit the port on their own. You can still connect them by bridging to your running
--httpserver withmcp-remote(this is what makes Claude Desktop work with--http). Simpler alternative if you don't specifically need HTTP: just use the stdio setup. To bridge, inclaude_desktop_config.json:Desktop launches MCP servers with a minimal{ "mcpServers": { "resilio-http": { "command": "/absolute/path/to/npx", "args": ["-y", "mcp-remote@latest", "http://localhost:3001/", "--header", "Authorization: Bearer <token>", "--transport", "http-only"], "env": { "PATH": "/absolute/path/to/node/bin:/usr/local/bin:/usr/bin:/bin" } } } }PATH, so use absolute paths. Quit and reopen Desktop after editing, and keep the--httpserver from step 2 running — the bridge connects to it on demand.
-
Token housekeeping:
- Rotate tokens by re-running
--generate-token— it rewrites only theRESILIO_HTTP_TOKEN_HASHline (every other key preserved), the old token stops working immediately, then update your client configuration with the new one. - Storage is hash-only — The 256-bit random token can't be recovered from its stored hash, so a leaked
.envexposes nothing usable. - Don't confuse it with
RESILIO_API_TOKEN/RESILIO_AUTH_TYPE- The HTTP bearer token is how clients authenticate to this server;RESILIO_API_TOKENis how this server authenticates to the Management Console — opposite directions. An incorrectRESILIO_AUTH_TYPEmakes tool calls fail against the Management Console even though the HTTP token is correct.
Threat model
The HTTP transport is designed to be safe to run on your workstation against the following threats:
- Off-machine attackers (anyone on your LAN or the internet) cannot reach the server. Kestrel binds to the loopback interface only.
- Malicious websites you visit in a browser, including DNS-rebinding attacks where an attacker resolves
evil.comto127.0.0.1, cannot make working requests against the server. Cross-origin requests are blocked by anOriginallowlist, and rebinding-style requests are blocked by aHostallowlist.
The HTTP transport is not designed to isolate the MCP Server from other processes running on the same machine as the same user. Any local process running as your user account can connect to the loopback port and call tools. This is treated as an acceptable risk — those processes already have full access to your files, network, and existing MCP .env. If you don't trust local code running as your user, neither stdio nor --http mode will help.
How the protection works
When you run ./resilio-mcp-server --http (or dotnet run -- --http in development), four layers apply to every incoming request, in the following order:
- Loopback-only binding - Kestrel listens on
127.0.0.1/[::1]only. There is no listener on any external interface. Hostheader check - TheHostheader must belocalhost,127.0.0.1, or[::1](any port). A browser fetchinghttp://evil.com:3001/...— even after DNS rebinding to a loopback address — still sendsHost: evil.comand is rejected with403 Forbidden.Originheader check - Cross-origin requests are rejected unless theirOriginis in the allowlist (see below). Browsers stamp the page's real origin into this header; page JavaScript cannot forge it.- Bearer-token check - Every request must carry
Authorization: Bearer <token>matching the configured token, or it is rejected with401 Unauthorized(no body). This runs last, after theHost/Originchecks, on purpose: a rebinding or cross-origin probe is dropped with a403before the token is ever consulted, so a failed probe never learns whether a token would have worked.
The token check is per request, not per connection — it runs on the very first message (initialize) and on every tool call after it. A wrong or missing token fails initialize, so the client can't even connect; there is no "authenticate once, then trust the session."
Requests with no Origin header — which is how native MCP clients connect — pass the Origin check, since they aren't browser requests. The Host and bearer-token checks still apply to them.
Origin allowlist (RESILIO_HTTP_ALLOWED_ORIGINS)
By default (with RESILIO_HTTP_ALLOWED_ORIGINS unset or empty), any loopback origin is allowed (http://localhost:<any-port>, http://127.0.0.1:<any-port>, etc.).
If you want a different origin (for example a browser-based MCP client running at http://localhost:5172), set the variable to a comma-separated list of exact origins:
Any request with an Origin header not in the list is rejected with 403 Forbidden. The comparison is case-insensitive; entries must be full origins (scheme + host + port), with no trailing slash. The literal opaque origin null (sent by file:// pages and sandboxed iframes) is never accepted.
Session idle timeout (RESILIO_HTTP_IDLE_TIMEOUT)
The Streamable HTTP transport tracks one session per client and closes it after an idle period. The default is 24 hours (1440 minutes) — deliberately long so a bridged client (e.g. mcp-remote) doesn't hit Session not found between tool calls. Set RESILIO_HTTP_IDLE_TIMEOUT to a positive number of minutes to override it; empty, non-numeric, or non-positive values fall back to the default.