Skip to main content
Glama
BilalAtique

expensify-mcp

by BilalAtique

expensify-mcp

Full-capability MCP server for Expensify, built on the Integration Server API.

Expensify's official hosted MCP (expensify.com/mcp) is deliberately read-only — it "cannot approve transactions, edit data, or move money." This server adds the write surface the Integration Server API actually exposes: creating expenses and reports, managing policies, categories, tags, members, approval routing, and expense rules.

What this can and cannot do

Can do (17 tools):

Tool

Type

Purpose

expensify_list_policies

read

List workspaces + IDs

expensify_get_policy

read

Categories, tags, report fields, tax rates, employees

expensify_get_domain_cards

read

Corporate card assignments

expensify_export_reports

read

Export reports → filename

expensify_export_card_reconciliation

read

Export card transactions → filename

expensify_download_file

read

Fetch an exported file's contents

expensify_create_expenses

write

Create expenses on an account

expensify_create_report

write

Create a report, optionally with expenses

expensify_mark_reports_reimbursed

write

Approved → Reimbursed

expensify_create_policy

write

New workspace

expensify_update_policy_categories

write

Merge/replace categories

expensify_update_policy_tags

write

Merge/replace tag groups

expensify_update_employees

write

Add/update members, roles, routing

expensify_remove_employees

write

Remove members

expensify_update_tag_approvers

write

Per-tag approvers

expensify_create_expense_rule

write

Auto-tag / billable rules

expensify_update_expense_rule

write

Modify a rule

Cannot do — no supported API exists:

  • Approving a report. There is no approve endpoint. mark_reports_reimbursed only moves Approved → Reimbursed; getting a report to Approved is app-only.

  • Moving money. Marking Reimbursed is a bookkeeping flag recording that you paid outside Expensify. No ACH, no payment.

  • Submitting a report into the approval workflow, SmartScan OCR, card issuance/limits, bank account setup, most workspace settings, Concierge chat.

The practical ceiling is "create and configure everything, read everything, but cannot approve or move money."

Related MCP server: Concur Expense MCP Server

Setup

npm install
npm run build

Generate credentials at https://www.expensify.com/tools/integrations/. They are shown once.

cp .env.example .env   # then fill in the two credential values

Safety model

These tools write to real financial records. Expensify has no sandbox tier, so protection is enforced locally:

  • EXPENSIFY_DRY_RUN defaults to true. Mutating tools return a preview of the exact payload instead of sending it. Only the literal string false disables this — a typo fails closed.

  • EXPENSIFY_ALLOWED_POLICY_IDS (optional) refuses any mutation touching a policy outside the list.

  • EXPENSIFY_MAX_BATCH_SIZE (default 100) caps records per write.

  • Guards run before the dry-run check, so a blocked write is never even previewed.

  • The partner secret is redacted from every preview and error message.

Start with dry-run on, read the previews, then flip it off for the specific operation you intend.

Hosted deployment (optional)

The server also ships an HTTP transport at api/mcp.ts, so it can run on Vercel and be added as a custom connector instead of a local subprocess.

This hosts your credentials behind your token — it is not multi-tenant. Expensify's Integration Server API has no OAuth and no delegated access, so there is no way for other users to connect their own accounts through a hosted instance. Anyone with the URL and the bearer token acts as the account whose credentials are in the environment.

Required environment variables:

Variable

Purpose

EXPENSIFY_PARTNER_USER_ID

Your Expensify credential

EXPENSIFY_PARTNER_USER_SECRET

Your Expensify credential

MCP_AUTH_TOKEN

Bearer token gating the endpoint. Generate with openssl rand -hex 32

EXPENSIFY_DRY_RUN

Recommended true until you have tested the deployment

The auth gate fails closed: if MCP_AUTH_TOKEN is unset, every request is refused with a 503 rather than exposing an unauthenticated write endpoint. Requests without a valid Authorization: Bearer <token> header get a 401.

