Changelog

New tools, improvements, and fixes across the gateway and its connectors.

notionnotion-mcpconnections

Notion connector

Notion now works inside your DataToRAG agent, with Gmail, Drive and Jira in the same conversation. Connect it from the connections page. Notion asks which pages to share, and the connector sees only those, children included. You can share more later from a page's ••• menu, under Connections, without reconnecting.

Reading. notion_search finds pages and databases by title, notion_get_page returns a page's properties as plain values and its content as markdown, and notion_query_data_source filters, sorts and pages through a database, or runs one of its saved views.

Writing. Create pages and database rows, edit content in markdown, change properties, move, duplicate, trash and restore pages, write comments, and create databases and views. In an Agent conversation, every write asks for approval before it runs.

Workspaces. Each Notion workspace is its own connected account. account takes the email, or the workspace name or id when one email has several.

Notion's API searches titles, not page content, so search here does too. The full list of tools, limits and what is not possible is on the Notion docs page, and the launch post walks through it.

dashboardgoogle-workspacebugfix

The note on the Google card now sits inside the card

The note on the Google Workspace card on your dashboard, the one that says what the connect button opens and to tick every box, was drawn below the card's button row rather than in it. Once you had an account connected it sat under Add account as a separate strip, cut off from the card it belongs to.

It now sits inside the card, under the buttons, in the same band as Add account and Browse tools (or under Connect, before you have connected anything). The wording is the same, and hiding it works the same way: hide it once and it stays hidden on every device you sign in on.

sitestatus

A status page that shows what works today

Every day a test run calls the tools on production the way you would, with real accounts, and checks what comes back: it sends an email and waits for it to arrive, creates a Jira issue and deletes it, writes to a spreadsheet and reads it back. Until now only we saw the result.

It is public now, at /status. The page is the latest full run, grouped by service: each check in plain words, whether it worked, and a strip of the 30 days before it. Under each service are its tools and their state, including the ones no check exercises yet, listed as exactly that.

If a check fails, it shows as failing in the latest check, and the service with it. If the last full run is more than a day and a half old, the page says so at the top rather than showing an old green as a current one.

It doubles as a list of what you can do with DataToRAG, each line backed by the latest run.

gmaildrivecalendargws-mcp

Ten Gmail, Calendar and Drive actions the built-in connectors had and we did not

Claude's own Gmail, Calendar and Drive connectors could do a few things ours could not. Now ours does them too.

Calendar. calendar_respond_to_event answers an invitation with accepted, declined or tentative, and changes only your own response. calendar_suggest_time finds free slots for you and the people you name, inside working hours, and says whose calendars it could not see. calendar_list_calendars lists the calendars on the account.

Gmail. gmail_label_message takes a thread_id, so a label goes on or comes off a whole conversation in one call. gmail_trash_thread and gmail_untrash_thread do the same for Trash, and gmail_mark_spam and gmail_unmark_spam report a message as spam and take it back.

Drive. drive_share_file shares a file with one person as reader, commenter or writer, drive_get_file_permissions lists who has access, and drive_list_recent_files lists what you opened or changed most recently.

Every one of them takes an account, like the rest of the connector. In the Agent, the ones that change something ask for approval before they run.

Why these, and what the table says now: The Gaps in the Comparison Table Were Ours. They Are Closed..

drivefile-referencesgws-mcp

Download a Drive file, or a Doc as a PDF, without it entering the chat

A Google Drive file can now be named by a file reference, the same way an email or one of its attachments already could, so the tools that take a file take a Drive file too.

There are two new references. drive_file names a file as it is stored in Drive: a PDF, an image, a spreadsheet someone uploaded. drive_export names a Google Docs, Sheets or Slides file together with a format, such as pdf, docx, xlsx or pptx, and the file is exported to it.

With file_download_link, a Drive file or a Doc as a PDF goes to your computer through a link that works once, with the SHA-256 of what was sent. With jira_add_attachment it goes onto a Jira issue. With drive_upload_file and a reference naming another of your connected Google accounts, it is copied from one account's Drive into another's. In every case the file's content is not returned and does not enter the conversation.

A folder, a shortcut, a file in Trash, and a Google file asked for as a stored one are refused before anything is read. Moving files between services lists the formats each kind of Google file exports to.

Why these, and what the table says now: The Gaps in the Comparison Table Were Ours. They Are Closed..

gws-mcpmcp

The raw Google API call is off the list, so named tools come first

The Google Workspace connector's raw API tool, gws_run, is no longer in the tool list your client or the Agent sees. With the nine tools from the last release, the jobs it was being used for have tools of their own, and a model that can see a generic tool sometimes picks it over the named one and guesses at Google's request shape.

So a client now gets the named tools only: gmail_, calendar_, drive_, sheets_, docs_ and tasks_. A client still holding an older list that calls the raw tool gets a short answer pointing at those, and that call does not count against your plan. The tool counts on this site leave it out too.

If you were using the raw call for something no named tool covers, tell us what. That is how the nine got built, and it is how the next one will.

gmaildrivesheetscalendargws-mcp

Nine tools for what people were reaching the raw API call for

The Google Workspace connector has one generic tool, gws_run, that sends a single request to a Google API method by name. It is there for the calls nothing else covers. A call made that way needs the caller to know Google's resource paths and parameters, and it fails in ways that say little: a list of ranges handed to a method that takes one, a drafts listing refused for a userId nobody mentioned, an attachment fetched whole and then rejected for its size.

Nine of those calls are now tools of their own.

Gmail. gmail_trash moves a message to Trash and gmail_untrash takes it back out. gmail_list_drafts lists the mailbox's drafts with the IDs the other draft tools take. gmail_get_attachment describes one attachment by its part ID, with its name, type and size, and returns the content as text when it is a text file of up to 0.5 MB. Anything else, or anything larger, comes back as a description that states the size, with no content. File bytes are never returned as base64. To get a file somewhere you can open it, gmail_save_attachment_to_drive still puts it in Drive.

