Skip to main content
Glama

BotSpot: AI Trading, Backtests and Bots

Save and manage your custom Python indicators

indicators
Destructive

Save, version, read, list and delete your own custom Python indicators (LumiBot Indicator classes). Before writing custom chart source, load the custom-chart-indicators reference. Use from lumibot.indicators import Indicator, InputSpec, OutputSpec (and Level when needed), the sandbox-supported API. If asked to change a chart before creating or adding an indicator, confirm the chart change before saving the indicator; then add the saved indicator to that same chart. action="create" saves version 1; action="update" with full source saves a new version and keeps old ones, so a bot pinned to a version keeps it; action="get" returns the code (newest, or a pinned version or revisionId); action="revisions" lists versions; action="delete" previews unless confirm is true. Indicators are private: only the owner can read or change the code. Only the signed-in person can use this tool.

Set "action" to choose the operation. Only send the fields listed for that action.

action="create": Save a new custom indicator

Required fields: name, source. Saves a new custom Python indicator (a LumiBot Indicator class) to the signed-in person's account as version 1. It starts private. Indicators are private: only the owner can read or change the code. Nobody else can read or edit it, including anyone it is shared with or sold to later. Use indicators(action="update") to save changes as a new version.

action="update": Save a new version of a custom indicator

Required fields: indicatorId. Saves changed source as a new version of one of the signed-in person's indicators. Old versions are kept unchanged, so a bot pinned to an older version keeps running it. Send the full source plus changeNotes. To only rename or change the description, leave source out (no new version is made). Indicators are private: only the owner can read or change the code. Nobody else can read or edit it, including anyone it is shared with or sold to later.

action="get": Read a custom indicator and its code

Required fields: indicatorId. Returns one of the signed-in person's indicators with its Python source: the newest version, or a pinned version by number or revision id. Source is returned to only the owner; any other id answers not found.

action="list": List your custom indicators

No other fields required. Lists the signed-in person's own custom indicators (name, id, newest version, visibility). Never shows code.

action="revisions": List the versions of a custom indicator

Required fields: indicatorId. Lists every saved version of one of the signed-in person's indicators, newest first, with what changed. Never shows code; read a version with indicators(action="get").

action="delete": Delete a custom indicator

Required fields: indicatorId. Deletes one of the signed-in person's indicators. Without confirm: true it only previews what will be deleted. Deletion is a soft delete: saved versions are kept and staff can restore them.

action="publish": List your indicator on the marketplace

Required fields: indicatorId. Lists one of your saved indicators on the BotSpot marketplace, or updates its listing. Visitors see what it draws on a live preview chart; buyers (anyone, when free) can add it to their charts. sourceVisibility "private" (default) keeps the code yours: buyers run it but never read it. "open" shows the code to everyone. pricingModel "free" (default) or "monthly" with priceAmountCents (100 to 1,000,000).

action="unpublish": Take your indicator off the marketplace

Required fields: listingId. Takes one of your indicator listings off the marketplace. The indicator itself stays saved.

action="marketplace": Browse indicators on the marketplace

No other fields required. Lists indicators on the BotSpot marketplace with their creator, price and link. creator filters to one creator by handle (as in botspot.trade/community/) or account id. Never returns code.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "action": "<action>"
    },
    "name": "indicators"
  }
}

Input Schema

