MCP Server (Strategy)
Connect an AI agent directly to the Strategy Storage API via the Model Context Protocol — save, fetch, and manage Strategy DSL objects as standalone assets, independent of any backtest or live subscription.
#Overview
emidlabs-strategy-mcp is a hosted Model Context Protocol (MCP) server that wraps the Strategy Storage API as agent-callable tools — a strategy saved here gets a stable id you can reference later, or pass its definition straight into emidlabs-backtest-mcp's submit_backtest or emidlabs-live-mcp's create_subscription.
Endpoint: https://mcp.strategy.emidlabs.com/mcp (Streamable HTTP transport).
riskManagement close a position, does entryFeePct apply) depends entirely on where you submit it afterward — submit_backtest or create_subscription, not this server.#Connecting an agent
Pick your client
Claude and ChatGPT discover this server automatically over OAuth. Cursor and most coding agents instead want the raw JSON config block below.
Add the connector
Add the server to your MCP client's configuration. The exact file differs by client, but the shape is the same everywhere — a name and a URL:
{
"mcpServers": {
"emidlabs-strategy": {
"url": "https://mcp.strategy.emidlabs.com/mcp"
}
}
}/mcp path — https://mcp.strategy.emidlabs.com/mcp, not just mcp.strategy.emidlabs.com. Dropping the path is the most common reason a connector fails to register, and the resulting error rarely makes the real cause obvious.Authenticate
Three ways to authenticate, and you can combine more than one — the connector tries them in the order below:
| Method | How | Best for |
|---|---|---|
| OAuth login (recommended) | Just add the connector with no extra config. Claude/ChatGPT discover the login flow automatically and prompt you to sign in with your EmidLabs account — a dedicated API key is created for your account the first time and reused after that. | Personal Claude.ai / ChatGPT connectors. Nothing to copy, paste, or type — ever. |
| x-api-key header | Configure a specific EmidLabs API key once when adding the connector (e.g. Claude’s "custom header" / static_headers option) — attached automatically to every request from then on. | Org-managed connectors where an admin wants every member sharing one specific key instead of individual OAuth logins. |
| Tool argument | Pass an API key as strategyApiKey on each call — the agent is told the key directly (e.g. in conversation). | Coding agents, local/CLI use, or any client without connector-level auth support. |
#Tools
save_strategy
Saves a Strategy DSL object as a first-class, standalone asset — independent of any backtest or live subscription. Returns a stable id.
| Argument | Type | Description |
|---|---|---|
| strategyApiKey | string (optional) | Not needed if you connected via OAuth login or the x-api-key header is configured on this connector. |
| name | string | Human-readable name for this strategy. |
| description | string (optional) | Free-text notes about this strategy. |
| definition | object | The Strategy DSL object — see the strategy-dsl-spec resource below. |
| tags | string[] (optional) | Freeform labels for filtering later via list_strategies. |
| strategyBaseUrl | string (optional) | Defaults to the public production API. |
get_strategy
Fetches a saved strategy by id, including its full definition.
| Argument | Type | Description |
|---|---|---|
| strategyApiKey | string (optional) | Not needed if you connected via OAuth login or the x-api-key header is configured on this connector. |
| id | string | The id returned by save_strategy. |
| strategyBaseUrl | string (optional) | Defaults to the public production API. |
list_strategies
Lists saved strategies for this account, paginated, optionally filtered by tag and/or status. Each item includes the full definition — no separate fetch needed just to browse.
| Argument | Type | Description |
|---|---|---|
| strategyApiKey | string (optional) | Not needed if you connected via OAuth login or the x-api-key header is configured on this connector. |
| tag | string (optional) | Filter to strategies carrying this tag. |
| status | string (optional) | "Active" or "Archived". Defaults to Active-only when omitted. |
| page | integer (optional) | Page number, starting at 1. Defaults to 1. |
| pageSize | integer (optional) | Results per page, 1-100. Defaults to 20. |
| strategyBaseUrl | string (optional) | Defaults to the public production API. |
Omitting status returns Active strategies only — pass status: "Archived"explicitly to see ones you've archived.
update_strategy
Updates a saved strategy's fields. Only pass the fields you want to change — omitted fields keep their current value. Overwrites in place; there is no version history yet.
| Argument | Type | Description |
|---|---|---|
| strategyApiKey | string (optional) | Not needed if you connected via OAuth login or the x-api-key header is configured on this connector. |
| id | string | The id returned by save_strategy. |
| name | string (optional) | New name. Omit to leave unchanged. |
| description | string (optional) | New description. Omit to leave unchanged. |
| definition | object (optional) | New Strategy DSL object. Omit to leave unchanged. |
| tags | string[] (optional) | New tag list — replaces the existing tags entirely. Omit to leave unchanged. |
| strategyBaseUrl | string (optional) | Defaults to the public production API. |
archive_strategy
Archives a saved strategy — soft-delete, sets status to Archived, never hard-deletes. Archived strategies still exist and are still fetchable via get_strategy, they're just excluded from list_strategies's default listing.
| Argument | Type | Description |
|---|---|---|
| strategyApiKey | string (optional) | Not needed if you connected via OAuth login or the x-api-key header is configured on this connector. |
| id | string | The id returned by save_strategy. |
| strategyBaseUrl | string (optional) | Defaults to the public production API. |
#Resources
strategy-dsl-spec
A condensed, markdown reference for the exact Strategy DSL JSON shape expected by save_strategy's definition field (emidlabs://strategy-dsl-spec) — this is the canonical copy: emidlabs-strategy-api is the domain owner of what a Strategy is, so this server is the source of truth for how to build one.
inputs/conditions/scoresection — the part that's genuinely identical no matter where the strategy ends up — is fetched live from strategy-api's own GET /dsl-core-reference and cached for a few minutes, rather than hand-copied. The three MCP servers (backtest, live, and this one) each fetch the same core and splice it into their own local content, so that part can't drift out of sync between them.Reading this resource first is optional, not required — every field in save_strategy's own tool schema already documents its exact shape directly, since MCP clients don't reliably fetch a separate resource before generating a call.
#Rate limits
Two independent limits apply, and they surface differently on purpose so they're never confused for each other:
| Limit | Scope | What it protects | What you see |
|---|---|---|---|
| Strategy-api quota | Per API key | Your account’s real usage/billing limit | A 4xx from strategy-api, passed through as an MCP tool error. |
| MCP infra guard | Per IP/connection | This MCP process itself, against runaway loops or malformed floods | A 429 with a message explicitly identifying it as the MCP layer’s own guard, not your account quota. |
#Scope
This server only exposes strategy storage — saving, fetching, listing, updating, and archiving strategy definitions. It never submits a backtest or creates a live subscription itself (use emidlabs-backtest-mcp or emidlabs-live-mcp for that), and it does not expose any Console actions (creating or rotating API keys, changing billing plans, account management).