CellDelta Request access
Documentation

CellGuard MCP connector

Last updated: 14 July 2026 · rules-1.1 · 42 named checks

01What CellGuard is

CellGuard is an independent, deterministic validator for spreadsheet edits to financial models. When an AI assistant proposes a change to a workbook, CellGuard checks that change against a catalogue of 42 fixed, versioned rules (rules-1.1) and returns one of three verdicts before the edit is committed: block, flag or pass. Every verdict is sealed in a SHA-256 hash-chained, tamper-evident audit record.

Deterministic by construction. Identical inputs — the same workbook, edits, policy and engine version — always produce an identical verdict, for everyone, on every run. The validator is separate from whatever proposes the edit, so author and checker are never the same component.

What it does not do

Finite by design. CellGuard catches structural and quantitative breakage — overwritten formulas, magnitude and decimal slips, sign flips, broken tie-outs and roll-forwards, dependency and lookup faults, declared-identity violations. It does not claim to catch every business-logic error that recomputes to a plausible-but-wrong number with no overwrite, magnitude jump, sign flip or broken tie-out. That boundary is named, deterministic and reproducible by design.

02Connect it as an MCP server

CellGuard is exposed as a remote Model Context Protocol (MCP) server. Point any MCP-capable client — Claude Code, Cursor, the Claude Agent SDK, or any host that supports remote MCP — at the HTTPS endpoint:

https://mcp.celldelta.ai/mcp

All transport is over TLS/HTTPS. Authentication is required; if it is not configured the server fails closed and returns 503 rather than accepting unauthenticated calls. Two authentication methods are supported:

OAuth 2.1

Bearer API key

Per-client setup

What access it has

CellGuard is read-mostly: it evaluates a proposed edit or an uploaded workbook and returns a verdict. It never writes to your workbook — your own agent applies the edit. The only state-changing tools are commit (appends a decision to the audit chain) and set_policy (changes thresholds), and both are recorded. It reads only the edits or workbook you pass it and reaches no external data source.

Browser-facing endpoints enforce a strict Origin allowlist, and both per-IP and per-key token-bucket rate limiting apply. Each deployment is single-tenant: it carries one shared approval credential, and sessions are isolated by an unguessable random session_id rather than by per-user identity.

Deployment modes

Sending a workbook for a full-file check

For cross-sheet, recompute and balance checks, send the file over a side channel rather than pasting it into chat (a long base64 blob is slow and can corrupt the bytes). Call request_upload for a one-time URL, then from your code sandbox stream the raw file:

curl -sS -X POST '<upload_url>' --data-binary @model.xlsx # → {"workbook_id": "wb_…"}

Pass the returned workbook_id to verify_workbook / verify_plan / analyze_workbook. On Claude.ai, allow the host once under Settings → Capabilities → Code execution and file creation → Additional allowed domains (add mcp.celldelta.ai), or use the no-setup browser upload page the tool returns. For a quick edit-level check with no file at all, use verify_ops.

03Verdicts & coverage

Every check resolves to one of three deterministic verdicts. They are control outputs for a human or agent to act on, not advice:

Coverage is stamped on every verdict. verify_ops runs the local, edit-level checks only — it does not see cross-sheet dependency, recompute, balance or roll-forward, so a pass there is not full coverage. For those, send the file (request_uploadverify_workbook / verify_plan). On three real single-author finance models the measured false-positive rate via verify_plan (recompute on) was 0/90, Wilson 95% upper bound 4.09% — a signal on real models, not a multi-author benchmark and not a "zero false positives" claim.

04The tools

The MCP server exposes the following tools. Each has a title and read-only / destructive hints set, so a host can render and gate them correctly. They operate solely on the workbook and edits you provide and reach no external data source.

Verify core

