> ## Documentation Index
> Fetch the complete documentation index at: https://docs.particle.pro/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> What's new on the Particle Pro MCP server — new tools and capabilities, and anything that changes how your agent connects or calls.

Tool *behavior* grows additively — new `include` sections and modes never break an existing call. Renames and changes that could affect your integration are called out explicitly.

## September 2026

### Pay per request with x402 — keyless `POST /mcp`

A keyless `POST` to the MCP endpoint now returns `402` with two challenges instead of a bare `401`: the x402 payment requirements in `PAYMENT-REQUIRED` (a flat \$0.01 in USDC on Base per HTTP request) and the usual `WWW-Authenticate: Bearer … resource_metadata="…"` pointer for OAuth clients. An agent with a funded wallet can pay per request and call any payable read-only tool without an account (project-scoped tools such as the `particle_alert_*` family still need a credential); a paid request skips the bearer requirement and is served exactly as a keyed one. OAuth and API-key traffic is unchanged — any presented credential takes the normal auth path. See [Pay per request with x402](/x402).

### Related episodes — `particle_podcast_list_related_episodes`

A new standard-tier [`particle_podcast_list_related_episodes`](/mcp/tools/podcasts/podcast-list-related-episodes) answers "who else covered this": episodes from other shows on the same story or subject as an episode, best first, each with a `score`, a `band`, and — with `include: ["basis"]` — the shared entities, topics, news story, guests and days apart. `published_within_days` narrows to a recency window and `same_podcast` opts the source show in. Not a topic search (`particle_podcast_search_transcripts`) or a mention list (`particle_podcast_find_mentions`). The REST counterpart is [`GET /v1/podcasts/episodes/{id}/related`](/podcasts/related-episodes).

### Related podcasts — `particle_podcast_list_related` and `include: ["related"]`

A new standard-tier [`particle_podcast_list_related`](/mcp/tools/podcasts/podcast-list-related) answers "shows like this show": the shows most related to a podcast, best first, each with a calibrated `score`, a `band` (`strong` / `moderate` / `weak`) to branch on, and — with `include: ["basis"]` — the signals behind the pairing (content similarity of recent episodes, shared topics, named shared guests, same publisher, shared sponsors). Related sets are precomputed per show and restricted to its language; a show whose set has not landed yet returns an empty list rather than an error. [`particle_podcast_resolve`](/mcp/tools/podcasts/podcast-resolve) gains `include: ["related"]` for the five most related shows inline. Slugs are edges as always: every related show feeds the podcast tools, and the people and topics in the basis feed the guest and resolve tools. The REST counterpart is [`GET /v1/podcasts/{id}/related`](/podcasts/related).

### Sponsor prospecting — `include: ["recommended_sponsors"]` on `particle_podcast_resolve`

