Documentation

# MCP tool reference

Every tool the Clinical Terminal MCP server exposes: health-tech vendors, the hospitals and health systems that buy from them, the people who run both, and the signals moving between them, plus the few tools that publish a page. To connect a client first, start with the [setup guide](/docs/mcp/).

Each entry lists the tool’s parameters, an example arguments object, the fields that come back and the errors it can return. Access comes with a **Landscape** subscription, which covers every tool here except the two Analysis tools; those need an enterprise key.

## Start here

Two tools answer most first questions. Reach for these before chaining anything.

For a question about *one company*, `get_vendor_dossier` takes a name and returns the profile, the hospital customers with the verbatim quote each was evidenced by, current products and recent signals — in one call, instead of four.

For a question about *a market*, `find_vendors_for_problem` takes a buyer problem in plain words and routes it to one of the KLAS Revenue Cycle segments, then returns that segment’s vendors ranked by traction.

One habit worth forming: an empty result here means **not covered**, never **does not exist**. Several tools say so explicitly in their response rather than handing back a bare empty list.

## How responses work

- Every tool returns one text content block holding JSON. Most responses are pretty-printed; get\_vendor\_dossier, get\_provider and get\_persona return compact JSON.
- **A missing key means unknown.** Null and empty fields are dropped from every row rather than sent as null, so never read an absent field as zero or false.
- A response longer than 50,000 characters is cut off and ends with … \[truncated at 50000 chars — narrow your query with filters or a smaller limit]. The two dossier tools keep to their own smaller budgets instead and list what they trimmed in meta.truncated.
- Arguments are validated against each tool’s schema before it runs. A wrong type, an out-of-range number or an unknown enum value is rejected with a validation error, so the tool-specific errors below are the ones a well-formed call can still hit.
- Numeric limits accept any number in range and are rounded down to a whole number.

## Companies & vendors

The published health-tech vendors, their products, and their own websites. Coverage is uneven: nearly every vendor has a logo and a summary, fewer have a product catalog, so a thin result means thin data rather than a thin company.

### `get_vendor_dossier`

The fastest path to any single-vendor question. One call by name returns the profile, hospital customers with their evidence quotes, current products, recent signals, ownership and what we know of the vendor’s website — instead of chaining a search, a fetch, a product lookup and a signal query.

Ask it: *“Give me the dossier on Waystar.”*

Parameters

| Name            | Type   | Description                                                                                                                     |
| --------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------- |
| vendor required | string | A vendor name (“Waystar”), vendor id or numeric slug. A unique near-miss spelling is corrected automatically. 1–200 characters. |

Example arguments

```
{
  "vendor": "Waystar"
}
```

Returns

One object. Each section can independently be replaced by an unavailable marker (see errors).

|              |                                                                                                                                    |
| ------------ | ---------------------------------------------------------------------------------------------------------------------------------- |
| vendor       | The vendor profile, as get\_vendor returns it.                                                                                     |
| customers\[] | Up to 10 customer relationships, strongest evidence first, with the evidence quote, evidence tier and citable article.             |
| products\[]  | Up to 5 current products.                                                                                                          |
| signals\[]   | Up to 5 recent signals, one per source article.                                                                                    |
| ownership\[] | Acquisitions in either direction. Omitted when none are on file.                                                                   |
| funding      | Funding and M\&A news we hold. roundsTracked is always false: this is news, not a round history.                                   |
| siteMap      | Pages we know on the vendor’s website, by category, with freshness.                                                                |
| meta         | The query, the resolved vendor, spellingCorrected when a typo was fixed, and truncated listing anything trimmed to fit the budget. |

Errors and special responses

- Ambiguous name — Returns candidates\[] (up to 5, each with id, name and domain) instead of a dossier. Call again with the id you meant.
- Unknown vendor — Entity not found: "\<id>". followed by how to pass an id: the id from search\_vendors, a numeric slug, or a terminalId. A vendor name is not an id.
- A section failed — That section becomes { unavailable: true, reason }; the rest of the dossier still comes back. Retry, or use the section’s own tool.

### `search_vendors`

Find vendors by name, domain or category. Multi-word queries match on all words, then top up with looser any-word matches; results rank exact name matches first, then by how much news a company is generating.

Ask it: *“Which vendors work in denials management?”*

Parameters

| Name           | Type    | Description                                                                             |
| -------------- | ------- | --------------------------------------------------------------------------------------- |
| query required | string  | Matched against name, domain and categories; multi-word phrases work. 1–200 characters. |
| limit optional | integer | Maximum results, 1–50. Default 20.                                                      |

Example arguments

```
{
  "query": "denials management",
  "limit": 10
}
```

Returns

An array of vendors, best match first.

|             |                                     |
| ----------- | ----------------------------------- |
| id          | Vendor id — pass it to get\_vendor. |
| name        | Vendor name.                        |
| domain      | The vendor’s web domain.            |
| summary     | Company summary.                    |
| logoUrl     | Permanent logo URL.                 |
| companyType | Always vendor.                      |

Errors and special responses

- No match — Returns { results: \[], note } instead of an array. The note is the coverage contract: a miss means Clinical Terminal does not cover the vendor, not that it does not exist.

### `get_vendor`

The full profile once you have an id or numeric slug. There is no vendor score on this server — the denial/appeals/prebill scores were retired from every read path on 2026-08-04 and are never returned.

Parameters

| Name        | Type   | Description                                                                      |
| ----------- | ------ | -------------------------------------------------------------------------------- |
| id required | string | Vendor id from search\_vendors, or the numeric slug. A vendor name is not an id. |

Example arguments

```
{
  "id": "100000001"
}
```

