Skip to main content
Glama

Ray notifications

Server Details

Send email, push, Slack, Discord, Telegram and webhook notifications and manage templates with Ray.

If you are the author of this connector, you can claim ownership by verifying the domain or GitHub account it belongs to. Claimed connector authors can inspect health checks, view analytics, and manage their listing.
Status
Healthy
Uptime
99.9% over 22 days
Last Tested
Transport
Streamable HTTP · MCP 2025-11-25
URL
Repository
gege-mn/ray-mcp
GitHub Stars
0
Server Listing
Ray: Your Notification Infra

TDQS

A4.2/5.0

Scored across 21 tools

Disambiguation5/5

Each tool maps to a distinct resource and action, including template lifecycle, webhook CRUD, sending/test-sending, status/analytics, channels, feeds, docs, and authentication. Even similar operations like publish_template and update_template_draft are clearly separated by their behavior.

Naming Consistency4/5

Nearly all tools follow a consistent snake_case verb_noun pattern (create_template, list_webhooks, get_send_status). The only minor deviation is whoami, a conventional standalone command-style name that does not disrupt the overall pattern.

Tool Count3/5

At 21 tools, the server is on the heavy side and feels large, even though the tools cover multiple related subdomains. Each tool has a purpose, but the count is closer to a broad platform SDK than a focused notification MCP.

Completeness5/5

The tool surface covers the core notification workflows thoroughly: template draft/publish/archive/unarchive, sending with multiple modes, test sends, delivery status, click stats, webhook CRUD, feed reading, usage/billing, channel discovery, and docs. Channel creation is intentionally dashboard-only, and no obvious workflow dead-end remains.

Available Tools

21 tools
archive_templateArchive templateA
DestructiveIdempotent
Inspect

Archive a template (POST /templates/{id}/archive; write scope). Sends that reference it fail until it is restored with unarchive_template; its name stays reserved meanwhile. Confirm with the user first if it may be in production use.

ParametersJSON Schema
NameRequiredDescriptionDefault
templateIdYesThe template id (UUID).

TDQS

A4.5/5.0
Behavior5/5

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

Goes well beyond the annotations by disclosing the concrete behavioral side effects: referencing sends fail until restored with unarchive_template, and the template name stays reserved meanwhile. This gives the agent real operational understanding of the action.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Each sentence is compact and informative, covering the action, effects, and user-facing guidance. No filler words, and the most important details are placed early.

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 one-parameter destructive tool, the description addresses the action, consequences, restoration path, and a caution for production usage. No output schema is needed, and the required context is covered.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides a full description for templateId and the schema description coverage is 100%. The assistant description does not add additional parameter semantics, so it stays at the baseline for high schema coverage.

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 the specific verb and resource—'Archive a template'—and further pins it down with the raw endpoint and write scope. The reference to unarchive_template clearly separates it from the restoring sibling.

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?

Provides clear context for when this should be used carefully ('Confirm with the user first if it may be in production use') and explains the main consequence: sends that reference the template will fail until restored. It could more explicitly contrast when to choose archive versus unarchive, but the context is strong.

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

create_templateCreate templateAInspect

Create a template (POST /templates; write scope). channelKind is permanent and must match the channels you'll send through (list_channels templateKind). It is saved as an unpublished draft unless publish: true; sending by templateId needs a published version (publish_template). Names are unique per workspace including archived templates: a collision returns 409, so unarchive_template the old one instead. Returns { id, requiredParams }. Designed (drag-and-drop) email templates can only be made in the dashboard.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesTemplate name, unique per workspace (archived templates included).
folderNoOptional folder path for organisation, e.g. "billing".
contentYesChannel-shaped template body; the shape is fixed by `channelKind`: email_html → `{ subject, bodyHtml, bodyText }`; fcm_basic → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_text → `{ text }`; discord_text → `{ content }` (max 2000 chars); telegram_text → `{ text, disableLinkPreview? }`; sms_text → `{ text }` (plain text, max 1600; long text is split into several billed SMS — on sendsms_mn into parts of 159 plain-Latin / 69 Cyrillic chars); webhook_json → `{ title, body, data?: { [key]: string } }`. Use `{{name}}` placeholders and `{{#items}}…{{/items}}` sections; the required params are derived from them automatically.
publishNotrue = publish this version immediately so sends by templateId use it. Default false (saved as draft).
logTitleYesShort title shown in the in-app feed and delivery logs, e.g. "Invoice {{number}} is due". Placeholders allowed.
channelKindYesWhich channel family the template renders for. Must match the `templateKind` of the channels you will send through (list_channels). Can't be changed after creation.
logDescriptionYesOne-line description for the in-app feed and delivery logs. Placeholders allowed.
paramOverridesNoPer-param metadata keyed by param name: `{ optional?: boolean, description?: string }`. Mark a placeholder optional so sends may omit it.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations only mark this as a non-read-only, non-idempotent mutation. The description adds important behavior: channelKind is permanent, templates save as drafts unless publish is true, collisions return 409, and the return value is { id, requiredParams }. It also names the required list_channels verification. No contradiction with annotations exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, each earning its place: the core creation call, the permanent channelKind constraint, the draft/publish behavior, the unique-name collision handling, the return shape, and the dashboard limitation. No filler or redundant restatement of the title.

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 complex tool with 8 parameters, nested objects, and no output schema, the description covers the key behavioral gaps: endpoint, write scope, return shape, uniqueness rules, publish semantics, and a notable platform limitation. The input schema already provides rich per-parameter documentation, so nothing critical 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 coverage is 100%, so the baseline is 3. The description adds cross-parameter context not in the schema, such as channelKind needing to match list_channels templateKind and publish controlling unpublished-vs-published state. It also explains that requiredParams are auto-derived from placeholders, which helps agents understand the response despite the absence of an output schema.

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?

The description clearly states the action: create a template via POST /templates with write scope. It also distinguishes this tool from related operations like publish_template and update_template_draft by describing the draft/publish lifecycle.

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?

It explicitly gives when-to-use guidance and alternatives: publishing is needed before sending by templateId (publish_template), archived name collisions should be resolved via unarchive_template, and drag-and-drop email templates must use the dashboard. This is strong routing advice beyond the schema.

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

create_webhookCreate webhookAInspect

Create an outbound webhook that Ray POSTs signed event payloads to (POST /tenant-webhooks; write scope; Pro plan or higher, otherwise 403). The URL must be public HTTPS. The response contains the signing secret exactly once: show it to the user to store (e.g. as an env var), since it can't be read again, only rotated with update_webhook. Read the webhooks docs page for the signature scheme.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesPublic HTTPS endpoint that will receive the events.
nameYesLabel for the webhook, e.g. "Production delivery events".
eventsYesEvents to receive: "notification.delivered", "notification.failed_terminal" (one per recipient), and "send.completed" (once per send, with status totals).

TDQS

A4.5/5.0
Behavior5/5

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

