SKILL.md
TextForge Email Skill
Use this skill when the user wants to draft emails, read inbox threads, search email, or manage email follow-ups via TextForge. Every email draft requires human approval before it sends.
For email composition best practices, see the email-writing skill.
ID Types
TextForge uses two types of thread identifiers:
| ID Type | Format | Example | Where It Appears |
|---|---|---|---|
Internal ID (id) |
GUID | 3fa85f64-5717-4562-b3fc-2c963f66afa6 |
listthreads, listengagedthreads, searchthreadsbycontact, matched results in search_messages |
Provider ID (externalThreadId) |
Hex string | 19d2243fcda1917c |
search_messages (unmatched results), email headers |
- Use internal IDs with:
getthread,syncthread,create_draft(threadId param) - Use provider IDs with:
getthreadbyexternalid,import_thread - Never pass a provider ID to
get_thread— it requires GUID format and will error
Workflow
- Find context —
searchmessages,searchthreadsbycontact,listthreads, orlistrecent_messages
- searchmessages returns two groups: matched threads (already in TextForge, have an id GUID) and unmatched provider threads (only have externalThreadId) - listrecent_messages returns individual messages filtered by date — useful for "what came in recently?"
- Import if needed — For unmatched results from
searchmessages, useimportthreadwith theexternalThreadIdto pull the thread into TextForge. This returns the internalid. - Read thread —
getthreadwith the internalid(GUID format). Do NOT pass provider thread IDs to this tool — usegetthreadbyexternal_idfor those. - Draft email —
create_draftwithbodyFormat: "Html"(seeemail-writingskill for composition guidelines) - Attach files —
getdraftattachmentuploadurlthen upload via presigned URL - User gets notified — Slack, Discord, or webhook with draft preview
- User reviews/approves — edit in TextForge UI, then send
- If edits needed — use
update_draft, never delete/recreate - Check activity —
getdraftactivityto see full draft history
Never tell the user an email was "sent" — it was drafted and queued for their approval.
Quick Formatting Reference
- Use
<br>for line breaks, not<p>tags - Use
<br><br>between paragraphs - Set
bodyFormat: "Html"unless the user explicitly wants Markdown - No em dashes — they're an immediate LLM tell
- No email signatures — TextForge appends the user's configured signature
For the full writing guide, anti-pattern reference, and AI pattern audit, see the email-writing skill.
Available Tools
Draft Management (8 tools)
mcptextforgecreate_draft
Create an email draft for human approval.
subject(string, required): Email subject linebody(string, required): Email bodybodyFormat(string):"Html"or"Markdown"(default:"Html")toRecipients(string, required): Comma-separated recipient emailsccRecipients(string, optional): Comma-separated CC emailsbccRecipients(string, optional): Comma-separated BCC emailsthreadId(string, optional): Internal TextForge thread ID (GUID) to reply to an existing threadscheduledFor(string, optional): ISO 8601 datetime for scheduled send
Drafts are automatically submitted for approval upon creation.
mcptextforgelist_drafts
List email drafts with optional filtering by status or recipient.
status(string, optional): Filter by status (e.g.,"PendingApproval","Approved","Sent")recipient(string, optional): Filter by recipient emaillimit(number, optional): Max results (default: 20)
mcptextforgeget_draft
Get detailed information about a specific draft including body, recipients, and status.
draftId(string, required): The draft ID
mcptextforgeupdate_draft
Update an existing draft's content. Only works on editable drafts. Always use this instead of deleting/recreating — drafts in PendingApproval status cannot be deleted.
draftId(string, required): The draft ID to updatesubject(string, optional): Updated subjectbody(string, optional): Updated bodybodyFormat(string, optional):"Html"or"Markdown"toRecipients(string, optional): Updated recipientsccRecipients(string, optional): Updated CCbccRecipients(string, optional): Updated BCC
mcptextforgesubmit_draft
Submit a draft for human approval. Rarely needed since create_draft auto-submits.
draftId(string, required): The draft ID
mcptextforgegetdraftactivity
Get the complete activity history for a draft (created, edited, submitted, approved, rejected, sent).
draftId(string, required): The draft ID
mcptextforgereject_draft
Reject a draft that is pending approval.
draftId(string, required): The draft IDreason(string, optional): Rejection reason
mcptextforgedelete_draft
Permanently delete a draft. Only works on non-sendable statuses.
draftId(string, required): The draft ID
Thread Management (10 tools)
mcptextforgelist_threads
List email threads with optional filtering. Returns threads with hasUnreadReply, lastInboundAt, and lastOutboundAt fields.
participantEmail(string, optional): Filter by participant email addresspage(number, optional): Page number, 1-based (default: 1)pageSize(number, optional): Items per page (default: 25, max: 100)
mcptextforgelistengagedthreads
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.
page(number, optional): Page number, 1-based (default: 1)pageSize(number, optional): Items per page (default: 25, max: 100)
mcptextforgeget_thread
Get full thread details including messages and threading headers for replies. Requires an internal TextForge thread ID (GUID format).
threadId(string, required): Internal TextForge thread ID (GUID format, e.g.,"3fa85f64-5717-4562-b3fc-2c963f66afa6"). Use theidfield fromlistthreads,searchthreadsbycontact, or matchedsearchmessagesresults. Do NOT pass provider/Gmail thread IDs here — usegetthreadbyexternal_idfor those.maxMessages(number, optional): Max messages to return (default: 5, set to 0 for all)stripQuotedReplies(boolean, optional): Strip quoted reply content (default: true)
mcptextforgegetthreadbyexternalid
Look up a thread by the email provider's thread ID. Use this with provider thread IDs from searchmessages results or email headers. If not found, use importthread to import it first.
externalThreadId(string, required): Provider thread ID (e.g., Gmail thread ID like"19d2243fcda1917c")maxMessages(number, optional): Max messages to return (default: 5, set to 0 for all)stripQuotedReplies(boolean, optional): Strip quoted reply content (default: true)
mcptextforgesearch_messages
Search emails using Gmail-style query syntax. Returns two result groups:
threads— already in TextForge, haveid(GUID) and full metadata (subject, participants, timestamps) for use withget_threadunmatchedProviderThreads— not yet imported, haveexternalThreadIdonly — useimport_threadfirst
query(string, required): Search query (e.g.,"from:[email protected] after:2026-01-01","subject:invoice","has:attachment")maxResults(number, optional): Max results (default: 100, max: 500)pageToken(string, optional): Page token for pagination (from previous response)
mcptextforgesearchthreadsby_contact
Find all threads involving a specific email address or domain. Returns threads with full metadata including hasUnreadReply.
email(string, required): Contact email to search for (e.g.,"[email protected]"or"@example.com"for domain)
mcptextforgesync_thread
Sync a specific thread from the email provider to fetch new messages. Requires an internal TextForge thread ID (GUID).
threadId(string, required): Internal TextForge thread ID (GUID format)
mcptextforgesync_inbox
Trigger a full inbox sync to discover new threads and messages.
mcptextforgeimport_thread
Import a thread from the email provider by its external thread ID (e.g., from the unmatchedProviderThreads array in searchmessages results). Returns the thread with its internal id (GUID) for use with getthread, create_draft, etc. Idempotent: if already imported, syncs instead.
externalThreadId(string, required): Provider thread ID to import
mcptextforgelistrecentmessages
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.
since(string, required): Return messages after this date/time (ISO 8601, e.g.,"2026-03-25T00:00:00Z")direction(string, optional): Filter by direction:"inbound","outbound", or omit for alllimit(number, optional): Max results (default: 50, max: 100)newestFirst(boolean, optional): Sort order (default: true)
Attachment Management (5 tools)
mcptextforgelistmessageattachments
List attachments for a received email message.
messageId(string, required): The message ID
mcptextforgelistdraftattachments
List attachments currently attached to a draft.
draftId(string, required): The draft ID
mcptextforgegetattachmentdownload_url
Get a presigned URL to download an attachment. URL expires in 10 minutes.
attachmentId(string, required): The attachment ID
mcptextforgegetdraftattachmentuploadurl
Get a presigned URL to upload an attachment to a draft.
draftId(string, required): The draft IDfileName(string, required): Name of the file to uploadcontentType(string, required): MIME type (e.g.,"application/pdf")
mcptextforgeremovedraftattachment
Remove an attachment from a draft email.
draftId(string, required): The draft IDattachmentId(string, required): The attachment ID
Attachment Workflow
To attach a file to a draft:
- Create the draft via
create_draft - Get an upload URL via
getdraftattachmentuploadurlwith the draft ID, filename, and content type - Upload the file via HTTP PUT to the returned
uploadUrl:
``bash curl -X PUT "<uploadUrl>" \ -H "Content-Type: application/pdf" \ --data-binary "@/path/to/file.pdf" ``
- The upload URL is single-use and expires in 10 minutes
To access received attachments:
- Use
listmessageattachmentson a message ID - Use
getattachmentdownload_urlto get a presigned download URL
Common attachment types: PDF, images (PNG/JPG), documents (DOCX), spreadsheets (XLSX).
What to Tell the User
After creating a draft:
"I've queued a draft in TextForge for your review. You'll be notified via your configured channel — approve or edit it there before it sends."
Never say "I sent an email" or "the email was sent."
Pricing
Both plans include a 7-day free trial. No credit card required to start.
| Plan | Price | Includes |
|---|---|---|
| Solo | $9.99/month | 20 drafts/day, 2 webhooks, 30-day inbox sync |
| Pro | $19.99/month | Unlimited drafts, 10 webhooks, full inbox history |