Returns

One vendor object.

|                           |                                                                    |
| ------------------------- | ------------------------------------------------------------------ |
| id, name, domain          | Identity.                                                          |
| slug                      | Numeric terminalId, as a string.                                   |
| summary, logoUrl          | Company summary and logo URL.                                      |
| categories\[]             | KLAS segment slugs, rolled up from the products this vendor sells. |
| foundedYear, headquarters | Company basics, when known.                                        |
| ceoName, ceoTitle         | The current CEO, when known.                                       |

Errors and special responses

- Unknown or unpublished id — Vendor not found.

### `find_vendors_for_problem`

Capability discovery through the KLAS segment index — the same taxonomy the app routes vendor discovery through. Routing is deterministic, never a model guess. Vendors rank by tracked hospital relationships, then news volume, then products in the segment.

Ask it: *“Which vendors do ambient clinical documentation?”*

Parameters

| Name             | Type    | Description                                                                                                        |
| ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------ |
| problem required | string  | A buyer problem or capability in plain words, or an exact segment name from list\_segments. At least 2 characters. |
| limit optional   | integer | Maximum vendors, 1–25. Default 10.                                                                                 |

Example arguments

```
{
  "problem": "denials management",
  "limit": 10
}
```

Returns

An object with status: "ok" and the segment it routed to.

|                                      |                                                                                                                                                        |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| segmentId, segmentName, segmentGroup | The segment the problem routed to.                                                                                                                     |
| matchMethod                          | How it routed: exact, alias or substring.                                                                                                              |
| vendors\[]                           | Ranked vendors: id, name, terminalId, domain, summary, logoUrl, up to 5 productNames in the segment, productsInSegment, customerEdges and signalCount. |

Errors and special responses

- Could not route the phrase — Returns status: "no\_route" with segmentMenu\[]. Pick the closest segment and call again with its exact name.
- Reading customerEdges — It is an ordinal traction signal, not an audited customer count. Corroborate with get\_relationships before citing a number.

### `list_segments`

Every KLAS Revenue Cycle segment with live vendor and product counts — the index behind the tool above. A zero count means no published product evidence yet, not an empty market.

Parameters

None — call it with an empty arguments object.

Example arguments

```
{}
```

Returns

An array of every segment, including empty ones.

|                           |                                                        |
| ------------------------- | ------------------------------------------------------ |
| id                        | Segment slug.                                          |
| name                      | Display name — pass it to find\_vendors\_for\_problem. |
| group, description        | The segment’s group and what it covers.                |
| vendorCount, productCount | Vendors and active products tagged with the segment.   |

### `search_products`

Search what vendors actually sell. Defaults to current products, because a large share of the catalog is discontinued; status always comes back so you can tell the difference.

Parameters

| Name                       | Type    | Description                                                     |
| -------------------------- | ------- | --------------------------------------------------------------- |
| query optional             | string  | Matched against product name and description. 1–200 characters. |
| vendor\_id optional        | string  | Restrict to one vendor’s catalog.                               |
| include\_inactive optional | boolean | Also return discontinued products. Default false.               |
| limit optional             | integer | Maximum results, 1–50. Default 20.                              |

Example arguments

```
{
  "query": "prior authorization",
  "limit": 20
}
```

Returns

An array of products, by vendor name then product name.

|                      |                                                |
| -------------------- | ---------------------------------------------- |
| id                   | Product id — pass it to get\_product.          |
| vendorId, vendorName | The vendor that sells it.                      |
| name                 | Product name.                                  |
| productType          | service, software, platform, module or device. |
| status               | active or inactive.                            |
| description          | Product description.                           |
| rcmSegments\[]       | KLAS segment slugs the product is tagged with. |

Errors and special responses

- Empty array — Usually means the vendor is not catalogued, not that it sells nothing.

### `get_product`

One product in full, with the vendor it belongs to.

Parameters

| Name        | Type   | Description                       |
| ----------- | ------ | --------------------------------- |
| id required | string | Product id from search\_products. |

Example arguments

```
{
  "id": "prod_8f2k1"
}
```

Returns

One product object, with the same fields as a search\_products row.

Errors and special responses

- Unknown id — Product not found.

### `get_vendor_pages`

A vendor’s own website as data — the pages we have crawled and classified. Filter by category to jump straight to the page worth reading.

Parameters

| Name                   | Type    | Description                                                                                                                                                      |
| ---------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendor required        | string  | Vendor name, id or numeric slug. 1–200 characters.                                                                                                               |
| category optional      | enum    | One of homepage, about, leadership, contact, news, careers, blog, legal, product, pricing, customers, integrations, demo, resources, other. Omit for every page. |
| include\_dead optional | boolean | Also return pages that no longer resolve. Default false.                                                                                                         |
| limit optional         | integer | Rows to return, 1–100. Default 50.                                                                                                                               |
| offset optional        | integer | Rows to skip, for paging. Default 0.                                                                                                                             |

Example arguments

```
{
  "vendor": "Waystar",
  "category": "customers",
  "limit": 25
}
```

Returns

One object.

|                           |                                                                                                                                                      |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendor                    | The resolved vendor: id, name, terminalId.                                                                                                           |
| pages\[]                  | Each page: page\_id (pass it to get\_page\_content), url, classification, scraped (whether we hold its text), and isDead when it no longer resolves. |
| pagesKnown, pagesReturned | Live pages we hold, and rows in this response.                                                                                                       |
| scrapedCount, deadPages   | Pages we hold text for, and pages that no longer resolve.                                                                                            |
| lastCrawledAt             | When content was last fetched — the freshness stamp.                                                                                                 |
| note                      | Why a result is empty or partial, and how to page on.                                                                                                |

