@mateusz-klatt/snapper-mcp

Lightweight stdio-to-HTTP Model Context Protocol bridge. Spawns as a
subprocess, speaks MCP over stdio to Claude Desktop / Claude Code, and
proxies every request to a Snapper backend's /api/mcp endpoint with
Bearer-token auth.
What is this
Snapper is a multi-tenant trading platform. Its backend exposes MCP at
/api/mcp, guarded by Bearer-JWT auth, feature flag, and per-principal
rate limiting. MCP hosts (Claude Desktop, Claude Code) speak MCP over
stdio — they spawn a subprocess and exchange JSON-RPC frames over
stdin/stdout. @mateusz-klatt/snapper-mcp is the stdio ⇄ HTTP bridge that
makes that conversation work.
It is a thin TypeScript bridge using Node's built-in fetch, plus
@modelcontextprotocol/sdk for MCP framing. No OAuth, no telemetry.
Standalone hosts (Claude Desktop, systemd, plain CLI) can provide
credentials through CLI flags, a hardened --config JSON file, or
environment variables. Claude Code plugin installs write a
0600-mode env.json into the per-plugin ${CLAUDE_PLUGIN_DATA}
directory at proxy startup so the auto-spawned monitor process can
read its credentials via --config=PATH; the file is owned by the
plugin's data dir and is overwritten atomically on every proxy
startup.
Install
Three install paths, in recommended order. All three end at the same
runtime — pick whichever matches your MCP host.
Option 1 — Claude Code plugin (recommended)
In any Claude Code session:
/plugin marketplace add mateusz-klatt/snapper-mcp
/plugin install snapper-mcp@mateusz-klatt-snapper-mcp
Claude Code prompts for two values:
- Snapper API URL — your backend's
/api/mcp endpoint.
- Access token — paste from Snapper's Settings -> AI Delegates
page (the config-snippet generator). The same token authenticates
both the proxy MCP server and the watch monitor.
Plugin changes installed mid-session need /reload-plugins (or a
Claude Code restart) before the MCP server starts. After reloading,
/mcp list should show the snapper server connected.
The plugin manifest threads both credentials (SNAPPER_BASE_URL,
SNAPPER_ACCESS_TOKEN) into the proxy MCP subprocess as env vars via
${user_config.KEY} interpolation. The proxy then writes a
0600-mode env.json snapshot into ${CLAUDE_PLUGIN_DATA} at
startup so the auto-spawned watch monitor can read the same values
via --config="${CLAUDE_PLUGIN_DATA}/env.json". Claude Code stores
sensitive: true user_config values in the OS keychain when
available, falling back to ~/.claude/.credentials.json — they
never land in settings.json or the manifest.
Option 2 — Claude Desktop manual config
Add to your Claude Desktop config
(~/Library/Application Support/Claude/claude_desktop_config.json on
macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows):
{
"mcpServers": {
"snapper": {
"command": "npx",
"args": ["-y", "@mateusz-klatt/snapper-mcp"],
"env": {
"SNAPPER_BASE_URL": "https://your-snapper-instance.example.com/api/mcp",
"SNAPPER_ACCESS_TOKEN": "<generated via Snapper UI: Settings -> AI Delegates>"
}
}
}
}
Restart Claude Desktop; the Snapper server shows up in the MCP Servers
settings panel.
Option 3 — Direct CLI / custom hosts
SNAPPER_BASE_URL="..." SNAPPER_ACCESS_TOKEN="..." \
npx -y @mateusz-klatt/snapper-mcp
npm install -g @mateusz-klatt/snapper-mcp
SNAPPER_BASE_URL="..." SNAPPER_ACCESS_TOKEN="..." snapper-mcp
Requires Node 26+ (uses Node's built-in fetch, AbortController,
and ESM top-level await). CI validates the declared minimum
(Node 26) across Ubuntu / macOS / Windows.
Configuration
Two environment variables are the common MCP-host configuration shape:
| Variable | Required? | Purpose |
|---|
SNAPPER_BASE_URL | yes | URL of Snapper's /api/mcp endpoint. |
SNAPPER_ACCESS_TOKEN | yes | Long-lived AI delegate JWT for Bearer auth (generated in Snapper UI). The same token authenticates both the proxy MCP server and the watch monitor. |
See .env.example for placeholder values.