Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/backtest-kit/ai-trading-mcp/llms.txt

Use this file to discover all available pages before exploring further.

When an LLM trades a live portfolio, “what did it know and when did it know it” must be answerable — not just in principle, but with a file you can open after the fact. AI Trading MCP closes that loop by writing every get_status response to disk, in full, before it is returned to the agent.

What Gets Dumped

Every get_status response — portfolio state across all symbols, command history, and the complete Telegram feed including chart screenshots — is persisted to two directories before the result is returned. The dump happens synchronously inside GET_STATUS_FN so there is no race between “what the model received” and “what ended up on disk”:
// packages/agent/src/lib/services/controller/StatusControllerService.ts
const GET_STATUS_FN = queued(async (self, dto) => {
  let messages = [];
  messages = messages.concat(
    await MCP.getDefaultMessages(dto.context, dto.when, dto.mcpName)
  ); // engine portfolio
  messages = messages.concat(
    await MCP.getHistoryMessages(dto.mcpName)
  ); // command history
  messages = messages.concat(
    await FETCH_TELEGRAM_HISTORY_FN(self, dto.when)
  ); // the feed

  // ...timeout / restart handling...

  // ↓ written to disk BEFORE returning to the agent
  await self.statusMarkdownService.dumpStatus(result, dto.context, dto.when);
  return result;
});

Where Dumps Live

dump/mcp/

Full text content of each get_status response, one file per call. Filename is a minute-level timestamp: 20260802_0934.md. Images are referenced with relative paths so the file renders anywhere.

dump/images/

Chart screenshots from the Telegram feed, base64-decoded back to PNG. Each file is named after its MCP message ID: <id>.png. Referenced from the markdown as ../images/<id>.png.

The dumpStatus Implementation

StatusMarkdownService.dumpStatus iterates the message list and writes text blocks inline and image blocks as separate PNG files with relative markdown references:
// packages/agent/src/lib/services/markdown/StatusMarkdownService.ts
const IMAGE_DIR = join("./dump", "images");
const MCP_DIR   = join("./dump", "mcp");

public dumpStatus = async (
  messages: IMCPMessage[],
  context: IMCPContext,
  when: Date,
): Promise<void> => {
  await fs.mkdir(IMAGE_DIR, { recursive: true });
  await fs.mkdir(MCP_DIR,   { recursive: true });

  let content = "";

  for (const message of messages) {
    if (message.type === "text") {
      content += message.text;
      content += "\n\n";
      continue;
    }
    // image block: decode base64 → PNG file, embed relative reference
    await fs.writeFile(
      join(IMAGE_DIR, `${message.id}.png`),
      Buffer.from(message.data, "base64"),
    );
    content += `![${message.id}](../images/${message.id}.png)\n\n`;
  }

  const dumpIndex = getMomentStamp(when, "minute");
  await fs.writeFile(join(MCP_DIR, `${dumpIndex}.md`), content, "utf8");
};
Timestamp format. getMomentStamp(when, "minute") produces a minute-level stamp (e.g., 20260802_0934). One file is written per get_status call; if two calls land within the same minute the second overwrites the first, which is by design — the minute-stamped file always holds the most recent snapshot for that minute.

Position Provenance

The dump captures not just what the model saw but what it decided and why. The note parameter of open_position is echoed back in every subsequent get_status response, so the position’s basis travels forward through the audit trail:
Active position: short (note: Paper trade at user's request. Basis — signal from
Telegram feed -1002833393903, 2026-08-02 09:34 UTC ("Working BTC — short, sized
for a possible add"), entry ~63 285.75. No own technical confirmation; the source
shows signs of unreliability.)
This means any dump file captured while the position is open contains both the current market state and a human-readable statement of why the position was opened. Cross-referencing the dump timestamp with the position’s entry note is sufficient to reconstruct the full decision chain.

The Dump Viewer

The web UI served on :60050 ships a built-in dump viewer that renders the markdown files with inline images. Open it in a browser while the trading process is running to browse the full history of what the model saw, including chart screenshots from the feed.
# start the trading process with the UI flag
npm start -- --paper --entry ./content/manual.strategy/manual.strategy.ts --ui
# dump viewer available at http://localhost:60050

Persistence and Process Restarts

Dump files survive process restarts — they are plain files written to dump/mcp/ and dump/images/. The trading engine’s own state persistence (open positions, signals, brackets, history) is configured separately in config/setup.config.ts and stored under dump/data/. Both survive restarts independently.
dump/
  data/      ← engine state: signals, positions, storage, sessions (config/setup.config.ts)
  mcp/       ← audit trail: one .md per get_status call
  images/    ← chart screenshots decoded from MCP image blocks
  report/    ← event streams: live.jsonl, performance.jsonl, max_drawdown.jsonl, …
Dump files can grow large on active chart channels. An image-heavy Telegram feed with frequent get_status calls will accumulate PNGs quickly. The dump/ directory is in .gitignore by default — archive or prune it periodically for long-running sessions.

Build docs developers (and LLMs) love