verify_opsNo-file, edit-level pre-commit check. Send each edit's old value (and optional row context) without uploading a file. Runs local checks only (formula→value overwrite — including a formula blanked or replaced with text, magnitude/decimal slip, sign flip with row context, volatile/external injection, approximate-match lookup). Returns block / flag / pass with stamped local coverage.
verify_workbookFull-file check of an uploaded workbook. Recomputes the model and evaluates cross-sheet dependency, balance and statement tie-outs, roll-forward and the full rule set. Returns block / flag / pass at full coverage.
verify_planFull check of a batch of proposed edits against an uploaded workbook. Applies the planned ops on a recompute and returns the verdict before anything is written. Returns block / flag / pass at full coverage.
analyze_workbookRead-only structural analysis of an uploaded workbook (sheets, statements, dependency structure, health signals) to scope a model before checks. Informational; does not itself block.

Session & upload lifecycle

open_sessionStart an isolated verification session, returning an unguessable session_id that scopes subsequent calls and the audit chain.
request_uploadRequest a one-time upload URL for a workbook, then stream the raw .xlsx over HTTPS. Returns a workbook_id to pass to the full-file tools.
commitRecord an applied edit and the user's decision (accept / override / reject) as the next entry in the SHA-256 hash chain. Each entry carries the verdict of the preceding verification (verify_verdict); an accept of ops verified as block is refused and must be an explicit override. This is the canonical record of what was done.
close_sessionClose the session and release its in-memory state.

Audit & evidence record

audit_logReturn the hash-chained audit log for the session: timestamped verdicts, decisions, provenance and an ops_digest per entry. Stores digests and metadata, not cell values.
evidence_packProduce a reviewable evidence bundle of verdicts and decisions for a session, for model-risk or audit review.
model_diffReport what changed since a prior baseline or sign-off — a change-control view of the model across versions.
drift_reportSummarise drift across checks or versions, highlighting where a model has moved away from its expected state.
telemetryReturn operational counters for the deployment (verdict counts, rule activity). No cell values.

Policy & reference config

set_policyConfigure the active policy for a session or deployment — thresholds and any approved overrides that change how a verdict is reached. Changes are recorded.
explainExplain a specific verdict or rule — the reason, the cells involved and the suggested fix — so a reviewer can understand why a check fired.
rules_catalogList the full catalogue of deterministic rules behind the verdicts, with their families and tiers. Read-only.
capability_matrixShow surface × error-class × blocks-pre-commit, the named out-of-scope boundary and the measured false-positive rate with its Wilson bound. Read-only.

05A typical flow

CellGuard sits between a proposed edit and the workbook. The agent calls it before writing, presents the verdict faithfully, and only commits on a clean result.

# minimal no-file check, then commit on a clean verdict open_session() → session_id verify_ops(session_id, ops=[...]) → {verdict: "pass" | "flag" | "block", coverage, reason, ...} # on pass (or accepted flag): apply the edit in your tool, then commit(session_id, decision="accept", ops=[...]) audit_log(session_id) → hash-chained entries (digests + metadata, no cell values)

Example prompts you can give your agent:

06Skills

A skill is a reusable instruction file that tells your AI client how to use the CellGuard MCP server effectively: when to trigger it, how to sequence tool calls, and what patterns to follow. Add it to your client once and it will know how to drive CellGuard without extra prompting.

CellGuard agent skill paste-ready
---
name: cellguard
description: >
  Use CellGuard whenever an AI is about to write, change, or delete a value or
  formula in a financial spreadsheet or model (DCF, 3-statement, LBO, budget,
  consolidation, FX, any .xlsx with financial logic). Call it BEFORE applying
  the edit, present its verdict exactly as returned, and on a block verdict do
  not apply the edit or build a workaround. CellGuard is an independent,
  deterministic validator: it never runs a language model and never guesses.
---

# CellGuard: independent pre-write control for AI edits to financial models

## What it is
CellGuard is an INDEPENDENT, DETERMINISTIC validator for spreadsheet edits to
financial models. It never runs a language model and never guesses: the same
workbook, ops, policy, and engine version always produce the same verdict, for
everyone, on every run. The verdict is a CONTROL OUTPUT, not advice. You are the
author of the edit; CellGuard is the separate checker. Catalog: 42 named rules
(rules-1.1). Remote MCP endpoint: https://mcp.celldelta.ai/mcp.

## When to use this skill
Call CellGuard BEFORE you write, change, or delete any value or formula in a
financial model. Triggers include:
- Setting a cell value or replacing a formula (for example changing WACC, a
  growth rate, a margin, a tax rate, a discount factor).
