sc-mcp
# sc-mcp
Connect your [Scalable Capital](https://scalable.capital) brokerage to any
[MCP](https://modelcontextprotocol.io)-capable assistant. This server is a thin,
read-friendly wrapper around Scalable Capital's official `sc` CLI — agents get
your portfolio, trades, analytics, quotes, charts, watchlist and alerts with the
same pieces of config across Claude Code, Claude Desktop, Codex, Cursor and VS
Code.
## Features
- **Live broker data** — overview, holdings, transactions, analytics, cash
breakdown, performance charts, quotes, security news.
- **Portfolio management extras** — watchlist, price alerts, portfolio groups
and savings-plan config.
- **Fast by default** — read responses are cached in a SQLite file (survives
restarts, see [Configuration](#configuration)).
- **Safety first** — no trades, no orders. Write tools are off unless you opt
in; money-moving commands are absent by design.
- **Runs anywhere** — plain stdio for desktop clients, HTTP for remote access,
or a fully self-contained Docker image.
> [!Warning]
> **Unofficial.** A community wrapper around Scalable Capital's `sc` CLI — not
> affiliated with or endorsed by Scalable Capital. A stopgap until a first-party
> MCP server exists, and likely to be retired once it does.
>
> **No warranty.** Provided "as is" under the MIT License; no responsibility for
> loss, damage, incorrect data or any financial consequence. Not financial
> advice — verify anything you act on.
## Tools
Read-only tools hit the broker live; successful responses are cached for
5 minutes (configurable) in a SQLite file that survives restarts.
| Tool | Returns | `sc` CLI since |
|------|---------|----------------|
| `sc_overview` | Portfolio value, cash, performance | v0.1.0 |
| `sc_holdings` | Positions with prices, quantities, market values | v0.1.0 |
| `sc_transactions` | Trade history with filters (date, ISIN, type, paging) | v0.1.0 |
| `sc_analytics` | Allocation, sector/region exposure, attribution | v0.1.0 |
| `sc_security_news` | Latest news for a security by ISIN | v0.1.0 |
| `sc_quote` | Current quote by ISIN | v0.2.0 |
| `sc_search` | Search securities within the portfolio context | v0.1.0 |
| `sc_transaction` | Single transaction details by ID | v0.2.0 |
| `sc_cash_breakdown` | Buying power, cash, credit, derivatives availability | **v0.4.0** |
| `sc_chart` | Historical OHLCV by ISIN (1d/7d/1m/3m/6m/ytd/1y/max) | **v0.5.0** |
| `sc_overnight` | Overnight savings account summary | **v0.5.0** |
| `sc_overnight_transactions` | Overnight transaction history with filters | **v0.5.0** |
| `sc_portfolio_groups` | Groups with since-buy performance, ungrouped holdings | **v0.6.0** |
| `sc_derivatives_search` | Derivative discovery (knockout/warrant/factor) | **v0.3.0** |
| `sc_watchlist` | Watchlist (read) | v0.1.0 |
| `sc_price_alerts` | Price alerts, optionally active-only | v0.1.0 |
| `sc_savings_plans_config` | Savings-plan config & ex-ante fees (read-only) | **v0.6.0** |
| `sc_capabilities` | CLI capability dump (version, commands, exit codes) | v0.1.0 |
| `sc_watchlist_add` ⚠️ | Add to watchlist | v0.1.0 |
| `sc_watchlist_remove` ⚠️ | Remove from watchlist | v0.1.0 |
| `sc_price_alert_add` ⚠️ | Create price alert | v0.1.0 |
| `sc_price_alert_remove` ⚠️ | Remove price alert | v0.2.0 |
| `sc_portfolio_group_create` ⚠️ | Create group | **v0.6.0** |
| `sc_portfolio_group_update` ⚠️ | Update group name/description | **v0.6.0** |
| `sc_portfolio_group_delete` ⚠️ | Delete group | **v0.6.0** |
| `sc_portfolio_group_assign` ⚠️ | Assign holdings to a group | **v0.6.0** |
| `sc_portfolio_group_unassign` ⚠️ | Unassign holdings from a group | **v0.6.0** |
⚠️ = requires `SC_MCP_ENABLE_WRITES=true`, off by default.
The `sc` CLI also exposes `trade` and `savings-plans add/remove`. Those are
**deliberately not exposed** — money-moving commands are out of scope entirely
(the write tools above only touch watchlists, alerts and groups).
## Quick start
Pick one path — all three end with a working server:
| Path | What you need | Docs |
|------|---------------|------|
| Claude Code plugin | Claude Code only — zero config | [below](#claude-code-plugin) |
| `uvx` one-liner | `uv` + a logged-in `sc` CLI | [any client](#uvx-one-liner) |
| Docker | Docker only — nothing installed locally | [below](#docker) |
### Claude Code plugin
```text
/plugin marketplace add NinjaEde/mcp-scalable-capital
/plugin install sc-mcp
```
That registers the `scalable-capital` MCP server and a skill that tells Claude
when and how to use the tools.
### uvx one-liner
```bash
uvx --from git+https://github.com/NinjaEde/mcp-scalable-capital@v0.2.0 sc-mcp
```
Point any MCP client at that command (`sc-mcp` started stdio, pin the tag per
[Versioning](#versioning)).
## Requirements
1. [`uv`](https://docs.astral.sh/uv/) on `PATH` — _skip this with [Docker](#docker)._
2. The [`sc`](https://github.com/ScalableCapital/scalable-cli) CLI on `PATH`
(see [Authentication](#authentication)).
3. An authenticated session: `sc login` (see [Authentication](#authentication)).
Docker bundles both the CLI and this server, so the only manual step there is
the login below.
## Authentication
Every `sc_*` tool shells out to Scalable Capital's official `sc` CLI, which
must be installed **and** logged in once per machine (or per Docker volume).
### Install the CLI
**macOS (Homebrew):**
```bash
brew install scalablecapital/tap/scalable-cli
```
**Linux** (also the binary baked into the Docker image): download the official
build for your architecture and put `sc` on `PATH`:
```bash
ARCH=$(uname -m) # x86_64 or aarch64
curl -fSL "https://github.com/ScalableCapital/scalable-cli/releases/download/v0.6.0/sc-v0.6.0-linux-${ARCH}-gnu.tar.gz" -o /tmp/sc.tar.gz
tar xzf /tmp/sc.tar.gz -C /tmp
sudo install -m 0755 /tmp/sc-v0.6.0-linux-${ARCH}-gnu/sc /usr/local/bin/sc
```
Verify:
```bash
sc --version # e.g. "sc 0.6.0"
```
### Log in (once)
```bash
sc login # device flow: open the printed URL, confirm, done
sc whoami # confirm the session works
```
If a tool later reports *"session may have expired — try `sc login`"*, just
re-run `sc login`.
### Where the session lives
`~/.config/scalable-cli/`:
| File | Purpose |
|------|---------|
| `session.json` | Your authenticated session (the `sc-cli-config` volume in Docker) |
| `config.toml` | Optional settings — e.g. the session backend |
**Headless / keyring-less environments** (Docker, CI, servers): the CLI defaults
to the OS keyring. Where none exists, point it at a plain file (the Docker image
does this for you in `docker/entrypoint.sh`):
```toml
# ~/.config/scalable-cli/config.toml
[auth]
session_backend = "file"
```
Then run `sc login` again — the session lands in `session.json` and persists
across restarts.
> **Tip:** reuse a host session inside containers instead of logging in twice:
>
> ```bash
> docker cp ~/.config/scalable-cli/session.json sc-mcp:/home/sc/.config/scalable-cli/session.json
> docker compose restart
> ```
>
> Treat that file like a password — never commit it.
## Integrating with clients
### Claude Code (manual)
```bash
claude mcp add scalable-capital -- uvx --from git+https://github.com/NinjaEde/mcp-scalable-capital@v0.2.0 sc-mcp
```
### Cursor
[**Add to Cursor**](cursor://anysphere.cursor-deeplink/mcp/install?name=scalable-capital&config=eyJjb21tYW5kIjogInV2eCIsICJhcmdzIjogWyItLWZyb20iLCAiZ2l0K2h0dHBzOi8vZ2l0aHViLmNvbS9OaW5qYUVkZS9tY3Atc2NhbGFibGUtY2FwaXRhbEB2MC4yLjAiLCAic2MtbWNwIl19)
— or add to `.cursor/mcp.json` (or `~/.cursor/mcp.json`):
```json
{
"mcpServers": {
"scalable-capital": {
"command": "uvx",
"args": ["--from", "git+https://github.com/NinjaEde/mcp-scalable-capital@v0.2.0", "sc-mcp"]
}
}
}
```
### Codex
Add to `~/.codex/config.toml`:
```toml
[mcp_servers.scalable-capital]
command = "uvx"
args = ["--from", "git+https://github.com/NinjaEde/mcp-scalable-capital@v0.2.0", "sc-mcp"]
```
### Claude Desktop (bundle, no config editing)
Download [**`sc-mcp.mcpb`**](https://github.com/NinjaEde/mcp-scalable-capital/releases/latest/download/sc-mcp.mcpb),
then in Claude Desktop go to **Settings → Extensions → Install Extension** and
pick the file.
> [!Note]
> If Claude Desktop can't find `uvx`, open the extension's settings and set the
> full path (e.g. `/opt/homebrew/bin/uvx`). GUI apps on macOS don't always
> inherit your shell `PATH`.
### VS Code / other MCP clients
```json
{
"mcpServers": {
"scalable-capital": {
"command": "uvx",
"args": ["--from", "git+https://github.com/NinjaEde/mcp-scalable-capital@v0.2.0", "sc-mcp"]
}
}
}
```
> Pin the `@v0.2.0` tag (see [Versioning](#versioning)). Drop it to track the
> latest `main`.
## Docker
The whole stack — this server **and** the `sc` CLI — runs in containers, so you
only need Docker (no local `uv`, Python, or `sc`):
```bash
docker compose up -d --build # build + start on http://localhost:8000/mcp
docker compose run --rm sc-login # first time only — interactive device flow
```
The session is stored in the `sc-cli-config` volume and survives restarts.
Writes stay off unless you set `SC_MCP_ENABLE_WRITES: "true"` in
`docker-compose.yml`.
Point any HTTP-capable MCP client at the server URL:
```json
{
"mcpServers": {
"scalable-capital": {
"type": "http",
"url": "http://localhost:8000/mcp"
}
}
}
```
> The container talks to `scalable.capital` directly. The device-flow URL from
> `sc login` works the same as on your host; just follow it in a browser. The
> image already ships the `session_backend = "file"` config (see
> [Authentication](#authentication)).
## Compatibility
Tested against **`sc` 0.6.x**. The CLI is pre-1.0 and its command surface can
change between minor versions; the server logs a warning to stderr at startup
if your installed `sc` differs from the tested major.minor. `sc` is an external
binary, not a Python dependency, so that's the only enforcement available. If
you see the warning and a tool misbehaves, the mismatch is the likely cause.
## Configuration
| Env var | Default | Effect |
|---------|---------|--------|
| `SC_MCP_CACHE_TTL` | `300` | Seconds to cache successful responses. `0` disables caching (always hit the broker live). |
| `SC_MCP_CACHE_DB` | `~/.cache/sc-mcp/cache.db` | Path to the SQLite cache file. |
| `SC_MCP_ENABLE_WRITES` | *unset* | Set to `1`, `true`, or `yes` to enable the ⚠️ write tools. |
| `SC_MCP_TRANSPORT` | `stdio` | `streamable-http` (or `http`) serves over HTTP instead of stdio — used by Docker. |
| `SC_MCP_HTTP_HOST` | `0.0.0.0` | Bind address for the HTTP transport. |
| `SC_MCP_HTTP_PORT` | `8000` | Port for the HTTP transport. |
## Develop
```bash
uv sync
uv run sc-mcp # starts the stdio server
# or
SC_MCP_TRANSPORT=streamable-http uv run sc-mcp
uv run pytest
```
How to stay in sync with `sc` (when to add/update tools, bump
`SUPPORTED_SC_VERSION`, read-only invariants) is documented in
[CLAUDE.md](CLAUDE.md).
## Versioning
SemVer — the tools are the public API:
| Bump | Trigger |
|------|---------|
| **MAJOR** | A tool is removed/renamed, or a parameter changes incompatibly |
| **MINOR** | A tool or optional parameter is added |
| **PATCH** | Bug fix, error-message wording, internals |
Releases are tagged `vX.Y.Z`; **pin a tag** when installing via `uvx --from
git+...`, which otherwise tracks the default branch and can change your tool
surface under you. Most bumps are driven by `sc` CLI changes (see
[Compatibility](#compatibility)); the version is this package's own, not the
`sc` version.
## License
[MIT](LICENSE)TDQS
Scored across 27 tools
Each tool targets a distinct resource and action: overview, holdings, transactions, watchlist, price alerts, portfolio groups, and market data are cleanly separated. Even similar-looking tools like sc_transactions and sc_transaction are clearly plural-list vs singular-detail.
All tools share the sc_ prefix and use snake_case. Reads are sc_<noun> and mutations are sc_<noun>_<verb> (add/remove/create/update/delete/assign), forming a predictable and uniform convention.
With 27 tools, the surface exceeds the point where an agent can easily select among options. Several related operations could be consolidated into compound tools, e.g., portfolio group CRUD or watchlist read/write/delete.
The read side is quite complete: portfolio, transactions, analytics, market data, overnight savings, and configuration are covered. Missing order placement and savings-plan write actions are notable gaps, but the given scope is mostly coherent.