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.
Why connect them
Section titled “Why connect them”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.
1. Add the server to Claude Desktop
Section titled “1. Add the server to Claude Desktop”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):
{ "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):
| Tool | What the client is told |
|---|---|
| analyze_files | Start 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_report | Ask 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_metrics | Confirm (or edit) the metric definitions of a job waiting for confirmation, as YAML; the job resumes. Invalid definitions are refused with reasons. |
| explain_number | Show 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_report | The 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.
2. Ask
Section titled “2. Ask”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):
→ {"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.→ {"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,
…→ {"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.
3. Over HTTP instead
Section titled “3. Over HTTP instead”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:
AA_MCP_ROOTS=/path/to/agentic-analytics/examples AA_DEMO_MODEL=scripted bun run aa serve --embedder hashThen 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.
What you learned
Section titled “What you learned”- 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_ROOTSlimits which folders can be read.
Next: Run evals on your own data.
Reference: MCP · MCP specification