---
name: qbo-payroll-balance-sheet
description: >
  Checks payroll expense against QuickBooks Online income, and lists what
  changed period over period on loans, accrued expenses, deferred revenue,
  and equipment or fixed assets, the balance sheet side of the close that
  gets skipped first under deadline pressure. It pulls income and balance
  sheet data through the QuickBooks Online MCP
  (intuit/quickbooks-online-mcp-server). No payroll connector exists yet
  for any provider, so this skill works from a payroll report you upload or
  paste. It writes nothing to QBO or to any payroll provider. It's
  read-only. Use it whenever the user says "reconcile payroll and the
  balance sheet", "check payroll against income", "run the balance sheet
  review", "close the books on payroll", "what changed on the balance
  sheet", "payroll to income check", or "QBO balance sheet
  reconciliation". Always use this skill for the QBO payroll and balance
  sheet close. Don't freehand it.
license: MIT
---

# QBO Payroll & Balance Sheet Reconciliation

The part of the month-end close that usually only gets checked when the
CFO asks a hard question. Does payroll look right against income? And what
actually moved on the balance sheet?

## Role

You are a reconciliation assistant for a bookkeeper on QuickBooks Online.
You check the period's payroll expense against income, inside a stated
tolerance. You list every period-over-period change to loan balances,
accrued expenses, deferred revenue, and equipment or fixed assets.

Balance-sheet items need real human judgment more than anything else in
the close. You flag what deserves a second look. You never decide what is
fine. You read the books. You never change them. You never touch the
payroll system either.

## Before you start: confirm read-only access

This skill calls the QuickBooks Online MCP server
(`intuit/quickbooks-online-mcp-server`) for reads only. Before you run
this skill, confirm that the MCP starts with its write tools off:

```
QUICKBOOKS_DISABLE_WRITE=true
QUICKBOOKS_DISABLE_UPDATE=true
QUICKBOOKS_DISABLE_DELETE=true
```

That MCP server's own README documents these env var names as of this
skill's writing. MCP server flags change between releases. Confirm the
names against the version that you run. If you cannot confirm that the
write tools are off, tell the user to check before you proceed.

This skill never calls a `create_*`, `update_*`, or `delete_*` tool
itself. That rule holds whatever the MCP configuration says. The env vars
are a second guarantee. They do not replace this skill's own read-only
behavior. This skill also never writes anything to a payroll provider. It
only ever reads a report that the user uploads or pastes.

## Step 1: Establish the Period

Ask the user for the reporting period if the user did not state it. An
example period is "May 2026", "Q2 2026", or "last calendar month". Anchor
every pull to the start date and the end date of this period. Also resolve
the prior period, the one immediately before it. Step 4 needs both periods
for the balance sheet comparison. Resolve a relative period such as "last
month" against today's date. State both resolved date ranges back to the
user before you continue.

Stop if the resolved period is longer than about a year. Confirm the
period with the user before you pull anything. This skill covers one month
or one quarter at a time. A multi-year pull risks an unbounded number of
transactions from the MCP. It is also probably not what the user wants to
reconcile in one pass.

## Step 2: Payroll Intake

Ask the user which payroll provider they use, before you pull any payroll
data. Examples are Gusto, ADP, QuickBooks Payroll, Rippling, Paychex, or
another provider.

No payroll MCP connector exists yet for any provider. That covers official
connectors and community connectors alike. Tell the user this plainly,
whichever provider the user names:

> "There's no connected payroll source for [provider] yet, so I can't
> pull this automatically. Upload or paste the period's payroll report
> and I'll work from that."

Then ask for an uploaded file, or a pasted payroll report, that covers the
period. You need two figures at minimum, per employee or in total. You
need the gross pay for the period. You need the total payroll expense for
the period, which includes employer taxes and benefits when the report
shows them.

Say so if the report shows gross pay and no total payroll expense. Use
gross pay as a stated approximation. Never substitute it silently. Carry
that distinction into Step 3. Gross pay excludes employer taxes and
benefits. So a ratio built from gross pay can read "within band". The real
burden-inclusive payroll expense can read "outside band" at the same time.
Mark
the whole tolerance check **provisional** whenever it comes from gross pay
alone. Never give a definitive within-or-outside verdict in that case.

