Delta Exchange # delta-exchange-mcp > *Ask about Delta Exchange India in plain English — live prices, option chains, your own positions — from Claude or your editor.* ![Status: Beta][beta-badge] [![PyPI version][pypi-version-badge]][pypi-version-link] [![Download for Claude Desktop][claude-desktop-badge]][claude-desktop-link] [![Add to Cursor][cursor-badge]][cursor-link] [![Install in VS Code][vs-code-badge]][vs-code-link] [![Claude Code][claude-code-jump-badge]][claude-code-jump-link] [![Codex][codex-jump-badge]][codex-jump-link] [![Windsurf][windsurf-jump-badge]][windsurf-jump-link] [![Zed][zed-jump-badge]][zed-jump-link]
Official MCP (Model Context Protocol) server for **Delta Exchange India**: market data for everyone, and your own account — reads and live trading alike — with an API key. What the key is allowed to do is what the assistant can do. > [!NOTE] > **Beta.** Functional and used internally, but the tool surface and configuration may still > change. Please [open an issue](https://github.com/delta-exchange/delta-exchange-mcp/issues) > for bugs, missing tools, or rough edges — early reports directly shape what ships next. ## Use it — no setup Hit **Download for Claude Desktop** above and double-click the file. Claude Desktop shows a form, then installs the server — no config file, and **no need to install `uv` or Python first**: the app fetches both itself. Unlike the Cursor and VS Code buttons, this one is a file download rather than a link that configures your editor; bundles are read only by Claude Desktop, Claude Code, and MCP for Windows. The form has three fields: - **Environment** — which exchange to talk to: `india_prod` for the real one, or `india_testnet` for the practice site at demo.delta.exchange. - **API key** and **API secret** — fill them in to let the assistant reach your own account. Create them under [Account → API Keys](https://www.delta.exchange/app/account/manageapikeys). Pick the **Read Data** permission, which allows viewing but not trading. A Read Data key is enough for every account read. Leaving the fields empty gives you market data only, unless you have already put a key in the [shared file](#add-your-api-key), in which case that one is used. > [!WARNING] > A key carrying the **Trading** permission can place **real orders with no size cap**, sized > in **contracts rather than coins**, from the moment it is saved. There is no separate mode, > no restart and no confirmation step. Give the server a **Read Data** key unless letting an > assistant trade your account is exactly what you want.
Claude Desktop — JSON config by hand (also how you pin a specific version) Open **Settings → Developer → Edit config**, or edit directly at: - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json` - Windows: `%APPDATA%\Claude\claude_desktop_config.json` - Linux: `~/.config/Claude/claude_desktop_config.json` ```json { "mcpServers": { "delta-exchange-mcp": { "command": "uvx", "args": ["delta-exchange-mcp"] } } } ``` Quit and relaunch Claude Desktop for changes to take effect.
## Wire it into your editor **Prerequisite:** [`uv`](https://docs.astral.sh/uv/getting-started/installation/) installed on your machine. Sanity-check: ```bash uvx delta-exchange-mcp --help ``` The server runs **local stdio only**: your MCP client launches it as a subprocess, and your API keys never leave your machine — they live in one file that every client reads, not in each client's config. See [Add your API key](#add-your-api-key). `uvx` resolves the latest published version from PyPI on each launch. To pin a specific version, use `uvx "delta-exchange-mcp==0.4.2"`. Pin `0.4.2` or newer: earlier versions do not start on a fresh install (see [Troubleshooting](#troubleshooting)). **Cursor** and **VS Code** install with one click from the buttons above; every other client takes a CLI one-liner or a short config block — all covered per client under [Install in your MCP client](#install-in-your-mcp-client). ## What you can ask ```txt What's the current BTCUSD mark price and 24h range? Show the options chain for BTC expiring this Friday. What positions do I have open and what's my total unrealized PnL? List my fills from the last 24 hours grouped by symbol. How much USDT do I have free vs blocked in margin? ``` The assistant picks the right tool based on the question — you never name a tool. A real exchange, verbatim from a Claude Desktop session against the live API: > **eth prices, use delta-exchange** > > ETHUSD Perpetual (Delta Exchange): $1,856.25 (last) — down 3.15% in 24h (24h range: > $1,847.25 – $1,936.25). Spot index: $1,857.19. Mark price: $1,856.07. Funding rate: > −0.284%. Open interest: ~$54.2M. ## Capabilities What the server can do is decided entirely by your API key — three tiers, each a strict superset of the one above it: | Tier | You set | Unlocks | |---|---|---| | Market data | nothing | Prices, order books, option chains, candles, funding / OI history, indices | | Account, read-only | an API key — see [Add your API key](#add-your-api-key) | Your positions, orders, fills, balances, trading stats, preferences | | Trading | a key with **Trading** permission | Place / edit / cancel orders, brackets, leverage, margin, close-all | A key without its matching secret is ignored and you stay on market data — the two are always used together. ### Trading **The key's permissions are the only gate.** There is no mode to set and no restart to do: save a key with Trading permission and the order tools are there. Save a Read Data key and they are still listed, but Delta rejects every order the assistant sends — which is the boundary that actually holds, because it is enforced on Delta's side rather than here. > [!WARNING] > What this will **not** do: cap notional or position size, ask you to confirm before > sending, rehearse an order without sending it, keep a local record of what it sent, > convert between contracts and coins, or judge whether an order makes sense. `close_all_positions` > takes no arguments and closes your entire account. Those are your responsibility. Try > `DELTA_MCP_ENV=india_testnet` first. To keep an assistant off your orders, give it a Read Data key. To let it trade, give it one with Trading permission — and note that Delta requires an IP whitelist entry on such keys. The one thing that has not changed: unlike GET reads, mutations are never auto-retried on a timeout or a rate limit. A failure is surfaced, not silently re-sent, because re-sending an order can place it twice. Delta checks permission for each endpoint. An `Unauthorized` response means the key cannot reach that endpoint, such as a Read Data key placing an order; it does not mean the key is invalid. ## Add your API key **You may not need one.** Market data works with no key at all, so if you only want prices, option chains or funding history, skip this section entirely. To let an assistant read your own account, the key goes in **one file, once** — not into each client's config: ``` ~/.delta-exchange-mcp/config.env ``` Every MCP client on your machine reads it, so a key set here works in Claude Desktop, Cursor, Claude Code and everything else at the same time. The server creates the file the first time it runs, with instructions inside it, and prints the path in its startup line. It is created owner-only (`0600`). Three ways to fill it in. Pick one — they all write the same file. **In the conversation**, without leaving it. Ask your assistant to *connect my Delta account* and a small form appears inline: ```txt Connect my Delta Exchange account ``` It asks three things: which site the key was made on (delta.exchange or the practice site at demo.delta.exchange), then the key and the secret. What the assistant can do follows from the key's own permissions. It checks the key against Delta before saving, and once it saves it replaces itself with the account it connected, so you can see which one you got. What you type in that form goes straight to the file. It is not part of the conversation and the assistant cannot read it, because the form runs in its own frame rather than in the chat. This needs a client that renders in-chat forms — Claude Desktop and the Codex desktop app do today; if nothing appears, yours doesn't, and the assistant will tell you so and point you at one of the other two ways. > [!IMPORTANT] > Sending your key to the assistant as an ordinary chat message is not the same thing. A > message is in the assistant's context and is stored in the conversation. The form exists > precisely so it isn't. If an assistant offers to take the key that way, decline. **At a terminal**, which shows a `*` for each character you type or paste and checks the key works before saving anything: ```bash uvx delta-exchange-mcp login ``` **By hand**, if you'd rather. Open the file and fill in the three lines already waiting there — plain `NAME=value`, no punctuation to get wrong: ```dotenv DELTA_API_KEY=your-key-here DELTA_API_SECRET=your-secret-here DELTA_MCP_ENV=india_prod ``` The terminal and by-hand routes normally need your MCP client restarted afterwards; asking for the connection status can also make a running server reconcile safe external changes. The in-chat form usually needs neither: it atomically moves market and account calls to the saved environment and key, registers the account tools there, and tells the client its tool list changed — so first-time setup, environment changes, and key rotation become usable in the same conversation, including the trading tools — they follow the key, so saving one that carries Trading permission brings them up in the same session. If your client has its own place to put credentials — the Claude Desktop bundle's form, VS Code's prompts, the Codex desktop app's fields — those still work and take precedence over this file. ### Getting the key itself 1. Create it at [delta.exchange/app/account/manageapikeys](https://www.delta.exchange/app/account/manageapikeys) (testnet: [demo.delta.exchange](https://demo.delta.exchange/app/account/manageapikeys)). 2. Both `api_key` and `api_secret` are shown **once at creation**. Save the secret immediately; it can't be re-derived. 3. **Read Data** permission is what stops an assistant placing orders. A Read Data key is enough for every account read. A key with Trading permission is needed only to place orders, Delta asks for an IP whitelist on it, and it can place them as soon as it is saved. 4. Delta can reject a request when its source IP is not on the key's whitelist. The error names the IP that Delta received, so you can update the key in API management. 5. **Match the environment**: a key from delta.exchange works only with `india_prod`, one from demo.delta.exchange only with `india_testnet`. Mixing them returns `InvalidApiKey`. The in-chat form and `login` check the credential pair against the account identity endpoint and refuse to save a key that Delta rejects. Both also write `DELTA_MCP_ENV` alongside the key, so the environment stays with the credential pair. ### Settings reference Each setting is read from your MCP client first, then from `~/.delta-exchange-mcp/config.env`. A value your client sets always wins; leaving it empty there means "not answered" and falls through to the file. | Var | Default | Shared file? | Purpose | |---|---|---|---| | `DELTA_MCP_ENV` | `india_prod` | yes | `india_prod`, `india_testnet`, or `india_devnet`. | | `DELTA_API_KEY` | _(unset)_ | yes | API key. Optional; when set with `DELTA_API_SECRET`, the account and trading tools register. What the key may actually do is decided by its own permissions on Delta's side. | | `DELTA_API_SECRET` | _(unset)_ | yes | API secret matching `DELTA_API_KEY`. | | `DELTA_MCP_DEBUG` | _(unset)_ | yes | `1`/`true`/`yes`/`on` writes HTTP request URLs and response bodies to a log file (see [Debugging](#debugging--reporting-a-bug)). | | `DELTA_MCP_DEBUG_FILE` | _(auto)_ | yes | Override the debug log path. Default: `~/.delta-exchange-mcp/logs/debug--.log`. | | `DELTA_MCP_CONFIG_FILE` | _(auto)_ | n/a | Move the shared file itself. Default: `~/.delta-exchange-mcp/config.env`. | The key and its secret are always taken from the same place. If either is set in your client, both come from there; otherwise both come from the file. That prevents pairing a stale key from your shell with a secret from the file — a combination that was never issued together, and which fails every signed call while the server reports the account tools as available. ## Install in your MCP client None of the snippets below carry credentials, because they don't need to — put the key in [the shared file](#add-your-api-key) once instead. Set `DELTA_MCP_ENV=india_testnet` there for testnet. ### Let your coding agent set it up Copy this into Claude Code, Codex, Cursor, or any agent that can edit files on your machine. Claude Desktop's chat is not one of those — it has no access to your filesystem, so use the **Download for Claude Desktop** bundle at the top of this page instead. ```text Install the Delta Exchange MCP server into my MCP client: uvx delta-exchange-mcp, local stdio, entry name delta-exchange-mcp, no env block. Leave my other servers alone, and never ask me for my API key. Verify with `uvx delta-exchange-mcp --version` — never run it bare, it serves stdio and won't exit. Then tell me to restart the app and stop there — don't authenticate me first, don't send me to a terminal, and don't start a new chat. We carry on in this one after the restart. If you can't edit files on this machine, say so and read the README below for the simplest path for my client — don't improvise a config for me to paste. If you don't know where my client keeps its MCP config, read https://raw.githubusercontent.com/delta-exchange/delta-exchange-mcp/main/README.md ``` The entry it writes holds no credentials and needs none — the server comes up on market data and works the moment you restart. Your key goes in [the shared file](#add-your-api-key) instead, which is why the agent never has to touch it. To set it up by hand, follow the steps for your client below. Restart the app, then carry on in the same conversation: ask it to connect your Delta account and the form opens there. The restart is needed because a client builds its list of tools when it starts, so a server added after that isn't connected yet — which is also why an assistant asked to authenticate you before restarting will reach for a terminal instead. It has nothing else to offer at that point. ### Cursor [![Add to Cursor][cursor-badge]][cursor-link] Cursor shows an approval dialog and writes the entry itself. `DELTA_API_KEY` and `DELTA_API_SECRET` arrive **empty**, so the market-data tools work immediately — fill them in, in the entry it creates, to reach your account. They are empty rather than placeholder text on purpose: a non-empty key registers the account tools and then fails every call, whereas an empty one keeps the server cleanly in public-data mode.
Cursor — JSON config by hand Global: `~/.cursor/mcp.json` (or `%USERPROFILE%\.cursor\mcp.json` on Windows). Project-scoped alternative: `.cursor/mcp.json` in the repo root. ```json { "mcpServers": { "delta-exchange-mcp": { "command": "uvx", "args": ["delta-exchange-mcp"] } } } ``` Restart Cursor or open **Settings → Tools & MCP** to refresh.
### VS Code (GitHub Copilot) [![Install in VS Code][vs-code-badge]][vs-code-link] [![Install in VS Code Insiders][vs-code-insiders-badge]][vs-code-insiders-link] VS Code prompts for the key and secret with the input masked, offers the environment as a dropdown, and writes the entry itself — nothing to edit afterwards. Leave both credential prompts empty for public-data-only mode.
VS Code — JSON config by hand Add to `.vscode/mcp.json` in your workspace. The top-level key is `servers` and each entry needs an explicit `"type": "stdio"`. Declaring the credentials as `inputs` means VS Code prompts for them once and stores them itself, so your secret never lands in a file you might commit — and `pickString` makes the environment a dropdown rather than free text you could typo: ```json { "inputs": [ { "type": "promptString", "id": "delta-api-key", "description": "Delta API key (leave empty for market data only)", "password": true }, { "type": "promptString", "id": "delta-api-secret", "description": "Delta API secret (must match the key)", "password": true }, { "type": "pickString", "id": "delta-env", "description": "Delta Exchange environment", "options": ["india_prod", "india_testnet"], "default": "india_prod" } ], "servers": { "delta-exchange-mcp": { "type": "stdio", "command": "uvx", "args": ["delta-exchange-mcp"], "env": { "DELTA_MCP_ENV": "${input:delta-env}", "DELTA_API_KEY": "${input:delta-api-key}", "DELTA_API_SECRET": "${input:delta-api-secret}" } } } } ``` The `env` block is what makes those prompts happen — VS Code only asks for an input that something references, so without it the three declarations above are inert and you are never asked for a key. Leave both prompts empty for public-data-only mode. A key entered here is passed by VS Code on every launch and takes precedence over the [shared file](#add-your-api-key), so the in-chat form cannot replace it — clear these prompts first if you want to manage the key there instead.
### Claude Code ```bash claude mcp add delta-exchange-mcp \ --scope user -- uvx delta-exchange-mcp ``` `--scope user` makes the server available across all projects. Verify with `claude mcp list`. ### Codex ```bash codex mcp add delta-exchange-mcp -- uvx delta-exchange-mcp ``` Verify with `codex mcp list`. ### OpenClaw ```bash openclaw mcp add delta-exchange-mcp \ --command uvx \ --arg delta-exchange-mcp ``` Repeat `--arg` once per value. Writes to `~/.openclaw/openclaw.json`, where MCP servers live under `mcp.servers` rather than a top-level `mcpServers` key.
Codex — TOML config, or the desktop app's form Write `~/.codex/config.toml` by hand: ```toml [mcp_servers.delta-exchange-mcp] command = "uvx" args = ["delta-exchange-mcp"] ``` Desktop app: go to **Plugins → MCPs → Connect to a custom MCP**, leave **Type** as STDIO, and fill in: | Field | Value | |---|---| | Name | `delta-exchange-mcp` | | Command to launch | `uvx` (`uvx.exe` on Windows) | | Arguments | `delta-exchange-mcp` | | Environment variables | leave empty | Leave the other fields empty, then restart the app.
### Windsurf
JSON config Add to `~/.codeium/windsurf/mcp_config.json` (macOS / Linux) or `%USERPROFILE%\.codeium\windsurf\mcp_config.json` (Windows). UI route: **Settings → Cascade → Plugins (MCP servers) → Manage Plugins → View raw config**. ```json { "mcpServers": { "delta-exchange-mcp": { "command": "uvx", "args": ["delta-exchange-mcp"] } } } ```
### Zed
JSON config Add to `~/.config/zed/settings.json` (user-level) or `.zed/settings.json` (project-level). Zed calls the top-level key `context_servers` rather than `mcpServers`; the entry itself has the usual shape: ```json { "context_servers": { "delta-exchange-mcp": { "command": "uvx", "args": ["delta-exchange-mcp"] } } } ```
### Google Antigravity
JSON config Add to `~/.gemini/config/mcp_config.json` — note the `.gemini` directory, which Antigravity shares rather than using one of its own. In the IDE you can reach the same file without typing a path: the `...` menu at the top of the agent panel → **MCP Servers → Manage MCP Servers → View raw config**. In the CLI, type `/mcp`. ```json { "mcpServers": { "delta-exchange-mcp": { "command": "uvx", "args": ["delta-exchange-mcp"] } } } ``` Prefer that global file over a project-local one: a project-level `mcp_config.json` is reported to be read and then silently ignored. Reopen the MCP panel after editing so the server actually spawns, and check the credentials really arrived — there are reports of `env` values not reaching the process, in which case the market-data tools work but account tools stay absent.
## Safety - **Your key is the boundary.** The server applies no gate of its own: a key with Trading permission can place orders as soon as it is saved, and a Read Data key cannot, because Delta rejects it. Choose the permission you actually want. - **API key permission.** Delta checks permission for each endpoint. An `Unauthorized` response means that the key cannot access the requested endpoint; it does not prove that the key is invalid. A Read Data key is enough for account reads. - **No rehearsal, no confirmation, no caps.** Orders go out as sent. There is no dry run, no local record of what was sent, and no notional or size limit. - **No silent retries.** Mutations are never auto-retried on a timeout or rate limit; a failure is surfaced rather than re-sent, because re-sending an order can place it twice. - **Local stdio only.** Per-user keys never leave your machine; no shared hosted endpoint. - **Read the code.** It's a financial-tool MCP; treat it like one. ## `X-Delta-MCP-*` request headers Every request to Delta's API carries these headers. They tell Delta which MCP client and which tool caused the request. There is no setting to turn them off. | Header | Example | What it holds | | --- | --- | --- | | `X-Delta-MCP-Version` | `0.7.0` | Version of this package. Sent on every request. | | `X-Delta-MCP-Client` | `claude-ai` | Name the client gave in the MCP handshake. | | `X-Delta-MCP-Client-Version` | `1.30096.5` | That client's version, as it reported it. | | `X-Delta-MCP-Tool` | `get_ticker` | Tool that caused the request. | | `X-Delta-MCP-Protocol` | `2025-06-18` | MCP protocol version the client and server agreed on. | | `X-Delta-MCP-Context` | `{"capabilities":["roots"],"platform":"Darwin arm64","python":"3.12"}` | OS and CPU, Python version, and the optional MCP features the client declared. | - No API key, secret, signature or account detail goes into these headers. - The client names itself, and nothing checks that name. A client can report any name. - Client values are percent-encoded and cut to 200 characters, so a client name cannot add or break a header. ## Updating `uvx` caches the resolved package, so a new PyPI release isn't picked up automatically. To move to the latest version: 1. **If your config pins a version** (`uvx "delta-exchange-mcp==0.4.2"`), bump the pin to the new version, or drop it to float to latest. 2. **Refresh the `uvx` cache** so it fetches the new build: ```bash uvx --refresh delta-exchange-mcp --help ``` 3. **Reload the server** so your client respawns the process — in Claude Code, run `/mcp` and reconnect `delta-exchange-mcp`, or restart the client. Other clients: restart the app. New tools appear only after the respawn. The MCP `list_changed` notification refreshes the tool list of an already-running server; it does **not** swap the underlying package version, which always requires a restart. ## Troubleshooting ### The key form doesn't appear in the chat You asked the assistant to connect your account, and it replied with a file path and a command instead of showing a form. That is the intended fallback, not a failure: rendering a form inline is an optional part of MCP that only some clients implement, and the server cannot tell in advance which ones do — Claude Desktop, for instance, renders these forms without announcing that it can. So the server always returns working instructions alongside the form, and on a client that shows nothing you see only the instructions. Use [one of the other two ways](#add-your-api-key): `uvx delta-exchange-mcp login`, or open `~/.delta-exchange-mcp/config.env` and fill in the three lines. Both write the same file the form would have. ### The form saved my key, but the assistant still can't see my account The form says it saved, and names a setting your client sets in its own configuration. That is the whole failure, stated plainly: a value in your client's MCP entry — or in the fields it asked you to fill in when you installed it — is read before the shared file and wins over it. So the form verified your key, saved it correctly, and the server carries on signing with whatever your client passes instead. Restarting does not help, because the client passes its own value again every time it starts. Clear those fields from that client's entry, then restart it. Which setting is at fault is named in the message the form shows. `uvx delta-exchange-mcp login` runs the same check and warns on stderr, though there it reports what your *shell* is setting, since that is the environment it can see. ### `ModuleNotFoundError: No module named 'mcp.server.fastmcp'` Your client shows the server as failed, and the process writes this traceback to stderr. Version 0.4.1 and all earlier versions declare `mcp>=1.12.4` with no upper limit. The `mcp` package published 2.0.0 on 28 July 2026, and 2.0.0 removed the `mcp.server.fastmcp` module. `uvx` resolves from the declared range and ignores `uv.lock`, so a fresh install gets 2.0.0 and the server stops at import. Existing installs and `uv sync` checkouts are not affected. Move to 0.4.2 or a newer version. Those releases pin the SDK to a range that works: ```bash uvx --refresh delta-exchange-mcp --help ``` To stay on an older version, set the limit yourself: ```bash uvx --with "mcp<2" "delta-exchange-mcp==0.4.1" ``` Add the same `--with` argument to your MCP client config if you pin an older version there: ```jsonc "delta-exchange-mcp": { "command": "uvx", "args": ["--with", "mcp<2", "delta-exchange-mcp==0.4.1"] } ``` ## Debugging / reporting a bug To capture exactly what the server sends and receives — useful when a tool returns something unexpected — set `DELTA_MCP_DEBUG=1` in your MCP client config: ```jsonc "delta-exchange-mcp": { "command": "uvx", "args": ["delta-exchange-mcp"], "env": { "DELTA_MCP_DEBUG": "1" } } ``` Or set it once for every client by adding `DELTA_MCP_DEBUG=1` to [the shared file](#add-your-api-key). Restart the client and re-run the action. Each HTTP call (request URL incl. filter params + response body + status) is logged to `~/.delta-exchange-mcp/logs/`. The exact path is printed on startup and you can also just **ask the assistant: _"where is the debug log?"_**. > The log **never** contains your API key, secret, or request signatures — but response bodies > **do** contain your account data (balances, positions, transactions). **Review before sharing.** ## Running a dev / unreleased branch To test an unreleased commit, branch, or fork before it's on PyPI, swap `uvx delta-exchange-mcp` for `uvx --from git+@ delta-exchange-mcp`. `` can be a branch, tag, or commit SHA. CLI sanity check: ```bash uvx --from git+https://github.com/delta-exchange/delta-exchange-mcp.git@develop delta-exchange-mcp --help ``` `uv` caches the git resolution, so to pick up new commits on the same branch: ```bash uvx --refresh --from git+https://github.com/delta-exchange/delta-exchange-mcp.git@develop delta-exchange-mcp --help ``` ### In your MCP client config Replace `args` in any snippet above with the `git+` form. Three flavours: **Claude Code:** ```bash claude mcp add delta-exchange-mcp-dev \ --scope user \ -- uvx --from git+https://github.com/delta-exchange/delta-exchange-mcp.git@develop delta-exchange-mcp ``` **Cursor / Windsurf / Claude Desktop (any `mcpServers` JSON):** ```json { "mcpServers": { "delta-exchange-mcp-dev": { "command": "uvx", "args": [ "--from", "git+https://github.com/delta-exchange/delta-exchange-mcp.git@develop", "delta-exchange-mcp" ] } } } ``` **Zed (`context_servers` key):** ```json { "context_servers": { "delta-exchange-mcp-dev": { "command": "uvx", "args": [ "--from", "git+https://github.com/delta-exchange/delta-exchange-mcp.git@develop", "delta-exchange-mcp" ] } } } ``` Register the dev server under a separate name (e.g. `delta-exchange-mcp-dev`) so it doesn't collide with the PyPI install. The git+URL form rebuilds from source on each launch and is meant for testing unreleased changes — stick with `uvx delta-exchange-mcp` for everyday use. ## Development ```bash uv sync # install deps uv run pytest # run tests (no network, respx-mocked) uv run ruff check src tests # lint uv run delta-exchange-mcp # run server (stdio) ``` ### Testing with MCP Inspector ```bash # stdio CLI mode bash scripts/inspect.sh --cli --method tools/list bash scripts/inspect.sh --cli --method tools/call \ --tool-name get_ticker --tool-arg symbol=BTCUSD # with auth DELTA_API_KEY=... DELTA_API_SECRET=... \ bash scripts/inspect.sh --cli --method tools/call --tool-name get_wallet_balances # web UI bash scripts/inspect.sh # → http://localhost:6274 ``` Maintainers: see [`RELEASING.md`](RELEASING.md) for the release procedure. ## Roadmap - **Now**: public market data, authenticated read-only account access, and trading gated only by the API key's own permissions. ## Feedback & issues This is the first public cut and we want to make it better. Please file: - Bugs (incorrect data, signing/auth errors, crashes) - Missing tools or fields you'd want exposed - Rough edges in setup, docs, or error messages - Anything you'd build on top of this if a primitive existed → [github.com/delta-exchange/delta-exchange-mcp/issues](https://github.com/delta-exchange/delta-exchange-mcp/issues) Please redact `api_key` / `api_secret` from any logs or screenshots before attaching. ---
[MIT licence](https://github.com/delta-exchange/delta-exchange-mcp/blob/main/LICENSE) · [Source](https://github.com/delta-exchange/delta-exchange-mcp) · [Issues](https://github.com/delta-exchange/delta-exchange-mcp/issues) · [PyPI](https://pypi.org/project/delta-exchange-mcp/)
[beta-badge]: https://img.shields.io/badge/status-beta-orange?style=flat-square [pypi-version-badge]: https://img.shields.io/pypi/v/delta-exchange-mcp?style=flat-square [pypi-version-link]: https://pypi.org/project/delta-exchange-mcp/ [cursor-badge]: https://img.shields.io/badge/Cursor-Add_Server-0098FF?style=for-the-badge&logo=cursor&logoColor=white [cursor-link]: https://cursor.com/install-mcp?name=delta-exchange-mcp&config=eyJjb21tYW5kIjoidXZ4IiwiYXJncyI6WyJkZWx0YS1leGNoYW5nZS1tY3AiXSwiZW52Ijp7IkRFTFRBX01DUF9FTlYiOiJpbmRpYV9wcm9kIiwiREVMVEFfQVBJX0tFWSI6IiIsIkRFTFRBX0FQSV9TRUNSRVQiOiIifX0%3D [vs-code-badge]: https://img.shields.io/badge/VS_Code-Install_Server-0098FF?style=for-the-badge&logo=githubcopilot&logoColor=white [vs-code-link]: https://insiders.vscode.dev/redirect/mcp/install?name=delta-exchange-mcp&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22delta-exchange-mcp%22%5D%2C%22env%22%3A%7B%22DELTA_MCP_ENV%22%3A%22%24%7Binput%3Adelta-env%7D%22%2C%22DELTA_API_KEY%22%3A%22%24%7Binput%3Adelta-api-key%7D%22%2C%22DELTA_API_SECRET%22%3A%22%24%7Binput%3Adelta-api-secret%7D%22%7D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22delta-api-key%22%2C%22description%22%3A%22Delta%20API%20key%20%28leave%20empty%20for%20market%20data%20only%29%22%2C%22password%22%3Atrue%7D%2C%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22delta-api-secret%22%2C%22description%22%3A%22Delta%20API%20secret%20%28must%20match%20the%20key%29%22%2C%22password%22%3Atrue%7D%2C%7B%22type%22%3A%22pickString%22%2C%22id%22%3A%22delta-env%22%2C%22description%22%3A%22Delta%20Exchange%20environment%22%2C%22options%22%3A%5B%22india_prod%22%2C%22india_testnet%22%5D%2C%22default%22%3A%22india_prod%22%7D%5D [vs-code-insiders-badge]: https://img.shields.io/badge/VS_Code_Insiders-Install_Server-24bfa5?style=for-the-badge&logo=githubcopilot&logoColor=white [vs-code-insiders-link]: https://insiders.vscode.dev/redirect/mcp/install?name=delta-exchange-mcp&config=%7B%22type%22%3A%22stdio%22%2C%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22delta-exchange-mcp%22%5D%2C%22env%22%3A%7B%22DELTA_MCP_ENV%22%3A%22%24%7Binput%3Adelta-env%7D%22%2C%22DELTA_API_KEY%22%3A%22%24%7Binput%3Adelta-api-key%7D%22%2C%22DELTA_API_SECRET%22%3A%22%24%7Binput%3Adelta-api-secret%7D%22%7D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22delta-api-key%22%2C%22description%22%3A%22Delta%20API%20key%20%28leave%20empty%20for%20market%20data%20only%29%22%2C%22password%22%3Atrue%7D%2C%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22delta-api-secret%22%2C%22description%22%3A%22Delta%20API%20secret%20%28must%20match%20the%20key%29%22%2C%22password%22%3Atrue%7D%2C%7B%22type%22%3A%22pickString%22%2C%22id%22%3A%22delta-env%22%2C%22description%22%3A%22Delta%20Exchange%20environment%22%2C%22options%22%3A%5B%22india_prod%22%2C%22india_testnet%22%5D%2C%22default%22%3A%22india_prod%22%7D%5D&quality=insiders [claude-desktop-badge]: https://img.shields.io/badge/Claude_Desktop-Download_bundle-D97757?style=for-the-badge&logo=claude&logoColor=white [claude-desktop-link]: https://github.com/delta-exchange/delta-exchange-mcp/releases/latest/download/delta-exchange-mcp.mcpb [claude-code-jump-badge]: https://img.shields.io/badge/Claude_Code-setup_below-6e7681?style=for-the-badge&logo=claude&logoColor=white [claude-code-jump-link]: #claude-code [codex-jump-badge]: https://img.shields.io/badge/Codex-setup_below-6e7681?style=for-the-badge&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0id2hpdGUiPjxwYXRoIGQ9Ik0yMi4yODIgOS44MjFhNS45ODUgNS45ODUgMCAwIDAtLjUxNi00LjkxIDYuMDQ2IDYuMDQ2IDAgMCAwLTYuNTEtMi45QTYuMDY1IDYuMDY1IDAgMCAwIDQuOTgxIDQuMThhNS45ODUgNS45ODUgMCAwIDAtMy45OTggMi45IDYuMDQ2IDYuMDQ2IDAgMCAwIC43NDMgNy4wOTcgNS45OCA1Ljk4IDAgMCAwIC41MSA0LjkxMSA2LjA1MSA2LjA1MSAwIDAgMCA2LjUxNSAyLjlBNS45ODUgNS45ODUgMCAwIDAgMTMuMjYgMjRhNi4wNTYgNi4wNTYgMCAwIDAgNS43NzItNC4yMDYgNS45OSA1Ljk5IDAgMCAwIDMuOTk3LTIuOSA2LjA1NiA2LjA1NiAwIDAgMC0uNzQ3LTcuMDczek0xMy4yNiAyMi40M2E0LjQ3NiA0LjQ3NiAwIDAgMS0yLjg3Ni0xLjA0bC4xNDEtLjA4MSA0Ljc3OS0yLjc1OGEuNzk1Ljc5NSAwIDAgMCAuMzkyLS42ODF2LTYuNzM3bDIuMDIgMS4xNjhhLjA3MS4wNzEgMCAwIDEgLjAzOC4wNTJ2NS41ODNhNC41MDQgNC41MDQgMCAwIDEtNC40OTQgNC40OTR6TTMuNiAxOC4zMDRhNC40NyA0LjQ3IDAgMCAxLS41MzUtMy4wMTRsLjE0Mi4wODUgNC43ODMgMi43NTlhLjc3MS43NzEgMCAwIDAgLjc4IDBsNS44NDMtMy4zNjl2Mi4zMzJhLjA4LjA4IDAgMCAxLS4wMzMuMDYyTDkuNzQgMTkuOTVhNC41IDQuNSAwIDAgMS02LjE0LTEuNjQ2ek0yLjM0IDcuODk2YTQuNDg1IDQuNDg1IDAgMCAxIDIuMzY2LTEuOTczVjExLjZhLjc2Ni43NjYgMCAwIDAgLjM4OC42NzdsNS44MTUgMy4zNTQtMi4wMiAxLjE2OGEuMDc2LjA3NiAwIDAgMS0uMDcxIDBsLTQuODMtMi43ODZBNC41MDQgNC41MDQgMCAwIDEgMi4zNCA3Ljg3MnptMTYuNTk3IDMuODU1LTUuODMzLTMuMzg3TDE1LjExOSA3LjJhLjA3Ni4wNzYgMCAwIDEgLjA3MSAwbDQuODMgMi43OTFhNC40OTQgNC40OTQgMCAwIDEtLjY3NiA4LjEwNXYtNS42NzhhLjc5Ljc5IDAgMCAwLS40MDctLjY2N3ptMi4wMS0zLjAyMy0uMTQxLS4wODUtNC43NzQtMi43ODJhLjc3Ni43NzYgMCAwIDAtLjc4NSAwTDkuNDA5IDkuMjNWNi44OTdhLjA2Ni4wNjYgMCAwIDEgLjAyOC0uMDYxbDQuODMtMi43ODdhNC41IDQuNSAwIDAgMSA2LjY4IDQuNjZ6TTguMzA1IDEyLjg2M2wtMi4wMi0xLjE2NGEuMDguMDggMCAwIDEtLjAzOC0uMDU3VjYuMDc1YTQuNSA0LjUgMCAwIDEgNy4zNzUtMy40NTNsLS4xNDIuMDhMOC43IDUuNDZhLjc5NS43OTUgMCAwIDAtLjM5My42ODF6bTEuMDk3LTIuMzY1IDIuNjAyLTEuNSAyLjYwNyAxLjV2Mi45OTlsLTIuNTk3IDEuNS0yLjYwNy0xLjV6Ii8%2BPC9zdmc%2B [codex-jump-link]: #codex [windsurf-jump-badge]: https://img.shields.io/badge/Windsurf-setup_below-6e7681?style=for-the-badge&logo=windsurf&logoColor=white [windsurf-jump-link]: #windsurf [zed-jump-badge]: https://img.shields.io/badge/Zed-setup_below-6e7681?style=for-the-badge&logo=zedindustries&logoColor=white [zed-jump-link]: #zed