Analytics
precis.finance
Provides access to planning scenarios and metric catalogs for data analysis.
ENDPOINT 1
https://mcp.precis.finance/mcp
MCP server metadata
- Name
- precis
- Version
- 0.2.4
# Précis — Finance Intelligence (MCP connector) You are connected to Précis, a **read-only** FP&A data platform for your organisation: query financial statements and metrics, and inspect row-level detail. Reporting tools come in variants — `run_statement`/`run_metric` show the user a table; `run_statement_data`/`run_metric_data` return the raw figures for you to analyse or compute over. The rest of this document details the data model. You cannot write plans, create scenarios, or change settings — those live in the Précis app. ## How the reporting tools are shaped The two reporting tools come in variants — pick the one that matches what the user needs: - **`run_statement` / `run_metric`** — render a formatted table for the user (the default; use when they want to *see* the figures). - **`run_statement_data` / `run_metric_data`** — return the raw figures for you to analyse, compute over, or transform (no table is shown to the user). Figures default to thousands with one decimal place unless you pass `scale` / `decimals` explicitly. For a general P&L request, when the user has not chosen a statement and no active report default applies, use `full_pnl` if it is listed under **Available Statements**. Respect an explicit request for a narrower statement or executive summary; if `full_pnl` is not listed, choose the closest available P&L statement. **Always give every scenario a user-facing `alias`.** The `scenario` value is an internal query key; `alias` is the column heading the user sees. Prefer concise finance labels such as `Actuals`, `Budget`, `Variance`, `Var %`, or `Prior Year`. For example: `scenarios=[{"scenario":"actuals","alias":"Actuals"}, {"scenario":"actuals_vs_budget_pct","alias":"Var %"}]`. Never let raw keys such as `actuals_vs_budget_pct` become visible table headings. **Period filters are grain-tagged.** `period_start` / `period_end` take a period code whose shape sets the grain: `2025-06` (month), `2025-Q2` (quarter), `2025` (fiscal year), `2025-W37` (week), `2025-06-14` (day). Both bounds must share a grain. Month/quarter/fiscal-year work on every statement; week and day only where the domain's data carries them — `list_dimensions` reports each dimension's grain, and an unsupported grain is rejected with the supported set named. Prior-year and prior-period comparisons work at any grain, and sum / avg / closing metrics roll up correctly at each grain. Utility tools — `list_scenarios`, `list_kpis`, `list_dimensions`, `search_hierarchy`, `list_inspection_sources`, `get_inspection_schema`, `inspect_rows`, `list_variants` — discover valid scenario ids, metric keys, dimensions, and row-level detail before composing a query. `list_dimensions` tells you which dimension keys exist (metadata only); `search_hierarchy` lists or searches a dimension's members — reach for it whenever you need valid member ids. ## Choosing run_statement vs run_metric - **Financial statement** (P&L, variance report, executive summary) → `run_statement`. Rows = statement lines (Revenue, Direct Cost, Gross Margin, …); columns = scenarios (Actuals, Budget, Variance, …). - **Metric breakdown** (revenue by project, utilisation by employee, headcount, GL account drill-down) → `run_metric`. Rows = a dimension; columns = metrics × scenarios. Always pass `scenarios` explicitly, e.g. `scenarios=[{"scenario": "actuals", "alias": "Actuals"}]`, unless the user named another scenario. The `period` and `cost_centre` dimensions work for every statement; other dimensions may only apply to compatible metrics. ## Breaking down by a hierarchy A hierarchy dimension can be used as a breakdown: it shows **one level down** — the filtered hierarchy node is the **Total**, its **immediate children** are the rows. Pass a filter selecting one node of the hierarchy together with the hierarchy as the dimension: `filters={<hierarchy>: <node_id>}` with `dimensions=[<hierarchy>]`. "Drill into {X}" means filter the hierarchy to X's node and break down by that hierarchy. Use `search_hierarchy` to get a node's id. One hierarchy at a time (the sole breakdown axis), a node filter is required, and a time/calendar hierarchy cannot be broken down this way. ## The data model ## Available Statements The `run_statement` tool accepts a `statement` parameter to control which metrics are included. When the user has not chosen a statement and no active report default applies, use `full_pnl` for a general P&L request. Respect an explicit request for a narrower or summary statement. When the user asks for "the full picture", "with FTEs", or a "comprehensive" view, use `full_pnl`. When they ask for a "summary" or "executive" view, use `executive_summary`. | Statement | Label | Description | |---|---|---| | `pnl` | P&L Statement | Standard P&L with revenue, costs, gross margin, contribution margin, and EBITDA. | | `statistical` | Statistical KPIs | Operational metrics: billable/total hours, utilisation rate, and FTE counts (average and closing). | | `ratios` | Ratios | Realised rate, revenue per FTE, and payroll cost per FTE — pricing, productivity, and cost efficiency indicators. | | `full_pnl` | Full P&L with KPIs | Complete view: P&L financials followed by statistical KPIs (hours, FTEs, utilisation) and per-FTE ratios. Use when the user asks for 'the full picture', 'metrics at the bottom', 'FTEs and hours', or a comprehensive report. | | `executive_summary` | Executive Summary | Compact board-level view: revenue, margins, EBITDA, total FTEs, utilisation, and revenue per FTE on a single page. | --- ## Available Scenarios Pass scenarios as objects whose `scenario` field holds a visible key and whose `alias` is a concise, user-facing column label, e.g. `[{"scenario": "actuals", "alias": "Actuals"}, {"scenario": "budget", "alias": "Budget 2026"}]`. Always provide `alias`: without it, internal keys such as `actuals_vs_budget_pct` become visible table headings. Real scenarios come from `semantic.scenarios`; shifted and comparison scenarios are generated. ### Data scenarios (stored data) | `scenario` | Scenario ID | Label | Status | Description | |---|---|---|---|---| | `actuals` | `ACTUALS` | Actuals | LOCKED | ACTUALS|base_year=0 | | `budget` | `BUD-2026` | Budget 2026 | APPROVED | BUDGET|base_year=2026 | | `forecast_q1` | `FC-2026-Q1` | Forecast 2026 Q1 Reforecast | DRAFT | FORECAST|base_year=2026 | ### Shifted scenarios (auto-offset periods) | `scenario` | Base | Offset | Label | Description | |---|---|---|---|---| | `actuals_py` | `actuals` | -12 months | Actuals PY | Actuals shifted by -12 months. | | `actuals_pp` | `actuals` | -1 months | Actuals PP | Actuals shifted by -1 month. | | `budget_py` | `budget` | -12 months | Budget 2026 PY | Budget 2026 shifted by -12 months. | | `budget_pp` | `budget` | -1 months | Budget 2026 PP | Budget 2026 shifted by -1 month. | | `forecast_q1_py` | `forecast_q1` | -12 months | Forecast 2026 Q1 Reforecast PY | Forecast 2026 Q1 Reforecast shifted by -12 months. | | `forecast_q1_pp` | `forecast_q1` | -1 months | Forecast 2026 Q1 Reforecast PP | Forecast 2026 Q1 Reforecast shifted by -1 month. | **How shifted scenarios work:** Keep the requested period unchanged and use a visible shifted key such as `actuals_py`; the engine applies its offset. ### Computed scenarios (calculated from other scenarios) | `scenario` | Formula | Label | Description | |---|---|---|---| | `actuals_vs_budget` | `actuals - budget` | Actuals vs Budget 2026 | Actuals vs Budget 2026: Actuals minus Budget 2026. | | `actuals_vs_budget_pct` | `(actuals - budget) / abs(budget) * 100` | Actuals vs Budget 2026 % | Actuals vs Budget 2026: Actuals minus Budget 2026. Percentage variance vs comparator. | | `actuals_vs_forecast_q1` | `actuals - forecast_q1` | Actuals vs Forecast 2026 Q1 Reforecast | Actuals vs Forecast 2026 Q1 Reforecast: Actuals minus Forecast 2026 Q1 Reforecast. | | `actuals_vs_forecast_q1_pct` | `(actuals - forecast_q1) / abs(forecast_q1) * 100` | Actuals vs Forecast 2026 Q1 Reforecast % | Actuals vs Forecast 2026 Q1 Reforecast: Actuals minus Forecast 2026 Q1 Reforecast. Percentage variance vs comparator. | | `budget_vs_actuals` | `budget - actuals` | Budget 2026 vs Actuals | Budget 2026 vs Actuals: Budget 2026 minus Actuals. | | `budget_vs_actuals_pct` | `(budget - actuals) / abs(actuals) * 100` | Budget 2026 vs Actuals % | Budget 2026 vs Actuals: Budget 2026 minus Actuals. Percentage variance vs comparator. | | `budget_vs_forecast_q1` | `budget - forecast_q1` | Budget 2026 vs Forecast 2026 Q1 Reforecast | Budget 2026 vs Forecast 2026 Q1 Reforecast: Budget 2026 minus Forecast 2026 Q1 Reforecast. | | `budget_vs_forecast_q1_pct` | `(budget - forecast_q1) / abs(forecast_q1) * 100` | Budget 2026 vs Forecast 2026 Q1 Reforecast % | Budget 2026 vs Forecast 2026 Q1 Reforecast: Budget 2026 minus Forecast 2026 Q1 Reforecast. Percentage variance vs comparator. | | `forecast_q1_vs_actuals` | `forecast_q1 - actuals` | Forecast 2026 Q1 Reforecast vs Actuals | Forecast 2026 Q1 Reforecast vs Actuals: Forecast 2026 Q1 Reforecast minus Actuals. | | `forecast_q1_vs_actuals_pct` | `(forecast_q1 - actuals) / abs(actuals) * 100` | Forecast 2026 Q1 Reforecast vs Actuals % | Forecast 2026 Q1 Reforecast vs Actuals: Forecast 2026 Q1 Reforecast minus Actuals. Percentage variance vs comparator. | | `forecast_q1_vs_budget` | `forecast_q1 - budget` | Forecast 2026 Q1 Reforecast vs Budget 2026 | Forecast 2026 Q1 Reforecast vs Budget 2026: Forecast 2026 Q1 Reforecast minus Budget 2026. | | `forecast_q1_vs_budget_pct` | `(forecast_q1 - budget) / abs(budget) * 100` | Forecast 2026 Q1 Reforecast vs Budget 2026 % | Forecast 2026 Q1 Reforecast vs Budget 2026: Forecast 2026 Q1 Reforecast minus Budget 2026. Percentage variance vs comparator. | | `actuals_vs_actuals_py` | `actuals - actuals_py` | Actuals vs Actuals PY | Actuals vs Actuals PY: Actuals minus Actuals PY. | | `actuals_vs_actuals_py_pct` | `(actuals - actuals_py) / abs(actuals_py) * 100` | Actuals vs Actuals PY % | Actuals vs Actuals PY: Actuals minus Actuals PY. Percentage variance vs comparator. | | `budget_vs_budget_py` | `budget - budget_py` | Budget 2026 vs Budget 2026 PY | Budget 2026 vs Budget 2026 PY: Budget 2026 minus Budget 2026 PY. | | `budget_vs_budget_py_pct` | `(budget - budget_py) / abs(budget_py) * 100` | Budget 2026 vs Budget 2026 PY % | Budget 2026 vs Budget 2026 PY: Budget 2026 minus Budget 2026 PY. Percentage variance vs comparator. | | `forecast_q1_vs_forecast_q1_py` | `forecast_q1 - forecast_q1_py` | Forecast 2026 Q1 Reforecast vs Forecast 2026 Q1 Reforecast PY | Forecast 2026 Q1 Reforecast vs Forecast 2026 Q1 Reforecast PY: Forecast 2026 Q1 Reforecast minus Forecast 2026 Q1 Reforecast PY. | | `forecast_q1_vs_forecast_q1_py_pct` | `(forecast_q1 - forecast_q1_py) / abs(forecast_q1_py) * 100` | Forecast 2026 Q1 Reforecast vs Forecast 2026 Q1 Reforecast PY % | Forecast 2026 Q1 Reforecast vs Forecast 2026 Q1 Reforecast PY: Forecast 2026 Q1 Reforecast minus Forecast 2026 Q1 Reforecast PY. Percentage variance vs comparator. | **Additional comparisons available on demand.** The table above is a curated default. The engine resolves `{left}_vs_{right}` and `{left}_vs_{right}_pct` keys where each side uses only a real or shifted scenario visible above. Visible compatibility aliases: `prior_year`, `prior_period`. Use these when the user's question implies a cross-scenario time-shifted comparison. --- ## Available Dimensions Each key below is a catalogue dimension name. Use the **same** key in both `filters` and `dimensions` — never a source-view column name. ### Quick Reference — Valid Keys per Domain **`gl`** - Metrics: `gl_amount` - Dimension keys (`filters` and `dimensions`): `account`, `account_type`, `calendar`, `cost_centre`, `department`, `division`, `fiscal_year`, `fs_line`, `org_structure`, `period`, `quarter`, `solution_portfolio` **`gl_federated`** - Metrics: `federated_debit_amount`, `federated_credit_amount`, `federated_net_amount`, `federated_revenue_amount` - Dimension keys (`filters` and `dimensions`): `account`, `account_type`, `calendar`, `cost_centre`, `department`, `division`, `fiscal_year`, `fs_line`, `org_structure`, `period`, `quarter`, `solution_portfolio` - Axis-only keys (valid in `dimensions` only, not `filters`): `posting_date`, `supplier_id` **`intercompany`** - Metrics: `intercompany_amount` - Dimension keys (`filters` and `dimensions`): `calendar`, `cost_centre`, `counterparty_cc`, `counterparty_department`, `counterparty_division`, `department`, `division`, `fiscal_year`, `org_structure`, `period`, `quarter`, `solution_portfolio` **`payroll`** - Metrics: `headcount`, `gross_salary`, `employer_contributions`, `bonus_cost`, `total_payroll_cost` - Dimension keys (`filters` and `dimensions`): `calendar`, `cost_centre`, `department`, `division`, `employee`, `fiscal_year`, `grade`, `org_structure`, `period`, `quarter`, `solution_portfolio` **`pipeline`** - Metrics: `pipeline_value`, `weighted_pipeline`, `open_count`, `avg_deal_size`, `bookings`, `won_count`, `lost_count`, `win_rate` - Dimension keys (`filters` and `dimensions`): `calendar`, `crm_account`, `crm_industry`, `crm_region`, `crm_segment`, `fiscal_year`, `period`, `quarter` **`pnl`** - Metrics: `revenue`, `direct_cost`, `indirect_cost`, `sga`, `billable_hours`, `total_hours`, `avg_fte_billable`, `avg_fte_overhead`, `closing_fte_billable`, `closing_fte_overhead`, `gross_margin`, `gross_margin_pct`, `contribution_margin`, `ebitda`, `ebitda_margin_pct`, `avg_fte_total`, `utilisation_rate`, `realised_rate`, `revenue_per_fte`, `payroll_cost_per_fte` - Dimension keys (`filters` and `dimensions`): `calendar`, `cost_centre`, `department`, `division`, `fiscal_year`, `org_structure`, `period`, `quarter`, `solution_portfolio` **`project_economics`** - Metrics: `project_revenue`, `project_cost`, `project_margin`, `project_margin_pct`, `project_billings`, `project_billable_hours`, `project_worked_hours`, `realised_bill_rate`, `project_wip`, `project_percent_complete`, `project_cum_revenue`, `project_cum_cost`, `project_cum_billed` - Dimension keys (`filters` and `dimensions`): `calendar`, `client`, `client_portfolio`, `cost_centre`, `department`, `division`, `fiscal_year`, `org_structure`, `period`, `project`, `project_status`, `project_type`, `quarter`, `solution_portfolio` **`timesheets`** - Metrics: `hours_worked`, `hours_billable`, `hours_non_billable`, `ts_utilisation_rate` - Dimension keys (`filters` and `dimensions`): `calendar`, `client`, `client_portfolio`, `cost_centre`, `day`, `department`, `division`, `employee`, `fiscal_year`, `grade`, `org_structure`, `period`, `project`, `project_status`, `project_type`, `quarter`, `solution_portfolio`, `week` **`worklog_federated`** - Metrics: `federated_hours_worked`, `federated_billable_hours`, `federated_billable_amount`, `federated_utilisation` - Dimension keys (`filters` and `dimensions`): `calendar`, `client`, `client_portfolio`, `cost_centre`, `department`, `division`, `employee`, `fiscal_year`, `grade`, `org_structure`, `period`, `project`, `project_status`, `project_type`, `quarter`, `solution_portfolio` - Axis-only keys (valid in `dimensions` only, not `filters`): `activity_type`, `approval_status`, `source_system`, `task_code`, `work_date` ### Dimension Reference The same key works as a filter and as a breakdown axis. | Dimension key | Type | Example | |---|---|---| | `cost_centre` | leaf | `{"cost_centre": "CC-CLOUD-01"}` | | `counterparty_cc` | leaf | `{"counterparty_cc": "<Counterparty Cost Centre>"}` | | `account` | leaf | `{"account": "4100"}` | | `employee` | leaf | `{"employee": "42"}` | | `project` | leaf | `{"project": "6"}` | | `period` | leaf | `{"period": "2025-03"}` | | `crm_account` | leaf | `{"crm_account": "<CRM Account>"}` | | `client` | leaf | `{"client": "<Client>"}` | | `day` | leaf | `{"day": "<Day>"}` | | `week` | leaf | `{"week": "<Week>"}` | | `department` | derived (from cost_centre) | `{"department": "<Department>"}` | | `division` | derived (from cost_centre) | `{"division": "<Division>"}` | | `counterparty_department` | derived (from counterparty_cc) | `{"counterparty_department": "<Counterparty Department>"}` | | `counterparty_division` | derived (from counterparty_cc) | `{"counterparty_division": "<Counterparty Division>"}` | | `fs_line` | derived (from account) | `{"fs_line": "<Financial Statement Line>"}` | | `account_type` | derived (from account) | `{"account_type": "<Account Type>"}` | | `grade` | derived (from employee) | `{"grade": "<Grade>"}` | | `project_type` | derived (from project) | `{"project_type": "<Project Type>"}` | | `project_status` | derived (from project) | `{"project_status": "<Project Status>"}` | | `crm_industry` | derived (from crm_account) | `{"crm_industry": "<Industry (CRM)>"}` | | `crm_segment` | derived (from crm_account) | `{"crm_segment": "<Segment>"}` | | `crm_region` | derived (from crm_account) | `{"crm_region": "<Region>"}` | | `quarter` | derived (from period) | `{"quarter": "<Quarter>"}` | | `fiscal_year` | derived (from period) | `{"fiscal_year": "<Fiscal Year>"}` | | `org_structure` | ragged hierarchy | `{"org_structure": "<value>"}` — use `search_hierarchy` | | `solution_portfolio` | ragged hierarchy | `{"solution_portfolio": "<value>"}` — use `search_hierarchy` | | `calendar` | ragged hierarchy | `{"calendar": "<value>"}` — use `search_hierarchy` | | `client_portfolio` | ragged hierarchy | `{"client_portfolio": "<node_id>"}` — use `search_hierarchy` | ### Filtering Rules 1. **Pick the filter key that matches the user's intent.** If the user asks about a department, use `department` — not `cost_centre`. The quick reference above lists every valid key per domain. 2. **Leaf and derived filters** use plain values. Example: `{"cost_centre": "CC-CLOUD-01"}` or `{"department": "Cloud & Infrastructure"}`. 3. **Ragged hierarchy filters** use node_id values. Call `search_hierarchy` to find the exact value. Example: `{"org_structure": "Cloud & Infrastructure"}`. 4. **Axis-only breakdown keys** can be used only in `dimensions`, not in `filters`. They are source-only columns on federated domains. Use `search_hierarchy` to find valid *values* for any filter key. Do NOT use it to discover filter key names — the tables above are authoritative. Use `list_kpis` for metric descriptions, formats, and available dimensions. ## Presenting results - Resolve ambiguous requests yourself — infer the period, scenario, and comparison basis from the conversation and FP&A norms rather than asking the user to specify what you can reasonably infer. - Present the figures and findings directly. Do not narrate which tools you called — the user sees the result, not the plumbing. - Never fabricate figures or account codes. If a query returns no data, say so.
Known tools 17
list_kpisBrowse the metric catalogue — metric keys, formats, domains, and the dimensions available per metric.
Inferred read-onlyinspect_rowsInspect the row-level detail behind a figure, from an enabled inspection source.
Inferred read-onlyrun_statementRun a financial statement — P&L, variance report, or executive summary.
Inferred read-onlyrun_statement_dataRun a financial statement — P&L, variance report, or executive summary.
Inferred read-onlyrun_metricBreak one or more metrics down by a dimension — revenue by project, utilisation by employee, headcount trends, GL account drill-down.
Inferred read-onlyrun_metric_dataBreak one or more metrics down by a dimension — revenue by project, utilisation by employee, headcount trends, GL account drill-down.
Inferred read-onlysearch_hierarchySearch the dimension hierarchies (cost centres, accounts, …) to find valid codes and ids before composing a query.
Inferred read-onlylist_dimensionsList the dimensions defined in the model — keys, labels, and kinds (leaf / derived / ragged hierarchy).
Inferred read-onlylist_load_historyList data-load attempts from the ingestion audit trail — when each dataset landed, with what status.
Inferred read-onlyget_load_statusFetch one data load's full detail by load_id — timestamps, status, rows landed, and any error message.
Potential side effectslist_bindingsList the configured data feeds (ingestion bindings) with their schedule — which datasets load, from where, how often.
Inferred read-onlyget_bindingFetch one data feed's full configuration: source, target dataset, schedule, and extract parameters.
Inferred read-onlyCONNECT WITH APPROVAL
Client installation
Review this server and its permissions before adding it. Secret placeholders must be set locally.
Codex
~/.codex/config.toml
[mcp_servers.precis]
url = "https://mcp.precis.finance/mcp"
enabled = true
Claude Code
.mcp.json
{
"mcpServers": {
"precis": {
"type": "http",
"url": "https://mcp.precis.finance/mcp"
}
}
}
Claude Desktop
Settings → Connectors → Add custom connector
Name: precis
Remote MCP URL: https://mcp.precis.finance/mcp
Add this remote URL as a custom connector in Claude Desktop. Availability depends on the user plan and workspace policy.
Cursor
.cursor/mcp.json
{
"mcpServers": {
"precis": {
"url": "https://mcp.precis.finance/mcp"
}
}
}
Visual Studio Code
.vscode/mcp.json
Add to Visual Studio Code{
"servers": {
"precis": {
"type": "http",
"url": "https://mcp.precis.finance/mcp"
}
}
}
Generic MCP
Client-specific MCP configuration
{
"name": "precis",
"transport": "streamable-http",
"url": "https://mcp.precis.finance/mcp"
}
MCP Inspector
Run the official MCP Inspector locally and enter the indexed Streamable HTTP endpoint.
TRUST AND VERIFICATION EVIDENCE
Loading Trust v2 evidence…
Checking the associated registrable domain. The BuiltWith key remains server-side.
Evidence is source-attributed and does not guarantee that a third-party server is safe. Risk labels are conservative metadata heuristics.