Clinical Terminal
Docs menu · MCP tools
On this page
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.

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
NameTypeDescription
vendor requiredstringA 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).

vendorThe 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.
fundingFunding and M&A news we hold. roundsTracked is always false: this is news, not a round history.
siteMapPages we know on the vendor’s website, by category, with freshness.
metaThe 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
NameTypeDescription
query requiredstringMatched against name, domain and categories; multi-word phrases work. 1–200 characters.
limit optionalintegerMaximum results, 1–50. Default 20.
Example arguments
{
  "query": "denials management",
  "limit": 10
}
Returns

An array of vendors, best match first.

idVendor id — pass it to get_vendor.
nameVendor name.
domainThe vendor’s web domain.
summaryCompany summary.
logoUrlPermanent logo URL.
companyTypeAlways 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
NameTypeDescription
id requiredstringVendor 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, domainIdentity.
slugNumeric terminalId, as a string.
summary, logoUrlCompany summary and logo URL.
categories[]KLAS segment slugs, rolled up from the products this vendor sells.
foundedYear, headquartersCompany basics, when known.
ceoName, ceoTitleThe 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
NameTypeDescription
problem requiredstringA buyer problem or capability in plain words, or an exact segment name from list_segments. At least 2 characters.
limit optionalintegerMaximum 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, segmentGroupThe segment the problem routed to.
matchMethodHow 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.

idSegment slug.
nameDisplay name — pass it to find_vendors_for_problem.
group, descriptionThe segment’s group and what it covers.
vendorCount, productCountVendors 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
NameTypeDescription
query optionalstringMatched against product name and description. 1–200 characters.
vendor_id optionalstringRestrict to one vendor’s catalog.
include_inactive optionalbooleanAlso return discontinued products. Default false.
limit optionalintegerMaximum results, 1–50. Default 20.
Example arguments
{
  "query": "prior authorization",
  "limit": 20
}
Returns

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

idProduct id — pass it to get_product.
vendorId, vendorNameThe vendor that sells it.
nameProduct name.
productTypeservice, software, platform, module or device.
statusactive or inactive.
descriptionProduct 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
NameTypeDescription
id requiredstringProduct 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
NameTypeDescription
vendor requiredstringVendor name, id or numeric slug. 1–200 characters.
category optionalenumOne of homepage, about, leadership, contact, news, careers, blog, legal, product, pricing, customers, integrations, demo, resources, other. Omit for every page.
include_dead optionalbooleanAlso return pages that no longer resolve. Default false.
limit optionalintegerRows to return, 1–100. Default 50.
offset optionalintegerRows to skip, for paging. Default 0.
Example arguments
{
  "vendor": "Waystar",
  "category": "customers",
  "limit": 25
}
Returns

One object.

vendorThe 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, pagesReturnedLive pages we hold, and rows in this response.
scrapedCount, deadPagesPages we hold text for, and pages that no longer resolve.
lastCrawledAtWhen content was last fetched — the freshness stamp.
noteWhy 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
NameTypeDescription
page_id requiredstringA 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, classificationWhich page this is.
vendorThe published vendor that owns the page.
scrapedWhether we hold its text.
title, contentWhen scraped: the title, and Markdown up to 10,000 characters inside a BEGIN/END UNTRUSTED WEBSITE CONTENT fence.
truncatedTrue when the content was cut at a paragraph boundary.
scrapedAtWhen 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.
updatedAtWhen 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.

providerTypeSegment key — pass it to search_providers.
countProvider entities in the segment.
signals7d, signals7dPriorSignal rows in the last 7 days, and days 8–14.
deltaThe 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
NameTypeDescription
query optionalstringProvider name or fragment; multi-word phrases work. 1–200 characters.
provider_type optionalenumA segment key from get_provider_segments, such as health_system, acute_care, critical_access, fqhc or asc.
state optionalstringA two-letter code or a full state name (“TX” or “Texas”).
health_sys_id optionalstringOnly members of one health system — a healthSysId from a result.
min_beds optionalintegerMinimum staffed beds, 1–5000. Drops providers with no bed count, such as clinics.
sort optionalenumsize (most beds first), name, or signal_recency (newest news first). Defaults to relevance with a query, name without.
limit optionalintegerMaximum results, 1–50. Default 20.
Example arguments
{
  "query": "Baylor Scott",
  "state": "TX",
  "sort": "size",
  "limit": 10
}
Returns

An array of providers.