The annotations only indicate that the operation is not read-only, not idempotent, and not destructive. The description adds substantial behavioral context: auth/plan failure (403), HTTPS requirement, and the critical one-time secret retrieval behavior with rotation via update_webhook. This goes well beyond what the structured fields provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences, each earning its place: endpoint/scope/plan, HTTPS constraint, one-time secret warning, rotation path, and docs pointer. The most important operational risk (secret can't be read again) is explicitly called out without fluff.

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?

Given no output schema, the description still tells the agent what matters in the response (the secret, exactly once), the prerequisites for a successful call, and where to learn the signature scheme. This is sufficient for an agent to invoke the tool and handle the most consequential behavior correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents url, name, and events in detail. The description adds the public-HTTPS requirement and secret response behavior, but it does not materially extend the meaning of the parameters themselves beyond what the schema already states.

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?

The description uses a specific verb and resource ('Create an outbound webhook') and adds the endpoint (POST /tenant-webhooks), the payload direction (Ray POSTs signed event payloads), and the scope/plan requirement. This clearly distinguishes it from siblings like update_webhook, delete_webhook, and get_webhook.

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?

It states clear conditions for use: write scope, Pro plan or higher, public HTTPS URL. It also tells the agent that the secret is only shown once and that update_webhook is the rotation path, which is a concrete alternative. It doesn't exhaustively list when not to use it, but the constraints are enough for selection.

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

delete_webhookDelete webhookA
DestructiveIdempotent
Inspect

Delete (archive) a webhook so it receives no more events (DELETE /tenant-webhooks/{id}; write scope). It cannot be restored through the API; confirm with the user first.

ParametersJSON Schema
NameRequiredDescriptionDefault
webhookIdYesThe webhook id (UUID).

TDQS

A4.5/5.0
Behavior5/5

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

Annotations already carry destructive and idempotent flags, but the description adds vital context: it archives the webhook, that events stop, and that the deletion cannot be undone through the API. It also notes the required 'write scope', providing security-relevant information that is not present in the structured annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Everything is captured in two concise sentences with no filler. The core outcome ('receives no more events') is front-loaded, followed by the irreversible caution and user confirmation, making every word earn its place.

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 single-parameter destructive action with no output schema, the description covers all essential context: the action, the result, the irreversibility, the permission, and the safety step required before invocation. Nothing an agent needs to decide whether to call it is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides 100% coverage with a description for the only parameter (webhookId), including UUID format and pattern. The tool description adds only a passing mention of {id} in the path, which is useful but does not materially enrich the meaning beyond the schema's own definition.

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?

The description uses a specific action verb ('Delete (archive)') on a concrete resource ('webhook') and states the immediate effect: it no longer receives events. It also includes the HTTP method and scope, making the tool's function unambiguous and clearly distinct from siblings like update_webhook, enable_webhook, or get_webhook.

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?

It clearly warns that the action is irreversible and instructs to confirm with the user first, which is a strong usage guideline. However, it does not explicitly mention when to use this tool instead of a soft-disable via update_webhook, so it misses the remainder of the 'vs alternatives' guidance.

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

get_click_statsGet click statsA
Read-onlyIdempotent
Inspect

Email link click counts grouped by destination URL (GET /clicks) for a sendId, a campaignId, or both (at least one is required). Only links from email sends made with trackClicks: true are counted.

ParametersJSON Schema
NameRequiredDescriptionDefault
sendIdNoA sendId from send_notification.
campaignIdNoThe `campaignId` passed to send_notification, to total clicks across many sends.

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, so safety is covered. The description adds meaningful behavior beyond those annotations: results are grouped by destination URL and only links from trackClicks-enabled sends are counted. It does not discuss response shape or pagination, but the core filtering behavior is transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The first sentence front-loads the resource, grouping behavior, and accepted identifiers; the second adds the key tracking precondition. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only two-parameter tool with fully described schema properties and no output schema, the description provides the required parameter relationship, the grouping concept, and the filtering caveat. It does not spell out the exact response fields, but 'click counts grouped by destination URL' gives enough shape for an agent to invoke and interpret the result.

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 baseline is 3, but the description adds real semantics: at least one of sendId/campaignId is required, campaignId totals across many sends, and only tracked-link emails contribute. These details are not encoded in the schema's property constraints and meaningfully shape invocation.

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?

The description uses a specific verb and resource: it returns email link click counts grouped by destination URL, and it identifies the query scope (sendId, campaignId, or both). This clearly separates it from sibling read tools like get_send_status and get_usage.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

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

The description states what identifiers the tool operates on and that at least one is required, and it gives an important precondition (trackClicks: true). However, it never explicitly contrasts this with alternatives such as get_send_status or get_usage, so an agent must infer when this tool is the right choice.

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

get_send_statusGet send statusA
Read-onlyIdempotent
Inspect

Delivery status of a send (GET /sends/{id}): aggregate counts per status over the whole send (pending, claimed, delivered, failed_retryable, failed_terminal, suppressed) plus one page of per-recipient delivery rows including provider errors. Right after sending, rows are usually pending; check again after a few seconds. Feed-only sends have no rows. For more rows, pass the returned nextCursor as cursor.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoRows per page (default 50, max 200).
cursorNo`nextCursor` from the previous page.
sendIdYesThe `sendId` returned by send_notification or test_send_template.

TDQS

A4.1/5.0
Behavior4/5

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

The description goes beyond the idempotent/read-only annotations by revealing the dynamic behavior of the response (pending -> eventual statuses), the caveat about feed-only sends having no rows, and the pagination mechanism (nextCursor). This adds helpful context for an agent, though the annotations already cover idempotency and read-only safety, so the description adds value but doesn't disclose every possible behavior.

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 description is concise but packs a lot of essential info in two sentences. It starts with the core purpose, then explains the response contents, adds a timing tip, a special case, and pagination guidance. It is efficient without being sparse, though it could be slightly more structured (e.g., bullet points) but that's not required. It's a good length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only status tool with only 3 parameters (well-documented in schema) and no output schema, the description covers the response structure, timing considerations, special cases, and pagination. This makes it complete enough for an agent to call correctly. The only minor gap is lack of explicit mention of what 'provider errors' look like, but that's not essential for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already has 100% coverage with descriptions for each parameter: `sendId` is explained (returned by send_notification), `limit` has defaults and max, and `cursor` is tied to `nextCursor`. The description reinforces pagination via the `nextCursor` but does not add much extra meaning beyond the schema. Baseline is 3 due to high coverage.

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?

The description clearly states the tool's purpose with a specific verb ('get') and resource ('send status'), and provides detailed details on the response: aggregate counts per status, per-recipient rows with provider errors. It distinguishes itself from other tools by focusing on delivery status, and the HTTP method and endpoint are stated explicitly.

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?

The description provides clear guidance on when to use the tool: to check delivery status after sending a notification. It notes that rows may be 'pending' initially and suggests checking again after a few seconds, offering practical usage tips. It also mentions that feed-only sends have no rows retreating directly from the tool's behavior, but does not explicitly state when not to use it or mention alternatives, so it's not a full 5.

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

get_templateGet templateA
Read-onlyIdempotent
Inspect

Get one template with its published version and its current draft (GET /templates/{id}): content, logTitle/logDescription, requiredParams a send must supply, and paramOverrides. Read this before update_template_draft, which needs the full body.

ParametersJSON Schema
NameRequiredDescriptionDefault
templateIdYesThe template id (UUID).

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint, covering the safety profile. The description adds useful behavioral context: the tool returns both the published version and current draft, includes requiredParams and paramOverrides, and is the required precursor to update_template_draft. It doesn't cover error cases or auth, but the annotations plus this context are sufficient for a read-only fetch.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no redundancy. The first sentence front-loads the endpoint and payload fields; the second provides critical usage guidance. Every clause earns its place.

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 simple read tool with one fully documented parameter and annotations covering safety, the description provides enough return-value detail despite no output schema: it names the key fields and the relationship to update_template_draft. An agent can confidently select and invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with the only parameter templateId fully documented as 'The template id (UUID).' The description confirms the parameter appears in the URL path but adds no new semantic detail beyond the schema, so the baseline score of 3 is appropriate.

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: 'Get one template with its published version and its current draft', and lists the exact fields returned (content, logTitle/logDescription, requiredParams, paramOverrides). It also gives the endpoint '(GET /templates/{id})', making it easy to distinguish from siblings like list_templates or update_template_draft.

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?

Explicitly tells the agent when to use this tool: 'Read this before update_template_draft, which needs the full body.' This names the sibling alternative and gives a clear sequencing rule, so an agent knows this is the prerequisite read for a specific downstream action.

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

get_usageGet plan and usageA
Read-onlyIdempotent
Inspect

The workspace's plan, subscription status and this calendar month's usage against the monthly quota (GET /billing/subscription). used/remaining are null on unmetered plans. On a hard-capped plan, sends beyond the quota fail with HTTP 402 quota_exceeded.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.9/5.0
Behavior3/5

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

Annotations already cover read-only, idempotent, non-destructive behaviorhol, so the description adds value by specifying that `used`/`remaining` are null on unmetered plans and that hard-capped plans return HTTP 402 quota_exceeded on sends. This is useful behavioral context beyond the annotations, though it doesn't detail the full response structure beyond those fields.

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 description is two sentences and front-loads the core purpose before adding edge-case details about unmetered plans and quota failures. Every sentence adds value, though the technical HTTP 402 detail could be slightly trimmed without losing essential meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (no params, no output schema), the description covers the key behavioral nuances: null values on unmetered plans and quota enforcement. It's complete enough for an agent to know when to call it and what to expect, though it could mention that this is account-scoped rather than template/webhook-scoped.

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?

There are zero parameters)Skip the schema covers 100% of parameter docs by having none, so the description carries no parameter burden. The tool's no-argument nature is implicit but the description adds clarity by explaining the output fields' semantics (used/remaining null on unmetered plans). This is enough given no params exist.

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?