Errors and special responses

- Ambiguous name — Returns candidates\[] instead of pages.
- Unknown vendor — Entity not found: "\<id>". followed by how to pass an id: the id from search\_vendors, a numeric slug, or a terminalId. A vendor name is not an id.
- Unpublished vendor — Its website corpus is not available on this server.
- No crawl yet — An empty list with a note saying we have not mapped the site — absence of data on our side, not absence of pages on theirs.
- Corpus tools switched off — An error saying the website-corpus tools are temporarily disabled; every other tool is unaffected.

### `get_page_content`

Read the text of one of those pages: product copy, case studies and bios rather than a guess from the URL. It arrives inside an explicit untrusted-content fence, because it is verbatim third-party marketing — evidence to quote, never instructions to follow.

Parameters

| Name              | Type   | Description                                                                   |
| ----------------- | ------ | ----------------------------------------------------------------------------- |
| page\_id required | string | A page\_id from get\_vendor\_pages. A URL or a vendor name is not a page\_id. |

Example arguments

```
{
  "page_id": "pg_3k9x2"
}
```

Returns

One object.

|                               |                                                                                                                   |
| ----------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| page\_id, url, classification | Which page this is.                                                                                               |
| vendor                        | The published vendor that owns the page.                                                                          |
| scraped                       | Whether we hold its text.                                                                                         |
| title, content                | When scraped: the title, and Markdown up to 10,000 characters inside a BEGIN/END UNTRUSTED WEBSITE CONTENT fence. |
| truncated                     | True when the content was cut at a paragraph boundary.                                                            |
| scrapedAt                     | When the text was fetched.                                                                                        |

Errors and special responses

- Not scraped — Not an error: scraped: false with a note to fetch the URL directly.
- Unknown page\_id — An error naming the id and where page\_ids come from.
- Page of an unpublished vendor — Its content is not available here.

### `get_my_context`

The organizations you have been working with in Clinical Terminal chat, most recent first. This is what lets an assistant resolve “that vendor” or “my target” across sessions instead of asking you again.

Ask it: *“What was I looking at last time?”*

Parameters

None — call it with an empty arguments object.

Example arguments

```
{}
```

Returns

One object.

|                   |                                                                                                                                  |
| ----------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| recentEntities\[] | Up to 25, most recent first: tid (usable with get\_relationships or get\_vendor\_dossier), name, type, lastSeenAt and seenCount. |
| updatedAt         | When the chat memory last changed.                                                                                               |

Errors and special responses

- No chat history — Plain text, not JSON: no chat memory yet, or the key has no linked user.

## Providers

The buy side: US hospitals, health systems, FQHCs, rural health clinics, ASCs, imaging centers, physician groups, skilled nursing and home health.

### `get_provider_segments`

Start any provider-market question here. Every segment with its entity count, its trailing-7-day signal volume, and the signed change against the week before. All segment keys come back, including the quiet ones, so you never have to guess whether a segment exists.

Ask it: *“Which parts of the provider market moved this week?”*

Parameters

None — call it with an empty arguments object.

Example arguments

```
{}
```

Returns

An array with one row per provider segment, zero-filled.

|                           |                                                |
| ------------------------- | ---------------------------------------------- |
| providerType              | Segment key — pass it to search\_providers.    |
| count                     | Provider entities in the segment.              |
| signals7d, signals7dPrior | Signal rows in the last 7 days, and days 8–14. |
| delta                     | The signed change between the two.             |

Errors and special responses

- Reading signal counts — They count article-by-entity rows, not distinct articles, and are non-zero only for hospital and health-system segments.

### `search_providers`

The provider counterpart to vendor search — by name, segment, state, health system or size. Names collide heavily in this data, so filter by state or size when you can.

Parameters

| Name                     | Type    | Description                                                                                                             |
| ------------------------ | ------- | ----------------------------------------------------------------------------------------------------------------------- |
| query optional           | string  | Provider name or fragment; multi-word phrases work. 1–200 characters.                                                   |
| provider\_type optional  | enum    | A segment key from get\_provider\_segments, such as health\_system, acute\_care, critical\_access, fqhc or asc.         |
| state optional           | string  | A two-letter code or a full state name (“TX” or “Texas”).                                                               |
| health\_sys\_id optional | string  | Only members of one health system — a healthSysId from a result.                                                        |
| min\_beds optional       | integer | Minimum staffed beds, 1–5000. Drops providers with no bed count, such as clinics.                                       |
| sort optional            | enum    | size (most beds first), name, or signal\_recency (newest news first). Defaults to relevance with a query, name without. |
| limit optional           | integer | Maximum results, 1–50. Default 20.                                                                                      |

Example arguments

```
{
  "query": "Baylor Scott",
  "state": "TX",
  "sort": "size",
  "limit": 10
}
```

Returns

An array of providers.

|                              |                                                               |
| ---------------------------- | ------------------------------------------------------------- |
| id, terminalId               | Either one works with get\_provider.                          |
| name, city, state            | Identity and location.                                        |
| providerSubtype, companyType | Segment key, and the coarse type it derives from.             |
| staffedBeds                  | Bed count, for hospitals and health systems.                  |
| healthSysId                  | The parent health system, for a system-to-members lookup.     |
| linkedin                     | LinkedIn URL.                                                 |
| lastSignalAt                 | Most recent news detection, for hospitals and health systems. |

Errors and special responses

- Unrecognised state — Unknown state: "\<state>". with the list of valid codes.

### `search_service_lines`

