Skip to content

MCP

Connect Claude Code, Cursor, or any MCP client to your logs. Your agent reads production while it debugs, over one URL and a read-only key.

LogNorth speaks the Model Context Protocol at POST /mcp. Your coding agent reads production logs while it fixes the bug, in the same pane as the code.

Requires LogNorth v0.16.0 or later. Run lognorth update if you are on an older version.

The endpoint runs inside the LogNorth process. There is no separate binary, no gateway, and nothing on your machine to keep updated. If your server is current, the MCP endpoint is current.

Open Settings > Developer and create an Agent key. It is read-only and starts with lgn-agent-. It is separate from the app keys your SDKs use to send events.

Keep it and your server’s URL to hand. The next step asks for both.

In Claude Code:

/plugin marketplace add karloscodes/lognorth-releases
/plugin install lognorth
/lognorth:connect

/lognorth:connect is the only step that touches your credentials. It asks for the URL and the key, or takes them inline:

/lognorth:connect https://logs.yoursite.com lgn-agent-...

It calls tools/list against your server to check both before saving anything, so a rejected key or a server without /mcp gets explained instead of written to disk. Then it stores them where Claude Code applies them to every project and session.

Restart Claude Code, then /mcp lists the server. Ask “what’s breaking in production?” and it calls list_issues.

There is nothing to export and no config file to edit. The plugin brings the MCP server and the skills that read it.

The plugin is Claude Code’s format. Every other client takes the same endpoint in its own config, with the URL and key written in directly.

Claude Code without the plugin:

Terminal window
claude mcp add --transport http lognorth https://logs.yoursite.com/mcp \
--header "Authorization: Bearer lgn-agent-..."

Cursor, in ~/.cursor/mcp.json for every project or .cursor/mcp.json for one:

{
"mcpServers": {
"lognorth": {
"url": "https://logs.yoursite.com/mcp",
"headers": { "Authorization": "Bearer lgn-agent-..." }
}
}
}

VS Code, with Copilot:

Terminal window
code --add-mcp '{"name":"lognorth","type":"http","url":"https://logs.yoursite.com/mcp","headers":{"Authorization":"Bearer lgn-agent-..."}}'

Gemini CLI, in ~/.gemini/settings.json:

{
"mcpServers": {
"lognorth": {
"httpUrl": "https://logs.yoursite.com/mcp",
"headers": { "Authorization": "Bearer lgn-agent-..." }
}
}
}

Windsurf, in ~/.codeium/windsurf/mcp_config.json:

{
"mcpServers": {
"lognorth": {
"serverUrl": "https://logs.yoursite.com/mcp",
"headers": { "Authorization": "Bearer lgn-agent-..." }
}
}
}

Codex CLI, Zed, and other stdio-only clients. Bridge with mcp-remote, which makes a stdio client speak HTTP. In ~/.codex/config.toml:

[mcp_servers.lognorth]
command = "npx"
args = [
"-y", "mcp-remote",
"https://logs.yoursite.com/mcp",
"--header", "Authorization: Bearer lgn-agent-..."
]

The same npx -y mcp-remote <url> --header "Authorization: Bearer <key>" works for any client that takes a stdio command.

Use http://localhost:8080/mcp against a local instance. Most clients read MCP config only at startup, so restart yours after editing.

These files hold the key in plain text, so keep them out of version control.

You: the checkout endpoint is throwing 500s, what's happening?
Claude: [searches the log, errors only, last hour]
Three failures on POST /api/checkout in the last 12 minutes,
all the same error: "Stripe timeout after 30s", 121-123ms each.
[opens the trace for the first one]
The trace shows GET /api/health succeeded in the same request
window, so the box is up. The timeout is Stripe-side.
ToolWhat it does
list_appsLists your apps with their ids. Call it first when a tool needs an app_id.
search_logsSearches requests by text, errors only, and time window.
get_eventOne event with its full context and every event sharing its trace.
list_issuesGrouped errors with occurrence counts and when each was last seen.
ArgumentExampleDescription
searchtimeoutText to match in the message and context
errors_onlytrueOnly requests that failed. Default false
since15m, 2h, 7dHow far back to look. Default 1h
app_id2Restrict to one app, from list_apps
limit50Max events, 1 to 200. Default 20

The defaults are deliberately small. An agent that needs more asks for more, and that keeps the first answer cheap.

Takes one id from search_logs. Returns the event, its parsed context, and relatedEvents: every other event with the same trace_id. That is how the agent reconstructs the whole request instead of guessing from one line.

Every tool is read-only. There is no tool to write an event, mute an issue, change a setting, or delete anything. The agent can look, never touch.

The agent key only reaches these read tools. It cannot ingest events and it cannot sign in to the web UI.

Your logs stay on your server. The agent asks your instance, your instance answers, and only that answer travels to your AI provider along with the rest of your conversation. LogNorth never sees any of it.

For a closed loop, point a local model at the same endpoint. Your key, your provider choice, your tradeoffs.

  • Transport is Streamable HTTP. One JSON-RPC 2.0 request per POST, one JSON response back.
  • Protocol revisions: 2025-06-18, 2025-03-26, 2024-11-05. The server answers with your client’s revision when it knows it, otherwise with the newest.
  • Notifications get 202 with no body.
  • Auth is the agent key as Authorization: Bearer lgn-agent-.... Without it the endpoint returns 401 and no data.

Call it by hand to check a setup:

Terminal window
curl -X POST https://logs.yoursite.com/mcp \
-H "Authorization: Bearer lgn-agent-..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

Once it is connected, ask in plain English:

  • “What’s breaking in production?”
  • “Show me the last 10 errors on /checkout”
  • “What happened during request abc-123?”
  • “Did the deploy fix the Stripe timeouts?”
  • “What broke in the last hour?”

The agent picks the tools. You read the answer.