id, terminalIdEither one works with get_provider.
name, city, stateIdentity and location.
providerSubtype, companyTypeSegment key, and the coarse type it derives from.
staffedBedsBed count, for hospitals and health systems.
healthSysIdThe parent health system, for a system-to-members lookup.
linkedinLinkedIn URL.
lastSignalAtMost 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
NameTypeDescription
service_line requiredenumThe department key, such as cardiology, oncology, neurology, orthopedics, obgyn, behavioral, imaging or emergency.
state optionalstringA two-letter code or a full state name (“TX” or “Texas”).
cities optionalstring[]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 optionalenumhospital (individual facilities), system (health-system parents) or any. A system’s beds are its system-wide total. Default hospital.
provider_type optionalenumOne segment, such as acute_care, critical_access or childrens.
min_beds optionalintegerMinimum staffed beds, 1–5000. Drops providers with no bed count.
min_evidence optionalenumstrong keeps only a dedicated website section or 2+ staff titles; any also includes single mentions. Default any.
include_unclassified optionalbooleanReturn 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 optionalintegerMaximum 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.

lineThe department key and its label.
results[].terminalId, openInGetProviderPass 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, websiteThe provider. beds is null when unknown.
results[].evidencestrength (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).
providersWithLineEvery provider with evidence for the line.
droppedUnclassified, droppedByFilter, droppedNoCity, droppedNoCard, droppedBySizeWhy each provider read was not returned. droppedNoCity counts providers with no city on record, which a cities filter cannot match.
truncatedThe scan cap stopped the sweep. Narrow by state.
asOfWhen 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
NameTypeDescription
id requiredstringProvider 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.

providerThe profile, as a search_providers row.
systemThe health system, its true member count, and up to 10 largest members. Omitted when the provider has no system.
edgesUp to 10 technology relationships, strongest evidence first.
signalsUp to 5 recent signals, one per source article.
serviceLinesClinical departments, strongest evidence first — each with its label, strength, staff title headcount and website tier. An absent department is unknown, not missing.
metaThe 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
NameTypeDescription
query requiredstringA 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, labelThe seniority-by-department group it resolved to.
roleDefinitionWhat the role is.
titleVariants[]Real job titles held, with counts.
censusHow many people we track, and at which employer types.
responsibilities[], kpis[], buyingRoleWhat the role does and is measured on.
jdQuotesQuotes from real job postings, fenced as untrusted text.
aggregatedWhat 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
NameTypeDescription
query optionalstringMatched against name, employer and job title. 1–200 characters.
organization_id optionalstringOnly people currently at this organization.
vendor_id optionalstringOlder name for organization_id. Pass one or the other.
department optionalenumOne of clinical, operations, general, finance, recruiting, customer_success, marketing, engineering, legal, data, product, sales, security, design, editorial, research.
role optionalenumSeniority: c_suite, vp, director, or executive for all three. Does not count as a filter on its own.
limit optionalintegerMaximum 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.

idPerson id — pass it to get_person.
name, jobTitle, organizationWho, and the role shown.
positionLevelSeniority: CEO, President, C_Suite, VP, Director, …
functionalDepartmentDepartment of that role.
personaId<level>_<department>, such as c_suite_ceo. An absent value means the role is unclassified, not junior.
headline, imageUrl, linkedinProfile headline, photo and LinkedIn.
otherCurrentRoles[]Up to 5 other visible roles, most senior first.
otherCurrentRolesHiddenOther 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
NameTypeDescription
id requiredstringPerson 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.
pastRolesWithheldPast 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
NameTypeDescription
vendor_id requiredstringA published vendor’s id or numeric slug. A name is not an id.
left_after optionaldateYYYY-MM-DD. Only people who left on or after this date.
role optionalenumSeniority of the past role: c_suite, vp, director or executive.
department optionalstringDepartment of the past role, such as sales or engineering.
limit optionalintegerMaximum people, 1–50. Default 25.
Example arguments
{
  "vendor_id": "100000001",
  "left_after": "2025-09-01",
  "role": "executive"
}
Returns

One object.