Hospitals and health systems that run a clinical department — cardiology, oncology, neurology, orthopedics and 41 more — each with the evidence that says so: staff job titles naming the department, and sections of the provider’s own website. Use it instead of search\_providers for any department question; that tool matches names only. This is a floor, not an inventory: a provider missing from the list may still run the department.

Ask it: *“Which hospitals in Texas run a cardiology program?”*

Parameters

| Name                           | Type      | Description                                                                                                                                                                                                                  |
| ------------------------------ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| service\_line required         | enum      | The department key, such as cardiology, oncology, neurology, orthopedics, obgyn, behavioral, imaging or emergency.                                                                                                           |
| state optional                 | string    | A two-letter code or a full state name (“TX” or “Texas”).                                                                                                                                                                    |
| cities optional                | string\[] | Only providers in these cities; needs state. A metro is several cities, so list the suburbs too, such as \["Houston", "Sugar Land", "The Woodlands"]. Case, “St” versus “Saint” and punctuation don’t matter.                |
| level optional                 | enum      | hospital (individual facilities), system (health-system parents) or any. A system’s beds are its system-wide total. Default hospital.                                                                                        |
| provider\_type optional        | enum      | One segment, such as acute\_care, critical\_access or childrens.                                                                                                                                                             |
| min\_beds optional             | integer   | Minimum staffed beds, 1–5000. Drops providers with no bed count.                                                                                                                                                             |
| min\_evidence optional         | enum      | strong keeps only a dedicated website section or 2+ staff titles; any also includes single mentions. Default any.                                                                                                            |
| include\_unclassified optional | boolean   | Return providers with no recorded segment, shown with a null providerType. Most are real hospitals and regional systems; a few are universities or payers, so check the name. false withholds and counts them. Default true. |
| limit optional                 | integer   | Maximum providers, 1–50. Default 25.                                                                                                                                                                                         |

Example arguments

```
{
  "service_line": "oncology",
  "state": "TX",
  "cities": [
    "Houston",
    "Sugar Land",
    "The Woodlands",
    "Katy"
  ],
  "limit": 25
}
```

Returns

One object: the line, the providers largest first, and counters that explain every provider not returned.

|                                                                                   |                                                                                                                                                                                                                |
| --------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| line                                                                              | The department key and its label.                                                                                                                                                                              |
| results\[].terminalId, openInGetProvider                                          | Pass terminalId to get\_provider as id when openInGetProvider is true. When it is false, the provider is not in the provider directory yet (mostly unclassified rows), so cite the row’s own evidence instead. |
| results\[].name, city, state, providerType, isSystem, beds, website               | The provider. beds is null when unknown.                                                                                                                                                                       |
| results\[].evidence                                                               | strength (strong or some), titles (headcount and up to 3 verbatim titles) and website (tier 1–3, pages, share of the site, up to 3 URLs).                                                                      |
| providersWithLine                                                                 | Every provider with evidence for the line.                                                                                                                                                                     |
| droppedUnclassified, droppedByFilter, droppedNoCity, droppedNoCard, droppedBySize | Why each provider read was not returned. droppedNoCity counts providers with no city on record, which a cities filter cannot match.                                                                            |
| truncated                                                                         | The scan cap stopped the sweep. Narrow by state.                                                                                                                                                               |
| asOf                                                                              | When the nightly build last ran.                                                                                                                                                                               |

Errors and special responses

- Unrecognised state — Unknown state: "\<state>". with the list of valid codes.
- cities without state — cities needs state — city names repeat across states, so pass both.
- An empty list — No provider with evidence for the department matched. That means none recorded, not none exist — read the counters.

### `get_provider`

One provider in depth: profile, health-system context including parent and largest members, technology relationships with verbatim evidence quotes, recent signals, and the clinical departments we hold evidence for. Each section says which kind of empty it is.

Parameters

| Name        | Type   | Description                                                            |
| ----------- | ------ | ---------------------------------------------------------------------- |
| id required | string | Provider id or terminalId from search\_providers. A name is not an id. |

Example arguments

```
{
  "id": "100245871"
}
```

Returns

One compact object, kept within a 20,000-character budget.

|              |                                                                                                                                                                       |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| provider     | The profile, as a search\_providers row.                                                                                                                              |
| system       | The health system, its true member count, and up to 10 largest members. Omitted when the provider has no system.                                                      |
| edges        | Up to 10 technology relationships, strongest evidence first.                                                                                                          |
| signals      | Up to 5 recent signals, one per source article.                                                                                                                       |
| serviceLines | Clinical departments, strongest evidence first — each with its label, strength, staff title headcount and website tier. An absent department is unknown, not missing. |
| meta         | The resolved provider, a coverageNote for non-hospital providers, and truncated listing anything trimmed.                                                             |

Errors and special responses

- Unknown id — Provider not found: "\<id>". — search first; names are not ids.
- A section is unavailable — { status: "unavailable", reason }: a source was down. Retry.
- A section is not tracked — { status: "not\_tracked\_for\_this\_provider\_type", reason }: relationships and signals are linked for hospitals and health systems only today, so for other providers this is unknown, not zero.

## People

People with a current role at any hospital, health system, or published vendor, investor, payor or association, plus the alumni trail behind them.

### `get_persona`

Research a role the way you would research a company. Real job titles with counts, how many people we track and at what kind of employer, duties quoted verbatim from real job postings, typical KPIs, buying role, and what people in the role say they care about — grounded in the census rather than in generic knowledge.

Ask it: *“What does a CDI nurse actually do all day?”*

Parameters

| Name           | Type   | Description                                                                                         |
| -------------- | ------ | --------------------------------------------------------------------------------------------------- |
| query required | string | A role in plain words (“CDI nurse”, “VP of revenue cycle”) or an exact personaId. 1–200 characters. |

