# MCP Tools

> Complete catalog of the tools exposed by the Lev MCP server, including read/write classification, parameters, response shape, and links to the matching REST reference. Covers the 60 registered tools across 13 groups.

Source: https://www.lev.com/docs/build/mcp/tools

Last updated: June 2026

---
## Reading the Catalog

- **R / W** — Read tools are safe to call repeatedly. Write tools mutate state and should be gated behind human confirmation in agent workflows.
- **Parameters** — only the notable ones are listed. Most list tools accept `limit`, `offset`, and `sort` as well.
- **Enums** — all enum values are lowercase on the wire. The server lowercases user input automatically, but prompt enums in lowercase to reduce model errors.
- **Related REST page** — links to the matching reference in the Lev API docs for full schema.
- **MCP Apps helpers** — app-only tools are registered for inline widgets and are marked below. Models should not call them directly.

## Deals

| Tool | Type | Description |
|------|------|-------------|
| `list_deals` | R | Search deals. Filters: `loan_type`, `transaction_type`, `business_plan`, `min_loan_amount`, `max_loan_amount`, `archived`. See [Deals](/build/deals). |
| `get_deal` | R | Fetch a deal with optional include for financials, properties, team; the response also reports the deal's `archived` state. Takes `deal_id`. |
| `show_deal` | R | Show one deal visually as an interactive overview card on MCP Apps hosts, with headline terms, property, pipeline status, an archived badge when the deal is archived, team, and key indexed facts. Other hosts receive a compact text summary. Takes `deal_id`. Use `summarize_deal` for prose and `get_deal` for raw CRM fields. |
| `summarize_deal` | R | Narrative deal snapshot at three detail levels (`brief`, `standard`, `memo`). Takes `deal_id` and optional `detail`. Consolidates `get_deal`, `search_deal_index`, `list_term_sheets`, and `list_placements` into prose for chat surfaces; quantitative claims cite their source document. Flags archived deals and labels the pipeline stage as the last stage when archived. |
| `show_deal` | R | Visual overview of one deal, an interactive card of its headline terms, property, pipeline stage, an archived badge when archived, key financials, team, and indexed facts. Takes `deal_id`. Renders inline on MCP Apps hosts; other hosts get a compact text summary. Use for "show me / pull up / open the deal". For a written narrative use `summarize_deal`; for raw CRM fields, `get_deal`; for one metric or its source, `search_deal_index`. |
| `search_deal_index` | R | Search indexed canonical deal facts for a specific question. Takes `deal_id`, `context`, optional `min_score`, `limit`, and `include_signed_urls`. Use for source-backed underwriting facts, metrics, and provenance after resolving the deal. See [Search Index](/build/deals#search-index). |
| `list_deal_index_observations` | R | Inspect every value extracted from documents for a single deal fact. Takes `deal_id` plus `sot_id` (preferred, from a prior `search_deal_index` result) or `metric_id`. Use to show provenance, pick among candidate values, or prepare an `observation_id` for `update_deal_index_fact`. See [Index Observations](/build/deals#index-observations). |
| `update_deal_index_fact` | W | Change a deal fact's canonical value. Takes `deal_id`, `sot_id`, and exactly one of `value` (free-text replacement) or `observation_id` (promote an extracted value — preserves source provenance). Server-side editability is enforced; non-editable metrics return a clear error. See [Update Index Fact](/build/deals#update-index-fact). |
| `list_deal_index_metric_definitions` | R | List the metrics that can be recorded on a deal, each with a `suggested_write_via` routing hint. Takes `deal_id` plus optional `metric_label`, `category_id`, `limit`, `offset`. Use to discover what's recordable before `record_deal_facts`. See [Metric Definitions](/build/deals#metric-definitions). |
| `record_deal_facts` | W | Record one or more user-supplied metric values on a deal (NOI, occupancy, valuation, etc.). Takes `deal_id` and `values` — each a `metric_id` plus `value`, with optional `entity_ref` from `GET /index/entities`. If the same metric/entity already has a canonical value, this appends a user-input observation; Lev's promotion logic decides the displayed value. To correct one specific value, use `update_deal_index_fact` instead. See [Insert Index Facts](/build/deals#insert-index-facts). |
| `list_deal_memos` | R | List a deal's memos (AI-generated deal books) — both published and draft, most recently active first. Takes `deal_id` plus optional filters — `status` (`published`/`draft`), `search` (title substring), `memo_type`, `pdf_ready` — and `vault_id`, `limit` (default 20), and `offset`. Spans every vault by default; pass `vault_id` (from `list_deal_vaults`) to list only one vault's memos. Returns each memo's `uuid`, `title`, type, `status` (`published`/`draft`), published date, last-modified date, creator (`{id, name}`), `pdf_ready` flag, and the `vaults` it lives in; no PDF link (use `get_deal_memo`). See [List Memos](/build/deals#list-memos). |
| `get_deal_memo` | R | Fetch one memo for a deal with its creator, last-modified date, the `vaults` it lives in, and a ready-to-click PDF link. Takes `deal_id`, `memo_id` (the memo's `uuid`), and optional `quality` (`original` default, or `high`/`medium`/`low`). Unrendered drafts have no PDF (`pdf_ready: false`). See [Get Memo](/build/deals#get-memo). |
| `create_deal` | W | Create a new deal. Requires `title`. Optional deal fields: `loan_amount`, `loan_type`, `transaction_type`, `business_plan`, `description`, `estimated_close_date`, `sponsor_private_company_id`. Optional financial fields: `purchase_price`, `estimated_value`, `total_cost`, `total_cost_basis`, `land_cost`. |
| `update_deal` | W | Update deal fields and canonical deal-level financials. Takes `deal_id` plus fields to change. Financial fields: `purchase_price`, `estimated_value`, `total_cost`, `total_cost_basis`, `land_cost`. |
| `delete_deal` | W | Soft delete a deal. Takes `deal_id`. |
| `move_deal_to_pipeline_status` | W | Move a deal to a specific pipeline status. Takes `deal_id`, `pipeline_id`, `pipeline_status_id`. |

**Enums**

- `loan_type`: `construction`, `heavy_bridge`, `light_bridge`, `permanent`, `land`, `predevelopment`, `tbd`
- `transaction_type`: `acquisition`, `refinance`, `new_construction`, `tbd`
- `business_plan`: `stabilized`, `value_add`, `construction`, `land`

Related REST pages: [Deals](/build/deals), [Pipelines](/build/pipelines).

## Documents and Vaults

| Tool | Type | Description |
|------|------|-------------|
| `list_deal_vaults` | R | List a deal's vaults — its shared Deal Rooms (datarooms) and its private Resources area. Takes `deal_id`. Returns each vault's title, whether it is the deal's primary Deal Room, and its document count. These are the containers, not the files — use `list_deal_documents` for the files inside. |
| `list_deal_documents` | R | Browse the files uploaded to a deal, across its Resources area and any Deal Rooms. Takes `deal_id` plus optional `search`, `extension`, `folder_id`, `vault_id` (from `list_deal_vaults`), `limit`, `cursor`. Returns file metadata only — no download links. On a broad "what documents/files are on this deal" ask, also call `list_deal_memos` so uploaded files and generated deal books appear together. |
| `get_deal_document` | R | Fetch one uploaded document, including a clickable, short-lived download link. Takes `deal_id` and `document_id`. Use after `list_deal_documents` to open or download a specific file; use `get_deal_memo` instead for generated memo / deal-book PDFs. |
| `browse_deal_vaults` | R | Open a deal's document workspace — an inline browser of every vault with the documents and memos inside. Takes `deal_id`. Renders an interactive vault browser on MCP Apps hosts; other hosts get a summary with per-vault counts. For just the list of vaults use `list_deal_vaults`; for a plain document list, `list_deal_documents`. |
| `get_deal_checklist` | R | Read a deal's diligence checklists — what is still outstanding, requested, reviewing, or completed in each Deal Room. Takes `deal_id` plus optional `vault_id` (a Deal Room from `list_deal_vaults`). Returns one checklist per Deal Room, each with its sections and tasks; tasks expose `status`, assignees, expected `document_types` (`id`, `name`), and linked `files` (`document_id`, `vault_resource_id`, `name`, `origin`). This is the deal's to-do / request list, not its files — use `list_deal_documents` for uploaded files. See [List Checklists](/build/deals#list-checklists). |
| `create_checklist_task` | W | Add a task to a deal's checklist — a document request or to-do. Anchor it under exactly one of `section_id`, `checklist_id`, or `parent_task_id` (ids from `get_deal_checklist`). Optional `description`, `status`, `assigned_user_id` (from `list_team_members`), `due_date`, `document_type_ids`. To comment on a task use `create_note`; to mark one done use `complete_checklist_task`. See [Create Checklist Task](/build/deals#create-checklist-task). |
| `update_checklist_task` | W | Edit an existing checklist task — retitle, re-status, reassign, set a `due_date`, or reopen it (`is_completed=false`). Takes `task_id` from `get_deal_checklist` and sends only the fields you pass. To mark a task done use `complete_checklist_task`, not this. See [Update Checklist Task](/build/deals#update-checklist-task). |
| `complete_checklist_task` | W | Mark a checklist task done — checks it off and approves any files already attached to it. Takes `task_id` from `get_deal_checklist`. Reopen with `update_checklist_task` (`is_completed=false`). See [Complete Checklist Task](/build/deals#complete-checklist-task). |

**Enum** — checklist task `status` (`get_deal_checklist` returns it; `create_checklist_task` and `update_checklist_task` accept it): `to_do`, `requested`, `reviewing`, `updates_needed`, `approved`, `cancelled`.

To customers, "vaults" usually means the shared Deal Rooms; every deal also has one private Resources area for its own working files. When naming a vault, use its title (the Resources area shows as Deal Resources), never the raw `type` value.

## Contacts

| Tool | Type | Description |
|------|------|-------------|
| `list_contacts` | R | Search contacts. Filters: `contact_type`, `email`, `first_name`, `last_name`. |
| `get_contact` | R | Fetch a contact by `contact_id`. |
| `create_contact` | W | Create a contact linked to a company. Requires `company_id`, `contact_type`, `first_name`, `last_name`. |
| `update_contact` | W | Update any contact field. Takes `contact_id` plus fields to change. |
| `unlock_contact` | W | Reveal a masked lender contact — full name, email, phone. Takes the `contact_id` (never a placement id), spends about 200 credits, and is irreversible, so confirm the cost with the user first. Reveals a contact that Lev's AI match attached to a placement and left masked; an already-revealed or connected contact reads free through `get_contact`. Idempotent — re-running on an already-unlocked contact returns it without a second charge. See [Unlock Contact](/build/contacts#unlock-contact). |

**Enum** — `contact_type`: `lender_contact`, `sponsor`.

Related REST page: [Contacts](/build/contacts).

## Companies

| Tool | Type | Description |
|------|------|-------------|
| `list_companies` | R | Search private companies (lenders, sponsors). Filters: `name`, `state`, `city`. |
| `get_company` | R | Fetch a company by `company_id`. |
| `create_company` | W | Create a company. Requires `name` and `company_type`. Optional: `website`, `city`, `state`, and `org_id` to link the company to a lender recommendation from `get_lender_recommendations`. |
| `update_company` | W | Update any company field. Takes `company_id` plus fields to change. |

**Enum** — `company_type`: `lender`, `sponsor`.

Related REST page: [Companies](/build/companies).

## Notes

| Tool | Type | Description |
|------|------|-------------|
| `list_notes` | R | Read free-text notes (call logs, relationship context) logged on a contact, deal, placement, or company — or the comment thread on a checklist task. Requires `parent_type` and `parent_id`; optional `limit`, `cursor`. For structured underwriting facts use `search_deal_index` instead — notes are human commentary, not indexed facts. |
| `create_note` | W | Log a free-text note on a contact, deal, placement, or company — or post a comment on a checklist task. Requires `parent_type`, `parent_id`, and non-empty `text`. To record a structured deal fact, use `record_deal_facts` instead. |
| `update_note` | W | Edit the text of a note. Requires `parent_type`, `parent_id`, `note_id`, and replacement `text`. You can only edit a note you created. |
| `delete_note` | W | Permanently delete a note (hard delete, no undo). Requires `parent_type`, `parent_id`, `note_id`. You can only delete a note you created. |

**Enum** — `parent_type`: `contact`, `deal`, `placement`, `company`, `checklist_task`.

Use `checklist_task` to read or post the borrower-portal **comments** on a diligence item (for example, a document request) — the same comments your team and the borrower see and post in the portal.

Related REST pages: [Contacts](/build/contacts#list-contact-notes), [Deals](/build/deals#list-deal-notes), [Placements](/build/placements#list-placement-notes), [Companies](/build/companies#list-company-notes), [Checklist tasks](/build/deals#list-checklist-task-notes).

## Lenders

| Tool | Type | Description |
|------|------|-------------|
| `get_lender` | R | Fetch a lender by `lender_id`. Optional `include_programs` to return lending programs. Useful when a `lender_id` surfaces from placements, term sheets, or companies. |
| `recommend_lenders_for_deal` | W | Run Lev's AI lender match for a deal — ranks the lenders most likely to finance it. Takes `deal_id` and spends about 2,000 credits, so confirm the cost with the user first; called without confirmation it previews the cost and charges nothing. Matching runs in the background — read the ranked lenders with `get_lender_recommendations`. The deal needs a geocoded property and loan expectations set to be search-eligible. |
| `get_lender_recommendations` | R | Read the ranked lenders from a deal's AI match. Takes `deal_id`, paginated (`limit` defaults to 10, capped at 25; `offset`). Each result carries the lender `org_id`, an `ai_score`, the match reasoning, and relevant loan programs. Materialize one into a company with `create_company` — pass the recommendation's `organization_name` as `name`, set `company_type` to `lender`, and pass its `org_id` — then open outreach with `create_placement`. |

Related REST pages: [Lender Directory](/build/lender-directory).

## Placements

| Tool | Type | Description |
|------|------|-------------|
| `list_placements` | R | Search lender placements (outreach). Filters: `deal_id`, `status`, `lender_status`, `visibility`, `contact_id`, `private_company_id`, plus `min_created_at`/`max_created_at` and `min_updated_at`/`max_updated_at` range filters. Sort: `status`, `score`, `created_at`, `updated_at` (prefix `-` for descending). |
| `get_placement` | R | Fetch a placement by `placement_id` with match score and metadata. When Lev's AI match has attached a recommended contact, the `contact_id` is present but its identity stays masked (`contact_name` is null) until you reveal it with `unlock_contact`. |
| `create_placement` | W | Open lender outreach on a deal. Requires `deal_id` and `private_company_id`. Optional `contact_id`, `status`, `visibility`, `description`, `score`, `outreach_date`, `lender_status`. Cannot create with `status="archived"`. Omit `contact_id` and Lev may run AI contact-matching in the background: poll `get_placement` for the matched `contact_id`, then reveal it with `unlock_contact`. See [Create Placement](/build/placements#create-placement). |
| `update_placement` | W | Update a placement. Takes `placement_id` plus any of `status`, `visibility`, `description`, `score`, `outreach_date`, `lender_status`. Use `status="archived"` to remove (no DELETE verb). `deal_id`, `private_company_id`, and `contact_id` are locked at create time. See [Update Placement](/build/placements#update-placement). |

**Enums**

- `status`: `new`, `sent`, `lender_reviewing`, `terms_received`, `term_sheet_received`, `executed_ts_in_closing`, `closed`, `unresponsive`, `willing_to_negotiate`, `lender_passed`, `archived`, `carve_out`, `carve_out_closed`
- `lender_status`: `origination`, `new`, `lead_qualification`, `quotation`, `negotiation`, `offer`, `term_sheet`, `good_faith_deposit`, `diligence`, `in_closing`, `closed`, `archived`
- `visibility`: `hidden`, `masked`, `shared`

`archived` is reserved for `update_placement` and cannot be sent to `create_placement`.

Related REST page: [Placements](/build/placements).

## Pipelines

| Tool | Type | Description |
|------|------|-------------|
| `list_pipelines` | R | Fetch all pipelines with their statuses. No parameters. |
| `summarize_pipeline` | R | Narrative pipeline snapshot at three detail levels (`brief`, `standard`, `memo`). Takes optional `pipeline_id` (defaults to the lowest-order pipeline) and `detail`. Aggregates stages, per-stage deal counts, loan totals, and highlighted deals (stuck longest, closing soon) into prose. |

To read a deal's current pipeline status, call `get_deal` with `include=pipelines` (the default) — each deal returns up to 10 current pipeline rows, each including `pipeline_id`, `status_name`, and `updated_at`.

Related REST page: [Pipelines](/build/pipelines).

## Term Sheets

| Tool | Type | Description |
|------|------|-------------|
| `list_term_sheets` | R | Fetch loan quotes for a deal. Takes `deal_id`. |
| `get_term_sheet` | R | Fetch a full term sheet with rates, fees, and terms. Takes `deal_id` and `term_sheet_id`. |
| `summarize_term_sheets` | R | Narrative comparison of all term sheets on a deal at three detail levels (`brief`, `standard`, `memo`). Takes `deal_id` and optional `detail`. Computes the lowest-rate and lowest all-in-cost leaders and surfaces rate, fee, and term tradeoffs. |
| `create_term_sheet` | W | Record a lender quote against a placement. Requires `deal_id`, `placement_id`, `total_rate`, `initial_funding`, `quote_type`, and `rate_type`. Many optional fields for fees, recourse, DSCR/debt yield, extension options, etc. See [Create Term Sheet](/build/term-sheets#create-term-sheet). |
| `update_term_sheet` | W | Revise a term sheet. Takes `deal_id` and `term_sheet_id` plus any field to change. `placement_id` and `deal_id` are locked. Omitted arguments stay unchanged; the MCP wrapper does not forward explicit nulls, so the REST null-clearing behavior for `base_rate` and the non-nullable boolean 422s are reachable through the REST API only. See [Update Term Sheet](/build/term-sheets#update-term-sheet). |
| `delete_term_sheet` | W | Soft-delete a term sheet (reversible by Lev support). Takes `deal_id` and `term_sheet_id`. See [Delete Term Sheet](/build/term-sheets#delete-term-sheet). |

For term-sheet rates, `total_rate` is the spread when the term sheet has a benchmark `base_rate`. It is the all-in fixed rate only when the resulting term sheet has no benchmark (`base_rate` is `null` or `none-fixed`). For create calls, omitting `base_rate` creates a no-benchmark quote. For update calls, omitted arguments stay unchanged. For base-rate quotes, calculate all-in rate as `base_rate_value + total_rate` when both values are present.

**Enums**

- `quote_type`: `guidance`, `indication`, `soft_quote`, `hard_quote`, `term_sheet`
- `rate_type`: `fixed`, `floating`
- `recourse`: `personal_recourse`, `fund_corporate_recourse`, `non_recourse`
- `recourse_type`: `full`, `partial`, `burn_off`
- `floor_type`: `base_rate`, `total_rate`
- `prepayment_penalty`: `step_down`, `defeasance`, `minimum_interest`, `yield_maintenance`, `minimum_multiple`, `swap_breakage`, `no_prepayment_penalty`, `no_ability_to_prepay`, `flat_fee`, `other`
- `payment_method`: `accrued`, `partial`, `current_pay`
- `capital_source_type`: `balance_sheet`, `agency`, `cmbs_clo`, `warehouse`, `sba`
- `base_rate`: either an enum key (e.g. `treasury_y5`, `sofr_m1`, `prime_rate`) or the matching display value from [`get_base_rates`](#market-data) (e.g. `Treasury 5-Yr`, `SOFR 30-Day Avg`, `Prime Rate`). Use the literal `none-fixed` for fixed-rate quotes with no underlying benchmark. When you use a real base-rate value, send `total_rate` as the spread over that base rate

Related REST page: [Term Sheets](/build/term-sheets).

## Market Data

| Tool | Type | Description |
|------|------|-------------|
| `get_base_rates` | R | Current SOFR, Prime, Treasury rates. Cached ~30 minutes. No parameters. |
| `get_asset_types` | R | Property asset type classifications (Office, Multifamily, Industrial, Retail, Hotel, Self-Storage, ...). No parameters. |

Related REST page: [Market Data](/build/market-data).

## Account

| Tool | Type | Description |
|------|------|-------------|
| `get_my_profile` | R | Returns user, active account, available accounts, subscription, granted scopes. Call this first to confirm the connection. |
| `list_team_members` | R | Fetch team members in the active account. |
| `list_available_accounts` | R | Fetch accounts the user can switch to. |
| `switch_account` | W | Pin the MCP session to a specific account by name or slug (fuzzy matched). |

See [MCP Authentication](/build/mcp/auth) for how account context propagates across tool calls.

Related REST page: [Account & Team](/build/account).

## Billing

| Tool | Type | Description |
|------|------|-------------|
| `get_my_billing_summary` | R | Fetch the active account's subscription metadata and credit balance. Use before workflows that may consume credits. |

Related REST page: [Billing](/build/billing).

## MCP Apps Helpers

| Tool | Type | Description |
|------|------|-------------|
| `read_memo_pdf_bytes` | R | App-only helper used by the inline memo viewer to stream authorized memo PDF byte ranges. The model should not call this directly. |
| `read_deal_document_bytes` | R | App-only helper used by the vault browser to stream authorized uploaded-document bytes. The model should not call this directly. |

## Response Shape

Every tool returns a JSON string. The shape depends on the operation.

**List tools**

```json
{
  "deals": [ { "id": 101, "title": "..." }, { "id": 102, "title": "..." } ],
  "total": 237,
  "showing": 20,
  "has_more": true
}
```

**Detail tools**

```json
{
  "deal": { "id": 101, "title": "...", "loan_amount": 12500000 }
}
```

**Write tools**

```json
{
  "message": "Deal created successfully",
  "deal": { "id": 103, "title": "..." }
}
```

**Errors**

Errors are returned as plain strings, never as raised exceptions. Common patterns include `"Validation failed: loan_amount must be greater than 0"` or `"Deal not found: 101"`. See [MCP Errors & Limits](/build/mcp/errors-limits) for the full convention.