Announcing CIMD support for MCP Client registration
Learn more

Otter’s MCP Server or Otter API? Decide The Tool Calling Interface for Your Agent

Saif Ali Shaik
Founding Developer Advocate

TL;DR

  • Otter ships two official programmatic surfaces, and they are not interchangeable. The Model Context Protocol (MCP) server is read-only: search meetings, fetch a transcript, get the current user. The Public API adds channels, audio downloads, structured action items, insights, outlines, file ingestion, and webhooks.
  • The availability model is inverted from most tools. The MCP server connects from a standard Otter account over OAuth; the Public API is gated to Enterprise workspaces and authenticates with Bearer API keys only, no OAuth.
  • Only the API is event-driven. Otter webhooks push conversation and action-item events in real time; the MCP server is pull-only inside an active agent turn.
  • Both paths hand you one credential per user. MCP gives you an OAuth token; the API gives you a static Bearer key (a maximum of two per user, 10 requests per second). Neither gives you storage, rotation, or revocation.
  • Scalekit's Otter connector wraps the vendor MCP with OAuth 2.1, a token vault, per-user scoping, and agent audit logs, so the MCP-vs-API decision does not change your auth infrastructure.

Your agent needs to read what happened in a meeting. Otter.ai now offers two official ways in: a hosted MCP server and a Public API. They cover overlapping data but different capabilities, sit behind different auth, and carry different operational weight in production. One is read-only and connects from almost any account. The other is Enterprise-gated, key-based, and the only path that can push events. This article is the decision framework for which one your agent should build against, and how to wire either through Scalekit.

What Otter MCP and Otter API actually are

These are two distinct objects with different design intents. The MCP server exists to drop meeting context into an interactive AI client. The API exists to move meeting data into systems on a schedule or on an event.

Otter MCP: the hosted, read-only connector

Otter runs a provider-hosted MCP server at mcp.otter.ai/mcp. Access is OAuth-authenticated with per-meeting permissions, so an agent reads only meetings the user captured or had shared with them. The surface is deliberately small: three tools that search meetings, fetch a full transcript, and return the current user with get user info. There are no create, update, or delete tools; the server is read-only by design. Details are in Otter's MCP server documentation.

Otter API: the Enterprise, key-based surface

The Public API is a REST surface at api.otter.ai/v1, available to Enterprise workspaces only. It authenticates with a Bearer API key created in the workspace Developer settings, capped at two keys per user and 10 requests per second. It exposes channels and members, conversations (list, retrieve, and POST to ingest a file), audio download links, workspace details, and cursor-based pagination. It also ships webhooks. The full reference is in Otter's Public API documentation.

Comparing them where it matters for agents

The two paths diverge on four axes that decide production fit: what your agent can do, how it authenticates, what you operate, and which scenarios each one wins. Read the capability gap first; it drives the rest.

What your agent can actually do

The MCP server is strongest at retrieval-by-meaning: its search tool takes a semantic query plus filters for attendee, date range, folder, channel, and transcript keywords. The API has no semantic search endpoint; it lists and filters conversations, but it returns richer structured objects and can write.

Capability
Otter MCP
Otter API
Semantic meeting search
Yes
No (list and filter only)
Fetch full transcript
Yes
Yes (include=transcript)
AI summary
Yes
Yes (abstract_summary)
Structured action items
Limited (inside transcript text)
Yes (relationships.action_items)
Insights and outline
Limited
Yes (include=insights,outline)
List channels and members
No
Yes
Download audio (MP3)
No
Yes
Ingest a file (create conversation)
No
Yes (POST /conversations)
Workspace details
User profile only
Yes (GET /workspace)
Webhooks / real-time events
No
Yes
Write operations
No (read-only)
Yes (ingestion)

The gap is real in both directions. If your agent needs to answer "which calls mentioned pricing pushback," the MCP server does it in one call. If your agent needs the MP3, the per-meeting action items as data, or a push when a transcript is ready, only the API delivers that.

The auth path each one puts you on

This is where Otter departs from the usual pattern. The MCP server uses OAuth 2.1 with a browser consent step, minting a token scoped to what the user authorized. The API does not support OAuth at all; it uses a static Bearer key the user generates in the dashboard. There is no public API key for the MCP server, and no OAuth for the API. The choice picks your credential type.

For a multi-tenant B2B agent, the implication is identical on both paths. Every user carries their own Otter credential: an OAuth token on the MCP path, an API key on the API path. That is N credentials to store, refresh or rotate, and revoke, regardless of which surface you chose. The token type changes; the isolation requirement does not.