Example arguments

```
{
  "query": "VP of revenue cycle"
}
```

Returns

One object with status: "ok".

|                                          |                                                                                                    |
| ---------------------------------------- | -------------------------------------------------------------------------------------------------- |
| personaId, label                         | The seniority-by-department group it resolved to.                                                  |
| roleDefinition                           | What the role is.                                                                                  |
| titleVariants\[]                         | Real job titles held, with counts.                                                                 |
| census                                   | How many people we track, and at which employer types.                                             |
| responsibilities\[], kpis\[], buyingRole | What the role does and is measured on.                                                             |
| jdQuotes                                 | Quotes from real job postings, fenced as untrusted text.                                           |
| aggregated                               | What people in the role say they care about. Withheld below an anonymity floor, and note says why. |

Errors and special responses

- No match — status: "no\_route" with personaMenu\[]. Pick the closest personaId and call again.
- More than one match — status: "ambiguous" with candidates\[]. Call again with one of them; never guess.

### `search_people`

Find people by name, employer or job title, or everyone at one organization. Every result holds a current role at a visible organization and lists the person’s other current roles. Pass at least one of query, organization\_id or department.

Parameters

| Name                      | Type    | Description                                                                                                                                                               |
| ------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| query optional            | string  | Matched against name, employer and job title. 1–200 characters.                                                                                                           |
| organization\_id optional | string  | Only people currently at this organization.                                                                                                                               |
| vendor\_id optional       | string  | Older name for organization\_id. Pass one or the other.                                                                                                                   |
| department optional       | enum    | One of clinical, operations, general, finance, recruiting, customer\_success, marketing, engineering, legal, data, product, sales, security, design, editorial, research. |
| role optional             | enum    | Seniority: c\_suite, vp, director, or executive for all three. Does not count as a filter on its own.                                                                     |
| limit optional            | integer | Maximum results, 1–50. Default 20.                                                                                                                                        |

Example arguments

```
{
  "query": "revenue cycle",
  "role": "executive",
  "limit": 10
}
```

Returns

An array of people, one row per person, showing the most senior role that matched.

|                              |                                                                                                             |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------- |
| id                           | Person id — pass it to get\_person.                                                                         |
| name, jobTitle, organization | Who, and the role shown.                                                                                    |
| positionLevel                | Seniority: CEO, President, C\_Suite, VP, Director, …                                                        |
| functionalDepartment         | Department of that role.                                                                                    |
| personaId                    | \<level>\_\<department>, such as c\_suite\_ceo. An absent value means the role is unclassified, not junior. |
| headline, imageUrl, linkedin | Profile headline, photo and LinkedIn.                                                                       |
| otherCurrentRoles\[]         | Up to 5 other visible roles, most senior first.                                                             |
| otherCurrentRolesHidden      | Other roles at employers we cannot name.                                                                    |

Errors and special responses

- No filter — Provide at least one of query, organization\_id, or department.
- organization\_id and vendor\_id disagree — An error asking for one of them.
- People held back — A second text block after the results counts people who matched but whose roles are at organizations not published here. Treat it as a coverage gap.

### `get_person`

One profile in full: title, employer, other current roles, past roles, headline, headshot and LinkedIn.

Parameters

| Name        | Type   | Description                               |
| ----------- | ------ | ----------------------------------------- |
| id required | string | Person id from search\_people, or a slug. |

Example arguments

```
{
  "id": "Xk29fPq7LmN3"
}
```

Returns

One person object with the fields of a search\_people row, plus:

|                   |                                                                                              |
| ----------------- | -------------------------------------------------------------------------------------------- |
| pastRoles\[]      | Up to 25 closed roles, newest departure first, with employer, title and dated start and end. |
| pastRolesWithheld | Past employers we cannot name.                                                               |

Errors and special responses

- Not found — Person not found. Also returned for a person with no current role at a visible organization.

### `search_alumni`

The departures side of the graph. Anchor on a vendor and get each person’s past role with a dated departure, plus every current role they hold, most senior first. Current employers are named when published and counted when not.

Ask it: *“Who left Epic in the last year and where did they land?”*

Parameters

| Name                 | Type    | Description                                                      |
| -------------------- | ------- | ---------------------------------------------------------------- |
| vendor\_id required  | string  | A published vendor’s id or numeric slug. A name is not an id.    |
| left\_after optional | date    | YYYY-MM-DD. Only people who left on or after this date.          |
| role optional        | enum    | Seniority of the past role: c\_suite, vp, director or executive. |
| department optional  | string  | Department of the past role, such as sales or engineering.       |
| limit optional       | integer | Maximum people, 1–50. Default 25.                                |

Example arguments

```
{
  "vendor_id": "100000001",
  "left_after": "2025-09-01",
  "role": "executive"
}
```

Returns

One object.

|                      |                                                                                                                                                            |
| -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vendor               | The anchor vendor.                                                                                                                                         |
| results\[]           | Newest departure first: the person, their pastRole at the vendor with dates, and every currentRoles\[] entry, with customer evidence for vendor employers. |
| totalMatched         | Everyone with a past role at the vendor, before filters.                                                                                                   |
| \_dropped\* counters | Why matched people are missing, by reason.                                                                                                                 |

Errors and special responses

- Unknown or unpublished vendor — Vendor not found: "\<id>". — pass an id from search\_vendors.
- Undated departures — Excluded when left\_after is set, and counted in the drop counters.

### `search_retirements`

