Connect your AI assistant to Serin

Serin speaks the Model Context Protocol (MCP), so an AI assistant you already use can read your portfolio and answer questions about it. Your data never leaves your server, and the model runs on whatever subscription you already pay for — Serin charges nothing for this.

What it can and cannot do

It can read: totals and weights, real time-weighted and money-weighted returns, FIFO-matched realised gains, individual holdings and their tax lots, transactions, cached price history, and the data-quality gaps that would make any of those unreliable.

It cannot write. There is no tool to add, edit or delete a position, and the tool registry refuses to accept one — a hallucinated edit would corrupt cost basis, which is the number the whole product exists to get right.

It does not give financial advice, and it is not a trading interface.

Answers come back already computed. Ask "what's my YTD return" and the model receives the number Serin calculated, not forty rows to add up itself.


Step 1 — create a token

In Serin: Connectors → Agent access → Create token.

Copy it immediately. Serin stores only a hash, so it cannot be shown again — if you lose it, revoke it and make another.

A token is read-only and scoped to /api/agent. It cannot change anything, cannot download a backup, and cannot create another token. Revoking one does not sign you out anywhere.


Step 2 — pick your path

Which recipe you want depends on what you have on the machine running the AI client, not on which client it is.

Your situation Use
Serin Cloud Remote MCP, or the one-file bridge
Self-hosted with Docker Docker, or remote MCP
Self-hosted from a checkout From a checkout

Everything below produces the same eight tools. Pick one.

A. Remote MCP (nothing to install)

The simplest path if your client supports remote MCP servers:

URL:    https://your-serin/api/agent/mcp
Header: Authorization: Bearer serin_at_...

On Serin Cloud the URL is https://serin.money/api/agent/mcp.

One endpoint, one JSON-RPC message per request, stateless. Client support for remote servers with bearer auth is still uneven — if yours cannot, use the one-file bridge below, which works with every client.

B. The one-file bridge

For Serin Cloud, or any machine with no checkout and no container. The bridge is a thin HTTP client with no Serin dependencies, so it runs on its own:

curl -O https://raw.githubusercontent.com/aviary-ai-labs/serin/main/backend/mcp_server.py
pip install httpx

Then point your client at it, using an absolute path:

{
  "mcpServers": {
    "serin": {
      "command": "python",
      "args": ["/absolute/path/to/mcp_server.py"],
      "env": {
        "SERIN_URL": "https://serin.money",
        "SERIN_AGENT_TOKEN": "serin_at_..."
      }
    }
  }
}

Needs Python 3.10 or newer and httpx, nothing else. Self-hosters: set SERIN_URL to wherever you reach Serin in a browser.

C. Inside the container

If you run Serin with docker compose up, you have no checkout — but the image already contains the bridge, so run it there:

{
  "mcpServers": {
    "serin": {
      "command": "docker",
      "args": [
        "exec", "-i",
        "-e", "SERIN_URL=http://127.0.0.1:8890",
        "-e", "SERIN_AGENT_TOKEN=serin_at_...",
        "serin",
        "python", "-m", "backend.mcp_server"
      ]
    }
  }
}

serin is the container name from docker-compose.yml, and it must be running when the client starts. 127.0.0.1:8890 is correct here because the command runs inside the container.

D. From a checkout

{
  "mcpServers": {
    "serin": {
      "command": "python",
      "args": ["-m", "backend.mcp_server"],
      "cwd": "/path/to/your/serin/checkout",
      "env": {
        "SERIN_URL": "http://127.0.0.1:8890",
        "SERIN_AGENT_TOKEN": "serin_at_..."
      }
    }
  }
}

Where your client keeps its config

The JSON above goes in your client's MCP config file.

Claude Desktop

Create it if it isn't there, then restart the app.

Claude Code

claude mcp add serin \
  -e SERIN_URL=https://serin.money \
  -e SERIN_AGENT_TOKEN=serin_at_... \
  -- python /absolute/path/to/mcp_server.py

Flags move between releases — claude mcp add --help is authoritative.

Cursor, Cline, Zed and others use the same mcpServers shape but keep it in their own file. Copy the block above and check your client's MCP documentation for where that lives.

What you can ask

Serin reports how fresh its prices are with every answer that uses them, so your assistant can tell a current quote from a cached one.


Not using MCP?

The same tools are plain HTTP, published in /openapi.json — enough for LangChain, LlamaIndex, OpenAI function calling, or your own loop:

Endpoint What it does
GET /api/agent/tools Every tool with its JSON schema
POST /api/agent/tools/{name} Run one; arguments are the JSON body
GET /api/agent/context.md The whole portfolio as Markdown
POST /api/agent/mcp MCP over HTTP

context.md is the zero-integration option: it works with any assistant at all, including ones with no tool support, and you can paste it into a chat window yourself.


Troubleshooting

The client shows no tools. It never finished connecting. Check the client's MCP log: a bridge that cannot import backend.mcp_server exits immediately. Use the Docker recipe, or set cwd to a Serin checkout.

401 Unauthorized. SERIN_AGENT_TOKEN is missing, mistyped, or revoked. Tokens are shown once — make a new one rather than guessing.

403 Forbidden. That credential isn't an agent token. A session token or app passphrase will not work here; agent tokens start with serin_at_.

Connection refused. SERIN_URL is wrong. On Cloud it is https://serin.money — with the scheme, and no trailing path. From inside the container it is http://127.0.0.1:8890. From your own machine against a self-hosted box, it is wherever you reach Serin in a browser.

ModuleNotFoundError: No module named 'backend'. You used a checkout-shaped recipe without a checkout. Use the one-file bridge (B) or the Docker recipe (C).

Answers cite old prices. That is Serin being honest — the price cache survives a failed refresh, and every tool reports its own staleness. Run a price refresh.


On Serin Cloud (and any shared deployment)

A token names the account that issued it (serin_at_<account>.<secret>) and every request runs bound to that account, so it reads your portfolio and no one else's. The account half is not a secret; swapping it for someone else's looks up their stored hashes, which will not match, so a token cannot be pointed at another account.