diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 19ee807..71e95ba 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.19.0" + ".": "0.20.0" } diff --git a/.stats.yml b/.stats.yml index 1132870..8b90b08 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 25 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inbound%2Finbound-3a201e697c7829392693d40176a670c003c2f60d490c2cc51147ee341251678b.yml -openapi_spec_hash: 4f2b2086e995bc095acf7db4506b3355 -config_hash: 7664efcf01b23a96ae00ead0a64f22ee +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/inbound%2Finbound-04a8a5e5040d2818c904bbe928e57c790f8f06b7e1335197f8d9d9f66b202b3a.yml +openapi_spec_hash: c84e146f4513cb7169350473efb20290 +config_hash: 1450bd31f2a046791524466b8a5ea006 diff --git a/CHANGELOG.md b/CHANGELOG.md index e2b2ae2..5b81be9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 0.20.0 (2025-12-11) + +Full Changelog: [v0.19.0...v0.20.0](https://github.com/inboundemail/inbound-typescript-sdk/compare/v0.19.0...v0.20.0) + +### Features + +* **api:** api update ([feb8844](https://github.com/inboundemail/inbound-typescript-sdk/commit/feb884455a3fceda6cf1968a10d6553299e98400)) +* **api:** api update ([b7926ec](https://github.com/inboundemail/inbound-typescript-sdk/commit/b7926ec7c9dfea912995ec1e1be0cb89a02f2448)) +* **api:** api update ([ba47317](https://github.com/inboundemail/inbound-typescript-sdk/commit/ba473173ccab81066589006e8f905a40c595d40f)) +* **api:** api update ([d2fb94d](https://github.com/inboundemail/inbound-typescript-sdk/commit/d2fb94d3af9c8ebaa77723d40c7710c8c8ba2ed6)) +* **api:** api update ([2299442](https://github.com/inboundemail/inbound-typescript-sdk/commit/22994422dd114b52a9af6c3e3797ca32394ebd4a)) +* **api:** api update ([0ad20fe](https://github.com/inboundemail/inbound-typescript-sdk/commit/0ad20fecf3bd20dddba107b21ab5944c7eee90b6)) + + +### Bug Fixes + +* **mcp:** add client instantiation options to code tool ([cf6642b](https://github.com/inboundemail/inbound-typescript-sdk/commit/cf6642bed6778b624007f12f327b553aac286107)) + + +### Chores + +* **internal:** configure MCP Server hosting ([d4a7a76](https://github.com/inboundemail/inbound-typescript-sdk/commit/d4a7a7665c01b70b8dea8d835f761bbeeb5b18b9)) + ## 0.19.0 (2025-12-09) Full Changelog: [v0.18.0...v0.19.0](https://github.com/inboundemail/inbound-typescript-sdk/compare/v0.18.0...v0.19.0) diff --git a/README.md b/README.md index 3af60f9..fee8895 100644 --- a/README.md +++ b/README.md @@ -340,7 +340,6 @@ TypeScript >= 4.9 is supported. The following runtimes are supported: -- Web browsers (Up-to-date Chrome, Firefox, Safari, Edge, and more) - Node.js 20 LTS or later ([non-EOL](https://endoflife.date/nodejs)) versions. - Deno v1.28.0 or higher. - Bun 1.0 or later. @@ -349,6 +348,9 @@ The following runtimes are supported: - Jest 28 or greater with the `"node"` environment (`"jsdom"` is not supported at this time). - Nitro v2.6 or greater. +> [!WARNING] +> Web browser runtimes aren't supported. The SDK will throw an error if used in a browser environment. + Note that React Native is not supported at this time. If you are interested in other runtime environments, please open or upvote an issue on GitHub. diff --git a/package.json b/package.json index 65e919f..dfa8833 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "inboundemail", - "version": "0.19.0", + "version": "0.20.0", "description": "The official TypeScript library for the Inbound API", "author": "Inbound ", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/.dockerignore b/packages/mcp-server/.dockerignore new file mode 100644 index 0000000..1850726 --- /dev/null +++ b/packages/mcp-server/.dockerignore @@ -0,0 +1,66 @@ +# Dependencies +node_modules/ +**/node_modules/ + +# Build outputs +dist/ +**/dist/ +build/ +**/build/ + +# Git +.git/ +.gitignore + +# CI/CD +.github/ +.gitlab-ci.yml +.travis.yml + +# IDE +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db + +# Documentation +*.md +docs/ +LICENSE + +# Testing +test/ +tests/ +__tests__/ +*.test.js +*.spec.js +coverage/ +.nyc_output/ + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Environment +.env +.env.* + +# Temporary files +*.tmp +*.temp +.cache/ + +# Examples and scripts +examples/ +bin/ + +# Other packages (we only need mcp-server) +packages/*/ +!packages/mcp-server/ diff --git a/packages/mcp-server/Dockerfile b/packages/mcp-server/Dockerfile new file mode 100644 index 0000000..b952b0b --- /dev/null +++ b/packages/mcp-server/Dockerfile @@ -0,0 +1,81 @@ +# Dockerfile for Inbound MCP Server + # + # This Dockerfile builds a Docker image for the MCP Server. + # + # To build the image locally: + # docker build -f packages/mcp-server/Dockerfile -t inbound-docs-mcp:local . + # + # To run the image: + # docker run -i inbound-docs-mcp:local [OPTIONS] + # + # Common options: + # --tool= Include specific tools + # --resource= Include tools for specific resources + # --operation=read|write Filter by operation type + # --client= Set client compatibility (e.g., claude, cursor) + # --transport= Set transport type (stdio or http) + # + # For a full list of options: + # docker run -i inbound-docs-mcp:local --help + # + # Note: The MCP server uses stdio transport by default. Docker's -i flag + # enables interactive mode, allowing the container to communicate over stdin/stdout. + + # Build stage + FROM node:20-alpine AS builder + +# Enable corepack to use pnpm +RUN corepack enable && corepack prepare pnpm@latest --activate + + # Install bash for build script + RUN apk add --no-cache bash openssl + + # Set working directory + WORKDIR /build + + # Copy entire repository + COPY . . + + # Install all dependencies and build everything + RUN pnpm install --frozen-lockfile && \ + pnpm build + + # Production stage + + FROM denoland/deno:alpine + RUN apk add --no-cache npm + + # Add non-root user + RUN addgroup -g 1001 -S nodejs && adduser -S nodejs -u 1001 + + # Set working directory + WORKDIR /app + +# Copy the built mcp-server preserving directory structure +COPY --from=builder /build/packages/mcp-server/dist ./packages/mcp-server/dist +COPY --from=builder /build/packages/mcp-server/node_modules ./packages/mcp-server/node_modules + +# Copy node_modules from root (pnpm hoists dependencies here) +COPY --from=builder /build/node_modules ./node_modules + + # Copy the built inboundemail into node_modules + COPY --from=builder /build/dist ./node_modules/inboundemail + + # Change ownership to nodejs user + RUN chown -R nodejs:nodejs /app + + # Switch to non-root user + USER nodejs + + # The MCP server uses stdio transport by default + # No exposed ports needed for stdio communication + + # This is needed for node to run on the deno:alpine image. + # See . + ENV LD_LIBRARY_PATH=/usr/lib:/usr/local/lib + + # Set the entrypoint to the MCP server + ENTRYPOINT ["node", "packages/mcp-server/dist/index.js"] + + # Allow passing arguments to the MCP server + CMD [] diff --git a/packages/mcp-server/README.md b/packages/mcp-server/README.md index f4bac76..1200119 100644 --- a/packages/mcp-server/README.md +++ b/packages/mcp-server/README.md @@ -246,8 +246,8 @@ The following tools are available in this MCP server. ### Resource `domains`: -- `create_domains` (`write`): Add a new domain for email receiving. Automatically initiates SES verification and returns required DNS records. Subdomains inherit verification from their verified parent domain. -- `retrieve_domains` (`read`): Get detailed information about a specific domain including DNS records. Use `?check=true` for live DNS and SES verification. +- `create_domains` (`write`): Add a new domain for email receiving. Automatically initiates verification and returns required DNS records. Subdomains inherit verification from their verified parent domain. +- `retrieve_domains` (`read`): Get detailed information about a specific domain including DNS records. Use `?check=true` for a live verification check. - `update_domains` (`write`): Update catch-all email settings for a domain. Catch-all receives emails sent to any address on your domain. Domain must be verified first. - `list_domains` (`read`): Get paginated list of domains for authenticated user with optional filtering. - `delete_domains` (`write`): Delete a domain and all associated resources including email addresses, DNS records, and SES configurations. Root domains with subdomains must have subdomains deleted first. @@ -263,48 +263,16 @@ The following tools are available in this MCP server. ### Resource `email_addresses`: -- `create_email_addresses` (`write`): Create a new email address for an authenticated user's domain. Automatically configures AWS SES receipt rules. +- `create_email_addresses` (`write`): Create a new email address for an authenticated user's domain, optionally routing to a webhook or endpoint. - `retrieve_email_addresses` (`read`): Get a specific email address by ID with detailed information including routing configuration - `update_email_addresses` (`write`): Update an email address's routing (endpoint/webhook) or active status. Cannot have both endpoint and webhook. - `list_email_addresses` (`read`): Get paginated list of email addresses for authenticated user with optional filtering by domain, active status, and receipt rule configuration -- `delete_email_addresses` (`write`): Delete an email address and clean up associated SES receipt rules. Returns cleanup status. +- `delete_email_addresses` (`write`): Delete an email address. Returns cleanup status. ### Resource `emails`: - `retrieve_emails` (`read`): Retrieve a single email by ID. Works for sent, received, and scheduled emails. - `list_emails` (`read`): List all email activity (sent, received, and scheduled) with comprehensive filtering options. - - **Type Filtering:** - - - `all` - Returns sent, received, and scheduled emails combined (default) - - `sent` - Only outbound emails you've sent - - `received` - Only inbound emails you've received - - `scheduled` - Only emails scheduled for future delivery - - **Status Filtering:** - - - `delivered` - Successfully delivered emails - - `pending` - Emails currently being processed - - `failed` - Emails that failed to deliver - - `bounced` - Emails that bounced (sent only) - - `scheduled` - Emails scheduled for future delivery - - `cancelled` - Cancelled scheduled emails - - `unread` - Unread received emails - - `read` - Read received emails - - `archived` - Archived received emails - - **Time Range Filtering:** - - - `1h` - Last hour - - `24h` - Last 24 hours - - `7d` - Last 7 days - - `30d` - Last 30 days (default) - - `90d` - Last 90 days - - `all` - All time - - **Address Filtering:** - Supports filtering by domain ID, domain name, address ID, or raw email address (e.g., 'user@example.com'). - - `delete_emails` (`write`): Cancel a scheduled email by ID. Only works for emails that haven't been sent yet. - `reply_emails` (`write`): Reply to an email or thread. Accepts either an email ID or thread ID (replies to latest message in thread). Supports reply all functionality. - `retry_emails` (`write`): Retry delivery of a received email. Can retry to a specific endpoint, retry a specific failed delivery, or retry to all configured endpoints. @@ -325,44 +293,10 @@ The following tools are available in this MCP server. - `inbound` - Emails you received - `outbound` - Emails you sent (includes delivery status) - **Message Content:** - Each message includes: - - - Full body content (text and HTML) - - Sender and recipient information - - Attachments metadata - - Read status and timestamps - - Threading headers (In-Reply-To, References) - - **Typical Workflow:** - - 1. List threads using `GET /mail/threads` - 2. User clicks a thread - 3. Fetch full thread using this endpoint - 4. Display conversation view with all messages - - `list_mail` (`read`): List email threads (conversations) for your inbox with cursor-based pagination. This is the primary endpoint for building an inbox UI. **What is a Thread?** A thread groups related emails together based on the In-Reply-To and References headers, similar to how Gmail groups conversations. Each thread contains both inbound (received) and outbound (sent) messages. - **Filtering:** - - - `domain` - Filter by domain ID or name (e.g., 'example.com'). Returns threads where any participant matches the domain. - - `address` - Filter by email address (e.g., 'user@example.com'). Returns threads where the address is a participant. - - `search` - Search in subject lines and participant emails. - - `unread` - Set to 'true' to only return threads with unread messages. - - **Pagination:** - Uses cursor-based pagination for efficient infinite scroll. Pass `pagination.next_cursor` from the response as the `cursor` parameter to get the next page. - - **Response:** - Each thread includes: - - - Thread metadata (subject, participants, message count) - - `latest_message` - Preview of the most recent message (inbound or outbound) - - `has_unread` - Whether there are unread inbound messages - - `unread_count` - Number of unread messages - **Use with /mail/threads/:id:** Use this endpoint to list threads, then use `GET /mail/threads/:id` to fetch all messages in a specific thread. diff --git a/packages/mcp-server/package.json b/packages/mcp-server/package.json index 133a068..affcec6 100644 --- a/packages/mcp-server/package.json +++ b/packages/mcp-server/package.json @@ -1,6 +1,6 @@ { "name": "inbound-docs-mcp", - "version": "0.19.0", + "version": "0.20.0", "description": "The official MCP Server for the Inbound API", "author": "Inbound ", "types": "dist/index.d.ts", diff --git a/packages/mcp-server/src/code-tool.ts b/packages/mcp-server/src/code-tool.ts index 3e1f4fb..da99397 100644 --- a/packages/mcp-server/src/code-tool.ts +++ b/packages/mcp-server/src/code-tool.ts @@ -39,6 +39,7 @@ export async function codeTool() { }, body: JSON.stringify({ project_name: 'inbound', + client_opts: {}, code, }), }); diff --git a/packages/mcp-server/src/server.ts b/packages/mcp-server/src/server.ts index b885e82..87a602a 100644 --- a/packages/mcp-server/src/server.ts +++ b/packages/mcp-server/src/server.ts @@ -34,7 +34,7 @@ export const newMcpServer = () => new McpServer( { name: 'inboundemail_api', - version: '0.19.0', + version: '0.20.0', }, { capabilities: { tools: {}, logging: {} } }, ); diff --git a/packages/mcp-server/src/tools/domains/create-domains.ts b/packages/mcp-server/src/tools/domains/create-domains.ts index 05df068..51bf251 100644 --- a/packages/mcp-server/src/tools/domains/create-domains.ts +++ b/packages/mcp-server/src/tools/domains/create-domains.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'create_domains', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nAdd a new domain for email receiving. Automatically initiates SES verification and returns required DNS records. Subdomains inherit verification from their verified parent domain.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/domain_create_response',\n $defs: {\n domain_create_response: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n canReceiveEmails: {\n type: 'boolean'\n },\n createdAt: {\n type: 'string',\n format: 'date-time'\n },\n dnsRecords: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n isRequired: {\n type: 'boolean'\n },\n name: {\n type: 'string'\n },\n type: {\n type: 'string'\n },\n value: {\n type: 'string'\n },\n description: {\n type: 'string'\n }\n },\n required: [ 'isRequired',\n 'name',\n 'type',\n 'value'\n ]\n }\n },\n domain: {\n type: 'string'\n },\n domainProvider: {\n type: 'string'\n },\n hasMxRecords: {\n type: 'boolean'\n },\n providerConfidence: {\n type: 'string'\n },\n status: {\n type: 'string',\n enum: [ 'pending',\n 'verified',\n 'failed'\n ]\n },\n updatedAt: {\n type: 'string',\n format: 'date-time'\n },\n dnsConflict: {\n type: 'object',\n properties: {\n hasConflict: {\n type: 'boolean'\n },\n message: {\n type: 'string'\n },\n conflictType: {\n type: 'string',\n enum: [ 'mx',\n 'cname',\n 'both'\n ]\n },\n existingRecords: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n type: {\n type: 'string'\n },\n value: {\n type: 'string'\n }\n },\n required: [ 'type',\n 'value'\n ]\n }\n }\n },\n required: [ 'hasConflict',\n 'message'\n ]\n },\n mailFromDomain: {\n type: 'string'\n },\n mailFromDomainStatus: {\n type: 'string'\n },\n message: {\n type: 'string'\n },\n parentDomain: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'canReceiveEmails',\n 'createdAt',\n 'dnsRecords',\n 'domain',\n 'domainProvider',\n 'hasMxRecords',\n 'providerConfidence',\n 'status',\n 'updatedAt'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nAdd a new domain for email receiving. Automatically initiates verification and returns required DNS records. Subdomains inherit verification from their verified parent domain.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/domain_create_response',\n $defs: {\n domain_create_response: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n canReceiveEmails: {\n type: 'boolean'\n },\n createdAt: {\n type: 'string',\n format: 'date-time'\n },\n dnsRecords: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n isRequired: {\n type: 'boolean'\n },\n name: {\n type: 'string'\n },\n type: {\n type: 'string'\n },\n value: {\n type: 'string'\n },\n description: {\n type: 'string'\n }\n },\n required: [ 'isRequired',\n 'name',\n 'type',\n 'value'\n ]\n }\n },\n domain: {\n type: 'string'\n },\n domainProvider: {\n type: 'string'\n },\n hasMxRecords: {\n type: 'boolean'\n },\n providerConfidence: {\n type: 'string'\n },\n status: {\n type: 'string',\n enum: [ 'pending',\n 'verified',\n 'failed'\n ]\n },\n updatedAt: {\n type: 'string',\n format: 'date-time'\n },\n dnsConflict: {\n type: 'object',\n properties: {\n hasConflict: {\n type: 'boolean'\n },\n message: {\n type: 'string'\n },\n conflictType: {\n type: 'string',\n enum: [ 'mx',\n 'cname',\n 'both'\n ]\n },\n existingRecords: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n type: {\n type: 'string'\n },\n value: {\n type: 'string'\n }\n },\n required: [ 'type',\n 'value'\n ]\n }\n }\n },\n required: [ 'hasConflict',\n 'message'\n ]\n },\n mailFromDomain: {\n type: 'string'\n },\n mailFromDomainStatus: {\n type: 'string'\n },\n message: {\n type: 'string'\n },\n parentDomain: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'canReceiveEmails',\n 'createdAt',\n 'dnsRecords',\n 'domain',\n 'domainProvider',\n 'hasMxRecords',\n 'providerConfidence',\n 'status',\n 'updatedAt'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/domains/retrieve-domains.ts b/packages/mcp-server/src/tools/domains/retrieve-domains.ts index 68d620e..70d68e0 100644 --- a/packages/mcp-server/src/tools/domains/retrieve-domains.ts +++ b/packages/mcp-server/src/tools/domains/retrieve-domains.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'retrieve_domains', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nGet detailed information about a specific domain including DNS records. Use `?check=true` for live DNS and SES verification.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/domain_retrieve_response',\n $defs: {\n domain_retrieve_response: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n canReceiveEmails: {\n type: 'boolean'\n },\n catchAllEndpointId: {\n type: 'string'\n },\n createdAt: {\n type: 'string',\n format: 'date-time'\n },\n dnsRecords: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n createdAt: {\n type: 'string',\n format: 'date-time'\n },\n domainId: {\n type: 'string'\n },\n isRequired: {\n type: 'boolean'\n },\n isVerified: {\n type: 'boolean'\n },\n lastChecked: {\n type: 'string',\n format: 'date-time'\n },\n name: {\n type: 'string'\n },\n recordType: {\n type: 'string'\n },\n value: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'createdAt',\n 'domainId',\n 'isRequired',\n 'isVerified',\n 'lastChecked',\n 'name',\n 'recordType',\n 'value'\n ]\n }\n },\n domain: {\n type: 'string'\n },\n domainProvider: {\n type: 'string'\n },\n hasMxRecords: {\n type: 'boolean'\n },\n isCatchAllEnabled: {\n type: 'boolean'\n },\n lastDnsCheck: {\n type: 'string',\n format: 'date-time'\n },\n lastSesCheck: {\n type: 'string',\n format: 'date-time'\n },\n mailFromDomain: {\n type: 'string'\n },\n mailFromDomainStatus: {\n type: 'string'\n },\n mailFromDomainVerifiedAt: {\n type: 'string',\n format: 'date-time'\n },\n providerConfidence: {\n type: 'string'\n },\n receiveDmarcEmails: {\n type: 'boolean'\n },\n stats: {\n type: 'object',\n properties: {\n activeEmailAddresses: {\n type: 'number'\n },\n emailsLast24h: {\n type: 'number'\n },\n emailsLast30d: {\n type: 'number'\n },\n emailsLast7d: {\n type: 'number'\n },\n totalEmailAddresses: {\n type: 'number'\n }\n },\n required: [ 'activeEmailAddresses',\n 'emailsLast24h',\n 'emailsLast30d',\n 'emailsLast7d',\n 'totalEmailAddresses'\n ]\n },\n status: {\n type: 'string'\n },\n updatedAt: {\n type: 'string',\n format: 'date-time'\n },\n userId: {\n type: 'string'\n },\n authRecommendations: {\n type: 'object',\n properties: {\n dmarc: {\n type: 'object',\n properties: {\n description: {\n type: 'string'\n },\n name: {\n type: 'string'\n },\n value: {\n type: 'string'\n }\n },\n required: [ 'description',\n 'name',\n 'value'\n ]\n },\n spf: {\n type: 'object',\n properties: {\n description: {\n type: 'string'\n },\n name: {\n type: 'string'\n },\n value: {\n type: 'string'\n }\n },\n required: [ 'description',\n 'name',\n 'value'\n ]\n }\n }\n },\n catchAllEndpoint: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n isActive: {\n type: 'boolean'\n },\n name: {\n type: 'string'\n },\n type: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'isActive',\n 'name',\n 'type'\n ]\n },\n inheritsFromParent: {\n type: 'boolean'\n },\n parentDomain: {\n type: 'string'\n },\n verificationCheck: {\n type: 'object',\n properties: {\n dnsRecords: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n isVerified: {\n type: 'boolean'\n },\n name: {\n type: 'string'\n },\n type: {\n type: 'string'\n },\n value: {\n type: 'string'\n },\n error: {\n type: 'string'\n }\n },\n required: [ 'isVerified',\n 'name',\n 'type',\n 'value'\n ]\n }\n },\n isFullyVerified: {\n type: 'boolean'\n },\n lastChecked: {\n type: 'string',\n format: 'date-time'\n },\n sesStatus: {\n type: 'string'\n },\n dkimStatus: {\n type: 'string'\n },\n dkimTokens: {\n type: 'array',\n items: {\n type: 'string'\n }\n },\n dkimVerified: {\n type: 'boolean'\n },\n mailFromDomain: {\n type: 'string'\n },\n mailFromStatus: {\n type: 'string'\n },\n mailFromVerified: {\n type: 'boolean'\n }\n },\n required: [ 'dnsRecords',\n 'isFullyVerified',\n 'lastChecked',\n 'sesStatus'\n ]\n }\n },\n required: [ 'id',\n 'canReceiveEmails',\n 'catchAllEndpointId',\n 'createdAt',\n 'dnsRecords',\n 'domain',\n 'domainProvider',\n 'hasMxRecords',\n 'isCatchAllEnabled',\n 'lastDnsCheck',\n 'lastSesCheck',\n 'mailFromDomain',\n 'mailFromDomainStatus',\n 'mailFromDomainVerifiedAt',\n 'providerConfidence',\n 'receiveDmarcEmails',\n 'stats',\n 'status',\n 'updatedAt',\n 'userId'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nGet detailed information about a specific domain including DNS records. Use `?check=true` for a live verification check.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/domain_retrieve_response',\n $defs: {\n domain_retrieve_response: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n canReceiveEmails: {\n type: 'boolean'\n },\n catchAllEndpointId: {\n type: 'string'\n },\n createdAt: {\n type: 'string',\n format: 'date-time'\n },\n dnsRecords: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n createdAt: {\n type: 'string',\n format: 'date-time'\n },\n domainId: {\n type: 'string'\n },\n isRequired: {\n type: 'boolean'\n },\n isVerified: {\n type: 'boolean'\n },\n lastChecked: {\n type: 'string',\n format: 'date-time'\n },\n name: {\n type: 'string'\n },\n recordType: {\n type: 'string'\n },\n value: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'createdAt',\n 'domainId',\n 'isRequired',\n 'isVerified',\n 'lastChecked',\n 'name',\n 'recordType',\n 'value'\n ]\n }\n },\n domain: {\n type: 'string'\n },\n domainProvider: {\n type: 'string'\n },\n hasMxRecords: {\n type: 'boolean'\n },\n isCatchAllEnabled: {\n type: 'boolean'\n },\n lastDnsCheck: {\n type: 'string',\n format: 'date-time'\n },\n lastSesCheck: {\n type: 'string',\n format: 'date-time'\n },\n mailFromDomain: {\n type: 'string'\n },\n mailFromDomainStatus: {\n type: 'string'\n },\n mailFromDomainVerifiedAt: {\n type: 'string',\n format: 'date-time'\n },\n providerConfidence: {\n type: 'string'\n },\n receiveDmarcEmails: {\n type: 'boolean'\n },\n stats: {\n type: 'object',\n properties: {\n activeEmailAddresses: {\n type: 'number'\n },\n emailsLast24h: {\n type: 'number'\n },\n emailsLast30d: {\n type: 'number'\n },\n emailsLast7d: {\n type: 'number'\n },\n totalEmailAddresses: {\n type: 'number'\n }\n },\n required: [ 'activeEmailAddresses',\n 'emailsLast24h',\n 'emailsLast30d',\n 'emailsLast7d',\n 'totalEmailAddresses'\n ]\n },\n status: {\n type: 'string'\n },\n updatedAt: {\n type: 'string',\n format: 'date-time'\n },\n userId: {\n type: 'string'\n },\n authRecommendations: {\n type: 'object',\n properties: {\n dmarc: {\n type: 'object',\n properties: {\n description: {\n type: 'string'\n },\n name: {\n type: 'string'\n },\n value: {\n type: 'string'\n }\n },\n required: [ 'description',\n 'name',\n 'value'\n ]\n },\n spf: {\n type: 'object',\n properties: {\n description: {\n type: 'string'\n },\n name: {\n type: 'string'\n },\n value: {\n type: 'string'\n }\n },\n required: [ 'description',\n 'name',\n 'value'\n ]\n }\n }\n },\n catchAllEndpoint: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n isActive: {\n type: 'boolean'\n },\n name: {\n type: 'string'\n },\n type: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'isActive',\n 'name',\n 'type'\n ]\n },\n inheritsFromParent: {\n type: 'boolean'\n },\n parentDomain: {\n type: 'string'\n },\n verificationCheck: {\n type: 'object',\n properties: {\n dnsRecords: {\n type: 'array',\n items: {\n type: 'object',\n properties: {\n isVerified: {\n type: 'boolean'\n },\n name: {\n type: 'string'\n },\n type: {\n type: 'string'\n },\n value: {\n type: 'string'\n },\n error: {\n type: 'string'\n }\n },\n required: [ 'isVerified',\n 'name',\n 'type',\n 'value'\n ]\n }\n },\n isFullyVerified: {\n type: 'boolean'\n },\n lastChecked: {\n type: 'string',\n format: 'date-time'\n },\n sesStatus: {\n type: 'string'\n },\n dkimStatus: {\n type: 'string'\n },\n dkimTokens: {\n type: 'array',\n items: {\n type: 'string'\n }\n },\n dkimVerified: {\n type: 'boolean'\n },\n mailFromDomain: {\n type: 'string'\n },\n mailFromStatus: {\n type: 'string'\n },\n mailFromVerified: {\n type: 'boolean'\n }\n },\n required: [ 'dnsRecords',\n 'isFullyVerified',\n 'lastChecked',\n 'sesStatus'\n ]\n }\n },\n required: [ 'id',\n 'canReceiveEmails',\n 'catchAllEndpointId',\n 'createdAt',\n 'dnsRecords',\n 'domain',\n 'domainProvider',\n 'hasMxRecords',\n 'isCatchAllEnabled',\n 'lastDnsCheck',\n 'lastSesCheck',\n 'mailFromDomain',\n 'mailFromDomainStatus',\n 'mailFromDomainVerifiedAt',\n 'providerConfidence',\n 'receiveDmarcEmails',\n 'stats',\n 'status',\n 'updatedAt',\n 'userId'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/email-addresses/create-email-addresses.ts b/packages/mcp-server/src/tools/email-addresses/create-email-addresses.ts index d6a43f0..85d40b0 100644 --- a/packages/mcp-server/src/tools/email-addresses/create-email-addresses.ts +++ b/packages/mcp-server/src/tools/email-addresses/create-email-addresses.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'create_email_addresses', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nCreate a new email address for an authenticated user's domain. Automatically configures AWS SES receipt rules.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/email_address_create_response',\n $defs: {\n email_address_create_response: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n address: {\n type: 'string'\n },\n createdAt: {\n type: 'string',\n format: 'date-time'\n },\n domain: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n name: {\n type: 'string'\n },\n status: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'name',\n 'status'\n ]\n },\n domainId: {\n type: 'string'\n },\n endpointId: {\n type: 'string'\n },\n isActive: {\n type: 'boolean'\n },\n isReceiptRuleConfigured: {\n type: 'boolean'\n },\n receiptRuleName: {\n type: 'string'\n },\n routing: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n isActive: {\n type: 'boolean'\n },\n name: {\n type: 'string'\n },\n type: {\n type: 'string',\n enum: [ 'webhook',\n 'endpoint',\n 'none'\n ]\n },\n config: {\n type: 'object',\n additionalProperties: true\n }\n },\n required: [ 'id',\n 'isActive',\n 'name',\n 'type'\n ]\n },\n updatedAt: {\n type: 'string',\n format: 'date-time'\n },\n userId: {\n type: 'string'\n },\n webhookId: {\n type: 'string'\n },\n warning: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'address',\n 'createdAt',\n 'domain',\n 'domainId',\n 'endpointId',\n 'isActive',\n 'isReceiptRuleConfigured',\n 'receiptRuleName',\n 'routing',\n 'updatedAt',\n 'userId',\n 'webhookId'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nCreate a new email address for an authenticated user's domain, optionally routing to a webhook or endpoint.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/email_address_create_response',\n $defs: {\n email_address_create_response: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n address: {\n type: 'string'\n },\n createdAt: {\n type: 'string',\n format: 'date-time'\n },\n domain: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n name: {\n type: 'string'\n },\n status: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'name',\n 'status'\n ]\n },\n domainId: {\n type: 'string'\n },\n endpointId: {\n type: 'string'\n },\n isActive: {\n type: 'boolean'\n },\n isReceiptRuleConfigured: {\n type: 'boolean'\n },\n receiptRuleName: {\n type: 'string'\n },\n routing: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n isActive: {\n type: 'boolean'\n },\n name: {\n type: 'string'\n },\n type: {\n type: 'string',\n enum: [ 'webhook',\n 'endpoint',\n 'none'\n ]\n },\n config: {\n type: 'object',\n additionalProperties: true\n }\n },\n required: [ 'id',\n 'isActive',\n 'name',\n 'type'\n ]\n },\n updatedAt: {\n type: 'string',\n format: 'date-time'\n },\n userId: {\n type: 'string'\n },\n webhookId: {\n type: 'string'\n },\n warning: {\n type: 'string'\n }\n },\n required: [ 'id',\n 'address',\n 'createdAt',\n 'domain',\n 'domainId',\n 'endpointId',\n 'isActive',\n 'isReceiptRuleConfigured',\n 'receiptRuleName',\n 'routing',\n 'updatedAt',\n 'userId',\n 'webhookId'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/email-addresses/delete-email-addresses.ts b/packages/mcp-server/src/tools/email-addresses/delete-email-addresses.ts index 6031c60..a6670ce 100644 --- a/packages/mcp-server/src/tools/email-addresses/delete-email-addresses.ts +++ b/packages/mcp-server/src/tools/email-addresses/delete-email-addresses.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'delete_email_addresses', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nDelete an email address and clean up associated SES receipt rules. Returns cleanup status.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/email_address_delete_response',\n $defs: {\n email_address_delete_response: {\n type: 'object',\n properties: {\n cleanup: {\n type: 'object',\n properties: {\n domain: {\n type: 'string'\n },\n emailAddress: {\n type: 'string'\n },\n sesRuleUpdated: {\n type: 'boolean'\n },\n warning: {\n type: 'string'\n }\n },\n required: [ 'domain',\n 'emailAddress',\n 'sesRuleUpdated'\n ]\n },\n message: {\n type: 'string'\n }\n },\n required: [ 'cleanup',\n 'message'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nDelete an email address. Returns cleanup status.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/email_address_delete_response',\n $defs: {\n email_address_delete_response: {\n type: 'object',\n properties: {\n cleanup: {\n type: 'object',\n properties: {\n domain: {\n type: 'string'\n },\n emailAddress: {\n type: 'string'\n },\n sesRuleUpdated: {\n type: 'boolean'\n },\n warning: {\n type: 'string'\n }\n },\n required: [ 'domain',\n 'emailAddress',\n 'sesRuleUpdated'\n ]\n },\n message: {\n type: 'string'\n }\n },\n required: [ 'cleanup',\n 'message'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/emails/list-emails.ts b/packages/mcp-server/src/tools/emails/list-emails.ts index c807aa5..d4658f7 100644 --- a/packages/mcp-server/src/tools/emails/list-emails.ts +++ b/packages/mcp-server/src/tools/emails/list-emails.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_emails', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nList all email activity (sent, received, and scheduled) with comprehensive filtering options.\n\n**Type Filtering:**\n- `all` - Returns sent, received, and scheduled emails combined (default)\n- `sent` - Only outbound emails you've sent\n- `received` - Only inbound emails you've received\n- `scheduled` - Only emails scheduled for future delivery\n\n**Status Filtering:**\n- `delivered` - Successfully delivered emails\n- `pending` - Emails currently being processed\n- `failed` - Emails that failed to deliver\n- `bounced` - Emails that bounced (sent only)\n- `scheduled` - Emails scheduled for future delivery\n- `cancelled` - Cancelled scheduled emails\n- `unread` - Unread received emails\n- `read` - Read received emails\n- `archived` - Archived received emails\n\n**Time Range Filtering:**\n- `1h` - Last hour\n- `24h` - Last 24 hours\n- `7d` - Last 7 days\n- `30d` - Last 30 days (default)\n- `90d` - Last 90 days\n- `all` - All time\n\n**Address Filtering:**\nSupports filtering by domain ID, domain name, address ID, or raw email address (e.g., 'user@example.com').\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/email_list_response',\n $defs: {\n email_list_response: {\n type: 'object',\n properties: {\n data: {\n type: 'array',\n description: 'Array of email objects matching the query',\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Unique identifier for the email'\n },\n created_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the email was created/received'\n },\n from: {\n type: 'string',\n description: 'Sender email address'\n },\n has_attachments: {\n type: 'boolean',\n description: 'Whether the email has any attachments'\n },\n status: {\n type: 'string',\n description: 'Current status of the email (delivered, pending, failed, bounced, scheduled, cancelled)'\n },\n subject: {\n type: 'string',\n description: 'Email subject line'\n },\n to: {\n type: 'array',\n description: 'Array of recipient email addresses',\n items: {\n type: 'string'\n }\n },\n type: {\n type: 'string',\n enum: [ 'sent',\n 'received',\n 'scheduled'\n ]\n },\n attachment_count: {\n type: 'number',\n description: 'Number of attachments on the email'\n },\n cc: {\n type: 'array',\n description: 'Array of CC recipient email addresses',\n items: {\n type: 'string'\n }\n },\n from_name: {\n type: 'string',\n description: 'Sender display name if available'\n },\n is_archived: {\n type: 'boolean',\n description: 'Whether the email has been archived (only for received emails)'\n },\n is_read: {\n type: 'boolean',\n description: 'Whether the email has been read (only for received emails)'\n },\n message_id: {\n type: 'string',\n description: 'RFC 2822 Message-ID header value'\n },\n preview: {\n type: 'string',\n description: 'First 200 characters of the email body as a preview'\n },\n read_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the email was marked as read (only for received emails)'\n },\n scheduled_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the email is scheduled to be sent'\n },\n sent_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the email was sent'\n },\n thread_id: {\n type: 'string',\n description: 'ID of the thread this email belongs to, if threaded'\n }\n },\n required: [ 'id',\n 'created_at',\n 'from',\n 'has_attachments',\n 'status',\n 'subject',\n 'to',\n 'type'\n ]\n }\n },\n filters: {\n type: 'object',\n description: 'Applied filters for this query',\n properties: {\n address: {\n type: 'string',\n description: 'Applied address filter'\n },\n domain: {\n type: 'string',\n description: 'Applied domain filter'\n },\n search: {\n type: 'string',\n description: 'Applied search query'\n },\n status: {\n type: 'string',\n description: 'Applied status filter'\n },\n time_range: {\n type: 'string',\n description: 'Applied time range filter'\n },\n type: {\n type: 'string',\n description: 'Applied type filter'\n }\n }\n },\n pagination: {\n type: 'object',\n description: 'Pagination metadata',\n properties: {\n has_more: {\n type: 'boolean',\n description: 'Whether there are more results available'\n },\n limit: {\n type: 'number',\n description: 'Number of results per page'\n },\n offset: {\n type: 'number',\n description: 'Number of results skipped'\n },\n total: {\n type: 'number',\n description: 'Total number of matching emails'\n }\n },\n required: [ 'has_more',\n 'limit',\n 'offset',\n 'total'\n ]\n }\n },\n required: [ 'data',\n 'filters',\n 'pagination'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nList all email activity (sent, received, and scheduled) with comprehensive filtering options.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/email_list_response',\n $defs: {\n email_list_response: {\n type: 'object',\n properties: {\n data: {\n type: 'array',\n description: 'Array of email objects matching the query',\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Unique identifier for the email'\n },\n created_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the email was created/received'\n },\n from: {\n type: 'string',\n description: 'Sender email address'\n },\n has_attachments: {\n type: 'boolean',\n description: 'Whether the email has any attachments'\n },\n status: {\n type: 'string',\n description: 'Current status of the email (delivered, pending, failed, bounced, scheduled, cancelled)'\n },\n subject: {\n type: 'string',\n description: 'Email subject line'\n },\n to: {\n type: 'array',\n description: 'Array of recipient email addresses',\n items: {\n type: 'string'\n }\n },\n type: {\n type: 'string',\n enum: [ 'sent',\n 'received',\n 'scheduled'\n ]\n },\n attachment_count: {\n type: 'number',\n description: 'Number of attachments on the email'\n },\n cc: {\n type: 'array',\n description: 'Array of CC recipient email addresses',\n items: {\n type: 'string'\n }\n },\n from_name: {\n type: 'string',\n description: 'Sender display name if available'\n },\n is_archived: {\n type: 'boolean',\n description: 'Whether the email has been archived (only for received emails)'\n },\n is_read: {\n type: 'boolean',\n description: 'Whether the email has been read (only for received emails)'\n },\n message_id: {\n type: 'string',\n description: 'RFC 2822 Message-ID header value'\n },\n preview: {\n type: 'string',\n description: 'First 200 characters of the email body as a preview'\n },\n read_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the email was marked as read (only for received emails)'\n },\n scheduled_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the email is scheduled to be sent'\n },\n sent_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the email was sent'\n },\n thread_id: {\n type: 'string',\n description: 'ID of the thread this email belongs to, if threaded'\n }\n },\n required: [ 'id',\n 'created_at',\n 'from',\n 'has_attachments',\n 'status',\n 'subject',\n 'to',\n 'type'\n ]\n }\n },\n filters: {\n type: 'object',\n description: 'Applied filters for this query',\n properties: {\n address: {\n type: 'string',\n description: 'Applied address filter'\n },\n domain: {\n type: 'string',\n description: 'Applied domain filter'\n },\n search: {\n type: 'string',\n description: 'Applied search query'\n },\n status: {\n type: 'string',\n description: 'Applied status filter'\n },\n time_range: {\n type: 'string',\n description: 'Applied time range filter'\n },\n type: {\n type: 'string',\n description: 'Applied type filter'\n }\n }\n },\n pagination: {\n type: 'object',\n description: 'Pagination metadata',\n properties: {\n has_more: {\n type: 'boolean',\n description: 'Whether there are more results available'\n },\n limit: {\n type: 'number',\n description: 'Number of results per page'\n },\n offset: {\n type: 'number',\n description: 'Number of results skipped'\n },\n total: {\n type: 'number',\n description: 'Total number of matching emails'\n }\n },\n required: [ 'has_more',\n 'limit',\n 'offset',\n 'total'\n ]\n }\n },\n required: [ 'data',\n 'filters',\n 'pagination'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/emails/send-emails.ts b/packages/mcp-server/src/tools/emails/send-emails.ts index 0d50a59..6512c7a 100644 --- a/packages/mcp-server/src/tools/emails/send-emails.ts +++ b/packages/mcp-server/src/tools/emails/send-emails.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'send_emails', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nSend an email immediately or schedule it for later using the scheduled_at parameter. Supports HTML/text content, attachments, and custom headers.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/email_send_response',\n $defs: {\n email_send_response: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n message_id: {\n type: 'string'\n }\n },\n required: [ 'id'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nSend an email immediately or schedule it for later using the scheduled_at parameter. Supports HTML/text content, attachments, and custom headers.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/email_send_response',\n $defs: {\n email_send_response: {\n type: 'object',\n properties: {\n id: {\n type: 'string'\n },\n message_id: {\n type: 'string'\n },\n scheduled_at: {\n type: 'string'\n },\n status: {\n type: 'string',\n enum: [ 'sent',\n 'scheduled'\n ]\n },\n timezone: {\n type: 'string'\n }\n },\n required: [ 'id'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/endpoints/create-endpoints.ts b/packages/mcp-server/src/tools/endpoints/create-endpoints.ts index 84b87bf..3ee5dc3 100644 --- a/packages/mcp-server/src/tools/endpoints/create-endpoints.ts +++ b/packages/mcp-server/src/tools/endpoints/create-endpoints.ts @@ -26,6 +26,7 @@ export const tool: Tool = { anyOf: [ { type: 'object', + title: 'WebhookConfig', properties: { url: { type: 'string', @@ -46,6 +47,7 @@ export const tool: Tool = { }, { type: 'object', + title: 'EmailConfig', properties: { forwardTo: { type: 'string', @@ -58,6 +60,7 @@ export const tool: Tool = { }, { type: 'object', + title: 'EmailGroupConfig', properties: { emails: { type: 'array', diff --git a/packages/mcp-server/src/tools/endpoints/update-endpoints.ts b/packages/mcp-server/src/tools/endpoints/update-endpoints.ts index 69cb298..c2ba408 100644 --- a/packages/mcp-server/src/tools/endpoints/update-endpoints.ts +++ b/packages/mcp-server/src/tools/endpoints/update-endpoints.ts @@ -29,6 +29,7 @@ export const tool: Tool = { anyOf: [ { type: 'object', + title: 'WebhookConfig', properties: { url: { type: 'string', @@ -49,6 +50,7 @@ export const tool: Tool = { }, { type: 'object', + title: 'EmailConfig', properties: { forwardTo: { type: 'string', @@ -61,6 +63,7 @@ export const tool: Tool = { }, { type: 'object', + title: 'EmailGroupConfig', properties: { emails: { type: 'array', diff --git a/packages/mcp-server/src/tools/mail/list-mail.ts b/packages/mcp-server/src/tools/mail/list-mail.ts index d7700c6..0efcf5a 100644 --- a/packages/mcp-server/src/tools/mail/list-mail.ts +++ b/packages/mcp-server/src/tools/mail/list-mail.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'list_mail', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nList email threads (conversations) for your inbox with cursor-based pagination. This is the primary endpoint for building an inbox UI.\n\n**What is a Thread?**\nA thread groups related emails together based on the In-Reply-To and References headers, similar to how Gmail groups conversations. Each thread contains both inbound (received) and outbound (sent) messages.\n\n**Filtering:**\n- `domain` - Filter by domain ID or name (e.g., 'example.com'). Returns threads where any participant matches the domain.\n- `address` - Filter by email address (e.g., 'user@example.com'). Returns threads where the address is a participant.\n- `search` - Search in subject lines and participant emails.\n- `unread` - Set to 'true' to only return threads with unread messages.\n\n**Pagination:**\nUses cursor-based pagination for efficient infinite scroll. Pass `pagination.next_cursor` from the response as the `cursor` parameter to get the next page.\n\n**Response:**\nEach thread includes:\n- Thread metadata (subject, participants, message count)\n- `latest_message` - Preview of the most recent message (inbound or outbound)\n- `has_unread` - Whether there are unread inbound messages\n- `unread_count` - Number of unread messages\n\n**Use with /mail/threads/:id:**\nUse this endpoint to list threads, then use `GET /mail/threads/:id` to fetch all messages in a specific thread.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/mail_list_response',\n $defs: {\n mail_list_response: {\n type: 'object',\n properties: {\n filters: {\n type: 'object',\n description: 'Applied filters for this query',\n properties: {\n address: {\n type: 'string',\n description: 'Applied address filter (resolved email address)'\n },\n domain: {\n type: 'string',\n description: 'Applied domain filter (resolved domain name)'\n },\n search: {\n type: 'string',\n description: 'Applied search query'\n },\n unread_only: {\n type: 'boolean',\n description: 'Whether filtering for unread threads only'\n }\n }\n },\n pagination: {\n type: 'object',\n description: 'Pagination metadata for cursor-based pagination',\n properties: {\n has_more: {\n type: 'boolean',\n description: 'Whether there are more threads available after this page'\n },\n limit: {\n type: 'number',\n description: 'Number of results per page'\n },\n next_cursor: {\n type: 'string',\n description: 'Cursor to pass as the `cursor` parameter to fetch the next page. Null if no more results.'\n }\n },\n required: [ 'has_more',\n 'limit'\n ]\n },\n threads: {\n type: 'array',\n description: 'Array of thread objects matching the query, sorted by last message date (newest first)',\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Unique identifier for the thread'\n },\n created_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the thread was created (first message received)'\n },\n has_unread: {\n type: 'boolean',\n description: 'Whether the thread has any unread inbound messages'\n },\n is_archived: {\n type: 'boolean',\n description: 'Whether the thread has been archived'\n },\n last_message_at: {\n type: 'string',\n description: 'ISO 8601 timestamp of the most recent message in the thread'\n },\n message_count: {\n type: 'number',\n description: 'Total number of messages in the thread (both inbound and outbound)'\n },\n participant_emails: {\n type: 'array',\n description: 'Array of all unique email addresses that have participated in this thread',\n items: {\n type: 'string'\n }\n },\n participant_names: {\n type: 'array',\n description: 'Array of formatted participant names in the format \\'First Last \\' or just \\'email@domain.com\\' if no name is available',\n items: {\n type: 'string'\n }\n },\n root_message_id: {\n type: 'string',\n description: 'RFC 2822 Message-ID of the first message in the thread'\n },\n latest_message: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Unique identifier of the message'\n },\n from_text: {\n type: 'string',\n description: 'Formatted sender information (name and/or email)'\n },\n has_attachments: {\n type: 'boolean',\n description: 'Whether the message has any attachments'\n },\n is_read: {\n type: 'boolean',\n description: 'Whether the message has been read (always true for outbound)'\n },\n type: {\n type: 'string',\n description: 'Whether the message was received (inbound) or sent (outbound)',\n enum: [ 'inbound',\n 'outbound'\n ]\n },\n date: {\n type: 'string',\n description: 'ISO 8601 timestamp of when the message was sent/received'\n },\n subject: {\n type: 'string',\n description: 'Subject line of the message'\n },\n text_preview: {\n type: 'string',\n description: 'First 200 characters of the message body as a preview'\n }\n },\n required: [ 'id',\n 'from_text',\n 'has_attachments',\n 'is_read',\n 'type'\n ]\n },\n normalized_subject: {\n type: 'string',\n description: 'Normalized subject line (stripped of Re:, Fwd:, etc.) used for thread grouping'\n },\n unread_count: {\n type: 'number',\n description: 'Number of unread messages in the thread'\n }\n },\n required: [ 'id',\n 'created_at',\n 'has_unread',\n 'is_archived',\n 'last_message_at',\n 'message_count',\n 'participant_emails',\n 'participant_names',\n 'root_message_id'\n ]\n }\n }\n },\n required: [ 'filters',\n 'pagination',\n 'threads'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nList email threads (conversations) for your inbox with cursor-based pagination. This is the primary endpoint for building an inbox UI.\n\n**What is a Thread?**\nA thread groups related emails together based on the In-Reply-To and References headers, similar to how Gmail groups conversations. Each thread contains both inbound (received) and outbound (sent) messages.\n\n**Use with /mail/threads/:id:**\nUse this endpoint to list threads, then use `GET /mail/threads/:id` to fetch all messages in a specific thread.\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/mail_list_response',\n $defs: {\n mail_list_response: {\n type: 'object',\n properties: {\n filters: {\n type: 'object',\n description: 'Applied filters for this query',\n properties: {\n address: {\n type: 'string',\n description: 'Applied address filter (resolved email address)'\n },\n domain: {\n type: 'string',\n description: 'Applied domain filter (resolved domain name)'\n },\n search: {\n type: 'string',\n description: 'Applied search query'\n },\n unread_only: {\n type: 'boolean',\n description: 'Whether filtering for unread threads only'\n }\n }\n },\n pagination: {\n type: 'object',\n description: 'Pagination metadata for cursor-based pagination',\n properties: {\n has_more: {\n type: 'boolean',\n description: 'Whether there are more threads available after this page'\n },\n limit: {\n type: 'number',\n description: 'Number of results per page'\n },\n next_cursor: {\n type: 'string',\n description: 'Cursor to pass as the `cursor` parameter to fetch the next page. Null if no more results.'\n }\n },\n required: [ 'has_more',\n 'limit'\n ]\n },\n threads: {\n type: 'array',\n description: 'Array of thread objects matching the query, sorted by last message date (newest first)',\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Unique identifier for the thread'\n },\n created_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the thread was created (first message received)'\n },\n has_unread: {\n type: 'boolean',\n description: 'Whether the thread has any unread inbound messages'\n },\n is_archived: {\n type: 'boolean',\n description: 'Whether the thread has been archived'\n },\n last_message_at: {\n type: 'string',\n description: 'ISO 8601 timestamp of the most recent message in the thread'\n },\n message_count: {\n type: 'number',\n description: 'Total number of messages in the thread (both inbound and outbound)'\n },\n participant_emails: {\n type: 'array',\n description: 'Array of all unique email addresses that have participated in this thread',\n items: {\n type: 'string'\n }\n },\n participant_names: {\n type: 'array',\n description: 'Array of formatted participant names in the format \\'First Last \\' or just \\'email@domain.com\\' if no name is available',\n items: {\n type: 'string'\n }\n },\n root_message_id: {\n type: 'string',\n description: 'RFC 2822 Message-ID of the first message in the thread'\n },\n latest_message: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Unique identifier of the message'\n },\n from_text: {\n type: 'string',\n description: 'Formatted sender information (name and/or email)'\n },\n has_attachments: {\n type: 'boolean',\n description: 'Whether the message has any attachments'\n },\n is_read: {\n type: 'boolean',\n description: 'Whether the message has been read (always true for outbound)'\n },\n type: {\n type: 'string',\n description: 'Whether the message was received (inbound) or sent (outbound)',\n enum: [ 'inbound',\n 'outbound'\n ]\n },\n date: {\n type: 'string',\n description: 'ISO 8601 timestamp of when the message was sent/received'\n },\n subject: {\n type: 'string',\n description: 'Subject line of the message'\n },\n text_preview: {\n type: 'string',\n description: 'First 200 characters of the message body as a preview'\n }\n },\n required: [ 'id',\n 'from_text',\n 'has_attachments',\n 'is_read',\n 'type'\n ]\n },\n normalized_subject: {\n type: 'string',\n description: 'Normalized subject line (stripped of Re:, Fwd:, etc.) used for thread grouping'\n },\n unread_count: {\n type: 'number',\n description: 'Number of unread messages in the thread'\n }\n },\n required: [ 'id',\n 'created_at',\n 'has_unread',\n 'is_archived',\n 'last_message_at',\n 'message_count',\n 'participant_emails',\n 'participant_names',\n 'root_message_id'\n ]\n }\n }\n },\n required: [ 'filters',\n 'pagination',\n 'threads'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/packages/mcp-server/src/tools/mail/retrieve-mail.ts b/packages/mcp-server/src/tools/mail/retrieve-mail.ts index 0cdf7ef..af7d6be 100644 --- a/packages/mcp-server/src/tools/mail/retrieve-mail.ts +++ b/packages/mcp-server/src/tools/mail/retrieve-mail.ts @@ -18,7 +18,7 @@ export const metadata: Metadata = { export const tool: Tool = { name: 'retrieve_mail', description: - "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nRetrieve a complete email thread (conversation) with all messages.\n\n**What You Get:**\n- Thread metadata (subject, participants, timestamps)\n- All messages in the thread (both inbound and outbound)\n- Messages sorted chronologically by thread position\n\n**Message Types:**\n- `inbound` - Emails you received\n- `outbound` - Emails you sent (includes delivery status)\n\n**Message Content:**\nEach message includes:\n- Full body content (text and HTML)\n- Sender and recipient information\n- Attachments metadata\n- Read status and timestamps\n- Threading headers (In-Reply-To, References)\n\n**Typical Workflow:**\n1. List threads using `GET /mail/threads`\n2. User clicks a thread\n3. Fetch full thread using this endpoint\n4. Display conversation view with all messages\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/mail_retrieve_response',\n $defs: {\n mail_retrieve_response: {\n type: 'object',\n properties: {\n messages: {\n type: 'array',\n description: 'Array of all messages in the thread, sorted by thread position (chronological)',\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Unique identifier for the message'\n },\n attachments: {\n type: 'array',\n description: 'Array of attachment metadata',\n items: {\n type: 'object',\n properties: {\n content: {\n type: 'string',\n description: 'Base64-encoded content (if included)'\n },\n contentId: {\n type: 'string',\n description: 'Content-ID for inline attachments'\n },\n contentType: {\n type: 'string',\n description: 'MIME type of the attachment'\n },\n filename: {\n type: 'string',\n description: 'Original filename of the attachment'\n },\n size: {\n type: 'number',\n description: 'Size of the attachment in bytes'\n }\n }\n }\n },\n bcc: {\n type: 'array',\n description: 'Array of BCC recipient email addresses',\n items: {\n type: 'string'\n }\n },\n cc: {\n type: 'array',\n description: 'Array of CC recipient email addresses',\n items: {\n type: 'string'\n }\n },\n from: {\n type: 'string',\n description: 'Formatted sender (display name and email)'\n },\n has_attachments: {\n type: 'boolean',\n description: 'Whether the message has any attachments'\n },\n headers: {\n type: 'object',\n description: 'Raw email headers as key-value pairs',\n additionalProperties: true\n },\n is_read: {\n type: 'boolean',\n description: 'Whether the message has been read (always true for outbound)'\n },\n references: {\n type: 'array',\n description: 'Array of Message-IDs from the References header',\n items: {\n type: 'string'\n }\n },\n tags: {\n type: 'array',\n description: 'Array of tags attached to the message (outbound only)',\n items: {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n description: 'Tag name'\n },\n value: {\n type: 'string',\n description: 'Tag value'\n }\n },\n required: [ 'name',\n 'value'\n ]\n }\n },\n thread_position: {\n type: 'number',\n description: 'Position of the message in the thread (0 = first message)'\n },\n to: {\n type: 'array',\n description: 'Array of recipient email addresses',\n items: {\n type: 'string'\n }\n },\n type: {\n type: 'string',\n enum: [ 'inbound',\n 'outbound'\n ]\n },\n date: {\n type: 'string',\n description: 'ISO 8601 timestamp from the Date header'\n },\n failure_reason: {\n type: 'string',\n description: 'Error message if the outbound message failed to send'\n },\n from_address: {\n type: 'string',\n description: 'Sender email address'\n },\n from_name: {\n type: 'string',\n description: 'Sender display name if available'\n },\n html_body: {\n type: 'string',\n description: 'HTML body of the message'\n },\n in_reply_to: {\n type: 'string',\n description: 'RFC 2822 In-Reply-To header value'\n },\n message_id: {\n type: 'string',\n description: 'RFC 2822 Message-ID header value'\n },\n read_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the message was marked as read'\n },\n received_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the message was received (inbound only)'\n },\n sent_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the message was sent (outbound only)'\n },\n status: {\n type: 'string',\n description: 'Delivery status for outbound messages (pending, sent, failed, bounced)'\n },\n subject: {\n type: 'string',\n description: 'Subject line of the message'\n },\n text_body: {\n type: 'string',\n description: 'Plain text body of the message'\n }\n },\n required: [ 'id',\n 'attachments',\n 'bcc',\n 'cc',\n 'from',\n 'has_attachments',\n 'headers',\n 'is_read',\n 'references',\n 'tags',\n 'thread_position',\n 'to',\n 'type'\n ]\n }\n },\n thread: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Unique identifier for the thread'\n },\n created_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the thread was created'\n },\n last_message_at: {\n type: 'string',\n description: 'ISO 8601 timestamp of the most recent message'\n },\n message_count: {\n type: 'number',\n description: 'Total number of messages in the thread'\n },\n participant_emails: {\n type: 'array',\n description: 'Array of all unique email addresses that have participated in this thread',\n items: {\n type: 'string'\n }\n },\n participant_names: {\n type: 'array',\n description: 'Array of formatted participant names in the format \\'First Last \\' or just \\'email@domain.com\\' if no name is available',\n items: {\n type: 'string'\n }\n },\n root_message_id: {\n type: 'string',\n description: 'RFC 2822 Message-ID of the first message in the thread'\n },\n updated_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the thread was last updated'\n },\n normalized_subject: {\n type: 'string',\n description: 'Normalized subject line (stripped of Re:, Fwd:, etc.)'\n }\n },\n required: [ 'id',\n 'created_at',\n 'last_message_at',\n 'message_count',\n 'participant_emails',\n 'participant_names',\n 'root_message_id',\n 'updated_at'\n ]\n },\n total_count: {\n type: 'number',\n description: 'Total number of messages returned'\n }\n },\n required: [ 'messages',\n 'thread',\n 'total_count'\n ]\n }\n }\n}\n```", + "When using this tool, always use the `jq_filter` parameter to reduce the response size and improve performance.\n\nOnly omit if you're sure you don't need the data.\n\nRetrieve a complete email thread (conversation) with all messages.\n\n**What You Get:**\n- Thread metadata (subject, participants, timestamps)\n- All messages in the thread (both inbound and outbound)\n- Messages sorted chronologically by thread position\n\n**Message Types:**\n- `inbound` - Emails you received\n- `outbound` - Emails you sent (includes delivery status)\n\n\n# Response Schema\n```json\n{\n $ref: '#/$defs/mail_retrieve_response',\n $defs: {\n mail_retrieve_response: {\n type: 'object',\n properties: {\n messages: {\n type: 'array',\n description: 'Array of all messages in the thread, sorted by thread position (chronological)',\n items: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Unique identifier for the message'\n },\n attachments: {\n type: 'array',\n description: 'Array of attachment metadata',\n items: {\n type: 'object',\n properties: {\n content: {\n type: 'string',\n description: 'Base64-encoded content (if included)'\n },\n contentId: {\n type: 'string',\n description: 'Content-ID for inline attachments'\n },\n contentType: {\n type: 'string',\n description: 'MIME type of the attachment'\n },\n filename: {\n type: 'string',\n description: 'Original filename of the attachment'\n },\n size: {\n type: 'number',\n description: 'Size of the attachment in bytes'\n }\n }\n }\n },\n bcc: {\n type: 'array',\n description: 'Array of BCC recipient email addresses',\n items: {\n type: 'string'\n }\n },\n cc: {\n type: 'array',\n description: 'Array of CC recipient email addresses',\n items: {\n type: 'string'\n }\n },\n from: {\n type: 'string',\n description: 'Formatted sender (display name and email)'\n },\n has_attachments: {\n type: 'boolean',\n description: 'Whether the message has any attachments'\n },\n headers: {\n type: 'object',\n description: 'Raw email headers as key-value pairs',\n additionalProperties: true\n },\n is_read: {\n type: 'boolean',\n description: 'Whether the message has been read (always true for outbound)'\n },\n references: {\n type: 'array',\n description: 'Array of Message-IDs from the References header',\n items: {\n type: 'string'\n }\n },\n tags: {\n type: 'array',\n description: 'Array of tags attached to the message (outbound only)',\n items: {\n type: 'object',\n properties: {\n name: {\n type: 'string',\n description: 'Tag name'\n },\n value: {\n type: 'string',\n description: 'Tag value'\n }\n },\n required: [ 'name',\n 'value'\n ]\n }\n },\n thread_position: {\n type: 'number',\n description: 'Position of the message in the thread (0 = first message)'\n },\n to: {\n type: 'array',\n description: 'Array of recipient email addresses',\n items: {\n type: 'string'\n }\n },\n type: {\n type: 'string',\n enum: [ 'inbound',\n 'outbound'\n ]\n },\n date: {\n type: 'string',\n description: 'ISO 8601 timestamp from the Date header'\n },\n failure_reason: {\n type: 'string',\n description: 'Error message if the outbound message failed to send'\n },\n from_address: {\n type: 'string',\n description: 'Sender email address'\n },\n from_name: {\n type: 'string',\n description: 'Sender display name if available'\n },\n html_body: {\n type: 'string',\n description: 'HTML body of the message'\n },\n in_reply_to: {\n type: 'string',\n description: 'RFC 2822 In-Reply-To header value'\n },\n message_id: {\n type: 'string',\n description: 'RFC 2822 Message-ID header value'\n },\n read_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the message was marked as read'\n },\n received_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the message was received (inbound only)'\n },\n sent_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the message was sent (outbound only)'\n },\n status: {\n type: 'string',\n description: 'Delivery status for outbound messages (pending, sent, failed, bounced)'\n },\n subject: {\n type: 'string',\n description: 'Subject line of the message'\n },\n text_body: {\n type: 'string',\n description: 'Plain text body of the message'\n }\n },\n required: [ 'id',\n 'attachments',\n 'bcc',\n 'cc',\n 'from',\n 'has_attachments',\n 'headers',\n 'is_read',\n 'references',\n 'tags',\n 'thread_position',\n 'to',\n 'type'\n ]\n }\n },\n thread: {\n type: 'object',\n properties: {\n id: {\n type: 'string',\n description: 'Unique identifier for the thread'\n },\n created_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the thread was created'\n },\n last_message_at: {\n type: 'string',\n description: 'ISO 8601 timestamp of the most recent message'\n },\n message_count: {\n type: 'number',\n description: 'Total number of messages in the thread'\n },\n participant_emails: {\n type: 'array',\n description: 'Array of all unique email addresses that have participated in this thread',\n items: {\n type: 'string'\n }\n },\n participant_names: {\n type: 'array',\n description: 'Array of formatted participant names in the format \\'First Last \\' or just \\'email@domain.com\\' if no name is available',\n items: {\n type: 'string'\n }\n },\n root_message_id: {\n type: 'string',\n description: 'RFC 2822 Message-ID of the first message in the thread'\n },\n updated_at: {\n type: 'string',\n description: 'ISO 8601 timestamp when the thread was last updated'\n },\n normalized_subject: {\n type: 'string',\n description: 'Normalized subject line (stripped of Re:, Fwd:, etc.)'\n }\n },\n required: [ 'id',\n 'created_at',\n 'last_message_at',\n 'message_count',\n 'participant_emails',\n 'participant_names',\n 'root_message_id',\n 'updated_at'\n ]\n },\n total_count: {\n type: 'number',\n description: 'Total number of messages returned'\n }\n },\n required: [ 'messages',\n 'thread',\n 'total_count'\n ]\n }\n }\n}\n```", inputSchema: { type: 'object', properties: { diff --git a/src/client.ts b/src/client.ts index 9c7290c..e97b1ff 100644 --- a/src/client.ts +++ b/src/client.ts @@ -68,6 +68,7 @@ import { } from './resources/endpoints'; import { Mail, MailListParams, MailListResponse, MailRetrieveResponse } from './resources/mail'; import { type Fetch } from './internal/builtin-types'; +import { isRunningInBrowser } from './internal/detect-platform'; import { HeadersLike, NullableHeaders, buildHeaders } from './internal/headers'; import { FinalRequestOptions, RequestOptions } from './internal/request-options'; import { readEnv } from './internal/utils/env'; @@ -202,6 +203,12 @@ export class Inbound { baseURL: baseURL || `https://inbound.new`, }; + if (isRunningInBrowser()) { + throw new Errors.InboundError( + "It looks like you're running in a browser-like environment, which is disabled to protect your secret API credentials from attackers. If you have a strong business need for client-side use of this API, please open a GitHub issue with your use-case and security mitigations.", + ); + } + this.baseURL = options.baseURL!; this.timeout = options.timeout ?? Inbound.DEFAULT_TIMEOUT /* 1 minute */; this.logger = options.logger ?? console; @@ -631,7 +638,7 @@ export class Inbound { private calculateDefaultRetryTimeoutMillis(retriesRemaining: number, maxRetries: number): number { const initialRetryDelay = 0.5; - const maxRetryDelay = 8.0; + const maxRetryDelay = 5.0; const numRetries = maxRetries - retriesRemaining; diff --git a/src/resources/domains.ts b/src/resources/domains.ts index a588d76..30b6ab5 100644 --- a/src/resources/domains.ts +++ b/src/resources/domains.ts @@ -8,8 +8,8 @@ import { path } from '../internal/utils/path'; export class Domains extends APIResource { /** - * Add a new domain for email receiving. Automatically initiates SES verification - * and returns required DNS records. Subdomains inherit verification from their + * Add a new domain for email receiving. Automatically initiates verification and + * returns required DNS records. Subdomains inherit verification from their * verified parent domain. */ create(body: DomainCreateParams, options?: RequestOptions): APIPromise { @@ -21,7 +21,7 @@ export class Domains extends APIResource { /** * Get detailed information about a specific domain including DNS records. Use - * `?check=true` for live DNS and SES verification. + * `?check=true` for a live verification check. */ retrieve( id: string, diff --git a/src/resources/email-addresses.ts b/src/resources/email-addresses.ts index f8c025f..e902759 100644 --- a/src/resources/email-addresses.ts +++ b/src/resources/email-addresses.ts @@ -8,8 +8,8 @@ import { path } from '../internal/utils/path'; export class EmailAddresses extends APIResource { /** - * Create a new email address for an authenticated user's domain. Automatically - * configures AWS SES receipt rules. + * Create a new email address for an authenticated user's domain, optionally + * routing to a webhook or endpoint. */ create(body: EmailAddressCreateParams, options?: RequestOptions): APIPromise { return this._client.post( @@ -53,8 +53,7 @@ export class EmailAddresses extends APIResource { } /** - * Delete an email address and clean up associated SES receipt rules. Returns - * cleanup status. + * Delete an email address. Returns cleanup status. */ delete(id: string, options?: RequestOptions): APIPromise { return this._client.delete(path`/api/e2/email-addresses/${id}`, options); diff --git a/src/resources/emails.ts b/src/resources/emails.ts index f3f7adf..4fbebbc 100644 --- a/src/resources/emails.ts +++ b/src/resources/emails.ts @@ -29,37 +29,6 @@ export class Emails extends APIResource { /** * List all email activity (sent, received, and scheduled) with comprehensive * filtering options. - * - * **Type Filtering:** - * - * - `all` - Returns sent, received, and scheduled emails combined (default) - * - `sent` - Only outbound emails you've sent - * - `received` - Only inbound emails you've received - * - `scheduled` - Only emails scheduled for future delivery - * - * **Status Filtering:** - * - * - `delivered` - Successfully delivered emails - * - `pending` - Emails currently being processed - * - `failed` - Emails that failed to deliver - * - `bounced` - Emails that bounced (sent only) - * - `scheduled` - Emails scheduled for future delivery - * - `cancelled` - Cancelled scheduled emails - * - `unread` - Unread received emails - * - `read` - Read received emails - * - `archived` - Archived received emails - * - * **Time Range Filtering:** - * - * - `1h` - Last hour - * - `24h` - Last 24 hours - * - `7d` - Last 7 days - * - `30d` - Last 30 days (default) - * - `90d` - Last 90 days - * - `all` - All time - * - * **Address Filtering:** Supports filtering by domain ID, domain name, address ID, - * or raw email address (e.g., 'user@example.com'). */ list( query: EmailListParams | null | undefined = {}, @@ -391,6 +360,12 @@ export interface EmailSendResponse { id: string; message_id?: string; + + scheduled_at?: string; + + status?: 'sent' | 'scheduled'; + + timezone?: string; } export interface EmailListParams { diff --git a/src/resources/endpoints.ts b/src/resources/endpoints.ts index ada6af3..3a3d9ff 100644 --- a/src/resources/endpoints.ts +++ b/src/resources/endpoints.ts @@ -308,9 +308,9 @@ export interface EndpointTestResponse { export interface EndpointCreateParams { config: - | EndpointCreateParams.UnionMember0 - | EndpointCreateParams.UnionMember1 - | EndpointCreateParams.UnionMember2; + | EndpointCreateParams.WebhookConfig + | EndpointCreateParams.EmailConfig + | EndpointCreateParams.EmailGroupConfig; name: string; @@ -320,7 +320,7 @@ export interface EndpointCreateParams { } export namespace EndpointCreateParams { - export interface UnionMember0 { + export interface WebhookConfig { url: string; /** @@ -333,13 +333,13 @@ export namespace EndpointCreateParams { timeout?: number; } - export interface UnionMember1 { + export interface EmailConfig { forwardTo: string; preserveHeaders?: boolean; } - export interface UnionMember2 { + export interface EmailGroupConfig { emails: Array; preserveHeaders?: boolean; @@ -348,9 +348,9 @@ export namespace EndpointCreateParams { export interface EndpointUpdateParams { config?: - | EndpointUpdateParams.UnionMember0 - | EndpointUpdateParams.UnionMember1 - | EndpointUpdateParams.UnionMember2; + | EndpointUpdateParams.WebhookConfig + | EndpointUpdateParams.EmailConfig + | EndpointUpdateParams.EmailGroupConfig; description?: string; @@ -362,7 +362,7 @@ export interface EndpointUpdateParams { } export namespace EndpointUpdateParams { - export interface UnionMember0 { + export interface WebhookConfig { url: string; /** @@ -375,13 +375,13 @@ export namespace EndpointUpdateParams { timeout?: number; } - export interface UnionMember1 { + export interface EmailConfig { forwardTo: string; preserveHeaders?: boolean; } - export interface UnionMember2 { + export interface EmailGroupConfig { emails: Array; preserveHeaders?: boolean; diff --git a/src/resources/mail.ts b/src/resources/mail.ts index cdd37cb..7887d91 100644 --- a/src/resources/mail.ts +++ b/src/resources/mail.ts @@ -19,21 +19,6 @@ export class Mail extends APIResource { * * - `inbound` - Emails you received * - `outbound` - Emails you sent (includes delivery status) - * - * **Message Content:** Each message includes: - * - * - Full body content (text and HTML) - * - Sender and recipient information - * - Attachments metadata - * - Read status and timestamps - * - Threading headers (In-Reply-To, References) - * - * **Typical Workflow:** - * - * 1. List threads using `GET /mail/threads` - * 2. User clicks a thread - * 3. Fetch full thread using this endpoint - * 4. Display conversation view with all messages */ retrieve(id: string, options?: RequestOptions): APIPromise { return this._client.get(path`/api/e2/mail/threads/${id}`, options); @@ -47,26 +32,6 @@ export class Mail extends APIResource { * In-Reply-To and References headers, similar to how Gmail groups conversations. * Each thread contains both inbound (received) and outbound (sent) messages. * - * **Filtering:** - * - * - `domain` - Filter by domain ID or name (e.g., 'example.com'). Returns threads - * where any participant matches the domain. - * - `address` - Filter by email address (e.g., 'user@example.com'). Returns - * threads where the address is a participant. - * - `search` - Search in subject lines and participant emails. - * - `unread` - Set to 'true' to only return threads with unread messages. - * - * **Pagination:** Uses cursor-based pagination for efficient infinite scroll. Pass - * `pagination.next_cursor` from the response as the `cursor` parameter to get the - * next page. - * - * **Response:** Each thread includes: - * - * - Thread metadata (subject, participants, message count) - * - `latest_message` - Preview of the most recent message (inbound or outbound) - * - `has_unread` - Whether there are unread inbound messages - * - `unread_count` - Number of unread messages - * * **Use with /mail/threads/:id:** Use this endpoint to list threads, then use * `GET /mail/threads/:id` to fetch all messages in a specific thread. */ diff --git a/src/version.ts b/src/version.ts index 02c8084..b4e51da 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.19.0'; // x-release-please-version +export const VERSION = '0.20.0'; // x-release-please-version