The description clearly states the tool returns the workspace's plan, subscription status, and month-to-date usage against quota, and it also names the underlying endpoint (GET /billing/subscription). It distinguishes itself from the 20 sibling tools by focusing on billing/usage rather than templates, webhooks, or sends. This is a specific verb+resource definition.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

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

The description implies this tool is for checking billing/usage context, but it does not explicitly state when to use it vs. alternatives like whoami or list_* tools. It also doesn't mention that it's a zero-parameter call that gives account-level info. The context of when to check usage vs. other endpoints is left to the agent's inference.

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

get_webhookGet webhookA
Read-onlyIdempotent
Inspect

Get one outbound webhook (GET /tenant-webhooks/{id}) including its delivery health (consecutiveFailures, lastDeliveryAt, lastFailureAt, lastError).

ParametersJSON Schema
NameRequiredDescriptionDefault
webhookIdYesThe webhook id (UUID).

TDQS

A3.8/5.0
Behavior3/5

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

The annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, which clearly indicate this is a safe, non-mutating read operation. The description adds context about the specific fields returned (consecutiveFailures, lastDeliveryAt, lastFailureAt, lastError), which is useful for the agent. However, it doesn't disclose behaviors like caching, rate limiting, or error responses. Given the annotations cover the safety profile, the description adds some value but not extensive behavioral detail. It does not contradict the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence with no filler. It front-loads the essential action and resource (Get one outbound webhook), then adds a brief mention of the endpoint and the health fields. Every word is purposeful and contributes to the agent's understanding. It is appropriately sized and well-structured for quick consumption.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (one parameter, read-only, safe), the description is quite complete. It tells the agent what it does, what it returns (health fields), and the endpoint. Since the schema fully documents the parameter and there is no output schema, the description suffices to guide correct invocation. The only minor gap is not explicitly stating the tool is used to fetch a single webhook versus listing all, but that is arguably covered by the purpose clarity. Overall, it's complete for its complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides 100% coverage of the single parameter 'webhookId', including its type, format (UUID), pattern, and a description. This is comprehensive. The description does not add anything about the parameter itself; it only refers to 'one outbound webhook', which implicitly ties the parameter to a webhook resource. Since the schema fully documents the parameter, the description is not required to add more, but it also doesn't enhance the meaning beyond what's already there. Baseline 3 is appropriate.

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?

The description states a specific verb ('Get') and resource ('one outbound webhook'), and clearly identifies the tool's function: retrieving a single webhook by its ID. It also mentions the inclusion of delivery health fields, which distinguishes it from sibling tools like list_webhooks and update_webhook. The inclusion of the HTTP method (GET) and endpoint path provides additional clarity. An agent can immediately understand what this tool does and how it differs from other webhook-related tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

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

The description implies when to use this tool: when you need details about a specific webhook, including its delivery health. However, it does not explicitly state when not to use it or mention alternatives like list_webhooks for retrieving all webhooks. It also lacks guidance on prerequisites, such as the need to have a valid webhook ID. The description provides basic usage context but does not explicitly guide the agent on choosing between this and other webhook tools. Effective but not explicit.

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

list_channelsList channelsA
Read-onlyIdempotent
Inspect

List the delivery channels configured in this workspace (GET /channels). Call this FIRST before sending: each entry's id is the channelConfigId for send_notification and test_send_template, kind is the channel type (ses_email, smtp_email, fcm_push, slack_webhook, discord_webhook, telegram_bot, twilio_sms, sendsms_mn, generic_webhook), templateKind is the template channelKind it accepts, and recipientSchema is the exact JSON Schema of the recipient it expects. Channels and their provider credentials are set up in the Ray dashboard, not through this API; if the list is empty, ask the user to add one there.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already indicate read-only, idempotent, non-destructive behavior, so the description adds meaningful context beyond them. It discloses that channels are provisioned externally via the Ray dashboard, not through this API, and explains what each response field means (e.g., recipientSchema is the exact JSON Schema for the recipient). This goes well beyond the annotation safety profile.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no wasted words: endpoint, invocation order, field meanings, and external dependency are each packed in efficiently. The long enumeration of kind types is a trade-off that eliminates the need for the agent to look them up elsewhere, and the front-loaded 'List' + 'GET /channels' makes the purpose immediately obvious.

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 zero-parameter tool with no output schema, the description fully compensates by explaining the return structure and exactly how to use each field. It covers the full workflow: what to call first, how to consume the result, and what to do if the list is empty. Nothing an agent needs to invoke it correctly 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?

The input schema has zero parametersholidays, so there is nothing for the description to add – the rubric's 0-param baseline is 4. The description focuses instead on response semantics, which is the more important information for an agent since there are no inputs to configure.

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?

The description opens with a specific verb and resource ('List the delivery channels configured in this workspace') plus the exact endpoint (GET /channels). It explicitly ties the output fields (id, kind, templateKind, recipientSchema) to sibling tools like send_notification and test_send_template, making it unmistakably distinct from lists of templates or webhooks.

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?

The description gives explicit procedural guidance: 'Call this FIRST before sending' and explains that each entry's id is the channelConfigId for send_notification and test_send_template. It also specifies the fallback behavior for an empty list ('ask the user to add one there'), which is exactly the kind of when-to-use/when-not-to-use guidance an agent needs.

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

list_feed_notificationsList feed notificationsA
Read-onlyIdempotent
Inspect

Read one end user's in-app notification feed (GET /notifications): the entries created by sends with feed or showInFeed. This is what an in-app inbox would show, not delivery status (use get_send_status for that). Paginate by passing nextCursor back as cursor.

ParametersJSON Schema
NameRequiredDescriptionDefault
afterNoOnly entries created after this ISO 8601 UTC datetime (e.g. "2026-09-01T00:00:00Z").
limitNoEntries per page (default 50, max 200).
beforeNoOnly entries created before this ISO 8601 UTC datetime.
cursorNo`nextCursor` from the previous page.
templateIdNoOnly entries from this template.
externalUserIdYesThe end user whose feed to read (the `externalUserId` used when sending).
channelConfigIdNoOnly entries whose first delivery used this channel.

TDQS

A4.6/5.0
Behavior4/5

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

Annotations already declare readOnly, idempotent, and non-destructive behavior. The description adds meaningful context beyond annotations: the feed is specifically populated by sends with 'feed' or 'showInFeed', and pagination requires passing nextCursor back as cursor. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: what the tool reads, what it excludes, and how pagination works. The most important scope information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only feed tool with 7 parameters, high schema coverage, and annotations covering safety, the description is mostly complete. It identifies the resource type, the relevant send modes, and pagination flow. It does not describe output ordering, but no output schema is declared and this is a minor gap for a list-type operation.

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 100%, so the baseline is 3. The description adds useful parameter-related context by explaining the pagination contract ('Passing nextCursor back as cursor') and clarifying the feed's relationship to sends, which goes slightly beyond the schema's individual field descriptions.

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?

