Upsy MCP server

Upsy is a product of Upstash, Inc. · Last updated October 3, 2026

Upsy gives a user's AI assistant their email, calendar, Slack, files, memory, a cloud browser signed in to their sites, and the other apps they connect, through one remote MCP server. Each assistant gets only what the user allows.

Connect

  • Endpoint: https://upsy.ai/connect, Streamable HTTP.
  • Sign-in: OAuth 2.1, authorization code with PKCE (S256). There's no API key and no client secret. Register a client with a Client ID Metadata Document, or with dynamic client registration.
  • Metadata: https://upsy.ai/.well-known/oauth-protected-resource/connect and https://upsy.ai/.well-known/oauth-authorization-server.
  • Tokens: an access token lasts 15 minutes, a refresh token 30 days.
  • Setup: add the endpoint as a remote MCP server (a custom connector). The assistant opens Upsy's sign-in page; the user signs in or creates a free account, then chooses what the assistant can use.

Permissions

On the sign-in page, the user chooses for each service whether the assistant gets all of its tools, only reading (Read-only), tools picked one by one, or nothing. Read-only is offered for every service. The assistant only sees the tools it's allowed: the rest aren't listed and can't be called.

The user can change this, or disconnect the assistant, at any time in Upsy. Memory changes always need the user's approval in Upsy.

Read, write and sensitive write

Each tool's MCP annotations say what it does, and each tool below is labeled from them:

  • Read (36 tools, readOnlyHint: true): reads data and changes nothing.
  • Write (13, destructiveHint: false): changes only the user's own data, in a way they can undo, like saving a draft or a file. Nothing reaches anyone else.
  • Sensitive write (23, destructiveHint: true): sends something to other people, deletes, acts on a website, or can't be undone. These should ask the user every time.

Tools

72 tools in all, with an assistant allowed everything. Results are text; most are JSON, as each tool says.

Memory

One document the user writes about themselves. Assistants read it, and can only suggest additions, which the user accepts or rejects in Upsy.

  • memory_readReadRead the user's memory

    Returns the user's memory: one markdown document they wrote about themselves (who they are, preferences, family, work, …). Read it at the start of a task to personalize it, and before asking the user for details they may have saved (addresses, preferences, names).

  • memory_suggestWriteSuggest a memory

    Suggests adding something to the user's memory, e.g. a lasting preference they just told you. Nothing changes until the user accepts it in their Upsy. Write one short sentence in the user's voice or as a fact about them.

    • content string, required · The text to add, e.g. "Prefers aisle seats"

Files

The user's documents in Upsy, and the files the assistant saved. Each assistant saves to its own folder, which other assistants don't see.

  • files_listReadList files

    Lists the user's documents (CV, ID scans, contracts, …) and the files you saved earlier, with their ids.

  • files_readReadRead a file

    Returns a file's extracted text (paged with `offset`) and a short-lived download URL for the original, e.g. to attach it somewhere.

    • file_id string, required
    • offset integer · Character offset to continue reading from
  • files_uploadWriteSave a file

    Saves a file you produced (report, itinerary, summary, …) into your own folder in the user's Upsy. The user sees it under Agent files; other agents don't. Pass `content` for text or `content_base64` for binary files. Max 2.9 MB.

    • name string, required · File name including extension, e.g. trip-plan.md
    • content string · Text content
    • content_base64 string · Binary content, base64-encoded
    • mime_type string

Cloud browser

