# OpenMarket chart MCP URL: https://mcp.openmarket.xyz/ Transport: Streamable HTTP ## Connect (do this first) The user signs in once in the browser and picks the access level there: "Read only" or "Read and control charts" ("Read, control charts and trade" where agent trading is offered), plus the "Alerts and watchlists" box, ticked by default. The sentence you were given may end with "to chart ": that is the chart the user is looking at right now. Keep the id for the first step after connecting. ### Agents with a shell (Claude Code, Codex, Cursor): add the connector yourself Run the command for your client. Do not ask the user for a token. Claude Code: claude mcp add --scope user --transport http openmarket https://mcp.openmarket.xyz/ --scope user adds the connector for every folder, not only the one it was added in. The first use asks the user to authenticate (/mcp, then Authenticate); the browser opens once. Codex: codex mcp add openmarket --url https://mcp.openmarket.xyz/ The add detects the OAuth sign-in and opens the browser. If the sign-in does not complete, run: codex mcp login openmarket Cursor: add this to ~/.cursor/mcp.json (every project) or .cursor/mcp.json (this project): { "mcpServers": { "openmarket": { "url": "https://mcp.openmarket.xyz/" } } } ### Chat apps (claude.ai, Claude Desktop, ChatGPT): give the user these steps A chat app cannot add a connector itself. Give the user the steps for their app with the URL. Claude (claude.ai or Claude Desktop): Customize > Connectors, click +, then Add custom connector, paste https://mcp.openmarket.xyz/, click Add, and sign in to OpenMarket when asked. In a chat, turn it on from + > Connectors. Free plans allow one custom connector. On Team and Enterprise plans an Owner adds it first, in Organization settings > Connectors; members then click Connect under Customize > Connectors. ChatGPT (on the web; Plus, Pro, Business, Enterprise and Edu): Settings > Security and login, turn on Developer mode. Then open Plugins, click +, name it OpenMarket, paste https://mcp.openmarket.xyz/ under Connection, create it, and sign in to OpenMarket when asked. In a chat, choose Developer mode from the + menu and select OpenMarket. ChatGPT also connects at https://mcp.openmarket.xyz/chatgpt, which serves every tool here but the trade tools. Other clients: add https://mcp.openmarket.xyz/ as a remote MCP server (connector) and follow the sign-in prompt. Protected resource: https://mcp.openmarket.xyz/.well-known/oauth-protected-resource Authorization server: https://mcp.openmarket.xyz/.well-known/oauth-authorization-server ## After connecting 1. If the sentence named a chart, call chart_workspace_select with that workspaceId first. The active workspace is only the last one any agent used with this key, so without a named chart call chart_list and ask the user which chart they have open; never assume. 2. Call chart_status with {} to check the connection and the active workspace. 3. Call chart_refresh with {} and tell the user which chart you see: symbol, timeframe, indicators. 4. Offer one small visible change and wait for a yes (add an indicator, switch the timeframe). 5. Make it, then say what changed so the user can see it on their chart. Read-only access can inspect charts; chart changes require mcp:chart. ## Symbols and scratch charts enum: the exact values the market tools take; domain "exchange_id" lists every venue served here with what it lists (HYPERLIQUID is Hyperliquid spot, HYPERLIQUID_FUTURES its perpetuals). Look a venue up instead of guessing it. symbol_resolve: run it before chart_symbol whenever you are unsure of a venue or ticker. It answers the exact exchange and symbol the chart lists (bound), or named candidates, never a guess. directory_unavailable means the directory could not be read right now: find the listing with markets (symbolFilter set to the ticker) and pass a row's exchange and rawSymbol to chart_symbol. Venues: US stocks are POLYGON with the symbol as AAPL/USD; chart_symbol and chart_grid map listing venues like NASDAQ or NYSE to POLYGON for you. chart_symbol checks the pair against the chart's symbol directory before applying it. The directory carries only the top venues of each asset, so it refuses unknown_market (up to 5 candidates, nothing changed) only when it can prove the pair wrong: a bare ticker or a misspelled symbol on an exchange that lists the asset another way. Show the user the candidates, or look the listing up the way the refusal's hint says (markets with symbolFilter while the directory cannot be read); never retry the same pair. A pair the directory does not carry, or any pair while it cannot be read, is looked up in the venue's own listing (one markets read): a symbol the venue lists is applied, one it does not list is refused unknown_market with the venue's nearest rows as candidates, and a venue whose listing is not read here (POLYGON, CME, FX) or a failed read applies the pair with the warning unverified_market, which names the check that could not vouch. A chart-UI alias (BINANCE.F) and a venue this endpoint does not chart are refused with the nearest venue ids. chart_create and watchlist_add_symbols check their markets the same way. Passing transformations outright always applies the pair. After the change lands, chart_symbol returns load: state loaded (with rowCount), empty, error or unknown (no tab was watching, or it timed out). Only loaded means the pane shows data; empty or error also carries the empty_load warning: say so, never describe the chart as showing the market. Scratch charts: chart_create with scratch: true makes a temporary chart for a bare "show me BTC". A scratch chart expires 48 hours after the last agent use, at most 30 days after creation; chart_keep makes it permanent. ## Reading the chart's numbers (mcp:read) chart_read: the numbers on the chart the user has open: symbol, timeframe, last price, the high, low and change over the bars on screen, and every indicator's latest value. Prefer it over chart_screenshot for any price or indicator-value question; the screenshot is for how the chart looks. bars: pass bars (up to 300) only when you need per-candle values (candles plus each indicator's value per bar); every bar costs tokens. chartIndex: picks a pane in a multi-chart layout; omit it for the active pane. Tab: the user's open chart tab answers the read, so it must be open on the selected workspace. no_tab: the answer may name the workspace(s) this account has a chart tab open on; select one with chart_workspace_select and call again, or ask the user to open that chart, or read the market with metric_get, points or markets, which need no tab. expired: ask them to refresh the tab. draining, no_data, relay_unavailable: retry shortly. rate: 60 reads a minute per key. exchange_license: this market's data can't be shared with agents (an exchange license, decided in the tab). Chart changes, drawings and indicators still work; withheld lists the indicators kept back for the same reason. ## Market data without a tab (mcp:read) metric_get (indicator and feed values for one market), points (candles, open interest, funding, liquidations), markets (listings, last price, 24h change), metric_screen and market_screen read market data on the user's key with no chart tab open. Use them when chart_read answers no_tab, or when the question is about a market rather than the chart on screen. A points candle answer carries each bar's open time as t and the newest bar's last trade time as summary.last_trade_at. Limits: the Free plan's data rate is 10 weight per minute, and Plus allows a higher rate. Candle history: 364 days on Plus, 719 hours (just under 30 days) on Free, and 167 hours (just under 7 days) on a key issued before 2026-10-12, until the agent reconnects. A read over the rate answers rate_limited with the wait; a longer window is trimmed to the plan's history and history_note says so. ## Token fallback (scripts, CI, clients without a browser) Token: Create an agent token at https://openmarket.xyz/chart/console/agents. Access: Choose read for inspection, chart for chart changes, or trade for execution through your tab. Scopes: mcp:read; mcp:read mcp:chart; mcp:read mcp:chart mcp:trade. Orders: mcp:trade adds order_place, order_cancel, order_modify, account_positions, account_orders, account_balance, account_fills and market_quote. Alerts: the Alerts and watchlists add-on (mcp:alerts, on top of any level) adds the alert_* and watchlist_* tools. Keep the token in your local client configuration. Never paste it into a chat or commit it. Replace locally in the commands below. Claude Code: claude mcp add --scope user --transport http openmarket https://mcp.openmarket.xyz/ --header "Authorization: Bearer " Codex: Set OM_MCP_TOKEN in the environment that starts Codex, then run: codex mcp add openmarket --url https://mcp.openmarket.xyz/ --bearer-token-env-var OM_MCP_TOKEN Cursor: cursor --add-mcp '{"name":"openmarket","type":"http","url":"https://mcp.openmarket.xyz/","headers":{"Authorization":"Bearer "}}' Cursor mcp.json: { "mcpServers": { "openmarket": { "url": "https://mcp.openmarket.xyz/", "headers": { "Authorization": "Bearer " } } } } ## Alerts and watchlists (mcp:alerts) Tools: alert_create, alert_list, alert_update, alert_pause, alert_resume, alert_delete, alert_history; watchlist_list, watchlist_get, watchlist_create, watchlist_update, watchlist_delete, watchlist_add_symbols, watchlist_remove_symbols. Delivery: alerts fire in the user's OpenMarket notifications (toast, optional email), whether or not a chart is open. Limits: price and market-series alerts Free 200, Plus 500; indicator alerts Free 5, Plus 50; 50 watchlists of 250 symbols each. Watchlist refs are EXCHANGE:SYMBOL off a markets row or symbol_resolve (HYPERLIQUID_FUTURES:SOL for a Hyperliquid perp; HYPERLIQUID alone is the spot book); watchlist_add_symbols checks every ref against the symbol directory and the venue's listing and answers unknown_market with details.unknown[].candidates when one names no listing. Indicator alerts: source rsi, ema, sma, macd or bollinger_bands with params (e.g. {"period": 14}); price_vs_ema / price_vs_sma is price minus the average, so "price crosses above EMA(200)" is source price_vs_ema, params {"period": 200}, condition cross_up, value 0. alert_create refuses before sending: a venue outside enum's exchange_id (POLYGON is accepted for US stocks, price and market series only), a multi-series source without output, an output the source lacks, params the source does not take, a derivatives series on a spot venue, a symbol the venue does not list (unknown_market with candidates) and a past expires_at. A created alert whose status is not armed carries a not_armed warning: it does not fire yet, so never tell the user it is set. scope_insufficient (needed mcp:alerts): this sign-in did not include alerts. Ask the user to add the connector again and tick "Alerts and watchlists" on the sign-in page; a token from the Agents page with that add-on also works. ## Execution through the tab (mcp:trade) Consent: Orders are placed by the user's own browser tab inside limits the user set there. Arm in the tab: Open Wallet > Agent trading and arm this agent for the session. Recovery: no_arm means the user must open Wallet > Agent trading in the tab and arm this agent. Reads: The five account/quote tools need an open owner tab but do not need an arm. Scope: A legacy unscoped key has read and chart access only, never trade access. scope_insufficient (needed mcp:trade): this sign-in did not include trading. Ask the user to add the connector again and pick "Read, control charts and trade" on the sign-in page; a Trading access token from the Agents page also works. Idempotency: Pass idempotency_key on writes (1-64 characters: A-Z, a-z, 0-9, _, ., :, -). Retry: Reuse the same key for the same request; the tab deduplicates it. Without one, save request_id and reuse it as idempotency_key. no_workspace: Select a workspace with chart_workspace_select using a token with mcp:chart. relay_unavailable: The chart service could not be reached; the order was not sent. relay_uncertain: The order may still have executed. Read account_orders before retrying with the same idempotency_key. Tab refusals include account_unwatched, invalid_request, and envelope:daily_ceiling (the daily limit the user set in the tab). Report the tab's status and reason verbatim, including future reason codes. Status meanings: submitted: Accepted by the venue, resting or working. filled: The venue's answer already carried a fill. rejected: The venue or user said no; report reason. blocked: The tab did not sign; report reason. dry_run: Evaluated and recorded, nothing sent. pending_confirm: The user has a dialog open; call again with the same idempotency_key to learn the outcome. error: Transport or uncertain; read account_orders before retrying.