@three-ws/portfolio-mcp
v0.1.0
Published
An AI agent's own trading state over MCP — portfolio summary, value history, live wallet balances, the public closed-trade PnL feed, and one real write: a signed on-chain Solana transfer. Powered by three.ws.
Maintainers
Readme
A Model Context Protocol server that gives an AI agent programmatic access to its own trading state over stdio: what it holds, how that value moves over time, a single token's position with live market data, the platform-wide feed of closed trades and their realized PnL, live on-chain balances for any wallet — and one real write, a signed Solana transfer of SOL or any SPL token.
Reads hit the live three.ws API and Solana RPC — nothing is mocked. The account-scoped reads run against the agent wallets you own (resolved from your three.ws session). The one write, send_transfer, signs locally with your own key and moves real funds on mainnet.
Install
npm install @three-ws/portfolio-mcpOr run with npx (no install):
npx @three-ws/portfolio-mcpQuick start
Claude Code, one line:
claude mcp add portfolio -- npx -y @three-ws/portfolio-mcpClaude Desktop / Cursor (claude_desktop_config.json or mcp.json):
{
"mcpServers": {
"portfolio": {
"command": "npx",
"args": ["-y", "@three-ws/portfolio-mcp"],
"env": {
"THREE_WS_SESSION": "<your __Host-sid cookie>",
"SOLANA_SECRET_KEY": "<base58 secret of the sending wallet>"
}
}
}
}THREE_WS_SESSION is only needed for the account-scoped reads; SOLANA_SECRET_KEY is only needed for send_transfer. The trade feed and on-chain balance reads work with no configuration at all.
Inspect the surface with the MCP Inspector:
npx -y @modelcontextprotocol/inspector npx @three-ws/portfolio-mcpTools
| Tool | Type | What it does |
| ------------------------ | --------------------- | ------------------------------------------------------------------------------------------------------------------- |
| get_portfolio_summary | read · session | Live holdings + USD value across every agent wallet you own, with a per-wallet breakdown. Optional snapshot. |
| get_portfolio_history | read · session | Your total portfolio USD value over time, from stored snapshots — the performance chart. |
| get_portfolio_asset | read · session | One token deep-dive: which wallets hold it, your total amount/USD, plus live market data and a price-history chart. |
| get_trades_feed | read · public | The platform-wide feed of closed positions and their realized PnL — newest exit first, filterable by coin. |
| get_wallet_balances | read · public | Live on-chain SOL + SPL (incl. Token-2022) balances for any Solana address, straight from the RPC. |
| send_transfer | write · destructive | Sign and broadcast a real, irreversible Solana mainnet transfer of SOL or any SPL token from your own wallet. |
Everything reads live state — balances, feeds, and broadcasts all move between calls — so no tool is idempotent. send_transfer is the only tool that mutates anything.
Input parameters
get_portfolio_summary — snapshot (bool, default false — also persist a history point).
get_portfolio_history — days (1–365, default 90).
get_portfolio_asset — chain (solana | evm, required), id (native or the base58 mint / 0x contract, required), days (1–365, default 30).
get_trades_feed — network (mainnet | devnet, default mainnet), window (1h | 6h | 24h | 7d | 30d | all, default 24h), min_pnl_pct (default 10), limit (1–80, default 40), cursor (ISO timestamp for pagination), mint (filter to one coin).
get_wallet_balances — address (base58, required), include_tokens (bool, default true).
send_transfer — recipient (base58, required), amount (decimal string, required), mint (base58 SPL mint; omit / native for SOL), secret (base58, overrides SOLANA_SECRET_KEY), priorityMicroLamports (0–50,000,000), confirm (must be true to execute).
Realized vs. live value
Two different questions, two different tools:
- "What am I worth right now?" →
get_portfolio_summary/get_portfolio_asset— live holdings priced in USD. - "How have my closed trades done?" →
get_trades_feed— realized PnL per closed position (entry/exit in SOL, profit %, multiple, hold time).
The write tool — send_transfer
send_transfer broadcasts a real, irreversible transaction on Solana mainnet and moves funds out of the signing wallet. It signs locally with the per-call secret or SOLANA_SECRET_KEY — the three.ws API never holds your key. Guardrails:
confirm: truerequired whileREQUIRE_CONFIRMis on (the default) — the first call without it returns a refusal, not a broadcast.MAX_SOL_PER_TXcaps native SOL sends (default 0.5 SOL).RECIPIENT_ALLOWLIST, when set, restricts the destination to a known set.- The
mintis runtime input — pass the$THREEmint or any SPL token you hold. No mint is hardcoded.
For an SPL transfer it reads the mint's decimals on-chain, verifies your balance, and auto-creates the recipient's associated token account when missing. On a confirmation timeout it returns tx_unconfirmed with the signature rather than silently retrying — check Solscan before resending to avoid a double-spend.
Requirements
- Node.js >= 20.
- Network access to
https://three.ws(or your ownTHREE_WS_BASE) and a Solana RPC.
Environment variables
| Variable | Required | Default |
| ----------------------- | ------------------------- | --------------------------------------- |
| THREE_WS_BASE | no | https://three.ws |
| THREE_WS_TIMEOUT_MS | no | 20000 |
| THREE_WS_SESSION | for account-scoped reads | — |
| SOLANA_RPC_URL | no | https://api.mainnet-beta.solana.com |
| SOLANA_SECRET_KEY | for send_transfer | — |
| MAX_SOL_PER_TX | no | 0.5 |
| RECIPIENT_ALLOWLIST | no | — (any valid pubkey allowed) |
| REQUIRE_CONFIRM | no | true |
THREE_WS_SESSION is the value of the __Host-sid cookie from a signed-in three.ws browser session. Treat it — and SOLANA_SECRET_KEY — like a password.
Links
- Homepage: https://three.ws
- Changelog: https://three.ws/changelog
- Issues: https://github.com/nirholas/three.ws/issues
- License: Apache-2.0 — see LICENSE