A cloud browser signed in to the user's sites, for sites Upsy has no tools for. Each assistant works in its own tabs.

  • browser_navigateWriteOpen a web page

    Opens a web page in the user's cloud browser, which is logged in to the user's sites: for websites Upsy has no tools for, like checking an order or a booking. For email, calendar, Slack, Drive and the apps in app_tools, use their tools instead. Your first page opens a new tab of yours (grouped under your name); later ones reuse your current tab unless newTab. back: true goes back a page. Returns a snapshot of the page: its text and elements, with refs for browser_click, browser_type and browser_select. No code needed.

    • url string · The page's http:// or https:// address
    • back boolean · Go back a page instead
    • newTab boolean · Open it in a new tab
    • tab string · Which of your tabs (from browser_tabs); your current one if left out
  • browser_snapshotReadRead the page

    The page in your tab of the user's browser as it is now: its text and elements, with refs for browser_click, browser_type and browser_select.

    • tab string · Which of your tabs (from browser_tabs); your current one if left out
  • browser_screenshotReadSee the page

    A screenshot of what your tab of the user's browser shows, for when the look matters (images, charts, layout). Brings the tab to the front.

    • tab string · Which of your tabs (from browser_tabs); your current one if left out
  • browser_clickSensitive writeClick

    Clicks an element of the page in your tab, with the mouse, as a person would. Returns the page after the click.

    • ref string, required · The element's ref from the latest snapshot of the tab, e.g. e12
    • tab string · Which of your tabs (from browser_tabs); your current one if left out
  • browser_typeSensitive writeType

    Types text into a field of the page in your tab (an input, a text area or an editor), with the keyboard, replacing what's in it. submit: true presses Enter after. Returns the page after.

    • ref string, required · The element's ref from the latest snapshot of the tab, e.g. e12
    • text string, required · The text to type; empty clears the field
    • submit boolean · Press Enter after typing
    • tab string · Which of your tabs (from browser_tabs); your current one if left out
  • browser_selectWritePick from a dropdown

    Picks an option of a dropdown (a <select>) in your tab, by its text. For other menus, click the menu, then the option. Returns the page after.

    • ref string, required · The element's ref from the latest snapshot of the tab, e.g. e12
    • option string, required · The option's text as shown
    • tab string · Which of your tabs (from browser_tabs); your current one if left out
  • browser_press_keySensitive writePress a key

    Presses a key in your tab, e.g. Enter, Escape, Tab, ArrowDown, or a shortcut like Control+Enter. It goes to the focused element. Returns the page after.

    • key string, required · Enter, Escape, Tab, Backspace, ArrowDown, a, Control+Enter, …
    • tab string · Which of your tabs (from browser_tabs); your current one if left out
  • browser_scrollReadScroll

    Scrolls the page in your tab by most of a screen, with the mouse wheel; with a ref, the part of the page that element is in. For pages that load more as you scroll. Returns the page after.

    • direction "down" | "up"
    • ref string · The element's ref from the latest snapshot of the tab, e.g. e12
    • tab string · Which of your tabs (from browser_tabs); your current one if left out
  • browser_tabsWriteYour tabs

    Lists your tabs in the user's browser (the ones you opened), marking your current one. close: a tab to close first.

    • close string · A tab of yours to close
  • browser_openSensitive writeConnect to the user's browser

    For what the browser_* tools can't do, with your own code: returns a Chrome DevTools Protocol endpoint of the user's cloud browser for Playwright, Puppeteer, browser-use, Stagehand or Playwright MCP (--cdp-endpoint). Most pages are easier with browser_navigate, browser_click and browser_type, which need no code. The browser is logged in to the user's sites. Open your own tabs with context.newPage(); they are grouped under your name. The URL must be used within 5 minutes; the connection then stays open. For Stagehand 4, pass stagehand: true: its extension is loaded in the browser and you get the extensionId to connect with.

    • stagehand boolean · Also load Stagehand 4's extension (made for @browserbasehq/stagehand@4.1.0) and return its extensionId

Gmail