Drive. drive_get_file describes a file or folder without reading it: name, type, size, the folders it is in, owners, dates and link. drive_move_file moves it into another folder and takes it out of the one it was in. drive_trash_file moves it to Trash.

Sheets. sheets_get_metadata returns a spreadsheet's tabs with their titles, sheet IDs, grid sizes and frozen rows, and no cell data at any size. sheets_copy_tab_to copies a tab, by title, into another spreadsheet.

Calendar. calendar_list_events has always returned a nextPageToken when there were more events than it was asked for. It now takes that token back as page_token, so the next page can be read.

Reading several ranges in one sheets_read call, with ranges, was already there.

gws_run itself does the same thing it did. Its description now says what it is: a custom query tool for the Gmail, Calendar, Drive, Sheets, Docs, Slides, People and Tasks APIs, with a link to Google's reference. In the Agent, the moving and trashing tools ask for approval before they run, like every other write.

What the raw call was being used for, and why these nine: We Read What People Used the Raw API Call For, and Built Nine Tools Instead.

drivegmailfiles

Save an email or an attachment to Drive, with a checksum of what Drive stored

drive_upload_file takes the same file reference jira_add_attachment and file_download_link take, an email or one of its attachments, and puts the file into Google Drive under its own name. Pass a folder id to choose where it goes; without one it lands in the root of My Drive.

The receipt can say something the Jira one cannot: Drive computes its own SHA-256 of the file it stored, and the receipt sets it beside the SHA-256 of what was sent, with checksum_match saying whether they agree. If they do not, the call answers with an error and the full receipt, and the file stays in Drive for you to look at.

The receipt also names the folder's owners, whether it is shared and whether it is in a shared drive, next to the account that received the file, so a folder that belongs to someone else is visible before you rely on it.

The email can come from one connected Google account and go into the Drive of another. The file's content never enters the conversation and is never written to our disks.

Details are on the file references page. The story behind it: Save the Email to Your Own Computer, With a Checksum You Can Check.

gmailfiles

Save an email or an attachment to your computer from a link

A file reference can now go to your own disk. file_download_link takes the same reference jira_add_attachment takes, an email or one of its attachments, and answers with a link that saves the file to your computer.

The link opens a page with the file's name, its size and one button. The button saves the file. A link works once and lasts ten minutes. If you work in a terminal, the receipt also carries a one-line command that saves the file without the page.

The receipt gives the size in bytes and the SHA-256 of the file, so you can check your copy with shasum -a 256, sha256sum or Get-FileHash. The file is the unmodified original: a message exactly as Gmail returns it in raw form, or an attachment's own bytes. Before it is sent it is read again and compared with the receipt, and if it no longer matches, nothing is sent.

The file's content never enters the conversation and is never written to our disks. It is held in memory only while it is being read. For up to twenty minutes after a link is made we keep what identifies the file (the message it names and the account it is in, its name, size and SHA-256), and none of its content.

A link is for you. A call to any DataToRAG tool that carries one of your unused links is refused and the link is cancelled. In a chat with the DataToRAG agent you are asked before a link is made, and a skill run cannot make one.

Details and limits are on the file references page. The story behind it, and why the link opens a page with one button: Save the Email to Your Own Computer, With a Checksum You Can Check.

gatewaygoogle-workspace

Your accounts now say what they granted, and gws_auth_setup is gone

Two changes to how a client finds out why a Google call was refused.

list_connected_accounts shows what each Google account granted. Google's consent screen lets you untick services one at a time, so an account can be connected and still unable to touch your sheets. Each Google Workspace account in the answer now carries two lists: granted_services and missing_services, by name (Gmail, Drive, Calendar, Docs, Sheets, Slides, Contacts, Tasks). When something is missing, the account also says where to reconnect it. The fields the answer already had are unchanged, so nothing that reads it today breaks.

An account connected before grants were recorded says "not recorded" there. We would sooner say that than tell you every service was granted when nobody checked.

gws_auth_setup is removed. It came from a time when the Google tools ran on your own machine and had a login of their own. Behind the gateway there is nothing for it to log in to, and for a while its only answer was that authentication is handled elsewhere. The Google Workspace tool count goes from 68 to 67.

If Google refuses a token, the error now names the two things that help: call list_connected_accounts to see what is connected, then reconnect the account on the connections page.

If you have a prompt or a saved skill that calls gws_auth_setup, swap it for list_connected_accounts. A client that cached the old tool list will pick up the new one the next time it connects.

dashboardbilling

The Billing page loads for Pro accounts again

If you are on Pro, the Billing page in the dashboard failed to load, with an error that a reload did not clear. It worked for Free accounts, which is how it went unnoticed.

The cause was ours and had nothing to do with your subscription or with Stripe: the page could not draw the price on your own plan card. Your plan, your payment method and your invoices were never affected. What you lost was the way to them from the dashboard, including the button to manage or cancel, and we are sorry for that.

It is fixed, and the page now shows your plan card, your usage for the period, your card on file and your recent invoices as intended. A check now runs with every change to the site for the kind of mistake behind this one.

dashboardgoogle-workspace

Connecting Google: a clearer first step, and a second try that does not start over

Google's consent screen shows its permission checkboxes unticked. If you press Continue without ticking them, Google connects nothing, and until now that left you back on the dashboard under a small banner. Four changes around that moment.

  • If Google connects nothing, you land on a page that says so. It names what happened, shows the box to tick (Select all), lists the services it covers, and has one button: Try again.
  • Try again goes straight back to the consent screen. It used to send you through Google's account chooser first, which felt like signing in all over again. It now returns to the consent screen for the account you just picked. You can still switch accounts there.
  • A note under the Google connect button says what the button opens, to tick every box, and that you can disconnect any time. Hide it once and it stays hidden on every device you sign in on. It comes back by itself if a connect returns with nothing granted.
  • The agent's first screen numbers its steps. For an account with nothing connected it now reads "1. Connect an account" and "2. Once you connect, ask for something like", so the first thing to do is not left to guesswork.
