BakedBrie docs

Recipe: connect Google Workspace

This recipe connects Google with the google_workspace preset, so a board can read a sheet, add a row, read your calendar, see busy times, add a calendar event with no guests, list Drive files and read YouTube numbers while it works. It uses your own Google Cloud app (its client id and client secret). Read Connect a service that signs in with OAuth first for how OAuth connections, limits, requests and receipts work, and Let your board use a service while it works for connections in general.

What this connection can never do:

  • No Gmail. It never asks for a Gmail scope, and BakedBrie refuses every Gmail path on every connection. To put approved emails in Gmail Drafts, use the Gmail draft destination in Draft invoice reminders in Gmail.
  • No invites. calendar_create_event sends sendUpdates=none and has no guests field, so the event has no one to email. Any other calendar event write is refused. Google's own page warns that "some emails might still be sent" with sendUpdates=none; with no guests on the event, there is no one to send them to.
  • No sharing. Drive sharing (adding a permission) makes Google email the new reader, so BakedBrie refuses it on every connection.
  • Nothing wider than you tick. The connection asks Google for exactly the scopes of the operations you choose, computed for you. A wider set is refused (CONNECTION_SCOPE_WIDER_THAN_OPERATIONS).

Before you run it

  1. In the Google Cloud console, pick or create a project and turn on the APIs for the operations you want: Google Sheets API, Google Calendar API, Google Drive API, YouTube Data API v3, YouTube Analytics API.
  2. Set up the OAuth consent screen. Choose the user type:
    • Internal (only people in your Google Workspace organization can sign in): no Google verification and no 7-day limit. Best for a company on Google Workspace.
    • External (any Google account, including personal Gmail): while the app's publishing status is Testing, refresh tokens expire after 7 days and at most 100 test users can sign in, so the connection asks you to "Sign in to Google again" every week. Once published but not verified, Google shows a warning screen at sign-in and caps the app at 100 users over its life, which is fine for one company. Sensitive scopes need Google's verification for an External app in production, and Restricted scopes also need a yearly security assessment.
  3. Create an OAuth client of type Web application and add this exact redirect URI (character for character; it is the same for every BakedBrie connection and destination):
   https://app.bakedbrie.com/settings/destinations/oauth/callback
  1. Add the scopes of the operations you will tick on the consent screen's Data Access page (the table below lists them). Google shows each scope's class there.
  2. Note the client id. Put the client secret in your own shell, for example export GOOGLE_CLIENT_SECRET=.... Never paste it into the chat.
  3. whoami must show connections and connections_oauth on.

Operations and scopes

Tick only what the board needs. The create form ticks the three reads marked "default"; writes and Restricted operations are never ticked for you. The scopes are computed from your ticks and shown under the checklist. Every scope below starts with https://www.googleapis.com/auth/.

OperationWhat it doesReads or writesScopeGoogle class
sheets_read_range (default)Up to 50 rows of one range, first 8 columnsreadspreadsheets.readonlySensitive
sheets_append_rowAdds one row of up to 5 values after the last row of a rangewritespreadsheetsSensitive
calendar_list_events (default)Up to 50 events on your main calendar between two dates (UTC): title, status, timesreadcalendar.events.owned.readonlynot stated in Google's docs
calendar_freebusy (default)Busy blocks on your main calendar between two dates, no detailsreadcalendar.freebusynot stated in Google's docs
calendar_create_eventAdds an event with no guests to your main calendar; nobody is invited or emailedwritecalendar.events.ownednot stated in Google's docs
drive_list_filesUp to 50 files this Google app created or a person opened with itreaddrive.fileNon-sensitive
drive_get_fileOne file's name, date and size, if this app can see itreaddrive.fileNon-sensitive
drive_list_files_allUp to 50 of all your Drive files: names, dates, sizesreaddrive.metadata.readonlyRestricted
drive_get_file_anyAny file's name, date and size by its idreaddrive.metadata.readonlyRestricted
youtube_channel_statsViews, subscribers and video count of your channelreadyoutube.readonlynot stated in Google's docs
youtube_video_statsViews, likes and comments of one videoreadyoutube.readonlynot stated in Google's docs
youtube_analytics_reportViews and likes per day for your channel, up to 50 daysreadyt-analytics.readonly and youtube.readonlynot stated in Google's docs

