Skip to main content

Tools reference

The MCP server advertises 19 tools: 12 read and 7 write. The canonical surface comes from the platform's tool registry; this page mirrors it. Where the rendered text disagrees with what the live server reports from tools/list, the live server is authoritative.

Every tool runs inside the authenticated user's withSession transaction. Row-level security gates visibility identically to the web app — a tool sees what the user could already see from app.evenhandhq.com.

Three concepts recur in the descriptions below:

  • feature_not_available — the tool's backing build step has not shipped to production. The tool is advertised by tools/list so clients can discover the full surface area, but every call returns { "error": "feature_not_available", "message": "..." } until the corresponding platform build step lands.
  • Write tools — must additionally pass the per-tool grant and (where applicable) the per-deal opt-in. See Write gating.
  • deal_id — a UUID identifying a deal the caller participates in. Calls naming a deal the caller cannot see return an empty result; calls naming a non-existent deal are indistinguishable from that case by design.

Read tools

evenhand_deals_list

List deals visible to the caller. Filters by state and brokerage_id.

{
"state": "string, optional, 1–32 chars",
"brokerage_id": "string, optional, 1–128 chars"
}

Returns { deals: Deal[] }. Each deal carries id, title, state, organization_id, exclusive_buyer_user_id, exclusivity_granted_at, exclusivity_expires_at, closed_at, created_at, updated_at, and a synthesized caller_role of broker_assigned, exclusive_buyer, participant, or viewer. Capped at 200 rows. RLS limits the result to deals the caller can read on the web app.

evenhand_deals_get

Fetch a single deal with its participants. RLS-bounded — non-participants get null.

{
"deal_id": "uuid, required"
}

Returns { deal: Deal | null, participants: Participant[] }. A null deal means either the deal does not exist or the caller is not on its participant list. Each participant row carries user_id, role, status.

evenhand_qoe_get

Per-category QoE progress (status, last update). Returns the deal's QoE checklist progress and most-recent accounting snapshot summary.

{
"deal_id": "uuid, required",
"category": "string, optional, 1–64 chars"
}

Returns { progress: ProgressRow[], recent_accounting_snapshots: SnapshotRow[] }. Progress rows carry id, status, completed_at, category, title; the snapshot list is the five most-recent accounting snapshots with id, snapshot_type, status, requested_at, completed_at. RLS restricts both to deals the caller participates in.

evenhand_qoe_pl_periods

P&L period rows from the accounting snapshot pipeline. Filterable by date range.

{
"deal_id": "uuid, required",
"start_date": "string (ISO date), optional",
"end_date": "string (ISO date), optional"
}

Returns { periods: PlPeriodRow[] } drawn from every accounting snapshot on the deal. Capped at 500 rows, ordered by period_start_date descending. Empty when the deal has no accounting snapshots.

evenhand_qoe_customer_concentration

Top-N customer concentration metrics derived from the accounting snapshot's customer-revenue periods.

{
"deal_id": "uuid, required",
"as_of_period": "string (ISO date), optional"
}

Returns { customers: CustomerRevenueRow[] } from the most-recent accounting snapshot, ordered by revenue total descending and capped at 50 rows. Empty when the deal has no accounting snapshots.

evenhand_findings_list

List diligence findings on a deal across all categories.

{
"deal_id": "uuid, required",
"category": "string, optional",
"severity": "enum: critical | major | minor | informational, optional",
"status": "enum: open | mitigated | accepted | resolved, optional"
}

Returns feature_not_available until Phase 2C Build Step 53 ships. Advertised in tools/list so clients can discover the surface ahead of the rollout.

evenhand_findings_get

Fetch a single finding by id.

{
"finding_id": "uuid, required"
}

Returns feature_not_available until Phase 2C Build Step 53 ships.

evenhand_questions_list

List deal Q&A visible to the caller.

{
"deal_id": "uuid, required",
"status": "string, optional, 1–64 chars"
}

Returns { questions: Question[] }. Each row carries id, category, status, asked_at, question_text, distributed_response. Capped at 200 rows, ordered by asked_at descending. RLS limits results to questions the caller may see — typically the caller's own questions as a buyer, or all questions on a deal as a broker.

evenhand_documents_list

List documents accessible to the caller — filename and metadata only. Document bodies are never returned via MCP.

{
"deal_id": "uuid, required",
"category": "string, optional, 1–64 chars",
"confidentiality_level": "enum: public | nda_gated | selected_buyer_only, optional"
}