pricingbilling

Pro now includes 400 agent runs a month, and Free 40

The monthly allowance of agent runs goes up on both plans. Pro goes from 100 to 400, and Free goes from 25 to 40. Prices do not change.

The higher number applies to the period you are in now, on either plan. There is nothing to do. The Billing page in the dashboard and the meter in the Agent show it against your usage.

Nothing else moves. The tool call allowances stay where they were, 10,000 a month on Pro and 250 on Free, and so does the ceiling on what a single run can use.

dashboardsite

One click to sign in

Every Get started, Start free, Sign in and Run this skill button on the site now opens Google sign-in directly. There used to be a page in between with a single "Continue with Google" button on it. It asked for a second click to do what the first one already meant, and some people never made it past.

What changed around that:

  • The button shows it heard you. Handing over to Google takes a moment. The button now dims while that happens and ignores a second click, where before it looked as if nothing had happened.
  • You still land where you were going. A skill's Run button still ends in the agent with that skill loaded, and the Pro button on the pricing page still comes back to pricing.
  • If sign-in does not finish, you get a way back. Closing Google's screen used to end on a bare line of error text. It now returns to the sign-in page with a note and the button.
  • Terms and privacy are stated where you sign in. The sentence that lived on the old page now sits beside the main sign-up buttons and on the first screen of the dashboard, with links to both documents.

The sign-in page itself is still there. It is where you arrive if a session expires while a dashboard page is open, or if a sign-in is interrupted.

pricingbilling

Pro now includes 10,000 tool calls a month

The Pro plan's monthly allowance of tool calls goes from 2,000 to 10,000. The price does not change, and neither does anything else on the plan: 100 agent runs a month, every connector and every tool, and an approval on every write.

If you are already on Pro, the higher number applies to the period you are in now. There is nothing to do. The Billing page in the dashboard shows it against your usage.

Pro has never stopped you at the allowance, and it still does not. The Free plan is unchanged: 250 tool calls and 25 agent runs a month.

agentdashboard

Agent steps you can read at a glance, and waits that show they are moving

Three changes to how a run looks in the dashboard agent while it works.

  • Each step says what it was called with. A step in the thread used to show a tool name and a status. It now also shows a short line of what the call was made with, such as the range it wrote or the search it ran, so a run of steps reads as a list of what happened. The full parameters and result are still one click away.
  • An opened step stays inside its card. Opening a step with a large result, a long inbox listing for example, used to push the rest of the conversation off the screen. The parameters and the result now scroll inside the card.
  • A long wait counts. Once a step has been thinking or running for more than five seconds, the progress line shows how long it has been going. It is a measurement of the wait so far, not an estimate of what is left.

And one that was missing words:

  • "Interrupted" now says what it means. If a step's result never comes back, the run stops at that step. The thread now says so under the message and offers Try again. It also tells you to check first if the step was a write, because a call that was sent may have gone through even though its result did not reach the page.
agentdashboard

The agent no longer crashes on a page your browser has translated

If your browser translates the dashboard into your own language, the agent page could be replaced by a blank "this page couldn't load" screen in the middle of a run. It happened the moment a tool step changed state: a step finishing, or a write waiting for your approval. The run itself was fine and kept going on our side. The page drawing it was what failed.

The cause was ours. A translating browser rewrites the text on the page, and one small part of each tool step (the status badge) was built in a way that could not survive being rewritten while it changed. That part is rebuilt, and the whole conversation is now tested on a translated page from the first message to the last.

Three things come with the fix:

  • A fault in the chat stays in the chat. If the conversation ever fails to draw again, for any reason, you get a card where the conversation was, with Reload this conversation. The rest of the dashboard stays on screen, and a run in progress carries on and is saved.
  • The dashboard has its own error page. A fault on any dashboard page now keeps the navigation and offers Try again, where it used to replace the whole page.
  • Sending too quickly asks you to wait. A burst of requests is briefly refused. The chat used to read that refusal as your run allowance being used up and hid the message box. It now says to wait a moment and leaves the box where it was.

One limit to know about: on a translated page, an answer that is still streaming can show its text in the original language until the browser translates it again. Nothing is lost, and reloading the conversation shows the full answer.

gatewaysheetstools

A wrong argument is refused in words, before anything is sent

When a tool call leaves out a required argument, or names one the tool does not have, the gateway now refuses it before the connector is called. The answer says which argument is missing or unknown, suggests the closest real name for a misspelling, lists what the tool requires, and ends with "Nothing was sent." Before this, such a call often reached the service and came back as an error that did not say what was wrong, and one search tool ran with no query at all.

The check covers the names of a tool's own arguments. The values, and anything nested inside an argument, are still judged by the connector.

sheets_append and sheets_update now say in their descriptions how numeric-looking text is typed: the way the Sheets UI types it, so 007 is stored as the number 7 and reads back as 7. To keep such a value as text, pass value_input_option: "RAW" for the call, or put a leading apostrophe on that one value. Nothing about the write changed; the description now states it.

jiragmailtools

Attach an email's attachment to a Jira issue

jira_add_attachment now takes a second kind of file reference: one attachment of a Gmail message. Name the issue, the message and the attachment's part id, and the file lands on the issue under the sender's file name and type, without passing through the conversation or being downloaded.

The part id is the one to use, not the attachment id. Gmail issues a new attachment id every time a message is read, so an id copied from one read does not match the next; the part id stays the same, and gmail_read now lists it beside each attachment.

Each call moves one file, up to 25 MB, and answers with the same receipt as before: the attachment's name and size, the SHA-256 and byte count of what was sent, and the issue it went to. An email with three PDFs is three calls. See Moving files between services. The story behind it, and where the file is while it moves: Claude can file an email on a Jira issue now.

