Provider REST API

Communication

Connect Claude to Zoom

Schedule and manage Zoom meetings, and read recordings, participants and users. Toolspoke puts 10 of its actions behind one MCP endpoint that Claude, Cursor, and Codex all speak.

Connection
Provider REST API
Authentication
Server-to-server OAuth
Actions exposed
10
Cost per call (typical)
1 credit
Adapter
Maintained by Toolspoke

Connected in three steps

  1. 1

    Install Zoom

    Open the marketplace in your workspace, add Zoom to the project your agents work in, and it appears on the gateway immediately.

  2. 2

    Connect the credential

    Authenticate with server-to-server oauth. Where to get one, and what it has to be able to reach, is the next section.

  3. 3

    Point your agent at the gateway

    Give your client one address, https://toolspoke.com/mcp. Claude Code takes it as a command, Claude and Claude Desktop add it as a custom connector, and Cursor, Codex and VS Code each read it from a config file of their own.

.mcp.json
{
  "mcpServers": {
    "toolspoke": {
      "type": "http",
      "url": "https://toolspoke.com/mcp"
    }
  }
}

One block covers every tool you have installed. Zoom shows up in the client as soon as your policy allows it, and so does everything else you install later.

Where the address goes, per client

Claude Code

Run it in your project, then /mcp to sign in

claude mcp add --transport http toolspoke https://toolspoke.com/mcp
Claude and Claude Desktop

Settings, then Connectors, then Add custom connector

https://toolspoke.com/mcp
Cursor

~/.cursor/mcp.json, or .cursor/mcp.json for one project

{ "mcpServers": { "toolspoke": { "url": "https://toolspoke.com/mcp" } } }
Codex

~/.codex/config.toml

[mcp_servers.toolspoke]
url = "https://toolspoke.com/mcp"
VS Code

.vscode/mcp.json, or the MCP: Add Server command

{ "servers": { "toolspoke": { "type": "http", "url": "https://toolspoke.com/mcp" } } }

What Zoom asks for

Server-to-server OAuth. You provide it once, when you install the connector. Toolspoke encrypts it at rest and decrypts it only for the length of a single call, and the gateway attaches it to the outbound request itself, so it is never part of the arguments an agent sends.

Account IDRequired
Zoom App Marketplace → Develop → Build App → Server-to-Server OAuth → your app → App Credentials. It names the Zoom account the token is minted for.
AbCdEfGhIjKlMnOpQrStUv
Client IDRequired
Shown beside the Account ID on the app's App Credentials page.
AbCdEfGhIjKlMnOpQrStUv
Client secretRequired
App Credentials → Client Secret. Add the scopes separately under the app's Scopes tab: user:read:admin covers the user reads, meeting:read:admin and meeting:write:admin the meetings, recording:read:admin the recordings.
Paste the secret value
Default host (email or user ID)Optional
Used whenever an action that acts on one person's meetings is called without an explicit user_id. A server-to-server app has no signed-in person, so the literal "me" does not work here - name a real user. list_users shows which ones the app can see.
[email protected]

What Claude can do in Zoom

10 actions, each one declared and named by the connector rather than discovered at runtime. A workspace policy grants a person all of them, a hand-picked selection, everything on the read side, everything on the write side, or none.

Reads
7Reads
Writes
2Writes
Destructive
1Destructive

Reads

7

Fetches data and changes nothing.

  • list_users

    List the users on the Zoom account, with each one's id, email, name, type and status. Call it first when you do not know which host to act on, and to find out whether the connection reaches anything at all - a failure here usually means the app is missing the user:read:admin scope rather than that the credentials are wrong. Only active users are returned unless status says otherwise. Page with next_page_token, which expires after fifteen minutes.

  • get_user

    Fetch one user's record: id, email, display name, licence type, personal meeting id, timezone and department. Use it to resolve an email address to the user id that the meeting operations take, or to confirm what licence a host has before scheduling something their plan does not allow.

  • list_meetings

    List one host's meetings. `type` decides which: scheduled (the default) returns unexpired past, live and upcoming scheduled meetings, live returns only what is running now, upcoming returns future meetings including live ones, and previous_meetings returns meetings whose end time has passed. Two limits are Zoom's rather than this connector's: instant meetings never appear here at all, and upcoming, upcoming_meetings and previous_meetings return at most six months of data. The `id` returned is what get_meeting, update_meeting and delete_meeting take.

  • get_meeting

    Fetch one meeting in full: topic, agenda, start time, duration, timezone, join URL, passcode, recurrence and every setting. IMPORTANT: a Zoom meeting id can be more than ten digits, so pass it as a string here - a numeric id truncated by a caller's own integer handling addresses a different meeting or none at all. Use occurrence_id to read a single occurrence of a recurring meeting.

  • list_recordings

    List one host's cloud recordings. IMPORTANT: the from/to window can span at most one month, and Zoom does not tell you when you ask for more - it silently answers with a shorter range. Leaving both out means today and tomorrow, not everything, which is the other half of the same surprise. Trashed recordings are a separate listing reached with trash, and Zoom ignores from and to entirely for those. Requires a Pro plan or higher and the recording:read:admin scope. The array comes back under `meetings`, each with its recording_files.

  • get_recording

    Fetch the recording files for one meeting: video, audio, chat, transcript and closed captions, each with its size, type and Zoom download URL. This connector returns the URLs and never downloads the media itself. `meeting_id` accepts a meeting id, which returns the latest instance, or a meeting UUID, which returns exactly that one - and a UUID that starts with a slash or contains a double slash must be double URL-encoded before it is passed here, which is Zoom's own requirement rather than this connector's. Set include_fields to download_access_token when the URLs need to be usable without a Zoom session, and ttl to say for how many seconds, up to 604800.

  • list_past_participants

    List who attended a meeting that has already finished, with each person's name, email, join and leave times and duration. `meeting_id` takes a meeting id, which reports on the latest instance, or a meeting UUID for one specific instance - and a UUID beginning with a slash or containing a double slash must be double URL-encoded, which is Zoom's own requirement. Requires a Pro plan or higher, and Zoom keeps this data for fifteen months. A meeting with only one participant is omitted entirely unless the account has the "Show one person meetings and webinars on Dashboard and Reports" setting enabled, which is the usual reason this comes back empty for a meeting that certainly happened.

