Reading CodeScout with an AI agent
You are already debugging with an AI agent in your editor. It can read your source, but it cannot see what your app did when it ran, so you end up as the transport layer: copying a stack trace out of the dashboard, pasting it into a chat, describing the rest from memory.
CodeScout speaks MCP, which closes that loop. The agent reads your logs itself. You describe the bug, it goes and looks.
Setting it up
Section titled “Setting it up”Create a token. In the dashboard, open the account menu and choose Personal settings, then API tokens. Give it a name that says where it will live, something like “Claude Code on my laptop”, and press Create. The token is shown once and never again, so copy it now.
Point a client at it. The endpoint is /api/mcp on the same server as your dashboard. It
speaks streamable HTTP and takes the token as a bearer header, so there is nothing to install and
nothing to run locally. Every client below is asking for the same three things: a name, that URL,
and that header.
Replace logs.example.com with your own dashboard’s host and paste in the token you just copied.
Claude Code
Section titled “Claude Code”claude mcp add --transport http code-scout https://logs.example.com/api/mcp \ --header "Authorization: Bearer csp_your_token_here"Cursor
Section titled “Cursor”.cursor/mcp.json in the project, or ~/.cursor/mcp.json to have it everywhere:
{ "mcpServers": { "code-scout": { "url": "https://logs.example.com/api/mcp", "headers": { "Authorization": "Bearer csp_your_token_here" } } }}VS Code
Section titled “VS Code”.vscode/mcp.json in the project, next to your other workspace settings:
{ "servers": { "code-scout": { "type": "http", "url": "https://logs.example.com/api/mcp", "headers": { "Authorization": "Bearer csp_your_token_here" } } }}Windsurf
Section titled “Windsurf”~/.codeium/windsurf/mcp_config.json:
{ "mcpServers": { "code-scout": { "serverUrl": "https://logs.example.com/api/mcp", "headers": { "Authorization": "Bearer csp_your_token_here" } } }}Anything else
Section titled “Anything else”There is no CodeScout plugin to find. If your client can talk to a remote MCP server it can talk
to this one, and the config will be some spelling of the block above: a URL and an Authorization
header. Check your client’s docs for whether the key is url, serverUrl or endpoint, and
whether servers live under mcpServers, servers or context_servers.
If your client only speaks stdio, bridge it:
{ "mcpServers": { "code-scout": { "command": "npx", "args": [ "-y", "mcp-remote", "https://logs.example.com/api/mcp", "--header", "Authorization: Bearer csp_your_token_here" ] } }}That is the whole setup. Ask your agent something like “which of my projects has the most errors this week?” and it will start looking.
The handover this is really for
Section titled “The handover this is really for”A tester finds a bug. They are on a different desk, or a different continent, and the report you get is two sentences and a screenshot.
Now they open the CodeScout panel in the app, go to Info, and press Copy all. That puts a short block on their clipboard with the session id, the device, the OS, your app’s version and build, whether the launch was sampled in, and how many logs are still waiting to upload. They send that to you along with what they were doing.
You paste the whole thing into your agent and say what the tester told you. The agent reads the session id, pulls the entire launch back, and starts from the same evidence you would have had if you had been sitting next to them. No build with extra logging, no day of waiting.
What it can read
Section titled “What it can read”Eighteen tools, all of them read only.
Finding things. search_logs takes the same query syntax as the dashboard’s search box, so
level:error last:24h tag:checkout means exactly what it means when you type it. request: with a
call’s request id finds that call’s request and response logs and every log your app linked to the
call. Results are paginated, and the agent walks the pages itself. get_log fetches a single log
whole, which matters because list results trim very long messages and drop oversized metadata to
keep from flooding the agent’s context. Anything trimmed is flagged as trimmed, so the agent knows
to go and fetch it rather than assuming it saw everything.
Understanding a problem. get_error_groups returns your errors collapsed into distinct
problems, most frequent first, each with its latest stack trace and how many sessions it hit.
get_project_overview gives counts and an activity chart over 24 hours, 7 days or 30 days, with
the previous period alongside for comparison.
Following one launch. get_session_timeline is the one the QA handover uses. Give it a
session id and it returns that launch’s device and app details followed by its logs in order.
list_sessions, list_devices and get_device cover the questions that span launches, like
which installs are still running the build without the fix.
Network. list_network_calls returns one row per call with its phases already paired, filtered
by path, method, status class or session. get_network_request returns a single call in two
parts. phases is the call itself: its full request and its response or error, headers and bodies
included, subject to whatever redaction your app configured. linked_logs is what your app logged
with the call’s request id, such as the error its model threw on the body. The two are kept apart
so that an agent never reads your app’s decode failure as the call failing. linked_logs lists the
earliest twenty, trimmed the way search_logs rows are, and linked_logs_total counts all of them.
When none of the call’s phases were stored, phases is empty and a note says why. See
When the API changes under you for the whole workflow.
The tools that return stored logs give numbers back as they were stored, so 12.0 and 12 stay
different values. That matters when the question is whether a field changed type.
Live devices. While a device is paired, list_live_sessions and tail_live_session let the
agent read what is streaming in right now. The live database tools go further: live_db_sources,
live_db_namespaces, live_db_schema and live_db_rows read the app’s own SQLite tables,
shared_preferences and Hive boxes off the phone while the bug is on screen.
That last one is worth stopping on. When a tester says the cart looks empty, your agent can read the logs and then query the actual cart table on the actual device, at the moment it is wrong.
What it cannot do
Section titled “What it cannot do”It cannot write anything. Not a project, not a setting, not a cell in a device’s database. This is not a permission that could be granted later by mistake: no tool has a field an instruction could arrive in, so there is no shape a write could take. Editing a value on a paired device stays something a person does in the dashboard, deliberately.
It cannot see more than you can. A token carries its owner’s access and nothing more. If you cannot open a project in the dashboard, your agent gets “project not found” for it, which is the same answer it gets for a project that does not exist. It cannot even confirm the project is real.
It never returns your secrets. Project secrets, password hashes and tokens are not fields any tool returns.
Managing tokens
Section titled “Managing tokens”Personal settings lists your tokens with the last four characters, when each was created, when it was last used and when it expires. Only your own tokens appear, and only you can revoke them.
Tokens expire in 90 days by default. You can pick 30 days or no expiry when you create one. Something long lived that sits in a config file is exactly the thing worth expiring, so pick the shortest window you will tolerate re-doing. You can hold twenty at once, which is more than anyone needs and low enough that a script gone wrong stops rather than fills a table.
The server stores a SHA-256 hash of the token and never the token itself, so nobody who reads the database, a backup or a log can use what they find there. That also means we genuinely cannot show it to you again, which is why the create screen says to copy it right away.
Some things to ask
Section titled “Some things to ask”Once it is connected, these all work as plain questions:
- “Which project is throwing the most errors, and what is the top one?”
- “Read session
a3f2c7d1-...and tell me what went wrong.” - “Find every failed network call to
/v2/paymentsin the last day and look for a pattern.” - “Request
5c67a6d7-...could not be decoded. Compare its response body with theCartclass inlib/cart/cart.dartand tell me which field changed.” - “This user reported a crash on 3.11.2. Which devices are on that build and what did they log?”
- “A device is live right now. Read its cart table and tell me why the screen shows nothing.”
The agent picks the tools. You describe the problem.
Troubleshooting
Section titled “Troubleshooting”“Missing bearer token” or “Invalid token”. The header did not arrive or the token is not one this instance knows. Tokens belong to the instance that created them, so one minted on your local CodeScout will not work against a shared server, and vice versa. Check which URL your client is pointed at.
“This token has expired”. Create a new one under Personal settings and update your client’s config.
“This account must change its password”. Sign in to the dashboard and set your own password first. An account on a temporary password cannot use a token, for the same reason it cannot use the rest of the dashboard.
“The device did not answer”. A live database read went out to a phone that did not reply in ten seconds, which almost always means the app is in the background. Open the app on the device and try again.
Nothing works behind your reverse proxy. The MCP endpoint is ordinary HTTP POSTs, so unlike live streaming it needs no special proxy configuration. If plain dashboard pages work, this will too.