Docs

MCP Setup Guide

Configure TextForge as an MCP (Model Context Protocol) server for your AI tools. This enables your AI agents to draft and manage emails through TextForge.

Want the config generated automatically? Use the MCP Setup Generator to get a copy-paste config for your specific tool and auth method.

Authentication

TextForge supports two ways to authenticate MCP connections: OAuth 2.0 and API keys. Which one you use depends on your tool.

Connect with OAuth (Recommended)

Tools that support MCP OAuth handle the entire auth flow for you — no tokens to copy, no environment variables to set. Run a single command or click a button, approve access in your browser, and you’re connected. If you don’t have a TextForge account yet, the OAuth flow walks you through signup automatically.

OAuth grants both mcp:drafts and mcp:threads scopes by default, which covers all 23 MCP tools.

Connect with an API Key

For tools that don’t support OAuth yet, or when you need fine-grained control over which permissions a connection has, create an API token in Settings → API Tokens and pass it as a Bearer token. See the Tokens Guide for details on creating and managing tokens.

When to use which: OAuth grants mcp:drafts and mcp:threads by default — that covers everything most people need. Use an API key if you want to limit a connection to specific permissions (e.g., read-only access) or if your tool doesn’t support OAuth.
Keep your API tokens secure. Never commit tokens to version control or share them publicly. Treat your token like a password.

Tool Compatibility

Tool OAuth API Key
Claude Code CLIYesYes
Claude DesktopYesYes
VS CodeNoYes
CursorYesYes
WindsurfYesYes
ClineNoYes
ZedNoYes
GitHub Copilot CLINoYes
OpenCodeYesYes
AmpYesYes
OpenClawNoYes (via MCPorter)

OpenClaw

OpenClaw connects to MCP servers through MCPorter. Install MCPorter and add the TextForge server:

OpenClaw does not natively support MCP — it uses MCPorter as a bridge. See the textforge-app/openclaw-textforge skill for a complete setup with email writing best practices.
npm install -g mcporter mcporter config add textforge https://textforge.net/mcp \ --header "Authorization: Bearer $TEXTFORGE_TOKEN"

Set your token as an environment variable: export TEXTFORGE_TOKEN="your_api_token"

Test the connection: mcporter call textforge.list_threads limit:5

Once configured, your OpenClaw agent can use TextForge tools to draft emails, read threads, and manage conversations — all with human approval before anything sends. See OpenClaw Email Safety for why this matters.

Claude Code CLI

Claude Code supports both OAuth and API key authentication. Official documentation.

Connect with OAuth (Recommended)

One command, no tokens to manage. Claude Code handles the OAuth flow automatically — it opens your browser, you approve access, and you’re connected. If you don’t have a TextForge account yet, the flow walks you through signup too.

claude mcp add textforge --transport http https://textforge.net/mcp

That’s it. No --header flag, no environment variables, no config files to edit.

Connect with an API Key

If you need custom permissions or prefer manual token management, you can connect with an API key instead.

Install via Plugin

The official plugin bundles MCP configuration, skills, and prompt templates: textforge-app/textforge-claude-plugin.

/plugin marketplace add textforge-app/textforge-claude-plugin /plugin install textforge@textforge

Add via CLI

claude mcp add textforge \ --transport http \ https://textforge.net/mcp \ --header "Authorization: Bearer YOUR_API_TOKEN"
Known issue: The --header flag may have bugs in some versions. If the CLI approach fails, edit the config file directly (see below).

Manual Configuration

Edit ~/.claude.json (user-level) or .mcp.json (project-level):

~/.claude.json
{ "mcpServers": { "textforge": { "type": "http", "url": "https://textforge.net/mcp", "headers": { "Authorization": "Bearer ${TEXTFORGE_TOKEN}" } } } }

Set your token as an environment variable: export TEXTFORGE_TOKEN="your_api_token"

Useful commands for managing MCP servers:

Claude Desktop

Claude Desktop supports both OAuth (via the Settings UI) and API keys (via mcp-remote). Official documentation.

Option 1: Settings → Connectors (Recommended)

Go to Settings → Connectors in Claude Desktop and add TextForge as a remote server using the URL https://textforge.net/mcp. Claude Desktop handles the OAuth flow automatically — no token needed.

Option 2: API Key with mcp-remote