jiragmailtools

Attach an email to a Jira issue, as the original file

Putting an email on a Jira issue used to mean downloading the message from Gmail and uploading it to Jira by hand. jira_add_attachment does it in one call: name the issue and the Gmail message, and the email's original .eml file lands on the issue.

The file is the message exactly as Gmail returns it in raw form, unchanged by us. Its content never passes through the conversation. It is held in the gateway's memory only while the transfer runs, and is never written to our disks.

The answer is a receipt: the attachment's name and size, the SHA-256 and byte count of what was sent, and the issue's key, project and summary, so you can see what went where. One file per call, up to 25 MB.

This is the first of a general way to move files between connected services; see Moving files between services. The story behind it, and where the file is while it moves: Claude can file an email on a Jira issue now.

gmailreliability

Gmail searches hold up when Claude runs several at once

When Claude ran several Gmail searches at the same time, Google sometimes refused one of them for being too many requests at once, and the search came back as an error. DataToRAG now waits a moment and tries that read again, up to three times in all, so the search normally returns its results. This applies to most reads across Gmail, Drive, Sheets, Docs and Calendar. Sends and other writes are never retried, so nothing can go out twice.

gmailtools

Replies go where Gmail would send them

When Claude replied to an email for you, the reply went to whoever was in the From line. That is wrong in two common cases. A message with a Reply-To address, such as a booking system or a support desk, wants the answer somewhere else. And a reply to a message you sent yourself went back to you.

gmail_reply now addresses a reply the way Gmail's own Reply button does:

  • To the Reply-To address when the message has one, otherwise to the sender.
  • To the people you wrote to, when the message is one you sent.
  • To everyone on the original when you ask for it, with the new reply_all option. It is off unless you ask, and it leaves your own addresses out.

The response says who the reply went to. Because a Reply-To can point somewhere other than the sender you see, there is also a guard: pass expected_to with the address or addresses you mean to answer, and the reply is refused before anything is sent unless it would go to exactly those.

One more fix. gmail_mark_read used to mark a message read even when you only asked it to add a label. It now does exactly what you ask: with no labels given it marks the message read, and with labels given it applies those and nothing else.

sheetstools

Sheets queries find the tab you named, or say they can't

Asking Claude to query a tab that did not exist used to return rows anyway. They came from the first tab of the spreadsheet, with no error, so a typo in a tab name looked like a real answer. A tab with an apostrophe in its name, such as Bob's, did the same thing.

sheets_query now checks the range against the spreadsheet's actual tabs before it runs:

  • A tab that does not exist is refused, and the refusal lists the tabs the spreadsheet has.
  • A tab name on its own works even when it also reads as a cell, so a tab called Q3 or Log is the tab, not cell Q3 or column LOG.
  • Tab names with apostrophes or exclamation marks resolve to the right tab. sheets_find_rows also reports the right row number on a tab with an exclamation mark in its name.

sheets_format_table and sheets_format_range resolve tabs the same way. If you ask sheets_format_table to trim the grid on a name that is both a tab and a cell reference, the call is refused with a note on how to say which one you meant.

One thing we measured and cannot change: when a column mixes numbers and text, Google's query endpoint reads it as whichever type most of its cells hold, and the others come back empty. The tool's description now says so. For a column like that, sheets_read or sheets_find_rows returns every cell.

billingdashboard

The Billing page shows your plan, what you've used, your card and your invoices

Billing in the dashboard is rebuilt around four things you could not see there before.

Your plan, on the same cards as the pricing page. The three plans are shown side by side with the one you are on marked "Current plan". From Free, Upgrade to Pro is on the Pro card. On Pro, "Manage or cancel" is on your own card and "Downgrade" on the Free one, and both open the Stripe billing portal. If you cancel, Pro stays active until the end of the period you have paid for.

This period. Two meters, tool calls and agent and skill runs, each against your plan's allowance, with the date the allowance resets. They read the same counters the limit itself uses, so the page and the limit cannot disagree.

Payment method. The card on file, its brand, last four digits and expiry, with Update beside it.

Invoices. Your recent invoices with the date, the amount, the status and a PDF link, and "All invoices" for the full list in the portal.

Payment method and Invoices appear once the account has been billed through Stripe; a free account that has never paid sees the plans and its usage. If Stripe is slow to answer, those two sections say so and point to the portal, and the rest of the page still loads.

gmaildrivegws-mcp

Attach Drive files to the mail your assistant sends

gmail_send, gmail_reply, gmail_forward, gmail_create_draft and gmail_update_draft take an attachments list. Each entry is a Drive file id. A PDF, an image or any other file is attached as it is. A Google Doc, Sheet or Slides deck passed by id alone goes in as a link in the body, the way Gmail's own compose does it; pass {file_id, as: "pdf"} to attach an export instead. Docs export as pdf, docx, txt, html, md, rtf, odt or epub; Sheets as pdf, xlsx, csv, tsv, html or ods; Slides as pdf, pptx, txt or odp. csv and tsv export one tab: add tab to choose it, and the response says which tab went.

Inline images. Reference a file in html_body as <img src="cid:FILENAME"> and it renders in place instead of as an attachment at the bottom, the same structure Gmail builds when you paste an image into a message.

Forwarding carries the original's files. gmail_forward now includes the forwarded message's own attachments, counted in the limit. Pass include_original_attachments: false to forward the text alone.

Limits and refusals. At most 10 files and 25 MB per message. A refusal comes before any download for files whose size Drive reports, and names the file and the cap; an export is counted as it downloads, and one over the cap stops the message before it is sent. Two attachments may not share a filename.

Drafts with files are signed. gmail_send_draft adds your Gmail signature to a draft that holds files, the way it already does for plain drafts. Updating a draft replaces it whole: files it held are dropped unless you pass them again.

