Skip to main content
Glama

Range Remote

Range Remote is an open-source remote MCP service designed for ChatGPT plugins. It lets a user connect a computer or server through an outbound-only agent and then use narrowly described MCP tools for filesystem inspection, file editing, Git inspection, and shell execution under a locally selected restricted or unrestricted mode.

Architecture

ChatGPT / Codex
      |
      | OAuth 2.1 / OIDC
      v
Range Remote auth
      |
      | JWT bearer token
      v
Range Remote relay (MCP over HTTPS)
      |
      | authenticated WebSocket
      v
Range Remote agent
      |
      +-- restricted mode: allowed roots / sensitive-file policy / optional shell
      +-- unrestricted mode: full permissions of the local OS user

The relay never needs inbound access to the user's device. The agent opens the connection outward. Local access policy is chosen on the device and cannot be changed remotely.

Related MCP server: Kastor

Local access modes

Restricted mode remains the default for new pairings. It limits filesystem operations to explicit roots, blocks common credential paths by default, and requires a separate shell opt-in.

For a trusted personal device, --unrestricted deliberately removes those application-level permission barriers. Filesystem and Git operations may reach any path the agent OS user can access, sensitive-file filtering is disabled, shell execution is enabled, and child processes inherit the agent's full environment. Operating-system permissions and UAC/sudo still apply. Relay-side authentication, device ownership checks, rate limits, and OCI isolation are unchanged.

npm run dev:agent -- pair \
  --server https://remotemcp.range08.shop \
  --code ABCDEF-GHJKLM \
  --name my-pc \
  --unrestricted

Codex skills and MCP bridge

Range Remote can expose Codex-compatible skills and locally configured MCP servers from a paired device without moving their credentials to the relay.

Skills use Codex's progressive-loading shape: list_skills returns only the name, description, source, and SKILL.md path, while read_skill loads the selected instructions, optional agents/openai.yaml, and resource filenames. Project skills are discovered from .agents/skills along the current working directory's repository path; user and administrator locations are ~/.agents/skills and /etc/codex/skills when local policy permits them.

The MCP bridge reads Codex-style mcp_servers configuration from /etc/codex/config.toml, $CODEX_HOME/config.toml (default ~/.codex/config.toml), and project .codex/config.toml files from repository root to the requested working directory. Later layers override earlier ones. It supports STDIO and Streamable HTTP servers, fixed environment variables, Codex env_vars string/object entries with local sources, configured HTTP headers, bearer-token environment variables, tool allow/deny filters, startup_timeout_sec/startup_timeout_ms, and tool timeouts. Secret environment/header values are consumed only on the paired device and are not returned by list_mcp_servers.

MCP execution is a separate local capability because starting an STDIO server or contacting an HTTP MCP server can execute code or access external services. Restricted pairings require --allow-mcp; unrestricted pairings enable it automatically. Existing unrestricted configs created before this capability are treated as MCP-enabled on load, while existing restricted configs remain disabled. Restricted mode still applies the existing allowed-root policy to skill and Codex configuration paths, so user-level locations outside the allowed roots are intentionally not exposed unless the device is paired with a suitable root or unrestricted mode.

Interactive downstream OAuth and Codex's http_headers_helper are not bridged yet. Codex remote-executor MCP placement (experimental_environment = "remote" and env_vars entries with source = "remote") is also rejected explicitly because the paired-device bridge has no Codex remote-executor context. Servers using OAuth need a locally available bearer token/header configuration or will return an explicit authentication error.

Usage dashboard

Authenticated users can open /usage on the public Range Remote host to see private usage analytics for their own account. The dashboard shows tool calls for the current UTC calendar month, today's calls, all-time calls, success rate, average latency, a 30-day activity chart, top tools, and recent tool activity. Range Remote does not impose a monthly usage quota; the dashboard labels the plan as Unlimited rather than presenting an artificial limit.

The same data is available to MCP clients through the read-only get_usage_statistics tool. The statistics query does not count itself. Analytics persist in the relay SQLite database and contain only the tool name, success/failure result, execution duration, timestamp, OAuth client identifier, and targeted device identifier when applicable. Tool arguments, file paths, command text, outputs, and returned file contents are not stored as usage analytics.