Returns { documents: DocumentMetadata[] }. Each row carries id, filename, confidentiality, size_bytes, an upload or creation timestamp, and a source field of simple or production indicating which document table the row came from. Capped at 200 rows per source.

evenhand_offers_list

List buyer offers visible to the caller on a deal — the caller's own offers as a buyer, or every buyer's offer as a broker or seller.

{
"deal_id": "uuid, required"
}

Returns { offers: Offer[] }. Each row carries id, buyer_user_id, revision_number, is_current, submitted_at, payload. Capped at 50 rows, ordered by submitted_at descending. The payload shape is documented in the platform's offer schema.

evenhand_financing_stack_get

List the caller's financing sources on a deal.

{
"deal_id": "uuid, required"
}

Returns feature_not_available until Phase 2C Build Step 54 ships.

evenhand_closing_conditions_list

List closing conditions visible to the caller on a deal.

{
"deal_id": "uuid, required"
}

Returns { closing_conditions: ClosingCondition[] }. Each row carries id, name, status, owner_user_id, deadline, completed_at. Capped at 100 rows, ordered by created_at descending.

Write tools

Every write tool below additionally requires the mcp:write scope, an active per-tool grant, and (for deal-scoped tools) an active per-deal opt-in. See Write gating.

evenhand_findings_create

Create a finding on a deal.

{
"deal_id": "uuid, required",
"category": "string, required, 1–64 chars",
"title": "string, required, 1–120 chars",
"description": "string, optional, ≤ 8000 chars",
"severity": "enum: critical | major | minor | informational, required",
"owner_user_id": "string, optional"
}

Returns feature_not_available until Phase 2C Build Step 53 ships.

evenhand_findings_update_status

Update a finding's status.

{
"finding_id": "uuid, required",
"status": "enum: open | mitigated | accepted | resolved, required",
"status_notes": "string, optional, ≤ 8000 chars"
}

Returns feature_not_available until Phase 2C Build Step 53 ships.

evenhand_findings_comment

Add a comment to a finding's thread.

{
"finding_id": "uuid, required",
"body": "string, required, 1–8000 chars"
}

Returns feature_not_available until Phase 2C Build Step 53 ships.

evenhand_questions_create

Submit a buyer Q&A question. Requires an active NDA on the deal; broker review-required state is the default.

{
"deal_id": "uuid, required",
"category": "enum, required (see the live tools/list response for the full set of Q&A categories)",
"question_text": "string, required, 1–4000 chars"
}

Returns { id: "uuid" } on success — the new deal_questions.id, which is then in status = pending_broker_review per the standard Q&A flow.

A submission that the database rejects (no active NDA on the deal, no broker review path configured, etc.) returns a structured { "error": "submission_rejected", "message": "..." } rather than throwing. The web app's Q&A submission flow handles the same case identically.

evenhand_qoe_normalization_create

Record a financial normalization adjustment on a deal's QoE workspace.

{
"deal_id": "uuid, required",
"period_label": "string, required, 1–64 chars",
"adjustment_category": "enum: owner_comp | related_party | one_time | other, required",
"adjustment_amount": "string, required, 1–40 chars (decimal as string)",
"rationale": "string, optional, ≤ 2000 chars"
}

Returns { id: "uuid" } on success. If RLS rejects the insert — the caller is not authorized for this deal's QoE workspace — the tool returns { "error": "rls_denied", "message": "..." }.

The amount is passed as a string to preserve decimal precision end to end; the platform stores it as a numeric column.

evenhand_financing_source_create

Add a financing source to a deal's stack.

{
"deal_id": "uuid, required",
"source_type": "enum: sba_7a | sba_504 | conventional_senior_debt | mezzanine | seller_note | rollover_equity | cash_buyer_equity | equity_investor_check | earnout_credit | other, required",
"source_name": "string, required, 1–256 chars",
"commitment_amount": "integer, required, ≥ 0",
"commitment_status": "enum: identified | applied | term_sheet | committed | funded | expired | withdrawn, optional"
}

Returns feature_not_available until Phase 2C Build Step 54 ships.

evenhand_financing_source_update_status

Update commitment status on a financing source.

{
"source_id": "uuid, required",
"commitment_status": "enum: identified | applied | term_sheet | committed | funded | expired | withdrawn, required"
}

Returns feature_not_available until Phase 2C Build Step 54 ships.