Executives who will retire or have retired, each with the last day, a confidence and who said so. Editor-confirmed retirements (a published story) come first; after them, people whose own LinkedIn profile says they have retired, marked low confidence. Every row is backed by a sourced claim, and the list grows as retirements are recorded.

Ask it: *“Which health-system CEOs have announced they are retiring?”*

Parameters

| Name                     | Type    | Description                                                                                                 |
| ------------------------ | ------- | ----------------------------------------------------------------------------------------------------------- |
| status optional          | enum    | announced (last day still ahead), completed, or any. Default any.                                           |
| seat optional            | string  | A seat such as ceo, cfo, cno or cio.                                                                        |
| since optional           | date    | YYYY-MM-DD. Only last days on or after this date; rows with no last day are excluded.                       |
| min\_confidence optional | enum    | high returns editor-confirmed retirements only; low or any also returns LinkedIn self-reports. Default any. |
| limit optional           | integer | Maximum people, 1–50. Default 25.                                                                           |

Example arguments

```
{
  "status": "announced",
  "seat": "ceo"
}
```

Returns

One object.

|                                                |                                                                                                                                                                                                            |
| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| results\[]                                     | Announced first (soonest last day first), then completed, editor-confirmed before self-reported: the person, organization, seat, lastDay, status, confidence, the reporting source and every claims entry. |
| retirementsRecorded                            | Every retirement on record.                                                                                                                                                                                |
| droppedByFilter, droppedNoPhoto, droppedBySize | Why rows are missing; droppedBySize above zero means narrow the query or lower limit.                                                                                                                      |
| organizationHidden                             | People returned with the organization left blank because it is not published.                                                                                                                              |
| note                                           | What the list does and does not cover.                                                                                                                                                                     |

Errors and special responses

- Empty results — No matching retirements are recorded yet — not an error.

## Signals

What the market did lately — news, funding, leadership changes.

### `search_signals`

Recent market signals, newest first. Filter by text, by the entity a signal came from, by type, by source format, or by a detection window.

Ask it: *“Show me every funding round in revenue cycle since May.”*

Parameters

| Name                          | Type    | Description                                                                                            |
| ----------------------------- | ------- | ------------------------------------------------------------------------------------------------------ |
| query optional                | string  | Matched against title and summary. 1–200 characters.                                                   |
| entity\_id optional           | string  | Only signals about this entity.                                                                        |
| origin\_entity\_type optional | enum    | vendor, provider (includes hospitals), hospital, investor or organization.                             |
| signal\_type optional         | string  | An exact, case-sensitive category such as Funding / Investment or Leadership Change.                   |
| source\_type optional         | enum    | The source format, such as news\_article, press\_release, linkedin\_post, sec\_filing or job\_posting. |
| detected\_after optional      | date    | ISO date or UTC datetime. On or after.                                                                 |
| detected\_before optional     | date    | ISO date or UTC datetime. On or before; a bare date includes the whole day.                            |
| sort optional                 | enum    | importance or recency. Accepted, but results currently always come back newest first. Default recency. |
| distinct\_articles optional   | boolean | One row per article instead of one per article and linked entity. Default false.                       |
| limit optional                | integer | Maximum rows, 1–50. Default 20.                                                                        |

Example arguments

```
{
  "signal_type": "Funding / Investment",
  "detected_after": "2026-05-01",
  "distinct_articles": true,
  "limit": 50
}
```

Returns

An array of signals, newest first.

|                                  |                                                                             |
| -------------------------------- | --------------------------------------------------------------------------- |
| id, articleId                    | Row id, and the article it came from — group on articleId to count stories. |
| title, summary, sourceUrl        | The story.                                                                  |
| detectedAt                       | When we detected it.                                                        |
| topics\[], categories\[]         | What it is about. Prefer these to signalType.                               |
| originEntityId, originEntityType | Which entity the row is about.                                              |
| linkedEntityCount                | How many entities the article names.                                        |
| urgency, painPoint, salesAngle   | Machine-written sales analysis.                                             |

Errors and special responses

- Empty array — Nothing matched; there is no coverage note on this tool.

## Graph

Who runs what. This is the only place hospitals are addressable as an anchor.

### `resolve_hospital`

Turn a hospital name into the id the relationship lookup accepts. Resolution only, not a profile — it returns ranked candidates so you can pick the right St. Mary’s before you ask about edges.

Parameters

| Name           | Type    | Description                                                |
| -------------- | ------- | ---------------------------------------------------------- |
| query required | string  | Hospital name or part of one. 1–200 characters.            |
| state optional | string  | A two-letter state code. Full names are not accepted here. |
| limit optional | integer | Maximum candidates, 1–20. Default 10.                      |

Example arguments

```
{
  "query": "Massachusetts General",
  "state": "MA",
  "limit": 5
}
```

Returns

An array of candidates, largest by staffed beds first.

|                           |                                                    |
| ------------------------- | -------------------------------------------------- |
| terminalId                | The preferred get\_relationships input.            |
| id                        | Also accepted by get\_relationships.               |
| name, city, state         | Which hospital this is.                            |
| hospitalType, staffedBeds | Type and size, to tell same-named hospitals apart. |

Errors and special responses

- Empty array — No hospital matched.

### `get_relationships`

Company-to-company edges touching an entity, with provenance: source, evidence quote, evidence tier, a citable article and when it was first seen. The anchor can be a vendor or a hospital, which is what makes “what does this hospital run” answerable.

Ask it: *“What technology does Mass General run?”*

Parameters

| Name                | Type    | Description                                                                 |
| ------------------- | ------- | --------------------------------------------------------------------------- |
| entity\_id required | string  | A vendor or hospital id, numeric slug or terminalId. Not a name.            |
| edge\_type optional | string  | A relationship type such as CUSTOMER\_OF or INVESTED\_IN; case-insensitive. |
| limit optional      | integer | Maximum edges, 1–200. Default 50.                                           |

