Skip to main content
Glama

llm-gateway

Local MCP gateway to LLM-powered tools, backed by an OpenAI-compatible LLM (LM Studio by default). Runs shell commands and compresses their output, extracts answers from large files, drives local opencode and Codex agents, and runs browser-automation tasks.

Run

cd ui && npm install && npm run build
OPENAI_BASE_URL=http://127.0.0.1:1234/v1 uv run llm-gateway

ui/dist is a gitignored build artifact; build it before starting from a fresh checkout. Example systemd user units are in contrib/systemd/, see below.

Serves over HTTP (streamable-http) at http://<MCP_HOST>:<MCP_PORT>/mcp.

Env

Default

Purpose

MCP_TRANSPORT

streamable-http

Transport: streamable-http, sse, or stdio.

MCP_HOST

127.0.0.1

Bind address (HTTP transports).

MCP_PORT

1235

Bind port (HTTP transports).

OPENAI_BASE_URL

http://127.0.0.1:1234/v1

OpenAI-compatible backend for compression.

OPENAI_API_KEY

lmstudio

Backend API key.

COMPRESSOR_MODEL

empty

Model to use; empty lets the backend use its loaded model.

COMPRESSOR_MAX_INPUT_CHARS

100000

Input size cap before truncation.

OPENCODE_URL

http://127.0.0.1:4096

opencode serve endpoint for opencode and browser.

CODEX_APP_SERVER_SOCKET

$XDG_RUNTIME_DIR/codex-app-server/app-server.sock

Codex app-server unix socket.

CODEX_APP_SERVER_TRANSPORT

websocket

Codex socket protocol: websocket or jsonl.

LLM_GATEWAY_ALLOW_REMOTE

unset

Set to 1 to allow a non-loopback MCP_HOST.

LLM_GATEWAY_ALLOWED_HOSTS

empty

Extra allowed Host values, comma-separated (e.g. 192.168.1.5:1235).

Related MCP server: Termada

Security

The gateway has no authentication and its tools run arbitrary shell commands, read any file and drive agents. It is meant for loopback use only. See SECURITY.md for the threat model and how to report issues.

  • Every HTTP route (MCP and dashboard) rejects requests whose Host is not loopback or listed in LLM_GATEWAY_ALLOWED_HOSTS (421), whose Origin is not allowed (403), and POSTs without Content-Type: application/json (400). This blocks DNS rebinding and cross-site requests from pages open in your browser.

  • A non-loopback MCP_HOST (e.g. 0.0.0.0) is refused at startup unless LLM_GATEWAY_ALLOW_REMOTE=1. With it set, anyone who can reach the port can run commands. Prefer an SSH tunnel.

Tools

Tool

Params

Purpose

run_command

command, prompt, timeout=90, cwd

Run a shell command, return LLM-compressed output.

extract_from_file

file_path, prompt, cwd

Extract only the requested information from a file.

opencode

prompt, cwd, session_id, timeout=3600

Run the local opencode agent.

browser

task, url, cwd, session_id, timeout=3600

Browser task via opencode with Playwright MCP; pass/fail verdict.

codex

prompt, cwd, session_id, timeout=3600

Run Codex through the local app-server.

Tools are auto-registered from tools/ (every BaseTool subclass); the handle() docstring becomes the MCP tool description. cwd must be an absolute existing directory for opencode, browser and codex. Each agent tool prints Session ID: ... on the first output line; pass it back as session_id to continue that session.

Codex tool

codex connects to the locally installed, already-authenticated Codex app-server. It needs no API key in the gateway process. Ensure codex is on the service's PATH, its service user has completed Codex authentication, and codex-app-server.service is running. Each call opens a connection to the private app-server socket, runs with the on-request approval policy, and confines each turn to a workspace-write sandbox rooted at its supplied cwd. The dashboard approval card handles requested sandbox escapes, command, file-change, and extra-permission prompts.

Dashboard & live streaming

A run dashboard is served at / (same host:port as /mcp): a two-pane UI listing past runs, streaming live progress, answering permission prompts, and showing Claude / Codex subscription usage.