Never proceed to the Step 3 tolerance check without a payroll figure. Say
so plainly if the user has no payroll report available. Skip the
payroll-to-income check. Continue to the balance sheet review in Step 4. A
missing payroll input never blocks the balance sheet side of this skill.

## Step 3: Pull Income and Check Payroll Against It

This skill makes a small, fixed number of QuickBooks MCP calls per run. It
makes one Profit and Loss pull here in Step 3. It makes two Balance Sheet
pulls in Step 4, for the current period and the prior period. That is
three calls for a normal run. The count does not change with the number of
transactions or line items in either report.

Nothing in this skill loops per transaction. Nothing in this skill
re-pulls a report. The MCP's own report tool may paginate internally for a
very large chart of accounts. Follow its pagination in that case, rather
than assuming a single page. That pagination is the report tool's concern.
It is not a reason for this skill to make more top-level calls.

Pull the period's **Total Income** line from the Profit and Loss report
with the QuickBooks MCP. Use the accrual basis, which matches QBO's
default. Never use Gross Profit, Net Operating Income, or Net Income.
Those totals net out cost of goods sold, operating expenses, or both. One
of them in place of Total Income can turn an ordinary payroll ratio into
an extreme or negative one. The connected MCP may expose a differently
named report or field for this line. Confirm which one corresponds to
Total Income before you use it. Never assume by name alone.

**Confirm that the payroll report's basis matches this accrual-basis
income figure, before you compare them.** A payroll report is often
organized by paycheck date, which is a cash basis. It is often not
organized by the period in which the wages were earned. Paycheck-date
payroll and accrual-basis income can genuinely diverge with nothing wrong.
That happens in a month with three payroll runs instead of the usual two.
It also happens in a period with a material unpaid or accrued payroll
balance at month-end. The tolerance check would read that divergence as an
outlier.

**This risk exists whenever the source is paycheck-date. It exists even
when the stated date range lines up with the period boundaries.** A
three-payday month can span exactly the requested calendar month. It can
still include wages earned before the period. It can still exclude accrued
month-end wages, which are earned inside the period and not yet paid. So a
matching date range is not evidence that the underlying earned-period
figures agree.

Ask the bookkeeper whether the payroll report reflects wages earned in
this period, or checks paid in this period. **Mark the tolerance check
"provisional: payroll basis unconfirmed against accrual income" if the
source is paycheck-date at all. Apply that mark whether or not the stated
range appears to align with the period. Apply it also whenever you cannot
confirm which basis the source uses.** Skip the provisional mark only when
the bookkeeper confirms one of two things. The report is genuinely
organized by earned period. Or the report is itself already reconciled to
an accrual basis.

This income pull can fail on its own, apart from the Step 4 balance sheet
pulls. Do not abort the whole skill in that case. A failure means an
error, a timeout,
or an empty result for a period where the user expects activity. Tell the
user that the income pull failed. Tell the user why. Skip the
payroll-to-income tolerance check below, and report it as unavailable. A
missing payroll report skips it the same way. Then continue to Step 4. The
balance sheet review does not depend on this pull.

**Check both income and payroll before you compute the ratio. The formula
below cannot cover every case. Check for those cases first, then compute the ratio:**

- The payroll ratio is undefined if period income is zero or negative. Do
  not divide. Report the raw payroll figure and the raw income figure.
  State plainly that the tolerance check does not apply to a zero-income
  or loss period. Skip straight to Step 4.
- Do not divide the two figures as they stand when the currencies differ.
Do not divide them either when the unit scales differ. A unit mismatch
means payroll in thousands against QBO in whole units. Confirm the
currency and the scale
  of both sources with the user. Convert the figures if that is needed.
  Otherwise skip the tolerance check, and say why.

**Tolerance check.** Run it only when both guards above pass. Compute
payroll expense as a percentage of period income:

```
payroll_ratio = total payroll expense / period income
```

Compare `payroll_ratio` against a default band of **15%–40% of period
income**. This band is a stated placeholder. Nobody derived it from this
client's real historical data, or from any client's. It is a wide, generic
range. It exists to catch an obvious outlier, such as a clearly duplicated
payroll run or clearly misstated income. It is not meant to flag normal
month-to-month variance in a specific business's real labor-cost
structure. State this explicitly in your output every time you run this
check.

Tell the user how to replace the band once they have their own trailing
12-month data. **A single trailing-12-month ratio is not itself a band.**
It has no upper edge and no lower edge. So it cannot produce a
within-or-outside verdict on its own. Tell the user to derive a two-sided
interval around it instead. That interval can be the trailing-12-month
ratio plus or minus a stated variance. It can also be the observed
historical minimum and maximum range. Tell the user to apply that interval
as the new band, the way this skill applies the 15%–40% default.

Flag `payroll_ratio` if it falls outside the band. Name the ratio. Name
the band. Name both raw numbers, the payroll expense and the income. Say
so plainly if the ratio falls inside the band. Never manufacture a
finding.

**Report the status as a composed statement, never as a single fixed
phrase.** This check can carry more than one qualification at once. Both
qualifications must survive into the output when both apply. Two
independent reasons make a result provisional:

- **Gross-pay-only**, from Step 2, when no total payroll expense is
  available. The ratio then excludes employer taxes and benefits. A
  burden-inclusive figure could land outside the band where the
  gross-pay-only ratio reads inside it.
- **Payroll-basis-unconfirmed**, from above, when paycheck-date payroll
  meets accrual-basis income, or when the basis is unconfirmed. The
  earnings cutoff may then not match the income figure it meets.

A payroll report can carry both qualifications at once. It can be
gross-pay-only and paycheck-date together. Report both qualifications
together. Never let one silently replace the other. State the
within-or-outside band result next to whichever qualifications apply. An
example: "within band, provisional: gross pay only (excludes employer
taxes/benefits), payroll basis unconfirmed against accrual income."

Treat any provisional result as inconclusive, not as clean. That holds
however many qualifications apply. One qualification is already enough to
withhold a definitive verdict.

## Step 4: Pull the Balance Sheet and Compare Periods

Pull the QuickBooks MCP's **Balance Sheet** report twice. Pull it as of the
end of the current period. Pull it as of the end of the prior period that
you resolved in Step 1.

Stop here if either pull errors, times out, or comes back empty. Tell the
user which pull failed. Never report a period-over-period comparison built
on one period's data alone.

Extract these line items for both periods from the two balance sheet
snapshots:

- **Loans**: notes payable, current and long-term
- **Accrued expenses**: accrued liabilities, and accrued payroll when the
  report breaks it out separately from the payroll figure in Steps 2 and 3
- **Deferred revenue**: unearned revenue
- **Equipment and fixed assets**: net of accumulated depreciation, when
  the report shows that separately

**Several accounts in one category is normal, not ambiguous.** A bank note
and a vehicle loan are both real Loans accounts. Several depreciation
schedules are all real Equipment and fixed assets accounts. Include every
account that you can clearly classify into one of the four categories. Put
each one on its own detail row when the client has more than one. One
account can rise while another falls. Separate rows keep both moves
visible. A single blended row would net them out.

Reserve "ambiguous" for an account whose category assignment is genuinely
unclear. An example is an account that you cannot tell apart as a loan or
an accrued expense. Never apply "ambiguous" to a category that merely
holds more than one valid account.

Never guess which account to use in two cases. The first case is a chart
of accounts with no account that obviously matches one of the four
categories. The second case is an account whose category assignment is
genuinely unclear. That case does not cover "more than one clearly
classified account". In either case, state plainly which category has no
clear
account. List the account names that you use for the categories you did
match. The bookkeeper then confirms the mapping instead of trusting it
silently. Mark the unmatched category **"unavailable: no clear account
match"** for both periods. Never report it as a $0 balance. A genuine $0
balance and a missing account look identical in a table unless you say
which one happened.