- Overwriting a formula with a hardcoded number.
- A batch of proposed edits to a model before any of them is applied.
- The user asks to "check", "validate", or "gate" an edit to a spreadsheet, or
  asks for an audit-ready record of a change.
Run the check first, then act strictly on the verdict. Do not apply first and
verify after.

## Core workflow: verify, then decide, then record

### Step 1: verify (pick one path)

Path A. NO FILE (fast, edit-level only): use `verify_ops`. No upload, no
session. Pass each edit with its current value as `old_value`:

    verify_ops(ops=[
      { "type": "set_value",
        "params": {
          "cell": "G3", "value": 0.28, "old_value": "=F3/E3"
        } }
    ])

- ALWAYS include `params.old_value` (the cell's current formula or value) so the
  formula-overwrite (including a formula blanked or replaced with text) and
  magnitude/decimal checks can run.
- To also check SIGN convention, ASSUMPTION bounds, and magnitude peer-fit, add
  `params.row_context`:

    { "type": "set_value",
      "params": {
        "cell": "B12", "value": 80, "old_value": -98,
        "row_context": { "label": "Operating costs",
                         "peers": [-100, -98, -105] }
      } }

- `verify_ops` runs LOCAL, edit-level checks only. It does NOT see cross-sheet
  dependency, recompute, or balance / tie-outs. Read the stamped coverage
  (`coverage: "local"`, plus `coverage_note`): a `pass` here is NOT full
  coverage.

Path B. FULL FILE (cross-sheet dependency, recompute, balance, roll-forward):
send the workbook over the upload side channel, then verify against the whole
model.

1. Get a one-time upload URL:

       request_upload()   ->   { "upload_url": "...", "how_to": "..." }

2. In your code sandbox, stream the raw .xlsx. Do NOT base64 it into chat: that
   is slow and corrupts the bytes.

       curl -sS -X POST '<upload_url>' --data-binary @model.xlsx
       # -> {"workbook_id": "..."}

3. Verify the planned edits against the full model:

       verify_workbook(
         workbook_id="...",
         ops=[ { "type": "set_value",
                 "params": { "cell": "G3", "value": 0.28,
                             "old_value": "=F3/E3", "sheet": "DCF" } } ]
       )

For a stateful loop (several checks on one model, then commit to an audit chain),
open a session first and use `verify_plan`:

       open_session(workbook_id="...")   ->   { "session_id": "...", ... }
       verify_plan(session_id="...", ops=[ ... ])

To scope a model before checking it, call `analyze_workbook(workbook_id="...")`
(read-only Model-Health score, 0-100, plus findings; it does not itself block).

Claude.ai note: if the sandbox blocks outbound network, allowlist the host once
under Settings > Capabilities > Code execution and file creation > Additional
allowed domains (add `mcp.celldelta.ai`), or use the browser upload page
(`<server>/u`) returned in `how_to`.

### Step 2: decide (read the verdict, do not edit it)

Every verify call returns ONE tiered verdict with a stamped coverage. Present it
to the user clearly. You MAY phrase it in the user's language for readability,
but you MUST keep the verdict, the numbers, and the cell references EXACTLY as
returned. Do NOT soften, strengthen, add findings of your own, or second-guess
CellGuard itself. Do not claim an edit is safe beyond the stated coverage.

- block: a hard integrity failure (overwritten formula, ~100x magnitude slip,
  broken balance or roll-forward, circular reference, declared-identity break).
  Do NOT apply the edit and do NOT engineer a workaround. Show the reason and any
  `suggested_fixes`, and let the user decide. The user can override via policy.
- flag (the warning tier, returned on the wire as `warn`): surface it and ASK
  the user before proceeding.
- pass: no rule fired WITHIN the stamped coverage only. A `verify_ops` pass
  (`coverage: "local"`) is not full coverage; for cross-sheet, recompute, and
  balance, upload the file and use `verify_workbook` / `verify_plan`.

Deterministic fixes, when available, are in `verdict.suggested_fixes`. Use
`explain(check_type="...")` to tell the user what a check catches and its tier
(the detection method itself is intentionally not exposed).

### Step 3: record (commit the decision)

Only after the user accepts (or overrides), and after you have applied the edit
in your own tool, append the decision to the tamper-evident audit chain:

       commit(session_id="...", ops=[ ... ],
              decision="accept",        # accept | override | reject
              reason="user approved WACC change",
              provenance="ai")          # ai | human

`commit` requires a session (`open_session`). It appends a SHA-256 hash-chained
entry holding an ops digest plus metadata (no cell values). Each entry also
records the verdict of the verification that preceded it (`verify_verdict`:
block / warn / pass / unverified). A plain `decision="accept"` of ops the
session verified as block is refused — record an explicit `decision="override"`
with a reason instead, so the override is visible in the chain. Retrieve the
record with `audit_log(session_id="...")` (returns the chain and whether it is
cryptographically valid) or `evidence_pack(session_id="...")` for an
auditor-ready bundle mapped to control frameworks.

## Tool reference

VERIFY (the core pre-write checks)
- verify_ops(ops): no-file, edit-level check. Each op needs params.old_value;
  optional params.row_context. Coverage: local. Use when you cannot upload the
  file and want a fast pre-write check.
- verify_workbook(ops, workbook_id): full-model check of a plan against an
  uploaded workbook (cross-sheet, recompute, balance). Use for full coverage
  without managing a session.
- verify_plan(session_id, ops): full-model check inside a session, without
  committing. Use in a stateful verify -> commit -> audit loop.
- analyze_workbook(workbook_id): read-only Model-Health audit (0-100 score,
  findings). Does not block. Use to scope a model before checks.

UPLOAD AND SESSION (lifecycle)
- request_upload(): one-time presigned upload URL plus how_to. Always call before
  any full-file tool, then curl the .xlsx to the URL.
- open_session(workbook_id): start a stateful session (returns session_id,
  recompute availability, initial health). Use for verify_plan / commit / audit.
- commit(session_id, ops, decision, reason, provenance): apply edits in the
  session and append a tamper-evident audit entry. decision: accept | override |
  reject; provenance: ai | human. The entry records the verdict of the preceding
  verification (verify_verdict); an accept of ops verified as block is refused —
  use an explicit override with a reason. Use to record an accepted or
  overridden edit.
- close_session(session_id): free session resources. Use when done.

AUDIT, EVIDENCE, CHANGE-CONTROL (the record)
- audit_log(session_id): the append-only hash chain plus validity flag. Use to
  show the canonical record of what was done.
- evidence_pack(session_id): auditor-ready bundle (decision log plus metadata,
  mapped to EU AI Act Art. 12, SOX/ICFR, DORA, EUC/model-risk). Use for a review
  committee.
- model_diff(session_id, baseline_workbook_id): deterministic structural diff vs
  the sign-off baseline (formulas frozen to literals, formulas removed,
  aggregation basis changed AVERAGE/SUM, SUM ranges shrunk, volatile/external
  refs introduced). Defaults to the workbook as opened if baseline_workbook_id is
  omitted. Use for change-control. Reports facts, not a verdict.

POLICY AND REFERENCE (config and lookup)
- set_policy(session_id, policy): attach a versioned Policy Pack (tiers,
  tightened bounds, two_person, conventions: custom label->concept and sign
  conventions). Use to declare model identities or adjust thresholds.
- explain(check_type): what a check catches, its default tier, rules version.
  Use to explain a fired check to the user.
- rules_catalog(): the full 42-rule catalog. Use to list available rules.
- capability_matrix(): surface x error-class x blocks-pre-commit, the named
  out-of-scope boundary, and the measured false-positive rate with its Wilson
  bound. Use to show what is gated before commit.

OPERATIONAL (observability, rarely driven by the agent)
- telemetry(session_id): per-session counters (plans/edits verified, errors
  caught, decisions, dollars at risk in blocked edits). Session-scoped only.
- drift_report(session_id): per-session control evidence (volume, override rate,
  dollars-at-risk-prevented, top firing rules). Session-scoped only.

## Patterns

Quick gate, no file (single edit):
       verify_ops(ops=[{ "type":"set_value",
         "params":{ "cell":"G3","value":0.28,"old_value":"=F3/E3" } }])
   -> on pass: apply the edit; on flag: ask first; on block: do not apply, show
      reason plus suggested_fixes.

Full-coverage gate with audit trail (recommended for real models):
       request_upload()                          # -> upload_url
       curl -sS -X POST '<upload_url>' --data-binary @model.xlsx   # -> workbook_id
       open_session(workbook_id="...")           # -> session_id
       verify_plan(session_id, ops=[ ... ])      # full verdict, nothing written yet
       # user accepts -> apply the edit in your tool, then:
       commit(session_id, ops=[ ... ], decision="accept", provenance="ai")
       audit_log(session_id)                     # canonical hash-chained record

Change-control review since sign-off:
       open_session(workbook_id="<current>")
       model_diff(session_id, baseline_workbook_id="<signed-off baseline>")
   -> report exactly what changed structurally; this is facts, not a verdict.

Declared identities / tighter bounds for a specific model:
       set_policy(session_id, policy={
         "identities": [ { "name": "balance",
                           "expr": "total_assets == total_liabilities",
                           "tier": "block" } ],
         "conventions": { ... }, "tiers": { ... } })
       verify_plan(session_id, ops=[ ... ])
   Identity expressions accept cell refs or concept names (total_assets,
   gross_profit, revenue, cogs, ...), resolved to the workbook's own rows.
   Out of the box, with no policy at all, CellGuard already guards the
   balance-sheet identity and the gross-profit identity (both sign
   conventions); disable with policy default_identities: false.

## Important notes
- Verdict semantics are load-bearing. block = do not apply, no workaround; flag =
  ask first; pass = clear within the stamped coverage only. The verdict is a
  deterministic control output, not your opinion. Never invent, drop, soften, or
  strengthen a finding, and never comment on or second-guess CellGuard itself.
- The middle tier shows as flag in product copy but the wire value is `warn`;
  treat them as the same tier.
- Coverage is stamped on every verdict. `verify_ops` is edit-level only
  (`coverage: "local"`): it does NOT see cross-sheet dependency, recompute, or
  balance, so a local pass is NOT a clean full-model result. Upload the file and
  use verify_workbook / verify_plan for those.
- Endpoint is https://mcp.celldelta.ai/mcp (note the /mcp path; the bare host is
  only a status page). Auth is OAuth 2.1 plus PKCE or a bearer key; the server
  fails closed (401 until authenticated, 503 if no auth is configured).