NameRequiredDescriptionDefault
nameNoA short name the person will recognize. Used with action="create", action="update". Required for action="create".
queryNoUsed with action="marketplace".
titleNoThe listing title. Defaults to the indicator name. Used with action="publish".
actionYesWhich operation to run: "create", "update", "get", "list", "revisions", "delete", "publish", "unpublish", "marketplace". See the tool description for each one.
sourceNoThe full Python source of the indicator: a LumiBot Indicator class. Send the whole file, not a diff. Used with action="create", action="update". Required for action="create".
confirmNoSet true to delete after showing the preview. Used with action="delete".
creatorNoUsed with action="marketplace".
versionNoA version number to read. Used with action="get".
metadataNoOptional. What the indicator declares: settings (name, type, default, description), outputs, placement ("overlay" draws on the price chart, "pane" in its own pane) and dataNeeds. Used with action="create", action="update".
listingIdNoThe listing id from indicators(action="publish") or the marketplace. Used with action="unpublish". Required for action="unpublish".
revisionIdNoA revision id to read. Used with action="get".
changeNotesNoWhat changed in this version, in plain words. Used with action="create", action="update".
descriptionNoaction="create": What the indicator shows. | action="publish": What it shows and how to use it. Used with action="create", action="update", action="publish".
indicatorIdNoThe indicator id from indicators(action="list"). Used with action="update", action="get", action="revisions", action="delete", action="publish". Required for action="update", action="get", action="revisions", action="delete", action="publish".
pricingModelNoUsed with action="publish".
priceAmountCentsNoUsed with action="publish".
sourceVisibilityNoUsed with action="publish".

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed11 schema fields changed
    • changedInput schema / properties / action / description
      Previous value: -"Which operation to run: \"create\", \"update\", \"get\", \"list\", \"revisions\", \"delete\". See the tool description for each one."New value: +"Which operation to run: \"create\", \"update\", \"get\", \"list\", \"revisions\", \"delete\", \"publish\", \"unpublish\", \"marketplace\". See the tool description for each one."
    • changedInput schema / properties / action / enum
      Previous value: -[
      -  "create",
      -  "update",
      -  "get",
      -  "list",
      -  "revisions",
      -  "delete"
      -]New value: +[
      +  "create",
      +  "update",
      +  "get",
      +  "list",
      +  "revisions",
      +  "delete",
      +  "publish",
      +  "unpublish",
      +  "marketplace"
      +]
    • addedInput schema / properties / creator
      Added value: +{
      +  "description": "Used with action=\"marketplace\".",
      +  "maxLength": 80,
      +  "type": "string"
      +}
    • changedInput schema / properties / description / description
      Previous value: -"What the indicator shows. Used with action=\"create\", action=\"update\"."New value: +"action=\"create\": What the indicator shows. | action=\"publish\": What it shows and how to use it. Used with action=\"create\", action=\"update\", action=\"publish\"."
    • changedInput schema / properties / indicatorId / description
      Previous value: -"The indicator id from indicators(action=\"list\"). Used with action=\"update\", action=\"get\", action=\"revisions\", action=\"delete\". Required for action=\"update\", action=\"get\", action=\"revisions\", action=\"delete\"."New value: +"The indicator id from indicators(action=\"list\"). Used with action=\"update\", action=\"get\", action=\"revisions\", action=\"delete\", action=\"publish\". Required for action=\"update\", action=\"get\", action=\"revisions\", action=\"delete\", action=\"publish\"."
    • addedInput schema / properties / listingId
      Added value: +{
      +  "description": "The listing id from indicators(action=\"publish\") or the marketplace. Used with action=\"unpublish\". Required for action=\"unpublish\".",
      +  "format": "uuid",
      +  "type": "string"
      +}
    • addedInput schema / properties / priceAmountCents
      Added value: +{
      +  "description": "Used with action=\"publish\".",
      +  "type": "integer"
      +}
    • addedInput schema / properties / pricingModel
      Added value: +{
      +  "description": "Used with action=\"publish\".",
      +  "enum": [
      +    "free",
      +    "monthly"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / query
      Added value: +{
      +  "description": "Used with action=\"marketplace\".",
      +  "maxLength": 80,
      +  "type": "string"
      +}
    • addedInput schema / properties / sourceVisibility
      Added value: +{
      +  "description": "Used with action=\"publish\".",
      +  "enum": [
      +    "private",
      +    "open"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / title
      Added value: +{
      +  "description": "The listing title. Defaults to the indicator name. Used with action=\"publish\".",
      +  "maxLength": 140,
      +  "type": "string"
      +}
  2. Added

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare destructive/non-idempotent; the description goes much further, disclosing versioning (old versions kept so a bot pinned to a version keeps it), soft delete with staff restore, preview-unless-confirm semantics, owner-only code reads ("any other id answers not found"), and "Never shows code" for list/revisions/marketplace. It also explains marketplace visibility tradeoffs ("private" keeps the code yours; buyers run it but never read it) — real behavioral context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded and well-structured with per-action headings and a "Required fields" line, which is the right shape for a 9-action tool. However, the two-sentence privacy disclaimer ("Indicators are private... including anyone it is shared with or sold to later") is repeated verbatim in the intro, create, and update sections, and the action list is restated — avoidable bloat in an already long description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and 17 parameters across 9 actions, the description still covers what each action returns ("Returns one of the signed-in person's indicators with its Python source", "newest first, with what changed", "with their creator, price and link"). Deletion, versioning, privacy, and listing lifecycle are all addressed, so an agent has enough to call every action correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description adds genuine meaning on top, including per-action required fields, that update must send "the full source plus changeNotes" while leaving source out only renames, and publish defaults/ranges ("free" default, monthly with priceAmountCents 100 to 1,000,000). It stops short of explaining every one of the 17 parameters (e.g. metadata sub-fields, query/creator handling), so not a 5.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb list plus the exact resource: "Save, version, read, list and delete your own custom Python indicators (LumiBot Indicator classes)." The nine per-action headings each restate verb+object ("Save a new custom indicator", "List the versions of a custom indicator"), so an agent can map any requested operation to the right action without reading the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit routing rules: create for a brand-new indicator vs update for changes as a new version, and the concrete conditional "If asked to change a chart before creating or adding an indicator, confirm the chart change before saving the indicator; then add the saved indicator to that same chart." It also names a prerequisite tool reference ("load the custom-chart-indicators reference") and the exact import surface, which is guidance an agent cannot infer from siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.