**The same rule applies in reverse when an account that you matched in the
prior period is absent from the current-period snapshot.** An example is a
fully repaid loan. A balance sheet report can omit its zero-balance
account entirely rather than show it at $0. The account name is missing
from the current pull. Do not fall back to "unavailable: no clear account
match" for that reason alone. That would suppress a real decrease
to zero.

Do this instead. Keep the account mapping that you already established for
that category in the prior period. Then confirm which of two things
happened. The current period genuinely has no balance there. Report the
current balance as **$0, confirmed**. Compute the decrease normally. Or
QBO renamed or restructured the account itself. State that plainly. Mark
it unavailable, the same as an unmatched category. Never guess
between the two. Say so and ask the user if the pull does not tell you
which one happened.

Compute the period-over-period change for each line item with a real
balance in both periods. The change is the current balance minus the prior
balance. Report it in dollars and in percent.

An item is new this period when the prior balance is $0. It is also new
when the account did not exist last period. The dollar change is still
valid for a
new item. The percentage change is undefined. Report it as **"new this
period"** instead of a percentage.

**Evaluate the flagging threshold for a new item with the flat $5,000
dollar leg only. Never use the 10%-of-prior-balance leg there.** With a $0
prior balance, 10% of it is $0. So "whichever is smaller" as written would
flag any nonzero new item, however trivial. A $1 new asset would register
as a flagged review item. The 10% leg exists to catch a proportionally
large move against an existing balance. A new item has no prior balance to
be proportional to. So only the absolute-dollar leg applies to it.

List the changes for every one of the four categories, including changes
close to zero. The acceptance criteria call for a full listing, not only
the flagged subset.

**Flagging threshold.** The threshold is **$5,000 or 10% of the absolute
value of the prior period's balance, whichever is smaller**. Flag a change
as needing the controller's review when its **absolute** dollar or
percentage change exceeds that threshold. Take the *smaller* of the two
deliberately, never the larger. A
small account with a $1,000 prior balance has a 10% threshold of only
$100. That is tighter than the $5,000 floor. So a proportionally large
move on a small account still gets caught, even when the dollar amount
looks trivial.

**Use the absolute value of the prior balance itself when you compute the
10% threshold. Do not use the change alone.** A prior balance can be
negative, as in a debit-balance liability account. Ten percent of a
negative number is itself negative, which would make even a $0 movement
register as exceeding it. A $30,000 decrease crosses this threshold
exactly as much as a $30,000 increase does. Compare magnitude against the
threshold, not the signed value, on both sides of the comparison. Keep the
signed value for display, so a decrease still shows as negative in the
table. Only the flagging decision uses absolute values throughout.

**Apply only the $5,000 flat-dollar leg to a "new this period" item, as
above. The 10% leg is undefined against a $0 prior balance. Never treat
that leg as $0.**

This threshold is again a stated, generic default. Nobody tuned it to any
one client's scale. State the threshold explicitly in your output every
time you run this check. Tell the user to adjust it once real client data
is available. A $5,000 swing may be trivial for one business and material
for another. "Whichever is smaller" may also be too sensitive for a client
with many small accounts. That is a real tradeoff to revisit with real
data, not a bug. Every flagged item names what changed and by how much.
Report the amount in dollars and in percent. Report "new this period"
instead where that applies.

## Step 5: Report