Endpoint

Purpose

GET /

Dashboard UI.

GET /runs

JSON list of run summaries.

GET /events

SSE firehose of all runs' events.

GET /events/{id}

SSE stream for one run; replays buffered events, then tails.

POST /permission/{request_id}/reply

Answer a pending permission prompt: {reply: once|always|reject, message?}.

GET /usage

Claude and Codex usage windows; Codex cached 5 min, ?refresh=1 forces a re-read.

POST /usage/claude

Claude Code status line reports {rate_limits}, see below.

GET /screenshot?path=...

Serve a png/jpg/webp screenshot published by the browser tool since server start.

GET /plan/{id}

Planner plan review UI, see below.

/usage never reads credential files. Codex windows come from the local Codex app-server (account/rateLimits/read). Claude windows are pushed by Claude Code's own status line, which receives rate_limits on stdin (Pro / Max, after the first response in a session). Add this to your status line script right after it reads stdin; until it reports, the Claude card shows "no data yet":

input=$(cat)
printf '%s' "$input" | python3 /path/to/llm-gateway/scripts/claude_usage_report.py >/dev/null 2>&1 &

Each SSE event is {run_id, seq, ts, type, ...}. Lifecycle events (produced by the hub): run_started {meta}, meta {meta}, run_finished {exit_code, timed_out}. Content events (produced by each tool, translated into this canonical shape, see events.py): line {text}, text {part_id?, text}, reasoning {part_id?, text}, tool_use {part_id?, tool, arg, status, output?, duration_ms?, screenshot_url?} (status is one of running / completed / error), step_start {part_id?}, step_finish {part_id?, tokens_total, cost?}, permission_ask {part_id?, request_id, title, status, reply?} (status is pending or resolved). Codex runs additionally publish codex_event {event_type, data} for every app-server notification and request; the dashboard shows these as expandable trace entries so unrecognized future protocol events are not silently lost.

UI dev server with API proxy to LLM_GATEWAY_URL (default http://127.0.0.1:1235):

cd ui && npm run dev

Planner plugin

plugins/planner is a Claude Code plugin that reviews plans from plan mode in the browser. Its PermissionRequest hook on ExitPlanMode posts the plan to the gateway (POST /plan), opens /plan/{id} for line annotations and approve / request changes, then long-polls GET /plan/{id}/decision. If the gateway is unreachable it fails open to the built-in approval prompt. See plugins/planner/README.md for install. The hook reaches the gateway at LLM_GATEWAY_URL (default http://127.0.0.1:1235).

Claude Code MCP config

claude mcp add --transport http llm-gateway http://127.0.0.1:1235/mcp

Or in config:

{
  "mcpServers": {
    "llm-gateway": {
      "type": "http",
      "url": "http://127.0.0.1:1235/mcp"
    }
  }
}

Tools are exposed to Claude as mcp__llm-gateway__<tool>, e.g. mcp__llm-gateway__run_command.

Tests

uv run python -m unittest discover -s tests

systemd user services

Example units live in contrib/systemd/:

  • llm-gateway.service requires codex-app-server.service and wants opencode-serve.service.

  • codex-app-server.service runs codex app-server --listen unix://%t/codex-app-server/app-server.sock.

  • opencode-serve.service runs opencode serve on 127.0.0.1:4096.

They assume the repo is cloned to ~/llm-gateway, uv and codex are in ~/.local/bin and opencode is in ~/.opencode/bin. Adjust WorkingDirectory, ExecStart and PATH to match your setup.

cp contrib/systemd/*.service ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now codex-app-server.service opencode-serve.service llm-gateway.service
journalctl --user -u llm-gateway.service -f

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Transform your local machine into a powerful code command center. Automate file handling, run terminal commands, and leverage AI to enhance your development workflows—all securely and instantly, without cloud latency.
    14
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to securely execute terminal commands with persistent sessions, async jobs, and mission control, while providing a live dashboard for human oversight.
    4
    Apache 2.0