Connecting over MCP
Constance exposes its whole tool catalogue as a Model Context Protocol server. Your agent and your model do the reasoning; Constance only serves the data, scoped to your account. There is no LLM on this endpoint and no token budget. Requests are the resource that is capped, not tokens. This is the right surface when you already run an agent (Claude Code, a Cursor workspace, an internal research harness) and want it to answer with your real portfolio numbers instead of guessing.Endpoint
202 and no body. There is no server-initiated stream: GET and DELETE on the endpoint answer 405, and JSON-RPC batches are rejected with 400.
Supported protocol versions: 2025-06-18 (default), 2025-03-26, 2024-11-05. The server advertises the tools capability only. There are no prompts or resources.
Authentication
Mint a Renesis API key (prefixak_) from your user page in the dashboard, under Profile, API keys, with access set to Constance only. That preset restricts the key to the /constance/mcp path, so the key can read portfolio data through Constance and nothing else. The secret is shown once at creation.
Pass it in the X-API-Key header on every request.
Authorization: Bearer <token>); that is what the terminal uses. For an MCP client prefer the key, since it has no session to keep alive.
Rejections
Key verification happens at the gateway, before Constance is reached:
Constance itself adds one more:
Most MCP clients do not retry a
503 on their own. If a tool call fails with that body, call it again.
Client setup
- Claude Code
- Cursor
- Claude Desktop
- Any client
/mcp lists the server and its tools. Ask in plain words: “what is my NAV across all accounts” and Claude picks list_accounts and get_all_account_summaries itself.Verify the connection
Initialize, then list tools. Theinstructions field in the initialize result is the server’s standing guidance to your model: Constance is the authoritative source for this user’s portfolio data, start with list_accounts, and never fetch the same data from anywhere else.
isError is true when that JSON carries an error key.
How to work with the tools
Resolve ids first. Account-scoped tools take anexchange_account_id slug (like exchange_mighty_purple_condor), portfolio-scoped tools take a portfolio_id. Both come from list_accounts and list_portfolios. Most tools accept either, so a question about “the whole book” goes to the portfolio id and a question about Kraken goes to that account’s slug.
Results are compact by design. Every tool answer is cut to a character budget, by whole list items, and the real total is kept in the payload. Time series are downsampled to at most 60 points. Lists are paged (page from 0, size per tool). If your model needs more, page, narrow the window, or use run_aggregation to have the server do the sum.
Errors are one short sentence. A tool that cannot answer returns {"error": "that data is not available"}. An account you cannot access and an account that does not exist read the same, on purpose. An empty list is a real answer: an account with no open derivatives returns [] from get_open_positions, not an error.
Reads are marked. Each tool in tools/list carries annotations.readOnlyHint. It is true for everything except create_alert, update_alert and delete_alert.
Writes need confirmation on your side. The server will create an alert the moment it is asked. The “restate and confirm first” rule in those tool descriptions is guidance to your model, not a server-side gate. If your harness auto-approves tool calls, keep that in mind.
Limits
Tool reference
Every tool with its parameters and what it returns.
Portfolio NAV endpoint
The plain HTTP path for NAV if you do not need an agent at all.