The response says what happened. Each entry is reported as attached, inline, linked or exported, with its size or link.

Files come from Drive only. To send something that is not in Drive yet, put it there first and pass its id. The design, and why the bytes never pass through the model, is in Your Agent Can Attach Files to Email Now.

gmaildrivegws-mcp

Large attachments save to Drive whole

gmail_save_attachment_to_drive streams the attachment from Gmail into Drive instead of holding it in memory, so a 9 MB PDF arrives in Drive byte for byte with a matching checksum. Anything over 5 MB goes through Google's resumable upload. Before this, an attachment that size failed on a buffer limit.

Underneath, the Google Workspace connector now calls Google's APIs directly with your token on every call, rather than through a bundled command-line tool. You should notice nothing except that big files work and errors from Google come back with their real reason.

site

FAQs on every connector page

Every connector, pricing and docs page now ends with the questions people actually ask about it, over 180 answers in all, and there is a single page at /faq with all of them. Three published claims were corrected while writing them, including that the built-in Gmail connector sends, replies and forwards, which it does.

sheetsgws-mcp

sheets_read returns every range you ask for, even the same one twice

Asking sheets_read for the same range more than once in one ranges call used to leave the later copies empty, because Google returns one block for two identical requests. Each requested range now gets its data in its own slot, in request order. Found by our own test suite on its first run.

gmailgws-mcp

Mail your assistant sends now carries your Gmail signature

Email sent through the Gmail connector now ends with the signature you set in Gmail, the same one Gmail adds when you write the message yourself. It applies to gmail_send, gmail_reply, gmail_forward and gmail_send_draft. There is nothing to configure: the signature is read from the address the message is sent from, so an alias gets its own.

Where it goes. On a new message the signature closes the body. On a reply or a forward it sits under your note and above the quoted message, where Gmail puts it.

Drafts are signed when they are written. gmail_create_draft and gmail_update_draft add the signature the way Gmail's own Compose does, so a draft you review in Gmail already carries it, and sending it from Gmail or through gmail_send_draft never adds a second one; gmail_send_draft signs only a draft that has none. Pass signature: false on the draft tools to leave it out.

Turning it off. Pass signature: false on any of the four send tools and the message goes out exactly as written. Asking your assistant to "send this without my signature" does it.

The response says what happened. Every send returns a signature field: applied, none_set when the account has no signature, suppressed when you turned it off, already_present when the body already ended with it, unavailable when the signature could not be read and the mail went out unsigned, and skipped_unsupported_draft when a draft's format is one we send untouched rather than rewrite.

Replies and forwards also changed shape underneath. They are now sent with both a plain-text and an HTML version, as new messages already were, so a plain-text reply keeps its plain-text part when a signature is added. The signature itself lives in the HTML version only.

One thing you may notice on a phone: Gmail's mobile apps fold a signature they recognise behind the three-dot button, including on mail you wrote by hand. That is Gmail's display, not a missing signature.

Corrected September 18: drafts were unsigned when this shipped; they are signed from the same day's follow-up release.

gws-mcpsheetsgmail

gws_run takes repeated query parameters

Pass a list where the API takes one. gws_run now accepts an array for any query parameter the Google API repeats: ranges on a spreadsheet get, labelIds on a Gmail message list, metadataHeaders on a message get. { "ranges": ["Sheet1!A1:B2", "Totals!A1:B5"] } fetches both blocks in one call. Until today the call was refused with "Array-valued parameters are not supported" and the only way through was one call per value.

taskssheetsgws-mcpskills

Many tasks and many ranges in one call

Two per-item tools gained a batch form, so a routine that used to spend one model step per item spends one.

tasks_create takes a list. Pass tasks (each with a title, optional notes, due date and task list) and every task is created in one call, with a per-task result so a partial batch is visible. The single-task shape still works. The morning brief uses this for its follow-ups.

sheets_read takes several ranges. Pass ranges and get one block per range, each labelled with the range the API echoed, in the order you asked. A header row and a data block, or two tabs, are one call instead of two. An empty range comes back as an empty block in its place.

agentskillsusage

Skill runs that finish: Stop means stop, a report near the limit, and what each run cost

Four changes to how a skill run behaves in the dashboard agent, all live today.

Stop means stop. Pressing Stop now ends the run on the server at the next step boundary. The step already in flight finishes, no further model call starts, and the thread shows a card that says you stopped it and what was saved. Before this, Stop only closed your browser's connection, and a run that had been told to label mail and send a digest kept doing exactly that.

A long thinking step no longer ends as "network error". The stream stays alive while the model thinks, so a step that streams nothing for two minutes still reaches your browser. Runs that dropped mid-way on a seven-account brief now finish.

A run near its limit writes its report. At 85 percent of the run budget the model is told to stop calling tools and write what it has. The budget itself now counts cached tokens at their real weight, so a run is no longer cut short for reading the same prefix it read a step earlier.

Every run says what it cost. The last line of a run reads like 6 steps, 64k tokens, about $0.29, and the Usage page has an agent section with the same numbers per session. Thinking tokens are counted; nothing about the content of the run is stored.

skillsagentgmailcalendar

Skills: eleven published routines, Run from the dashboard, fork your own

Skills are published routines for the tools you already connected: a morning brief across every mailbox and calendar, inbox triage, a week-ahead, filing recurring attachments into Drive, a Confluence retro into Jira tickets, and six more. Eleven so far, at /skills, the morning brief first.

Run from the dashboard. Every skill page and every card on the dashboard's Skills page has a Run button. It opens the agent with the skill loaded and starts the run on the accounts you have connected; a multi-account skill covers every account of that service and never asks which.

Copy into Claude. Each skill is the actual file. Paste it into Claude and it runs the same way through the gateway.

Fork and edit. Fork a published skill, change the steps, keep your own copy. Free on every plan.