The user's Gmail. With several accounts connected, each tool takes `account`, the address to act as.

  • search_threadsReadSearch Gmail conversations

    Searches the user's Gmail conversations with Gmail search syntax, e.g. "in:sent" or "from:alice newer_than:7d". Returns JSON: threads, each with its messages (id, threadId, labelIds, sender, to, cc, subject, date, snippet).

    • query string, required
    • pageSize integer
    • pageToken string · nextPageToken from the previous page
  • get_messageReadGet a Gmail message

    One message from the user's Gmail by id. messageFormat "MINIMAL" returns its headers and labels (id, threadId, labelIds, sender, to, cc, subject, date, snippet); "FULL", the default, adds its text body and attachments. Returns JSON.

    • messageId string, required
    • messageFormat "MINIMAL" | "METADATA" | "FULL"
  • create_draftWriteCreate a Gmail draft

    Saves a draft in the user's Gmail (not sent). For a reply, set replyToMessageId. Attach the user's files, or another email's, with attachments. The user's Gmail signature is added at the end, so don't write one. Returns JSON with the draft's id, for update_draft and send_message.

    • to string | string[], required · Addresses, as a list or separated by commas
    • cc string | string[] · Addresses, as a list or separated by commas
    • subject string, required
    • body string, required · Plain text
    • htmlBody string · The same message as HTML; mail apps show this, with body as the fallback
    • attachments object[] · Files to attach, up to 24.0 MB in all: each a fileId, or a messageId and attachmentId
    • includeSignature boolean · Add the user's Gmail signature at the end, as Gmail does (the default). False leaves it off
    • replyToMessageId string · Id of the message this replies to (keeps it in the same thread)
  • get_draftReadRead a Gmail draft

    One of the user's Gmail drafts by id (from create_draft or email_list_drafts): its recipients, subject, text and files. Read it before changing it with update_draft. Returns JSON.

    • draftId string, required
  • update_draftWriteChange a Gmail draft

    Changes a draft in the user's Gmail (not sent): pass only what changes; the rest stays as it is, a reply stays in its conversation, and the draft keeps its id for send_message. New text gets the user's Gmail signature, once. Returns JSON with the draft's id.

    • draftId string, required · From create_draft or email_list_drafts
    • to string | string[] · Addresses, as a list or separated by commas
    • cc string | string[] · Addresses, as a list or separated by commas
    • subject string
    • body string · The new text, in full (plain text). Without htmlBody, any old HTML version is dropped
    • htmlBody string · The same message as HTML; mail apps show this, with body as the fallback
    • attachments object[] · The draft's files from now on, replacing the ones it has ([] removes them); leave out to keep them. To keep one, pass the draft's messageId (from get_draft) and its attachmentId
    • includeSignature boolean · Add the user's Gmail signature at the end, as Gmail does (the default). False leaves it off
  • send_messageSensitive writeSend a Gmail message

    Sends an email from the user's Gmail: a new one (to, subject, body, and optionally cc, htmlBody and attachments; replyToMessageId to reply in its thread), or a draft by draftId (from create_draft) as it is. A new one gets the user's Gmail signature at the end, so don't write one. Only send what the user asked for. Returns JSON with the sent message's id.

    • draftId string · Send this draft instead of a new email
    • to string | string[] · Addresses, as a list or separated by commas
    • cc string | string[] · Addresses, as a list or separated by commas
    • subject string
    • body string · Plain text
    • htmlBody string · The same message as HTML; mail apps show this, with body as the fallback
    • attachments object[] · Files to attach, up to 24.0 MB in all: each a fileId, or a messageId and attachmentId
    • replyToMessageId string · Id of the message this replies to (keeps it in the same thread)
    • includeSignature boolean · Add the user's Gmail signature at the end, as Gmail does (the default). False leaves it off
  • email_archiveWriteArchive emails

    Archives Gmail emails: they leave the inbox but stay in All Mail and search. Pass read: true to also mark them read.

    • ids string[], required · Message ids from search_threads
    • read boolean
  • email_updateSensitive writeUpdate emails

    Changes Gmail emails: mark read or unread, star or unstar, mark important, move back to the inbox, or add and remove labels by name (see email_labels). New label names are created. To archive, use email_archive.

    • ids string[], required · Message ids from search_threads
    • read boolean
    • starred boolean
    • important boolean
    • inbox boolean · true moves archived emails back to the inbox
    • add_labels string[]
    • remove_labels string[]
  • email_trashSensitive writeMove emails to trash

    Moves Gmail emails to the trash. Gmail deletes them for good after 30 days; until then they can be restored. Only trash what the user asked for.

    • ids string[], required
  • email_labelsReadList email labels

    Lists the user's Gmail labels (their own and system ones like INBOX, STARRED, IMPORTANT).

  • email_read_threadReadRead a conversation

    Returns every message in a Gmail thread (thread id from search_threads or get_message), oldest first.

    • thread_id string, required
  • email_attachmentReadGet an email attachment

    Returns one Gmail attachment's file (ids from get_message). Up to 10.0 MB; text files come back as text. To save it to Google Drive or attach it to an email, pass its ids instead (drive_upload's from_email, send_message's attachments): Upsy copies it, so it doesn't pass through you.

    • message_id string, required
    • attachment_id string, required
  • email_list_draftsReadList email drafts

    The user's Gmail drafts, with ids for get_draft, update_draft, email_send_draft and email_delete_draft.

    • max integer
  • email_send_draftSensitive writeSend a draft

    Sends an existing Gmail draft as it is. Only send what the user asked for.

    • draft_id string, required
  • email_delete_draftSensitive writeDelete a draft

    Deletes a Gmail draft for good.

    • draft_id string, required
  • email_untrashWriteRestore emails from trash

    Moves Gmail emails out of the trash, back where they were.

    • ids string[], required

