Skip to content

Learn

Use it from Claude via MCP

Connect Claude Desktop (or any MCP client) to the engine, ask it to analyse a folder, and get verified numbers back that the model quotes instead of recomputing.

Tutorial 4 of 5. About fifteen minutes. You need Claude Desktop or another MCP client; the engine itself still runs offline.

A chat assistant is good at conversation and bad at arithmetic over your files. The engine is the opposite. The Model Context Protocol (MCP) is an open standard that lets an assistant call tools on your machine. With it, you ask Claude in plain words; Claude calls the engine; the engine does the reading, the SQL and the verification; Claude quotes the result.

Your files never leave your machine through the engine: it reads local paths and returns text.

Open Settings → Developer → Edit Config, and add the engine as a stdio server. Claude Desktop starts it for you. This configuration uses the scripted planner and the offline embedder, so it works with no model; replace them with your model settings later (see Running on free models):

claude_desktop_config.json
{
"mcpServers": {
"agentic-analytics": {
"command": "node",
"args": ["/path/to/agentic-analytics/apps/cli/bin/aa.js", "mcp", "--embedder", "hash"],
"env": {
"AA_DEMO_MODEL": "scripted",
"AA_JOBS_DIR": "/path/to/agentic-analytics/data/jobs"
}
}
}
}

Restart Claude Desktop. The server offers these tools (their real descriptions, as the client sees them):

ToolWhat the client is told
analyze_filesStart an analysis job on local files or folders (spreadsheets, CSV, PDF, Word, email). Returns the job id and status; with wait=true, waits and returns the report summary. Numbers in the result are verified facts computed by the engine (SQL or deterministic code) with provenance. Quote them exactly as given; never recalculate, round differently or derive new numbers from them.
ask_reportAsk a follow-up question about a finished report. The answer is claims that passed the same verification as the report, with their facts and citations; claims that failed are listed as dropped. Numbers in the result are verified facts computed by the engine (SQL or deterministic code) with provenance. Quote them exactly as given; never recalculate, round differently or derive new numbers from them.
confirm_metricsConfirm (or edit) the metric definitions of a job waiting for confirmation, as YAML; the job resumes. Invalid definitions are refused with reasons.
explain_numberShow how one number in a report was computed: its SQL and parameters (or function and inputs), the metric definition, and the input rows. Numbers in the result are verified facts computed by the engine (SQL or deterministic code) with provenance. Quote them exactly as given; never recalculate, round differently or derive new numbers from them.
get_reportThe report of a job: format=summary (headline, top findings and recommendations, as text) or json (the full verified report.json with facts, citations and verification). Numbers in the result are verified facts computed by the engine (SQL or deterministic code) with provenance. Quote them exactly as given; never recalculate, round differently or derive new numbers from them.

Note the last sentence of most descriptions: the calling model is told the numbers are verified and must be quoted, never recalculated.

Try: “Analyse the files in /path/to/agentic-analytics/examples/coffee-roaster and tell me why revenue fell.” Claude calls the tools. Below are those calls and the engine’s real answers, recorded through the MCP SDK’s own client against the same server aa mcp runs (only the path and the job ID are shown generically):

analyze_files
→ {"paths":["/path/to/agentic-analytics/examples/coffee-roaster"],"currency":"USD","wait":true}

<job-id>: done

Revenue fell after March, driven by wholesale (a change of −7,900).

Findings:
• Revenue fell after March, driven by wholesale
  Revenue went from 44,100 in 2026-03 to 36,200 in 2026-04 (a change of −7,900, −17.9%). It stood at 37,000 in 2026-06.
• Refund rate rose after the packaging supplier switch
  Refund rate went from 1.2% in 2026-03 to 1.3% in 2026-04 (a change of 0.1 pp, 8.3%). It stood at 3.4% in 2026-06.
• A change in revenue
  Revenue for “Green Leaf Bakery” went from 2,745.86 in 2026-05 to 1,966.87 in 2026-06 (a change of −778.99, −28.4%).

Recommendations:
• Offer wholesale accounts a volume-tier discount to win back paused standing orders
  Expected impact: 3,995 to 7,191 next quarter
• Return to the previous packaging supplier, or fix the new valve bags
  Expected impact: 407 to 732.60 next two months