What changed under the hood to make a long run finish: a skill run sees only the tools it declares, so its cached prefix is about a fifth of what it was; runs think at a lower effort than chat; the stream stays alive while the model thinks; and at 85 percent of the run budget the run is told to write its report. A seven-account morning brief that used to stop at the size limit now completes in about three minutes.

The write-up, with one real run and its numbers: Skills are live.

gmailgws-mcpskills

Label a batch in one call

gmail_label_message now leads with the batch form. Pass message_ids (up to 1,000) with add_labels and remove_labels and every message is modified by one request, so an agent no longer works through a triage pile one message at a time. The label-and-mark-read pair is a single call: add_labels set to the label id, remove_labels set to ["UNREAD"].

The result now lists every id with its own outcome. When Gmail refuses the batch request, each id is retried on its own and reported, so a partial batch is visible instead of an all-or-nothing error.

The inbox-triage and morning-brief skills say the batch form explicitly.

agentgateway

The agent now uses the same MCP you do

The agent in your dashboard used to connect straight to the connector servers behind the gateway. It had every connector tool that way, and none of the gateway's own, which is why it could run a Gmail search for you but could not answer "which accounts am I connected to". The one question it was most often asked about itself was the one question it had no tool for.

It is now a client of our MCP, the same surface your desktop client talks to. Concretely:

It can tell you what you have connected. Ask it, and it checks, the same way any other client would.

It can hand you your MCP config. Ask for it in the thread instead of going to find the setup page.

What it can do and what your own client can do no longer drift. There is one tool surface and both of you are looking at it. A tool that appears for one appears for the other, on the same day, because it is the same list.

The tool cards in the thread say what happened rather than which function ran: "Checking your connected accounts" instead of a snake_case id. Connector calls keep their literal tool names, deliberately, because someone auditing what the agent touched in their mailbox wants the exact name.

Nothing changes about how you connect, what the agent is allowed to do, or which calls ask you for approval first.

usagesheetsgateway

Google Workspace errors survive redaction, and one lookup stopped asking permission

A failed Google Workspace call now shows you the real error. Open a tool in your dashboard's usage view and each failed call carries a message. For a long time almost every one of those read [redacted-content], which told you a call failed and nothing else.

The cause was our redaction rule, not the errors. It treated any quoted string over 40 characters as your content, and a JSON error envelope quotes everything. So a Google message saying replacement text parameter is required but not specified was destroyed for being long. Every diagnostic worth reading was over the limit by construction.

Redaction is now by field rather than by shape. A recognised error envelope is parsed and rebuilt from an allowlist of diagnostic fields, so the code, the message and the reason survive. Everything kept is still scrubbed by the old rules, so an email address, a long file id, or a run of your document text quoted inside a diagnostic still gets redacted. Fields we do not recognise are dropped rather than passed through, and anything that does not parse takes the old blanket path unchanged. Ambiguity still resolves to "this is content".

The honest limit: only Google's envelope shape is recognised. Jira and Confluence return errors in a different shape, and some of our own messages are plain prose rather than an envelope at all. Both still take the blanket path, so a failed Atlassian call can still read [redacted-content] in your usage log.

We are not going to fix that by teaching the parser one more shape, and then the next one. The redaction rule exists to keep your content out of a third-party analytics tool, which is a real constraint that is not going anywhere. It was never a reason to censor the copy we store for you and show back to you, in a table only you can see, quoting an error you already received in full at the time of the call. So the stored copy is going to stop being redacted at all. That fixes Atlassian, our own messages, and every connector we add later, in one change.

sheets_find_rows no longer asks for approval in the agent. It searches a range and returns matching row numbers, and it changes nothing, so the prompt was never a judgement anyone made: the classifier fails closed on any tool it has not been told is a read, and this one had not been reviewed yet. sheets_update, sheets_format_range, sheets_format_table and sheets_batch_update still ask, and a tool the classifier does not recognise still asks.

docssheetsgws-mcp

Read part of a long document, and clearer errors in Sheets and Docs

Three changes, all of them prompted by real calls that failed.

docs_get can now read part of a document. Pass start_index and end_index and you get that slice back. They are the same character indices mode: "index" reports and docs_batch_update consumes, so a read and the edit that follows it speak one coordinate system rather than two.

A ranged response also tells you where you are: totalEndIndex for the document's full length, clipped for whether there is more, and nextStartIndex to continue from. That matters more than the range itself. Without it, a few thousand characters coming back looks identical whether the document ended or the answer was cut off, and those two need opposite next steps. With no range given, nothing changes and you get the whole document as before.

docs_batch_update now shows what a request looks like. The description carries worked examples for the common shapes, replaceAllText among them, including the detail that matchCase belongs inside containsText and not at the top level. That nesting is easy to get wrong and the API only tells you afterwards.

sheets_find_rows answers a bad tab name with the real ones. Ask for a range naming a tab that does not exist and instead of a raw parse error you get told there is no tab of that name, followed by the tabs the spreadsheet actually has. One round trip instead of a guess. The examples in the range parameter no longer name a tab that most spreadsheets do not have, which is where some of those wrong guesses were coming from in the first place.

drivegws-mcp

Rename and copy files in Drive

Drive could search, read and create folders. It could not rename anything, and it could not copy anything. Two tools close that.

drive_rename_file renames a file or folder. The name changes and nothing else does: content, location and sharing are untouched. It works on any Drive item the account can edit, Docs and Sheets and Slides and folders alike.

drive_copy_file copies a file and names the copy in the same call, optionally placing it in a different folder with parent_id.

The copy is the more useful of the two, and the reason is templates. Ask Claude to rebuild a template and you get something that looks close and drifts a little every time. Ask it to copy one and you get the original's tabs, formatting and formulas exactly, because it is the same file. Copy first, then fill in the copy.

One limit worth stating plainly: folders cannot be copied. Drive answers a folder copy with a 403 saying the file cannot be copied by the user, which reads like a permissions problem you should retry. It is not. It is how the API works, and no amount of access changes it.