The description names the specific resource ('one end user's in-app notification feed'), the exact verb ('Read'), and the endpoint (GET /notifications). It also clearly differentiates this from delivery status, which is handled by get_send_status.

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?

It states exactly when to use this tool: to read in-app feed entries from sends with 'feed' or 'showInFeed'. It explicitly points to get_send_status as the alternative for delivery status, giving the agent clear routing guidance.

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

list_templatesList templatesA
Read-onlyIdempotent
Inspect

List message templates (GET /templates): id, name, folder, channelKind, and publishedVersionId (null = never published, so it cannot be sent by templateId yet). Archived templates are hidden unless includeArchived is true. Use get_template for content and required params.

ParametersJSON Schema
NameRequiredDescriptionDefault
folderNoOnly templates in this folder.
includeArchivedNoInclude archived templates. Default false.

TDQS

A4.5/5.0
Behavior4/5

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

Annotations already declare readOnly/idempotent/non-destructive, so the bar is lower. The description adds useful behavior beyond annotations: archived templates are excluded by default, and publishedVersionId null means the template has never been published and cannot yet be sent by templateId. There is no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler: endpoint, return fields, caveats, and sibling pointer are each given exactly one clause. The most decision-relevant information (what is listed and when archived templates appear) is front-loaded.

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 simple filtered list tool with readOnly/idempotent annotations, the description covers purpose, return fields, the one non-default flag, and the alternative for deeper content. No output schema exists, so the field enumeration and null semantics carry the necessary return-value explanation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3 and the description does not need to compensate. It restates includeArchived's effect but adds no new meaning to either parameter beyond what the input schema already documents.

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?

The description opens with a specific verb and resource ('List message templates') and names the exact endpoint plus the returned fields. It also distinguishes itself from get_template by delegating content and required params to that sibling, so an agent can tell the tools apart.

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?

It explicitly states that archived templates are hidden unless includeArchived is true, which tells the agent when to set that flag. It also gives an explicit alternative: 'Use get_template for content and required params,' covering the main when-not condition for this listing tool.

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

list_webhooksList webhooksA
Read-onlyIdempotent
Inspect

List the workspace's outbound event webhooks (GET /tenant-webhooks): url, subscribed events, enabled flag and delivery health (consecutiveFailures, lastError). Signing secrets are never returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
includeArchivedNoInclude deleted (archived) webhooks. Default false.

TDQS

A4.1/5.0
Behavior4/5

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

Annotations already cover the read-only, idempotent, and non-destructive nature of the operation. The description adds meaningful context by specifying the returned fields and explicitly stating that signing secrets are never returned, which is a useful safety-related disclosure beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single compact sentence that front-loads the verb, resource, and endpoint, then packs in the key return fields and the signing-secret caveat. There is no redundant or filler content.

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 simple list operation with rich annotations and only one optional parameter, the description is complete. It explains what the tool returns, includes the relevant endpoint, and adds a security note; the one parameter is already fully explained in the schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the includeArchived parameter is fully documented in the schema. The description does not add any additional parameter semantics, but it does not need to; the baseline of 3 applies.

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?

The description states a specific verb ('List') and resource ('the workspace's outbound event webhooks'), and enumerates what is included in the result. It is immediately distinguishable from sibling tools like get_webhook, delete_webhook, and update_webhook because it clearly frames this as a read-only listing operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

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

The description makes the tool's purpose clear enough that an agent can infer when to call it, but it never explicitly contrasts it with alternatives. It does not mention get_webhook for single-webhook retrieval or state when to prefer list_webhooks over the other webhook-related siblings.

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

publish_templatePublish templateAInspect

Publish a template's current draft as its new live version (POST /templates/{id}/publish; write scope). Sends by templateId use it immediately. Fails if there is no draft or the template is archived.

ParametersJSON Schema
NameRequiredDescriptionDefault
templateIdYesThe template id (UUID).

TDQS

A4.2/5.0
Behavior4/5

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

The description discloses key behavioral traits: it requires write scope, it fails if there is no draft or the template is archived, and it publishes immediately. The annotations already indicate it's not read-only, not idempotent, and not destructive, but the description adds context about the draft/live version mechanism and failure conditions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded with the core action, followed by the endpoint, scope requirement, and failure conditions. Every sentence earns its place with no waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter tool with a clear schema and annotations, the description is quite complete. It covers the action, the endpoint, the scope requirement, and failure conditions. It doesn't describe the return value, but there's no output schema and the tool is simple enough that this is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already provides 100% coverage for the single parameter (templateId) with a clear description. The description doesn't add much beyond the schema, but the baseline of 3 is appropriate since the schema does the heavy lifting.

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?

The description clearly states the action (publish a template's current draft as its new live version), the resource (template), and the endpoint (POST /templates/{id}/publish). It distinguishes itself from sibling tools like update_template_draft and archive_template by focusing on the publish action.

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?

The description provides clear context for when to use the tool: when you want to publish a template's draft as the live version. It also mentions failure conditions (no draft or archived template), which helps the agent decide when not to use it. However, it doesn't explicitly name alternative tools for those cases.

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

read_docsRead Ray docsA
Read-onlyIdempotent
Inspect

Read Ray's documentation as markdown. With no slug it returns the index (llms.txt) listing every page; then pass a page slug, i.e. the path after /docs/ without .md, such as sending, templates, idempotency, errors, rate-limits, webhooks, status-and-feeds or channels/telegram. Use it for anything the tool descriptions don't cover.

ParametersJSON Schema
NameRequiredDescriptionDefault
slugNoPage slug like "sending" or "channels/push-fcm". Omit for the index of all pages.

TDQS

A4.7/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds behavioral context beyond annotations by explaining the two modes (index vs. page) and the slug format requirement (path after /docs/ without .md). It doesn't mention rate limits or response size, but for a read-only docs tool the added context is sufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: it states the core function first, then explains the two modes, gives examples, and ends with usage guidance. Every sentence earns its place with no redundancy or filler.

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 simple read-only tool with one optional parameter and no output schema, the description is complete. It explains the two invocation modes, the slug format, provides examples, and states when to use the tool. The annotations cover the safety profile, and the schema covers the parameter. Nothing an agent needs to call it correctly 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 100%, so the schema already documents the slug parameter. The description adds value by explaining the slug format precisely (path after /docs/ without .md) and providing concrete examples, plus clarifying that omitting it returns the index. This goes beyond the schema's generic 'Page slug like...' description.

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?

The description clearly states the tool reads Ray's documentation as markdown, with a specific verb and resource. It distinguishes itself from siblings by being the documentation lookup tool, and explicitly says to use it for anything the tool descriptions don't cover, which differentiates it from the other API tools.

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?

The description provides explicit usage guidance: with no slug it returns the index, and with a slug it returns a specific page. It also gives concrete examples of valid slugs and states when to use it ('for anything the tool descriptions don't cover'), which is clear context for when to invoke this tool over alternatives.

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

send_notificationSend notificationAInspect

Send a notification (POST /send; needs a write-scoped key). Returns { sendId } with HTTP 202: delivery is asynchronous, so check the outcome with get_send_status. Use exactly one mode:

  1. Single: channelConfigId + recipient.

  2. Fan-out: channelConfigId + targets (1-1000 { recipient, externalUserId? }), one channel, one sendId.

  3. Multi-channel: deliveries (1-10, each with its own channelConfigId, recipient and templateId or content) for ONE person over several channels; add feed + externalUserId for a single in-app feed entry.

  4. Feed-only: feed (with title) + externalUserId and no channel: an in-app notification only. In modes 1-2 give exactly one of templateId (a published template, plus params) or inline content; in mode 3 that choice is made per delivery. Get channel ids and each recipient shape from list_channels first. Pass idempotencyKey whenever a retry must not deliver twice.

ParametersJSON Schema
NameRequiredDescriptionDefault
feedNoCreate exactly ONE in-app feed entry for `externalUserId` (read back with list_feed_notifications). `title`/`description` default to the rendered template text; `title` is required for a feed-only send (mode 4).
paramsNoValues for the template's `{{placeholders}}`. Any JSON: strings, numbers, booleans, arrays and nested objects (arrays/objects drive `{{#section}}…{{/section}}` blocks). Missing required params are rejected with a 400 naming them.
contentNoInline message content, used INSTEAD of `templateId` (give exactly one of the two). Shape by channel kind: ses_email / smtp_email → `{ subject, bodyHtml, bodyText }`; fcm_push → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_webhook → `{ text }` (Slack mrkdwn); discord_webhook → `{ content }` (max 2000 chars); telegram_bot → `{ text, disableLinkPreview? }` (Telegram HTML subset); twilio_sms / sendsms_mn → `{ text }` (plain text; up to 1600 chars on Twilio, sendsms_mn splits long text into SMS of 159 plain-Latin / 69 Cyrillic chars, each billed); generic_webhook → `{ title, body, data?: { [key]: string } }`. `{{name}}` placeholders are filled from `params` and escaped for the channel.
targetsNoMode 2: fan-out to 1-1000 recipients over ONE channel, sharing one sendId. Mutually exclusive with `recipient`.
logTitleNoFeed/log title for inline `content` sends only (template sends take it from the template). Placeholders allowed.
priorityNo"high" (default) for transactional messages; "low" for marketing/bulk so it never delays transactional sends.
notBeforeNoSchedule delivery for later: ISO 8601 datetime with offset, e.g. "2026-09-15T09:00:00+08:00". Omit to send now.
recipientNoMode 1: the single recipient. Mutually exclusive with `targets`. Channel-specific delivery target. Its shape depends on the kind of the chosen channel (list_channels returns each channel's exact `recipientSchema`): ses_email / smtp_email → `{ email, name?, cc?: [{ email, name? }], bcc?: [...], attachments?: [{ filename, content (base64), contentType?, disposition?: "attachment"|"inline", contentId? }] }`; fcm_push → `{ deviceToken }` OR `{ topic }` (exactly one; Ray keeps no device registry); telegram_bot → `{ chatId }` (numeric id as a string, or "@channelname"); twilio_sms → `{ phoneNumber }` (international E.164, e.g. "+97699112233"); sendsms_mn → `{ phoneNumber }` (Mongolian 8-digit, e.g. "99112233"); slack_webhook, discord_webhook, generic_webhook → `{}` (the destination is part of the channel config).
campaignIdNoFree-form campaign id used to group click stats across sends.
deliveriesNoMode 3: the same notification to ONE person over several channels (e.g. push + email), max 10. Each entry has its own channel, recipient and content source. Do not combine with top-level channelConfigId/recipient/targets/templateId/content.
showInFeedNoLegacy modes 1-2 flag: also add a feed entry for each target that has an externalUserId. Prefer `feed`. Not valid with `deliveries`.
templateIdNoModes 1-2: a PUBLISHED template to render (see list_templates / publish_template). Exactly one of `templateId` or `content`. Its channelKind must match the channel's `templateKind`.
trackClicksNoEmail channels only: rewrite links in bodyHtml so clicks are counted (read with get_click_stats). Default false.
externalUserIdNoYour own id for the end user. Required with `feed`; keys their in-app feed.
idempotencyKeyNoSent as the Idempotency-Key header. Retrying with the same key and same arguments returns the original sendId without sending again (24h window); the same key with different arguments fails with 409. Use a fresh unique value (e.g. a UUID) per logical notification.
logDescriptionNoFeed/log description for inline `content` sends only. Placeholders allowed.
channelConfigIdNoModes 1-2: the channel to send through — an `id` from list_channels. Not allowed together with `deliveries`.

TDQS

A4.4/5.0
Behavior5/5

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

Annotations only convey mutating, non-idempotent, open-world, non-destructive; the description adds the consequential traits: asynchronous delivery (HTTP 202 with sendId), the need for write-scoped credentials, billing behavior for sendsms_mn (splits long text and bills each SMS), and the mandate to pass idempotencyKey when a retry must not deliver twice. This context goes well beyond what the annotations express, and nothing contradicts them.

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?

Critical facts (endpoint, auth, async return) are front-loaded, and the modes are structured as a numbered list with exclusive parameter sets. The length is significant, but the per-mode constraints are load-bearing for a 17-parameter tool rather than padding. Every sentence earns its place.

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?

There is no output schema, but the description supplies the return shape { sendId }, the HTTP 202 async semantics, and routes follow-up to get_send_status. Prerequisite discovery (list_channels for ids and recipient schemas; list_templates/publish_template for templates) is covered in description and schema, and error behavior (400 naming missing params, 409 on repeated key) is described. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so each parameter is already documented in the schema, including channel-specific content/recipient shapes and mutual exclusions. The description adds a useful mode taxonomy that organizes the 17 parameters, but it introduces no per-parameter facts beyond what the schema already provides. Baseline 3 applies.

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 ('Send'), resource ('notification'), the endpoint (POST /send), required auth scope ('write'-scoped key) and the immediate return contract ({ sendId } with HTTP 202). The scope is cleanly separated from siblings like get_send_status (outcome checking) and test_send_template (testing a template).

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?

The description enumerates four mutually exclusive modes with exact parameter combinations, names prerequisites ('Get channel ids and each recipient shape from list_channels first') and the follow-up tool ('check the outcome with get_send_status'). It also gives a conditional rule for idempotencyKey. It does not explicitly point at test_send_template as the 'try before delivering' alternative, which is a minor gap.

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

test_send_templateTest-send templateAInspect

Send a real test of a template's PUBLISHED version to one recipient (POST /templates/{id}/test-send; write scope). It goes through the provider for real, so use a recipient the user controls. Test sends don't count toward the monthly quota (a small daily allowance applies instead) and never appear in feeds. Returns { sendId } for get_send_status.

ParametersJSON Schema
NameRequiredDescriptionDefault
paramsNoValues for the template's `{{placeholders}}`. Any JSON: strings, numbers, booleans, arrays and nested objects (arrays/objects drive `{{#section}}…{{/section}}` blocks). Missing required params are rejected with a 400 naming them.
recipientYesChannel-specific delivery target. Its shape depends on the kind of the chosen channel (list_channels returns each channel's exact `recipientSchema`): ses_email / smtp_email → `{ email, name?, cc?: [{ email, name? }], bcc?: [...], attachments?: [{ filename, content (base64), contentType?, disposition?: "attachment"|"inline", contentId? }] }`; fcm_push → `{ deviceToken }` OR `{ topic }` (exactly one; Ray keeps no device registry); telegram_bot → `{ chatId }` (numeric id as a string, or "@channelname"); twilio_sms → `{ phoneNumber }` (international E.164, e.g. "+97699112233"); sendsms_mn → `{ phoneNumber }` (Mongolian 8-digit, e.g. "99112233"); slack_webhook, discord_webhook, generic_webhook → `{}` (the destination is part of the channel config).
templateIdYesThe template id (UUID).
channelConfigIdYesChannel to test through (from list_channels); its templateKind must match the template's channelKind.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations only say readOnlyHint=false, openWorldHint=true, idempotentHint=false, destructiveHint=false. The description adds significant behavioral detail beyond that: the send goes through the real provider, it is not counted against monthly quota but uses a daily allowance, it never appears in feeds, and it returns a sendId. This fully informs the agent of side effects and result.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each carrying distinct value: operation and auth scope, real-provider warning, quota/feed behavior, and return value. Critical side effects are front-loaded right after the purpose, with no tautology or filler.

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 4-parameter, nested-object tool with no output schema and minimal annotations, the description covers purpose, real-world side effects, quota implications, feed visibility, and return shape. Combined with the exhaustive schema, nothing needed to invoke the tool correctly 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?

The input schema already covers all parameters at 100%, including detailed recipient shapes, so the baseline is 3. The description adds meaningful extra semantics by specifying that the PUBLISHED version of the template is sent and that exactly one recipient is targeted, which clarifies how templateId and recipient are interpreted.

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?

The first sentence names a specific verb ('Send'), a specific resource ('a template's PUBLISHED version'), and a scope ('to one recipient'), so an agent knows exactly what operation this is. It also signals this is a test send, distinguishing it from production send siblings like send_notification without needing to open schemas.

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?

The description establishes clear usage context: use a recipient the user controls because the send is real, test sends have a separate daily allowance rather than monthly quota, and they never appear in feeds. It does not explicitly name send_notification as the alternative for real production sends, so it stops short of full when-to-use/when-not-to-use guidance.

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

unarchive_templateUnarchive templateA
Idempotent
Inspect

Restore an archived template (POST /templates/{id}/unarchive; write scope). This is how to reclaim a name held by an archived template instead of creating a new one.

ParametersJSON Schema
NameRequiredDescriptionDefault
templateIdYesThe template id (UUID).

TDQS

A4.3/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true, and destructiveHint=false, so the core safety profile is covered. The description adds the behavioral context of restoring an archived template and reclaiming a name, which is useful beyond the annotations. It does not add further details like response behavior or side effects, but the annotations lower the burden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The purpose is front-loaded, the endpoint provides precise grounding, and the alternative use case is stated in the second sentence. Every word earns its place.

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 single-parameter, no-output-schema tool, the description plus annotations and schema fully cover what an agent needs: what the tool does, when to use it, the parameter format, and the safe/idempotent behavior. Nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and the single parameter templateId already has a clear description ('The template id (UUID).'). The tool description adds no additional parameter-level meaning, so the baseline of 3 applies.

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?

The description opens with a specific verb and resource: "Restore an archived template". It then names the HTTP endpoint, which unambiguously identifies the operation, and contrasts it with creating a new template. This clearly differentiates the tool from siblings like archive_template and create_template.

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?

The description explicitly states when to use this tool: "This is how to reclaim a name held by an archived template". It also names the alternative behavior it replaces ("instead of creating a new one"). This gives an agent a concrete decision rule for selection among siblings.

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

update_template_draftUpdate template draftAInspect

Replace a template's draft (PATCH /templates/{id}; write scope). This is a full replacement, not a partial patch: pass content, logTitle, logDescription and paramOverrides as they should end up (get_template first). name, folder and channelKind are required for validation but not changed (channelKind must equal the original). Live sends keep using the published version until you publish, either with publish: true here or publish_template. Fails on archived templates.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesTemplate name, unique per workspace (archived templates included).
folderNoOptional folder path for organisation, e.g. "billing".
contentYesChannel-shaped template body; the shape is fixed by `channelKind`: email_html → `{ subject, bodyHtml, bodyText }`; fcm_basic → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_text → `{ text }`; discord_text → `{ content }` (max 2000 chars); telegram_text → `{ text, disableLinkPreview? }`; sms_text → `{ text }` (plain text, max 1600; long text is split into several billed SMS — on sendsms_mn into parts of 159 plain-Latin / 69 Cyrillic chars); webhook_json → `{ title, body, data?: { [key]: string } }`. Use `{{name}}` placeholders and `{{#items}}…{{/items}}` sections; the required params are derived from them automatically.
publishNotrue = publish this version immediately so sends by templateId use it. Default false (saved as draft).
logTitleYesShort title shown in the in-app feed and delivery logs, e.g. "Invoice {{number}} is due". Placeholders allowed.
templateIdYesThe template id (UUID).
channelKindYesWhich channel family the template renders for. Must match the `templateKind` of the channels you will send through (list_channels). Can't be changed after creation.
logDescriptionYesOne-line description for the in-app feed and delivery logs. Placeholders allowed.
paramOverridesNoPer-param metadata keyed by param name: `{ optional?: boolean, description?: string }`. Mark a placeholder optional so sends may omit it.

TDQS

A4.9/5.0
Behavior5/5

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

Annotations only provide read/write hints, so the description carries the behavioral burden and does it well: full replacement vs merge, draft-not-live semantics, publish-triggering behavior, and the archived-template failure case are all disclosed. This goes far beyond what the sparse annotations convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four dense sentences carry a large amount of information with no filler. Critical constraints are front-loaded: full replacement first, then required-but-unchanged fields, then live-publish behavior and failure conditions.

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?

Despite having no output schema, the description covers all invocation-critical context: mutation semantics, required fields, publish behavior, and error case. The rich param schema already handles per-field details, so nothing needed for correct use 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 coverage is 100%, so the schema already documents each parameter thoroughly. The description adds valuable cross-parameter semantics: `name`, `folder`, and `channelKind` must be passed but are not changed, `channelKind` must match the original, and `paramOverrides` should be passed as the final desired state. This meaningfully supplements the schema.

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?

The description opens with a specific verb and resource: 'Replace a template's draft', and clarifies the HTTP operation (PATCH /templates/{id}). It distinguishes itself from a partial patch and implicitly from publish_template by explaining the publish flow, making the tool's purpose unmistakable.

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?

It explicitly tells the agent to call get_template first, says which fields are required for validation but not changed, and names the sibling publish_template as the alternative or the `publish: true` flag. It even warns about archived templates failing, leaving no ambiguity about when and how to use this tool.

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

update_webhookUpdate webhookAInspect

Change a webhook (PATCH /tenant-webhooks/{id}; write scope). Only the fields you pass change; pass at least one. rotateSecret: true issues a new signing secret, returned once in the response, and the old secret stops verifying immediately, so the receiving service must be updated at the same time.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoNew public HTTPS endpoint.
nameNoNew label.
eventsNoReplaces the subscribed events. Events to receive: "notification.delivered", "notification.failed_terminal" (one per recipient), and "send.completed" (once per send, with status totals).
enabledNofalse pauses deliveries without deleting the webhook.
webhookIdYesThe webhook id (UUID).
rotateSecretNotrue rotates the signing secret (new secret returned once; old one invalid immediately).

TDQS

A4.7/5.0
Behavior5/5

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

Annotations only provide readOnly=false, so the description carries the burden of exposing mutation behavior. It discloses write scope, one-time secret return, immediate invalidation of the old secret, and the coordination requirement for rotateSecret, going well beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences carry the essential information with no redundancy. The endpoint and primary purpose are front-loaded, and the rotateSecret warning is placed where it matters most.

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?

Given no output schema, the description still covers the output-critical behavior: a new signing secret is returned once. Combined with the rich schema, an agent has enough to call this tool correctly, including the operational risk of rotating the secret.

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 100%, so the baseline is 3, and the description adds additional meaningful semantics: partial update, requiring at least one field, and the special side-effect of rotateSecret. It focuses on the riskiest parameter rather than duplicating the schema.

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?

The description states a specific verb ('Change'), a specific resource ('a webhook'), and the endpoint/method (PATCH /tenant-webhooks/{id}). This clearly separates it from sibling tools like create_webhook, delete_webhook, get_webhook, and list_webhooks.

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?

It makes the intended usage clear with partial-update semantics ('Only the fields you pass change; pass at least one') and gives a strong caution for rotateSecret. It does not explicitly enumerate when to prefer this tool over sibling alternatives, but the context is unambiguous.

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

whoamiWho am IA
Read-onlyIdempotent
Inspect

Identify the API key this connection uses (GET /me): tenantId (the workspace), apiKeyId and scopes. Write tools need the write scope; call this to check before attempting them.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.9/5.0
Behavior5/5

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

Annotations already mark the tool as read-only, idempotent, and non-destructive. The description adds important behavioral context beyond that by specifying what the endpoint returns (tenantId, apiKeyId, scopes) and why the scope info matters. Since there is no output schema, this return-value disclosure is especially valuable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the first states the purpose and result fields, the second gives the operational trigger. Every phrase earns its place, and the most actionable guidance comes immediately after the core purpose.

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 zero-parameter identity-check tool, the description is complete: it explains what the tool does, what it returns, and when to call it. Annotations cover the safety profile, and no output schema is needed because the description names the key return fields.

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?

The tool has zero parameters, so the baseline is 4. The description appropriately focuses on the output rather than inputs; no additional parameter documentation is needed.

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?

The description uses a specific verb ('Identify') and resource ('the API key this connection uses'), and names the returned fields (tenantId, apiKeyId, scopes). It is immediately distinct from all sibling tools, which focus on templates, webhooks, notifications, and stats.

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?

The description explicitly states when to call the tool: before attempting write tools, because they need the `write` scope. This gives an agent a clear decision rule despite the tool having no obvious siblings performing a similar function.

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

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updates
    • Changedcreate_template1 field changed
      • changedInput schema / properties / content / description
        Previous value: -"Channel-shaped template body; the shape is fixed by `channelKind`: email_html → `{ subject, bodyHtml, bodyText }`; fcm_basic → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_text → `{ text }`; discord_text → `{ content }` (max 2000 chars); telegram_text → `{ text, disableLinkPreview? }`; sms_text → `{ text }` (plain text, max 1600; sendsms_mn channels only send up to 159 chars after rendering); webhook_json → `{ title, body, data?: { [key]: string } }`. Use `{{name}}` placeholders and `{{#items}}…{{/items}}` sections; the required params are derived from them automatically."New value: +"Channel-shaped template body; the shape is fixed by `channelKind`: email_html → `{ subject, bodyHtml, bodyText }`; fcm_basic → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_text → `{ text }`; discord_text → `{ content }` (max 2000 chars); telegram_text → `{ text, disableLinkPreview? }`; sms_text → `{ text }` (plain text, max 1600; long text is split into several billed SMS — on sendsms_mn into parts of 159 plain-Latin / 69 Cyrillic chars); webhook_json → `{ title, body, data?: { [key]: string } }`. Use `{{name}}` placeholders and `{{#items}}…{{/items}}` sections; the required params are derived from them automatically."
    • Changedsend_notification2 fields changed
      • changedInput schema / properties / content / description
        Previous value: -"Inline message content, used INSTEAD of `templateId` (give exactly one of the two). Shape by channel kind: ses_email / smtp_email → `{ subject, bodyHtml, bodyText }`; fcm_push → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_webhook → `{ text }` (Slack mrkdwn); discord_webhook → `{ content }` (max 2000 chars); telegram_bot → `{ text, disableLinkPreview? }` (Telegram HTML subset); twilio_sms / sendsms_mn → `{ text }` (plain text; up to 1600 chars on Twilio, at most 159 after rendering on sendsms_mn); generic_webhook → `{ title, body, data?: { [key]: string } }`. `{{name}}` placeholders are filled from `params` and escaped for the channel."New value: +"Inline message content, used INSTEAD of `templateId` (give exactly one of the two). Shape by channel kind: ses_email / smtp_email → `{ subject, bodyHtml, bodyText }`; fcm_push → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_webhook → `{ text }` (Slack mrkdwn); discord_webhook → `{ content }` (max 2000 chars); telegram_bot → `{ text, disableLinkPreview? }` (Telegram HTML subset); twilio_sms / sendsms_mn → `{ text }` (plain text; up to 1600 chars on Twilio, sendsms_mn splits long text into SMS of 159 plain-Latin / 69 Cyrillic chars, each billed); generic_webhook → `{ title, body, data?: { [key]: string } }`. `{{name}}` placeholders are filled from `params` and escaped for the channel."
      • changedInput schema / properties / deliveries / items / properties / content / description
        Previous value: -"Inline message content, used INSTEAD of `templateId` (give exactly one of the two). Shape by channel kind: ses_email / smtp_email → `{ subject, bodyHtml, bodyText }`; fcm_push → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_webhook → `{ text }` (Slack mrkdwn); discord_webhook → `{ content }` (max 2000 chars); telegram_bot → `{ text, disableLinkPreview? }` (Telegram HTML subset); twilio_sms / sendsms_mn → `{ text }` (plain text; up to 1600 chars on Twilio, at most 159 after rendering on sendsms_mn); generic_webhook → `{ title, body, data?: { [key]: string } }`. `{{name}}` placeholders are filled from `params` and escaped for the channel."New value: +"Inline message content, used INSTEAD of `templateId` (give exactly one of the two). Shape by channel kind: ses_email / smtp_email → `{ subject, bodyHtml, bodyText }`; fcm_push → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_webhook → `{ text }` (Slack mrkdwn); discord_webhook → `{ content }` (max 2000 chars); telegram_bot → `{ text, disableLinkPreview? }` (Telegram HTML subset); twilio_sms / sendsms_mn → `{ text }` (plain text; up to 1600 chars on Twilio, sendsms_mn splits long text into SMS of 159 plain-Latin / 69 Cyrillic chars, each billed); generic_webhook → `{ title, body, data?: { [key]: string } }`. `{{name}}` placeholders are filled from `params` and escaped for the channel."
    • Changedupdate_template_draft1 field changed
      • changedInput schema / properties / content / description
        Previous value: -"Channel-shaped template body; the shape is fixed by `channelKind`: email_html → `{ subject, bodyHtml, bodyText }`; fcm_basic → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_text → `{ text }`; discord_text → `{ content }` (max 2000 chars); telegram_text → `{ text, disableLinkPreview? }`; sms_text → `{ text }` (plain text, max 1600; sendsms_mn channels only send up to 159 chars after rendering); webhook_json → `{ title, body, data?: { [key]: string } }`. Use `{{name}}` placeholders and `{{#items}}…{{/items}}` sections; the required params are derived from them automatically."New value: +"Channel-shaped template body; the shape is fixed by `channelKind`: email_html → `{ subject, bodyHtml, bodyText }`; fcm_basic → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_text → `{ text }`; discord_text → `{ content }` (max 2000 chars); telegram_text → `{ text, disableLinkPreview? }`; sms_text → `{ text }` (plain text, max 1600; long text is split into several billed SMS — on sendsms_mn into parts of 159 plain-Latin / 69 Cyrillic chars); webhook_json → `{ title, body, data?: { [key]: string } }`. Use `{{name}}` placeholders and `{{#items}}…{{/items}}` sections; the required params are derived from them automatically."
  2. 4 tool updates
    • Changedcreate_template2 fields changed
      • changedInput schema / properties / channelKind / enum
        Previous value: -[
        -  "email_html",
        -  "fcm_basic",
        -  "slack_text",
        -  "discord_text",
        -  "telegram_text",
        -  "webhook_json"
        -]New value: +[
        +  "email_html",
        +  "fcm_basic",
        +  "slack_text",
        +  "discord_text",
        +  "telegram_text",
        +  "sms_text",
        +  "webhook_json"
        +]
      • changedInput schema / properties / content / description
        Previous value: -"Channel-shaped template body; the shape is fixed by `channelKind`: email_html → `{ subject, bodyHtml, bodyText }`; fcm_basic → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_text → `{ text }`; discord_text → `{ content }` (max 2000 chars); telegram_text → `{ text, disableLinkPreview? }`; webhook_json → `{ title, body, data?: { [key]: string } }`. Use `{{name}}` placeholders and `{{#items}}…{{/items}}` sections; the required params are derived from them automatically."New value: +"Channel-shaped template body; the shape is fixed by `channelKind`: email_html → `{ subject, bodyHtml, bodyText }`; fcm_basic → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_text → `{ text }`; discord_text → `{ content }` (max 2000 chars); telegram_text → `{ text, disableLinkPreview? }`; sms_text → `{ text }` (plain text, max 1600; sendsms_mn channels only send up to 159 chars after rendering); webhook_json → `{ title, body, data?: { [key]: string } }`. Use `{{name}}` placeholders and `{{#items}}…{{/items}}` sections; the required params are derived from them automatically."
    • Changedsend_notification5 fields changed
      • changedInput schema / properties / content / description
        Previous value: -"Inline message content, used INSTEAD of `templateId` (give exactly one of the two). Shape by channel kind: ses_email / smtp_email → `{ subject, bodyHtml, bodyText }`; fcm_push → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_webhook → `{ text }` (Slack mrkdwn); discord_webhook → `{ content }` (max 2000 chars); telegram_bot → `{ text, disableLinkPreview? }` (Telegram HTML subset); generic_webhook → `{ title, body, data?: { [key]: string } }`. `{{name}}` placeholders are filled from `params` and escaped for the channel."New value: +"Inline message content, used INSTEAD of `templateId` (give exactly one of the two). Shape by channel kind: ses_email / smtp_email → `{ subject, bodyHtml, bodyText }`; fcm_push → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_webhook → `{ text }` (Slack mrkdwn); discord_webhook → `{ content }` (max 2000 chars); telegram_bot → `{ text, disableLinkPreview? }` (Telegram HTML subset); twilio_sms / sendsms_mn → `{ text }` (plain text; up to 1600 chars on Twilio, at most 159 after rendering on sendsms_mn); generic_webhook → `{ title, body, data?: { [key]: string } }`. `{{name}}` placeholders are filled from `params` and escaped for the channel."
      • changedInput schema / properties / deliveries / items / properties / content / description
        Previous value: -"Inline message content, used INSTEAD of `templateId` (give exactly one of the two). Shape by channel kind: ses_email / smtp_email → `{ subject, bodyHtml, bodyText }`; fcm_push → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_webhook → `{ text }` (Slack mrkdwn); discord_webhook → `{ content }` (max 2000 chars); telegram_bot → `{ text, disableLinkPreview? }` (Telegram HTML subset); generic_webhook → `{ title, body, data?: { [key]: string } }`. `{{name}}` placeholders are filled from `params` and escaped for the channel."New value: +"Inline message content, used INSTEAD of `templateId` (give exactly one of the two). Shape by channel kind: ses_email / smtp_email → `{ subject, bodyHtml, bodyText }`; fcm_push → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_webhook → `{ text }` (Slack mrkdwn); discord_webhook → `{ content }` (max 2000 chars); telegram_bot → `{ text, disableLinkPreview? }` (Telegram HTML subset); twilio_sms / sendsms_mn → `{ text }` (plain text; up to 1600 chars on Twilio, at most 159 after rendering on sendsms_mn); generic_webhook → `{ title, body, data?: { [key]: string } }`. `{{name}}` placeholders are filled from `params` and escaped for the channel."
      • changedInput schema / properties / deliveries / items / properties / recipient / description
        Previous value: -"Channel-specific delivery target. Its shape depends on the kind of the chosen channel (list_channels returns each channel's exact `recipientSchema`): ses_email / smtp_email → `{ email, name?, cc?: [{ email, name? }], bcc?: [...], attachments?: [{ filename, content (base64), contentType?, disposition?: \"attachment\"|\"inline\", contentId? }] }`; fcm_push → `{ deviceToken }` OR `{ topic }` (exactly one; Ray keeps no device registry); telegram_bot → `{ chatId }` (numeric id as a string, or \"@channelname\"); slack_webhook, discord_webhook, generic_webhook → `{}` (the destination is part of the channel config)."New value: +"Channel-specific delivery target. Its shape depends on the kind of the chosen channel (list_channels returns each channel's exact `recipientSchema`): ses_email / smtp_email → `{ email, name?, cc?: [{ email, name? }], bcc?: [...], attachments?: [{ filename, content (base64), contentType?, disposition?: \"attachment\"|\"inline\", contentId? }] }`; fcm_push → `{ deviceToken }` OR `{ topic }` (exactly one; Ray keeps no device registry); telegram_bot → `{ chatId }` (numeric id as a string, or \"@channelname\"); twilio_sms → `{ phoneNumber }` (international E.164, e.g. \"+97699112233\"); sendsms_mn → `{ phoneNumber }` (Mongolian 8-digit, e.g. \"99112233\"); slack_webhook, discord_webhook, generic_webhook → `{}` (the destination is part of the channel config)."
      • changedInput schema / properties / recipient / description
        Previous value: -"Mode 1: the single recipient. Mutually exclusive with `targets`. Channel-specific delivery target. Its shape depends on the kind of the chosen channel (list_channels returns each channel's exact `recipientSchema`): ses_email / smtp_email → `{ email, name?, cc?: [{ email, name? }], bcc?: [...], attachments?: [{ filename, content (base64), contentType?, disposition?: \"attachment\"|\"inline\", contentId? }] }`; fcm_push → `{ deviceToken }` OR `{ topic }` (exactly one; Ray keeps no device registry); telegram_bot → `{ chatId }` (numeric id as a string, or \"@channelname\"); slack_webhook, discord_webhook, generic_webhook → `{}` (the destination is part of the channel config)."New value: +"Mode 1: the single recipient. Mutually exclusive with `targets`. Channel-specific delivery target. Its shape depends on the kind of the chosen channel (list_channels returns each channel's exact `recipientSchema`): ses_email / smtp_email → `{ email, name?, cc?: [{ email, name? }], bcc?: [...], attachments?: [{ filename, content (base64), contentType?, disposition?: \"attachment\"|\"inline\", contentId? }] }`; fcm_push → `{ deviceToken }` OR `{ topic }` (exactly one; Ray keeps no device registry); telegram_bot → `{ chatId }` (numeric id as a string, or \"@channelname\"); twilio_sms → `{ phoneNumber }` (international E.164, e.g. \"+97699112233\"); sendsms_mn → `{ phoneNumber }` (Mongolian 8-digit, e.g. \"99112233\"); slack_webhook, discord_webhook, generic_webhook → `{}` (the destination is part of the channel config)."
      • changedInput schema / properties / targets / items / properties / recipient / description
        Previous value: -"Channel-specific delivery target. Its shape depends on the kind of the chosen channel (list_channels returns each channel's exact `recipientSchema`): ses_email / smtp_email → `{ email, name?, cc?: [{ email, name? }], bcc?: [...], attachments?: [{ filename, content (base64), contentType?, disposition?: \"attachment\"|\"inline\", contentId? }] }`; fcm_push → `{ deviceToken }` OR `{ topic }` (exactly one; Ray keeps no device registry); telegram_bot → `{ chatId }` (numeric id as a string, or \"@channelname\"); slack_webhook, discord_webhook, generic_webhook → `{}` (the destination is part of the channel config)."New value: +"Channel-specific delivery target. Its shape depends on the kind of the chosen channel (list_channels returns each channel's exact `recipientSchema`): ses_email / smtp_email → `{ email, name?, cc?: [{ email, name? }], bcc?: [...], attachments?: [{ filename, content (base64), contentType?, disposition?: \"attachment\"|\"inline\", contentId? }] }`; fcm_push → `{ deviceToken }` OR `{ topic }` (exactly one; Ray keeps no device registry); telegram_bot → `{ chatId }` (numeric id as a string, or \"@channelname\"); twilio_sms → `{ phoneNumber }` (international E.164, e.g. \"+97699112233\"); sendsms_mn → `{ phoneNumber }` (Mongolian 8-digit, e.g. \"99112233\"); slack_webhook, discord_webhook, generic_webhook → `{}` (the destination is part of the channel config)."
    • Changedtest_send_template1 field changed
      • changedInput schema / properties / recipient / description
        Previous value: -"Channel-specific delivery target. Its shape depends on the kind of the chosen channel (list_channels returns each channel's exact `recipientSchema`): ses_email / smtp_email → `{ email, name?, cc?: [{ email, name? }], bcc?: [...], attachments?: [{ filename, content (base64), contentType?, disposition?: \"attachment\"|\"inline\", contentId? }] }`; fcm_push → `{ deviceToken }` OR `{ topic }` (exactly one; Ray keeps no device registry); telegram_bot → `{ chatId }` (numeric id as a string, or \"@channelname\"); slack_webhook, discord_webhook, generic_webhook → `{}` (the destination is part of the channel config)."New value: +"Channel-specific delivery target. Its shape depends on the kind of the chosen channel (list_channels returns each channel's exact `recipientSchema`): ses_email / smtp_email → `{ email, name?, cc?: [{ email, name? }], bcc?: [...], attachments?: [{ filename, content (base64), contentType?, disposition?: \"attachment\"|\"inline\", contentId? }] }`; fcm_push → `{ deviceToken }` OR `{ topic }` (exactly one; Ray keeps no device registry); telegram_bot → `{ chatId }` (numeric id as a string, or \"@channelname\"); twilio_sms → `{ phoneNumber }` (international E.164, e.g. \"+97699112233\"); sendsms_mn → `{ phoneNumber }` (Mongolian 8-digit, e.g. \"99112233\"); slack_webhook, discord_webhook, generic_webhook → `{}` (the destination is part of the channel config)."
    • Changedupdate_template_draft2 fields changed
      • changedInput schema / properties / channelKind / enum
        Previous value: -[
        -  "email_html",
        -  "fcm_basic",
        -  "slack_text",
        -  "discord_text",
        -  "telegram_text",
        -  "webhook_json"
        -]New value: +[
        +  "email_html",
        +  "fcm_basic",
        +  "slack_text",
        +  "discord_text",
        +  "telegram_text",
        +  "sms_text",
        +  "webhook_json"
        +]
      • changedInput schema / properties / content / description
        Previous value: -"Channel-shaped template body; the shape is fixed by `channelKind`: email_html → `{ subject, bodyHtml, bodyText }`; fcm_basic → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_text → `{ text }`; discord_text → `{ content }` (max 2000 chars); telegram_text → `{ text, disableLinkPreview? }`; webhook_json → `{ title, body, data?: { [key]: string } }`. Use `{{name}}` placeholders and `{{#items}}…{{/items}}` sections; the required params are derived from them automatically."New value: +"Channel-shaped template body; the shape is fixed by `channelKind`: email_html → `{ subject, bodyHtml, bodyText }`; fcm_basic → `{ title, body, imageUrl?, data?: { [key]: string } }`; slack_text → `{ text }`; discord_text → `{ content }` (max 2000 chars); telegram_text → `{ text, disableLinkPreview? }`; sms_text → `{ text }` (plain text, max 1600; sendsms_mn channels only send up to 159 chars after rendering); webhook_json → `{ title, body, data?: { [key]: string } }`. Use `{{name}}` placeholders and `{{#items}}…{{/items}}` sections; the required params are derived from them automatically."
  3. 21 tool updates
    • First observedarchive_template
    • First observedcreate_template
    • First observedcreate_webhook
    • First observeddelete_webhook
    • First observedget_click_stats
    • First observedget_send_status
    • First observedget_template
    • First observedget_usage
    • First observedget_webhook
    • First observedlist_channels
    • First observedlist_feed_notifications
    • First observedlist_templates
    • First observedlist_webhooks
    • First observedpublish_template
    • First observedread_docs
    • First observedsend_notification
    • First observedtest_send_template
    • First observedunarchive_template
    • First observedupdate_template_draft
    • First observedupdate_webhook
    • First observedwhoami

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    Enables sending rich notifications to Discord and/or Slack webhooks with automatic service detection, retry logic, and support for embeds, blocks, and attachments. Provides secure webhook management with comprehensive input validation and rate limiting.
    3
    TypeScript
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Unified notification MCP server with 36 tools to send messages across 23 channels — Email, SMS, Slack, Telegram, Discord, Teams, WhatsApp, Firebase Push, and more.
    5
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables agents and applications to send notifications through configurable channels such as Telegram or a JSONL file, with queued delivery, status tracking, idempotency, and event-based routing.
    2
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables agents to send structured notifications to recipients via configurable channels (initial SMTP provider) without exposing delivery addresses or credentials, with tools for listing recipients, listing channels, and sending notifications.
    -
Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.