Skip to main content
Glama

bulk_unsubscribe

Idempotent

Unsubscribe from several mailing lists in one call using thread IDs; run dryRun first to preview which senders would be contacted.

Instructions

Unsubscribe from several mailing lists in one call, one thread id per list. Threads are processed SEQUENTIALLY, and at most ONE request is made per sender — a second thread from a sender whose request already went out is reported with duplicateOf and no request (and says so when it advertises a DIFFERENT endpoint, i.e. is probably a separate list from the same sender). The whole call shares a 60-second budget; threads left over when it runs out come back with skippedOutOfTime and a reason, so re-running with the remaining ids finishes the job. Like unsubscribe, there is no URL parameter: every endpoint comes from that thread's own List-Unsubscribe header. Only RFC 8058 one-click senders are contacted; the rest come back with their alternatives in options. Partial success is reported, never hidden: a thread that cannot be read or whose endpoint fails becomes an entry with a reason, and the remaining threads still run. Set dryRun:true to rehearse: same header reads, same per-sender dedupe (as a real run with every request succeeding), and each entry a real run would contact reports the endpoint it wouldCall; refusals and duplicates carry none — and nobody is contacted. USE WHEN: clearing out several newsletters at once — pair with list_subscriptions, which gives you the sender rows and their newestThreadId; dryRun first to show the user which senders would be contacted. DO NOT USE: for one thread (use unsubscribe), or to find candidates (use list_subscriptions — it contacts nobody). SIDE EFFECTS: up to one outbound HTTPS request per DISTINCT sender (plus up to 3 redirects each) — the only non-Google hosts mailwarden ever contacts (none with dryRun). Each confirms to that sender that the address is live, and none of it can be undone. The mailbox itself is not changed.

Tool call template

Replace each placeholder with a value matching the input schema. Only required parameters are included; add optional parameters as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {
      "threadIds": "<threadIds>"
    },
    "name": "bulk_unsubscribe"
  }
}

Input Schema

NameRequiredDescriptionDefault
dryRunNo
threadIdsYes

Output Schema

NameRequiredDescriptionDefault
dryRunYes
resultsYes
requestsYes
attemptedYes
requestedYes
unsubscribedYes
skippedOutOfTimeYes
skippedDuplicatesYes

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changedv0.25.0
    • removedInput schema / additionalProperties
      Removed value: -false
  2. Changed5 schema fields changedv0.11.0
    • addedInput schema / properties / dryRun
      Added value: +{
      +  "default": false,
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / dryRun
      Added value: +{
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / requests
      Added value: +{
      +  "type": "number"
      +}
    • addedOutput schema / properties / results / items / properties / wouldCall
      Added value: +{
      +  "type": "string"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "requested",
      -  "attempted",
      -  "unsubscribed",
      -  "skippedDuplicates",
      -  "skippedOutOfTime",
      -  "results"
      -]New value: +[
      +  "dryRun",
      +  "requested",
      +  "attempted",
      +  "unsubscribed",
      +  "skippedDuplicates",
      +  "skippedOutOfTime",
      +  "requests",
      +  "results"
      +]
  3. Addedv0.9.0

TDQS

A4.8/5.0
Behavior5/5

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

Annotations cover the safety profile (not read-only, not destructive), and the description adds a great deal beyond them: sequential processing, one request per distinct sender with `duplicateOf` dedupe, a 60-second shared budget with `skippedOutOfTime` and a resume path, and per-thread `reason` failures with partial success. It also discloses real-world side effects — outbound HTTPS to non-Google hosts, up to 3 redirects, sender learns the address is live, irreversible — plus what dryRun does and does not touch. Minor tension: `idempotentHint: true` alongside repeated calls re-contacting senders, but the description never claims repeated calls are no-ops.

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?

Front-loaded with the operation and its sequencing, then dryRun, then USE WHEN / DO NOT USE / SIDE EFFECTS blocks, so it is scannable despite its length. Some passages are heavier than needed — capitalized emphasis scattered mid-sentence and the aside about being "the only non-Google hosts mailwarden ever contacts" — but nearly every sentence carries operational 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?

For a two-parameter tool with an output schema and partial-failure semantics, the description covers everything an agent needs to call it correctly and interpret the result: entry shapes (`duplicateOf`, `skippedOutOfTime`, `reason`, `wouldCall`, `options`) are surfaced even though an output schema exists. No prerequisite, exclusion, or recovery path 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?

Schema description coverage is 0%, so the description carries the burden — and it does explain `dryRun` thoroughly (same header reads and dedupe, reports `wouldCall`, contacts nobody) and defines `threadIds` as one thread id per list, sourced from `newestThreadId` in list_subscriptions. It omits the 25-item cap and the thread-vs-message id distinction, so it doesn't fully compensate.

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?

"Unsubscribe from several mailing lists in one call, one thread id per list" gives a specific verb, resource, and batching scope in one clause. The batching scope immediately separates it from the single-item `unsubscribe` and from `list_subscriptions`.

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?

Explicit USE WHEN (clearing out several newsletters, pair with list_subscriptions for sender rows and newestThreadId, dryRun to preview) and DO NOT USE clauses that name the correct alternatives (`unsubscribe` for one thread, `list_subscriptions` to find candidates). Nothing is left to inference.

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