Add it as a custom connector with the deployment's /mcp URL and the bearer token. Rotate the token by updating the env var and redeploying.

Client configuration

Claude Code:

claude mcp add expensify -- node /absolute/path/to/expensify-mcp/dist/index.js

Or in .mcp.json / claude_desktop_config.json:

{
  "mcpServers": {
    "expensify": {
      "command": "node",
      "args": ["/absolute/path/to/expensify-mcp/dist/index.js"],
      "env": {
        "EXPENSIFY_PARTNER_USER_ID": "...",
        "EXPENSIFY_PARTNER_USER_SECRET": "...",
        "EXPENSIFY_DRY_RUN": "true"
      }
    }
  }
}

Live verification status

Verified against the real API on 2026-07-27 using a throwaway workspace.

Tool

Status

list_policies

verified

get_policy

verified

create_policy

verified — created the test workspace

create_expenses

verified

create_report

verified

update_policy_categories

verified — persistence confirmed by read-back

update_policy_tags

verified — see the data-loss warning below

update_tag_approvers

verified

create_expense_rule

verified — duplicate correctly rejected on re-run

export_reports

verified — exported 18 real reports

download_file

verified — retrieved the exported CSV

update_employees / remove_employees

untested — account returns 403

export_card_reconciliation

untested — needs a card domain

mark_reports_reimbursed

untested — needs an Approved report, unreachable via API

get_domain_cards

untested — needs a verified domain

Four bugs were found and fixed, every one of them a payload-placement mistake that this API reports opaquely:

  1. Categories and tags belong at the top level of the job description, not inside inputSettings. Nested, the API returns 200 and silently discards the change.

  2. The employee updater needs dataSource: "request", entity: "generic", and the roster in a separate data form field.

  3. Export jobs need onReceive.immediateResponse, and fileExtension goes in outputSettings, not inputSettings. Without it the request blocks and then fails with a bare 500 that looks like an outage.

  4. The download job takes fileName / fileSystem at the top level and no inputSettings at all.

All four are regression-tested. The lesson generalises: when this API returns a 500, or a 200 that changes nothing, suspect payload placement before concluding the endpoint is broken or the account is limited. Comparing against a raw curl built straight from the docs is the fastest way to tell.

Data-loss warning: tag merges

Verified against the live API: a tag group is replaced wholesale even with action: "merge". Sending a group with one tag deletes every other tag in that group. merge only protects groups you did not mention.

Always expensify_get_policy first and send the complete tag list plus your additions. Categories do not behave this way — they genuinely merge.

API conventions worth knowing

These bite hard, so the schemas enforce them:

  • Amounts are integer cents. 1234 means $12.34. Floats are rejected outright — passing 12.34 would otherwise post a 100×-wrong expense.

  • Dates are strictly yyyy-MM-dd.

  • Categories and tags must already exist on the policy. Call expensify_get_policy first.

  • action: "replace" on categories/tags deletes everything not in the payload. "merge" is the safe default.

  • Rate limits: 5 requests / 10s and 20 / 60s. Both windows are enforced client-side with a queue; 429s are retried with backoff.

  • responseCode 207 means partial success — check failedReports / skippedReports in the response.

Development

npm run dev          # run from source via bun
npm test             # 27 tests
npm run type-check   # tsc --noEmit, clean
npm run build

Tests cover the rate limiter's dual-window behavior, the write-guard matrix (dry-run, allowlist, batch cap, secret redaction), transport encoding, and error mapping. The server was additionally smoke-tested over the real MCP stdio protocol.

Structure

src/
  index.ts            # MCP server, tool registration, error formatting
  lib/
    config.ts         # env parsing, fail-closed dry-run
    client.ts         # form-encoded transport, 429 retry, error mapping
    rate-limiter.ts   # dual sliding windows, serialized
    write-guard.ts    # the single chokepoint for all mutations
    errors.ts         # typed errors with explicit constructors
    schemas.ts        # shared Zod schemas (cents, dates, currency)
  tools/
    read.ts           # policy + card reads
    export.ts         # report/reconciliation export + download
    write-expenses.ts # expenses, reports, reimbursement status
    write-policy.ts   # policies, categories, tags, members, rules

