Skip to main content
Glama

Cooper Email

Register webhook

cooper_register_webhook

Use this when the agent or app should be notified immediately (HTTP POST) when mail arrives instead of polling cooper_list_messages. Requires auth. Inputs: url (required; public http or https URL; localhost and private addresses are rejected), events (optional; any of message.received, message.held, message.sent, message.blocked, message.bounced, message.complained, task.received, owner.reply, domain.verified, draft.created, draft.approved, draft.rejected, draft.sent; default [message.received]), inbox_id (optional; one inbox) or inbox_ids (optional; at most 10 inbox ids; omit both for every inbox), client_id (optional idempotency key; the same value returns the original hook with HTTP 200 and a redacted secret), headers (optional; up to 5 extra headers named Authorization or X-*, stored encrypted and never returned in full). Returns {id, url, events, inbox_id, inbox_ids, enabled, secret, headers (redacted), created_at}. Each delivery sends x-cooper-signature (sha256= HMAC of the raw body) and x-cooper-signature-v2 (v1= HMAC of timestamp, a dot, and the raw body) plus x-cooper-timestamp. message.blocked fires when an allow or block list drops inbound mail before it is stored. Fails with 400 too_many_inboxes, 400 invalid_url, or 404 inbox_not_found.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYesPublic https URL that receives POST deliveries
eventsNoEvent types to deliver. Default: ["message.received"]
headersNoUp to 5 extra headers sent on delivery. Names must be Authorization or X-*. Values are stored encrypted and never returned in full.
inbox_idNoOnly deliver events for this inbox. Stored into inbox_ids. Omit for every inbox on the account.
client_idNoOptional idempotency key. The same client_id returns the original hook with the secret redacted.
inbox_idsNoUp to 10 inbox ids. The hook matches when this list is empty or contains the event inbox. More than 10 returns 400 too_many_inboxes.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / events / items / enum
      Previous value: -[
      -  "message.received",
      -  "message.held",
      -  "message.sent",
      -  "message.blocked",
      -  "message.bounced",
      -  "message.complained",
      -  "task.received",
      -  "owner.reply",
      -  "domain.verified"
      -]New value: +[
      +  "message.received",
      +  "message.held",
      +  "message.sent",
      +  "message.blocked",
      +  "message.bounced",
      +  "message.complained",
      +  "task.received",
      +  "owner.reply",
      +  "domain.verified",
      +  "draft.created",
      +  "draft.approved",
      +  "draft.rejected",
      +  "draft.sent"
      +]
  2. Changed1 schema field changed
    • changedInput schema / properties / events / items / enum
      Previous value: -[
      -  "message.received",
      -  "message.sent",
      -  "message.blocked",
      -  "message.bounced",
      -  "message.complained",
      -  "task.received",
      -  "owner.reply",
      -  "domain.verified"
      -]New value: +[
      +  "message.received",
      +  "message.held",
      +  "message.sent",
      +  "message.blocked",
      +  "message.bounced",
      +  "message.complained",
      +  "task.received",
      +  "owner.reply",
      +  "domain.verified"
      +]
  3. Changed1 schema field changed
    • changedInput schema / properties / events / items / enum
      Previous value: -[
      -  "message.received",
      -  "message.sent",
      -  "message.blocked",
      -  "task.received",
      -  "owner.reply",
      -  "domain.verified"
      -]New value: +[
      +  "message.received",
      +  "message.sent",
      +  "message.blocked",
      +  "message.bounced",
      +  "message.complained",
      +  "task.received",
      +  "owner.reply",
      +  "domain.verified"
      +]
  4. Changed4 schema fields changed
    • addedInput schema / properties / client_id
      Added value: +{
      +  "description": "Optional idempotency key. The same client_id returns the original hook with the secret redacted.",
      +  "type": "string"
      +}
    • changedInput schema / properties / events / items / enum
      Previous value: -[
      -  "message.received",
      -  "message.sent",
      -  "message.blocked",
      -  "task.received",
      -  "owner.reply"
      -]New value: +[
      +  "message.received",
      +  "message.sent",
      +  "message.blocked",
      +  "task.received",
      +  "owner.reply",
      +  "domain.verified"
      +]
    • changedInput schema / properties / inbox_id / description
      Previous value: -"Only deliver events for this inbox. Omit for every inbox on the account."New value: +"Only deliver events for this inbox. Stored into inbox_ids. Omit for every inbox on the account."
    • addedInput schema / properties / inbox_ids
      Added value: +{
      +  "description": "Up to 10 inbox ids. The hook matches when this list is empty or contains the event inbox. More than 10 returns 400 too_many_inboxes.",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
  5. Changed1 schema field changed
    • changedInput schema / properties / events / items / enum
      Previous value: -[
      -  "message.received",
      -  "message.sent",
      -  "task.received",
      -  "owner.reply"
      -]New value: +[
      +  "message.received",
      +  "message.sent",
      +  "message.blocked",
      +  "task.received",
      +  "owner.reply"
      +]
  6. Changed2 schema fields changed
    • addedInput schema / properties / events / description
      Added value: +"Event types to deliver. Default: [\"message.received\"]"
    • addedInput schema / properties / url / description
      Added value: +"Public https URL that receives POST deliveries"
  7. Changed2 schema fields changed
    • addedInput schema / properties / headers
      Added value: +{
      +  "additionalProperties": {
      +    "type": "string"
      +  },
      +  "description": "Up to 5 extra headers sent on delivery. Names must be Authorization or X-*. Values are stored encrypted and never returned in full.",
      +  "type": "object"
      +}
    • addedInput schema / properties / inbox_id
      Added value: +{
      +  "description": "Only deliver events for this inbox. Omit for every inbox on the account.",
      +  "type": "string"
      +}
  8. First observed

TDQS

A4.7/5.0
Behavior5/5

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

Goes well beyond the annotations (readOnlyHint=false, openWorldHint=true): it discloses auth requirements, URL validation rules (localhost/private rejected), cross-field scoping constraints, opt-in idempotency via client_id with HTTP 200 + redacted secret, header encryption/redaction, HMAC signature headers on delivery, and three specific error codes. This is exactly the behavioral depth a mutation tool needs.

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-loads the decision ('use this when...instead of polling') before the detailed input/output/error inventory. It is a single dense block rather than scannable sections, and a few clauses restate schema-level facts, but no sentence is wasted.

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?

With no output schema and no structured annotations covering behavior, the description still describes the return shape ({id, url, events, enabled, secret, ...}), the signature headers, and failure modes. An agent has everything needed to call this 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?

Although schema coverage is 100%, the description adds cross-parameter semantics the schema does not spell out: inbox_id vs inbox_ids are mutually exclusive, inbox_ids is capped at 10, omitting both targets every inbox, and client_id acts as an idempotency key returning the original hook with a redacted secret. It also documents header naming rules and default event behavior.

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 (register a webhook) and immediately frames the purpose as push notification via HTTP POST when mail arrives. It explicitly distinguishes itself from the polling sibling cooper_list_messages, so an agent can route between the two 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 Guidelines4/5

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

Gives a clear when-to-use condition (notify immediately instead of polling) and names the polling alternative cooper_list_messages. It does not differentiate from cooper_update_webhook or cooper_test_webhook, nor state explicit exclusions, so it falls just short of full when/when-not coverage.

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.