npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

replylayer-mcp

v0.11.0

Published

MCP server for ReplyLayer — safe email for AI agents

Readme

replylayer-mcp

The MCP server for ReplyLayer — safe email for AI agents. It exposes ReplyLayer's email surface (send, reply, read, monitor, release) as MCP tools so an MCP client (Claude Desktop, Cursor, …) can drive transactional and operational email with built-in security scanning. Not a bulk or marketing tool.

Server identity: replylayer v0.11.0. 44 tools.

Install

Published to npm as replylayer-mcp. Most MCP clients launch it via npx (no global install needed) — see Client config. To run or install it directly:

npx -y replylayer-mcp        # or: npm install -g replylayer-mcp

Credentials

Auth is a single ReplyLayer API key. The server resolves it from the REPLYLAYER_API_KEY environment variable first, then from the stored credentials file at ~/.replylayer/credentials. Production (https://api.replylayer.ai) is the default endpoint; REPLYLAYER_API_URL is a testing-only override.

Set up the stored credential interactively (writes ~/.replylayer/credentials, mode 0600):

replylayer-mcp init        # or, without a global install: npx -y replylayer-mcp init

For CI / automation, skip init and pass REPLYLAYER_API_KEY in the environment.

A new key is inert until a human completes a one-time email-verification bootstrap (invite-gated signup + a 6-digit code). The server runs with a key a human has already provisioned and verified.

Client config (copy-paste)

Claude Desktop (claude_desktop_config.json) or Cursor (mcpServers) — launch via npx so there's no global install or absolute path to manage:

{
  "mcpServers": {
    "replylayer": {
      "command": "npx",
      "args": ["-y", "replylayer-mcp"],
      "env": {
        "REPLYLAYER_API_KEY": "rly_live_k3m9p2qx7vn4hjd0.uZ8Qb1vK3mN0pR7sT2wX9yA4cF6gH8jL1nP3rT5vW7z"
      }
    }
  }
}

If you ran replylayer-mcp init to store the key, the env block is optional. With a global install (npm i -g replylayer-mcp), use "command": "replylayer-mcp" and drop the args.

The directional safety model

Every message is security-scanned, and scanning is directional:

  • Outbound text that resembles prompt-injection is your agent's own authored content — delivered clean. The secrets scanner is outbound-only.
  • Inbound prompt-injection is quarantined.

The send tools (send_email, reply_to_message, send_draft) return a status: sent | quarantined | blocked | pending_review. Branch on status, not on success/failure. Those send responses now carry the why inline: scan (the scanner verdict — inspect scan.verdict, scan.findings, and scan.findings[].agent_instructions) and hold_context (the policy/HITL reason when a clean scan is held by your mailbox policy). Call read_message for full detail. A finding with failure_class: "inference_error" is an infrastructure error, not a content judgment — retry or release, do not rewrite.

Recovery: inbound quarantinedrelease_quarantined_message; firewall_blockedrelease_firewall_blocked_message; pending_review needs human approval (agent keys cannot approve — escalate). RATE_LIMITED → if details.reset_at is present it is the daily send quota (back off until then); otherwise it is a short-window limit — wait for details.retry_after (or the time in the error message), then retry. RECIPIENT_SUPPRESSED / BILLING_* / EMAIL_NOT_VERIFIED → escalate, do not retry.

This server does no implicit retry (neither on 5xx nor on a 429 Retry-After): every tool call fails fast and returns the structured error, so the agent owns retry timing and a tool call is never held open by a silent server-side wait.

Trusted instruction sources

By default every inbound read carries the standing untrusted-content contract: agent_safety_context.untrusted_content: true plus a guidance string telling the agent not to follow instructions embedded in the message body. Relaxing that on a given read is entirely server-side and operator-configured — this server has no client-side opt-in or env var for it. The server relaxes a read only when the customer has (a) put the mailbox into instruction_trust_mode: 'enabled', (b) enabled this API key's instruction-trust capability, and (c) designated that exact sender address (address-grain only — no domain-wide trust) as a trusted instruction source, and the message itself is verified_aligned (Mailgun-verified domain authenticity), clean-scanning, and available from that sender. When all of that lines up, guidance is replaced with trusted-instruction guidance (the agent may act on that verified sender's own explicit requests in this message) and a thin instruction_trust basis object is attached — untrusted_content stays true. This is read-relaxation only: it never changes how an outbound send is gated.

Default is off end to end: no operator configuration → no relaxation → byte-identical legacy reads. There is currently no MCP tool to grant, list, or revoke trusted sources — see the note at the end of Tool surface.

Tool surface (44 tools)

Reads (no side effects): list_messages (search + filters + paging), read_message, get_thread, list_threads, wait_for_message, list_mailboxes, list_recipients, list_suppressions, list_allowlist, list_allowlist_blocked_attempts, list_drafts, get_draft, list_inbound_blocklist, list_inbound_allowlist, list_inbound_firewall_blocked_attempts, get_account_usage, get_agent_quota, get_attachment_preview, get_link_scanning_status.