The browser dashboard uses the existing Range Remote account credentials. A signed HTTP-only dashboard session is also issued after a successful OAuth login. The authorization service reads usage through an internal-only relay endpoint protected by INTERNAL_API_TOKEN; the gateway does not expose that endpoint publicly. Existing installations must set a long random INTERNAL_API_TOKEN before deploying this feature.

Security defaults

  • Restricted mode confines filesystem tools to explicitly configured roots; unrestricted mode intentionally removes this application-level boundary.

  • Restricted mode denies common sensitive credential paths by default. Because tracked diffs can expose file contents, git_diff also requires local sensitive-file opt-in in restricted mode. Unrestricted mode intentionally permits these operations subject to OS permissions.

  • Restricted mode disables shell execution unless enabled locally. Unrestricted mode enables shell automatically and passes through the agent process environment. In either mode, shell commands run with the operating-system permissions of the agent process.

  • File reads/writes and command output have size limits.

  • Restricted path checks resolve symlinks before enforcing allowed roots.

  • Device tokens are generated once and stored only as SHA-256 hashes on the relay.

  • MCP access requires OAuth 2.1 bearer tokens.

  • Tools advertise readOnlyHint, destructiveHint, and openWorldHint to ChatGPT.

Repository layout

  • apps/server: public HTTPS MCP relay and device WebSocket gateway.

  • apps/auth: OAuth 2.1 / OpenID Connect authorization server with DCR, PKCE S256, RFC 8707 resource indicators, SQLite persistence, and persistent signing keys.

  • apps/agent: local/remote device agent.

  • packages/shared: RPC schemas shared by relay and agent.

  • PRIVACY.md: privacy and data-handling notes.

Local development

Requirements: Node.js 24.15+.

npm install
npm run build
npm test

Copy .env.example to .env, set two cookie-signing keys, and set AUTH_ALLOW_REGISTRATION=true only while creating an account. Registration is disabled by default. Then start the authorization server and relay in separate terminals:

npm --workspace @range-remote/auth run dev
npm run dev:server

The built-in authorization server supports dynamic client registration, authorization code + PKCE S256, refresh tokens through offline_access, and resource-bound JWT access tokens.

Pair an agent:

npm run dev:agent -- pair \
  --server http://127.0.0.1:8787 \
  --code ABCD-EFGH \
  --name my-device \
  --root "$HOME/projects"

Shell access requires an explicit local opt-in:

npm run dev:agent -- pair \
  --server http://127.0.0.1:8787 \
  --code ABCD-EFGH \
  --name my-device \
  --root "$HOME/projects" \
  --allow-shell

Then keep the agent connected:

npm run dev:agent -- start

Inspect the saved local mode without printing the device token:

node apps/agent/dist/index.js status

Production

The production MCP endpoint is https://remotemcp.range08.shop/mcp. Range Remote uses its own dedicated range-remote-gateway on the remotemcp.range08.shop origin; it is not routed through or combined with the personal range08.shop homepage. Cloudflare Tunnel reaches only the gateway. The authorization server and MCP relay live on a separate internal-only Docker network and have no published host ports or direct Internet egress.

Production containers run as non-root with read-only root filesystems, dropped Linux capabilities, no-new-privileges, and CPU, memory, and PID limits. Only the authorization container receives cookie-signing secrets; the MCP relay receives the internal JWKS URL and public authorization metadata instead. The relay also bounds WebSocket payloads, connected agents, pending device calls, per-device concurrency, and per-user request concurrency/rate so an authenticated user cannot consume unbounded OCI resources.

The authorization server advertises authorization-code flow only, requires PKCE S256, supports refresh tokens, and binds access tokens to the dedicated Range Remote origin.

Support

Use the GitHub issue tracker for non-sensitive support requests. Report security vulnerabilities privately through GitHub Security Advisories.

  • Privacy: PRIVACY.md

  • Terms: TERMS.md

  • Security: SECURITY.md

Related MCP Connectors

Related MCP Servers