email

Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.

我該用這個嗎

品質與安全性

A
說明品質
97%
結構描述完整度
85%
命名品質
98%
汙染風險
100%
權限相符程度
80%
協定合規性
100%

發現項目(2)

  • LOWTool 'listWebhookDeliveries' suggests web access but openWorldHint=false在 listWebhookDeliveries 中
  • LOWTool 'replayWebhookDelivery' suggests web access but openWorldHint=false在 replayWebhookDelivery 中

根據工具定義與協定合規性的自動化分析。

上下文成本

~10,537Token(工具定義)
~3.1 KB典型回應大小
顯著的注意力影響(128k 上下文的 8.23%)

這是每次將伺服器的工具載入模型上下文時所消耗的約略 token 數量。數量越高,可用於其他工作的注意力就越少。

安裝

一鍵安裝

將以下內容加入你的 `claude_desktop_config.json` 檔案:

{
  "mcpServers": {
    "email": {
      "url": "https://www.primitive.dev/mcp"
    }
  }
}

遠端端點

https://www.primitive.dev/mcpstreamable-http

它能做什麼

工具清單

工具(30)

🟢 唯讀🟡 寫入🔴 刪除⚪ 未知
🟢listDomains

List all inbound domains for the organization, both verified and unverified. Each domain includes its verification status and DNS records. Use before addDomain to check whether a domain is already claimed.

輸入結構描述

