
Your agent needs to open a Jam and do something useful with it: read the failing requests, correlate the console errors, file the ticket. Jam ships a hosted MCP server, a CLI, and webhooks. What it does not ship is the thing most teams look for first: a documented public REST API. That flips the usual MCP vs API question. For Jam, "the API" is a CLI binary and an event stream, and the MCP server is where most of the capability lives. Here's how to pick, and what you still own on either path.
Two objects are being compared, but not the two most MCP vs API comparisons assume.
Jam's MCP server is a remote server hosted and maintained by Jam, available since August 2025. Jam's MCP documentation covers setup for Claude, ChatGPT, Claude Code, Cursor, VS Code, Windsurf, Codex, and OpenCode. The agent receives a Jam link or ID, and the tools load that Jam's recording, console, network, and event data into context.
Auth takes two forms. Interactive clients complete a browser OAuth flow and pick a workspace. Headless clients send a PAT as a bearer token. Either way, MCP mirrors the user's existing Jam permissions: it grants nothing that user could not already see in the Jam web or mobile apps.
Jam's documentation index has no public REST API reference as of September 2026. The non-MCP surface is two things. The Jam CLI is a native binary for macOS, Linux, and Windows that exposes every read and write as a command, emits JSON when piped, and publishes its machine-readable command schema through jam agent-context.
Jam webhooks push jam.created and recording_link.created events to your HTTPS endpoint, signed in the Standard Webhooks format through Svix. The CLI talks to a Jam backend, but that backend is not documented as a contract you can build against directly. Treat the CLI as the API.
The four dimensions below are fixed across this series. For Jam, the gap runs in an unusual direction: the MCP server is the broader surface, and the direct path fills specific holes around creation and events.
For reading Jams, the two surfaces are near parity; MCP leads on video understanding.
The real gap is on the write side. MCP can manage existing Jams; only the direct path can create one or react when one appears.
Three constraints surface in production, not in demos. The video tools (analyzeVideo, getVideoTranscript, getVideoChapters, getFrames) and getScreenshots are unavailable for Instant Replay Jams. getFrames works only on video Jams hosted on Cloudflare Stream. And Jam recommends feeding an agent one Jam at a time, because a single Jam's logs and network payloads can exhaust a context window.
There is also a data path to review. Jam states that some MCP tools use Google's Gemini, with training opted out and data de-identified. For regulated customers, that belongs in the security questionnaire before launch, not after.
Jam MCP accepts two credential types. Browser OAuth is the default for Claude, ChatGPT, and IDE clients: the user signs in, picks a workspace, and the client holds the token. PATs skip the browser entirely and travel as Authorization: Bearer jam_pat_....
The CLI accepts the same two. jam auth login runs OAuth and stores access and refresh tokens in ~/.config/jam/credentials.json with 0600 permissions; alternatively a PAT is piped to jam auth login --token or set as JAM_TOKEN. Webhooks use a third credential: a per-endpoint whsec_ signing secret you verify with HMAC-SHA256 over the svix-id, svix-timestamp, and body.
PATs are the headless answer, and Jam designed them carefully. Each token is scoped to one workspace, tied to one user, carries mcp:read, mcp:write, or both, and has a mandatory expiry of 7, 30, or 90 days, or one year. Jam stores only a hash, so the plaintext is shown once.
That design is right for a developer's Cursor config. It is awkward for a B2B product: every customer user mints a token in Jam settings, pastes it into your app, and repeats the ritual at expiry. Both paths require per-user credential isolation in a multi-tenant B2B agent. In neither case does the path solve storage, rotation, or revocation; those are infrastructure problems regardless of which path you choose.
With MCP, Jam owns the tool schemas, the filtering logic, and the video analysis pipeline. That is real leverage. getNetworkRequests already filters by status code, host, method, and content type, which is the difference between a handful of failing requests and every request the page made landing in context.
What you still own: token storage, refresh, and handling the moment a user revokes access under Settings > MCP. The surface also moves on Jam's schedule. Jam's docs list 33 tools today, while Scalekit's Jam connector catalog lists 15, a gap that shows how quickly the server-side tool set has grown. Jam publishes no versioning scheme for MCP tool schemas, so re-list tools per run rather than hardcoding them.
The CLI path means owning a binary in your agent runtime: process spawning, JSON parsing, exit codes (3 for auth failures, 7 for HTTP 429), cursor pagination capped at 500 items per page, and version pinning with jam upgrade --target. Set JAM_SKIP_UPDATE_CHECK=1 in CI so the pinned binary stays pinned.
Webhooks add a public HTTPS endpoint, signature verification, and idempotency keyed on svix-id. Jam retries failed deliveries on a fixed schedule that starts immediately and backs off to 10-hour intervals, so design for redelivery: a consumer that times out after processing will see the same svix-id again.
Whichever path you choose, a multi-tenant Jam agent holds one Jam credential per user. Two hundred customer workspaces with 1,800 connected users means 1,800 credential lifecycles.
OAuth tokens from the MCP flow need refreshing. PATs hit a hard expiry with no refresh at all; the user has to mint a new one. Any user can revoke an MCP client or a PAT from Settings > MCP, and the next tool call fails. An agent that does not check connection state before a run finds out mid-task, usually as a triage that silently never happened.
Each token also has to live somewhere: encrypted at rest, isolated per tenant, never logged, and never in the LLM context. Neither Jam path provides that. For a deeper look at how to handle token refresh for AI agents, the patterns apply equally here.
Scalekit's Jam MCP connector handles the OAuth flow, token storage, and refresh, so credentials never touch the agent runtime. The user authorizes once in a browser; every later run, including background runs, resolves that user's vaulted token server-side. One caveat stated plainly: Scalekit covers the MCP path. If you also run the Jam CLI in CI for recording, that PAT stays yours to manage.
Recommended Reading: Token Vault for AI Agent Workflows
Scalekit exposes Jam through one connector, Jam MCP (jammcp), which routes tool calls to Jam's own MCP server. There is no separate Jam API connector, which matches Jam's own surface. The examples use Python: the Anthropic SDK for direct tool calling, then LangChain over a Virtual MCP server.
The connected account is the per-user instance of the Jam connection. Check its status, send the user through the authorization link if it is not active, and fail closed if it still is not. Production apps surface the link in their own UI; see Authorize a user.
list_scoped_tools does not return a flat connector catalog. It returns the tools the current user's connected account is authorized to call. The code then narrows that surface to the five tools a triage role needs, because the fix for tool bloat is not better prompting. It is surface reduction. This is the same principle behind moving from single-tenant to multi-tenant tool calling — identity and scope boundaries must be explicit.
Every tool call goes through execute_tool, which resolves the user's Jam token inside Scalekit. The agent sees tool results, never credentials. The loop continues until Claude stops requesting tools.
The full Anthropic pattern, including a Node.js version, is in the Anthropic example.
A Jam agent rarely stops at Jam. Triage ends in Linear, Jira, or GitHub. A Virtual MCP server gives that agent one endpoint exposing only the tools you allow from each connection, plus a short-lived session token per user per run. No MCP server to deploy, host, or maintain.
Create the server once, not once per user. The response carries a static mcp_server_url that every user and every run reuses. This one pairs four read-only Jam tools with three Linear tools; both connection names must exist in AgentKit > Connections.
Before each run, confirm the user's Jam and Linear accounts are still active, then mint a token scoped to that user. Set expiry above the expected run time. The Node.js SDK does not mint session tokens yet, so this step belongs on a Python backend.
LangChain connects through langchain-mcp-adapters (pip install "langchain-mcp-adapters>=0.3,<1" langchain-openai). The agent sees seven tools, acts as this user in both Jam and Linear, and nothing else is reachable. For more on how LangChain tool calling works and where it stops, the architecture patterns translate directly to this Jam setup.
See the LangChain example and Set up and connect for the full reference.
The code above is short because the hard parts moved out of it. Here is what moved.
Every execute_tool call is recorded with the identifier, the connected account, and an execution ID. When a triage agent posts a wrong comment on a customer's Jam, "which user's credential did this, and when" is one lookup, not a grep across agent logs. Connected account status also tells you when a user must re-authorize, which matters because Jam revocations happen in Jam's settings, outside your app. For the compliance angle, see Audit Trails for Agent Auth.
Jam's MCP server documents destructive tools, including deleteJam and deleteFolder, which removes every Jam inside a folder with no restore. Scalekit's catalog does not list them today, but tool surfaces grow. A Virtual MCP server with an explicit four-tool allowlist keeps anything added later unreachable, rather than merely discouraged by a prompt. What the user can't do, the agent can't do; what the role doesn't need, the agent can't see.
One server definition serves every customer. Each run gets a session token bound to one user's connected accounts, so an agent acting for one customer's engineer cannot reach another customer's Jam workspace. The endpoint is static; the identity is not. Adding GitHub or Jira later is a mapping change, not a new OAuth integration. For the tradeoffs, read Single vs Multi-Tenant Tool Calling and Virtual MCP Server.
If your agent reads Jams to debug, triage, or plan fixes, build on Jam MCP. It is the broader surface, Jam maintains the schemas, and the video and network tooling is already agent-shaped.
Reach for the CLI and webhooks when the agent must create evidence rather than consume it: recording a fix, turning a Playwright trace into a Jam, or starting work the instant jam.created fires. Many production setups use both, with a webhook triggering an MCP-based triage run.
Either way, the credential problem is identical. One Jam credential per user, each needing a vault, refresh, revocation handling, and an audit trail. That is what needs production-grade infrastructure. Understanding who holds the token across agent tool-calling patterns is the right frame for evaluating this tradeoff.
Building a Jam agent and want a second set of eyes on the auth model? Talk to us.