If you need custom permissions, use the mcp-remote npm package to bridge remote servers. This runs a local process that proxies requests to TextForge.

Config file locations:

claude_desktop_config.json
{ "mcpServers": { "textforge": { "command": "npx", "args": [ "mcp-remote", "https://textforge.net/mcp", "--header", "Authorization:${AUTH_TOKEN}" ], "env": { "AUTH_TOKEN": "Bearer YOUR_API_TOKEN" } } } }

Restart Claude Desktop after making changes.

VS Code (Native MCP)

VS Code has native MCP support since version 1.102. This works with GitHub Copilot and other VS Code AI features. Official documentation.

VS Code does not yet support OAuth for MCP servers. Use an API key to connect.

Configuration

Create or edit mcp.json in your VS Code user settings directory, or use .vscode/mcp.json for project-level configuration.

mcp.json
{ "inputs": [ { "type": "promptString", "id": "textforge-token", "description": "TextForge API Token", "password": true } ], "servers": { "textforge": { "type": "http", "url": "https://textforge.net/mcp", "headers": { "Authorization": "Bearer ${input:textforge-token}" } } } }

VS Code will securely prompt for your API token when the server is first used. Reload the window after adding the configuration.

GitHub Copilot CLI

Configure TextForge in your Copilot CLI MCP settings file at ~/.copilot/mcp-config.json. Official documentation.

GitHub Copilot CLI does not yet support OAuth for MCP servers. Use an API key to connect.

Configuration

~/.copilot/mcp-config.json
{ "mcpServers": { "textforge": { "type": "http", "url": "https://textforge.net/mcp", "tools": ["*"], "headers": { "Authorization": "Bearer $COPILOT_MCP_TEXTFORGE_TOKEN" } } } }

Set the environment variable: export COPILOT_MCP_TEXTFORGE_TOKEN="your_api_token"

You can also use project-level configuration by placing the file at .copilot/mcp-config.json in your project root.

Useful CLI commands:

OpenCode

OpenCode supports both OAuth and API key authentication. Official documentation.

Connect with OAuth (Recommended)

opencode mcp add

Select Remote when prompted and enter the URL https://textforge.net/mcp. OpenCode handles the OAuth flow automatically — no token needed.

Connect with an API Key

Add to ~/.config/opencode/opencode.json (global) or opencode.json in your project root:

opencode.json
{ "mcp": { "textforge": { "type": "remote", "url": "https://textforge.net/mcp", "headers": { "Authorization": "Bearer {env:TEXTFORGE_TOKEN}" }, "enabled": true } } }

Note: OpenCode uses {env:VAR} syntax (without the $ prefix) for environment variables.

Cursor

Cursor supports both OAuth and API key authentication. Edit the MCP settings file at ~/.cursor/mcp.json (global) or .cursor/mcp.json (project-level). Official documentation.

Configuration

~/.cursor/mcp.json
{ "mcpServers": { "textforge": { "type": "streamableHttp", "url": "https://textforge.net/mcp", "headers": { "Authorization": "Bearer ${env:TEXTFORGE_TOKEN}" } } } }

Set your token as an environment variable: export TEXTFORGE_TOKEN="your_api_token"

Windsurf

Windsurf supports both OAuth and API key authentication. Add TextForge to your Windsurf MCP configuration at ~/.codeium/windsurf/mcp_config.json. Official documentation.

Configuration

~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "textforge": { "serverUrl": "https://textforge.net/mcp", "headers": { "Authorization": "Bearer ${env:TEXTFORGE_TOKEN}" } } } }

Note: Windsurf uses serverUrl instead of url. Set your token as an environment variable: export TEXTFORGE_TOKEN="your_api_token"

Cline (VS Code)

Cline stores MCP configuration in VS Code's globalStorage directory. Click the MCP Servers icon in Cline and select "Configure MCP Servers" to open the file. Official documentation.

Cline does not yet support OAuth for MCP servers. Use an API key to connect.
Known issues: Cline may have bugs with Bearer token forwarding for HTTP servers. If you experience authentication issues, try regenerating your API token or check the Cline output panel for errors.

Configuration

The config file is located at: ~/.vscode/extensions/saoudrizwan.claude-dev-*/settings/cline_mcp_settings.json (the exact path varies by extension version).

cline_mcp_settings.json
{ "mcpServers": { "textforge": { "type": "streamableHttp", "url": "https://textforge.net/mcp", "headers": { "Authorization": "Bearer YOUR_API_TOKEN" }, "disabled": false } } }