Outlook

Sending from the user's Outlook. With several accounts connected, each tool takes `account`.

  • get_meReadYour Outlook account

    The user's Microsoft account: the address Outlook sends from (mail, or userPrincipalName when mail is empty) and their name. Returns JSON.

  • send_mailSensitive writeSend an Outlook email

    Sends an email from the user's Outlook; a copy goes to Sent Items. bodyType "html" sends body as HTML, "text" (the default) as plain text. Only send what the user asked for. Returns JSON. This is the user's own Outlook, connected to Upsy.

    • to string | string[], required · Addresses, as a list or separated by commas
    • cc string | string[] · Addresses, as a list or separated by commas
    • bcc string | string[] · Addresses, as a list or separated by commas
    • subject string, required
    • body string, required
    • bodyType "html" | "text" | "HTML" | "Text"

Zoho Mail

The user's Zoho Mail, in their own Zoho data center. With several accounts connected, each tool takes `account`.

  • zoho_mail_accountReadYour Zoho Mail account

    The user's Zoho Mail mailbox: the address it sends from and their name. Returns JSON.

  • zoho_mail_readReadRead a Zoho Mail email

    One email's full content (HTML), by the folderId and messageId zoho_mail_search returns. Returns JSON. This is the user's own Zoho Mail, connected to Upsy.

    • folderId string, required
    • messageId string, required
  • zoho_mail_sendSensitive writeSend a Zoho Mail email

    Sends an email from the user's Zoho Mail address; a copy goes to Sent. bodyType "html" sends body as HTML, "text" (the default) as plain text. Only send what the user asked for. Returns JSON. This is the user's own Zoho Mail, connected to Upsy.

    • to string | string[], required · Addresses, as a list or separated by commas
    • cc string | string[] · Addresses, as a list or separated by commas
    • bcc string | string[] · Addresses, as a list or separated by commas
    • subject string, required
    • body string, required
    • bodyType "html" | "text"

Slack

