Skip to main content
Glama

Extract contacts from a website

extract_contacts
Read-onlyIdempotent

Crawl a company website and extract emails, phone numbers and social profiles. Accepts a bare domain or a full URL; max_pages (1-20, default 5) bounds the crawl.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
websiteYesThe website to crawl: a bare domain ('example.com') or a full URL ('https://example.com').
max_pagesNoMaximum number of pages to crawl (1-20, default 5).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlNoThe start URL crawled.
errorNoSet only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.
domainNoThe site's registrable domain.
emailsNoAddresses on the site's own domain.
githubNoGitHub profile.
phonesNoPhone numbers found.
messageNoA sentence for the caller.
twitterNoX / Twitter profile.
youtubeNoYouTube channel.
facebookNoFacebook profile.
linkedinNoLinkedIn page.
instagramNoInstagram profile.
otherEmailsNoOther addresses found on the site.
socialLinksNoEvery social link found, best first.
pagesCrawledNoPages read.
personalEmailsNoAddresses shaped like a person's (firstname.lastname@): personal data, so GDPR art. 14 and Law 506/2004 apply. Role addresses (office@) rank first.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • addedOutput schema / properties / personalEmails
      Added value: +{
      +  "description": "Addresses shaped like a person's (firstname.lastname@): personal data, so GDPR art. 14 and Law 506/2004 apply. Role addresses (office@) rank first.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": [
      +    "array",
      +    "null"
      +  ]
      +}
  2. Changed3 schema fields changed
    • addedInput schema / properties / max_pages / description
      Added value: +"Maximum number of pages to crawl (1-20, default 5)."
    • addedInput schema / properties / website / description
      Added value: +"The website to crawl: a bare domain ('example.com') or a full URL ('https://example.com')."
    • changedOutput schema / (root)
      Previous value: -nullNew value: +{
      +  "additionalProperties": true,
      +  "description": "Contacts found on a website.",
      +  "properties": {
      +    "domain": {
      +      "description": "The site's registrable domain.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "emails": {
      +      "description": "Addresses on the site's own domain.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    },
      +    "error": {
      +      "description": "Set only when there is no answer (empty_query, invalid_cui, data_unavailable, plan_required ...); such a call is not counted.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "facebook": {
      +      "description": "Facebook profile.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "github": {
      +      "description": "GitHub profile.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "instagram": {
      +      "description": "Instagram profile.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "linkedin": {
      +      "description": "LinkedIn page.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "message": {
      +      "description": "A sentence for the caller.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "otherEmails": {
      +      "description": "Other addresses found on the site.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    },
      +    "pagesCrawled": {
      +      "description": "Pages read.",
      +      "type": [
      +        "integer",
      +        "null"
      +      ]
      +    },
      +    "phones": {
      +      "description": "Phone numbers found.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    },
      +    "socialLinks": {
      +      "description": "Every social link found, best first.",
      +      "items": {
      +        "type": "string"
      +      },
      +      "type": [
      +        "array",
      +        "null"
      +      ]
      +    },
      +    "twitter": {
      +      "description": "X / Twitter profile.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "url": {
      +      "description": "The start URL crawled.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "youtube": {
      +      "description": "YouTube channel.",
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    }
      +  },
      +  "type": "object"
      +}
  3. First observed

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint and destructiveHint=false, so the safety profile is covered. The description's remaining behavioral contribution is the crawl-bound statement (max_pages 1-20, default 5), which largely duplicates the schema. It says nothing about runtime, throttling, or what happens on a large or unreachable site, so it adds only modest context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler: the capability statement comes first, then the input/crawl-bound note. Every clause earns its place and nothing is buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not explain return values, and annotations carry the safety profile. Combined with a fully documented two-parameter schema, the definition is nearly complete; only the absence of any sibling routing (enrich_company, lookup_domain) leaves a small gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and both parameters already carry format and range details in the schema ('bare domain' vs 'full URL', '1-20, default 5'). The description restates those same facts rather than extending them, so the baseline of 3 for fully documented schema applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a concrete verb+resource pairing ('Crawl a company website and extract emails, phone numbers and social profiles') and names the exact artifact produced, so the agent can distinguish it from lookup-style siblings like find_company_by_domain or lookup_domain. It stops short of explicitly contrasting itself with those siblings, which keeps it at a 4 rather than a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the purpose ('crawl a website' clearly maps to the contact-extraction job in this toolset), and it notes the accepted input formats for the website argument. However, it offers no when-to-use/when-not guidance and never points to a sibling such as enrich_company or lookup_domain for overlapping contact-enrichment needs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources