protogrid

Search / io.github.gege-mn/ray-mcp

Ray notifications

R1· needs a key

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

v0.1.0 · active · repository · website · descriptor JSON · versions

An agent can connect on its own if it already holds ray_api_key.Remote endpoint behind a static API key or header. The registry never sees the value; the agent fills the placeholder.
Quality82good
Trust94of 100
Uptime, 30 days98%
Latency p50620 ms

Connect

8 clients · secrets stay placeholders
{
  "mcpServers": {
    "ray-mcp": {
      "type": "http",
      "url": "https://ray-api.gege.mn/mcp",
      "headers": {
        "Authorization": "Bearer ${ray_api_key}"
      }
    }
  }
}
claude mcp add --transport http ray-mcp https://ray-api.gege.mn/mcp --header "Authorization: Bearer ${ray_api_key}"
[mcp_servers.ray-mcp]
url = "https://ray-api.gege.mn/mcp"
bearer_token_env_var = "ray_api_key"
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ray-mcp": {
      "type": "remote",
      "url": "https://ray-api.gege.mn/mcp",
      "enabled": true,
      "headers": {
        "Authorization": "Bearer {env:ray_api_key}"
      }
    }
  }
}
{
  "mcpServers": {
    "ray-mcp": {
      "type": "http",
      "url": "https://ray-api.gege.mn/mcp",
      "headers": {
        "Authorization": "Bearer ${ray_api_key}"
      }
    }
  },
  "deeplink": "cursor://anysphere.cursor-deeplink/mcp/install?name=ray-mcp&config=eyJ0eXBlIjoiaHR0cCIsInVybCI6Imh0dHBzOi8vcmF5LWFwaS5nZWdlLm1uL21jcCIsImhlYWRlcnMiOnsiQXV0aG9yaXphdGlvbiI6IkJlYXJlciAke3JheV9hcGlfa2V5fSJ9fQ%3D%3D"
}
{
  "servers": {
    "ray-mcp": {
      "type": "http",
      "url": "https://ray-api.gege.mn/mcp",
      "headers": {
        "Authorization": "Bearer ${ray_api_key}"
      }
    }
  }
}
{
  "mcpServers": {
    "ray-mcp": {
      "httpUrl": "https://ray-api.gege.mn/mcp",
      "headers": {
        "Authorization": "Bearer ${ray_api_key}"
      }
    }
  }
}
extensions:
  "ray-mcp":
    enabled: true
    name: "ray-mcp"
    type: streamable_http
    uri: "https://ray-api.gege.mn/mcp"
    headers:
      "Authorization": "Bearer ${ray_api_key}"
    timeout: 300

Placeholders to fill from your own secret store: ${ray_api_key}. The registry never accepts secret values.

Quality 82 / 100good

protocol75 · weight 25
  • warn
    protocol.modernnewest supported version is 2025-11-25; 2026-07-28 not supported, older versions are deprecated until 2027-07-28
  • n/a
    protocol.statelessonly applies to 2026-07-28 servers
  • pass
    protocol.transportstreamable HTTP
  • n/a
    protocol.list_ttlonly applies to 2026-07-28 servers
authorizationn/a · weight 15
  • n/a
    auth.prm, auth.as_metadata, auth.cimdno remote uses OAuth
  • n/a
    auth.secret_in_urlno templated URL
tool hygiene86 · weight 30
  • pass
    tools.descriptionsevery tool has a description
  • pass
    tools.description_lengthdescriptions are concise
  • pass
    tools.schemasevery tool has an object input schema
  • pass
    tools.annotations21 of 21 tools declare readOnlyHint or destructiveHint
  • warn
    tools.directory_hints3 of 21 tools declare all four hints; missing: get_usage (openWorldHint); update_template_draft (openWorldHint); get_click_stats (openWorldHint); …
  • warn
    tools.token_costabout 8,321 tokens to load every tool
  • pass
    tools.api_dumptools are not a one-to-one API dump
stability100 · weight 15
  • pass
    stability.changesno tool changes in 30 days
  • pass
    stability.rug_pullno tool changed its meaning under the same name
dependencies67 · weight 15
  • pass
    deps.known_vulnsno known advisory in 98 resolved packages
  • fail
    deps.mcp_sdk_version@modelcontextprotocol/sdk 1.30.1 has 1 known advisory (GHSA-6qxp-vccf-f47h); update @modelcontextprotocol/sdk to 1.31.0 or later
  • pass
    deps.resolvable@gege-mn/[email protected] resolved: 98 packages

21 tools, about 8,321 tokens to load them all · tool set 04312e76c6ee · checked 2026-10-20 11:08 UTC

Tool changes

No tool definition changes recorded. A server's first observation is its baseline; later probes record what changes.

Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed. How it is computed.

Trust 94 / 100

provenance90
liveness99
freshness85
hygiene100

+repository +namespace-matches-repo +website +reachable +uptime-98% ~updated-36d-ago

Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed. How it is computed.

Dependencies

@gege-mn/[email protected] npm97 dependencies, resolved · MCP SDK @modelcontextprotocol/sdk 1.30.1 · advisories checked 2026-10-19

advisoryseveritypackagefixed in
GHSA-6qxp-vccf-f47hMCP TypeScript SDK: OAuth client could send credentials to an authorization server chosen by the MCP serverhigh@modelcontextprotocol/[email protected]MCP SDK, directfixed in 1.31.0

Dependency graphs from deps.dev; advisories from OSV.dev, including the GitHub Advisory Database and the PyPI Advisory Database; all CC BY 4.0. The graph is what a clean install of this version resolves today; nothing was installed or run. How it is checked.

Endpoints

remoteauthreachableuptime 30dp50protocollast ok
https://ray-api.gege.mn/mcp streamable-httpapi_key ${ray_api_key}yes98%620 ms2025-11-252026-10-20
packageregistryversionruntimesecrets
@gege-mn/ray-mcpnpm0.1.0npxRAY_API_KEY

Tools (21)

archive_templatedestructiveArchive 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.
create_templateCreate 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.
create_webhookCreate 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.
delete_webhookdestructiveDelete (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.
get_click_statsread-onlyEmail 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.
get_send_statusread-onlyDelivery 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`.
get_templateread-onlyGet 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.
get_usageread-onlyThe 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.
get_webhookread-onlyGet one outbound webhook (GET /tenant-webhooks/{id}) including its delivery health (consecutiveFailures, lastDeliveryAt, lastFailureAt, lastError).
list_channelsread-onlyList 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.
list_feed_notificationsread-onlyRead 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`.
list_templatesread-onlyList 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.
list_webhooksread-onlyList the workspace's outbound event webhooks (GET /tenant-webhooks): url, subscribed events, enabled flag and delivery health (consecutiveFailures, lastError). Signing secrets are never returned.
publish_templatePublish 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.
read_docsread-onlyRead 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.
send_notificationSend 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.
test_send_templateSend 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.
unarchive_templateRestore 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.
update_template_draftReplace 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.
update_webhookChange 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.
whoamiread-onlyIdentify 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.

Schemas: list_tools.

Similar MCP servers

Official server.json
{
  "name": "io.github.gege-mn/ray-mcp",
  "title": "Ray notifications",
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "remotes": [
    {
      "url": "https://ray-api.gege.mn/mcp",
      "type": "streamable-http",
      "headers": [
        {
          "name": "Authorization",
          "value": "Bearer {ray_api_key}",
          "isSecret": true,
          "variables": {
            "ray_api_key": {
              "isSecret": true,
              "isRequired": true,
              "description": "Ray API key (ck_live_...)",
              "placeholder": "ck_live_..."
            }
          },
          "isRequired": true,
          "description": "Bearer token with your Ray API key, created at https://ray.gege.mn under API keys."
        }
      ]
    }
  ],
  "version": "0.1.0",
  "packages": [
    {
      "version": "0.1.0",
      "transport": {
        "type": "stdio"
      },
      "identifier": "@gege-mn/ray-mcp",
      "runtimeHint": "npx",
      "registryType": "npm",
      "registryBaseUrl": "https://registry.npmjs.org",
      "environmentVariables": [
        {
          "name": "RAY_API_KEY",
          "isSecret": true,
          "isRequired": true,
          "description": "Ray API key (ck_live_...). Create one at https://ray.gege.mn under API keys; use the write scope to send and edit.",
          "placeholder": "ck_live_..."
        },
        {
          "name": "RAY_MCP_URL",
          "format": "string",
          "default": "https://ray-api.gege.mn/mcp",
          "description": "Hosted Ray MCP endpoint to bridge to. Only change this for self-hosted or staging deployments."
        }
      ]
    }
  ],
  "repository": {
    "url": "https://github.com/gege-mn/ray-mcp",
    "source": "github"
  },
  "websiteUrl": "https://ray.gege.mn/docs",
  "description": "Send email, push, Slack, Discord, Telegram and webhook notifications and manage templates with Ray."
}