Example arguments

```
{
  "entity_id": "100000001",
  "edge_type": "CUSTOMER_OF",
  "limit": 100
}
```

Returns

An array of edges, active first. When some were withheld it is instead { relationships, withheld, note }.

|                                  |                                                                                                   |
| -------------------------------- | ------------------------------------------------------------------------------------------------- |
| edgeType, relationshipLabel      | The type to filter on, and its plain-English form.                                                |
| label                            | The organization on the other end.                                                                |
| sourceId, targetId               | terminalIds of the two ends.                                                                      |
| evidenceSnippet, evidenceTier    | The supporting quote, and its strength: 1 case study, 2 customer list, 3 logo or passing mention. |
| evidenceNamesLabel               | Whether the quote actually names the other organization.                                          |
| topArticleUrl                    | An article to cite.                                                                               |
| firstSeenAt, lastConfirmedAt     | When the edge was first and last seen.                                                            |
| corroborated, corroborationQuote | Independent corroboration, when checked.                                                          |

Errors and special responses

- Unknown id — Entity not found: "\<id>". followed by how to pass an id: the id from search\_vendors, a numeric slug, or a terminalId. A vendor name is not an id.
- Withheld edges — Counted in withheld: the other organization is unpublished and cannot be named. Say “at least” when counting.

## Publishing

The only tools here that write. Everything above is read-only.

### `publish_page`

Publish a page your assistant composed — a market analysis, a vendor write-up, an article — as a hosted page on clinicalterminal.com, styled like the product and stamped with its publish date. Unlisted by default: only someone with the link can read it. A public page gets a keyword URL, a sitemap listing and a Markdown twin for other agents.

Parameters

| Name                   | Type      | Description                                                                                                                                   |
| ---------------------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| title required         | string    | Page title, 1–200 characters. Be specific.                                                                                                    |
| body\_html required    | string    | The page body only — what goes inside \<body>, using the allowed tags and .ct-\* classes. Up to 256 KB.                                       |
| summary required       | string    | One sentence, up to 500 characters: the meta description and list subtitle.                                                                   |
| citations optional     | array     | Up to 50 { label, url } sources, rendered in the page footer. Default \[].                                                                    |
| source\_tools optional | string\[] | Which tools on this server produced the data. Default \[].                                                                                    |
| visibility optional    | enum      | unlisted (unguessable link, not indexed) or public (indexable). Use public only when the user asks for a discoverable page. Default unlisted. |
| page\_type optional    | enum      | comparison, analysis or article: the visual register. Guessed from the title when omitted.                                                    |
| artifact\_id optional  | string    | Omit to create a page. Pass an existing id to update it in place at the same URL; visibility and page\_type are then ignored.                 |

Example arguments

```
{
  "title": "Texas acute-care hospitals: Q3 news activity",
  "summary": "Twelve Texas systems drove most provider news this quarter.",
  "body_html": "<h1>Texas acute-care activity</h1><p>Baylor Scott and White led signal volume.</p>",
  "page_type": "analysis"
}
```

Returns

One object.

|                           |                                                                                   |
| ------------------------- | --------------------------------------------------------------------------------- |
| url                       | The page URL — give it to the user exactly as returned.                           |
| artifact\_id              | For later updates or revocation.                                                  |
| visibility                | public or unlisted.                                                               |
| published\_at, byte\_size | When, and how large.                                                              |
| markdown\_url             | Public pages only: the agent-readable twin.                                       |
| revision, note            | On an update: the revision number and a note that readers see it within a minute. |

Errors and special responses

- Rejected HTML — Sending \<!doctype>, \<html>, \<head>, \<body>, \<style>, \<script> or \<link>, an inline style or id, an event handler, or an image from an unapproved host is rejected with an error naming each offender. Nothing is silently stripped.
- Too large — body\_html over 262,144 bytes. Cut sections rather than truncating.
- Daily quota — 20 publishes per key per UTC day, updates included, shared with publish\_comparison.
- Storage quota — 200 live pages per key. Revoking one frees a slot.
- Update of an unknown id — No live page with that artifact\_id is published under this account.

### `publish_comparison`

The same mechanics, shape and quota as publish\_page, with guidance tuned for a vendor comparison, and page\_type defaulting to comparison. A comparison assembled in a chat window dies in the scrollback; this is the version you can send to someone.

Parameters

| Name                   | Type      | Description                                                                                          |
| ---------------------- | --------- | ---------------------------------------------------------------------------------------------------- |
| title required         | string    | Page title, 1–200 characters — “Waystar vs Adonis — denials, 400-bed IDN” beats “Vendor Comparison”. |
| body\_html required    | string    | The page body only. Same allowed tags and .ct-\* classes as publish\_page.                           |
| summary required       | string    | One sentence, up to 500 characters.                                                                  |
| citations optional     | array     | Up to 50 { label, url } sources. Default \[].                                                        |
| source\_tools optional | string\[] | Which tools produced the data, such as get\_vendor\_dossier. Default \[].                            |
| visibility optional    | enum      | unlisted or public. Default unlisted.                                                                |
| page\_type optional    | enum      | comparison, analysis or article. Default comparison.                                                 |
| artifact\_id optional  | string    | Pass an existing id to update in place.                                                              |

Example arguments