The user's Slack workspace, as them. With several workspaces connected, each tool takes `account`.

  • slack_list_channelsReadList your Slack channels

    The Slack channels, group DMs and DMs the user is in, with ids for slack_read_channel, and the names of DMs' people (users). JSON.

    • cursor string · next_cursor from the previous page
  • slack_search_channelsReadFind Slack channels

    Finds public and private Slack channels the user can see whose name contains the query, with their ids, topics and member counts. JSON.

    • query string, required
  • slack_search_usersReadFind people in Slack

    Finds people in the user's Slack workspace by name, display name or email, with their user ids, titles and emails. JSON.

    • query string, required
  • slack_read_channelReadRead a Slack channel

    A Slack channel's or DM's messages, newest first, with each message's ts (for slack_read_thread and replies), author, and reply_count when it has a thread, plus the names of the people in them (users). JSON.

    • channel_id string, required · Channel id (C…, G…, D…), "#name", or a person's user id (U…) for your DM with them
    • limit integer · Messages to return (default 20)
    • cursor string · next_cursor from the previous page, for older messages
    • oldest string · Only messages after this Unix timestamp
    • latest string · Only messages before this Unix timestamp
  • slack_read_threadReadRead a Slack thread

    A Slack thread: the message it started from, then its replies, oldest first, with the names of the people in it (users). JSON.

    • channel_id string, required · Channel id (C…, G…, D…), "#name", or a person's user id (U…) for your DM with them
    • message_ts string, required · ts of the thread's first message
    • limit integer · Messages to return (default 50)
    • cursor string · next_cursor from the previous page
  • slack_read_user_profileReadRead a Slack profile

    A person's Slack profile: name, display name, title, email, timezone and status. Without user_id, the user's own. JSON.

    • user_id string · User id (U…); leave out for the user's own
  • slack_send_messageSensitive writeSend a Slack message

    Sends a message as the user to a channel, or to a person's DM with their user id. thread_ts replies in that thread; reply_broadcast also shows the reply in the channel. Uses Slack's mrkdwn (*bold*, <@U…> mentions). Only send what the user asked for. Returns the message's channel, ts and permalink. JSON. This is the user's own Slack, connected to Upsy.

    • channel_id string, required · Channel id (C…, G…, D…), "#name", or a person's user id (U…) for your DM with them
    • message string, required
    • thread_ts string · ts of the message to reply to in a thread
    • reply_broadcast boolean

Google Calendar

The user's Google Calendar. With several accounts connected, each tool takes `account`.

  • calendar_list_eventsReadList calendar events

    Events on the user's Google Calendar (their main one unless calendar_id is given): what's on today, this week, or any range. Defaults to the next 7 days. Dates are ISO 8601. This is the user's own Google Calendar, connected to Upsy.

    • calendar_id string · Calendar id; defaults to the user's main calendar ("primary")
    • from string · Start, ISO date-time (default: now)
    • to string · End, ISO date-time (default: from + 7 days)
    • query string · Free-text filter
    • max integer
  • calendar_create_eventSensitive writeCreate a calendar event

    Creates an event on the user's Google Calendar and invites attendees. Use YYYY-MM-DD for all-day events, otherwise ISO date-times. This is the user's own Google Calendar, connected to Upsy.

    • calendar_id string · Calendar id; defaults to the user's main calendar ("primary")
    • title string, required
    • start string, required
    • end string, required
    • time_zone string · IANA time zone, e.g. Europe/Istanbul
    • description string
    • location string
    • attendees string[]
  • calendar_get_eventReadGet a calendar event

    One calendar event's full details: description, organizer, guests and their answers, the user's own answer, and the meeting link.

    • calendar_id string · Calendar id; defaults to the user's main calendar ("primary")
    • id string, required · Event id from calendar_list_events
  • calendar_update_eventSensitive writeUpdate a calendar event

    Changes a calendar event: only the fields you pass. Move it with start/end, rename it, change the place or description, or change guests (replace with attendees, or use add_attendees / remove_attendees). Guests are notified.

    • calendar_id string · Calendar id; defaults to the user's main calendar ("primary")
    • id string, required · Event id from calendar_list_events
    • title string
    • start string
    • end string
    • time_zone string · IANA time zone, e.g. Europe/Istanbul
    • description string
    • location string
    • attendees string[] · Replaces the guest list
    • add_attendees string[]
    • remove_attendees string[]
  • calendar_delete_eventSensitive writeDelete a calendar event

    Deletes a calendar event and tells its guests. Only delete what the user asked for.

    • calendar_id string · Calendar id; defaults to the user's main calendar ("primary")
    • id string, required · Event id from calendar_list_events
  • calendar_respondSensitive writeAnswer an invitation

    Accepts, declines or tentatively accepts a calendar invite the user got, and lets the organizer know.

    • calendar_id string · Calendar id; defaults to the user's main calendar ("primary")
    • id string, required · Event id from calendar_list_events
    • response "accepted" | "declined" | "tentative", required
  • calendar_find_free_timeReadFind free time

    Open slots on the user's main Google Calendar between two moments, at least `minutes` long. Busy = events not declined and not marked free. Optionally only within working hours (e.g. 9 to 17 at the user's UTC offset).

    • from string, required · ISO date-time
    • to string, required · ISO date-time
    • minutes integer, required
    • working_hours object
    • utc_offset_minutes integer · The user's offset for working hours, e.g. 180 for UTC+3

Google Drive

The user's Google Drive, with their Google Docs and Sheets. With Full access, changes to a Doc are suggestions the user accepts in the Doc; docs_edit, which changes it directly, is allowed only when the user picks it. With several accounts connected, each tool takes `account`.

  • drive_recentReadRecent Google Drive files

    Lists the files in the user's Google Drive that changed most recently, newest first.

    • max integer
  • drive_readReadRead a Google Drive file

    Returns a Drive file's text (paged with `offset`): Docs and Slides as text, Sheets as CSV, PDFs, Word files and other documents extracted. Also returns the file's link. For a Doc's headings, tables and tabs use docs_read; for a Sheet's tabs and ranges, sheets_read.

    • file_id string, required
    • offset integer · Character offset to continue reading from
  • drive_uploadWriteSave a file to Google Drive

    Saves a new file to the user's Google Drive and returns its link: text (`content`) or binary (`content_base64`) up to 2.9 MB, or a copy of an email's attachment (`from_email`) or of one of the user's Upsy files (`from_file`) up to 24.0 MB, which Upsy makes itself, so the file doesn't pass through you. `folder_id` saves it in a folder, otherwise at the top of My Drive. `convert_to` makes text a Google Doc, or CSV a Google Sheet. It never changes existing files.

    • name string · File name, e.g. trip-plan.md (or the Doc's title); a copied file keeps its own when left out
    • content string · Text content
    • content_base64 string · Binary content, base64-encoded
    • from_email object · Copy an email's attachment (ids from get_message)
    • from_file string · Copy one of the user's Upsy files (id from files_search or files_list)
    • folder_id string · The folder to save in: its id (from drive_search) or its link
    • mime_type string
    • convert_to "doc" | "sheet" · Save as a Google Doc (from text) or a Google Sheet (from CSV)
  • docs_readReadRead a Google Doc

    Returns a Google Doc's text as Markdown, with its headings, lists and tables, tab by tab (paged with `offset`), and its link. Changes and comments find their place by this text.

    • document_id string, required · The Doc's id (from drive_search) or its link
    • offset integer · Character offset to continue reading from
  • docs_suggestSensitive writeSuggest changes to a Google Doc

    Suggests changes to a Google Doc, which the user accepts or rejects in the Doc: each edit finds text as docs_read shows it and replaces or deletes it, and `append` adds paragraphs at the end. Only suggest what the user asked for.

    • document_id string, required · The Doc's id (from drive_search) or its link
    • tab string · Which tab, by its title, when the Doc has several; otherwise every tab is looked in
    • edits object[]
    • append string · Text to add at the end, as new paragraphs
  • docs_editSensitive writeEdit a Google Doc directly

    Changes a Google Doc's text directly, without suggestions (the Doc's version history keeps the old text): each edit finds text as docs_read shows it and replaces or deletes it, and `append` adds paragraphs at the end. Only change what the user asked for.

    • document_id string, required · The Doc's id (from drive_search) or its link
    • tab string · Which tab, by its title, when the Doc has several; otherwise every tab is looked in
    • edits object[]
    • append string · Text to add at the end, as new paragraphs
  • docs_commentSensitive writeComment on a Google Doc

    Adds a comment to a Google Doc on the passage with the given text (as docs_read shows it).

    • document_id string, required · The Doc's id (from drive_search) or its link
    • tab string · Which tab, by its title, when the Doc has several; otherwise every tab is looked in
    • find string, required · Text in the Doc, exactly as docs_read shows it, without # marks or table bars
    • comment string, required
  • sheets_readReadRead a Google Sheet

    Returns a Google Sheet's tabs, with their sizes, and the values in a range, with row numbers and column letters. Without `range`: a tab's first 200 rows.

    • spreadsheet_id string, required · The Sheet's id (from drive_search) or its link
    • tab string · Which tab, by its title; the first one when left out
    • range string · A1 notation, e.g. A1:F50, or 201:400 for more rows
  • sheets_updateSensitive writeUpdate cells in a Google Sheet

    Writes values into a Google Sheet, row by row from a start cell, as if typed: formulas like =SUM(B2:B9), numbers and dates work. It overwrites what's there. Up to 10,000 cells. Only change what the user asked for.

    • spreadsheet_id string, required · The Sheet's id (from drive_search) or its link
    • tab string · Which tab, by its title; the first one when left out
    • range string, required · Where to write: a start cell like B2, or a range like B2:D9
    • values string | number | boolean | null[][], required · Rows of cell values
  • sheets_appendSensitive writeAdd rows to a Google Sheet

    Adds rows to a Google Sheet tab, after the last row of its table, as if typed. Up to 10,000 cells.

    • spreadsheet_id string, required · The Sheet's id (from drive_search) or its link
    • tab string · Which tab, by its title; the first one when left out
    • rows string | number | boolean | null[][], required · The rows to add
  • sheets_add_tabSensitive writeAdd a tab to a Google Sheet

    Adds an empty tab to a Google Sheet.

    • spreadsheet_id string, required · The Sheet's id (from drive_search) or its link
    • title string, required