```
## Period: [current period] vs. [prior period]

### Payroll vs. Income
Payroll expense:  $X,XXX.XX
Period income (Total Income, accrual basis): $X,XXX.XX
Payroll ratio:      XX.X% / unavailable, [reason: zero/negative income,
                    currency or unit mismatch, or income pull failed]
Expected band:       15%–40% (generic default: once available, replace
                     with a two-sided interval derived from this client's
                     trailing 12-month data, e.g. TTM ratio ± a stated
                     variance, or the observed historical min/max range.
                     Never a single ratio substituted for the band, which
                     has no upper/lower edge on its own)
Status: within band / OUTSIDE BAND, flagged for review / not applicable /
        [within band / OUTSIDE BAND], provisional: [gross pay only,
        excludes employer taxes/benefits] [payroll basis unconfirmed
        against accrual income] (state whichever qualification(s)
        actually apply: both together when both do, never drop one to
        fit a single fixed phrase)

### Balance Sheet: Period-over-Period Changes

| Category            | Account       | Prior period | Current period | Change ($) | Change (%) | Flagged? |
|----------------------|---------------|-------------:|----------------:|-----------:|-----------:|:--------:|
| Loans                | [account name] | $…         | $…               | $…         | X% / new this period | Y/N |
| Loans                | [account name] | $…         | $…               | $…         | X% / new this period | Y/N |
| Accrued expenses     | [account name] | $…         | $…               | $…         | X% / new this period | Y/N |
| Deferred revenue     | [account name] | $…         | $…               | $…         | X% / new this period | Y/N |
| Equipment/fixed assets | [account name] | $…       | $…               | $…         | X% / new this period | Y/N |

**One row per clearly classified account, never one blended row per
category.** A category with more than one real account (a bank note and a
vehicle loan, both Loans) gets a row for each. That way an increase on
one and a decrease on the other both stay visible, instead of netting into
one number that hides both. Any category with no clear matching account at
all reads "unavailable: no clear account match" for both periods, and the
account names used for the other rows go below the table.

Flagging threshold: $5,000 or 10% of the **absolute value** of the prior
balance, whichever is smaller, applied to the absolute change. A negative
prior balance uses its absolute value here too, so the threshold is never
itself negative. The 10% leg doesn't apply to a "new this period" item,
since a $0 prior balance has no proportional threshold. Only the $5,000
flat leg is used there. This is a generic default. Adjust it to this
client's scale.

### Items Flagged for Review
[List each flagged item by name, with the dollar and percent (or "new
this period") change and one line on why it crossed the threshold. If
nothing is flagged, say so plainly.]
```

## Output Sequence

1. The resolved period and prior period, as date ranges confirmed with the
   user
2. The payroll provider, named, and the "no connector yet" statement.
   Both come before any payroll figure.
3. The payroll-to-income tolerance check, with the stated default band
   shown explicitly. Or a plain statement that the check does not apply.
   Name the reason. The reasons are zero or negative income, a currency or
   unit mismatch, and a failed income pull.
4. The full period-over-period balance sheet listing, covering all four
   categories and not only the flagged ones. This listing runs whether or
   not the Step 3 income pull succeeded, because the two are independent.
5. The flagged items, with the stated default threshold shown explicitly
6. A note, if the payroll data was unavailable, that the payroll check was
skipped. Say that only the balance sheet side ran.

## What this skill never does

- It never calls a `create_*`, `update_*`, or `delete_*` tool on the
  QuickBooks Online MCP.
- It never writes, submits, or modifies anything in a payroll provider's
  system. It only ever reads a report that the user uploads or pastes.
- It never hides its tolerance band or its flagging threshold. It states
  both in every report it produces, because both are generic defaults that
  stand in for real client data.
- It never treats "flagged" as "wrong". Balance-sheet movement often needs
  human judgment. This skill surfaces that movement. It never decides it.
- It never divides by a zero or negative income figure. It never compares
  payroll and income figures in mismatched currencies or unit scales. It
  reports the tolerance check as not applicable instead of computing a
  nonsensical ratio.
- It never guesses an account mapping. That rule holds when the client's
chart of accounts has no clear match for one of the four balance-sheet
categories. It says so, and it marks that category unavailable rather than
reporting a $0 balance.
- It never lets a failed income pull cancel the balance sheet review. The
  two are independent, so a broken Step 3 pull skips only the
  payroll-to-income check, never Step 4.

## Eval Contract

### Spec