Restart VS Code after saving changes. A green indicator shows successful connection.

Zed

Add TextForge to your Zed settings under context_servers. Open Settings (Cmd/Ctrl + ,) and add the configuration. Official documentation.

Zed does not yet support OAuth for MCP servers. Use an API key to connect.

Configuration

Add the following to your Zed settings file. Note that context_servers is a top-level key in the settings:

Zed Settings
{ "context_servers": { "textforge": { "url": "https://textforge.net/mcp", "headers": { "Authorization": "Bearer YOUR_API_TOKEN" } } } }

Check the Agent Panel settings – a green indicator next to the server name means it's connected successfully.

Amp

Amp supports both OAuth and API key authentication. Official documentation.

Connect with OAuth (Recommended)

amp mcp add textforge https://textforge.net/mcp

Amp handles the OAuth flow automatically — it opens your browser on startup to complete authentication.

Connect with an API Key

Add to ~/.config/amp/settings.json under the amp.mcpServers key:

~/.config/amp/settings.json
{ "amp.mcpServers": { "textforge": { "url": "https://textforge.net/mcp", "headers": { "Authorization": "Bearer ${TEXTFORGE_TOKEN}" } } } }

Set your token as an environment variable: export TEXTFORGE_TOKEN="your_api_token"

Or add via CLI: amp mcp add textforge --header "Authorization=Bearer YOUR_API_TOKEN" https://textforge.net/mcp

Other MCP-Compatible Tools

TextForge works with any MCP-compatible tool. The general configuration pattern is:

TextForge uses stateless MCP mode for better reliability with long-running sessions. Each request is authenticated independently.

Use the MCP Setup Generator to create a client-specific configuration for any tool listed above.

Available MCP Tools

TextForge exposes 23 MCP tools across 3 categories. MCP-compatible AI tools discover these tools and their parameters automatically when they connect. The descriptions below are generated from the same [Description] attributes that MCP clients see, so they always match what your agent receives.

Draft Management (8 tools)

create_draft

Create a new email draft and submit it for human approval. This is the primary way for LLM agents to initiate the email sending workflow. The draft will be created and automatically submitted for approval. To create a reply to an existing thread, provide either threadId or externalThreadId.

Parameter Type Required Description
subject string No Email subject line
body string No Email body content
toRecipients string No To recipients (comma-separated email addresses)
bodyFormat string No Body format: Html (default) or Markdown. Markdown will be converted to HTML.
ccRecipients string No CC recipients (comma-separated email addresses)
bccRecipients string No BCC recipients (comma-separated email addresses)
scheduledFor string No Scheduled send time in ISO 8601 format (e.g., 2024-12-25T10:00:00Z). If not provided, email will be sent immediately upon approval.
threadId string No Thread ID (GUID) to reply to. Creates a reply draft linked to this thread with proper email threading headers.
externalThreadId string No External thread ID to reply to (alternative to threadId). Looks up the thread by provider thread identifier.

delete_draft

Permanently delete a draft. Only drafts that will not be sent can be deleted: Draft (not yet submitted), Rejected, Expired, or SendFailed status. Cannot delete drafts that are PendingApproval, Approved, or Sent.

Parameter Type Required Description
draftId string No Draft ID to delete (GUID format)

get_draft

Get detailed information about a specific draft including subject, body, recipients, status, and approval history.

Parameter Type Required Description
draftId string No Draft ID (GUID format)

get_draft_activity

Get the complete activity history for a draft, including creation, updates, approval/rejection, and sending events.

Parameter Type Required Description
draftId string No Draft ID (GUID format)

list_drafts

List email drafts with optional filtering by status or recipient email. Returns paginated results with draft metadata including subject, status, recipients, and creation info.

Parameter Type Required Description
status string No Filter by draft status: Draft, PendingApproval, Approved, Rejected, Sent, or SendFailed
recipientEmail string No Filter by recipient email address (searches To, CC, and BCC fields)
page integer No Page number (1-based, default: 1)
pageSize integer No Number of items per page (default: 25, max: 100)

reject_draft

Reject a draft that is pending approval. Only drafts in 'PendingApproval' status can be rejected. Use this to withdraw a draft that should not be sent.