Notes:

  • Drive. drive.file is the default and Non-sensitive, but Google then shows only files this Google app created or a person opened with it. BakedBrie has no file picker, so these two operations usually find little until your app has been used with the files. The _all and _any variants see every file's name and date, but drive.metadata.readonly is Restricted: an External app in production needs Google's yearly security assessment (an Internal app does not). Neither reads file contents.
  • Sheets. Values are added with valueInputOption=RAW: Google stores them exactly as typed and never as formulas. BakedBrie also refuses a value that starts with =, +, - or @. A spreadsheet id and a range like Invoices!A1:E1 (a sheet name without spaces) are the inputs.
  • Calendar. Every operation uses your main (primary) calendar. Event times you send need a time zone offset, like 2026-10-01T09:00:00-04:00.
  • YouTube. Each Data API call uses 1 unit of your project's daily YouTube quota. Google now requires youtube.readonly for Analytics reports too, so youtube_analytics_report asks for both scopes.
  • Where Google's docs state no class, check the Data Access page in your Cloud console; it shows the class when you add the scope.

What the board sees, and the taint rule

Answers are provider data, shown to agents only as untrusted facts. Anything a person typed is free_text: sheet cells, event titles and file names. A run that read a non-empty free_text field can only read in the same round (CONNECTION_WRITE_TAINTED), so "read a sheet, then add a row" in one agent round needs a person, or a flow where the write comes first or follows a read of numbers only. Busy times and YouTube numbers never taint.

Writes (sheets_append_row, calendar_create_event) run within limits a person sets in the web app, and BakedBrie sends each at most once. Google documents no idempotency key for these calls, so if BakedBrie cannot tell whether Google accepted a write, it never sends it again by itself: check the sheet or calendar before a person chooses Send again.

The prompt

In BakedBrie, connect Google Workspace to the board "{{BOARD_NAME}}". Use only the BakedBrie MCP tools. Start with whoami and stop if connections or connections_oauth is off. First read /docs/recipes/connections-oauth and /docs/recipes/google-workspace with read_docs.

My Google OAuth client id is {{CLIENT_ID}}. The client secret is in my environment variable GOOGLE_CLIENT_SECRET. The operations I want: {{OPERATIONS, for example sheets_read_range, sheets_append_row}}.

1. Call manage_connection with action presets, preset google_workspace and operations [my operations]. Show me the computed scopes and each scope's class. Stop if any is Restricted and I did not ask for it.
2. Call prepare_secret with kind google, purpose connection and env_var GOOGLE_CLIENT_SECRET. Run the command it returns in my shell exactly as given, then use the drop_id. Never print the secret.
3. Create it: manage_connection action create, name "Google", preset google_workspace, operations [my operations], client_id {{CLIENT_ID}}, credential {"drop_id": "<the drop id>"}, and a new request_id.
4. Call manage_connection action connect_oauth. Give me oauth.consent_url: only a person can finish signing in. I open it in the browser where I am signed in to BakedBrie, approve at Google, and click Finish connecting. Then call oauth_status until the grant is connected, or tell me its error code.
5. Attach it: manage_board_connection action attach, handle google, the operations, the agents and stages that may use it, and when_to_use.
6. Stop and tell me: "Only a person can let a board use a connection. Open the limits link and set limits." Suggest $0.00 per call, reads 10 per card and 200 per month, writes 1 per card and 20 per month.

A schedule example: YouTube numbers into a sheet

Tick youtube_analytics_report and sheets_append_row. With schedules, make a Monday card "Add last week's YouTube views to the sheet". The maker reads youtube_analytics_report for the last 7 days (numbers only, so the round stays untainted) and then asks for one sheets_append_row with the week and the total views. The write needs a limit a person set, and it lands at the end of the range you name.

Sign-in facts to know

  • Access tokens last about an hour; BakedBrie refreshes them itself.
  • A refresh token unused for 6 months stops working.
  • Google keeps at most 100 refresh tokens per Google Account per OAuth client and silently drops the oldest, so signing in many times with one app can end an older sign-in.
  • A password change ends sign-ins that hold Gmail scopes. This connection holds none.
  • Adding or removing an operation changes the scopes, so the connection asks you to sign in again with exactly the new set. BakedBrie sends include_granted_scopes=false, so a new sign-in never inherits scopes an older one held.
  • Disconnecting revokes the sign-in at Google (https://oauth2.googleapis.com/revoke) and deletes BakedBrie's copy.
  • Provider events (Calendar and Drive push notifications) are not supported yet. Use a schedule.

Refusals you may see

CodeWhat it meansFix
CONNECTION_SCOPE_WIDER_THAN_OPERATIONSThe definition asks for a scope no ticked operation needs.Remove the scope, or tick the operation that needs it.
CONNECTION_EMAIL_ENDPOINT_REFUSEDA path reaches Gmail.Use the Gmail draft destination instead.
CONNECTION_MESSAGE_ENDPOINT_REFUSEDA calendar write with guests or without sendUpdates=none, or a Drive sharing call.Keep the preset's calendar_create_event as it is.
OAUTH_SCOPE_WIDER_THAN_REQUESTEDGoogle granted more than BakedBrie asked for.Sign in again; BakedBrie never accepts extra access.

View as Markdown