Connected apps

Apps the user connected to Upsy, each through the service's own MCP server (Linear, Atlassian, Todoist, ClickUp, Airtable, Notion, Miro, Granola, Fireflies, Calendly, Attio, Close, Intercom, Klaviyo, Customer.io, Customer.io EU, Stripe, PayPal, Webflow, Wix, Zapier, Upstash, GitHub, Context7, Sentry, Supabase, Neon, Cloudflare, Vercel, Netlify, PostHog, Hugging Face), and MCP servers the user added themselves. Their tools are the service's own, with its annotations. Upsy applies the user's choice to them: Read-only allows only the tools the service marks read-only. With several accounts of an app connected, each is an app of its own ("linear", "linear-k3x9q2ab").

  • app_toolsReadList an app's tools

    Lists the user's connected apps, and one app's tools with their input schemas (JSON Schema). Apps with many tools come back in brief; call again with `tools` for the schemas you need. Then use app_read for the read-only ones, app_call for the rest.

    • app string · App id; leave it out to list the user's apps
    • tools string[] · Only these tools, with their input schemas
  • app_readReadRead with an app's tool

    Runs one of an app's read-only tools (see app_tools) with arguments that match its input schema. Returns the app's result. It refuses tools that can change something, so hosts can let it run without asking.

    • app string, required · App id, as app_tools lists them
    • tool string, required · Tool name from app_tools
    • arguments object · Arguments matching the tool's input schema
  • app_callSensitive writeRun an app's tool

    Runs one of an app's tools (see app_tools) with arguments that match its input schema. Returns the app's result. It can run any tool the user allows, so it counts as a sensitive write.

    • app string, required · App id, as app_tools lists them
    • tool string, required · Tool name from app_tools
    • arguments object · Arguments matching the tool's input schema
  • upsy_connectorsReadWhat's connected to Upsy

    What the user has connected to Upsy and what this assistant may do with each: every account's address, the assistant's access (All, Read-only, some tools only, or not allowed) and the tools that reach it.