vendorThe 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.
totalMatchedEveryone with a past role at the vendor, before filters.
_dropped* countersWhy 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
NameTypeDescription
status optionalenumannounced (last day still ahead), completed, or any. Default any.
seat optionalstringA seat such as ceo, cfo, cno or cio.
since optionaldateYYYY-MM-DD. Only last days on or after this date; rows with no last day are excluded.
min_confidence optionalenumhigh returns editor-confirmed retirements only; low or any also returns LinkedIn self-reports. Default any.
limit optionalintegerMaximum 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.
retirementsRecordedEvery retirement on record.
droppedByFilter, droppedNoPhoto, droppedBySizeWhy rows are missing; droppedBySize above zero means narrow the query or lower limit.
organizationHiddenPeople returned with the organization left blank because it is not published.
noteWhat 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
NameTypeDescription
query optionalstringMatched against title and summary. 1–200 characters.
entity_id optionalstringOnly signals about this entity.
origin_entity_type optionalenumvendor, provider (includes hospitals), hospital, investor or organization.
signal_type optionalstringAn exact, case-sensitive category such as Funding / Investment or Leadership Change.
source_type optionalenumThe source format, such as news_article, press_release, linkedin_post, sec_filing or job_posting.
detected_after optionaldateISO date or UTC datetime. On or after.
detected_before optionaldateISO date or UTC datetime. On or before; a bare date includes the whole day.
sort optionalenumimportance or recency. Accepted, but results currently always come back newest first. Default recency.
distinct_articles optionalbooleanOne row per article instead of one per article and linked entity. Default false.
limit optionalintegerMaximum 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, articleIdRow id, and the article it came from — group on articleId to count stories.
title, summary, sourceUrlThe story.
detectedAtWhen we detected it.
topics[], categories[]What it is about. Prefer these to signalType.
originEntityId, originEntityTypeWhich entity the row is about.
linkedEntityCountHow many entities the article names.
urgency, painPoint, salesAngleMachine-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
NameTypeDescription
query requiredstringHospital name or part of one. 1–200 characters.
state optionalstringA two-letter state code. Full names are not accepted here.
limit optionalintegerMaximum candidates, 1–20. Default 10.
Example arguments
{
  "query": "Massachusetts General",
  "state": "MA",
  "limit": 5
}
Returns

An array of candidates, largest by staffed beds first.

terminalIdThe preferred get_relationships input.
idAlso accepted by get_relationships.
name, city, stateWhich hospital this is.
hospitalType, staffedBedsType 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
NameTypeDescription
entity_id requiredstringA vendor or hospital id, numeric slug or terminalId. Not a name.
edge_type optionalstringA relationship type such as CUSTOMER_OF or INVESTED_IN; case-insensitive.
limit optionalintegerMaximum 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, relationshipLabelThe type to filter on, and its plain-English form.
labelThe organization on the other end.
sourceId, targetIdterminalIds of the two ends.
evidenceSnippet, evidenceTierThe supporting quote, and its strength: 1 case study, 2 customer list, 3 logo or passing mention.
evidenceNamesLabelWhether the quote actually names the other organization.
topArticleUrlAn article to cite.
firstSeenAt, lastConfirmedAtWhen the edge was first and last seen.
corroborated, corroborationQuoteIndependent 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
NameTypeDescription
title requiredstringPage title, 1–200 characters. Be specific.
body_html requiredstringThe page body only — what goes inside <body>, using the allowed tags and .ct-* classes. Up to 256 KB.
summary requiredstringOne sentence, up to 500 characters: the meta description and list subtitle.
citations optionalarrayUp to 50 { label, url } sources, rendered in the page footer. Default [].
source_tools optionalstring[]Which tools on this server produced the data. Default [].
visibility optionalenumunlisted (unguessable link, not indexed) or public (indexable). Use public only when the user asks for a discoverable page. Default unlisted.
page_type optionalenumcomparison, analysis or article: the visual register. Guessed from the title when omitted.
artifact_id optionalstringOmit 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.

urlThe page URL — give it to the user exactly as returned.
artifact_idFor later updates or revocation.
visibilitypublic or unlisted.
published_at, byte_sizeWhen, and how large.
markdown_urlPublic pages only: the agent-readable twin.
revision, noteOn 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
NameTypeDescription
title requiredstringPage title, 1–200 characters — “Waystar vs Adonis — denials, 400-bed IDN” beats “Vendor Comparison”.
body_html requiredstringThe page body only. Same allowed tags and .ct-* classes as publish_page.
summary requiredstringOne sentence, up to 500 characters.
citations optionalarrayUp to 50 { label, url } sources. Default [].
source_tools optionalstring[]Which tools produced the data, such as get_vendor_dossier. Default [].
visibility optionalenumunlisted or public. Default unlisted.
page_type optionalenumcomparison, analysis or article. Default comparison.
artifact_id optionalstringPass 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
NameTypeDescription
limit optionalintegerHow many to return, 1–50. Default 20.
include_revoked optionalbooleanInclude 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, summaryWhich page.
urlThe page URL; dead once revoked.
visibilitypublic (indexable) or unlisted (link only).
revokedTrue once taken down.
published_at, byte_sizeWhen, and how large.
view_count_approxApproximate 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
NameTypeDescription
artifact_id requiredstringThe 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.
readMeHow 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
NameTypeDescription
dataset optionalenumknowledge_graph, clinical_ai_design or analytics. Default knowledge_graph.
table optionalstringRestrict 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
NameTypeDescription
sql requiredstringOne SELECT or WITH query against the allowed datasets.
params optionalobjectNamed 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.

CodeWhat it means
401No authorization header was sent.
403Invalid or revoked key, a lapsed Landscape subscription, or over the monthly quota. The response says which.
429Per-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.