Available Tools

17 tools
expensify_create_expense_ruleB
Destructive

Create an expense rule that automatically applies a tag or billable status for an employee on a policy.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionsYes
policyIDYesExpensify policy (workspace) ID
employeeEmailYesEmployee the rule applies to

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate write and destructive behavior. The description adds the important note that dry-run is enabled, so it previews only, which clarifies current behavior. However, it does not disclose other behavioral traits like error handling or necessary permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise with two sentences. The first sentence states the purpose, and the second sentence provides critical usage context (write and dry-run). No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 3 required parameters including a nested object and no output schema, the description is incomplete. It lacks information about what the dry-run preview returns, prerequisites (e.g., valid policy and employee), and any side effects beyond the dry-run note.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67%, leaving the 'actions' object partially described. The description adds meaning by referencing 'tag or billable status,' which maps to two subproperties. However, it does not enrich the understanding of policyID or employeeEmail beyond the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (create), the resource (expense rule), and its purpose (apply tag or billable status for an employee on a policy). It distinguishes from other create tools like creating expenses or reports, but does not explicitly differentiate from the sibling tool expensify_update_expense_rule.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It mentions 'Dry-run is currently ON' but does not explain under what circumstances to use this tool or when to use the update sibling instead.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_create_expensesA
Destructive

Create one or more expenses on a user account. Amounts are INTEGER CENTS (1234 = $12.34) and dates must be yyyy-MM-dd. Category and tag values must already exist on the policy — call expensify_get_policy first to check. Set externalID per expense to make re-runs traceable. Expenses can be attached to an existing report via reportID, or left standalone.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
employeeEmailYesAccount the expenses are created on
transactionListYesExpenses to create

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses that it WRITES to Expensify and that a dry-run mode is currently active, which is critical behavioral context not captured by annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two well-structured paragraphs: purpose, key formatting rules, prerequisite, idempotency, attachment option, and dry-run note. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Provides sufficient context for a write tool with no output schema, though it does not describe the response format. Sibling tools and annotations fill gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the description largely reiterates schema descriptions (e.g., amounts in cents, date format). It adds marginal value with usage hints like 'externalID for traceability'.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Create' and resource 'one or more expenses on a user account', distinguishing it from sibling tools like expensify_create_expense_rule.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance on prerequisites (categories and tags must exist, call expensify_get_policy), idempotency via externalID, and attachment option. Could be improved by contrasting with other expense creation methods.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_create_policyA
Destructive

Create a new Expensify policy (workspace). Returns the new policyID.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
typeNoPolicy tier. Defaults to team
policyNameYesName for the new workspace

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations show destructiveHint=true and readOnlyHint=false. The description adds 'WRITES to Expensify' (consistent) and importantly discloses the dry-run behavior, which is not in annotations. This provides critical behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no wasted words. Front-loaded with purpose, then return value, then important behavioral note. Excellent structure.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description adequately mentions return of policyID. Annotations cover destructive nature. Dry-run handling is explained. For a simple 2-param tool, this is sufficiently complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for both parameters. The description does not add additional parameter meaning beyond what the schema already provides, so baseline score of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Create a new Expensify policy (workspace)' with a specific verb and resource, and distinguishes from siblings like list_policies or get_policy by focusing on creation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly notes 'Dry-run is currently ON — this will preview only', guiding the agent to use this tool for preview rather than actual creation until dry-run is disabled. However, no explicit when-not-to-use or alternative tool comparisons.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_create_reportA
Destructive