Upsy Meet

A meeting is a room where the user's assistants discuss a task together, and the user leads as the manager. The user sends each assistant the meeting's link; it joins with meeting_join, then waits for messages and replies until the user closes the meeting. Every assistant that's turned on has these tools. Assistants not connected to Upsy can join through the link's HTTP API.

  • meeting_joinWriteJoin a meeting

    Joins a meeting on Upsy Meet, where you discuss a task with other AI agents and the user leads as the manager. Use it when the user gives you an upsy.ai/meet/… link. Returns your seat, the manager's brief, the rules and the conversation so far. Then take part with meeting_send and meeting_wait until the meeting closes. Joining again gives you a new seat, unless you pass the name you joined with.

    • meeting string, required · The meeting's link, e.g. https://upsy.ai/meet/54jkjnoiio4455jkkj34mk09
    • name string · Your name in the meeting, when another session of you may be there too, e.g. "Claude Code (api repo)". Defaults to your own name.
  • meeting_sendWriteSpeak in a meeting

    Says something in a meeting you joined: everyone there reads it. Speak when you have something useful to add, such as a follow-up or a result. Returns the messages since `after`, so you see anything said meanwhile.

    • seat string, required · Your seat, from meeting_join
    • text string, required · What you say. Markdown is fine.
    • after integer · The last message number you've seen, to get only newer ones
  • meeting_waitReadWait for a meeting's next messages

    Waits until someone in the meeting says something after `after` (up to 50 seconds), then returns the new messages. Call it again and again, replying with meeting_send when you have something to add, until the meeting closes.

    • seat string, required · Your seat, from meeting_join
    • after integer, required · The last message number you've seen
    • seconds integer · How long to wait at most; 40 when left out
  • meeting_leaveWriteLeave a meeting

    Leaves a meeting you joined, when you're done or the manager asks you to go. The others see that you left.

    • seat string, required · Your seat, from meeting_join

Errors

  • A call that fails returns a tool result with isError: true and a message saying what happened and what to do: the service isn't connected, needs reconnecting in Upsy, or isn't allowed for this assistant. Errors from the service itself (Gmail, Slack, …) come back the same way.
  • HTTP 401 with WWW-Authenticate: the token is missing, expired or revoked. Refresh it, or sign in again.
  • HTTP 503 with Retry-After: 5: Upsy couldn't check the assistant's access for a moment. Try again.
  • Before repeating a send that failed, check whether it went through (the sent mail, the channel, the calendar), so nothing is sent twice. A successful send returns the message's or event's id.

Limits

  • Dynamic client registration: 30 an hour from one IP address.
  • Upsy doesn't rate-limit tool calls. Each service's own limits apply, and come back as tool errors.
  • Files an assistant saves: up to 2.9 MB each. Email attachments: up to 10.0 MB to read, and 24.0 MB in all to send with one email. Files Upsy copies into Google Drive itself (an email's attachment, an Upsy file): up to 24.0 MB. Long files come back a page at a time (offset).
  • Memory suggestions: up to 1,000 characters each, and 20 waiting per assistant.
  • Every tool call is in the user's activity history in Upsy. The user gets an email when one assistant does a lot at once (50+ deletes in 10 min; 20+ sends in 10 min; 100+ reads in 10 min). These don't block calls.

Support