Dimension
Otter MCP
Otter API
Auth method
OAuth 2.1, browser consent
Bearer API key
Availability
Standard Otter account
Enterprise workspaces only
Credential per user
OAuth token
API key (max 2 per user)
Published rate limit
Not specified per tool
10 requests / second
Best fit
Interactive read and query
Headless pipelines and events

What you own in production

On the MCP path, the hosted server owns tool schemas, endpoint normalization, and transport. You still own the OAuth lifecycle: token storage, proactive refresh, revocation on offboarding, and tenant isolation across users. When Otter renames or reshapes a tool, your agent should discover the current surface at runtime rather than hardcode names.

On the API path you own more. You write and version the request layer, handle 429 backoff against the 10-per-second limit, page through cursors, manage two-key-per-user limits, and stand up a webhook receiver if you want real-time behavior. Nothing about the key rotates itself. The tradeoff is control: deterministic, auditable, event-driven pipelines that the read-only MCP server cannot express.

When to use MCP, when to use the API

The decision is rarely about preference; it follows the shape of the agent.

Use Otter MCP when:

  • You are building an interactive meeting assistant that answers questions over a user's own transcripts.
  • You want semantic search across meetings without writing filter logic.
  • Your users are on standard Otter plans, not only Enterprise.
  • Otter is one connector among several in a tool-calling agent, and you want a uniform OAuth model.

Use the Otter API when:

  • You need to react to events: sync a summary to a CRM the moment a transcript is ready, or push action items into a tracker.
  • You need audio files, structured action items and insights as data, or channel and workspace metadata.
  • You are ingesting external recordings into Otter through POST /conversations.
  • You are running a deterministic, high-volume pipeline inside an Enterprise workspace.

The credential problem that exists on both paths

The comparison table can make this look like a clean either-or. In production it is not, because the hard part is the same on both sides. Neither path is a credential manager.

One credential per user, on either path

An OAuth token and an API key are both just a credential handed to your agent. Neither Otter surface gives you a vault, a rotation schedule, or a revocation flow. In a single-user demo that is invisible. In a multi-tenant agent it is the whole problem: every user has their own Otter credential, and that is N secrets to store encrypted, refresh before expiry, isolate per tenant, and kill on offboarding. Get this wrong and one tenant's agent can reach another tenant's meetings.

Where Scalekit fits

This is the layer Scalekit's Otter connector owns: it runs the OAuth 2.1 flow, vaults and refreshes tokens, and scopes execution to a per-user connected account, so the MCP-vs-API decision does not change your auth infrastructure. For the deeper pattern, see single vs multi-tenant tool-calling agent auth.

Building an Otter agent with Scalekit

Scalekit's prebuilt Otter connector wraps the vendor MCP, so you get authenticated tool calls without writing schemas or handling tokens. The pattern is always the same order: resolve who the user is, retrieve the tools their connected account authorizes, then run the agent loop. The examples below use LangChain in TypeScript and the Claude SDK in Python.

Prerequisites: create the connection

In the Scalekit dashboard, go to AgentKit, Connections, Create Connection, and add otteraimcp. Copy SCALEKIT_ENV_URL, SCALEKIT_CLIENT_ID, and SCALEKIT_CLIENT_SECRET from Developers, API Credentials. The connection name you pass in code must match the dashboard name character for character; a mismatch is the most common cause of an empty tool list. Full setup is in the AgentKit quickstart.

Authorize and scope: TypeScript with LangChain

Before the loop runs, the user connects Otter once over OAuth, and the agent loads only the tools that connected account is authorized to call. It receives a scoped surface, not a flat catalog. The code below sends the user through consent, then binds the scoped Otter tools into a LangGraph agent.

import { ScalekitClient } from "@scalekit-sdk/node"; import { ChatAnthropic } from "@langchain/anthropic"; import { createReactAgent } from "@langchain/langgraph/prebuilt"; const sk = new ScalekitClient( process.env.SCALEKIT_ENV_URL!, process.env.SCALEKIT_CLIENT_ID!, process.env.SCALEKIT_CLIENT_SECRET!, ); const identifier = "user_123"; // resolved from your own session, never from the client // One-time per user: send them through OAuth to connect Otter const { link } = await sk.actions.getAuthorizationLink({ connectionName: "otteraimcp", identifier, }); console.log("Authorize Otter:", link); // After the user authorizes, retrieve only the tools this connected account can call const { tools } = await sk.tools.listScopedTools(identifier, { filter: { connectionNames: ["otteraimcp"] }, pageSize: 100, }); const agent = createReactAgent({ llm: new ChatAnthropic({ model: "claude-sonnet-4-6" }), tools, }); const result = await agent.invoke({ messages: [ { role: "user", content: "Find my Acme calls from last quarter and list every action item." }, ], }); console.log(result);