[`particle_podcast_resolve`](/mcp/tools/podcasts/podcast-resolve) takes `include: ["recommended_sponsors"]` (premium-grade) to attach the five advertisers a show could pitch: sponsors that run on its related shows but not on it, each with the linked company, a score, a band, how many related shows run it, its ads and most recent ad across them, and which shows. The paged form is [`GET /v1/podcasts/{id}/recommendations/sponsors`](/podcasts/advertising#sponsors-a-podcast-could-pitch).

### Guest recommendations and inline related episodes — new `include` values

Three of the get/resolve tools gain an inline section, so the common follow-up needs no second call: [`particle_podcast_get_episode`](/mcp/tools/podcasts/podcast-get-episode) takes `include: ["related"]` for the five episodes from other shows most related to the one you have; [`particle_podcast_get_guest`](/mcp/tools/podcast_guests/podcast-get-guest) takes `include: ["recommended_podcasts"]` for the five shows a person could plausibly appear on next — shows related to the ones they have guested on, minus those, with the venues behind each pick (the pitch list); and [`particle_podcast_resolve`](/mcp/tools/podcasts/podcast-resolve) takes `include: ["recommended_guests"]` for the five guests a show could book that it hasn't — people booked by its related shows, with how many and which (the booking pipeline). Each section is present even when empty, with a note saying why, so an honoured-but-empty include is distinguishable from one not requested. The paged REST forms are [`GET /v1/podcasts/guests/{id}/recommendations/podcasts`](/podcasts/guests#recommended-podcasts-for-a-guest) and [`GET /v1/podcasts/{id}/recommendations/guests`](/podcasts/guests#recommended-guests-for-a-podcast).

**Include values are now validated on these three tools.** An unknown value in `include` on `particle_podcast_resolve`, `particle_podcast_get_episode` or `particle_podcast_get_guest` returns an `invalid_parameter` error naming the accepted values, where it was previously ignored. Calls that pass documented values are unaffected.

### Segments carry transcript line ranges, and the tiling claim is corrected

Segments now report `start_line` and `end_line` — 1-indexed inclusive transcript line
numbers — on [`particle_podcast_get_episode`](/mcp/tools/podcasts/podcast-get-episode) with
`include: ["segments"]`, and on `GET /v1/podcasts/episodes/{id}/segments`,
`GET /v1/podcasts/segments`, and `GET /v1/podcasts/segments/{id}`. They match the `number`
field on each line of `GET /v1/podcasts/episodes/{id}/transcript`, so a transcript can be
sliced by segment exactly instead of by arithmetic on float timestamps.

**A documentation correction ships with them.** These docs and the
`particle_podcast_search_transcripts` tool description previously said segments "tile an
episode end-to-end" and that "every minute belongs to exactly one segment." That was wrong,
and it is the reason a segment's `end_seconds` does not equal the next segment's
`start_seconds`. Segments are contiguous in transcript *lines*, not in wall-clock seconds:
`start_seconds` is when a segment's first spoken line begins and `end_seconds` is when its
last spoken line ends, so consecutive segments are separated by whatever silence sat between
those two utterances — usually a fraction of a second, occasionally minutes of music or an
ad-stitch window. On episodes reporting `start_line`/`end_line`, those intervals contain no
transcribed speech and nothing is omitted from them; see the caveat below for older
episodes.

**No existing data changed** — this is what segments produced by the current segmenter have
always been, now described accurately and made checkable. `start_line`/`end_line` are recorded on newly segmented
episodes and omitted on everything segmented earlier; backfilling them across the historical
corpus is a follow-up and has not shipped.

Two different dates are in play here, and conflating them would be misleading:

* **Line-range persistence starts with this release.** Every episode segmented before it
  omits `start_line`/`end_line`, however healthy its coverage is.
* **Coverage was fixed on 24 July 2026.** Episodes segmented before *that* came from a
  version of the segmenter that could genuinely leave transcript lines in no segment, and
  about 11% of them did. A repair of that cohort is in progress.

So the absence of `start_line`/`end_line` does **not** by itself mean an episode has gaps —
the large majority of episodes without them were segmented after the coverage fix and are
complete. It only means the partition cannot be verified from the response alone. Where that
matters, check the episode transcript directly.

## August 2026

### Alerts watch exactly one entity

An alert now watches a single entity: [`particle_alert_create`](/mcp/tools/alerts/alert-create), [`particle_alert_update`](/mcp/tools/alerts/alert-update), and [`particle_alert_preview`](/mcp/tools/alerts/alert-preview) accept exactly one slug in `entities`, and passing more than one returns an `invalid_parameter` error telling you to create one alert per entity. The REST endpoints (`POST /v1/projects/{projectId}/alerts`, `PATCH /v1/alerts/{id}`, and the preview) enforce the same `maxItems: 1`. Alerts created before this rule keep their multi-entity watch list and keep matching and delivering; the next write to their `entities` field must name a single entity.

Separately, advertised tool input schemas now carry the numeric and array bounds the server already enforced — `minimum`/`maximum` (e.g. `window_days` 1–30) and `minItems`/`maxItems` — across every tool, so agents can self-correct before a failed call instead of after.

### Semantic trend counting on the episode timeseries

[`particle_podcast_get_episode_timeseries`](/mcp/tools/podcasts/podcast-get-episode-timeseries) takes `semantic_search` — the counting twin of [`particle_podcast_search_transcripts`](/mcp/tools/podcasts/podcast-search-transcripts)' semantic query, using the same embedding and similarity threshold so the counts agree with search results. "How often do podcasts discuss weight-loss drugs, per week" is now one aggregated call instead of paging search once per period. It adds the same per-bucket `mention_count` and range `total_mentions` that `keyword_search` produces; the two cannot be combined, and `semantic_search` requires `published_after` (ranges up to \~2 years). The REST endpoint `GET /v1/podcasts/episodes/timeseries` gained the matching `semantic_search` query parameter.

### Keyword search now filters instead of only ranking

`keyword_search` on [`particle_podcast_search_transcripts`](/mcp/tools/podcasts/podcast-search-transcripts) and `GET /v1/podcasts/episodes/search` used to be a *ranking* signal: the words nudged relevance but nothing was excluded, so a hybrid call could return passages containing none of the words you typed. It is now a filter — every word must appear in the matched passage — which also means a hybrid call is the intersection of `semantic_search` and `keyword_search` rather than a blend of both.

**This changes results for existing calls.** A search for `QuillBot` that returned 100 passages now returns the 21 that actually say "QuillBot"; the rest were semantic neighbours. Where `keyword_search` is a loose bag of related words that will not co-occur in one passage, the new `keyword_match: "ranked"` restores the previous behavior. Quoted phrases are unchanged — they have always been exact.

### Searches that return nothing now say why

An empty search used to be indistinguishable from "we have no such content", which left agents unable to tell an over-specified query from an empty corpus. Both surfaces now report the cause, measured by re-running the query with each filter removed in turn.

`GET /v1/podcasts/episodes/search` returns a `diagnostics` object on an empty page, naming the filter that excluded everything, why it did, and a `retry_with` parameter delta. [`particle_podcast_search_transcripts`](/mcp/tools/podcasts/podcast-search-transcripts) turns the same finding into an actionable error carrying the corrected call, so an agent can retry directly. When the query text genuinely matches nothing, that is still an ordinary empty result rather than an error.

### Entity and role filters cover the whole corpus

`entity_slug` / `person_slug` / `company_slug` / `role` / `entity_type` filters were resolved against at most 1,000 episodes per entity. For anything widely discussed that was a small, arbitrary slice — Andy Burnham appears in 10,418 episodes, and 90% of them could never be returned. These filters now run natively against the full index, so a filtered search sees every episode. [`particle_podcast_search_transcripts`](/mcp/tools/podcasts/podcast-search-transcripts) also gained `entity_type`, for "discussions of X that mention some book".

### Unresolvable references are rejected, not ignored

Passing a name that matches nothing — `company_slug: "x"` — used to either empty the results or be silently dropped, depending on whether another parameter happened to resolve. It now returns an `unresolved_reference` error naming the parameter and the resolve endpoint to call.

### Lighter search responses

Search results embedded the parent episode three times per match (once at the top level, once under the segment, once per clip). The redundant copies are gone; the episode on each match is unchanged. If you read `segment.episode` or `clips[].episode` out of a search response, read the match's own `episode` instead.

### Language filter across the podcast tools

[`particle_podcast_find_mentions`](/mcp/tools/podcasts/podcast-find-mentions) and [`particle_podcast_search_transcripts`](/mcp/tools/podcasts/podcast-search-transcripts) take a `language` filter — a two-letter ISO 639-1 code (e.g. `"fr"`) restricting results to episodes of podcasts in that language. "Mentions of Sam Altman on French-language podcasts" is now one call: `{"person_slug": "sam-altman", "language": "fr"}`. The existing `language` filter on [`particle_podcast_list_episodes`](/mcp/tools/podcasts/podcast-list-episodes) and [`particle_podcast_get_episode_timeseries`](/mcp/tools/podcasts/podcast-get-episode-timeseries) was upgraded from an exact tag match to the same semantics: values are validated (an unknown code is an actionable error rather than a silent empty result) and matched on the podcast's primary language subtag, so `fr` covers `fr-FR` and `fr-ca`. The REST endpoints `GET /v1/podcasts/mentions`, `GET /v1/podcasts/mentions/timeseries`, and `GET /v1/podcasts/episodes/search` gained the matching `language` query parameter, with the same subtag semantics applied to the existing filter on `GET /v1/podcasts` and `GET /v1/podcasts/episodes`.

### `company_slug` now carries the knowledge-graph slug

[`particle_podcast_get_sponsors`](/mcp/tools/podcast_advertising/podcast-get-sponsors), [`particle_podcast_get_sponsor_leaderboard`](/mcp/tools/podcast_advertising/podcast-get-sponsor-leaderboard), and [`particle_company_get_podcast_ad_presence`](/mcp/tools/podcast_advertising/company-get-podcast-ad-presence) used to put a domain-preferred identifier in `company_slug` (e.g. `okx.com`). `company_slug` now carries the actual knowledge-graph slug (e.g. `okx`), and the previous domain-preferred value moved to a new `company_id` field — both are valid `/v1/companies/{id}` keys, but `company_slug` is the stable one. If your agent parses `company_slug` out of any of those tools' JSON output, expect a different value. The rendered markdown still shows `company_id`, because a domain like `okx.com` stays recognizable where a generated entity slug can be `huntchef-g-11j62z1w0g`. The REST endpoint behind the ad-presence tool, `GET /v1/companies/{id}/podcast/advertising`, gained the matching `slug` field. [`particle_podcast_get_episode_ads`](/mcp/tools/podcast_advertising/podcast-get-episode-ads) and its REST endpoint `GET /v1/podcasts/episodes/{id}/ads` now populate `company.slug` alongside the existing `company.id`.

### Clips filter by speaker

[`particle_podcast_list_clips`](/mcp/tools/podcasts/podcast-list-clips) takes a `speaker` filter: a person slug (from [`particle_person_resolve`](/mcp/tools/people/person-resolve)), a knowledge-graph entity slug for the same person, or an ID. The listing then returns only clips whose primary speaker is that person — "an insightful Sam Altman clip" is now one call: `{"speaker": "sam-altman", "type": "INSIGHTFUL"}`. A speaker — or podcast — reference that resolves to nothing now returns an empty listing rather than silently widening back to the full catalog. The REST endpoint `GET /v1/podcasts/clips` gained the matching `speaker` query parameter.

## July 2026

### Speaker roles — a documented, closed set

Every `role` an episode or transcript tool returns is now one of fourteen documented
values — see [Episodes → Speaker roles](/podcasts/episodes#speaker-roles). Previously
the field could carry any of \~130 values produced during transcript analysis; those
are now normalized into the documented buckets on the way out, so an agent can branch
on `role` without a catch-all.

Role arguments — `role` on the episode and mention tools, `speaker_roles` on the alert
tools — are now case-insensitive, so echoing back a value in the casing it appeared in
prose no longer fails validation. `CO_HOST` is retired and folds into `HOST`.

### Ad timeseries scopes to a show or a network

[`particle_podcast_get_ad_trends`](/mcp/tools/podcast_advertising/podcast-get-ad-trends) in `timeseries` mode now takes `podcast_slug` and `publisher_slug`, so a company's ad volume can be charted on one show or across one publisher's catalog instead of the whole corpus. Both accept a slug or an ID, matching the same filters on the mentions timeseries — which is what makes organic mentions and ad reads comparable under one scope. A reference that resolves to nothing returns zero-filled buckets rather than silently widening back to the full corpus. Omitting both preserves the previous behavior. The REST endpoint `GET /v1/podcasts/advertising/timeseries` gained the matching `podcast_id` and `publisher_id` query parameters.

### REST parity: five new tools and six expanded ones

The MCP surface now covers every public GA REST capability. Five new tools:

* [`particle_podcast_get_episode_timeseries`](/mcp/tools/podcasts/podcast-get-episode-timeseries) — time-bucketed episode and mention counts with the same filters as `particle_podcast_list_episodes` plus `keyword_search`; the purpose-built answer to "how often is X discussed over time".
* [`particle_podcast_list_clips`](/mcp/tools/podcasts/podcast-list-clips) — browse highlight clips by podcast, type, or engagement score, with a `clip_id` detail path and `include=["transcript"]`.
* [`particle_podcast_get_episode_ads`](/mcp/tools/podcast_advertising/podcast-get-episode-ads) (premium) — every detected ad read inside one episode with sponsor, product, offer, read type, placement, and exact offsets.
* [`particle_podcast_get_ad_trends`](/mcp/tools/podcast_advertising/podcast-get-ad-trends) (premium) — `sponsor_trends` (advertisers ramping up or pulling back) and `timeseries` (one company's ad volume over time, split host-read vs pre-recorded).
* [`particle_entity_get`](/mcp/tools/people/entity-get) — a knowledge-graph entity's profile, closing the loop for `place`/`other` slugs from `particle_entity_resolve`.

And six expanded surfaces (all additive — existing calls are unchanged):

* [`particle_podcast_list_guests`](/mcp/tools/podcast_guests/podcast-list-guests) takes `podcast_slug` for one show's guest roster (one-off guests included).
* [`particle_podcast_get_rankings`](/mcp/tools/podcast_rankings/podcast-get-rankings) adds `mode=slots` — every valid source, country, and `category_slug` with live chart data, so filter values are discovered rather than guessed.
* [`particle_podcast_get_publisher`](/mcp/tools/podcast_publishers/podcast-get-publisher) takes `query` to resolve a publisher name to a slug in the same call (candidates on ambiguity). The REST `GET /v1/podcasts/publishers` listing gained the matching `q` filter.
* [`particle_podcast_get_sponsor_leaderboard`](/mcp/tools/podcast_advertising/podcast-get-sponsor-leaderboard) adds `mode=publishers` (the sell-side leaderboard with `unique_sponsors` and `ads_per_active_podcast` metrics) and a `publisher_slug` filter for sponsors mode.
* [`particle_company_get_podcast_ad_presence`](/mcp/tools/podcast_advertising/company-get-podcast-ad-presence) adds `include=podcasts` (full ranked show list), `include=segments` (actual ad-read segments with AI summaries), and `include=co_advertisers` (sponsor pairs sharing episodes).
* [`particle_podcast_get_episode`](/mcp/tools/podcasts/podcast-get-episode) cross-references the new episode-ads tool.

### Premium include sections now honor the plan's premium entitlement

The include sections that carry premium-grade data on standard-tier tools now require a plan with premium endpoints, matching the premium-tier tools themselves: `suitability` and `rankings` on [`particle_podcast_resolve`](/mcp/tools/podcasts/podcast-resolve), and `bias`, `suitability`, and `advertising` on [`particle_podcast_get_publisher`](/mcp/tools/podcast_publishers/podcast-get-publisher). Entitled plans are unaffected. A plan without premium endpoints now receives a `premium_required` error naming the offending include values — retry without them for the standard sections (the high-level `suitability_tier` and `bias` enums on resolve results are standard data and always rendered).

### Filter-aware alert previews

[`particle_alert_preview`](/mcp/tools/alerts/alert-preview) now accepts the same `filters` object as [`particle_alert_create`](/mcp/tools/alerts/alert-create), so the match-frequency estimate reflects what the alert would actually surface once its filters are applied. `languages` and `speaker_roles` narrow the historical sweep exactly; `relevance` and `source_popularity` are graded at read time and don't run on historical episodes, so they leave the count unchanged (the estimate is an upper bound when `relevance=RELEVANT`). The preview cache key keys on the count-affecting filters — changing `languages` or `speaker_roles` starts a fresh sweep, while toggling `relevance` or `source_popularity` returns the same cached count. Omitting `filters` preserves the previous unfiltered behavior.

## June 2026

### Alert filters — narrow what an alert surfaces

Alerts now carry a persistent `filters` object that narrows what gets surfaced — applied identically to the matches list, the realtime email, and the daily/weekly digests. Four axes: `languages` (BCP-47 tags), `relevance` (`EVERYTHING` vs `RELEVANT`), `source_popularity` (`ANY` vs `POPULAR` = top 5% of currently-charting podcasts), and `speaker_roles` for `PODCAST_SPEAKER` alerts (defaults to `GUEST,PANELIST,CORRESPONDENT,AUDIENCE,SOUNDBITE_SPEAKER`; sending it on an `ENTITY_MENTION` alert returns an `unprocessable_entity` error).

[`particle_alert_create`](/mcp/tools/alerts/alert-create) and [`particle_alert_update`](/mcp/tools/alerts/alert-update) accept the `filters` object directly, and [`particle_alert_get`](/mcp/tools/alerts/alert-get) / [`particle_alert_list`](/mcp/tools/alerts/alert-list) echo the active filter set back so reads expose the current state. Update semantics mirror `entities`/`notifications`: passing `filters` on update **replaces** the whole set, `{}` clears all four axes, and omitting it leaves the existing set unchanged. See [Alerts → Filtering matches](/alerts/overview#filtering-matches) for the per-axis spec and the [REST changelog](/changelog#alert-filters-%E2%80%94-narrow-what-an-alert-surfaces) for the wire shape — the same filter object is accepted on `POST /v1/projects/{projectId}/alerts` and `PATCH /v1/alerts/{id}`.

### Better entity & person resolution

* [`particle_entity_resolve`](/mcp/tools/people/entity-resolve) and [`particle_person_resolve`](/mcp/tools/people/person-resolve) now rank across people, companies, and knowledge graph entities with one relevance model (exact name / identifier / known alias → prefix → all-words → fuzzy), replacing the prior name-only substring match. Results are better-ordered and tolerate typos, stock tickers, `@handles`, and domains. `particle_person_resolve` also now finds people who aren't yet linked to a knowledge-graph entity. Each match carries the canonical `slug`, `name`, and `description` (plus a company's `company_domain`) — enough to confirm the hit and traverse to the matching `get` tool.

### Alerts

* **Seven alert lifecycle tools** — a new default `alerts` category brings the [Alerts](/api-reference/alerts) feature to the MCP surface: [`particle_alert_create`](/mcp/tools/alerts/alert-create), [`particle_alert_list`](/mcp/tools/alerts/alert-list), [`particle_alert_get`](/mcp/tools/alerts/alert-get), [`particle_alert_update`](/mcp/tools/alerts/alert-update), [`particle_alert_delete`](/mcp/tools/alerts/alert-delete), [`particle_alert_preview`](/mcp/tools/alerts/alert-preview), and [`particle_alert_list_matches`](/mcp/tools/alerts/alert-list-matches). Watch a person, company, or other entity and get emailed whenever it's mentioned on a podcast (`ENTITY_MENTION`) or appears as a speaker (`PODCAST_SPEAKER`); preview match frequency before committing; and review the matches an alert has caught.
* **The first writable tools** — `particle_alert_create`/`particle_alert_update` mutate and `particle_alert_delete` is a destructive soft delete, so these are *not* `readOnlyHint: true`. They act on the **single project your credential is scoped to** — there is no project parameter and no way to reach another project's alerts. Watch targets are passed as the same entity slugs the resolve tools return (resolve a name once, then watch it).

### Richer external links

* **External-link attributes in markdown** — when [`particle_podcast_resolve`](/mcp/tools/podcasts/podcast-resolve) hydrates `include: ["external_links"]`, each platform bullet now appends the attributes the platform reports (audience size, content tallies, verified status, ...), so a YouTube channel renders its subscriber and video counts alongside the URL rather than the link alone. The attributes were already present on the `output_format: "json"` form; this surfaces them in the default markdown.

### Agent discovery (auth.md)

* **`/auth.md`** — both hosts now serve the [auth.md](https://github.com/workos/auth.md) agent-onboarding document at [`https://api.particle.pro/auth.md`](https://api.particle.pro/auth.md) and [`https://mcp.particle.pro/auth.md`](https://mcp.particle.pro/auth.md): the discovery walkthrough, a credential decision tree, registration steps, errors, and revocation, with the flows Particle Pro deliberately does not offer declared up front.
* **`agent_auth` block** — the [AS metadata](https://api.particle.pro/.well-known/oauth-authorization-server) now embeds a machine-readable registration summary (`register_uri`, identity and credential types, revocation). [Authentication → Agent discovery](/mcp/authentication#agent-discovery).
* **REST protected-resource metadata** — `https://api.particle.pro/.well-known/oauth-protected-resource` now serves an RFC 9728 document describing the REST API resource (previously 404). The MCP document at `https://mcp.particle.pro/.well-known/oauth-protected-resource` is unchanged.

### Skill bundles and exact-tool selection

* **[Skill bundles](/mcp/skills)** — three ready-made skills (Podcast Intelligence, Company Deep Dive, Guest & People Research): a connection URL scoped to just the tools each workflow needs, plus a copy-paste SKILL.md that teaches your agent the workflow.
* **`?tools=` selector** — pin a connection to exactly the tools you want advertised: `?tools=particle_podcast_resolve,particle_podcast_search_transcripts`. See [Tool sets & discovery](/mcp/tool-sets#selecting-exact-tools).
* **More clients in the quickstart** — Windsurf, Zed, ChatGPT developer mode, and server-side wiring examples for the Anthropic Messages API and OpenAI Responses API. [Quickstart](/mcp/quickstart).

### Connect without a browser

* **API keys as MCP credentials** — the server now accepts the same `pp_*` project API keys as the REST API (`Authorization: Bearer` or `X-API-Key`), so headless agents — cron jobs, the OpenAI Responses API, server-side harnesses — no longer need an interactive OAuth consent. OAuth remains the recommended path when a human is present. [Authentication](/mcp/authentication#api-keys-for-headless-agents).
* **One-click installs** — Cursor and VS Code install buttons in the [Quickstart](/mcp/quickstart).
* **[llms.txt](https://docs.particle.pro/llms.txt)** — now opens with instructions for LLM agents: which surface to pick, how the tools compose, and the conventions that save wasted round-trips.

### Smarter discovery on connect

* **Conventions taught up front** — connecting clients now receive server instructions covering the two things a bare tool list doesn't show: tools are lean by default and expand via `include`/`mode`/`format` parameters, and every slug a tool returns is a valid input to the other tools (resolve a name once, then traverse).
* **`particle_catalog` shows each tool's depth** — the catalog menu lists every tool's expand options (`↳ include: … · mode: …`), so an agent can see what a tool can really do before fetching its full schema.

### 25 tools, flat names, opt-in categories

* **Renames (action needed if you call tools by name)** — every tool moved to a flat `particle_*` identifier, e.g. `entities/resolve_entity` → `particle_entity_resolve`. The [tool reference](/mcp/tools/overview) lists all current names.
* **Consolidations** — `search_dialogue` and `list_clips` merged into [`particle_podcast_search_transcripts`](/mcp/tools/podcasts/podcast-search-transcripts): relevant clips now arrive inline on search matches, and a known episode's full clip list comes from `particle_podcast_get_episode` with `include: ["clips"]`. `get_entity_mentions` became [`particle_podcast_find_mentions`](/mcp/tools/podcasts/podcast-find-mentions). Boolean flags on get-tools became `include` arrays.
* **12 new tools** — people profiles and resolution, podcast guests, chart rankings, publishers, listener ratings, and political-bias and brand-suitability analytics. Browse them in the [tool reference](/mcp/tools/overview).
* **Default vs opt-in advertisement** — six tool categories advertise on a bare connection; five more (advertising, publishers, ratings, bias, suitability) advertise when you opt in with `?include=`. Every public tool stays callable by name either way, and the always-on `particle_catalog` / `particle_call` meta-tools let any connection discover and reach the full surface. [Tool sets & discovery](/mcp/tool-sets).

## May 2026

### Launch

* The Particle Pro MCP server ships at `https://mcp.particle.pro`: read-only tools over podcasts, companies, and the knowledge graph, with [OAuth 2.1](/mcp/authentication) and markdown outputs designed for agent loops.
* MCP requests and per-tool usage appear in your organization's request logs alongside REST traffic.

***

Missing something? Email [api@particle.pro](mailto:api@particle.pro).
