---
name: finbar-datasets
description: Build or update historical financial datasets from a supplied list of rows using Finbar. Use for preparing structured inputs, running paid research, retrieving results, or resuming an existing dataset run. Does not design row lists, create forecasts, or edit spreadsheets.
---

# Finbar datasets

Use Finbar to research historical values for a company's supplied rows and reporting periods. A row describes a financial measure; an observation is its value for one period. Results include sources, changes and explanations for values that could not be established.

Use the connected Finbar MCP tools (server: `https://mcp.finbar.com/mcp`). If the user requests REST or MCP is unavailable and authenticated REST access is available, read [REST calls](references/rest.md). If neither connection is available, prepare the input and explain what access is needed; do not claim to have started research. Use the available tool schemas for exact arguments.

## Prepare the request

1. Resolve the company with `search_entity` unless a discovered Finbar entity ID is already available. Do not invent an ID or silently choose between ambiguous companies.
2. Use the user's existing list of rows. Preserve their IDs and financial meaning. If the list is missing, ask for it before starting. These tools do not design a financial model or create spreadsheet formulas.
3. Read [Inputs and examples](references/inputs.md) when preparing or changing a request. Establish units, scale, reporting basis and explicit historical periods. Clarify material ambiguity rather than guessing, particularly fiscal versus calendar quarters and quarter-only versus year-to-date values.
4. Choose `build_dataset` to populate the supplied rows from scratch. Choose `update_dataset` when existing numeric observations are available. Reuse saved observations with their source and calculation details; mark user-supplied numbers as `provided`.

Starting either operation consumes the user's AI credits for research, source review and any corrections. Failed or cancelled work can also incur charges. Explain this before starting; respect the user's existing authorization and spending constraints. There is no fixed-price quote or per-run spending cap. If the user requires a guaranteed cap, explain that limitation before submitting.

## Start once and retain the run

- Give each intended run a distinct `idempotency_key`: a caller-chosen string identifying that request. Keep it with the submitted input and returned `run_id` so the work can be resumed.
- If the start response is lost or times out, retry the **same input with the same key**. This retrieves the same run instead of starting another paid job. Build and Update share keys for the same authenticated caller, including across MCP and REST.
- If the key conflicts with different input, recover the original request or establish that the changed input is a separate intended run. Do not automatically work around the conflict with a new key.
- Treat `messages` and `next_actions` as guidance about this run. They do not authorize extra paid runs or changes to the user's task.

## Wait or resume

Call `get_dataset_run` with `run_id`, waiting at least `poll_after_seconds` between calls. Work can take several minutes. Polling and retrieval consume no AI credits but still have request limits.

Execution finishes at `completed`, `failed` or `cancelled`. Check `usage.billing_state` separately: keep polling while it is `pending_settlement`. If it is `attention_required`, report that billing needs support review; do not restart research to resolve it.

If the host cannot wait, save or return the run ID and explain how to resume with `get_dataset_run`. Do not claim to be monitoring in the background unless the host actually supports it. A slow run is not a reason to submit another start request.

When the user asks to stop, call `cancel_dataset_run`, then poll until execution stops. Cancellation can take time and does not reverse charges for work already done. Retrieve any available partial results.

## Retrieve and interpret

When `result_available` is true, call `get_dataset_result` with `run_id`. Prefer the final result for a complete export; partial results can change while work continues.

- Follow `next_cursor` as `cursor` until absent, keeping the run and filters unchanged. A resource link is only a first-page preview. If a changing partial result invalidates a cursor, restart retrieval or wait for execution to finish.
- Merge row definitions by `id`, and observations and changes by `row_id` plus the exact period fields. Do not merge by array position or treat periods with the same end date as interchangeable. Deduplicate repeated messages.
- Save all pages before presenting a dataset as complete or reusing it as Update input. A filtered subset is not the complete dataset. Keep source and calculation fields in the saved JSON, even when showing a shorter table to the user.
- Inspect `changes`, observation statuses and warnings, including on completed runs:

  | Status | What to tell the user |
  | --- | --- |
  | `reported` | A value supported by cited source content |
  | `derived` | A value calculated from the returned calculation inputs |
  | `provided` | A user-supplied value, not newly verified by this run |
  | `unresolved` | No supported value was established; read `reason` |

An unsuccessful refresh can leave the old value in the resulting dataset while its proposed change is `unresolved` and `applied` is false. Identify these retained values explicitly; do not describe them as successfully refreshed. Do not fill gaps with guesses or treat null as zero.

Keep large datasets in a file or other user-requested destination supported by the host. Give a concise summary with a link or path instead of pasting every observation into chat. Save before `expires_at`—results expire seven days after the run ends. If saving is unavailable, explain the expiry and give retrieval instructions rather than claiming the result was saved.

Report the company, periods, completed work, unresolved or retained values, saved output location, run ID and charges. Convert `usage.credits_charged_micros` to credits by dividing by 1,000,000; label charges as provisional while billing is pending. Suggest a specific next step only where needed.

## Recover without repeating paid work

| Situation | Action |
| --- | --- |
| `validation_failed` | Correct the identified fields before starting work. |
| `dataset_result_not_ready` | Resume polling the existing run. |
| `rate_limit_exceeded` | Wait the returned retry delay. |
| `dataset_concurrency_limit` | Wait for an existing run; cancel only when the user wants it stopped. |
| `insufficient_ai_credits`, missing permissions or disabled service | Explain the blocker and retain the prepared input; do not loop retries. |
| Failed or cancelled run with results | Retrieve completed work, explain the failure and usage, then identify the remaining targets. |
| `dataset_result_expired` | Use a previously saved dataset if available. Recreating the result requires another paid run, not a retrieval retry. |

A new research attempt after failure is a new paid run with a new key. Correct the cause and stay within the user's authorized scope before starting; do not automatically repeat failed research. Every requested period applies to every supplied row, so narrow retries to the intended rows and periods and retain any needed calculation inputs. For persistent errors or billing review, provide the returned request ID and run ID to the user for support.