Create an expense report on a policy, optionally with expenses attached in the same call. Returns the new reportID. Note: this creates the report in an unsubmitted state — the Expensify API cannot submit it for approval or approve it. Amounts are integer cents; dates are yyyy-MM-dd.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleYesReport title
fieldsNoCustom report field values, keyed by field name
expensesNoExpenses to create and attach to the new report
policyIDYesExpensify policy (workspace) ID
employeeEmailYesAccount the report is created on

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations, the description discloses that the report is created in an unsubmitted state, that the API cannot submit/approve, and that a dry-run is currently preventing actual writes. These add significant behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with clear structure, but includes a line break that could be smoothed. It is efficient and contains no extraneous information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with nested objects and no output schema, the description covers key aspects: return value, state, and temporary dry-run. It is sufficient for an agent to understand the tool's effect, though error handling is not covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for all parameters. The description adds value by clarifying amount units (cents) and date format, but this is partially redundant with schema pattern and type constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool creates an expense report on a policy, optionally attaching expenses, and returns the reportID. This distinguishes it from sibling tools like expensify_create_expenses.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives context about the unsubmitted state and dry-run, but does not explicitly instruct when to use this tool versus alternatives like expensify_create_expenses. Usage guidance is implied but not explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_download_fileA
Read-only

Download the contents of a file produced by expensify_export_reports or expensify_export_card_reconciliation, using the filename those tools return.

ParametersJSON Schema
NameRequiredDescriptionDefault
fileNameYesFilename returned by a previous export job
fileSystemNoDefaults to integrationServer

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations (readOnlyHint=true, destructiveHint=false) already indicate safe operation. The description adds context about dependency on export tools, but does not detail behavior if file is missing or size limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence with clear front-loading of purpose and no unnecessary words. The structure directly addresses what the tool does and how to use it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is adequate for a simple download tool, but lacks details about the output format or content type, which could be helpful since there is no output schema. It covers essential usage context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with parameter descriptions. The description adds semantic value by linking fileName to previous export outputs, though it does not add extra syntax or format details beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'download', the resource ('contents of a file'), and ties the tool to specific producer tools (expensify_export_reports, expensify_export_card_reconciliation), distinguishing it from sibling tools that perform other actions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states the prerequisite: use the filename from export tools. It implies the tool should be used after exports, but does not explicitly mention when not to use or alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_export_card_reconciliationA
Read-only

Export company card transactions for a given feed and date range, including transactions not yet attached to a report. Returns a filename to pass to expensify_download_file.

ParametersJSON Schema
NameRequiredDescriptionDefault
endDateYes
feedNameNoSpecific card feed; omit for all feeds on the domain
templateNoFreemarker template
startDateYes
domainNameYesCard domain, e.g. "example.com"
outputFormatNoDefaults to csv

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, which aligns with 'export' meaning read-only. The description adds the behavioral trait of returning a filename to download, which goes beyond annotations. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no fluff; front-loaded with key purpose and workflow hint. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description outlines the workflow. However, it misses details about optional parameters, error handling, or filename format, leaving completeness gaps for a tool with 6 parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 67%, moderately high. The description mentions feed and date range but does not elaborate on domainName, template, or outputFormat beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool exports company card transactions for a given feed and date range, including unreported transactions. It distinguishes from sibling tools like expensify_export_reports by specifying card transactions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is used for exporting card transactions and mentions a two-step process with download_file, but it lacks explicit guidance on when to use this versus alternatives like expensify_export_reports.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_export_reportsA
Read-only

Start an export of expense reports and return the generated filename. Filter by report IDs, date range, or approval state. Pass the returned filename to expensify_download_file to get the contents. Supply a freemarker template to control the columns, or omit it for a default CSV of reportID, name, status, date, merchant, amount, currency, category and tag.

This is the only API that enumerates reports — there is no list-reports job. Use it to count or inspect reports.