Parameter Type Required Description
draftId string No Draft ID to reject (GUID format)
rejectionReason string No Optional reason for rejection

submit_draft

Submit a draft for human approval. Note: create_draft automatically submits, so this is only needed for drafts that were not auto-submitted.

Parameter Type Required Description
draftId string No Draft ID to submit (GUID format)

update_draft

Update an existing draft's content. Only drafts in 'Draft' or 'PendingApproval' status can be updated.

Parameter Type Required Description
draftId string Yes Draft ID to update (GUID format)
subject string No New email subject line
body string No New email body content
toRecipients string No New To recipients (comma-separated email addresses)
bodyFormat string No Body format: Html (default) or Markdown. Markdown will be converted to HTML.
ccRecipients string No New CC recipients (comma-separated email addresses). Set to empty string to clear.
bccRecipients string No New BCC recipients (comma-separated email addresses). Set to empty string to clear.
scheduledFor string No New scheduled send time in ISO 8601 format. Set to empty string to clear and send immediately upon approval.

Thread Management (10 tools)

get_thread

Get full details of a specific email thread including messages. Requires an internal TextForge thread ID (GUID format) — use the 'id' field from list_threads, list_engaged_threads, search_threads_by_contact, or matched search_messages results. Do NOT pass provider/Gmail thread IDs here; use get_thread_by_external_id for those. By default returns the latest 5 messages with quoted reply content stripped. Set maxMessages=0 for all messages.

Parameter Type Required Description
threadId string No Internal TextForge thread ID (GUID format, e.g., '3fa85f64-5717-4562-b3fc-2c963f66afa6'). Use the 'id' field from thread listing or search results.
maxMessages integer No Max messages to return (latest N). Default: 5. Set to 0 for all.
stripQuotedReplies boolean No Strip quoted reply content from bodyText. Default: true.

get_thread_by_external_id

Look up a thread by the email provider's thread ID (e.g., Gmail thread ID from search_messages results or email headers). Use this when you have a provider thread ID instead of an internal TextForge GUID. If not found, use import_thread to import it first. By default returns the latest 5 messages with quoted reply content stripped.

Parameter Type Required Description
externalThreadId string No Provider thread ID (e.g., Gmail thread ID like '19d2243fcda1917c' from search_messages results)
maxMessages integer No Max messages to return (latest N). Default: 5. Set to 0 for all.
stripQuotedReplies boolean No Strip quoted reply content from bodyText. Default: true.

import_thread

Import a thread from the email provider by its external thread ID (e.g., from the 'unmatchedProviderThreads' array in search_messages results). Returns the thread with its internal 'id' (GUID) for use with get_thread, create_draft, etc. Idempotent: if already imported, syncs instead. Requires 'threads:sync' permission.

Parameter Type Required Description
externalThreadId string No Provider thread ID (e.g., Gmail thread ID from search_messages results)

list_engaged_threads

List threads where you have previously sent at least one message, ordered by most recent activity. Includes 'hasUnreadReply' (true when the latest message is inbound — the ball is in your court) plus 'lastInboundAt' and 'lastOutboundAt' timestamps. Use this to find conversations that need a response.

Parameter Type Required Description
page integer No Page number (1-based, default: 1)
pageSize integer No Number of items per page (default: 25, max: 100)

list_recent_messages

List recent email messages across all threads, filtered by date and optionally by direction. Returns individual messages (not threads) with thread context (threadId, threadSubject) so you can navigate to the full thread via get_thread. Use this to quickly find recent inbound emails without paging through threads. Requires 'threads:read' permission.

Parameter Type Required Description
since string No Return messages after this date/time (ISO 8601, e.g., '2026-03-25T00:00:00Z'). Required.
direction string No Filter by direction: 'inbound', 'outbound', or omit for all messages
limit integer No Max results to return (default: 50, max: 100)
newestFirst boolean No Sort order: true for newest first (default), false for oldest first

list_threads

List email threads (conversations) for the authenticated user's organization. Threads are created when emails are sent and track both outbound and inbound messages. Use this to find threads for context when composing replies.

Parameter Type Required Description
participantEmail string No Filter by participant email address. Returns threads where this email appears in From, To, or CC.
page integer No Page number (1-based, default: 1)
pageSize integer No Number of items per page (default: 25, max: 100)

search_messages

