Search, enrich and watch people and companies from a single conversation in Claude with Crustdata. Build TAM, prospect and candidate lists using 150+ search filters such as job title, industry, funding and more. You can also enrich people and company profiles with 350+ datapoints such as verified emails, full work experience, education, funding, headcount, web traffic, job postings and more.
Protocol
MCP 2026-07-28
Server version
4.0.1
Supports
Tools
Resources
Prompts
Logging
Overall score
C
Overall quality score: 69 out of 10069/100
Server metadata
4 of 8 fields50/1004 / 8 pts
Identity, discovery, and usage metadata advertised during the MCP handshake.
Crustdata MCP Server — B2B company and people intelligence platform (800M+ profiles, 200M+ companies).
TOOL SELECTION (use this order of preference):
- Company lookup: crustdata_company_identify_v2 (FREE) → crustdata_company_enrich_v2
- People search: crustdata_people_search_db_v2 → ONLY fall back to crustdata_people_search_live_v2 if it returns 0 results
- Company search: crustdata_company_search_db_v2 → ONLY fall back to crustdata_company_search_v2 for live LinkedIn data
- Contact info (emails/phones): crustdata_people_contact_enrich — THE tool for contact data; sync, up to 100 LinkedIn URLs per call. Use crustdata_people_enrich_v2 only for full profile data (work history, education, skills)
- Social posts: crustdata_social_post_search (indexed post dataset — posts by author, keyword, or engagement, with reactors/comments on request) → crustdata_social_posts_v2 (live, by person OR company profile) or crustdata_social_posts_by_keyword_v2 (live, by keyword) when the freshest posts matter
- Job listings: crustdata_job_search (filters/sorts/aggregations) or crustdata_job_search_live (realtime LinkedIn scrape by company)
- Web: crustdata_web_search_v2 to find pages → crustdata_web_fetch_v2 to read them
- Credit costs: run crustdata_credit_costs for the per-tool rate card before estimating spend — tool descriptions do not carry prices
- Batch jobs: crustdata_batch_job_search (async, every listing for up to 10 companies — no limit) or crustdata_batch_job_search_live (async live scrape, up to 10 companies)
- Alerts/webhooks: crustdata_watch_create (DEFAULT — profile changes on known people/companies, or NEW people/companies matching a filter) → crustdata_watch_list. Use the legacy crustdata_watcher_create → crustdata_watcher_list ONLY for LinkedIn posts, job postings, or person press mentions
- Discover valid filter values: crustdata_autocomplete_company_v2, crustdata_autocomplete_person_v2, crustdata_autocomplete_job (dataset searches); crustdata_autocomplete_filter_v2
Protocol
Pass100/10016 / 16 pts
Connection, authentication, and protocol compatibility.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description91/100
CREDIT BALANCE (/account/credits, API version 2025-11-01). FREE. The balance is under `account.credits`, with the recurring grant (recurring_credits, recurring_credits_frequency, recurring_credits_refresh_date). Accounts with credit wallets also get a `wallets` list splitting recurring (spent first) from top-up (rolls over until expires_at) — informational only; gate spending decisions on account.credits.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_credits_check_v2",
"title": "Check credit balance",
"description": "CREDIT BALANCE (/account/credits, API version 2025-11-01). FREE. The balance is under `account.credits`, with the recurring grant (recurring_credits, recurring_credits_frequency, recurring_credits_refresh_date). Accounts with credit wallets also get a `wallets` list splitting recurring (spent first) from top-up (rolls over until expires_at) — informational only; gate spending decisions on account.credits.",
"inputSchema": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
CREDIT BALANCE (/account/credits, API version 2025-11-01). FREE. The balance is under `account.credits`, with the recurring grant (recurring_credits, recurring_credits_frequency, recurring_credits_refresh_date). Accounts with credit wallets also get a `wallets` list splitting recurring (spent first) from top-up (rolls over until expires_at) — informational only; gate spending decisions on account.credits.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_credits_check",
"title": "Get credit balance",
"description": "CREDIT BALANCE (/account/credits, API version 2025-11-01). FREE. The balance is under `account.credits`, with the recurring grant (recurring_credits, recurring_credits_frequency, recurring_credits_refresh_date). Accounts with credit wallets also get a `wallets` list splitting recurring (spent first) from top-up (rolls over until expires_at) — informational only; gate spending decisions on account.credits.",
"inputSchema": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
ACCOUNT ENDPOINT PERMISSIONS — NEW API (v2025-11-01). Lists every Crustdata API endpoint with this account's access status (enabled/disabled), effective rate limit in requests/minute, and — with include_fields=true — the response fields enabled and disabled for the account. FREE, no credits. THE tool for diagnosing a 403 from any v2 tool ('is this endpoint on my plan?') and for answering 'what am I allowed to call / what is my rate limit?'. Narrow with path (exact match), category, or status — filters combine with AND, and unknown path/category values return an empty list rather than an error. RESPONSE: {api_version, token_limit_rpm, endpoints: [{path, category, status, effective_rate_limit_rpm, fields?}]}.
The description explains the capability, when to use it, and what to expect.
Inputs99/100
Input documentation gives an agent enough context to populate the arguments.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › path
Return only the endpoint whose path matches EXACTLY, e.g. '/company/enrich'. Acts as a filter, not a lookup — an unknown path returns an empty list rather than an error.
Clear enough to supply this argument.
params › category
Return only endpoints in this product category (case-insensitive), e.g. 'Company', 'Person', 'Jobs', 'Web'. Unknown categories return an empty list.
Clear enough to supply this argument.
params › status
Return only endpoints with this access status. Use 'disabled' to list exactly what the account would 403 on.
Clear enough to supply this argument.
params › include_fields
Include the per-endpoint enabled/disabled response-field lists. Off by default because those lists are long — turn it on only when the question is about FIELD-level access ('can I get technographics?'), not endpoint-level access.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_account_endpoints_v2",
"title": "List endpoint access and limits",
"description": "ACCOUNT ENDPOINT PERMISSIONS — NEW API (v2025-11-01). Lists every Crustdata API endpoint with this account's access status (enabled/disabled), effective rate limit in requests/minute, and — with include_fields=true — the response fields enabled and disabled for the account. FREE, no credits. THE tool for diagnosing a 403 from any v2 tool ('is this endpoint on my plan?') and for answering 'what am I allowed to call / what is my rate limit?'. Narrow with path (exact match), category, or status — filters combine with AND, and unknown path/category values return an empty list rather than an error. RESPONSE: {api_version, token_limit_rpm, endpoints: [{path, category, status, effective_rate_limit_rpm, fields?}]}.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"properties": {
"path": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Return only the endpoint whose path matches EXACTLY, e.g. '/company/enrich'. Acts as a filter, not a lookup — an unknown path returns an empty list rather than an error."
},
"status": {
"anyOf": [
{
"enum": [
"enabled",
"disabled"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Return only endpoints with this access status. Use 'disabled' to list exactly what the account would 403 on."
},
"category": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Return only endpoints in this product category (case-insensitive), e.g. 'Company', 'Person', 'Jobs', 'Web'. Unknown categories return an empty list."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"include_fields": {
"type": "boolean",
"default": false,
"description": "Include the per-endpoint enabled/disabled response-field lists. Off by default because those lists are long — turn it on only when the question is about FIELD-level access ('can I get technographics?'), not endpoint-level access."
}
},
"description": "Input for GET /account/endpoints (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
PERSON FIELD AUTOCOMPLETE (/person/search/autocomplete, API version 2025-11-01). It replaces the retired crustdata_autocomplete_person. FREE. Resolves exact indexed values for the filters of crustdata_people_search_db_v2 and crustdata_people_search_semantic. Takes nested field paths (experience.employment_details.current.title, basic_profile.location.city, …). Suggestions come from the whole dataset — they are not narrowed by other conditions. Feed a returned value back into a search filter verbatim. For live-search values (people_search_live_v2) crustdata_autocomplete_filter_v2 is the matching tool.
The description explains the capability, when to use it, and what to expect.
Inputs94/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › query
Prefix/partial text to match. Empty string is allowed and returns the most common values for the field by frequency — useful for discovering what a field actually contains.
Clear enough to supply this argument.
params › limit
Maximum number of suggestions (default 20, max 100).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › field
Nested v2 field path to autocomplete. Common values: 'basic_profile.name', 'basic_profile.headline', 'basic_profile.location.city', 'basic_profile.location.country', 'experience.employment_details.current.name', 'experience.employment_details.current.title', 'experience.employment_details.current.seniority_level', 'education.schools.school', 'skills.professional_network_skills'. Past-role equivalents live under experience.employment_details.past.*. The endpoint accepts an allowlisted subset of /person/search fields — an unsupported field returns a 400 listing every accepted value.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_autocomplete_person_v2",
"title": "Autocomplete person filter values",
"description": "PERSON FIELD AUTOCOMPLETE (/person/search/autocomplete, API version 2025-11-01). It replaces the retired crustdata_autocomplete_person. FREE. Resolves exact indexed values for the filters of crustdata_people_search_db_v2 and crustdata_people_search_semantic. Takes nested field paths (experience.employment_details.current.title, basic_profile.location.city, …). Suggestions come from the whole dataset — they are not narrowed by other conditions. Feed a returned value back into a search filter verbatim. For live-search values (people_search_live_v2) crustdata_autocomplete_filter_v2 is the matching tool.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"field"
],
"properties": {
"field": {
"type": "string",
"description": "Nested v2 field path to autocomplete. Common values: 'basic_profile.name', 'basic_profile.headline', 'basic_profile.location.city', 'basic_profile.location.country', 'experience.employment_details.current.name', 'experience.employment_details.current.title', 'experience.employment_details.current.seniority_level', 'education.schools.school', 'skills.professional_network_skills'. Past-role equivalents live under experience.employment_details.past.*. The endpoint accepts an allowlisted subset of /person/search fields — an unsupported field returns a 400 listing every accepted value."
},
"limit": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Maximum number of suggestions (default 20, max 100)."
},
"query": {
"type": "string",
"default": "",
"description": "Prefix/partial text to match. Empty string is allowed and returns the most common values for the field by frequency — useful for discovering what a field actually contains."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
}
},
"description": "Input for POST /person/search/autocomplete (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description89/100
COMPANY FIELD AUTOCOMPLETE (/company/search/autocomplete, API version 2025-11-01). It replaces the retired crustdata_autocomplete_company. FREE. Resolves exact indexed values for the filters of crustdata_company_search_db_v2, crustdata_company_search_semantic, and crustdata_company_search_by_technology. Takes nested field paths (locations.country, taxonomy.professional_network_industry, …); suggestions come from the whole dataset, not narrowed by other conditions. The technographics vocabulary is field='technology' (tech names, e.g. query='snow' → 'Snowflake') and field='technology_category' (kebab-case slugs, e.g. query='data' → 'data-warehouse'). Feed a returned value back into a search filter verbatim.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › query
Prefix/partial text to match. Empty string is allowed and returns the most common values for the field by frequency — useful for discovering what a field actually contains.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › limit
Maximum number of suggestions (default 20, max 100).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › field
Nested v2 field path to autocomplete. Common values: 'basic_info.name', 'basic_info.industries', 'basic_info.company_type', 'locations.country', 'taxonomy.professional_network_industry', 'funding.last_round_type', 'funding.investors', 'headcount.largest_headcount_country'. An unsupported field returns a 400 listing every accepted value.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_autocomplete_company_v2",
"title": "Autocomplete company filter values",
"description": "COMPANY FIELD AUTOCOMPLETE (/company/search/autocomplete, API version 2025-11-01). It replaces the retired crustdata_autocomplete_company. FREE. Resolves exact indexed values for the filters of crustdata_company_search_db_v2, crustdata_company_search_semantic, and crustdata_company_search_by_technology. Takes nested field paths (locations.country, taxonomy.professional_network_industry, …); suggestions come from the whole dataset, not narrowed by other conditions. The technographics vocabulary is field='technology' (tech names, e.g. query='snow' → 'Snowflake') and field='technology_category' (kebab-case slugs, e.g. query='data' → 'data-warehouse'). Feed a returned value back into a search filter verbatim.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"field"
],
"properties": {
"field": {
"type": "string",
"description": "Nested v2 field path to autocomplete. Common values: 'basic_info.name', 'basic_info.industries', 'basic_info.company_type', 'locations.country', 'taxonomy.professional_network_industry', 'funding.last_round_type', 'funding.investors', 'headcount.largest_headcount_country'. An unsupported field returns a 400 listing every accepted value."
},
"limit": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Maximum number of suggestions (default 20, max 100)."
},
"query": {
"type": "string",
"default": "",
"description": "Prefix/partial text to match. Empty string is allowed and returns the most common values for the field by frequency — useful for discovering what a field actually contains."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
}
},
"description": "Input for POST /company/search/autocomplete (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
JOB FIELD AUTOCOMPLETE (v2025-11-01). FREE — no credits. Returns the exact indexed values a crustdata_job_search filter will accept, so use it BEFORE filtering on a free-text job field (title, category, company name, location) — a near-miss value like 'SWE' for 'Software Engineer' matches zero jobs silently. Not version-gated: crustdata_job_search already runs on the 2025-11-01 /job/search endpoint, so this is simply its value-discovery helper. Empty `query` returns the most common values for the field.
The description explains the capability, when to use it, and what to expect.
Inputs94/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › query
Prefix/partial text to match. Empty string is allowed and returns the most common values for the field by frequency — useful for discovering what a field actually contains.
Clear enough to supply this argument.
params › limit
Maximum number of suggestions (default 20, max 100).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › field
The /job/search field whose values to autocomplete — the same names used in crustdata_job_search filters, plus short aliases. Common values: 'title', 'category', 'workplace_type', 'company.name', 'company.industries', 'location.country', 'location.city', 'location.state'. An unsupported field returns a 400 listing every accepted value.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_autocomplete_job",
"title": "Autocomplete job filter values",
"description": "JOB FIELD AUTOCOMPLETE (v2025-11-01). FREE — no credits. Returns the exact indexed values a crustdata_job_search filter will accept, so use it BEFORE filtering on a free-text job field (title, category, company name, location) — a near-miss value like 'SWE' for 'Software Engineer' matches zero jobs silently. Not version-gated: crustdata_job_search already runs on the 2025-11-01 /job/search endpoint, so this is simply its value-discovery helper. Empty `query` returns the most common values for the field.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"field"
],
"properties": {
"field": {
"type": "string",
"description": "The /job/search field whose values to autocomplete — the same names used in crustdata_job_search filters, plus short aliases. Common values: 'title', 'category', 'workplace_type', 'company.name', 'company.industries', 'location.country', 'location.city', 'location.state'. An unsupported field returns a 400 listing every accepted value."
},
"limit": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Maximum number of suggestions (default 20, max 100)."
},
"query": {
"type": "string",
"default": "",
"description": "Prefix/partial text to match. Empty string is allowed and returns the most common values for the field by frequency — useful for discovering what a field actually contains."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
}
},
"description": "Input for POST /job/search/autocomplete (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description96/100
COMPANY IDENTIFY (/company/identify, API version 2025-11-01). It replaces the retired crustdata_company_identify. FREE. Resolves a company to its crustdata_company_id. Identifiers are plural arrays (up to 25 values) of exactly ONE type per call: domains / names / crustdata_company_ids / professional_network_profile_urls — for mixed identifiers, make one call per type. Crunchbase URLs are not an identify input; filter crustdata_company_search_db_v2 on social_profiles.crunchbase.url instead. RESPONSE: list of {matched_on, match_type, matches: [{confidence_score, company_data.basic_info}]}.
The description explains the capability, when to use it, and what to expect.
Inputs86/100
Explain the meaning of this value, not just its name.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › domains
Company domains, e.g. ['stripe.com'].
Clear enough to supply this argument.
params › names
Company names, e.g. ['Stripe'].
Clear enough to supply this argument.
params › crustdata_company_ids
Crustdata company IDs.
Explain the meaning of this value, not just its name.
params › professional_network_profile_urls
LinkedIn company URLs.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
params › fields
Rarely needed. Identify returns only crustdata_company_id, basic_info and social_profiles on each match, and these (or basic_info.<field>) are the only valid values. For headcount, funding, people and every other section, call crustdata_company_enrich_v2 with the resolved crustdata_company_id.
Clear enough to supply this argument.
params › exact_match
When identifying by `names`, return only exact name matches instead of fuzzy candidates. Use for unambiguous brand names; leave off for typo-tolerant matching.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_identify_v2",
"title": "Identify companies",
"description": "COMPANY IDENTIFY (/company/identify, API version 2025-11-01). It replaces the retired crustdata_company_identify. FREE. Resolves a company to its crustdata_company_id. Identifiers are plural arrays (up to 25 values) of exactly ONE type per call: domains / names / crustdata_company_ids / professional_network_profile_urls — for mixed identifiers, make one call per type. Crunchbase URLs are not an identify input; filter crustdata_company_search_db_v2 on social_profiles.crunchbase.url instead. RESPONSE: list of {matched_on, match_type, matches: [{confidence_score, company_data.basic_info}]}.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"properties": {
"names": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Company names, e.g. ['Stripe']."
},
"fields": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Rarely needed. Identify returns only crustdata_company_id, basic_info and social_profiles on each match, and these (or basic_info.<field>) are the only valid values. For headcount, funding, people and every other section, call crustdata_company_enrich_v2 with the resolved crustdata_company_id."
},
"domains": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Company domains, e.g. ['stripe.com']."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"exact_match": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"description": "When identifying by `names`, return only exact name matches instead of fuzzy candidates. Use for unambiguous brand names; leave off for typo-tolerant matching."
},
"crustdata_company_ids": {
"anyOf": [
{
"type": "array",
"items": {
"type": "integer"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Crustdata company IDs."
},
"professional_network_profile_urls": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "LinkedIn company URLs."
}
},
"description": "Input for POST /company/identify (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
COMPANY ENRICHMENT (/company/enrich, API version 2025-11-01). It replaces the retired crustdata_company_enrich. Full company profile from the Crustdata dataset. Identifiers are plural arrays (up to 25 values) of exactly ONE type per call: domains / names / crustdata_company_ids / professional_network_profile_urls. The default response is basic_info only — list the sections you need in `fields` (headcount, funding, hiring, web_traffic, employee_reviews, people, news, …; see the fields parameter). 'technographics' in fields bills an add-on; for the tech stack alone crustdata_company_technographics is the purpose-built tool. Data is served from the dataset — there is no real-time refresh on this endpoint. RESPONSE: list of {matched_on, match_type, matches: [{confidence_score, company_data}]} with company_data nested by section (basic_info / headcount / funding / …).
The description explains the capability, when to use it, and what to expect.
Inputs71/100
Explain the meaning of this value, not just its name.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › domains
Company domains.
Explain the meaning of this value, not just its name.
params › names
Company names.
Explain the meaning of this value, not just its name.
params › crustdata_company_ids
Crustdata company IDs.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
params › professional_network_profile_urls
LinkedIn company URLs.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
params › fields
Field groups to return. Omitted = basic_info only; every other section must be listed. Groups: basic_info, headcount, funding, revenue, hiring (job openings), web_traffic, seo, competitors, employee_reviews (Glassdoor), software_reviews (G2), market_intel (Gartner), public_launches (Product Hunt), followers, news, people (founders / cxos / decision_makers), locations (incl. all_office_addresses), taxonomy, social_profiles, reviews, metadata, social_posts, technographics (billed as an add-on). Legacy group names (glassdoor, g2, founders, job_openings, …) are rewritten to these.
Clear enough to supply this argument.
params › exact_match
When enriching by `names`, match the name exactly instead of fuzzily. Use for unambiguous brand names.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_enrich_v2",
"title": "Enrich companies",
"description": "COMPANY ENRICHMENT (/company/enrich, API version 2025-11-01). It replaces the retired crustdata_company_enrich. Full company profile from the Crustdata dataset. Identifiers are plural arrays (up to 25 values) of exactly ONE type per call: domains / names / crustdata_company_ids / professional_network_profile_urls. The default response is basic_info only — list the sections you need in `fields` (headcount, funding, hiring, web_traffic, employee_reviews, people, news, …; see the fields parameter). 'technographics' in fields bills an add-on; for the tech stack alone crustdata_company_technographics is the purpose-built tool. Data is served from the dataset — there is no real-time refresh on this endpoint. RESPONSE: list of {matched_on, match_type, matches: [{confidence_score, company_data}]} with company_data nested by section (basic_info / headcount / funding / …).",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"properties": {
"names": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Company names."
},
"fields": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Field groups to return. Omitted = basic_info only; every other section must be listed. Groups: basic_info, headcount, funding, revenue, hiring (job openings), web_traffic, seo, competitors, employee_reviews (Glassdoor), software_reviews (G2), market_intel (Gartner), public_launches (Product Hunt), followers, news, people (founders / cxos / decision_makers), locations (incl. all_office_addresses), taxonomy, social_profiles, reviews, metadata, social_posts, technographics (billed as an add-on). Legacy group names (glassdoor, g2, founders, job_openings, …) are rewritten to these."
},
"domains": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Company domains."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"exact_match": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"description": "When enriching by `names`, match the name exactly instead of fuzzily. Use for unambiguous brand names."
},
"crustdata_company_ids": {
"anyOf": [
{
"type": "array",
"items": {
"type": "integer"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Crustdata company IDs."
},
"professional_network_profile_urls": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "LinkedIn company URLs."
}
},
"description": "Input for POST /company/enrich (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
COMPANY SEARCH — DATASET (/company/search, API version 2025-11-01). It replaces the retired crustdata_company_search_db. The primary company search: filter the Crustdata company dataset by industry, location, headcount, funding, growth, and more. Filter leaves use {field, type, value} with nested field paths (basic_info.name, headcount.total, locations.country, …); branches use {op, conditions}. Pagination is cursor-based (pass back next_cursor). Returns a markdown table by default; format='json' returns the nested records (compacted to key fields unless compact=false). Also filters on technographics (technographics.technologies.name / .category / .total_technologies), though crustdata_company_search_by_technology is the purpose-built tool for that.
The description explains the capability, when to use it, and what to expect.
Inputs89/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › filters
Filter tree. Leaves: {field, type, value} (NOT 'column'); branches: {op: 'and'|'or'|'all_of', conditions: [...]}. Common field paths: basic_info.name, basic_info.primary_domain, locations.country (ISO-3 like 'USA'/'DEU'), taxonomy.professional_network_industry, headcount.total, headcount.largest_headcount_country. Operators: =, !=, <, =<, >, => (not >= / <=), in, not_in (value is an array), has_all, contains / not_contains (case-insensitive substring), (.) (all words, any order, typo-tolerant), [.] (exact phrase), (!) (excludes a substring), is_null / is_not_null (omit value), geo_distance, geo_exclude. There is no 'between': send '=>' and '=<' leaves in an 'and' group. Fields are validated locally against the full generated catalog — unknown paths return did-you-mean suggestions instead of an API error. Use crustdata_autocomplete_company_v2 to resolve values.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › sorts
Optional sorts: [{field, order: 'asc'|'desc'}], e.g. field 'headcount.total'. NOTE: the key is 'order' (a 'direction' key is auto-renamed).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › limit
Results per page (1-1000, default 25). Combine a big page with `fields` to keep the response manageable.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › cursor
Opaque next_cursor from the previous page (v2 has no numeric offset).
Clear enough to supply this argument.
params › fields
Limit response to specific field paths (e.g. ['basic_info.name', 'headcount.total']). Omit for the full nested payload. Implies compact=false output shaping is unnecessary — you already chose the fields.
Clear enough to supply this argument.
params › truncate
Truncate long text fields in results (recommended).
Clear enough to supply this argument.
params › compact
format='json' only: return trimmed records with key fields. Set false for full nested data.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › format
Response format: 'markdown' (default) or 'json'. Markdown returns the companies as a compact table plus the pagination footer — use json when you need structured data for programmatic follow-up (e.g. extracting crustdata_company_id values).
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_search_db_v2",
"title": "Search company database",
"description": "COMPANY SEARCH — DATASET (/company/search, API version 2025-11-01). It replaces the retired crustdata_company_search_db. The primary company search: filter the Crustdata company dataset by industry, location, headcount, funding, growth, and more. Filter leaves use {field, type, value} with nested field paths (basic_info.name, headcount.total, locations.country, …); branches use {op, conditions}. Pagination is cursor-based (pass back next_cursor). Returns a markdown table by default; format='json' returns the nested records (compacted to key fields unless compact=false). Also filters on technographics (technographics.technologies.name / .category / .total_technologies), though crustdata_company_search_by_technology is the purpose-built tool for that.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"filters"
],
"properties": {
"limit": {
"type": "integer",
"default": 25,
"maximum": 1000,
"minimum": 1,
"description": "Results per page (1-1000, default 25). Combine a big page with `fields` to keep the response manageable."
},
"sorts": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
{
"type": "null"
}
],
"default": null,
"description": "Optional sorts: [{field, order: 'asc'|'desc'}], e.g. field 'headcount.total'. NOTE: the key is 'order' (a 'direction' key is auto-renamed)."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Opaque next_cursor from the previous page (v2 has no numeric offset)."
},
"fields": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Limit response to specific field paths (e.g. ['basic_info.name', 'headcount.total']). Omit for the full nested payload. Implies compact=false output shaping is unnecessary — you already chose the fields."
},
"format": {
"enum": [
"markdown",
"json"
],
"type": "string",
"default": "markdown",
"description": "Response format: 'markdown' (default) or 'json'. Markdown returns the companies as a compact table plus the pagination footer — use json when you need structured data for programmatic follow-up (e.g. extracting crustdata_company_id values)."
},
"compact": {
"type": "boolean",
"default": true,
"description": "format='json' only: return trimmed records with key fields. Set false for full nested data."
},
"filters": {
"type": "object",
"description": "Filter tree. Leaves: {field, type, value} (NOT 'column'); branches: {op: 'and'|'or'|'all_of', conditions: [...]}. Common field paths: basic_info.name, basic_info.primary_domain, locations.country (ISO-3 like 'USA'/'DEU'), taxonomy.professional_network_industry, headcount.total, headcount.largest_headcount_country. Operators: =, !=, <, =<, >, => (not >= / <=), in, not_in (value is an array), has_all, contains / not_contains (case-insensitive substring), (.) (all words, any order, typo-tolerant), [.] (exact phrase), (!) (excludes a substring), is_null / is_not_null (omit value), geo_distance, geo_exclude. There is no 'between': send '=>' and '=<' leaves in an 'and' group. Fields are validated locally against the full generated catalog — unknown paths return did-you-mean suggestions instead of an API error. Use crustdata_autocomplete_company_v2 to resolve values.",
"additionalProperties": true
},
"truncate": {
"type": "boolean",
"default": true,
"description": "Truncate long text fields in results (recommended)."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
}
},
"description": "Input for POST /company/search (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
COMPANY SEMANTIC SEARCH — natural-language ranked company search on the /company/search dataset (v2025-11-01). crustdata_company_search_db_v2 covers ordinary filter-based company search. This tool is for requests that describe companies by what they do — a product, capability, business model, or customer base that maps to no filter field — or that ask for semantic / natural-language search or results ranked by relevance. WHAT IT DOES: ranks companies by how well their profile (description, products, industry, specialities) matches `query`; optional `filters` are hard constraints applied before ranking; `search_mode` picks keyword, embedding, or both (hybrid, the default). KEY BEHAVIORS: (1) Results come back relevance-ordered in pages of up to 100; pass `next_cursor` back as `cursor` for more, up to 1,000 candidates per search (cursors expire after 20 minutes). `total_count` is always null and `sorts` is rejected. (2) No per-company score is returned; the order is the ranking. (3) Ranked search is enabled per account: a 'Company semantic search is not available for your account' error is that enablement, separate from /company/search access, and crustdata_company_search_db_v2 keeps working — ask Crustdata to enable it. RESPONSE: a markdown table by default; format='json' returns the same nested company records as crustdata_company_search_db_v2 (basic_info / headcount / locations / taxonomy / funding …), compacted to key fields unless compact=false.
The description explains the capability, when to use it, and what to expect.
Inputs95/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › query
Natural-language description of the companies to find — what they do, build, or sell, their business model or customers. e.g. 'AI infrastructure companies building tools for model deployment and monitoring', 'B2B marketplaces for construction materials'. This text is the ranking signal.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › search_mode
Retrieval signal for the query (maps to search.mode). 'hybrid' (default) = keyword + embedding, best general default. 'lexical' = keyword only, when the literal wording matters (product names, acronyms). 'semantic' = embedding only, when companies may describe the same capability in different words.
Clear enough to supply this argument.
params › filters
OPTIONAL structured filter tree applied as a hard constraint BEFORE ranking, so only companies that pass it are ranked — same shape and field paths as crustdata_company_search_db_v2: leaves {field, type, value}, branches {op: 'and'|'or', conditions: [...]}, e.g. locations.country = 'USA' or headcount.total => 50. Fields are validated locally against the generated catalog before any API call.
Clear enough to supply this argument.
params › limit
Companies per page (1-100, default 20). Pass `next_cursor` back as `cursor` for the next page; a ranked search covers at most 1,000 candidates.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › cursor
Opaque next_cursor from the previous page of THIS search. Keep query, search_mode and filters unchanged between pages (limit and fields may change). Cursors expire 20 minutes after the first page — restart without one if it is refused. A short or empty page can still carry a cursor; stop when next_cursor is null.
Clear enough to supply this argument.
params › fields
Limit the response to specific field paths (e.g. ['basic_info.name', 'basic_info.primary_domain', 'headcount.total']). Omit for the full nested payload, compacted to key fields unless compact=false.
Clear enough to supply this argument.
params › truncate
Truncate long text fields in results (recommended).
Clear enough to supply this argument.
params › compact
format='json' only: return trimmed records with key fields. Set false for full nested data.
Clear enough to supply this argument.
params › format
Response format: 'markdown' (default) or 'json'. Markdown returns the companies as a compact table plus the pagination footer — use json when you need structured data for programmatic follow-up (e.g. extracting crustdata_company_id values).
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_search_semantic",
"title": "Semantic company search",
"description": "COMPANY SEMANTIC SEARCH — natural-language ranked company search on the /company/search dataset (v2025-11-01). crustdata_company_search_db_v2 covers ordinary filter-based company search. This tool is for requests that describe companies by what they do — a product, capability, business model, or customer base that maps to no filter field — or that ask for semantic / natural-language search or results ranked by relevance. WHAT IT DOES: ranks companies by how well their profile (description, products, industry, specialities) matches `query`; optional `filters` are hard constraints applied before ranking; `search_mode` picks keyword, embedding, or both (hybrid, the default). KEY BEHAVIORS: (1) Results come back relevance-ordered in pages of up to 100; pass `next_cursor` back as `cursor` for more, up to 1,000 candidates per search (cursors expire after 20 minutes). `total_count` is always null and `sorts` is rejected. (2) No per-company score is returned; the order is the ranking. (3) Ranked search is enabled per account: a 'Company semantic search is not available for your account' error is that enablement, separate from /company/search access, and crustdata_company_search_db_v2 keeps working — ask Crustdata to enable it. RESPONSE: a markdown table by default; format='json' returns the same nested company records as crustdata_company_search_db_v2 (basic_info / headcount / locations / taxonomy / funding …), compacted to key fields unless compact=false.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"query"
],
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Companies per page (1-100, default 20). Pass `next_cursor` back as `cursor` for the next page; a ranked search covers at most 1,000 candidates."
},
"query": {
"type": "string",
"minLength": 1,
"description": "Natural-language description of the companies to find — what they do, build, or sell, their business model or customers. e.g. 'AI infrastructure companies building tools for model deployment and monitoring', 'B2B marketplaces for construction materials'. This text is the ranking signal."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Opaque next_cursor from the previous page of THIS search. Keep query, search_mode and filters unchanged between pages (limit and fields may change). Cursors expire 20 minutes after the first page — restart without one if it is refused. A short or empty page can still carry a cursor; stop when next_cursor is null."
},
"fields": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Limit the response to specific field paths (e.g. ['basic_info.name', 'basic_info.primary_domain', 'headcount.total']). Omit for the full nested payload, compacted to key fields unless compact=false."
},
"format": {
"enum": [
"markdown",
"json"
],
"type": "string",
"default": "markdown",
"description": "Response format: 'markdown' (default) or 'json'. Markdown returns the companies as a compact table plus the pagination footer — use json when you need structured data for programmatic follow-up (e.g. extracting crustdata_company_id values)."
},
"compact": {
"type": "boolean",
"default": true,
"description": "format='json' only: return trimmed records with key fields. Set false for full nested data."
},
"filters": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "OPTIONAL structured filter tree applied as a hard constraint BEFORE ranking, so only companies that pass it are ranked — same shape and field paths as crustdata_company_search_db_v2: leaves {field, type, value}, branches {op: 'and'|'or', conditions: [...]}, e.g. locations.country = 'USA' or headcount.total => 50. Fields are validated locally against the generated catalog before any API call."
},
"truncate": {
"type": "boolean",
"default": true,
"description": "Truncate long text fields in results (recommended)."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"search_mode": {
"enum": [
"hybrid",
"lexical",
"semantic"
],
"type": "string",
"default": "hybrid",
"description": "Retrieval signal for the query (maps to search.mode). 'hybrid' (default) = keyword + embedding, best general default. 'lexical' = keyword only, when the literal wording matters (product names, acronyms). 'semantic' = embedding only, when companies may describe the same capability in different words."
}
},
"description": "Input for natural-language ranked company search on POST /company/search (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Search the job listings database. Find jobs by company, title, location, category, and more. Supports filters, sorting, cursor pagination (up to 1000 results), and aggregations (counts/breakdowns). No charge when a query returns 0 results. Filters use 'field'/'type'/'value' keys with nested field paths (e.g., 'job_details.title', 'company.basic_info.name'). RESPONSE: By default returns a compact markdown table without descriptions. Use aggregations with limit=0 to get counts without fetching listings (e.g., 'how many engineering jobs at Google?').
The description explains the capability, when to use it, and what to expect.
Inputs83/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › filters
Search filters. Each filter has 3 keys: "field", "type", "value".
Single filter:
{"field": "job_details.title", "type": "(.)", "value": "Software Engineer"}
Multiple filters (AND):
{
"op": "and",
"conditions": [
{"field": "company.basic_info.name", "type": "(.)", "value": "Google"},
{"field": "company.locations.country", "type": "=", "value": "United States of America (the)"}
]
}
Operators:
- (.) = fuzzy/contains match (best for text searches)
- [.] = exact substring match
- = != = exact match / not equal
- in not_in = set membership (value must be an array)
- > < => =< = numeric/date comparison
- is_null is_not_null = null checks
VALID FIELD VALUES — auto-synced from the Crustdata v2025-11-01 API schema. Use these EXACT names (the MCP rejects unknown ones with a clear error).
Top-level fields:
- crustdata_job_id
Under company.:
- company.basic_info.crustdata_company_id
- company.basic_info.company_id
- company.basic_info.primary_domain
- company.basic_info.professional_network_id
- company.basic_info.name
- company.basic_info.industries
- company.locations.country
- company.locations.state
- company.locations.city
- company.locations.street_address
- company.headcount.total
- company.headcount.range
- company.headcount.largest_country
- company.followers.count
- company.revenue.estimated.lower_bound_usd
- company.revenue.estimated.upper_bound_usd
- company.funding.last_fundraise_date
- company.funding.last_round_type
- company.funding.num_funding_rounds
- company.funding.investors
- company.competitors.websites
- company.revenue.public_markets.stock_symbols
- company.revenue.public_markets.fiscal_year_end
- company.revenue.acquisition_status
- company.funding.total_investment_usd
- company.funding.valuation_usd
Under content.:
- content.description
Under job_details.:
- job_details.title
- job_details.category
- job_details.workplace_type
- job_details.source
- job_details.employment_type
- job_details.url
- job_details.reposted_job
Under location.:
- location.city
- location.country
- location.state
- location.raw
- location.district
Under metadata.:
- metadata.date_added
- metadata.date_updated
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › limit
Number of results to return (default: 20, max: 1000). Set to 0 with aggregations to get only counts/breakdowns without listings.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › cursor
Pagination cursor from a previous response's next_cursor field.
Clear enough to supply this argument.
params › sorts
Sort options. Each entry is {"field": ..., "order": "asc"|"desc"}. Example: [{"field": "metadata.date_added", "order": "desc"}]. Sortable fields: crustdata_job_id, metadata.date_added, metadata.date_updated, relevance (only meaningful with a text filter), company.headcount.total, company.followers.count, company.revenue.estimated.lower_bound_usd, company.funding.last_fundraise_date, company.funding.num_funding_rounds.
Clear enough to supply this argument.
params › aggregations
Get counts and breakdowns. Examples: [{"type": "count"}] for total count, [{"type": "group_by", "field": "job_details.category", "agg": "count", "size": 10}] for top categories (group_by uses "field", NOT "column"; max size 1000). Aggregatable fields: job_details.title, job_details.category, job_details.workplace_type, location.country, company.basic_info.crustdata_company_id, company.basic_info.primary_domain, company.basic_info.industries, company.headcount.range, company.funding.last_round_type.
Clear enough to supply this argument.
params › fields
Comma-separated list of fields to return per result: 'title,company_name,location,url'. Applied after flattening.
Resolve the mismatch between this description and its schema constraints.
params › compact
Strip full job descriptions to reduce response size (descriptions are often 1000+ words). Set to false to include descriptions.
Clear enough to supply this argument.
params › truncate
If true (default), enforce a 75K-char response cap by progressively compacting/dropping fields. Set to false to bypass the cap entirely — useful when dumping data for offline analysis. Claude Code spills large results to disk automatically.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › format
Response format: 'markdown' (default, compact table) or 'json' (structured data). Use 'json' when you need structured data for programmatic follow-up.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
PERSON ENRICHMENT (/person/enrich, API version 2025-11-01). It replaces the retired crustdata_people_enrich. Full person profile (work history, education, skills, social handles) by LinkedIn profile URL or business email — plural arrays, exactly one identifier type per call, max 25 each. The default response is basic_profile + social_handles only — pass `fields` for experience / education / skills / professional_network / contact. COST: additive — contact and dev-platform field groups bill add-ons on top of the base profile (run crustdata_credit_costs for rates). Contact data: contact.personal_emails / contact.phone_numbers come back here only when previously enriched — crustdata_people_contact_enrich is the on-demand contact tool. OTHER IDENTIFIERS: a personal email (e.g. Gmail) resolves through crustdata_batch_person_identify; a GitHub URL through crustdata_github_enrich. FRESH DATA: the cached dataset is used unless realtime=true, which fetches a fresh profile from the web (enterprise, URLs only). If the plan denies some requested fields, the cached path strips the gated fields and retries once (noted in the response). RESPONSE: list of {matched_on, match_type, matches: [{confidence_score, person_data}]}; unmatched identifiers return matches: [].
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › professional_network_profile_urls
LinkedIn profile URLs to enrich (max 25). Direct lookup — confidence_score is 1.0 for matches.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › business_emails
Business emails to reverse-lookup (max 25). Use min_similarity_score to control match strictness.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › fields
Sections or dot-paths to return, e.g. ['basic_profile', 'experience', 'education', 'skills', 'professional_network', 'social_handles', 'contact', 'dev_platform_profiles'] or 'basic_profile.name'. Omitted = basic_profile + social_handles only. experience / education / skills / professional_network are covered by the base credit.
Clear enough to supply this argument.
params › min_similarity_score
Minimum confidence (0-1) for business-email reverse-lookup matches. Omit to return all matches regardless of confidence.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › realtime
If true, fetch a FRESH profile from the web via /person/professional_network/enrich/live instead of the cached dataset. Slower, enterprise-only, ~10 req/min. Requires professional_network_profile_urls (no email lookup); fields may not include dev_platform_profiles. IMPORTANT: live enrich needs the EXACT current vanity URL — URL variants that the cached lookup tolerates return empty matches here. If live returns matches: [], first resolve the canonical profile_url via a cached call (realtime=false), then retry. Set this when the user wants fresh / real-time / up-to-the-minute data.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_people_enrich_v2",
"title": "Enrich person profiles",
"description": "PERSON ENRICHMENT (/person/enrich, API version 2025-11-01). It replaces the retired crustdata_people_enrich. Full person profile (work history, education, skills, social handles) by LinkedIn profile URL or business email — plural arrays, exactly one identifier type per call, max 25 each. The default response is basic_profile + social_handles only — pass `fields` for experience / education / skills / professional_network / contact. COST: additive — contact and dev-platform field groups bill add-ons on top of the base profile (run crustdata_credit_costs for rates). Contact data: contact.personal_emails / contact.phone_numbers come back here only when previously enriched — crustdata_people_contact_enrich is the on-demand contact tool. OTHER IDENTIFIERS: a personal email (e.g. Gmail) resolves through crustdata_batch_person_identify; a GitHub URL through crustdata_github_enrich. FRESH DATA: the cached dataset is used unless realtime=true, which fetches a fresh profile from the web (enterprise, URLs only). If the plan denies some requested fields, the cached path strips the gated fields and retries once (noted in the response). RESPONSE: list of {matched_on, match_type, matches: [{confidence_score, person_data}]}; unmatched identifiers return matches: [].",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"properties": {
"fields": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Sections or dot-paths to return, e.g. ['basic_profile', 'experience', 'education', 'skills', 'professional_network', 'social_handles', 'contact', 'dev_platform_profiles'] or 'basic_profile.name'. Omitted = basic_profile + social_handles only. experience / education / skills / professional_network are covered by the base credit."
},
"realtime": {
"type": "boolean",
"default": false,
"description": "If true, fetch a FRESH profile from the web via /person/professional_network/enrich/live instead of the cached dataset. Slower, enterprise-only, ~10 req/min. Requires professional_network_profile_urls (no email lookup); fields may not include dev_platform_profiles. IMPORTANT: live enrich needs the EXACT current vanity URL — URL variants that the cached lookup tolerates return empty matches here. If live returns matches: [], first resolve the canonical profile_url via a cached call (realtime=false), then retry. Set this when the user wants fresh / real-time / up-to-the-minute data."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"business_emails": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
},
"maxItems": 25
},
{
"type": "null"
}
],
"default": null,
"description": "Business emails to reverse-lookup (max 25). Use min_similarity_score to control match strictness."
},
"min_similarity_score": {
"anyOf": [
{
"type": "number",
"maximum": 1,
"minimum": 0
},
{
"type": "null"
}
],
"default": null,
"description": "Minimum confidence (0-1) for business-email reverse-lookup matches. Omit to return all matches regardless of confidence."
},
"professional_network_profile_urls": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
},
"maxItems": 25
},
{
"type": "null"
}
],
"default": null,
"description": "LinkedIn profile URLs to enrich (max 25). Direct lookup — confidence_score is 1.0 for matches."
}
},
"description": "Input for POST /person/enrich (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
PEOPLE SEARCH — DATASET (/person/search, API version 2025-11-01). It replaces the retired crustdata_people_search_db. The primary people search: filter the Crustdata people dataset by title, employer, seniority, location, education, skills, and more. Returns vanity LinkedIn URLs (linkedin.com/in/jane-doe). crustdata_people_search_live_v2 is the real-time fallback when this returns 0 results. FILTER SHAPE: leaves use {field, type, value} (NOT 'column'). Field paths are nested, e.g. basic_profile.name, experience.employment_details.current.title, experience.employment_details.current.company_name, education.schools.school. Branches use {op: 'and'|'or', conditions: [...]}. RESPONSE: a markdown table by default (with next_cursor and remarks in the footer); format='json' returns the native nested shape — basic_profile / contact / experience / education / social_handles / professional_network, with the LinkedIn URL at social_handles.professional_network_identifier.profile_url. ZERO RESULTS: `remarks` says which condition emptied the result — a condition_eliminates_all remark carries that condition's `path` (e.g. filters.conditions[2]) and `matches_without` (how many match without it), so that condition, not the whole filter, is what needs changing. no_single_culprit means removing any one probed condition still leaves 0; its message says how many of the conditions were probed.
The description explains the capability, when to use it, and what to expect.
Inputs83/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › filters
Filter tree. LEAF: {"field": "<nested.path>", "type": "<operator>", "value": ...}. BRANCH: {"op": "and"|"or"|"all_of", "conditions": [...]}. On one nested field (e.g. experience.employment_details.title) an 'and' group means ONE entry matches every condition; 'all_of' lets each condition match a different entry (held title A in one job and title B in another). NOTE: the key is "field" (not "column" like the legacy tool). Operators: =, !=, <, =<, >, => (not >= / <=), in, not_in (value is an array), has_all (array; every value matched by some entry), [.] (case-insensitive exact phrase), (.) (case-insensitive all words, any order), (!) (excludes a substring), is_null / is_not_null (value null), geo_distance, geo_exclude. Common field paths: basic_profile.name, basic_profile.headline, basic_profile.location.country, basic_profile.location.state, basic_profile.location.city, experience.employment_details.current.company_name, experience.employment_details.current.title, experience.employment_details.current.seniority_level, experience.employment_details.current.function_category, experience.employment_details.current.company_id, experience.employment_details.current.company_industries, experience.employment_details.current.company_website_domain, experience.employment_details.current.company_headcount_latest, experience.employment_details.past.company_name, experience.employment_details.past.title, education.schools.school, education.schools.degree, skills.professional_network_skills, professional_network.followers, professional_network.connections, years_of_experience_raw, recently_changed_jobs
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › limit
Results per page (1-1000, default 20). Ask for a big page + pass `fields` to keep the response manageable instead of paginating.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › cursor
Pagination cursor from previous response.
Clear enough to supply this argument.
params › sorts
Optional sort list, e.g. [{"field": "years_of_experience_raw", "order": "desc"}]. Each entry: field + order (asc/desc).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › fields
Limit response to specific field paths (e.g. ['basic_profile.name', 'social_handles.professional_network_identifier.profile_url']). Omit for full nested payload. Comma-separated string also accepted. Response paths differ from filter paths for employers: the current employer is returned as experience.employment_details.current.name / .crustdata_company_id / .company_website (not .company_name / .company_id / .company_website_domain); the past.* twins match.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › exclude_profiles
LinkedIn profile URLs to exclude from results (post_processing; up to 50,000). Use to skip people already in the user's CRM / previous pages.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › exclude_names
Exact person names to exclude from results (post_processing).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › truncate
If true (default), enforce a 75K-char response cap by progressively dropping fields. Set false when dumping raw data for offline analysis.
Clear enough to supply this argument.
params › format
Response format: 'markdown' (default) or 'json'. Markdown returns the profiles as a compact table plus the pagination footer — use json when you need structured data for programmatic follow-up (e.g. extracting LinkedIn URLs to enrich).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_people_search_db_v2",
"title": "Search people database",
"description": "PEOPLE SEARCH — DATASET (/person/search, API version 2025-11-01). It replaces the retired crustdata_people_search_db. The primary people search: filter the Crustdata people dataset by title, employer, seniority, location, education, skills, and more. Returns vanity LinkedIn URLs (linkedin.com/in/jane-doe). crustdata_people_search_live_v2 is the real-time fallback when this returns 0 results. FILTER SHAPE: leaves use {field, type, value} (NOT 'column'). Field paths are nested, e.g. basic_profile.name, experience.employment_details.current.title, experience.employment_details.current.company_name, education.schools.school. Branches use {op: 'and'|'or', conditions: [...]}. RESPONSE: a markdown table by default (with next_cursor and remarks in the footer); format='json' returns the native nested shape — basic_profile / contact / experience / education / social_handles / professional_network, with the LinkedIn URL at social_handles.professional_network_identifier.profile_url. ZERO RESULTS: `remarks` says which condition emptied the result — a condition_eliminates_all remark carries that condition's `path` (e.g. filters.conditions[2]) and `matches_without` (how many match without it), so that condition, not the whole filter, is what needs changing. no_single_culprit means removing any one probed condition still leaves 0; its message says how many of the conditions were probed.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"filters"
],
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 1000,
"minimum": 1,
"description": "Results per page (1-1000, default 20). Ask for a big page + pass `fields` to keep the response manageable instead of paginating."
},
"sorts": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
{
"type": "null"
}
],
"default": null,
"description": "Optional sort list, e.g. [{\"field\": \"years_of_experience_raw\", \"order\": \"desc\"}]. Each entry: field + order (asc/desc)."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Pagination cursor from previous response."
},
"fields": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Limit response to specific field paths (e.g. ['basic_profile.name', 'social_handles.professional_network_identifier.profile_url']). Omit for full nested payload. Comma-separated string also accepted. Response paths differ from filter paths for employers: the current employer is returned as experience.employment_details.current.name / .crustdata_company_id / .company_website (not .company_name / .company_id / .company_website_domain); the past.* twins match."
},
"format": {
"enum": [
"markdown",
"json"
],
"type": "string",
"default": "markdown",
"description": "Response format: 'markdown' (default) or 'json'. Markdown returns the profiles as a compact table plus the pagination footer — use json when you need structured data for programmatic follow-up (e.g. extracting LinkedIn URLs to enrich)."
},
"filters": {
"type": "object",
"description": "Filter tree. LEAF: {\"field\": \"<nested.path>\", \"type\": \"<operator>\", \"value\": ...}. BRANCH: {\"op\": \"and\"|\"or\"|\"all_of\", \"conditions\": [...]}. On one nested field (e.g. experience.employment_details.title) an 'and' group means ONE entry matches every condition; 'all_of' lets each condition match a different entry (held title A in one job and title B in another). NOTE: the key is \"field\" (not \"column\" like the legacy tool). Operators: =, !=, <, =<, >, => (not >= / <=), in, not_in (value is an array), has_all (array; every value matched by some entry), [.] (case-insensitive exact phrase), (.) (case-insensitive all words, any order), (!) (excludes a substring), is_null / is_not_null (value null), geo_distance, geo_exclude. Common field paths: basic_profile.name, basic_profile.headline, basic_profile.location.country, basic_profile.location.state, basic_profile.location.city, experience.employment_details.current.company_name, experience.employment_details.current.title, experience.employment_details.current.seniority_level, experience.employment_details.current.function_category, experience.employment_details.current.company_id, experience.employment_details.current.company_industries, experience.employment_details.current.company_website_domain, experience.employment_details.current.company_headcount_latest, experience.employment_details.past.company_name, experience.employment_details.past.title, education.schools.school, education.schools.degree, skills.professional_network_skills, professional_network.followers, professional_network.connections, years_of_experience_raw, recently_changed_jobs",
"additionalProperties": true
},
"truncate": {
"type": "boolean",
"default": true,
"description": "If true (default), enforce a 75K-char response cap by progressively dropping fields. Set false when dumping raw data for offline analysis."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"exclude_names": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Exact person names to exclude from results (post_processing)."
},
"exclude_profiles": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
},
"maxItems": 50000
},
{
"type": "null"
}
],
"default": null,
"description": "LinkedIn profile URLs to exclude from results (post_processing; up to 50,000). Use to skip people already in the user's CRM / previous pages."
}
},
"description": "Input parameters for the new /person/search dataset API (2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
PEOPLE SEMANTIC SEARCH (beta) — natural-language people search on the /person/search dataset (v2025-11-01). crustdata_people_search_db_v2 covers ordinary filter-based people search. This tool is for requests that ask for semantic / natural-language search specifically — 'use semantic search', 'natural-language search', 'search by description', 'rank these by relevance', or a pasted job description with a request for similar people. WHAT IT DOES: ranks people by how well their whole profile (title, skills, company history, education, location, summary) matches `query`. KEY BEHAVIORS: (1) It always returns results — the per-profile `fit` tier (strong / possible / weak) is the quality signal; the result count is not. (2) `total_count` is the size of the ranked pool, not a count of good matches. (3) Results are already relevance-ordered — sorting is not available. PARAMS: `query` (required natural-language text); `search_mode` (hybrid/lexical/semantic); `recall_mode` (managed/exact — use 'exact' to enforce `filters` as hard constraints); `query_syntax='boolean'` reads `query` as a keyword expression (AND / | / + / - / "phrase" / prefix*; lexical + exact only); optional `filters` (same tree shape as crustdata_people_search_db_v2, leaves use 'field' not 'column'). RESPONSE: a markdown table by default (with a Fit column); format='json' returns the native nested v2 shape (basic_profile / contact / experience / education / social_handles / professional_network) plus a per-profile `fit` tier, with top-level total_count + total_count_relation (eq | gte).
The description explains the capability, when to use it, and what to expect.
Inputs80/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › query
Natural-language description of the people to find — a role, persona, skill set, or pasted job description. e.g. 'founding engineers at developer-tools startups', 'backend engineers with Golang and distributed systems experience'. This text is the ranking signal.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › search_mode
Retrieval signal for the query (maps to search.mode). 'hybrid' (default) = keyword + vector, best general default. 'lexical' = keyword only (exact terms, acronyms, names, IDs). 'semantic' = vector only (concept match even with different wording).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › query_syntax
How `query` is read (maps to search.query_syntax). 'plain' (default) = plain text. 'boolean' = a keyword expression: a space is AND, '|' is OR, '+term' is required, '-term' is excluded, "..." is an exact phrase, 'kuber*' is a prefix, and () groups, e.g. '"site reliability" +kubernetes (golang | rust) -recruiter'. 'boolean' needs search_mode='lexical' and recall_mode='exact'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › recall_mode
How explicit filters combine with the query (maps to the top-level mode). 'managed' (default) = filters are a recall/ranking signal and Crustdata may extract extra constraints from the query. 'exact' = filters are enforced as a hard set and the query only ranks within it. Use 'exact' when every returned profile has to satisfy the filters, or when counts need to be reproducible.
Clear enough to supply this argument.
params › filters
OPTIONAL structured filter tree to constrain/seed the ranked set — same shape as crustdata_people_search_db_v2. LEAF: {"field": "<nested.path>", "type": "<operator>", "value": ...}. BRANCH: {"op": "and"|"or", "conditions": [...]}. Common field paths: basic_profile.name, basic_profile.headline, basic_profile.location.country, basic_profile.location.state, basic_profile.location.city, experience.employment_details.current.company_name, experience.employment_details.current.title, experience.employment_details.current.seniority_level, experience.employment_details.current.function_category, experience.employment_details.current.company_id, experience.employment_details.current.company_industries, experience.employment_details.current.company_website_domain, experience.employment_details.current.company_headcount_latest, experience.employment_details.past.company_name, experience.employment_details.past.title, education.schools.school, education.schools.degree, skills.professional_network_skills, professional_network.followers, professional_network.connections, years_of_experience_raw, recently_changed_jobs
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › limit
Results per page (1-500, default 20). Semantic ranking degrades in the tail — prefer moderate pages plus the `fit` tier over one huge dump.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › cursor
Pagination cursor from a previous response.
Clear enough to supply this argument.
params › fields
Limit the response to specific field paths (list or comma-separated string). 'fit' is auto-added so the per-profile relevance tier is never dropped. Omit for the full nested payload. Response paths differ from filter paths for employers: the current employer is returned as experience.employment_details.current.name / .crustdata_company_id / .company_website (not .company_name / .company_id / .company_website_domain); the past.* twins match.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › truncate
If true (default), enforce a 75K-char response cap by progressively dropping fields. Set false when dumping raw data for offline analysis.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › format
Response format: 'markdown' (default) or 'json'. Markdown returns the profiles as a compact table plus the pagination footer — use json when you need structured data for programmatic follow-up (e.g. extracting LinkedIn URLs to enrich).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_people_search_semantic",
"title": "Semantic people search",
"description": "PEOPLE SEMANTIC SEARCH (beta) — natural-language people search on the /person/search dataset (v2025-11-01). crustdata_people_search_db_v2 covers ordinary filter-based people search. This tool is for requests that ask for semantic / natural-language search specifically — 'use semantic search', 'natural-language search', 'search by description', 'rank these by relevance', or a pasted job description with a request for similar people. WHAT IT DOES: ranks people by how well their whole profile (title, skills, company history, education, location, summary) matches `query`. KEY BEHAVIORS: (1) It always returns results — the per-profile `fit` tier (strong / possible / weak) is the quality signal; the result count is not. (2) `total_count` is the size of the ranked pool, not a count of good matches. (3) Results are already relevance-ordered — sorting is not available. PARAMS: `query` (required natural-language text); `search_mode` (hybrid/lexical/semantic); `recall_mode` (managed/exact — use 'exact' to enforce `filters` as hard constraints); `query_syntax='boolean'` reads `query` as a keyword expression (AND / | / + / - / \"phrase\" / prefix*; lexical + exact only); optional `filters` (same tree shape as crustdata_people_search_db_v2, leaves use 'field' not 'column'). RESPONSE: a markdown table by default (with a Fit column); format='json' returns the native nested v2 shape (basic_profile / contact / experience / education / social_handles / professional_network) plus a per-profile `fit` tier, with top-level total_count + total_count_relation (eq | gte).",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"query"
],
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 500,
"minimum": 1,
"description": "Results per page (1-500, default 20). Semantic ranking degrades in the tail — prefer moderate pages plus the `fit` tier over one huge dump."
},
"query": {
"type": "string",
"minLength": 1,
"description": "Natural-language description of the people to find — a role, persona, skill set, or pasted job description. e.g. 'founding engineers at developer-tools startups', 'backend engineers with Golang and distributed systems experience'. This text is the ranking signal."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Pagination cursor from a previous response."
},
"fields": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Limit the response to specific field paths (list or comma-separated string). 'fit' is auto-added so the per-profile relevance tier is never dropped. Omit for the full nested payload. Response paths differ from filter paths for employers: the current employer is returned as experience.employment_details.current.name / .crustdata_company_id / .company_website (not .company_name / .company_id / .company_website_domain); the past.* twins match."
},
"format": {
"enum": [
"markdown",
"json"
],
"type": "string",
"default": "markdown",
"description": "Response format: 'markdown' (default) or 'json'. Markdown returns the profiles as a compact table plus the pagination footer — use json when you need structured data for programmatic follow-up (e.g. extracting LinkedIn URLs to enrich)."
},
"filters": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "OPTIONAL structured filter tree to constrain/seed the ranked set — same shape as crustdata_people_search_db_v2. LEAF: {\"field\": \"<nested.path>\", \"type\": \"<operator>\", \"value\": ...}. BRANCH: {\"op\": \"and\"|\"or\", \"conditions\": [...]}. Common field paths: basic_profile.name, basic_profile.headline, basic_profile.location.country, basic_profile.location.state, basic_profile.location.city, experience.employment_details.current.company_name, experience.employment_details.current.title, experience.employment_details.current.seniority_level, experience.employment_details.current.function_category, experience.employment_details.current.company_id, experience.employment_details.current.company_industries, experience.employment_details.current.company_website_domain, experience.employment_details.current.company_headcount_latest, experience.employment_details.past.company_name, experience.employment_details.past.title, education.schools.school, education.schools.degree, skills.professional_network_skills, professional_network.followers, professional_network.connections, years_of_experience_raw, recently_changed_jobs"
},
"truncate": {
"type": "boolean",
"default": true,
"description": "If true (default), enforce a 75K-char response cap by progressively dropping fields. Set false when dumping raw data for offline analysis."
},
"recall_mode": {
"enum": [
"managed",
"exact"
],
"type": "string",
"default": "managed",
"description": "How explicit filters combine with the query (maps to the top-level mode). 'managed' (default) = filters are a recall/ranking signal and Crustdata may extract extra constraints from the query. 'exact' = filters are enforced as a hard set and the query only ranks within it. Use 'exact' when every returned profile has to satisfy the filters, or when counts need to be reproducible."
},
"search_mode": {
"enum": [
"hybrid",
"lexical",
"semantic"
],
"type": "string",
"default": "hybrid",
"description": "Retrieval signal for the query (maps to search.mode). 'hybrid' (default) = keyword + vector, best general default. 'lexical' = keyword only (exact terms, acronyms, names, IDs). 'semantic' = vector only (concept match even with different wording)."
},
"query_syntax": {
"enum": [
"plain",
"boolean"
],
"type": "string",
"default": "plain",
"description": "How `query` is read (maps to search.query_syntax). 'plain' (default) = plain text. 'boolean' = a keyword expression: a space is AND, '|' is OR, '+term' is required, '-term' is excluded, \"...\" is an exact phrase, 'kuber*' is a prefix, and () groups, e.g. '\"site reliability\" +kubernetes (golang | rust) -recruiter'. 'boolean' needs search_mode='lexical' and recall_mode='exact'."
}
},
"description": "Input parameters for Person Semantic Search (beta) on POST /person/search."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
Align the title with the capability actually described by this tool.
Description91/100
RENAMED — call crustdata_batch_person_contact_enrich instead. This name is kept as a temporary alias for backward compatibility; it forwards to crustdata_batch_person_contact_enrich unchanged and will be removed in a future release. The new name says what the tool actually returns — CONTACT fields (business email / personal emails / phone numbers) — so it can't be mistaken for crustdata_batch_person_profile_enrich, which returns full profiles.
The description explains the capability, when to use it, and what to expect.
Inputs85/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › professional_network_profile_urls
List of LinkedIn profile URLs to enrich (1-300 per job — the API rejects more; split a longer list into several jobs). Example: ['https://www.linkedin.com/in/satyanadella', 'https://www.linkedin.com/in/sundarpichai']. Each URL costs the vendor charge per result returned (see fields).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › fields
Dotted-path field names to return. Default: ['business_email', 'personal_contact_info.personal_emails', 'personal_contact_info.phone_numbers']. Other valid roots: 'business_email', 'personal_contact_info'. Note: the new-API field-path style uses dots — e.g. 'personal_contact_info.phone_numbers', NOT 'phone_numbers'. The endpoint will return its valid field list on a bad name.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › verified
Keep only business emails that pass a deliverability check (deliverable or catch_all). A person left with none gets an empty business_email list and business_email_message 'no verified emails found'. Affects business_email only; adds 0.5 credits per matched person who gets at least one verified business email.
Clear enough to supply this argument.
params › poll_timeout_seconds
Max seconds to wait for batch completion before returning a timeout response (default 300). Long-running batches return the batch_id so the caller can re-poll later via the same status endpoint.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_batch_people_enrich",
"title": "Batch enrich contact details (renamed alias)",
"description": "RENAMED — call crustdata_batch_person_contact_enrich instead. This name is kept as a temporary alias for backward compatibility; it forwards to crustdata_batch_person_contact_enrich unchanged and will be removed in a future release. The new name says what the tool actually returns — CONTACT fields (business email / personal emails / phone numbers) — so it can't be mistaken for crustdata_batch_person_profile_enrich, which returns full profiles.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"professional_network_profile_urls"
],
"properties": {
"fields": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Dotted-path field names to return. Default: ['business_email', 'personal_contact_info.personal_emails', 'personal_contact_info.phone_numbers']. Other valid roots: 'business_email', 'personal_contact_info'. Note: the new-API field-path style uses dots — e.g. 'personal_contact_info.phone_numbers', NOT 'phone_numbers'. The endpoint will return its valid field list on a bad name."
},
"verified": {
"type": "boolean",
"default": false,
"description": "Keep only business emails that pass a deliverability check (deliverable or catch_all). A person left with none gets an empty business_email list and business_email_message 'no verified emails found'. Affects business_email only; adds 0.5 credits per matched person who gets at least one verified business email."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"poll_timeout_seconds": {
"type": "integer",
"default": 300,
"maximum": 600,
"minimum": 30,
"description": "Max seconds to wait for batch completion before returning a timeout response (default 300). Long-running batches return the batch_id so the caller can re-poll later via the same status endpoint."
},
"professional_network_profile_urls": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 300,
"minItems": 1,
"description": "List of LinkedIn profile URLs to enrich (1-300 per job — the API rejects more; split a longer list into several jobs). Example: ['https://www.linkedin.com/in/satyanadella', 'https://www.linkedin.com/in/sundarpichai']. Each URL costs the vendor charge per result returned (see fields)."
}
},
"description": "Input parameters for batch contact enrichment."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
RETRIEVE AN EXISTING ASYNC BATCH by its batch_id — status plus results. Use this whenever a batch tool returned a batch_id instead of results because the job was still running: contact enrich, profile enrich, company enrich, job search, and person identify all funnel through it. It polls the job and, once complete, returns the records. It does NOT submit a new job and NEVER bills again — so when a batch times out, call THIS with the same batch_id rather than re-running the submit tool, which would start a fresh billable batch. RESPONSE: the API's job status verbatim — {batch_id, status (pending / processing / completed / failed), entity, action, identifier_count, result_count, entities_requested, entities_fulfilled, created_at, completed_at, error_message (failed jobs), download_url + download_urls (completed jobs)} — plus `results`, the downloaded records, once a completed job has any. While the job is still running, just call again later. An unknown or expired id returns a clear error (result files are retrievable for ~5 days after completion).
The description explains the capability, when to use it, and what to expect.
Inputs92/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › batch_id
The batch_id handed back by a batch submit tool (e.g. crustdata_batch_person_contact_enrich). This retrieves that existing job — it does NOT start a new one and never bills again.
Clear enough to supply this argument.
params › poll_timeout_seconds
Max seconds to wait if the job is still running before returning a status response (default 300). Pass 0 for an immediate one-shot status check. A timeout is not an error — the job keeps running server-side; call this tool again later with the same batch_id.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_get_batch",
"title": "Get batch job results",
"description": "RETRIEVE AN EXISTING ASYNC BATCH by its batch_id — status plus results. Use this whenever a batch tool returned a batch_id instead of results because the job was still running: contact enrich, profile enrich, company enrich, job search, and person identify all funnel through it. It polls the job and, once complete, returns the records. It does NOT submit a new job and NEVER bills again — so when a batch times out, call THIS with the same batch_id rather than re-running the submit tool, which would start a fresh billable batch. RESPONSE: the API's job status verbatim — {batch_id, status (pending / processing / completed / failed), entity, action, identifier_count, result_count, entities_requested, entities_fulfilled, created_at, completed_at, error_message (failed jobs), download_url + download_urls (completed jobs)} — plus `results`, the downloaded records, once a completed job has any. While the job is still running, just call again later. An unknown or expired id returns a clear error (result files are retrievable for ~5 days after completion).",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"batch_id"
],
"properties": {
"batch_id": {
"type": "string",
"description": "The batch_id handed back by a batch submit tool (e.g. crustdata_batch_person_contact_enrich). This retrieves that existing job — it does NOT start a new one and never bills again."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"poll_timeout_seconds": {
"type": "integer",
"default": 300,
"maximum": 600,
"minimum": 0,
"description": "Max seconds to wait if the job is still running before returning a status response (default 300). Pass 0 for an immediate one-shot status check. A timeout is not an error — the job keeps running server-side; call this tool again later with the same batch_id."
}
},
"description": "Input for retrieving an existing async batch job by its ID."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
LIST THE ACCOUNT'S ASYNC BATCH JOBS, most recent first — every batch type (company/person enrich, contact enrich, person identify, job search). Use it to find a batch_id you no longer have, or to see what is still running. Optional `status` filter (pending / processing / completed / failed); page with `cursor` = the previous page's next_cursor while has_more is true. Summaries only, no records or download links — pass a job's batch_id to crustdata_get_batch for its results. FREE. RESPONSE: {jobs: [{batch_id, status, entity, action, identifier_count, result_count, entities_requested, entities_fulfilled, created_at, completed_at}], job_count, next_cursor, has_more}.
The description explains the capability, when to use it, and what to expect.
Inputs81/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › limit
Jobs per page (1-100, default 20).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › status
Return only jobs in this status. Omit to list jobs in every status.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › cursor
The next_cursor from the previous page. Omit on the first page.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_list_batches",
"title": "List batch jobs",
"description": "LIST THE ACCOUNT'S ASYNC BATCH JOBS, most recent first — every batch type (company/person enrich, contact enrich, person identify, job search). Use it to find a batch_id you no longer have, or to see what is still running. Optional `status` filter (pending / processing / completed / failed); page with `cursor` = the previous page's next_cursor while has_more is true. Summaries only, no records or download links — pass a job's batch_id to crustdata_get_batch for its results. FREE. RESPONSE: {jobs: [{batch_id, status, entity, action, identifier_count, result_count, entities_requested, entities_fulfilled, created_at, completed_at}], job_count, next_cursor, has_more}.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Jobs per page (1-100, default 20)."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The next_cursor from the previous page. Omit on the first page."
},
"status": {
"anyOf": [
{
"enum": [
"pending",
"processing",
"completed",
"failed"
],
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Return only jobs in this status. Omit to list jobs in every status."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
}
},
"description": "Input for listing the account's async batch jobs, most recent first."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
Shorten the title to an action and subject; move usage details into the description.
Description96/100
Retired. Company identify on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_company_identify_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_identify",
"title": "Identify companies (retired v1 API)",
"description": "Retired. Company identify on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_company_identify_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description96/100
Retired. Company enrichment on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_company_enrich_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.
The description explains the capability, when to use it, and what to expect.
Inputs95/100
Input documentation gives an agent enough context to populate the arguments.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_enrich",
"title": "Enrich companies (retired v1 API)",
"description": "Retired. Company enrichment on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_company_enrich_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
Retired. Company database search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_company_search_db_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Input documentation gives an agent enough context to populate the arguments.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_search_db",
"title": "Search company database (retired v1 API)",
"description": "Retired. Company database search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_company_search_db_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Align the title with the capability actually described by this tool.
Description95/100
Retired. Live company search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_company_search_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_company_search_db_v2 covers it for the indexed company dataset.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Input documentation gives an agent enough context to populate the arguments.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_search",
"title": "Search companies live (retired v1 API)",
"description": "Retired. Live company search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_company_search_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_company_search_db_v2 covers it for the indexed company dataset.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Autocomplete company filter values (retired v1 API)
Shorten the title to an action and subject; move usage details into the description.
Description97/100
Retired. Company filter autocomplete on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_autocomplete_company_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_autocomplete_company",
"title": "Autocomplete company filter values (retired v1 API)",
"description": "Retired. Company filter autocomplete on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_autocomplete_company_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Shorten the title to an action and subject; move usage details into the description.
Description98/100
Retired. Person enrichment on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_people_enrich_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_people_contact_enrich covers it for emails and phone numbers.
The description explains the capability, when to use it, and what to expect.
Inputs95/100
Input documentation gives an agent enough context to populate the arguments.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_people_enrich",
"title": "Enrich person profiles (retired v1 API)",
"description": "Retired. Person enrichment on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_people_enrich_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_people_contact_enrich covers it for emails and phone numbers.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Shorten the title to an action and subject; move usage details into the description.
Description97/100
Retired. People database search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_people_search_db_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.
The description explains the capability, when to use it, and what to expect.
Inputs96/100
Remove repeated schema validation from descriptions; focus on meaning and usage context.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_people_search_db",
"title": "Search people database (retired v1 API)",
"description": "Retired. People database search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_people_search_db_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Shorten the title to an action and subject; move usage details into the description.
Description97/100
Retired. Live people search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_people_search_live_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_people_search_db_v2 covers it for the indexed people dataset.
The description explains the capability, when to use it, and what to expect.
Inputs95/100
Input documentation gives an agent enough context to populate the arguments.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_people_search",
"title": "Search people live (retired v1 API)",
"description": "Retired. Live people search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_people_search_live_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_people_search_db_v2 covers it for the indexed people dataset.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Autocomplete person filter values (retired v1 API)
Shorten the title to an action and subject; move usage details into the description.
Description97/100
Retired. Person filter autocomplete on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_autocomplete_person_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_autocomplete_person",
"title": "Autocomplete person filter values (retired v1 API)",
"description": "Retired. Person filter autocomplete on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_autocomplete_person_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Shorten the title to an action and subject; move usage details into the description.
Description97/100
Retired. Social posts by profile on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_social_posts_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_social_post_search covers it for the indexed post dataset.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_social_posts",
"title": "Get LinkedIn posts (retired v1 API)",
"description": "Retired. Social posts by profile on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_social_posts_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_social_post_search covers it for the indexed post dataset.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Shorten the title to an action and subject; move usage details into the description.
Description96/100
Retired. Social post keyword search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_social_posts_by_keyword_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_social_post_search covers it for the indexed post dataset.
The description explains the capability, when to use it, and what to expect.
Inputs95/100
Input documentation gives an agent enough context to populate the arguments.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_social_posts_by_keyword",
"title": "Search LinkedIn posts by keyword (retired v1 API)",
"description": "Retired. Social post keyword search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_social_posts_by_keyword_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_social_post_search covers it for the indexed post dataset.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Align the title with the capability actually described by this tool.
Description96/100
Retired. Social post keyword search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_social_posts_by_keyword_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_social_post_search covers it for the indexed post dataset.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_social_posts",
"title": "Search LinkedIn posts by keyword (retired alias)",
"description": "Retired. Social post keyword search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_social_posts_by_keyword_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name. crustdata_social_post_search covers it for the indexed post dataset.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Shorten the title to an action and subject; move usage details into the description.
Description96/100
Retired. Web search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_web_search_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_web_search",
"title": "Search the web (retired v1 API)",
"description": "Retired. Web search on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_web_search_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Shorten the title to an action and subject; move usage details into the description.
Description97/100
Retired. Web page fetch on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_web_fetch_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_web_fetch",
"title": "Fetch a web page (retired v1 API)",
"description": "Retired. Web page fetch on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_web_fetch_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Shorten the title to an action and subject; move usage details into the description.
Description97/100
Retired. Live-search filter autocomplete on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_autocomplete_filter_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.
The description explains the capability, when to use it, and what to expect.
Inputs75/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params
Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_autocomplete_filter",
"title": "Autocomplete live-search filter values (retired v1 API)",
"description": "Retired. Live-search filter autocomplete on the v1 API, which has been shut down; every call returns an error and makes no API request. crustdata_autocomplete_filter_v2 covers this capability on the current API, including requests that ask for the legacy or v1 API by name.",
"inputSchema": {
"type": "object",
"properties": {
"params": {
"type": "object",
"default": {},
"properties": {},
"description": "Accepted and ignored: this tool was retired with the v1 API and returns an error naming its replacement.",
"additionalProperties": true
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description94/100
Install Crustdata research skills locally so they appear as native /slash-commands in Claude Code (e.g., /research-person). By default writes full skill content (SKILL.md + helper files like references/, scripts/) plus a .crustdata_version marker. Each skill becomes invokable without any further server roundtrips. Use crustdata_skill_versions periodically to check whether a re-install is needed.
The description explains the capability, when to use it, and what to expect.
Inputs95/100
Input documentation gives an agent enough context to populate the arguments.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › stub_only
If true, install only thin SKILL.md stubs that fetch full content via crustdata_get_skill_body on every invocation (legacy behavior — guarantees always-fresh content but adds a tool roundtrip per use). Default: false (write full skill content + helper files locally for fast invocation, with a .crustdata_version marker so clients can check freshness via crustdata_skill_versions).
Clear enough to supply this argument.
params › only
Optional list of skill names to install. When set, only those skills are returned (intersected with the caller's grants). Used by the per-skill auto-update preamble to fetch just the one skill being invoked, keeping the response small enough for the Claude Code harness to process. When omitted, returns every granted skill.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_install_skills",
"title": "Install Crustdata skills",
"description": "Install Crustdata research skills locally so they appear as native /slash-commands in Claude Code (e.g., /research-person). By default writes full skill content (SKILL.md + helper files like references/, scripts/) plus a .crustdata_version marker. Each skill becomes invokable without any further server roundtrips. Use crustdata_skill_versions periodically to check whether a re-install is needed.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"properties": {
"only": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Optional list of skill names to install. When set, only those skills are returned (intersected with the caller's grants). Used by the per-skill auto-update preamble to fetch just the one skill being invoked, keeping the response small enough for the Claude Code harness to process. When omitted, returns every granted skill."
},
"stub_only": {
"type": "boolean",
"default": false,
"description": "If true, install only thin SKILL.md stubs that fetch full content via crustdata_get_skill_body on every invocation (legacy behavior — guarantees always-fresh content but adds a tool roundtrip per use). Default: false (write full skill content + helper files locally for fast invocation, with a .crustdata_version marker so clients can check freshness via crustdata_skill_versions)."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
}
},
"description": "Input parameters for installing Crustdata skills locally."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description91/100
Return current server-side version markers for the caller's granted skills. Each version is the ISO timestamp of the most recent update to the skill in the admin DB. Compare against the .crustdata_version file written at install time — if they differ, re-run crustdata_install_skills to refresh local content. Cheap, single DB query. Safe to call once per session.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_skill_versions",
"title": "Check installed skill versions",
"description": "Return current server-side version markers for the caller's granted skills. Each version is the ISO timestamp of the most recent update to the skill in the admin DB. Compare against the .crustdata_version file written at install time — if they differ, re-run crustdata_install_skills to refresh local content. Cheap, single DB query. Safe to call once per session.",
"inputSchema": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description93/100
Fetch a helper file (reference, script, README, etc.) for a centrally-managed skill. Use this whenever the live SKILL.md body (from crustdata_get_skill_body) references a relative path like `references/foo.md` or `scripts/bar.py` — the file is NOT installed locally, only on the server. For executable scripts, write the returned content to a temp path before running.
The description explains the capability, when to use it, and what to expect.
Inputs92/100
Explain what happens when this optional value is omitted.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Explain what happens when this optional value is omitted.
params › skill_name
Name of the skill (folder name), e.g. 'source-candidates'.
Clear enough to supply this argument.
params › file_path
Relative path within the skill, e.g. 'references/profile-card.md' or 'scripts/compress_pool.py'.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_get_skill_file",
"title": "Get a skill helper file",
"description": "Fetch a helper file (reference, script, README, etc.) for a centrally-managed skill. Use this whenever the live SKILL.md body (from crustdata_get_skill_body) references a relative path like `references/foo.md` or `scripts/bar.py` — the file is NOT installed locally, only on the server. For executable scripts, write the returned content to a temp path before running.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"skill_name",
"file_path"
],
"properties": {
"file_path": {
"type": "string",
"description": "Relative path within the skill, e.g. 'references/profile-card.md' or 'scripts/compress_pool.py'."
},
"skill_name": {
"type": "string",
"description": "Name of the skill (folder name), e.g. 'source-candidates'."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
}
},
"description": "Input parameters for fetching a helper file from a skill."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
Fetch the live SKILL.md body for a centrally-managed skill. The local SKILL.md installed at ~/.claude/skills/<name>/SKILL.md is intentionally a stub that points here — call this tool to get the current playbook before executing the skill. Returns the full instructions exactly as authored in the admin UI. Throws if the caller hasn't been granted access to this skill.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Explain what happens when this optional value is omitted.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Explain what happens when this optional value is omitted.
params › skill_name
Name of the skill (folder name), e.g. 'research-person'.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_get_skill_body",
"title": "Get a skill playbook",
"description": "Fetch the live SKILL.md body for a centrally-managed skill. The local SKILL.md installed at ~/.claude/skills/<name>/SKILL.md is intentionally a stub that points here — call this tool to get the current playbook before executing the skill. Returns the full instructions exactly as authored in the admin UI. Throws if the caller hasn't been granted access to this skill.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"skill_name"
],
"properties": {
"skill_name": {
"type": "string",
"description": "Name of the skill (folder name), e.g. 'research-person'."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
}
},
"description": "Input parameters for fetching a skill's live SKILL.md body."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
List the Crustdata skills your account has access to install. Use this BEFORE crustdata_install_skills to see what's available, or to confirm what was granted. Returns names + descriptions.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_list_my_skills",
"title": "List available skills",
"description": "List the Crustdata skills your account has access to install. Use this BEFORE crustdata_install_skills to see what's available, or to confirm what was granted. Returns names + descriptions.",
"inputSchema": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
SOCIAL POST SEARCH (/social_post/search, API version 2025-11-01). Searches the indexed LinkedIn post dataset — the tool for questions about posts: what a person or company posted, posts mentioning a keyword, company, or person, the most-engaged posts on a topic, and who reacted or commented. Each post carries its author (with Crustdata id, title, employer, location), engagement counts, and on request every reactor and commenter. COST: billed per post returned; limit=0 counts matches for free (run crustdata_credit_costs for rates). FRESHNESS: the index trails the live network by days to a couple of weeks; crustdata_social_posts_v2 (by author or post URL) and crustdata_social_posts_by_keyword_v2 (by keyword) fetch straight from the network when the latest posts matter. A company's posts take two calls: crustdata_company_identify_v2 (free) returns the company's crustdata_company_id — every candidate when a name is ambiguous, so the right company is picked before anything is searched — then filters actor.crustdata_entity_id = that id with actor.actor_type = 'company'. Filters use {field, type, value} leaves; a keyword is text with '[.]'. Pagination is cursor-based. RESPONSE: a markdown table by default (with total and next_cursor); format='json' returns {posts, next_cursor, total_count}.
The description explains the capability, when to use it, and what to expect.
Inputs82/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › filters
Filter tree. Leaves: {field, type, value}; groups: {op: 'and'|'or', conditions: [...]} (a bare list is an AND group). Author: actor.crustdata_entity_id (a company id from crustdata_company_identify_v2, a person id from crustdata_people_search_db_v2 / crustdata_people_enrich_v2) together with actor.actor_type = 'company' | 'person'; a person's profile URL also matches on actor.professional_network_url (company pages are stored with a /posts suffix, so match companies by id: crustdata_company_identify_v2 first). Text: text with '[.]' (exact phrase) or '(.)' (all words, typo-tolerant). Other fields: date_posted (ISO date, with '=>' / '=<'), post_type, hashtags, actor.name / title / company_name / industry / location.country, engagement.total_reactions / total_comments, reactors.name / title / company, comments.text, mentions.company_id / person_id, content_type ('document' | 'article' | 'poll'). Operators: =, !=, <, =<, >, =>, in, not_in, is_null, is_not_null, (.), [.], has_all, geo_distance / geo_exclude (actor.location only). Omit for all posts.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › sorts
Sorts: [{field, order: 'asc'|'desc'}]. Sortable: date_posted (the default, newest first), engagement.total_reactions, engagement.total_comments, engagement.num_shares, post_type, actor.actor_type, and a few more.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › limit
Posts per page (0-1000, default 20). limit=0 returns only total_count, free of charge.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › cursor
Opaque next_cursor from the previous page.
Clear enough to supply this argument.
params › fields
Dot-paths to return per post (list or comma-separated). Omitted: every group except reactors and comments. Add 'reactors' / 'comments' to get who reacted and commented (returned in full, so ask for them only when needed).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › format
Response format: 'markdown' (default) or 'json'. Markdown returns the posts as a compact table (author, text, date, engagement counts, URL) — use json when you need structured data for programmatic follow-up. Requests for reactors or comments always return json, since the per-post reactor/commenter lists do not fit a table.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_social_post_search",
"title": "Search social posts",
"description": "SOCIAL POST SEARCH (/social_post/search, API version 2025-11-01). Searches the indexed LinkedIn post dataset — the tool for questions about posts: what a person or company posted, posts mentioning a keyword, company, or person, the most-engaged posts on a topic, and who reacted or commented. Each post carries its author (with Crustdata id, title, employer, location), engagement counts, and on request every reactor and commenter. COST: billed per post returned; limit=0 counts matches for free (run crustdata_credit_costs for rates). FRESHNESS: the index trails the live network by days to a couple of weeks; crustdata_social_posts_v2 (by author or post URL) and crustdata_social_posts_by_keyword_v2 (by keyword) fetch straight from the network when the latest posts matter. A company's posts take two calls: crustdata_company_identify_v2 (free) returns the company's crustdata_company_id — every candidate when a name is ambiguous, so the right company is picked before anything is searched — then filters actor.crustdata_entity_id = that id with actor.actor_type = 'company'. Filters use {field, type, value} leaves; a keyword is text with '[.]'. Pagination is cursor-based. RESPONSE: a markdown table by default (with total and next_cursor); format='json' returns {posts, next_cursor, total_count}.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 1000,
"minimum": 0,
"description": "Posts per page (0-1000, default 20). limit=0 returns only total_count, free of charge."
},
"sorts": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
{
"type": "null"
}
],
"default": null,
"description": "Sorts: [{field, order: 'asc'|'desc'}]. Sortable: date_posted (the default, newest first), engagement.total_reactions, engagement.total_comments, engagement.num_shares, post_type, actor.actor_type, and a few more."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Opaque next_cursor from the previous page."
},
"fields": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Dot-paths to return per post (list or comma-separated). Omitted: every group except reactors and comments. Add 'reactors' / 'comments' to get who reacted and commented (returned in full, so ask for them only when needed)."
},
"format": {
"enum": [
"markdown",
"json"
],
"type": "string",
"default": "markdown",
"description": "Response format: 'markdown' (default) or 'json'. Markdown returns the posts as a compact table (author, text, date, engagement counts, URL) — use json when you need structured data for programmatic follow-up. Requests for reactors or comments always return json, since the per-post reactor/commenter lists do not fit a table."
},
"filters": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "array",
"items": {}
},
{
"type": "null"
}
],
"default": null,
"description": "Filter tree. Leaves: {field, type, value}; groups: {op: 'and'|'or', conditions: [...]} (a bare list is an AND group). Author: actor.crustdata_entity_id (a company id from crustdata_company_identify_v2, a person id from crustdata_people_search_db_v2 / crustdata_people_enrich_v2) together with actor.actor_type = 'company' | 'person'; a person's profile URL also matches on actor.professional_network_url (company pages are stored with a /posts suffix, so match companies by id: crustdata_company_identify_v2 first). Text: text with '[.]' (exact phrase) or '(.)' (all words, typo-tolerant). Other fields: date_posted (ISO date, with '=>' / '=<'), post_type, hashtags, actor.name / title / company_name / industry / location.country, engagement.total_reactions / total_comments, reactors.name / title / company, comments.text, mentions.company_id / person_id, content_type ('document' | 'article' | 'poll'). Operators: =, !=, <, =<, >, =>, in, not_in, is_null, is_not_null, (.), [.], has_all, geo_distance / geo_exclude (actor.location only). Omit for all posts."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
}
},
"description": "Input for POST /social_post/search (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
WEB SEARCH (/web/search/live, API version 2025-11-01). It replaces the retired crustdata_web_search. Live search across web, news, scholar, AI, and social sources. Returns result titles, URLs, and snippets — not page content: to read pages, pass result URLs to crustdata_web_fetch_v2. The country param is 'location' (ISO alpha-2); 'page' aggregates that many result pages; optional human_mode for bot-protected retrieval. RESPONSE: {success, query, timestamp (ms), results[], metadata} — result shape varies by source.
The description explains the capability, when to use it, and what to expect.
Inputs81/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › query
Search query text (max 5,000 chars). Supports operators like site: and filetype:.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › location
ISO 3166-1 alpha-2 country code for region-specific results (e.g. 'US', 'GB'). NOTE: named 'location' in v2 (v1 calls it geolocation).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › sources
Sources to query: 'web', 'news', 'scholar-articles', 'scholar-articles-enriched', 'scholar-author', 'ai', 'social'. Omit to search all sources — but always specify sources for predictable result shapes.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › site
Restrict results to a domain (e.g. 'linkedin.com/company', 'github.com'). Only effective for 'web' and 'news' sources.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › start_date
Unix timestamp (SECONDS). Only results after this date.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › end_date
Unix timestamp (SECONDS). Only results before this date. Must be > start_date.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › human_mode
Attempt a browser-like retrieval path when standard search access is blocked by bot protection.
Clear enough to supply this argument.
params › page
Number of result pages to aggregate into one response (~10 results/page). Check metadata.failed_pages / empty_pages.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description97/100
WEB FETCH (/web/enrich/live, API version 2025-11-01). It replaces the retired crustdata_web_fetch. Fetch the content of 1-10 web pages. Optional human_mode (browser-like fetch for bot-protected pages). Content is the page's visible text: HTML is stripped and each page is capped at 30,000 characters (`_content_truncated` and `_content_original_chars` mark a capped page). RESPONSE is a top-level ARRAY of {success, url, timestamp (s), title, content}. Failed URLs come back as success=false with null fields, in any order — match entries by url, not index.
The description explains the capability, when to use it, and what to expect.
Inputs83/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › urls
URLs to fetch (1-10). Must include http:// or https://.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › human_mode
Attempt a browser-like fetch path when a site is protected by Cloudflare or similar bot controls.
Explain what happens when this optional value is omitted.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_web_fetch_v2",
"title": "Fetch a web page",
"description": "WEB FETCH (/web/enrich/live, API version 2025-11-01). It replaces the retired crustdata_web_fetch. Fetch the content of 1-10 web pages. Optional human_mode (browser-like fetch for bot-protected pages). Content is the page's visible text: HTML is stripped and each page is capped at 30,000 characters (`_content_truncated` and `_content_original_chars` mark a capped page). RESPONSE is a top-level ARRAY of {success, url, timestamp (s), title, content}. Failed URLs come back as success=false with null fields, in any order — match entries by url, not index.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"urls"
],
"properties": {
"urls": {
"type": "array",
"items": {
"type": "string"
},
"maxItems": 10,
"minItems": 1,
"description": "URLs to fetch (1-10). Must include http:// or https://."
},
"human_mode": {
"anyOf": [
{
"type": "boolean"
},
{
"type": "null"
}
],
"default": null,
"description": "Attempt a browser-like fetch path when a site is protected by Cloudflare or similar bot controls."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
}
},
"description": "Input for POST /web/enrich/live (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
TECHNOGRAPHICS — what technologies a company uses (v2025-11-01). Billed as a base enrich plus a technographics add-on (rates: crustdata_credit_costs); companies with no technographics data are billed the base only. THE tool for 'what is X's tech stack?', 'does X use Snowflake?', 'what data warehouse does X run?'. Returns total_technologies (true count), top_technologies (most notable, up to 25) and — where the account has field-level permission — a detailed technologies[] list of {name, category, sources}, ordered by how central the tech is to the company. Sources are 'web signals' (the company's site) or 'job posting'. Provide EXACTLY ONE identifier list: domains, names, crustdata_company_ids, or professional_network_profile_urls. To go the other way — find companies that use a given technology — use crustdata_company_search_by_technology.
The description explains the capability, when to use it, and what to expect.
Inputs82/100
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › domains
Company domains, e.g. ['stripe.com'].
Clear enough to supply this argument.
params › names
Company names, e.g. ['Stripe'].
Clear enough to supply this argument.
params › crustdata_company_ids
Crustdata company IDs.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
params › professional_network_profile_urls
LinkedIn company URLs.
Clarify units, where to obtain this value, or conventions not already expressed in the schema.
params › max_technologies
Cap on how many entries of the detailed technologies[] list to return per company (the API caps it at 500, which is a lot of tokens). total_technologies always reports the true count.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › compact
Flatten to one readable record per company (name, domain, counts, technologies). Set false for the raw /company/enrich match envelope.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_technographics",
"title": "Get a company's tech stack",
"description": "TECHNOGRAPHICS — what technologies a company uses (v2025-11-01). Billed as a base enrich plus a technographics add-on (rates: crustdata_credit_costs); companies with no technographics data are billed the base only. THE tool for 'what is X's tech stack?', 'does X use Snowflake?', 'what data warehouse does X run?'. Returns total_technologies (true count), top_technologies (most notable, up to 25) and — where the account has field-level permission — a detailed technologies[] list of {name, category, sources}, ordered by how central the tech is to the company. Sources are 'web signals' (the company's site) or 'job posting'. Provide EXACTLY ONE identifier list: domains, names, crustdata_company_ids, or professional_network_profile_urls. To go the other way — find companies that use a given technology — use crustdata_company_search_by_technology.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"properties": {
"names": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Company names, e.g. ['Stripe']."
},
"compact": {
"type": "boolean",
"default": true,
"description": "Flatten to one readable record per company (name, domain, counts, technologies). Set false for the raw /company/enrich match envelope."
},
"domains": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Company domains, e.g. ['stripe.com']."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"max_technologies": {
"type": "integer",
"default": 100,
"maximum": 500,
"minimum": 1,
"description": "Cap on how many entries of the detailed technologies[] list to return per company (the API caps it at 500, which is a lot of tokens). total_technologies always reports the true count."
},
"crustdata_company_ids": {
"anyOf": [
{
"type": "array",
"items": {
"type": "integer"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Crustdata company IDs."
},
"professional_network_profile_urls": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "LinkedIn company URLs."
}
},
"description": "Input for POST /company/enrich with the technographics field group."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
FIND COMPANIES BY TECHNOLOGY (technographics search, v2025-11-01). THE tool for 'which companies use Snowflake?', 'find companies running dbt AND Airflow', 'companies with a data warehouse', 'accounts on my competitor's stack'. Filters the company dataset on detected tech: `technologies` (names — set match='all' to require every one, default 'any'), `categories` (kebab-case slugs like 'data-warehouse'), and `min_technologies`. Narrow further with `additional_filters` (headcount.total, locations.country, …). Resolve tech names and categories first with crustdata_autocomplete_company_v2 (field='technology' or 'technology_category') — it is FREE and returns the exact stored spellings, and an unrecognised name silently matches nothing. NOTE: search FILTERS on the stack, it does not RETURN it — results are company records. To see what a matched company actually uses, pass it to crustdata_company_technographics.
The description explains the capability, when to use it, and what to expect.
Inputs90/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › technologies
Technology names, e.g. ['Snowflake', 'dbt']. Values must match the catalog exactly — resolve them first with crustdata_autocomplete_company_v2 (field='technology'), which returns the stored spellings.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › match
'any' (default) matches companies using AT LEAST ONE of `technologies`; 'all' matches only companies using EVERY one of them.
Clear enough to supply this argument.
params › categories
Technology category slugs, lowercase kebab-case, e.g. ['data-warehouse', 'frontend-frameworks', 'cloud-platforms-iaas']. Values must match exactly — discover them with crustdata_autocomplete_company_v2 (field='technology_category'); an unknown slug silently matches nothing.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › min_technologies
Only companies with at least this many detected technologies.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › additional_filters
Optional non-technographics filter tree, AND-ed with the technology conditions — same shape as crustdata_company_search_db_v2 ({field, type, value} leaves; {op, conditions} branches). Use it to narrow by firmographics, e.g. headcount.total or locations.country (ISO-3 like 'USA').
Clear enough to supply this argument.
params › sorts
Optional sorts: [{field, order: 'asc'|'desc'}], e.g. field 'technographics.total_technologies' or 'headcount.total'. A 'direction' key is renamed to 'order'.
Clear enough to supply this argument.
params › limit
Results per page (max 100).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › cursor
Opaque next_cursor from the previous page (no numeric offset).
Clear enough to supply this argument.
params › compact
Return trimmed company records. Set false for full nested records.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_company_search_by_technology",
"title": "Find companies by technology",
"description": "FIND COMPANIES BY TECHNOLOGY (technographics search, v2025-11-01). THE tool for 'which companies use Snowflake?', 'find companies running dbt AND Airflow', 'companies with a data warehouse', 'accounts on my competitor's stack'. Filters the company dataset on detected tech: `technologies` (names — set match='all' to require every one, default 'any'), `categories` (kebab-case slugs like 'data-warehouse'), and `min_technologies`. Narrow further with `additional_filters` (headcount.total, locations.country, …). Resolve tech names and categories first with crustdata_autocomplete_company_v2 (field='technology' or 'technology_category') — it is FREE and returns the exact stored spellings, and an unrecognised name silently matches nothing. NOTE: search FILTERS on the stack, it does not RETURN it — results are company records. To see what a matched company actually uses, pass it to crustdata_company_technographics.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"properties": {
"limit": {
"type": "integer",
"default": 25,
"maximum": 100,
"minimum": 1,
"description": "Results per page (max 100)."
},
"match": {
"enum": [
"any",
"all"
],
"type": "string",
"default": "any",
"description": "'any' (default) matches companies using AT LEAST ONE of `technologies`; 'all' matches only companies using EVERY one of them."
},
"sorts": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
{
"type": "null"
}
],
"default": null,
"description": "Optional sorts: [{field, order: 'asc'|'desc'}], e.g. field 'technographics.total_technologies' or 'headcount.total'. A 'direction' key is renamed to 'order'."
},
"cursor": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Opaque next_cursor from the previous page (no numeric offset)."
},
"compact": {
"type": "boolean",
"default": true,
"description": "Return trimmed company records. Set false for full nested records."
},
"categories": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Technology category slugs, lowercase kebab-case, e.g. ['data-warehouse', 'frontend-frameworks', 'cloud-platforms-iaas']. Values must match exactly — discover them with crustdata_autocomplete_company_v2 (field='technology_category'); an unknown slug silently matches nothing."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"technologies": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Technology names, e.g. ['Snowflake', 'dbt']. Values must match the catalog exactly — resolve them first with crustdata_autocomplete_company_v2 (field='technology'), which returns the stored spellings."
},
"min_technologies": {
"anyOf": [
{
"type": "integer",
"minimum": 1
},
{
"type": "null"
}
],
"default": null,
"description": "Only companies with at least this many detected technologies."
},
"additional_filters": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "Optional non-technographics filter tree, AND-ed with the technology conditions — same shape as crustdata_company_search_db_v2 ({field, type, value} leaves; {op, conditions} branches). Use it to narrow by firmographics, e.g. headcount.total or locations.country (ISO-3 like 'USA')."
}
},
"description": "Input for POST /company/search filtered on the technographics namespace."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
Lightweight liveness probe for the Crustdata MCP server itself. Returns {status: 'ok'} when the server is reachable. Does NOT call the Crustdata API or consume credits. Use this when you need to verify the MCP connection is healthy without spending credits.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_healthz",
"title": "Check server health",
"description": "Lightweight liveness probe for the Crustdata MCP server itself. Returns {status: 'ok'} when the server is reachable. Does NOT call the Crustdata API or consume credits. Use this when you need to verify the MCP connection is healthy without spending credits.",
"inputSchema": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Return a markdown table of how many Crustdata credits each MCP tool call costs, broken down by variation (cached vs realtime, reactors/comments, business email, exact keyword match, per-result, etc.). Prices are the published Crustdata API prices. Free — makes no API call and consumes no credits. Answers 'how much does X cost?' and sizes spend before expensive calls. Note: credits are only charged when a call returns results.
The description explains the capability, when to use it, and what to expect.
Inputs100/100
This tool declares no inputs, so argument descriptions are not needed.
No input fields.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_credit_costs",
"title": "Get the credit price list",
"description": "Return a markdown table of how many Crustdata credits each MCP tool call costs, broken down by variation (cached vs realtime, reactors/comments, business email, exact keyword match, per-result, etc.). Prices are the published Crustdata API prices. Free — makes no API call and consumes no credits. Answers 'how much does X cost?' and sizes spend before expensive calls. Note: credits are only charged when a call returns results.",
"inputSchema": {
"type": "object",
"properties": {},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": false,
"destructiveHint": false
}
}
Align the title with the capability actually described by this tool.
Description97/100
LEGACY event watcher (v1 /watcher/watches). Create a watch ONLY for the three subjects the v2 system has no dataset for: LinkedIn POSTS (by keyword, by person, or by company), INDIVIDUAL JOB POSTINGS matched on keyword/location, and PERSON PRESS MENTIONS. For anything else, including profile or attribute changes on known people/companies and discovery of new people/companies matching filters, use crustdata_watch_create instead. Note this tool fires at most once a DAY (frequency is in days); crustdata_watch_create goes hourly, so a need for fresher data is a reason to prefer it, not this. notification_endpoint is REQUIRED and must be an HTTPS URL the user controls. Ask for it rather than guessing, and never point a watch at a Crustdata-owned host. Delivered payloads are also readable in chat via crustdata_watcher_run_summary, so the user does not have to build anything against their endpoint to see results. Creating a watch is FREE; credits are only charged when the watch runs. Event types include 'job-posting-with-keyword-and-location' (new job postings), 'company-watch-linkedin-posts' (company LinkedIn activity), 'linkedin-person-post-updates' (person LinkedIn posts), 'person-discovery-via-filters' (people matching Sales Nav filters), and more. Use crustdata_watcher_simulate to dry-run first, crustdata_watcher_cancel to permanently stop a watch. The response includes an `api_request` field with the exact JSON body posted and a copy-pasteable curl; after creating, surface that curl to the user so they can reproduce or save it. SEE ALSO: crustdata_watch_create — the NEW v2 watch system (entity + discovery watchers on people/companies data) and the DEFAULT choice for creating a watch; this legacy tool is the fallback only for posts, individual job postings, and person press mentions.
The description explains the capability, when to use it, and what to expect.
Inputs90/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › event_type_slug
Type of event to monitor. Pick the right family for the user's intent:
Person tracking (specific LinkedIn profiles — pass LINKEDIN_PROFILE_URL in event_filters):
- 'linkedin-person-profile-updates' — profile/job/title/headline/location CHANGES
- 'linkedin-person-post-updates' — new LinkedIn POSTS from that profile
- 'linkedin-person-press-mentions' — press articles MENTIONING that person
Company tracking (specific LinkedIn companies — pass LINKEDIN_COMPANY_URL in event_filters):
- 'company-watch-linkedin-posts' / 'company-watch-linkedin-job-postings' /
'company-watch-funding-milestones' / 'company-watch-press-mentions' /
'company-watch-headcount-growth'
Discovery — filter-based, find new matches over time. Each has specific filter requirements:
- 'person-discovery-via-filters' — people matching Sales Nav filters; put filters in event_filters (KEYWORD, CURRENT_TITLE, REGION, SENIORITY_LEVEL, INDUSTRY, COMPANY_HEADCOUNT, RECENTLY_CHANGED_JOBS, etc.)
- 'linkedin-post-with-keyword' — REQUIRES event_filters=[{filter_type:KEYWORD,...}] AND either account_filters or lead_filters (Sales Nav filters about author/company)
- 'new-funding-announcements' — REQUIRES account_filters (INDUSTRY, COMPANY_HQ_COUNTRY, COMPANY_HEADCOUNT, LAST_FUNDING_ROUND_TYPE). event_filters can be empty or contain optional FUNDING_ROUND_TYPE. No need to identify specific companies first — just pass the firmographic account_filters.
- 'job-posting-with-keyword-and-location' / 'job-posting-with-location' — REQUIRES event_filters with TITLE+REGION (or DESCRIPTION+REGION) and account_filters with COMPANY_HEADCOUNT / COMPANY_HQ_COUNTRY etc.
- 'person-starting-new-position'
- 'company-headcount-growth' / 'company-headcount-growth-over-baseline' /
'company-department-headcount' / 'first-person-hired-in-company-department' /
'first-person-hired-internationally' / 'company-employee-job-location-in-two-countries'
HEURISTICS:
- 'profile change' / 'job change' for a specific person URL → 'linkedin-person-profile-updates' (NOT post-updates).
- 'when companies in X raise funding' / 'funding alerts for industry Y' → go straight to 'new-funding-announcements' with account_filters — resolving specific companies first is unnecessary here.
- 'monitor company X's posts' → 'company-watch-linkedin-posts' with LINKEDIN_COMPANY_URL.
- 'people leaving company X' / 'who recently left X' → 'person-discovery-via-filters' with event_filters LAST_COMPANY (company LinkedIn URL or domain, e.g. 'https://www.linkedin.com/company/openai/' or 'openai.com'; max 10 values) AND RECENTLY_CHANGED_JOBS. LAST_COMPANY is our post-search filter that matches the person's MOST RECENTLY ENDED job — i.e. the company they actually just left. PAST_COMPANY alone expresses a different intent: it matches anyone who EVER worked there, including 10 years ago, so combined with RECENTLY_CHANGED_JOBS it returns people who ever-touched-X-and-recently-left-anywhere. 'person-starting-new-position' is also a different thing — it watches LinkedIn POSTS whose text says 'Starting a new position', not actual employer-change events.
Clear enough to supply this argument.
params › event_filters
Event-specific filters. Example: [{"filter_type": "REGION", "type": "in", "value": "San Francisco"}].
TITLE MATCHING GUIDANCE (person-discovery-via-filters):
Sales Nav has two title-matching mechanisms with different semantics — pick the right one:
- CURRENT_TITLE (default): tokenized substring match across the current_title field. Good for generic titles where you want variants — e.g. "Director" matches "Sr. Director", "Senior Director, Engineering", etc. Ignores quote marks; cannot enforce literal phrase matching.
- KEYWORD: full-text search across title + headline + summary that DOES respect quoted phrases. Only one KEYWORD value allowed per watcher — combine multiple phrases with Sales Nav boolean OR, e.g. `"AI Founder" OR "Founder AI" OR "AI CEO"`.
Use KEYWORD with quoted phrases (instead of CURRENT_TITLE) when ANY of:
- The title contains a short 2-3 letter acronym (AI, ML, BI, HR, IT, RH, AD, etc.). Without quotes Sales Nav strips dots and collides with abbreviations like "a.i." (Dutch *ad interim*), "A.D." (German), etc.
- The user used quotes around the title, or said "exactly", "literally", "the title is".
- The REGION is non-English (NL/DE/FR/IT/ES/PT/etc.) where abbreviated job titles are common in business culture.
Note: KEYWORD doesn't count toward the 10k pre-flight cap, so a KEYWORD-narrowed search often needs SENIORITY_LEVEL + INDUSTRY + COMPANY_HEADCOUNT to bring the candidate pool under 10k before creation.
Clear enough to supply this argument.
params › notification_endpoint
HTTPS URL that receives the webhook POST when events fire. REQUIRED. There is no Crustdata-hosted default. Watcher payloads carry data about named third parties, so they are only delivered to an endpoint the account owner controls. Ask the user for their URL; never invent one and never reuse a Crustdata-owned host. If the user has nowhere to host a receiver, they still get every payload in chat via crustdata_watcher_run_summary (which reads the delivered payloads back from the API, scoped to the caller's own account). A URL is still required at create time, so ask for one.
Clear enough to supply this argument.
params › frequency
Notification frequency in days (minimum 1 day). Default: 1
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › account_filters
Company filters. Filter types: INDUSTRY, COMPANY_HEADCOUNT, COMPANY_HQ_COUNTRY, LAST_FUNDING_ROUND_TYPE
Clear enough to supply this argument.
params › lead_filters
Person filters. Filter types: CURRENT_TITLE, PAST_TITLE, CURRENT_COMPANY, PAST_COMPANY, REGION, etc.
Clear enough to supply this argument.
params › expiration_date
Subscription expiration date in YYYY-MM-DD format. Must be a future date.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › approximate_notification_time
Hour of day (0-23, UTC) to send notifications.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › max_notifications_per_execution
Optional cap on notifications sent per watch execution. Must be a positive multiple of 50. If omitted, all matching events are sent.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watcher_create",
"title": "Create an event watcher",
"description": "LEGACY event watcher (v1 /watcher/watches). Create a watch ONLY for the three subjects the v2 system has no dataset for: LinkedIn POSTS (by keyword, by person, or by company), INDIVIDUAL JOB POSTINGS matched on keyword/location, and PERSON PRESS MENTIONS. For anything else, including profile or attribute changes on known people/companies and discovery of new people/companies matching filters, use crustdata_watch_create instead. Note this tool fires at most once a DAY (frequency is in days); crustdata_watch_create goes hourly, so a need for fresher data is a reason to prefer it, not this. notification_endpoint is REQUIRED and must be an HTTPS URL the user controls. Ask for it rather than guessing, and never point a watch at a Crustdata-owned host. Delivered payloads are also readable in chat via crustdata_watcher_run_summary, so the user does not have to build anything against their endpoint to see results. Creating a watch is FREE; credits are only charged when the watch runs. Event types include 'job-posting-with-keyword-and-location' (new job postings), 'company-watch-linkedin-posts' (company LinkedIn activity), 'linkedin-person-post-updates' (person LinkedIn posts), 'person-discovery-via-filters' (people matching Sales Nav filters), and more. Use crustdata_watcher_simulate to dry-run first, crustdata_watcher_cancel to permanently stop a watch. The response includes an `api_request` field with the exact JSON body posted and a copy-pasteable curl; after creating, surface that curl to the user so they can reproduce or save it. SEE ALSO: crustdata_watch_create — the NEW v2 watch system (entity + discovery watchers on people/companies data) and the DEFAULT choice for creating a watch; this legacy tool is the fallback only for posts, individual job postings, and person press mentions.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"event_type_slug",
"event_filters",
"notification_endpoint"
],
"properties": {
"frequency": {
"type": "integer",
"default": 1,
"minimum": 1,
"description": "Notification frequency in days (minimum 1 day). Default: 1"
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"lead_filters": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
{
"type": "null"
}
],
"default": null,
"description": "Person filters. Filter types: CURRENT_TITLE, PAST_TITLE, CURRENT_COMPANY, PAST_COMPANY, REGION, etc."
},
"event_filters": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
},
"description": "Event-specific filters. Example: [{\"filter_type\": \"REGION\", \"type\": \"in\", \"value\": \"San Francisco\"}]. \n\nTITLE MATCHING GUIDANCE (person-discovery-via-filters):\nSales Nav has two title-matching mechanisms with different semantics — pick the right one:\n- CURRENT_TITLE (default): tokenized substring match across the current_title field. Good for generic titles where you want variants — e.g. \"Director\" matches \"Sr. Director\", \"Senior Director, Engineering\", etc. Ignores quote marks; cannot enforce literal phrase matching.\n- KEYWORD: full-text search across title + headline + summary that DOES respect quoted phrases. Only one KEYWORD value allowed per watcher — combine multiple phrases with Sales Nav boolean OR, e.g. `\"AI Founder\" OR \"Founder AI\" OR \"AI CEO\"`.\n\nUse KEYWORD with quoted phrases (instead of CURRENT_TITLE) when ANY of:\n- The title contains a short 2-3 letter acronym (AI, ML, BI, HR, IT, RH, AD, etc.). Without quotes Sales Nav strips dots and collides with abbreviations like \"a.i.\" (Dutch *ad interim*), \"A.D.\" (German), etc.\n- The user used quotes around the title, or said \"exactly\", \"literally\", \"the title is\".\n- The REGION is non-English (NL/DE/FR/IT/ES/PT/etc.) where abbreviated job titles are common in business culture.\n\nNote: KEYWORD doesn't count toward the 10k pre-flight cap, so a KEYWORD-narrowed search often needs SENIORITY_LEVEL + INDUSTRY + COMPANY_HEADCOUNT to bring the candidate pool under 10k before creation."
},
"account_filters": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
{
"type": "null"
}
],
"default": null,
"description": "Company filters. Filter types: INDUSTRY, COMPANY_HEADCOUNT, COMPANY_HQ_COUNTRY, LAST_FUNDING_ROUND_TYPE"
},
"event_type_slug": {
"type": "string",
"description": "Type of event to monitor. Pick the right family for the user's intent:\n\nPerson tracking (specific LinkedIn profiles — pass LINKEDIN_PROFILE_URL in event_filters):\n - 'linkedin-person-profile-updates' — profile/job/title/headline/location CHANGES\n - 'linkedin-person-post-updates' — new LinkedIn POSTS from that profile\n - 'linkedin-person-press-mentions' — press articles MENTIONING that person\n\nCompany tracking (specific LinkedIn companies — pass LINKEDIN_COMPANY_URL in event_filters):\n - 'company-watch-linkedin-posts' / 'company-watch-linkedin-job-postings' /\n 'company-watch-funding-milestones' / 'company-watch-press-mentions' /\n 'company-watch-headcount-growth'\n\nDiscovery — filter-based, find new matches over time. Each has specific filter requirements:\n - 'person-discovery-via-filters' — people matching Sales Nav filters; put filters in event_filters (KEYWORD, CURRENT_TITLE, REGION, SENIORITY_LEVEL, INDUSTRY, COMPANY_HEADCOUNT, RECENTLY_CHANGED_JOBS, etc.)\n - 'linkedin-post-with-keyword' — REQUIRES event_filters=[{filter_type:KEYWORD,...}] AND either account_filters or lead_filters (Sales Nav filters about author/company)\n - 'new-funding-announcements' — REQUIRES account_filters (INDUSTRY, COMPANY_HQ_COUNTRY, COMPANY_HEADCOUNT, LAST_FUNDING_ROUND_TYPE). event_filters can be empty or contain optional FUNDING_ROUND_TYPE. No need to identify specific companies first — just pass the firmographic account_filters.\n - 'job-posting-with-keyword-and-location' / 'job-posting-with-location' — REQUIRES event_filters with TITLE+REGION (or DESCRIPTION+REGION) and account_filters with COMPANY_HEADCOUNT / COMPANY_HQ_COUNTRY etc.\n - 'person-starting-new-position'\n - 'company-headcount-growth' / 'company-headcount-growth-over-baseline' /\n 'company-department-headcount' / 'first-person-hired-in-company-department' /\n 'first-person-hired-internationally' / 'company-employee-job-location-in-two-countries'\n\nHEURISTICS:\n- 'profile change' / 'job change' for a specific person URL → 'linkedin-person-profile-updates' (NOT post-updates).\n- 'when companies in X raise funding' / 'funding alerts for industry Y' → go straight to 'new-funding-announcements' with account_filters — resolving specific companies first is unnecessary here.\n- 'monitor company X's posts' → 'company-watch-linkedin-posts' with LINKEDIN_COMPANY_URL.\n- 'people leaving company X' / 'who recently left X' → 'person-discovery-via-filters' with event_filters LAST_COMPANY (company LinkedIn URL or domain, e.g. 'https://www.linkedin.com/company/openai/' or 'openai.com'; max 10 values) AND RECENTLY_CHANGED_JOBS. LAST_COMPANY is our post-search filter that matches the person's MOST RECENTLY ENDED job — i.e. the company they actually just left. PAST_COMPANY alone expresses a different intent: it matches anyone who EVER worked there, including 10 years ago, so combined with RECENTLY_CHANGED_JOBS it returns people who ever-touched-X-and-recently-left-anywhere. 'person-starting-new-position' is also a different thing — it watches LinkedIn POSTS whose text says 'Starting a new position', not actual employer-change events."
},
"expiration_date": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Subscription expiration date in YYYY-MM-DD format. Must be a future date."
},
"notification_endpoint": {
"type": "string",
"description": "HTTPS URL that receives the webhook POST when events fire. REQUIRED. There is no Crustdata-hosted default. Watcher payloads carry data about named third parties, so they are only delivered to an endpoint the account owner controls. Ask the user for their URL; never invent one and never reuse a Crustdata-owned host. If the user has nowhere to host a receiver, they still get every payload in chat via crustdata_watcher_run_summary (which reads the delivered payloads back from the API, scoped to the caller's own account). A URL is still required at create time, so ask for one."
},
"approximate_notification_time": {
"anyOf": [
{
"type": "integer",
"maximum": 23,
"minimum": 0
},
{
"type": "null"
}
],
"default": null,
"description": "Hour of day (0-23, UTC) to send notifications."
},
"max_notifications_per_execution": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional cap on notifications sent per watch execution. Must be a positive multiple of 50. If omitted, all matching events are sent."
}
},
"description": "Watcher creation parameters."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description88/100
Update an existing watcher subscription. Can change status (pause/resume), update webhook endpoint, or modify filters for certain subscription types. SEE ALSO: crustdata_watch_update — the NEW v2 watch system (entity + discovery watchers on people/companies data); prefer it for tracking profile-data changes. This legacy tool remains for event-webhook subscriptions.
The description explains the capability, when to use it, and what to expect.
Inputs83/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › subscription_id
ID of the subscription to update. Must be positive.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › status
New status: 'active' (resume) or 'paused'. To permanently cancel a watch, use crustdata_watcher_cancel instead — the update endpoint cannot cancel.
Clear enough to supply this argument.
params › notification_endpoint
New HTTPS webhook endpoint URL.
Clear enough to supply this argument.
params › event_filters
Updated event filters (only for certain subscription types).
Explain the meaning of this value, not just its name.
params › max_notifications_per_execution
Optional cap on notifications sent per watch execution. Must be a positive multiple of 50. If omitted, all matching events are sent. Applied from the next watch execution onward.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watcher_update",
"title": "Update an event watcher",
"description": "Update an existing watcher subscription. Can change status (pause/resume), update webhook endpoint, or modify filters for certain subscription types. SEE ALSO: crustdata_watch_update — the NEW v2 watch system (entity + discovery watchers on people/companies data); prefer it for tracking profile-data changes. This legacy tool remains for event-webhook subscriptions.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"subscription_id"
],
"properties": {
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "New status: 'active' (resume) or 'paused'. To permanently cancel a watch, use crustdata_watcher_cancel instead — the update endpoint cannot cancel."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"event_filters": {
"anyOf": [
{
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
}
},
{
"type": "null"
}
],
"default": null,
"description": "Updated event filters (only for certain subscription types)."
},
"subscription_id": {
"type": "integer",
"description": "ID of the subscription to update. Must be positive.",
"exclusiveMinimum": 0
},
"notification_endpoint": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "New HTTPS webhook endpoint URL."
},
"max_notifications_per_execution": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional cap on notifications sent per watch execution. Must be a positive multiple of 50. If omitted, all matching events are sent. Applied from the next watch execution onward."
}
},
"description": "Watcher update parameters."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description91/100
Simulate a watcher subscription to test your webhook endpoint. Sends a test notification without creating a persistent subscription.
The description explains the capability, when to use it, and what to expect.
Inputs72/100
Explain the meaning of this value, not just its name.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › event_type_slug
Type of event to simulate monitoring.
Explain the meaning of this value, not just its name.
params › event_filters
Event-specific filters for the simulation.
Explain the meaning of this value, not just its name.
params › notification_endpoint
HTTPS URL to receive test webhook notification. Must use HTTPS protocol.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › frequency
Simulated notification frequency in days (minimum 1 day).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › account_filters
Company filters to simulate (same shape as crustdata_watcher_create). Filter types: INDUSTRY, COMPANY_HEADCOUNT, COMPANY_HQ_COUNTRY, LAST_FUNDING_ROUND_TYPE.
Clear enough to supply this argument.
params › lead_filters
Person filters to simulate (same shape as crustdata_watcher_create). Filter types: CURRENT_TITLE, PAST_TITLE, CURRENT_COMPANY, PAST_COMPANY, REGION, etc.
Explain the meaning of this value, not just its name.
params › expiration_date
Optional expiration date (YYYY-MM-DD, future) for the simulated watch.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › max_notifications_per_execution
Optional cap on notifications sent per watch execution. Must be a positive multiple of 50. If omitted, all matching events are sent.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description100/100
List the caller's watcher subscriptions, most recent first. Returns id, event_type_slug, status, frequency, created_at, last_run_id, notification_endpoint, and max_notifications_per_execution. An account with no watchers returns an empty list, which is a normal result rather than an error. By default returns the 50 most recent watchers in compact form (bulky filter payloads stripped to avoid context overflow). Use this at the start of any session that references a previously-created watch — users often forget the subscription_id, so match by event_type_slug + created_at to recover it. Pass compact=false only when the user explicitly asks to see filter details, and consider pairing with limit=10 for very active accounts. SEE ALSO: crustdata_watch_list — the NEW v2 watch system (entity + discovery watchers on people/companies data); prefer it for tracking profile-data changes. This legacy tool remains for event-webhook subscriptions.
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › include_cancelled
When true, cancelled watches are returned alongside active/paused ones. Default false (cancelled watches are hidden).
Clear enough to supply this argument.
params › compact
When true (default), return only the headline fields per watcher (id, event_type_slug, status, frequency, created_at, last_run_id, notification_endpoint, max_notifications_per_execution) and drop the bulky event_filters / account_filters / lead_filters payloads. Set to false when the user explicitly asks to inspect filter configuration.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › limit
Maximum number of watchers to return (most recent first). Default 50. Use a smaller limit (e.g. 10) if you only need the latest few.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watcher_list",
"title": "List event watchers",
"description": "List the caller's watcher subscriptions, most recent first. Returns id, event_type_slug, status, frequency, created_at, last_run_id, notification_endpoint, and max_notifications_per_execution. An account with no watchers returns an empty list, which is a normal result rather than an error. By default returns the 50 most recent watchers in compact form (bulky filter payloads stripped to avoid context overflow). Use this at the start of any session that references a previously-created watch — users often forget the subscription_id, so match by event_type_slug + created_at to recover it. Pass compact=false only when the user explicitly asks to see filter details, and consider pairing with limit=10 for very active accounts. SEE ALSO: crustdata_watch_list — the NEW v2 watch system (entity + discovery watchers on people/companies data); prefer it for tracking profile-data changes. This legacy tool remains for event-webhook subscriptions.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"properties": {
"limit": {
"anyOf": [
{
"type": "integer",
"maximum": 500,
"minimum": 1
},
{
"type": "null"
}
],
"default": 50,
"description": "Maximum number of watchers to return (most recent first). Default 50. Use a smaller limit (e.g. 10) if you only need the latest few."
},
"compact": {
"type": "boolean",
"default": true,
"description": "When true (default), return only the headline fields per watcher (id, event_type_slug, status, frequency, created_at, last_run_id, notification_endpoint, max_notifications_per_execution) and drop the bulky event_filters / account_filters / lead_filters payloads. Set to false when the user explicitly asks to inspect filter configuration."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"include_cancelled": {
"type": "boolean",
"default": false,
"description": "When true, cancelled watches are returned alongside active/paused ones. Default false (cancelled watches are hidden)."
}
},
"description": "List options (include_cancelled, compact, limit)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description92/100
Get the full details of a single watcher subscription by ID (status, filters, endpoint, frequency, etc.). SEE ALSO: crustdata_watch_get — the NEW v2 watch system (entity + discovery watchers on people/companies data); prefer it for tracking profile-data changes. This legacy tool remains for event-webhook subscriptions.
The description explains the capability, when to use it, and what to expect.
Inputs87/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › subscription_id
ID of the watch. Must be positive.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watcher_get",
"title": "Get an event watcher",
"description": "Get the full details of a single watcher subscription by ID (status, filters, endpoint, frequency, etc.). SEE ALSO: crustdata_watch_get — the NEW v2 watch system (entity + discovery watchers on people/companies data); prefer it for tracking profile-data changes. This legacy tool remains for event-webhook subscriptions.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"subscription_id"
],
"properties": {
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"subscription_id": {
"type": "integer",
"description": "ID of the watch. Must be positive.",
"exclusiveMinimum": 0
}
},
"description": "The watch ID to fetch."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
List recent runs of a watcher. Each entry includes the run id, status (RUNNING/SUCCESS/FAILED/SKIPPED), started_at, completed_at, new_records_count, credits_deducted, and notification_http_status. Cursor-paginated, most recent first. Use this to find out which runs have results worth inspecting (use crustdata_watcher_run_summary to fetch the actual delivered records for any run).
The description explains the capability, when to use it, and what to expect.
Inputs88/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › subscription_id
ID of the watch whose run history you want.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › limit
Maximum number of runs to return (most recent first). Default 20, max 100.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › cursor
Pagination cursor — pass the next_cursor returned by the previous call to fetch the next page. Omit for the first page.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watcher_runs",
"title": "List watch runs",
"description": "List recent runs of a watcher. Each entry includes the run id, status (RUNNING/SUCCESS/FAILED/SKIPPED), started_at, completed_at, new_records_count, credits_deducted, and notification_http_status. Cursor-paginated, most recent first. Use this to find out which runs have results worth inspecting (use crustdata_watcher_run_summary to fetch the actual delivered records for any run).",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"subscription_id"
],
"properties": {
"limit": {
"type": "integer",
"default": 20,
"maximum": 100,
"minimum": 1,
"description": "Maximum number of runs to return (most recent first). Default 20, max 100."
},
"cursor": {
"anyOf": [
{
"type": "integer"
},
{
"type": "null"
}
],
"default": null,
"description": "Pagination cursor — pass the next_cursor returned by the previous call to fetch the next page. Omit for the first page."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"subscription_id": {
"type": "integer",
"description": "ID of the watch whose run history you want.",
"exclusiveMinimum": 0
}
},
"description": "Subscription id, pagination cursor, and limit."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
Fetch the detailed summary of a single watcher run: per-stage pipeline logs with timestamps AND the actual webhook payload(s) we delivered for that run. Each entry in `notifications` has sent_at, http_status, and the full `payload` we POSTed (subscription_id, event_type, timestamp, and the matching records). Use this to show the user the actual matches their watcher produced. The payloads are read back from the API and scoped to the caller's own account, so the user does not have to build a listener against their notification_endpoint to see results. If the run is still in progress, logs and notifications may be empty arrays.
The description explains the capability, when to use it, and what to expect.
Inputs87/100
Explain what happens when this optional value is omitted.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Explain what happens when this optional value is omitted.
params › subscription_id
ID of the watch the run belongs to.
Clear enough to supply this argument.
params › run_id
ID of the specific run (from crustdata_watcher_runs).
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watcher_run_summary",
"title": "Get a watch run summary",
"description": "Fetch the detailed summary of a single watcher run: per-stage pipeline logs with timestamps AND the actual webhook payload(s) we delivered for that run. Each entry in `notifications` has sent_at, http_status, and the full `payload` we POSTed (subscription_id, event_type, timestamp, and the matching records). Use this to show the user the actual matches their watcher produced. The payloads are read back from the API and scoped to the caller's own account, so the user does not have to build a listener against their notification_endpoint to see results. If the run is still in progress, logs and notifications may be empty arrays.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"subscription_id",
"run_id"
],
"properties": {
"run_id": {
"type": "integer",
"description": "ID of the specific run (from crustdata_watcher_runs).",
"exclusiveMinimum": 0
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"subscription_id": {
"type": "integer",
"description": "ID of the watch the run belongs to.",
"exclusiveMinimum": 0
}
},
"description": "Subscription id and run id."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
Permanently cancel a watcher subscription by ID. Cancellation is irreversible — the watch stops running and cannot be reactivated (use crustdata_watcher_update with status='paused' if you only want to pause it). Notification history and run records are preserved. The cancelled watch is hidden from crustdata_watcher_list unless include_cancelled=true. SEE ALSO: crustdata_watch_cancel — the NEW v2 watch system (entity + discovery watchers on people/companies data); prefer it for tracking profile-data changes. This legacy tool remains for event-webhook subscriptions.
The description explains the capability, when to use it, and what to expect.
Inputs85/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › subscription_id
ID of the watch. Must be positive.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watcher_cancel",
"title": "Cancel an event watcher",
"description": "Permanently cancel a watcher subscription by ID. Cancellation is irreversible — the watch stops running and cannot be reactivated (use crustdata_watcher_update with status='paused' if you only want to pause it). Notification history and run records are preserved. The cancelled watch is hidden from crustdata_watcher_list unless include_cancelled=true. SEE ALSO: crustdata_watch_cancel — the NEW v2 watch system (entity + discovery watchers on people/companies data); prefer it for tracking profile-data changes. This legacy tool remains for event-webhook subscriptions.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"subscription_id"
],
"properties": {
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"subscription_id": {
"type": "integer",
"description": "ID of the watch. Must be positive.",
"exclusiveMinimum": 0
}
},
"description": "The watch ID to cancel."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": true,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
WATCH CREATE — NEW watcher system (v2025-11-01 API). Create an entity or discovery watch on people or companies. This is the DEFAULT tool for creating any watch: use it unless the subject is one v2 has no dataset for. The legacy crustdata_watcher_* tools cover exactly three such subjects: LinkedIn POSTS (by keyword, by person, or by company), INDIVIDUAL JOB POSTINGS matched on keyword/location (v2 carries only an aggregate hiring.open_jobs_timeseries count, not the postings), and PERSON PRESS MENTIONS (v2 has news on company only). Everything else belongs here: profile and attribute changes on known people or companies, and discovery of new people or companies matching filters. Cadence is not a reason to choose v1: v1 fires at most once a DAY, this tool fires as often as hourly. mode='entity' tracks known people/companies you list for profile changes; mode='discovery' alerts on NEW people/companies matching a saved filter. Entity mode: POST /watch/{entity_type} with entities + track (+ optional fields); billed per change notification (check crustdata_credit_costs) — person watches tier by config.refresh_frequency_days (fresher data costs more), first run is a free baseline and no-change runs are free. Discovery mode: POST /watch/{entity_type}/search with filters; billed per new match delivered, first run is a free baseline of up to 5 matches. Both modes need config.trigger ({type: 'interval', every_hours: N}) and at least one notifications channel. RESPONSE: {api_request, response} — api_request echoes the exact API call (with a copy-pasteable curl) and response is the created watch.
The description explains the capability, when to use it, and what to expect.
Inputs83/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › entity_type
Which dataset to watch: 'person' or 'company'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › mode
'entity' = watch a known list you supply (entities + track); 'discovery' = alert on NEW matches of a filter (filters).
Clear enough to supply this argument.
params › entities
Entity mode only. Map of identifier type -> list of values. person accepts only 'professional_network_profile_urls'; company accepts 'domains', 'names', 'professional_network_profile_urls', and 'crustdata_company_ids' (mixable). Up to 10,000 entities per watch.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › track
Entity mode only. Condition tree for when to fire. Leaves: {field, type, value?} where type is 'changed' (scalar), 'added' (array), or a comparison '>', '<', '=', '!=', '=>' (>=), '=<' (<=) with value required; branches: {op: 'and'|'or', conditions: [...]}. Field paths match the v2 Enrich response, e.g. person basic_profile.current_title / experience.employment_details.current (added), company headcount.total (changed) / news (added). Fixed at create time.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › fields
Entity mode only. Field groups delivered in each notification's record (payload projection — does not affect when the watch fires or pricing). Defaults minimal: person basic_profile + social_handles, company basic_info. No wildcard; fixed at create time.
Clear enough to supply this argument.
params › filters
Discovery mode only. Filter tree identical to the v2 person/company search: leaves {field, type, value}, branches {op: 'and'|'or', conditions: [...]}.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › config
Schedule + caps. 'trigger' is REQUIRED: {'type': 'interval', 'every_hours': N} (integer >= 1). Optional: 'max_results_per_run' (1-1000, default 25; discovery baseline is always capped at 5), 'preferred_hour' (0-23), 'expires_at' ('YYYY-MM-DD').
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › notifications
One or more delivery channels (at least one required). Webhook: {type: 'webhook', url, headers?}; Slack: {type: 'slack', webhook_url} (must be a hooks.slack.com incoming webhook); Google Chat: {type: 'google_chat', url}.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watch_create",
"title": "Create a watch",
"description": "WATCH CREATE — NEW watcher system (v2025-11-01 API). Create an entity or discovery watch on people or companies. This is the DEFAULT tool for creating any watch: use it unless the subject is one v2 has no dataset for. The legacy crustdata_watcher_* tools cover exactly three such subjects: LinkedIn POSTS (by keyword, by person, or by company), INDIVIDUAL JOB POSTINGS matched on keyword/location (v2 carries only an aggregate hiring.open_jobs_timeseries count, not the postings), and PERSON PRESS MENTIONS (v2 has news on company only). Everything else belongs here: profile and attribute changes on known people or companies, and discovery of new people or companies matching filters. Cadence is not a reason to choose v1: v1 fires at most once a DAY, this tool fires as often as hourly. mode='entity' tracks known people/companies you list for profile changes; mode='discovery' alerts on NEW people/companies matching a saved filter. Entity mode: POST /watch/{entity_type} with entities + track (+ optional fields); billed per change notification (check crustdata_credit_costs) — person watches tier by config.refresh_frequency_days (fresher data costs more), first run is a free baseline and no-change runs are free. Discovery mode: POST /watch/{entity_type}/search with filters; billed per new match delivered, first run is a free baseline of up to 5 matches. Both modes need config.trigger ({type: 'interval', every_hours: N}) and at least one notifications channel. RESPONSE: {api_request, response} — api_request echoes the exact API call (with a copy-pasteable curl) and response is the created watch.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"entity_type",
"mode",
"config",
"notifications"
],
"properties": {
"mode": {
"enum": [
"entity",
"discovery"
],
"type": "string",
"description": "'entity' = watch a known list you supply (entities + track); 'discovery' = alert on NEW matches of a filter (filters)."
},
"track": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "Entity mode only. Condition tree for when to fire. Leaves: {field, type, value?} where type is 'changed' (scalar), 'added' (array), or a comparison '>', '<', '=', '!=', '=>' (>=), '=<' (<=) with value required; branches: {op: 'and'|'or', conditions: [...]}. Field paths match the v2 Enrich response, e.g. person basic_profile.current_title / experience.employment_details.current (added), company headcount.total (changed) / news (added). Fixed at create time."
},
"config": {
"type": "object",
"description": "Schedule + caps. 'trigger' is REQUIRED: {'type': 'interval', 'every_hours': N} (integer >= 1). Optional: 'max_results_per_run' (1-1000, default 25; discovery baseline is always capped at 5), 'preferred_hour' (0-23), 'expires_at' ('YYYY-MM-DD').",
"additionalProperties": true
},
"fields": {
"anyOf": [
{
"type": "array",
"items": {
"type": "string"
}
},
{
"type": "null"
}
],
"default": null,
"description": "Entity mode only. Field groups delivered in each notification's record (payload projection — does not affect when the watch fires or pricing). Defaults minimal: person basic_profile + social_handles, company basic_info. No wildcard; fixed at create time."
},
"filters": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "Discovery mode only. Filter tree identical to the v2 person/company search: leaves {field, type, value}, branches {op: 'and'|'or', conditions: [...]}."
},
"entities": {
"anyOf": [
{
"type": "object",
"additionalProperties": true
},
{
"type": "null"
}
],
"default": null,
"description": "Entity mode only. Map of identifier type -> list of values. person accepts only 'professional_network_profile_urls'; company accepts 'domains', 'names', 'professional_network_profile_urls', and 'crustdata_company_ids' (mixable). Up to 10,000 entities per watch."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"entity_type": {
"enum": [
"person",
"company"
],
"type": "string",
"description": "Which dataset to watch: 'person' or 'company'."
},
"notifications": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": true
},
"description": "One or more delivery channels (at least one required). Webhook: {type: 'webhook', url, headers?}; Slack: {type: 'slack', webhook_url} (must be a hooks.slack.com incoming webhook); Google Chat: {type: 'google_chat', url}."
}
},
"description": "Input for POST /watch/{entity_type} (entity) or /watch/{entity_type}/search (discovery)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": true,
"destructiveHint": false
}
}
Shorten the title to an action and subject; move usage details into the description.
Description98/100
WATCH LIST — NEW watcher system (v2025-11-01 API). Manages watches created by crustdata_watch_create (NOT the legacy crustdata_watcher_* watches). FREE. Lists the caller's v2 watches for one dataset as an array of watch objects (id, kind: 'entity'|'discovery', dataset, status, config, notifications, created_at, last_run_at). Returns the first 50 by default with each watch's identifier lists collapsed to entity_count; filter with status, page with limit/offset, and use crustdata_watch_get for one watch's full payload. Never lists everything at once: an active account's full list does not fit in context.
The description explains the capability, when to use it, and what to expect.
Inputs83/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › entity_type
Which dataset to watch: 'person' or 'company'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › status
Optional status filter, e.g. 'active' or 'paused'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › limit
Page size (default 50, max 200). Page through larger accounts with offset instead of raising this.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › offset
Optional pagination offset.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › compact
Default True: replace each watch's 'entities' block (up to 10,000 identifiers) with 'entity_count' so a long list fits in context. Pass False only when the user asks to see the tracked identifiers; prefer crustdata_watch_get for a single watch's full payload.
Clear enough to supply this argument.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watch_list",
"title": "List watches",
"description": "WATCH LIST — NEW watcher system (v2025-11-01 API). Manages watches created by crustdata_watch_create (NOT the legacy crustdata_watcher_* watches). FREE. Lists the caller's v2 watches for one dataset as an array of watch objects (id, kind: 'entity'|'discovery', dataset, status, config, notifications, created_at, last_run_at). Returns the first 50 by default with each watch's identifier lists collapsed to entity_count; filter with status, page with limit/offset, and use crustdata_watch_get for one watch's full payload. Never lists everything at once: an active account's full list does not fit in context.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"entity_type"
],
"properties": {
"limit": {
"type": "integer",
"default": 50,
"maximum": 200,
"minimum": 1,
"description": "Page size (default 50, max 200). Page through larger accounts with offset instead of raising this."
},
"offset": {
"anyOf": [
{
"type": "integer",
"minimum": 0
},
{
"type": "null"
}
],
"default": null,
"description": "Optional pagination offset."
},
"status": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "Optional status filter, e.g. 'active' or 'paused'."
},
"compact": {
"type": "boolean",
"default": true,
"description": "Default True: replace each watch's 'entities' block (up to 10,000 identifiers) with 'entity_count' so a long list fits in context. Pass False only when the user asks to see the tracked identifiers; prefer crustdata_watch_get for a single watch's full payload."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"entity_type": {
"enum": [
"person",
"company"
],
"type": "string",
"description": "Which dataset to watch: 'person' or 'company'."
}
},
"description": "Input for GET /watch/{entity_type} (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
WATCH GET — NEW watcher system (v2025-11-01 API). Manages watches created by crustdata_watch_create (NOT the legacy crustdata_watcher_* watches). FREE. Returns the full watch object (kind, dataset, status, entities/track or filters, fields, config, notifications, created_at, last_run_at). last_run_at is null until the baseline run completes.
The description explains the capability, when to use it, and what to expect.
Inputs83/100
Explain what happens when this optional value is omitted.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Explain what happens when this optional value is omitted.
params › entity_type
Which dataset to watch: 'person' or 'company'.
Clear enough to supply this argument.
params › watch_id
ID of the watch. Must be positive.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watch_get",
"title": "Get a watch",
"description": "WATCH GET — NEW watcher system (v2025-11-01 API). Manages watches created by crustdata_watch_create (NOT the legacy crustdata_watcher_* watches). FREE. Returns the full watch object (kind, dataset, status, entities/track or filters, fields, config, notifications, created_at, last_run_at). last_run_at is null until the baseline run completes.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"entity_type",
"watch_id"
],
"properties": {
"watch_id": {
"type": "integer",
"description": "ID of the watch. Must be positive.",
"exclusiveMinimum": 0
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"entity_type": {
"enum": [
"person",
"company"
],
"type": "string",
"description": "Which dataset to watch: 'person' or 'company'."
}
},
"description": "Input for GET /watch/{entity_type}/{watch_id} (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description98/100
WATCH UPDATE — NEW watcher system (v2025-11-01 API). Manages watches created by crustdata_watch_create (NOT the legacy crustdata_watcher_* watches). FREE. PATCH to pause/resume (status 'paused'/'active') and/or replace the watched entities list, config, or notifications. A watch's track and fields are fixed at create time — create a new watch to change what you watch for. To delete permanently, use crustdata_watch_cancel. RESPONSE: {api_request, response} — api_request echoes the exact API call (with a copy-pasteable curl) and response is the updated watch.
The description explains the capability, when to use it, and what to expect.
Inputs79/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › entity_type
Which dataset to watch: 'person' or 'company'.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › watch_id
ID of the watch. Must be positive.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › status
Pause with 'paused'; resume with 'active'.
Explain what happens when this optional value is omitted.
params › entities
Entity watches only. REPLACEMENT identifier map (same shape as create) — add or remove watched people/companies. Newly added entities are baselined silently on the next run, so adding never fires a spurious notification.
Clear enough to supply this argument.
params › config
Updated schedule/caps block (same shape as create).
Explain the meaning of this value, not just its name.
params › notifications
Updated delivery channels (same shape as create).
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
The title clearly communicates the tool’s action and subject. Keep it concise.
Description99/100
WATCH CANCEL — NEW watcher system (v2025-11-01 API). Manages watches created by crustdata_watch_create (NOT the legacy crustdata_watcher_* watches). FREE. DELETE the watch — returns 204 No Content (surfaced here as {success: true}). Deletion is terminal; the watch cannot be resumed. If the user may want it back, pause it via crustdata_watch_update instead. RESPONSE: {api_request, response} — api_request echoes the exact API call (with a copy-pasteable curl) and response is the deletion result.
The description explains the capability, when to use it, and what to expect.
Inputs80/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › entity_type
Which dataset to watch: 'person' or 'company'.
Clear enough to supply this argument.
params › watch_id
ID of the watch. Must be positive.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_watch_cancel",
"title": "Cancel a watch",
"description": "WATCH CANCEL — NEW watcher system (v2025-11-01 API). Manages watches created by crustdata_watch_create (NOT the legacy crustdata_watcher_* watches). FREE. DELETE the watch — returns 204 No Content (surfaced here as {success: true}). Deletion is terminal; the watch cannot be resumed. If the user may want it back, pause it via crustdata_watch_update instead. RESPONSE: {api_request, response} — api_request echoes the exact API call (with a copy-pasteable curl) and response is the deletion result.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"entity_type",
"watch_id"
],
"properties": {
"watch_id": {
"type": "integer",
"description": "ID of the watch. Must be positive.",
"exclusiveMinimum": 0
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"entity_type": {
"enum": [
"person",
"company"
],
"type": "string",
"description": "Which dataset to watch: 'person' or 'company'."
}
},
"description": "Input for GET /watch/{entity_type}/{watch_id} (v2025-11-01)."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": false,
"openWorldHint": true,
"destructiveHint": true
}
}
The title clearly communicates the tool’s action and subject. Keep it concise.
Description87/100
Find recent Twitter/X posts from a company or person by their Twitter handle. This is the Twitter/X post tool — it covers tweets, X posts and Twitter posts, which the social_posts tools do not (those are LinkedIn only). Runs a web search on x.com (/web/search/live) and returns post titles, URLs, and snippets.
Describe the returned information so the agent knows whether it will answer the request.
Inputs92/100
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
params › user_query
The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from.
Clear enough to supply this argument.
params › twitter_handle
Twitter/X handle of the company (with or without @). For example: 'crustdata' or '@crustdata'.
Clear enough to supply this argument.
params › num_pages
Number of result pages. Each page returns up to ~10 posts and bills 1 credit. Default: 1.
Remove validation rules already expressed in this field’s schema; describe its meaning and usage instead.
Annotations75/100
Declare idempotentHint based on the tool’s actual behavior.
No output schema is declared. Add one for structured results so clients can interpret returned fields.
Not declared
Original tool metadata
{
"name": "crustdata_get_twitter_posts",
"title": "Get X/Twitter posts",
"description": "Find recent Twitter/X posts from a company or person by their Twitter handle. This is the Twitter/X post tool — it covers tweets, X posts and Twitter posts, which the social_posts tools do not (those are LinkedIn only). Runs a web search on x.com (/web/search/live) and returns post titles, URLs, and snippets.",
"inputSchema": {
"type": "object",
"required": [
"params"
],
"properties": {
"params": {
"type": "object",
"required": [
"twitter_handle"
],
"properties": {
"num_pages": {
"type": "integer",
"default": 1,
"maximum": 15,
"minimum": 1,
"description": "Number of result pages. Each page returns up to ~10 posts and bills 1 credit. Default: 1."
},
"user_query": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"default": null,
"description": "The user's original question in their own words. The only record of what was asked, and what a later billing or data question is answered from."
},
"twitter_handle": {
"type": "string",
"description": "Twitter/X handle of the company (with or without @). For example: 'crustdata' or '@crustdata'."
}
},
"description": "Input parameters for fetching Twitter/X posts from a company."
}
},
"additionalProperties": false
},
"annotations": {
"readOnlyHint": true,
"openWorldHint": true,
"destructiveHint": false
}
}
Loading score analytics…
Put your MCP to the test
A few tasks worth trying with this server, chosen from its reviewed tools. These have not been run.
01Search job postingsSearch the job listings database.
02Semantic people searchPEOPLE SEMANTIC SEARCH (beta) — natural-language people search on the /person/search dataset (v2025-11-01).
03Autocomplete job filter valuesJOB FIELD AUTOCOMPLETE (v2025-11-01).
04Search company databaseCOMPANY SEARCH — DATASET (/company/search, API version 2025-11-01).
05Semantic company searchCOMPANY SEMANTIC SEARCH — natural-language ranked company search on the /company/search dataset (v2025-11-01).
Want to run these tasks against your MCP server with us?
crustdata_company_identifycrustdata_company_enrichcrustdata_company_search_dbcrustdata_company_searchcrustdata_company_linkedin_postscrustdata_job_searchcrustdata_job_search_livecrustdata_batch_job_searchcrustdata_batch_job_search_livecrustdata_people_enrichcrustdata_people_search_dbcrustdata_people_search+11 more
Crustdata MCP Server setup, tools, quality score, publishing readiness, and alternatives.
How do I add Crustdata MCP Server to Claude, ChatGPT, or Cursor?
Add Crustdata MCP Server to Claude, ChatGPT, or Cursor by connecting its remote MCP URL in each client's MCP settings. In Claude, add a custom connector. In ChatGPT, add an MCP app. In Cursor, add an MCP server under Settings. The MCP URL is https://mcp.crustdata.com/mcp. This server requires OAuth, so complete the login prompt after you connect.
Is Crustdata MCP Server MCP ready for ChatGPT and Claude?
As of October 15, 2026, Crustdata MCP Server scores 96/100 on Manufact's MCP publishing checklist. The scan meets ChatGPT publishing checks and meets Claude publishing checks. Passing these checks does not guarantee marketplace approval.
How clear is Crustdata MCP Server's MCP tool documentation?
As of October 15, 2026, Crustdata MCP Server scores 82/100 in Manufact's review of tool titles, descriptions, input and output schemas, and behavior annotations. The review covers 58 of 58 discovered tools. The quality score measures documentation clarity; runtime behavior and marketplace readiness require separate checks.
What tools does the Crustdata MCP Server MCP server provide?
Crustdata MCP Server lists 23 MCP tools, including crustdata_company_identify, crustdata_company_enrich, crustdata_company_search_db, crustdata_company_search, crustdata_company_linkedin_posts, crustdata_job_search, crustdata_job_search_live, crustdata_batch_job_search, crustdata_batch_job_search_live, crustdata_people_enrich, crustdata_people_search_db, and crustdata_people_search.
What are the best alternatives to Crustdata MCP Server?
As of October 20, 2026, alternatives to Crustdata MCP Server in data-analytics on the Manufact MCP leaderboard include Epicure, Newsflash, Point Topic, Pricing Optimizer AI, and StatCite.
Does Crustdata MCP Server MCP require authentication?
Crustdata MCP Server requires authentication. Connect it in Claude, ChatGPT, or Cursor and complete the OAuth login prompt.
How can Crustdata MCP Server improve its MCP documentation?
crustdata_batch_people_enrich is the lowest-scoring reviewed tool at 68/100. No output schema is declared. Add one for structured results so clients can interpret returned fields. Open its review for feedback and a copyable fix prompt, then rerun the documentation review after updating your tool metadata.
Who develops Crustdata MCP Server?
Crustdata MCP Server is developed by Crustdata. It is listed as partner on the Claude connector directory.
Not your MCP?
Review any public or OAuth MCP server for protocol compatibility, tool documentation, and ChatGPT and Claude publishing readiness. No account required.