MCP tools reference
Chartnaut's MCP server at https://api.chartnaut.com/v1/mcp offers 15 tools, 3 prompts and the scripting reference as resources. This page lists each one with every input, its default and limits, what it returns, the API endpoints behind it and what it costs. You rarely call these yourself: the AI app picks them. Read this page to know what the app can do, or to build your own MCP client.
How the tools work
Each tool call is served as one or more ordinary API requests, made as you with the connection's token or API key. Everything the API enforces applies: scopes, your plan's API limits, heavy calls, plan caps and ownership. A tool can do nothing the endpoints behind it cannot. How the MCP server works follows one call through.
Inputs are checked first. A malformed ref, slug, run id or
kindis refused withError invalid_requestbefore any request is made, and costs nothing.Requests a minute. Each API request a tool makes counts once. Connecting and listing the tools count nothing. Limits and cost has the table.
Scopes. Each tool below names the scope it needs. Permissions and connected apps
Waiting. No tool holds for more than 25 seconds. A run still going after that comes back with its id and a
next_step, and the app asks again withget_run.Next steps. Run and collection answers carry a
next_stepfield that tells the model which tool to call next, with the arguments filled in.Untrusted text. Names, descriptions, tags and categories of other people's scripts come back inside
untrusted_author_text, with a note telling the model to treat them as data. Your own scripts and Chartnaut's built-ins are returned as they are.Output. Every result is one text item: compact JSON, or markdown for doc pages, at most 40 KB. Output limits
Tools at a glance
Tool | Does | Scope | Requests | Changes your account |
|---|---|---|---|---|
Finds scripting reference topics |
| 1 | No | |
Reads one topic |
| 1 | No | |
Finds scripts you can run |
| 1 | No | |
Settings, outputs and events of a library script |
| 1 | No | |
Lists your scripts |
| 1 | No | |
Reads one of your scripts, source included |
| 1 | No | |
Checks a script without saving it |
| 1, heavy | No | |
Creates a script or saves a version |
| 1 or 2, one heavy | Yes | |
Runs a saved or inline script |
| 2, one heavy | Yes, starts a run | |
A run's status, failure and summary |
| 1 | No | |
What a run produced |
| 1 to 4 | No | |
A definition's stored events |
| 1 to 4 | No | |
Runs a definition over a window and stores its events |
| 1 plus 1 every 3 s, one heavy | Yes | |
Instruments and the dates your plan reaches |
| 1 | No | |
Your plan, scopes and usage |
| 2 | No |
Tools that change nothing carry MCP's read-only hint, which some apps use to run them without asking you first. The three that change your account are marked as not destructive: none of them deletes or overwrites anything.
Docs
search_docs
Finds topics in the scripting reference. Each word of the query is matched, ignoring case, against every topic's id and title; topics that match more words come first. With an empty query, it lists the top-level topics.
Input | Type | Default | Description |
|---|---|---|---|
| string | Empty | Words to look for, such as |
Returns topics, up to 25, each with topic (the id for get_doc) and title, and a hint. When nothing matches, the hint says to try other words or an empty query.
Calls List doc topics. Costs 1 request.
get_doc
Reads one topic as markdown, the same page chartnaut docs <topic> prints.
Input | Type | Default | Description |
|---|---|---|---|
| string | Required | A topic id from |
Returns the page as markdown. A page over 40 KB is cut, with a line at the end saying so.
Calls Get a doc topic. Costs 1 request. Errors not_found for an unknown topic, with advice to use search_docs.
Library
search_library
Searches every script you can run: your own, Chartnaut's built-ins and other people's public ones. Never returns source.
Input | Type | Default | Description |
|---|---|---|---|
| string | None | Search words. Every word must match the name, slug, description, tags, category or author |
| string | Any |
|
| string |
|
|
| string | Any | A username, |
| integer | 20 | 1 to 100. Higher values are treated as 100 |
| string | None |
|
Returns scripts, each with ref (usable in run_script and describe_script), kind, name, description (cut at 300 characters), author, official, owned, installed, latest_version, adoptions, tags and category, and next_cursor. For other people's scripts, name, description, tags and category sit inside untrusted_author_text.
Calls Search the library. Costs 1 request.
describe_script
Describes one library script: its settings, outputs or events, and dependencies. Never source, even for your own scripts; use get_script for that.
Input | Type | Default | Description |
|---|---|---|---|
| string | Required |
|
| string | None | Only when one of your studies shares the slug with an indicator or definition |
Returns the Library script object without files, with other people's text inside untrusted_author_text.
Calls Get a library script. Costs 1 request. Errors not_found; conflict when the slug is ambiguous and kind is missing.
Your scripts
list_my_scripts
Lists your own indicators, definitions and studies, without source.
Input | Type | Default | Description |
|---|---|---|---|
| string | Any |
|
| string | None | Matches part of the slug, name or description |
| integer | 50 | 1 to 200. Higher values are treated as 200 |
| string | None |
|
Returns scripts, each with slug, kind, name, description, visibility, latest_version and updated_at, and next_cursor.
Calls List scripts. Costs 1 request.
get_script
Reads one of your own scripts. A ref with a / is refused: other people's scripts are read with describe_script, without source.
Input | Type | Default | Description |
|---|---|---|---|
| string | Required |
|
| boolean |
| Return the files. Needed before editing |
| string | None | Only when one of your studies shares the slug |
Returns the Script object: its interface, dependencies and latest_version, and with include_source its files, each with path, code and entry. When the whole answer would pass 40 KB, files lists each file's path, entry and size in bytes with no code, and _truncated tells the model not to save over the script from a partial copy.
Calls Get a script. Costs 1 request. Errors not_found, conflict.
validate_script
Lints and resolves a script without saving or running it. It is a heavy call, and uses no run.
Input | Type | Default | Description |
|---|---|---|---|
| string | Required |
|
| array of file | Required | The complete file set. Each file has |
Returns ok, the diagnostics with file, line and severity, and the settings, outputs or events the script declares.
Calls Validate a script. Costs 1 request, heavy.
save_script
Saves a script. Without base_version it creates a new one, and refuses if you already have a script with that slug, naming its latest version and telling the model to read it and save over it with base_version instead. With base_version it saves a new version over that one; if the script changed since, for example in the app, it returns version_conflict and saves nothing. An invalid script is never saved.
Input | Type | Default | Description |
|---|---|---|---|
| string | Required |
|
| string | Required | 2 to 63 lowercase letters, digits and dashes, starting with a letter or digit. No |
| array of file | Required | The complete file set. Files left out are deleted from the new version |
| integer | None | The version the edit started from, |
| string | None | Display name |
| string | None | One or two sentences |
| string | None | What changed, in one line |
Returns the saved Script without its files, with saved: true.
Calls to create: Get a script to check the slug is free, then Create a script. To save a version: Save a script version, then Update script details when name or description is given. Costs 2 requests to create; 1 to save a version, 2 with a new name or description. One of them is heavy. Scopes scripts:write; creating also needs scripts:read, for the slug check.
Errors conflict when the slug is taken; version_conflict; script_invalid with the diagnostics; plan_limit past your plan's cap on scripts of that kind.
run_script
Runs a saved script, or inline source without saving it, on one instrument, timeframe and window. Studies run by ref only, so a new study is saved first.
Input | Type | Default | Description |
|---|---|---|---|
| string | None | A saved ref: |
| string | None | With |
| array of file | None | Inline source to run without saving, in the shape |
| string | Required | A symbol such as |
| string | Required |
|
| object | Required | Exactly one of: |
| object | Defaults | Setting overrides by id. Settings left out keep their defaults |
| object | None | Study only. Keeps events whose payload matches these values |
Returns the Run: id, status, progress, failure with its diagnostics when it failed, the summary when it succeeded, and the first 20 console lines with a console_note giving the total. next_step says to call get_results when it succeeded, get_run when it is still queued or running, and to read failure when it failed.
Calls Create a run with wait set to 0, so starting never holds a heavy-call place while the run executes, then, while the run is not done, Get a run with wait set to 25. If that wait is refused, the tool returns the run as it started and the app polls with get_run. Costs 2 requests, 1 when the run is done as it starts. The start is heavy and the wait is a long poll. The run takes one of your runs at once. Scopes runs:write to start; the wait also needs scripts:read.
Errors unknown_instrument, unsupported_timeframe, out_of_coverage, script_invalid, busy when your run queue is full, and invalid_request for an inline study or a missing window.
get_run
Returns a run's status, progress, failure with its diagnostics, summary and the first 20 console lines, with a next_step.
Input | Type | Default | Description |
|---|---|---|---|
| string | Required | The id |
| integer | 0 | Hold up to this many seconds, at most 25, for the run to finish |
Returns the same shape as run_script.
Calls Get a run. Costs 1 request, a long poll when wait_seconds is set. Past your plan's long polls at once, it answers straight away with the run as it is.
get_results
Reads what a succeeded run produced: an indicator's output series, a definition's events, or a study's result blocks.
Input | Type | Default | Description |
|---|---|---|---|
| string | Required | A succeeded run's id |
| string | All | Indicator. Comma list of output ids |
| string | All | Definition. Only this declared event |
| string | None | Study. Comma list of result keys to return in full. Large blocks are left out unless named here |
| string | None | Only points or events at or after this time, RFC 3339 |
| string | None | Only points or events before this time, RFC 3339 |
| integer | 300 | Points per output, or events, per page. Up to 50,000 |
| string | None |
|
Returns the run results for the run's kind, with next_cursor. When a page of points or events is over 40 KB, the tool asks again with a smaller limit, up to three times, and adds limit_used and a page_note with the cursor for the next page. Study results are not re-paged; a study answer over 40 KB is cut with a _truncated note, so name the keys you want.
Calls Get run results. Costs 1 request, up to 4 when it shrinks the page. Errors run_not_finished for a run still going, failed or cancelled; not_found with 410 once results have expired after 7 days.
Definition events
definition_events
Reads the events one of your definitions has stored from running over history, across instruments, timeframes and windows. With summary, it returns the totals instead.
Input | Type | Default | Description |
|---|---|---|---|
| string | Required | Your definition's slug |
| boolean |
| Return totals per instrument and timeframe, the runs still in progress and any that failed, instead of events. Only |
| string | Any | Only this instrument |
| string | Any | Only this timeframe, one of |
| string | Any | Only this declared event |
| string | None | Events starting at or after this time, RFC 3339 |
| string | None | Events ending at or before this time, RFC 3339 |
| integer | Any | Only events stored by this version |
| array | None | Payload filters, all of which must match. Each has |
| integer | 100 | 1 to 1,000. Lowered to fit 40 KB |
| string | None |
|
Returns a page of events with next_cursor, and limit_used and page_note when the page was shrunk. With summary, the summary with collecting for runs in progress.
Calls List events, or Summarise events with summary. Costs 1 request, up to 4 when it shrinks the page.
run_definition_over_history
Runs one of your definitions over history on a window and stores its events, so studies and definition_events can read them. Only the part not already stored runs. It waits for the work to finish, checking every 3 seconds.
Input | Type | Default | Description |
|---|---|---|---|
| string | Required | Your definition's slug |
| string | Required | A symbol such as |
| string | Required |
|
| object | Required | The same shape as |
| integer | Latest | Definition version |
| integer | 20 | Wait up to this many seconds, at most 25. 0 means the default |
Returns collect, the answer from starting; status, done or collecting; summary, the latest summary while it waited; and next_step. When nothing was left to run, it answers done at once. When it is still collecting, next_step says to check later with definition_events and summary.
Calls Run a definition over history, then Summarise events every 3 seconds until nothing is in progress or the wait ends. Costs 1 request to start, heavy, plus 1 per check: at most 8 in all with the default wait, 10 at 25 seconds. It takes no run slot. Stored events count toward your plan's definition events limit. Scopes runs:write; the checks also need scripts:read, and without it the tool answers collecting straight after starting.
Catalogue and account
list_instruments
Finds instruments to run on, with the dates your plan can reach on each.
Input | Type | Default | Description |
|---|---|---|---|
| string | None | Matches the symbol, short symbol and name, such as |
| string | Any | Such as |
| integer | 25 | 1 to 100. Higher values are treated as 100 |
| string | None |
|
Returns instruments, each with symbol, short, name, category, order_flow and coverage (start and end your plan reaches), and next_cursor. The instrument object
Calls Search instruments. Costs 1 request.
account
Returns who the connection acts as and what the plan allows. It takes no inputs.
Returns me, with your user name, plan and token: the connection's name, scopes and expires_at. For a browser sign-in, the name is the app's and the expiry is the current access token's, within the hour. usage holds the plan, this month's period, compute_units used, caps for indicators, definitions, studies, events and concurrent_runs, each with used and limit, history_start, memory_bars, and api_limits with requests_per_minute, concurrent_heavy and concurrent_waits.
Calls Get the current key and Get usage. Costs 2 requests.
Prompts
Prompts are ready-made requests the app can offer you, often as a menu or a slash command. Each one steers the model through the right tools in order. Fetching a prompt costs nothing; the tool calls it leads to cost as usual. What you can ask shows them in use.
Prompt | Arguments | What it asks for |
|---|---|---|
|
| Check the library for an existing one, read the reference, validate until clean, try it on 30 days of 1-hour bars without saving, and ask before saving |
|
| Turn the idea into testable conditions, write a definition, run it over the last year, report how often it fired and what followed, with the caveats, and offer to save it and run it over more history |
|
| Explain a failure and propose a fix, or explain the results without inventing numbers, then say what to try next |
Resources
The scripting reference is also available as resources, for apps that let you attach them to a chat:
URI | Contents |
|---|---|
| Every topic, as a markdown list of links, indented by depth |
| One topic as markdown, such as |
Reading a resource makes the same API request as search_docs or get_doc, and counts the same way. An unknown topic answers MCP's resource-not-found error.
Output limits
A tool result is at most 40 KB of text, so one answer never floods the model's context.
Lists come in pages. Pass
next_cursorback ascursorfor the next one.Results and events lower the page size until the answer fits, and say so with
limit_usedand apage_note.Anything else over 40 KB is cut: the longest lists are shortened first, then the longest text, and a
_truncatedfield says what was cut and how to ask for less.Source is never cut, so a model never saves over a script from a partial copy.
get_scriptreturns no code at all when the answer would pass 40 KB.Doc pages over 40 KB end with a note that the rest was cut.
Errors carry the first 30 diagnostics, with a count of the rest.
Library descriptions are cut at 300 characters, and run console output at 20 lines.
One MCP request can carry up to 3 MB, enough for a script's full 2 MB of files.
Errors
A refused tool call comes back as a result with isError: true and a text the model can read: Error <code>: with the API's message, then advice on what to do next, then any details and diagnostics. The codes are the API's own, listed in Errors and exit codes.
Code | What the model is told |
|---|---|
| A limit of your plan. Tell you, and do not retry |
| The connection lacks the permission. Tell you to reconnect and allow it, or use a key with that scope |
| Too many heavy calls or runs at once. Wait for the |
| Past your requests a minute. Wait the |
| The script changed since |
| The slug is already one of your scripts, or it names more than one of your scripts: pass |
| Nothing was saved or run. Fix the diagnostics, which follow in the error |
| Check the ref or id: your own scripts with |
| Call |
| Find the symbol and its dates with |
| The timeframes are |
| Another of your scripts depends on this one |
| An input is malformed. The message names it |
| The connection was refused. You need to connect again |
| A Chartnaut server error. Retry once, then tell you |
Before a tool runs at all, the MCP endpoint itself answers 401 with a WWW-Authenticate header when the token is missing, expired or revoked, which starts the app's sign-in; 403 forbidden for a browser request from a site Chartnaut does not recognise; and 403 plan_limit on Free. Call the MCP server has the details, and Troubleshooting MCP what to do about each.