ParametersJSON Schema
NameRequiredDescriptionDefault
stateNoFilter to these report states
endDateNoInclude reports on or before this date
templateNoFreemarker template controlling output columns
startDateNoInclude reports on or after this date
approvedOnlyNo
outputFormatNoDefaults to csv
policyIDListNoLimit the export to these policies
reportIDListNoSpecific report IDs to export

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false, but the description adds valuable context: it reveals that the tool generates a file and returns its filename, and it describes the default output columns. This extra detail clarifies the tool's behavioral traits beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is relatively concise—a few sentences that front-load the main action. Every sentence contributes meaning, though it could be slightly tightened without losing clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the parameter count, schema coverage, and annotations, the description feels complete. It explains the output (generated filename), the default CSV columns, and the complementary tool. No output schema exists, but the description provides sufficient detail about return values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 88% schema description coverage, the schema already handles most parameter meanings. The description adds value by explaining the default column output when 'template' is omitted, which is not in the schema. However, it does not elaborate on all parameters, so a score of 4 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with a clear verb+resource: 'Start an export of expense reports and return the generated filename.' It also distinguishes this tool from siblings by stating it is the only API that enumerates reports, making the purpose unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit guidance is provided on when to use this tool: for filtering by report IDs, date range, or approval state. It also explains the next step—passing the returned filename to expensify_download_file—and notes that this is the sole way to enumerate reports, effectively directing the agent to this tool over alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_get_domain_cardsA
Read-only

List corporate/domain card assignments, including bank source and import history. Requires domain admin rights on the account.

ParametersJSON Schema
NameRequiredDescriptionDefault
domainNameYesDomain to query, e.g. "example.com"

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds meaningful behavioral context beyond annotations: it requires domain admin rights and describes the data returned (assignments, bank source, import history). No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: two sentences, no fluff. The purpose is front-loaded, and every word adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one parameter, no output schema), the description is largely complete. It covers purpose, content, and a key prerequisite. It could mention pagination or limits, but that is not essential for this low-complexity tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the parameter description in the schema is already clear. The tool description does not add additional semantics beyond what the schema provides, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it lists domain card assignments with specific details (bank source, import history). The verb 'List' is appropriate and distinct from sibling tools which focus on policies, reports, expenses, etc.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description specifies a prerequisite ('Requires domain admin rights'), providing clear context. It does not explicitly mention when not to use or alternatives, but given the sibling tools, there is no overlap, so the guidance is adequate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_get_policyA
Read-only

Fetch configuration for one or more policies: categories, tags, report fields, tax rates, and the employee roster. Use this to discover valid category and tag names before creating expenses, since the API rejects values that do not already exist on the policy.

ParametersJSON Schema
NameRequiredDescriptionDefault
fieldsNoWhich sections to return. Defaults to all of: categories, reportFields, tags, tax, employees
policyIDListYesPolicy IDs to fetch

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds context that the API rejects unknown values, reinforcing the read-only nature and providing behavioral insight beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tightly written sentences: first states purpose and output, second provides usage context. No redundant information; every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the moderate complexity, the description covers what the tool returns (categories, tags, etc.) and provides a critical use case. The lack of an output schema is acceptable because the description lists return sections. Slightly more detail on response structure could help, but not essential.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%; the description adds no additional parameter-level detail beyond listing the fields in prose. Baseline of 3 is appropriate as the schema already documents each parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Fetch') and resource ('configuration for one or more policies') and lists the returned sections. It distinguishes from siblings like expensify_list_policies by implying it retrieves detailed settings and provides a concrete use case.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: 'discover valid category and tag names before creating expenses' and explains the reason (API rejects unknown values). While it doesn't explicitly mention when not to use or list alternatives, the guidance is clear and actionable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_list_policiesA
Read-only