- Send files over the upload side channel, never base64 in chat: request_upload,
  then `curl -sS -X POST '<upload_url>' --data-binary @file.xlsx` to get a
  workbook_id. On Claude.ai add `mcp.celldelta.ai` under Settings > Capabilities >
  Code execution and file creation > Additional allowed domains, or use the
  returned browser upload page.
- Determinism: identical (workbook, ops, policy, engine version) always yields an
  identical verdict. CellGuard never runs a model, never trains on your data, and
  makes no outbound call in the verification path.
- Single-tenant per deployment: sessions are isolated by an unguessable
  `session_id`, which is a session boundary, not a per-user authorization
  boundary. Deploy separate instances for separate tenants.
- Finite by design. CellGuard catches structural and quantitative faults
  (overwritten formulas, magnitude/decimal slips, sign flips, broken balance /
  roll-forward / tie-outs, dependency and lookup faults, declared-identity
  violations). It does NOT opine on business-logic correctness that recomputes to
  a plausible-but-wrong number with no structural signal. A pass is never a
  guarantee the model is correct.

07Data handling

Full details are in the Privacy Policy, the Security overview and the Terms. A Data Processing Agreement is available on request.

08Troubleshooting

09Support

Questions about connecting CellGuard, requesting an API key, a Data Processing Agreement, or a self-hosted deployment:

Krzysztof Dalewski (CellDelta)
ul. Capri 4/18, 02‑762 Warsaw, Poland
[email protected]

MCP endpoint: mcp.celldelta.ai/mcp · Site: celldelta.ai