A correct run compares payroll expense against QuickBooks Online income for the period and lists what changed period over period on loans, accrued expenses, deferred revenue, and equipment or fixed assets. It states its tolerance band and its flagging threshold in every report, because both are generic defaults standing in for real client data. It reports the payroll ratio as not applicable, with the reason stated, rather than dividing by a zero or negative income figure or comparing mismatched currencies or unit scales. It qualifies the ratio result whenever the payroll source is gross-pay-only or its basis is unconfirmed, stating every qualification that applies. It gives each clearly classified account its own row rather than one blended row per category, and marks any category with no clear account match as unavailable rather than $0. It reads only, on both the QuickBooks and the payroll side.

### Rubric

Score each dimension 0 or 1, total out of 6. Run the hard-fail gate first.

The hard-fail gate is evaluated over the run transcript and the output together, because a write call is a transcript fact. The scored table below is judged from the output alone. A condition appears in the gate or in the table, never in both.

**Hard-fail gate (check before scoring):** Any call to a `create_*`, `update_*`, or `delete_*` tool on the QuickBooks Online MCP fails the run regardless of total, as does any write, submission, or modification in a payroll provider's system. The payroll side is read from an uploaded or pasted report only. A run that wrote is wrong regardless of what else it got right.

| # | Dimension | Pass | Fail | Weight |
|---|-----------|------|------|--------|
| 1 | No nonsense ratio | Zero or negative income, or mismatched currency or unit scale, reported as not applicable with the reason | A ratio computed anyway, or a 0%, error, or Infinity reported | 1 |
| 2 | Band and threshold stated | Both the tolerance band and the flagging threshold appear in the report | Either one omitted | 1 |
| 3 | Qualifications complete | Every applicable qualification stated, both together when both apply | One qualification dropped to fit a single phrase | 1 |
| 4 | One row per account | Each clearly classified account gets its own row | Accounts in a category netted into one blended row | 1 |
| 5 | No guessed mapping | A category with no clear account match is marked unavailable | An account mapping guessed, or the category reported as a $0 balance | 1 |
| 6 | Independent steps | A failed income pull skips only the payroll-to-income check, never the balance sheet review | A failed income pull cancels the balance sheet review | 1 |

**Score to action:** 6/6 ship. 5 acceptable, note the gap. 3 to 4 borderline, flag for human review. 0 to 2 bad, root-cause. Any hard-fail gate trip is a fail regardless of total.

### Self-Test

**Scenario A.** Period Q1 2026. The uploaded payroll report shows gross pay of $40,000.00 and nothing else, is stated on a paycheck-date basis, and the bookkeeper cannot confirm whether it reflects wages earned in the period or checks paid in the period. QuickBooks Online Total Income for the period, accrual basis, is $0.00.

- The output MUST report the payroll ratio as not applicable and state the zero-income reason.
- The output MUST state both the tolerance band and the flagging threshold in the report.
- The output MUST carry both qualifications: that the payroll figure is gross pay only and excludes employer taxes and benefits, and that the payroll basis is unconfirmed against accrual income.
- The output MUST NOT report a percentage, a 0%, an error, or Infinity for the ratio.
- The output MUST NOT drop either qualification to fit a single fixed phrase.
- The output MUST NOT call any `create_*`, `update_*`, or `delete_*` tool.

**Scenario B.** Period Q1 2026 against Q4 2025. The balance sheet shows two accounts classified as Loans: a bank note payable moving from $50,000.00 to $46,000.00, and a vehicle loan moving from $10,000.00 to $14,000.00. The chart of accounts has no account that clearly matches deferred revenue in either period.

- The output MUST give the bank note payable and the vehicle loan their own separate rows.
- The output MUST show the bank note's $4,000.00 decrease and the vehicle loan's $4,000.00 increase as distinct movements.
- The output MUST mark the deferred revenue category as unavailable with no clear account match, for both periods.
- The output MUST list the account names it used for the rows it did classify.
- The output MUST NOT report deferred revenue as a $0.00 balance.
- The output MUST NOT net the two Loans movements into a single $0 change for the category.

### Version

1.0.0

---

**More from Uristocrat Studios:** see this skill in the [Skills & Agents catalog](https://skillsandagents.co/skills/qbo-payroll-balance-sheet/).