List Expensify policies (workspaces) the authenticated account can see. Returns id, name, owner, role, type and output currency for each. Start here when you need a policy ID for any other tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
adminOnlyNoOnly return policies where the account is an admin
userEmailNoFetch policies for another user the account can access

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, covering the tool's safety profile. The description adds the return fields but does not elaborate on behavioral traits such as whether the list is complete, pagination, or rate limits. It does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise at two sentences, front-loading the purpose and return fields in the first sentence and providing usage context in the second. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple list tool with two optional parameters and no output schema, the description is fairly complete: it lists return fields and gives usage context. It could mention ordering or pagination, but it is adequate for the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already describes both parameters. The description adds no additional meaning beyond what the schema provides, so the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists Expensify policies (workspaces) visible to the authenticated account, specifies returned fields, and explicitly positions it as the starting point for obtaining policy IDs, differentiating it from siblings like expensify_get_policy and expensify_create_policy.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage guidance by stating 'Start here when you need a policy ID for any other tool,' implying it is the primary listing tool. However, it does not explicitly mention when not to use it or contrast with alternatives like expensify_get_policy for fetching a single policy.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_mark_reports_reimbursedA
Destructive

Mark already-APPROVED reports as REIMBURSED. This records that payment happened outside Expensify — it does NOT move money and does NOT approve anything. Reports not already in Approved state will be rejected by the API. This is the only report-status transition the API supports.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
reportIDListYesIDs of approved reports to mark reimbursed
paymentSourceNoFree-text payment source label, e.g. "ADP"

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Description adds beyond annotations: confirms it writes (consistent with readOnlyHint=false), warns of destructiveHint, and adds critical info about dry-run mode and API rejection of non-approved reports. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences followed by a brief note. Front-loaded with key action and constraints. No wasted words; every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, description fully covers behavior: dry-run preview, precondition (approved state), side effect (records external payment), and API limitation (only transition). Complete for a 2-parameter tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema already describes both parameters with 100% coverage. Description does not add additional parameter-level detail but provides relevant context linking reportIDList to approved reports. Baseline 3 is appropriate as schema carries the burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the action: mark approved reports as reimbursed, records external payment, does not move money or approve. Distinguishes from other actions by specifying it's the only supported report-status transition.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use: only reports already in Approved state; non-approved will be rejected. Mentions dry-run is ON, so preview only. Provides clear context on when not to use (e.g., for reports not yet approved).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_remove_employeesA
Destructive

Remove members from a policy. Sets isTerminated on each record, which is how the API removes someone from their assigned policy.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
policyIDYesExpensify policy (workspace) ID
employeesYes
shouldRemoveFromUnassignedPoliciesNoAlso remove them from policies not listed here

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses that this tool writes to Expensify and sets isTerminated, aligning with destructiveHint=true. It also notes that dry-run is currently ON, providing critical behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences: purpose, implementation, and a dry-run warning. No redundant words, and key information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description explains the action, mechanism, and current dry-run state. It could mention success responses or error conditions, but overall it's fairly complete for this tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 67%, and the description adds some context (e.g., how removal works via isTerminated) but does not elaborate on parameter meanings beyond what the schema provides. Baseline score is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Remove members from a policy,' specifying both the action (remove) and the resource (policy members). It explains the internal mechanism (sets isTerminated) and distinguishes from sibling tools like expensify_update_employees.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use when you need to remove employees, but does not explicitly contrast with alternatives (e.g., expensify_update_employees). The dry-run note is helpful but not a usage guideline per se.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_update_employeesA
Destructive

Add or update members on a policy, including role, manager, approval limits and routing. Members are matched by email and updated in place. employeeEmail, managerEmail and employeeID are required for each record. To remove someone use expensify_remove_employees.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
policyIDYesExpensify policy (workspace) ID
employeesYes
notifyEmailsNoEmail these addresses a summary when the job finishes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

States it writes to Expensify and is currently in dry-run mode, adding context beyond the annotations (destructiveHint). The matching-by-email behavior is explained.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences plus a note, no fluff. Efficiently conveys the core information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, usage, and behavior. Lacks output description but mentions dry-run preview. Adequate for a mutation tool with no output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds that employeeEmail, managerEmail, employeeID are required and explains matching, but much of this is already in the schema. Schema coverage is 67%.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it adds or updates policy members with specific fields (role, manager, approval limits), and distinguishes from the sibling expensify_remove_employees.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly mentions the removal alternative and the dry-run mode, but could be more detailed about prerequisites like policy existence.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_update_expense_ruleA
Destructive