gmailemailtools

Claude can send properly formatted email now

Until today, every email sent through DataToRAG went out as plain text. If you asked Claude for a formatted summary with links, the recipient got the HTML as visible tags.

gmail_send, gmail_create_draft and gmail_update_draft now take an html_body. The message goes out as multipart/alternative with a plain-text fallback, so clients that render HTML show your formatting and clients that do not still get something readable. Pass body as well and that becomes the fallback part; leave it out and we derive one from the HTML.

gmail_reply and gmail_forward take html_body too, and behave differently in one way worth knowing. They send single-part text/html with no plain-text alternative, because those paths hand quoting and threading to a composer that builds the whole message. Same parameter, same result in a normal mail client, but no fallback part. We would rather tell you that than have you find it.

One smaller fix came with it: gmail_forward now accepts a body. It never did. You could forward a message but not say anything above it.

Nothing changes if you were already sending plain text. html_body is optional everywhere and no existing call behaves differently.

sheetsformattingtools

Sheets Claude writes now look like someone made them

Writing values into a spreadsheet gives you no formatting at all. The default is columns 100 pixels wide with every long cell clipped to a slit, so a sheet with entirely correct data is routinely unreadable, and the reader never learns there was more text.

Four tools fix that, and they are live now.

sheets_format_table does the whole readable pass in one call: column widths, wrapped and top-aligned cells, a styled and frozen header row, hairline borders. This is the one to run on any sheet a person is going to open.

sheets_format_range is for specific styling on top: fonts, colours, alignment, padding, number formats, merges. It takes a list of instructions and applies them in one atomic call, so a whole formatting pass is one call rather than one per range.

sheets_batch_update is the escape hatch beneath both, for anything they do not cover: borders, banding, copy and paste, inserting or deleting columns, duplicating sheets.

sheets_find_rows is the one that saves the most work and is easiest to miss. It finds rows by value and returns their row numbers, so you can update them directly instead of reading a whole sheet and filtering it yourself. It searches many values in one call, so looking up twenty customers is one call and not twenty, and values that matched nothing come back listed separately, so an empty result cannot be mistaken for a broken one.

Nothing changes for existing calls. All four are additions.

connectionsoauthonboardingbugfix

Connecting Google now actually connects

If you connected Google and then found that nothing worked, this is why, and it was our fault rather than yours.

Google's consent screen brings the service checkboxes up unticked. You had just signed in, where clicking Continue was correct and sufficient, so clicking Continue again was the natural thing to do. It granted us nothing. And we recorded that as a successful connection, so your dashboard said Google was connected while every tool call failed.

Two changes.

We now tell you what is coming before we hand you to Google. A short page explains that the boxes come unticked and that "Select all" is the one control that matters. It sits on the connect route itself, so every path to connecting gets it: the dashboard, the connections page, the agent's inline prompt, links from the docs.

A consent that grants no services is now refused rather than recorded. If you continue without ticking anything, we do not write a connection at all. You land back with a clear message and a retry, instead of a dashboard that claims you are connected and a set of tools that quietly refuse.

A connection that granted only some services is unaffected and still works for what you did grant. The change is specific to grants that cover nothing, which we can now tell apart from a grant we simply could not read.

connectionsmulti-accountoauth

Choose which account your tool calls run as

If you have connected more than one Google account, one of them is the default: the account a tool call runs as when you do not name one. Until now you could see which one it was and nothing more.

You can now change it. Each connected account carries a control to make it the default, on both the connections overview and the per-service page. It asks you to confirm first, because the default decides the identity every unqualified call acts as, writes included, and a silent switch is not something you should discover from a file appearing in the wrong Drive.

When the current default cannot serve anything and another account can, we say so. One line names the account that would work, with the switch beside it. It never suggests moving away from a default that grants at least one service, since that may be exactly what you intended.

Two smaller honesty fixes came with it. A permission refusal now links straight to the service page that offers the fix, instead of a page that redirects somewhere else. And an account connected before we started recording permissions now says its grant predates recording, rather than claiming every service was granted.

connectionsmulti-accountoauthbugfix

Reconnecting with the right permissions now works

A bug worth describing plainly, because if you hit it, nothing you did would have fixed it.

When you connect more than one Google account, one of them is the default: the account a tool call runs as when you do not name one. The first account you ever connected became the default and nothing ever moved it. So if that first account granted no services, every call failed, and connecting a second account with full permissions did not help. The calls still ran as the first one.

The failure was silent and permanent, and it was worse than it sounds: our own error message told you to grant the missing permissions, and doing exactly that changed nothing.

Fixed. A default account whose grant covers no services now yields to one that works. A default that grants at least one service is never touched, because that may be a deliberate choice on a multi-account setup, and moving it would be its own bug.

Scope errors also now name the account that can serve the call, so a refusal points somewhere instead of repeating itself.

connectionsoauthscopes

See what each connected account actually granted

Connecting a Google account and granting it access to your Google services are two different things, and until now the product treated them as one. If you clicked through the consent screen without ticking the service boxes, we said "Connected" and then failed every call.

Two changes, and the second is the one that matters.

The connections page now shows what each account actually granted, service by service, rather than a single Connected badge. A connection is shown as complete, partial, or identity-only, so "Connected" now means connected.

A failed call tells you which service was missing. Instead of a bare 403, a tool that needs a scope you did not grant now says so by name, for example Gmail not granted, and the connection state above tells you where to fix it.

If you connected an account weeks ago and have been wondering why a tool kept refusing, open your connections page. The answer is probably on it now.

site

FAQ page

Frequently asked questions now have a home: the FAQ. It covers getting set up (including why connecting an account comes before copying your config), what the gateway can and can't do, safety topics like the approval gate on writes and Google's verification of the app, and account basics. Answers link into the docs and blog wherever there's a longer story.

