Files
Pratik Bhadane 58a1dc2308 chore: remove .coverage file and update .gitignore to exclude coverage files
- Deleted the .coverage file to clean up the repository.
- Updated .gitignore to ensure .coverage and .coverage.* files are ignored in future commits.
- Revised README.md to enhance clarity and conciseness regarding the library's capabilities and performance.
- Improved documentation for the MCP server, emphasizing its expanded functionality and integration with clients.
2026-03-24 12:49:17 +05:30

4.6 KiB

MCP Server

ferro-ta ships an optional MCP (Model Context Protocol) server built on the official Python SDK's FastMCP layer. The server now exposes the broad public ferro-ta callable surface instead of a tiny hand-picked subset.

That means MCP clients can use:

  • Exact top-level ferro-ta exports such as SMA, RSI, MACD, about, methods, info, benchmark, and traced
  • Non-top-level public tools such as compute_indicator, run_backtest, check_cross, aggregate_ticks, TickAggregator, and AlertManager
  • Legacy lowercase convenience aliases: sma, ema, rsi, macd, and backtest
  • Generic instance tools for stateful classes and stored callables: list_instances, describe_instance, call_instance_method, call_stored_callable, and delete_instance

Installation

Install the optional MCP extra:

pip install "ferro-ta[mcp]"

If you are working from this repository, you can install the same extra into the project environment with:

uv sync --extra mcp

Running the server

Run the server over stdio:

python -m ferro_ta.mcp

The command exits immediately with an install hint if the optional mcp dependency is missing.


Connect in Cursor

Add the server to Cursor's MCP settings:

{
  "mcpServers": {
    "ferro-ta": {
      "command": "python",
      "args": ["-m", "ferro_ta.mcp"],
      "description": "ferro-ta technical analysis tools"
    }
  }
}

You can place this in your user settings JSON or in a workspace-level .cursor/mcp.json.


Tool naming

The MCP server prefers the real ferro-ta API names.

  • Use exact public names when possible, for example SMA, MACD, compute_indicator, trade_stats, TickAggregator, or AlertManager
  • Use the legacy lowercase aliases only when you want the old MCP-friendly shortcuts and result shapes
  • Use about, methods, indicators, and info to discover what is available from inside an MCP client

Stateful classes and object references

Class tools return stored object references instead of plain text placeholders. For example, calling TickAggregator or AlertManager returns a payload like:

{
  "instance_id": "tickaggregator-0001",
  "type": "ferro_ta.data.aggregation.TickAggregator",
  "repr": "TickAggregator(rule='tick:2')"
}

Use that instance_id with:

  • describe_instance to inspect the stored object and list public methods
  • call_instance_method to call methods like aggregate, update, run_backtest, or to_dict
  • delete_instance to remove stored objects when you are done

If a tool returns a stored callable, use call_stored_callable.


Callable references

Some ferro-ta APIs accept other callables, for example benchmark, log_call, traced, or multi_timeframe(indicator=...).

Pass public ferro-ta callables using:

{"callable": "SMA"}

Pass stored objects using:

{"instance_id": "function-0001"}

Example prompts

Once connected, you can ask an MCP-compatible client things like:

"Run SMA with close=[100, 101, 102, 103, 104] and timeperiod=3."

"Use compute_indicator to calculate MACD for this close series."

"Call about and summarize the current ferro-ta API surface."

"Create a TickAggregator with rule='tick:50', aggregate this tick data, then delete the instance."

"Benchmark SMA over this price series using a callable reference."


Programmatic use

Use the server entrypoint:

from ferro_ta.mcp import create_server

server = create_server()
# server.run(transport="stdio")

Or call the handlers directly without starting the server:

from ferro_ta.mcp import handle_call_tool, handle_list_tools
import json

tools = handle_list_tools()
print(len(tools["tools"]))

close = [100, 101, 102, 103, 104]
result = handle_call_tool("SMA", {"close": close, "timeperiod": 3})
print(json.loads(result["content"][0]["text"]))

aggregator = json.loads(
    handle_call_tool("TickAggregator", {"rule": "tick:2"})["content"][0]["text"]
)
bars = handle_call_tool(
    "call_instance_method",
    {
        "instance_id": aggregator["instance_id"],
        "method": "aggregate",
        "args": [{"price": [1, 2, 3, 4], "size": [1, 1, 1, 1]}],
    },
)
print(json.loads(bars["content"][0]["text"]))

See also

  • python -m ferro_ta.mcp - stdio MCP entrypoint
  • ferro_ta.mcp.create_server() - FastMCP server factory
  • ferro_ta.tools.api_info - API discovery helpers used by the MCP catalog
  • ferro_ta.tools - stable wrappers such as compute_indicator
  • docs/agentic.md - workflow and agent integration notes