Gem
Analyze and manage Gem data
- Category
- HR & Recruiting
- Primary Subcategory
- Applicant Tracking & Recruiting Workflow
Integration details
Description
Connect Gem with ChatGPT to bring your recruiting data to where you work. With the Gem MCP, you can query hiring analytics, pull applications, rediscover past talent, and take bulk actions in natural language.
- Integration type
- Plugin
- Verification status
- Not applicable
- Platform
- ChatGPT
- Primary Subcategory
- Applicant Tracking & Recruiting Workflow
- Secondary Subcategories
- None listed
- Brand
- Gem
- Access
- Account required
- First tracked
- 2026-08-18
- Tool count
- 32
- Geography
- US
The Primary Subcategory used for this profile’s headline score.
Other Subcategories where the Integration is listed.
ChatGPT Plugin Discovery Score
ChatGPT Plugin discovery is coming soon
ChatGPT can surface a Plugin when it matches a user's request.Your Plugin Discovery Score measures how often yours appears.
No spam. Unsubscribe any time.
What discovery looks like

Competing in ChatGPT Applicant Tracking & Recruiting Workflow
View Category32 tools agents can invoke
Add a note to a person's activity feed. Pass `person_ext_id` (e.g. from `search`, `search_people`, or `get_person`) and the note `content`. `content` is plain text by default; set `content_format='html'` to pass sanitized rich formatting (`<p>`, `<br>`, `<b>`, `<ul>`/`<li>`, `<a href>`). To @-mention a teammate, put an `@[user_id]` token (the `user_id` from `search_users`) inline in `content` — they're notified and start following the person. A visible note can also notify teammates who follow the person and, for eligible Greenhouse teams, sync to the ATS activity feed. Returns the person's `ext_id` and the new note's `ext_id`.
add_note_to_person
Add candidates to or remove them from an existing project. Pass the project's `project_ext_id` (e.g. from `search` or `get_project`) plus `add_person_ext_ids` and/or `remove_person_ext_ids` (person ext_ids from `search`, `search_people`, or `get_person`). Returns the `project_ext_id`, how many were `added` and `removed`, and the `skipped` ext_ids. Use `save_project` to create the project itself or edit its name/description.
edit_project_enrollment
Archive an existing project, or restore an archived one. Pass the project's `project_ext_id` (e.g. from `search` or `get_project`); `archived` defaults to true to archive. This is reversible — call again with `archived=false` to unarchive and restore the project. Returns the `project_ext_id` and the project's new `is_archived` state. Archiving hides the project from active views but does not delete it or its candidates.
archive_project
Archive an outreach sequence template, or unarchive it to restore it (pass `archived=false`). Only sequence templates can be archived — not drafts or individual sequence instances. Archiving is reversible. Consider `get_sequence` first to see how many people are still actively enrolled. Returns the sequence's `ext_id` and its resulting `is_archived` state.
archive_sequence
Create a new analytics dashboard or edit an existing one's metadata — name, description, emoji, visibility ('PUBLIC' for the whole team or 'PRIVATE' for owner + link), date_range (the relative time window it opens in, e.g. 'last_90_days'), and `filter_terms` (a JSON-string array of dashboard-wide filters applied to every widget; pass query_metrics-style {dimension_id, ids} terms and they're converted to the stored form on save, like save_widget's filter_terms). Omit `dashboard_ext_id` to create a fresh dashboard (new ones default to PUBLIC and the last 90 days); pass one — e.g. an ext_id from `search` — to update, and only the fields you include change. Returns the dashboard's `ext_id`, `name`, and a `created` flag (true when a new dashboard was made). This sets up the dashboard shell only; it does not add or configure widgets.
save_dashboard
Create a new sourcing project or edit an existing one's metadata (name, description, privacy). Omit `project_ext_id` to create; pass it to update. Returns the project's `ext_id`, `name`, `privacy_type`, and a `created` flag. Sets up the project shell only; it does not add or remove candidates.
save_project
Create a new outreach sequence or rename an existing one. Omit `sequence_ext_id` to create a fresh sequence (set `is_template` to make it a reusable template); pass one — e.g. an ext_id from `search` — to rename that sequence. Returns the sequence's `ext_id`, `name`, and a `created` flag (true when a new sequence was made). This sets up the sequence shell only; it does not add or edit outreach stages or recipients.
save_sequence
Create a chart widget on a dashboard, or edit an existing one. Core config is title, metric, visualization, time_granularity, and aggregation_type; breakdowns go in group_breakdown_types and stage_types_and_names, and outreach metrics use outreach_breakdown / outreach_group_by / outreach_activities — each field's accepted values are documented on the field. filter_terms and outreach_filter_terms accept query_metrics-style {dimension_id, ids} terms (as in get_widget's query_metrics.filters) and convert them to the stored dashboard format on save; visualization_options is a JSON-string object of chart options. `[]`/`{}` clears any of them. Specialized modes: text_content for a TEXT widget, benchmark_statistic_type + benchmark_categories for an industry-standard overlay, the passthrough_* fields for a PASSTHROUGH_RATE / TIME_IN_STAGE cohort, and outreach_funnel_stages for a CANDIDATE_COHORTS_* widget. Size and arrange the widget with `width` (1/2/3 columns or "max" for full-bleed), `height` (row span), and `position` (0-based slot among the dashboard's widgets); new widgets otherwise append in creation order at a default size, and `get_dashboard` reports each widget's current size and order. Omit `widget_ext_id` and pass `dashboard_ext_id` (e.g. from `search` or `save_dashboard`) to create; pass `widget_ext_id` to update, and only the fields you include change. Returns the widget's `ext_id`, its `dashboard_ext_id`, and a `created` flag.
save_widget
Permanently delete a widget from its dashboard. The widget is removed immediately and cannot be recovered. Returns the deleted widget's `ext_id` and `deleted=true`.
delete_widget
Enroll people into an existing outreach sequence and/or unenroll them. Pass `sequence_ext_id` (owned by the current user) plus `add_person_ext_ids` and/or `remove_person_ext_ids` (person ext_ids, e.g. from `search` or `search_people`). Returns how many were newly `added`, how many `removed`, a `skipped` list pairing each person NOT acted on with the `reason`, and any `warnings` about the people who were. Enrolling into a reusable template copies it into a new sequence, so the returned `sequence_ext_id` may differ from the one passed in. Use `save_sequence` first to create the sequence shell.
edit_sequence_enrollment
Edit one outreach stage (an email/message step) of a sequence owned by the current user — its `subject`, `body_html` (rich-text body), `stage_type`, and `wait_days` — addressed by `index` (use N+1 to append a new follow-up). Pass the `version` from `get_sequence`: the edit is rejected if the sequence changed since you read it, and a successful edit returns the new `version` to chain the next edit. An unknown merge token is rejected; text that only looks suspect comes back in `warnings`. Returns the affected `index`, a `created` flag, the new `version`, and any `warnings`. Use `save_sequence` to create the sequence first, and `get_sequence` to read the stages and current version.
edit_sequence_stages
Look up one application (a candidate on a specific job) by ext_id — status, stage, stage_entry, `gem_status` (the Talent Pipeline's computed next-step status and SLA health, e.g. NEEDS_DECISION / MISSED_TARGET; null for closed applications and for ATSes without support), source, job ref, rejection (its `reason_type` says whether we rejected them or they declined), and form answers: the full evaluation record behind an application. Get an ext_id from a person's applications (`get_person`) or from `search_applications`. Use `fields` for interviewer scorecards and the offer. The response is `{found, entity}` — check `found` before reading `entity`; a missing row and a no-access row both return `found: false`.
get_application
Look up one dashboard by ext_id — name, owner, link, and its `widgets` in display order. Each widget lists the metric it reports and how it's sliced (metric, visualization, stages, breakdowns, time granularity) plus its grid size — `width` ("1"/"2"/"3" columns or "max" for full-bleed) and `height` (row span), both settable back via `save_widget`. Use it to see what a dashboard tracks and how it's laid out, then call `query_metrics` to compute those numbers. A dashboard's `ext_id` is what `search` (kind=dashboard) returns, and the id in a gem.com `/dashboard/<ext_id>` URL. The response is `{found, entity}` — check `found` before reading `entity`; a missing row and a no-access row both return `found: false`.
get_dashboard
Look up one job by ext_id — title, status, requisition id, ATS, department/office, and link. Cross-ATS. For Gem ATS jobs also returns `openings` ({ext_id, name} → get_opening) and the pipeline `stages` ({ext_id, name, index} → search_applications's stage_ids). Use `fields` for the job's custom fields and/or its `job_posts` (posting descriptions). A job's `ext_id` is what `search` / `search_jobs` return, and the id in a gem.com `/ats/jobs/<ext_id>` URL. The response is `{found, entity}` — check `found` before reading `entity`; a missing row and a no-access row both return `found: false`.
get_job
Look up one opening (headcount/requisition) by ext_id — name, status, hire type, department, locations, job levels, associated jobs, target dates, and link. Use `fields` for its custom fields. **Gem ATS only:** other ATSes return `found: false`. ext_id is an opening id, e.g. from a gem.com URL `/ats/openings/<ext_id>`. The response is `{found, entity}` — check `found` before reading `entity`; a missing row and a no-access row both return `found: false`.
get_opening
Look up one candidate by ext_id — name, current title, company, school, emails, phone numbers, and links, plus optional `fields` (full work history, education, custom fields, applications, activity timeline, sequence responses, and resumes — presigned download URLs valid for 7 days for the candidate's resume files, including the LinkedIn PDF imported at sourcing time). Feed an application's ext_id into get_application for its scorecards. A candidate's `ext_id` is what `search` (kind=person) and `search_people` return, and the id in a gem.com `/candidate/<ext_id>` URL. The response is `{found, entity}` — check `found` before reading `entity`; a missing row and a no-access row both return `found: false`.
get_person
Look up one project by ext_id — name, description, owner, link, type, privacy, archived status, and people_count (candidates in the project). Use `fields` for its custom fields and/or its `people` (the candidates in the project). A project's `ext_id` is what `search` (kind=project) returns, and the id after `--` in a gem.com `/projects/--<ext_id>` URL. The response is `{found, entity}` — check `found` before reading `entity`; a missing row and a no-access row both return `found: false`.
get_project
Look up one saved analytics report (Pipeline Analytics or Outreach) by ext_id — its name, type, owner, link, and a ready-to-run `query_metrics` payload translated from the report's saved configuration. Run that payload through `query_metrics` to reproduce the report's numbers. For Outreach reports the payload's metrics are the standard activity/cohort family (the report may display a subset). Check `fully_reproducible`/`caveats`: when false, the report uses a knob query_metrics can't express and the payload is a best-effort approximation. A saved report's `ext_id` is the `reportId` in a gem.com analytics report URL (e.g. `/pipeline-stats?reportId=<ext_id>` or `/outreach-stats?reportId=<ext_id>`). The response is `{found, entity}` — check `found` before reading `entity`; a missing row and a no-access row both return `found: false`.
get_saved_report
Look up one outreach sequence by ext_id — name, status, whether it is a reusable template (`is_template`) and whether it is archived (`is_archived`), owner, link, a `version` (the sequence's edit version — pass it to `edit_sequence_stages`, which rejects edits made against a stale version), and its ordered `stages` (index, stage_type channel, subject, body as plain text, and days_after cadence). Pass `fields` for two opt-in sections: `enrollment` — its recipients with each one's current stage, next send time, reply status, and stop reason (capped, with the full `total`); and `personalization` — the per-person AI `{gem_ai:}` values with a `reviewed` status (capped, with the full `total`), where `reviewed=false` means the value has not yet been approved to send. A sequence's `ext_id` is what `search` (kind=sequence) returns, and the id in a gem.com `/sequence/<ext_id>` URL. The response is `{found, entity}` — check `found` before reading `entity`; a missing row and a no-access row both return `found: false`.
get_sequence
List the merge tokens available for writing a sequence stage's subject or body on this team. Call this before authoring a stage so you know which {{tokens}} you can use. Each token's `key` is the field name that goes inside the braces (write {{first_name}} to insert the candidate's first name), with a human `label` and a `category`: Person (the candidate's profile), Custom (the team's custom person fields), Computed (filled at send time, e.g. day_of_week), Job (recruiter_name, only when the team has a connected ATS), and AI, listed only when Gem AI is enabled for the team — a freeform per-person token: write {{gem_ai: <your instruction>}} in the body, then set each person's value with set_sequence_personalization (not pulled from a fixed field). Feed the keys into `edit_sequence_stages`.
get_sequence_tokens
List the current user's actionable to-dos: their upcoming scheduled interviews ('what interviews do I have this week?') and the scorecards they still owe. Pass `kind` ('interview' or 'scorecard') to filter, or omit for both; soonest first. Each task carries a `title`, `gem_link`, the `candidate` and `job`, and an `application_ext_id` to feed into `get_application`. Interview tasks also carry `location`, `duration_minutes`, `video_conferencing_url` (present only when Gem created the meeting), and `interviewers` — the full panel with each one's name, email, and response_status. Scorecard tasks also include the `questions` to fill out (each with text, answer_type, options, and whether it's required). This is the 'what's on my plate' tool — it needs no candidate or job id.
get_tasks
Look up one dashboard widget by ext_id (a widget_id from get_dashboard) — its title, visualization, metric, parent dashboard, and a ready-to-run `query_metrics` payload translated from the widget's saved configuration. Run that payload through `query_metrics` to reproduce the widget's numbers. For Outreach widgets the payload's metrics are the standard activity/cohort family (the widget may display a subset). Check `fully_reproducible`/`caveats`: when false, the widget uses a knob query_metrics can't express and the payload is a best-effort approximation. TEXT widgets have no metric; they return `text_content`, the full authored body as HTML. get_dashboard carries only a truncated `content_preview`, so read the body here and pass it back as `save_widget`'s `text_content` when copying a dashboard. The response is `{found, entity}` — check `found` before reading `entity`; a missing row and a no-access row both return `found: false`.
get_widget
Quick cross-type lookup of a Gem entity by name or keyword — people, projects, sequences, dashboards, or jobs. Start here when the user names something: it's the fastest way to turn that name into an ext_id, which you then feed into the get tool for that kind (person→get_person, project→get_project, sequence→get_sequence, dashboard→get_dashboard, job→get_job) or use as a filter elsewhere. Returns lightweight stubs (ext_id, display_name, gem_link). To find candidates by attribute (title, skills, location, pipeline) use search_people instead; for counts, rates, or trends use query_metrics.
search
List the metrics and dimensions this team can report on with `query_metrics`. Call this first to get valid metric and dimension ids. Returns groups of co-queryable metrics: metrics in the same group share a data source, so they can be combined in one `query_metrics` call and grouped or filtered by that group's dimensions, while metrics from different groups need separate calls. Each metric carries its id, unit, and valid aggregations; each dimension marks whether it's filterable or group-by only. Groups flagged `requires_date_range` take a `date_range` from the returned `date_ranges`. Also returns `pipeline_stages` — the team's normalized stages in order, each with an `id` (the STAGE_TYPE:name string) for query_metrics's `stages` / `exclude_stages` / `cohort_entry_stage` and a `name` for search_people's `ats_pipeline_stage` — and `widget_metrics`, the separate `metric` vocabulary save_widget accepts, each mapped to the query_metrics id it corresponds to. Pass `groups` to slim a large catalog to just the areas you need.
get_metrics_catalog
Run a recruiting-analytics query and get back an aggregated `{columns, rows}` table. Use this for reporting and any 'how many / what rate / trend over time' question — pipeline health, pass-through, time-in-stage, outreach, offers, hires. Call `get_metrics_catalog` first for the metric and dimension ids this team can use; all metrics in one call must come from the same catalog group, and Pipeline Analytics accepts only one metric per query (request candidates / time-in-stage / pass-through separately).
query_metrics
List the candidates in one job's pipeline. Requires `job_id` — a job ext_id from `search` or `get_job`. Returns shallow application summaries (ext_id, status, stage, stage_id, stage_entry, `gem_status` — the Talent Pipeline's computed next-step status and SLA health `{status, sla_status, associated_ts_ms}` for open applications; null for closed ones and for ATSes without support — candidate name/email/location with a get_person-compatible ext_id when person-linked, applied/closed dates, rejection, `gem_link`, and `candidate_tags`), newest first; active applications only by default — set `include_rejected` / `include_hired` to widen, or `stage_ids` to filter to stages. Filter by `application_statuses` (e.g. SCHEDULED, NEEDS_DECISION), `sla_statuses` (`["MISSED_TARGET"]` = stalled past the team's SLA target, auto-excluding already-scheduled candidates), or `candidate_tags` (whole tag names, case-insensitive; every result carries its own tags, so an unfiltered call shows which ones the job uses); with these filters `total_count` counts only matching applications. Page with `limit`/`offset` while `has_next_page` is true. Feed an ext_id into `get_application` for scorecards, the offer, and form answers. For candidates across many jobs use `search_people`; for pipeline counts use `query_metrics`.
search_applications
Find jobs by criteria — turn a job name or req id into the ext_id other tools take, or browse a team's jobs. `query` matches job title and requisition id; omit it to list all open jobs, and filter by department or office (each with a recursive variant covering sub-departments / child locations), or set `following` to return only jobs you follow. Returns shallow job stubs (ext_id, title, status, requisition_id, department, offices, gem_link), best match first; page with `limit`/`offset` while `has_next_page` is true. Feed an ext_id into `get_job` for the full record or `search_applications` for that job's candidates; for job counts or rates use `query_metrics`.
search_jobs
Find candidates by attribute across CRM and ATS — title, company, skills, location, years of experience, pipeline stage, scorecards, and contact recency. Filters combine with AND; page with `page` while `has_next_page` is true. By default returns only candidates not in an active pipeline and not yet hired (available for fresh outreach) — set `include_open_applications` to widen. Feed a result's ext_id into `get_person`. The result also carries a top-level `gem_link`, a shareable gem.com link that reopens the whole search in Gem's UI. Use `search` if you already know the person's name, or `query_metrics` to count or aggregate instead of paging here.
search_people
Resolve a teammate to their ATS ID (used for analytics queries and filters that rely on it) and Gem ID (used for tagging in notes). Search by name or email. Each hit returns `display_name`, `email`, `user_ats_id`, and `user_id`.
search_users
Set per-person AI personalization values for a sequence's `{{gem_ai: <prompt>}}` tokens — the custom text each recipient sees in place of a token. Pass `sequence_ext_id` (owned by the current user) and `personalizations`, a list of `{person_ext_id, prompt, value}` where `prompt` matches a `{{gem_ai: <prompt>}}` token placed in a stage body via `edit_sequence_stages`. Returns how many were `set` and a `skipped` list. Every value is stored UNREVIEWED — it does not send until a human reviews and approves it.
set_sequence_personalization
Send feedback about these Gem tools to the team at Gem that builds them — a bug, a missing capability, or confusing behavior. Say what you were trying to do and what went wrong; don't include candidate names or other personal data. Use only when the user explicitly asks to send feedback or report a problem to Gem.
submit_mcp_feedback
Return the Gem user this session is authenticated as: user_id, team, email, client id, and the team's ATS (e.g. 'Gem ATS', 'Greenhouse'). Use it to confirm whose data the other tools read, or to resolve who "me" / "my team" is before a filtered search or task lookup.
whoami
How do I improve a ChatGPT Plugin's discoverability?
The levers are the listing surface agents actually read: names, descriptions, keywords, tool metadata, and registry health. Which lever matters depends on where discovery breaks, which is what continuous measurement shows.
What are Gem alternatives on ChatGPT?
As of 2026-09-11, Gem competes with 100Hires ATS, Ashby, Candidate Time Extractor, Dover, Intevie, Manatal, Recooty, Recruta, Ribbon, Teamtailor, Workable MCP Server in ChatGPT Applicant Tracking & Recruiting Workflow, ranked by public Discoverability Score.
Where is this profile measured?
This profile uses the geography attached to the latest public registry snapshot: US. Locale tags are intentionally omitted.