get_link_scanning_status reports whether malicious link scanning (URL reputation, backed by Google Web Risk) is active for the account. Turning it on is an admin action (it enables an account-wide sub-processor data flow), so the MCP surface is read-only here — enable it from the dashboard, the SDK, or rly account link-scanning enable.

Sends (dispatch outbound mail): send_email, reply_to_message, send_draft.

The high-traffic tools — the 6 reads (list_messages, read_message, get_thread, list_threads, list_mailboxes, wait_for_message) and the 3 sends (send_email, reply_to_message, send_draft) — now return structuredContent (a typed object you can consume without re-parsing the text blob) alongside the text block, with declared outputSchemas. get_attachment_preview also returns structuredContent.

Drafts: create_draft, update_draft, delete_draft (plus send_draft above).

Inbound triage: release_quarantined_message, block_quarantined_message, report_and_block (block + blocklist the sender, inbound-only), release_firewall_blocked_message. Human-in-the-loop (admin-only; agent keys 403): approve_review, deny_review.

Delete: delete_message — soft-deletes a message (any direction) and purges its raw MIME; agent keys require the account delete policy to be enabled (else 403).

Policy / contacts: add_recipient, add_suppression, add_inbound_blocklist, add_inbound_allowlist_entry, mark_message_read, mark_thread_read.

Star / unstar: star_message (toggle a message's starred flag), star_thread (toggle a thread's starred flag).

Bulk policy mutations: add_inbound_allowlist_bulk (up to 1000 sender addresses for a mailbox's inbound allowlist in one call), add_suppressions_bulk (up to 1000 addresses to the account-wide do-not-contact list), add_inbound_blocklist_bulk (up to 1000 addresses to the account-wide inbound blocklist).

Policy stub (intentionally unavailable): remove_suppression — always returns an isError result explaining that suppression removal is a per-human admin decision; use rly suppressions remove, an SDK admin key, or the dashboard instead.

Not yet a tool: trusted-instruction-source management (grant / list / revoke, plus the mailbox mode and per-key capability toggles — see above) has no MCP wrapper today. That includes the revoke endpoint, which — like the inbound-triage release tools — is unprivileged and agent-key-callable server-side; it just isn't exposed here yet. Manage trusted sources from the ReplyLayer dashboard (or the REST API directly) in the meantime.

Tool notes

  • star_message — wraps PATCH /v1/messages/:id/star. Input: message_id, starred: boolean. Use one tool call to star or unstar (matches the SDK/REST {starred} shape — there are no separate star/unstar verbs).
  • star_thread — wraps PATCH /v1/mailboxes/:id/threads/:thread_id/star. Input: mailbox, thread_id, starred: boolean.
  • get_attachment_preview — wraps GET /v1/messages/:id/attachments/:idx/preview. Returns derived text preview only (PDF, Office, text/plain, text/csv). Surfaces 404 ATTACHMENT_PREVIEW_NOT_AVAILABLE as an isError result when the derivative is not ready, failed, or unavailable. Returns structuredContent alongside the text block.
  • add_inbound_allowlist_bulk — wraps POST /v1/mailboxes/:id/inbound-allowlist/bulk. Input: mailbox, emails: string[] (max 1000). Returns the full partial-success shape: added, already_existed, invalid (with per-entry reason), and counts.
  • add_suppressions_bulk — wraps POST /v1/suppressions/bulk. Input: emails: string[] (max 1000). Same partial-success shape.
  • add_inbound_blocklist_bulk — wraps POST /v1/inbound-blocklist/bulk. Input: emails: string[] (max 1000). Same partial-success shape.
  • remove_suppression — policy-explanation stub. Always returns isError with code SUPPRESSION_REMOVE_NOT_AVAILABLE. Improves agent UX by explaining why removal is not available via MCP rather than returning a generic unknown-tool error.
  • wait_for_message timeout — the tool reflects the real server cap: max 30 s per call (not 120 s). For longer waits, call the tool again.

Browse & search

Inbox search and full thread reads are first-class on MCP: list_messages filters by keyword search, sender, date range, direction, status (incl. the held-mail states quarantined / pending_review for triage) and starred, and pages older via before=<oldest message id from the previous page>. list_threads lists conversations (with starred / has_inbound), and get_thread reads a full thread — pass mailbox to disambiguate a thread key that resolves in more than one mailbox. list_messages also supports has_attachment (true/false) — it probes /v1/health for the messages.has_attachment_filter capability and returns a structured SEARCH_OPERATOR_UNSUPPORTED on older servers that don't advertise it.

See also

  • Public CLI repo (install & package trust): https://github.com/replylayer/rly
  • The agent SKILL.md, the CLI ↔ MCP ↔ REST verb-parity map, and ENDPOINTS.md (the REST API contract) will be published with the hosted docs site when it is available.