Skip to main content
Glama

insaight

LinkedIn prospect intelligence inside Claude — it automates the research, not the outreach.

MIT License Tests Python 3.11+

Insaight scrapes public LinkedIn data via Apify, stores it in local SQLite, and hands it to Claude through an MCP server and eight skills. Data flows in once, then stays on your machine — repeat questions hit SQLite, not Apify.

Architecture

graph LR
    C["Claude Code / Desktop<br/>8 skills"] -->|MCP| S["insaight server<br/>18 tools"]
    S --> DB[("SQLite<br/>~/.insaight/posts.db")]
    S --> M["memory/<br/>style.md · playbook.md"]
    S -->|fresh scrapes only| A["Apify<br/>LinkedIn actors"]

Related MCP server: linkedin-engine

Install in 30 seconds

Prerequisite: uv and Python 3.11+. The plugin runs the MCP server with uvx, so without uv the tools never load.

curl -LsSf https://astral.sh/uv/install.sh | sh   # skip if you already have uv

Then, in Claude Code:

/plugin marketplace add spirosbax/insaight
/plugin install insaight@insaight

Add your Apify token (free tier works):

mkdir -p ~/.insaight && echo "APIFY_API_TOKEN=apify_api_..." >> ~/.insaight/.env

Restart Claude Code and say "research Anthropic on LinkedIn". The plugin registers the MCP server and installs all eight skills; there is nothing to clone.

On the very first run, uvx builds the server before it answers — give it a few seconds. If the insaight tools never appear, check that uv is on your PATH.

Add to claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):

{
  "mcpServers": {
    "insaight": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/spirosbax/insaight", "insaight"],
      "env": { "APIFY_API_TOKEN": "apify_api_..." }
    }
  }
}

Restart Claude Desktop, then add the skills under Settings → Skills → Add skills, selecting the SKILL.md files from this repo's skills/ directory.

git clone https://github.com/spirosbax/insaight.git && cd insaight
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"
pytest -q                                                      # hermetic — temp SQLite, no credentials
claude mcp add insaight -s user -- "$PWD/.venv/bin/insaight"   # local checkout instead of uvx

A checkout with a data/ directory uses it as INSAIGHT_HOME, keeping the dev database inside the repo (gitignored).

Skills

Eight skills that chain conversationally — each one's output feeds the next. They are plain Markdown with YAML frontmatter: easy to read, fork, and customize.

Skill

One line

research-person

Intelligence brief on an individual: themes, decision-maker signals, outreach hooks, uncommon commonalities

research-company

Company analysis from company posts + up to 3 C-level executives' posts, with a prospect score

research-post

Mine a post's comment thread for warm leads, decision-makers, and competitor mentions

draft-outreach

Cold DM + email, two variants each, using prior research + your learned style memory

draft-post

LinkedIn post in your company's voice, styled on your own past posts (URL-to-post supported)

track-outreach

Log sends and outcomes in the local ledger ("I sent it", "she replied", "mark as ghosted")

reflect

Analyze outcomes, propose evidence-backed memory updates — applied only on your approval

save-notion

Persist research briefs to your configured Notion page (optional, needs the Notion MCP)

prospecting     research company → draft outreach → save to Notion
person-first    research person  → draft outreach
qualification   research company → read the prospect evaluation → pursue or pass

An unedited Claude Code session: install, research Anthropic, find the right person, draft the DM, log the send.

The memory loop

draft → send → "I sent it"          → logged (log_outreach)
       → "she replied" / "ghosted"  → outcome recorded (record_outcome)
       → every N outcomes           → reflection proposed (default 10; REFLECT_EVERY)
       → you approve                → style.md + playbook.md updated

Outcomes are logged because you say so — Insaight never reads your inbox. Every playbook claim carries its evidence ("question hooks: 4/9 replied vs statement hooks: 1/8"), and below n=10 a pattern is a hypothesis, not a rule. Nothing is written to memory without your approval. The ledger also powers prior-contact warnings ("you messaged this person 3 weeks ago — ghosted") whenever you research or draft.

Tool

Purpose

list_accounts

Discover tracked companies and personal profiles

scrape_profile

Fetch fresh posts for any LinkedIn URL (Apify)

scrape_people

Fetch company employees and leadership (Apify, Short or Full mode)

scrape_person_profile

Enrich one person with full profile: experience, education, skills, volunteer, languages

list_posts

Token-cheap index: metadata + 150-char snippet

get_posts

Full content for selected posts by URN (max 20 per call)

search_posts

Full-text keyword search across stored posts

list_people

Query stored employees/leadership (instant, free)

scrape_post_comments

Fetch a post's comment thread with author info (Apify)

list_comments

Query stored comments for a post, ranked by likes

get_stats

Database overview: counts, date range, categories

log_outreach

Record a sent message in the ledger (flags prior contact)

record_outcome

Record replied / positive / meeting / ghosted; flags when reflection is due

list_outreach

Query the ledger: prior-contact checks, pending sends, history

get_outreach_stats

Reply-rate breakdown by hook type, variant, and channel

get_memory

Read the learned style guide + strategy playbook

update_memory

Rewrite a memory file (only after an approved reflection)

get_config

Read your Notion pages + company config from ~/.insaight/config.md (creates it with placeholders on first call)

Reading pattern: list_posts returns ~80 tokens per post; scan snippets, then get_posts only the interesting ones.

Everything is under ~/.insaight/ (override with INSAIGHT_HOME):

~/.insaight/
  .env         APIFY_API_TOKEN, ANTHROPIC_API_KEY (optional), REFLECT_EVERY
  config.md    Notion pages + company config (read by get_config)
  posts.db     SQLite: posts, people, comments, outreach ledger
  memory/      style.md + playbook.md (written by the reflect skill)

Actor

Scrapes

Approx. cost

harvestapi/linkedin-profile-posts

Company or personal posts

~$1.50 / 1k posts

harvestapi/linkedin-company-employees

Employees and leadership

~$4 / 1k (Short), ~$8 / 1k (Full)

harvestapi/linkedin-profile-scraper

Single-profile enrichment

$4 / 1k ($10 / 1k with email search)

harvestapi/linkedin-post-comments

Comment threads

see actor page

Rates as published at time of writing — check the actor pages for current pricing.

A standalone CLI for batch work outside Claude (insaight-cli in a dev install, or uvx --from git+https://github.com/spirosbax/insaight insaight-cli):

insaight-cli scrape --accounts config/accounts.txt   # scrape tracked accounts (--no-categorize skips the Anthropic API)
insaight-cli stats                                   # database overview
insaight-cli export --format csv --output posts.csv  # export to CSV or JSON

Data, privacy & terms

Everything stays local: posts, people, the outreach ledger, and learned memory live in SQLite and Markdown on your machine, and nothing is sent anywhere except your own Apify/Anthropic/Notion accounts. No inbox access — outcomes exist because you reported them. Insaight fetches public LinkedIn data through third-party Apify actors; automated collection may conflict with LinkedIn's Terms of Service, and you are responsible for how you use this tool. Keep volumes reasonable and respect the people behind the profiles.

License

MIT

Available Tools

18 tools
get_configA

Return the user's insaight config (Notion pages, company name/slug).

Skills call this first to learn where to save research and whose voice to write in. The file lives at /config.md (default ~/.insaight/config.md); it is created with placeholder values on first call. If values are still placeholders, ask the user to edit the file.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

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

With no annotations provided, the description carries the full disclosure burden and delivers: it reveals where the config file lives (<INSAIGHT_HOME>/config.md), that the file is created with placeholder values on first call (a genuine side effect), and instructs the agent to ask the user to edit the file if values remain placeholders. This is exactly the behavior an agent needs disclosed that structured fields cannot convey.

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?

Three dense sentences, each earning its place: core purpose, workflow timing, then file location plus edge-case handling. The most important information is front-loaded and there is zero fluff.

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

Completeness5/5

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

Given zero parameters, no annotations, and an existing output schema, the description covers everything an agent needs: what the config contains, where it lives, the first-call creation side effect, and how to handle placeholder values. Nothing material is missing.

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

Parameters4/5

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

The tool has zero parameters and an empty properties schema, so there is nothing for the description to add about parameter semantics. The 0-parameter baseline of 4 applies because no parameter documentation is needed.

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

Purpose5/5

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

The description states a specific verb and resource — 'Return the user's insaight config (Notion pages, company name/slug)' — making what the tool does unambiguous. While it doesn't name a sibling explicitly, none of the listed siblings (list_accounts, get_stats, get_memory, etc.) plausibly overlaps with a config-bootstrap tool, and the usage line further establishes its unique role.

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

Usage Guidelines4/5

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

'Skills call this first to learn where to save research and whose voice to write in' gives explicit workflow context: this tool is the entry point before saving research or writing. It clearly states when to use it but does not name alternatives or state when-not-to, so it stops short of a 5.

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

get_memoryA

Read the distilled outreach memory: the style guide and the strategy playbook. The draft-outreach and draft-post skills should read THIS (a few hundred tokens) instead of re-deriving style from raw history.

Returns both files plus whether they've been learned yet and the reflection state. If not yet learned, fall back to reading recent outreach (list_outreach) or the Notion log, and suggest running insaight-reflect once a few outcomes are logged.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

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

With no annotations, the description carries the full burden. It discloses that the tool returns both memory files, a learned flag, and reflection state, and explains the conditional fallback behavior. It stops short of explicitly stating side-effect status or auth requirements, but 'Read' and 'Returns' make the read-only nature reasonably clear.

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?

Three sentences, all information-dense and front-loaded. The first sentence states the core purpose, the second summarizes the return payload, and the third gives fallback guidance. No wasted words.

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

Completeness5/5

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

Given the zero-parameter surface and an output schema that can define the return shape, the description provides complete operational context: what it reads, who should use it, what it returns, and what to do when the learned state is absent.

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

Parameters4/5

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

There are zero parameters and the schema is empty, so there is no parameter-level meaning to convey. The description compensates by explaining what the tool reads and returns, which is the relevant semantic content for an argument-less call.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Read the distilled outreach memory', naming the style guide and strategy playbook. It clearly differentiates this tool by stating that drafting skills should use it instead of re-deriving style from raw history, which separates it from list_outreach and other siblings.

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

Usage Guidelines5/5

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

The description explicitly tells the intended callers (draft-outreach and draft-post skills) to use this tool for distilled memory, and provides a concrete fallback path (list_outreach or Notion log) and an actionable suggestion (run insaight-reflect) when memory has not been learned yet.

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

get_outreach_statsA

Reply-rate breakdown of the outreach ledger: totals plus per-hook_type, per-variant, and per-channel rates (pending sends excluded from rates), and the current reflection state.

This is the evidence source for the insaight-reflect skill — cite these counts (e.g. "question hooks: 4/9 replied") in any proposed memory update.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

Even without annotations, the description reveals meaningful behavioral details: pending sends are excluded from rates, and the tool also returns the current reflection state. This goes beyond simply saying 'get stats' and gives the agent important context about what the values represent.

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?

The description is compact and front-loaded: the first sentence conveys the result and key exclusions, and the second provides practical guidance on how to use the output. No words are wasted, and every sentence earns its place.

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

Completeness5/5

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

For a zero-parameter read-only-style tool with an output schema available, the description covers the result shape, a critical calculation nuance (pending sends excluded), and the intended downstream use. Nothing essential is missing for an agent to select and invoke the tool correctly.

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

Parameters4/5

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

The tool has zero parameters and 100% schema description coverage, so there is nothing for the description to clarify about input semantics. The baseline of 4 for a no-parameter tool applies, and the description adds no unnecessary parameter-related filler.

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

Purpose5/5

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

The description states exactly what the tool does: provides a reply-rate breakdown of the outreach ledger with totals and per-hook_type, per-variant, and per-channel rates. It also clearly distinguishes the resource (outreach stats) and includes a notable behavioral detail (pending sends excluded). This is specific enough to differentiate it from generic siblings like get_stats.

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

Usage Guidelines4/5

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

The description explicitly identifies the intended use case: it is the evidence source for the insaight-reflect skill, and agents should cite these counts in proposed memory updates. It does not explicitly say when not to use the tool or contrast it with alternatives, but the context is clear and actionable.

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

get_postsA

Fetch full content for a specific list of posts by their URNs.

Use this after list_posts() to read only the posts you actually need. Accepts up to 20 URNs per call. URNs come from the 'urn' field in list_posts results.

Args: urns: List of post URN strings to fetch (max 20).

ParametersJSON Schema
NameRequiredDescriptionDefault
urnsYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior3/5

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

With no annotations provided, the description carries the behavioral burden. It discloses the 20-URN limit and that URNs originate from list_posts, but does not mention error handling, invalid URN behavior, or whether the operation is strictly read-only beyond the word 'Fetch'.

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?

The description is concise and well-structured: a one-sentence summary, usage guidance, a constraint, and a clear Args block. Every sentence contributes useful information with no redundancy.

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?

For a simple fetch-by-URN tool with an output schema, the description covers the essential aspects: what it does, when to use it, and parameter constraints. Minor gaps like behavior for nonexistent URNs or pagination are not critical given the output schema exists.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must compensate. It explains that 'urns' is a list of post URN strings to fetch and adds the critical max-20 constraint, which is absent from the schema.

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

Purpose5/5

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

The description states a specific verb ('Fetch') and resource ('full content for a specific list of posts'), and clarifies the key identifier (URNs). This clearly distinguishes it from sibling tools like list_posts or search_posts.

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

Usage Guidelines4/5

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

It explicitly says to use this tool after list_posts() to read only needed posts, and points out that URNs come from the 'urn' field in list_posts results. It provides clear context but does not explicitly state when not to use it or name direct alternatives.

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

get_statsA

Return a DB-wide overview: total posts, accounts, date range, category breakdown. Useful for a quick orientation before diving into posts.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior3/5

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

With no annotations provided, the description must carry the behavioral burden itself. It does convey that this is a read-only aggregate operation and lists the response contents, which is the core safety-relevant trait, but it adds no depth beyond that — nothing about freshness of stats, computation cost of a DB-wide scan, or auth/rate-limit implications.

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 zero filler: the first states the deliverable and its contents, the second states when to reach for it. The core identity ('DB-wide overview') is front-loaded and every sentence earns its place.

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?

For a zero-parameter tool with an output schema, the description covers nearly everything an agent needs: what it returns and when to call it. The only notable gap is that it doesn't explicitly differentiate from the overlapping sibling get_outreach_stats, though the 'DB-wide' wording does most of that work.

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

Parameters4/5

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

The tool has zero parameters and the input schema is empty, so the description owes nothing here; the baseline of 4 applies. The words 'date range' and 'category breakdown' describe output fields, not inputs, and the output schema documents the return shape.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Return a DB-wide overview' and enumerates the exact contents (total posts, accounts, date range, category breakdown). The 'DB-wide' framing separates it from the sibling list_* tools and the outreach-specific get_outreach_stats without requiring schema inspection.

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

Usage Guidelines4/5

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

'Useful for a quick orientation before diving into posts' gives a clear temporal/use-case signal: run this first for orientation, then move to post-level tools such as list_posts or search_posts. It provides clear context but stops short of explicitly naming alternatives or stating when not to use it.

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

list_accountsA

List all tracked LinkedIn accounts (companies and profiles) in the database.

Returns each account's slug (short name), full URL, post count, and date of most recent post. ALWAYS call this first to discover what accounts are available and learn the correct slugs to use in other tools.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations provided, the description carries the burden of behavioral disclosure. It clearly indicates this is a non-mutating list operation by saying 'List all' and explains what is returned. It does not discuss pagination, ordering, or access requirements, but for a zero-parameter read-only listing tool these omissions are minor.

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?

The description is three sentences with no filler. The action and resource are front-loaded, the return payload is summarized concisely, and the usage guidance is a clear directive. Every sentence adds value.

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

Completeness5/5

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

For a zero-parameter list tool with an output schema present, the description is complete: it explains what the tool returns, what accounts include, and how the tool should be used within a workflow. Nothing critical is missing for correct invocation.

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

Parameters4/5

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

The tool has zero parameters, and schema description coverage is 100%, so the baseline is 4. The description adds relevant context about the output even though no parameters need explanation.

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

Purpose5/5

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

The description states a specific action ('List all tracked LinkedIn accounts') and identifies the exact resource ('companies and profiles in the database'). It also enumerates the returned fields, making the tool's purpose unambiguous and distinguishable from sibling tools that operate on posts, people, or comments.

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

Usage Guidelines4/5

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

The description gives explicit usage context: 'ALWAYS call this first to discover what accounts are available and learn the correct slugs to use in other tools.' This clearly tells an agent when to invoke it, though it does not name specific alternative tools or state when not to use it.

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

list_commentsA

List stored comments for a post, ranked by likes desc then time.

Provide either post_urn (e.g. "urn:li:activity:7451209045283254272") or post_url (the full LinkedIn URL — the URN is extracted automatically).

Args: post_urn: Post URN. Use this OR post_url. post_url: Full LinkedIn post URL. The URN is extracted from it. limit: Max comments returned (default 100). min_likes: Only return comments with at least this many likes. include_replies: If False, only top-level comments are returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
post_urlNo
post_urnNo
min_likesNo
include_repliesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

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

With no annotations provided, the description carries the behavioral disclosure burden. It discloses ranking order, automatic URN extraction from URLs, filtering by min_likes, and the include_replies behavior. It does not discuss pagination, rate limits, or error cases, but covers the core behaviors an agent needs to invoke it correctly.

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?

The description is front-loaded with a clear one-sentence purpose, then gives a brief usage line, followed by a compact Args list. Every sentence adds information; there is no filler.

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

Completeness5/5

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

Given five parameters, a 0% schema description coverage, no annotations, and an output schema that covers return shape, the description gives all necessary parameter semantics and behavioral detail. It includes the mutual exclusivity constraint for the two post identifiers and explains each optional parameter. The only omission is explicit sibling differentiation, but that does not compromise the ability to call the tool correctly.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must explain all five parameters, and it does: post_urn/post_url are described with mutual exclusivity, limit with max comments and default 100, min_likes with a semantic filter, and include_replies with its 'only top-level' behavior. This fully compensates for the bare schema.

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

Purpose5/5

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

The opening sentence states a specific action ('List stored comments') and object ('a post'), and specifies the ordering ('ranked by likes desc then time'). The word 'stored' distinguishes it from the sibling scrape_post_comments, which implies fetching fresh data rather than reading persisted ones.

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

Usage Guidelines4/5

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

The description clearly states the input requirements (provide either post_urn or post_url) and describes the data as 'stored comments,' giving context for when this read-style tool is appropriate. It does not explicitly name alternatives or state when not to use it, but the 'stored' qualifier and the parameter guidance provide adequate usage context.

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

list_outreachA

Query the outreach ledger, newest first. Use for prior-contact checks ("have I messaged this person?"), reviewing pending sends, or pulling recent messages for reflection.

Args: outcome: Filter: "pending" | "replied" | "positive" | "meeting" | "ghosted". Empty = all. target: Substring match on target URL, name, or company. limit: Max records (default 30, max 100). full: If True, include full message text (use for reflection); default False returns a 150-char snippet.

ParametersJSON Schema
NameRequiredDescriptionDefault
fullNo
limitNo
targetNo
outcomeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

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

With no annotations, the description carries the burden and does well by disclosing ordering, the default snippet behavior, the full-message option, and limits. It does not explicitly say the operation is read-only, but the use-case framing and query semantics strongly imply it. No annotation contradiction exists.

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?

The description is compact and well-structured: a one-sentence purpose, a short use-case list, and a clearly formatted parameter block. Every sentence adds useful information without redundancy.

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

Completeness5/5

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

All four parameters are explained, usage scenarios are given, and an output schema exists so return formatting does not need to be described. The tool is a straightforward list query, and nothing essential for correct invocation is missing.

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

Parameters5/5

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

Schema coverage is 0%, but the description fully documents each parameter: outcome values, target substring matching, limit defaults/maximum, and the full flag behavior. This adds substantial meaning beyond the raw schema, which only gives types and defaults.

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

Purpose5/5

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

The description states a specific verb ('Query') and resource ('outreach ledger') and adds ordering ('newest first'). This clearly distinguishes it from write tools like log_outreach and record_outcome, and from get_outreach_stats which is about statistics.

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

Usage Guidelines4/5

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

The description explicitly lists when to use this tool: prior-contact checks, reviewing pending sends, and pulling recent messages for reflection. It does not explicitly state when not to use it or name alternatives, but the use cases are concrete and helpful enough to guide selection.

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

list_peopleA

List stored employees/leadership for a company from the local database.

This is instant (no Apify call). If the result is empty, call scrape_people() first to populate the database for this company.

Args: account: Slug (e.g. "acme-charging") or full LinkedIn company URL. Use list_accounts() to discover available slugs. role: Optional keyword to filter by — matched against name, headline, and job titles. Examples: "CEO", "founder", "sales", "engineer". Leave empty to return all stored people. limit: Max results to return (default 50).

ParametersJSON Schema
NameRequiredDescriptionDefault
roleNo
limitNo
accountYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral burden and does well: it states the tool is instant, makes no Apify call, reads from a local database, and may return empty results requiring population. It could additionally mention whether results are sorted or whether the role filter is case-sensitive, but the key behavioral traits are disclosed.

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?

The description is efficiently structured: purpose first, then key behavioral note, then parameter details. Every sentence adds genuine value, and the parameter documentation is scannable and complete without being bloated.

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

Completeness5/5

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

For a three-parameter list tool with an output schema available, the description covers what is needed to invoke it correctly: required account, optional filters, local vs. remote behavior, and the empty-result fallback. It does not need to describe return values because an output schema exists.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must fully explain the parameters, and it does. It explains account as slug or full URL, role as an optional filter matched against name/headline/job titles with examples, and limit as the max results with a default.

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

Purpose5/5

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

The description states a specific verb, resource, and scope: "List stored employees/leadership for a company from the local database." It clearly differentiates this from scraping tools by emphasizing "stored" and "local database," and it names the fallback to scrape_people().

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

Usage Guidelines5/5

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

The description gives explicit when-to-use guidance: use this for instant local results, and if empty, call scrape_people() first to populate the database. It also directs users to list_accounts() for discovering valid account slugs, which is exactly the kind of routing an agent needs.

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

list_postsA

Return a slim index of posts (metadata + 150-char snippet, NO full content).

Use this to survey what posts exist before deciding which ones to read in full via get_posts(). Fetching slim records first is far more token-efficient.

Args: account: Slug (e.g. "acme-charging") or full LinkedIn URL. Empty = all accounts. Use list_accounts() to find slugs. category: Filter by semantic category (e.g. "product", "hiring"). days_ago: Only posts from the last N days (0 = no limit). min_engagement: Only posts where likes+comments+shares >= this value. limit: Max posts to return (default 30, max 100).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
accountNo
categoryNo
days_agoNo
min_engagementNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior4/5

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

With no annotations, the description carries the full burden of behavioral disclosure. It clearly states the key behavioral traits: results are slim indexes, full content is excluded, and records include a 150-char snippet. It also frames the operation as non-destructive and efficient. It does not mention ordering or pagination, but for a read-only list tool with a defined limit parameter, the disclosed behavior is sufficient.

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?

The description is compact and front-loaded: the first sentence states purpose and output scope, the second provides usage guidance, and the third gives the efficiency rationale. The Args block is structured and every line adds necessary semantics. There is no filler or redundancy.

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

Completeness5/5

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

The description covers the tool's purpose, the relevant sibling flow, all parameter semantics, and the critical output difference from get_posts(). Since an output schema exists, the exact return fields do not need to be restated. The description is complete enough for an agent to select and invoke the tool correctly.

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

Parameters5/5

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

The input schema provides only type/default information and has 0% description coverage, so the parameter descriptions carry the full burden. The Args section adds rich meaning: account accepts a slug or URL, empty means all accounts and points to list_accounts(), category is a semantic filter, days_ago has a clear meaning, and limit gets default/max constraints. This fully compensates for the schema's lack of descriptions.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Return a slim index of posts.' It explicitly distinguishes the tool by noting it returns 'metadata + 150-char snippet, NO full content' and frames it as the survey-before-reading counterpart to get_posts(). This leaves no ambiguity about what the tool does.

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

Usage Guidelines5/5

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

The description gives a clear usage scenario: 'Use this to survey what posts exist before deciding which ones to read in full via get_posts().' It also explains why this path is preferable ('Fetching slim records first is far more token-efficient'), which helps the agent choose it over get_posts().

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

log_outreachA

Record an outreach message the user actually SENT. Call this when the user says they sent a message ("I sent it", "log this outreach").

The stored ledger replaces a manual sent-log: it powers prior-contact checks, reply-rate stats, and the reflection loop that learns what works. The response includes any prior contact with the same target — surface that to the user if present.

Args: target_url: LinkedIn profile URL (or email address) of the recipient. message: The exact message text that was sent. target_name: Recipient's name (optional but recommended). company: Recipient's company (optional). channel: "dm" | "email" | "other" (default "dm"). variant: Which draft variant was sent: "warm" | "direct" | "follow-up" | free text. hook_type: Opening hook used: "question" | "statement" | "story" | "stat" | "commonality" | free text. Used for reply-rate breakdowns. notes: Anything worth remembering about this send (optional).

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNo
channelNodm
companyNo
messageYes
variantNo
hook_typeNo
target_urlYes
target_nameNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.6/5.0
Behavior4/5

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

With no annotations provided, the description carries the full behavioral burden. It discloses that the tool writes to a ledger, that the ledger powers downstream analytics, and that the response includes prior contact history with the same target. This is substantive behavioral context beyond the schema.

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?

The description is well-organized: trigger phrasing first, then ledger purpose, then a concise reference-style Args list. There is no filler, and every sentence adds decision-relevant information.

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

Completeness5/5

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

Given the tool's moderate complexity, the description covers invocation triggers, parameter semantics, behavioral side effects, and response expectations in a compact way. The output schema exists, so the description does not need to detail the full return type, and it even instructs the agent to surface prior-contact matches from the response.

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

Parameters5/5

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

The schema has 0% description coverage, but the description fully compensates with an Args block that explains every parameter, including valid enum values for channel, variant, and hook_type, plus optionality and defaults. This adds significant meaning beyond the raw schema titles.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Record an outreach message the user actually SENT.' It clarifies the tool's exact scope and even gives example user phrasings that should trigger it, which distinguishes it from outcome-related tools like record_outcome.

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

Usage Guidelines4/5

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

It explicitly states when to call the tool: 'Call this when the user says they sent a message.' It also explains the broader purpose of the stored ledger, giving clear context. It stops short of naming alternatives or saying when not to use it, so it misses the top score.

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

record_outcomeA

Record what happened to a sent outreach message. Call when the user says the target replied, booked a meeting, or went quiet.

Identify the record by outreach_id, OR by target_url (resolves to that target's most recent pending message).

The response includes reflection_due — when true, tell the user that enough outcomes have accumulated and offer to run the insaight-reflect skill.

Args: outreach_id: Row id returned by log_outreach() (preferred). target_url: Alternative lookup: the target's URL/email. outcome: "replied" | "positive" | "meeting" | "ghosted". (positive = reply with clear interest; meeting = call booked) reply_snippet: A short quote from the reply — evidence for reflection. notes: Optional context (e.g. "replied after the follow-up nudge").

ParametersJSON Schema
NameRequiredDescriptionDefault
notesNo
outcomeNoreplied
target_urlNo
outreach_idNo
reply_snippetNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations, the description carries the behavioral burden. It discloses that target_url resolves to the target's most recent pending message and that reflection_due should trigger a follow-up skill. It does not detail overwrite/duplicate behavior or error paths, but the core write behavior and response signal are adequately explained.

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?

Information is front-loaded: purpose, trigger, lookup, response behavior, then args. Each sentence carries operational value and the Args block is scannable; there is no filler.

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?

Covers the key invocation decisions: when to call, which identifier to use, accepted outcome values, and what to do when reflection_due appears in the response. It does not spell out the constraint that at least one identifier must be supplied or what happens when target_url matches nothing, but the clear lookup description and output schema make it reasonably complete.

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

Parameters5/5

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

Schema description coverage is 0%, so the description fully compensates with an Args section that explains all five parameters, including preferred vs alternative lookup, enum values with parenthetical meanings, and the optional nature of notes. This adds substantial meaning beyond the bare schema.

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

Purpose5/5

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

Description states a clear verb+resource: 'Record what happened to a sent outreach message.' The trigger phrase 'replied, booked a meeting, or went quiet' and the reference to log_outreach() in the args distinguish it from sibling logging/listing tools.

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

Usage Guidelines4/5

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

Explicit call condition is given: 'Call when the user says the target replied, booked a meeting, or went quiet.' It also tells the agent to prefer outreach_id over target_url. It does not explicitly state when not to use it or name alternative tools, so it falls short of a 5.

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

scrape_peopleA

Scrape and store company employees/leadership from LinkedIn via Apify.

Results are stored in the database so subsequent calls to list_people() are instant without any Apify cost. Run this once per company; re-run only when you need fresher data (people data is updated by upsert, not duplicated).

Args: url: Full LinkedIn company URL. Example: https://www.linkedin.com/company/acme-charging job_titles: Optional list of job titles to filter by on LinkedIn. Example: ["CEO", "Founder", "CTO", "Head of", "Director"] Leave empty to scrape all visible employees (up to max_items). max_items: Maximum number of profiles to fetch (default 50, max 200). For leadership only, use 10–20 with specific job_titles. full_mode: If True, uses Full profile scraper mode ($8/1k) to also fetch about, experience, education, skills, certifications, languages, volunteer, projects, recommendations. Default False (Short mode, $4/1k) which returns only name, headline, location, current role. Use True when you need commonality-mining data for outreach.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes
full_modeNo
max_itemsNo
job_titlesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

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

With no annotations, the description fully bears the burden of disclosing side effects. It clearly states that data is persisted in the database, upserted rather than duplicated, and that subsequent list_people calls avoid Apify costs. It also reveals cost differences between full_mode and short mode and lists exactly which fields each mode returns, giving an unusually transparent view of the tool's behavior.

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?

The description is well-structured with a purpose sentence, a usage/storage note, and an Args block. Every sentence carries functional value, and the parameter details are dense but easily scannable. While it is longer than average, the complexity of the tool justifies the length, and the key usage constraints are front-loaded.

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

Completeness5/5

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

The tool has 4 parameters, one required, and an output schema, so the description need not explain return values. It covers all parameter semantics, default behaviors, cost implications, storage effects, and recommended usage patterns. An agent has enough information to call this tool correctly and decide when to use it.

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

Parameters5/5

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

Schema description coverage is 0%, but the description compensates thoroughly. For url it provides a full example; for job_titles it gives a concrete list and explains the empty default; for max_items it gives default, max, and recommended values for leadership; for full_mode it explains cost, returned fields, and when to enable it. This far exceeds bare schema documentation.

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

Purpose5/5

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

The description starts with 'Scrape and store company employees/leadership from LinkedIn via Apify,' which names a specific verb, resource, and destination. It clearly distinguishes this company-level scraping tool from the sibling list_people and profile-level scrapers by highlighting that results are stored for instant retrieval.

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

Usage Guidelines4/5

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

The description gives clear when-to-use guidance: 'Run this once per company; re-run only when you need fresher data.' It also explains the relationship with list_people, saying results are stored so later calls are instant and cost-free. However, it does not explicitly mention alternatives like scrape_person_profile or scrape_profile for individual profile scraping, so the differentiation is incomplete.

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

scrape_person_profileA

Enrich ONE LinkedIn profile with full data (experience, education, skills, certifications, languages, volunteer, projects, recommendations, about).

Use this when you need commonality hooks for outreach — e.g. overlapping past employers, shared schools, mutual volunteer work, common languages. The result is upserted into the people table, so existing short-mode data is preserved and the extended fields are merged in.

Uses harvestapi/linkedin-profile-scraper ($4/1k without email, $10/1k with).

Args: url: Full LinkedIn profile URL. Example: https://www.linkedin.com/in/williamhgates with_email: If True, also runs email search ($10/1k instead of $4/1k). Default False. company_url: Optional LinkedIn company URL to associate this person with. If empty, uses the person's current company from Apify (or falls back to the profile URL itself).

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes
with_emailNo
company_urlNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does substantial work: it discloses that the tool mutates state ('The result is upserted into the people table'), that it preserves existing short-mode data while merging extended fields, and reveals the underlying provider and per-thousand cost ($4 vs $10 with email). This is exactly the kind of side-effect disclosure a scrape-named tool needs; it only omits edge cases like not-found profiles or failure behavior.

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

Conciseness4/5

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

The description is front-loaded: purpose first, then usage, then side effects, then pricing, then a clean Args block. It is slightly redundant in that cost appears both in the provider sentence and again in the with_email arg, but the overall structure is logical and every section earns its place.

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?

The description covers purpose, usage triggers, the database side effect, costs, and all three parameters in depth, and an output schema exists so return values need no explanation. The main gaps are that it never differentiates this tool from the sibling scrape_profile and doesn't state prerequisites (e.g., whether the person must already exist in the people table before enrichment).

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

Parameters5/5

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

Schema description coverage is 0%, so the description must fully compensate, and it does. url gets a full format explanation plus a concrete example (https://www.linkedin.com/in/williamhgates), with_email gets its behavior, cost implication, and default, and company_url gets its fallback logic ('uses the person's current company from Apify... falls back to the profile URL itself'). Every parameter is meaningfully explained.

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

Purpose5/5

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

Opens with a specific verb and resource: 'Enrich ONE LinkedIn profile with full data' followed by an explicit field list (experience, education, skills, certifications, etc.). The deliberate 'ONE' scopes it against the plural sibling scrape_people, and the semantic of enrichment distinguishes it from the similarly named scrape_profile.

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

Usage Guidelines4/5

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

Provides an explicit trigger condition: 'Use this when you need commonality hooks for outreach' with concrete examples (overlapping past employers, shared schools, mutual volunteer work, common languages). It gives clear when-to-use context but does not name alternative tools or state when not to use it, so it stops short of a 5.

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

scrape_post_commentsA

Scrape and store comments on a LinkedIn post via Apify.

Use this to research who is engaging with a specific post — comments often reveal warm leads, decision-makers, competitor mentions, and pain points.

Args: post_url: Full LinkedIn post URL. Either /posts/_-activity-XXX or /feed/update/urn:li:activity:XXX form is accepted. max_items: Max comments (and replies) to fetch (default 50, capped at 200). include_replies: If True, also fetch nested replies (default True). profile_mode: "short" (free profile data attached to each comment) or "main" ($0.002/profile, more author detail). Default "short".

ParametersJSON Schema
NameRequiredDescriptionDefault
post_urlYes
max_itemsNo
profile_modeNoshort
include_repliesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden. It discloses the persistent 'store' side effect, a hard cap at 200 comments, nested reply behavior, and per-profile costs for profile_mode='main'. It does not mention auth requirements, rate limits, or duplicate handling, but the major behavioral traits are surfaced.

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?

The description is front-loaded with the core purpose, followed by a short motivation sentence, then a structured Args block. Every sentence earns its place and the parameter documentation is tight and readable with no filler.

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?

Given that an output schema exists and all parameters are well documented, the agent has enough to invoke the tool correctly. Missing context is mainly cross-tool: it does not clarify when to use list_comments instead, nor does it note any prerequisite such as Apify credentials or LinkedIn access. These are relevant but not fatal gaps.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must fully compensate. It does: post_url documents both accepted URL formats, max_items documents default and cap, include_replies explains nested replies, and profile_mode explains cost and detail tradeoff. Every parameter receives meaning beyond the raw schema.

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 first sentence names a specific operation and target: 'Scrape and store comments on a LinkedIn post via Apify.' It is clear that this is an external scraping/writing tool, not the same as list_comments. However, it does not explicitly contrast itself with sibling list_comments, so it stops short of top-tier sibling differentiation.

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

Usage Guidelines4/5

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

The description gives a concrete use case: 'Use this to research who is engaging with a specific post' and lists the insight types it supports (warm leads, decision-makers, competitor mentions, pain points). This is clear context for when to invoke it, but it omits explicit 'when not to use this' guidance or alternatives such as list_comments for already-stored data.

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

scrape_profileA

Scrape fresh LinkedIn posts from any company or personal profile URL via Apify and store them in the database. Works for profiles NOT yet in the database.

Use this when the user asks about a LinkedIn account that list_accounts() doesn't return, or when they want up-to-date posts for an existing account.

Requires APIFY_API_TOKEN to be set in the project .env file.

Args: url: Full LinkedIn URL of the company or person to scrape. Examples: https://www.linkedin.com/company/acme-charging https://www.linkedin.com/in/williamhgates max_posts: Maximum number of posts to fetch (default 30, max 100).

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYes
max_postsNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

With no annotations, the description carries the disclosure burden. It reveals that the tool performs an external Apify scrape, writes to the database, and requires APIFY_API_TOKEN in the .env file. It does not discuss rate limits, latency, or whether existing records are overwritten, but the key side effects and prerequisites are disclosed.

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?

The description is tightly organized: purpose sentence, usage guidance, environment requirement, then parameter details. Every sentence earns its place and there is no redundant filler.

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?

It covers purpose, use cases, authentication, and all parameter semantics in a compact form. The only slight ambiguity is the line 'Works for profiles NOT yet in the database' followed by a use case for existing accounts, but the later sentence resolves the intent. An output schema exists, so return-value details are not required.

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

Parameters5/5

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

Schema description coverage is 0%, so the description must compensate. It fully documents url with realistic examples and max_posts with default and maximum values, adding meaning far beyond the raw schema.

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

Purpose5/5

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

The description opens with a specific verb and resource: scrapes fresh LinkedIn posts and stores them in the database. It distinguishes itself from siblings by emphasizing it works for profiles not returned by list_accounts and by targeting posts rather than people or comments.

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

Usage Guidelines4/5

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

It explicitly says when to use the tool: when list_accounts() does not return the account, or when fresh posts are needed for an existing account. It does not name exclusions or alternatives like get_posts/list_posts for reading already-stored posts, so it stops short of full alternative routing.

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

search_postsA

Full-text search across post content (case-insensitive keyword/phrase match).

Returns full content for matched posts only — use for targeted lookups rather than open-ended browsing (use list_posts for that).

Args: query: Word or phrase to search for in post text. account: Slug or full URL to restrict search to one account (optional). days_ago: Only search posts from the last N days (0 = no limit). limit: Max results (default 15, max 50).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
queryYes
accountNo
days_agoNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior4/5

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

With no annotations provided, the description carries the behavioral burden. It discloses case-insensitive matching, that only matched posts' full content is returned, and that it is best for targeted lookups. While it could mention ordering or pagination, it still gives meaningful behavioral context well beyond a bare verb.

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?

Every sentence earns its place. The purpose is front-loaded, the usage distinction follows immediately, and the parameter list is compact yet complete. No filler or redundant restatement of schema titles.

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

Completeness5/5

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

The description covers purpose, usage boundaries, edge interpretations of parameters, and result scope. An output schema exists to describe the return structure, and the description itself is sufficient for an agent to select and invoke this tool correctly among many siblings.

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

Parameters5/5

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

The input schema has 0% description coverage, but the description manually explains every parameter: query as word/phrase, account as slug or full URL, days_ago with '0 = no limit', and limit with default/max values. This fully compensates for the empty schema descriptions.

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

Purpose5/5

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

The description opens with a specific verb and resource: 'Full-text search across post content (case-insensitive keyword/phrase match).' It clearly identifies what the tool does and remains distinguishable from sibling tools such as list_posts and get_posts.

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

Usage Guidelines5/5

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

Explicitly routes the agent: 'use for targeted lookups rather than open-ended browsing (use list_posts for that).' This names the alternative and states the deciding condition, leaving no ambiguity about when this tool is appropriate.

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

update_memoryA

Rewrite a memory file. ONLY call this after the user has approved the proposed content (the insaight-reflect skill shows a draft first — never overwrite memory silently).

Args: kind: "style" or "playbook". content: The full new Markdown content of the file (not a diff). mark_reflection_done: Set True on the LAST update of a reflection run — resets the outcomes-since-reflection counter.

ParametersJSON Schema
NameRequiredDescriptionDefault
kindYes
contentYes
mark_reflection_doneNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior4/5

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

With no annotations, the description carries the full behavioral burden. It discloses that the tool replaces the entire file ('full new Markdown content', 'not a diff') and that setting mark_reflection_done resets the outcomes-since-reflection counter. It could add more about response or failure behavior, but the output schema covers return details.

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?

The description is compact and front-loads the critical approval gate before the parameter list. Each line earns its place, and the arg formatting is easy to scan.

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

Completeness5/5

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

For a 3-parameter mutation tool with no annotations, this description covers all operational essentials: the approval precondition, the full-overwrite semantics, the meaning of each parameter, and the reflection-counter side effect. The output schema handles return-value expectations, so nothing critical is missing.

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

Parameters5/5

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

Schema description coverage is 0%, so the description fully compensates. It explains allowed values for kind, clarifies that content must be the complete file rather than a diff, and gives the precise condition for mark_reflection_done. This is substantially more informative than the bare schema.

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

Purpose5/5

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

The description opens with a clear verb and resource, 'Rewrite a memory file', which immediately distinguishes it from read-oriented siblings like get_memory. The args further specify that kind selects 'style' or 'playbook', making the exact target explicit.

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

Usage Guidelines5/5

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

The description gives explicit when and when-not guidance: call only after the user approves the draft shown by the insaight-reflect skill, and never overwrite memory silently. This is strong enough for an agent to know exactly when the tool is appropriate, even though no alternative write tool is named.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 18 tool updatesv0.1.0
    • First observedget_config
    • First observedget_memory
    • First observedget_outreach_stats
    • First observedget_posts
    • First observedget_stats
    • First observedlist_accounts
    • First observedlist_comments
    • First observedlist_outreach
    • First observedlist_people
    • First observedlist_posts
    • First observedlog_outreach
    • First observedrecord_outcome
    • First observedscrape_people
    • First observedscrape_person_profile
    • First observedscrape_post_comments
    • First observedscrape_profile
    • First observedsearch_posts
    • First observedupdate_memory

TDQS

A4.3/5.0

Scored across 18 tools

Disambiguation4/5

Each major workflow—accounts, posts, people, comments, outreach, and memory—has mostly distinct tools with clear descriptions. The main risk is scrape_profile versus scrape_person_profile, since both mention profiles, and get_stats versus get_outreach_stats could cause momentary confusion, though their descriptions disambiguate them well.

Naming Consistency4/5

Tool names follow a consistent snake_case verb_noun pattern with list_* for reading stored data, scrape_* for fetching fresh data, and get_* for direct retrieval. The pair scrape_profile/scrape_person_profile is slightly confusing because 'profile' is used to mean both a LinkedIn account's posts and an individual person's full profile, but overall the naming is predictable.

Tool Count4/5

Eighteen tools is on the heavier side, but the server genuinely covers multiple related domains: LinkedIn post scraping, people research, comment scraping, outreach tracking, memory, and configuration. Each tool has a distinct job, so the count feels reasonable for the stated scope rather than padded.

Completeness4/5

The core lifecycle is well covered: discover accounts, scrape and read posts, search content, scrape people and comments, log outreach, record outcomes, and update memory. Minor gaps include no delete/edit path for accounts, people, or outreach records, and no direct get-person-by-URL tool for retrieving enriched profile details after scrape_person_profile.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Connects Claude Desktop to LinkedIn's data layer for AI-powered networking, enabling profile research, content creation and scheduling, engagement automation, analytics tracking, and messaging through natural language.
    14
    85
    41
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables B2B prospecting from natural language: detect buying signals, score leads against ICP, enrich decision-makers, and draft personalized outreach messages via Claude.
    2
    MIT
  • F
    license
    A
    quality
    B
    maintenance
    Outbound sales agent for Claude Code. MCP server handles prospect list building, dedup, quotas, and structured rejection feedback, while the plugin runs per-prospect research, email writing, Gmail sending, and reply tracking. Open source, self-hostable.
    55
    3
    -