Skip to content

feat(agent): local MCP servers, rootly mcp commands and /mcp connectors page - #75

Open
kwent wants to merge 14 commits into
devin/1793275858-agent-typed-errorsfrom
devin/1793454306-agent-mcp
Open

kwent wants to merge 14 commits into
devin/1793275858-agent-typed-errorsfrom
devin/1793454306-agent-mcp

Conversation

@kwent

@kwent kwent commented Oct 31, 2026 •

Copy link
Copy Markdown
Member

Summary

Why: the hidden rootly agent (#74) can only use Rootly's cloud tools. This lets it use the user's own MCP servers (configured like Claude Code / Codex) and shows cloud connectors next to them, per the shared Rails <-> CLI contract (Rails side is behind LD ai-cli-local-mcp-tools, default OFF).

What

  • internal/mcp: Claude .mcp.json-shaped config in three scopes (local default = ~/.rootly-cli/mcp.json projects[<abs cwd>], user = top-level mcpServers, project = ./.mcp.json, other keys preserved), ${VAR} / ${VAR:-default} expansion, read-only imports (Claude Code, Codex TOML, Cursor, VS Code servers, Claude Desktop) that stay OFF until enabled, project approvals keyed by abs path + name + config hash, OAuth (go-sdk v1.8.0 discovery/DCR/PKCE/loopback, tokens 0600 in ~/.rootly-cli/mcp-oauth.json), and a Manager that connects in the background (stdio / streamable HTTP / SSE).
  • rootly mcp add|add-json|list|get|remove|login|logout|import (hidden, claude mcp add syntax + Codex --url / --bearer-token-env-var). Env/header values and secret-looking args print as *****.
  • Agent: client_tools on POST /v1/ai/chat/stream named local_<server>_<tool> (sanitized, truncated, _2 dedupe, mapped back), read_only from readOnlyHint; client_tool_call → y/n card for writes → ⚙ local · <server> · <tool> → POST /v1/ai/chat/tool_results (output capped at 100 KB, decline = is_error: true, "User declined"). client_tools_accepted: 0 with tools sent prints "Local MCP tools are off for your org" once. -p mode declines writes unless the user types y on a TTY; no bypass flag.
  • /mcp (alias /connectors): full-screen page like /sessions with Rootly cloud (GET /v1/ai/connectors, Load more), Project / User / Imported groups, detail view with tool filter and space/a/l/r; virtualized so 1,000 tools render instantly. Esc restores the chat.

Before / after: before, the agent had cloud tools only. After, enabled+approved local MCP tools are offered to the model when the org flag is on; with the flag off the stream behaves exactly as before, plus a one-line notice.

Risk: risk:low: rootly agent and rootly mcp are both hidden, nothing existing changes, and local tools only run when the server accepts them (flag OFF by default). Secrets never leave the machine: only tool names, schemas, inputs and outputs go to Rootly.

Rollback: revert this PR; the CLI ignores the new contract fields when they're missing.

Stacked on #74 (devin/1793275858-agent-typed-errors).

Link to Devin session: https://rootly.devinenterprise.com/sessions/5e2e52b477b74d98b9ed9500fe7b4860
Open in Devin Desktop: https://rootly.devinenterprise.com/desktop/session/5e2e52b477b74d98b9ed9500fe7b4860?variant=devin
Requested by: @kwent


Devin Review

devin-ai-integration Bot and others added 6 commits October 31, 2026 13:51
Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
… trip

Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin resolved all 8 findings on 8b2da05

Fixed by Devin (8)

  • Default-port redirects block MCP connections
  • Broken MCP configuration fails silently
  • Login fails after saving disabled server credentials
  • Cloud connector changes never appear
  • MCP command names hide matching skills
  • Tool detail list disappears after reconnect
  • Project-controlled servers can inherit global trust
  • Changed project server retains unapproved connection

View all findings in Devin Review

Devin Review

devin-ai-integration Bot and others added 2 commits October 31, 2026 14:09
…ogin on off servers

Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
…ve mcp slugs, show config problems

Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
@greptile-apps

greptile-apps Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

RetriggerView in GreptileConfidence Score: 5/5

[High impact] The PR appears safe to merge, with all four previous findings addressed and no new actionable issues found.

Summary

Adds local MCP servers to the agent, hidden rootly mcp commands, OAuth login, and a /mcp page for local and cloud connectors.

  • The agent can run tools from connected local MCP servers.
  • People can set up, import, and sign in to local MCP servers.
  • The agent's /mcp page brings local servers and cloud connectors together.

Reviews (2) · Last reviewed commit: "fix(api): send client_tools and tool_res..." · Reviewed by Greptile

Comment thread internal/mcp/manager.go Resolved
Comment thread internal/mcp/state.go Resolved
Comment thread internal/cmd/mcp/mcp.go Resolved
Comment thread internal/mcp/manager.go Resolved
devin-ai-integration Bot and others added 6 commits October 31, 2026 14:14
Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
…-origin redirects

Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
…ect server

Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
Co-Authored-By: Quentin Rousseau <quentin@rootly.com>
@devin-ai-integration

devin-ai-integration Bot commented Oct 31, 2026 •

Copy link
Copy Markdown
Contributor

Real e2e: local MCP against Rails (rootlyhq/rootly#26040)

Tested in a real tmux terminal with a real LLM, using the frozen CLI binary at 8b2da05. ai-cli-local-mcp-tools was on, with Redis running.

Latest run: Rails 7d689c6 (adds the <local_tools> prompt block)

Every prompt below was phrased generically, with no tool name in it, and each one passed on the first attempt:

  • Read: "read the file at …/seed.txt and tell me what it says" ran ⚙ local · fs · read_text_file with no confirmation card and returned the exact text (amber-lantern-842).
  • Approved write: "write 'hello from rootly' to …/approved2.txt" showed the y/n card. The file didn't exist while the card was waiting. After y, it existed and contained exactly hello from rootly.
  • -p print mode: rootly agent -p "read the file at …/seed.txt …" showed the local activity line, returned the exact text, and exited, with no approval needed.
  • Each turn reported client_tools_accepted=14, and all 14 local_fs_* tools reached the model.

Generic local MCP flow

Generic read Generic write card
read card
Approved write on disk -p print-mode read
disk print

Earlier run: Rails dbd192c (not repeated above, since 7d689c6 only changes the prompt and some connector/security code)

  • stdio server (@modelcontextprotocol/server-filesystem) added at user scope. list/get mask env values. /mcp and /connectors show fs with 14 tools, and the detail filter works.
  • Declined write: n left no file on disk, and the model said the write was declined.
  • Server side: the POST /v1/ai/chat/tool_results calls returned 202. The audit rows have provider client_tool: read/success, write/success, and the declined write as error.
  • Flag off: "Local MCP tools are off for your org" showed exactly once over two prompts, chat still answered, and no local tools were sent to the model.
  • Braintrust (rootly mcp add --transport http braintrust https://api.braintrust.dev/mcp) shows ▲ needs authentication.
  • Bug found and fixed in this PR (8b2da05): the CLI sent client_tools and tool_results as application/json, which Rails rejects with 415 for newer teams. They are now sent as application/vnd.api+json, and unit tests check the header.

Earlier run: full flow

Config masked /mcp tool filter
masked filter
Local read Approve card
read approve
Decline result Disk proof
declined disk
Flag off, notice once Braintrust needs auth
flag-off braintrust

Written by Devin

@devin-ai-integration

Copy link
Copy Markdown
Contributor

@greptileai review

Written by Devin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant