Skip to main content
Glama

Query People

query_people
Read-only

Columns: id, display_name, title, headline, company, location, summary, linkedin_url, linkedin_provider_id, email, connections_count, follower_count, is_open_profile, is_premium, work_experience (JSONB), education (JSONB), company_profile_id, owner_email, data (JSONB), created_at, updated_at. company_profile_id is the person's canonical employer FK (NULL when unresolved). Sliq's CRM is deals and tasks: to see whether someone has a deal or a task, use query_deals (status='all') / query_crm_tasks with person_id. connections_count / follower_count are NULL when never fetched (not 0); is_open_profile / is_premium are NULL likewise. JSONB queries: data->>'some_key' ILIKE '%...%'.

work_experience and education are the person's full LinkedIn employment and education history — the same arrays enrich_linkedin_profiles returns, already stored on the person from the last profile lookup, so reading them here costs nothing (answer "where did they go to school", "are they an LSU alum", "how long in seat" from these instead of a fresh enrich). Each is a list; an empty list means it was never captured for that person. They arrive in LinkedIn display order (NOT sorted by date). These arrays are large for senior people — a broad limit=200 read that returns them can exceed the 50KB direct-return cap and truncate; for a wide pull, either narrow the where_clause or call this from run_code (nothing truncates there) and print only the fields you need.

To list the outreach prospects tracking a person, take an id from here and call query_prospects with where_clause="person_id = <id>".

Each row also carries segments: the person's segment tags across every segment group they're classified into — [{group_id, group_name, tag}], tag 'No match' where the classifier couldn't place them (empty when no group has classified them). Segments are the LLM-defined people dimensions from the Explore Segments surface (e.g. Seniority -> VP); manage them with the segment tools (list_segment_groups etc.).

Pass group_by for per-bucket counts over ALL your people instead of a row list — a whole-set aggregate, never capped at the 200-row limit, so it answers "how many people per " without paging. outreach_stage buckets each person by their most-advanced lead-funnel stage across every campaign; segment buckets each person by their tag in one segment group (pass that group's id as segment_group_id). Both ignore where_clause. In row mode (group_by omitted) — a dict with count, truncated, and items array (each row {id, display_name, title, headline, company, location, summary, linkedin_url, linkedin_provider_id, email, connections_count, follower_count, is_open_profile, is_premium, work_experience, education, company_profile_id, owner_email, segments: [{group_id, group_name, tag}], data, created_at, updated_at}). In aggregate mode (group_by set) — a dict {group_by, groups} where groups is a list of {key, count} ordered by count descending; for "segment" the keys are tag names, 'No match' for people the classifier couldn't place, and '' for people the group hasn't classified.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNoMax results (default 50, capped at 200).
offsetNoRows to skip for paging (default 0). When the result is truncated, re-call with offset += limit for the next page.
group_byNoAggregate mode, returned instead of the row list — whole-set per-bucket counts over all your people (not capped by `limit`). "title" / "company" / "location" bucket by that column's value; "outreach_stage" by the person's collapsed lead-funnel bucket; "segment" by the person's tag in the `segment_group_id` group. Omit for the row list.
order_byNoSQL ORDER BY (default: created_at DESC).created_at DESC
where_clauseNoSQL WHERE condition (default: all your people). Examples: "display_name ILIKE '%chen%'", "title ILIKE '%VP%'", "company_profile_id = 42", "linkedin_url = 'some-slug'".1=1
segment_group_idNoRequired with group_by="segment" — the segment group (from list_segment_groups) to bucket by. Ignored otherwise.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / group_by / description
      Previous value: -"Aggregate mode, returned instead of the row list — whole-set per-bucket counts\nover all your people (not capped by `limit`). \"title\" / \"company\" / \"location\" bucket\nby that firmographic — \"title\" falls back to the headline when the title is blank, so\nlist a title bucket's people with \"COALESCE(NULLIF(title, ''), headline) = '<key>'\";\n\"outreach_stage\" by the person's collapsed lead-funnel bucket;\n\"segment\" by the person's tag in the `segment_group_id` group. Omit for the row list."New value: +"Aggregate mode, returned instead of the row list — whole-set per-bucket counts\nover all your people (not capped by `limit`). \"title\" / \"company\" / \"location\" bucket\nby that column's value; \"outreach_stage\" by the person's collapsed lead-funnel bucket;\n\"segment\" by the person's tag in the `segment_group_id` group. Omit for the row list."
  2. Changed1 schema field changed
    • changedInput schema / properties / group_by / description
      Previous value: -"Aggregate mode, returned instead of the row list — whole-set per-bucket counts\nover all your people (not capped by `limit`). \"title\" / \"company\" / \"location\" bucket\nby that firmographic; \"outreach_stage\" by the person's collapsed lead-funnel bucket;\n\"segment\" by the person's tag in the `segment_group_id` group. Omit for the row list."New value: +"Aggregate mode, returned instead of the row list — whole-set per-bucket counts\nover all your people (not capped by `limit`). \"title\" / \"company\" / \"location\" bucket\nby that firmographic — \"title\" falls back to the headline when the title is blank, so\nlist a title bucket's people with \"COALESCE(NULLIF(title, ''), headline) = '<key>'\";\n\"outreach_stage\" by the person's collapsed lead-funnel bucket;\n\"segment\" by the person's tag in the `segment_group_id` group. Omit for the row list."
  3. Changed3 schema fields changed
    • changedInput schema / properties / group_by / anyOf
      Previous value: -[
      -  {
      -    "enum": [
      -      "title",
      -      "company",
      -      "location",
      -      "outreach_stage"
      -    ],
      -    "type": "string"
      -  },
      -  {
      -    "type": "null"
      -  }
      -]New value: +[
      +  {
      +    "enum": [
      +      "title",
      +      "company",
      +      "location",
      +      "outreach_stage",
      +      "segment"
      +    ],
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • changedInput schema / properties / group_by / description
      Previous value: -"Aggregate mode, returned instead of the row list — whole-set per-bucket counts\nover all your people (not capped by `limit`). \"title\" / \"company\" / \"location\" bucket\nby that firmographic; \"outreach_stage\" by the person's collapsed lead-funnel bucket.\nOmit for the row list."New value: +"Aggregate mode, returned instead of the row list — whole-set per-bucket counts\nover all your people (not capped by `limit`). \"title\" / \"company\" / \"location\" bucket\nby that firmographic; \"outreach_stage\" by the person's collapsed lead-funnel bucket;\n\"segment\" by the person's tag in the `segment_group_id` group. Omit for the row list."
    • addedInput schema / properties / segment_group_id
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Required with group_by=\"segment\" — the segment group (from\nlist_segment_groups) to bucket by. Ignored otherwise."
      +}
  4. Changed1 schema field changed
    • addedInput schema / properties / group_by
      Added value: +{
      +  "anyOf": [
      +    {
      +      "enum": [
      +        "title",
      +        "company",
      +        "location",
      +        "outreach_stage"
      +      ],
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "default": null,
      +  "description": "Aggregate mode, returned instead of the row list — whole-set per-bucket counts\nover all your people (not capped by `limit`). \"title\" / \"company\" / \"location\" bucket\nby that firmographic; \"outreach_stage\" by the person's collapsed lead-funnel bucket.\nOmit for the row list."
      +}
  5. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Goes well beyond readOnlyHint=true: documents the 50KB direct-return cap and truncation behavior with the run_code workaround, NULL-vs-0 semantics for counts/flags, JSONB query syntax, work_experience/education provenance and display-order caveats, and that group_by is an uncapped whole-set aggregate. This is unusually rich behavioral context.

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 summary is front-loaded with the core purpose before the detailed column list and modes. It is long, but for a 6-param tool with two operating modes most sentences carry load; minor density from the full column enumeration keeps it from a 5.

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?

Covers columns, return shapes for both row and aggregate modes (embedded returns block), truncation/limit behavior, and cross-tool joins. Nothing an agent needs to invoke it correctly is missing, despite no formal output schema.

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 coverage is 100%, so the schema already carries per-parameter meaning (baseline 3). The description adds real value on top by explaining group_by aggregate vs row mode, that segment_group_id is required for group_by="segment", and that both aggregate modes ignore where_clause.

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?

States a specific verb and resource ('Query your canonical people (`person_profiles`) — one deduped row per real person') and immediately distinguishes the entity from the sibling it could be confused with. An agent can tell it apart from query_prospects (per-owner tracking rows) without opening either schema.

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?

Provides explicit routing: use this for person-level questions, use query_prospects for outreach progress, query_deals/query_crm_tasks for CRM relations, and query_prospects with where_clause="person_id = <id>" to list tracking rows. Includes concrete example queries ('people who are VPs at fintech companies').

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