Modify an existing expense rule by its ruleID.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
ruleIDYesID of the rule to modify
actionsYes
policyIDYesExpensify policy (workspace) ID
employeeEmailYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations show destructiveHint=true and readOnlyHint=false. The description adds critical context not in annotations: 'WRITES to Expensify. Dry-run is currently ON — this will preview only.' This clearly discloses the mutation and temporary preview mode, exceeding what annotations alone provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences: the first states the action and key identifier, the second adds essential behavioral context about write and dry-run. No filler, all sentences earn their place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the action and dry-run behavior but omits details about the response format, error conditions, or permissions. For a mutation tool with no output schema, more context would be helpful, but annotations partially compensate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has ~50% description coverage (some parameters lack descriptions). The tool description does not add any parameter-level details beyond the schema, so its value is marginal. With moderate schema coverage, a baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Modify an existing expense rule by its ruleID', specifying the action (modify) and the resource (expense rule), differentiating from similar tools like expensify_create_expense_rule. The additional note about dry-run further clarifies the current behavior.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description indicates it is a write operation with dry-run enabled, but does not provide explicit guidance on when to use this tool versus alternatives (e.g., create vs update), or prerequisites like policyID or employeeEmail requirements.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_update_policy_categoriesA
Destructive

Add, update, or replace expense categories on a policy. action="merge" upserts the supplied categories and leaves others untouched. action="replace" DELETES every category not listed in this call — use with care. maxExpenseAmount is in integer cents.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionYesmerge keeps existing entries and upserts the ones provided; replace deletes every entry not present in this payload
policyIDYesExpensify policy (workspace) ID
categoriesYes

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate destructiveHint=true and readOnlyHint=false. The description adds specifics: 'WRITES to Expensify' and 'Dry-run is currently ON — this will preview only,' providing context beyond annotations. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no redundancy: first sentence states purpose, second explains actions, third adds behavioral context. Front-loaded and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers purpose, usage, and behavioral traits adequately for a write tool. However, it lacks details on the response format. No output schema exists, so a brief note on expected return would improve completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema coverage at 67%, the description adds value by explaining the action parameter's effect and noting that maxExpenseAmount is in integer cents. This complements the schema but could include more detail on categories object fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it adds, updates, or replaces expense categories on a policy. It distinguishes between merge and replace actions, which differentiates it from sibling tools like expensify_update_policy_tags.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly explains when to use merge vs replace, including a warning about replace's destructive nature. It also mentions the dry-run mode, but does not contrast with other policy update tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_update_policy_tagsA
Destructive

Add, update, or replace tags on a policy. Tags are grouped into lists; each group has a name and its own tags array.

DATA LOSS WARNING (verified against the live API): a tag group is replaced WHOLESALE even with action="merge". Any tag already in the group but absent from your payload is DELETED. Always call expensify_get_policy first, then send the full existing tag list plus your additions. action="merge" only protects OTHER groups, not tags within the groups you send.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
actionYesmerge keeps existing entries and upserts the ones provided; replace deletes every entry not present in this payload
policyIDYesExpensify policy (workspace) ID
tagGroupsYesTag lists to apply to the policy

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (destructiveHint: true), description adds a detailed DATA LOSS WARNING explaining that merge replaces tags within groups, and notes that dry-run is currently ON.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short paragraphs with clear front-loading: purpose, warning, dry-run note. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Completely covers purpose, usage, behavioral nuances, prerequisites, and current dry-run state for a mutation tool with no output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. Description adds context about action behavior and the need to include all tags, but mostly reinforces schema fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Explicitly states the tool adds, updates, or replaces tags on a policy grouped into lists. Distinguishes from sibling tools like expensify_list_policies (read-only) and expensify_update_policy_categories (different resource).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance: always call expensify_get_policy first and send full existing tag list. Explains when to use merge vs. replace and warns against data loss.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