```
{
  "title": "Waystar vs Adonis: denials, 400-bed IDN",
  "summary": "Waystar has broader confirmed hospital traction; Adonis is newer with regional references.",
  "body_html": "<h1>Waystar vs Adonis</h1><p>Waystar leads on confirmed customers.</p>",
  "citations": [
    {
      "label": "Waystar case study",
      "url": "https://www.waystar.com/case-studies/"
    }
  ],
  "source_tools": [
    "get_vendor_dossier",
    "get_relationships"
  ]
}
```

Returns

The same object as publish\_page.

Errors and special responses

- Every publish\_page error — Applies here too, against the same shared quota.

### `list_my_comparisons`

Everything published under your key, newest first. This is your exposure audit — the one place to check what of yours is publicly readable.

Parameters

| Name                      | Type    | Description                                                                  |
| ------------------------- | ------- | ---------------------------------------------------------------------------- |
| limit optional            | integer | How many to return, 1–50. Default 20.                                        |
| include\_revoked optional | boolean | Include revoked pages, flagged. Set false for live pages only. Default true. |

Example arguments

```
{
  "limit": 10,
  "include_revoked": false
}
```

Returns

{ ok: true, artifacts }, newest first.

|                              |                                             |
| ---------------------------- | ------------------------------------------- |
| artifact\_id, title, summary | Which page.                                 |
| url                          | The page URL; dead once revoked.            |
| visibility                   | public (indexable) or unlisted (link only). |
| revoked                      | True once taken down.                       |
| published\_at, byte\_size    | When, and how large.                        |
| view\_count\_approx          | Approximate page loads — not analytics.     |

### `revoke_comparison`

Take a published page offline. The body is deleted rather than hidden and the URL stops working within about a minute. Permanent: republishing produces a new URL. Works for pages from either publish tool.

Parameters

| Name                  | Type   | Description                                              |
| --------------------- | ------ | -------------------------------------------------------- |
| artifact\_id required | string | The id a publish tool or list\_my\_comparisons returned. |

Example arguments

```
{
  "artifact_id": "waystar-vs-adonis-denials-k3f9x2"
}
```

Returns

{ ok: true, artifact\_id }. One stored-page slot is freed.

Errors and special responses

- Unknown, not yours, or already revoked — The same answer for all three, so ids cannot be probed.

## Brand kit

Clinical Terminal's own press kit, as data. For an assistant that is designing something about us rather than asking about the market.

### `get_brand_kit`

The same kit that lives at clinicalterminal.com/pressrelease, returned as data. An assistant that calls it first uses the real marks; one that does not tends to invent a red.

Ask it: *“Design a LinkedIn banner in Clinical Terminal's brand”*

Parameters

None — call it with an empty arguments object.

Example arguments

```
{}
```

Returns

One object.

|                      |                                                                                                                 |
| -------------------- | --------------------------------------------------------------------------------------------------------------- |
| assets\[]            | Every logo, wordmark, avatar, banner and cover: absolute url, kind, format, theme, pixel size and transparency. |
| colors\[]            | The brand colors as hex, each with its role.                                                                    |
| fonts\[]             | The typefaces, their roles and where to get them.                                                               |
| usage, principles\[] | Do and don’t rules, and one-line brand rules.                                                                   |
| readMe               | How to read the payload. Quote values exactly.                                                                  |

## Analysis

Ad-hoc SQL across the warehouse. These two need an enterprise key; every other tool on this page does not.

### `describe_schema`

The column inventory for an allowed dataset, so an assistant can author correct SQL instead of guessing at table shapes.

Parameters

| Name             | Type   | Description                                                                    |
| ---------------- | ------ | ------------------------------------------------------------------------------ |
| dataset optional | enum   | knowledge\_graph, clinical\_ai\_design or analytics. Default knowledge\_graph. |
| table optional   | string | Restrict to one table.                                                         |

Example arguments

```
{
  "dataset": "knowledge_graph",
  "table": "providers"
}
```

Returns

{ dataset, columns }, ordered by table then column position.

|            |                                                      |
| ---------- | ---------------------------------------------------- |
| columns\[] | Each column’s table name, column name and data type. |

Errors and special responses

- Any failure — Never an error response: columns comes back empty with an error field. An unknown table returns an empty list with no error.

### `run_analysis_sql`

A read-only query for analysis the fixed tools cannot express. One statement, writes rejected, a LIMIT 1000 added when you give none, and capped at 5 GiB scanned.

Parameters

| Name            | Type   | Description                                            |
| --------------- | ------ | ------------------------------------------------------ |
| sql required    | string | One SELECT or WITH query against the allowed datasets. |
| params optional | object | Named parameters, referenced as @name in the SQL.      |

Example arguments

```
{
  "sql": "SELECT provider_subtype, COUNT(*) AS n FROM `clinical-ai-design.knowledge_graph.providers` WHERE state = @st GROUP BY 1 ORDER BY n DESC",
  "params": {
    "st": "TX"
  }
}
```

Returns

{ ok, rows, bytesProcessed }.

Errors and special responses

- Any rejection — Never an error response: ok: false with an error naming the rule — multiple statements, anything but SELECT/WITH, a write keyword anywhere in the text, a dataset or project outside the allowlist, or a scan estimated over 5 GiB.

## Limits & errors

These apply to every tool, before it runs. Tool-specific errors are listed on each entry above.

| Code | What it means                                                                                                |
| ---- | ------------------------------------------------------------------------------------------------------------ |
| 401  | No authorization header was sent.                                                                            |
| 403  | Invalid or revoked key, a lapsed Landscape subscription, or over the monthly quota. The response says which. |
| 429  | Per-minute rate limit. Retry after the interval the response names.                                          |

The monthly cap is the control that actually binds. The per-minute limit is counted per server instance and the service scales out, so treat the stamped number as a floor rather than a promise.