Note: some metric definitions were assumed, not confirmed. Check them in the report's Metrics section.
explain_number
→ {"job_id":"<job-id>","fact_id":"N30"}

{
  "fact": {
    "id": "N30",
    "label": "I5 trend_break.v1 revenue 2026-04:change_pct",
    "value": -17.91383219954654,
    "unit": "percent",
    "computation": {
      "kind": "function",
      "fn": "pct_change",
      "inputs": [
        "N11",
        "N12"
      ]
    },
    "citations": [],
    "verified": true
  },
  "inputs": [
    {
      "id": "N11",
      "label": "revenue_2026-04",
      "value": 36200.00000000003,
      "unit": "currency",
      "currency": "USD",
      "metric_id": "revenue",
      "computation": {
        "kind": "sql",
        "sql": "WITH m1 AS (SELECT strftime(\"date\", '%Y-%m') AS period, sum(\"amount\") AS value FROM \"t_t1\" WHERE NOT _is_total AND \"date\" IS NOT NULL AND ((\"status\" IS NULL) OR (\"status\" NOT IN ($1))) AND strftime(\"date\", '%Y-%m') BETWEEN $2 AND $3 GROUP BY ALL)\nSELECT period, value FROM m1 ORDER BY period",
        "params": {
          "$1": "refunded",
          "$2": "2026-04",
          "$3": "2026-04",
          "input_rows": 1020
        }
      },
      "citations": [
        {
          "source_id": "T1",
          "rows": [
            3095,
            3096,
            3097,
            3098,
            3099,
            3100,
            3101,
            3102,
            3103,
            3104,
            3105,
            3106,
            3107,
            3108,
            3109,
          …
ask_report
→ {"job_id":"<job-id>","question":"Why did revenue drop in April?"}

{
  "answer": [
    "Revenue went from 44,100 in 2026-03 to 36,200 in 2026-04 (a change of −7,900, −17.9%). It stood at 37,000 in 2026-06."
  ],
  "claims": [
    {
      "text": "Revenue went from {{N12}} in 2026-03 to {{N11}} in 2026-04 (a change of {{N29}}, {{N30}}). It stood at {{N17}} in 2026-06.",
      "facts": [
        "N12",
        "N11",
        "N29",
        "N30",
        "N17"
      ],
      "citations": [],
      "causal_grade": "observed",
      "verified": true
    }
  ],
  "facts": [
    {
      "id": "N11",
      "label": "revenue_2026-04",
      "value": 36200.00000000003,
      "unit": "currency",
      "currency": "USD",
      "metric_id": "revenue",
      "computation": {
        "kind": "sql",
        "sql": "WITH m1 AS (SELECT strftime(\"date\", '%Y-%m') AS period, sum(\"amount\") AS value FROM \"t_t1\" WHERE NOT _is_total AND \"date\" IS NOT NULL AND ((\"status\" IS NULL) OR (\"status\" NOT IN ($1))) AND strftime(\"date\", '%Y-%m') BETWEEN $2 AND $3 GROUP BY ALL)\nSELECT period, value FROM m1 ORDER BY period",
        "params": {
          "$1": "refunded",
          "$2": "2026-04",
          "$3": "2026-04",
          "input_rows": 1020
        }
      },
      "citations": [
        {
          "source_id": "T1",
          "rows": [
            3095,
            3096,
            3097,
            3098,
            3099,
            3100,
       …

analyze_files with wait: true returned the summary. explain_number returned the computation behind the headline percentage. ask_report returned claims that passed verification, and lists any that failed.

A long job can outlast a client’s request timeout. Ask Claude to start with wait: false and then poll get_report.

aa serve also serves MCP over streamable HTTP at /mcp, for clients that connect to a URL. Over HTTP anyone who can reach the port could ask for files, so local paths are read only inside the folders you list in AA_MCP_ROOTS:

Terminal
AA_MCP_ROOTS=/path/to/agentic-analytics/examples AA_DEMO_MODEL=scripted bun run aa serve --embedder hash

Then point the client at http://127.0.0.1:8080/mcp. The server listens on localhost only; set API_TOKEN before exposing it anywhere else.

  • MCP lets an assistant call the engine’s tools on your machine.
  • The assistant gets verified numbers with IDs and is told to quote them.
  • Over HTTP, AA_MCP_ROOTS limits which folders can be read.

Next: Run evals on your own data.

Reference: MCP · MCP specification