SheetWA MCP
Run your WhatsApp API workspace from an AI assistant. Claude, Cursor, VS Code and any other MCP client can search contacts, send templates, run broadcasts, answer the inbox and manage auto replies for you.
- tools
- 46
- URL to connect
- 1
- requests per minute
- 120
https://backend.sheetwa.com/api/v3/mcpPrerequisites#
- A SheetWA workspace with a WhatsApp number connected through the WhatsApp API.
- Owner or admin access to that workspace. Members cannot create keys.
- An active WhatsApp API plan for anything that sends messages or switches an auto reply on. Reading data works on any plan.
- An AI client that supports MCP, such as Claude Code, Claude Desktop, Cursor or VS Code.
Create an API key#
- 1
Open API Keys
In the SheetWA dashboard, open API Keys in the sidebar (https://app.sheetwa.com/waca-api-keys).
- 2
Create a key
Click Create API key, give it a name you will recognise later, like "Claude on my laptop", and pick an expiry.
- 3
Copy it now
The full key starts with sk_live_ and is shown only once. Copy it straight into your client's config.
Treat the key like a password
Anyone holding it can act in your workspace with your role. Keep it out of shared files and screenshots. If it leaks, revoke it on the API Keys page and it stops working on the next request.
Server URL#
Every client connects to the same Streamable HTTP endpoint. Send the key in the Authorization header.
https://backend.sheetwa.com/api/v3/mcpAuthorization: Bearer sk_live_your_key_hereKeys go in the header only
A key passed in the URL query string is refused, so it never ends up in server logs or browser history.
Connect your client#
Pick your client, paste the snippet and swap in your key. Restart the client if it was already open.
Configure in Terminal
- 1Run this once in your terminal.
- 2Start Claude Code and type /mcp to check SheetWA shows as connected.
claude mcp add --transport http sheetwa https://backend.sheetwa.com/api/v3/mcp \
--header "Authorization: Bearer sk_live_your_key_here"Try it#
Once connected, ask in plain words. The assistant picks the right tools on its own. A few prompts to start with:
- "Is my WhatsApp number connected, and what is its quality rating?"
- "Show my approved templates and the placeholders each one needs."
- "Find contacts tagged VIP who have not chatted in 30 days."
- "Summarise unread inbox conversations and draft replies for me to check."
- "Add an auto reply that answers 'price' with a link to our pricing page, paused for now."
Keep a human in the loop for sends
Tools that reach a customer's phone are marked as outbound, so most clients ask before running them. Leave that confirmation on until you trust the workflow.
Tool reference
Every tool name starts with waca_ and only touches the workspace the key belongs to. Badges show what each one does.
Connection#
Check that the WhatsApp number is live before doing anything else. 1 tools.
waca_connection_status#WhatsApp connection status
Shows the WhatsApp Business number connected to this workspace: status, phone number, quality rating, the 24-hour messaging quota and whether sends are currently blocked. Call this first when a send fails or before planning a broadcast. Reads SheetWA's cached state only; it never contacts Meta.
Takes no parameters.
Contacts and tags#
Search, create and update CRM contacts, manage opt-outs and organise people with tags. 12 tools.
waca_contacts_search#Search contacts
Finds contacts in the CRM by name or phone text, status, tags and chat activity. Returns a page with names, phones, tag names and last-chat time. Use detailed when you need contact_id/tag_ids for a follow-up call. Narrow the search rather than paging through everything.
Parameters (9)›
querystring
Free text matched against name and phone.status"okay" | "duplicate" | "issue" | "unsubscribed"[]
Filter by derived status.unsubscribed= opted out.tag_idsstring[]
Only contacts carrying ALL of these tags.chat_activity"all" | "chatted" | "never"
chatted= has a WhatsApp thread,never= no inbound message yet.Default"all"sort"createdAt" | "updatedAt" | "firstName" | "lastName" | "status" | "chatActivity"
No extra notes.Default"createdAt"order"asc" | "desc"
No extra notes.Default"desc"pageinteger
1-based page number.Default1page_sizeinteger
Rows per page, 1-100. Default 20.Default20response_format"concise" | "detailed"
concisereturns the fields a person reads;detailedadds ids and raw fields for follow-up calls.Default"concise"
waca_contacts_get#Get one contact
Full profile of one contact: name, phone, status, opt-out state, tags, custom attributes and chat activity.
Parameters (1)›
contact_idrequiredstring
No extra notes.
waca_contacts_check_phone#Check whether a phone is already a contact
Normalises a phone number and reports whether a contact with it already exists. Call before waca_contacts_create to avoid a PHONE_DUPLICATE error.
Parameters (2)›
country_coderequiredstring
Country calling code digits only, e.g.91for India.phonerequiredstring
Local number or full E.164 without the plus sign.
waca_contacts_create#Create a contact
Adds one contact to the CRM. Every contact needs at least one tag: pass existing tag_ids from waca_tags_list or create one with waca_tags_create first. Fails with PHONE_DUPLICATE when the number already exists (the error carries existingId).
Parameters (6)›
first_namerequiredstring
No extra notes.last_namestring
No extra notes.country_coderequiredstring
Country calling code digits only, e.g.91for India.phonerequiredstring
Local number or full E.164 without the plus sign.tag_idsrequiredstring[]
No extra notes.attributesobject
Custom attribute values keyed by attribute key; list valid keys with waca_contact_attributes_list.
waca_contacts_bulk_create#Create up to 100 contacts
Creates many contacts in one call (max 100). Each row is validated on its own; the answer lists what was created and what failed with the reason, so a duplicate does not stop the rest. Same tag rule as waca_contacts_create.
Parameters (2)›
tag_idsrequiredstring[]
Tags applied to every created contact.contactsrequiredobject[]
Each item: first_name (string), last_name (string), country_code (string), phone (string), attributes (object).
waca_contacts_update#Update a contact
Changes name, phone, tags or custom attributes of one contact. Omitted fields stay as they are. tag_ids, when given, replaces the whole tag set (at least one). Opt-out is not changed here: use waca_contacts_set_opt_out.
Parameters (7)›
contact_idrequiredstring
No extra notes.first_namestring
No extra notes.last_namestring
No extra notes.country_codestring
Country calling code digits only, e.g.91for India.phonestring
Local number or full E.164 without the plus sign.tag_idsstring[]
No extra notes.attributesobject
Custom attribute values keyed by attribute key; list valid keys with waca_contact_attributes_list.
waca_contacts_set_opt_out#Opt a contact out or back in
Marks a contact as opted out of messages (opted_out: true) or re-enables them (false). Broadcasts skip opted-out contacts and single sends refuse them. Use this when a customer asks to stop receiving messages. Idempotent.
Parameters (3)›
contact_idrequiredstring
No extra notes.opted_outrequiredboolean
No extra notes.reasonstring
Why they are being re-enabled; kept in the audit trail.
waca_contact_attributes_list#List custom attribute definitions
The custom attribute keys this workspace accepts on contacts (key, label, type). Use the key values in the attributes object of create/update.
Takes no parameters.
waca_tags_list#List tags
Every contact tag in the workspace with its id and how many contacts carry it. Tags group contacts for broadcasts and searches.
Takes no parameters.
waca_tags_create#Create a tag
Creates a contact tag by name. If a tag with that name already exists, its id is returned with already_existed: true.
Parameters (1)›
namerequiredstring
No extra notes.
waca_tags_assign#Add tags to contacts
Adds one or more tags to one or more contacts. Existing tags on those contacts are kept.
Parameters (2)›
tag_idsrequiredstring[]
No extra notes.contact_idsrequiredstring[]
No extra notes.
waca_tags_unassign#Remove tags from contacts
Removes tags from contacts. A contact always keeps at least one tag; the tool refuses with CANNOT_UNASSIGN_LAST_TAG and lists the contacts that would be left without one.
Parameters (2)›
tag_idsrequiredstring[]
No extra notes.contact_idsrequiredstring[]
No extra notes.
Templates#
Read Meta-approved templates, save drafts and submit new ones for approval. 6 tools.
waca_templates_list#List message templates
Templates registered with Meta for this workspace, with status (APPROVED templates are the only ones that can be sent), body text and the list of placeholders each needs. Use detailed for the raw components and version.
Parameters (5)›
status"APPROVED" | "PENDING" | "REJECTED" | "PAUSED" | "DISABLED"
No extra notes.category"MARKETING" | "UTILITY" | "AUTHENTICATION"
No extra notes.querystring
Substring of the template name or body.page_sizeinteger
Rows per page, 1-100. Default 20.Default20response_format"concise" | "detailed"
concisereturns the fields a person reads;detailedadds ids and raw fields for follow-up calls.Default"concise"
waca_templates_get#Get one template
One template by name and language, with its body, placeholders, buttons, status and rejection reason. Check placeholders before any template send.
Parameters (2)›
template_namerequiredstring
Template name as registered with Meta: lowercase snake case.languagerequiredstring
Template language code, e.g.en_US,en,hi.
waca_templates_list_drafts#List template drafts
Local drafts not yet submitted to Meta. A draft becomes a real template with waca_templates_submit.
Takes no parameters.
waca_templates_save_draft#Save a template draft
Writes a template draft locally without submitting it to Meta, so a person can review it in the dashboard. Pass draft_id to update an existing draft. Body placeholders are positional {{1}}, {{2}}. Nothing is sent to Meta.
Parameters (11)›
template_namerequiredstring
Template name as registered with Meta: lowercase snake case.languagerequiredstring
Template language code, e.g.en_US,en,hi.categoryrequired"MARKETING" | "UTILITY" | "AUTHENTICATION"
MARKETING for promotions, UTILITY for transactional updates, AUTHENTICATION for codes.bodyrequiredstring
Message body. Positional placeholders{{1}},{{2}}… in order; no placeholder at the very start or end.header_textstring
Short text header. Mutually exclusive with header_format.header_format"IMAGE" | "VIDEO" | "DOCUMENT"
Media header type; pair with header_asset_id from waca_media_list.header_asset_idstring
Media-library asset used as the header sample.footer_textstring
No extra notes.quick_reply_buttonsstring[]
No extra notes.url_buttonobject
No extra notes.draft_idstring
No extra notes.
waca_templates_submit#Submit a template to Meta for approval
Submits a template to Meta. Approval usually takes minutes to hours; the template cannot be sent until its status is APPROVED. Either pass draft_id alone to submit an existing draft, or the full fields. Owner/admin only.
Parameters (11)›
template_namestring
Template name as registered with Meta: lowercase snake case.languagestring
Template language code, e.g.en_US,en,hi.category"MARKETING" | "UTILITY" | "AUTHENTICATION"
MARKETING for promotions, UTILITY for transactional updates, AUTHENTICATION for codes.bodystring
Message body. Positional placeholders{{1}},{{2}}… in order; no placeholder at the very start or end.header_textstring
Short text header. Mutually exclusive with header_format.header_format"IMAGE" | "VIDEO" | "DOCUMENT"
Media header type; pair with header_asset_id from waca_media_list.header_asset_idstring
Media-library asset used as the header sample.footer_textstring
No extra notes.quick_reply_buttonsstring[]
No extra notes.url_buttonobject
No extra notes.draft_idstring
No extra notes.
waca_templates_library_search#Search the template library
Ready-made template ideas from Meta's utility library and SheetWA's community library, searchable by words, category and industry. Use one as the starting point for waca_templates_save_draft. Read-only; importing is done by a person in the dashboard.
Parameters (5)›
querystring
No extra notes.source"meta" | "community" | "both"
No extra notes.Default"both"category"MARKETING" | "UTILITY" | "AUTHENTICATION"
No extra notes.industrystring
No extra notes.page_sizeinteger
Rows per page, 1-100. Default 20.Default20
Media#
Files already in your media library, ready to attach to broadcasts. 1 tools.
waca_media_list#List media library files
Images, videos, documents and audio already uploaded to the workspace's media library. Use an asset_id as a template media header (waca_templates_save_draft) or as the file of a media broadcast (waca_broadcasts_create). Uploading new files is done by a person in the dashboard.
Parameters (4)›
kind"image" | "video" | "document" | "audio"
No extra notes.querystring
Start of the file name.pageinteger
1-based page number.Default1page_sizeinteger
Rows per page, 1-100. Default 20.Default20
Broadcasts#
Create campaigns, follow delivery and pause, resume, cancel or retry them. 9 tools.
waca_broadcasts_list#List broadcasts
Campaigns in this workspace, newest first, with status and delivery counts. Filter by status. Use waca_broadcasts_stats for the failure breakdown of one campaign.
Parameters (4)›
status"queued" | "scheduled" | "running" | "paused" | "completed" | "failed" | "cancelled"
No extra notes.pageinteger
1-based page number.Default1page_sizeinteger
Rows per page, 1-100. Default 20.Default20response_format"concise" | "detailed"
concisereturns the fields a person reads;detailedadds ids and raw fields for follow-up calls.Default"concise"
waca_broadcasts_get#Get one broadcast
One campaign with its template or text, schedule, counts, error and retry history.
Parameters (1)›
campaign_idrequiredstring
No extra notes.
waca_broadcasts_stats#Why did a broadcast fail? Counts and failure breakdown
Delivery counts of one campaign plus every failure reason grouped by Meta error code, each with a plain-language label, a class (transient / blocked / permanent / unknown) and whether a retry can work. retry_suggestion lists the codes worth passing to waca_broadcasts_retry.
Parameters (1)›
campaign_idrequiredstring
No extra notes.
waca_broadcasts_recipients#List a broadcast's recipients
Per-recipient rows of one campaign, filterable by status or error code (use unknown for failures without a code). Each row carries the phone, status, error and timestamps.
Parameters (6)›
campaign_idrequiredstring
No extra notes.status"pending" | "sent" | "delivered" | "read" | "failed" | "skipped"
No extra notes.error_codestring
No extra notes.querystring
Phone substring.pageinteger
1-based page number.Default1page_sizeinteger
Rows per page, 1-100. Default 20.Default20
waca_broadcasts_create#Create a broadcast (template, text or media) to many recipients
Creates and queues a campaign. Recipients come either from recipients (explicit phones with per-recipient variables) or from tag_ids (every opted-in contact carrying any of those tags, at most 500 per call). For template sends, check placeholders with waca_templates_get; supply variables (same for everyone) or variables_from_contact (per-contact fields such as first_name). Text and media broadcasts only reach people who messaged in the last 24 hours. Pass scheduled_at (ISO) to send later. This reaches real phones and is billed.
Parameters (12)›
namerequiredstring
Campaign name shown in the dashboard.message_kind"template" | "text" | "media"
No extra notes.Default"template"template_namestring
No extra notes.languagestring
No extra notes.text_bodystring
For message_kind text.media_asset_idstring
For message_kind media: an asset from waca_media_list.recipientsobject[]
Each item: country_code (string), phone (string), variables (string[]).tag_idsstring[]
Send to opted-in contacts with any of these tags.variablesstring[]
Body values used for every recipient.variables_from_contactstring[]
Per-contact body values, in placeholder order: first_name, last_name, phone or a custom attribute key. Tag sends only.scheduled_atstring
ISO 8601 with offset; omit to send now.rate_per_secondinteger
No extra notes.
waca_broadcasts_pause#Pause a broadcast
Pauses a running, queued or scheduled campaign. Resume with waca_broadcasts_resume.
Parameters (1)›
campaign_idrequiredstring
No extra notes.
waca_broadcasts_resume#Resume a paused broadcast
Continues a paused campaign from where it stopped.
Parameters (1)›
campaign_idrequiredstring
No extra notes.
waca_broadcasts_cancel#Cancel a broadcast
Stops a campaign for good; pending recipients are closed as cancelled. Cannot be undone. Owner/admin only.
Parameters (1)›
campaign_idrequiredstring
No extra notes.
waca_broadcasts_retry#Retry failed recipients by error code
Re-sends a finished campaign to recipients that failed with the given Meta error codes (use unknown for failures without a code). Get the codes and retry_suggestion from waca_broadcasts_stats; permanent failures such as 131026 (number not on WhatsApp) never succeed. Optionally schedule the retry for later, which is what transient limits need.
Parameters (3)›
campaign_idrequiredstring
No extra notes.error_codesrequiredstring[]
No extra notes.scheduled_atstring
No extra notes.
Inbox#
Read conversations, reply inside the 24-hour window and open or close threads. 7 tools.
waca_inbox_counts#What is waiting in the inbox
Counts of unassigned, mine, open, closed and unread conversations. The quickest way to see whether anything needs attention.
Takes no parameters.
waca_inbox_list_conversations#List inbox conversations
WhatsApp threads with the contact name, phone, unread count, who holds it, the last message preview and whether the free-text reply window is open. view picks the queue: unassigned, mine (held by this key's owner), all, closed or unread. Page with cursor.
Parameters (7)›
view"unassigned" | "mine" | "all" | "closed" | "unread"
No extra notes.Default"all"querystring
Contact name or phone.tag_idstring
No extra notes.assignee_account_idstring
No extra notes.cursorstring
No extra notes.page_sizeinteger
Rows per page, 1-100. Default 20.Default20response_format"concise" | "detailed"
concisereturns the fields a person reads;detailedadds ids and raw fields for follow-up calls.Default"concise"
waca_inbox_get_conversation#Get one conversation
One thread's header: contact, state, assignee, unread count, tags and reply-window state. Read the messages with waca_inbox_list_messages.
Parameters (1)›
conversation_idrequiredstring
No extra notes.
waca_inbox_list_messages#Read a conversation's messages
Messages of one thread, oldest to newest within the page, with direction, text, type, status and who sent it. Page backwards in time with cursor.
Parameters (3)›
conversation_idrequiredstring
No extra notes.cursorstring
No extra notes.page_sizeinteger
Rows per page, 1-100. Default 20.Default20
waca_inbox_set_state#Assign, claim, release, close, reopen or mark read
Changes a thread's state. assign needs assignee_account_id (from waca_workspace_members_list). claim takes the thread for this key's owner; release gives it back to the unassigned queue; close ends it; reopen brings a closed thread back; mark_read clears the unread count.
Parameters (3)›
conversation_idrequiredstring
No extra notes.actionrequired"assign" | "claim" | "release" | "close" | "reopen" | "mark_read"
No extra notes.assignee_account_idstring
No extra notes.
waca_inbox_reply#Reply to a conversation with text
Sends a free-text WhatsApp reply on a thread. Only works while the 24-hour reply window is open (reply_window_open on the conversation); otherwise use waca_inbox_reply_template. Claims an unassigned thread for this key's owner. Reaches a real phone.
Parameters (2)›
conversation_idrequiredstring
No extra notes.textrequiredstring
No extra notes.
waca_inbox_reply_template#Reply to a conversation with a template
Sends an APPROVED template on a thread, which is the only way to reach the customer after the 24-hour window closes. variables fill the body placeholders in order (check with waca_templates_get). Claims an unassigned thread. Reaches a real phone and is billed.
Parameters (4)›
conversation_idrequiredstring
No extra notes.template_namerequiredstring
No extra notes.languagerequiredstring
No extra notes.variablesstring[]
No extra notes.Default[]
Single messages#
Send one template message and look up any message's delivery status. 2 tools.
waca_messages_get#Get delivery status of a sent message
Status of one outbound message (queued, sent, delivered, read, failed) with Meta's error code and text when it failed. Use the message_id a send tool returned.
Parameters (1)›
message_idrequiredstring
No extra notes.
waca_messages_send_template#Send a template message to one person
Sends one APPROVED template to one recipient, outside or inside the 24-hour window. Give contact_id or a phone with country code. variables fill the body placeholders in order; check the count with waca_templates_get first. Refuses opted-out contacts (CONTACT_OPTED_OUT). For many recipients use waca_broadcasts_create. This reaches a real phone and is billed.
Parameters (6)›
contact_idstring
No extra notes.country_codestring
No extra notes.phonestring
No extra notes.template_namerequiredstring
No extra notes.languagerequiredstring
No extra notes.variablesstring[]
No extra notes.Default[]
Auto replies#
Create, edit, pause and delete keyword rules that answer incoming messages automatically. 4 tools.
waca_auto_replies_list#List auto-reply rules
Every auto-reply rule on the connected number: its trigger words, reply text, and whether it is active. A dormant rule is over the plan's limit and does not fire.
Takes no parameters.
waca_auto_replies_create#Create an auto-reply rule
Adds a rule that answers incoming WhatsApp messages automatically when they match its triggers. Pass active: false to save it paused. Fails with DUPLICATE_RULE when another rule already replies to the same word.
Parameters (4)›
triggersrequiredobject[]
Each item: keyword (string), match_type ("exact" | "contains").match_mode"any" | "all"
anyfires when one trigger matches;allneeds every trigger.reply_textrequiredstring
The text sent back automatically.activeboolean
No extra notes.
waca_auto_replies_update#Edit, pause or resume an auto-reply rule
Changes a rule's triggers, match mode or reply text, or switches it on or off with active. Only the fields given change. Turning a rule on needs an active plan; pausing never does.
Parameters (5)›
rule_idrequiredstring
No extra notes.triggersobject[]
Each item: keyword (string), match_type ("exact" | "contains").match_mode"any" | "all"
anyfires when one trigger matches;allneeds every trigger.reply_textstring
The text sent back automatically.activeboolean
No extra notes.
waca_auto_replies_delete#Delete an auto-reply rule
Removes a rule for good. To stop it for now, use waca_auto_replies_update with active: false instead.
Parameters (1)›
rule_idrequiredstring
No extra notes.
Notes#
Private team notes on threads and contacts. Customers never see them. 2 tools.
waca_notes_list#List internal notes
Private team notes on an inbox thread or a CRM contact. Notes are never sent to the customer. A thread's list also includes notes written on its contact.
Parameters (2)›
conversation_idstring
An inbox thread. Give this or contact_id.contact_idstring
A CRM contact. Give this or conversation_id.
waca_notes_add#Add an internal note
Writes a private note on an inbox thread or a CRM contact for the team to read. The customer never sees it. Good for summaries, hand-over context and follow-up reminders.
Parameters (3)›
conversation_idstring
An inbox thread. Give this or contact_id.contact_idstring
A CRM contact. Give this or conversation_id.bodyrequiredstring
No extra notes.
Workspace#
Team members and saved quick replies, so the assistant writes like your team. 2 tools.
waca_workspace_members_list#List team members
People in this workspace with their role (owner, admin, member) and account_id. Use an account_id to assign an inbox conversation with waca_inbox_set_state.
Takes no parameters.
waca_quick_replies_list#List saved quick replies
The team's saved canned replies for the inbox (name and message text). Reuse their wording in waca_inbox_reply so replies match how the team already talks to customers.
Takes no parameters.
Errors#
A refused tool call comes back as a normal result with isError set, a code and a hint, so the assistant can fix its next call on its own.
VALIDATION_FAILED
Status: 400
What it means: An input failed its schema. The details list each field.
API_SUBSCRIPTION_REQUIRED
Status: 402
What it means: This action needs an active WhatsApp API plan.
PLAN_LIMIT_REACHED
Status: 402
What it means: The monthly message allowance or a plan cap is used up.
FORBIDDEN
Status: 403
What it means: The action needs an owner or admin key.
NOT_FOUND, CONTACT_NOT_FOUND, …
Status: 404
What it means: Nothing with that id exists in this workspace.
PHONE_DUPLICATE
Status: 409
What it means: That number is already a contact.
DUPLICATE_RULE
Status: 409
What it means: Another auto reply already answers that word.
WINDOW_CLOSED
Status: 409
What it means: Free text is only allowed within 24 hours of the customer's last message. Use a template.
NO_CONNECTION
Status: 409
What it means: No WhatsApp number is connected.
| Code | Status | What it means |
|---|---|---|
| VALIDATION_FAILED | 400 | An input failed its schema. The details list each field. |
| API_SUBSCRIPTION_REQUIRED | 402 | This action needs an active WhatsApp API plan. |
| PLAN_LIMIT_REACHED | 402 | The monthly message allowance or a plan cap is used up. |
| FORBIDDEN | 403 | The action needs an owner or admin key. |
| NOT_FOUND, CONTACT_NOT_FOUND, … | 404 | Nothing with that id exists in this workspace. |
| PHONE_DUPLICATE | 409 | That number is already a contact. |
| DUPLICATE_RULE | 409 | Another auto reply already answers that word. |
| WINDOW_CLOSED | 409 | Free text is only allowed within 24 hours of the customer's last message. Use a template. |
| NO_CONNECTION | 409 | No WhatsApp number is connected. |
Limits and security#
Requests per key
Value: 120 per minute, then 429
Recipients per tag broadcast call
Value: 500
Page size on list tools
Value: 20 by default, up to 100
Who can create keys
Value: Owners and admins
Workspace scope
Value: A key only ever sees the workspace it was created in
| Rule | Value |
|---|---|
| Requests per key | 120 per minute, then 429 |
| Recipients per tag broadcast call | 500 |
| Page size on list tools | 20 by default, up to 100 |
| Who can create keys | Owners and admins |
| Workspace scope | A key only ever sees the workspace it was created in |
- Keys are stored hashed. SheetWA cannot show a key again after it is created.
- If the person who created a key loses their owner or admin role, the key stops working.
- Messages sent through MCP are recorded as sent by an agent, so you can tell them apart from your team's.