MCP server that handshakes keys so Speed-CLI and agents can use them without manual setup. Keys are not saved on client or read by the agent.
- Agents get swap quotes, bridge quotes, and balances without the user running
speed setupor pasting API keys. - Keys live on the server; the agent never sees them
- User keeps
PRIVATE_KEYin~/.speed/.env; the server never touches it.
- Create
.envin this directory (or set env vars):
ALCHEMY_API_KEY=your_alchemy_api_key
0X_API_KEY=your_0x_api_key
SQUID_INTEGRATOR_ID=your_squid_integrator_id
OPENSEA_API_KEY=your_opensea_api_keyCopy from .env.example. Get keys from:
- Alchemy → Create app
- 0x Dashboard → Create app
- Squid integrator form
- OpenSea (for SANS listing/offers)
Optional: RPC_URL for Base (8453) only (overrides Alchemy for that chain; same as Speed-CLI’s
rpc.js).
- Install and run:
cd speed-mcp-server
pip install -e .
speed-mcpOr with a venv:
Add the server so Cursor spawns it (stdio). In Cursor → Open MCP settings (Ctrl+Shift+P → "Open MCP settings"), add:
{
"mcpServers": {
"speed": {
"command": "c:\\path\\to\\speed-mcp-server\\.venv\\Scripts\\speed-mcp.exe",
"env": {}
}
}
}Or point to your Python and the module:
{
"mcpServers": {
"speed": {
"command": "python",
"args": ["-m", "speed_mcp_server.main"],
"cwd": "c:\\Users\\user\\OneDrive\\Desktop\\apps\\speedtest\\speed-mcp-server",
"env": {}
}
}
}Load API keys from a .env in cwd by running from the server directory, or set env with the keys (avoid committing those).
To allow an MCP client on a different machine to connect, run the server with Streamable HTTP so it listens on a port:
- In the server’s
.env(or environment), set:
MCP_TRANSPORT=streamable-http
MCP_HOST=0.0.0.0
MCP_PORT=8000- Start the server (from the machine that holds the secrets):
cd speed-mcp-server
speed-mcpYou should see: Speed MCP server listening on http://0.0.0.0:8000 (Streamable HTTP)...
3. On the other machine, configure your MCP client to connect to the server’s URL. Use the server’s hostname or IP and port, e.g.:
- URL:
http://SERVER_IP:8000(orhttp://your-server-hostname:8000) - The client must use the Streamable HTTP transport and point to this base URL (the exact path may be
/mcpor as required by your client SDK).
- Firewall / network: Ensure port 8000 (or your
MCP_PORT) is open on the server and reachable from the client machine. For production, put the server behind HTTPS and consider auth (the MCP Python package supports auth options).
Cursor (remote agent): In MCP settings on the client machine, use a url entry instead of command, e.g. "url": "http://your-server-ip:8000" if Cursor supports URL-based MCP for Streamable HTTP.
| Tool | Description |
|---|---|
get_speed_env_vars |
Returns env vars encrypted for the client. Requires client_public_key_pem (RSA public key PEM). Client decrypts with ~/.speed/speed_mcp_key.pem and applies to process.env. |
get_balance |
Native balance for an address on a chain (Alchemy). chain_id: 1=ETH, 8453=Base, 10=OP, 42161=Arbitrum, 137=Polygon, 56=BNB. |
get_swap_quote |
0x swap quote (sellToken, buyToken, sellAmount, chainId). |
get_bridge_quote |
Squid bridge/route quote (fromChain, toChain, tokens, amount, fromAddress). |
run_speed_with_env |
Returns instructions + command so the agent runs a speed command with env from get_speed_env_vars; signing uses local PRIVATE_KEY. |
- Read-only (balance, quotes): use the MCP tools; no need to run speed.
- Actions (swap, bridge, SANS list/buy/offer): agent calls
get_speed_env_vars, sets those env vars in the shell, then runsspeed <command>. The user’s~/.speed/.envsuppliesPRIVATE_KEY; the server never sees it.
Speed-CLI client: Configure the MCP URL with speed start <url> (e.g. speed start http://127.0.0.1:8000), which writes mcpUrl to ~/.speed/config.json. Put an RSA private key at ~/.speed/speed_mcp_key.pem; Speed-CLI sends the corresponding public key in get_speed_env_vars and decrypts the response locally. The server always returns an encrypted payload in result.content[0].text as JSON: { "encrypted_key_b64", "nonce_b64", "ciphertext_b64" }. The client decrypts with the private key, then uses the env object.
Set **MCP_DEBUG=1** in the server’s environment to log which env keys are sent for each get_speed_env_vars call (key names and whether each is set or empty; values are never logged). Restart the server after setting it.
Credentials can be sent encrypted so only the client can read them. Use this for speed setup when talking to the MCP server.
- Speed-CLI (or any client):
- Has an RSA keypair; stores the private key in
~/.speed/speed_mcp_key.pem. Never send the private key to the server. - Calls MCP tool
get_speed_env_varswith client_public_key_pem (required) set to the PEM-encoded public key.
- Has an RSA keypair; stores the private key in
- Server encrypts the env dict with that public key (hybrid: AES-256-GCM for payload, RSA-OAEP-SHA256 for the AES key) and returns an object with:
encrypted: truealgorithm: "RSA-OAEP-AES256GCM"encrypted_key_b64,nonce_b64,ciphertext_b64(base64-encoded).
- Speed-CLI decrypts using its private key: decrypt
encrypted_key_b64with RSA-OAEP-SHA256 to get the AES key; decryptciphertext_b64with AES-256-GCM using that key andnonce_b64; parse the result as JSON to get the env dict. Merge withPRIVATE_KEYand write~/.speed/.env.
Credentials never cross the wire in plaintext; only the holder of the private key can recover them. In Node (Speed-CLI) use node:crypto: crypto.privateDecrypt (RSA-OAEP, SHA-256) for the key, then crypto.createDecipheriv("aes-256-gcm", ...) for the payload (use the 12-byte nonce and 16-byte auth tag at the end of the ciphertext if you follow standard GCM layout).
GPLv3