The agent loop: Python with the Claude SDK

The Python path uses the same connected account. list_scoped_tools returns Otter's tools in Anthropic's native format, so there is no schema writing. Each tool_use block is executed with the user's identifier, and Scalekit resolves the connected account, pulls the vaulted token, and calls Otter as that user. Credentials never touch the agent runtime.

import os import anthropic from scalekit.client import ScalekitClient sk = ScalekitClient( env_url=os.getenv("SCALEKIT_ENV_URL"), client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), ) client = anthropic.Anthropic(api_key=os.getenv("ANTHROPIC_API_KEY")) identifier = "user_123" # resolved from your own session, never from the client connection = "otteraimcp" # One-time: user connects Otter over OAuth link = sk.actions.get_authorization_link(connection_name=connection, identifier=identifier) print("Authorize Otter:", link.link) input("Press Enter after authorizing...") # Retrieve the tools this user's connected account is authorized to call llm_tools = sk.tools.list_scoped_tools( identifier=identifier, filter={"connection_names": [connection]}, ) messages = [{ "role": "user", "content": "Summarize yesterday's leadership sync and pull out the decisions.", }] while True: response = client.messages.create( model=os.getenv("ANTHROPIC_MODEL", "claude-sonnet-4-6"), max_tokens=1024, tools=llm_tools, messages=messages, ) if response.stop_reason != "tool_use": print(response.content[0].text) break messages.append({"role": "assistant", "content": response.content}) tool_results = [] for block in response.content: if block.type == "tool_use": result = sk.actions.execute_tool( tool_name=block.name, connection_name=connection, identifier=identifier, tool_input=block.input, ) tool_results.append({ "type": "tool_result", "tool_use_id": block.id, "content": str(result), }) messages.append({"role": "user", "content": tool_results})

Tool names come from the connector's current tool list; when in doubt, list the tools for the user first rather than hardcoding a name. Runnable versions live in the Scalekit LangChain and Anthropic examples.

Why build Otter agents the Scalekit way

Otter's MCP surface is small, so this is not a story about taming a hundred tools. The value shows up on the two problems a meeting agent actually hits in production: per-user isolation across tenants, and combining Otter with other connectors under one identity.

Per-user isolation for multi-tenant agents

A shared credential gives every user the same access, which fails the moment a second user arrives. A connected account inverts that: scope is derived from what each user individually authorized in Otter, nothing more. What the user cannot see, the agent cannot fetch. Scope becomes a function of identity, not connector configuration; see access control for multi-tenant AI agents and the token vault model.

Virtual MCP for multi-tool meeting agents

A real meeting agent rarely stops at Otter; it also touches a CRM, a tracker, or Slack. A Virtual MCP Server gives that agent one scoped endpoint that exposes only the tools you allow across connectors, with per-user credential isolation handled by a short-lived session token minted before each run. One server definition serves all users, and there is no MCP server to deploy, host, or maintain. Background is in agent tool observability and when to use one.

Auth logs and downstream tool-call observability

Because the read-only MCP path and the write-capable API path both act as a user, you need to answer who authorized, which agent ran, which tool it called, and what came back. Scalekit records that per tool call, so a transcript pulled or a conversation ingested is traceable to a specific connected account. See audit trails for agent auth and the broader pattern of secure token management for AI agents.

Which one to build against

If your Otter agent is interactive and read-oriented, answering questions over a user's transcripts across standard plans, build against the MCP server. If it is event-driven or needs audio, structured insights, ingestion, or channel metadata inside an Enterprise workspace, build against the Public API. Many teams end up running both: the MCP server for the conversational surface, the API for the pipeline behind it. Either way, the credential problem is identical, and that is the part that needs production-grade infrastructure rather than a token pasted into an environment file. For the broader framing, see how MCP and APIs differ.

Talk to us

Building a meeting agent on Otter? Browse the Scalekit Otter connector and its docs page, then start from a template like meeting prep, sales call prep, or the deal intelligence agent. Pricing is on the Scalekit pricing page, and the full catalog is under all connectors.

For hands-on help, join the Scalekit community on Slack or talk to us for immediate answers.

No items found.
Agent
Auth Quickstart
On this page
Share this article
Agent
Auth Quickstart

Acquire enterprise customers with
zero upfront cost.

Every feature unlocked. No hidden fees.