Agent Connections (MCP)
Pair an external AI agent — Claude Code, Claude Desktop, Codex CLI, or any client that speaks the Model Context Protocol over stdio — with your running ScreenerBot. A new connection starts with full control of the app, and you can narrow it per capability at any time. Wallet private-key material is the one thing no agent can ever read or write.
What a connection actually is
The app is the authority and the executable
screenerbot mcp serve is a thin bridge built into the same binary you already run. It holds no trading logic and no tool registry of its own: it finds the running app through agent-runtime.jsonand calls a loopback endpoint on that live process. The app resolves the connection's stored permissions, decides, and runs the tool where the services, databases, and your wallet already live.
There is no separate package to install, no sidecar, no browser extension, and no hosted endpoint. The transport is stdio only — no HTTP MCP server is exposed anywhere, and the bridge dials nothing but 127.0.0.1.
Full control by default
What a new connection can do
- Analyze tokens and read security findings
- Read positions, balance, and P&L
- Buy, sell, and close positions
- Read and change any setting, RPC endpoints included
- Force stop the engine and clear the force stop again
In short: everything you can do from the dashboard yourself.
What no connection can ever do
Read or write your wallet private key. The encrypted key material (wallet_encrypted, wallet_nonce) is redacted from every read and refused on every write — including through a parent path, and including at full access. There is no permission level that unlocks it.
ScreenerBot signs transactions locally with a key that never leaves the machine. An agent asks the app to trade; it is never handed anything it could sign with.
Limiting a connection
Each connection carries its own policy, stored with the pairing — not a global setting. Five capability categories, three levels each. Edit it any time from Settings → Agent Connections → Permissions, without recreating the connection or restarting anything.
Allow
The tool runs immediately in the live app. This is the default for every category.
Ask
The call parks on the approval queue. Nothing happens until you approve or deny it in ScreenerBot.
Off
The category is refused, and its tools are not even listed to the client.
| Category | Tools | What it grants |
|---|---|---|
| Analysis | analyze_token, get_market_data, check_security | Read token metrics, market data, and security findings. |
| Portfolio | get_positions, get_position, get_balance, get_pnl | Read open positions, wallet balance, and realized/unrealized P&L. |
| Trading | buy_token, sell_token, close_position | Spend SOL and close positions through the live trading engine. |
| Config | get_config, describe_config, update_config | Discover the schema and read or change any non-secret app setting. |
| System | get_status, get_events, force_stop, clear_force_stop | Read runtime status and events; halt or resume execution. |
Presets, and anything in between
Full access sets every category to Allow. Ask first sets every category to Ask. Read only allows analysis and portfolio and turns the rest off. Any per-category combination is valid — for example allow analysis, portfolio, and config, ask before trading, and turn system actions off entirely.
The policy is read from the pairing store on every call, so tightening a connection — or revoking it — takes effect on that client's next request. No restart on either side, and no re-pairing.
What an agent can configure
Every setting, by path — not an allowlist
update_config addresses settings by dotted path over the live configuration, so an agent can set your RPC endpoints, position sizing, filtering thresholds, slippage, or anything else the app exposes. A setting becomes agent-settable the moment it exists in the schema — there is no separate list to fall out of date.
rpc.urls
trader.max_open_positions
filtering.min_liquidity_usd
swaps.slippage.default_slippage_percentdescribe_config returns the schema — labels, types, ranges — so the agent can discover what it may set instead of guessing. Every write is type-checked and validated exactly like a dashboard edit, applied atomically inside the configuration write lock: if one value in a batch is rejected, nothing changes.
RPC changes need a restart to take effect
An RPC endpoint change is saved immediately, but the RPC manager binds its endpoints when the app launches. Restart ScreenerBot for the new endpoints to be used. The tool result says so when it happens.
Pairing a client
Open Settings → Agent Connections
ScreenerBot must be running. The dashboard window can be closed afterwards as long as the process stays up — but you need it open to decide anything a connection has set to Ask.
Name it, pick the client, set its permissions
The form opens at full access. Narrow it now, or leave it and narrow it later — either works.
Copy the one-time secret
It is shown once and cannot be retrieved. ScreenerBot keeps only a SHA-256 verifier of it. Lose it and you revoke the connection and create another.
Apply the generated setup and restart the client
The panel fills in the client id, the secret, and the running app’s absolute path, in that client’s own native format.
There is no universal MCP client configuration format, so each client gets its own artifact. Every one of them runs the same command — screenerbot mcp serve — with the same two environment variables. The secret is read only from the environment, never from a command-line argument.
claude mcp add --scope user screenerbot \
-e 'SCREENERBOT_CLIENT_ID=<client id>' \
-e 'SCREENERBOT_PAIRING_SECRET=<secret>' \
-- '/absolute/path/to/screenerbot' mcp serve{
"mcpServers": {
"screenerbot": {
"command": "/absolute/path/to/screenerbot",
"args": ["mcp", "serve"],
"env": {
"SCREENERBOT_CLIENT_ID": "<client id>",
"SCREENERBOT_PAIRING_SECRET": "<secret>"
}
}
}
}codex mcp add screenerbot \
--env 'SCREENERBOT_CLIENT_ID=<client id>' \
--env 'SCREENERBOT_PAIRING_SECRET=<secret>' \
-- '/absolute/path/to/screenerbot' mcp servemcp_servers:
screenerbot:
command: "/absolute/path/to/screenerbot"
args: ["mcp", "serve"]
env:
SCREENERBOT_CLIENT_ID: "<client id>"
SCREENERBOT_PAIRING_SECRET: "<secret>"OpenClaw uses its own openclaw mcp add command, and any other stdio client takes the same JSON object as Claude Desktop. If you run ScreenerBot with a non-default data directory, pass SCREENERBOT_DATA_DIR to the client too, so the bridge finds the right runtime file.
Approvals and execution
How an Ask call behaves
- The request appears in ScreenerBot; the prompt is visible from every dashboard page.
- The client waits up to five minutes, then returns “still pending”.
- An approved request runs at most once.
- Approving later and retrying the same call does not double-execute it.
- A denied or expired request never runs.
Trades are still the engine's
A tool call is a request to the trading engine, not a transaction. It takes the same manual-trade path the dashboard uses: the buy is capped at your configured trade size, refused if a position for that token is already open, quoted and executed by the router, and verified on chain. An agent never builds or signs a transaction itself.
Every request, decision, and execution is written to the agent audit log with the connection that asked for it, and every resulting trade shows up in Positions and Transactions like any other.
Checking a connection
SCREENERBOT_CLIENT_ID=<id> SCREENERBOT_PAIRING_SECRET=<secret> screenerbot mcp doctordoctor prints reachability and pairing status to stderr and never prints the secret. Its exit code is the contract:
| Exit code | Meaning |
|---|---|
| 0 | The live app answered a pairing probe. Everything is wired. |
| 3 | No runtime — ScreenerBot is not running, or agent-runtime.json is not a loopback origin. |
| 4 | SCREENERBOT_CLIENT_ID and SCREENERBOT_PAIRING_SECRET are not both set. |
| 5 | Runtime found, but the bridge could not be reached. |
| 6 | Bridge reached, pairing rejected — revoked, unknown, or agent control disabled. |
Common causes
- The client lists no tools. ScreenerBot is not running, or the pairing is missing or revoked.
- The client lists fewer tools than expected. That category is set to Off for this connection.
- A config write is refused as wallet key material. The path resolves to the encrypted key. No permission level grants it; nothing else was affected.
- Every trade waits for approval. Trading is set to Ask. Approve it, or set the category to Allow if you want the connection to trade unattended.
Revoking a connection
Effective on the next request
Revoke from Settings → Agent Connections → Revoke. It cannot be undone, and it needs no restart. Then remove the server from the client itself:
claude mcp remove --scope user screenerbot
codex mcp remove screenerbotTurning off [agent_control] enabled disables every connection at once, without deleting any of them.