Search emails using Gmail-style query syntax (e.g., from:, subject:, has:attachment). Returns two result groups: 'threads' contains matches already in TextForge with full metadata and an internal 'id' (GUID) for use with get_thread; 'unmatchedProviderThreads' contains provider-only results not yet imported — use import_thread with their 'externalThreadId' first, then get_thread with the returned id. Requires 'threads:read' permission.

Parameter Type Required Description
query string No Search query using Gmail syntax (e.g., from:[email protected], subject:"invoice", has:attachment, after:2026/01/01)
maxResults integer No Maximum number of results (default: 100, max: 500)
pageToken string No Page token for pagination (from previous response)

search_threads_by_contact

Search for email threads involving a specific contact (email address). Searches across From, To, and CC fields of all messages in threads. Useful for finding all email history with a particular person or company.

Parameter Type Required Description
email string No Email address to search for (e.g., '[email protected]' or '@example.com' for domain)
page integer No Page number (1-based, default: 1)
pageSize integer No Number of items per page (default: 25, max: 100)

sync_inbox

Trigger a full inbox sync to discover new threads and update existing ones from the email provider. Like hitting refresh in an email client. Use this when you need to find recently arrived emails that aren't yet in TextForge. Requires 'threads:sync' permission.

sync_thread

Sync a thread from the email provider to fetch any new messages. Use this before composing a reply to ensure you have the latest conversation context. Requires an internal TextForge thread ID (GUID). Requires 'threads:sync' permission.

Parameter Type Required Description
threadId string No Internal TextForge thread ID (GUID format). Use the 'id' field from thread listing or search results.

Attachment Management (5 tools)

get_attachment_download_url

Get a presigned URL to download an attachment. The URL expires in 10 minutes. Works for both message attachments and draft attachments.

Parameter Type Required Description
parentId string No The message ID (for message attachments) or draft ID (for draft attachments)
attachmentId string No The attachment ID to download
sourceType string No Source type: 'message' for received emails or 'draft' for draft attachments

get_draft_attachment_upload_url

Get a presigned URL to upload an attachment to a draft. The URL is single-use and expires in 10 minutes. Use HTTP PUT to upload raw file bytes to the returned URL.

Parameter Type Required Description
draftId string No The draft ID to attach the file to (GUID format)
filename string No The filename for the attachment
contentType string No The MIME type of the file (e.g., 'application/pdf', 'image/png')
sizeBytes integer No The expected file size in bytes

list_draft_attachments

List attachments currently attached to a draft email. Returns attachment metadata including filename, MIME type, size, and upload time.

Parameter Type Required Description
draftId string No The draft ID to list attachments for (GUID format)

list_message_attachments

List attachments for a received email message. Returns attachment metadata including filename, MIME type, and size. Use get_attachment_download_url to download content.

Parameter Type Required Description
messageId string No The message ID (GUID format)

remove_draft_attachment

Remove an attachment from a draft email. The attachment will be permanently deleted.

Parameter Type Required Description
draftId string No The draft ID containing the attachment (GUID format)
attachmentId string No The attachment ID to remove (GUID format)

Quick start workflow

Here is a typical agent flow using TextForge MCP tools:

  1. search_threads_by_contact("[email protected]") — find existing conversation history
  2. get_thread(threadId) — read the full thread for context
  3. create_draft(subject, body, toRecipients, threadId) — draft a reply
  4. Human reviews and approves in the TextForge UI or via Slack notification
  5. list_drafts(status: "Sent") — confirm delivery

For the REST API equivalent, see the API Reference or the Interactive API Reference.

Agent Skills & Plugins

Pre-built skills give your AI tool the full TextForge workflow out of the box — not just MCP tool access, but email writing best practices, draft lifecycle patterns, and a built-in audit for common AI writing tells. Both packs include the same two skills. See the AI Email Writing Skill page for the full breakdown.

OpenClaw

textforge-app/openclaw-textforge — Install via mcporter. Includes the TextForge skill and the email writing skill. See the OpenClaw setup section above for installation commands.

Claude Code

textforge-app/textforge-claude-plugin — Install via the Claude Code plugin marketplace. Includes the TextForge skill and the email writing skill.

/plugin marketplace add textforge-app/textforge-claude-plugin /plugin install textforge@textforge
The .mcp.json inside these plugins uses the same format as VS Code, Copilot, and other MCP-compatible tools. The connection config is portable across clients — only the skill files are tool-specific.