jiraatlassian-mcp

jira_search returns full issue rows

jira_search results now carry the fields a search is usually after: each row includes the issue key, summary, status, priority, and assignee, plus a browsable /browse/ URL that opens the issue in Jira. Enough to report results, and link them, straight from the search response.

gmailgws-mcp

Gmail labels

Your assistant can now manage Gmail labels, not just search by them. gmail_create_label creates a label (nest with / in the name, like Alerts/Invoices) and returns it, including its ID. gmail_list_labels lists every label on the account, system and user-created alike, with ID, name, and type; those IDs are what gmail_label_message, gmail_update_label, and gmail_delete_label take. gmail_update_label renames a label or changes its visibility, by ID rather than name, and a rename keeps the label on messages that already carry it. gmail_delete_label deletes a label by ID and removes it from every message carrying it; the messages themselves are untouched, and system labels (INBOX, UNREAD, SENT) cannot be deleted.

The workhorse is gmail_label_message: add or remove labels on one message or several in a single call. Since Gmail treats inbox state as labels, this is also how you archive (remove INBOX) and mark read (remove UNREAD).

sheetsgws-mcp

Sheets values starting with = are stored as text

When your assistant writes to a spreadsheet, a value beginning with = is now stored as text, never run as a formula. A cell written as =SUM(A1:A10) holds that string; nothing evaluates. Other values keep Sheets' usual interpretation, so a numeric-looking string like 007 is still stored as the number 7.

If you want a live formula in a cell, enter it in the Sheets editor, where it evaluates as always.

sheetsgws-mcp

Sheets tab lifecycle

Tabs are now first-class. sheets_add_tab adds a tab to an existing spreadsheet, with a title and an optional header row. sheets_rename_tab renames a tab by its current title and leaves the data untouched; saved ranges that name the old title stop resolving. sheets_clear clears the values in a range while the tab and its formatting stay; pass a bare tab name to clear the whole tab. sheets_delete_tab deletes a tab and every row in it, and cannot be undone through the API, so when "empty, but keep the tab" is what you mean, sheets_clear is the non-destructive alternative.

siteskills

Skills page

There's a new Skills page. Each entry is a working agent skill you can copy into Claude: triage your inbox, see the week ahead across every calendar, keep a knowledge base in a Google Sheet, turn a retro page into Jira tickets. They're the actual files we run, not descriptions of what's possible. Paste one into Claude, connect your account, and it runs against your own data through the gateway. Browse the full grid, or start from a persona that matches how you work.

calendargws-mcp

Compact calendar_list_events

calendar_list_events now returns a compact view by default: per event you get the id, title, times, location, a plain-text description (HTML stripped and truncated, tune with max_description_chars), the organizer, an attendee count plus your own response status, and the video join link (Meet, or Zoom and friends from conference data). Meetings with 10 or fewer people keep their full roster, so a 1:1 still tells you who it's with; bigger meetings collapse to the count. Recurring events are flagged and attachments come through. What's gone from the default payload: large-meeting rosters, reminders, and raw conference metadata.

Why: on a busy calendar, a 7-day pull was returning ~55 KB for 25 events (mostly HTML meeting boilerplate and 100+ attendee objects) and overflowing the tool response limit before your assistant saw a single event. The compact view is roughly 85% smaller on the same calendar.

Need the raw Calendar API payload? Pass full: true. calendar_get_event also converts descriptions to plain text now, with the same full opt-out for the original HTML.

dashboardgateway

Playground runs and a rebuilt setup wizard

The dashboard now has a Playground. Example prompts don't just sit there anymore: hit Run and a Claude-powered agent executes them against your connected Google Workspace and Atlassian accounts, choosing tools and streaming results live. It's a demo surface for trying the connectors before you wire up your own client, with about 20 free runs per account. Every response gets a thumbs up/down so you can tell us what worked and what didn't.

The client setup wizard is rebuilt too, with step-by-step flows for Claude web, Claude Desktop, Claude Code, Cursor, and ChatGPT. A live status check flips to green when your first tool call comes through, so you know the connection works before you close the tab.

gmailgws-mcp

Batch mark-read

gmail_mark_read now accepts message_ids (up to 1,000) to change labels on a whole batch in one call, using the Gmail batchModify API. The single-message path is unchanged. Small quality-of-life fix in the same release: gws_run documentation now spells out dotted API resource paths (users.drafts, not drafts).

gmailgws-mcp

Leaner Gmail reads and search results

gmail_read gains a text_only mode: flattened from/to/cc/subject/date headers, the decoded plain-text body, and attachment metadata instead of the raw MIME payload. On a typical marketing email that is about 2% of the full response size. max_body_chars truncates long bodies with a marker. Default behavior is unchanged.

gmail_search and gmail_list results are now flattened to {id, threadId, from, to, subject, date, snippet, labelIds}. This also fixes a bug where search and list results were missing From/Subject headers entirely.

gmailgws-mcp

Gmail drafts: full lifecycle

Two new tools, gmail_send_draft and gmail_delete_draft, complete the draft lifecycle. Together with gmail_create_draft and gmail_update_draft (shipped earlier), your assistant can now create a draft, revise it across turns, and send or discard it when you give the word. The human-in-the-loop flow this enables: AI writes, you review in Gmail, AI sends.

gmailgws-mcpbreaking

Removed: gmail_triage

The experimental gmail_triage tool is removed. Its job is better done by composing gmail_search, gmail_read (now with text_only), and gmail_mark_read directly.

gmailgws-mcp

gmail_mark_read

New gmail_mark_read tool for label modification: mark messages read, and add or remove labels in the same call. Marking read always removes the UNREAD label regardless of other labels you add.

docsgws-mcp

docs_get returns inline image metadata

docs_get responses now include metadata for inline images embedded in a document, so assistants can see where images sit in the content flow instead of silently skipping them.