{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
⚪addDomain(requestBody)

Claim a new domain and receive the DNS records to publish. Returns dns_records with the exact records to add. If the domain has an mx_conflict (existing mail provider), re-call with confirmed: true to proceed. After publishing DNS records, call verifyDomain to complete setup.

輸入結構描述

{
  "type": "object",
  "properties": {
    "requestBody": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "domain": {
          "type": "string",
          "minLength": 1,
          "maxLength": 253,
          "description": "The domain name to claim (e.g. \"example.com\")."
        },
        "confirmed": {
          "type": "boolean",
          "description": "Set to true to confirm replacing an existing mailbox provider after an mx_conflict response."
        }
      },
      "required": [
        "domain"
      ]
    }
  },
  "required": [
    "requestBody"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢verifyDomain(id)

Check DNS records for a domain claim (MX, TXT, SPF, DKIM, DMARC). On success the domain becomes verified and starts receiving mail. On failure, returns which checks passed and which still need attention. If DNS propagation is incomplete, wait a few minutes and retry.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Domain ID returned by addDomain or listDomains."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢downloadDomainZoneFile(id, outbound_only)

Download a BIND-format DNS zone file for a domain. Useful when users want to import all required DNS records at once rather than copying them individually. Returns plain text in BIND zone file format.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Domain ID from listDomains or addDomain."
    },
    "outbound_only": {
      "type": "boolean",
      "description": "When true, include only outbound DNS records (SPF, DKIM, DMARC). Defaults to all records for unverified domains, outbound-only for verified."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢getAccount(api_key)

Use this when you need the authenticated Primitive account summary, including plan, onboarding state, and managed inbox domain. managed_inbox_address is a domain, not a complete mailbox. When it is non-null, this MCP result also includes sender_address, such as [email protected], for use as sendEmail.requestBody.from.

輸入結構描述

{
  "type": "object",
  "properties": {
    "api_key": {
      "type": "string",
      "minLength": 8,
      "maxLength": 200,
      "description": "Primitive API key (prim_...). Only needed when this connection has no signed-in account: pass the api_key returned by createEmailAddress, unchanged, on every call for the rest of the conversation. Omit it when the user is signed in."
    }
  },
  "required": [],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢getInboxStatus(api_key)

Use this when the user asks whether inbound email is ready or needs setup. Returns domains, routes, deployed Functions, and recent inbound activity.

輸入結構描述

{
  "type": "object",
  "properties": {
    "api_key": {
      "type": "string",
      "minLength": 8,
      "maxLength": 200,
      "description": "Primitive API key (prim_...). Only needed when this connection has no signed-in account: pass the api_key returned by createEmailAddress, unchanged, on every call for the rest of the conversation. Omit it when the user is signed in."
    }
  },
  "required": [],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢getOutboundStatus

What can I send FROM? Lists this account's verified outbound (sendable) domains plus any domains still pending DNS verification, with next actions. Call this BEFORE sendEmail to pick a valid `from` domain — the account email is not necessarily sendable. The same sendable list is echoed in a cannot_send_from_domain error.

輸入結構描述

{
  "type": "object",
  "properties": {},
  "required": [],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢listEmails(cursor, since, wait, limit, domain_id, ...)

Use this when you need to browse inbound emails received at verified domains with cursor pagination, status filters, date filters, or sender/recipient search.

輸入結構描述

{
  "type": "object",
  "properties": {
    "cursor": {
      "type": "string",
      "description": "Backward (history) pagination cursor from a previous response's `meta.cursor` field: returns emails OLDER than this position, newest-first. Mutually exclusive with `since`."
    },
    "since": {
      "type": "string",
      "description": "Forward-tail cursor (a `meta.cursor` value, format `{ISO datetime}|{UUID}`): returns emails strictly NEWER than this position, oldest-first, for lossless polling of just-arrived mail. Mutually exclusive with `cursor`."
    },
    "wait": {
      "type": "number",
      "minimum": 0,
      "maximum": 30,
      "default": 0,
      "description": "Long-poll up to this many seconds (0–30, default 0) holding the request for new mail instead of returning an empty page immediately. Requires `since`. Returns as soon as matching mail arrives, or an empty page when the wait elapses."
    },
    "limit": {
      "type": "number",
      "minimum": 1,
      "maximum": 100,
      "default": 50,
      "description": "Maximum number of emails to return (1–100, default 50)."
    },
    "domain_id": {
      "type": "string",
      "format": "uuid",
      "description": "Filter to emails received on a specific verified domain."
    },
    "status": {
      "type": "string",
      "enum": [
        "pending",
        "accepted",
        "completed",
        "rejected"
      ],
      "description": "Filter to emails in this processing status."
    },
    "search": {
      "type": "string",
      "maxLength": 500,
      "description": "Free-text search across sender, recipient, and subject."
    },
    "date_from": {
      "type": "string",
      "format": "date-time",
      "description": "Inclusive lower bound on created_at (ISO 8601)."
    },
    "date_to": {
      "type": "string",
      "format": "date-time",
      "description": "Inclusive upper bound on created_at (ISO 8601)."
    },
    "api_key": {
      "type": "string",
      "minLength": 8,
      "maxLength": 200,
      "description": "Primitive API key (prim_...). Only needed when this connection has no signed-in account: pass the api_key returned by createEmailAddress, unchanged, on every call for the rest of the conversation. Omit it when the user is signed in."
    }
  },
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢searchEmails(q, from, to, subject, body, ...)

Use this when you need to find inbound emails with structured filters or full-text matching. Use sort=received_at_asc plus date_from for new-mail polling.

輸入結構描述

{
  "type": "object",
  "properties": {
    "q": {
      "type": "string",
      "maxLength": 500,
      "description": "Full-text query matched across subject, body, sender, and recipient."
    },
    "from": {
      "type": "string",
      "maxLength": 255,
      "description": "Filter to emails from this sender address or domain."
    },
    "to": {
      "type": "string",
      "maxLength": 255,
      "description": "Filter to emails addressed to this recipient."
    },
    "subject": {
      "type": "string",
      "maxLength": 500,
      "description": "Filter to emails whose subject contains this string."
    },
    "body": {
      "type": "string",
      "maxLength": 2000,
      "description": "Filter to emails whose body contains this string."
    },
    "domain_id": {
      "type": "string",
      "format": "uuid",
      "description": "Filter to emails received on a specific verified domain."
    },
    "reply_to_sent_email_id": {
      "type": "string",
      "format": "uuid",
      "description": "Filter to inbound emails that are replies to a specific sent email ID."
    },
    "status": {
      "type": "string",
      "enum": [
        "pending",
        "accepted",
        "completed",
        "rejected"
      ],
      "description": "Filter to emails in this processing status."
    },
    "date_from": {
      "type": "string",
      "format": "date-time",
      "description": "Inclusive lower bound on received_at (ISO 8601)."
    },
    "date_to": {
      "type": "string",
      "format": "date-time",
      "description": "Inclusive upper bound on received_at (ISO 8601)."
    },
    "has_attachment": {
      "type": "string",
      "enum": [
        "true",
        "false"
      ],
      "description": "Filter to emails that have (\"true\") or lack (\"false\") attachments."
    },
    "spam_score_lt": {
      "type": "number",
      "description": "Filter to emails with a spam score strictly below this value."
    },
    "spam_score_gte": {
      "type": "number",
      "description": "Filter to emails with a spam score at or above this value."
    },
    "sort": {
      "type": "string",
      "enum": [
        "relevance",
        "received_at_desc",
        "received_at_asc"
      ],
      "description": "Sort order. Use received_at_asc with date_from for polling new mail."
    },
    "cursor": {
      "type": "string",
      "maxLength": 200,
      "description": "Pagination cursor from a previous response's `meta.cursor` field."
    },
    "limit": {
      "type": "number",
      "minimum": 1,
      "maximum": 100,
      "default": 50,
      "description": "Maximum number of emails to return (1–100, default 50)."
    },
    "snippet": {
      "type": "string",
      "enum": [
        "true",
        "false"
      ],
      "default": "true",
      "description": "Include a short body snippet in each result (default true)."
    },
    "include_facets": {
      "type": "string",
      "enum": [
        "true",
        "false"
      ],
      "default": "true",
      "description": "Include aggregated facet counts (sender, domain, status) in the response (default true)."
    }
  },
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢getEmail(id, api_key)

Use this when you need full details for one inbound email ID, including parsed bodies, threading metadata, SMTP envelope, webhook state, and replies.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Inbound email ID from listEmails or searchEmails."
    },
    "api_key": {
      "type": "string",
      "minLength": 8,
      "maxLength": 200,
      "description": "Primitive API key (prim_...). Only needed when this connection has no signed-in account: pass the api_key returned by createEmailAddress, unchanged, on every call for the rest of the conversation. Omit it when the user is signed in."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🔴replyToEmail(id, requestBody, api_key)

Use this when the user has selected a specific inbound email and confirmed a reply. Sends real outbound email with threading handled server-side.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Inbound email ID to reply to. Threading headers are set server-side."
    },
    "requestBody": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "body_text": {
          "type": "string",
          "description": "Plain-text reply body. Provide at least one of body_text or body_html."
        },
        "body_html": {
          "type": "string",
          "description": "HTML reply body. Provide at least one of body_text or body_html."
        },
        "from": {
          "type": "string",
          "minLength": 3,
          "maxLength": 998,
          "description": "RFC 5322 From header. Defaults to the original recipient address if omitted."
        },
        "wait": {
          "type": "boolean",
          "description": "When true, wait for the first SMTP delivery outcome before returning."
        },
        "attachments": {
          "type": "array",
          "maxItems": 100,
          "description": "Optional file attachments to include in the reply.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "filename": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255,
                "description": "Attachment filename including extension."
              },
              "content_type": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255,
                "description": "MIME type of the attachment (e.g. \"application/pdf\"). Inferred from the filename when omitted."
              },
              "content_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128,
                "pattern": "^[\\x21-\\x3B\\x3D\\x3F-\\x7E]+$",
                "description": "Content-ID for an inline (cid) attachment: 1-128 printable ASCII characters, no whitespace or angle brackets. When set, the part renders inline and body_html can reference it (e.g. src=\"cid:logo-1\"). Omit for a regular downloadable attachment."
              },
              "content_base64": {
                "type": "string",
                "minLength": 1,
                "maxLength": 44040192,
                "description": "Base64-encoded attachment content."
              }
            },
            "required": [
              "filename",
              "content_base64"
            ]
          }
        }
      }
    },
    "api_key": {
      "type": "string",
      "minLength": 8,
      "maxLength": 200,
      "description": "Primitive API key (prim_...). Only needed when this connection has no signed-in account: pass the api_key returned by createEmailAddress, unchanged, on every call for the rest of the conversation. Omit it when the user is signed in."
    }
  },
  "required": [
    "id",
    "requestBody"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🔴sendEmail(Idempotency-Key, requestBody, api_key)

Use this when the user has confirmed a new outbound email. Sends real email through Primitive's relay and can wait for the first SMTP delivery outcome, or schedule the send for a future time with scheduled_at. IMPORTANT: `from` is YOUR OWN complete mailbox address, never the recipient's. Use sender_address from createEmailAddress or getAccount for a managed inbox. AFTER sending, if you expect an answer, immediately call awaitReply with the returned id and wait for it, rather than telling the user the message was sent and stopping. Most agent mailboxes answer within seconds, and the answer is usually the thing the user actually asked you for.

輸入結構描述

{
  "type": "object",
  "properties": {
    "Idempotency-Key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 255,
      "description": "Client-supplied idempotency key. Retrying with the same key returns the original result without re-sending."
    },
    "requestBody": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "from": {
          "type": "string",
          "minLength": 3,
          "maxLength": 998,
          "description": "RFC 5322 From header: YOUR OWN complete mailbox address, never the recipient's. createEmailAddress.address and getAccount.managed_inbox_address are domains, not mailbox addresses. When present, use the sender_address added to those MCP results, such as [email protected]. Putting the recipient's address here mails them as themselves, which they will ignore. The sender domain must be a verified outbound domain for your organization."
        },
        "to": {
          "oneOf": [
            {
              "type": "string",
              "minLength": 3,
              "maxLength": 998
            },
            {
              "type": "array",
              "minItems": 1,
              "maxItems": 100,
              "items": {
                "type": "string",
                "minLength": 3,
                "maxLength": 998
              }
            }
          ],
          "description": "Recipient email address (RFC 5321 mailbox, display-name form allowed), or an array of single-address strings to address multiple recipients with one message. Each array entry must be exactly one address. Combined to+cc+bcc count max 100."
        },
        "cc": {
          "oneOf": [
            {
              "type": "string",
              "minLength": 3,
              "maxLength": 998
            },
            {
              "type": "array",
              "minItems": 1,
              "maxItems": 100,
              "items": {
                "type": "string",
                "minLength": 3,
                "maxLength": 998
              }
            }
          ],
          "description": "Optional CC recipients: a single address or an array of single-address strings (each entry exactly one address). Counts toward the combined to+cc+bcc max of 100."
        },
        "bcc": {
          "oneOf": [
            {
              "type": "string",
              "minLength": 3,
              "maxLength": 998
            },
            {
              "type": "array",
              "minItems": 1,
              "maxItems": 100,
              "items": {
                "type": "string",
                "minLength": 3,
                "maxLength": 998
              }
            }
          ],
          "description": "Optional BCC recipients: a single address or an array of single-address strings (each entry exactly one address). Counts toward the combined to+cc+bcc max of 100."
        },
        "reply_to": {
          "oneOf": [
            {
              "type": "string",
              "minLength": 3,
              "maxLength": 998
            },
            {
              "type": "array",
              "minItems": 1,
              "maxItems": 10,
              "items": {
                "type": "string",
                "minLength": 3,
                "maxLength": 998
              }
            }
          ],
          "description": "Optional Reply-To header: a single address or an array of up to 10 single-address entries. A pure header: adds no recipients and does not count toward the recipient cap."
        },
        "subject": {
          "type": "string",
          "minLength": 1,
          "maxLength": 998,
          "description": "Email subject line."
        },
        "body_text": {
          "type": "string",
          "description": "Plain-text message body. Provide at least one of body_text or body_html."
        },
        "body_html": {
          "type": "string",
          "description": "HTML message body. Provide at least one of body_text or body_html. Reference inline attachments via cid: URLs matching their content_id."
        },
        "in_reply_to": {
          "type": "string",
          "minLength": 1,
          "maxLength": 998,
          "description": "Message-ID of the email being replied to, for threading (e.g. \"<[email protected]>\")."
        },
        "references": {
          "type": "array",
          "maxItems": 100,
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 998
          },
          "description": "List of Message-IDs for the References header, oldest-first."
        },
        "attachments": {
          "type": "array",
          "maxItems": 100,
          "description": "Optional file attachments. Not allowed on scheduled sends (scheduled_at).",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "filename": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255,
                "description": "Attachment filename including extension."
              },
              "content_type": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255,
                "description": "MIME type of the attachment (e.g. \"application/pdf\"). Inferred from the filename when omitted."
              },
              "content_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128,
                "pattern": "^[\\x21-\\x3B\\x3D\\x3F-\\x7E]+$",
                "description": "Content-ID for an inline (cid) attachment: 1-128 printable ASCII characters, no whitespace or angle brackets. When set, the part renders inline and body_html can reference it (e.g. src=\"cid:logo-1\"). Omit for a regular downloadable attachment."
              },
              "content_base64": {
                "type": "string",
                "minLength": 1,
                "maxLength": 44040192,
                "description": "Base64-encoded attachment content."
              }
            },
            "required": [
              "filename",
              "content_base64"
            ]
          }
        },
        "tags": {
          "type": "array",
          "maxItems": 10,
          "description": "Optional metadata tags (max 10, unique names) stored on the send record for correlation and filtering via listSentEmails. Never rendered into headers and never delivered.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "pattern": "^[A-Za-z0-9_-]+$",
                "description": "Tag name: ASCII letters, digits, underscores, dashes only."
              },
              "value": {
                "type": "string",
                "minLength": 1,
                "maxLength": 256,
                "pattern": "^[A-Za-z0-9_-]+$",
                "description": "Tag value: same charset as the name. Use \"true\" for a bare marker tag."
              }
            },
            "required": [
              "name",
              "value"
            ]
          }
        },
        "scheduled_at": {
          "type": "string",
          "format": "date-time",
          "description": "Schedule the send for a future time (ISO 8601 UTC, e.g. \"2026-08-01T09:00:00Z\"). Must be strictly in the future and at most 30 days out. Cannot be combined with wait or with attachments. Cancel before dispatch with cancelScheduledSend."
        },
        "wait": {
          "type": "boolean",
          "description": "When true, wait for the first SMTP delivery outcome before returning. Respects wait_timeout_ms. Cannot be combined with scheduled_at."
        },
        "wait_timeout_ms": {
          "type": "number",
          "minimum": 1000,
          "maximum": 30000,
          "description": "How long to wait for delivery confirmation when wait is true (1000-30000 ms, default 10000)."
        }
      },
      "required": [
        "from",
        "to",
        "subject"
      ]
    },
    "api_key": {
      "type": "string",
      "minLength": 8,
      "maxLength": 200,
      "description": "Primitive API key (prim_...). Only needed when this connection has no signed-in account: pass the api_key returned by createEmailAddress, unchanged, on every call for the rest of the conversation. Omit it when the user is signed in."
    }
  },
  "required": [
    "requestBody"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢sendEmailDemo(requestBody)

SIMULATION ONLY: nothing is delivered. NEVER call this when the user actually wants an email to arrive, and never describe its result as a sent email: no message is sent, queued, or stored, and the recipient receives nothing. To really send with no account, call createEmailAddress (instant, no signup form and no verification) and then sendEmail with the api_key it returns; that is the correct path for any genuine send request. This tool exists only to preview the response shape: it validates the body against the exact same schema as sendEmail (including cc/bcc, reply_to, tags, attachments, and scheduled_at) and returns a synthetic success envelope marked demo: true. Demo requests are capped at 16KB total body, so large attachments are rejected even though the schema allows them.

輸入結構描述

{
  "type": "object",
  "properties": {
    "requestBody": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "from": {
          "type": "string",
          "minLength": 3,
          "maxLength": 998,
          "description": "RFC 5322 From header: YOUR OWN complete mailbox address, never the recipient's. createEmailAddress.address and getAccount.managed_inbox_address are domains, not mailbox addresses. When present, use the sender_address added to those MCP results, such as [email protected]. Putting the recipient's address here mails them as themselves, which they will ignore. The sender domain must be a verified outbound domain for your organization."
        },
        "to": {
          "oneOf": [
            {
              "type": "string",
              "minLength": 3,
              "maxLength": 998
            },
            {
              "type": "array",
              "minItems": 1,
              "maxItems": 100,
              "items": {
                "type": "string",
                "minLength": 3,
                "maxLength": 998
              }
            }
          ],
          "description": "Recipient email address (RFC 5321 mailbox, display-name form allowed), or an array of single-address strings to address multiple recipients with one message. Each array entry must be exactly one address. Combined to+cc+bcc count max 100."
        },
        "cc": {
          "oneOf": [
            {
              "type": "string",
              "minLength": 3,
              "maxLength": 998
            },
            {
              "type": "array",
              "minItems": 1,
              "maxItems": 100,
              "items": {
                "type": "string",
                "minLength": 3,
                "maxLength": 998
              }
            }
          ],
          "description": "Optional CC recipients: a single address or an array of single-address strings (each entry exactly one address). Counts toward the combined to+cc+bcc max of 100."
        },
        "bcc": {
          "oneOf": [
            {
              "type": "string",
              "minLength": 3,
              "maxLength": 998
            },
            {
              "type": "array",
              "minItems": 1,
              "maxItems": 100,
              "items": {
                "type": "string",
                "minLength": 3,
                "maxLength": 998
              }
            }
          ],
          "description": "Optional BCC recipients: a single address or an array of single-address strings (each entry exactly one address). Counts toward the combined to+cc+bcc max of 100."
        },
        "reply_to": {
          "oneOf": [
            {
              "type": "string",
              "minLength": 3,
              "maxLength": 998
            },
            {
              "type": "array",
              "minItems": 1,
              "maxItems": 10,
              "items": {
                "type": "string",
                "minLength": 3,
                "maxLength": 998
              }
            }
          ],
          "description": "Optional Reply-To header: a single address or an array of up to 10 single-address entries. A pure header: adds no recipients and does not count toward the recipient cap."
        },
        "subject": {
          "type": "string",
          "minLength": 1,
          "maxLength": 998,
          "description": "Email subject line."
        },
        "body_text": {
          "type": "string",
          "description": "Plain-text message body. Provide at least one of body_text or body_html."
        },
        "body_html": {
          "type": "string",
          "description": "HTML message body. Provide at least one of body_text or body_html. Reference inline attachments via cid: URLs matching their content_id."
        },
        "in_reply_to": {
          "type": "string",
          "minLength": 1,
          "maxLength": 998,
          "description": "Message-ID of the email being replied to, for threading (e.g. \"<[email protected]>\")."
        },
        "references": {
          "type": "array",
          "maxItems": 100,
          "items": {
            "type": "string",
            "minLength": 1,
            "maxLength": 998
          },
          "description": "List of Message-IDs for the References header, oldest-first."
        },
        "attachments": {
          "type": "array",
          "maxItems": 100,
          "description": "Optional file attachments. Not allowed on scheduled sends (scheduled_at).",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "filename": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255,
                "description": "Attachment filename including extension."
              },
              "content_type": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255,
                "description": "MIME type of the attachment (e.g. \"application/pdf\"). Inferred from the filename when omitted."
              },
              "content_id": {
                "type": "string",
                "minLength": 1,
                "maxLength": 128,
                "pattern": "^[\\x21-\\x3B\\x3D\\x3F-\\x7E]+$",
                "description": "Content-ID for an inline (cid) attachment: 1-128 printable ASCII characters, no whitespace or angle brackets. When set, the part renders inline and body_html can reference it (e.g. src=\"cid:logo-1\"). Omit for a regular downloadable attachment."
              },
              "content_base64": {
                "type": "string",
                "minLength": 1,
                "maxLength": 44040192,
                "description": "Base64-encoded attachment content."
              }
            },
            "required": [
              "filename",
              "content_base64"
            ]
          }
        },
        "tags": {
          "type": "array",
          "maxItems": 10,
          "description": "Optional metadata tags (max 10, unique names) stored on the send record for correlation and filtering via listSentEmails. Never rendered into headers and never delivered.",
          "items": {
            "type": "object",
            "additionalProperties": false,
            "properties": {
              "name": {
                "type": "string",
                "minLength": 1,
                "maxLength": 64,
                "pattern": "^[A-Za-z0-9_-]+$",
                "description": "Tag name: ASCII letters, digits, underscores, dashes only."
              },
              "value": {
                "type": "string",
                "minLength": 1,
                "maxLength": 256,
                "pattern": "^[A-Za-z0-9_-]+$",
                "description": "Tag value: same charset as the name. Use \"true\" for a bare marker tag."
              }
            },
            "required": [
              "name",
              "value"
            ]
          }
        },
        "scheduled_at": {
          "type": "string",
          "format": "date-time",
          "description": "Schedule the send for a future time (ISO 8601 UTC, e.g. \"2026-08-01T09:00:00Z\"). Must be strictly in the future and at most 30 days out. Cannot be combined with wait or with attachments. Cancel before dispatch with cancelScheduledSend."
        },
        "wait": {
          "type": "boolean",
          "description": "When true, wait for the first SMTP delivery outcome before returning. Respects wait_timeout_ms. Cannot be combined with scheduled_at."
        },
        "wait_timeout_ms": {
          "type": "number",
          "minimum": 1000,
          "maximum": 30000,
          "description": "How long to wait for delivery confirmation when wait is true (1000-30000 ms, default 10000)."
        }
      },
      "required": [
        "from",
        "to",
        "subject"
      ]
    }
  },
  "required": [
    "requestBody"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢listSentEmails(cursor, limit, status, request_id, idempotency_key, ...)

List outbound emails sent by this org, with cursor pagination and filters. Bodies are omitted from list rows to keep responses small — use getSentEmail to fetch a specific row with full body. Useful for auditing delivery status, finding bounced sends, or checking gate-denied attempts.

輸入結構描述

{
  "type": "object",
  "properties": {
    "cursor": {
      "type": "string",
      "description": "Pagination cursor from a previous response's `meta.cursor` field."
    },
    "limit": {
      "type": "number",
      "minimum": 1,
      "maximum": 100,
      "default": 50,
      "description": "Maximum number of sent emails to return (1–100, default 50)."
    },
    "status": {
      "type": "string",
      "enum": [
        "queued",
        "submitted_to_agent",
        "agent_failed",
        "gate_denied",
        "unknown",
        "delivered",
        "bounced",
        "deferred",
        "wait_timeout",
        "scheduled",
        "canceled"
      ],
      "description": "Filter to rows in this status. Use \"scheduled\" to find pending scheduled sends (cancelable via cancelScheduledSend) and \"canceled\" for ones already canceled."
    },
    "request_id": {
      "type": "string",
      "format": "uuid",
      "description": "Filter to the row matching a specific server-issued request_id from a /send-mail response."
    },
    "idempotency_key": {
      "type": "string",
      "minLength": 1,
      "maxLength": 255,
      "description": "Filter to rows with the given client idempotency key."
    },
    "date_from": {
      "type": "string",
      "format": "date-time",
      "description": "Inclusive lower bound on created_at (ISO 8601)."
    },
    "date_to": {
      "type": "string",
      "format": "date-time",
      "description": "Inclusive upper bound on created_at (ISO 8601)."
    }
  },
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢getSentEmail(id)

Get the full record for a single sent email by id, including body_text and body_html. Use to inspect delivery details for a specific send — e.g. the SMTP response on a bounced row, or the gate denial reason on a gate_denied row.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Sent email ID from listSentEmails or a /send-mail response."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🔴cancelScheduledSend(id)

Cancel a still-scheduled send before it dispatches (terminal status "canceled"; the same idempotency key becomes reusable). Pass the sent email id from a sendEmail response that used scheduled_at, or from listSentEmails. Returns a conflict error once the send has already started dispatching.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Sent email ID of the scheduled send, from a sendEmail response or listSentEmails."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢awaitReply(id, wait, wait_timeout_ms, api_key)

Wait for the threaded reply to a sent email. Call this immediately after sendEmail or replyToEmail when you expect an answer. With only the sent email's id it long-polls for up to 30 seconds by default. Do not report that nobody replied or ask the user to check later until this call returns with no reply. Set wait=false only for a deliberate immediate poll. Matching uses reply threading, not a sender or subject guess.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "The sent email id to fetch the reply for (from a sendEmail/replyToEmail response)."
    },
    "wait": {
      "type": "boolean",
      "default": true,
      "description": "When true, long-poll until a reply arrives or wait_timeout_ms elapses. Defaults to true. Set false only for a single immediate poll."
    },
    "wait_timeout_ms": {
      "type": "number",
      "minimum": 1000,
      "maximum": 30000,
      "default": 30000,
      "description": "How long to wait when wait=true (1000 to 30000 ms). Defaults to 30000."
    },
    "api_key": {
      "type": "string",
      "minLength": 8,
      "maxLength": 200,
      "description": "Primitive API key (prim_...). Only needed when this connection has no signed-in account: pass the api_key returned by createEmailAddress, unchanged, on every call for the rest of the conversation. Omit it when the user is signed in."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢getConversation(id)

Get the full conversation an inbound email belongs to as ordered, chat-model-ready turns with bodies. Each message is oldest-first with a direction (inbound/outbound) and a derived role (inbound→user, outbound→assistant). For a brand-new message, returns just that one turn. The response includes a truncated boolean (true when the message cap was reached) and a message_count field.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "ID of any inbound email in the conversation."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢getThread(id)

Get a conversation thread by id: metadata plus all inbound and outbound messages interleaved oldest-first. Each message has a direction (inbound/outbound) and id; fetch inbound message bodies via getEmail, or outbound bodies via getSentEmail. Discover thread_id from any email or sent-email record. Compare message_count against messages.length to detect truncation.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Thread ID from the thread_id field on any email or sent-email."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢downloadEmailAttachments(id, token)

Download all attachments for an inbound email as a gzip-compressed tar archive. Returns the archive as a base64-encoded string along with the attachment count and SHA-256 digest. Prefer getEmail first to check the attachment manifest before downloading.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Inbound email ID."
    },
    "token": {
      "type": "string",
      "description": "Signed download token from a webhook payload. Optional — the bearer token is used when this is omitted."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢listEndpoints

List all active webhook endpoints for the organization. Each endpoint shows its URL, enabled state, and optional domain restriction.

輸入結構描述

{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟡createEndpoint(requestBody)

Create a webhook endpoint to receive email.received events. If an endpoint with the same URL already exists but is deactivated, it is reactivated. After creating, call testEndpoint to confirm your signature verifier accepts the payload.

輸入結構描述

{
  "type": "object",
  "properties": {
    "requestBody": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "url": {
          "type": "string",
          "minLength": 1,
          "description": "The webhook URL to deliver events to."
        },
        "enabled": {
          "type": "boolean",
          "default": true,
          "description": "Whether the endpoint should receive deliveries immediately after creation (default true)."
        },
        "domain_id": {
          "type": "string",
          "format": "uuid",
          "description": "Restrict deliveries to emails from a specific domain. Omit to receive events for all domains."
        },
        "rules": {
          "type": "object",
          "additionalProperties": true,
          "description": "Endpoint-specific filtering rules."
        }
      },
      "required": [
        "url"
      ]
    }
  },
  "required": [
    "requestBody"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🔴deleteEndpoint(id)

Soft-delete a webhook endpoint. The endpoint will no longer receive deliveries.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Endpoint ID from listEndpoints or createEndpoint."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟡testEndpoint(id)

Send a sample email.received event to a webhook endpoint to verify your signature verifier. Rate limited to 4/min and 30/hr. Successful deliveries and verified-domain endpoints are exempt.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Endpoint ID from listEndpoints or createEndpoint."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢listFilters

List all whitelist and blocklist filter rules for the organization.

輸入結構描述

{
  "type": "object",
  "properties": {},
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟡createFilter(requestBody)

Create a whitelist or blocklist filter rule. Patterns are stored lowercase. Per-domain filters require a Pro plan.

輸入結構描述

{
  "type": "object",
  "properties": {
    "requestBody": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "enum": [
            "whitelist",
            "blocklist"
          ],
          "description": "Whether to allow (whitelist) or block (blocklist) matching senders."
        },
        "pattern": {
          "type": "string",
          "minLength": 1,
          "maxLength": 500,
          "description": "Email address or pattern to filter."
        },
        "domain_id": {
          "type": "string",
          "format": "uuid",
          "description": "Restrict to a specific domain (Pro plan required). Omit for org-wide filter."
        }
      },
      "required": [
        "type",
        "pattern"
      ]
    }
  },
  "required": [
    "requestBody"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🔴deleteFilter(id)

Delete a filter rule.

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "format": "uuid",
      "description": "Filter rule ID from listFilters or createFilter."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟢listWebhookDeliveries(cursor, limit, email_id, status, date_from, ...)

List webhook delivery attempts with pagination and filters. Each delivery includes the target endpoint and a nested email object with sender/recipient/subject. Useful for diagnosing delivery failures or confirming a specific email was delivered.

輸入結構描述

{
  "type": "object",
  "properties": {
    "cursor": {
      "type": "string",
      "description": "Pagination cursor from a previous response's `meta.cursor` field."
    },
    "limit": {
      "type": "number",
      "minimum": 1,
      "maximum": 100,
      "default": 50,
      "description": "Maximum number of delivery records to return (1–100, default 50)."
    },
    "email_id": {
      "type": "string",
      "format": "uuid",
      "description": "Filter by inbound email ID."
    },
    "status": {
      "type": "string",
      "enum": [
        "pending",
        "delivered",
        "header_confirmed",
        "failed"
      ],
      "description": "Filter to deliveries in this status."
    },
    "date_from": {
      "type": "string",
      "format": "date-time",
      "description": "Inclusive lower bound on attempted_at (ISO 8601)."
    },
    "date_to": {
      "type": "string",
      "format": "date-time",
      "description": "Inclusive upper bound on attempted_at (ISO 8601)."
    }
  },
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟡replayWebhookDelivery(id)

Re-send a stored webhook payload from a previous delivery attempt to its original endpoint. Rate limited per org (burst + sustained windows, shared budget with email webhook replays).

輸入結構描述

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Delivery ID (numeric string from listWebhookDeliveries)."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}
🟡createEmailAddress(requestBody)

Get this user's Primitive managed inbox domain, creating the account on first use: no signup form, no password, no email verification, no browser. CALL THIS FIRST whenever you do not already have a Primitive API key and the user wants to send or receive email, instead of telling them to sign up or visit a website. On first use the REST response's address field is a domain such as pink-ram.primitive.email, not a complete mailbox. When it is non-null, this MCP result also includes sender_address such as [email protected] for use as sendEmail.requestBody.from. It also returns an api_key. IMPORTANT: pass that api_key as the `api_key` argument on every later Primitive tool call in this conversation, exactly as returned; those calls fail without it. If this user already has a domain, the result repeats it with existing_account: true. Report it as their existing managed inbox rather than announcing a new one, and calling again will not produce a different one. The result also carries an upgrade link the user can open whenever they want to attach this domain to a full account.

輸入結構描述

{
  "type": "object",
  "properties": {
    "requestBody": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "terms_accepted": {
          "const": true,
          "description": "Must be true. Creating the account accepts Primitive's terms of service (https://www.primitive.dev/terms); say so to the user rather than accepting silently on their behalf."
        },
        "device_name": {
          "type": "string",
          "description": "Optional label for where the account was created, e.g. \"ChatGPT\". Up to 80 characters once surrounding whitespace is removed. Shown to the user later so they can recognise this account."
        }
      },
      "required": [
        "terms_accepted"
      ]
    }
  },
  "required": [
    "requestBody"
  ],
  "additionalProperties": false
}

輸出結構描述

{
  "type": "object",
  "properties": {
    "tool": {
      "type": "string"
    },
    "status": {
      "type": "number"
    },
    "statusText": {
      "type": "string"
    },
    "data": {}
  },
  "required": [
    "tool",
    "status",
    "data"
  ],
  "additionalProperties": false
}

社群

為此伺服器評分

證據

近期觀測

已驗證未記錄版本30 個工具
已驗證未記錄版本30 個工具