Writes

2

Creates or updates something on the other side.

  • create_meeting

    Schedule a meeting for one host. Zoom rate-limits this to 100 meetings per day per host. `start_time` is either yyyy-MM-ddTHH:mm:ssZ in GMT, or yyyy-MM-ddTHH:mm:ss alongside a `timezone`. `type` defaults to 2, a plain scheduled meeting; pass 8 with the recurrence arguments for a recurring meeting at a fixed time, and note that Zoom rejects recurrence on any other type. Waiting room and join-before-host contradict each other - turning the waiting room on disables join-before-host, whatever this call says. Returns the meeting including its id, join URL and passcode.

  • update_meeting

    Change an existing meeting: retime it, rename it, rewrite the agenda or change its settings. Pass only what you want changed; everything omitted is left alone. A write rather than a destructive act - the change is as reversible as making it - but note that moving a meeting is visible to everyone holding the invitation. Zoom answers 204 with no body, so read the result back with get_meeting if you need to confirm it. Naming an occurrence_id restricts the edit to one instance of a recurring meeting, and Zoom then accepts only agenda, start_time, duration and a handful of settings.

Destructive

1

Deletes or permanently alters something. Worth granting on purpose.

  • delete_meeting

    Delete a meeting. There is no Zoom API that restores one: the join link stops working for everyone holding it, and any registration attached to it goes with it. That is why this is classified destructive and cannot be reached by a read-only or write grant. Both notification flags default to false, so nobody is mailed unless the caller asks - set cancel_meeting_reminder to notify registrants that the meeting is off, and schedule_for_reminder to notify the host and any alternative hosts. Pass occurrence_id to cancel a single occurrence rather than the whole series. Zoom answers 204 with no body.

What it will not do

Enforced by the gateway rather than left to convention, which is why each of these can be stated flatly.

It cannot call anything else
The 10 actions above are the whole of it. A call to any other name is refused before it reaches Zoom rather than forwarded on, and connecting your account does not add to the list: it is fixed by the connector, not discovered at run time.
It reaches no further than your credential
Toolspoke holds no access to Zoom of its own. Every call carries the credential you stored and nothing besides, so whatever that credential cannot reach, this connector cannot reach either.
It never hears from Zoom
Nothing is pushed to it. There is no webhook, no subscription and no polling, so this connector cannot notice by itself that something changed in Zoom. An agent has to ask.
It does not smooth over provider limits
Toolspoke does not retry, queue or back off around Zoom's own rate limits. A call that Zoom refuses comes back to the agent as a failed call.

Before you connect it

What can Claude do in Zoom?

10 named actions: 7 that only read, 2 that write and 1 that delete or permanently alter something. They include list_users, get_user and list_meetings. Nothing outside that list is reachable: the connector declares each operation by name rather than proxying whatever an agent asks for.

What credentials does the Zoom connector need?

Server-to-server OAuth. The connector asks for account id, client id and client secret, and optionally default host (email or user id). Values are encrypted at rest and attached to the outbound request by the gateway, so they are never part of the arguments an agent sends and never reach the audit log.

Does the Zoom connector work with Cursor and Codex, or only Claude?

Any client that speaks MCP, and every one of them gets the same 10 actions. There is a single address, https://toolspoke.com/mcp. Claude Code adds it with claude mcp add --transport http, Claude and Claude Desktop take it as a custom connector in settings, Cursor reads it from .cursor/mcp.json, Codex from ~/.codex/config.toml, and VS Code from .vscode/mcp.json. Each of them signs in to the gateway itself, so there is no key to paste.

What does the Zoom connector not do?

The 10 actions above are the whole of it. A call to any other name is refused before it reaches Zoom rather than forwarded on, and connecting your account does not add to the list: it is fixed by the connector, not discovered at run time. Toolspoke holds no access to Zoom of its own. Every call carries the credential you stored and nothing besides, so whatever that credential cannot reach, this connector cannot reach either. Nothing is pushed to it. There is no webhook, no subscription and no polling, so this connector cannot notice by itself that something changed in Zoom. An agent has to ask. Toolspoke does not retry, queue or back off around Zoom's own rate limits. A call that Zoom refuses comes back to the agent as a failed call.

Can I limit which actions an agent can call?

Yes, in two places. The project switches Zoom's actions on and off one at a time, for everyone in the project at once, and the screen groups them by read, write and destructive so turning off everything that deletes is one click. An individual agent key can then be narrowed further, to particular toolkits in a project and to particular actions in a toolkit. Whatever it was granted, a key never reaches a project its owner cannot.

What gets recorded when an agent calls Zoom?

Every attempt, with the agent that made it and the person that agent belongs to, the full request payload, the response payload, the status, the duration, and the credits spent. Values whose key names a secret are masked out before the record is shown to anyone. An operation the connector marks as not retained never has its response body written at all, so the gateway keeps no second copy of what was read.