expensify_update_tag_approversA
Destructive

Set or clear the approver for individual tags on a policy. Pass an empty string as approver to clear one. Only single-level tags are supported. Tag names must already exist on the policy.

WRITES to Expensify. Dry-run is currently ON — this will preview only.

ParametersJSON Schema
NameRequiredDescriptionDefault
policyIDYesExpensify policy (workspace) ID
tagApproversYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (destructiveHint=true), description adds critical behavioral details: 'WRITES to Expensify. Dry-run is currently ON — this will preview only.' This informs the agent that despite being destructive, current execution is safe and only returns a preview. It also clarifies tag level constraints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is extremely concise: three sentences plus a bolded warning. Every sentence adds value with zero waste. The most critical information (dry-run, tag level) is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

While description covers purpose, usage, and behavioral traits, it lacks information about the response format, especially since dry-run mode returns a preview. No output schema exists, so the description should hint at what 'preview' entails (e.g., list of changes). Also no error handling or permission notes.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema already describes all parameters (policyID, tagApprovers, name, approver). The description adds context: 'Pass an empty string as approver to clear one' and 'Tag names must already exist on the policy,' which clarifies preconditions and usage beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the action: 'Set or clear the approver for individual tags on a policy.' It specifies the resource (tags on a policy) and the action (set or clear approver), differentiating it from sibling tools like expensify_update_policy_tags which handle tag names or statuses.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Description provides clear usage context: 'Only single-level tags are supported' and 'Tag names must already exist on the policy.' It implies when to use this tool but does not explicitly state when not to use it or suggest alternatives. However, given the sibling tools, no direct alternative exists for this specific operation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 17 tool updatesv0.1.0
    • First observedexpensify_create_expense_rule
    • First observedexpensify_create_expenses
    • First observedexpensify_create_policy
    • First observedexpensify_create_report
    • First observedexpensify_download_file
    • First observedexpensify_export_card_reconciliation
    • First observedexpensify_export_reports
    • First observedexpensify_get_domain_cards
    • First observedexpensify_get_policy
    • First observedexpensify_list_policies
    • First observedexpensify_mark_reports_reimbursed
    • First observedexpensify_remove_employees
    • First observedexpensify_update_employees
    • First observedexpensify_update_expense_rule
    • First observedexpensify_update_policy_categories
    • First observedexpensify_update_policy_tags
    • First observedexpensify_update_tag_approvers

TDQS

A4.1/5.0

Scored across 17 tools

Disambiguation5/5

Every tool targets a distinct resource or action (e.g., policies, expenses, reports, employees, rules, exports). Even related tools like create/update expense rules are clearly separated, and operations like exporting vs downloading have different names and purposes.

Naming Consistency5/5

All tool names follow the exact pattern 'expensify_verb_noun' (e.g., list_policies, get_policy, create_policy, export_reports). The convention is uniform with no mixing of camelCase or other styles.

Tool Count5/5

17 tools cover the major workflows in expense management: policy lifecycle, expense/report creation, rule management, employee administration, and data export. The count feels comprehensive without being bloated.

Completeness4/5

Core CRUD operations are present for policies, expenses, reports, employees, categories, tags, and rules. The only notable gaps are lacking a policy delete tool and a direct list-reports endpoint (the export tool substitutes). Given API constraints, this is reasonable.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    MCP server for personal finance management. Enables natural language expense logging, budgeting, recurring charge detection, and statement import with deterministic local calculations.
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    An MCP server for managing SAP Concur expense reports, allowing AI agents to create and update expenses, attach receipts and attendees, and read report data, while leaving submission and approval to humans.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    MCP server for Expense, a receipt tracker that lets AI assistants capture receipts, log mileage, answer spending questions, build reports, and reconcile bank statements from your expense data.
    6
    6
    ISC