Skip to content

Agents mcp - #1005

Open
dkackman wants to merge 11 commits into
xch-dev:mainfrom
dkackman:agents-mcp
Open

dkackman wants to merge 11 commits into
xch-dev:mainfrom
dkackman:agents-mcp

Conversation

@dkackman

Copy link
Copy Markdown
Collaborator

Sage Agents over MCP (stage 1, read-only)

Lets AI agents (Claude Code, other MCP clients) read a Sage wallet through a Model Context Protocol server built into Sage. Desktop only; off by default.

How it works

  • Server: Settings → Advanced → Agents starts an MCP server (rmcp, streamable HTTP) on 127.0.0.1 only, port 9258 by default. It rejects requests whose Host isn't local.

  • Agents and tokens: each agent gets its own bearer token (sage_agent_ + 64 hex characters). Sage stores only the SHA-256 hash, shows the token once and never logs it. Agents can be edited, have their token rotated, or be revoked, and changes apply on the agent's next request.

  • Reuses the Sage apps model: an agent is a new BridgeCaller::Agent in the existing bridge pipeline, with its own capabilities and wallet scope (AllWallets or specific wallets). Every tool call goes through process_agent:

    1. The method is in the agent catalog.
    2. The capability is granted.
    3. The current wallet is in the agent's scope (checked again under the lock while the method reads the wallet).
    4. The method runs.

    Anything that needs approval is refused with approval_unsupported.

  • Tools: 13 read-only wallet tools (balances, coins, transactions, sync status, price, address check). Secret-key and signing capabilities can't be granted. Each tool's input schema is derived from the type its bridge method deserializes, using the same utoipa derives the RPC's OpenAPI spec uses.

  • UI: the agent dialog reuses sage-app-ui's PermissionEditor and WalletScopeEditor (Permissions | Wallets tabs), the same editors Sage apps use. The editors gained optional label and collapse props, with defaults that leave the system apps unchanged.

  • Docs: docs/agents.md covers setup, ready-made client snippets, and the security model: a token grants only its capabilities, but an agent that can run shell commands as the same OS user isn't contained. The UI warns when the RPC server is on.

Build changes

The main app now imports sage-app-ui, whose dist is gitignored, so:

  • iOS and Android beforeBuildCommand run build:packages first. That adds a host build of sage-apps to mobile builds.
  • iOS and Android beforeDevCommand and pnpm sandbox run dev:prepare, which caches its builds.

Testing

  • cargo test -p sage-apps (236 tests): auth, token rotation and revocation mid-session, the token is never echoed, Host-header rejection, schema derivation, scope checks, and settings rollback.
  • pnpm test:unit (179 tests).
  • fmt, clippy, lint, prettier and tsc -b are clean.
  • Not yet done: a manual run with Claude Code against a real wallet, and a look at the dialog in pnpm tauri:dev. Mobile builds get their first real run on main.

Follow-ups

  • pnpm extract at the next release (new Lingui strings).
  • Stage 2: signing tools with approval in the Sage GUI.

🤖 Generated with Claude Code

dkackman and others added 9 commits November 14, 2026 15:59
- Introduced a new document outlining the design for Sage Agents interacting with wallets via the Model Context Protocol (MCP).
- Implemented the AgentSettings component to manage agent server settings, including adding, editing, and revoking agents.
- Integrated capabilities management for agents, allowing users to specify wallet scopes and capabilities.
- Added UI elements for displaying agent status, capabilities, and token management.
- Established a polling mechanism to keep agent server status updated in real-time.
- Added `AgentPermissionsPanel` component to manage agent capabilities and wallet scopes using `PermissionEditor` and `WalletScopeEditor`.
- Updated `tailwind.config.js` to include paths for `sage-app-ui` components.
- Created a new schema file for OpenAPI definitions in Rust.
- Developed tests for the new `AgentPermissionsPanel` and related functionalities.
- Defined utility functions for handling agent permissions and wallet scopes in `agentPermissions.ts`.
- Documented the implementation plan and design specifications for the agent permissions UI.
- Introduced a mechanism to drop deleted wallets from agents' scopes, ensuring that agents only retain access to existing wallets.
- Enhanced error reporting for agent server startup failures, providing clearer feedback on why the server could not start.
- Updated the agent settings UI to display error messages related to agent server startup issues.
- Refactored bridge methods to utilize a new `sage` method for accessing wallet state, improving code clarity and reducing redundancy.
- Added tests to verify the correct behavior of wallet retention logic and agent capabilities.
- Improved pluralization in UI messages for better user experience.
…base

- Take the data directory lock before reporting an apps database failure, so a second
  instance reports "already running" instead of offering to delete the live database
- Take the lock again in reset_apps_database before deleting any files
- Don't offer the reset when a newer version of Sage migrated the database, since
  installing that version again recovers the apps and agents
- Test that the agents migration keeps settings in an existing database
- Run agent tool calls straight from the catalog tool, without a JSON round trip, a
  second lookup by method name, or an allowlist of error codes
- Test the authorization of agent calls, including a method missing from the registry
- Prune deleted wallets from agent scopes without overwriting a newer edit
- Test that secret and signing grants expose no tools, and the exact Host header checks
- Test the app caller's wallet scope in the bridge context
- Move the port check and client snippets into agentPermissions and test them
- Test that the apps database reset needs a second confirmation
- Reuse SettingsSection and the warning Alert in the agent settings
- Drop the unused http dependency and showMoreLabel prop, and the implementation plans
- Keep the apps database reset out of mobile builds, which have no sage-apps crate
- Test which apps database failures offer the reset
- Authorize agent calls in one place, and share the watch-only check with apps
- Return the pruned agents from retain_agent_wallets instead of listing them twice
- Share the server status indicator between the RPC and agent settings
- Keep the agent dialog's wallets as WalletInfo, null until loaded
…eal check

- Check grants and wallet scope in call_tool, with the current wallet from the executor,
  before the executor runs; the bridge still checks again when it runs the method
- Test that switching to a wallet outside an agent's scope, or logging out, refuses calls
- Compute the dialog's loaded wallets once
Main split Settings into category pages, so the agent settings move to
src/pages/settings/AgentSettings.tsx and show on the Connected Apps page next to the RPC
server. ServerStatusIndicator moves into the new settings SettingsSection, and the user docs
point to the new location.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants