# Inspector Updates Source: https://docs.mcp-use.com/inspector/changelog New updates and improvements to the MCP Inspector **v20.3.24** ## Native hosted deployments Hosted Inspector builds install the exact package version from their Git commit through Railway's native GitHub integration. * **Fix**: verify npm publication before exposing canary's version commit to native deployments * **Fix**: invalidate the Docker install layer when the package version changes, reject dist-tags, and keep prerelease versions off production during promotion * **Cleanup**: remove the custom Railway deployment action and its token dependency **v20.3.23** ## Chat feedback, backgrounds & hosted connections Patch release paired with `mcp-use` v2.11.1, improving chat feedback and keeping hosted MCP requests on the correct route. * **Fix**: show the thinking indicator after a tool finishes or fails while the assistant request is still active. Keep it hidden while another tool is running or the assistant is writing text (`#2891`) * **Fix**: strip the Inspector's DevSpace routing headers before forwarding MCP proxy requests, so hosted MCP servers receive requests for their own hostname (`#2899`) * **Fix**: keep the chat mesh gradient visible while opening or closing chat history by redrawing the canvas immediately after resizing, including when animation is paused (`#2900`) * **Update**: Updated mcp-use to v2.11.1 **v20.3.22** ## Tool call timeouts, chat errors & proxy hardening Patch release paired with `mcp-use` v2.11.0, fixing a 10-second tool call timeout, surfacing chat failures, and hardening the proxy and OAuth routes. * **Fix**: tool calls on servers added from the dashboard no longer time out after 10 seconds. The Connect form's timeout fields start blank, meaning the default 10-minute request timeout and no overall limit. Servers added since v20.3.17 keep their saved 10000 / 60000 values until both fields are cleared in connection settings (`#2881`) * **Fix**: chat shows streamed provider errors, and explains responses that use up the output limit without producing content, instead of an empty turn (`#2877`) * **Fix**: chat tool calls on OpenAI models show their arguments in the tool drawer instead of `{}` (`#2551`) * **Fix**: OAuth metadata responses are always JSON with `X-Content-Type-Options: nosniff`, so a body from a caller-chosen server can no longer render as a page on the Inspector's origin (`#2855`) * **Fix**: proxy and OAuth rate limits apply per caller (client IP) under a process-wide ceiling, instead of one bucket shared by every user. A local Inspector or `mcp-use dev` is limited only by the process-wide ceiling (`#2855`) * **Update**: ChatGPT install steps in the tunnel panel follow the Plugins flow (Plugins → Add → Add Custom MCP Server) (`#2648`) * **Update**: rebuild bundled workspace code with @mcp-use/client v2.4.5 and @mcp-use/agent v2.0.25 * **Update**: Updated mcp-use to v2.11.0 **v20.3.21** ## Public MCP connections & tool headers Patch fixes for browser connections and tool calls, paired with `mcp-use` v2.10.1. * **Fix**: public MCP endpoints remain connected anonymously when fallback OAuth metadata belongs to a different resource, instead of incorrectly requiring authentication (`#2858`) * **Fix**: discard cached OAuth credentials without a valid issuer stamp or with a mismatched issuer. Affected users may need to sign in again (`#2858`) * **Fix**: tool calls send parameters annotated with `x-mcp-header` as `Mcp-Param-*` headers as well as in the request body, so servers requiring the headers accept browser calls (`#2803`) * **Update**: rebuild bundled workspace code with @mcp-use/client v2.4.4 and @mcp-use/agent v2.0.24 * **Update**: Updated mcp-use to v2.10.1 **v20.3.20** ## OAuth Proxy release alignment Patch release paired with `mcp-use` v2.10.0, rebuilding bundled workspace code with the framework's OAuth Proxy and build changes. This release has no Inspector-specific source changes. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.10.0 **v20.3.19** ## Composer mention search release alignment Patch release paired with `mcp-use` v2.9.0, rebuilding bundled workspace code with the framework's composer mention search helper. This release has no Inspector-specific source changes. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.9.0 **v20.3.18** ## Framework release alignment Patch release paired with `mcp-use` v2.8.2, rebuilding the bundled Inspector and synchronizing internal package metadata. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.8.2 **v20.3.17** ## Saved tool timeout settings Patch release paired with `mcp-use` v2.8.1, applying connection timeout settings to tool calls and preserving cleared values. * **Fix**: tool calls use the saved request timeout, maximum total timeout, and reset-on-progress setting instead of hard-coded defaults (`#2656`) * **Fix**: cleared timeout fields stay cleared when reopening or renaming a connection (`#2656`) * **Fix**: changing a connection URL rejects duplicates before removing the existing connection (`#2656`) * **Enhancement**: connection settings explain that a blank request timeout uses the 10-minute default and a blank maximum total timeout removes the overall time limit while retaining the request timeout (`#2656`) * **Update**: Updated mcp-use to v2.8.1 **v20.3.16** ## Framework release alignment Patch release paired with `mcp-use` v2.8.0, rebuilding the bundled Inspector with the ChatGPT Plugin Extensions framework updates. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.8.0 **v20.3.15** ## Chat input toolbar spacing Patch release paired with `mcp-use` v2.7.3, keeping multiline messages clear of the chat toolbar and updating dependencies. * **Fix**: chat input reserves space above the bottom toolbar so multiline text no longer overlaps its controls (`#2735`) * **Update**: update Hono to `^4.13.7` and refresh workspace dependency security floors (`#2746`) * **Update**: Updated mcp-use to v2.7.3 **v20.3.14** ## Disconnect abort & UserInfo proxy Patch release paired with `mcp-use` v2.7.2. The Express adapter stops holding upstream streams after the client leaves, and the OAuth proxy can fetch UserInfo. * **Fix**: disconnecting an Express client aborts the outbound fetch and the proxy read loop, so a long-lived SSE response no longer writes to a dead socket or leaves the upstream connection open (`#2394`) * **Enhancement**: the OAuth proxy allows GET to UserInfo endpoints listed on the authorization server's metadata, and rejects other methods and URLs that are not in that set (`#2688`) * **Update**: Updated mcp-use to v2.7.2 **v20.3.13** ## View cancellation release alignment Patch release paired with `mcp-use` v2.7.1; rebuilds the bundled Inspector with no Inspector-specific source changes. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.7.1 **v20.3.12** ## Mixed authentication release alignment Patch release paired with `mcp-use` v2.7.0; rebuilds the bundled Inspector with no Inspector-specific source changes. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.7.0 **v20.3.11** ## TanStack Start release alignment Patch release paired with `mcp-use` v2.6.0; there are no Inspector-specific source changes. * **Update**: Updated mcp-use to v2.6.0 **v20.3.10** ## Scrollable MCP App results Patch release paired with `mcp-use` v2.5.2, keeping tall tool results accessible. * **Fix**: tall MCP App tool results scroll within the result panel instead of extending beyond it (`#2598`) * **Update**: Updated mcp-use to v2.5.2 **v20.3.9** ## Managed chat model branding & provider selection Patch release paired with `mcp-use` v2.5.1, showing the selected cloud model accurately and simplifying provider selection. * **Fix**: managed chat badges use the selected cloud model's name and provider logo instead of the default transport model's branding (`#2575`) * **Enhancement**: the Manufact cloud provider picker offers OpenAI, Anthropic, and Google; existing selections from other providers remain visible with accurate labels, while evals retain the full catalog and BYOK OpenRouter remains available (`#2576`) * **Update**: `MCPServerConfig.auth_token` is deprecated but retained for type compatibility; use `authToken` to send an authentication token (`#2486`) * **Update**: update Hono to `^4.13.5` (`#2492`) * **Update**: Updated mcp-use to v2.5.1 **v20.3.8** ## Bundled Inspector rebuild Patch release paired with `mcp-use` v2.5.0, rebuilding the standalone Inspector with the agent OpenRouter fix. * **Fix**: rebuild the standalone Inspector with the OpenRouter Responses API agent fix and repair published framework peer metadata (`#2504`) * **Update**: Updated mcp-use to v2.5.0 **v20.3.7** ## Workspace package alignment Patch release paired with `mcp-use` v2.4.3; there are no Inspector-specific source changes. * **Update**: Updated mcp-use to v2.4.3 **v20.3.6** ## Publish artifact preservation Patch release paired with `mcp-use` v2.4.2, keeping package builds intact while npm pack runs. * **Fix**: concurrent publishing no longer drops the Client build while its tarball is created, and packed artifacts are checked for declared files and entry points (`#2428`) * **Update**: Updated mcp-use to v2.4.2 **v20.3.5** ## Chat widgets use the connection id Patch release paired with `mcp-use` v2.4.1, rendering chat MCP Apps against the registered connection. * **Fix**: chat MCP Apps render with the registered MCP connection id while preserving the logical server id for chat state and storage (`#2404`) * **Update**: Updated mcp-use to v2.4.1 **v20.3.4** ## Request duration & screenshot init failures Patch release paired with `mcp-use` v2.4.0, showing RPC duration, failing screenshots when an MCP App fails to initialize, and raising the embedded chat step cap. * **Enhancement**: RPC traffic rows show request duration in milliseconds instead of wall-clock time; unmatched rows omit the timing column (`#2364`) * **Fix**: `mcp-use screenshot` fails with `view_load_failed` when the MCP App fails to initialize (`#2355`) * **Enhancement**: embedded client-side chats can configure up to 100 agent steps (`#2401`) * **Update**: Updated mcp-use to v2.4.0 **v20.3.3** ## RPC latency in the timing column Patch release paired with `mcp-use` v2.3.4, moving response latency into the traffic timing column and labeling colocated Inspector logs. * **Enhancement**: response rows show latency in the traffic timing column instead of repeating it in the method label; unmatched rows still show the wall-clock time (`#2349`) * **Enhancement**: when Inspector shares the `mcp-use dev` process, proxy and OAuth BFF logs are prefixed `[inspector]` (`#2351`) * **Update**: Updated mcp-use to v2.3.4 **v20.3.2** ## Model tool-limit warnings Patch release paired with `mcp-use` v2.3.3, making model tool limits visible before a chat request is sent. * **Enhancement**: chat warns when a connected MCP server exposes more than the documented 128 tools supported by OpenAI or Gemini models (`#2333`) * **Update**: Updated mcp-use to v2.3.3 **v20.3.1** ## Correlated JSON-RPC responses Patch release paired with `mcp-use` v2.3.2, adding request context and timing to JSON-RPC response rows. * **Enhancement**: response rows show the matched request method and elapsed time and flag errors while keeping simultaneous bidirectional requests isolated by source, server, widget, direction, and ID type (`#2303`) * **Update**: Updated mcp-use to v2.3.2 **v20.3.0** ![Release 20.3.0](https://mcp-use.com/api/og/release?v=20.3.0\&title=Reusable%20connection%20settings\&date=2026-08\&lang=inspector) ## Reusable connection settings Minor release paired with `mcp-use` v2.3.1, exposing the Inspector connection form and configuration state for embedded consumers. * **New**: `@mcp-use/inspector/client` exports `ConnectionSettingsForm`, `useConnectionFormState`, custom-header controls, connection configuration types, and normalization helpers, with optional consumer URL validation (`#2319`) * **Update**: Updated mcp-use to v2.3.1 **v20.2.5** ## Isolated chat sessions & accurate cache usage Patch release paired with `mcp-use` v2.3.0, keeping concurrent chat sessions independent and preserving provider cache-token accounting. * **Fix**: each chat session owns one identifier and state record, so **New Chat** starts a fresh session while another is streaming; persistence and OAuth retry use the same identifier, and `ChatStorageProvider.createChat` accepts an optional caller-supplied `id` (`#2232`) * **Fix**: Anthropic `cacheCreationInputTokens` survives aggregation, LLM spans, and raw-chat `tokenUsage`, while totals avoid double-counting OpenAI cached input tokens (`#2127`) * **Update**: Updated mcp-use to v2.3.0 **v20.2.4** ## Workspace package alignment Patch release paired with `mcp-use` v2.2.4; there are no Inspector-specific source changes. * **Update**: Updated mcp-use to v2.2.4 **v20.2.3** ## Protocol version controls Patch release making MCP protocol selection visible in connection setup. * **Enhancement**: the connect form and connection settings expose protocol version selection and make configuration options easier to find * **Update**: Updated mcp-use to v2.2.3 **v20.2.2** ## Workspace package alignment Patch release paired with `mcp-use` v2.2.2; there are no Inspector-specific source changes. * **Update**: Updated mcp-use to v2.2.2 **v20.2.1** ## OAuth protected-resource compatibility Patch release accepting secure parent-path resource metadata during OAuth discovery. * **Fix**: protected-resource metadata may identify a same-origin, segment-aware parent of the MCP endpoint, matching the official MCP TypeScript SDK while rejecting cross-origin, sibling-path, credential-bearing, fragmented, and insecure non-loopback values * **Update**: Updated mcp-use to v2.2.1 **v20.2.0** ![Release 20.2.0](https://mcp-use.com/api/og/release?v=20.2.0\&title=CSP%20auditing%20%26%20embedded%20Inspector%20styles\&date=2026-08\&lang=inspector) ## CSP auditing & embedded Inspector styles Minor release paired with `mcp-use` v2.2.0, adding host-visible CSP verification and a consistent embedded surface contract. * **New**: the embedded Chat bridge exposes CSP mode and audit commands so hosts and coding agents can verify MCP Apps in Widget-Declared mode * **Enhancement**: a canonical client stylesheet provides the Inspector surface, shadow, hover, and active theme contract for embedded dialogs, dropdowns, and selects * **Fix**: embedded MCP Apps render in Vibe and preserve React state during remote HMR updates * **Fix**: remove unreachable exports and declare the Inspector tool-execution test's `jsdom` development dependency explicitly * **Update**: Updated mcp-use to v2.2.0 **v20.1.1** ## Mixed-auth chat recovery Patch release paired with `mcp-use` v2.1.1, allowing anonymous sessions to authenticate only when a protected operation requires it. * **Enhancement**: mixed-auth tool calls stay on the browser MCP connection, pause with an Authenticate action, and resume the same client-side turn after popup or redirect authorization * **Enhancement**: the Skills tab becomes available when a development HMR reload adds Skills after the initial connection negotiated without the extension * **Fix**: optional OAuth discovery and token projection no longer block connection readiness, transient metadata failures recover, and authenticated state remains accurate after a challenge * **Fix**: reverse-proxy buffering is disabled for open-ended MCP SSE responses so subscription acknowledgements arrive immediately * **Update**: Updated mcp-use to v2.1.1 **v20.1.0** ![Release 20.1.0](https://mcp-use.com/api/og/release?v=20.1.0\&title=Skills%20over%20MCP%20%26%20Inspector%20runtime\&date=2026-08\&lang=inspector) ## Skills over MCP & Inspector runtime Minor release paired with `mcp-use` v2.1.0 — typed Skills operations, an integrity-checked file explorer, and development/runtime fixes for the v2 Inspector. * **New**: typed Skills over MCP client operations, a capability-gated Inspector file explorer with integrity verification, and removable progressive skill context in Inspector chat * **Enhancement**: Skills discovery omits invalid skills from fresh development snapshots * **Enhancement**: the `window.openai` compatibility bridge exposes tool lifecycle globals and host actions while preserving the native MCP Apps handshake for v2 views; iframe console records are not parsed as MCP Apps JSON-RPC messages * **Fix**: provider assets load from the development server, widget-declared sandbox CSPs can use dynamic compilation within their declared domains, and embedded layouts fill their iframe height without the empty desktop header gap or standalone sidebar footer controls * **Fix**: avoid the Inspector tunnel flash while connection state transitions complete * **Update**: Updated mcp-use to v2.1.0 **v20.0.4** ## Stable npm README links Patch release fixing absolute links in the published Inspector documentation. * **Fix**: README images and repository links use stable absolute URLs so npm renders the published Inspector documentation correctly * **Update**: Updated mcp-use to v2.0.4 **v20.0.3** ## Stable package README metadata Patch release making the published Inspector README reliable on npm. * **Fix**: Publish a package-root README and verify that it stays synchronized with the repository README before packing * **Update**: Updated mcp-use to v2.0.3 **v20.0.1** ## Safer loopback proxy defaults Patch release paired with `mcp-use` v2.0.1, preventing publicly reachable Inspector mounts from proxying requests to host loopback services by default. * **Fix**: `mountInspector` defaults `oauthProxyAllowLoopback` to `false`; the standalone CLI permits loopback for local development but blocks it in production unless `INSPECTOR_ALLOW_LOOPBACK=true` * **Update**: runtime and bundled dependencies use patched stable releases with tightened transitive resolutions * **Update**: Updated mcp-use to v2.0.1 **v20.0.0** ![Release 20.0.0](https://mcp-use.com/api/og/release?v=20.0.0\&title=MCP%20SDK%20v2%20%26%20hosted%20Inspector\&date=2026-08\&lang=inspector) ## MCP SDK v2 & hosted Inspector Major release paired with `mcp-use` v2.0.0 — the Inspector moves to the official MCP SDK v2 and a project-pinned, secure relay/runtime architecture. * **Update**: The Inspector and client move to the official MCP SDK v2 with automatic protocol negotiation, ESM-only packages, Node.js 22.22.2+, redesigned OAuth, and v1 API cleanup * **New**: Project-pinned Inspector development owns the MCP/OAuth relay and serves local assets without a remote application fallback; the standalone package adds the full proxy and OAuth BFF * **New**: Hosted and localhost chat, MCP Apps tool lifecycle delivery, fullscreen chat controls, and streamed tool-call input improve interactive Inspector sessions * **Fix**: OAuth session values are encrypted at rest, secret connection fields are not persisted, browser launches and Inspector routes are hardened, and proxy/OAuth APIs are rate-limited * **Enhancement**: Immutable CDN asset resolution and zero-dependency packaging prevent mixed-version assets and keep standalone installs clean * **Update**: Updated mcp-use to v2.0.0 **v12.0.6** ## CLI version heading Patch release paired with `mcp-use` v1.34.6; includes the unpublished 12.0.4 docs-link fix. * **Enhancement**: the CLI help heading shows the installed Inspector version * **Documentation**: Inspector README drops dead documentation links * **Update**: Updated mcp-use to v1.34.6 **v12.0.3** ## Tunneling docs link Patch release fixing the tunnel popover documentation link. * **Documentation**: The tunnel popover now links to `https://mcp-use.com/docs/tunneling` instead of the removed Manufact URL * **Update**: Updated mcp-use to v1.34.3 **v12.0.2** ## Backend-less CDN shell support Patch release improving the Inspector bundle used by the SDK v2 backend-less shell. * **Fix**: CDN auto-connect reads `window.__MCP_USE_INSPECTOR__.autoConnectUrl`, and the version badge and MCP `clientInfo` fall back to the compile-time bundle version when runtime injection is absent * **Update**: Updated mcp-use to v1.34.2 **v12.0.1** ## mcp-use v1.34.1 Patch release paired with `mcp-use` v1.34.1; there are no Inspector-specific source changes. * **Update**: Updated mcp-use to v1.34.1 **v12.0.0** ## Hosted OAuth reliability (mcp-use v1.34.0) Major release paired with `mcp-use` v1.34.0 — peer dependency bump; runtime OAuth fixes come from the updated `mcp-use` dependency (no inspector-specific source changes in this wave). * **Fix**: gateway-fronted and hosted OAuth servers no longer drop to `failed` with "Server does not support OAuth" when discovery succeeded on an earlier pass — inherits `oauthProxyUrl` wiring and `pending_auth` handling from mcp-use v1.34.0 (`#1840`) * **Update**: Peer dependency on `mcp-use` moves to `>=1.34.0-canary.0` * **Update**: Updated mcp-use to v1.34.0 **v11.0.0** ![Release 11.0.0](https://mcp-use.com/api/og/release?v=11.0.0\&title=MCP%20Apps%20primary%20widget%20runtime\&date=2026-06\&lang=inspector) ## MCP Apps runtime, Auto connections & host context styles Major release paired with `mcp-use` v1.33.0 — widgets now render with MCP Apps as the primary runtime, new connections default to Auto mode with proxy fallback, and host context style variables are applied while the Apps SDK preview tab remains for `window.openai`-only widgets. * **New**: widgets render with the MCP Apps bridge as the primary runtime and apply host context style variables; the Apps SDK ("Component (Apps SDK)") preview tab remains for widgets that only speak `window.openai` (`#1739`) * **Enhancement**: new connections default to Auto mode, trying a direct browser connection first and falling back to the configured Inspector proxy when CORS or other proxy-resolvable connection errors occur; Direct and Proxy remain available as advanced overrides (`#1795`) * **Fix**: OAuth proxy fetch is scoped per server configuration, so connecting one server Via Proxy no longer mutates global `fetch`, changes unrelated requests, or affects other servers configured for Direct mode (`#1770`) * **Fix**: stale saved auto-connect entries are replaced when the advertised transport changes, so embedded Inspector instances stop retrying deprecated SSE connections after switching to streamable HTTP (`#1792`) * **Fix**: signed-in users on the hosted free tier are no longer shown the "sign in to increase your limits" prompt — the free-tier upgrade chrome only renders for anonymous visitors (`#1767`) * **Fix**: the inspector CLI handles `--version` and unknown options and reads its version from `package.json`, so canary builds and CLI version output stay in sync (`#1722`) * **Update**: Bumped `vite` to 8.0.16 (`#1742`) * **Update**: Peer dependency on `mcp-use` moves to `>=1.33.0-canary.0` * **Update**: Updated mcp-use to v1.33.0 **v10.0.1** ## Hosted localhost chat & chat scroll helper Patch release paired with `mcp-use` v1.32.1 — hosted inspector chat falls back to browser-side streaming for loopback MCP servers and adds a scroll-to-bottom affordance in long chats. * **Fix**: Hosted inspector chat detects localhost and loopback MCP server URLs and uses client-side streaming because the managed cloud backend cannot reach a user's local server; the configure-key empty state explains why a personal API key is needed (`#1736`) * **New**: Centered animated scroll-to-bottom button appears when viewing older chat messages (`#1538`) * **Update**: Peer dependency on `mcp-use` moves to `>=1.32.1-canary.0` * **Update**: Updated mcp-use to v1.32.1 **v10.0.0** ## mcp-use v1.32.0 Major release paired with `mcp-use` v1.32.0 — peer dependency moves to `>=1.32.0-canary.0`; no inspector-specific runtime changes. * **Update**: Peer dependency on `mcp-use` moves to `>=1.32.0-canary.0` * **Update**: Updated mcp-use to v1.32.0 **v9.0.1** ## mcp-use v1.31.1 Patch release paired with `mcp-use` v1.31.1 — picks up workspace dependency alignment; no inspector-specific runtime changes. * **Update**: Updated mcp-use to v1.31.1 **v9.0.0** ![Release 9.0.0](https://mcp-use.com/api/og/release?v=9.0.0\&title=OAuth%20credential%20lifecycle%20%26%20mcp-use%20v1.31.0\&date=2026-06\&lang=inspector) ## OAuth credential lifecycle & mcp-use v1.31.0 Major release paired with `mcp-use` v1.31.0 — peer dependency moves to `>=1.31.0-canary.1`; explicit OAuth credential cleanup when removing a saved server. * **Fix**: delete-server passes `{ clearCredentials: true }` to `removeConnection` so an explicit user removal forgets persisted OAuth credentials instead of leaving tokens behind (`#1703`) * **Update**: Peer dependency on `mcp-use` moves to `>=1.31.0-canary.1` * **Update**: Updated mcp-use to v1.31.0 **v8.0.2** ## mcp-use v1.30.2 Patch release paired with `mcp-use` v1.30.2 — picks up the chalk CJS compatibility fix; no inspector-specific runtime changes. * **Update**: Updated mcp-use to v1.30.2 **v8.0.1** ## Widget status label pointer-events fix Patch release paired with `mcp-use` v1.30.1 - invoking/invoked labels in the MCP Apps preview pane no longer block iframe interactions. * **Fix**: MCP Apps preview status label used an absolutely positioned `h-full` wrapper that intercepted hover, click, and form controls along the left edge of the widget iframe; apply `pointer-events-none`, remove the full-height wrapper, and align the Apps SDK label in `OpenAIComponentRenderer` (`#1694`, `#1678`) * **Update**: Updated mcp-use to v1.30.1 **v8.0.0** ## mcp-use v1.30.0 Major release paired with `mcp-use` v1.30.0 - peer dependency moves to `>=1.30.0-canary.0`; no inspector-specific runtime changes. * **Update**: Peer dependency on `mcp-use` moves to `>=1.30.0-canary.0` * **Update**: Updated mcp-use to v1.30.0 **v7.0.1** ## mcp-use v1.29.1 Patch release paired with `mcp-use` v1.29.1 - picks up OAuth transport auth hardening and workspace security dependency bumps; no inspector-specific runtime changes. * **Update**: Updated mcp-use to v1.29.1 **v7.0.0** ![Release 7.0.0](https://mcp-use.com/api/og/release?v=7.0.0\&title=Local%20LLM%20provider%2C%20image%20tool%20results%20%26%20widget%20display%20modes\&date=2026-06\&lang=inspector) ## Local LLM provider, image tool results & widget display modes Major release paired with `mcp-use` v1.29.0: chat against a local Ollama daemon, MCP image tool results forwarded to vision models as real images, an MCP-server reconnect banner, and a reworked widget fullscreen / picture-in-picture path - plus a large dead-code cleanup. * **New**: Ollama as a local LLM chat provider - local model discovery and streaming chat, talking to the daemon directly over CORS (no server-side proxy) with an `OLLAMA_ORIGINS` hint surfaced when the browser fetch is blocked (`#1395`) * **New**: MCP-server reconnect banner - chat recognises the cloud's `mcp_auth_required` 401 (e.g. an expired upstream OAuth token) and renders an inline reconnect banner for the affected server that refreshes the token in place, instead of pointing users at the Manufact account login (`#1485`) * **New**: copy button on user messages, matching the assistant-message UX (`#1556`) * **Enhancement**: `mcp-use client screenshot` auto-sizes to the widget's natural dimensions when `--width`/`--height` are omitted and handles external MCP server URIs (`ui:///.html`) (`#1579`) * **Enhancement**: snappier tab-switch animation timing (`#1544`) * **Fix**: MCP image tool results are forwarded to the model as real image content instead of base64-encoded JSON - image bytes route through each provider's vision channel (Anthropic `tool_result` image blocks; OpenAI / Google follow-up user turns), and text-only results now reach the model unwrapped (`#1487`) * **Fix**: widget fullscreen renders above embedded host chrome - native `requestFullscreen()` on the widget shell with an exit navbar, picture-in-picture portaled to `document.body` at `z-[100]`, and AppBridge reconnect after the sandbox iframe remounts (`#1605`) * **Fix**: stop `ToolInputForm` from writing an invalid per-property `required: boolean` onto the live tool `inputSchema` during render, which made Anthropic reject the chat request with `tools.0.custom.input_schema invalid` after a tool was opened in the Tools tab (`#1545`) * **Fix**: keep per-tab count badges visible and right-aligned in collapsed header tabs (`#1490`) * **Fix**: propagate server alias updates through the MCP server wrapper so the tile heading reflects a renamed alias immediately (`#1539`) * **Fix**: replace the trailing-slash regex in `normalizeOllamaBaseUrl` with a linear scan, resolving a CodeQL polynomial-regex alert (`#1534`) * **Chore**: add an OAuth redirect e2e against an emulated Google issuer, exercising both Direct and Via Proxy connection types (`#1481`, `#1609`) * **Chore**: remove 18 unused source files, stop generating the unused client-side `version.ts`, and drop dead barrel re-exports flagged by Knip (`#1510`, `#1533`, `#1607`) * **Update**: Updated mcp-use to v1.29.0 **v6.0.0** ![Release 6.0.0](https://mcp-use.com/api/og/release?v=6.0.0\&title=Widget%20preview%20route%20%26%20dark-mode%20scrollbars\&date=2026-05\&lang=inspector) ## Widget preview route & dark-mode scrollbars Major release paired with `mcp-use` v1.28.0: new `ViewPreview` component and `/preview/:view` client-side route that back the `mcp-use client screenshot` CLI pipeline, dark-mode aware scrollbars across the UI, and a cleanup of duplicate Knip-flagged exports. * **New**: `` internal component and `/preview/:view` client-side route — a chromeless surface the CLI screenshot pipeline drives via CDP. `MCPAppsRenderer` gains an optional `onReady` callback that the preview route uses to signal `body[data-view-ready="true"]`, which the CLI waits for before capturing. The preview route detects `globalThis.__mcpUsePreviewBundle` (injected by the CLI via CDP `Page.addScriptToEvaluateOnNewDocument`) and renders the widget inline, skipping the browser-side MCP connection entirely (`#1432`) * **Enhancement**: dark-mode aware scrollbars styled to match the inspector theme, with improved hover visibility (`#1484`) * **Fix**: removed the redundant default export of `JsonRpcLoggerView`; the named export is unchanged (`#1453`) * **Update**: Updated mcp-use to v1.28.0 **v5.0.1** ## MCP App width fix in chat Patch release paired with `mcp-use` v1.27.1: MCP App width is pinned in chat so only height responds to widget-reported sizes. * **Fix**: Pin MCP App width in chat - `onSizeChange` only updates height, and the inline transition no longer animates `width`; prevents the chat panel from collapsing when widgets report narrower content (`#1462`) * **Update**: Updated mcp-use to v1.27.1 **v5.0.0** ![Release 5.0.0](https://mcp-use.com/api/og/release?v=5.0.0\&title=OpenRouter%2C%20pre-registered%20OAuth%20%26%20telemetry%20env\&date=2026-05\&lang=inspector) ## OpenRouter, pre-registered OAuth & telemetry env Major release paired with `mcp-use` v1.27.0: OpenRouter and OpenAI-compatible providers in chat configuration, pre-registered OAuth client credentials in the connection dialog, and `MCP_USE_ANONYMIZED_TELEMETRY` honored in browser telemetry. * **New**: OpenRouter as a first-class chat provider - a single OpenRouter API key fronts upstream OpenAI / Anthropic / Google models; internally reuses the OpenAI provider with an override base URL and the required `HTTP-Referer` / `X-Title` headers (`#1403`) * **New**: "OpenAI Compatible" entry in the chat provider dropdown - point inspector chat at any OpenAI-compatible API (LM Studio, Ollama, OpenRouter, etc.) with a required Base URL field and an optional API key; the standard OpenAI provider is unchanged (`#1437`) * **New**: `Client ID`, `Client Secret`, and `Scope` fields in the Authentication dialog wired through `addServer` / `updateServer` for pre-registered OAuth flows against providers that strip `registration_endpoint` from metadata (`#1400`) * **Fix**: Browser telemetry honors `MCP_USE_ANONYMIZED_TELEMETRY=false` - the inspector server mirrors the env var into `window.__MCP_USE_ANONYMIZED_TELEMETRY__` before the client bundle loads, so a single env var disables both `mcp-use`'s in-browser `posthog-js` and the inspector's own client telemetry (`#1443`) * **Update**: Updated mcp-use to v1.27.0 **v3.0.2** ## E2E alignment for Settings dropdown Patch release updating Playwright coverage for the command palette Settings entry after the navbar refactor; paired with `mcp-use` v1.25.2. * **Fix**: Command palette e2e test targets the Settings option via the dropdown trigger introduced in the inspector settings UX (`#1428`) * **Update**: Updated mcp-use to v1.25.2 **v3.0.1** ## OAuth single-tab flow, embed fixes & Hono detection Patch release fixing OAuth redirect flows, embedded `ChatTab` UI leaks, and Hono duck-type detection in `mountInspector`; paired with `mcp-use` v1.25.1. * **Fix**: OAuth authorization now opens in the current tab (`useRedirectFlow: true`, `preventAutoAuth: true`) and the callback navigates the same tab back - users no longer end up with two inspector tabs (`#1391`) * **Fix**: Store connection config in `sessionStorage` before OAuth redirect so auto-reconnect works after the callback without a `?autoConnect` param (`#1404`) * **Fix**: OAuth callback redirects back to the inspector with error parameters on failure (user denies, server error) instead of showing a raw error page; surfaced as a persistent app-level toast (`#1381`) * **Fix**: `mountInspector(app)` detects Hono via duck-typing (`.fetch(Request) => Response`) instead of `instanceof`, resolving crashes when the host and inspector resolve different Hono module records (`#1417`) * **Fix**: MCP App widget z-index - removed explicit `z-20`/`z-10` from sandboxed iframe wrappers so widgets scroll beneath the chat header instead of painting over it (`#1407`) * **Fix**: Free-tier upgrade UI (`Model & usage` dialog, model badge) is now opt-in via `enableFreeTierUpgrade` on `ChatTab` (default `false`) and is hidden for host-app embeds that manage their own session (`#1399`) * **Fix**: Suppress duplicate model chrome (landing pill, `ChatHeader` badge) when host passes `managedLlmConfig` + `hideModelBadge`; chat no longer auto-switches to client-side streaming when `localLlmConfig` exists in localStorage and the host owns the chat stream (`#1418`) * **Documentation**: `--no-open` CLI flag added to the inspector CLI reference (`#1397`) * **Update**: Updated mcp-use to v1.25.1 **v3.0.0** ![Release 3.0.0](https://mcp-use.com/api/og/release?v=3.0.0\&title=Inline%20elicitation%20%26%20social%20meta%20tags\&date=2026-04\&lang=inspector) ## Inline elicitation & social meta tags Major release paired with `mcp-use` v1.25.0: chat-initiated elicitation requests render inline in the chat thread, hosted inspector links get rich previews, and the peer dependency on `mcp-use` tracks the 1.25 OAuth refactor. * **New**: Elicitation requests triggered from the Chat tab render inline in the chat thread instead of routing users through a toast to the Elicitation tab; Tools-tab triggers keep the existing toast flow, and the Elicitation tab remains available as an audit view (`#1336`) * **New**: Links to the hosted inspector now render rich previews on Slack, X/Twitter, LinkedIn, Discord, and other platforms (`#1376`) * **Update**: Peer dependency on `mcp-use` moves to `>=1.25.0-canary.9` to pick up the OAuth DCR-direct refactor * **Update**: Updated mcp-use to v1.25.0 **v2.2.0** ![Release 2.2.0](https://mcp-use.com/api/og/release?v=2.2.0\&title=Hosted%20chat%2C%20LLM%20providers%20%26%20chat%20export\&date=2026-04\&lang=inspector) ## Hosted chat runtime, LLM providers & chat export Minor release paired with `mcp-use` v1.24.2: first-party inspector LLM streaming (no LangChain on the chat path), copy/export chat, runtime hosted-chat URL, hosted free-tier chat, and cloud env tooling via the CLI (`#1372`). * **New**: First-party LLM providers for inspector chat (Anthropic, OpenAI, Google) with shared message formatting, SSE streaming, and tool loops - the inspector no longer depends on LangChain for chat (`#1372`) * **New**: "Copy Chat" and "Export Chat" in the chat header - markdown to clipboard; download as JSON or Markdown with tool calls in order (`#1324`) * **New**: Free tier chat on the hosted inspector (`#1368`) * **New**: Hosted chat URL from runtime config - inspector server reads `MANUFACT_CHAT_URL` and injects `window.__MANUFACT_CHAT_URL__`; `InspectorProvider` prefers that value and falls back to `VITE_MANUFACT_CHAT_URL` for local dev (`#1370`) * **Fix**: OAuth login popup - drop `noopener` and redirect `callbackURL` to `/inspector/oauth-popup-closed.html` so the popup self-closes instead of loading the full inspector (`#1370`) * **Update**: Updated mcp-use to v1.24.2 **v2.1.0** ## Navbar, theme & debug controls Minor release with MCP Apps debug theme toggle and navbar/settings UX improvements; dependency bump to `mcp-use` v1.24.1. * **New**: Theme toggle button in MCP Apps debug controls toolbar * **Enhancement**: Navbar - chat tab first with label and separator; `alwaysExpanded` on tab triggers so the active label stays visible when collapsed; Deploy links to manufact.com/signup with inspector referrer; tunnel control between Add to Client and Deploy with updated styling and mobile visibility; theme toggle, command palette, and GitHub under a settings dropdown; "Report a Bug" prefills a GitHub issue with the inspector label * **Update**: Updated mcp-use to v1.24.1 **v2.0.0** ![Release 2.0.0](https://mcp-use.com/api/og/release?v=2.0.0\&title=Subpath%20OAuth%2C%20chat%20UX%20%26%20tab%20persistence\&date=2026-04\&lang=inspector) ## Subpath OAuth, chat UX & tab persistence Major release paired with `mcp-use` v1.24.0: correct OAuth redirects when the inspector is served under `/inspector`, clearer chat streaming UI, and restored tab state after reload. * **Fix**: `McpClientProvider` receives `defaultCallbackUrl` so OAuth redirects target `/inspector/oauth/callback` (matches React Router `basename`); removes the authentication dialog "Redirect URL" field that was not wired to the live connection * **Fix**: Hide the thinking indicator when the assistant message already has rendered parts so the spinner does not linger after streaming completes * **Enhancement**: Persist the active inspector tab across page refresh * **Update**: Updated mcp-use to v1.24.0 **v1.0.1** ## Embedded inspector without LangChain Patch release fixing server routes that imported `telFetch` from the root `mcp-use` package. * **Fix**: Import `telFetch` from `mcp-use/telemetry/tel-fetch` so shared routes do not load the root entry (which eagerly pulls the agent graph); resolves embedded inspector failures when `langchain` is not installed * **Update**: Updated mcp-use to v1.23.1 **v1.0.0** ![Release 1.0.0](https://mcp-use.com/api/og/release?v=1.0.0\&title=Stream%20Protocol%2C%20Aliases%20%26%20Chat%20Tooling\&date=2026-04\&lang=inspector) ## Stream protocol, aliases & chat tooling Major release with MCP stream support in chat, connection UX improvements, and dependency hardening. * **New**: MCP data stream protocol support in `ChatTab` and `useChatMessages` * **Enhancement**: `disabledTools` prop on `ChatTab` and `useChatMessages` for finer tool control * **New**: Editable MCP server aliases in connection settings; `updateServerMetadata()` from `McpClientProvider` updates display names without a full reconnect; shared `getServerDisplayName` across dashboard tiles, server dropdown, header actions, command palette, server info modal, and server icon * **Fix**: Alias-only edits no longer trigger a full reconnect; IME composition no longer submits the connection form when pressing Enter mid-composition * **Enhancement**: Persist tabs on refresh; sync URL `tab` query param when switching tabs so state survives reload * **Enhancement**: Tool-invocation serialization, screenshots, and message list refs for integrations such as manufact.build * **Update**: Removed unused `transportType` / `setTransportType` props from `ConnectionSettingsForm` * **Fix**: Tighter `pnpm` overrides and lockfile refresh for `pnpm audit`; `lodash` override in the mcp-apps scaffold template for standalone installs * **Update**: Vite 8.0.5, Hono 4.12.12, `@hono/node-server` 1.19.13 * **Update**: Updated mcp-use to v1.23.0 **v0.26.1** ## Dependency & bundling alignment Patch release aligning how `@mcp-use/inspector` packages `mcp-use` for bundling and shared types. * **Fix**: Restore `mcp-use` as both a `dependency` and `peerDependency` - tsup bundles non-React subpaths with transitive deps; `peerDependency` preserves shared `mcp-use`/`react` types with the host app * **Update**: Updated mcp-use to v1.22.3 **v0.26.0** ## Peer Dependency Alignment & MCP UI v7 Minor release aligning inspector dependency strategy for shared type safety and upgrading MCP UI client rendering internals. * **Fix**: Moved `mcp-use` from `dependencies` to `peerDependencies` in `@mcp-use/inspector` so consumers reuse a single `mcp-use` type instance (prevents pnpm duplicate-type TS2322 conflicts) * **Enhancement**: Upgraded `@mcp-ui/client` from v6 to v7 * **Enhancement**: Replaced removed legacy `UIResourceRenderer` path with sandboxed iframe rendering for legacy `ui://` resources * **Enhancement**: Removed remote-dom usage to align with upstream `@mcp-ui/client` v7 changes * **Update**: Updated mcp-use to v1.22.2 **v0.25.1** ## Chat History Tool Results & ErrorBoundary Customization Patch release improving chat history reconstruction so tool calls/results (including `structuredContent`) persist across turns, plus ErrorBoundary fallback/reporting hooks. * **Fix**: Preserve tool invocation context across chat turns - reconstruct assistant messages as `AIMessage` tool calls plus `ToolMessage` results; keep `structuredContent` and strip `_meta` before sending to the model * **Enhancement**: Chat message conversion supports tool results and multimodal content more reliably * **Enhancement**: `ErrorBoundary` now supports `fallback` (node or `(error) => node`) and `onError` for reporting (default UI unchanged) * **Update**: Updated mcp-use to v1.22.1 **v0.25.0** ## Tunnel Controls & Vite 8 Minor release with tunnel management for `mcp-use dev`, Vite 8 build stack, and elicit payload alignment with the MCP spec. * **New**: Start/stop the `mcp-use dev` tunnel from the Inspector * **Enhancement**: Vite 8.0 with Rolldown bundler and `@vitejs/plugin-react` 6 in the inspector build * **Fix**: Elicit - send `content` instead of `data` per the MCP spec; aligns with `createElicitMethod` validation on the client * **Update**: Updated mcp-use to v1.22.0 **v0.24.5** ## Dependency Updates Patch release with dependency updates. * **Fix**: Dependabot security alerts - updated vulnerable dependencies (hono, dompurify, etc.) * **Update**: Updated mcp-use to v1.21.5 **v0.24.4** ## Dependency Update Patch release with dependency update. * **Update**: Updated mcp-use to v1.21.4 **v0.24.3** ## Sandbox Host Fix Patch release fixing sandbox host derivation for cloud-embedded inspector pages. * **Fix**: Sandbox host derivation for cloud-embedded pages - apex hosts (e.g. manufact.com) now resolve to `sandbox-inspector.{domain}` instead of `sandbox-{domain}` * **Update**: Updated mcp-use to v1.21.3 **v0.24.2** ## Embedded Inspector Proxy Fix Patch release fixing auto-connect when inspector is served from MCP server (Python, custom servers). * **Fix**: Skip proxy when inspector origin matches MCP server origin - no longer routes through missing `/inspector/api/proxy` on embedded servers * **Fix**: Detect proxy availability via runtime config injection (`__MCP_PROXY_URL__`); disable autoProxyFallback when no proxy is available * **Update**: Updated mcp-use to v1.21.2 **v0.24.1** ## Chat Components & Dark Mode Fixes Patch release with exported chat component enhancements and proxy header handling. * **Fix**: Tools selection and attachment button icons invisible in dark mode * **Enhancement**: Strip infra headers from proxied requests * **New**: Initial messages support for exported chat components (`ChatTab`, `useChatMessages`) * **Update**: Updated mcp-use to v1.21.1 **v0.24.0** ## Inspector Embedding & MCP Apps Minor release with embedding support and logger improvements. * **New**: Inspector embedding support - build fix and `InspectorProvider` for embedded usage * **New**: MCP Apps support in `clientInfo.capabilities` - inspector advertises `io.modelcontextprotocol/ui` * **Enhancement**: Logger middleware filters noisy API endpoints (telemetry, RPC stream/log) * **Fix**: `--no-open` flag respected in standalone dev mode (was always opening browser) * **Update**: Updated mcp-use to v1.21.0 **v0.23.1** ## Dependency Update Patch release with dependency update. * **Update**: Updated mcp-use to v1.20.5 **v0.23.0** ## Embedded Chat Improvements Minor release improving embedded chat experience. * **Enhancement**: Improved embedded chat * **Update**: Updated mcp-use to v1.20.4 **v0.22.3** ## Standalone Deployment Fix Patch release fixing version import in standalone deployment. * **Fix**: Standalone deployment was importing the version from the wrong path * **Update**: Updated mcp-use to v1.20.3 **v0.22.2** ## Connection & Widget Display Improvements Patch release with useAutoConnect, MCPAppsRenderer, and chat agent fixes. * **Fix**: useAutoConnect now retains tile visibility on connection failure * **Enhancement**: MCPAppsRenderer and OpenAIComponentRenderer - improved border handling and status display; `prefersBorder` default set to false; status labels above widget in inline mode * **Enhancement**: ToolResultDisplay z-index for proper sticky layering * **Enhancement**: `exposeResourcesAsTools` and `exposePromptsAsTools` options in MCPAgentOptions; inspector chat tab sets both to `false` so agent only exposes actual MCP tools * **Update**: Updated mcp-use to v1.20.2 **v0.22.1** ## Widget Status Texts & CSP Fixes Patch release with invoking/invoked status display and CSP handling improvements. * **New**: Display of `invoking` and `invoked` status texts in MCPAppsRenderer, OpenAIComponentRenderer, ToolResultDisplay, ToolResultRenderer * **Enhancement**: MCPAppsDebugControls adjusts violation indicators based on CSP mode * **Fix**: sandbox-proxy strips existing CSP meta tags before injecting permissive CSP * **Update**: Updated mcp-use to v1.20.1 **v0.22.0** ![Release 0.22.0](https://mcp-use.com/api/og/release?v=0.22.0\&title=Iframe%20Console%20%26%20CSP%20Panel\&date=2026-02\&lang=inspector) ## Iframe Console & CSP Panel Minor release with Iframe Console enhancements and CSP violation handling. * **New**: Iframe Console with expandable logs, level filter, search, resizable height * **New**: Widget debug context for chat * **Enhancement**: MCP Apps debug controls (tool props JSON view, required props hint, SEP-1865 semantics) * **New**: CDN build * **Fix**: useSyncExternalStore first-render handling; reconnect logic; Tools tab sends only explicitly set fields; resource annotations include `_meta` * **New**: CSP violations panel with clear action; widget re-execution on CSP mode change; CSP mode for Apps SDK * **Update**: Updated mcp-use to v1.20.0 **v0.21.1** ## Dependency Update Patch release with dependency update. * **Update**: Updated mcp-use to v1.19.3 **v0.21.0** ![Release 0.21.0](https://mcp-use.com/api/og/release?v=0.21.0\&title=Bulk%20Paste%20%26%20Tool%20Definition%20Enhancements\&date=2026-02\&lang=inspector) ## Bulk Paste & Tool Definition Enhancements Minor release adding bulk paste functionality and enhanced tool definition handling. * **New**: Bulk paste functionality in ToolsTab - paste JSON or JavaScript object syntax directly * **New**: Auto-fill dialog to confirm updates when pasted data would overwrite existing values * **Enhancement**: ToolExecutionPanel now copies full tool definition * **Enhancement**: Added utility functions for parsing and converting JavaScript object syntax to JSON * **Enhancement**: Visual feedback for auto-filled fields in ToolInputForm * **Update**: Updated mcp-use to v1.19.2 **v0.20.1** ## MCPApps & Widget Improvements Patch release improving widget loading and iframe handling. * **Enhancement**: Improved MCPAppsRenderer loading logic and widget handling * **Enhancement**: Enhanced useWidget for better iframe lifecycle management * **Update**: Updated mcp-use to v1.19.1 **v0.20.0** ![Release 0.20.0](https://mcp-use.com/api/og/release?v=0.20.0\&title=Chat%20Quick%20Questions%20%26%20Enhanced%20UX\&date=2026-02\&lang=inspector) ## Chat Quick Questions & Enhanced UX Minor release with chat quick questions and followups, improved loading states, and developer experience enhancements. ### Chat Enhancements * **New**: Support for `chatQuickQuestions` and `chatFollowups` in ChatTab components ### Loading & Error Handling * **Enhancement**: MCPAppsRenderer shows loading spinner with `isReady` state management * **Enhancement**: Replaced shimmer with Spinner component for better initial widget load UX * **Enhancement**: Added skeleton loading state for widgets * **Enhancement**: Global error listeners and improved error logging in widget components ### Developer Experience * **New**: Copy all logs to clipboard feature * **Enhancement**: Enhanced theme handling in OpenAIComponentRenderer * **Enhancement**: ToolsList displays metadata and icons differentiating MCP/OpenAI tool types * **Fix**: Allow permissive CSP frame ancestors by default * **Fix**: Correct MIME type for mcp\_apps resource counting ### Dependencies * **Update**: Updated mcp-use to v1.19.0 **v0.19.0** ![Release 0.19.0](https://mcp-use.com/api/og/release?v=0.19.0\&title=Tool%20Arguments%20%26%20Streaming%20Input\&date=2026-02\&lang=inspector) ## Tool Arguments, Streaming Input & Elicitation Enum Support Minor release with tool argument handling, streaming input support, and elicitation enum variants. * **New**: Tool argument type coercion and schema resolution (boolean, array, object); ToolsTab and ToolInputForm use new schema utilities; validation server tool and E2E tests for typed arguments * **New**: Partial tool input handling for streaming arguments in MCPAppsRenderer; MessageList and ToolResultRenderer support streaming states; useChatMessagesClientSide handles streaming tool call arguments; useWidget types for partial/streaming state * **New**: Elicitation support for SEP-1330 enum schema variants (single-select, multi-select); client and server handling; Elicitation tab docs and tests * **Fix**: Readiness state reset when widget URL changes in OpenAIComponentRenderer; improved tool output and response metadata handling for pending-to-ready transitions * **Update**: Updated mcp-use to v1.18.0 **v0.18.9** ## Log Noise Reduction Patch release reducing dev server log noise and aligning dependencies. * **Fix**: Reduced noisy logs in the dev server * **Update**: Updated mcp-use to v1.17.4 **v0.18.8** ## Widget Readiness & Iframe Global Sync Fixes Patch release focused on widget iframe lifecycle reliability and state update safety. * **Fix**: Reset widget readiness state when widget URL changes so new iframes re-initialize correctly * **Enhancement**: Improved tool output and response metadata transitions from pending to ready states * **Enhancement**: Queued iframe global updates until OpenAI globals are available for more reliable widget synchronization * **Fix**: Added animation frame cleanup logic to prevent memory leaks during component unmount * **Update**: Updated mcp-use to v1.17.3 **v0.18.7** ## Chat Conversion & Error Copy Fixes Patch release improving chat message conversion and copy behavior. * **Fix**: Copy button now copies actual error text instead of `null` * **Fix**: Chat message conversion now falls back to `parts` when `content` is empty, with improved attachment handling * **Enhancement**: Chat request streaming now uses external history for better context handling and to avoid duplicated messages * **Update**: Updated mcp-use to v1.17.2 **v0.18.6** ## Dependency Update Patch release aligned with mcp-use dependency updates. * **Update**: Updated mcp-use to v1.17.1 **v0.18.5** ## Iframe Embedding & Reverse Proxy Support Patch release with iframe embedding configuration, reverse proxy improvements, and widget rendering fixes. * **New**: `MCP_INSPECTOR_FRAME_ANCESTORS` environment variable to control which origins can embed the inspector in iframes via CSP `frame-ancestors` * **New**: `mountInspector` accepts `devMode` and `sandboxOrigin` options for deployment flexibility * **New**: Runtime config injection (`__MCP_DEV_MODE__`, `__MCP_SANDBOX_ORIGIN__` window globals) without rebuild * **Enhancement**: Server-side widget fetches convert external proxy URLs to localhost for correct content retrieval * **Enhancement**: Simplified widget asset URL rewriting for improved reverse proxy reliability * **Fix**: Infinite re-render loop in `MCPAppsRenderer` caused by excessive `useEffect` dependencies * **Update**: Updated mcp-use to v1.17.0 **v0.18.4** ![Release 0.18.4](https://mcp-use.com/api/og/release?v=0.18.4\&title=E2E%20Testing%20%26%20Refresh%20Features\&date=2026-02\&lang=inspector) ## E2E Testing & Refresh Features Patch release with comprehensive E2E testing infrastructure and enhanced UI functionality. ### E2E Testing Infrastructure * **New**: Comprehensive Playwright-based E2E test suite with full coverage for chat, connections, HMR, widgets, and command palette * **New**: GitHub Actions workflow (`.github/workflows/inspector-e2e.yml`) for automated E2E testing across multiple modes * **New**: Test fixtures for authentication servers (OAuth mock, API key, custom headers) * **New**: Test helpers for connection, authentication, and debugger tools * **New**: Test matrix for parameterized test scenarios across multiple inspector modes (mix, prod, builtin) * **New**: Widget examples for conformance testing (weather-display, status-card, display-info, apps-sdk-only-card) * **Enhancement**: Comprehensive E2E testing documentation in `tests/e2e/README.md` ### Testability Improvements * **Enhancement**: Added `data-testid` attributes across 40+ UI components for reliable element selection * **Enhancement**: Enhanced component accessibility for automated testing including connection forms, server list, command palette, chat interface, tool execution panels, resources/prompts/tools tabs, and elicitation/sampling displays ### UI Enhancements * **New**: Refresh buttons with loading states for Tools, Resources, and Prompts tabs * **New**: `ListTabHeader` component with refresh functionality and spinning icon animation * **Enhancement**: Manual refresh capability for primitives without reconnecting to server * **Fix**: Inspector now detects when `server=` query parameter contains a URL that's not already connected and automatically redirects to use `autoConnect=` instead * **Enhancement**: Added comprehensive URL parameters documentation page to inspector reference ### Widget Improvements * **Fix**: Widget pending state now correctly emulated to reflect ChatGPT behavior * **Enhancement**: MCPAppsRenderer and OpenAIComponentRenderer handle tool output and metadata more effectively * **Enhancement**: Immediate rendering of widgets even when results are pending * **Enhancement**: MessageList and ToolResultRenderer support immediate rendering of widget tools * **Enhancement**: Widget props support in ToolResultDisplay ### Server Improvements * **Enhancement**: Changed default port from 3001 to 3000 for production builds (dev still uses 3001) * **Enhancement**: Skip telemetry (PostHog/Scarf) when `NODE_ENV=test` or `MCP_USE_ANONYMIZED_TELEMETRY=false` * **New**: `start-auth-servers.ts` utility for running authentication test servers ### Dependencies * **Update**: Updated mcp-use to v1.16.4 **v0.18.3** ## Dependency Update Patch release with dependency updates. * **Update**: Updated mcp-use to v1.16.3 **v0.18.2** ## Inspector Fixes Patch release with widget behavior fix and improved URL handling. * **Fix**: Widget pending state now correctly emulated to reflect ChatGPT behavior * **Fix**: Inspector now detects when `server=` query parameter contains a URL that's not already connected and automatically redirects to use `autoConnect=` instead * **Update**: Updated mcp-use dependency to v1.16.2 **v0.18.1** ## Dependency Update Patch release aligned with mcp-use v1.16.1. * **Update**: Updated mcp-use dependency to v1.16.1 **v0.18.0** ![Release 0.18.0](https://mcp-use.com/api/og/release?v=0.18.0\&title=Chat%20Prompts%20%26%20Multimodal%20Support\&date=2026-01\&lang=inspector) ## Chat Prompts & Multimodal Support Minor release introducing prompts in chat and multimodal image support for vision-capable LLMs. ### Chat Prompts * **New**: Prompts in Chat - type / to open a prompt, run it, and include its result in the thread before sending * **Note**: Prompts with arguments are not yet supported in this release ### Multimodal Support * **New**: Image attachment support in Inspector chat * **New**: Upload and send images to vision-capable LLMs (GPT-4o, Claude, Gemini) using the paperclip button * **Enhancement**: MCP prompts that return images are now properly displayed instead of showing raw JSON * **Enhancement**: Full multimodal support for image content in chat interface ### Dependencies * **Update**: Updated mcp-use to v1.16.0 **v0.17.3** ## Theme URL Parameter Fix Patch release enabling dark mode through URL parameter. * **Fix**: Enable dark mode through theme URL parameter * **Update**: Aligned with mcp-use v1.15.3 **v0.17.2** ## HMR File Watcher Fix Patch release fixing file watcher resource exhaustion in containerized environments. * **Fix**: HMR file watcher exhausting inotify limits by properly ignoring node\_modules * **Fix**: Prevented ENOSPC errors in containerized environments caused by watching files inside `node_modules/` * **Update**: Aligned with mcp-use v1.15.2 **v0.17.1** ## Dependency Update Patch release with dependency updates. * **Update**: Updated mcp-use to v1.15.1 **v0.17.0** ![Release 0.17.0](https://mcp-use.com/api/og/release?v=0.17.0\&title=MCP%20Apps%20Support%20%26%20Landing%20Pages\&date=2026-01\&lang=inspector) ## MCP Apps Support & Landing Pages Major release introducing MCP Apps support with dual-protocol widget rendering and enhanced inspector capabilities. ### MCP Apps Support * **New**: Dual-protocol support enabling widgets to work with both MCP Apps and ChatGPT Apps SDK * **New**: `MCPAppsRenderer` component for advanced debugging and visualization * **New**: `MCPAppsDebugControls` component for widget debugging * **New**: Sandboxed iframe support with console logging and safe area insets for isolated widget rendering * **New**: Widget adapters (MCP Apps, Apps SDK) with protocol helpers for seamless cross-protocol compatibility ### Landing Pages * **New**: HTML landing page support for MCP server endpoints * **New**: Connection instructions for Claude Code, Cursor, VS Code, VS Code Insiders, and ChatGPT * **Enhancement**: Browser host normalization for server connections ### Bug Fixes & Security * **Fix**: MCP server landing now shows the external URL instead of the internal URL * **Fix**: Zod JIT compilation to prevent CSP violations in sandboxed environments * **Security**: Fixed vulnerabilities in dependencies ### Dependencies * **Update**: Updated mcp-use to v1.15.0 **v0.16.2** ## UI Enhancements & Connection Handling Patch release with improved UI components, widget security enhancements, and better connection management. ### UI Enhancements * **Enhancement**: CustomHeadersEditor with improved focus management and title prop support * **Enhancement**: Standardized proxy configuration - renamed `customHeaders` to `headers` in InspectorDashboard and ServerConnectionModal for consistency ### Widget Security * **Enhancement**: Widget security headers with frame domain support * **Enhancement**: Added `frame_domains` to widgetCSP interface for iframe embed control * **Enhancement**: Updated getWidgetSecurityHeaders to include frame\_domains in CSP for OpenAI compatibility * **Enhancement**: CSP handling in OpenAIComponentRenderer prioritizes metadata from tool results and resources ### Connection Handling * **Enhancement**: Improved server connection handling with new handleReconnect function * **Enhancement**: UI elements reflect connection states more accurately with better hover effects and error displays * **Enhancement**: Enhanced error handling for unauthorized connections with clearer user feedback * **Enhancement**: State management for connecting servers in InspectorDashboard ### Dependencies * **Update**: Aligned with mcp-use v1.14.2 improvements **v0.16.1** ## Tool Output Display Fix Patch release with tool output display improvement. * **Fix**: Inspector tool output now displays at full height for better content visibility * **Update**: Aligned with mcp-use v1.14.1 **v0.16.0** ![Release 0.16.0](https://mcp-use.com/api/og/release?v=0.16.0\&title=RPC%20Message%20Management%20%26%20LangChain%20Fixes\&date=2026-01\&lang=inspector) ## RPC Message Management & LangChain Fixes Release with enhanced RPC message handling and critical bug fixes for Anthropic integration. ### RPC Message Management * **New**: Copy functionality for RPC messages in Prompts, Resources, and Tools tabs * **New**: Reusable `RpcPanel` component for consistent RPC message handling across tabs * **New**: Export functionality for RPC messages * **Enhancement**: Improved panel management with refactored ResizablePanel components ### Resource Properties Management * **New**: Custom properties support for resources - dynamically configure resource properties * **New**: `PropsSelect` component for intuitive property selection and management * **New**: `PropsConfigDialog` with AI-powered property suggestions using Claude * **New**: `SchemaFormField` component for rendering JSON schema-based forms * **New**: `usePropsLLM` hook leveraging Claude for intelligent property suggestions * **New**: `useResourceProps` hook for managing resource props state ### Inspector Improvements * **Enhancement**: Extracted MCP prompts logic into reusable `useMCPPrompts` hook * **Enhancement**: Server metadata display with website URLs and icons * **Enhancement**: Better tool management - cleared selected tools when removed from list * **Enhancement**: Enhanced `JSONDisplay` with improved line wrapping and font size for better readability * **Enhancement**: `ToolExecutionPanel` now includes collapsible description section * **Enhancement**: Integrated JSON metadata visualization in tool execution panel * **Enhancement**: `McpUIRenderer` and `OpenAIComponentRenderer` support `customProps` parameter * **Enhancement**: `ResourceResultDisplay` with dynamic property configuration UI * **Enhancement**: Enhanced Prism theme support for better code highlighting * **Enhancement**: Updated `useMcp` hook to expose `mcpServerUrl` for resource operations ### Bug Fixes * **Fix**: Resolved Anthropic `tool_use.id` required error with LangChain 1.3.10 update * **Fix**: Proper tool\_call ID generation ensuring unique IDs for all tool\_use blocks * **Fix**: Improved backward compatibility by checking both 'headers' and 'customHeaders' ### Dependencies * **Update**: `@langchain/anthropic` to 1.3.10 * **Update**: `@langchain/core` to 1.1.15 * **Update**: `langchain` to 1.2.10 * **Update**: `react-resizable-panels` to 4.4.1 **v0.15.3** ## Dependency Update Patch release with dependency updates. * **Enhancement**: Updated mcp-use dependency to latest version **v0.15.2** ## OAuth Proxy URL Handling Improvements Patch release with improved OAuth proxy URL handling and connection logic. * **Enhancement**: Improved OAuth proxy URL derivation from callback URLs * **Enhancement**: Better handling of root path callbacks in OAuth flow * **Enhancement**: Clearer separation between OAuth proxy URLs and connection URLs * **Fix**: Maintains valid OAuth tokens across sessions by not clearing OAuth storage before connecting **v0.15.1** ## URL Validation & LocalStorage Enhancements Patch release with URL validation improvements and localStorage functionality. * **Enhancement**: Automatically prepends "https\://" to URLs without protocol for better user experience * **Enhancement**: Improved URL validation logic in InspectorDashboard and ServerConnectionModal * **Enhancement**: Added localStorage clearing functionality for MCP-related items to help with troubleshooting * **Fix**: Enhanced localStorage checks to verify both existence and functional methods before usage * **Fix**: Clear stale OAuth storage before connecting to ensure fresh authentication flow **v0.15.0** ![Release 0.15.0](https://mcp-use.com/api/og/release?v=0.15.0\&title=Chat%20Stop%20Functionality\&date=2026-01\&lang=inspector) ## Chat Stop Functionality Minor release adding the ability to stop ongoing chat responses in the inspector. ### Chat Functionality * **New**: Stop functionality for chat responses - users can now abort streaming responses * **New**: Export stop function from `useChatMessagesClientSide` hook connected to `abortControllerRef` * **New**: `abortControllerRef` added to `useChatMessages` hook for proper abort control * **Enhancement**: Stop button connected to abort streaming responses for better user control ### UI & Authentication * **Enhancement**: Simplified authentication button logic in InspectorDashboard * **Enhancement**: Updated multi-server example to link directly to authentication URL * **Fix**: Updated dependency `hono` to 4.11.4 **v0.14.6** ## Dependency Update Patch release with dependency updates. * **Enhancement**: Updated mcp-use dependency to latest version **v0.14.5** ## OAuth & Metadata Enhancements Minor release with OAuth proxy support, metadata caching, and favicon improvements. ### OAuth & Client Info * **Enhancement**: Enhanced OAuth proxy to support gateway/proxy scenarios (e.g., Supabase MCP servers) * **Enhancement**: Client info support with branding displayed on OAuth consent pages * **Enhancement**: Server metadata caching for immediate display on reconnect - improves UX by showing server info instantly * **Enhancement**: Improved logging middleware for API routes with better debugging visibility * **Enhancement**: Enabled OAuth proxy logging for better flow visibility ### Favicon Detection * **Enhancement**: Enhanced favicon detector to try all subdomain levels (e.g., mcp.supabase.com → supabase.com → com) * **Enhancement**: Detection of default vs custom favicons using JSON API response * **Enhancement**: Prefer non-default favicons when available ### Bug Fixes * **Fix**: Remove import from "mcp-use" which causes langchain import in server * **Enhancement**: Enhanced synchronization for tools, prompts, and resources during HMR **v0.14.4** ## Connection Fix Patch release fixing autoconnect configuration parsing. * **Fix**: Autoconnect now correctly parses config objects in addition to string URLs **v0.14.3** ## Security Fixes & OAuth Improvements Patch release addressing multiple security vulnerabilities and fixing OAuth flow issues. ### Security Fixes * **Security**: Fixed 13 vulnerabilities (3 moderate, 10 high) * **Security**: Updated `langchain` to 1.2.3 (fixes serialization injection vulnerability) * **Security**: Updated `@langchain/core` to 1.1.8 (fixes serialization injection vulnerability) * **Security**: Updated `react-router` to 7.12.0 (fixes XSS and CSRF vulnerabilities) * **Security**: Added overrides for `qs` and `preact` vulnerabilities ### OAuth & Connection Improvements * **Fix**: Resolved OAuth flow looping issue by removing duplicate fallback logic * **Enhancement**: Simplified connection handling with consolidated state management * **Enhancement**: Enhanced OAuth authentication flow with improved connection settings * **Enhancement**: Improved auto-connect functionality with better proxy handling and error management * **Enhancement**: Enhanced theme toggling with dropdown menu for better UX and accessibility * **Enhancement**: Updated OAuth flow management in browser provider and callback handling **v0.14.2** ![Release 0.14.2](https://mcp-use.com/api/og/release?v=0.14.2\&title=Automatic%20Proxy%20Fallback%20%26%20Reconnect\&date=2026-01\&lang=inspector) ## Automatic Proxy Fallback & Reconnect Minor release with automatic proxy fallback, OAuth proxy support, and reconnect functionality. ### Breaking Changes (with Deprecation Warnings) * **Breaking**: Renamed `customHeaders` to `headers` across all APIs. Old name still works but shows deprecation warnings. * **Breaking**: Renamed `samplingCallback` to `onSampling` for consistency. Old name still works but shows deprecation warnings. ### New Features * **New**: Reconnect functionality for failed connections - reconnect button in InspectorDashboard UI * **New**: Reconnect option in dropdown menu for failed connections * **New**: Configurable clientInfo support for MCP connection initialization with full metadata * **New**: Automatic Proxy Fallback - automatically retries failed connections through proxy * **New**: OAuth Proxy Support with oauthProxyUrl configuration ### Improvements * **Enhancement**: Better detection of OAuth discovery failures, CORS errors, and connection issues * **Enhancement**: OAuth provider uses original target URL for discovery, not proxy URL * **Enhancement**: HttpConnector automatic reconnection disabled, shifting responsibility to higher-level logic for better control ### Bug Fixes * **Fix**: Custom headers now correctly included when copying connection configuration from saved tiles * **Fix**: Headers correctly read from localStorage where stored in proxyConfig.customHeaders **v0.14.1** ## Security Update Patch release with security fixes and build improvements. * **Security**: Updated `@modelcontextprotocol/sdk` to 1.25.2 (fixes ReDoS vulnerability in UriTemplate regex patterns) * **Fix**: Updated building script to correctly export types for inspector/client components **v0.14.0** ## Multi-Server Support & Browser Compatibility Release with multi-server management, improved UI responsiveness, and enhanced browser compatibility. ### Breaking Changes * **Breaking**: Removed `winston` dependency. The logging system now uses a simple console logger that works in both browser and Node.js environments. ### Multi-Server Support * **New**: Multi-server management with `McpClientProvider` to manage multiple MCP server connections * **New**: Dynamic addition and removal of servers in React applications * **New**: Pluggable storage system with `LocalStorageProvider` and `MemoryStorageProvider` for flexible server configuration persistence * **Enhancement**: Refactored `useMcp` hook for better multi-server support * **Enhancement**: Removed obsolete `McpContext` (replaced with `McpClientProvider`) ### UI & UX Improvements * **Enhancement**: Improved UI responsiveness with enhanced mobile and tablet layouts and adaptive component visibility * **Enhancement**: Better server management with refactored server connection handling, improved icon display, and status tracking * **Enhancement**: Enhanced debugging with detailed logging in Layout and useAutoConnect components for better monitoring of server connection states * **Enhancement**: Simplified connection settings by removing deprecated transport types * **Enhancement**: Improved server icon support and component interactions * **Enhancement**: Added embedded mode support * **New**: Support for passing tab as query parameter for direct navigation * **New**: Prompt rendering support with enhanced display * **New**: Add to Client dropdown for quickly adding MCP servers to Cursor, VS Code, Claude Desktop, and CLI tools ### Browser Compatibility * **Enhancement**: Enhanced inspector components for better browser compatibility * **Enhancement**: Better configuration handling and MCP proxy integration * **Enhancement**: Improved browser-based MCP client with better connection handling ### Bug Fixes * **Fix**: Query URL handling in built mode now preserves arguments correctly * **Fix**: Server connection retrieval in `OpenAIComponentRenderer` to directly access connections array * **Fix**: Add client SDKs to add to client dropdown * **Fix**: Respect query tab parameter when existing server is already connected **v0.13.2** ## Documentation Updates - **Enhancement**: Updated examples and documentation to use preferred methods and APIs **v0.13.1** ## Bug Fixes - **Fix**: Widget props not picked up when using Zod schemas **v0.13.0** ## Session Management & Architecture Improvements Release aligned with mcp-use v1.11.0, featuring session management architecture and improved inspector capabilities. ### Breaking Changes * **Breaking**: WebSocket transport support removed. Use streamable HTTP or SSE transports instead. * **Breaking**: LangChain adapter moved from main entry point to `mcp-use/adapters` subpath. ### Session Management * **Enhancement**: Support for pluggable session management architecture with Redis support * **Enhancement**: Improved session persistence and connection handling * **Enhancement**: Better support for distributed deployments with cross-server notifications ### Inspector Features * **Enhancement**: Enhanced connection handling with automatic 404 handling and re-initialization * **Enhancement**: Improved tool, resource, and prompt management * **Enhancement**: Better integration with session management architecture * **Enhancement**: Enhanced debugging capabilities with better error handling ### Widget Support * **Enhancement**: Improved widget rendering and debugging for ChatGPT Apps * **Enhancement**: Better widget data handling and state management * **Enhancement**: Enhanced OpenAI component renderer with improved functionality ### UI Improvements * **Enhancement**: Better connection settings UI * **Enhancement**: Improved server management interface * **Enhancement**: Enhanced tool result display and formatting **v0.12.6** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.12.5** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.12.4** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.12.3** ## Bug Fixes - **Fix**: Deno 3 compatibility fixes **v0.12.2** ## Bug Fixes - **Fix**: Updated Zod error handling **v0.12.1** ## Bug Fixes - **Fix**: Zod import in official SDK - **Enhancement**: Added repository metadata in package.json **v0.12.0** ## Elicitation Support & API Improvements Release aligned with mcp-use v1.10.0, featuring elicitation support and enhanced inspector capabilities. ### Breaking Changes * **Breaking**: Server API renamed `createMCPServer()` factory function to `MCPServer` class constructor * **Breaking**: Session API replaced `session.connector.tools`, `session.connector.callTool()`, etc. with direct methods: `session.tools`, `session.callTool()`, etc. * **Breaking**: OAuth environment variables standardized to `MCP_USE_OAUTH_*` prefix ### New Features * **New**: Elicitation support in inspector - servers can request user input through clients * **New**: Client Capabilities API with `ctx.client.can()` and `ctx.client.capabilities()` * **New**: Session Notifications API with `ctx.sendNotification()` and `ctx.sendNotificationToSession()` * **New**: Session Info API with `ctx.session.sessionId` to access current session ID * **New**: Resource Template Flat Structure support with `uriTemplate` directly on definition * **New**: Resource Template Callback Signatures supporting multiple signatures ### Improvements * **Enhancement**: Enhanced type inference for resource template callbacks * **Enhancement**: Client capabilities tracking during initialization * **Enhancement**: Major documentation refactoring and restructuring * **Enhancement**: Edge runtime support improvements * **Enhancement**: Transport bug fixes **v0.11.0** ## Elicitation Support - **New**: Added support for elicitation in inspector, enabling servers to request user input through clients - **Fix**: Transport bug fixes **v0.10.1** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.10.0** ## Sampling Support - **New**: Added sampling support in inspector with LLM sampling capabilities - **Fix**: Long running sampling requests no longer timeout after 60 seconds - **Enhancement**: Better handling of extended sampling operations **v0.9.2** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.9.1** ## Bug Fixes - **Fix**: Fixed bin entry issue for pnpm installation - **Enhancement**: Standardized import statement formatting across multiple files **v0.9.0** ## OAuth Authentication System Release with complete OAuth 2.0 support and enhanced inspector capabilities. ### New Features * **New**: Complete OAuth 2.0 authentication framework with built-in providers (Auth0, WorkOS, Supabase, Keycloak) * **New**: OAuth middleware and routes for server-side OAuth flow handling * **New**: OAuth callback component in inspector for authentication flows * **New**: Context storage with async local storage for request-scoped context * **New**: Response helpers for standardized HTTP responses and error handling * **New**: Runtime detection utilities for Node.js, Bun, and Deno environments ### Inspector Enhancements * **Enhancement**: Enhanced useMcp hook with improved connection management and OAuth support * **Enhancement**: Enhanced inspector dashboard with OAuth configuration UI * **Enhancement**: Better authentication flow handling with OAuth integration * **Enhancement**: Improved auto-connect with enhanced connection recovery * **Enhancement**: Enhanced HTTP connectors with OAuth token handling ### UI Improvements * **Fix**: Fixed scrolls in tools, resources, and prompts tab * **Fix**: Fixed models and API keys box in inspector chat * **Fix**: Fixed rendering of table, inline-code, code and images in inspector chat * **Fix**: Fixed padding of RPC panels * **New**: Added enum input display for tools * **Enhancement**: Bundle minification (9.7mb → 4.2 mb) ### Bug Fixes * **Fix**: Switched to fork SDK to fix Zod errors on Deno runtime * **Fix**: Optimized dependencies **v0.8.3** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.8.2** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.8.1** ## Bug Fixes - **Fix**: Fixed auto-connect proxy fallback behavior - **Fix**: Fixed connection config updates not applying when connection already exists - **Enhancement**: Auto-switch (proxy fallback) now automatically enabled during auto-connect flow - **Enhancement**: Improved error messages for connection failures **v0.8.0** ## Notifications, Sampling & OpenAI Apps SDK Integration Release with bidirectional notifications, LLM sampling, and comprehensive OpenAI Apps SDK support. ### New Features * **New**: Bidirectional notification support between clients and servers * **New**: LLM sampling capabilities allowing MCP tools to request completions from connected clients * **New**: Widget build ID support for cache busting in widget UI resources * **New**: Inspector notifications tab with real-time display * **New**: Server capabilities modal showing supported MCP features * **New**: RPC message logging support in inspector ### OpenAI Apps SDK Integration * **New**: McpUseProvider component combining React setup (StrictMode, ThemeProvider, BrowserRouter, ErrorBoundary) * **New**: WidgetControls component with debug overlay and view controls (fullscreen, PIP) * **New**: useWidget hook for type-safe React adapter to OpenAI Apps SDK API * **New**: ErrorBoundary component for graceful error handling * **New**: Image component handling data URLs and public file paths * **New**: ThemeProvider for consistent theme management * **New**: WidgetInspectorControls for inspector-specific debugging * **New**: Console proxy toggle for iframe console logs * **New**: Product search result widget template with carousel and accordion components * **New**: Folder-based widget support with automatic detection * **New**: Public folder support for static assets ### Inspector Enhancements * **Enhancement**: Enhanced OpenAIComponentRenderer with better height calculation and theme support * **Enhancement**: Enhanced ToolResultDisplay with multiple content types (text, image, audio, resource links) * **Enhancement**: Resizable panels with collapse support * **Enhancement**: Better widget security headers and CSP configuration * **Enhancement**: Enhanced widget data handling and state management ### Improvements * **Enhancement**: Refactored HTTP transport to reuse sessions across requests * **Enhancement**: Session management with tracking and automatic cleanup * **Enhancement**: Roots support in connectors and session API * **Enhancement**: Enhanced search\_tools with metadata * **Enhancement**: Improved SSR configuration with proper Vite settings ### Bug Fixes * **Fix**: Fixed iframe height calculation issues * **Fix**: Fixed theme flashing on widget load * **Fix**: Fixed CSP header generation for dev mode * **Fix**: Fixed asset loading in dev widget proxy * **Fix**: Fixed console logging in iframe * **Fix**: Fixed widget state inspection * **Fix**: Fixed resizable panel collapse behavior **v0.7.1** ## Bug Fixes & Improvements - **Fix**: Fixed auto-connect proxy fallback behavior - **Fix**: Fixed connection config updates not applying when connection already exists - **Enhancement**: Auto-switch (proxy fallback) now automatically enabled during auto-connect flow - **Enhancement**: Improved error messages for connection failures **v0.7.0** ## Code Mode Support - **New**: Code Mode feature allowing agents to execute code using MCP tools - **Enhancement**: Enhanced MCPClient with code execution configuration - **Enhancement**: Comprehensive tests for code execution functionality **v0.6.1** ## Bug Fixes - **Fix**: Various bug fixes and improvements **v0.6.0** ## Edge Runtime Support - **Major**: Migrated to Hono framework for edge runtime support - **New**: Runtime detection for Deno and Node.js environments * **New**: Enhanced inspector dashboard with improved connection handling - **Enhancement**: Better auto-connection logic with error handling and retry mechanisms **v0.5.3** ## Bug Fixes & Improvements - **Fix**: Various bug fixes and stability improvements - **Enhancement**: Dependency updates **v0.5.2** ## Bug Fixes & Improvements - **Fix**: Various bug fixes and stability improvements - **Enhancement**: Dependency updates **v0.5.1** ## Bug Fixes - **Fix**: Various bug fixes and improvements **v0.5.0** ## LangChain 1.0.0 Support - **Major**: Support for LangChain 1.0.0 - **Fix**: Model type compatibility for LangChain 1.0.0 - **Enhancement**: Set CLI and inspector as dependencies **v0.4.13** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.12** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.11** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.10** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.9** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.8** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.7** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.6** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.5** ## Bug Fixes - **Fix**: Fixed inspector chat formatting **v0.4.4** ## Bug Fixes - **Fix**: Fixed inspector chat - **Fix**: Fixed inspector shadow **v0.4.3** ## Major Refactoring & Apps SDK Support Major refactoring with improved architecture and enhanced Apps SDK support. ### Major Refactoring * **Refactor**: Server architecture refactored with major improvements to routing and middleware * **Refactor**: Removed legacy `mcp-inspector.ts` file in favor of modular architecture * **Refactor**: Added new `cli.ts` for improved command-line interface handling * **Refactor**: Added `utils.ts` and `shared-utils-browser.ts` for better code organization * **Refactor**: Enhanced `shared-routes.ts` with improved route handling and error management ### Apps SDK Support * **Enhancement**: Enhanced widget data handling and state management * **New**: Added `readResource` method in MCPInspector for fetching resources based on server ID * **Enhancement**: Enhanced OpenAI component renderer to utilize serverId and readResource * **Enhancement**: Improved safe data serialization for widget state management ### UI/UX Improvements * **Enhancement**: Enhanced ConnectionSettingsForm with copy configuration feature * **Enhancement**: Updated OpenAIComponentRenderer to dynamically adjust iframe height * **Enhancement**: Improved resource display with duration metrics and enhanced badge styling * **Enhancement**: Enhanced LayoutHeader with dynamic badge styling * **Fix**: Fixed scrollable tool parameters for better user experience * **Enhancement**: Added mobile-responsive hiding features ### Bug Fixes * **Fix**: Fixed inspector mounting logic by simplifying server URL handling * **Fix**: Fixed linting issues across multiple components * **Fix**: Fixed server configuration for improved stability **v0.4.2** ## Auto-Connection & Multi-Server Support - **New**: Auto-connection functionality - inspector now automatically connects to MCP servers on startup * **New**: Multi-server support - enhanced support for connecting to multiple MCP servers simultaneously - **New**: Client-side chat functionality with improved message handling - **New**: Resource handling with enhanced chat components - **Enhancement**: Streamlined routing with refactored server and client routing - **Enhancement**: Enhanced connection handling with improved auto-connection logic - **Enhancement**: Better UI components with updated Layout, ChatTab, and ToolsTab components - **Fix**: Fixed connection handling in InspectorDashboard - **Fix**: Improved error messages in useMcp hook **v0.4.1** ## Bug Fixes - **Fix**: Minor fixes and improvements **v0.4.0** ## Major Refactor & Apps SDK Initial Integration Major refactor aligning inspector with mcp-use TypeScript package and initial Apps SDK integration. ### Major Refactoring * **Refactor**: Migrated from CommonJS to ESM format * **Refactor**: Added input validation for port and URL * **Refactor**: Improved error handling and logging * **Refactor**: Added `open` package for cross-platform browser launching * **Refactor**: Reorganized component structure (moved to `src/client/components/`) * **Refactor**: Refactored ChatTab to use streaming API and custom hooks * **Refactor**: Enhanced InspectorDashboard with auto-connect functionality * **Refactor**: Improved CommandPalette with better item selection * **Refactor**: Updated routing to use query parameters ### New Components * **New**: Chat components: `AssistantMessage`, `UserMessage`, `ToolCallDisplay`, `MCPUIResource`, `MessageList` * **New**: UI components: `aurora-background`, `text-shimmer`, `sheet`, `switch`, `kbd`, `shimmer-button`, `status-dot` * **New**: Form components: `ConnectionSettingsForm`, `ServerDropdown` * **New**: Tool components: `ToolExecutionPanel`, `ToolResultDisplay`, `SaveRequestDialog` * **New**: Resource components: `ResourceResultDisplay`, `ResourcesList` ### Apps SDK Integration * **New**: OpenAI Apps SDK integration with UI resource type * **New**: Enhanced MCP-UI adapter for Apps SDK metadata * **New**: Resource URI format supporting `ui://widget/` scheme ### Bug Fixes * **Fix**: Fixed CLI binary format and package configuration * **Fix**: Changed CLI build format from CommonJS to ESM * **Fix**: Added input validation for port and URL arguments * **Fix**: Improved error logging in API routes * **Fix**: Fixed async/await bugs in static file serving # CLI Usage Source: https://docs.mcp-use.com/inspector/cli Run the MCP Inspector from the command line The MCP Inspector can be run directly from the command line using `npx`, making it easy to quickly inspect and debug MCP servers without installing anything globally. ## Quick Start Run the inspector with a single command: ```bash theme={null} npx @mcp-use/inspector ``` This will: * Start the inspector server on an available port (default: 8080) * Automatically open your browser to the inspector interface * Display the URL in the terminal ## Command Options ### `--url ` Auto-connect to an MCP server when the inspector starts. ```bash theme={null} npx @mcp-use/inspector --url http://localhost:3000/mcp ``` ### `--port ` Specify the starting port number. The inspector will find the next available port if the specified port is already in use. ```bash theme={null} npx @mcp-use/inspector --port 9000 ``` **Default:** `8080` **Port Range:** Must be between 1 and 65535 ### `--no-open` Prevent the inspector from automatically opening a browser tab when it starts. Useful in CI/CD pipelines, headless environments, or when you prefer to open the URL manually. ```bash theme={null} npx @mcp-use/inspector --no-open ``` You can combine it with other flags: ```bash theme={null} npx @mcp-use/inspector --url http://localhost:3000/mcp --port 9000 --no-open ``` ### `--help, -h` Display help information and available options. ```bash theme={null} npx @mcp-use/inspector --help ``` ## Environment Variables ### `MCP_INSPECTOR_FRAME_ANCESTORS` Configure which origins can embed the inspector widget in iframes. This is useful when embedding the inspector into your own application or when testing widgets from different domains. **Default behavior:** * **Development mode**: `*` (allows all origins for easier development) * **Production mode**: `'self'` (same-origin only for security) **Format:** Space-separated list of origins or `*` for all origins **Examples:** ```bash theme={null} # Allow embedding from specific domains MCP_INSPECTOR_FRAME_ANCESTORS="https://app.example.com https://dev.example.com" npx @mcp-use/inspector # Allow embedding from any domain (useful for development) MCP_INSPECTOR_FRAME_ANCESTORS="*" npx @mcp-use/inspector # Multiple origins with wildcards MCP_INSPECTOR_FRAME_ANCESTORS="https://*.example.com http://localhost:*" npx @mcp-use/inspector ``` > [!NOTE] > > In production deployments, it's recommended to explicitly list allowed origins rather than using `*` to prevent unauthorized embedding. > [!TIP] > > When running in development mode (`npm run dev`), the inspector automatically allows all origins by default, so you don't need to set this variable unless you want to test production CSP policies. ### `MCP_URL` Set the external base URL for your MCP server. This is useful when running behind a reverse proxy (ngrok, E2B sandboxes, Cloudflare tunnels) where the public URL differs from `localhost`. When set, the CLI will use this URL for widget asset URLs and Vite HMR WebSocket connections, ensuring everything works correctly through the proxy. **Default behavior:** * If not set, the CLI generates a `localhost` URL automatically * If set, the CLI preserves your value and does not overwrite it **Examples:** ```bash theme={null} # ngrok tunnel MCP_URL=https://abc123.ngrok.io npx @mcp-use/cli dev # E2B sandbox MCP_URL=https://3000-abc123.e2b.app npx @mcp-use/cli dev # Cloudflare tunnel MCP_URL=https://my-tunnel.trycloudflare.com npx @mcp-use/cli dev ``` > [!TIP] > > When using a reverse proxy, set `MCP_URL` to the public-facing URL. This ensures widget hot-reload (HMR) and asset loading work correctly through the proxy. ## Related Documentation * [Getting Started](/inspector/index) - Overview of the inspector * [Connection Settings](/inspector/connection-settings) - Advanced connection configuration * [Mount the Inspector](/inspector/integration) - Serve the Inspector from an app # Command Palette Source: https://docs.mcp-use.com/inspector/command-palette Search Inspector servers, tools, prompts, resources, saved requests, and client setup actions. Press `Cmd/Ctrl + K` to open the command palette from anywhere in the Inspector. It searches the current Inspector state and lets you jump directly to the item you choose. ## What you can open The command palette searches: * connected servers by display name or URL * tools by name, description, and server * prompts by name, description, and server * resources by name, URI, and server * saved tool requests * global navigation actions * Add to Client actions for supported clients Search is fuzzy, so partial words usually work. For example, `lin iss` can match a Linear issue tool if that tool is connected. ## Run a tool from search Use the command palette when you know the tool name and want to skip tab navigation. 1. Press `Cmd/Ctrl + K`. 2. Type the tool name or part of its description. 3. Select the tool. 4. Fill the generated input form. 5. Run the tool. The Inspector opens the Tools tab with that tool selected. ## Load a saved request Saved requests appear in their own results category. Select one to open the matching tool with its saved arguments already loaded. Use saved requests for repeatable calls such as regression checks, widget test cases, or long input payloads. ## Switch servers When more than one server is connected, search by server display name or URL. Selecting a server opens that server's Inspector view. Display names are useful here. Rename saved servers from [Connection settings](/inspector/connection-settings) when several URLs are hard to scan. ## Add a server to a client Add to Client commands appear when a connected server can be installed or copied into a supported client. Search for the client name, then choose the matching action. Depending on the client, the action may open a deep link, download a configuration file, or copy a command to the clipboard. ## Keyboard controls | Key | Action | | - | - | | `Cmd/Ctrl + K` | Open the command palette. | | `Up` / `Down` | Move through results. | | `Enter` | Open the selected result. | | `Esc` | Close the palette. | For the full shortcut reference, see [Keyboard shortcuts](/inspector/keyboard-shortcuts). # Connection settings Source: https://docs.mcp-use.com/inspector/connection-settings Choose how the Inspector connects to an MCP server. Most servers work with only a transport and URL. Change connection settings when the browser cannot reach the server directly, when you want clearer names for saved servers, when OAuth needs pre-registered credentials, or when long-running tools need more time. ## Choose Auto, Direct, or Via Proxy The Inspector uses **Auto** mode by default: it tries a direct browser connection first, then falls back to the configured Inspector proxy if direct access fails because of CORS or network policy. | Connection mode | Use it when | Avoid it when | | - | - | - | | **Auto** | You want the Inspector to try Direct first and fall back to the proxy when needed. | You need to test one specific connection path. | | **Direct** | The server is local, public, or reachable from your browser. | The browser blocks the request because of CORS or network policy. | | **Via Proxy** | The browser is blocked by CORS, or you need to test proxy behavior. | The server works directly; proxying adds another moving part. | ## Name saved servers Set a display name when several saved servers have similar URLs. Changing only the display name updates labels in the dashboard, server list, header, command palette, and server picker. It does not reconnect the server or clear auth tokens. ## Add headers only when the server requires them Use custom headers for server-specific requirements such as bearer tokens, API keys, or version headers. Header values are used for the live connection only. They are intentionally not saved or restored after a reload, so supply them again at runtime. Prefer OAuth when the server supports it. > [!WARNING] > > Copy Config includes current form values. Remove OAuth tokens, API keys, and > other secrets before sharing exported configuration. ## Configure OAuth By default the inspector relies on Dynamic Client Registration (DCR), so no credentials are needed. Use the Authentication dialog when the upstream auth server doesn't expose `registration_endpoint` (common for proxy-mode servers fronting Slack, WorkOS, or GitHub). OAuth client secrets are runtime-only and are not restored after a reload. | Field | When to set it | | - | - | | Client ID | Use a pre-registered OAuth client instead of DCR. | | Client Secret | Use a confidential client; the SDK switches token endpoint auth away from `none`. | | Scope | Request a provider-specific space-separated scope list. | When a server protects the whole connection, it enters `pending_auth`. Click **Authenticate**, complete the provider flow, and return to the Inspector. If a popup is blocked, use the open-auth-page fallback link. Mixed-auth servers behave differently: the anonymous connection remains `ready`, and the Inspector shows **This server is using mixed auth** with an **Authenticate** action. Public operations remain available. You can authenticate up front, or wait for a protected tool, resource, or prompt to return a wire-level OAuth challenge and then authenticate. The classification comes from RFC 9728 protected-resource metadata discovered by the official MCP SDK after a successful anonymous connection. The Inspector does not use host-specific rules or interpret tool-level `isError` text as an OAuth challenge. Browser OAuth session values are encrypted at rest with AES-256-GCM. The non-extractable origin key is kept in IndexedDB, while versioned ciphertext envelopes remain in localStorage so popup storage events and reload persistence continue to work. ## Configuration Import/Export Use **Copy Config** to export the current connection form as JSON. Paste JSON into the URL field to populate the form in another Inspector instance. Example configuration: ```json theme={null} { "url": "https://mcp.example.com/mcp", "transportType": "http", "connectionMode": "auto", "headers": { "Authorization": "Bearer token123" }, "requestTimeout": 10000, "resetTimeoutOnProgress": true, "maxTotalTimeout": 60000, "oauth": { "clientId": "your-client-id", "clientSecret": "your-client-secret", "scope": "read write" } } ``` > [!NOTE] > > The paste detection only works in the URL field. Remove OAuth tokens, API keys, and other secrets before sharing a copied config. ## URL and tabs The Inspector keeps the active tab in the page URL (`?tab=...`). Switching tabs updates the query string so a refresh or shared link restores the same view. ## Tune timeouts for long work Use timeout settings only when a valid tool call or resource read needs more time. | Setting | Default | What it controls | | - | - | - | | Request timeout | `10000` ms | Time allowed for one request. | | Maximum total timeout | `60000` ms | Total time allowed across retries and progress updates. | If a request times out, first confirm the server eventually responds. Then raise the timeout to match the expected tool runtime. # Debug widgets in the Inspector Source: https://docs.mcp-use.com/inspector/debugging-chatgpt-apps Test MCP Apps widgets, ChatGPT compatibility, layout, CSP, and widget data in the Inspector. Use the Inspector to debug a widget before you try it in a production host. The fastest loop is: connect your server, run the tool that returns the widget, inspect the widget data, then test layout, display modes, and CSP. For building widgets, start with [Build widgets](/typescript/mcp-apps/widgets). For hook fields and host actions, use the [`useWidget()` API reference](/typescript/api-reference/react/usewidget). ## Connect the widget server Run your mcp-use app locally: ```bash theme={null} npm run dev ``` Open `http://localhost:3000/mcp/inspector` and connect to `http://localhost:3000/mcp`. If the server is remote, connect to its MCP endpoint instead. Use **Direct** first, then try **Via Proxy** only when the browser cannot reach the server directly. ## Run the widget-returning tool Open the **Tools** tab, select the tool that returns the widget, and run it with a small input. The widget should render below the tool result. The raw result should include the widget metadata and the structured data passed to the widget. If the tool succeeds but no widget renders, check these values first: * `widget.name` in the server tool definition * the matching folder under `resources/` * the tool result metadata that points to the widget resource * browser console errors from the widget iframe ## Switch protocols when compatibility matters The Inspector can test MCP Apps behavior and ChatGPT Apps SDK compatibility for widgets that support both runtimes. Use the protocol toggle when it appears: | Protocol | What it tests | | - | - | | **MCP Apps** | The standard MCP Apps bridge over `postMessage`. | | **ChatGPT Apps** | ChatGPT compatibility behavior, including Apps SDK-style host globals. | Prefer `useWidget()` and other `mcp-use/react` hooks in widget code. They abstract over the runtime differences that the Inspector is testing. See [Apps SDK compatibility](/typescript/mcp-apps/apps-sdk-compatibility) when you need ChatGPT-specific behavior. ## Inspect props, output, metadata, and state Use the widget debug panels to confirm what the widget receives. | Data | What to verify | | - | - | | `props` | The structured data the widget renders. | | `output` | The raw structured tool output, when exposed separately. | | `metadata` | Widget-only metadata such as timestamps, cache info, or host hints. | | `state` | Persisted widget state after user interactions. | | tool input | Arguments passed to the tool that produced the widget. | When `props` are missing, compare the server's `outputSchema` with the widget's expected prop shape. They should describe the same fields. ## Test layout and display modes Use the debug controls to test the widget in the contexts a host may provide. Check: * inline, picture-in-picture, and fullscreen display modes * desktop, tablet, and mobile sizing * touch and hover behavior * light and dark themes * locale and timezone-dependent formatting * safe-area insets for mobile layouts The host may grant a different display mode than the widget requests. Read `displayMode` from `useWidget()` when the current mode matters. ## Test Content Security Policy Use the widget-declared CSP mode before shipping a widget that loads external APIs, images, scripts, styles, or embeds. If the widget works in permissive mode but fails with widget-declared CSP, update the widget CSP configuration. See [Content Security Policy](/typescript/mcp-apps/content-security-policy) for the server and widget settings. ## Use console output Open browser DevTools while the widget is rendered. Console messages from the widget iframe help identify runtime errors, blocked requests, CSP violations, missing props, and failed tool calls. Keep console output intentional. Log the minimum state needed to debug the widget, then remove noisy logs before release. ## Test the widget in chat After the tool works directly, open the **Chat** tab and ask the model to use the tool. Use chat to verify end-to-end behavior: * the model chooses the right tool * the tool receives valid arguments * the model-visible text output is useful * the widget renders with the same structured data * widget actions such as tool calls, state updates, follow-up messages, and display-mode requests behave as expected Use the Tools tab again when you need to isolate whether a failure is in the tool, widget, or model behavior. ## Troubleshoot missing widgets If no widget appears, start with the smallest failing case. | Symptom | Check | | - | - | | Tool result appears, but no widget appears. | Confirm `widget.name` matches a folder under `resources/`. | | Widget frame appears blank. | Check iframe console errors and missing required props. | | Widget loads in permissive CSP only. | Add the required domains to widget CSP. | | ChatGPT protocol fails, but MCP Apps works. | Check [Apps SDK compatibility](/typescript/mcp-apps/apps-sdk-compatibility). | | A widget action fails. | Verify the tool name, arguments, auth state, and iframe console logs. | ## Next steps * Use [Build widgets](/typescript/mcp-apps/widgets) to review the server and widget structure. * Use [Interactivity](/typescript/mcp-apps/interactivity) to add tool calls, state, follow-up messages, and display controls. * Use [`useWidget()`](/typescript/api-reference/react/usewidget) for the full hook reference. # Inspector Source: https://docs.mcp-use.com/inspector/index Connect to an MCP server, run tools, inspect resources and prompts, and debug widgets. Use the Inspector when you need to test an MCP server from the browser. It lets you connect to a server, call tools with typed inputs, inspect resources and prompts, try chat, preview widgets, and copy client setup commands. [![Try this live](https://mintcdn.com/mcpuse/C8kWie3B44RcXcXB/images/UseLiveSmall.svg?fit=max\&auto=format\&n=C8kWie3B44RcXcXB\&q=85\&s=1e958317e42d5aa66125696e7777542e)](https://inspector.mcp-use.com) ![MCP Inspector dashboard](https://mintcdn.com/mcpuse/-dX3pYiRHSZpYTFG/images/inspector/inspector-dashboard.jpg?fit=max\&auto=format\&n=-dX3pYiRHSZpYTFG\&q=85\&s=a45b3ae6998884acf492e93725697739) If your server was created with `mcp-use`, run the dev server and open the local Inspector: ```bash theme={null} npm run dev ``` The default local URLs are: | URL | Purpose | | - | - | | `http://localhost:3000/mcp` | MCP endpoint | | `http://localhost:3000/mcp/inspector` | Inspector UI | You can also open the hosted Inspector at [inspector.mcp-use.com](https://inspector.mcp-use.com) or run it with [`npx @mcp-use/inspector`](/inspector/cli). ## Connect to a server Add a server from the dashboard. Choose the transport, enter the MCP endpoint URL, and click **Connect**. ![Inspector connection form](https://mintcdn.com/mcpuse/-dX3pYiRHSZpYTFG/images/inspector/connect-form.png?fit=max\&auto=format\&n=-dX3pYiRHSZpYTFG\&q=85\&s=fd226ba80cb22f38bd58ff64aed459a4) For most local and public HTTP servers, use **Direct**. Use **Via Proxy** only when the browser cannot reach the server directly because of CORS or network policy. See [Connection settings](/inspector/connection-settings) for the short decision guide. When a server protects the whole MCP endpoint with OAuth, the connection waits for authentication. Click **Authenticate**, complete the provider approval, and return to the Inspector. A mixed-auth server connects anonymously because its public tools are already usable. If it publishes OAuth protected-resource metadata, the server card and header show **This server is using mixed auth** with an **Authenticate** button. You can authenticate immediately or wait until a protected operation returns a wire-level OAuth challenge. The connection stays available for public operations while authentication is optional. ## Run a tool Open a connected server and select the **Tools** tab. Choose a tool, fill the generated form, and run it. ![Inspector server detail view with tools](https://mintcdn.com/mcpuse/-dX3pYiRHSZpYTFG/images/inspector/server-detail.png?fit=max\&auto=format\&n=-dX3pYiRHSZpYTFG\&q=85\&s=05cd5ed7f5b5dba0bc1d7ae23dcd251c) The Inspector shows the tool result, structured content, errors, and any widget returned by the tool. Use this view to verify schema validation, result shape, and widget data before testing the same server from a client. For mixed-auth servers, a protected tool can surface the authentication action only when it is needed. Authenticate, then retry the protected call. A normal MCP tool result with `isError: true` is still shown as a tool error; the Inspector does not infer OAuth from its text. ## Inspect resources and prompts Use **Resources** to read server-provided content by URI. Use **Prompts** to test reusable prompt templates with arguments. These tabs are useful when a client reports missing context. They show what the server actually exposes after connection and auth. ## Inspect Skills over MCP **Skills** is always present in the Inspector navigation. When a server does not advertise the experimental `io.modelcontextprotocol/skills` extension, the tab is disabled, like Sampling, with an explanation that Skills over MCP is not available from that server. When the extension is available, each skill appears as a folder containing its `SKILL.md` and supporting resources. When the extension is advertised but its catalog is empty, the tab is shown as a red error state and disabled, with a tooltip explaining that the server returned no skills. Select a file to read it on demand. Before previewing it, the Inspector verifies the raw SHA-256 digest advertised by the skill manifest. For `SKILL.md`, it also checks that the parsed YAML frontmatter matches the catalog entry. A digest mismatch blocks the preview instead of passing changed content to the user or model. Markdown, safe text, raster images, audio, and video have inline previews. Scripts, HTML, SVG, and other binary files are never executed; you can explicitly download verified files when needed. ## Try chat Use **Chat** to test how an LLM calls your server's tools in a conversation. The chat view can use hosted chat where available or a provider key stored in your browser. Keep chat testing focused on end-to-end behavior. Use the Tools tab first when you need to isolate input schemas, tool errors, or widget rendering. For servers that advertise Skills over MCP, chat receives a compact catalog of each skill's name, description, origin, and URI. When a skill is relevant, the chat host loads its `SKILL.md` and supporting resources lazily through the server's Skills over MCP and resource methods. It verifies each resource against the manifest's raw SHA-256 digest before making it available to the model. The Inspector never executes skill scripts or lets `allowed-tools` widen the selected MCP tool permissions. Skills over MCP remains experimental. Treat remote skill content as untrusted and review it before relying on its instructions. See the [working group](https://modelcontextprotocol.io/community/working-groups/skills-over-mcp), [SEP-2640](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2640), and [Agent Skills specification](https://agentskills.io/specification). ## Debug widgets When a tool returns an MCP App widget, the Inspector renders it below the tool result and exposes widget debug controls. Use the widget view to check: * the `props`, `output`, and metadata passed to the widget * inline, picture-in-picture, and fullscreen display modes * desktop, tablet, and mobile layout behavior * theme, locale, timezone, hover, touch, and safe-area settings * Content Security Policy behavior before trying the widget in a host See [Debug widgets in the Inspector](/inspector/debugging-chatgpt-apps) for the full workflow. ## Add the server to a client After a server connects, use **Add to Client** to install or copy setup for supported clients such as Cursor, VS Code, Claude Desktop, Claude Code, Gemini CLI, and Codex CLI. ![Add to Client dropdown in the Inspector](https://mintcdn.com/mcpuse/KxSD03INVc0k3tzd/images/inspector/add-to-client-dropdown.png?fit=max\&auto=format\&n=KxSD03INVc0k3tzd\&q=85\&s=90893b75cd76e2ccd01cbe0e7c7d7681) The Inspector uses the active connection settings when it prepares the client setup. Confirm the server URL and connection name before copying commands or opening client deep links. ## Command Palette Press `Cmd/Ctrl + K` to open the [Command Palette](/inspector/command-palette). Use it to jump to tools, prompts, resources, saved requests, connected servers, and client setup actions. For the full shortcut list, see [Keyboard shortcuts](/inspector/keyboard-shortcuts). For shareable links that open a server or tab directly, see [URL parameters](/inspector/url-parameters). ## Next steps > **[CLI usage](/inspector/cli)** > > Run the Inspector from the command line and auto-connect to a server. > **[Connection settings](/inspector/connection-settings)** > > Choose Direct or Via Proxy and tune connection details only when needed. > **[Debug widgets](/inspector/debugging-chatgpt-apps)** > > Test MCP Apps widgets, layout behavior, CSP, and display modes. > **[Mount the Inspector](/inspector/integration)** > > Serve the Inspector from an Express, Hono, or mcp-use server. > **[WebMCP Inspector](/inspector/webmcp-inspector)** > > Inspect the WebMCP tools a web page registers, from a Chrome side panel. # Integration Source: https://docs.mcp-use.com/inspector/integration Mount the Inspector in a mcp-use or Hono application. The Inspector is built-in local development tooling. `mcp-use` installs its prebuilt package, and `mcp-use dev` mounts it on the development listener at `/mcp/inspector`. ## Auto-Mounting with mcp-use When using a generated `mcp-use` project, run `npm run dev`. The CLI loads the Inspector supplied by `mcp-use`, serves its bundled UI locally, and opens `/mcp/inspector`. No extra dependency or CDN is involved. Production stays Inspector-free by default; use `mcp-use start --with-inspector` to mount it on the built server's existing listener. ### Example Generated and existing projects receive the Inspector through `mcp-use`. Add `@mcp-use/inspector` directly only when overriding the framework-supplied version or mounting it without `mcp-use`. ```typescript theme={null} import { MCPServer } from "mcp-use/server"; const server = new MCPServer({ name: "my-server", version: "1.0.0", }); // Add your tools, resources, prompts... server.tool(/* ... */); export default server; ``` Then run `mcp-use dev`; the Inspector is available at `http://localhost:3000/mcp/inspector`. Use `--no-inspector` for a headless development run. To inspect the production build locally, build once and opt in when starting it: ```bash theme={null} mcp-use build mcp-use start --with-inspector ``` This changes neither the build output nor its manifest. Treat a production Inspector as an internal tool: it can invoke MCP tools and proxy OAuth flows. ## Manual Integration For custom development servers, `mountInspector()` from `@mcp-use/inspector` provides the complete local Inspector: packaged UI, proxy, OAuth BFF, and callbacks. It can register on Hono/Express or return a framework-neutral Fetch handler. ```typescript theme={null} import { mountInspector } from "@mcp-use/inspector"; const inspect = mountInspector({ basePath: "/mcp", autoConnectUrl: "http://localhost:3000/mcp", }); const response = await inspect(request); ``` ### Hono Integration Mount the Inspector on a Hono application: ```typescript theme={null} import { Hono } from "hono"; import { mountInspector } from "@mcp-use/inspector"; const app = new Hono(); // Your Hono routes app.get("/api/health", (c) => { return c.json({ status: "ok" }); }); // Mount inspector at /mcp/inspector mountInspector(app, { basePath: "/mcp" }); // Start server with your Hono adapter export default app; ``` ## Path Customization `basePath` defaults to `/mcp`, so the Inspector lives at `/mcp/inspector`. Set `basePath: ''` for `/inspector`, or use another MCP prefix. ### Hono with Custom Path ```typescript theme={null} import { Hono } from "hono"; import { mountInspector } from "@mcp-use/inspector"; const app = new Hono(); mountInspector(app, { basePath: "/debug" }); // Inspector now available at http://localhost:3000/debug/inspector ``` ## Configuration Options ### `mountInspector` Options Pass options only when the default mount behavior is not enough. ```typescript theme={null} import { mountInspector } from "@mcp-use/inspector"; mountInspector(app, { basePath: "/mcp", autoConnectUrl: "http://localhost:3000/mcp", sandboxOrigin: "https://sandbox.example.com", }); ``` | Option | Type | Default | Description | | - | - | - | - | | `basePath` | `string` | `'/mcp'` | MCP prefix; Inspector mounts at `${basePath}/inspector` | | `autoConnectUrl` | `string \| null` | Current request origin + `basePath` | MCP server URL to auto-connect on load; `null` disables | | `devMode` | `boolean` | `true` | Enables same-origin sandbox for MCP Apps widgets | | `sandboxOrigin` | `string \| null` | `undefined` | Override the sandbox origin for MCP Apps widgets | | `oauthProxyAllowLoopback` | `boolean` | `true` | Permit local proxy/OAuth access to loopback targets | ## Protect mounted Inspector routes The Inspector can call tools, read resources, and inspect prompts on any connected server. Keep it in local development. If a custom integration exposes it on a network, disable loopback proxying and put it behind the same access controls as other internal tools. Each mounted Inspector also applies process-local limits of 120 proxy/OAuth requests and 600 asset requests per minute. Exhausted routes return `429 Too Many Requests` with `Retry-After`; these limits complement, rather than replace, network-edge authentication and rate limiting. ## Related Documentation * [Getting Started](/inspector/index) - Basic inspector usage * [CLI Usage](/inspector/cli) - Standalone inspector usage * [Inspector chat components](/typescript/api-reference/client/inspector-chat-components) - API reference for exported chat UI * [Debug widgets in the Inspector](/inspector/debugging-chatgpt-apps) - Test widget rendering and host behavior # Keyboard shortcuts Source: https://docs.mcp-use.com/inspector/keyboard-shortcuts Reference for Inspector keyboard shortcuts. Use keyboard shortcuts to move between Inspector views without leaving the current server context. ## Shortcuts | Shortcut | Action | Works while typing? | | - | - | - | | `Cmd/Ctrl + K` | Open the command palette. | Yes | | `Cmd/Ctrl + O` | Start a new chat. | No | | `Esc` | Close overlays, close dialogs, or blur the focused element. | Yes | | `t` | Open the Tools tab. | No | | `p` | Open the Prompts tab. | No | | `r` | Open the Resources tab. | No | | `c` | Open the Chat tab. | No | | `h` | Return to the dashboard. | No | | `f` | Focus search in the current tab when the tab has search. | No | `Cmd/Ctrl + K` is the only shortcut that intentionally works while an input field is focused. Single-letter shortcuts are disabled while you type in inputs, textareas, and content-editable elements. ## Command palette keys After opening the command palette: | Key | Action | | - | - | | `Up` / `Down` | Move through results. | | `Enter` | Open the selected result or run the selected command. | | `Esc` | Close the command palette. | See [Command Palette](/inspector/command-palette) for what you can search and open. # Self-Hosting Source: https://docs.mcp-use.com/inspector/self-hosting Deploy your own MCP Inspector instance with Docker. Run the Inspector on your own infrastructure when you need full control over your debugging environment. The official Docker image is published at [`mcpuse/inspector`](https://hub.docker.com/r/mcpuse/inspector) on Docker Hub. ## Quick start ```bash theme={null} docker run -d -p 127.0.0.1:8080:8080 --name mcp-inspector mcpuse/inspector:latest ``` Then open `http://localhost:8080` to access your self-hosted Inspector. > [!WARNING] > > Anyone who can reach the Inspector can use it to connect to and call your MCP servers. The examples bind to `127.0.0.1` so the Inspector is only reachable from the host itself. If you need remote access, put it behind a reverse proxy with authentication and TLS, or restrict access with firewall rules — don't publish port 8080 on all interfaces. ## Deployment options **Docker Run** ```bash theme={null} docker run -d \ --name mcp-inspector \ -p 127.0.0.1:8080:8080 \ mcpuse/inspector:latest ``` **Docker Compose** ```yaml theme={null} services: mcp-inspector: image: mcpuse/inspector:latest ports: - "127.0.0.1:8080:8080" restart: unless-stopped healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/inspector"] interval: 30s timeout: 10s retries: 3 ``` > [!NOTE] > > The image is based on `node:20-alpine`, which ships `wget` (BusyBox) but not `curl` — use `wget` in healthchecks. ## Ports The container always listens on port `8080` — the image's start command pins it with `--port 8080`, so a `PORT` environment variable has no effect. To serve on a different host port, remap it with Docker instead: ```bash theme={null} docker run -d -p 127.0.0.1:3001:8080 mcpuse/inspector:latest ``` `NODE_ENV=production` is already set in the image; no environment variables are required. ## Air-gapped installation For hosts without registry access, transfer the image as a tarball: ```bash theme={null} # On a connected host docker pull mcpuse/inspector:latest docker save mcpuse/inspector:latest -o mcp-inspector.tar # On the air-gapped host docker load -i mcp-inspector.tar ``` > [!NOTE] > > When connecting from a self-hosted Inspector to an MCP server on another host, the browser must be able to reach the server directly, or you can use the proxy connection mode. See [Connection settings](/inspector/connection-settings) for when to use each. ## Alternatives Self-hosting is one of three ways to run the Inspector: | Option | Command | Best for | | - | - | - | | Hosted | [inspector.mcp-use.com](https://inspector.mcp-use.com) | Quick testing, no install | | Local CLI | `npx @mcp-use/inspector` | Local development | | Self-hosted | `docker run mcpuse/inspector:latest` | Production, enterprise, air-gapped | Servers built with `mcp-use` also auto-mount the Inspector at `/inspector` — see the [Inspector overview](/inspector/index). # URL parameters Source: https://docs.mcp-use.com/inspector/url-parameters Open the Inspector with a selected server, tab, or embedded layout. Use URL parameters when you need a link that opens the Inspector on a specific server, starts a connection automatically, or restores a tab. ## Parameters | Parameter | Purpose | Values | | - | - | - | | `server` | Select an existing connection by server ID or URL. If no saved connection matches and the value is an HTTP(S) URL, connect to it. | Connection ID or URL string | | `autoConnect` | Connect to a server when the Inspector loads. | URL string or URL-encoded JSON config | | `tab` | Open a specific server tab. | `tools`, `prompts`, `resources`, `chat`, `sampling`, `elicitation`, `notifications`, `playground` | | `tunnelUrl` | Preserve a tunnel URL while navigating. Usually set by the CLI. | URL string | | `embedded` | Use embedded mode with reduced page chrome. | `true` | | `embeddedConfig` | Configure embedded styling. | URL-encoded JSON config | ## Select or connect to a server Use `server` when the Inspector should select a saved server by URL: ```text theme={null} /?server=https://mcp.example.com/mcp ``` If the server is not saved yet, the Inspector treats the HTTP(S) value like `autoConnect` and connects to it. ## Auto-connect on load Use `autoConnect` when a link should create the connection immediately: ```text theme={null} /?autoConnect=https://mcp.example.com/mcp ``` For advanced connection options, pass a URL-encoded JSON object. The `url` field is required. ```json theme={null} { "url": "https://mcp.example.com/mcp", "name": "Example server", "transportType": "http", "connectionMode": "auto", "connectionType": "Direct" } ``` Supported JSON fields are `url` (required), `name`, `transportType` (`"http"` or `"sse"`), `connectionMode` (`"auto"`, `"direct"`, or `"proxy"`), `autoProxyFallback`, `connectionType` (`"Direct"` or `"Via Proxy"` for older links), `customHeaders`, `auth`, `requestTimeout`, `resetTimeoutOnProgress`, and `maxTotalTimeout`. > [!TIP] > > When passing a JSON object for **autoConnect**, URL-encode the value so special characters are valid in the query string. ## Open a tab Use `tab` by itself to restore a view, or combine it with `server` or `autoConnect`. ```text theme={null} /?server=https://mcp.example.com/mcp&tab=tools ``` The Inspector also updates `tab` as you move between server tabs, so refreshes keep the current view. ## Embedded mode Use `embedded=true` when the Inspector is hosted inside another UI, such as an iframe. ```text theme={null} /?embedded=true ``` Use `embeddedConfig` with a URL-encoded JSON object when the embedded host needs styling overrides. ```json theme={null} { "backgroundColor": "#f5f5f5", "padding": "16px" } ``` ## Example links Open the hosted Inspector and connect to a server: ```text theme={null} https://inspector.mcp-use.com/inspect?autoConnect=https://your-server.com/mcp ``` Open the hosted Inspector, connect to a server, and show Tools: ```text theme={null} https://inspector.mcp-use.com/inspect?server=https://your-server.com/mcp&tab=tools ``` # WebMCP Inspector Source: https://docs.mcp-use.com/inspector/webmcp-inspector Inspect and call the WebMCP tools a web page registers, from a Chrome side panel. The WebMCP Inspector is a Chrome extension that inspects the WebMCP server a web page exposes. It opens as a side panel next to the page, lists the tools that page registers, and lets you call them with typed inputs and read the results without leaving the tab. Reach for it when you are building WebMCP into a website and need to answer questions like: * Are my tools actually registered, and with the schemas I expect? * Does a tool run correctly with a given set of parameters? * Do tools appear and disappear as they should when the page state or route changes? It is built with [WXT](https://wxt.dev), React, and TypeScript, and reuses components from the [mcp-use Inspector](/inspector/index). Unlike the Inspector, it does not connect to remote MCP servers — it only talks to the WebMCP API of the page in the active tab. The source lives at [mcp-use/webmcp-inspector](https://github.com/mcp-use/webmcp-inspector). > [!NOTE] > > WebMCP is experimental. If the API is unavailable on a page, enable **WebMCP for testing** > in `chrome://flags` and relaunch a compatible Chromium build. ## Install from the Chrome Web Store **1. Add the extension** Open the [WebMCP Inspector listing](https://chromewebstore.google.com/detail/webmcp-inspector/dgdidjgjofcenipdfaoebdeeppideadh) and click **Add to Chrome**. **2. Open the panel** Open a WebMCP-enabled page and click the extension's toolbar icon to open the side panel. > [!TIP] > > Clicking the toolbar icon is what grants the extension access to the current site, so > click it again after you switch to another site. Chrome internal pages and the Chrome > Web Store cannot be inspected. ## Inspect and call tools With the panel open, the tool list shows each tool the page registered with its description and parameter count, and a search box to filter them. Select a tool to get a form generated from its schema, fill it in, and run it with **Execute** (or `Cmd/Ctrl + Enter`). The panel validates input against the tool's JSON Schema before execution, and offers a raw JSON mode when a form is awkward for nested inputs. Results are shown with timing and errors, in a split you can drag or expand to fullscreen. Requests you want to keep can be saved by name; saved requests are stored locally and scoped to the site's origin. The list refreshes automatically when the page registers or removes tools, when you change tabs, and on page loads. ## Build from source (contributors) > [!NOTE] > > You only need this if you are working on the extension itself. To use the Inspector, > install it from the Chrome Web Store above. Use Node 22.12+ and pnpm. ```bash theme={null} git clone https://github.com/mcp-use/webmcp-inspector cd webmcp-inspector pnpm install pnpm build ``` Then open `chrome://extensions`, turn on **Developer mode**, click **Load unpacked**, and select `.output/chrome-mv3`. For iterating on the extension itself, `pnpm dev` runs a WXT development build with hot reload; load `.output/chrome-mv3-dev` instead. `pnpm zip` produces a release zip in `.output`. ## Next steps > **[mcp-use Inspector](/inspector/index)** > > Debug a remote or local MCP server from the browser: tools, resources, prompts, chat, > and widgets. > **[Chrome WebMCP docs](https://developer.chrome.com/docs/ai/webmcp/imperative-api)** > > The imperative WebMCP API a page uses to register the tools this extension inspects. # MCP Server Tunneling Source: https://docs.mcp-use.com/tunneling/index Expose a local MCP server through a public /mcp URL for testing in ChatGPT, Claude, and other remote MCP clients. Use a tunnel when ChatGPT, Claude, or another remote MCP client needs to reach a server running on your machine. The tunnel gives you a public HTTPS URL that forwards to your local MCP endpoint. With `mcp-use`, start the server with `--tunnel`, then copy the printed `Tunnel` URL. The URL you give to clients must include `/mcp`. ```text theme={null} https://-.tunnel.mcp-use.run/mcp ``` Keep the terminal process running while you test. The public URL stops working when the process exits. With `mcp-use dev --tunnel` or `mcp-use start --tunnel`, the framework connects directly to the relay over WebSocket. It does not install or execute a native tunnel binary or a separate tunnel package. If the relay connection drops while the command is still running, the tunnel reconnects automatically and reuses the same identifier when possible. The relay forwards both HTTP requests and WebSocket upgrades. In development, MCP App views loaded from the public tunnel keep Vite HMR: editing a local view updates the remote Inspector or client without restarting the tunnel. ## Start a tunnel with mcp-use Use `mcp-use dev --tunnel` while you are developing: ```bash theme={null} mcp-use dev --tunnel ``` Use `mcp-use start --tunnel` when you want to test the built server: ```bash theme={null} mcp-use build mcp-use start --port 3000 --tunnel ``` After the production server binds, successful output includes the local and public MCP endpoints: ```text theme={null} [mcp-use] starting tunnel for port 3000… mcp-use server running at http://localhost:3000/mcp mcp-use public MCP URL: https://proper-black.tunnel.mcp-use.run/mcp ``` Copy the value after `mcp-use public MCP URL:` into your remote MCP client. Do not copy only the tunnel origin; the client URL must end with `/mcp`. ## Verify the tunnel Verify the public URL with the `mcp-use client` CLI: ```bash theme={null} npx mcp-use client connect tunnel-test https://proper-black.tunnel.mcp-use.run/mcp npx mcp-use client tunnel-test tools list ``` The `connect` command performs the MCP handshake and saves the tunnel under the name `tunnel-test`. The `tools list` command should print the tools exposed by your local server. If the server uses OAuth or bearer authentication, complete the client authentication flow or pass the required auth option before testing tools. ## Stop the tunnel Press `Ctrl+C` in the terminal running the tunnel. When you started the tunnel with `mcp-use dev --tunnel` or `mcp-use start --tunnel`, stopping the command stops both the local server process and the tunnel. ## Lifetime and limits Tunnels are for local testing before deployment: * The tunnel is active only while the command is running. * With `mcp-use dev --tunnel` or `mcp-use start --tunnel`, a dropped tunnel registration is re-established automatically while the command runs. * Reservations that never connect expire after 5 minutes. * Connected tunnels expire after 24 hours. * Inactive tunnels are cleaned up after 1 hour without activity. * Each source IP can create up to 10 tunnels per hour. * Each source IP can have up to 5 active tunnels at a time. For a stable public URL, deploy the server instead of relying on a local tunnel. ## Next steps * Use the [TypeScript quickstart](/typescript/getting-started/quickstart) to create a local MCP server. * Use [Build your first MCP App](/typescript/mcp-apps/quickstart) to test widgets in a remote client. * Use [Deploy to Manufact Cloud](/typescript/server/deployment/mcp-use) when you are ready for a hosted MCP endpoint. # Inspector Updates Source: https://docs.mcp-use.com/inspector/changelog New updates and improvements to the MCP Inspector **v20.3.24** ## Native hosted deployments Hosted Inspector builds install the exact package version from their Git commit through Railway's native GitHub integration. * **Fix**: verify npm publication before exposing canary's version commit to native deployments * **Fix**: invalidate the Docker install layer when the package version changes, reject dist-tags, and keep prerelease versions off production during promotion * **Cleanup**: remove the custom Railway deployment action and its token dependency **v20.3.23** ## Chat feedback, backgrounds & hosted connections Patch release paired with `mcp-use` v2.11.1, improving chat feedback and keeping hosted MCP requests on the correct route. * **Fix**: show the thinking indicator after a tool finishes or fails while the assistant request is still active. Keep it hidden while another tool is running or the assistant is writing text (`#2891`) * **Fix**: strip the Inspector's DevSpace routing headers before forwarding MCP proxy requests, so hosted MCP servers receive requests for their own hostname (`#2899`) * **Fix**: keep the chat mesh gradient visible while opening or closing chat history by redrawing the canvas immediately after resizing, including when animation is paused (`#2900`) * **Update**: Updated mcp-use to v2.11.1 **v20.3.22** ## Tool call timeouts, chat errors & proxy hardening Patch release paired with `mcp-use` v2.11.0, fixing a 10-second tool call timeout, surfacing chat failures, and hardening the proxy and OAuth routes. * **Fix**: tool calls on servers added from the dashboard no longer time out after 10 seconds. The Connect form's timeout fields start blank, meaning the default 10-minute request timeout and no overall limit. Servers added since v20.3.17 keep their saved 10000 / 60000 values until both fields are cleared in connection settings (`#2881`) * **Fix**: chat shows streamed provider errors, and explains responses that use up the output limit without producing content, instead of an empty turn (`#2877`) * **Fix**: chat tool calls on OpenAI models show their arguments in the tool drawer instead of `{}` (`#2551`) * **Fix**: OAuth metadata responses are always JSON with `X-Content-Type-Options: nosniff`, so a body from a caller-chosen server can no longer render as a page on the Inspector's origin (`#2855`) * **Fix**: proxy and OAuth rate limits apply per caller (client IP) under a process-wide ceiling, instead of one bucket shared by every user. A local Inspector or `mcp-use dev` is limited only by the process-wide ceiling (`#2855`) * **Update**: ChatGPT install steps in the tunnel panel follow the Plugins flow (Plugins → Add → Add Custom MCP Server) (`#2648`) * **Update**: rebuild bundled workspace code with @mcp-use/client v2.4.5 and @mcp-use/agent v2.0.25 * **Update**: Updated mcp-use to v2.11.0 **v20.3.21** ## Public MCP connections & tool headers Patch fixes for browser connections and tool calls, paired with `mcp-use` v2.10.1. * **Fix**: public MCP endpoints remain connected anonymously when fallback OAuth metadata belongs to a different resource, instead of incorrectly requiring authentication (`#2858`) * **Fix**: discard cached OAuth credentials without a valid issuer stamp or with a mismatched issuer. Affected users may need to sign in again (`#2858`) * **Fix**: tool calls send parameters annotated with `x-mcp-header` as `Mcp-Param-*` headers as well as in the request body, so servers requiring the headers accept browser calls (`#2803`) * **Update**: rebuild bundled workspace code with @mcp-use/client v2.4.4 and @mcp-use/agent v2.0.24 * **Update**: Updated mcp-use to v2.10.1 **v20.3.20** ## OAuth Proxy release alignment Patch release paired with `mcp-use` v2.10.0, rebuilding bundled workspace code with the framework's OAuth Proxy and build changes. This release has no Inspector-specific source changes. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.10.0 **v20.3.19** ## Composer mention search release alignment Patch release paired with `mcp-use` v2.9.0, rebuilding bundled workspace code with the framework's composer mention search helper. This release has no Inspector-specific source changes. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.9.0 **v20.3.18** ## Framework release alignment Patch release paired with `mcp-use` v2.8.2, rebuilding the bundled Inspector and synchronizing internal package metadata. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.8.2 **v20.3.17** ## Saved tool timeout settings Patch release paired with `mcp-use` v2.8.1, applying connection timeout settings to tool calls and preserving cleared values. * **Fix**: tool calls use the saved request timeout, maximum total timeout, and reset-on-progress setting instead of hard-coded defaults (`#2656`) * **Fix**: cleared timeout fields stay cleared when reopening or renaming a connection (`#2656`) * **Fix**: changing a connection URL rejects duplicates before removing the existing connection (`#2656`) * **Enhancement**: connection settings explain that a blank request timeout uses the 10-minute default and a blank maximum total timeout removes the overall time limit while retaining the request timeout (`#2656`) * **Update**: Updated mcp-use to v2.8.1 **v20.3.16** ## Framework release alignment Patch release paired with `mcp-use` v2.8.0, rebuilding the bundled Inspector with the ChatGPT Plugin Extensions framework updates. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.8.0 **v20.3.15** ## Chat input toolbar spacing Patch release paired with `mcp-use` v2.7.3, keeping multiline messages clear of the chat toolbar and updating dependencies. * **Fix**: chat input reserves space above the bottom toolbar so multiline text no longer overlaps its controls (`#2735`) * **Update**: update Hono to `^4.13.7` and refresh workspace dependency security floors (`#2746`) * **Update**: Updated mcp-use to v2.7.3 **v20.3.14** ## Disconnect abort & UserInfo proxy Patch release paired with `mcp-use` v2.7.2. The Express adapter stops holding upstream streams after the client leaves, and the OAuth proxy can fetch UserInfo. * **Fix**: disconnecting an Express client aborts the outbound fetch and the proxy read loop, so a long-lived SSE response no longer writes to a dead socket or leaves the upstream connection open (`#2394`) * **Enhancement**: the OAuth proxy allows GET to UserInfo endpoints listed on the authorization server's metadata, and rejects other methods and URLs that are not in that set (`#2688`) * **Update**: Updated mcp-use to v2.7.2 **v20.3.13** ## View cancellation release alignment Patch release paired with `mcp-use` v2.7.1; rebuilds the bundled Inspector with no Inspector-specific source changes. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.7.1 **v20.3.12** ## Mixed authentication release alignment Patch release paired with `mcp-use` v2.7.0; rebuilds the bundled Inspector with no Inspector-specific source changes. * **Update**: rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated mcp-use to v2.7.0 **v20.3.11** ## TanStack Start release alignment Patch release paired with `mcp-use` v2.6.0; there are no Inspector-specific source changes. * **Update**: Updated mcp-use to v2.6.0 **v20.3.10** ## Scrollable MCP App results Patch release paired with `mcp-use` v2.5.2, keeping tall tool results accessible. * **Fix**: tall MCP App tool results scroll within the result panel instead of extending beyond it (`#2598`) * **Update**: Updated mcp-use to v2.5.2 **v20.3.9** ## Managed chat model branding & provider selection Patch release paired with `mcp-use` v2.5.1, showing the selected cloud model accurately and simplifying provider selection. * **Fix**: managed chat badges use the selected cloud model's name and provider logo instead of the default transport model's branding (`#2575`) * **Enhancement**: the Manufact cloud provider picker offers OpenAI, Anthropic, and Google; existing selections from other providers remain visible with accurate labels, while evals retain the full catalog and BYOK OpenRouter remains available (`#2576`) * **Update**: `MCPServerConfig.auth_token` is deprecated but retained for type compatibility; use `authToken` to send an authentication token (`#2486`) * **Update**: update Hono to `^4.13.5` (`#2492`) * **Update**: Updated mcp-use to v2.5.1 **v20.3.8** ## Bundled Inspector rebuild Patch release paired with `mcp-use` v2.5.0, rebuilding the standalone Inspector with the agent OpenRouter fix. * **Fix**: rebuild the standalone Inspector with the OpenRouter Responses API agent fix and repair published framework peer metadata (`#2504`) * **Update**: Updated mcp-use to v2.5.0 **v20.3.7** ## Workspace package alignment Patch release paired with `mcp-use` v2.4.3; there are no Inspector-specific source changes. * **Update**: Updated mcp-use to v2.4.3 **v20.3.6** ## Publish artifact preservation Patch release paired with `mcp-use` v2.4.2, keeping package builds intact while npm pack runs. * **Fix**: concurrent publishing no longer drops the Client build while its tarball is created, and packed artifacts are checked for declared files and entry points (`#2428`) * **Update**: Updated mcp-use to v2.4.2 **v20.3.5** ## Chat widgets use the connection id Patch release paired with `mcp-use` v2.4.1, rendering chat MCP Apps against the registered connection. * **Fix**: chat MCP Apps render with the registered MCP connection id while preserving the logical server id for chat state and storage (`#2404`) * **Update**: Updated mcp-use to v2.4.1 **v20.3.4** ## Request duration & screenshot init failures Patch release paired with `mcp-use` v2.4.0, showing RPC duration, failing screenshots when an MCP App fails to initialize, and raising the embedded chat step cap. * **Enhancement**: RPC traffic rows show request duration in milliseconds instead of wall-clock time; unmatched rows omit the timing column (`#2364`) * **Fix**: `mcp-use screenshot` fails with `view_load_failed` when the MCP App fails to initialize (`#2355`) * **Enhancement**: embedded client-side chats can configure up to 100 agent steps (`#2401`) * **Update**: Updated mcp-use to v2.4.0 **v20.3.3** ## RPC latency in the timing column Patch release paired with `mcp-use` v2.3.4, moving response latency into the traffic timing column and labeling colocated Inspector logs. * **Enhancement**: response rows show latency in the traffic timing column instead of repeating it in the method label; unmatched rows still show the wall-clock time (`#2349`) * **Enhancement**: when Inspector shares the `mcp-use dev` process, proxy and OAuth BFF logs are prefixed `[inspector]` (`#2351`) * **Update**: Updated mcp-use to v2.3.4 **v20.3.2** ## Model tool-limit warnings Patch release paired with `mcp-use` v2.3.3, making model tool limits visible before a chat request is sent. * **Enhancement**: chat warns when a connected MCP server exposes more than the documented 128 tools supported by OpenAI or Gemini models (`#2333`) * **Update**: Updated mcp-use to v2.3.3 **v20.3.1** ## Correlated JSON-RPC responses Patch release paired with `mcp-use` v2.3.2, adding request context and timing to JSON-RPC response rows. * **Enhancement**: response rows show the matched request method and elapsed time and flag errors while keeping simultaneous bidirectional requests isolated by source, server, widget, direction, and ID type (`#2303`) * **Update**: Updated mcp-use to v2.3.2 **v20.3.0** ![Release 20.3.0](https://mcp-use.com/api/og/release?v=20.3.0\&title=Reusable%20connection%20settings\&date=2026-08\&lang=inspector) ## Reusable connection settings Minor release paired with `mcp-use` v2.3.1, exposing the Inspector connection form and configuration state for embedded consumers. * **New**: `@mcp-use/inspector/client` exports `ConnectionSettingsForm`, `useConnectionFormState`, custom-header controls, connection configuration types, and normalization helpers, with optional consumer URL validation (`#2319`) * **Update**: Updated mcp-use to v2.3.1 **v20.2.5** ## Isolated chat sessions & accurate cache usage Patch release paired with `mcp-use` v2.3.0, keeping concurrent chat sessions independent and preserving provider cache-token accounting. * **Fix**: each chat session owns one identifier and state record, so **New Chat** starts a fresh session while another is streaming; persistence and OAuth retry use the same identifier, and `ChatStorageProvider.createChat` accepts an optional caller-supplied `id` (`#2232`) * **Fix**: Anthropic `cacheCreationInputTokens` survives aggregation, LLM spans, and raw-chat `tokenUsage`, while totals avoid double-counting OpenAI cached input tokens (`#2127`) * **Update**: Updated mcp-use to v2.3.0 **v20.2.4** ## Workspace package alignment Patch release paired with `mcp-use` v2.2.4; there are no Inspector-specific source changes. * **Update**: Updated mcp-use to v2.2.4 **v20.2.3** ## Protocol version controls Patch release making MCP protocol selection visible in connection setup. * **Enhancement**: the connect form and connection settings expose protocol version selection and make configuration options easier to find * **Update**: Updated mcp-use to v2.2.3 **v20.2.2** ## Workspace package alignment Patch release paired with `mcp-use` v2.2.2; there are no Inspector-specific source changes. * **Update**: Updated mcp-use to v2.2.2 **v20.2.1** ## OAuth protected-resource compatibility Patch release accepting secure parent-path resource metadata during OAuth discovery. * **Fix**: protected-resource metadata may identify a same-origin, segment-aware parent of the MCP endpoint, matching the official MCP TypeScript SDK while rejecting cross-origin, sibling-path, credential-bearing, fragmented, and insecure non-loopback values * **Update**: Updated mcp-use to v2.2.1 **v20.2.0** ![Release 20.2.0](https://mcp-use.com/api/og/release?v=20.2.0\&title=CSP%20auditing%20%26%20embedded%20Inspector%20styles\&date=2026-08\&lang=inspector) ## CSP auditing & embedded Inspector styles Minor release paired with `mcp-use` v2.2.0, adding host-visible CSP verification and a consistent embedded surface contract. * **New**: the embedded Chat bridge exposes CSP mode and audit commands so hosts and coding agents can verify MCP Apps in Widget-Declared mode * **Enhancement**: a canonical client stylesheet provides the Inspector surface, shadow, hover, and active theme contract for embedded dialogs, dropdowns, and selects * **Fix**: embedded MCP Apps render in Vibe and preserve React state during remote HMR updates * **Fix**: remove unreachable exports and declare the Inspector tool-execution test's `jsdom` development dependency explicitly * **Update**: Updated mcp-use to v2.2.0 **v20.1.1** ## Mixed-auth chat recovery Patch release paired with `mcp-use` v2.1.1, allowing anonymous sessions to authenticate only when a protected operation requires it. * **Enhancement**: mixed-auth tool calls stay on the browser MCP connection, pause with an Authenticate action, and resume the same client-side turn after popup or redirect authorization * **Enhancement**: the Skills tab becomes available when a development HMR reload adds Skills after the initial connection negotiated without the extension * **Fix**: optional OAuth discovery and token projection no longer block connection readiness, transient metadata failures recover, and authenticated state remains accurate after a challenge * **Fix**: reverse-proxy buffering is disabled for open-ended MCP SSE responses so subscription acknowledgements arrive immediately * **Update**: Updated mcp-use to v2.1.1 **v20.1.0** ![Release 20.1.0](https://mcp-use.com/api/og/release?v=20.1.0\&title=Skills%20over%20MCP%20%26%20Inspector%20runtime\&date=2026-08\&lang=inspector) ## Skills over MCP & Inspector runtime Minor release paired with `mcp-use` v2.1.0 — typed Skills operations, an integrity-checked file explorer, and development/runtime fixes for the v2 Inspector. * **New**: typed Skills over MCP client operations, a capability-gated Inspector file explorer with integrity verification, and removable progressive skill context in Inspector chat * **Enhancement**: Skills discovery omits invalid skills from fresh development snapshots * **Enhancement**: the `window.openai` compatibility bridge exposes tool lifecycle globals and host actions while preserving the native MCP Apps handshake for v2 views; iframe console records are not parsed as MCP Apps JSON-RPC messages * **Fix**: provider assets load from the development server, widget-declared sandbox CSPs can use dynamic compilation within their declared domains, and embedded layouts fill their iframe height without the empty desktop header gap or standalone sidebar footer controls * **Fix**: avoid the Inspector tunnel flash while connection state transitions complete * **Update**: Updated mcp-use to v2.1.0 **v20.0.4** ## Stable npm README links Patch release fixing absolute links in the published Inspector documentation. * **Fix**: README images and repository links use stable absolute URLs so npm renders the published Inspector documentation correctly * **Update**: Updated mcp-use to v2.0.4 **v20.0.3** ## Stable package README metadata Patch release making the published Inspector README reliable on npm. * **Fix**: Publish a package-root README and verify that it stays synchronized with the repository README before packing * **Update**: Updated mcp-use to v2.0.3 **v20.0.1** ## Safer loopback proxy defaults Patch release paired with `mcp-use` v2.0.1, preventing publicly reachable Inspector mounts from proxying requests to host loopback services by default. * **Fix**: `mountInspector` defaults `oauthProxyAllowLoopback` to `false`; the standalone CLI permits loopback for local development but blocks it in production unless `INSPECTOR_ALLOW_LOOPBACK=true` * **Update**: runtime and bundled dependencies use patched stable releases with tightened transitive resolutions * **Update**: Updated mcp-use to v2.0.1 **v20.0.0** ![Release 20.0.0](https://mcp-use.com/api/og/release?v=20.0.0\&title=MCP%20SDK%20v2%20%26%20hosted%20Inspector\&date=2026-08\&lang=inspector) ## MCP SDK v2 & hosted Inspector Major release paired with `mcp-use` v2.0.0 — the Inspector moves to the official MCP SDK v2 and a project-pinned, secure relay/runtime architecture. * **Update**: The Inspector and client move to the official MCP SDK v2 with automatic protocol negotiation, ESM-only packages, Node.js 22.22.2+, redesigned OAuth, and v1 API cleanup * **New**: Project-pinned Inspector development owns the MCP/OAuth relay and serves local assets without a remote application fallback; the standalone package adds the full proxy and OAuth BFF * **New**: Hosted and localhost chat, MCP Apps tool lifecycle delivery, fullscreen chat controls, and streamed tool-call input improve interactive Inspector sessions * **Fix**: OAuth session values are encrypted at rest, secret connection fields are not persisted, browser launches and Inspector routes are hardened, and proxy/OAuth APIs are rate-limited * **Enhancement**: Immutable CDN asset resolution and zero-dependency packaging prevent mixed-version assets and keep standalone installs clean * **Update**: Updated mcp-use to v2.0.0 **v12.0.6** ## CLI version heading Patch release paired with `mcp-use` v1.34.6; includes the unpublished 12.0.4 docs-link fix. * **Enhancement**: the CLI help heading shows the installed Inspector version * **Documentation**: Inspector README drops dead documentation links * **Update**: Updated mcp-use to v1.34.6 **v12.0.3** ## Tunneling docs link Patch release fixing the tunnel popover documentation link. * **Documentation**: The tunnel popover now links to `https://mcp-use.com/docs/tunneling` instead of the removed Manufact URL * **Update**: Updated mcp-use to v1.34.3 **v12.0.2** ## Backend-less CDN shell support Patch release improving the Inspector bundle used by the SDK v2 backend-less shell. * **Fix**: CDN auto-connect reads `window.__MCP_USE_INSPECTOR__.autoConnectUrl`, and the version badge and MCP `clientInfo` fall back to the compile-time bundle version when runtime injection is absent * **Update**: Updated mcp-use to v1.34.2 **v12.0.1** ## mcp-use v1.34.1 Patch release paired with `mcp-use` v1.34.1; there are no Inspector-specific source changes. * **Update**: Updated mcp-use to v1.34.1 **v12.0.0** ## Hosted OAuth reliability (mcp-use v1.34.0) Major release paired with `mcp-use` v1.34.0 — peer dependency bump; runtime OAuth fixes come from the updated `mcp-use` dependency (no inspector-specific source changes in this wave). * **Fix**: gateway-fronted and hosted OAuth servers no longer drop to `failed` with "Server does not support OAuth" when discovery succeeded on an earlier pass — inherits `oauthProxyUrl` wiring and `pending_auth` handling from mcp-use v1.34.0 (`#1840`) * **Update**: Peer dependency on `mcp-use` moves to `>=1.34.0-canary.0` * **Update**: Updated mcp-use to v1.34.0 **v11.0.0** ![Release 11.0.0](https://mcp-use.com/api/og/release?v=11.0.0\&title=MCP%20Apps%20primary%20widget%20runtime\&date=2026-06\&lang=inspector) ## MCP Apps runtime, Auto connections & host context styles Major release paired with `mcp-use` v1.33.0 — widgets now render with MCP Apps as the primary runtime, new connections default to Auto mode with proxy fallback, and host context style variables are applied while the Apps SDK preview tab remains for `window.openai`-only widgets. * **New**: widgets render with the MCP Apps bridge as the primary runtime and apply host context style variables; the Apps SDK ("Component (Apps SDK)") preview tab remains for widgets that only speak `window.openai` (`#1739`) * **Enhancement**: new connections default to Auto mode, trying a direct browser connection first and falling back to the configured Inspector proxy when CORS or other proxy-resolvable connection errors occur; Direct and Proxy remain available as advanced overrides (`#1795`) * **Fix**: OAuth proxy fetch is scoped per server configuration, so connecting one server Via Proxy no longer mutates global `fetch`, changes unrelated requests, or affects other servers configured for Direct mode (`#1770`) * **Fix**: stale saved auto-connect entries are replaced when the advertised transport changes, so embedded Inspector instances stop retrying deprecated SSE connections after switching to streamable HTTP (`#1792`) * **Fix**: signed-in users on the hosted free tier are no longer shown the "sign in to increase your limits" prompt — the free-tier upgrade chrome only renders for anonymous visitors (`#1767`) * **Fix**: the inspector CLI handles `--version` and unknown options and reads its version from `package.json`, so canary builds and CLI version output stay in sync (`#1722`) * **Update**: Bumped `vite` to 8.0.16 (`#1742`) * **Update**: Peer dependency on `mcp-use` moves to `>=1.33.0-canary.0` * **Update**: Updated mcp-use to v1.33.0 **v10.0.1** ## Hosted localhost chat & chat scroll helper Patch release paired with `mcp-use` v1.32.1 — hosted inspector chat falls back to browser-side streaming for loopback MCP servers and adds a scroll-to-bottom affordance in long chats. * **Fix**: Hosted inspector chat detects localhost and loopback MCP server URLs and uses client-side streaming because the managed cloud backend cannot reach a user's local server; the configure-key empty state explains why a personal API key is needed (`#1736`) * **New**: Centered animated scroll-to-bottom button appears when viewing older chat messages (`#1538`) * **Update**: Peer dependency on `mcp-use` moves to `>=1.32.1-canary.0` * **Update**: Updated mcp-use to v1.32.1 **v10.0.0** ## mcp-use v1.32.0 Major release paired with `mcp-use` v1.32.0 — peer dependency moves to `>=1.32.0-canary.0`; no inspector-specific runtime changes. * **Update**: Peer dependency on `mcp-use` moves to `>=1.32.0-canary.0` * **Update**: Updated mcp-use to v1.32.0 **v9.0.1** ## mcp-use v1.31.1 Patch release paired with `mcp-use` v1.31.1 — picks up workspace dependency alignment; no inspector-specific runtime changes. * **Update**: Updated mcp-use to v1.31.1 **v9.0.0** ![Release 9.0.0](https://mcp-use.com/api/og/release?v=9.0.0\&title=OAuth%20credential%20lifecycle%20%26%20mcp-use%20v1.31.0\&date=2026-06\&lang=inspector) ## OAuth credential lifecycle & mcp-use v1.31.0 Major release paired with `mcp-use` v1.31.0 — peer dependency moves to `>=1.31.0-canary.1`; explicit OAuth credential cleanup when removing a saved server. * **Fix**: delete-server passes `{ clearCredentials: true }` to `removeConnection` so an explicit user removal forgets persisted OAuth credentials instead of leaving tokens behind (`#1703`) * **Update**: Peer dependency on `mcp-use` moves to `>=1.31.0-canary.1` * **Update**: Updated mcp-use to v1.31.0 **v8.0.2** ## mcp-use v1.30.2 Patch release paired with `mcp-use` v1.30.2 — picks up the chalk CJS compatibility fix; no inspector-specific runtime changes. * **Update**: Updated mcp-use to v1.30.2 **v8.0.1** ## Widget status label pointer-events fix Patch release paired with `mcp-use` v1.30.1 - invoking/invoked labels in the MCP Apps preview pane no longer block iframe interactions. * **Fix**: MCP Apps preview status label used an absolutely positioned `h-full` wrapper that intercepted hover, click, and form controls along the left edge of the widget iframe; apply `pointer-events-none`, remove the full-height wrapper, and align the Apps SDK label in `OpenAIComponentRenderer` (`#1694`, `#1678`) * **Update**: Updated mcp-use to v1.30.1 **v8.0.0** ## mcp-use v1.30.0 Major release paired with `mcp-use` v1.30.0 - peer dependency moves to `>=1.30.0-canary.0`; no inspector-specific runtime changes. * **Update**: Peer dependency on `mcp-use` moves to `>=1.30.0-canary.0` * **Update**: Updated mcp-use to v1.30.0 **v7.0.1** ## mcp-use v1.29.1 Patch release paired with `mcp-use` v1.29.1 - picks up OAuth transport auth hardening and workspace security dependency bumps; no inspector-specific runtime changes. * **Update**: Updated mcp-use to v1.29.1 **v7.0.0** ![Release 7.0.0](https://mcp-use.com/api/og/release?v=7.0.0\&title=Local%20LLM%20provider%2C%20image%20tool%20results%20%26%20widget%20display%20modes\&date=2026-06\&lang=inspector) ## Local LLM provider, image tool results & widget display modes Major release paired with `mcp-use` v1.29.0: chat against a local Ollama daemon, MCP image tool results forwarded to vision models as real images, an MCP-server reconnect banner, and a reworked widget fullscreen / picture-in-picture path - plus a large dead-code cleanup. * **New**: Ollama as a local LLM chat provider - local model discovery and streaming chat, talking to the daemon directly over CORS (no server-side proxy) with an `OLLAMA_ORIGINS` hint surfaced when the browser fetch is blocked (`#1395`) * **New**: MCP-server reconnect banner - chat recognises the cloud's `mcp_auth_required` 401 (e.g. an expired upstream OAuth token) and renders an inline reconnect banner for the affected server that refreshes the token in place, instead of pointing users at the Manufact account login (`#1485`) * **New**: copy button on user messages, matching the assistant-message UX (`#1556`) * **Enhancement**: `mcp-use client screenshot` auto-sizes to the widget's natural dimensions when `--width`/`--height` are omitted and handles external MCP server URIs (`ui:///.html`) (`#1579`) * **Enhancement**: snappier tab-switch animation timing (`#1544`) * **Fix**: MCP image tool results are forwarded to the model as real image content instead of base64-encoded JSON - image bytes route through each provider's vision channel (Anthropic `tool_result` image blocks; OpenAI / Google follow-up user turns), and text-only results now reach the model unwrapped (`#1487`) * **Fix**: widget fullscreen renders above embedded host chrome - native `requestFullscreen()` on the widget shell with an exit navbar, picture-in-picture portaled to `document.body` at `z-[100]`, and AppBridge reconnect after the sandbox iframe remounts (`#1605`) * **Fix**: stop `ToolInputForm` from writing an invalid per-property `required: boolean` onto the live tool `inputSchema` during render, which made Anthropic reject the chat request with `tools.0.custom.input_schema invalid` after a tool was opened in the Tools tab (`#1545`) * **Fix**: keep per-tab count badges visible and right-aligned in collapsed header tabs (`#1490`) * **Fix**: propagate server alias updates through the MCP server wrapper so the tile heading reflects a renamed alias immediately (`#1539`) * **Fix**: replace the trailing-slash regex in `normalizeOllamaBaseUrl` with a linear scan, resolving a CodeQL polynomial-regex alert (`#1534`) * **Chore**: add an OAuth redirect e2e against an emulated Google issuer, exercising both Direct and Via Proxy connection types (`#1481`, `#1609`) * **Chore**: remove 18 unused source files, stop generating the unused client-side `version.ts`, and drop dead barrel re-exports flagged by Knip (`#1510`, `#1533`, `#1607`) * **Update**: Updated mcp-use to v1.29.0 **v6.0.0** ![Release 6.0.0](https://mcp-use.com/api/og/release?v=6.0.0\&title=Widget%20preview%20route%20%26%20dark-mode%20scrollbars\&date=2026-05\&lang=inspector) ## Widget preview route & dark-mode scrollbars Major release paired with `mcp-use` v1.28.0: new `ViewPreview` component and `/preview/:view` client-side route that back the `mcp-use client screenshot` CLI pipeline, dark-mode aware scrollbars across the UI, and a cleanup of duplicate Knip-flagged exports. * **New**: `` internal component and `/preview/:view` client-side route — a chromeless surface the CLI screenshot pipeline drives via CDP. `MCPAppsRenderer` gains an optional `onReady` callback that the preview route uses to signal `body[data-view-ready="true"]`, which the CLI waits for before capturing. The preview route detects `globalThis.__mcpUsePreviewBundle` (injected by the CLI via CDP `Page.addScriptToEvaluateOnNewDocument`) and renders the widget inline, skipping the browser-side MCP connection entirely (`#1432`) * **Enhancement**: dark-mode aware scrollbars styled to match the inspector theme, with improved hover visibility (`#1484`) * **Fix**: removed the redundant default export of `JsonRpcLoggerView`; the named export is unchanged (`#1453`) * **Update**: Updated mcp-use to v1.28.0 **v5.0.1** ## MCP App width fix in chat Patch release paired with `mcp-use` v1.27.1: MCP App width is pinned in chat so only height responds to widget-reported sizes. * **Fix**: Pin MCP App width in chat - `onSizeChange` only updates height, and the inline transition no longer animates `width`; prevents the chat panel from collapsing when widgets report narrower content (`#1462`) * **Update**: Updated mcp-use to v1.27.1 **v5.0.0** ![Release 5.0.0](https://mcp-use.com/api/og/release?v=5.0.0\&title=OpenRouter%2C%20pre-registered%20OAuth%20%26%20telemetry%20env\&date=2026-05\&lang=inspector) ## OpenRouter, pre-registered OAuth & telemetry env Major release paired with `mcp-use` v1.27.0: OpenRouter and OpenAI-compatible providers in chat configuration, pre-registered OAuth client credentials in the connection dialog, and `MCP_USE_ANONYMIZED_TELEMETRY` honored in browser telemetry. * **New**: OpenRouter as a first-class chat provider - a single OpenRouter API key fronts upstream OpenAI / Anthropic / Google models; internally reuses the OpenAI provider with an override base URL and the required `HTTP-Referer` / `X-Title` headers (`#1403`) * **New**: "OpenAI Compatible" entry in the chat provider dropdown - point inspector chat at any OpenAI-compatible API (LM Studio, Ollama, OpenRouter, etc.) with a required Base URL field and an optional API key; the standard OpenAI provider is unchanged (`#1437`) * **New**: `Client ID`, `Client Secret`, and `Scope` fields in the Authentication dialog wired through `addServer` / `updateServer` for pre-registered OAuth flows against providers that strip `registration_endpoint` from metadata (`#1400`) * **Fix**: Browser telemetry honors `MCP_USE_ANONYMIZED_TELEMETRY=false` - the inspector server mirrors the env var into `window.__MCP_USE_ANONYMIZED_TELEMETRY__` before the client bundle loads, so a single env var disables both `mcp-use`'s in-browser `posthog-js` and the inspector's own client telemetry (`#1443`) * **Update**: Updated mcp-use to v1.27.0 **v3.0.2** ## E2E alignment for Settings dropdown Patch release updating Playwright coverage for the command palette Settings entry after the navbar refactor; paired with `mcp-use` v1.25.2. * **Fix**: Command palette e2e test targets the Settings option via the dropdown trigger introduced in the inspector settings UX (`#1428`) * **Update**: Updated mcp-use to v1.25.2 **v3.0.1** ## OAuth single-tab flow, embed fixes & Hono detection Patch release fixing OAuth redirect flows, embedded `ChatTab` UI leaks, and Hono duck-type detection in `mountInspector`; paired with `mcp-use` v1.25.1. * **Fix**: OAuth authorization now opens in the current tab (`useRedirectFlow: true`, `preventAutoAuth: true`) and the callback navigates the same tab back - users no longer end up with two inspector tabs (`#1391`) * **Fix**: Store connection config in `sessionStorage` before OAuth redirect so auto-reconnect works after the callback without a `?autoConnect` param (`#1404`) * **Fix**: OAuth callback redirects back to the inspector with error parameters on failure (user denies, server error) instead of showing a raw error page; surfaced as a persistent app-level toast (`#1381`) * **Fix**: `mountInspector(app)` detects Hono via duck-typing (`.fetch(Request) => Response`) instead of `instanceof`, resolving crashes when the host and inspector resolve different Hono module records (`#1417`) * **Fix**: MCP App widget z-index - removed explicit `z-20`/`z-10` from sandboxed iframe wrappers so widgets scroll beneath the chat header instead of painting over it (`#1407`) * **Fix**: Free-tier upgrade UI (`Model & usage` dialog, model badge) is now opt-in via `enableFreeTierUpgrade` on `ChatTab` (default `false`) and is hidden for host-app embeds that manage their own session (`#1399`) * **Fix**: Suppress duplicate model chrome (landing pill, `ChatHeader` badge) when host passes `managedLlmConfig` + `hideModelBadge`; chat no longer auto-switches to client-side streaming when `localLlmConfig` exists in localStorage and the host owns the chat stream (`#1418`) * **Documentation**: `--no-open` CLI flag added to the inspector CLI reference (`#1397`) * **Update**: Updated mcp-use to v1.25.1 **v3.0.0** ![Release 3.0.0](https://mcp-use.com/api/og/release?v=3.0.0\&title=Inline%20elicitation%20%26%20social%20meta%20tags\&date=2026-04\&lang=inspector) ## Inline elicitation & social meta tags Major release paired with `mcp-use` v1.25.0: chat-initiated elicitation requests render inline in the chat thread, hosted inspector links get rich previews, and the peer dependency on `mcp-use` tracks the 1.25 OAuth refactor. * **New**: Elicitation requests triggered from the Chat tab render inline in the chat thread instead of routing users through a toast to the Elicitation tab; Tools-tab triggers keep the existing toast flow, and the Elicitation tab remains available as an audit view (`#1336`) * **New**: Links to the hosted inspector now render rich previews on Slack, X/Twitter, LinkedIn, Discord, and other platforms (`#1376`) * **Update**: Peer dependency on `mcp-use` moves to `>=1.25.0-canary.9` to pick up the OAuth DCR-direct refactor * **Update**: Updated mcp-use to v1.25.0 **v2.2.0** ![Release 2.2.0](https://mcp-use.com/api/og/release?v=2.2.0\&title=Hosted%20chat%2C%20LLM%20providers%20%26%20chat%20export\&date=2026-04\&lang=inspector) ## Hosted chat runtime, LLM providers & chat export Minor release paired with `mcp-use` v1.24.2: first-party inspector LLM streaming (no LangChain on the chat path), copy/export chat, runtime hosted-chat URL, hosted free-tier chat, and cloud env tooling via the CLI (`#1372`). * **New**: First-party LLM providers for inspector chat (Anthropic, OpenAI, Google) with shared message formatting, SSE streaming, and tool loops - the inspector no longer depends on LangChain for chat (`#1372`) * **New**: "Copy Chat" and "Export Chat" in the chat header - markdown to clipboard; download as JSON or Markdown with tool calls in order (`#1324`) * **New**: Free tier chat on the hosted inspector (`#1368`) * **New**: Hosted chat URL from runtime config - inspector server reads `MANUFACT_CHAT_URL` and injects `window.__MANUFACT_CHAT_URL__`; `InspectorProvider` prefers that value and falls back to `VITE_MANUFACT_CHAT_URL` for local dev (`#1370`) * **Fix**: OAuth login popup - drop `noopener` and redirect `callbackURL` to `/inspector/oauth-popup-closed.html` so the popup self-closes instead of loading the full inspector (`#1370`) * **Update**: Updated mcp-use to v1.24.2 **v2.1.0** ## Navbar, theme & debug controls Minor release with MCP Apps debug theme toggle and navbar/settings UX improvements; dependency bump to `mcp-use` v1.24.1. * **New**: Theme toggle button in MCP Apps debug controls toolbar * **Enhancement**: Navbar - chat tab first with label and separator; `alwaysExpanded` on tab triggers so the active label stays visible when collapsed; Deploy links to manufact.com/signup with inspector referrer; tunnel control between Add to Client and Deploy with updated styling and mobile visibility; theme toggle, command palette, and GitHub under a settings dropdown; "Report a Bug" prefills a GitHub issue with the inspector label * **Update**: Updated mcp-use to v1.24.1 **v2.0.0** ![Release 2.0.0](https://mcp-use.com/api/og/release?v=2.0.0\&title=Subpath%20OAuth%2C%20chat%20UX%20%26%20tab%20persistence\&date=2026-04\&lang=inspector) ## Subpath OAuth, chat UX & tab persistence Major release paired with `mcp-use` v1.24.0: correct OAuth redirects when the inspector is served under `/inspector`, clearer chat streaming UI, and restored tab state after reload. * **Fix**: `McpClientProvider` receives `defaultCallbackUrl` so OAuth redirects target `/inspector/oauth/callback` (matches React Router `basename`); removes the authentication dialog "Redirect URL" field that was not wired to the live connection * **Fix**: Hide the thinking indicator when the assistant message already has rendered parts so the spinner does not linger after streaming completes * **Enhancement**: Persist the active inspector tab across page refresh * **Update**: Updated mcp-use to v1.24.0 **v1.0.1** ## Embedded inspector without LangChain Patch release fixing server routes that imported `telFetch` from the root `mcp-use` package. * **Fix**: Import `telFetch` from `mcp-use/telemetry/tel-fetch` so shared routes do not load the root entry (which eagerly pulls the agent graph); resolves embedded inspector failures when `langchain` is not installed * **Update**: Updated mcp-use to v1.23.1 **v1.0.0** ![Release 1.0.0](https://mcp-use.com/api/og/release?v=1.0.0\&title=Stream%20Protocol%2C%20Aliases%20%26%20Chat%20Tooling\&date=2026-04\&lang=inspector) ## Stream protocol, aliases & chat tooling Major release with MCP stream support in chat, connection UX improvements, and dependency hardening. * **New**: MCP data stream protocol support in `ChatTab` and `useChatMessages` * **Enhancement**: `disabledTools` prop on `ChatTab` and `useChatMessages` for finer tool control * **New**: Editable MCP server aliases in connection settings; `updateServerMetadata()` from `McpClientProvider` updates display names without a full reconnect; shared `getServerDisplayName` across dashboard tiles, server dropdown, header actions, command palette, server info modal, and server icon * **Fix**: Alias-only edits no longer trigger a full reconnect; IME composition no longer submits the connection form when pressing Enter mid-composition * **Enhancement**: Persist tabs on refresh; sync URL `tab` query param when switching tabs so state survives reload * **Enhancement**: Tool-invocation serialization, screenshots, and message list refs for integrations such as manufact.build * **Update**: Removed unused `transportType` / `setTransportType` props from `ConnectionSettingsForm` * **Fix**: Tighter `pnpm` overrides and lockfile refresh for `pnpm audit`; `lodash` override in the mcp-apps scaffold template for standalone installs * **Update**: Vite 8.0.5, Hono 4.12.12, `@hono/node-server` 1.19.13 * **Update**: Updated mcp-use to v1.23.0 **v0.26.1** ## Dependency & bundling alignment Patch release aligning how `@mcp-use/inspector` packages `mcp-use` for bundling and shared types. * **Fix**: Restore `mcp-use` as both a `dependency` and `peerDependency` - tsup bundles non-React subpaths with transitive deps; `peerDependency` preserves shared `mcp-use`/`react` types with the host app * **Update**: Updated mcp-use to v1.22.3 **v0.26.0** ## Peer Dependency Alignment & MCP UI v7 Minor release aligning inspector dependency strategy for shared type safety and upgrading MCP UI client rendering internals. * **Fix**: Moved `mcp-use` from `dependencies` to `peerDependencies` in `@mcp-use/inspector` so consumers reuse a single `mcp-use` type instance (prevents pnpm duplicate-type TS2322 conflicts) * **Enhancement**: Upgraded `@mcp-ui/client` from v6 to v7 * **Enhancement**: Replaced removed legacy `UIResourceRenderer` path with sandboxed iframe rendering for legacy `ui://` resources * **Enhancement**: Removed remote-dom usage to align with upstream `@mcp-ui/client` v7 changes * **Update**: Updated mcp-use to v1.22.2 **v0.25.1** ## Chat History Tool Results & ErrorBoundary Customization Patch release improving chat history reconstruction so tool calls/results (including `structuredContent`) persist across turns, plus ErrorBoundary fallback/reporting hooks. * **Fix**: Preserve tool invocation context across chat turns - reconstruct assistant messages as `AIMessage` tool calls plus `ToolMessage` results; keep `structuredContent` and strip `_meta` before sending to the model * **Enhancement**: Chat message conversion supports tool results and multimodal content more reliably * **Enhancement**: `ErrorBoundary` now supports `fallback` (node or `(error) => node`) and `onError` for reporting (default UI unchanged) * **Update**: Updated mcp-use to v1.22.1 **v0.25.0** ## Tunnel Controls & Vite 8 Minor release with tunnel management for `mcp-use dev`, Vite 8 build stack, and elicit payload alignment with the MCP spec. * **New**: Start/stop the `mcp-use dev` tunnel from the Inspector * **Enhancement**: Vite 8.0 with Rolldown bundler and `@vitejs/plugin-react` 6 in the inspector build * **Fix**: Elicit - send `content` instead of `data` per the MCP spec; aligns with `createElicitMethod` validation on the client * **Update**: Updated mcp-use to v1.22.0 **v0.24.5** ## Dependency Updates Patch release with dependency updates. * **Fix**: Dependabot security alerts - updated vulnerable dependencies (hono, dompurify, etc.) * **Update**: Updated mcp-use to v1.21.5 **v0.24.4** ## Dependency Update Patch release with dependency update. * **Update**: Updated mcp-use to v1.21.4 **v0.24.3** ## Sandbox Host Fix Patch release fixing sandbox host derivation for cloud-embedded inspector pages. * **Fix**: Sandbox host derivation for cloud-embedded pages - apex hosts (e.g. manufact.com) now resolve to `sandbox-inspector.{domain}` instead of `sandbox-{domain}` * **Update**: Updated mcp-use to v1.21.3 **v0.24.2** ## Embedded Inspector Proxy Fix Patch release fixing auto-connect when inspector is served from MCP server (Python, custom servers). * **Fix**: Skip proxy when inspector origin matches MCP server origin - no longer routes through missing `/inspector/api/proxy` on embedded servers * **Fix**: Detect proxy availability via runtime config injection (`__MCP_PROXY_URL__`); disable autoProxyFallback when no proxy is available * **Update**: Updated mcp-use to v1.21.2 **v0.24.1** ## Chat Components & Dark Mode Fixes Patch release with exported chat component enhancements and proxy header handling. * **Fix**: Tools selection and attachment button icons invisible in dark mode * **Enhancement**: Strip infra headers from proxied requests * **New**: Initial messages support for exported chat components (`ChatTab`, `useChatMessages`) * **Update**: Updated mcp-use to v1.21.1 **v0.24.0** ## Inspector Embedding & MCP Apps Minor release with embedding support and logger improvements. * **New**: Inspector embedding support - build fix and `InspectorProvider` for embedded usage * **New**: MCP Apps support in `clientInfo.capabilities` - inspector advertises `io.modelcontextprotocol/ui` * **Enhancement**: Logger middleware filters noisy API endpoints (telemetry, RPC stream/log) * **Fix**: `--no-open` flag respected in standalone dev mode (was always opening browser) * **Update**: Updated mcp-use to v1.21.0 **v0.23.1** ## Dependency Update Patch release with dependency update. * **Update**: Updated mcp-use to v1.20.5 **v0.23.0** ## Embedded Chat Improvements Minor release improving embedded chat experience. * **Enhancement**: Improved embedded chat * **Update**: Updated mcp-use to v1.20.4 **v0.22.3** ## Standalone Deployment Fix Patch release fixing version import in standalone deployment. * **Fix**: Standalone deployment was importing the version from the wrong path * **Update**: Updated mcp-use to v1.20.3 **v0.22.2** ## Connection & Widget Display Improvements Patch release with useAutoConnect, MCPAppsRenderer, and chat agent fixes. * **Fix**: useAutoConnect now retains tile visibility on connection failure * **Enhancement**: MCPAppsRenderer and OpenAIComponentRenderer - improved border handling and status display; `prefersBorder` default set to false; status labels above widget in inline mode * **Enhancement**: ToolResultDisplay z-index for proper sticky layering * **Enhancement**: `exposeResourcesAsTools` and `exposePromptsAsTools` options in MCPAgentOptions; inspector chat tab sets both to `false` so agent only exposes actual MCP tools * **Update**: Updated mcp-use to v1.20.2 **v0.22.1** ## Widget Status Texts & CSP Fixes Patch release with invoking/invoked status display and CSP handling improvements. * **New**: Display of `invoking` and `invoked` status texts in MCPAppsRenderer, OpenAIComponentRenderer, ToolResultDisplay, ToolResultRenderer * **Enhancement**: MCPAppsDebugControls adjusts violation indicators based on CSP mode * **Fix**: sandbox-proxy strips existing CSP meta tags before injecting permissive CSP * **Update**: Updated mcp-use to v1.20.1 **v0.22.0** ![Release 0.22.0](https://mcp-use.com/api/og/release?v=0.22.0\&title=Iframe%20Console%20%26%20CSP%20Panel\&date=2026-02\&lang=inspector) ## Iframe Console & CSP Panel Minor release with Iframe Console enhancements and CSP violation handling. * **New**: Iframe Console with expandable logs, level filter, search, resizable height * **New**: Widget debug context for chat * **Enhancement**: MCP Apps debug controls (tool props JSON view, required props hint, SEP-1865 semantics) * **New**: CDN build * **Fix**: useSyncExternalStore first-render handling; reconnect logic; Tools tab sends only explicitly set fields; resource annotations include `_meta` * **New**: CSP violations panel with clear action; widget re-execution on CSP mode change; CSP mode for Apps SDK * **Update**: Updated mcp-use to v1.20.0 **v0.21.1** ## Dependency Update Patch release with dependency update. * **Update**: Updated mcp-use to v1.19.3 **v0.21.0** ![Release 0.21.0](https://mcp-use.com/api/og/release?v=0.21.0\&title=Bulk%20Paste%20%26%20Tool%20Definition%20Enhancements\&date=2026-02\&lang=inspector) ## Bulk Paste & Tool Definition Enhancements Minor release adding bulk paste functionality and enhanced tool definition handling. * **New**: Bulk paste functionality in ToolsTab - paste JSON or JavaScript object syntax directly * **New**: Auto-fill dialog to confirm updates when pasted data would overwrite existing values * **Enhancement**: ToolExecutionPanel now copies full tool definition * **Enhancement**: Added utility functions for parsing and converting JavaScript object syntax to JSON * **Enhancement**: Visual feedback for auto-filled fields in ToolInputForm * **Update**: Updated mcp-use to v1.19.2 **v0.20.1** ## MCPApps & Widget Improvements Patch release improving widget loading and iframe handling. * **Enhancement**: Improved MCPAppsRenderer loading logic and widget handling * **Enhancement**: Enhanced useWidget for better iframe lifecycle management * **Update**: Updated mcp-use to v1.19.1 **v0.20.0** ![Release 0.20.0](https://mcp-use.com/api/og/release?v=0.20.0\&title=Chat%20Quick%20Questions%20%26%20Enhanced%20UX\&date=2026-02\&lang=inspector) ## Chat Quick Questions & Enhanced UX Minor release with chat quick questions and followups, improved loading states, and developer experience enhancements. ### Chat Enhancements * **New**: Support for `chatQuickQuestions` and `chatFollowups` in ChatTab components ### Loading & Error Handling * **Enhancement**: MCPAppsRenderer shows loading spinner with `isReady` state management * **Enhancement**: Replaced shimmer with Spinner component for better initial widget load UX * **Enhancement**: Added skeleton loading state for widgets * **Enhancement**: Global error listeners and improved error logging in widget components ### Developer Experience * **New**: Copy all logs to clipboard feature * **Enhancement**: Enhanced theme handling in OpenAIComponentRenderer * **Enhancement**: ToolsList displays metadata and icons differentiating MCP/OpenAI tool types * **Fix**: Allow permissive CSP frame ancestors by default * **Fix**: Correct MIME type for mcp\_apps resource counting ### Dependencies * **Update**: Updated mcp-use to v1.19.0 **v0.19.0** ![Release 0.19.0](https://mcp-use.com/api/og/release?v=0.19.0\&title=Tool%20Arguments%20%26%20Streaming%20Input\&date=2026-02\&lang=inspector) ## Tool Arguments, Streaming Input & Elicitation Enum Support Minor release with tool argument handling, streaming input support, and elicitation enum variants. * **New**: Tool argument type coercion and schema resolution (boolean, array, object); ToolsTab and ToolInputForm use new schema utilities; validation server tool and E2E tests for typed arguments * **New**: Partial tool input handling for streaming arguments in MCPAppsRenderer; MessageList and ToolResultRenderer support streaming states; useChatMessagesClientSide handles streaming tool call arguments; useWidget types for partial/streaming state * **New**: Elicitation support for SEP-1330 enum schema variants (single-select, multi-select); client and server handling; Elicitation tab docs and tests * **Fix**: Readiness state reset when widget URL changes in OpenAIComponentRenderer; improved tool output and response metadata handling for pending-to-ready transitions * **Update**: Updated mcp-use to v1.18.0 **v0.18.9** ## Log Noise Reduction Patch release reducing dev server log noise and aligning dependencies. * **Fix**: Reduced noisy logs in the dev server * **Update**: Updated mcp-use to v1.17.4 **v0.18.8** ## Widget Readiness & Iframe Global Sync Fixes Patch release focused on widget iframe lifecycle reliability and state update safety. * **Fix**: Reset widget readiness state when widget URL changes so new iframes re-initialize correctly * **Enhancement**: Improved tool output and response metadata transitions from pending to ready states * **Enhancement**: Queued iframe global updates until OpenAI globals are available for more reliable widget synchronization * **Fix**: Added animation frame cleanup logic to prevent memory leaks during component unmount * **Update**: Updated mcp-use to v1.17.3 **v0.18.7** ## Chat Conversion & Error Copy Fixes Patch release improving chat message conversion and copy behavior. * **Fix**: Copy button now copies actual error text instead of `null` * **Fix**: Chat message conversion now falls back to `parts` when `content` is empty, with improved attachment handling * **Enhancement**: Chat request streaming now uses external history for better context handling and to avoid duplicated messages * **Update**: Updated mcp-use to v1.17.2 **v0.18.6** ## Dependency Update Patch release aligned with mcp-use dependency updates. * **Update**: Updated mcp-use to v1.17.1 **v0.18.5** ## Iframe Embedding & Reverse Proxy Support Patch release with iframe embedding configuration, reverse proxy improvements, and widget rendering fixes. * **New**: `MCP_INSPECTOR_FRAME_ANCESTORS` environment variable to control which origins can embed the inspector in iframes via CSP `frame-ancestors` * **New**: `mountInspector` accepts `devMode` and `sandboxOrigin` options for deployment flexibility * **New**: Runtime config injection (`__MCP_DEV_MODE__`, `__MCP_SANDBOX_ORIGIN__` window globals) without rebuild * **Enhancement**: Server-side widget fetches convert external proxy URLs to localhost for correct content retrieval * **Enhancement**: Simplified widget asset URL rewriting for improved reverse proxy reliability * **Fix**: Infinite re-render loop in `MCPAppsRenderer` caused by excessive `useEffect` dependencies * **Update**: Updated mcp-use to v1.17.0 **v0.18.4** ![Release 0.18.4](https://mcp-use.com/api/og/release?v=0.18.4\&title=E2E%20Testing%20%26%20Refresh%20Features\&date=2026-02\&lang=inspector) ## E2E Testing & Refresh Features Patch release with comprehensive E2E testing infrastructure and enhanced UI functionality. ### E2E Testing Infrastructure * **New**: Comprehensive Playwright-based E2E test suite with full coverage for chat, connections, HMR, widgets, and command palette * **New**: GitHub Actions workflow (`.github/workflows/inspector-e2e.yml`) for automated E2E testing across multiple modes * **New**: Test fixtures for authentication servers (OAuth mock, API key, custom headers) * **New**: Test helpers for connection, authentication, and debugger tools * **New**: Test matrix for parameterized test scenarios across multiple inspector modes (mix, prod, builtin) * **New**: Widget examples for conformance testing (weather-display, status-card, display-info, apps-sdk-only-card) * **Enhancement**: Comprehensive E2E testing documentation in `tests/e2e/README.md` ### Testability Improvements * **Enhancement**: Added `data-testid` attributes across 40+ UI components for reliable element selection * **Enhancement**: Enhanced component accessibility for automated testing including connection forms, server list, command palette, chat interface, tool execution panels, resources/prompts/tools tabs, and elicitation/sampling displays ### UI Enhancements * **New**: Refresh buttons with loading states for Tools, Resources, and Prompts tabs * **New**: `ListTabHeader` component with refresh functionality and spinning icon animation * **Enhancement**: Manual refresh capability for primitives without reconnecting to server * **Fix**: Inspector now detects when `server=` query parameter contains a URL that's not already connected and automatically redirects to use `autoConnect=` instead * **Enhancement**: Added comprehensive URL parameters documentation page to inspector reference ### Widget Improvements * **Fix**: Widget pending state now correctly emulated to reflect ChatGPT behavior * **Enhancement**: MCPAppsRenderer and OpenAIComponentRenderer handle tool output and metadata more effectively * **Enhancement**: Immediate rendering of widgets even when results are pending * **Enhancement**: MessageList and ToolResultRenderer support immediate rendering of widget tools * **Enhancement**: Widget props support in ToolResultDisplay ### Server Improvements * **Enhancement**: Changed default port from 3001 to 3000 for production builds (dev still uses 3001) * **Enhancement**: Skip telemetry (PostHog/Scarf) when `NODE_ENV=test` or `MCP_USE_ANONYMIZED_TELEMETRY=false` * **New**: `start-auth-servers.ts` utility for running authentication test servers ### Dependencies * **Update**: Updated mcp-use to v1.16.4 **v0.18.3** ## Dependency Update Patch release with dependency updates. * **Update**: Updated mcp-use to v1.16.3 **v0.18.2** ## Inspector Fixes Patch release with widget behavior fix and improved URL handling. * **Fix**: Widget pending state now correctly emulated to reflect ChatGPT behavior * **Fix**: Inspector now detects when `server=` query parameter contains a URL that's not already connected and automatically redirects to use `autoConnect=` instead * **Update**: Updated mcp-use dependency to v1.16.2 **v0.18.1** ## Dependency Update Patch release aligned with mcp-use v1.16.1. * **Update**: Updated mcp-use dependency to v1.16.1 **v0.18.0** ![Release 0.18.0](https://mcp-use.com/api/og/release?v=0.18.0\&title=Chat%20Prompts%20%26%20Multimodal%20Support\&date=2026-01\&lang=inspector) ## Chat Prompts & Multimodal Support Minor release introducing prompts in chat and multimodal image support for vision-capable LLMs. ### Chat Prompts * **New**: Prompts in Chat - type / to open a prompt, run it, and include its result in the thread before sending * **Note**: Prompts with arguments are not yet supported in this release ### Multimodal Support * **New**: Image attachment support in Inspector chat * **New**: Upload and send images to vision-capable LLMs (GPT-4o, Claude, Gemini) using the paperclip button * **Enhancement**: MCP prompts that return images are now properly displayed instead of showing raw JSON * **Enhancement**: Full multimodal support for image content in chat interface ### Dependencies * **Update**: Updated mcp-use to v1.16.0 **v0.17.3** ## Theme URL Parameter Fix Patch release enabling dark mode through URL parameter. * **Fix**: Enable dark mode through theme URL parameter * **Update**: Aligned with mcp-use v1.15.3 **v0.17.2** ## HMR File Watcher Fix Patch release fixing file watcher resource exhaustion in containerized environments. * **Fix**: HMR file watcher exhausting inotify limits by properly ignoring node\_modules * **Fix**: Prevented ENOSPC errors in containerized environments caused by watching files inside `node_modules/` * **Update**: Aligned with mcp-use v1.15.2 **v0.17.1** ## Dependency Update Patch release with dependency updates. * **Update**: Updated mcp-use to v1.15.1 **v0.17.0** ![Release 0.17.0](https://mcp-use.com/api/og/release?v=0.17.0\&title=MCP%20Apps%20Support%20%26%20Landing%20Pages\&date=2026-01\&lang=inspector) ## MCP Apps Support & Landing Pages Major release introducing MCP Apps support with dual-protocol widget rendering and enhanced inspector capabilities. ### MCP Apps Support * **New**: Dual-protocol support enabling widgets to work with both MCP Apps and ChatGPT Apps SDK * **New**: `MCPAppsRenderer` component for advanced debugging and visualization * **New**: `MCPAppsDebugControls` component for widget debugging * **New**: Sandboxed iframe support with console logging and safe area insets for isolated widget rendering * **New**: Widget adapters (MCP Apps, Apps SDK) with protocol helpers for seamless cross-protocol compatibility ### Landing Pages * **New**: HTML landing page support for MCP server endpoints * **New**: Connection instructions for Claude Code, Cursor, VS Code, VS Code Insiders, and ChatGPT * **Enhancement**: Browser host normalization for server connections ### Bug Fixes & Security * **Fix**: MCP server landing now shows the external URL instead of the internal URL * **Fix**: Zod JIT compilation to prevent CSP violations in sandboxed environments * **Security**: Fixed vulnerabilities in dependencies ### Dependencies * **Update**: Updated mcp-use to v1.15.0 **v0.16.2** ## UI Enhancements & Connection Handling Patch release with improved UI components, widget security enhancements, and better connection management. ### UI Enhancements * **Enhancement**: CustomHeadersEditor with improved focus management and title prop support * **Enhancement**: Standardized proxy configuration - renamed `customHeaders` to `headers` in InspectorDashboard and ServerConnectionModal for consistency ### Widget Security * **Enhancement**: Widget security headers with frame domain support * **Enhancement**: Added `frame_domains` to widgetCSP interface for iframe embed control * **Enhancement**: Updated getWidgetSecurityHeaders to include frame\_domains in CSP for OpenAI compatibility * **Enhancement**: CSP handling in OpenAIComponentRenderer prioritizes metadata from tool results and resources ### Connection Handling * **Enhancement**: Improved server connection handling with new handleReconnect function * **Enhancement**: UI elements reflect connection states more accurately with better hover effects and error displays * **Enhancement**: Enhanced error handling for unauthorized connections with clearer user feedback * **Enhancement**: State management for connecting servers in InspectorDashboard ### Dependencies * **Update**: Aligned with mcp-use v1.14.2 improvements **v0.16.1** ## Tool Output Display Fix Patch release with tool output display improvement. * **Fix**: Inspector tool output now displays at full height for better content visibility * **Update**: Aligned with mcp-use v1.14.1 **v0.16.0** ![Release 0.16.0](https://mcp-use.com/api/og/release?v=0.16.0\&title=RPC%20Message%20Management%20%26%20LangChain%20Fixes\&date=2026-01\&lang=inspector) ## RPC Message Management & LangChain Fixes Release with enhanced RPC message handling and critical bug fixes for Anthropic integration. ### RPC Message Management * **New**: Copy functionality for RPC messages in Prompts, Resources, and Tools tabs * **New**: Reusable `RpcPanel` component for consistent RPC message handling across tabs * **New**: Export functionality for RPC messages * **Enhancement**: Improved panel management with refactored ResizablePanel components ### Resource Properties Management * **New**: Custom properties support for resources - dynamically configure resource properties * **New**: `PropsSelect` component for intuitive property selection and management * **New**: `PropsConfigDialog` with AI-powered property suggestions using Claude * **New**: `SchemaFormField` component for rendering JSON schema-based forms * **New**: `usePropsLLM` hook leveraging Claude for intelligent property suggestions * **New**: `useResourceProps` hook for managing resource props state ### Inspector Improvements * **Enhancement**: Extracted MCP prompts logic into reusable `useMCPPrompts` hook * **Enhancement**: Server metadata display with website URLs and icons * **Enhancement**: Better tool management - cleared selected tools when removed from list * **Enhancement**: Enhanced `JSONDisplay` with improved line wrapping and font size for better readability * **Enhancement**: `ToolExecutionPanel` now includes collapsible description section * **Enhancement**: Integrated JSON metadata visualization in tool execution panel * **Enhancement**: `McpUIRenderer` and `OpenAIComponentRenderer` support `customProps` parameter * **Enhancement**: `ResourceResultDisplay` with dynamic property configuration UI * **Enhancement**: Enhanced Prism theme support for better code highlighting * **Enhancement**: Updated `useMcp` hook to expose `mcpServerUrl` for resource operations ### Bug Fixes * **Fix**: Resolved Anthropic `tool_use.id` required error with LangChain 1.3.10 update * **Fix**: Proper tool\_call ID generation ensuring unique IDs for all tool\_use blocks * **Fix**: Improved backward compatibility by checking both 'headers' and 'customHeaders' ### Dependencies * **Update**: `@langchain/anthropic` to 1.3.10 * **Update**: `@langchain/core` to 1.1.15 * **Update**: `langchain` to 1.2.10 * **Update**: `react-resizable-panels` to 4.4.1 **v0.15.3** ## Dependency Update Patch release with dependency updates. * **Enhancement**: Updated mcp-use dependency to latest version **v0.15.2** ## OAuth Proxy URL Handling Improvements Patch release with improved OAuth proxy URL handling and connection logic. * **Enhancement**: Improved OAuth proxy URL derivation from callback URLs * **Enhancement**: Better handling of root path callbacks in OAuth flow * **Enhancement**: Clearer separation between OAuth proxy URLs and connection URLs * **Fix**: Maintains valid OAuth tokens across sessions by not clearing OAuth storage before connecting **v0.15.1** ## URL Validation & LocalStorage Enhancements Patch release with URL validation improvements and localStorage functionality. * **Enhancement**: Automatically prepends "https\://" to URLs without protocol for better user experience * **Enhancement**: Improved URL validation logic in InspectorDashboard and ServerConnectionModal * **Enhancement**: Added localStorage clearing functionality for MCP-related items to help with troubleshooting * **Fix**: Enhanced localStorage checks to verify both existence and functional methods before usage * **Fix**: Clear stale OAuth storage before connecting to ensure fresh authentication flow **v0.15.0** ![Release 0.15.0](https://mcp-use.com/api/og/release?v=0.15.0\&title=Chat%20Stop%20Functionality\&date=2026-01\&lang=inspector) ## Chat Stop Functionality Minor release adding the ability to stop ongoing chat responses in the inspector. ### Chat Functionality * **New**: Stop functionality for chat responses - users can now abort streaming responses * **New**: Export stop function from `useChatMessagesClientSide` hook connected to `abortControllerRef` * **New**: `abortControllerRef` added to `useChatMessages` hook for proper abort control * **Enhancement**: Stop button connected to abort streaming responses for better user control ### UI & Authentication * **Enhancement**: Simplified authentication button logic in InspectorDashboard * **Enhancement**: Updated multi-server example to link directly to authentication URL * **Fix**: Updated dependency `hono` to 4.11.4 **v0.14.6** ## Dependency Update Patch release with dependency updates. * **Enhancement**: Updated mcp-use dependency to latest version **v0.14.5** ## OAuth & Metadata Enhancements Minor release with OAuth proxy support, metadata caching, and favicon improvements. ### OAuth & Client Info * **Enhancement**: Enhanced OAuth proxy to support gateway/proxy scenarios (e.g., Supabase MCP servers) * **Enhancement**: Client info support with branding displayed on OAuth consent pages * **Enhancement**: Server metadata caching for immediate display on reconnect - improves UX by showing server info instantly * **Enhancement**: Improved logging middleware for API routes with better debugging visibility * **Enhancement**: Enabled OAuth proxy logging for better flow visibility ### Favicon Detection * **Enhancement**: Enhanced favicon detector to try all subdomain levels (e.g., mcp.supabase.com → supabase.com → com) * **Enhancement**: Detection of default vs custom favicons using JSON API response * **Enhancement**: Prefer non-default favicons when available ### Bug Fixes * **Fix**: Remove import from "mcp-use" which causes langchain import in server * **Enhancement**: Enhanced synchronization for tools, prompts, and resources during HMR **v0.14.4** ## Connection Fix Patch release fixing autoconnect configuration parsing. * **Fix**: Autoconnect now correctly parses config objects in addition to string URLs **v0.14.3** ## Security Fixes & OAuth Improvements Patch release addressing multiple security vulnerabilities and fixing OAuth flow issues. ### Security Fixes * **Security**: Fixed 13 vulnerabilities (3 moderate, 10 high) * **Security**: Updated `langchain` to 1.2.3 (fixes serialization injection vulnerability) * **Security**: Updated `@langchain/core` to 1.1.8 (fixes serialization injection vulnerability) * **Security**: Updated `react-router` to 7.12.0 (fixes XSS and CSRF vulnerabilities) * **Security**: Added overrides for `qs` and `preact` vulnerabilities ### OAuth & Connection Improvements * **Fix**: Resolved OAuth flow looping issue by removing duplicate fallback logic * **Enhancement**: Simplified connection handling with consolidated state management * **Enhancement**: Enhanced OAuth authentication flow with improved connection settings * **Enhancement**: Improved auto-connect functionality with better proxy handling and error management * **Enhancement**: Enhanced theme toggling with dropdown menu for better UX and accessibility * **Enhancement**: Updated OAuth flow management in browser provider and callback handling **v0.14.2** ![Release 0.14.2](https://mcp-use.com/api/og/release?v=0.14.2\&title=Automatic%20Proxy%20Fallback%20%26%20Reconnect\&date=2026-01\&lang=inspector) ## Automatic Proxy Fallback & Reconnect Minor release with automatic proxy fallback, OAuth proxy support, and reconnect functionality. ### Breaking Changes (with Deprecation Warnings) * **Breaking**: Renamed `customHeaders` to `headers` across all APIs. Old name still works but shows deprecation warnings. * **Breaking**: Renamed `samplingCallback` to `onSampling` for consistency. Old name still works but shows deprecation warnings. ### New Features * **New**: Reconnect functionality for failed connections - reconnect button in InspectorDashboard UI * **New**: Reconnect option in dropdown menu for failed connections * **New**: Configurable clientInfo support for MCP connection initialization with full metadata * **New**: Automatic Proxy Fallback - automatically retries failed connections through proxy * **New**: OAuth Proxy Support with oauthProxyUrl configuration ### Improvements * **Enhancement**: Better detection of OAuth discovery failures, CORS errors, and connection issues * **Enhancement**: OAuth provider uses original target URL for discovery, not proxy URL * **Enhancement**: HttpConnector automatic reconnection disabled, shifting responsibility to higher-level logic for better control ### Bug Fixes * **Fix**: Custom headers now correctly included when copying connection configuration from saved tiles * **Fix**: Headers correctly read from localStorage where stored in proxyConfig.customHeaders **v0.14.1** ## Security Update Patch release with security fixes and build improvements. * **Security**: Updated `@modelcontextprotocol/sdk` to 1.25.2 (fixes ReDoS vulnerability in UriTemplate regex patterns) * **Fix**: Updated building script to correctly export types for inspector/client components **v0.14.0** ## Multi-Server Support & Browser Compatibility Release with multi-server management, improved UI responsiveness, and enhanced browser compatibility. ### Breaking Changes * **Breaking**: Removed `winston` dependency. The logging system now uses a simple console logger that works in both browser and Node.js environments. ### Multi-Server Support * **New**: Multi-server management with `McpClientProvider` to manage multiple MCP server connections * **New**: Dynamic addition and removal of servers in React applications * **New**: Pluggable storage system with `LocalStorageProvider` and `MemoryStorageProvider` for flexible server configuration persistence * **Enhancement**: Refactored `useMcp` hook for better multi-server support * **Enhancement**: Removed obsolete `McpContext` (replaced with `McpClientProvider`) ### UI & UX Improvements * **Enhancement**: Improved UI responsiveness with enhanced mobile and tablet layouts and adaptive component visibility * **Enhancement**: Better server management with refactored server connection handling, improved icon display, and status tracking * **Enhancement**: Enhanced debugging with detailed logging in Layout and useAutoConnect components for better monitoring of server connection states * **Enhancement**: Simplified connection settings by removing deprecated transport types * **Enhancement**: Improved server icon support and component interactions * **Enhancement**: Added embedded mode support * **New**: Support for passing tab as query parameter for direct navigation * **New**: Prompt rendering support with enhanced display * **New**: Add to Client dropdown for quickly adding MCP servers to Cursor, VS Code, Claude Desktop, and CLI tools ### Browser Compatibility * **Enhancement**: Enhanced inspector components for better browser compatibility * **Enhancement**: Better configuration handling and MCP proxy integration * **Enhancement**: Improved browser-based MCP client with better connection handling ### Bug Fixes * **Fix**: Query URL handling in built mode now preserves arguments correctly * **Fix**: Server connection retrieval in `OpenAIComponentRenderer` to directly access connections array * **Fix**: Add client SDKs to add to client dropdown * **Fix**: Respect query tab parameter when existing server is already connected **v0.13.2** ## Documentation Updates - **Enhancement**: Updated examples and documentation to use preferred methods and APIs **v0.13.1** ## Bug Fixes - **Fix**: Widget props not picked up when using Zod schemas **v0.13.0** ## Session Management & Architecture Improvements Release aligned with mcp-use v1.11.0, featuring session management architecture and improved inspector capabilities. ### Breaking Changes * **Breaking**: WebSocket transport support removed. Use streamable HTTP or SSE transports instead. * **Breaking**: LangChain adapter moved from main entry point to `mcp-use/adapters` subpath. ### Session Management * **Enhancement**: Support for pluggable session management architecture with Redis support * **Enhancement**: Improved session persistence and connection handling * **Enhancement**: Better support for distributed deployments with cross-server notifications ### Inspector Features * **Enhancement**: Enhanced connection handling with automatic 404 handling and re-initialization * **Enhancement**: Improved tool, resource, and prompt management * **Enhancement**: Better integration with session management architecture * **Enhancement**: Enhanced debugging capabilities with better error handling ### Widget Support * **Enhancement**: Improved widget rendering and debugging for ChatGPT Apps * **Enhancement**: Better widget data handling and state management * **Enhancement**: Enhanced OpenAI component renderer with improved functionality ### UI Improvements * **Enhancement**: Better connection settings UI * **Enhancement**: Improved server management interface * **Enhancement**: Enhanced tool result display and formatting **v0.12.6** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.12.5** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.12.4** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.12.3** ## Bug Fixes - **Fix**: Deno 3 compatibility fixes **v0.12.2** ## Bug Fixes - **Fix**: Updated Zod error handling **v0.12.1** ## Bug Fixes - **Fix**: Zod import in official SDK - **Enhancement**: Added repository metadata in package.json **v0.12.0** ## Elicitation Support & API Improvements Release aligned with mcp-use v1.10.0, featuring elicitation support and enhanced inspector capabilities. ### Breaking Changes * **Breaking**: Server API renamed `createMCPServer()` factory function to `MCPServer` class constructor * **Breaking**: Session API replaced `session.connector.tools`, `session.connector.callTool()`, etc. with direct methods: `session.tools`, `session.callTool()`, etc. * **Breaking**: OAuth environment variables standardized to `MCP_USE_OAUTH_*` prefix ### New Features * **New**: Elicitation support in inspector - servers can request user input through clients * **New**: Client Capabilities API with `ctx.client.can()` and `ctx.client.capabilities()` * **New**: Session Notifications API with `ctx.sendNotification()` and `ctx.sendNotificationToSession()` * **New**: Session Info API with `ctx.session.sessionId` to access current session ID * **New**: Resource Template Flat Structure support with `uriTemplate` directly on definition * **New**: Resource Template Callback Signatures supporting multiple signatures ### Improvements * **Enhancement**: Enhanced type inference for resource template callbacks * **Enhancement**: Client capabilities tracking during initialization * **Enhancement**: Major documentation refactoring and restructuring * **Enhancement**: Edge runtime support improvements * **Enhancement**: Transport bug fixes **v0.11.0** ## Elicitation Support - **New**: Added support for elicitation in inspector, enabling servers to request user input through clients - **Fix**: Transport bug fixes **v0.10.1** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.10.0** ## Sampling Support - **New**: Added sampling support in inspector with LLM sampling capabilities - **Fix**: Long running sampling requests no longer timeout after 60 seconds - **Enhancement**: Better handling of extended sampling operations **v0.9.2** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.9.1** ## Bug Fixes - **Fix**: Fixed bin entry issue for pnpm installation - **Enhancement**: Standardized import statement formatting across multiple files **v0.9.0** ## OAuth Authentication System Release with complete OAuth 2.0 support and enhanced inspector capabilities. ### New Features * **New**: Complete OAuth 2.0 authentication framework with built-in providers (Auth0, WorkOS, Supabase, Keycloak) * **New**: OAuth middleware and routes for server-side OAuth flow handling * **New**: OAuth callback component in inspector for authentication flows * **New**: Context storage with async local storage for request-scoped context * **New**: Response helpers for standardized HTTP responses and error handling * **New**: Runtime detection utilities for Node.js, Bun, and Deno environments ### Inspector Enhancements * **Enhancement**: Enhanced useMcp hook with improved connection management and OAuth support * **Enhancement**: Enhanced inspector dashboard with OAuth configuration UI * **Enhancement**: Better authentication flow handling with OAuth integration * **Enhancement**: Improved auto-connect with enhanced connection recovery * **Enhancement**: Enhanced HTTP connectors with OAuth token handling ### UI Improvements * **Fix**: Fixed scrolls in tools, resources, and prompts tab * **Fix**: Fixed models and API keys box in inspector chat * **Fix**: Fixed rendering of table, inline-code, code and images in inspector chat * **Fix**: Fixed padding of RPC panels * **New**: Added enum input display for tools * **Enhancement**: Bundle minification (9.7mb → 4.2 mb) ### Bug Fixes * **Fix**: Switched to fork SDK to fix Zod errors on Deno runtime * **Fix**: Optimized dependencies **v0.8.3** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.8.2** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.8.1** ## Bug Fixes - **Fix**: Fixed auto-connect proxy fallback behavior - **Fix**: Fixed connection config updates not applying when connection already exists - **Enhancement**: Auto-switch (proxy fallback) now automatically enabled during auto-connect flow - **Enhancement**: Improved error messages for connection failures **v0.8.0** ## Notifications, Sampling & OpenAI Apps SDK Integration Release with bidirectional notifications, LLM sampling, and comprehensive OpenAI Apps SDK support. ### New Features * **New**: Bidirectional notification support between clients and servers * **New**: LLM sampling capabilities allowing MCP tools to request completions from connected clients * **New**: Widget build ID support for cache busting in widget UI resources * **New**: Inspector notifications tab with real-time display * **New**: Server capabilities modal showing supported MCP features * **New**: RPC message logging support in inspector ### OpenAI Apps SDK Integration * **New**: McpUseProvider component combining React setup (StrictMode, ThemeProvider, BrowserRouter, ErrorBoundary) * **New**: WidgetControls component with debug overlay and view controls (fullscreen, PIP) * **New**: useWidget hook for type-safe React adapter to OpenAI Apps SDK API * **New**: ErrorBoundary component for graceful error handling * **New**: Image component handling data URLs and public file paths * **New**: ThemeProvider for consistent theme management * **New**: WidgetInspectorControls for inspector-specific debugging * **New**: Console proxy toggle for iframe console logs * **New**: Product search result widget template with carousel and accordion components * **New**: Folder-based widget support with automatic detection * **New**: Public folder support for static assets ### Inspector Enhancements * **Enhancement**: Enhanced OpenAIComponentRenderer with better height calculation and theme support * **Enhancement**: Enhanced ToolResultDisplay with multiple content types (text, image, audio, resource links) * **Enhancement**: Resizable panels with collapse support * **Enhancement**: Better widget security headers and CSP configuration * **Enhancement**: Enhanced widget data handling and state management ### Improvements * **Enhancement**: Refactored HTTP transport to reuse sessions across requests * **Enhancement**: Session management with tracking and automatic cleanup * **Enhancement**: Roots support in connectors and session API * **Enhancement**: Enhanced search\_tools with metadata * **Enhancement**: Improved SSR configuration with proper Vite settings ### Bug Fixes * **Fix**: Fixed iframe height calculation issues * **Fix**: Fixed theme flashing on widget load * **Fix**: Fixed CSP header generation for dev mode * **Fix**: Fixed asset loading in dev widget proxy * **Fix**: Fixed console logging in iframe * **Fix**: Fixed widget state inspection * **Fix**: Fixed resizable panel collapse behavior **v0.7.1** ## Bug Fixes & Improvements - **Fix**: Fixed auto-connect proxy fallback behavior - **Fix**: Fixed connection config updates not applying when connection already exists - **Enhancement**: Auto-switch (proxy fallback) now automatically enabled during auto-connect flow - **Enhancement**: Improved error messages for connection failures **v0.7.0** ## Code Mode Support - **New**: Code Mode feature allowing agents to execute code using MCP tools - **Enhancement**: Enhanced MCPClient with code execution configuration - **Enhancement**: Comprehensive tests for code execution functionality **v0.6.1** ## Bug Fixes - **Fix**: Various bug fixes and improvements **v0.6.0** ## Edge Runtime Support - **Major**: Migrated to Hono framework for edge runtime support - **New**: Runtime detection for Deno and Node.js environments * **New**: Enhanced inspector dashboard with improved connection handling - **Enhancement**: Better auto-connection logic with error handling and retry mechanisms **v0.5.3** ## Bug Fixes & Improvements - **Fix**: Various bug fixes and stability improvements - **Enhancement**: Dependency updates **v0.5.2** ## Bug Fixes & Improvements - **Fix**: Various bug fixes and stability improvements - **Enhancement**: Dependency updates **v0.5.1** ## Bug Fixes - **Fix**: Various bug fixes and improvements **v0.5.0** ## LangChain 1.0.0 Support - **Major**: Support for LangChain 1.0.0 - **Fix**: Model type compatibility for LangChain 1.0.0 - **Enhancement**: Set CLI and inspector as dependencies **v0.4.13** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.12** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.11** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.10** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.9** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.8** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.7** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.6** ## Dependency Updates - **Enhancement**: Updated dependencies **v0.4.5** ## Bug Fixes - **Fix**: Fixed inspector chat formatting **v0.4.4** ## Bug Fixes - **Fix**: Fixed inspector chat - **Fix**: Fixed inspector shadow **v0.4.3** ## Major Refactoring & Apps SDK Support Major refactoring with improved architecture and enhanced Apps SDK support. ### Major Refactoring * **Refactor**: Server architecture refactored with major improvements to routing and middleware * **Refactor**: Removed legacy `mcp-inspector.ts` file in favor of modular architecture * **Refactor**: Added new `cli.ts` for improved command-line interface handling * **Refactor**: Added `utils.ts` and `shared-utils-browser.ts` for better code organization * **Refactor**: Enhanced `shared-routes.ts` with improved route handling and error management ### Apps SDK Support * **Enhancement**: Enhanced widget data handling and state management * **New**: Added `readResource` method in MCPInspector for fetching resources based on server ID * **Enhancement**: Enhanced OpenAI component renderer to utilize serverId and readResource * **Enhancement**: Improved safe data serialization for widget state management ### UI/UX Improvements * **Enhancement**: Enhanced ConnectionSettingsForm with copy configuration feature * **Enhancement**: Updated OpenAIComponentRenderer to dynamically adjust iframe height * **Enhancement**: Improved resource display with duration metrics and enhanced badge styling * **Enhancement**: Enhanced LayoutHeader with dynamic badge styling * **Fix**: Fixed scrollable tool parameters for better user experience * **Enhancement**: Added mobile-responsive hiding features ### Bug Fixes * **Fix**: Fixed inspector mounting logic by simplifying server URL handling * **Fix**: Fixed linting issues across multiple components * **Fix**: Fixed server configuration for improved stability **v0.4.2** ## Auto-Connection & Multi-Server Support - **New**: Auto-connection functionality - inspector now automatically connects to MCP servers on startup * **New**: Multi-server support - enhanced support for connecting to multiple MCP servers simultaneously - **New**: Client-side chat functionality with improved message handling - **New**: Resource handling with enhanced chat components - **Enhancement**: Streamlined routing with refactored server and client routing - **Enhancement**: Enhanced connection handling with improved auto-connection logic - **Enhancement**: Better UI components with updated Layout, ChatTab, and ToolsTab components - **Fix**: Fixed connection handling in InspectorDashboard - **Fix**: Improved error messages in useMcp hook **v0.4.1** ## Bug Fixes - **Fix**: Minor fixes and improvements **v0.4.0** ## Major Refactor & Apps SDK Initial Integration Major refactor aligning inspector with mcp-use TypeScript package and initial Apps SDK integration. ### Major Refactoring * **Refactor**: Migrated from CommonJS to ESM format * **Refactor**: Added input validation for port and URL * **Refactor**: Improved error handling and logging * **Refactor**: Added `open` package for cross-platform browser launching * **Refactor**: Reorganized component structure (moved to `src/client/components/`) * **Refactor**: Refactored ChatTab to use streaming API and custom hooks * **Refactor**: Enhanced InspectorDashboard with auto-connect functionality * **Refactor**: Improved CommandPalette with better item selection * **Refactor**: Updated routing to use query parameters ### New Components * **New**: Chat components: `AssistantMessage`, `UserMessage`, `ToolCallDisplay`, `MCPUIResource`, `MessageList` * **New**: UI components: `aurora-background`, `text-shimmer`, `sheet`, `switch`, `kbd`, `shimmer-button`, `status-dot` * **New**: Form components: `ConnectionSettingsForm`, `ServerDropdown` * **New**: Tool components: `ToolExecutionPanel`, `ToolResultDisplay`, `SaveRequestDialog` * **New**: Resource components: `ResourceResultDisplay`, `ResourcesList` ### Apps SDK Integration * **New**: OpenAI Apps SDK integration with UI resource type * **New**: Enhanced MCP-UI adapter for Apps SDK metadata * **New**: Resource URI format supporting `ui://widget/` scheme ### Bug Fixes * **Fix**: Fixed CLI binary format and package configuration * **Fix**: Changed CLI build format from CommonJS to ESM * **Fix**: Added input validation for port and URL arguments * **Fix**: Improved error logging in API routes * **Fix**: Fixed async/await bugs in static file serving # CLI Usage Source: https://docs.mcp-use.com/inspector/cli Run the MCP Inspector from the command line The MCP Inspector can be run directly from the command line using `npx`, making it easy to quickly inspect and debug MCP servers without installing anything globally. ## Quick Start Run the inspector with a single command: ```bash theme={null} npx @mcp-use/inspector ``` This will: * Start the inspector server on an available port (default: 8080) * Automatically open your browser to the inspector interface * Display the URL in the terminal ## Command Options ### `--url ` Auto-connect to an MCP server when the inspector starts. ```bash theme={null} npx @mcp-use/inspector --url http://localhost:3000/mcp ``` ### `--port ` Specify the starting port number. The inspector will find the next available port if the specified port is already in use. ```bash theme={null} npx @mcp-use/inspector --port 9000 ``` **Default:** `8080` **Port Range:** Must be between 1 and 65535 ### `--no-open` Prevent the inspector from automatically opening a browser tab when it starts. Useful in CI/CD pipelines, headless environments, or when you prefer to open the URL manually. ```bash theme={null} npx @mcp-use/inspector --no-open ``` You can combine it with other flags: ```bash theme={null} npx @mcp-use/inspector --url http://localhost:3000/mcp --port 9000 --no-open ``` ### `--help, -h` Display help information and available options. ```bash theme={null} npx @mcp-use/inspector --help ``` ## Environment Variables ### `MCP_INSPECTOR_FRAME_ANCESTORS` Configure which origins can embed the inspector widget in iframes. This is useful when embedding the inspector into your own application or when testing widgets from different domains. **Default behavior:** * **Development mode**: `*` (allows all origins for easier development) * **Production mode**: `'self'` (same-origin only for security) **Format:** Space-separated list of origins or `*` for all origins **Examples:** ```bash theme={null} # Allow embedding from specific domains MCP_INSPECTOR_FRAME_ANCESTORS="https://app.example.com https://dev.example.com" npx @mcp-use/inspector # Allow embedding from any domain (useful for development) MCP_INSPECTOR_FRAME_ANCESTORS="*" npx @mcp-use/inspector # Multiple origins with wildcards MCP_INSPECTOR_FRAME_ANCESTORS="https://*.example.com http://localhost:*" npx @mcp-use/inspector ``` > [!NOTE] > > In production deployments, it's recommended to explicitly list allowed origins rather than using `*` to prevent unauthorized embedding. > [!TIP] > > When running in development mode (`npm run dev`), the inspector automatically allows all origins by default, so you don't need to set this variable unless you want to test production CSP policies. ### `MCP_URL` Set the external base URL for your MCP server. This is useful when running behind a reverse proxy (ngrok, E2B sandboxes, Cloudflare tunnels) where the public URL differs from `localhost`. When set, the CLI will use this URL for widget asset URLs and Vite HMR WebSocket connections, ensuring everything works correctly through the proxy. **Default behavior:** * If not set, the CLI generates a `localhost` URL automatically * If set, the CLI preserves your value and does not overwrite it **Examples:** ```bash theme={null} # ngrok tunnel MCP_URL=https://abc123.ngrok.io npx @mcp-use/cli dev # E2B sandbox MCP_URL=https://3000-abc123.e2b.app npx @mcp-use/cli dev # Cloudflare tunnel MCP_URL=https://my-tunnel.trycloudflare.com npx @mcp-use/cli dev ``` > [!TIP] > > When using a reverse proxy, set `MCP_URL` to the public-facing URL. This ensures widget hot-reload (HMR) and asset loading work correctly through the proxy. ## Related Documentation * [Getting Started](/inspector/index) - Overview of the inspector * [Connection Settings](/inspector/connection-settings) - Advanced connection configuration * [Mount the Inspector](/inspector/integration) - Serve the Inspector from an app # Command Palette Source: https://docs.mcp-use.com/inspector/command-palette Search Inspector servers, tools, prompts, resources, saved requests, and client setup actions. Press `Cmd/Ctrl + K` to open the command palette from anywhere in the Inspector. It searches the current Inspector state and lets you jump directly to the item you choose. ## What you can open The command palette searches: * connected servers by display name or URL * tools by name, description, and server * prompts by name, description, and server * resources by name, URI, and server * saved tool requests * global navigation actions * Add to Client actions for supported clients Search is fuzzy, so partial words usually work. For example, `lin iss` can match a Linear issue tool if that tool is connected. ## Run a tool from search Use the command palette when you know the tool name and want to skip tab navigation. 1. Press `Cmd/Ctrl + K`. 2. Type the tool name or part of its description. 3. Select the tool. 4. Fill the generated input form. 5. Run the tool. The Inspector opens the Tools tab with that tool selected. ## Load a saved request Saved requests appear in their own results category. Select one to open the matching tool with its saved arguments already loaded. Use saved requests for repeatable calls such as regression checks, widget test cases, or long input payloads. ## Switch servers When more than one server is connected, search by server display name or URL. Selecting a server opens that server's Inspector view. Display names are useful here. Rename saved servers from [Connection settings](/inspector/connection-settings) when several URLs are hard to scan. ## Add a server to a client Add to Client commands appear when a connected server can be installed or copied into a supported client. Search for the client name, then choose the matching action. Depending on the client, the action may open a deep link, download a configuration file, or copy a command to the clipboard. ## Keyboard controls | Key | Action | | - | - | | `Cmd/Ctrl + K` | Open the command palette. | | `Up` / `Down` | Move through results. | | `Enter` | Open the selected result. | | `Esc` | Close the palette. | For the full shortcut reference, see [Keyboard shortcuts](/inspector/keyboard-shortcuts). # Connection settings Source: https://docs.mcp-use.com/inspector/connection-settings Choose how the Inspector connects to an MCP server. Most servers work with only a transport and URL. Change connection settings when the browser cannot reach the server directly, when you want clearer names for saved servers, when OAuth needs pre-registered credentials, or when long-running tools need more time. ## Choose Auto, Direct, or Via Proxy The Inspector uses **Auto** mode by default: it tries a direct browser connection first, then falls back to the configured Inspector proxy if direct access fails because of CORS or network policy. | Connection mode | Use it when | Avoid it when | | - | - | - | | **Auto** | You want the Inspector to try Direct first and fall back to the proxy when needed. | You need to test one specific connection path. | | **Direct** | The server is local, public, or reachable from your browser. | The browser blocks the request because of CORS or network policy. | | **Via Proxy** | The browser is blocked by CORS, or you need to test proxy behavior. | The server works directly; proxying adds another moving part. | ## Name saved servers Set a display name when several saved servers have similar URLs. Changing only the display name updates labels in the dashboard, server list, header, command palette, and server picker. It does not reconnect the server or clear auth tokens. ## Add headers only when the server requires them Use custom headers for server-specific requirements such as bearer tokens, API keys, or version headers. Header values are used for the live connection only. They are intentionally not saved or restored after a reload, so supply them again at runtime. Prefer OAuth when the server supports it. > [!WARNING] > > Copy Config includes current form values. Remove OAuth tokens, API keys, and > other secrets before sharing exported configuration. ## Configure OAuth By default the inspector relies on Dynamic Client Registration (DCR), so no credentials are needed. Use the Authentication dialog when the upstream auth server doesn't expose `registration_endpoint` (common for proxy-mode servers fronting Slack, WorkOS, or GitHub). OAuth client secrets are runtime-only and are not restored after a reload. | Field | When to set it | | - | - | | Client ID | Use a pre-registered OAuth client instead of DCR. | | Client Secret | Use a confidential client; the SDK switches token endpoint auth away from `none`. | | Scope | Request a provider-specific space-separated scope list. | When a server protects the whole connection, it enters `pending_auth`. Click **Authenticate**, complete the provider flow, and return to the Inspector. If a popup is blocked, use the open-auth-page fallback link. Mixed-auth servers behave differently: the anonymous connection remains `ready`, and the Inspector shows **This server is using mixed auth** with an **Authenticate** action. Public operations remain available. You can authenticate up front, or wait for a protected tool, resource, or prompt to return a wire-level OAuth challenge and then authenticate. The classification comes from RFC 9728 protected-resource metadata discovered by the official MCP SDK after a successful anonymous connection. The Inspector does not use host-specific rules or interpret tool-level `isError` text as an OAuth challenge. Browser OAuth session values are encrypted at rest with AES-256-GCM. The non-extractable origin key is kept in IndexedDB, while versioned ciphertext envelopes remain in localStorage so popup storage events and reload persistence continue to work. ## Configuration Import/Export Use **Copy Config** to export the current connection form as JSON. Paste JSON into the URL field to populate the form in another Inspector instance. Example configuration: ```json theme={null} { "url": "https://mcp.example.com/mcp", "transportType": "http", "connectionMode": "auto", "headers": { "Authorization": "Bearer token123" }, "requestTimeout": 10000, "resetTimeoutOnProgress": true, "maxTotalTimeout": 60000, "oauth": { "clientId": "your-client-id", "clientSecret": "your-client-secret", "scope": "read write" } } ``` > [!NOTE] > > The paste detection only works in the URL field. Remove OAuth tokens, API keys, and other secrets before sharing a copied config. ## URL and tabs The Inspector keeps the active tab in the page URL (`?tab=...`). Switching tabs updates the query string so a refresh or shared link restores the same view. ## Tune timeouts for long work Use timeout settings only when a valid tool call or resource read needs more time. | Setting | Default | What it controls | | - | - | - | | Request timeout | `10000` ms | Time allowed for one request. | | Maximum total timeout | `60000` ms | Total time allowed across retries and progress updates. | If a request times out, first confirm the server eventually responds. Then raise the timeout to match the expected tool runtime. # Debug widgets in the Inspector Source: https://docs.mcp-use.com/inspector/debugging-chatgpt-apps Test MCP Apps widgets, ChatGPT compatibility, layout, CSP, and widget data in the Inspector. Use the Inspector to debug a widget before you try it in a production host. The fastest loop is: connect your server, run the tool that returns the widget, inspect the widget data, then test layout, display modes, and CSP. For building widgets, start with [Build widgets](/typescript/mcp-apps/widgets). For hook fields and host actions, use the [`useWidget()` API reference](/typescript/api-reference/react/usewidget). ## Connect the widget server Run your mcp-use app locally: ```bash theme={null} npm run dev ``` Open `http://localhost:3000/mcp/inspector` and connect to `http://localhost:3000/mcp`. If the server is remote, connect to its MCP endpoint instead. Use **Direct** first, then try **Via Proxy** only when the browser cannot reach the server directly. ## Run the widget-returning tool Open the **Tools** tab, select the tool that returns the widget, and run it with a small input. The widget should render below the tool result. The raw result should include the widget metadata and the structured data passed to the widget. If the tool succeeds but no widget renders, check these values first: * `widget.name` in the server tool definition * the matching folder under `resources/` * the tool result metadata that points to the widget resource * browser console errors from the widget iframe ## Switch protocols when compatibility matters The Inspector can test MCP Apps behavior and ChatGPT Apps SDK compatibility for widgets that support both runtimes. Use the protocol toggle when it appears: | Protocol | What it tests | | - | - | | **MCP Apps** | The standard MCP Apps bridge over `postMessage`. | | **ChatGPT Apps** | ChatGPT compatibility behavior, including Apps SDK-style host globals. | Prefer `useWidget()` and other `mcp-use/react` hooks in widget code. They abstract over the runtime differences that the Inspector is testing. See [Apps SDK compatibility](/typescript/mcp-apps/apps-sdk-compatibility) when you need ChatGPT-specific behavior. ## Inspect props, output, metadata, and state Use the widget debug panels to confirm what the widget receives. | Data | What to verify | | - | - | | `props` | The structured data the widget renders. | | `output` | The raw structured tool output, when exposed separately. | | `metadata` | Widget-only metadata such as timestamps, cache info, or host hints. | | `state` | Persisted widget state after user interactions. | | tool input | Arguments passed to the tool that produced the widget. | When `props` are missing, compare the server's `outputSchema` with the widget's expected prop shape. They should describe the same fields. ## Test layout and display modes Use the debug controls to test the widget in the contexts a host may provide. Check: * inline, picture-in-picture, and fullscreen display modes * desktop, tablet, and mobile sizing * touch and hover behavior * light and dark themes * locale and timezone-dependent formatting * safe-area insets for mobile layouts The host may grant a different display mode than the widget requests. Read `displayMode` from `useWidget()` when the current mode matters. ## Test Content Security Policy Use the widget-declared CSP mode before shipping a widget that loads external APIs, images, scripts, styles, or embeds. If the widget works in permissive mode but fails with widget-declared CSP, update the widget CSP configuration. See [Content Security Policy](/typescript/mcp-apps/content-security-policy) for the server and widget settings. ## Use console output Open browser DevTools while the widget is rendered. Console messages from the widget iframe help identify runtime errors, blocked requests, CSP violations, missing props, and failed tool calls. Keep console output intentional. Log the minimum state needed to debug the widget, then remove noisy logs before release. ## Test the widget in chat After the tool works directly, open the **Chat** tab and ask the model to use the tool. Use chat to verify end-to-end behavior: * the model chooses the right tool * the tool receives valid arguments * the model-visible text output is useful * the widget renders with the same structured data * widget actions such as tool calls, state updates, follow-up messages, and display-mode requests behave as expected Use the Tools tab again when you need to isolate whether a failure is in the tool, widget, or model behavior. ## Troubleshoot missing widgets If no widget appears, start with the smallest failing case. | Symptom | Check | | - | - | | Tool result appears, but no widget appears. | Confirm `widget.name` matches a folder under `resources/`. | | Widget frame appears blank. | Check iframe console errors and missing required props. | | Widget loads in permissive CSP only. | Add the required domains to widget CSP. | | ChatGPT protocol fails, but MCP Apps works. | Check [Apps SDK compatibility](/typescript/mcp-apps/apps-sdk-compatibility). | | A widget action fails. | Verify the tool name, arguments, auth state, and iframe console logs. | ## Next steps * Use [Build widgets](/typescript/mcp-apps/widgets) to review the server and widget structure. * Use [Interactivity](/typescript/mcp-apps/interactivity) to add tool calls, state, follow-up messages, and display controls. * Use [`useWidget()`](/typescript/api-reference/react/usewidget) for the full hook reference. # Inspector Source: https://docs.mcp-use.com/inspector/index Connect to an MCP server, run tools, inspect resources and prompts, and debug widgets. Use the Inspector when you need to test an MCP server from the browser. It lets you connect to a server, call tools with typed inputs, inspect resources and prompts, try chat, preview widgets, and copy client setup commands. [![Try this live](https://mintcdn.com/mcpuse/C8kWie3B44RcXcXB/images/UseLiveSmall.svg?fit=max\&auto=format\&n=C8kWie3B44RcXcXB\&q=85\&s=1e958317e42d5aa66125696e7777542e)](https://inspector.mcp-use.com) ![MCP Inspector dashboard](https://mintcdn.com/mcpuse/-dX3pYiRHSZpYTFG/images/inspector/inspector-dashboard.jpg?fit=max\&auto=format\&n=-dX3pYiRHSZpYTFG\&q=85\&s=a45b3ae6998884acf492e93725697739) If your server was created with `mcp-use`, run the dev server and open the local Inspector: ```bash theme={null} npm run dev ``` The default local URLs are: | URL | Purpose | | - | - | | `http://localhost:3000/mcp` | MCP endpoint | | `http://localhost:3000/mcp/inspector` | Inspector UI | You can also open the hosted Inspector at [inspector.mcp-use.com](https://inspector.mcp-use.com) or run it with [`npx @mcp-use/inspector`](/inspector/cli). ## Connect to a server Add a server from the dashboard. Choose the transport, enter the MCP endpoint URL, and click **Connect**. ![Inspector connection form](https://mintcdn.com/mcpuse/-dX3pYiRHSZpYTFG/images/inspector/connect-form.png?fit=max\&auto=format\&n=-dX3pYiRHSZpYTFG\&q=85\&s=fd226ba80cb22f38bd58ff64aed459a4) For most local and public HTTP servers, use **Direct**. Use **Via Proxy** only when the browser cannot reach the server directly because of CORS or network policy. See [Connection settings](/inspector/connection-settings) for the short decision guide. When a server protects the whole MCP endpoint with OAuth, the connection waits for authentication. Click **Authenticate**, complete the provider approval, and return to the Inspector. A mixed-auth server connects anonymously because its public tools are already usable. If it publishes OAuth protected-resource metadata, the server card and header show **This server is using mixed auth** with an **Authenticate** button. You can authenticate immediately or wait until a protected operation returns a wire-level OAuth challenge. The connection stays available for public operations while authentication is optional. ## Run a tool Open a connected server and select the **Tools** tab. Choose a tool, fill the generated form, and run it. ![Inspector server detail view with tools](https://mintcdn.com/mcpuse/-dX3pYiRHSZpYTFG/images/inspector/server-detail.png?fit=max\&auto=format\&n=-dX3pYiRHSZpYTFG\&q=85\&s=05cd5ed7f5b5dba0bc1d7ae23dcd251c) The Inspector shows the tool result, structured content, errors, and any widget returned by the tool. Use this view to verify schema validation, result shape, and widget data before testing the same server from a client. For mixed-auth servers, a protected tool can surface the authentication action only when it is needed. Authenticate, then retry the protected call. A normal MCP tool result with `isError: true` is still shown as a tool error; the Inspector does not infer OAuth from its text. ## Inspect resources and prompts Use **Resources** to read server-provided content by URI. Use **Prompts** to test reusable prompt templates with arguments. These tabs are useful when a client reports missing context. They show what the server actually exposes after connection and auth. ## Inspect Skills over MCP **Skills** is always present in the Inspector navigation. When a server does not advertise the experimental `io.modelcontextprotocol/skills` extension, the tab is disabled, like Sampling, with an explanation that Skills over MCP is not available from that server. When the extension is available, each skill appears as a folder containing its `SKILL.md` and supporting resources. When the extension is advertised but its catalog is empty, the tab is shown as a red error state and disabled, with a tooltip explaining that the server returned no skills. Select a file to read it on demand. Before previewing it, the Inspector verifies the raw SHA-256 digest advertised by the skill manifest. For `SKILL.md`, it also checks that the parsed YAML frontmatter matches the catalog entry. A digest mismatch blocks the preview instead of passing changed content to the user or model. Markdown, safe text, raster images, audio, and video have inline previews. Scripts, HTML, SVG, and other binary files are never executed; you can explicitly download verified files when needed. ## Try chat Use **Chat** to test how an LLM calls your server's tools in a conversation. The chat view can use hosted chat where available or a provider key stored in your browser. Keep chat testing focused on end-to-end behavior. Use the Tools tab first when you need to isolate input schemas, tool errors, or widget rendering. For servers that advertise Skills over MCP, chat receives a compact catalog of each skill's name, description, origin, and URI. When a skill is relevant, the chat host loads its `SKILL.md` and supporting resources lazily through the server's Skills over MCP and resource methods. It verifies each resource against the manifest's raw SHA-256 digest before making it available to the model. The Inspector never executes skill scripts or lets `allowed-tools` widen the selected MCP tool permissions. Skills over MCP remains experimental. Treat remote skill content as untrusted and review it before relying on its instructions. See the [working group](https://modelcontextprotocol.io/community/working-groups/skills-over-mcp), [SEP-2640](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2640), and [Agent Skills specification](https://agentskills.io/specification). ## Debug widgets When a tool returns an MCP App widget, the Inspector renders it below the tool result and exposes widget debug controls. Use the widget view to check: * the `props`, `output`, and metadata passed to the widget * inline, picture-in-picture, and fullscreen display modes * desktop, tablet, and mobile layout behavior * theme, locale, timezone, hover, touch, and safe-area settings * Content Security Policy behavior before trying the widget in a host See [Debug widgets in the Inspector](/inspector/debugging-chatgpt-apps) for the full workflow. ## Add the server to a client After a server connects, use **Add to Client** to install or copy setup for supported clients such as Cursor, VS Code, Claude Desktop, Claude Code, Gemini CLI, and Codex CLI. ![Add to Client dropdown in the Inspector](https://mintcdn.com/mcpuse/KxSD03INVc0k3tzd/images/inspector/add-to-client-dropdown.png?fit=max\&auto=format\&n=KxSD03INVc0k3tzd\&q=85\&s=90893b75cd76e2ccd01cbe0e7c7d7681) The Inspector uses the active connection settings when it prepares the client setup. Confirm the server URL and connection name before copying commands or opening client deep links. ## Command Palette Press `Cmd/Ctrl + K` to open the [Command Palette](/inspector/command-palette). Use it to jump to tools, prompts, resources, saved requests, connected servers, and client setup actions. For the full shortcut list, see [Keyboard shortcuts](/inspector/keyboard-shortcuts). For shareable links that open a server or tab directly, see [URL parameters](/inspector/url-parameters). ## Next steps > **[CLI usage](/inspector/cli)** > > Run the Inspector from the command line and auto-connect to a server. > **[Connection settings](/inspector/connection-settings)** > > Choose Direct or Via Proxy and tune connection details only when needed. > **[Debug widgets](/inspector/debugging-chatgpt-apps)** > > Test MCP Apps widgets, layout behavior, CSP, and display modes. > **[Mount the Inspector](/inspector/integration)** > > Serve the Inspector from an Express, Hono, or mcp-use server. > **[WebMCP Inspector](/inspector/webmcp-inspector)** > > Inspect the WebMCP tools a web page registers, from a Chrome side panel. # Integration Source: https://docs.mcp-use.com/inspector/integration Mount the Inspector in a mcp-use or Hono application. The Inspector is built-in local development tooling. `mcp-use` installs its prebuilt package, and `mcp-use dev` mounts it on the development listener at `/mcp/inspector`. ## Auto-Mounting with mcp-use When using a generated `mcp-use` project, run `npm run dev`. The CLI loads the Inspector supplied by `mcp-use`, serves its bundled UI locally, and opens `/mcp/inspector`. No extra dependency or CDN is involved. Production stays Inspector-free by default; use `mcp-use start --with-inspector` to mount it on the built server's existing listener. ### Example Generated and existing projects receive the Inspector through `mcp-use`. Add `@mcp-use/inspector` directly only when overriding the framework-supplied version or mounting it without `mcp-use`. ```typescript theme={null} import { MCPServer } from "mcp-use/server"; const server = new MCPServer({ name: "my-server", version: "1.0.0", }); // Add your tools, resources, prompts... server.tool(/* ... */); export default server; ``` Then run `mcp-use dev`; the Inspector is available at `http://localhost:3000/mcp/inspector`. Use `--no-inspector` for a headless development run. To inspect the production build locally, build once and opt in when starting it: ```bash theme={null} mcp-use build mcp-use start --with-inspector ``` This changes neither the build output nor its manifest. Treat a production Inspector as an internal tool: it can invoke MCP tools and proxy OAuth flows. ## Manual Integration For custom development servers, `mountInspector()` from `@mcp-use/inspector` provides the complete local Inspector: packaged UI, proxy, OAuth BFF, and callbacks. It can register on Hono/Express or return a framework-neutral Fetch handler. ```typescript theme={null} import { mountInspector } from "@mcp-use/inspector"; const inspect = mountInspector({ basePath: "/mcp", autoConnectUrl: "http://localhost:3000/mcp", }); const response = await inspect(request); ``` ### Hono Integration Mount the Inspector on a Hono application: ```typescript theme={null} import { Hono } from "hono"; import { mountInspector } from "@mcp-use/inspector"; const app = new Hono(); // Your Hono routes app.get("/api/health", (c) => { return c.json({ status: "ok" }); }); // Mount inspector at /mcp/inspector mountInspector(app, { basePath: "/mcp" }); // Start server with your Hono adapter export default app; ``` ## Path Customization `basePath` defaults to `/mcp`, so the Inspector lives at `/mcp/inspector`. Set `basePath: ''` for `/inspector`, or use another MCP prefix. ### Hono with Custom Path ```typescript theme={null} import { Hono } from "hono"; import { mountInspector } from "@mcp-use/inspector"; const app = new Hono(); mountInspector(app, { basePath: "/debug" }); // Inspector now available at http://localhost:3000/debug/inspector ``` ## Configuration Options ### `mountInspector` Options Pass options only when the default mount behavior is not enough. ```typescript theme={null} import { mountInspector } from "@mcp-use/inspector"; mountInspector(app, { basePath: "/mcp", autoConnectUrl: "http://localhost:3000/mcp", sandboxOrigin: "https://sandbox.example.com", }); ``` | Option | Type | Default | Description | | - | - | - | - | | `basePath` | `string` | `'/mcp'` | MCP prefix; Inspector mounts at `${basePath}/inspector` | | `autoConnectUrl` | `string \| null` | Current request origin + `basePath` | MCP server URL to auto-connect on load; `null` disables | | `devMode` | `boolean` | `true` | Enables same-origin sandbox for MCP Apps widgets | | `sandboxOrigin` | `string \| null` | `undefined` | Override the sandbox origin for MCP Apps widgets | | `oauthProxyAllowLoopback` | `boolean` | `true` | Permit local proxy/OAuth access to loopback targets | ## Protect mounted Inspector routes The Inspector can call tools, read resources, and inspect prompts on any connected server. Keep it in local development. If a custom integration exposes it on a network, disable loopback proxying and put it behind the same access controls as other internal tools. Each mounted Inspector also applies process-local limits of 120 proxy/OAuth requests and 600 asset requests per minute. Exhausted routes return `429 Too Many Requests` with `Retry-After`; these limits complement, rather than replace, network-edge authentication and rate limiting. ## Related Documentation * [Getting Started](/inspector/index) - Basic inspector usage * [CLI Usage](/inspector/cli) - Standalone inspector usage * [Inspector chat components](/typescript/api-reference/client/inspector-chat-components) - API reference for exported chat UI * [Debug widgets in the Inspector](/inspector/debugging-chatgpt-apps) - Test widget rendering and host behavior # Keyboard shortcuts Source: https://docs.mcp-use.com/inspector/keyboard-shortcuts Reference for Inspector keyboard shortcuts. Use keyboard shortcuts to move between Inspector views without leaving the current server context. ## Shortcuts | Shortcut | Action | Works while typing? | | - | - | - | | `Cmd/Ctrl + K` | Open the command palette. | Yes | | `Cmd/Ctrl + O` | Start a new chat. | No | | `Esc` | Close overlays, close dialogs, or blur the focused element. | Yes | | `t` | Open the Tools tab. | No | | `p` | Open the Prompts tab. | No | | `r` | Open the Resources tab. | No | | `c` | Open the Chat tab. | No | | `h` | Return to the dashboard. | No | | `f` | Focus search in the current tab when the tab has search. | No | `Cmd/Ctrl + K` is the only shortcut that intentionally works while an input field is focused. Single-letter shortcuts are disabled while you type in inputs, textareas, and content-editable elements. ## Command palette keys After opening the command palette: | Key | Action | | - | - | | `Up` / `Down` | Move through results. | | `Enter` | Open the selected result or run the selected command. | | `Esc` | Close the command palette. | See [Command Palette](/inspector/command-palette) for what you can search and open. # Self-Hosting Source: https://docs.mcp-use.com/inspector/self-hosting Deploy your own MCP Inspector instance with Docker. Run the Inspector on your own infrastructure when you need full control over your debugging environment. The official Docker image is published at [`mcpuse/inspector`](https://hub.docker.com/r/mcpuse/inspector) on Docker Hub. ## Quick start ```bash theme={null} docker run -d -p 127.0.0.1:8080:8080 --name mcp-inspector mcpuse/inspector:latest ``` Then open `http://localhost:8080` to access your self-hosted Inspector. > [!WARNING] > > Anyone who can reach the Inspector can use it to connect to and call your MCP servers. The examples bind to `127.0.0.1` so the Inspector is only reachable from the host itself. If you need remote access, put it behind a reverse proxy with authentication and TLS, or restrict access with firewall rules — don't publish port 8080 on all interfaces. ## Deployment options **Docker Run** ```bash theme={null} docker run -d \ --name mcp-inspector \ -p 127.0.0.1:8080:8080 \ mcpuse/inspector:latest ``` **Docker Compose** ```yaml theme={null} services: mcp-inspector: image: mcpuse/inspector:latest ports: - "127.0.0.1:8080:8080" restart: unless-stopped healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/inspector"] interval: 30s timeout: 10s retries: 3 ``` > [!NOTE] > > The image is based on `node:20-alpine`, which ships `wget` (BusyBox) but not `curl` — use `wget` in healthchecks. ## Ports The container always listens on port `8080` — the image's start command pins it with `--port 8080`, so a `PORT` environment variable has no effect. To serve on a different host port, remap it with Docker instead: ```bash theme={null} docker run -d -p 127.0.0.1:3001:8080 mcpuse/inspector:latest ``` `NODE_ENV=production` is already set in the image; no environment variables are required. ## Air-gapped installation For hosts without registry access, transfer the image as a tarball: ```bash theme={null} # On a connected host docker pull mcpuse/inspector:latest docker save mcpuse/inspector:latest -o mcp-inspector.tar # On the air-gapped host docker load -i mcp-inspector.tar ``` > [!NOTE] > > When connecting from a self-hosted Inspector to an MCP server on another host, the browser must be able to reach the server directly, or you can use the proxy connection mode. See [Connection settings](/inspector/connection-settings) for when to use each. ## Alternatives Self-hosting is one of three ways to run the Inspector: | Option | Command | Best for | | - | - | - | | Hosted | [inspector.mcp-use.com](https://inspector.mcp-use.com) | Quick testing, no install | | Local CLI | `npx @mcp-use/inspector` | Local development | | Self-hosted | `docker run mcpuse/inspector:latest` | Production, enterprise, air-gapped | Servers built with `mcp-use` also auto-mount the Inspector at `/inspector` — see the [Inspector overview](/inspector/index). # URL parameters Source: https://docs.mcp-use.com/inspector/url-parameters Open the Inspector with a selected server, tab, or embedded layout. Use URL parameters when you need a link that opens the Inspector on a specific server, starts a connection automatically, or restores a tab. ## Parameters | Parameter | Purpose | Values | | - | - | - | | `server` | Select an existing connection by server ID or URL. If no saved connection matches and the value is an HTTP(S) URL, connect to it. | Connection ID or URL string | | `autoConnect` | Connect to a server when the Inspector loads. | URL string or URL-encoded JSON config | | `tab` | Open a specific server tab. | `tools`, `prompts`, `resources`, `chat`, `sampling`, `elicitation`, `notifications`, `playground` | | `tunnelUrl` | Preserve a tunnel URL while navigating. Usually set by the CLI. | URL string | | `embedded` | Use embedded mode with reduced page chrome. | `true` | | `embeddedConfig` | Configure embedded styling. | URL-encoded JSON config | ## Select or connect to a server Use `server` when the Inspector should select a saved server by URL: ```text theme={null} /?server=https://mcp.example.com/mcp ``` If the server is not saved yet, the Inspector treats the HTTP(S) value like `autoConnect` and connects to it. ## Auto-connect on load Use `autoConnect` when a link should create the connection immediately: ```text theme={null} /?autoConnect=https://mcp.example.com/mcp ``` For advanced connection options, pass a URL-encoded JSON object. The `url` field is required. ```json theme={null} { "url": "https://mcp.example.com/mcp", "name": "Example server", "transportType": "http", "connectionMode": "auto", "connectionType": "Direct" } ``` Supported JSON fields are `url` (required), `name`, `transportType` (`"http"` or `"sse"`), `connectionMode` (`"auto"`, `"direct"`, or `"proxy"`), `autoProxyFallback`, `connectionType` (`"Direct"` or `"Via Proxy"` for older links), `customHeaders`, `auth`, `requestTimeout`, `resetTimeoutOnProgress`, and `maxTotalTimeout`. > [!TIP] > > When passing a JSON object for **autoConnect**, URL-encode the value so special characters are valid in the query string. ## Open a tab Use `tab` by itself to restore a view, or combine it with `server` or `autoConnect`. ```text theme={null} /?server=https://mcp.example.com/mcp&tab=tools ``` The Inspector also updates `tab` as you move between server tabs, so refreshes keep the current view. ## Embedded mode Use `embedded=true` when the Inspector is hosted inside another UI, such as an iframe. ```text theme={null} /?embedded=true ``` Use `embeddedConfig` with a URL-encoded JSON object when the embedded host needs styling overrides. ```json theme={null} { "backgroundColor": "#f5f5f5", "padding": "16px" } ``` ## Example links Open the hosted Inspector and connect to a server: ```text theme={null} https://inspector.mcp-use.com/inspect?autoConnect=https://your-server.com/mcp ``` Open the hosted Inspector, connect to a server, and show Tools: ```text theme={null} https://inspector.mcp-use.com/inspect?server=https://your-server.com/mcp&tab=tools ``` # WebMCP Inspector Source: https://docs.mcp-use.com/inspector/webmcp-inspector Inspect and call the WebMCP tools a web page registers, from a Chrome side panel. The WebMCP Inspector is a Chrome extension that inspects the WebMCP server a web page exposes. It opens as a side panel next to the page, lists the tools that page registers, and lets you call them with typed inputs and read the results without leaving the tab. Reach for it when you are building WebMCP into a website and need to answer questions like: * Are my tools actually registered, and with the schemas I expect? * Does a tool run correctly with a given set of parameters? * Do tools appear and disappear as they should when the page state or route changes? It is built with [WXT](https://wxt.dev), React, and TypeScript, and reuses components from the [mcp-use Inspector](/inspector/index). Unlike the Inspector, it does not connect to remote MCP servers — it only talks to the WebMCP API of the page in the active tab. The source lives at [mcp-use/webmcp-inspector](https://github.com/mcp-use/webmcp-inspector). > [!NOTE] > > WebMCP is experimental. If the API is unavailable on a page, enable **WebMCP for testing** > in `chrome://flags` and relaunch a compatible Chromium build. ## Install from the Chrome Web Store **1. Add the extension** Open the [WebMCP Inspector listing](https://chromewebstore.google.com/detail/webmcp-inspector/dgdidjgjofcenipdfaoebdeeppideadh) and click **Add to Chrome**. **2. Open the panel** Open a WebMCP-enabled page and click the extension's toolbar icon to open the side panel. > [!TIP] > > Clicking the toolbar icon is what grants the extension access to the current site, so > click it again after you switch to another site. Chrome internal pages and the Chrome > Web Store cannot be inspected. ## Inspect and call tools With the panel open, the tool list shows each tool the page registered with its description and parameter count, and a search box to filter them. Select a tool to get a form generated from its schema, fill it in, and run it with **Execute** (or `Cmd/Ctrl + Enter`). The panel validates input against the tool's JSON Schema before execution, and offers a raw JSON mode when a form is awkward for nested inputs. Results are shown with timing and errors, in a split you can drag or expand to fullscreen. Requests you want to keep can be saved by name; saved requests are stored locally and scoped to the site's origin. The list refreshes automatically when the page registers or removes tools, when you change tabs, and on page loads. ## Build from source (contributors) > [!NOTE] > > You only need this if you are working on the extension itself. To use the Inspector, > install it from the Chrome Web Store above. Use Node 22.12+ and pnpm. ```bash theme={null} git clone https://github.com/mcp-use/webmcp-inspector cd webmcp-inspector pnpm install pnpm build ``` Then open `chrome://extensions`, turn on **Developer mode**, click **Load unpacked**, and select `.output/chrome-mv3`. For iterating on the extension itself, `pnpm dev` runs a WXT development build with hot reload; load `.output/chrome-mv3-dev` instead. `pnpm zip` produces a release zip in `.output`. ## Next steps > **[mcp-use Inspector](/inspector/index)** > > Debug a remote or local MCP server from the browser: tools, resources, prompts, chat, > and widgets. > **[Chrome WebMCP docs](https://developer.chrome.com/docs/ai/webmcp/imperative-api)** > > The imperative WebMCP API a page uses to register the tools this extension inspects. # Installation Source: https://docs.mcp-use.com/python/getting-started/installation Install mcp-use and get your development environment ready > [!NOTE] > > **Prerequisites**: > > * Install [Python](https://python.org/) (version 3.11 or higher) > * pip, uv, or poetry package manager ## Install mcp-use ```bash pip theme={null} pip install mcp-use ``` ```bash uv theme={null} uv add mcp-use ``` ```bash poetry theme={null} poetry add mcp-use ``` This gives you access to everything: **MCPAgent**, **MCPClient**, and **MCPServer**. ## LLM Providers (for Agents) If you're building agents, install your preferred LLM provider: ```bash OpenAI theme={null} pip install langchain-openai ``` ```bash Anthropic theme={null} pip install langchain-anthropic ``` ```bash Google theme={null} pip install langchain-google-genai ``` ```bash Groq theme={null} pip install langchain-groq ``` > [!WARNING] > > **Tool Calling Required**: Only models with tool calling capabilities can be used with mcp-use agents. ## Environment Variables Create a `.env` file in your project root: ```bash theme={null} OPENAI_API_KEY=sk-... ANTHROPIC_API_KEY=sk-ant-... GOOGLE_API_KEY=AI... GROQ_API_KEY=gsk_... ``` Load them in your scripts: ```python theme={null} from dotenv import load_dotenv load_dotenv() ``` ## Development Installation Install from source for the latest features or to contribute: ```bash pip theme={null} git clone https://github.com/mcp-use/mcp-use.git cd mcp-use/libraries/python pip install -e . ``` ```bash dev mode theme={null} git clone https://github.com/mcp-use/mcp-use.git cd mcp-use/libraries/python pip install -e ".[dev]" ``` ## Next Steps > **[Agent](/python/agent/building-custom-agents)** > > Build AI Agents with tool calling capabilities through MCP connections > **[Client](/python/client/connection-types)** > > A full featured MCP Client implementation for Python > **[Server](/python/server)** > > The MCP Server framework implementation for Python > [!TIP] > > **Need Help?** Join our [Discord](https://discord.gg/XkNkSkMz3V) or [Github](https://github.com/mcp-use/mcp-use) communities. # Quickstart Source: https://docs.mcp-use.com/python/getting-started/quickstart Get started with mcp-use in minutes For the complete documentation index, see [llms.txt](https://mcp-use.com/docs/llms.txt). **mcp-use** is a unified MCP framework to build **MCP servers**, **MCP clients** and **MCP Agents**. ```mermaid theme={null} %%{init: {'theme':'neutral'}}%% graph LR Agent[MCP Agent] -->|uses| Client[MCP Client] Client -->|connects to| Server[MCP Server] Server -->|provides tools| Client ``` | Section | Description | | | - | - | - | | [Agent](#mcp-agent) | An AI Agent with tool calling capabilities through MCP connections | [Examples](https://github.com/mcp-use/mcp-use/tree/main/libraries/python/examples) | | [Client](#mcp-client) | A full featured MCP Client implementation for Python with async support | [Examples](https://github.com/mcp-use/mcp-use/tree/main/libraries/python/examples) | | [Server](#mcp-server) | The MCP Server framework implementation for Python | [Examples](https://github.com/mcp-use/mcp-use/tree/main/libraries/python/examples) | ## MCP Agent **mcp-use** has a complete MCP Agent implementation for Python. **MCP Agents** are AI-powered agents that can use tools from MCP servers to accomplish complex tasks. They reason across multiple steps, selecting and executing tools as needed. Building such agents is easy with **mcp-use**, all you need is an LLM and the MCP Client. ```bash pip theme={null} pip install mcp-use langchain-openai ``` ```bash uv theme={null} uv add mcp-use langchain-openai ``` ```bash poetry theme={null} poetry add mcp-use langchain-openai ``` > [!NOTE] > > The agent requires a LangChain LLM provider package. The examples use `langchain-openai` - swap for `langchain-anthropic`, `langchain-google-genai`, or `langchain-groq` as needed. Here's a simple example to get you started for an agent with **browser tools** support. ```python theme={null} import asyncio from langchain_openai import ChatOpenAI # use your preferred LLM provider from mcp_use import MCPAgent, MCPClient async def main(): # Create MCPClient from configuration object client = MCPClient({ "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"], "env": { "DISPLAY": ":1" } } } }) # Create agent with the client agent = MCPAgent( llm=ChatOpenAI(model="gpt-5.5"), # use your preferred LLM provider client=client, max_steps=30 ) # Run the query result = await agent.run( "Find the best restaurant in San Francisco USING GOOGLE SEARCH" ) print(f"\nResult: {result}") # Clean up await client.close_all_sessions() if __name__ == "__main__": asyncio.run(main()) ``` > [!TIP] > > For multi-server setups, tool restrictions, and advanced configuration options, see the [Agent Configuration](/python/agent/agent-configuration) and [Client Configuration](/python/client/client-configuration) guides. For a complete overview of the mcp-use MCP Agent, see the [MCP Agent](/python/agent/building-custom-agents) documentation. ### Available MCP Servers mcp-use supports **any MCP server**. Check out the [Awesome MCP Servers](https://github.com/punkpeye/awesome-mcp-servers) list for available options. Or deploy your own following the instruction [below](#mcp-server). ## MCP Client **mcp-use** has a complete MCP Client implementation for Python with full async support. It supports stdio and HTTP with SSE transports for connecting to any MCP server. ```bash pip theme={null} pip install mcp-use ``` ```bash uv theme={null} uv add mcp-use ``` ```bash poetry theme={null} poetry add mcp-use ``` Then create a new MCP Client: ```python theme={null} import asyncio from mcp_use import MCPClient async def main(): client = MCPClient({ "mcpServers": { "everything": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-everything"] } } }) # Initialize all configured sessions await client.create_all_sessions() # Get the session for a specific server session = client.get_session("everything") # List available tools tools = await session.list_tools() print(f"Available tools: {[t.name for t in tools]}") # Call a specific tool with arguments result = await session.call_tool("add", {"a": 1, "b": 2}) print(f"Result: {result}") # Clean up await client.close_all_sessions() if __name__ == "__main__": asyncio.run(main()) ``` To learn more about the MCP Client, see the [MCP Client](/python/client/connection-types) documentation. ## MCP Server **mcp-use** has a complete MCP server framework implementation for Python. It supports all official MCP features including tools, resources, prompts, and middleware. ```bash pip theme={null} pip install mcp-use ``` ```bash uv theme={null} uv add mcp-use ``` ```bash poetry theme={null} poetry add mcp-use ``` ### Scaffold a new project ```bash theme={null} # Via uvx (from PyPI) uvx --from mcp-use create-mcp-use my-server # Or if mcp-use is installed locally create-mcp-use my-server # Start the server cd my-server python server.py ``` ### Create an MCP server manually: ```python theme={null} from mcp_use import MCPServer server = MCPServer( name="my-server", version="1.0.0", instructions="A simple example server" ) # Define a tool @server.tool() def get_weather(city: str) -> dict: """Get weather for a city""" return {"temperature": 72, "condition": "sunny", "city": city} # Start the server if __name__ == "__main__": server.run() ``` To learn more about the MCP Server, see the [MCP Server](/python/server) documentation. *** ## Next Steps > **[Agent Configuration](/python/agent/agent-configuration)** > > Configure your Agent and connected MCP servers > **[LLM Integration](/python/agent/llm-integration)** > > Explore supported LLM providers and their setup > **[Examples](https://github.com/mcp-use/mcp-use/tree/main/libraries/python/examples)** > > Browse real-world examples and use cases > [!TIP] > > **Need Help?** Join our [Discord](https://discord.gg/XkNkSkMz3V) or [Github](https://github.com/mcp-use/mcp-use) communities. # Welcome Source: https://docs.mcp-use.com/python/getting-started/welcome Full-stack MCP framework for **Python** For the complete documentation index, see [llms.txt](https://mcp-use.com/docs/llms.txt). **mcp-use** is the fullstack MCP framework for Python. Build MCP Servers, MCP Apps, MCP Agents, and MCP Clients with a clean, typed, async-native API. ![mcp-use](https://mintcdn.com/mcpuse/wt6BMfRVwx5zEKIj/images/py_welcome.png?fit=max\&auto=format\&n=wt6BMfRVwx5zEKIj\&q=85\&s=16d154eda0eddaeb5b759663bd1c349b) Looking for the **TypeScript** docs? They're [here](/typescript/getting-started/welcome). > **[New to MCP?](/home/mcp101)** > > Start with MCP 101 - principles of the protocol, its three primitives, and how clients, servers, and agents fit together. ## Next Steps > **[Quickstart](/python/getting-started/quickstart)** > > Build your first MCP server in under 5 minutes. > **[Installation](/python/getting-started/installation)** > > Set up your Python environment. > **[MCP Server](/python/server/index)** > > Expose tools, resources, and prompts to any AI agent. > **[MCP Client](/python/client/client-configuration)** > > Connect to any MCP server programmatically. > **[MCP Agent](/python/agent/agent-configuration)** > > AI agents with tool-calling capabilities. > **[Inspector](/inspector/index)** > > Debug and test MCP servers interactively. > [!TIP] > > **Need help?** Join our [Discord](https://discord.gg/XkNkSkMz3V) or check out [GitHub](https://github.com/mcp-use/mcp-use). # Official SDK Compatibility Source: https://docs.mcp-use.com/python/server/compatibility Full compatibility with the official MCP Python SDK > [!NOTE] > > The mcp-use server framework is built on top of the official [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk). This ensures full compatibility with existing MCP clients and tools that adhere to the Model Context Protocol. mcp-use extends the SDK's core functionality, providing enhanced features without introducing breaking changes. ## Zero Breaking Changes mcp-use extends the official MCP Python SDK rather than replacing it, ensuring: * **All existing MCP clients work out of the box** * **Full protocol compliance** with MCP specifications * **Easy migration** from existing MCP servers * **Enhanced features** without breaking existing functionality ## Compatibility Matrix | Feature | FastMCP | mcp-use | Notes | | - | - | - | - | | MCP Protocol | ✅ | ✅ | Full compliance | | Tools | ✅ | ✅ | Same decorator API | | Resources | ✅ | ✅ | Same decorator API | | Prompts | ✅ | ✅ | Same decorator API | | Documentation | ❌ | ✅ | Built-in docs UI | | Inspector UI | ❌ | ✅ | Real-time monitoring | | Enhanced Logging | ❌ | ✅ | MCP method logging | | Much more to come... | ❌ | ✅ | Continuous enhancements | ## Migration Guide ### From FastMCP If you have an existing MCP server built with FastMCP, migration is as simple as changing the import: #### Migrating It literally cannot be easier to migrate from FastMCP to mcp-use. You just need to add `_use` to your import. ```python theme={null} from mcp.server import FastMCP #[!code --] from mcp_use.server import FastMCP #[!code ++] mcp = FastMCP() @mcp.tool() def add(a: int, b: int) -> int: """Add two numbers""" return a + b if __name__ == "__main__": mcp.run(transport="streamable-http", port=8000) ``` **That's it!** Just change the import and you get all the enhanced features: * Built-in inspector UI at `/inspector` * Enhanced logging with MCP method information * Documentation at `/docs` * OpenMCP configuration at `/openmcp.json` * Configurable paths for all endpoints ### Key Improvements 1. **Drop-in Replacement**: Same FastMCP API with enhanced features 2. **Built-in Documentation**: Automatic OpenAPI/Swagger docs at `/docs` 3. **Inspector UI**: Real-time monitoring and testing at `/inspector` 4. **Enhanced Logging**: MCP method information in structured logs 5. **Configurable Paths**: Customize all endpoint paths 6. **Much More Coming**: Continuous feature additions ## Protocol Compliance mcp-use maintains full compliance with the MCP protocol specifications: * **Tool Discovery**: Implements `tools/list` and `tools/call` endpoints * **Resource Management**: Implements `resources/list` and `resources/read` endpoints * **Prompt Templates**: Implements `prompts/list` and `prompts/get` endpoints * **Error Handling**: Proper error responses with MCP-compliant error codes * **Session Management**: Full support for MCP session lifecycle ## Client Compatibility All MCP clients that work with the official SDK will work with mcp-use servers: * **Claude Desktop**: Full compatibility * **ChatGPT**: Full compatibility * **Custom MCP Clients**: Full compatibility * **mcp-use Client**: Enhanced compatibility with additional features ## Testing Compatibility You can test your mcp-use server with any MCP client: ```bash theme={null} # Test with mcp-use client from mcp_use.client import MCPClient config = { "mcpServers": { "my-server": { "url": "http://localhost:3001/mcp" } } } client = MCPClient(config) session = await client.create_session("my-server") # List tools tools = await session.list_tools() print("Available tools:", [tool.name for tool in tools]) # Call a tool result = await session.call_tool("greet", {"name": "World"}) print("Result:", result) ``` ## Best Practices ### Maintaining Compatibility 1. **Use Type Hints**: Always use proper type hints for automatic schema generation 2. **Follow MCP Conventions**: Use descriptive tool names and clear documentation 3. **Handle Errors Gracefully**: Return proper error responses for invalid inputs 4. **Test with Multiple Clients**: Verify compatibility with different MCP clients ### Leveraging mcp-use Features 1. **Use Decorators**: Take advantage of the simplified decorator-based API 2. **Enable Documentation**: Use the built-in OpenAPI documentation 3. **Monitor with Inspector**: Use the inspector UI for debugging and monitoring 4. **Structured Logging**: Use JSON logging for better observability ## Next Steps * [Installation & Setup](/python/getting-started/installation) - Get started with mcp-use * [Quickstart Guide](/python/getting-started/quickstart) - Build your first server # Fastapi mount Source: https://docs.mcp-use.com/python/server/fastapi_mount # FastAPI Mounting Guide You can mount an `MCPServer` (or `FastMCP`) instance within an existing FastAPI application. This allows you to serve your MCP tools alongside your existing API endpoints. ## Basic Integration When mounting `MCPServer`, we need to ensure its internal task group (used for managing SSE streams) is properly initialized. We do this using FastAPI's lifespan events. ```python theme={null} from contextlib import asynccontextmanager from fastapi import FastAPI from mcp_use.server import MCPServer import uvicorn import anyio # 1. Create your MCP Server mcp = MCPServer("my-agent-server") @mcp.tool() def add(a: int, b: int) -> int: return a + b # 2. Define lifespan to manage MCP server startup/shutdown @asynccontextmanager async def lifespan(app: FastAPI): # Initialize the SSE task group async with anyio.create_task_group() as tg: # Inject the task group into the session manager mcp.session_manager._task_group = tg yield # 3. Create your existing FastAPI app with lifespan app = FastAPI(title="My Existing App", lifespan=lifespan) @app.get("/") def read_root(): return {"message": "Hello from the main app"} # 4. Mount the MCP Server mount_path = "/agent" app.mount(mount_path, mcp.app) if __name__ == "__main__": print(f"Serving MCP at http://localhost:8000{mount_path}/mcp") uvicorn.run(app, port=8000) ``` ## Important Considerations 1. **Lifespan Management:** The critical part is wrapping the application lifespan with an `anyio.create_task_group()` and assigning it to `mcp.session_manager._task_group`. This works around `FastMCP`'s assumption that it controls the main loop. 2. **Transport:** Mounting implies using the **Streamable HTTP** transport pattern. 3. **Paths:** The `MCPServer` has internal routes like `/mcp` (for SSE/POST) and `/docs`. When mounted at `/agent`, these become `/agent/mcp` and `/agent/docs`. ## Example with Shared State If you want your MCP tools to access the main application's state (like a database connection), you can pass that context into the tool or use a closure. ```python theme={null} fake_db = {"items": []} @mcp.tool() def add_item(name: str): fake_db["items"].append(name) return f"Added {name}" ``` # Introduction Source: https://docs.mcp-use.com/python/server/index Build MCP servers with mcp-use's enhanced server framework > The mcp-use server framework extends the official MCP Python SDK with enhanced features for building production-ready MCP servers. It provides built-in documentation endpoints, inspector UI, improved logging, and seamless integration with the mcp-use ecosystem. ## Why mcp-use Server Framework? While the [official MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) provides the core protocol functionality, mcp-use enhances it with production-ready features: > **[Official SDK Compatibility](/python/server/compatibility)** > > Fully compatible with the official MCP Python SDK. Extends existing functionality without breaking changes, ensuring seamless migration. > **[Inspector UI](/python/server/inspector)** > > Built-in web interface for real-time server monitoring, tool exploration, and debugging. Accessible at /inspector endpoint. > **[openmcp.json](/python/server/openmcp)** > > Automatic generation of openmcp.json endpoint for server discovery and metadata. Provides standardized server information for MCP clients and tools. > **[MCP-Specific Logging](/python/server/logging)** > > Enhanced logging system designed specifically for MCP servers with structured output, request tracing, and performance metrics. ## Compatibility ### Official MCP SDK mcp-use server framework is **fully compatible** with the official MCP Python SDK. It extends the SDK rather than replacing it, ensuring: * All official MCP features work as expected * Existing MCP servers can be easily migrated * Full compliance with MCP protocol specifications ### fastmcp2 mcp-use complements fastmcp2 by providing: * **Different Focus**: fastmcp2 focuses on rapid prototyping, mcp-use focuses on production features * **Enhanced Observability**: Better logging, metrics, and debugging tools * **Ecosystem Integration**: Native compatibility with mcp-use clients and agents * **Documentation**: Built-in API documentation and inspector UI You can use both frameworks in the same project if needed. ## Quick Start Build your first MCP server in minutes with this step-by-step guide: **1. Install mcp-use** ```bash theme={null} pip install mcp-use ``` **2. Create your server file** Create a new file called `my_server.py`: ```python theme={null} from mcp_use.server import MCPServer server = MCPServer( name="My Server", version="1.0.0", instructions="A simple example server" ) ``` **3. Add your first tool** Define a tool using the `@server.tool()` decorator: ```python theme={null} @server.tool() def echo(message: str) -> str: """Echo back the provided message.""" return f"Echo: {message}" ``` **4. Add more tools (optional)** Add additional tools to extend functionality: ```python theme={null} @server.tool() def calculate(a: int, b: int) -> int: """Add two numbers.""" return a + b @server.tool() def get_time() -> str: """Get current time.""" from datetime import datetime return datetime.now().isoformat() ``` **5. Run the server** Add the run command at the bottom of your file: ```python theme={null} if __name__ == "__main__": server.run(transport="streamable-http", debug=True) ``` Then run it: ```bash theme={null} python my_server.py ``` **6. Access your server** Your server is now running at `http://localhost:8000`: * **MCP endpoints**: `/mcp` * **OpenMCP metadata**: `/openmcp.json` (debug mode only) * **Documentation**: `/docs` (debug mode only) * **Inspector UI**: `/inspector` (debug mode only) ### Complete Example Here's the full code in one place: ```python theme={null} from mcp_use.server import MCPServer from datetime import datetime server = MCPServer( name="Example Server", version="1.0.0", instructions="This is an example server with a simple echo tool." ) @server.tool() def echo(message: str) -> str: """Echo back the provided message.""" return f"Echo: {message}" @server.tool() def calculate(a: int, b: int) -> int: """Add two numbers.""" return a + b @server.tool() def get_time() -> str: """Get current time.""" return datetime.now().isoformat() if __name__ == "__main__": server.run(transport="streamable-http", debug=True) ``` ### Transport Options Choose the right transport for your use case: ```python theme={null} # Standard input/output (for MCP clients like Claude Desktop) server.run(transport="stdio") # HTTP server (for web clients and testing) server.run(transport="streamable-http", host="0.0.0.0", port=8000) ``` ### Debug Mode Enable debug mode for development features: ```python theme={null} server = MCPServer(name="My Server", debug=True) ``` Debug mode provides: * `/openmcp.json` endpoint for server discovery * `/docs` endpoint with interactive documentation * Enhanced logging with detailed request information ### Server Icons Add icons to your server implementation so MCP clients can display them: ```python theme={null} from mcp.types import Icon from mcp_use.server import MCPServer server = MCPServer( name="My Server", icons=[Icon(src="https://example.com/icon.svg", mime_type="image/svg+xml")], ) ``` Icons are included in the `initialize` response and can be used by clients for display in tool pickers, server lists, etc. You can also set icons on individual tools via the `@server.tool()` decorator: ```python theme={null} @server.tool( icons=[Icon(src="https://example.com/tool-icon.png", mime_type="image/png")], ) def my_tool(param: str) -> str: return param ``` ## Next Steps * [Installation & Setup](/python/getting-started/installation) - Detailed installation instructions * [Running Your Server](/python/server/running) - Production deployment options * [Inspector UI](/python/server/inspector) - Monitor and debug your server # Prompts Source: https://docs.mcp-use.com/python/server/prompts Define and expose prompts from your MCP server Prompts are reusable message templates that help AI agents interact with your server effectively. They provide structured ways to guide conversations and standardize common interactions. ## Example ```python theme={null} @server.prompt( name="code_review", title="Code Review", description="Generate a code review prompt for a given language and focus area", ) def code_review_prompt(language: str, focus: str = "general") -> str: """Generate a code review prompt.""" focus_instructions = { "general": "for overall quality, readability, and best practices.", "security": "focusing on security vulnerabilities and potential exploits.", "performance": "focusing on performance optimizations and efficiency.", } instruction = focus_instructions.get(focus, focus_instructions["general"]) return f"Please review the following {language} code {instruction}" ``` ## Anatomy of a Prompt When a client calls `prompts/list`, the server returns metadata for each prompt including its arguments. Here's the JSON-RPC response that the example above produces when a client calls `prompts/list`: ```json theme={null} { "jsonrpc": "2.0", "id": 1, "result": { "prompts": [ { "name": "code_review", "title": "Code Review", "description": "Generate a code review prompt for a given language and focus area", "arguments": [ { "name": "language", "required": true }, { "name": "focus", "required": false } ] } ] } } ``` Here's what maps to what: | Python | MCP Schema | Notes | | - | - | - | | `name="code_review"` | `"name"` | Falls back to function name if omitted | | `title="Code Review"` | `"title"` | Human-readable display name | | `description="Generate a code review..."` | `"description"` | Falls back to docstring if omitted | | `language: str` (no default) | `{"name": "language", "required": true}` | Parameters without defaults are required | | `focus: str = "general"` | `{"name": "focus", "required": false}` | Parameters with defaults are optional | | `context: Context` | *(not in schema)* | Automatically excluded | ### Argument Descriptions You can add descriptions to prompt arguments the same way as tools, using `Annotated` and `Field`: ```python theme={null} from typing import Annotated from pydantic import Field @server.prompt(name="code_review") def code_review_prompt( language: Annotated[str, Field(description="The programming language of the code")], focus: Annotated[str, Field(description="Review focus area", default="general")], ) -> str: """Generate a code review prompt.""" return f"Please review the following {language} code for {focus}." ``` This adds `description` to each argument in the response: ```json theme={null} { "arguments": [ { "name": "language", "description": "The programming language of the code", "required": true }, { "name": "focus", "description": "Review focus area", "required": false } ] } ``` ## Minimal Definition At minimum, a prompt only needs a function: ```python theme={null} @server.prompt() def greeting() -> str: """A friendly greeting prompt.""" return "Hello! How can I help you today?" ``` The function name becomes the prompt name, and the docstring becomes the description. ## Using Context Access the MCP context for advanced features. Add a `Context` parameter - it's automatically excluded from the prompt's arguments: ```python theme={null} from mcp_use.server import Context @server.prompt(name="contextual") async def contextual_prompt(context: Context) -> str: """A prompt that uses context information.""" return "Based on the current context, please..." ``` ## Multi-Message Prompts Return structured messages for complex prompts: ```python theme={null} from mcp.types import PromptMessage, TextContent @server.prompt(name="interview") def interview_prompt(role: str) -> list[PromptMessage]: """Generate an interview prompt sequence.""" return [ PromptMessage( role="user", content=TextContent( type="text", text=f"I'm interviewing for a {role} position.", ), ), PromptMessage( role="assistant", content=TextContent( type="text", text=f"I'll help you prepare for your {role} interview. Let's start with common questions.", ), ), ] ``` ## Async Prompts Prompts can be async for dynamic content generation: ```python theme={null} @server.prompt(name="daily_brief") async def daily_brief() -> str: """Generate a daily briefing prompt.""" from datetime import datetime today = datetime.now().strftime("%A, %B %d") return f"Good morning! Today is {today}. What would you like to accomplish?" ``` ## Prompts vs Tools vs Resources | Aspect | Prompts | Tools | Resources | | - | - | - | - | | Purpose | Guide interactions | Perform actions | Expose data | | Returns | Message templates | Action results | Content/data | | Use case | Conversation starters, templates | Operations | Files, configs | | Invocation | User selects prompt | Agent calls tool | Agent reads resource | # Resources Source: https://docs.mcp-use.com/python/server/resources Define and expose resources from your MCP server Resources expose data to MCP clients. Unlike tools (which perform actions), resources provide read-only access to content like files, database records, or live data. ## Example ```python theme={null} @server.resource( uri="config://{section}", name="app_config", title="Application Config", description="Get configuration for a specific section", mime_type="application/json", ) def get_config(section: str) -> str: """Get configuration for a specific section.""" configs = { "database": '{"host": "localhost", "port": 5432}', "cache": '{"enabled": true, "ttl": 3600}', } return configs.get(section, '{"error": "Section not found"}') ``` ## Anatomy of a Resource When a client calls `resources/list`, the server returns metadata for each resource. Resources with URI templates (like `{section}`) are returned via `resources/templates/list` instead. Here's the JSON-RPC response that the example above produces when a client calls `resources/templates/list`: ```json theme={null} { "jsonrpc": "2.0", "id": 1, "result": { "resourceTemplates": [ { "uriTemplate": "config://{section}", "name": "app_config", "title": "Application Config", "description": "Get configuration for a specific section", "mimeType": "application/json" } ] } } ``` Here's what maps to what: | Python | MCP Schema | Notes | | - | - | - | | `uri="config://{section}"` | `"uriTemplate"` | `{section}` makes it a template; without it, it would be a static `"uri"` | | `name="app_config"` | `"name"` | Falls back to function name if omitted | | `title="Application Config"` | `"title"` | Human-readable display name | | `description="Get configuration..."` | `"description"` | Falls back to docstring if omitted | | `mime_type="application/json"` | `"mimeType"` | Tells clients how to interpret the content | | `section: str` | *(extracted from URI)* | Parameter matched from the URI template | > [!TIP] > > If your URI contains `{param}` placeholders, the resource is registered as a **template**. Otherwise, it's registered as a **static resource**. ## Static Resources Resources without URI parameters are static - they always return at the same URI: ```python theme={null} from datetime import datetime @server.resource( uri="time://current", name="current_time", title="Current Time", mime_type="text/plain", ) def current_time() -> str: """Returns the current server time.""" return datetime.now().isoformat() ``` ## Resource Templates Use `{param}` placeholders in the URI to create dynamic resources: ```python theme={null} @server.resource( uri="user://{user_id}", name="user_profile", title="User Profile", description="Get a user's profile by ID", mime_type="application/json", ) def get_user(user_id: str) -> str: """Fetch user profile by ID.""" users = {"1": "Alice", "2": "Bob"} name = users.get(user_id, "Unknown") return f'{{"id": "{user_id}", "name": "{name}"}}' ``` Clients request `user://123` and the function receives `user_id="123"`. ### Multiple Parameters Templates support multiple parameters: ```python theme={null} @server.resource( uri="file://{folder}/{filename}", name="file_content", mime_type="text/plain", ) def get_file(folder: str, filename: str) -> str: """Read a file from a folder.""" return f"Content of {folder}/{filename}" ``` ## Async Resources Resources can be async for I/O operations: ```python theme={null} import httpx @server.resource( uri="api://weather", mime_type="application/json", ) async def weather_data() -> str: """Fetch current weather data.""" async with httpx.AsyncClient() as client: response = await client.get("https://api.weather.com/current") return response.text ``` ## Binary Resources Return bytes for binary content: ```python theme={null} @server.resource( uri="image://logo", mime_type="image/png", ) def logo_image() -> bytes: """Return the application logo.""" with open("logo.png", "rb") as f: return f.read() ``` ## Resource Subscriptions Clients can subscribe to resources and receive notifications when they change. This follows the [MCP resource subscriptions spec](https://modelcontextprotocol.io/specification/2025-11-25/server/resources#subscriptions). ### How It Works 1. Client sends `resources/subscribe` with a resource URI 2. Your server updates the resource and calls `notify_resource_updated()` 3. All subscribed clients receive a `notifications/resources/updated` notification 4. Clients re-read the resource to get the new content MCPServer handles subscribe/unsubscribe tracking automatically - you just need to call `notify_resource_updated()` when your resource changes. ### Example ```python theme={null} current_price = 100.0 @server.resource(uri="data://price", name="stock_price", mime_type="text/plain") def get_price() -> str: return str(current_price) @server.tool() async def update_price(new_price: float) -> str: """Update the stock price and notify subscribers.""" global current_price current_price = new_price await server.notify_resource_updated("data://price") return f"Price updated to {new_price}" ``` When a client subscribes to `data://price` and then any client calls `update_price`, all subscribers receive the notification and can re-read the resource. > [!NOTE] > > Subscriptions are session-scoped - they're automatically cleaned up when a client disconnects. If the server restarts, clients need to re-subscribe. ## Common MIME Types | MIME Type | Use Case | | - | - | | `text/plain` | Plain text content | | `application/json` | JSON data | | `text/markdown` | Markdown documents | | `text/html` | HTML content | | `image/png` | PNG images | ## Resources vs Tools | Aspect | Resources | Tools | | - | - | - | | Purpose | Expose data | Perform actions | | Side effects | None (read-only) | May modify state | | Caching | Can be cached | Generally not cached | | Use case | Configuration, files, status | Operations, calculations | # Running the Server Source: https://docs.mcp-use.com/python/server/running How to run your mcp-use server with different transport methods > [!NOTE] > > Learn how to run your mcp-use server using different transport methods and configurations. ## Basic Usage ```python theme={null} from mcp_use.server import MCPServer server = MCPServer(name="My Server") # Run with stdio transport (for MCP clients) server.run(transport="stdio") # Run with HTTP transport (for web clients) server.run(transport="streamable-http") ``` ## Transport Methods ### stdio Transport Standard input/output transport for MCP clients: ```python theme={null} server.run(transport="stdio") ``` ### streamable-http Transport HTTP-based transport for web clients: ```python theme={null} server.run( transport="streamable-http", host="0.0.0.0", port=8000, reload=False, debug=False ) ``` ## Host and Port Configuration You can configure host and port either at initialization or when calling `run()`. Values passed to `run()` override those set in `__init__()`, and DNS rebinding protection is automatically reconfigured to match: ```python theme={null} # Set defaults at initialization server = MCPServer(name="My Server", host="0.0.0.0", port=3000) server.run() # Uses host="0.0.0.0", port=3000, no DNS protection # Override at runtime - DNS protection is reconfigured automatically server.run(host="127.0.0.1", port=8080) # Switches to localhost with DNS protection ``` ### Default Values | Parameter | Default | Description | | - | - | - | | `host` | `"0.0.0.0"` | Bind address. Use `"127.0.0.1"` for local-only access | | `port` | `8000` | Port number | ## Automatic Port Retry When the requested port is already in use (e.g., another server is running on port 8000), the server automatically tries the next available port instead of crashing: ``` Port 8000 is in use, using port 8001 instead. - Local: http://0.0.0.0:8001 - MCP: http://0.0.0.0:8001/mcp ``` The server tries up to 10 consecutive ports (8000, 8001, ..., 8009). If none are available, it raises an error. This makes it easy to run multiple MCP servers simultaneously during development without manually specifying different ports. > [!TIP] > > The startup output always shows the actual port the server bound to, so you'll know where to connect. ## Cloud and Proxy Deployments When deploying behind reverse proxies (Cloudflare, nginx, Fly.io, etc.), the server automatically configures DNS rebinding protection based on the host: * **`host="0.0.0.0"`** (default): DNS rebinding protection is **disabled**, allowing any Host header. This is safe when your proxy handles host validation. * **`host="127.0.0.1"`**: DNS rebinding protection is **enabled**, only allowing requests with `Host: 127.0.0.1:*` or `Host: localhost:*`. ```python theme={null} # Cloud deployment (behind proxy) - default, no DNS protection server = MCPServer(name="My Server") server.run(transport="streamable-http") # Local development - auto-enables DNS protection server = MCPServer(name="My Server", host="127.0.0.1") server.run(transport="streamable-http") ``` > [!WARNING] > > If you get **421 Misdirected Request** errors behind a proxy, ensure you're using > `host="0.0.0.0"` (the default). ## Debug Mode Enable debug mode for development features: ```python theme={null} server = MCPServer(name="My Server", debug=True) # Debug mode enables: # - /openmcp.json endpoint # - /docs endpoint # - /inspector endpoint # - Enhanced logging server.run(transport="streamable-http", debug=True) ``` ## Auto-reload Enable auto-reload during development: ```python theme={null} server.run(transport="streamable-http", reload=True) ``` ## Production Configuration ```python theme={null} server = MCPServer( name="My Server", host="0.0.0.0", port=8000, ) server.run( transport="streamable-http", reload=False, debug=False ) ``` ## Command Line Run directly with Python: ```bash theme={null} python my_server.py ``` Or use uvicorn directly: ```bash theme={null} uvicorn my_server:app --host 0.0.0.0 --port 8000 ``` # Session Management Source: https://docs.mcp-use.com/python/server/sessions Using session IDs in MCP servers Sessions keep per-client state (caching, auth, limits). Managed by the MCP SDK via `mcp-session-id` HTTP header (spec: [https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#session-management](https://modelcontextprotocol.io/specification/2025-11-25/basic/transports#session-management)). ## How it works * SDK generates a UUID when no session header is present. * Server returns it in `mcp-session-id` on initialize. * Client sends the header on all requests. * Server reuses the session; middleware sees it as `context.session_id`. ## Get session ID ```python theme={null} # Middleware sid = context.session_id or "anonymous" # Tool @server.tool() def session_id() -> dict: sid = server._get_session_id_from_request() return {"session_id": sid, "short": sid[:8] if sid else None} ``` ## Per-session patterns (minimal) **State / rate limit / cache key** by `context.session_id or "anonymous"`: ```python theme={null} class SessionState(Middleware): def __init__(self): self.counts = defaultdict(int) async def on_request(self, ctx, nxt): sid = ctx.session_id or "anonymous" self.counts[sid] += 1 return await nxt(ctx) ``` Per-session cache: ```python theme={null} class SessionCache(Middleware): def __init__(self): self.c = defaultdict(dict) async def on_read_resource(self, ctx, nxt): sid = ctx.session_id or "anonymous" uri = str(ctx.message.uri) cache = self.c[sid] if uri in cache: return cache[uri] res = await nxt(ctx); cache[uri] = res; return res ``` ## Notes * Only available on Streamable HTTP transport; stdio has no sessions. * Use per-session storage to avoid data leakage. * Keep session data lean; expire if needed. # Tools Source: https://docs.mcp-use.com/python/server/tools Define and expose tools from your MCP server Tools are the primary way your MCP server exposes functionality to clients. They represent actions that an AI agent can invoke to perform tasks. ## Example ```python theme={null} @server.tool( name="get_weather", title="Weather Information Provider", description="Get current weather information for a location", annotations=ToolAnnotations( readOnlyHint=True, openWorldHint=True, ), ) async def get_weather( location: Annotated[str, Field(description="City name or zip code")], units: Annotated[str, Field(description="Temperature units", default="celsius")], context: Context, ) -> str: """Get current weather information for a location.""" await context.info(f"Fetching weather for {location}") return f"Weather in {location}: 22 {units}" ``` ## Anatomy of a Tool Here's the JSON-RPC response that the example above produces when a client calls `tools/list`: ```json theme={null} { "jsonrpc": "2.0", "id": 1, "result": { "tools": [ { "name": "get_weather", "title": "Weather Information Provider", "description": "Get current weather information for a location", "annotations": { "readOnlyHint": true, "openWorldHint": true }, "inputSchema": { "type": "object", "properties": { "location": { "type": "string", "description": "City name or zip code" }, "units": { "type": "string", "description": "Temperature units", "default": "celsius" } }, "required": ["location"] } } ] } } ``` Here's what maps to what: | Python | MCP Schema | Notes | | - | - | - | | `name="get_weather"` | `"name"` | Falls back to function name if omitted | | `title="Weather Information Provider"` | `"title"` | Human-readable display name | | `description="Get current weather..."` | `"description"` | Falls back to docstring if omitted | | `annotations=ToolAnnotations(...)` | `"annotations"` | Behavioral hints for clients | | `location: str` | `"type": "string"` | Python type hint → JSON Schema type | | `Field(description="City name...")` | property `"description"` | Argument-level description | | `default="celsius"` | `"default": "celsius"` | Makes the parameter optional | | No default on `location` | `"required": ["location"]` | Parameters without defaults are required | | `context: Context` | *(not in schema)* | Automatically excluded from the schema | > [!TIP] > > Always use `Annotated[type, Field(description="...")]` for your tool parameters. Without it, LLMs calling your tool won't know what each argument means. ## Minimal Definition At minimum, a tool only needs a function with type hints: ```python theme={null} @server.tool() def greet(name: str) -> str: """Greet someone by name.""" return f"Hello, {name}!" ``` The function name becomes the tool name, the docstring becomes the description, and type hints define the input schema. ## Tool Options The `@server.tool()` decorator accepts these options: ```python theme={null} @server.tool( name="custom_name", # Override the function name title="Custom Title", # Human-readable title description="Custom desc", # Override the docstring annotations=ToolAnnotations( # Behavioral hints for clients destructiveHint=True, readOnlyHint=False, ), structured_output=True, # Return structured JSON output ) def my_tool(param: str) -> str: return param ``` ### Tool Annotations Tool annotations provide hints to clients about the tool's behavior: | Annotation | Description | | - | - | | `destructiveHint` | Tool may modify or delete data | | `readOnlyHint` | Tool only reads data, no side effects | | `idempotentHint` | Calling multiple times has same effect as once | | `openWorldHint` | Tool interacts with external systems | ## Async Tools Tools can be async for non-blocking I/O operations: ```python theme={null} import httpx @server.tool() async def fetch_url( url: Annotated[str, Field(description="The URL to fetch content from")], ) -> str: """Fetch content from a URL.""" async with httpx.AsyncClient() as client: response = await client.get(url) return response.text ``` ## Using Context Access the MCP context for logging and progress reporting. Add a `Context` parameter - it's automatically excluded from the tool's input schema: ```python theme={null} from mcp_use.server import Context @server.tool() async def long_task( items: Annotated[list[str], Field(description="Items to process")], context: Context, ) -> str: """Process items with progress reporting.""" results = [] for i, item in enumerate(items): await context.report_progress(i, len(items)) results.append(f"Processed: {item}") return "\n".join(results) ``` ## Parameter Types and JSON Schema Every tool parameter becomes a property in the tool's `inputSchema`. mcp-use uses [Pydantic](https://docs.pydantic.dev/) to generate [JSON Schema 2020-12](https://json-schema.org/draft/2020-12/schema) from your Python type hints. ### Type mapping | Python type | JSON Schema | Notes | | - | - | - | | `str` | `{"type": "string"}` | | | `int` | `{"type": "integer"}` | | | `float` | `{"type": "number"}` | | | `bool` | `{"type": "boolean"}` | | | `list[str]` | `{"type": "array", "items": {"type": "string"}}` | Works with any item type | | `dict[str, Any]` | `{"type": "object"}` | | | `Literal["a", "b"]` | `{"type": "string", "enum": ["a", "b"]}` | Renders as a dropdown in the Inspector | ### Required, optional, and nullable How you declare a parameter determines whether it appears in the `required` array: ```python theme={null} @server.tool() def example( # Required - no default, goes into "required" name: Annotated[str, Field(description="User name")], # Optional with default - NOT in "required", default shown in schema limit: Annotated[int, Field(description="Max results")] = 10, # Nullable - NOT in "required", type stays "string" (not anyOf) company: Annotated[str | None, Field(description="Company filter")] = None, ) -> str: ... ``` This produces: ```json theme={null} { "properties": { "name": { "type": "string", "description": "User name" }, "limit": { "type": "integer", "description": "Max results", "default": 10 }, "company": { "type": "string", "description": "Company filter", "default": null } }, "required": ["name"] } ``` > [!TIP] > > `Optional[str]` and `str | None` are identical at runtime and produce the same schema. ### Enum parameters with Literal Use `Literal` to restrict a parameter to a fixed set of values. MCP clients like the Inspector render these as dropdown selects: ```python theme={null} from typing import Literal @server.tool() def create_event( title: Annotated[str, Field(description="Event title")], visibility: Annotated[ Literal["public", "private", "team"], Field(description="Who can see this event"), ], recurrence: Annotated[ Literal["none", "daily", "weekly", "monthly"], Field(description="Recurrence pattern"), ] = "none", ) -> dict: ... ``` Produces `{"type": "string", "enum": ["public", "private", "team"]}` in the schema. > [!NOTE] > > mcp-use automatically simplifies Pydantic's nullable `anyOf` schemas. Without this, > `str | None` would produce `{"anyOf": [{"type": "string"}, {"type": "null"}]}` which > breaks description rendering in the MCP Inspector and fails validation in some clients > like Google's Gemini API. mcp-use collapses this into `{"type": "string", "default": null}`. ## Complex Input Types Use Pydantic models for complex inputs: ```python theme={null} from pydantic import BaseModel class SearchQuery(BaseModel): query: str = Field(description="The search query string") max_results: int = Field(default=10, description="Maximum number of results to return") include_metadata: bool = Field(default=False, description="Whether to include metadata") @server.tool() def search(params: SearchQuery) -> list[str]: """Search with complex parameters.""" return ["result1", "result2"] ``` ## Return Types Tools can return various types: ```python theme={null} # String @server.tool() def text_tool() -> str: return "Hello" # Dict (serialized to JSON) @server.tool() def json_tool() -> dict: return {"key": "value", "count": 42} # List @server.tool() def list_tool() -> list[str]: return ["a", "b", "c"] ``` ## Error Handling Raise exceptions to indicate errors. The error message will be returned to the client: ```python theme={null} @server.tool() def divide( a: Annotated[float, Field(description="Dividend")], b: Annotated[float, Field(description="Divisor")], ) -> float: """Divide two numbers.""" if b == 0: raise ValueError("Cannot divide by zero") return a / b ``` # MCP Server Tunneling Source: https://docs.mcp-use.com/tunneling/index Expose a local MCP server through a public /mcp URL for testing in ChatGPT, Claude, and other remote MCP clients. Use a tunnel when ChatGPT, Claude, or another remote MCP client needs to reach a server running on your machine. The tunnel gives you a public HTTPS URL that forwards to your local MCP endpoint. With `mcp-use`, start the server with `--tunnel`, then copy the printed `Tunnel` URL. The URL you give to clients must include `/mcp`. ```text theme={null} https://-.tunnel.mcp-use.run/mcp ``` Keep the terminal process running while you test. The public URL stops working when the process exits. With `mcp-use dev --tunnel` or `mcp-use start --tunnel`, the framework connects directly to the relay over WebSocket. It does not install or execute a native tunnel binary or a separate tunnel package. If the relay connection drops while the command is still running, the tunnel reconnects automatically and reuses the same identifier when possible. The relay forwards both HTTP requests and WebSocket upgrades. In development, MCP App views loaded from the public tunnel keep Vite HMR: editing a local view updates the remote Inspector or client without restarting the tunnel. ## Start a tunnel with mcp-use Use `mcp-use dev --tunnel` while you are developing: ```bash theme={null} mcp-use dev --tunnel ``` Use `mcp-use start --tunnel` when you want to test the built server: ```bash theme={null} mcp-use build mcp-use start --port 3000 --tunnel ``` After the production server binds, successful output includes the local and public MCP endpoints: ```text theme={null} [mcp-use] starting tunnel for port 3000… mcp-use server running at http://localhost:3000/mcp mcp-use public MCP URL: https://proper-black.tunnel.mcp-use.run/mcp ``` Copy the value after `mcp-use public MCP URL:` into your remote MCP client. Do not copy only the tunnel origin; the client URL must end with `/mcp`. ## Verify the tunnel Verify the public URL with the `mcp-use client` CLI: ```bash theme={null} npx mcp-use client connect tunnel-test https://proper-black.tunnel.mcp-use.run/mcp npx mcp-use client tunnel-test tools list ``` The `connect` command performs the MCP handshake and saves the tunnel under the name `tunnel-test`. The `tools list` command should print the tools exposed by your local server. If the server uses OAuth or bearer authentication, complete the client authentication flow or pass the required auth option before testing tools. ## Stop the tunnel Press `Ctrl+C` in the terminal running the tunnel. When you started the tunnel with `mcp-use dev --tunnel` or `mcp-use start --tunnel`, stopping the command stops both the local server process and the tunnel. ## Lifetime and limits Tunnels are for local testing before deployment: * The tunnel is active only while the command is running. * With `mcp-use dev --tunnel` or `mcp-use start --tunnel`, a dropped tunnel registration is re-established automatically while the command runs. * Reservations that never connect expire after 5 minutes. * Connected tunnels expire after 24 hours. * Inactive tunnels are cleaned up after 1 hour without activity. * Each source IP can create up to 10 tunnels per hour. * Each source IP can have up to 5 active tunnels at a time. For a stable public URL, deploy the server instead of relying on a local tunnel. ## Next steps * Use the [TypeScript quickstart](/typescript/getting-started/quickstart) to create a local MCP server. * Use [Build your first MCP App](/typescript/mcp-apps/quickstart) to test widgets in a remote client. * Use [Deploy to Manufact Cloud](/typescript/server/deployment/mcp-use) when you are ready for a hosted MCP endpoint. # Introduction Source: https://docs.mcp-use.com/v2/typescript/agent/index Build a TypeScript MCP agent that calls tools from MCP servers. `MCPAgent` from `@mcp-use/agent` connects a model to MCP tools, runs a bounded tool-calling loop, and returns the model's final answer. ## Install the agent ```bash npm theme={null} npm install @mcp-use/agent @mcp-use/client ``` ```bash pnpm theme={null} pnpm add @mcp-use/agent @mcp-use/client ``` ```bash bun theme={null} bun add @mcp-use/agent @mcp-use/client ``` `@mcp-use/agent` requires Node.js 22.22.2 or later. ## Run your first agent Set `OPENAI_API_KEY`, then run this example from a directory the filesystem server may read. ```typescript theme={null} import { MCPAgent } from "@mcp-use/agent"; async function main() { const agent = new MCPAgent({ llm: "openai/gpt-4o", mcpServers: { filesystem: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "./"], }, }, }); try { await agent.initialize(); const result = await agent.run({ prompt: "List the files in this directory, then summarize what the project does.", }); console.log(result); } finally { await agent.close(); } } main().catch(console.error); ``` A successful run prints a text answer based on the files the MCP server returned. > [!NOTE] > > Initialization is manual by default. Call `await agent.initialize()` before > `run()`, `stream()`, or `streamEvents()`. Set `autoInitialize: true` only when > you want the first call to initialize the agent for you. ## Understand the runtime defaults `maxSteps` defaults to `10`. Override it for the agent or for one call: ```typescript theme={null} const agent = new MCPAgent({ llm: "openai/gpt-4o", mcpServers, maxSteps: 15, }); await agent.initialize(); const result = await agent.run({ prompt: "Complete the audit.", maxSteps: 20 }); await agent.close(); ``` Conversation memory is enabled by default. Memory stores the user prompt and final assistant text from successful `run()` and `stream()` calls. It does not store tool transcripts or `streamEvents()` output. When you pass `mcpServers`, the agent creates and owns its `MCPClient`; `close()` closes those sessions. If you pass an existing client or connectors, their lifecycle remains under your control. ## Choose the next guide > **[LLM providers](/v2/typescript/agent/llm-providers)** > > Configure OpenAI, Anthropic, Google, OpenRouter, Ollama, or an OpenAI-compatible endpoint. > **[Memory management](/v2/typescript/agent/memory-management)** > > Inspect, disable, and clear conversation history. > **[Streaming](/v2/typescript/agent/streaming)** > > Stream tool steps or provider-neutral events. > **[LangChain integration](/v2/typescript/agent/langchain/index)** > > Add LangChain models, structured output, Server Manager, and callbacks. # Overview Source: https://docs.mcp-use.com/v2/typescript/agent/langchain/index Set up LangChainMCPAgent with a LangChain chat model and MCP tools. `LangChainMCPAgent` connects LangChain chat models and callbacks to MCP tools. Import it from `@mcp-use/agent/langchain`. ## When to use LangChainMCPAgent Use `LangChainMCPAgent` when you need at least one of these capabilities: * an existing LangChain chat model or custom LangChain tool; * Zod structured-output conversion after an agent run; * LangChain `StreamEvent` output or `prettyStreamEvents()`; * Server Manager for on-demand access to one MCP server's tools; or * LangChain callbacks, Langfuse tracing, metadata, and tags. ## Install LangChainMCPAgent Install the agent package, LangChain core packages, and the provider package for your model. ```bash npm theme={null} npm install @mcp-use/agent @mcp-use/client langchain @langchain/core @langchain/openai ``` ```bash pnpm theme={null} pnpm add @mcp-use/agent @mcp-use/client langchain @langchain/core @langchain/openai ``` ```bash bun theme={null} bun add @mcp-use/agent @mcp-use/client langchain @langchain/core @langchain/openai ``` Add `zod` for structured output. Add `langfuse` and `langfuse-langchain` for built-in Langfuse tracing. ## Run a LangChain agent Set `OPENAI_API_KEY`, then run: ```typescript theme={null} import { ChatOpenAI } from "@langchain/openai"; import { MCPClient } from "@mcp-use/client"; import { LangChainMCPAgent } from "@mcp-use/agent/langchain"; async function main() { const client = new MCPClient({ mcpServers: { filesystem: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "./"], }, }, }); const agent = new LangChainMCPAgent({ llm: new ChatOpenAI({ model: "gpt-4o", temperature: 0 }), client, }); try { await agent.initialize(); const result = await agent.run({ prompt: "Read package.json and summarize the project scripts.", }); console.log(result); } finally { await agent.close(); } } main().catch(console.error); ``` A successful run prints a text answer based on `package.json`. `LangChainMCPAgent` defaults to `5` model-call steps. > [!WARNING] > > `LangChainMCPAgent.close()` closes its MCP client even when you supplied that > client. Do not share the client with work that must continue after the agent > closes. ## Next steps > **[Structured output](/v2/typescript/agent/langchain/structured-output)** > > Convert final text into validated Zod data. > **[Server Manager](/v2/typescript/agent/langchain/server-manager)** > > Load one server's tools on demand. > **[Observability](/v2/typescript/agent/langchain/observability)** > > Trace runs with Langfuse or custom callbacks. # Observability Source: https://docs.mcp-use.com/v2/typescript/agent/langchain/observability Trace LangChainMCPAgent runs with Langfuse or custom LangChain callbacks. `LangChainMCPAgent` passes callbacks, metadata, and tags into LangChain agent execution. Use the built-in Langfuse integration or provide your own LangChain callbacks. ## Trace a run with Langfuse Install both Langfuse packages: ```bash theme={null} npm install langfuse langfuse-langchain ``` Set credentials before the process imports `@mcp-use/agent/langchain`: ```bash theme={null} export LANGFUSE_PUBLIC_KEY="pk-lf-..." export LANGFUSE_SECRET_KEY="sk-lf-..." export LANGFUSE_HOST="https://cloud.langfuse.com" ``` Then initialize and run the agent: ```typescript theme={null} import { ChatOpenAI } from "@langchain/openai"; import { MCPClient } from "@mcp-use/client"; import { LangChainMCPAgent } from "@mcp-use/agent/langchain"; async function main() { const client = new MCPClient({ mcpServers: { filesystem: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "./"], }, }, }); const agent = new LangChainMCPAgent({ llm: new ChatOpenAI({ model: "gpt-4o", temperature: 0 }), client, }); agent.setMetadata({ trace_name: "project-audit", session_id: "session-123", user_id: "user-456", environment: "production", }); agent.setTags(["docs", "project-audit"]); try { await agent.initialize(); const result = await agent.run({ prompt: "Inspect package.json and summarize the project scripts.", }); console.log(result); } finally { await agent.flush(); await agent.close(); } } main().catch(console.error); ``` Initialization auto-detects Langfuse only when both keys are present and `langfuse-langchain` can be imported. If no handler is available, the agent still runs without traces. ## Add metadata and tags `setMetadata()` merges new values into existing metadata. `setTags()` appends tags and removes duplicates. Both apply to later `stream()` and `streamEvents()` executions. Two metadata keys also control LangChain and Langfuse behavior: * `trace_name` sets the LangChain run name. The default is `mcp-use-agent`. * `session_id` is forwarded as the Langfuse session ID. The built-in Langfuse handler also recognizes `user_id`, adds MCP server metadata during initialization, and adds environment and agent tags when configured. Metadata keys replace characters outside letters, numbers, underscores, and hyphens with `_`. Arrays keep only primitive values. Serializable objects longer than 1,000 characters are stored as truncated strings. Unsupported or circular values are skipped. Tags allow letters, numbers, underscores, colons, and hyphens. Invalid characters become `_`, and tags longer than 50 characters are removed. ## Use custom callbacks Constructor callbacks replace auto-detected callbacks; they are not merged with the built-in Langfuse handler. ```typescript theme={null} import { ChatOpenAI } from "@langchain/openai"; import { CallbackHandler } from "langfuse-langchain"; import { MCPClient } from "@mcp-use/client"; import { LangChainMCPAgent } from "@mcp-use/agent/langchain"; const callback = new CallbackHandler({ publicKey: process.env.LANGFUSE_PUBLIC_KEY, secretKey: process.env.LANGFUSE_SECRET_KEY, baseUrl: process.env.LANGFUSE_HOST, }); const agent = new LangChainMCPAgent({ llm: new ChatOpenAI({ model: "gpt-4o" }), client: new MCPClient({ mcpServers }), callbacks: [callback], }); try { await agent.initialize(); console.log(await agent.run({ prompt: "Complete the traced task." })); } finally { await agent.flush(); await agent.close(); } ``` Custom callback objects receive normal LangChain lifecycle events. If a callback implements `flushAsync()`, `agent.flush()` calls it. During `agent.close()`, the observability manager flushes again, then calls `shutdownAsync()` or `shutdown()` when implemented. ## Flush and clean up Call `await agent.flush()` before a serverless function or short-lived process exits. It waits for each configured callback's `flushAsync()` method when present. Always call `await agent.close()` for full cleanup. Closing: 1. flushes and shuts down observability callbacks; 2. clears the LangChain executor and tool list; 3. closes the MCP client or direct connectors; and 4. marks the agent uninitialized. ## Disable callback discovery Set `observe: false` to disable all observability callbacks, including custom callbacks: ```typescript theme={null} const agent = new LangChainMCPAgent({ llm, client, observe: false, }); await agent.initialize(); console.log((await agent.observabilityManager.getStatus()).enabled); // false await agent.close(); ``` Set `MCP_USE_LANGFUSE=false` when you want callbacks in general but do not want built-in Langfuse auto-detection. ## Next steps * [Use structured output](/v2/typescript/agent/langchain/structured-output) * [Route tools with Server Manager](/v2/typescript/agent/langchain/server-manager) # Server Manager Source: https://docs.mcp-use.com/v2/typescript/agent/langchain/server-manager Let LangChainMCPAgent load one MCP server's tools on demand. Server Manager gives `LangChainMCPAgent` management tools first, then exposes the active MCP server's tools after the model selects a server. Use it when loading every tool from every configured server would create an oversized or confusing tool list. ## Enable Server Manager Server Manager requires explicit mode with an `MCPClient`. It cannot run with connectors alone. ```typescript theme={null} import { ChatOpenAI } from "@langchain/openai"; import { MCPClient } from "@mcp-use/client"; import { LangChainMCPAgent } from "@mcp-use/agent/langchain"; async function main() { const client = new MCPClient({ mcpServers: { filesystem: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"], }, browser: { command: "npx", args: ["@playwright/mcp@latest"], }, }, }); const agent = new LangChainMCPAgent({ llm: new ChatOpenAI({ model: "gpt-4o", temperature: 0 }), client, useServerManager: true, maxSteps: 12, }); try { await agent.initialize(); const result = await agent.run({ prompt: "List the available MCP servers, select the filesystem server, and summarize /tmp.", }); console.log(result); } finally { await agent.close(); } } main().catch(console.error); ``` A successful run lists the configured servers, activates `filesystem`, and uses its tools. The agent rebuilds its LangChain executor when the active tool set changes. ## Understand the management tools | Tool | Behavior | | - | - | | `list_mcp_servers` | Lists configured server names and cached item counts. Counts can be zero before tools are loaded or prefetched. | | `connect_to_mcp_server` | Reuses or creates a session, activates the server, and loads its tools, resources, and prompts when not cached. | | `get_active_mcp_server` | Reports the selected active server without changing it. | | `disconnect_from_mcp_server` | Releases the active selection so its cached tools are no longer exposed. | | `add_mcp_server_from_config` | Adds a server, creates its session, loads its tools, and makes it active. | Only one server is active at a time. The five management tools remain available alongside the active server's cached tools. > [!NOTE] > > `add_mcp_server_from_config` loads tools only. > `connect_to_mcp_server` loads tools, resources, and prompts when it first > caches a configured server. ## Release a server without closing its session Despite its tool name, `disconnect_from_mcp_server` does not close the underlying MCP session. It sets the active server to `null`; the session and cached tools remain available for later selection. Use `await agent.close()` to finish the agent lifecycle. `LangChainMCPAgent` shuts down observability, clears its executor and tools, and closes the `MCPClient` sessions. ## Customize the manager Import `ServerManager` and `LangChainAdapter` from the LangChain subpath. Use `serverManagerFactory` when you need to prefetch tools or provide a custom manager instance. ```typescript theme={null} import { LangChainAdapter, LangChainMCPAgent, ServerManager, } from "@mcp-use/agent/langchain"; const agent = new LangChainMCPAgent({ llm, client, useServerManager: true, serverManagerFactory: (managerClient) => { const adapter = new LangChainAdapter(); return new ServerManager(managerClient, adapter); }, }); await agent.initialize(); await agent.close(); ``` `prefetchServerTools()` caches tools, resources, and prompts for configured servers. It can create sessions and leaves those sessions open until client cleanup. ## Know when to skip it For one or two small servers, load tools normally. Server Manager adds a model decision before the first server tool call and can restart execution when the exposed tool set changes. ## Next steps * [Set up LangChainMCPAgent](/v2/typescript/agent/langchain/index) * [Trace Server Manager runs](/v2/typescript/agent/langchain/observability) # Structured output Source: https://docs.mcp-use.com/v2/typescript/agent/langchain/structured-output Convert LangChainMCPAgent results into validated Zod data. Pass a Zod `schema` to `LangChainMCPAgent` when you need validated data. The agent completes the task first, then asks the model to convert the final text and validates the result with Zod. ## Return a typed result Install `zod`, set `OPENAI_API_KEY`, and run: ```typescript theme={null} import { ChatOpenAI } from "@langchain/openai"; import { MCPClient } from "@mcp-use/client"; import { LangChainMCPAgent } from "@mcp-use/agent/langchain"; import { z } from "zod"; const ProjectSummary = z.object({ packageName: z.string().nullable(), scripts: z.array(z.string()), hasTests: z.boolean(), notes: z.string(), }); async function main() { const client = new MCPClient({ mcpServers: { filesystem: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "./"], }, }, }); const agent = new LangChainMCPAgent({ llm: new ChatOpenAI({ model: "gpt-4o", temperature: 0 }), client, maxSteps: 8, }); try { await agent.initialize(); const summary = await agent.run({ prompt: "Inspect package.json and summarize the project.", schema: ProjectSummary, }); console.log(summary.scripts); } finally { await agent.close(); } } main().catch(console.error); ``` A successful call returns `z.infer`. It does not return the raw final text. ## Choose a structured-output method | Method | During agent execution | Structured result | Conversion failure | | - | - | - | - | | `run()` | Does not yield progress | Resolves to the validated value | Rejects with `Failed to generate structured output: ...` | | `stream()` | Yields tool-call `AgentStep` values | Returns the validated value from the generator | Throws from the generator | | `streamEvents()` | Yields LangChain v2 events | Emits `on_structured_output` after the LangChain stream | Emits `on_structured_output_error`; it does not return the value | `run()` consumes `stream()` internally, so both methods use the same conversion path. ## Read the return value from `stream()` A `for await` loop cannot read an async generator's return value. Call `next()` until `done` when you need the validated result: ```typescript theme={null} const stream = agent.stream({ prompt: "Inspect package.json and summarize the project.", schema: ProjectSummary, }); while (true) { const next = await stream.next(); if (next.done) { console.log(next.value.scripts); break; } console.log(`Called ${next.value.action.tool}`); } ``` Tool steps are yielded before conversion. Conversion begins only after the agent produces non-empty final text. ## Handle structured events `streamEvents()` adds the schema description to the task so the agent gathers the required fields. It yields the underlying LangChain v2 events first, then custom conversion events: ```typescript theme={null} for await (const event of agent.streamEvents({ prompt: "Inspect package.json and summarize the project.", schema: ProjectSummary, })) { if (event.event === "on_structured_output_progress") { console.log(event.data?.message); } if (event.event === "on_structured_output") { const summary = ProjectSummary.parse(event.data?.output); console.log(summary.scripts); } if (event.event === "on_structured_output_error") { throw new Error(String(event.data?.error)); } } ``` Progress events are emitted every two seconds while conversion is still running. `streamEvents()` returns `void`; store the `on_structured_output` payload yourself. ## Handle validation boundaries `LangChainMCPAgent` uses `withStructuredOutput(schema)` when the model implements it. Otherwise, it prompts the same model to format JSON. It validates the result and retries conversion up to three times, including the previous validation error in later attempts. After three failures, the conversion error includes: ```text theme={null} Failed to generate valid structured output after 3 attempts. Last error: ... ``` `run()` and `stream()` wrap that message in `Failed to generate structured output: ...`. `streamEvents()` emits the message in `on_structured_output_error`. Required fields fail validation when they are `null`, `undefined`, an empty string, or an empty array, even if a broad Zod schema would otherwise accept the empty value. Mark genuinely missing values as optional or nullable. > [!WARNING] > > Conversion runs only when the agent produces non-empty final text. If no final > text exists, `run()` and `stream()` currently return `"No output generated"` > even when `schema` is set. Treat that string as an unsuccessful structured > result. ## Next steps * [Trace LangChain runs](/v2/typescript/agent/langchain/observability) # LLM providers Source: https://docs.mcp-use.com/v2/typescript/agent/llm-providers Configure MCPAgent for OpenAI, Anthropic, Google, OpenRouter, Ollama, or an OpenAI-compatible endpoint. `MCPAgent` supports OpenAI, Anthropic, Google, OpenRouter, Ollama, and OpenAI-compatible endpoints. Configure a provider with a `"provider/model"` string or a `ProviderConfig`. ## Choose a provider | Provider prefix | API key lookup | Configuration note | | - | - | - | | `openai` | `OPENAI_API_KEY` | Uses the built-in OpenAI provider. | | `anthropic` | `ANTHROPIC_API_KEY` | Uses the built-in Anthropic provider. | | `google` | `GOOGLE_API_KEY` or `GOOGLE_GENERATIVE_AI_API_KEY` | Uses the built-in Google provider. | | `openrouter` | `OPENROUTER_API_KEY` | Model names may contain `/`, such as `openai/gpt-4o`. | | `ollama` | No key required | Defaults to `http://localhost:11434`. | | `openai-compatible` | `OPENAI_API_KEY` or `llmConfig.apiKey` | Requires the endpoint in `llmConfig.baseUrl`. | ## Configure a provider string Set the provider's environment variable before starting the process. The agent resolves the key when it initializes. ```typescript theme={null} import { MCPAgent } from "@mcp-use/agent"; async function main() { const agent = new MCPAgent({ llm: "anthropic/claude-sonnet-4-6", llmConfig: { temperature: 0.2, maxTokens: 1_000, }, mcpServers: { filesystem: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "./"], }, }, }); try { await agent.initialize(); const result = await agent.run({ prompt: "Read package.json and list the available scripts.", }); console.log(result); } finally { await agent.close(); } } main().catch(console.error); ``` A successful run prints scripts found through the filesystem MCP server. The string parser accepts model names that contain `/`. For example, `openrouter/openai/gpt-4o` selects the `openrouter` provider and passes `openai/gpt-4o` as the model name. ## Connect an OpenAI-compatible endpoint Use `openai-compatible` for an endpoint that implements OpenAI chat-completions semantics. Supply the full API base URL and any required headers. ```typescript theme={null} import { MCPAgent, type ProviderConfig } from "@mcp-use/agent"; const provider: ProviderConfig = { provider: "openai-compatible", model: "my-tool-calling-model", apiKey: process.env.COMPATIBLE_API_KEY ?? "local", baseUrl: "http://localhost:8000/v1", extraHeaders: { "X-Workspace": "docs-example", }, }; const agent = new MCPAgent({ llm: provider, mcpServers }); try { await agent.initialize(); const result = await agent.run({ prompt: "Call one available tool and report its result.", }); console.log(result); } finally { await agent.close(); } ``` Verify that the selected model supports tool calling. A reachable text-only model cannot use MCP tools. ## Handle configuration errors Initialization throws when: * a provider string is not in `provider/model` form; * the provider prefix is unsupported; * a required API key is missing; or * no model driver can be created. Keep provider-specific tuning in `llmConfig` or `ProviderConfig`. See the [MCPAgent API reference](https://mcp-use-typescript-api-reference.vercel.app/modules/_mcp-use_agent.index.html#mcpagent) for the complete option types. ## Next steps * [Build an MCP agent](/v2/typescript/agent/index) * [Stream agent output](/v2/typescript/agent/streaming) # Memory management Source: https://docs.mcp-use.com/v2/typescript/agent/memory-management Inspect, disable, persist, and clear MCPAgent conversation history. `MCPAgent` keeps conversation history in memory by default. Successful `run()` and `stream()` calls store the user prompt and final assistant text as `ProviderMessage[]`. ## Keep conversation context This example completes two turns, inspects the stored messages, and then clears them. ```typescript theme={null} import { MCPAgent, type ProviderMessage } from "@mcp-use/agent"; async function main() { const agent = new MCPAgent({ llm: "openai/gpt-4o", mcpServers: { filesystem: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "./"], }, }, }); try { await agent.initialize(); await agent.run({ prompt: "My project codename is Cedar." }); const answer = await agent.run({ prompt: "What is the project codename?" }); console.log(answer); const history: ProviderMessage[] = agent.getConversationHistory(); console.log(history.map(({ role, content }) => ({ role, content }))); agent.clearConversationHistory(); console.log(agent.getConversationHistory().length); // 0 } finally { await agent.close(); } } main().catch(console.error); ``` After two successful calls, history normally contains four messages: one user and one assistant message for each turn. ## Know what is stored Conversation history uses the provider-neutral `ProviderMessage` shape. Each message has a `role` and `content`; provider messages can also represent tool calls and results. The agent's automatic memory is narrower: * `run()` and `stream()` append the prompt and final assistant text after a successful call. * Tool calls and tool results are not appended to automatic memory. * `streamEvents()` does not append any conversation history. * Per-call `messages` and `externalHistory` affect that call but are not copied into stored history. * A failed or aborted call does not append the prompt as a completed turn. `getConversationHistory()` returns a new array. Changing that array does not replace agent memory, although message objects inside it are not deep-cloned. ## Disable memory Set `memoryEnabled: false` when every call must start with only the system prompt, per-call messages, and current prompt. ```typescript theme={null} const agent = new MCPAgent({ llm: "openai/gpt-4o", mcpServers, memoryEnabled: false, }); await agent.initialize(); await agent.run({ prompt: "Remember the number 42." }); const result = await agent.run({ prompt: "What number did I give you?" }); console.log(result); await agent.close(); ``` With memory disabled, the second call does not receive the first turn from agent memory. ## Persist history outside the agent History lives only on the `MCPAgent` instance. It is not written to disk or restored after a process restart. Store `getConversationHistory()` in your application if you need durable conversations. Pass restored `ProviderMessage` values through `messages` for a later call: ```typescript theme={null} const savedHistory: ProviderMessage[] = agent.getConversationHistory(); const result = await anotherAgent.run({ messages: savedHistory, prompt: "Continue from the saved conversation.", }); ``` Passing `messages` provides context for that call. It does not seed `anotherAgent`'s internal history. ## Clear a conversation `clearConversationHistory()` removes all stored conversation messages immediately. The system prompt is held separately, so clearing history does not change it. Closing an agent does not clear its in-memory history. If you initialize the same instance again, its stored conversation remains until you clear it or discard the instance. ## Next steps * [Stream agent output](/v2/typescript/agent/streaming) * [Configure an LLM provider](/v2/typescript/agent/llm-providers) # Streaming Source: https://docs.mcp-use.com/v2/typescript/agent/streaming Stream MCPAgent tool steps and provider-neutral LLM events. `MCPAgent` provides two streaming APIs. Use `stream()` for tool-step progress and a final string. Use `streamEvents()` for provider-neutral token, tool, usage, error, and completion events. | Method | Use it for | Output | | - | - | - | | `stream()` | Tool progress and a final answer | Yields `AgentStep`; returns the final string | | `streamEvents()` | Token UIs and detailed tool lifecycle state | Yields `LlmStreamEvent`; returns `void` | ## Stream tool steps Read the generator directly when you need both yielded steps and its final return value. ```typescript theme={null} import { MCPAgent } from "@mcp-use/agent"; async function main() { const agent = new MCPAgent({ llm: "openai/gpt-4o", mcpServers: { filesystem: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "./"], }, }, }); try { await agent.initialize(); const stream = agent.stream({ prompt: "Inspect package.json and summarize the project scripts.", }); while (true) { const next = await stream.next(); if (next.done) { console.log("Final answer:", next.value); break; } console.log(`Tool: ${next.value.action.tool}`); console.log(`Input: ${JSON.stringify(next.value.action.toolInput)}`); if (next.value.observation) { console.log(`Result: ${next.value.observation}`); } } } finally { await agent.close(); } } main().catch(console.error); ``` For each tool call, `stream()` can yield an initial step with an empty `observation`, followed by another step containing the tool result. A `for await` loop receives the steps but does not expose the generator's final return value. ## Stream provider-neutral events `streamEvents()` uses the same `LlmStreamEvent` variants for every supported provider. ```typescript theme={null} import { MCPAgent, type LlmStreamEvent } from "@mcp-use/agent"; async function main() { const agent = new MCPAgent({ llm: "openai/gpt-4o", mcpServers: { filesystem: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "./"], }, }, }); let answer = ""; try { await agent.initialize(); for await (const event of agent.streamEvents({ prompt: "List the TypeScript files and summarize their purpose.", })) { handleEvent(event); if (event.type === "text-delta") { answer += event.delta; } } console.log("\nFinal answer:", answer); } finally { await agent.close(); } } function handleEvent(event: LlmStreamEvent) { switch (event.type) { case "tool-call-ready": console.log(`\nCalling ${event.toolName}`, event.args); break; case "tool-result": console.log(`\n${event.toolName} finished; error=${event.isError}`); break; case "error": console.error(`\nModel error: ${event.message}`); break; } } main().catch(console.error); ``` Accumulate `text-delta` values when your UI needs the complete final answer. `streamEvents()` itself returns no result and does not write the streamed turn to conversation memory. ## Handle every event variant | `type` | Meaning | | - | - | | `text-delta` | A text fragment from the model | | `tool-call-start` | The model started producing a tool call | | `tool-call-args-delta` | A partial JSON argument fragment; concatenate fragments before parsing | | `tool-call-ready` | A complete tool name and parsed argument object | | `tool-result` | The tool result, with `isError` indicating tool failure | | `usage` | Provider token usage, when available | | `error` | A model-loop error message | | `done` | The tool loop finished | Tool execution failures are emitted as `tool-result` with `isError: true`. Other streaming failures can appear as `error`. Decide whether your UI should show a partial answer, retry, or fail the request. ## Cancel a stream Pass an `AbortSignal` through the run options: ```typescript theme={null} const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 5_000); try { for await (const event of agent.streamEvents({ prompt: "Perform a long audit.", signal: controller.signal, })) { console.log(event.type); } } finally { clearTimeout(timeout); } ``` ## Next steps * [Manage conversation memory](/v2/typescript/agent/memory-management) * [Configure an LLM provider](/v2/typescript/agent/llm-providers) # CLI Reference Source: https://docs.mcp-use.com/v2/typescript/api-reference/cli-reference Command reference for the @mcp-use/cli package and mcp-use executable. The `mcp-use` package installs the `mcp-use` executable and includes the prebuilt `@mcp-use/cli` implementation. Use this page as the exhaustive command reference for local development, production builds, cloud deploys, saved MCP client sessions, and CLI environment variables. For hands-on workflows, see the [CLI Client guide](/v2/typescript/tooling/client-cli), [Tunneling guide](/tunneling/index), and [Manufact Cloud deployment guide](/v2/typescript/server/deployment/mcp-use). ## Command map > **[Run locally](#dev)** > > `mcp-use dev` starts the development server, view watcher, and Inspector. > **[Build and start](#build)** > > `mcp-use build` writes production artifacts. `mcp-use start` runs the built > server. > **[Deploy](#deploy)** > > `mcp-use deploy`, `mcp-use deployments`, and `mcp-use servers` manage > Manufact Cloud resources. > **[Client CLI](#client)** > > `mcp-use client` saves MCP servers, calls tools, reads resources, gets > prompts, and handles OAuth. > **[Tunnels](#tunneling-reference)** > > `mcp-use dev --tunnel` exposes a local server through a public URL. > **[Typecheck](#typecheck)** > > `mcp-use typecheck` refreshes MCP view types and runs the project's own > TypeScript compiler. ## Install the CLI Most projects install the framework, CLI, and Inspector together: ```bash theme={null} npm install mcp-use ``` The CLI package can also be installed directly: ```bash theme={null} npm install -g @mcp-use/cli ``` ```bash theme={null} npx @mcp-use/cli dev ``` ```bash theme={null} npm install --save-dev @mcp-use/cli ``` > [!TIP] > > `create-mcp-use-app` installs `mcp-use`, which supplies the CLI and Inspector > at matching versions. ## `dev` **Purpose:** Start a development server with TypeScript watching, view builds, automatic reloads, and the Inspector. **Syntax:** ```bash theme={null} mcp-use dev [options] ``` **Options:** | Option | Description | Default | | - | - | - | | `--path ` | Project root used for entry/view discovery, `.env`, and `tsconfig.json`. | Current directory | | `--entry ` | MCP server entry file, relative to the project. | Auto-detected | | `--mcp-dir ` | MCP source directory containing the entry and `views/`. | None | | `--views-dir ` | View directory, relative to the project root. | `views/` or `/views/` | | `--port ` | Server port. | `PORT` or `3000` | | `--host ` | Bind address. Use `0.0.0.0` to listen on all interfaces. | `HOST` or `127.0.0.1` | | `--no-open` | Do not open the Inspector automatically. | Opens by default | | `--no-inspector` | Run without loading the project-local Inspector. | Inspector enabled | | `--tunnel` | Create a public tunnel for the local server. | Disabled | **Examples:** ```bash theme={null} mcp-use dev mcp-use dev --port 8080 mcp-use dev --host 127.0.0.1 --no-open mcp-use dev --mcp-dir src/mcp mcp-use dev --entry src/server.ts --views-dir src/views mcp-use dev --path apps/web --entry ../mcp/src/server.ts --views-dir ../mcp/src/views mcp-use dev --tunnel ``` **Notes and behavior:** * The MCP endpoint is served at `/mcp`. * Address precedence is `--port` / `--host`, then `PORT` / `HOST`, then the defaults. `dev` does not import the server until after its listener is chosen, so it cannot use a server-configured address. * The Inspector supplied by `mcp-use` is mounted at `/mcp/inspector` and opens automatically unless `--no-open` is set. * Inspector UI, proxy, and OAuth routes remain local-only. A public tunnel exposes the MCP endpoint but returns `404` for `/mcp/inspector`. * The command sets `NODE_ENV=development` when it is not already set and sets `PORT` to the chosen listener port before importing the entry. * When `MCP_URL` is unset and the listener binds a loopback host, the command sets `MCP_URL` to `http://localhost:` only while it imports the entry, so module-scope OAuth configuration sees the local origin. Request handlers and tool code do not see this value. With `--tunnel`, the command still sets this local value and does not replace it with the public tunnel URL. * Source changes reload the exported server without dropping the long-lived HTTP listener. View modules use Vite HMR when views exist at startup. * Adding the first view to a project that started with none requires restarting `mcp-use dev`. * `mcp-use dev` keeps its Vite cache in `.mcp-use/cache/` and the tunnel subdomain in `.mcp-use/state/tunnel.json`. * See [Tunneling reference](#tunneling-reference) for the lifecycle and limits of `--tunnel`. ## `typecheck` **Purpose:** Refresh the managed `mcp-env.d.ts` declaration for the discovered server entry, then run the project's installed TypeScript compiler with `--noEmit`. **Syntax:** ```bash theme={null} mcp-use typecheck [options] [-- ] ``` The command accepts `--path`, `--entry`, and `--mcp-dir` with the same meanings as `dev` and `build`. Arguments after `--` are forwarded to TypeScript: ```bash theme={null} mcp-use typecheck mcp-use typecheck --entry src/server.ts mcp-use typecheck -- --project tsconfig.check.json --pretty false ``` `mcp-env.d.ts` is scaffolded into new projects, so editors and plain `tsc --noEmit` work before the first CLI run. The command refreshes declarations carrying an mcp-use generated header when the entry changes and never overwrites a user-owned declaration. TypeScript must be installed in the selected project. ## `build` **Purpose:** Build the exported MCP server and its views into `.mcp-use/build/`. **Syntax:** ```bash theme={null} mcp-use build [options] ``` **Options:** | Option | Description | Default | | - | - | - | | `--path ` | Project root used for entry/view discovery, `.env`, and `tsconfig.json`. | Current directory | | `--entry ` | MCP server entry file, relative to the project. | Auto-detected | | `--mcp-dir ` | MCP source directory containing the entry and `views/`. | None | | `--views-dir ` | View directory, relative to the project root. | `views/` or `/views/` | | `--source-maps` | Emit source maps for server and external view bundles. | Disabled | | `--inline` | Embed each view's bundled JavaScript and CSS in its MCP resource. | Disabled | **Examples:** ```bash theme={null} mcp-use build mcp-use build --inline mcp-use build --mcp-dir src/mcp mcp-use build --entry src/server.ts --views-dir src/views mcp-use build --path ./my-server ``` **Notes and behavior:** * The command bundles the default-exported server as `.mcp-use/build/index.js` and writes `.mcp-use/build/manifest.json`. * Each `views//view.tsx` builds to hashed external assets under `.mcp-use/build/views//` by default. * Pass `--inline` to embed each view's bundled JavaScript and CSS directly in the HTML returned by `resources/read`. There is no `--no-inline`; omit `--inline` to use external assets. * The build is transpile-only. Run `mcp-use typecheck` as a separate project script when type checking is required. * TypeScript path aliases come from the selected project's `tsconfig.json`. * If `MCP_ASSETS_URL` is set for an external build, view paths are rewritten to that asset origin using the server's `basePath`. Inline view bundles are not rewritten. * The selected project's `public/` directory is copied to `.mcp-use/build/views/public/`. ## `start` **Purpose:** Run the production server previously written to `.mcp-use/build/`. **Syntax:** ```bash theme={null} mcp-use start [options] ``` **Options:** | Option | Description | Default | | - | - | - | | `--path ` | Project root containing `.mcp-use/build/`. | Current directory | | `--port ` | Server port. | `PORT`, server config, or `3000` | | `--host ` | Bind address. Use `0.0.0.0` to listen on all interfaces. | `HOST`, server config, or `127.0.0.1` | | `--with-inspector` | Mount the bundled Inspector at `${basePath}/inspector`. | Disabled | | `--tunnel` | Create a public tunnel for the production server. | Disabled | **Examples:** ```bash theme={null} mcp-use start mcp-use start --port 8080 mcp-use start --host 0.0.0.0 mcp-use start --with-inspector mcp-use start --path ./my-server mcp-use start --tunnel ``` **Notes and behavior:** * Address precedence is CLI flag, environment variable, server configuration, then default: `--port` → `PORT` → `config.port` → `3000`, and `--host` → `HOST` → `config.host` → `127.0.0.1`. * `--tunnel` starts the tunnel only after the production server binds. The command prints the public MCP URL and closes the tunnel when the process shuts down. * The command requires `.mcp-use/build/manifest.json`; run `mcp-use build` first. * It imports the manifest's built `entryPoint` and requires that module to default-export an `MCPServer`. * `start` does not rediscover source entries or views. `--entry`, `--mcp-dir`, and `--views-dir` belong to `dev` and `build`. * The command sets `NODE_ENV=production` when it is not already defined and loads the selected project's production `.env` values before importing the built entry. * The build manifest never records Inspector state. `--with-inspector` is a runtime-only opt-in that mounts the Inspector on the same listener; it does not rebuild or alter `.mcp-use/build`. * The Inspector can call tools and proxy OAuth flows. Keep `--with-inspector` behind access controls when serving beyond localhost. ## Tunneling reference `mcp-use dev --tunnel` and `mcp-use start --tunnel` create a public URL that forwards to the local MCP server. ```bash theme={null} mcp-use dev --tunnel mcp-use start --tunnel ``` Tunnel limits and lifecycle: | Limit or behavior | Value | | - | - | | Tunnel lifetime | Expires 24 hours after creation | | Inactive tunnel cleanup | 1 hour of no activity | | Creation rate limit | 10 tunnel creations per IP per hour | | Active tunnel limit | 5 active tunnels per IP | | Close behavior | The tunnel closes when the CLI process exits | The standalone package is also available: ```bash theme={null} npx @mcp-use/tunnel 3000 ``` See the [Tunneling guide](/tunneling/index) for client setup and testing workflows. ## `deploy` **Purpose:** Create or update a Manufact Cloud deployment for an MCP server. **Syntax:** ```bash theme={null} mcp-use deploy [path] [options] ``` `[path]` is the project directory. It defaults to the current directory. **Options:** | Option | Description | Default | | - | - | - | | `--open` | Open the deployment in a browser after a successful deploy. | Disabled | | `--name ` | Server name. Also names the GitHub repository when the CLI creates one. | GitHub repository name; with `--no-github`, the `package.json` name or directory name | | `--new` | Create a new server instead of reusing the linked project. | Disabled | | `--env ` | Environment variable assignment. Repeatable. | None | | `--env-file ` | Load environment variables from a `.env` file. | None | | `--branch ` | Branch to deploy. Also scopes env sync to that branch preview environment. | Current git branch; `main` with `--no-github` | | `--root-dir ` | Root directory inside the repository for monorepos. | Repository root | | `--org ` | Target organization. | Active org | | `-y, --yes` | Accept confirmation prompts and authorize Git and repository changes: creating a private GitHub repository, committing and pushing uncommitted changes, and selecting the default GitHub App installation. | Disabled | | `--region ` | Deployment region: `US`, `EU`, or `APAC`. | `US` | | `--build-command ` | Build command override. | Auto-detected | | `--start-command ` | Start command override. | Auto-detected | | `--dockerfile ` | Non-default Dockerfile path, relative to `--root-dir` or repository root. | None | | `--watch-paths ` | Only auto-deploy when matching files change. Repeatable. GitHub only. | All changes | | `--wait-for-ci` | Hold GitHub auto-deploys until other check runs pass. GitHub only. | Disabled | | `--no-github` | Upload local source without connecting GitHub. | Disabled | | `--json` | Emit exactly one JSON result or error. Never prompts or opens a browser; cannot be combined with `--open`. | Human-readable text | **Examples:** ```bash theme={null} mcp-use deploy mcp-use deploy --no-github mcp-use deploy --name my-server --open mcp-use deploy --env DATABASE_URL=postgres://... --env API_KEY=secret mcp-use deploy --env-file .env.production mcp-use deploy --root-dir apps/mcp-server mcp-use deploy --root-dir apps/mcp-server --watch-paths "apps/mcp-server/**" --watch-paths "packages/shared/**" mcp-use deploy --new --name my-server-v2 mcp-use deploy --org manufact-inc --region EU --yes ``` **Notes and behavior:** * The default path deploys from GitHub. When it creates a new GitHub-backed server and the organization has no GitHub App installation, the command exits with `github_installation_required` and a link to the dashboard settings. If the project has no `origin` remote, an interactive run offers to create a private repository, initialize Git, commit, and push to `main`. If the working tree has uncommitted changes, it offers to commit and push them with `git add .`. `--yes` authorizes these Git changes without prompting. * `--no-github` packs and uploads local source to a platform-managed repository. * Redeploys of a project already linked to a platform-managed server auto-detect the upload path. `--no-github` is only required on the first deploy for that path. * The command writes `.mcp-use/cloud/link.json` to link the local project to the cloud server. * When it writes the project link, the CLI adds `.mcp-use/` to the repository's local `.git/info/exclude` if that file exists. It writes `.mcp-use/` to `.gitignore` only when it creates a new repository. * On a redeploy of a linked server, the supplied `--name`, `--branch`, `--region`, `--root-dir`, `--build-command`, `--start-command`, `--dockerfile`, `--watch-paths`, and `--wait-for-ci` values update that server's configuration before the deployment starts. * Environment variables passed through `--env` and `--env-file` are synced to the target branch preview environment when `--branch` is set. ## Authentication commands Authentication commands manage the user-level Manufact Cloud credentials in `~/.mcp-use/config.json`. ### `login` **Purpose:** Authenticate the CLI with Manufact Cloud. **Syntax:** ```bash theme={null} mcp-use login [options] ``` **Options:** | Option | Description | Default | | - | - | - | | `--api-key ` | Authenticate with an API key. | Browser/device flow | | `--device-code ` | Redeem a short-lived, pre-approved RFC 8628 device code. | None | | `--org ` | Select the active organization by ID or slug. | Account default | | `--no-open` | Do not open the verification URL during interactive login. | Opens on a TTY | | `--json` | Emit one machine-readable JSON result. | Human-readable text | **Examples:** ```bash theme={null} mcp-use login mcp-use login --device-code ABC123 mcp-use login --api-key mcp_... --org my-org ``` **Notes and behavior:** * Interactive login starts a device-code flow and opens a browser. * `--device-code` skips the browser and redeems the code through the same token endpoint. The CLI then creates, validates, and stores a persistent API key. * `--api-key` and `--device-code` cannot be combined. An explicit `--device-code` takes precedence over `MCP_USE_API_KEY`. * The CLI never writes the device code, bearer token, or API key to human-readable or JSON output. * If `--org` is omitted, the CLI stores the account-default organization when one is available. * `MCP_USE_API_KEY` can provide the API key for non-interactive login. ### `whoami` **Purpose:** Print the current authentication status and user information. **Syntax:** ```bash theme={null} mcp-use whoami ``` **Options:** | Option | Description | Default | | - | - | - | | `--json` | Emit a machine-readable identity object. | Human-readable text | **Examples:** ```bash theme={null} mcp-use whoami ``` **Notes and behavior:** The command reads `~/.mcp-use/config.json`. When that file selects no organization, it reports the account default, matching `org current` and the `servers`/`deployments` commands. This is the usual case when authenticating with `MCP_USE_API_KEY` instead of `mcp-use login`. ### `logout` **Purpose:** Remove saved Manufact Cloud credentials. **Syntax:** ```bash theme={null} mcp-use logout [options] ``` **Options:** | Option | Description | Default | | - | - | - | | `--yes` | Skip confirmation. Required for non-interactive and JSON runs. | Prompts on a TTY | | `--json` | Emit one machine-readable JSON result. | Human-readable text | **Examples:** ```bash theme={null} mcp-use logout --yes ``` **Notes and behavior:** The command removes credentials from `~/.mcp-use/config.json`. ## Organization commands Organization commands control the active Manufact Cloud organization for cloud commands. | Command | Purpose | Syntax | | - | - | - | | `org list` | List organizations available to the authenticated user. | `mcp-use org list` | | `org current` | Show the active organization. | `mcp-use org current` | | `org use ` | Select and persist a different active organization. | `mcp-use org use ` | **Notes and behavior:** * `deploy`, `deployments`, and `servers` use the active organization unless `--org` overrides it. * For CI or agent runs, pass `--org ` to `login`, `deploy`, `servers`, or `deployments` commands instead of switching global state. The value can be an organization slug, ID, or name. ## Deployment management commands **Purpose:** Inspect and manage existing Manufact Cloud deployments. **Syntax:** ```bash theme={null} mcp-use deployments [options] ``` **Subcommands:** | Subcommand | Purpose | Options | | - | - | - | | `list` | List deployments. | `--org `, `--server `, `--limit `, `--skip `, `--json` | | `get ` | Show deployment details. | `--json` | | `logs ` | View runtime logs. | `--build`, `--follow`, `--json` | | `restart ` | Trigger a new deployment on the same server. | `--follow`, `--branch `, `--json` | | `stop ` | Stop a running deployment. | `--yes`, `--json` | | `delete ` | Delete a deployment. | `--yes`, `--json` | **Examples:** ```bash theme={null} mcp-use deployments list mcp-use deployments get dep_abc123 mcp-use deployments logs dep_abc123 --build --follow mcp-use deployments restart dep_abc123 --branch main --follow mcp-use deployments stop dep_abc123 --yes mcp-use deployments delete dep_abc123 --yes ``` **Notes and behavior:** * `logs` shows runtime logs by default. Use `--build` for build logs. * `restart` redeploys the same server and uses the deployment branch unless `--branch` is set. * `stop` and `delete` prompt for confirmation on a TTY. Pass `--yes` in non-interactive or JSON runs. ## Server management commands **Purpose:** Manage cloud servers, which are long-lived Git-backed deploy targets that own deployments. **Syntax:** ```bash theme={null} mcp-use servers [options] ``` **Subcommands:** | Subcommand | Purpose | Options | | - | - | - | | `list` | List servers for an organization. | `--org `, `--limit `, `--skip ` | | `get ` | Show server details and recent deployments. | `--org ` | | `update ` | Update server configuration. | `--branch `, `--name `, `--description `, `--build-command `, `--start-command `, `--root-dir `, `--watch-paths `, `--deploy-branches `, `--wait-for-ci`, `--no-wait-for-ci`, `--org ` | | `delete ` | Delete a server and its deployments. | `--yes`, `--org ` | | `env ` | Manage server environment variables. | See [Server environment commands](#server-environment-commands). | **Examples:** ```bash theme={null} mcp-use servers list mcp-use servers get srv_abc123 mcp-use servers update srv_abc123 --branch main mcp-use servers update srv_abc123 --build-command "npm run build" mcp-use servers update srv_abc123 --watch-paths "apps/api/**" --watch-paths "packages/shared/**" --deploy-branches "release/*" mcp-use servers delete srv_abc123 --yes ``` **Notes and behavior:** * `servers update --branch` changes the production branch for future production deploys. * `--watch-paths` and `--deploy-branches` are repeatable. Pass the flag once per pattern; a second bare value is read as a positional, not as another pattern. * Pass an empty string to `--build-command`, `--start-command`, `--root-dir`, `--watch-paths`, or `--deploy-branches` to clear that setting. * `--wait-for-ci` and `--no-wait-for-ci` control whether auto-deploys wait for other check runs before deploying. * `servers delete` prompts for confirmation unless `--yes` is set. ## Server environment commands **Purpose:** List, set, and unset environment variables on a cloud server. **Syntax:** ```bash theme={null} mcp-use servers env [options] ``` **Subcommands:** | Subcommand | Purpose | Required arguments | Other options | | - | - | - | - | | `list ` | List environment variable metadata. | Server ID or slug | `--org `, `--branch ` | | `set ` | Create or update an environment variable. | Server ID or slug, value | `--org `, `--branch `, `--secret` | | `unset ` | Delete an environment variable by key. | Server ID or slug, key | `--org `, `--branch `, `--yes` | **Examples:** ```bash theme={null} mcp-use servers env list srv_abc123 mcp-use servers env list srv_abc123 --branch feature/example mcp-use servers env set srv_abc123 API_KEY=secret --secret mcp-use servers env set srv_abc123 FEATURE_FLAG=true --branch feature/example mcp-use servers env unset srv_abc123 API_KEY --yes ``` **Notes and behavior:** * `env list` returns metadata only. Values are never returned. * `env set` creates a production variable when `--branch` is omitted, or a preview variable when it is supplied. * `--secret` stores a value as write-only. It must be passed on **every** write to the variable, including updates and rotations: omitting it stores the value as non-sensitive, even if the variable was previously write-only. * `--branch ` scopes preview environment variables to a branch. Omit `--branch` for production resolution. * `env unset` prompts for confirmation unless `--yes` is set. If the key doesn't exist in the selected production or branch scope, it fails with `env_variable_not_found`. ## `client` **Purpose:** Save HTTP MCP server connections, call tools, read resources, get prompts, and manage OAuth credentials from the terminal. **Syntax:** ```bash theme={null} mcp-use client mcp-use client ``` **Top-level subcommands:** | Command | Purpose | Key options | | - | - | - | | `connect ` | Verify and save an HTTP(S) MCP server. | `-H, --header`, `--no-oauth`, `--auth-timeout `, `--protocol `, `--no-open`, `--json` | | `list` | List saved servers. | `--json` | | `remove ` | Remove a saved server and credentials. | `--json` | **Per-server scopes:** | Scope | Actions | | - | - | | `tools` | `list`, `describe `, `call [args...] [--timeout ]` | | `resources` | `list`, `read ` | | `prompts` | `list`, `get [args...]` | | `auth` | `login`, `status`, `logout [--yes]` | Every action in this table accepts `--json` except where the top-level table does not advertise it. **Examples:** ```bash theme={null} mcp-use client connect local http://localhost:3000/mcp mcp-use client list mcp-use client local tools list mcp-use client local tools call read_file path=/tmp/test.txt mcp-use client local resources read "file:///tmp/data.json" mcp-use client local prompts get greeting name=Alice mcp-use client local auth login mcp-use client local auth status ``` **Notes and behavior:** * Saved server metadata is stored in `~/.mcp-use/client/servers.json`. Credentials are stored separately under `~/.mcp-use/client/credentials/`. * In an interactive TTY, OAuth displays `This server requires OAuth. Press Enter to open your browser.` and opens the browser only after Enter. * When protected-resource metadata identifies mixed auth, `connect` succeeds anonymously, reports that public tools are available, and suggests `mcp-use client auth login`. The JSON connection result includes `authorization` metadata. * `auth login` starts OAuth for an already-saved server; otherwise the first wire-level OAuth challenge can start the flow later and the CLI retries that operation once. * `--no-open` and non-TTY human output never prompt or open a browser; they print a state-free local launcher URL while the loopback callback continues waiting. The local route redirects to the provider without exposing OAuth state in terminal output. * `--json` never opens a browser or prints an OAuth URL or state. If fresh consent is required, it exits `1` with `oauth_interaction_required` and an interactive retry command in `error.details.nextSteps`. * `connect --no-oauth` prevents automatic OAuth when the server returns `401`. * `--protocol auto` prefers the modern wire and falls back to legacy. `legacy` selects only the legacy wire. `modern` selects the stateless, sessionless modern wire with no fallback. * Repeated `-H, --header <"Key: Value">` options store static headers as credentials. * Tool and prompt arguments accept `key=value`, `key:=`, or a single JSON object argument. * `--json` may appear anywhere after `client`. Success emits exactly one JSON value to stdout. Errors emit exactly one JSON error envelope to stderr and no stdout value. * Calls, resource reads, and prompt gets emit raw MCP result envelopes. Lists emit arrays, and `tools describe` emits one tool object. * Tool `isError` results exit `1` and retain the original protocol result in `error.details` under `--json`; they and auth-like error text are not interpreted as OAuth challenges. > **[CLI Client guide](/v2/typescript/tooling/client-cli)** > > Use the guide for connection workflows, OAuth behavior, argument parsing > examples, and scripting patterns. ## `screenshot` **Purpose:** Call a view-backed MCP tool and capture its rendered MCP App as a PNG. **Syntax:** ```bash theme={null} mcp-use screenshot (--server | --mcp ) --tool [args...] [options] ``` Pass tool arguments after the options, either as one JSON object or as `key=value` / `key:=` pairs. **Source options:** | Option | Description | | - | - | | `--server ` | Use a server saved by `mcp-use client`. | | `--mcp ` | Connect directly to an HTTP(S) MCP endpoint. | | `-H, --header <"Key: Value">` | Header for `--mcp`. Repeatable, and incompatible with `--server`. | **Capture options:** | Option | Description | Default | | - | - | - | | `--tool ` | View-backed tool to call. Required. | None | | `--output ` | Output PNG path. | Timestamped view name | | `--width ` | Host and widget width, an integer from `1` to `10000000`. | `768` | | `--height ` | Host viewport height, an integer from `1` to `10000000`. The PNG is cropped to the widget bounds. | `720` | | `--device-scale-factor ` | Pixel density, greater than 0 and at most 4. | `1` | | `--theme ` | Host theme. | `light` | | `--wait-for ` | Wait for a selector before capture. | None | | `--delay ` | Additional delay after readiness. | `0` | | `--timeout ` | Tool, browser, and readiness timeout. | `30000` | | `--inspector ` | Use an existing Inspector origin. | Starts one | | `--cdp-url ` | Use an existing Chrome DevTools endpoint. | Launches Chrome | | `--json` | Emit one result or error and never prompt. | Off | **Examples:** ```bash theme={null} mcp-use screenshot --server demo --tool show-app appName=Demo mcp-use screenshot --mcp https://example.com/mcp --tool show-app \ '{"appName":"CI"}' --theme dark --output app.png --json ``` **Exit codes:** | Code | Meaning | | - | - | | `0` | Capture succeeded, or help was requested. | | `2` | Invalid arguments. | | `1` | MCP, tool, Inspector, browser, readiness, or write failure. | ## Environment variables | Variable | Used by | Description | Default | | - | - | - | - | | `PORT` | `dev`, `start`, server runtime | Server port when `--port` is not provided. `dev` sets it to the resolved listener port before importing the entry; `start` reads it before importing the built entry. | `3000` | | `HOST` | `dev`, `start`, server runtime | Bind host when `--host` is not provided. `start` and direct `listen()` fall back to `config.host` before `127.0.0.1`. | `127.0.0.1` | | `NODE_ENV` | `dev`, `build`, `start` | Runtime environment. When it is not already set, `dev` uses `development`, and `build` and `start` set `production` before loading the project `.env`. | Command-specific | | `MCP_URL` | server runtime, `dev`, `build` | **Server public origin**, such as `https://mcp.example.com`. OAuth resource URL, CSP `connectDomains`, dev HMR websocket. When OAuth derives its resource from `MCP_URL` (the provider sets no `resource`), a value with a path, query, or credentials makes the server constructor throw; views and CSP use only its origin. Lower priority than `CSP_URLS`. `dev` sets it only while importing the entry on loopback binds, `build` sets `http://localhost:3000` only while inspecting the entry, and `start` never sets it. | None (request origin) | | `MCP_ASSETS_URL` | `build`, server runtime | **Assets URL prefix** (origin + optional path) for view JS/CSS and `public/`. Falls back to `MCP_URL` origin. When set at build, manifest paths become full CDN URLs (path segment from server `basePath`). | None (falls back to server origin) | | `CSP_URLS` | server runtime | Comma-separated CSP domain shortcut — applied to all four MCP Apps categories when per-category vars are unset. Higher priority than `MCP_URL` auto-append. | None | | `CSP_CONNECT_DOMAINS` | server runtime | Overrides `CSP_URLS` for `connectDomains` | None | | `CSP_RESOURCE_DOMAINS` | server runtime | Overrides `CSP_URLS` for `resourceDomains` | None | | `CSP_FRAME_DOMAINS` | server runtime | Overrides `CSP_URLS` for `frameDomains` | None | | `CSP_BASE_URI_DOMAINS` | server runtime | Overrides `CSP_URLS` for `baseUriDomains` | None | | `MCP_USE_CLOUD_WEB_URL` | `deploy` | Manufact web URL for dashboard and GitHub settings links. | `https://manufact.com` | | `MCP_USE_CLOUD_API_URL` | `login` and all cloud commands | Manufact API URL. Takes precedence over `MCP_API_URL`. The CLI normalizes it to include `/api/v1`. | `https://cloud.manufact.com/api/v1` | | `MCP_API_URL` | `login` and all cloud commands | Fallback Manufact API URL when `MCP_USE_CLOUD_API_URL` is unset. | `https://cloud.manufact.com/api/v1` | | `MCP_USE_API_KEY` | `login` and all cloud commands | API key for non-interactive login. Cloud commands (`deploy`, `servers`, `deployments`, `org`, `whoami`) use it directly and prefer it over the saved credential. | None | | `MCP_USE_WS_RELAY` | `dev --tunnel`, `start --tunnel` | WebSocket relay API origin used when creating authenticated local tunnels. | `https://api.tunnel.mcp-use.run` | | `MCP_USE_CHROME_PATH` | `screenshot` | Chrome executable path for screenshots. | Auto-detected | | `PUPPETEER_EXECUTABLE_PATH` | `screenshot` | Fallback Chrome executable path. | Auto-detected | | `CHROME_PATH` | `screenshot` | Fallback Chrome executable path. | Auto-detected | **Examples:** ```bash theme={null} PORT=8080 mcp-use start MCP_URL=https://my-server.example.com MCP_ASSETS_URL=https://cdn.example.com/bucket mcp-use build MCP_USE_API_KEY=mcp_... mcp-use login --org my-org MCP_USE_CHROME_PATH=/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \ mcp-use screenshot --server local --tool show-board ``` ## Related references * [CLI Client guide](/v2/typescript/tooling/client-cli) * [Tunneling guide](/tunneling/index) * [Manufact Cloud deployment guide](/v2/typescript/server/deployment/mcp-use) * [ServerConfig API reference](https://mcp-use-typescript-api-reference.vercel.app/modules/mcp-use.index.html#serverconfig) # Updates Source: https://docs.mcp-use.com/v2/typescript/changelog New updates and improvements to the TypeScript SDK **v2.11.2** ## Hosted Inspector release ordering Patch release synchronizing the Inspector and CLI dependency metadata, with no server API changes. * **Update**: Updated @mcp-use/inspector to v20.3.24, using native Railway deployment with verified npm publication, exact package versions, and stable-only production builds; see the [Inspector changelog](/inspector/changelog) * **Update**: Updated @mcp-use/cli to v4.5.2 with synchronized Inspector dependency metadata **v2.11.1** ## Inspector chat & hosted connections Patch release updating the bundled Inspector and CLI, with no server API changes. * **Update**: Updated @mcp-use/inspector to v20.3.23, fixing thinking feedback between tool calls, chat backgrounds during history resizing, and hosted MCP proxy routing (`#2891`, `#2899`, `#2900`); see the [Inspector changelog](/inspector/changelog) * **Update**: Updated @mcp-use/cli to v4.5.1 with synchronized Inspector dependency metadata **v2.11.0** ![Release 2.11.0](https://mcp-use.com/api/og/release?v=2.11.0\&title=Custom%20landing%20pages\&date=2026-10\&lang=typescript) ## Custom landing pages Minor release adding a customizable page at the MCP URL with `landing.tsx`, plus agent streaming, OAuth client, and CLI fixes. * **New** (server, @mcp-use/cli): a `landing.tsx` in the MCP root replaces the page a browser sees at the MCP URL. `mcp-use dev` and `mcp-use build` find it (also under `--mcp-dir`) and `mcp-use start` serves the built page. It renders on the server and hydrates in the browser; without it, the built-in page is served as before (`#2648`) * **New** (server): `mcp-use/landing` exports React-free hooks for the page: `useServerInfo()`, `useToolList()`, `usePromptList()`, `useResourceList()` and `useInstallTargets()`. Server info always ships to the page; each list ships only when the page's import graph uses its hook (`#2648`) * **New** (server): `getInstallTargets({ url, name })` returns install links and commands for Claude Code, Cursor, VS Code, VS Code Insiders, ChatGPT and the Manufact Inspector, for use outside the server such as on a docs site (`#2648`) * **New** (server): `landing.tsx` can `export const metadata` (`title`, `description`, `icon`, `image`) to set the page title, meta description, and Open Graph and Twitter tags (`#2648`) * **New** (@mcp-use/cli): Tailwind classes work in `landing.tsx` without a CSS file and CSS imports are bundled. In dev, edits use Fast Refresh, adding or deleting `landing.tsx` switches pages live, and a broken edit keeps serving the last working page. Builds honor `MCP_ASSETS_URL` (`#2648`) * **New** (create-mcp-use-app): every template includes a Tailwind-styled `landing.tsx`; `blank` and `mcp-server` add React and its types, and every template's `tsconfig.json` typechecks `landing.tsx` (`#2648`) * **Fix** (server, @mcp-use/cli): landing pages set `data-theme` from the OS color scheme before first paint so `dark:` classes work; a page whose CSS imports Tailwind itself owns Tailwind; and in `mcp-use dev` the page's stylesheets load before hydration (`#2880`) * **Update** (server): ChatGPT install steps follow the Plugins flow (Plugins → Add → Add Custom MCP Server) instead of developer mode and the Connectors tab (`#2648`) * **Fix** (@mcp-use/cli): `mcp-use start --with-inspector` serves the Inspector at `/inspector` when `basePath` is `"/"`, and `mcp-use dev` prints `/inspector` instead of `//inspector` (`#2555`) * **Fix** (@mcp-use/cli): `mcp-use client` and `mcp-use screenshot` install a matching `@mcp-use/client` when they auto-install it, including on Windows where the install always failed (`#2853`) * **Fix** (@mcp-use/agent): the OpenAI Responses provider emits tool-call argument events, so `MCPAgent.stream()` and `streamEvents()` report steps for tool calls on OpenAI models (`#2551`) * **Fix** (@mcp-use/agent): `MCPAgent.stream()` returns and saves to memory only the final turn's text, the same as `run()`, instead of gluing on text written before tool calls (`#2723`) * **Fix** (@mcp-use/agent): `RemoteAgent.run` no longer rejects successful responses whose body has no `error` field, and error messages show the error instead of `[object Object]` (`#2651`) * **Fix** (@mcp-use/client): `useMcp().authTokens.expires_at` no longer moves later on every reconnect for opaque (non-JWT) tokens; the expiry is saved when tokens are received (`#2879`) * **Fix** (@mcp-use/client): Node OAuth loopback connections close after the callback, cancellation, or timeout, so the process can exit (`#2766`) * **Update**: Updated @mcp-use/cli to v4.5.0, create-mcp-use-app to v2.1.0, @mcp-use/client to v2.4.5, and @mcp-use/agent to v2.0.25 * **Update**: Updated @mcp-use/inspector to v20.3.22; see the [Inspector changelog](/inspector/changelog) **v2.10.1** ## OAuth discovery & browser tool calls Patch fixes for public MCP connections, OAuth credential binding, browser tool calls, and ChatGPT widget descriptions. * **Fix** (@mcp-use/client): validate OAuth protected-resource metadata with the official SDK before classifying an anonymous connection as mixed auth. Root metadata for a different resource no longer makes a public MCP endpoint appear to require authentication (`#2858`) * **Fix** (@mcp-use/client): discard cached OAuth credentials with a missing, empty, or mismatched issuer stamp. Affected users may need to sign in again (`#2858`) * **Fix** (@mcp-use/client): browser tool calls send `Mcp-Param-*` headers for parameters annotated with `x-mcp-header`, so servers that require those headers accept calls from clients such as the Inspector (`#2803`) * **Fix** (server): copy a tool view's `description` to `_meta["openai/widgetDescription"]` on `resources/list` and `resources/read`, restoring the widget description for ChatGPT (`#2845`) * **Update**: Updated @mcp-use/client to v2.4.4, @mcp-use/agent to v2.0.24, and @mcp-use/cli to v4.4.1 * **Update**: Updated @mcp-use/inspector to v20.3.21; see the [Inspector changelog](/inspector/changelog) **v2.10.0** ![Release 2.10.0](https://mcp-use.com/api/og/release?v=2.10.0\&title=OAuth%20Proxy%20for%20non-DCR%20providers\&date=2026-10\&lang=typescript) ## OAuth Proxy for non-DCR providers Minor release adding an OAuth authorization server in front of identity providers without dynamic client registration, secret-free production builds, and `.gitignore`-aware deployments. * **New** (server): `oauthProxy()` in `mcp-use/oauth` makes the MCP server its own authorization server in front of GitHub (`github()`), Google (`google()`), or any OAuth 2.0 provider (`upstream()`). Clients present a client ID metadata document or register (DCR), approve a server-owned consent page that names the server by its host, and receive the proxy's own opaque tokens (`#2822`) * **New** (server): the `clients` option limits which clients may connect, by metadata document URL, origin, or a client defined on the server (`#2822`) * **New** (server): the upstream client secret and user tokens stay on the server, encrypted in a shared store from `mcp-use/oauth/storage`: Upstash, Redis, Postgres, Firestore, Cloudflare D1 or Durable Object, or in-memory for local development. `redisStorage` takes a connected client or a lazy connect function (`#2822`) * **New** (server): tools read the upstream token with `upstreamToken(ctx.auth)` or `ctx.auth.upstream` (`#2822`) * **Enhancement** (server): failed sign-ins and refreshes log the cause without token or code values (provider error code and description, HTTP status and content type, mismatched `iss`, or network error); refused client metadata documents and records encrypted with a retired secret are also logged (`#2822`) * **Enhancement** (server): clients that signed in through the 1.x `oauthProxy` keep working while registration is on; users approve the consent page once and sign in again without removing the server (`#2822`) * **New** (server): OAuth providers can register public HTTP routes from `setup()` with `host.route()`, read `host.mode` and `host.listenHost`, and compute `oauthMetadata` from the resolved resource URL (`#2822`) * **Fix** (server): OAuth endpoints under the MCP path are never written to trace logs, and `oauthEnvironmentValue` no longer throws on runtimes without `process` (`#2822`) * **Fix** (server): trailing-slash trimming in `upstashStorage` and the GitHub and Google upstream providers no longer uses a backtracking regex * **New** (server, @mcp-use/cli): `mcp-use build` evaluates the entry with `MCP_USE_PHASE=build` and no longer needs runtime secrets; the new `isBuilding()` export lets module-scope code skip reading secrets or connecting to a database. `oauthProxy` and `upstashStorage` require no secrets or credentials while building (`#2830`) * **Fix** (@mcp-use/cli): `mcp-use build` exits when the build finishes, even if the entry opened a connection at module scope such as a Redis client (`#2830`) * **Fix** (@mcp-use/cli): `mcp-use build` builds for production when `NODE_ENV` is unset. Views no longer ship React's development build, and server-side JSX no longer compiles to `jsxDEV`, which failed under `mcp-use start` (`#2830`) * **Fix** (@mcp-use/cli): a failed build or dev start prints the cause of a refused connection instead of an empty line (`#2830`) * **New** (@mcp-use/cli): `mcp-use deploy --no-github` applies `.gitignore` rules when packaging, including wildcards, directory rules, and negation, while keeping the baseline cloud exclusions (`#2485`) * **Fix** (server): `MCPServer.fromOpenAPI` converts OpenAPI 3.0 boolean `exclusiveMinimum` and `exclusiveMaximum` into JSON Schema numeric bounds instead of throwing while registering tools (`#2717`) * **Fix** (@mcp-use/agent): the Anthropic provider sends `"[no content]"` for empty tool result content, avoiding HTTP 400 errors from the Messages API (`#2693`) * **Documentation**: add the [OAuth Proxy](/v2/typescript/server/authentication/providers/oauth-proxy) guide, [OAuth Proxy storage](/v2/typescript/server/authentication/providers/oauth-proxy-storage), v1 migration notes, and API reference; add GitHub and Google `oauthProxy` examples with Firestore (`#2841`, `#2831`) * **Documentation**: correct API reference comments: stdio `env` does not inherit the parent environment, `defaultRequestOptions` applies only to the initial tool listing, `VMExecutorOptions.memoryLimitMb` is not enforced, legacy stateless GET, DELETE, and HEAD return `204`, and `mcp-use/vite`, `mcp-use/tanstack-start`, and `mcp-use/tanstack-start/vite` appear in the generated reference (`#2838`) * **Update**: patch vulnerable transitive dependencies (`proxy-addr`, `shell-quote`, `source-map-js`) and update Next.js examples to `next` ^16.3.8 (`#2842`) * **Update**: Updated @mcp-use/cli to v4.4.0 * **Update**: Updated @mcp-use/agent to v2.0.23 and @mcp-use/client to v2.4.3 * **Update**: Updated @mcp-use/inspector to v20.3.20; see the [Inspector changelog](/inspector/changelog) **v2.9.0** ![Release 2.9.0](https://mcp-use.com/api/og/release?v=2.9.0\&title=Typed%20composer%20mention%20search\&date=2026-10\&lang=typescript) ## Typed composer mention search Minor release adding typed search for app-owned items in supporting ChatGPT desktop composers. * **New** (server): `server.mentions({ name, search })` registers a normal typed `ToolRef` for searching people, files, channels, and other app-owned items without a View or iframe handshake (`#2792`) * **New** (server): generate a required string `query` input schema and an `{ items: ResourceLink[] }` output schema using the official SDK resource-link schema; export `ResourceLink`, `MentionSearchParams`, `MentionSearchResult`, and `MentionsRegistration` from `mcp-use` (`#2792`) * **Enhancement** (server): mention tools advertise `mentions/search` extension metadata and always include app visibility, preserving unrelated descriptor metadata; search is annotated read-only by default (`#2792`) * **Enhancement** (server): search callbacks receive ordinary request context, OAuth sign-in defaults, and `ctx.signal`; empty and whitespace queries pass through unchanged. Applications control authorization, ranking, and result limits (`#2792`) * **Documentation**: add composer mention registration, result contracts, visibility behavior, and authorization guidance to [ChatGPT Plugin Extensions](/v2/typescript/mcp-apps/chatgpt-extensions#composer-mention-search) (`#2792`) * **Update** (@mcp-use/cli): rebuild bundled workspace code and synchronize published internal package metadata * **Update**: Updated @mcp-use/cli to v4.3.3 * **Update**: Updated @mcp-use/inspector to v20.3.19; see the [Inspector changelog](/inspector/changelog) **v2.8.2** ## Tunnel cancellation & API reference navigation Patch release keeping development tunnels connected when a cancellation arrives after its request has finished, with clearer API reference navigation. * **Fix** (@mcp-use/tunnel, @mcp-use/cli): ignore valid late or duplicate request cancellations so they no longer close the tunnel or interrupt unrelated requests; active requests still cancel normally (`#2664`) * **Documentation**: improve generated API reference navigation and clarify client and React hook documentation (`#2791`) * **Update**: Updated @mcp-use/tunnel to v0.2.2 and @mcp-use/cli to v4.3.2 * **Update**: Updated @mcp-use/inspector to v20.3.18; see the [Inspector changelog](/inspector/changelog) **v2.8.1** ## Streaming, code mode & deployment fixes Patch release fixing streamed tool notifications, code-mode discovery, CLI deployment links and remote validation, Windows scaffolding, and Inspector tool timeouts. * **Fix** (server): request logging no longer buffers SSE response bodies, so tool progress and log notifications reach clients before tool completion. This applies at every logging level, including trace; finite JSON response logging is preserved (`#2789`) * **Fix** (@mcp-use/client): `CodeModeConnector.listTools()` returns `execute_code` and `search_tools`, exposes tool capabilities and protocol metadata, and returns empty resource, resource-template, and prompt lists (`#2488`) * **Fix** (@mcp-use/client): `CodeModeConnector` honors request abort signals for listing and tool calls, including cancellation while waiting for code execution or tool search (`#2488`) * **Fix** (@mcp-use/cli): deployment dashboard links use the selected organization slug and server ID for managed uploads and GitHub deployments; organizations without a slug no longer receive an invalid link (`#2744`) * **Fix** (@mcp-use/cli): `mcp-use deploy` validates that Git remotes are hosted on `github.com`, rejecting other hosts that merely contain `github.com` in their hostname or path (`#2687`) * **Fix** (create-mcp-use-app): `--install` and the install prompt run npm and pnpm through a shell on Windows so their `.cmd` shims work instead of failing with `spawn npm ENOENT` (`#2696`) * **Fix** (@mcp-use/inspector): tool calls honor saved timeout settings and cleared timeouts stay cleared; see the [Inspector changelog](/inspector/changelog) (`#2656`) * **Update**: Updated @mcp-use/agent to v2.0.22 and @mcp-use/client to v2.4.2 * **Update**: Updated @mcp-use/inspector to v20.3.17; see the [Inspector changelog](/inspector/changelog) * **Update**: Updated @mcp-use/cli to v4.3.1 * **Update**: Updated create-mcp-use-app to v2.0.10 **v2.8.0** ![Release 2.8.0](https://mcp-use.com/api/og/release?v=2.8.0\&title=ChatGPT%20Plugin%20Extensions\&date=2026-10\&lang=typescript) ## ChatGPT Plugin Extensions Minor release adding typed ChatGPT Plugin Extensions across server and React APIs, with updated MCP SDKs and richer examples. * **New** (server): register typed global, thread, and file entrypoints on `tool.view`; launch contracts are validated and OpenAI tool metadata is preserved (`#2737`) * **New** (server): register native ChatGPT plugin settings with typed fields, optional layout, validated read/update tools, request context callbacks, and per-request capability advertisement. Applications keep control of persistence and authorization (`#2739`) * **New** (server): advertise top-level tool icons in `tools/list`, including proxied tools, and support public-relative icon assets (`#2779`) * **New** (@mcp-use/react): `useDeepLink` reads the initial and subsequent ChatGPT deep-link URLs through the existing MCP App connection (`#2738`) * **New** (@mcp-use/react): `useModelContext` manages keyed native text, image, resource-link, and embedded-resource attachments. It activates only for committed hook consumers and handles replacement, removal, cancellation, and delivery failures without restoring stale content (`#2776`) * **Enhancement** (server): define supported MCP App display modes and an optional initial ChatGPT display preference in the named `viewConfig` export; validate preferences while preserving broader host capabilities (`#2740`) * **Enhancement** (@mcp-use/cli): include display-mode configuration in development and production view manifests and pre-bundle the model-context schema for cold iframe startup (`#2740`, `#2776`) * **New** (examples): add a Bookshop Plugin Extensions example with entrypoint icons, plugin settings, and model-context attachments (`#2773`) * **Fix** (create-mcp-use-app): failed template selection or GitHub template cloning no longer leaves an empty project directory that blocks a retry (`#2765`) * **Update** (@mcp-use/client): update the official MCP client, core, and server SDKs to 2.3.1 and MCP Apps to 2.0.3. Node follows only same-origin redirects that preserve the request method; browsers reject redirects by default, so configure the final endpoint URL (`#2784`) * **Documentation**: add the ChatGPT Plugin Extensions guide for MCP Apps and clarify browser redirect restrictions (`#2772`, #2784) * **Update**: Updated @mcp-use/agent to v2.0.21 and @mcp-use/client to v2.4.1 * **Update**: Updated @mcp-use/inspector to v20.3.16; see the [Inspector changelog](/inspector/changelog) * **Update**: Updated @mcp-use/cli to v4.3.0 * **Update**: Updated create-mcp-use-app to v2.0.9 **v2.7.3** ## CLI argument & Windows screenshot fixes Patch release fixing CLI argument parsing, Windows browser discovery, scaffold deploy guidance, and Inspector chat input spacing, with dependency security updates. * **Fix** (@mcp-use/cli): plain `key=value` tool and prompt arguments preserve `:=` inside the value, so `code="x := 1"` is sent as a string; `key:=` still parses a typed JSON value (`#2665`) * **Fix** (@mcp-use/cli): on Windows, `mcp-use screenshot` also finds Chrome under `Program Files (x86)`, Microsoft Edge, and Brave instead of failing with `chrome_not_found` when neither original Chrome location exists (`#2725`) * **Fix** (create-mcp-use-app): scaffold completion prints `pnpm run deploy` so pnpm runs the project's deploy script instead of its built-in `deploy` command (`#2701`) * **Fix** (@mcp-use/inspector): multiline chat input stays clear of the bottom toolbar; see the [Inspector changelog](/inspector/changelog) (`#2735`) * **Update** (server): update Hono to `^4.13.7` and raise workspace dependency security floors (`#2746`) * **Documentation** (@mcp-use/client): the AI SDK OpenAI example installs from a fresh checkout with a frozen lockfile and runs TypeScript directly on Node.js 22.22.2 or newer (`#2672`) * **Documentation** (create-mcp-use-app): the Connect to AI example configures its MCP server through `MCPClient`'s `mcpServers` map (`#2727`) * **Update**: Updated @mcp-use/inspector to v20.3.15; see the [Inspector changelog](/inspector/changelog) * **Update**: Updated @mcp-use/cli to v4.2.1 * **Update**: Updated create-mcp-use-app to v2.0.8 **v2.7.2** ## OAuth UserInfo & stricter CLI flags Patch release exposing optional OAuth UserInfo, plus a CLI minor that rejects inline values on boolean flags. * **New** (@mcp-use/client): `useMcp` and `useMcpServer` expose reactive OAuth UserInfo. Set `oauth.fetchUserInfo: true` to load the account after the connection is ready, or call `getUserInfo()`. `userInfo` is `idle`, `loading`, `available`, `unavailable`, or `error`; a UserInfo failure does not change `state`. See [OAuth UserInfo](/v2/typescript/client/usemcp#oauth-userinfo) (`#2688`) * **Fix** (@mcp-use/client): base64 MCP App HTML resources decode as UTF-8, so non-ASCII text renders correctly in React views (`#2632`) * **Fix** (@mcp-use/agent): array-valued Gemini tool results are wrapped in an object so function responses match the provider schema in streaming and non-streaming calls (`#2675`) * **Fix** (@mcp-use/agent): `runToolLoopNonStreaming` stops dispatching the rest of a turn's tool calls when `signal` is aborted, matching `runToolLoop` (`#2667`) * **Fix** (server): proxied prompt requests receive the downstream cancellation signal (`#2568`) * **Fix** (@mcp-use/cli): an inline value on a boolean flag is rejected instead of ignored. `mcp-use dev --tunnel=false` used to open a public tunnel; it now fails with `--tunnel does not take a value`. The same applies to `--no-open`, `--no-inspector`, `--with-inspector`, `--source-maps`, `--inline`, `--help`, and `--version`. Flags that take a value still accept `--flag value` and `--flag=value` (`#2521`) * **Fix** (@mcp-use/cli): `mcp-use servers env --help` prints `servers env` help instead of the root `servers` help (`#2690`) * **Fix** (@mcp-use/inspector): the Express adapter aborts the upstream stream when the client disconnects during a response (`#2394`) * **Enhancement** (@mcp-use/inspector): the OAuth proxy allows GET to UserInfo endpoints advertised in authorization-server metadata (`#2688`) * **Update**: Updated @mcp-use/inspector to v20.3.14; see the [Inspector changelog](/inspector/changelog) * **Update**: Updated @mcp-use/cli to v4.2.0 * **Update**: Updated @mcp-use/client to v2.4.0 **v2.7.1** ## View cancellation & client fixes Patch release surfacing host tool cancellation in views, plus browser client and OAuth token expiry fixes. * **Fix** (server): views no longer stay pending when the host cancels the tool call that rendered them. `useToolContext()` switches to `status: "error"` with a new `ToolCancelledError` (exported from `mcp-use/react`) carrying the host's `reason`; a cancellation after a result is still ignored. `ToolContextError` is now `ToolError | ToolCancelledError`, so narrow with `instanceof ToolError` before reading `error.result` (`#2646`) * **Fix** (@mcp-use/client): `ViewRenderer` no longer sends `tool-cancelled` when a tool call made by the view fails; that failure already rejects the view's call (`#2646`) * **Fix** (@mcp-use/client): `BrowserMCPClient` expands the `capabilities.views` shorthand into the `io.modelcontextprotocol/ui` extension and forwards `roots` and `defaultRequestOptions` to the connector, matching the Node client (`#2476`) * **Fix** (@mcp-use/client): `getOAuthTokenExpiry` reads the JWT `exp` claim from Base64URL payloads containing `-` or `_`, which previously fell back to `expires_in`; the `authTokens.expires_at` docs now say milliseconds (`#2660`) * **Documentation** (@mcp-use/agent): `RunOptions.messages` is documented as native-agent only; the LangChain agent ignores it, so pass prior messages through `externalHistory` (`#2658`) * **Documentation**: the v2 migration guide shows a temporary middleware rewrite so ChatGPT apps that cached v1 widget URIs (`ui://widget/…`) can still read Views served at `ui://views/…` until the app is resubmitted (`#2668`) * **Update**: Updated @mcp-use/inspector to v20.3.13; see the [Inspector changelog](/inspector/changelog) * **Update**: Updated @mcp-use/cli to v4.1.17 **v2.7.0** ![Release 2.7.0](https://mcp-use.com/api/og/release?v=2.7.0\&title=Mixed%20authentication\&date=2026-09\&lang=typescript) ## Mixed authentication Minor release serving public, optional, and sign-in tools from one OAuth-enabled endpoint in Claude and ChatGPT, plus an OAuth provider setup hook. * **New** (server): `mixedAuth: true` lets clients connect and list tools, resources, and prompts without a token; it requires an `oauth` provider and makes nothing public on its own. See [Mixed authentication](/v2/typescript/server/authentication/mixed-auth) (`#2630`) * **New** (server): tools accept a `securitySchemes` field in the shape ChatGPT reads on `tools/list`: `[{ type: "noauth" }]` (public), `[{ type: "noauth" }, { type: "oauth2", scopes }]` (optional), or `[{ type: "oauth2", scopes }]` (sign-in with extra scopes); omitting it means sign-in with the provider's `requiredScopes`. The new `ToolSecurityScheme` type describes the entries (`#2630`) * **New** (server): a tool's `ctx.auth` is typed from its literal `securitySchemes`: required when the tool needs sign-in, possibly `undefined` when it accepts `noauth` (`#2630`) * **New** (server): refused calls are answered before the callback runs, as HTTP `401`/`403` with `WWW-Authenticate` for Claude and spec clients, or as an `isError` result with `_meta["mcp/www_authenticate"]` for ChatGPT; invalid or expired tokens always get `401`, even on public tools (`#2630`) * **Enhancement** (server): on a `mixedAuth` server, resources, resource templates, and prompts always require sign-in, while every tool's view loads signed out so ChatGPT can read views during app creation; tool results stay gated (`#2630`) * **Enhancement** (server): tools advertise their resolved `securitySchemes` on `tools/list`, top level and in `_meta.securitySchemes`; a hand-written `_meta.securitySchemes` passes through unenforced, with a warning on `mixedAuth` servers or when it differs from the declared field. `oauth2` scopes also work without `mixedAuth`, adding to the endpoint-wide requirement (`#2630`) * **New** (server): `oauthCustomProvider` accepts an optional synchronous `setup(host)` hook that runs once at mount to install `mcp:` middleware, register provider-owned tools, resources, resource templates, and prompts, validate app tools with `listTools()`, and rewrite instructions; `host.mixedAuth` reports signed-out access. A failed or async hook fails the mount. `OAuthProviderHost` is exported from `mcp-use/oauth` (`#2405`) * **Fix** (server): `ThemeProvider` no longer remounts the view when the display mode switches between inline and fullscreen or pip, so local state and `useCallTool` results survive (`#2641`) * **Fix** (@mcp-use/cli): `screenshot` rejects `--width` and `--height` values Chrome cannot use (`#2617`) * **Documentation**: new Mixed authentication guide and `setup` hook docs for custom providers; the `mixed-oauth` example now uses `mixedAuth` and `securitySchemes`, covers every scheme shape, and runs behind `mcp-use dev --tunnel` for testing in Claude and ChatGPT (`#2630`, `#2405`) * **Update**: Updated @mcp-use/inspector to v20.3.12; see the [Inspector changelog](/inspector/changelog) * **Update**: Updated @mcp-use/cli to v4.1.16 **v2.6.0** ![Release 2.6.0](https://mcp-use.com/api/og/release?v=2.6.0\&title=TanStack%20Start%20integration\&date=2026-09\&lang=typescript) ## TanStack Start integration Minor release adding Vite-powered MCP servers in TanStack Start, along with client, CLI, scaffold, and documentation updates. * **New** (server): `mcp-use/vite`, `mcp-use/tanstack-start`, and `mcp-use/tanstack-start/vite` mount an MCP server in a TanStack Start route; a dedicated Vite environment reloads server code, skills, and views during development and builds deployable assets for production (`#2517`) * **Fix** (server): the landing page hides the public chat button until public chat is available (`#2612`) * **Fix** (server): Vite integration base-path validation handles long paths with repeated slashes without slow regex matching * **Fix** (@mcp-use/client): sibling inline widgets preserve each other's fullscreen and picture-in-picture document state, and MCP App iframes remain transparent in dark hosts (`#2454`, `#2610`) * **Fix** (@mcp-use/cli): `whoami` uses the account's default organization when none is selected locally, and whitespace around `skills.directory` no longer breaks skill discovery (`#2570`, `#2597`) * **Fix** (create-mcp-use-app): template tsconfigs load Node types explicitly so new projects typecheck with TypeScript 7 (`#2595`) * **Documentation**: new cookbook recipes cover Daytona code execution, Next.js, Upstash rate limiting, Sentry error tracking, and TanStack Start; examples also show A2UI generative views (`#2513`, `#2515`, `#2564`, `#2566`, `#2572`, `#2518`) * **Update**: release CI checks SDK changesets and changelog entries (`#2579`) * **Update**: Updated @mcp-use/inspector to v20.3.11; see the [Inspector changelog](/inspector/changelog) * **Update**: Updated @mcp-use/cli to v4.1.15 * **Update**: Updated create-mcp-use-app to v2.0.7 **v2.5.2** ## Scrollable Inspector app results Patch release keeping tall MCP App tool results accessible in Inspector. * **Fix** (@mcp-use/inspector): tall MCP App results scroll within the tool result panel; see the [Inspector changelog](/inspector/changelog) (`#2598`) * **Update**: Updated @mcp-use/inspector to v20.3.10 * **Update**: Updated @mcp-use/cli to v4.1.14 **v2.5.1** ## Agent step limits & client progress routing Patch release fixing per-call agent budgets and SDK notification handling, with Inspector cloud model selection improvements. * **Fix** (@mcp-use/agent): `maxSteps` passed to `run`, `stream`, or `streamEvents` limits model calls for that invocation while preserving the constructor default for later calls (`#2437`) * **Fix** (@mcp-use/client): progress and cancellation notifications reach the SDK handlers with all required arguments; progress stays associated with the correct call across concurrent requests and multi-round retries (`#2548`) * **Update** (@mcp-use/agent): `MCPServerConfig.auth_token` is deprecated but retained for type compatibility; use `authToken` to send an authentication token (`#2486`) * **Fix** (@mcp-use/inspector): managed chat uses the selected model's branding and a curated cloud provider picker; see the [Inspector changelog](/inspector/changelog) (`#2575`, `#2576`) * **Update** (server): update Hono to `^4.13.5` and Next.js to `^16.3.3` (`#2492`, `#2495`) * **Update**: the TypeScript workspace no longer installs Husky Git hooks; contributors must run formatting and lint checks manually (`#2582`) * **Update**: Updated @mcp-use/inspector to v20.3.9 * **Update**: Updated @mcp-use/cli to v4.1.13 **v2.5.0** ![Release 2.5.0](https://mcp-use.com/api/og/release?v=2.5.0\&title=Public%20chat%20CTA\&date=2026-09\&lang=typescript) ## Public chat CTA Minor release adding a landing-page chat button plus client, CLI, and agent lifecycle fixes. * **New** (server): the HTML landing page shows a “Go to chat” button when public chat is ready (`#2496`) * **Fix** (server): proxied `resources/list` keeps upstream `annotations` and `_meta` (`#2469`) * **Fix** (server): a malformed `createJwtVerifier` `resource` option throws `TypeError` at startup instead of reporting `invalid_token` (`#2412`) * **Fix** (@mcp-use/client): concurrent connect and disconnect calls are coalesced; a later disconnect cancels in-flight reconnects (`#2458`) * **Fix** (@mcp-use/client): `useMcp` stabilizes `clientInfo` and `proxyConfig` dependencies so parent re-renders do not reconnect (`#2403`) * **Fix** (@mcp-use/client): `ViewRenderer` removes the sandbox listener and cancels the readiness wait on unmount (`#2421`) * **Fix** (@mcp-use/cli): `servers list` validates `--limit` and `--skip` before authenticating so bad pagination is a usage error instead of “Not logged in.” (`#2448`) * **Fix** (@mcp-use/cli): a malformed JSON argument to `client` or `screenshot` is a usage error (exit 2) (`#2444`) * **Fix** (@mcp-use/cli): `--secret` must be passed on every `servers env set` write; omitting it stores the value as non-sensitive (`#2423`) * **Fix** (@mcp-use/tunnel): standalone `mcp-tunnel` defaults `localHostHeader` to `localhost` (`#2456`) * **Fix** (@mcp-use/agent): OpenRouter BYOK requests to OpenAI models use the Responses API (`#2501`) * **Update**: replace the `@mcp-use/ext-apps` package alias with official `@modelcontextprotocol/ext-apps` 2.0.0 (`#2498`) * **Fix** (@mcp-use/inspector): standalone Inspector rebuilds with the agent OpenRouter fix and repaired peer metadata; see the Inspector changelog (`#2504`) * **Documentation** (@mcp-use/cli): CLI reference states that `--secret` must be passed on every `servers env set` write (`#2423`) * **Update**: Updated @mcp-use/inspector to v20.3.8 * **Update**: Updated @mcp-use/cli to v4.1.12 **v2.4.3** ## AI SDK adapter & stricter CLI deletes Patch release adding a dependency-free Vercel AI SDK adapter and failing CLI deletes when the target does not exist. * **New** (@mcp-use/client): `createAiSdkTools` exposes MCP tools as AI SDK dynamic tools (v5–v7) without adding an AI SDK dependency; example at `packages/client/examples/node/ai-sdk-openai` (`#2441`) * **Fix** (@mcp-use/cli): `servers env unset` and `client remove` fail when the target does not exist instead of printing a success line (`#2411`) * **Documentation**: elicitation samples no longer teach the removed `ctx.elicit` API (`#2409`); custom JWT docs distinguish `aud` from the RFC 8707 `resource` request parameter (`#2443`) * **Update**: Updated @mcp-use/inspector to v20.3.7 * **Update**: Updated @mcp-use/cli to v4.1.11 **v2.4.2** ## Publish artifact preservation Patch release keeping package builds intact while npm pack runs. * **Fix**: concurrent publishing no longer drops the Client build while its tarball is created, and packed artifacts are checked for declared files and entry points (`#2428`) * **Update**: Updated @mcp-use/inspector to v20.3.6 **v2.4.1** ## OAuth loopback recovery & scaffold help Patch release recovering Node OAuth after a failed loopback bind, dropping a dead scaffold flag, and fixing Inspector chat widget connections. * **Fix** (@mcp-use/client): Node OAuth rebinds the loopback listener after a failed bind instead of hanging until `authTimeoutMs` (`#2393`) * **Fix** (create-mcp-use-app): help no longer lists `--no-git`; scaffolding has not initialized a git repository since #820 (`#2392`) * **Fix** (@mcp-use/inspector): chat MCP Apps use the registered connection id while keeping the logical server id for chat state and storage; see the Inspector changelog (`#2404`) * **Update**: Updated @mcp-use/inspector to v20.3.5 * **Update**: Updated @mcp-use/cli to v4.1.10 * **Update**: Updated create-mcp-use-app to v2.0.6 **v2.4.0** ![Release 2.4.0](https://mcp-use.com/api/og/release?v=2.4.0\&title=Convex%20OAuth%20provider\&date=2026-09\&lang=typescript) ## Convex OAuth provider Minor release adding a built-in Convex verifier, failing screenshots on MCP App init errors, and stopping client OAuth retries after disconnect. * **New** (server/oauth): `oauthConvexProvider` verifies Convex OAuth Provider JWTs and exports from `mcp-use/oauth/convex` (`#2372`) * **Fix** (@mcp-use/client): OAuth authorization retries stop after the client disconnects (`#2367`) * **Fix** (@mcp-use/client): `listAllResources` holds one client reference across pagination so a mid-list disconnect surfaces the transport error instead of `TypeError` (`#2387`) * **Fix** (@mcp-use/cli): `mcp-use screenshot` fails with `view_load_failed` instead of writing a PNG when the MCP App fails to initialize (`#2355`) * **Enhancement** (@mcp-use/inspector): RPC traffic shows request duration instead of wall-clock time; see the Inspector changelog (`#2364`) * **Enhancement** (@mcp-use/inspector): embedded client-side chats can configure up to 100 agent steps; see the Inspector changelog (`#2401`) * **Documentation**: Convex provider guide under v2 TypeScript authentication (`#2372`) * **Documentation** (@mcp-use/cli): CLI reference corrections for org use, `logout --yes`, `deployments`, `client remove --json`, and removal of non-existent deploy flags (`#2376`, `#2379`, `#2380`, `#2382`) * **Update**: Updated @mcp-use/inspector to v20.3.4 * **Update**: Updated @mcp-use/cli to v4.1.9 **v2.3.4** ## Compact request logs & OAuth-ready tokens Patch release collapsing MCP request logs to one line, projecting React OAuth tokens before ready, and using native Windows file watching in `mcp-use dev`. * **Enhancement** (server): request logs collapse to one compact line per HTTP request (`tools/call greet /mcp 200 client=… 12ms`); default `info` omits payloads, `debug`/`trace` add detail, and colocated `mcp-use dev` prefixes server lines with `[server]` (`#2351`) * **Fix** (@mcp-use/client): `useMcp` exposes OAuth `authTokens` in the same render that marks an authenticated connection as ready (`#2358`) * **Fix** (@mcp-use/cli): `mcp-use dev` uses Vite's native file watching on Windows instead of 100ms polling, so an edit during startup is not swallowed as the watch baseline (`#2338`) * **Enhancement** (@mcp-use/inspector): JSON-RPC traffic rows show response latency in the timing column; see the Inspector changelog (`#2349`) * **Documentation** (@mcp-use/cli): published package README so the npm page is no longer blank (`#2350`) * **Update**: Updated @mcp-use/inspector to v20.3.3 * **Update**: Updated @mcp-use/cli to v4.1.8 **v2.3.3** ## Safer session replacement & scaffolds Patch release cleaning up replaced client sessions, fresh-project validation, and scaffold guidance. * **Fix** (@mcp-use/client): `MCPClient.createSession()` disconnects an existing session before replacing it, preventing unreachable stdio children and HTTP sessions from remaining open (`#1964`) * **Fix** (@mcp-use/cli): binding validation no longer loads the React Vite plugin for projects without views, eliminating first-build dependency-resolution warnings in fresh `mcp-server`, `blank`, and `starter` projects (`#2307`) * **Fix** (create-mcp-use-app): scaffold output sends its “Learn more” link to `docs.mcp-use.com` instead of Manufact dashboard documentation (`#2328`) * **Enhancement** (@mcp-use/inspector): chat warns when a server exceeds the documented 128-tool limit for OpenAI or Gemini models; see the Inspector changelog (`#2333`) * **Update**: Updated @mcp-use/inspector to v20.3.2 * **Update**: Updated @mcp-use/cli to v4.1.7 * **Update**: Updated create-mcp-use-app to v2.0.5 **v2.3.2** ## Claude view compatibility & request diagnostics Patch release restoring Claude's resource-domain contract, exposing prompt request controls, and making Inspector RPC responses easier to diagnose. * **Fix** (server/views): `resources/read` rewrites authored view domains to the stable SHA-256-based `*.claudemcpcontent.com` domain expected by Claude clients, using per-request client identity with a legacy `User-Agent` fallback while leaving other clients and `resources/list` unchanged (`#2326`) * **Enhancement** (@mcp-use/client): prompt reads accept MCP `RequestOptions` through both `MCPClientSession.getPrompt` and the underlying connector (`#2302`) * **Enhancement** (@mcp-use/inspector): JSON-RPC response rows show the correlated request method and elapsed time and flag error responses; see the Inspector changelog (`#2303`) * **Update**: Updated @mcp-use/inspector to v20.3.1 * **Update**: Updated @mcp-use/cli to v4.1.6 **v2.3.1** ## Responsive server URLs & reusable connection settings Patch release keeping long landing-page URLs contained and exposing Inspector connection controls for embedded consumers. * **Fix** (server): long MCP server URLs truncate inside the landing-page hero on narrow viewports while remaining available through the copy button (`#2313`) * **Enhancement** (@mcp-use/inspector): export `ConnectionSettingsForm`, `useConnectionFormState`, connection configuration types, and optional consumer URL validation from `@mcp-use/inspector/client`; see the Inspector changelog (`#2319`) * **Update**: Updated @mcp-use/inspector to v20.3.0 **v2.3.0** ![Release 2.3.0](https://mcp-use.com/api/og/release?v=2.3.0\&title=Scalekit%20OAuth%20provider\&date=2026-08\&lang=typescript) ## Scalekit OAuth provider Minor release adding a built-in Scalekit verifier and improving Inspector chat usage and session isolation. * **New** (server/oauth): `oauthScalekitProvider` validates environment-root and resource-scoped issuers, binds the JWT audience to the Scalekit `res_…` resource identifier, and advertises Dynamic Client Registration and Client ID Metadata Document support (`#2272`) * **Fix** (@mcp-use/inspector): Anthropic cache-creation tokens survive usage aggregation and Inspector traces without double-counting OpenAI cache reads; see the Inspector changelog (`#2127`) * **Fix** (@mcp-use/inspector): chat state, persistence, streaming, and OAuth retry are isolated by session so **New Chat** can start while another session is streaming; see the Inspector changelog (`#2232`) * **Update**: Updated @mcp-use/inspector to v20.2.5 **v2.2.4** ## Workspace package alignment Patch release aligning the published workspace dependency versions. * **Update**: Updated @mcp-use/inspector to v20.2.4 * **Update**: Updated @mcp-use/cli to v4.1.5 **v2.2.3** ## Inspector protocol selection Patch release exposing protocol version controls in Inspector connections. * **Enhancement** (@mcp-use/inspector): connection setup and settings expose MCP protocol version selection and make configuration options easier to find; see the Inspector changelog * **Update**: Updated @mcp-use/inspector to v20.2.3 **v2.2.2** ## Workspace package alignment Patch release aligning the published workspace dependency versions. * **Update**: Updated @mcp-use/inspector to v20.2.2 * **Update**: Updated @mcp-use/cli to v4.1.4 **v2.2.1** ## OAuth protected-resource compatibility Patch release accepting secure parent-path resource metadata in OAuth discovery. * **Fix** (auth): protected-resource metadata may identify a same-origin, segment-aware parent of the MCP endpoint, matching the official MCP TypeScript SDK while still rejecting unsafe resource values * **Update**: Updated @mcp-use/inspector to v20.2.1 * **Update**: Updated @mcp-use/cli to v4.1.3 **v2.2.0** ![Release 2.2.0](https://mcp-use.com/api/og/release?v=2.2.0\&title=Custom%20OAuth%20verification%20%26%20remote%20development\&date=2026-08\&lang=typescript) ## Custom OAuth verification & remote development Minor release exporting JWT verification primitives and making remote MCP App development more reliable. * **New** (server/oauth): export `createJwtVerifier`, `JwtVerifierOptions`, and `VerifiedPayload` from `mcp-use/oauth` for custom OAuth providers * **Fix** (server): restore zero-config OAuth provider setup through `MCP_USE_OAUTH_*` environment variables while preserving explicit overrides * **Fix** (@mcp-use/cli): route Vite assets and HMR through the configured public MCP origin, pre-bundle view runtime dependencies and Zod, and ignore managed dev-server logs so remote views mount and update reliably * **Enhancement** (@mcp-use/inspector): embedded Chat exposes CSP mode and audit commands and ships the canonical Inspector style contract; see the Inspector changelog * **Fix** (create-mcp-use-app): canary scaffolds install canary SDK and skill sources instead of falling back to stable branches * **Update**: Updated @mcp-use/inspector to v20.2.0 * **Update**: Updated @mcp-use/cli to v4.1.2 * **Update**: Updated create-mcp-use-app to v2.0.4 **v2.1.1** ## Mixed-auth recovery & scaffold names Patch release supporting optional OAuth without blocking anonymous MCP connections and fixing generated npm package names. * **Enhancement** (auth): detect mixed-auth servers without blocking anonymous connections, resume protected operations through the official SDK OAuth flow, and preserve multiple `Set-Cookie` headers through the Node bridge * **Fix** (auth): recover optional OAuth discovery and CLI login after transient failures, keep ready React connections stable, and avoid reporting user-cancelled Inspector tool calls as failures * **Fix** (server): disable reverse-proxy buffering for open-ended MCP SSE responses so subscription acknowledgements are delivered immediately * **Fix** (create-mcp-use-app): sanitize named projects into valid npm package names, including quoted names and names beginning with underscores * **Enhancement** (@mcp-use/inspector): mixed-auth tool calls pause for authentication and resume the same chat turn; see the Inspector changelog * **Update**: Updated @mcp-use/inspector to v20.1.1 * **Update**: Updated @mcp-use/cli to v4.1.1 * **Update**: Updated create-mcp-use-app to v2.0.3 **v2.1.0** ![Release 2.1.0](https://mcp-use.com/api/og/release?v=2.1.0\&title=Skills%20over%20MCP%20%26%20v2%20server%20tooling\&date=2026-08\&lang=typescript) ## Skills over MCP & v2 server tooling Minor release adding experimental Skills over MCP authoring to the v2 server and completing the package split around the standalone CLI and Inspector. * **Fix**: MCP v2 server responses preserve tool JSON Schema dialects and accept input-required prompt results (`#2147`) * **Fix**: Modern connections remain ready when optional upstream identity metadata is absent, while anonymous direct-proxy upstreams report a clear namespace error * **New**: Experimental Skills over MCP authoring discovers `skills/`, supports explicit disable and directory configuration, SEP-2640 resource methods, development reloads, and build-time embedding * **New**: Authenticated WebSocket tunneling is published as a standalone package and bundled into `mcp-use dev/start --tunnel`, with bounded HTTP, streaming, MCP JSON-RPC, and public WebSocket forwarding * **Enhancement**: `mcp-use dev` reconciles server and v2 view changes as coherent project generations, so stale reload candidates cannot replace the active handler or publish outdated catalogs * **Update** (@mcp-use/cli): CLI implementation and tests now live in `@mcp-use/cli` while preserving the `mcp-use` command and server API; Windows path handling and bundled SDK/license packaging are covered * **Enhancement** (@mcp-use/cli): Skills over MCP discovery in Inspector filters invalid skills from fresh development snapshots * **Fix**: Next.js Turbopack builds resolve the Skills over MCP loader correctly (`#2197`) * **Enhancement** (@mcp-use/inspector): typed Skills operations, a capability-gated file explorer with integrity verification, the `window.openai` compatibility bridge, and related runtime fixes; see the Inspector changelog * **Fix** (create-mcp-use-app): clear unused TypeScript export surface flagged by Knip without changing published package entry APIs * **Update**: Updated @mcp-use/inspector to v20.1.0 * **Update**: Updated @mcp-use/cli to v4.1.0 * **Update**: Updated create-mcp-use-app to v2.0.2 **v2.0.4** ## Stable npm README links Patch release fixing absolute links in the published package documentation. * **Fix**: README images and repository links use stable absolute URLs so npm renders the published package documentation correctly * **Update**: Updated @mcp-use/inspector to v20.0.4 **v2.0.3** ## Stable package README metadata Patch release making the published package README reliable on npm. * **Fix**: Publish a package-root README and verify that it stays synchronized with the repository README before packing * **Update**: Updated @mcp-use/inspector to v20.0.3 **v2.0.1** ## Safer Inspector proxy & clearer CLI feedback Patch release hardening hosted Inspector proxy defaults and making successful CLI commands visible. * **Fix** (@mcp-use/inspector): embedded and hosted Inspector mounts block loopback OAuth proxy targets by default; standalone local development keeps loopback access unless running in production * **Enhancement** (@mcp-use/cli): `mcp-use start --with-inspector` prints the mounted Inspector URL, and successful `mcp-use typecheck` runs print a completion message with elapsed time * **Update**: runtime and bundled dependencies use patched stable releases with tightened transitive resolutions * **Update**: Updated @mcp-use/inspector to v20.0.1 * **Update**: Updated @mcp-use/cli to v4.0.1 **v2.0.0** ![Release 2.0.0](https://mcp-use.com/api/og/release?v=2.0.0\&title=MCP%20SDK%20v2%20%26%20server%20tooling\&date=2026-08\&lang=typescript) ## MCP SDK v2 & server tooling Major release migrating the TypeScript stack to the official MCP SDK v2 and introducing the v2 server, views, CLI, and scaffold architecture. * **Update**: The client and agent stack moves to the official MCP SDK v2, with automatic protocol negotiation, redesigned OAuth handling, ESM-only packages, a Node.js 22.22.2+ floor, and removal of v1 API aliases * **New**: The v2 server exposes a fetch-native Hono surface with typed MCP middleware, observers, CORS, OpenAPI generation, a Next.js adapter, request-scoped helpers, and production `build`/`start` tooling * **New**: The v2 views runtime adds typed `ToolRef`/`useCallTool` registration, file-based views, external or inline assets, shared React runtime handling, and managed Inspector integration * **Enhancement** (@mcp-use/cli): the CLI becomes ESM, adds `client connect --negotiate`, automatic client SDK installation, `mcp-use typecheck`, device-code login, and production tunneling * **Enhancement** (create-mcp-use-app): v2 templates use `mcp-server`, `views/`, `mcp-env.d.ts`, Bun-aware installs, and opt-in source maps while retaining the `starter` template as a deprecated alias * **Enhancement** (@mcp-use/inspector): the v2 Inspector adds project-pinned relay/OAuth tooling, hosted and local chat, immutable CDN assets, and MCP Apps/fullscreen improvements; see the Inspector changelog * **Update**: Updated @mcp-use/inspector to v20.0.0 * **Update**: Updated @mcp-use/cli to v4.0.0 * **Update**: Updated create-mcp-use-app to v2.0.0 # Authentication Source: https://docs.mcp-use.com/v2/typescript/client/authentication OAuth and bearer tokens for MCP client connections HTTP connections support automatic OAuth, pre-registered public clients, bearer tokens, custom headers, and custom authentication providers. ## Automatic OAuth with `MCPClient` `MCPClient` creates an OAuth provider for an HTTP server unless the server configuration already supplies an `authProvider`, `authToken`, `oauth: false`, or an `Authorization` header. ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { demo: { url: "https://api.example.com/mcp" }, }, }); try { await client.connect("demo"); } finally { await client.close(); } ``` In Node.js, the default provider opens a browser and waits for its loopback callback. In the browser build, the default provider opens a popup; set `useRedirectFlow: true` inside the server's `oauth` options to use a full-page redirect. Pass a custom `authProvider` when your application owns the authorization flow. ## Whole-server and mixed OAuth Whole-server OAuth rejects the MCP connection until the user authorizes. A mixed-auth server instead allows anonymous connection and public operations, then requires OAuth only for protected tools, resources, or prompts. When a successfully connected server publishes [RFC 9728 protected-resource metadata](https://www.rfc-editor.org/rfc/rfc9728.html), `MCPClient` exposes it as mixed auth without forcing authorization: ```typescript theme={null} const connection = await client.connect("demo"); const authorization = await connection.discoverAuthorization(); if (authorization?.mode === "mixed" && !authorization.authenticated) { console.log("Public operations are available without signing in."); // Optional: authenticate now instead of waiting for a protected operation. await connection.authenticate(); } ``` After discovery, `connection.authorization` and `connection.info.authorization` expose the same state. It includes `resource` and `scopesSupported` when the protected-resource metadata advertises them. Mixed-auth discovery is best-effort and defaults to enabled for HTTP servers with an OAuth provider. Call `discoverAuthorization()` when using `MCPClient` directly; React performs the same discovery after publishing the ready connection. Set `detectMixedAuth: false` on the server configuration to skip the discovery request. If the client stays anonymous, a later wire-level OAuth challenge from a protected operation starts the official SDK flow. Automatic flows finish OAuth through the active transport and retry the logical operation once. Explicit browser flows surface the prepared authentication action so the host can authenticate and retry. MCP tool results with `isError: true` or auth-like text are application errors, not OAuth challenges. ## React: explicit authentication React connection APIs use an explicit authorization step by default. `preventAutoAuth` defaults to `true`, so an unauthorized connection enters `pending_auth` until the user calls `authenticate()`. ```tsx theme={null} import { useMcp } from "@mcp-use/client/react"; export function ProtectedConnection() { const mcp = useMcp({ url: "https://api.example.com/mcp", }); if (mcp.state === "pending_auth") { return ; } if ( mcp.authorization?.mode === "mixed" && !mcp.authorization.authenticated ) { return ( <>

Public tools are available. Sign in to use protected tools.

); } return

Connection state: {mcp.state}

; } ``` Set `preventAutoAuth: false` on `useMcp` or a `McpClientProvider` server configuration to start authorization automatically. Popup mode is the default; set the top-level React option `useRedirectFlow: true` for a full-page redirect. On your callback route, import `onMcpAuthorization` from `@mcp-use/client/react`. See [React integration](/v2/typescript/client/usemcp#oauth-callback). To show the authorized account, set `oauth.fetchUserInfo: true` and read `mcp.userInfo`. Its status is `idle`, `loading`, `available`, `unavailable`, or `error`; claims such as `email` are present only when released by the authorization server. You can also fetch explicitly: ```tsx theme={null} const result = await mcp.getUserInfo(); if (result.status === "available") console.log(result.claims.email); ``` See [OAuth UserInfo](/v2/typescript/client/usemcp#oauth-userinfo) for the options, state details, and a React example. ## Pre-registered clients The `MCPClient` configuration uses `oauth.staticClientInfo.client_id`: ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { slack: { url: "https://mcp.example.com/mcp", oauth: { staticClientInfo: { client_id: "my-client-id", }, clientMetadataUrl: "https://app.example.com/.well-known/oauth-client-metadata.json", scope: "openid profile", }, }, }, }); ``` React uses a different, UI-oriented shape: ```tsx theme={null} import { useMcp } from "@mcp-use/client/react"; const mcp = useMcp({ url: "https://mcp.example.com/mcp", oauth: { clientId: "my-client-id", clientMetadataUrl: "https://app.example.com/.well-known/oauth-client-metadata.json", scope: "openid profile", }, }); ``` Browser OAuth clients are public PKCE clients. Do not put a `client_secret` in browser configuration; `BrowserOAuthClientProvider` rejects one in `staticClientInfo`. ## OAuth proxy in the browser Use an OAuth proxy when the authorization server's metadata, token, or registration endpoints do not support browser CORS: ```tsx theme={null} import { useMcp } from "@mcp-use/client/react"; const mcp = useMcp({ url: "https://mcp.example.com/mcp", oauthProxyUrl: "https://app.example.com/api/mcp-oauth", }); ``` For the browser `MCPClient`, `oauth.oauthProxyUrl` configures the proxy and `oauth.proxyOAuthRequests` controls whether OAuth HTTP requests use it. The latter defaults to `true` when the browser provider is created. React routes its OAuth requests through the configured `oauthProxyUrl`; it does not expose `proxyOAuthRequests` as a `useMcp` option. ## Manual browser authorization Construct a `BrowserOAuthClientProvider` with `preventAutoAuth: true` and pass it to the browser client when you need to present the authorization URL yourself. Set `useRedirectFlow: true` when you navigate the current page to that URL: ```typescript theme={null} import { BrowserOAuthClientProvider, isUnauthorized, MCPClient, } from "@mcp-use/client"; const authProvider = new BrowserOAuthClientProvider( "https://api.example.com/mcp", { preventAutoAuth: true, useRedirectFlow: true } ); const client = new MCPClient({ mcpServers: { api: { url: "https://api.example.com/mcp", authProvider, }, }, }); try { await client.connect("api"); } catch (error) { if (!isUnauthorized(error)) throw error; const authorizationUrl = authProvider.getLastAttemptedAuthUrl(); if (authorizationUrl) { window.location.assign(authorizationUrl); } } ``` `getLastAttemptedAuthUrl()` returns the URL for the current provider instance. It is kept in memory only, so start a new authorization attempt after a page reload. The auto-provisioned browser provider also accepts `oauth.preventAutoAuth`, but an explicit provider gives your application access to the prepared URL. The provider records the flow type when it prepares the URL. With `useRedirectFlow: true`, the callback page that calls `onMcpAuthorization()` returns to the page that started authorization. Without it, the callback treats the navigation as a popup and leaves the user on the callback page. ## Bearer tokens ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { api: { url: "https://api.example.com/mcp", authToken: process.env.API_KEY, }, }, }); ``` An explicit `Authorization` header also disables automatic OAuth: ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { api: { url: "https://api.example.com/mcp", headers: { Authorization: `Bearer ${process.env.API_KEY}`, }, }, }, }); ``` ## `MCPClient` server fields | Field | Description | | - | - | | `authToken` | Bearer token | | `headers` | Custom HTTP headers | | `oauth` | Automatic OAuth options, or `false` to disable automatic OAuth | | `authProvider` | Custom SDK-compatible provider | | `detectMixedAuth` | Discover optional mixed OAuth after anonymous connection; defaults to `true` | ## Node OAuth helpers ```typescript theme={null} import { createOAuthProvider, NodeOAuthClientProvider, completeOAuthFlow, isUnauthorized, FileKVStore, } from "@mcp-use/client"; ``` Use these exports for headless scripts, custom storage, or an authorization flow you manage directly. # Code Mode Source: https://docs.mcp-use.com/v2/typescript/client/code-mode Let agents write code to call MCP tools Code mode exposes `execute_code` and `search_tools` so agents run JavaScript with access to connected MCP tools instead of making individual tool calls. Node.js only. ## Enable ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient( { mcpServers: { fs: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "./data"], }, }, }, { codeMode: true }, ); const result = await client.executeCode(` const files = await fs.list_directory({ path: "." }); return files.length; `); console.log(result.result, result.logs, result.error); await client.close(); ``` ## Executors | Executor | Use case | | - | - | | `"vm"` (default) | Local Node.js VM — fast, trusted environments | | `"e2b"` | Cloud sandbox — untrusted code (`@e2b/code-interpreter` + API key) | | Custom function / `BaseCodeExecutor` | Your own runtime | ```typescript theme={null} { codeMode: { enabled: true, executor: "e2b", executorOptions: { apiKey: process.env.E2B_API_KEY!, timeoutMs: 300_000 }, }} ``` A custom function receives `(code, timeout?)` and returns an `ExecutionResult`. It owns cleanup for whatever runtime it wraps — `client.close()` does not release anything on its behalf. A non-arrow function is invoked with the `MCPClient` as its `this`, so it can reach the client without closing over it: ```typescript theme={null} { codeMode: { enabled: true, executor: async function (this: MCPClient, code, timeout) { const servers = this.getServerNames(); return { result: await myRuntime.run(code, timeout, servers), logs: [], error: null, execution_time: 0, }; }, }} ``` ## Agent integration Use with `@mcp-use/agent` and `PROMPTS.CODE_MODE`: ```typescript theme={null} import { MCPAgent, PROMPTS } from "@mcp-use/agent"; const agent = new MCPAgent({ llm, client, systemPrompt: PROMPTS.CODE_MODE }); await agent.run("List all files and count them"); ``` ## Reference [Client API reference](https://mcp-use-typescript-api-reference.vercel.app/modules/_mcp-use_client.index.html) — config types, `searchTools`, and `ExecutionResult`. [Anthropic: Code execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp) # Completions Source: https://docs.mcp-use.com/v2/typescript/client/completion Autocomplete for prompt and resource template arguments Request suggestions for prompt arguments or resource template URI variables: ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { demo: { url: "http://localhost:3000/mcp" } }, }); try { const conn = await client.connect("demo"); const result = await conn.complete({ ref: { type: "ref/prompt", name: "code-review" }, argument: { name: "language", value: "py" }, }); console.log(result.completion.values); // e.g. ["python", "pytorch"] } finally { await client.close(); } ``` ## React ```tsx theme={null} const mcp = useMcp({ url: "http://localhost:3000/mcp" }); const result = await mcp.complete({ ref: { type: "ref/resource", uri: "file:///{path}" }, argument: { name: "path", value: "/tmp" }, }); ``` ## Reference [`MCPConnection`](https://mcp-use-typescript-api-reference.vercel.app/modules/_mcp-use_client.index.html#mcpconnection) — `complete()`. # Elicitation Source: https://docs.mcp-use.com/v2/typescript/client/elicitation Handle interactive user input requests from MCP servers Servers can ask the client for user input mid-tool-call via `elicitation/create`. Two modes: * **Form** — structured fields with a JSON schema * **URL** — redirect the user to an external page (required for credentials/OAuth) ## Setup ```typescript theme={null} import { stdin, stdout } from "node:process"; import { createInterface } from "node:readline/promises"; import { acceptWithDefaults, MCPClient, type OnElicitationCallback, } from "@mcp-use/client"; const onElicitation: OnElicitationCallback = async (params) => { if (params.mode === "url") { // The tool call continues as soon as this returns, so accept only after // the user has finished the external flow. console.log(`Visit: ${params.url}`); const prompt = createInterface({ input: stdin, output: stdout }); await prompt.question("Press Enter after you finish in the browser. "); prompt.close(); return { action: "accept" }; } // Form mode — collect fields from params.requestedSchema return acceptWithDefaults(params); }; const client = new MCPClient( { mcpServers: { demo: { url: "http://localhost:3000/mcp" } } }, { onElicitation }, ); ``` The second constructor argument is available only in the Node.js entry. In a browser build, set `onElicitation` at the top level of the configuration or on an individual server configuration instead. ## Helpers These helpers are exported only by the Node.js entry of `@mcp-use/client`. The browser entry and `@mcp-use/client/react` do not export them. | Helper | Purpose | | - | - | | `acceptWithDefaults(params)` | Accept using schema defaults | | `accept(content)` | Accept with user content | | `decline()`, `cancel()` | Reject or dismiss | | `validate(params, content)` | Client-side validation | | `getDefaults`, `applyDefaults` | Work with schema defaults | ## React The helpers above are not available in a browser build, so handle the request directly. This handler waits for the user to finish a URL request and accepts form requests with their schema defaults: ```tsx theme={null} import { useMcp, type ElicitResult } from "@mcp-use/client/react"; const mcp = useMcp({ url: "http://localhost:3000/mcp", onElicitation: async (params): Promise => { if (params.mode === "url") { window.open(params.url, "_blank", "noopener"); // The tool call continues as soon as this resolves, so accept only // after the user confirms they finished the external flow. const finished = window.confirm( `${params.message}\n\nSelect OK after you finish in the new tab.` ); return { action: finished ? "accept" : "cancel" }; } const content: NonNullable = {}; for (const [name, field] of Object.entries( params.requestedSchema.properties )) { if (field.default !== undefined) content[name] = field.default; } return { action: "accept", content }; }, }); ``` With the provider, use `pendingElicitationRequests` and `approveElicitation` / `rejectElicitation`. Without an `onElicitation` handler, tool calls that require input will fail. ## Reference Server-side: [Elicitation](/v2/typescript/server/elicitation) # Environments Source: https://docs.mcp-use.com/v2/typescript/client/environments Use the MCP client in Node.js, browser, and React The root `@mcp-use/client` import uses package conditions to select its runtime implementation. Node gets the Node entry; browsers and other default environments get the browser-safe entry. React connection management is available from a separate entry point. | Environment | Import | HTTP | Stdio | Config files | Code Mode | | - | - | - | - | - | - | | Node.js `>=22.22.2` | `@mcp-use/client` | Yes | Yes | Yes | Yes | | Browser | `@mcp-use/client` | Yes | No | No | No | | React | `@mcp-use/client/react` | Yes | No | No | No | ## Node.js The Node entry includes HTTP and stdio transports, filesystem configuration, Code Mode, and Node OAuth helpers. ```typescript theme={null} import { MCPClient, loadConfigFile } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { api: { url: "https://api.example.com/mcp" }, fs: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"], }, }, }); const clientFromFile = new MCPClient(loadConfigFile("./mcp-config.json")); try { const connections = await client.connectAll(); await connections.api.callTool("ping", {}); } finally { await Promise.all([client.close(), clientFromFile.close()]); } ``` ## Browser The browser entry exposes the HTTP connection API and browser OAuth support. It does not include process spawning, filesystem configuration, or local code execution. ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { api: { url: "https://api.example.com/mcp" }, }, }); try { const connection = await client.connect("api"); await connection.callTool("tool", {}); } finally { await client.close(); } ``` > [!WARNING] > > Do not hardcode secrets in browser bundles. Use OAuth or a backend proxy. ## React Install the client and your application's supported React version: ```bash theme={null} npm install @mcp-use/client react ``` `@mcp-use/client/react` provides connection-management APIs such as `useMcp`, `McpClientProvider`, `useMcpClient`, and `useMcpServer`. It also exports `ViewRenderer` for hosts that render an MCP App View. Code running inside a View uses the View APIs from `mcp-use/react`, including `useToolContext`, `useCallTool`, and `useViewState`. These hooks communicate with the host; they do not create or manage MCP server connections. See [React integration](/v2/typescript/client/usemcp) for connection setup and [MCP Apps](/v2/typescript/mcp-apps) for building and hosting Views. # MCP Client Source: https://docs.mcp-use.com/v2/typescript/client/index Connect a TypeScript app to MCP servers and call tools, resources, and prompts. `@mcp-use/client` connects your app to one or more MCP servers. By default, HTTP connections negotiate the server's supported MCP protocol automatically and stdio connections use the sessionful protocol; set `protocolNegotiation` to override either default. The same connection API works across sessionful and sessionless servers. ## Install ```bash theme={null} npm install @mcp-use/client ``` The package requires Node.js `>=22.22.2` for Node applications and is ESM-only. ## Quick start ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { demo: { url: "http://localhost:3000/mcp" }, }, }); try { const connection = await client.connect("demo"); const tools = await connection.listTools(); console.log(tools.map((tool) => tool.name)); const result = await connection.callTool("echo", { message: "hello" }); const text = result.content.find((block) => block.type === "text"); if (text?.type === "text") { console.log(text.text); } } finally { await client.close(); } ``` `connect(name)` returns a ready `MCPConnection`. Always close the client when your application is finished so its active connections and transports are released. ## Core types * **`MCPClient`** — holds server configuration and opens connections. * **`MCPConnection`** — calls tools, reads resources, and fetches prompts. `connection.info` exposes the negotiated protocol, server metadata, capabilities, and instructions. * **`MCPSession`** — deprecated compatibility alias for `MCPConnection`. Use `client.connect(name)` for one configured server or `client.connectAll()` to connect to every configured server. ## Configure servers ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { remote: { url: "https://api.example.com/mcp", authToken: process.env.MCP_TOKEN, }, local: { command: "npx", args: ["-y", "@modelcontextprotocol/server-filesystem", "./"], }, }, }); ``` HTTP servers support automatic OAuth, bearer tokens, and custom headers. Stdio connections are available only in Node.js. Migrating existing client code? Follow the [client migration guide](/v2/typescript/client/migration). ## Next steps > **[Tools](/v2/typescript/client/tools)** > > List and call server tools. > **[Migration guide](/v2/typescript/client/migration)** > > Update packages, imports, configuration, and connection code. > **[Authentication](/v2/typescript/client/authentication)** > > Configure OAuth and bearer tokens. > **[React](/v2/typescript/client/usemcp)** > > Manage connections with `McpClientProvider` and hooks. > **[Environments](/v2/typescript/client/environments)** > > Compare Node, browser, and React support. # Migrate to v2 Source: https://docs.mcp-use.com/v2/typescript/client/migration Migrate client, agent, and React connection code from mcp-use 1.x This guide updates applications from the mcp-use 1.x client surface to the v2 packages. It covers client, agent, and React connection code. > [!WARNING] > > Server and interactive UI APIs also have breaking changes. Do not assume that > existing server or widget code can be carried forward unchanged. Follow the > [server guide](/v2/typescript/server) and > [MCP Apps guide](/v2/typescript/mcp-apps) for those parts of your application. ## 1. Update the runtime and packages The current client and agent packages require Node.js `>=22.22.2` and are ESM-only. ```bash theme={null} npm install @mcp-use/client @mcp-use/agent ``` Install `mcp-use` when the same project builds a server or MCP App View: ```bash theme={null} npm install mcp-use ``` Ensure your project emits ESM and your bundler respects the package's `node` and `browser` export conditions. ## 2. Move imports to their package entry points | 1.x surface | Current import | Purpose | | - | - | - | | `MCPClient`, connectors, OAuth, and sessions from `mcp-use` | `@mcp-use/client` | Node or browser MCP client | | `useMcp` and `McpClientProvider` from `mcp-use/react` | `@mcp-use/client/react` | React connection management | | `MCPAgent` and `PROMPTS` from `mcp-use` | `@mcp-use/agent` | Native agent | | LangChain agent compatibility and `ServerManager` | `@mcp-use/agent/langchain` | Optional LangChain integration | | Widget hooks such as `useWidget` (removed) | `mcp-use/react` View hooks | Code running inside MCP App Views | | `MCPServer` and server capabilities | `mcp-use` | MCP server | ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; import { MCPAgent, PROMPTS } from "@mcp-use/agent"; ``` For the optional LangChain compatibility layer: ```typescript theme={null} import { LangChainMCPAgent, ServerManager, } from "@mcp-use/agent/langchain"; ``` The native `MCPAgent` and the LangChain compatibility agent are separate public entry points. Import `ServerManager` only from the LangChain entry. ### Removed client subpaths The client package exports its conditional root, the `./react` entry, and a `./sandbox` entry for the MCP Apps sandbox proxy document. Replace these removed imports: | Removed import | Use instead | | - | - | | `@mcp-use/client/browser` | `@mcp-use/client` in a browser build | | `@mcp-use/client/auth` | `@mcp-use/client` | | `@mcp-use/client/auth/node` | Node OAuth helpers from `@mcp-use/client` | The root entry resolves to the Node build under the `node` condition and to the browser-safe build under the `browser` or default condition. ## 3. Update the connection API Use `connect()` and `connectAll()`: ```typescript theme={null} import { MCPClient, type MCPConnection, } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { demo: { url: "https://api.example.com/mcp" }, }, }); try { const connection: MCPConnection = await client.connect("demo"); await connection.callTool("echo", { message: "hello" }); } finally { await client.close(); } ``` `createSession()` and `createAllSessions()` remain as deprecated compatibility aliases. `MCPSession` is a deprecated runtime and type alias for `MCPConnection`. Every connection exposes the negotiated server information: ```typescript theme={null} console.log(connection.info.protocolEra); console.log(connection.info.protocolVersion); console.log(connection.info.capabilities); console.log(connection.info.instructions); ``` ## 4. Configure protocol negotiation The public configuration field is `protocolNegotiation`, not `versionNegotiation`. HTTP connections default to `protocolNegotiation: "auto"`: they probe the sessionless protocol and fall back to the sessionful protocol. Stdio defaults to `"legacy"` to avoid probing a process that may be launched for one invocation. ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { compatible: { url: "https://api.example.com/mcp", protocolNegotiation: "auto", }, }, }); ``` The accepted values are `"auto"`, `"legacy"`, and `{ pin: "2026-07-28" }`. There is no `"modern"` value; pin the modern protocol version to use the sessionless protocol without fallback. The client CLI exposes the same choices as `--protocol auto`, `legacy`, and `modern`. Its `modern` mode uses `{ pin: "2026-07-28" }`: ```bash theme={null} mcp-use client connect demo https://api.example.com/mcp --protocol auto mcp-use client connect legacy https://legacy.example.com/mcp --protocol legacy mcp-use client connect modern https://modern.example.com/mcp --protocol modern ``` There is no `--negotiate` flag. ## 5. Rename client configuration Search your client configuration for the removed 1.x names and update them: | 1.x name | Current name | | - | - | | `samplingCallback` | `onSampling` | | `elicitationCallback` | `onElicitation` | | `auth_token` | `authToken` | | `customHeaders` | `headers` | | `clientConfig` | `clientInfo` | | `debug` | `logLevel` on `useMcp` | | `BrowserTelemetry` | `Telemetry` | | `ResourceTemplate` client type | `ResourceTemplateType` | `MCPClient` has no `logLevel` option. Set `MCP_USE_LOG_LEVEL` (for example `debug`; `DEBUG=2` also works) in the environment, or assign `logger.level` on the `logger` exported by `@mcp-use/client`. Sampling, elicitation, and notification callbacks can be set as global client defaults or on an individual server configuration. Per-server callbacks take precedence. ## 6. Update authentication behavior `MCPClient` automatically creates an OAuth provider for HTTP servers that do not already configure an `authProvider`, `authToken`, `oauth: false`, or an `Authorization` header. * Node OAuth opens a browser and waits for its loopback callback. * The browser root client opens a popup by default and can use a redirect. * `useMcp` and `McpClientProvider` default to `preventAutoAuth: true`. Handle `pending_auth` and call `authenticate()`. ```tsx theme={null} import { useMcpServer } from "@mcp-use/client/react"; export function ServerAuth() { const server = useMcpServer("demo"); if (server?.state === "pending_auth") { return ( ); } return null; } ``` For a React OAuth callback route, import `onMcpAuthorization` from `@mcp-use/client/react`. A non-React browser build can use the browser conditional root export. Pre-registered clients also have different configuration shapes: * `MCPClient`: `oauth.staticClientInfo.client_id` * React: `oauth.clientId` See [Authentication](/v2/typescript/client/authentication) for complete Node, browser, React, proxy, and public-client examples. ## 7. Update React connection code and Views Move connection management to `@mcp-use/client/react`: | 1.x usage | Current usage | | - | - | | `useMcp` from `mcp-use/react` | `useMcp` from `@mcp-use/client/react` | | `McpServerOptions` | `McpServerConfig` (`McpServerOptions` is deprecated) | | Server config `name` used as a display label | `displayName` | | Displayed `server.name` | Negotiated `server.serverInfo?.name` | `@mcp-use/client/react` also exports `ViewRenderer` for a host application that renders MCP App Views. Code running inside a View stays in `mcp-use/react`, but must use focused View hooks such as `useToolContext`, `useCallTool`, and `useViewState`. The widget hooks `useWidget`, `useWidgetProps`, and `useWidgetState` were removed; see the [server migration guide](/v2/typescript/server/migration) for their replacements. ## 8. Replace removed low-level exports The client root no longer re-exports the old Zod `*Schema` constants or `JSONSchemaToZod`. * Import protocol types from `@modelcontextprotocol/client`. * Use `ResourceTemplateType` for the protocol resource-template type. * Use Zod 4's `z.fromJSONSchema()` when you need to convert JSON Schema. The current telemetry implementation does not bundle the PostHog browser or Node SDKs. If you used the old telemetry override, note that `telFetch` is now a non-throwing `(url, init) => Promise` helper. Do not remove `@modelcontextprotocol/ext-apps` based on the old migration notes; the current client still uses it for MCP Apps bridging. ## 9. Review server and MCP App changes The server is now built around the root `mcp-use` entry, a stateless `MCPServer`, and standard protocol result envelopes. Review tool, resource, prompt, middleware, authentication, and deployment APIs against the [server guide](/v2/typescript/server). Interactive results use MCP Apps Views. Bind a View to a tool, return model-facing `content` and View props in `structuredContent`, and consume the result with focused hooks such as `useToolContext`. The widget hooks were removed; the deprecated `widget()` response helper remains only for compatibility. Follow the [MCP Apps guide](/v2/typescript/mcp-apps) before updating interactive UI code. ## 10. Check Inspector callback URLs The standalone Inspector OAuth callback resolves relative to the configured Inspector base path. With the normal `/inspector` base, the callback is `/inspector/oauth/callback`; deployments under another base use that base's `/oauth/callback`. If you run a custom OAuth proxy, continue to bind upstream targets to SDK-discovered metadata. The Inspector proxy rejects arbitrary upstream target URLs. ## Migration checklist **1. Update the runtime and packages** Use Node.js `>=22.22.2`, install the v2 packages, and confirm ESM output. **2. Fix imports** Search for client and agent imports from `mcp-use`, removed `@mcp-use/client/*` subpaths, and connection hooks from `mcp-use/react`. **3. Separate native and LangChain agents** Keep `MCPAgent` and `PROMPTS` on `@mcp-use/agent`; move `ServerManager` and LangChain compatibility imports to `@mcp-use/agent/langchain`. **4. Rename configuration** Search for `versionNegotiation`, `samplingCallback`, `elicitationCallback`, `auth_token`, `customHeaders`, `clientConfig`, and `debug`. **5. Use the connection API** Replace `createSession` and `createAllSessions` calls with `connect` and `connectAll`; replace `MCPSession` annotations with `MCPConnection`. **6. Update OAuth UI** Handle React's `pending_auth` state, use the correct pre-registered client shape for each API, and verify callback and proxy URLs. **7. Update Views** Separate React connection management from code that runs inside an MCP App View, then replace the removed widget hooks with View hooks. **8. Verify each environment** Type-check Node, browser, and React entry points independently, then connect to one sessionful and one sessionless server if your application supports both. ## Related * [Client overview](/v2/typescript/client/index) * [Authentication](/v2/typescript/client/authentication) * [React integration](/v2/typescript/client/usemcp) * [Server guide](/v2/typescript/server) * [MCP Apps guide](/v2/typescript/mcp-apps) # Notifications Source: https://docs.mcp-use.com/v2/typescript/client/notifications Handle one-way updates from MCP servers MCP notifications are one-way JSON-RPC messages with no response. Register a handler when your application needs to react to server updates. ## Receive server notifications Set a default handler on the client: ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { demo: { url: "http://localhost:3000/mcp" }, }, onNotification: async (notification) => { console.log(notification.method, notification.params); }, }); ``` An individual server configuration can provide its own `onNotification` callback. Per-server callbacks take precedence over the global default. You can also register a handler on a connection: ```typescript theme={null} const connection = await client.connect("demo"); connection.on("notification", async (notification) => { if (notification.method === "notifications/tools/list_changed") { await connection.listTools(); } }); ``` The standard list-change method names are: * `notifications/tools/list_changed` * `notifications/resources/list_changed` * `notifications/prompts/list_changed` The client automatically refreshes its tool cache for tool list changes. Refresh resources or prompts when your application needs their updated values. ## React Each server managed by `McpClientProvider` exposes: * `notifications`, the stored notification entries * `unreadNotificationCount` * `markNotificationRead`, `markAllNotificationsRead`, and `clearNotifications` Set `onNotificationReceived` on a server configuration to run custom logic when the provider receives and stores a notification. ## Roots compatibility `setRoots()` and `getRoots()` are compatibility APIs for sessionful servers. Roots are not part of the current sessionless protocol. For a compatible server, pass initial roots in its client configuration: ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { legacy: { url: "http://localhost:3000/mcp", roots: [{ uri: "file:///home/user/project", name: "Project" }], }, }, }); ``` Calling `connection.setRoots(roots)` replaces the cached roots and sends `notifications/roots/list_changed` when connected. `connection.getRoots()` returns the current cached list. Use these methods only for a server that negotiated the sessionful protocol and requests roots. ## Related Server-side notification sending is covered in [Notifications](/v2/typescript/server/notifications). # Prompts Source: https://docs.mcp-use.com/v2/typescript/client/prompts Fetch server-defined prompt templates Prompts are server-defined message templates. List the available prompts, then request one by name with its arguments. ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { demo: { url: "http://localhost:3000/mcp" }, }, }); try { const connection = await client.connect("demo"); const { prompts } = await connection.listPrompts(); for (const prompt of prompts) { console.log(prompt.name, prompt.description); } const result = await connection.getPrompt("plan_trip", { destination: "Japan", days: "7", }); console.log(result.description); for (const message of result.messages) { if (message.content.type === "text") { console.log(message.role, message.content.text); } } } finally { await client.close(); } ``` `listPrompts()` returns `{ prompts }`. `getPrompt(name, args)` returns a prompt result with an optional `description` and a `messages` array. Each message has a `role` and one MCP content block. ## React ```tsx theme={null} import { useMcpServer } from "@mcp-use/client/react"; export function LoadPromptButton() { const server = useMcpServer("demo"); async function handleLoad() { if (server?.state !== "ready") return; const result = await server.getPrompt("code_review", { language: "ts", }); console.log(result.messages); } return ( ); } ``` The React `getPrompt` arguments are optional and use string values. ## Reference [`MCPConnection`](https://mcp-use-typescript-api-reference.vercel.app/modules/_mcp-use_client.index.html#mcpconnection) — `listPrompts` and `getPrompt`. # Resources Source: https://docs.mcp-use.com/v2/typescript/client/resources List and read MCP server resources Resources are URI-addressed content exposed by MCP servers. ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { demo: { url: "http://localhost:3000/mcp" }, }, }); try { const connection = await client.connect("demo"); const { resources } = await connection.listAllResources(); for (const resource of resources) { console.log(resource.uri, resource.name, resource.mimeType); } const result = await connection.readResource("file:///config.json"); for (const content of result.contents) { if ("text" in content) { console.log(content.text); } } } finally { await client.close(); } ``` Use `listAllResources()` when you want the complete resource list. It follows pagination cursors for you and returns `{ resources }`. ## Paginate resources `listResources(cursor?)` returns an envelope with `resources` and an optional `nextCursor`. Handle the cursor yourself when you want to process one page at a time: ```typescript theme={null} import type { MCPConnection } from "@mcp-use/client"; async function logResourcePages(connection: MCPConnection): Promise { let cursor: string | undefined; do { const page = await connection.listResources(cursor); for (const resource of page.resources) { console.log(resource.uri); } cursor = page.nextCursor; } while (cursor); } ``` ## Resource templates Parameterized URIs such as `db://users/{id}` are discovered with `listResourceTemplates()`. Its result contains `resourceTemplates` and may contain `nextCursor`. The current `MCPConnection` method retrieves the first template page and does not accept a cursor argument. ```typescript theme={null} const page = await connection.listResourceTemplates(); for (const template of page.resourceTemplates) { console.log(template.uriTemplate, template.name); } ``` Resolve a template to a concrete URI in your application, then pass that URI to `readResource(uri)`. ## Subscribe to updates If the server supports resource subscriptions, subscribe and unsubscribe with the same concrete URI: ```typescript theme={null} await connection.subscribeToResource("file:///config.json"); // Receive notifications/resources/updated through your notification handler. await connection.unsubscribeFromResource("file:///config.json"); ``` ## React `useMcpServer` exposes the resource contents envelope returned by `readResource(uri)`: ```tsx theme={null} import { useMcpServer } from "@mcp-use/client/react"; export function ReadResourceButton({ uri }: { uri: string }) { const server = useMcpServer("demo"); async function handleRead() { if (server?.state !== "ready") return; const { contents } = await server.readResource(uri); console.log(contents); } return ( ); } ``` ## Reference [`MCPConnection`](https://mcp-use-typescript-api-reference.vercel.app/modules/_mcp-use_client.index.html#mcpconnection) — `listResources`, `listAllResources`, `listResourceTemplates`, `readResource`, `subscribeToResource`, and `unsubscribeFromResource`. # Sampling compatibility Source: https://docs.mcp-use.com/v2/typescript/client/sampling Handle sampling requests from compatible MCP server flows Sampling is a compatibility capability, not a primary capability of the current sessionless MCP protocol. Configure it only when a server flow requires the client to provide model output. The client can invoke `onSampling` in two cases: * A legacy sessionful server sends a `sampling/createMessage` request. * A sessionless server enters the temporary `input_required` multi-round-trip compatibility flow. Sampling is deprecated by the current sessionless protocol. Prefer server and tool designs that do not depend on client-provided sampling when you control both sides. ## Handle a request ```typescript theme={null} import { MCPClient, type OnSamplingCallback, type SamplingCreateMessageParams, } from "@mcp-use/client"; async function completeWithModel( params: SamplingCreateMessageParams ): Promise { // Send params.messages and the other sampling constraints to your model. throw new Error(`Connect a model for ${params.messages.length} messages`); } const onSampling: OnSamplingCallback = async (params) => { const text = await completeWithModel(params); return { role: "assistant", content: { type: "text", text }, model: "your-model", stopReason: "endTurn", }; }; const client = new MCPClient({ mcpServers: { demo: { url: "http://localhost:3000/mcp", onSampling, }, }, }); try { await client.connect("demo"); // A compatible server flow can now call onSampling. } finally { await client.close(); } ``` `OnSamplingCallback` receives the protocol parameters for `sampling/createMessage` and must return a `SamplingCreateMessageResult`. Setting the callback also advertises the sampling capability where the negotiated protocol supports it. ## Global and per-server handlers Set `onSampling` at the top level of the `MCPClient` configuration to use it as a global default. An `onSampling` callback on an individual server configuration takes precedence over that default. The Node client also accepts the global callback in its second constructor argument. ## React `useMcp({ onSampling })` handles compatible requests directly with your callback. `McpClientProvider` instead installs a handler that queues each request on the managed server: * `server.pendingSamplingRequests` contains the requests awaiting a decision. * `server.approveSampling(requestId, result)` resolves a request with a complete `SamplingCreateMessageResult`. * `server.rejectSampling(requestId, error?)` rejects it. * `onSamplingRequest` on the server configuration can notify your UI when a request is added to the queue. Queued requests remain pending until they are approved, rejected, disconnected, or timed out. ## Runnable example The maintained [sampling client example](https://github.com/mcp-use/mcp-use/blob/main/libraries/typescript/packages/client/examples/node/communication/sampling-client.ts) exercises both the legacy push request and the sessionless `input_required` compatibility flow. # Tools Source: https://docs.mcp-use.com/v2/typescript/client/tools List and call MCP server tools Use a ready `MCPConnection` to list and call tools. ```typescript theme={null} import { MCPClient } from "@mcp-use/client"; const client = new MCPClient({ mcpServers: { demo: { url: "http://localhost:3000/mcp" } }, }); try { const conn = await client.connect("demo"); const tools = await conn.listTools(); for (const tool of tools) { console.log(tool.name, tool.description); } const result = await conn.callTool("read_file", { path: "/tmp/a.txt" }); if (result.isError) { console.error(result.content); } else { for (const block of result.content) { if (block.type === "text") console.log(block.text); } } } finally { await client.close(); } ``` ## Timeouts Pass MCP request options as the third argument: ```typescript theme={null} const abortController = new AbortController(); await conn.callTool( "long_task", { input: "data" }, { timeout: 300_000, resetTimeoutOnProgress: true, maxTotalTimeout: 900_000, signal: abortController.signal, }, ); ``` ## Lazy connect ```typescript theme={null} let conn = client.getSession("demo"); if (!conn) conn = await client.connect("demo"); await conn.callTool("echo", { message: "hello" }); ``` `getSession` returns `null` when not connected. `requireSession` throws. ## Reference [`MCPConnection`](https://mcp-use-typescript-api-reference.vercel.app/modules/_mcp-use_client.index.html#mcpconnection) — `listTools`, `callTool`, and request options. # React Integration Source: https://docs.mcp-use.com/v2/typescript/client/usemcp React hooks and providers for MCP client connections Import from `@mcp-use/client/react`: ```typescript theme={null} import { McpClientProvider, useMcpClient, useMcpServer, useMcp, onMcpAuthorization, } from "@mcp-use/client/react"; ``` Use **`McpClientProvider`** for multi-server apps. Use standalone **`useMcp`** only for a single server. ## Provider setup ```tsx theme={null} import { useEffect } from "react"; import { McpClientProvider, useMcpClient, useMcpServer, } from "@mcp-use/client/react"; function App() { return ( ); } function Dashboard() { const { addServer, servers, storageLoaded } = useMcpClient(); useEffect(() => { // Wait for the provider's initial server load before adding servers. if (!storageLoaded) return; addServer("demo", { url: "http://localhost:3000/mcp", displayName: "Demo", }); }, [addServer, storageLoaded]); return servers.map((s) => ); } function ServerPanel({ serverId }: { serverId: string }) { const server = useMcpServer(serverId); if (!server || server.state !== "ready") { return
{server?.state ?? "loading"}…
; } return (

{server.displayName}

{server.tools.length} tools

); } ``` Call `addServer` only after `storageLoaded` is `true`. When the provider finishes its initial load, it replaces its server list with the servers from `storageProvider` and the `mcpServers` prop, if either is set, so a server added earlier is dropped. `addServer` ignores an ID that is already registered. ## Connection states | State | Meaning | | - | - | | `discovering` | Connecting | | `pending_auth` | OAuth required — call `server.authenticate()` | | `authenticating` | OAuth in progress | | `ready` | Connected | | `failed` | Error — call `server.retry()` | OAuth does not auto-start by default (`preventAutoAuth: true`). Show a sign-in button when `state === "pending_auth"`. Mixed auth is reported separately from the connection state. A mixed-auth server remains `ready` because its public operations are usable, while `authorization` describes the optional OAuth state: ```tsx theme={null} function ServerAuth({ serverId }: { serverId: string }) { const server = useMcpServer(serverId); if (!server) return null; const needsOptionalAuth = server.authorization?.mode === "mixed" && !server.authorization.authenticated; return needsOptionalAuth ? (

This server is using mixed auth. Public tools are available.

) : null; } ``` The hook detects mixed auth from RFC 9728 protected-resource metadata after an anonymous connection. Set `detectMixedAuth: false` to disable this best-effort discovery. With the default explicit browser flow, a wire-level OAuth challenge from a protected operation prepares the auth action; call `authenticate()` and retry that operation. Tool-level `isError` results do not trigger OAuth. ## OAuth callback Create a route (default: `/oauth/callback`): ```tsx theme={null} import { onMcpAuthorization } from "@mcp-use/client/react"; import { useEffect } from "react"; export default function OAuthCallback() { useEffect(() => { void onMcpAuthorization(); }, []); return
Completing sign-in…
; } ``` Override with `defaultCallbackUrl` on the provider or `callbackUrl` per server. `McpClientProvider` skips connecting its servers only on a page whose path ends in `/oauth/callback`. A connection attempt on the callback page can replace the in-flight PKCE verifier before `onMcpAuthorization()` exchanges the code. If your callback URL uses a different path, render that route outside `McpClientProvider`. ## Proxy fallback When direct browser connections fail (CORS / FastMCP), retry through a proxy: ```tsx theme={null} ``` MCP traffic and OAuth use separate proxy URLs so resource identity stays the upstream MCP URL. ## Persistence ```tsx theme={null} import { LocalStorageProvider } from "@mcp-use/client/react"; ; ``` Built-in providers persist only non-secret connection settings. Supply bearer tokens, request headers, and proxy headers again at runtime after a reload. Browser OAuth tokens remain persistent by default and are encrypted with AES-256-GCM using a non-extractable origin key stored in IndexedDB. ## Standalone `useMcp` For one server without the provider: ```tsx theme={null} const mcp = useMcp({ url: "http://localhost:3000/mcp" }); if (mcp.state === "pending_auth") { return ; } if (mcp.state !== "ready") return
Connecting…
; return ( <> {mcp.authorization?.mode === "mixed" && !mcp.authorization.authenticated && ( )}
{mcp.tools.map((t) => t.name).join("\n")}
); ``` ## OAuth UserInfo Set `oauth.fetchUserInfo: true` to fetch the authenticated account's UserInfo after the MCP connection becomes ready. The fetch runs independently of the connection; a UserInfo error does not change `mcp.state`. The authorization server must advertise a `userinfo_endpoint`, and the requested scopes must permit the claims you need (often `openid profile email`). ```tsx theme={null} function Account() { const mcp = useMcp({ url: "https://example.com/mcp", oauth: { scope: "openid profile email", fetchUserInfo: true }, }); return (
{mcp.userInfo.status === "available" && (mcp.userInfo.claims.email ?? mcp.userInfo.claims.sub)}
); } ``` `mcp.userInfo` is reactive and has these states: | Status | Meaning | | - | - | | `idle` | No request is in progress. | | `loading` | UserInfo is being fetched. | | `available` | Read `claims` and optional `issuer`; claims such as `email` may be absent. | | `unavailable` | Read `reason`: `not_authenticated`, `no_userinfo_endpoint`, or `session_changed`. | | `error` | Read `error`; call `getUserInfo()` to retry. | Automatic fetching is opt-in and retries an error once after a short delay. You can omit `fetchUserInfo` and call `await mcp.getUserInfo()` whenever you want to fetch the account explicitly; the method returns the same state it publishes to `mcp.userInfo`. ## Types * **`McpServerConfig`** — server options passed to `addServer` (replaces deprecated `McpServerOptions`). * **`displayName`** — your label for the server in UI. * **`serverInfo.name`** — name returned by the server at init. * **`authorization`** — optional mixed-auth metadata with `mode`, `authenticated`, `resource`, and `scopesSupported`. Sampling, elicitation, and notifications are queued on each `McpServer` (`pendingSamplingRequests`, `pendingElicitationRequests`, `notifications`). See [Sampling](/v2/typescript/client/sampling) and [Elicitation](/v2/typescript/client/elicitation). ## Reference [React client API reference](https://mcp-use-typescript-api-reference.vercel.app/modules/_mcp-use_client.react.html) — provider props, hook return values, and storage types. # A2UI Source: https://docs.mcp-use.com/v2/typescript/cookbook/a2ui Let the chat model generate interactive A2UI layouts and render them in an MCP App view. Add a `render-ui` tool that renders model-generated [A2UI](https://a2ui.org/) layouts inside an MCP App. The model writes the component layout and initial data as tool arguments, and the stock A2UI React renderer displays them in the view. The server needs no model API key or agent runtime. The host's chat model generates the tool arguments. ## Try the live example Ask the chat for a UI. Pick a suggestion or describe your own layout, then edit the inputs, sliders, and checkboxes in the result. [A2UI live example: MCP Inspector chat](https://inspector.manufact.com/inspector?embedded=true\&autoConnect=https%3A%2F%2Fmanufact-a2ui-example.run.mcp-use.com%2Fmcp\&embeddedConfig=%7B%22singleTab%22%3Atrue%2C%22defaultTab%22%3A%22chat%22%2C%22visibleTabs%22%3A%5B%22chat%22%5D%2C%22chatHideTitle%22%3Atrue%2C%22chatHideServerUrl%22%3Atrue%2C%22chatQuickQuestions%22%3A%5B%22Make%20an%20interactive%20weekend%20reading%20dashboard%20with%20two%20book%20cards%2C%20a%20reading-goal%20slider%2C%20and%20a%20checklist.%20Let%20me%20edit%20the%20reader%20name.%22%2C%22Build%20a%20packing%20checklist%20for%20a%20three-day%20beach%20trip%2C%20grouped%20into%20essentials%20and%20clothes%2C%20with%20an%20editable%20destination%20and%20a%20travel-style%20selector.%22%5D%7D) [Open the example in a new tab](https://inspector.manufact.com/inspector?embedded=true\&autoConnect=https%3A%2F%2Fmanufact-a2ui-example.run.mcp-use.com%2Fmcp\&embeddedConfig=%7B%22singleTab%22%3Atrue%2C%22defaultTab%22%3A%22chat%22%2C%22visibleTabs%22%3A%5B%22chat%22%5D%2C%22chatHideTitle%22%3Atrue%2C%22chatHideServerUrl%22%3Atrue%2C%22chatQuickQuestions%22%3A%5B%22Make%20an%20interactive%20weekend%20reading%20dashboard%20with%20two%20book%20cards%2C%20a%20reading-goal%20slider%2C%20and%20a%20checklist.%20Let%20me%20edit%20the%20reader%20name.%22%2C%22Build%20a%20packing%20checklist%20for%20a%20three-day%20beach%20trip%2C%20grouped%20into%20essentials%20and%20clothes%2C%20with%20an%20editable%20destination%20and%20a%20travel-style%20selector.%22%5D%7D). ## Prerequisites * A working [mcp-use server](/v2/typescript/getting-started/quickstart) that can build [MCP App views](/v2/typescript/mcp-apps/quickstart). * Node.js 22.22.2 or later. ## Add the integration The integration has three files: | File | Purpose | | - | - | | `views/generative-ui/catalog.ts` | The components the model may use, plus validation shared by the tool and the view | | `index.ts` | Your server entry, which registers the `render-ui` tool that accepts and returns `{ spec }` | | `views/generative-ui/view.tsx` | Converts the spec to A2UI messages and renders `` | ### Install A2UI Install the A2UI React renderer and its core message processor: ```bash theme={null} npm install @a2ui/react@0.11.0 @a2ui/web_core@0.10.7 react react-dom zod ``` A2UI depends on Zod 3, while mcp-use tool schemas use Zod 4. Add an `overrides` block to `package.json` so npm gives the A2UI packages their own Zod 3 copy: ```json package.json theme={null} { "overrides": { "@a2ui/react": { "zod": "3.25.76" }, "@a2ui/web_core": { "zod": "3.25.76" } } } ``` Run `npm install` again after adding the overrides. ### Define the component catalog The catalog is a subset of A2UI's basic catalog: Text, Row, Column, Card, Divider, TextField, CheckBox, Slider, and ChoicePicker. The refinement rejects specs the renderer cannot display, such as duplicate IDs, unreachable components, missing bindings, and initial values of the wrong type. ```typescript views/generative-ui/catalog.ts expandable theme={null} import { z } from "zod"; const id = z .string() .regex(/^[a-zA-Z][\w-]*$/) .max(64); const binding = z.object({ path: z.string().regex(/^\/[\w-]+$/) }); const text = z.union([z.string().max(3000), binding]); const component = z.discriminatedUnion("component", [ z.object({ id, component: z.literal("Text"), text, variant: z .enum(["h1", "h2", "h3", "h4", "h5", "body", "caption"]) .optional(), }), z.object({ id, component: z.literal("Column"), children: z.array(id).max(40), }), z.object({ id, component: z.literal("Row"), children: z.array(id).max(8) }), z.object({ id, component: z.literal("Card"), child: id }), z.object({ id, component: z.literal("Divider") }), z.object({ id, component: z.literal("CheckBox"), label: text, value: binding, }), z.object({ id, component: z.literal("TextField"), label: text, value: binding, variant: z.enum(["shortText", "longText", "number"]).optional(), }), z.object({ id, component: z.literal("Slider"), label: text, value: binding, min: z.number(), max: z.number(), }), z.object({ id, component: z.literal("ChoicePicker"), label: text, value: binding, options: z .array( z.object({ label: z.string().max(3000), value: z.string().max(3000) }) ) .min(1) .max(12), variant: z.enum(["mutuallyExclusive", "multipleSelection"]), }), ]); /** A small subset of A2UI's basic catalog, shared by the tool and view. */ export const specSchema = z .object({ components: z .array(component) .min(1) .max(64) .describe( "A2UI components with unique IDs. The root component must have id 'root'. Layouts reference children by ID." ), data: z .record( z.string(), z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]) ) .describe( "Initial values for every /key binding. CheckBox uses a boolean, Slider a number, TextField a string, ChoicePicker a string array." ), }) .superRefine((spec, ctx) => { const nodes = new Map(spec.components.map((node) => [node.id, node])); const fail = (message: string) => ctx.addIssue({ code: "custom", message }); if (nodes.size !== spec.components.length) fail("Component IDs must be unique."); if (!nodes.has("root")) fail("Include a component with id 'root'."); const visited = new Set(); function visit(key: string, ancestors = new Set()) { if (ancestors.has(key)) { fail(`Circular component reference: ${key}`); return; } if (visited.has(key)) return; const node = nodes.get(key); if (!node) { fail(`Missing component: ${key}`); return; } const path = new Set([...ancestors, key]); for (const child of "children" in node ? node.children : "child" in node ? [node.child] : []) visit(child, path); visited.add(key); } visit("root"); if (visited.size !== nodes.size) fail("All components must be reachable from root."); for (const node of spec.components) { for (const value of Object.values(node)) { if ( value && typeof value === "object" && "path" in value && !Object.hasOwn(spec.data, value.path.slice(1)) ) fail(`Missing initial data for ${value.path}`); } if ("value" in node) { const value = spec.data[node.value.path.slice(1)]; const valid = node.component === "CheckBox" ? typeof value === "boolean" : node.component === "Slider" ? typeof value === "number" && node.min < node.max && value >= node.min && value <= node.max : node.component === "ChoicePicker" ? Array.isArray(value) && value.every((item) => node.options.some((option) => option.value === item) ) && (node.variant !== "mutuallyExclusive" || value.length <= 1) : typeof value === "string"; if (!valid) fail( `Invalid initial value or range for ${node.id} (${node.component}).` ); } } }); /** Validated model-generated A2UI layout and initial data. */ export type UISpec = z.infer; ``` ### Register the tool The tool description is the model's only guide to the catalog, so it lists every component, the binding rules, and a small example. The callback returns the validated spec in `structuredContent`, and `view` attaches the `generative-ui` view to the result. ```typescript index.ts theme={null} import { MCPServer } from "mcp-use"; import { z } from "zod"; import { specSchema } from "./views/generative-ui/catalog.js"; const server = new MCPServer({ name: "a2ui-generative-ui", version: "1.0.0", title: "A2UI Generative UI", description: "Model-generated A2UI layouts rendered inside an MCP App.", legacy: "stateless", }); /** Render the model's A2UI component layout in the attached MCP App. */ export const renderUi = server.tool( { name: "render-ui", title: "Render A2UI", description: `Generate and render an interactive UI using A2UI's basic catalog. Write one structured spec object, not JSONL or a string. You choose the layout and content. Use Text, Row, Column, Card, Divider, TextField, CheckBox, Slider, and ChoicePicker. Put component properties directly alongside id and component (no props wrapper). Start with a Column named root. Refer to children by ID; a Card takes one child. Use Text variants h2/h3/body/caption for hierarchy and Cards for related groups. Bind editable controls with value: {path: "/key"} and put initial values in spec.data. CheckBox values are booleans, Slider values are numbers, TextField values are strings, and ChoicePicker values are arrays of option strings. Text can also bind to /key, so a Text and TextField sharing a binding update together. These controls edit local UI state. Do not invent submit buttons, saving, calculations, network requests, or actions. This example displays the completed response. Example: {"components":[{"id":"root","component":"Column","children":["heading","done"]},{"id":"heading","component":"Text","text":"My checklist","variant":"h2"},{"id":"done","component":"CheckBox","label":"Try A2UI","value":{"path":"/done"}}],"data":{"done":false}}`, inputSchema: z.object({ spec: specSchema }), outputSchema: z.object({ spec: specSchema }), annotations: { readOnlyHint: true, openWorldHint: false }, view: { name: "generative-ui", prefersBorder: false }, }, async ({ spec }) => ({ content: [ { type: "text", text: `Rendered ${spec.components.length} A2UI components.`, }, ], structuredContent: { spec }, }) ); export default server; ``` ### Render the spec in the view The view waits for the completed tool result, then passes three standard A2UI v0.9 messages to a `MessageProcessor`: `createSurface`, `updateComponents`, and `updateDataModel`. `` renders the resulting surface and keeps its bound values in local state. ```tsx views/generative-ui/view.tsx theme={null} import { A2uiSurface, basicCatalog } from "@a2ui/react/v0_9"; import { MessageProcessor } from "@a2ui/web_core/v0_9"; import { ThemeProvider, useToolContext } from "mcp-use/react"; import { useState } from "react"; import type { UISpec } from "./catalog.js"; import "./view.css"; function GeneratedUI({ spec }: { spec: UISpec }) { const [processor] = useState(() => { const instance = new MessageProcessor([basicCatalog]); instance.processMessages([ { version: "v0.9", createSurface: { surfaceId: "ui", catalogId: basicCatalog.id }, }, { version: "v0.9", updateComponents: { surfaceId: "ui", components: spec.components }, }, { version: "v0.9", updateDataModel: { surfaceId: "ui", path: "/", value: spec.data }, }, ]); return instance; }); const surface = processor.model.getSurface("ui"); return surface ? ( ) : (

Unable to render this interface.

); } function Content() { const view = useToolContext<"render-ui">(); if (view.status === "error") return

{view.error.message}

; if (view.status !== "ready") return

Designing your interface…

; return ( ); } /** Render a completed model-generated A2UI spec inside an ordinary MCP App. */ export default function GenerativeUI() { return (
); } ``` Copy [`view.css`](https://github.com/manufacts/mcp-use-a2ui-example/blob/main/views/generative-ui/view.css) from the example for the theme, or remove the `./view.css` import to use A2UI's default styles. ## Try it Start your server: ```bash theme={null} npm run dev ``` Open the Inspector URL printed by the CLI, select **Chat**, and sign in with Manufact or configure a model provider. Try: ```text theme={null} Build a packing checklist for a three-day beach trip, grouped into essentials and clothes, with an editable destination and a travel-style selector. ``` The model calls `render-ui`, and the view appears when the tool result completes. To test without a model, select **Tools → render-ui** and enter: ```json theme={null} { "spec": { "components": [ { "id": "root", "component": "Column", "children": ["heading", "done"] }, { "id": "heading", "component": "Text", "text": "My checklist", "variant": "h2" }, { "id": "done", "component": "CheckBox", "label": "Try A2UI", "value": { "path": "/done" } } ], "data": { "done": false } } } ``` ## Adapt it to your app * **Local state only:** inputs, checkboxes, sliders, and choices edit the view's data model. Components that share a `/key` binding update together. Edits are not sent back to the server and reset when the host recreates the view. * **Add components:** add the A2UI component shape to the `component` union in `catalog.ts`, then describe it in the tool description so the model knows when to use it. * **Add actions:** this recipe has no submit buttons or server actions. To act on user input, call a server tool from the view with [`useCallTool`](/v2/typescript/mcp-apps/interactivity). * **Other hosts:** the view carries its own A2UI renderer, so any MCP Apps host can display it without registering an A2UI catalog. See the [complete A2UI example](https://github.com/manufacts/mcp-use-a2ui-example) for the runnable project and catalog tests, the [A2UI React renderer](https://github.com/a2ui-project/a2ui/tree/main/renderers/react), and [A2UI inside MCP Apps](https://a2ui.org/guides/a2ui-in-mcp-apps/). For streaming partial specs into the view while the model writes them, see [Generative UI](/v2/typescript/mcp-apps/generative-ui). # Daytona Source: https://docs.mcp-use.com/v2/typescript/cookbook/daytona Add a run_code tool that executes code in a Daytona sandbox and returns the output through MCP. Give your existing mcp-use server a `run_code` tool. Each call creates a fresh Daytona sandbox, runs the code, and deletes the sandbox afterward. ## Try the live example Run code through our deployed Daytona server. Pick a suggestion or ask the chat to run your own snippet. [Daytona live example — MCP Inspector chat](https://inspector.manufact.com/inspector?embedded=true\&autoConnect=https%3A%2F%2Fmanufact-daytona-example.run.mcp-use.com%2Fmcp\&embeddedConfig=%7B%22singleTab%22%3Atrue%2C%22defaultTab%22%3A%22chat%22%2C%22visibleTabs%22%3A%5B%22chat%22%5D%2C%22chatHideTitle%22%3Atrue%2C%22chatHideServerUrl%22%3Atrue%2C%22chatQuickQuestions%22%3A%5B%22Use%20run_code%20to%20run%20Python%20that%20prints%20the%20first%2010%20Fibonacci%20numbers.%22%2C%22Use%20run_code%20to%20run%20JavaScript%20that%20calculates%20the%20sum%20of%20the%20squares%20from%201%20to%2010.%22%5D%7D) [Open the example in a new tab](https://inspector.manufact.com/inspector?embedded=true\&autoConnect=https%3A%2F%2Fmanufact-daytona-example.run.mcp-use.com%2Fmcp\&embeddedConfig=%7B%22singleTab%22%3Atrue%2C%22defaultTab%22%3A%22chat%22%2C%22visibleTabs%22%3A%5B%22chat%22%5D%2C%22chatHideTitle%22%3Atrue%2C%22chatHideServerUrl%22%3Atrue%2C%22chatQuickQuestions%22%3A%5B%22Use%20run_code%20to%20run%20Python%20that%20prints%20the%20first%2010%20Fibonacci%20numbers.%22%2C%22Use%20run_code%20to%20run%20JavaScript%20that%20calculates%20the%20sum%20of%20the%20squares%20from%201%20to%2010.%22%5D%7D). ## Prerequisites * A working [mcp-use server](/v2/typescript/getting-started/quickstart). * A [Daytona API key](https://app.daytona.io/). ## Add the integration Install the Daytona SDK in your server project: ```bash theme={null} npm install @daytona/sdk@0.210.0 ``` Add your key to `.env`: ```bash .env theme={null} DAYTONA_API_KEY=your_daytona_api_key ``` Copy this complete example into your server entry (`index.ts` in a project created with `create-mcp-use-app`), or adapt its Daytona client and `run_code` tool for your existing server: ```typescript index.ts theme={null} import { Daytona, type Sandbox } from "@daytona/sdk"; import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "daytona-example", version: "1.0.0", description: "Run Python, TypeScript, or JavaScript in a fresh Daytona sandbox.", }); let daytona: Daytona | undefined; /** Execute one code snippet and delete its isolated sandbox after the attempt. */ export const runCode = server.tool( { name: "run_code", description: "Execute Python, TypeScript, or JavaScript in a fresh Daytona sandbox. Returns output and exit code; files and state are discarded afterward.", inputSchema: z.object({ code: z.string().min(1).max(100_000).describe("Source code to execute."), language: z .enum(["python", "typescript", "javascript"]) .default("python"), timeoutSeconds: z.number().int().min(1).max(120).default(30), }), }, async ({ code, language, timeoutSeconds }) => { if (!process.env.DAYTONA_API_KEY?.trim()) { return { isError: true, content: [ { type: "text" as const, text: "Set DAYTONA_API_KEY in .env and restart the server before calling run_code.", }, ], }; } let sandbox: Sandbox | undefined; let output: string | undefined; let exitCode: number | undefined; let error: string | undefined; let cleanupError: string | undefined; try { daytona ??= new Daytona(); // Auto-stop/delete also limits leftovers if the server exits unexpectedly. sandbox = await daytona.create( { language, autoStopInterval: 5, autoDeleteInterval: 0 }, { timeout: 60 } ); const result = await sandbox.process.codeRun( code, undefined, timeoutSeconds ); output = result.result; exitCode = result.exitCode; } catch { // SDK errors can contain request details; do not expose credentials to clients. error = "Daytona could not create the sandbox or execute the code. Check your API key, Daytona quota and service availability, or increase timeoutSeconds (maximum 120)."; } finally { if (daytona && sandbox) { try { await daytona.delete(sandbox, 30, true); } catch { cleanupError = `Could not confirm deletion of sandbox ${sandbox.id}. Check the Daytona dashboard and delete it if needed; automatic deletion is configured after stopping.`; } } } return { isError: Boolean( error || cleanupError || (exitCode !== undefined && exitCode !== 0) ), content: [ { type: "text" as const, text: JSON.stringify({ output, exitCode, error, cleanupError }), }, ], }; } ); /** Daytona cookbook server; the mcp-use CLI owns its HTTP listener. */ export default server; ``` ## Try it Start or restart your server so it loads the key: ```bash theme={null} npm run dev ``` In the Inspector, select **Tools → run\_code** and enter: ```json theme={null} { "language": "python", "code": "print(sum([1, 2, 3]))" } ``` The result contains `output: "6\n"` and `exitCode: 0`. With a model configured in the Inspector's **Chat** tab, try: ```text theme={null} Use run_code to run Python that prints the first 10 Fibonacci numbers. ``` Each call uses your Daytona account, consumes its sandbox quota and credits, and discards its sandbox files afterward. Before exposing your server publicly, require authentication and enforce rate and spending limits to control who can execute code and how much they can spend. Code execution has a 30-second timeout; sandbox creation and deletion have separate timeouts. # Cookbook Source: https://docs.mcp-use.com/v2/typescript/cookbook/index Extend your MCP server with practical integration examples. Start with a working app or MCP server and add an integration. Each recipe includes the code you need and a quick way to try it. ## Recipes > **[Daytona](/v2/typescript/cookbook/daytona)** > > Run Python, TypeScript, or JavaScript in an isolated sandbox. Add a `run_code` tool to your MCP server. > **[Next.js](/v2/typescript/cookbook/nextjs)** > > Add an MCP endpoint to your existing Next.js app. Define a tool and mount it with the Next.js adapter. > **[TanStack Start](/v2/typescript/cookbook/tanstack-start)** > > Add an MCP endpoint to your existing TanStack Start app. Define a tool and mount it with the Vite plugin and a server route. > **[Upstash](/v2/typescript/cookbook/upstash)** > > Rate-limit MCP tool calls with Upstash Redis. Share a quota across server instances before running a tool. > **[Sentry](/v2/typescript/cookbook/sentry)** > > Trace MCP tool calls and report failures in Sentry. Monitor successful calls, tool errors, and exceptions. > **[A2UI](/v2/typescript/cookbook/a2ui)** > > Let the chat model generate interactive layouts. Render A2UI components in an MCP App view. > **[Property search](/v2/typescript/cookbook/property-search)** > > Build a map-based home search MCP App. Let the model refine the open view with view tools. # Next.js Source: https://docs.mcp-use.com/v2/typescript/cookbook/nextjs Add an MCP endpoint to your existing Next.js app with one simple tool. Expose a `greet` tool at `/api/mcp` in your existing Next.js app. Next.js serves your application and the MCP endpoint together. ## Prerequisites * A working Next.js app using the App Router and TypeScript. ## Add the integration Install mcp-use and Zod in your Next.js project: ```bash theme={null} npm install mcp-use zod ``` Keep `mcp-server.ts` at the root of your Next.js project, alongside `next.config.ts`. Add the MCP route inside your existing `app` directory: ```text theme={null} my-next-app/ ├── app/ │ ├── api/ │ │ └── mcp/ │ │ └── [[...path]]/ │ │ └── route.ts # Add: mount the MCP endpoint │ ├── layout.tsx │ └── page.tsx ├── public/ ├── mcp-server.ts # Add: define your server and tools ├── next.config.ts # Update: enable the adapter ├── package.json └── tsconfig.json ``` If your project uses `src/app`, the route goes inside that directory instead. Keep `mcp-server.ts` and `next.config.ts` at the project root. ### Define the server Create `mcp-server.ts` at the project root. Register a tool that accepts a name and returns a greeting: ```typescript mcp-server.ts theme={null} import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "my-next-app", version: "1.0.0", basePath: "/api/mcp", }); server.tool( { name: "greet", description: "Greet a person.", inputSchema: z.object({ name: z.string() }), }, async ({ name }) => ({ content: [{ type: "text", text: `Hello, ${name}!` }], }), ); export default server; ``` ### Configure the adapter Wrap your existing Next.js configuration with `withMcpUse`. Keep your application's current options inside `nextConfig`: ```typescript next.config.ts theme={null} import type { NextConfig } from "next"; import { withMcpUse } from "mcp-use/next"; const nextConfig: NextConfig = {}; export default withMcpUse(nextConfig, { entry: "./mcp-server.ts", basePath: "/api/mcp", }); ``` ### Mount the endpoint Create an optional catch-all Route Handler at `app/api/mcp/[[...path]]/route.ts`: ```typescript app/api/mcp/[[...path]]/route.ts theme={null} import { createNextHandler } from "mcp-use/next"; import server from "../../../../mcp-server"; export const { GET, POST, DELETE, OPTIONS } = createNextHandler(server); ``` If your app uses `src/app`, put the route at `src/app/api/mcp/[[...path]]/route.ts` and use `../../../../../mcp-server` to import the server from the project root. ## Try it Start your Next.js app with its usual command: ```bash theme={null} npm run dev ``` In a second terminal, open the Inspector connected to your new endpoint: ```bash theme={null} npx @mcp-use/inspector --url http://localhost:3000/api/mcp ``` Select **Tools → greet** and enter: ```json theme={null} { "name": "Ada" } ``` Run the tool. It returns `Hello, Ada!`. Use your app's port if it differs from `3000`. Restart `next dev` after editing `mcp-server.ts` so the adapter's startup build runs again. See the [complete Next.js example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/nextjs) for a runnable application, or the [Next.js guide](/v2/typescript/server/nextjs-drop-in) for shared UI views and standalone servers. # Property search Source: https://docs.mcp-use.com/v2/typescript/cookbook/property-search Build a map-based home search MCP App that the chat model refines in place with view tools. Build a Zillow-style MCP App: listing cards next to an interactive map with price pins. The model opens the view once with `search-homes`. After that, the view registers its own tools, so follow-ups such as "now the Mission, under \$2M" update the open map instead of rendering a second view. The listings are fictional San Francisco homes. Map tiles come from Esri's keyless Canvas basemaps, so the example needs no listing API or API key. ## Try the live example Ask for homes in San Francisco. Select **Fullscreen** in the view to see the listing cards, then click a card or pin to load its details. [Property search live example: MCP Inspector chat](https://inspector.manufact.com/inspector?embedded=true\&autoConnect=https%3A%2F%2Fmanufact-property-search-example.run.mcp-use.com%2Fmcp\&embeddedConfig=%7B%22singleTab%22%3Atrue%2C%22defaultTab%22%3A%22chat%22%2C%22visibleTabs%22%3A%5B%22chat%22%5D%2C%22chatHideTitle%22%3Atrue%2C%22chatHideServerUrl%22%3Atrue%2C%22chatQuickQuestions%22%3A%5B%22Show%20me%20homes%20in%20San%20Francisco.%22%2C%22Show%20me%20homes%20in%20Pacific%20Heights.%22%5D%7D) [Open the example in a new tab](https://inspector.manufact.com/inspector?embedded=true\&autoConnect=https%3A%2F%2Fmanufact-property-search-example.run.mcp-use.com%2Fmcp\&embeddedConfig=%7B%22singleTab%22%3Atrue%2C%22defaultTab%22%3A%22chat%22%2C%22visibleTabs%22%3A%5B%22chat%22%5D%2C%22chatHideTitle%22%3Atrue%2C%22chatHideServerUrl%22%3Atrue%2C%22chatQuickQuestions%22%3A%5B%22Show%20me%20homes%20in%20San%20Francisco.%22%2C%22Show%20me%20homes%20in%20Pacific%20Heights.%22%5D%7D). > [!NOTE] > > This embedded chat runs its model on Manufact's servers, which cannot reach tools registered inside the view. Follow-up refinements such as "now the Mission, under \$2M" need a host that forwards view tools to the model. To try them, [run the example](#run-the-example) with your own model provider API key. ## Run the example The example is a complete project with about 3,500 lines of view code, so clone it instead of copying it. It requires Node.js 22.22.2 or later. ```bash theme={null} git clone https://github.com/manufacts/mcp-use-property-search-example.git cd mcp-use-property-search-example npm ci npm run dev ``` Open the Inspector URL printed by the CLI, select **Chat**, and configure a model provider with your own API key. The Inspector forwards view tools to the model only in this mode; the managed Manufact model cannot call them. Send these prompts in order: ```text theme={null} Show me homes in San Francisco. Now search the Mission, under $2M. Remove the most expensive home. Open the cheapest one on the map and save it. Zoom in one step. ``` The first prompt calls `search-homes` and opens the view. Each later prompt calls a view tool, and the open map updates in place. Select **Fullscreen** in the view to switch display modes. The project has four main files: | File | Contents | | - | - | | `src/index.ts` | The staged listings, `search-homes`, and `get-listing-details` | | `views/property-search/view.tsx` | The view, its view tools, and model context | | `views/property-search/map.tsx` | The Leaflet map, Esri tiles, price pins, and camera controls | | `views/property-search/cards.tsx` | Listing cards and the detail panel | ## How it works The example combines five MCP Apps patterns. Each one works on its own in your server. ### Open the view once with the whole dataset `search-homes` is the only tool that renders the view. Besides the matching listing IDs, it returns the whole staged catalog in `structuredContent`, so the view can filter any neighborhood locally without another server call. The tool description tells the model to use the view tools for follow-ups instead of calling `search-homes` again. ```typescript src/index.ts theme={null} export const searchHomes = server.tool( { name: "search-homes", title: "Search San Francisco homes", description: "Open the interactive HomeScout map for San Francisco homes. Call this once to put the map on screen. After that, use the view's tools, such as `search-in-view`, for every follow-up search.", inputSchema: z.object({ location: z.string().optional(), maxPrice: z.number().positive().optional(), minBeds: z.number().int().min(0).optional(), homeType: homeTypeSchema.optional(), }), outputSchema: z.object({ area: areaSchema.nullable(), matchedIds: z.array(z.string()), catalog: z.object({ listings: z.array(listingSchema), areas: z.array(areaMetaSchema), attribution: z.string(), }), }), view: { name: "property-search", prefersBorder: false, csp: { resourceDomains: ["https://server.arcgisonline.com"], connectDomains: ["https://server.arcgisonline.com"], }, }, }, async ({ location = "San Francisco", maxPrice, minBeds = 0, homeType }) => { const area = resolveArea(location); const matched = LISTINGS.filter( (listing) => (area === null || listing.area === area) && (maxPrice === undefined || listing.price <= maxPrice) && listing.beds >= minBeds && (homeType === undefined || listing.homeType === homeType) ); return { content: [ { type: "text", text: `HomeScout is open with ${matched.length} homes. Refine from here with the view tools.`, }, ], structuredContent: { area, matchedIds: matched.map((listing) => listing.id), catalog: { listings: LISTINGS, areas: AREAS, attribution: ATTRIBUTION }, }, }; } ); ``` This excerpt is shortened. The example also accepts `minPrice` and `minBaths` filters and returns the median price. ### Let the model drive the open view [`useViewTool()`](/v2/typescript/mcp-apps/interactivity) registers a tool that exists only while the view is mounted. The host lists it to the model, and the handler runs inside the view with access to React state and refs. The example registers seven view tools. This one zooms the Leaflet map: ```tsx views/property-search/view.tsx theme={null} const zoomMapDefinition = { name: "zoom-map", title: "Zoom the map", description: "Zoom the live map in or out by whole steps.", inputSchema: z.object({ direction: z.enum(["in", "out"]), steps: z.number().int().min(1).max(4).optional().describe("Defaults to 1"), }), outputSchema: z.object({ zoom: z.number() }), } as const; // Inside the view component: useViewTool( zoomMapDefinition, async ({ direction, steps = 1 }) => { mapRef.current?.zoomBy(direction === "in" ? steps : -steps); const zoom = mapRef.current?.zoom() ?? 0; return { content: [{ type: "text", text: `Zoomed ${direction} to level ${zoom.toFixed(1)}.` }], structuredContent: { zoom }, }; } ); ``` | View tool | Purpose | | - | - | | `search-in-view` | Change the area, price, beds, baths, home type, or sort in place | | `remove-listings` | Hide homes from the cards and map | | `select-listing` | Fly to a home and open its detail card | | `save-listings` | Save or unsave homes | | `fit-visible-results` | Fit every visible home in frame | | `zoom-map` | Zoom in or out | | `pan-map` | Pan north, south, east, or west | ### Keep the model in sync with the view Users also filter, remove, and select homes by clicking. [``](/v2/typescript/mcp-apps/model-context) reports the current view state to the model, so "remove the most expensive one" refers to what is on screen now: ```tsx views/property-search/view.tsx theme={null} `${listing.id}: ${listing.address}, ${compactPrice(listing.price)}`) .join("; ")}.`, ].join("\n")} /> ``` ### Load details with an app-only tool `get-listing-details` has `visibility: "app"`, so MCP Apps hosts hide it from the model while the view can still call it. The view calls it with [`useCallTool()`](/v2/typescript/mcp-apps/interactivity) when the user selects a card or pin: ```typescript src/index.ts theme={null} export const getListingDetails = server.tool( { name: "get-listing-details", visibility: "app", inputSchema: z.object({ id: z.string() }), // ... }, async ({ id }) => { // Look up the listing and return its staged details. } ); ``` ```tsx views/property-search/view.tsx theme={null} const detailsTool = useCallTool("get-listing-details"); // On card or pin selection: void detailsTool.callTool({ id }); ``` ### Allow map tiles and fullscreen The view loads tiles from `server.arcgisonline.com`, so the tool's `view.csp` lists that origin in `resourceDomains` and `connectDomains`. Without it, the host's [Content Security Policy](/v2/typescript/mcp-apps/content-security-policy) blocks the tiles and the map renders blank. The view declares both display modes in `viewConfig` and requests fullscreen from a button with `useDisplayMode()`: ```tsx views/property-search/view.tsx theme={null} export const viewConfig: ViewConfig = { autoResize: true, displayModes: ["inline", "fullscreen"], }; // Inside the view component: const { displayMode, availableDisplayModes, requestDisplayMode } = useDisplayMode(); const canFullscreen = availableDisplayModes.includes("fullscreen"); // On button click: void requestDisplayMode({ mode: "fullscreen" }); ``` ## Adapt it to your app * **Real listings:** replace the staged `LISTINGS` array with a call to your listing API inside `search-homes`. Keep the returned catalog small. For large datasets, return only the first page and fetch more from the view with an app-only tool. * **Another tile provider:** change the tile URL in `map.tsx`, update both CSP lists, and show the attribution your provider's terms require. * **Other domains:** the same shape fits any "search, then refine" app, such as hotels, restaurants, or job listings. Keep one rendering tool, move refinements into view tools, and report visible state with `ModelContext`. See the [complete property search example](https://github.com/manufacts/mcp-use-property-search-example) for the runnable project, and [Interactivity](/v2/typescript/mcp-apps/interactivity) for more on view tools, app-only tools, and follow-up messages. # Sentry Source: https://docs.mcp-use.com/v2/typescript/cookbook/sentry Trace MCP tool calls and report failures with Sentry. Add Sentry tracing and error reporting to your existing Node.js mcp-use server. Each tool call gets a span with its tool name and duration. Returned tool errors and thrown exceptions also appear in Sentry Issues. This recipe uses MCP middleware, so it does not need access to mcp-use's internal SDK instances. It monitors tool callbacks; it is not a replacement for instrumentation of the full HTTP transport or every MCP operation. ## Try the live example Select **monitored\_report**, choose an **outcome**, and click **Execute**. Try `success` for a report, `tool_error` for a returned tool error, and `exception` for a thrown exception. No chat model or API key is needed to use the demo. [Sentry live example — MCP Inspector tools](https://inspector.manufact.com/inspector?embedded=true\&autoConnect=https%3A%2F%2Fmanufact-sentry-example.run.mcp-use.com%2Fmcp\&embeddedConfig=%7B%22singleTab%22%3Atrue%2C%22defaultTab%22%3A%22tools%22%2C%22visibleTabs%22%3A%5B%22tools%22%5D%7D) [Open the example in a new tab](https://inspector.manufact.com/inspector?embedded=true\&autoConnect=https%3A%2F%2Fmanufact-sentry-example.run.mcp-use.com%2Fmcp\&embeddedConfig=%7B%22singleTab%22%3Atrue%2C%22defaultTab%22%3A%22tools%22%2C%22visibleTabs%22%3A%5B%22tools%22%5D%7D). > [!NOTE] > > This hosted demo sends traces and intentional errors to Manufact's demo Sentry project. The tool result is visible here; run your own copy with your DSN to inspect the corresponding issues and traces in your Sentry account. ## Prerequisites * A working [mcp-use server](/v2/typescript/getting-started/quickstart) running on Node.js. * A [Sentry project](https://sentry.io/) and its DSN, available under **Project Settings → Client Keys (DSN)**. The demo tool runs locally and does not call an LLM or another paid API. Sentry receives the telemetry when a DSN is configured; without one, the tool still works but no events are sent. ## Add the integration Install Sentry in your server project: ```bash theme={null} npm install @sentry/node@10.63.0 ``` Add your project's DSN to `.env`: ```bash .env theme={null} MCP_USE_SENTRY_DSN=https://your-public-key@your-ingest-host/your-project-id ``` Keep `.env` out of version control. Initialize Sentry once in your server entry point, then add the middleware below. If your application already initializes Sentry, reuse that initialization rather than calling `Sentry.init()` again. Copy this complete example into your server entry (`index.ts` in a project created with `create-mcp-use-app`), or keep your existing tools and add the initialization and middleware: ```typescript index.ts theme={null} import * as Sentry from "@sentry/node"; import { MCPServer } from "mcp-use"; import { z } from "zod"; Sentry.init({ dsn: process.env.MCP_USE_SENTRY_DSN, tracesSampleRate: 1.0, sendDefaultPii: false, // Explicit instrumentation keeps this recipe focused on MCP tool calls. defaultIntegrations: false, }); const server = new MCPServer({ name: "sentry-example", version: "1.0.0", description: "Trace a successful tool call, a tool error, or an exception.", }); server.use("mcp:tools/call", (ctx, next) => Sentry.withIsolationScope((scope) => { const toolName = ctx.params.name; scope.setTag("mcp.tool.name", toolName); return Sentry.startSpan( { name: `tools/call ${toolName}`, op: "mcp.server", attributes: { "mcp.method.name": "tools/call", "mcp.tool.name": toolName, }, }, async (span) => { try { const result = await next(); if ("isError" in result && result.isError === true) { span.setStatus({ code: 2, message: "internal_error" }); span.setAttribute("mcp.tool.is_error", true); // Capture a stable message, not potentially sensitive tool output. Sentry.captureMessage( `MCP tool returned an error: ${toolName}`, "error" ); } else { span.setStatus({ code: 1 }); } return result; } catch (error) { span.setStatus({ code: 2, message: "internal_error" }); Sentry.captureException(error); // Preserve normal MCP error handling instead of hiding the failure. throw error; } } ); }) ); /** Exercise success, returned tool errors, and thrown exceptions in Inspector. */ export const monitoredReport = server.tool( { name: "monitored_report", description: "Generate a sample report or deliberately fail to test Sentry.", inputSchema: z.object({ outcome: z .enum(["success", "tool_error", "exception"]) .default("success"), }), }, async ({ outcome }) => { if (outcome === "exception") { throw new Error("Demo report service unavailable"); } if (outcome === "tool_error") { return { isError: true, content: [ { type: "text" as const, text: "Demo report could not be generated.", }, ], }; } return { content: [ { type: "text" as const, text: "Report generated: 3 orders, total $60.", }, ], }; } ); /** Sentry example server; the mcp-use CLI owns its HTTP listener. */ export default server; ``` `withIsolationScope` keeps each call's error tags separate from concurrent requests. `startSpan` ends the span when the callback finishes. Returning `isError: true` is a valid MCP result, so the middleware explicitly marks it as failed and reports a stable message. Exceptions are captured and rethrown to preserve normal MCP error handling. ## Try it Start or restart your server so it loads `.env`: ```bash theme={null} npm run dev ``` Open the Inspector URL printed by the CLI. Select **Tools → monitored\_report** and try each input: | Input | MCP result | Sentry result | | - | - | - | | `{ "outcome": "success" }` | Sample report | Successful `tools/call monitored_report` span | | `{ "outcome": "tool_error" }` | Tool error | Failed span and `MCP tool returned an error: monitored_report` issue | | `{ "outcome": "exception" }` | MCP failure | Failed span and `Demo report service unavailable` exception | In your Sentry project, look for the transaction/span named `tools/call monitored_report` in **Traces**, and the two error types in **Issues**. Error events have the `mcp.tool.name` tag. Delivery and indexing are asynchronous; leave the development server running briefly after making the calls. ## Adapt it to your server * Replace `monitored_report` with your own tools. The middleware covers registered tool callbacks; discovery and failures rejected before callback dispatch are outside its scope. * The demo samples every trace with `tracesSampleRate: 1.0`. Choose a suitable sample rate for production traffic. * Tool arguments and returned content are not attached to telemetry. Captured exceptions still include their messages and stack traces; redact sensitive application errors using Sentry's `beforeSend` configuration as needed. * `defaultIntegrations: false` intentionally disables automatic integrations for this focused example. Applications that already use Sentry should retain their existing setup and check for overlapping error capture. Automatic HTTP/database instrumentation has additional initialization requirements; this recipe only demonstrates explicit spans. * For a long-running Node server, let Sentry send in the background. For a short-lived script, await `Sentry.flush(2000)` before exit. Serverless deployments need their platform's supported lifecycle integration so queued telemetry can finish; do not assume a returned HTTP response keeps the process alive. See the [complete Sentry example](https://github.com/manufacts/mcp-use-sentry-example) for the runnable project and tests, [Sentry's custom instrumentation guide](https://docs.sentry.io/platforms/javascript/guides/node/tracing/instrumentation/custom-instrumentation/) and [error capture documentation](https://docs.sentry.io/platforms/javascript/guides/node/usage/). This example uses the public middleware API; Sentry's `wrapMcpServerWithSentry` targets underlying MCP SDK instances and should not be applied directly to the outer mcp-use server. # TanStack Start Source: https://docs.mcp-use.com/v2/typescript/cookbook/tanstack-start Add an MCP endpoint to your existing TanStack Start app with one simple tool. Expose a `greet` tool at `/api/mcp` in your existing TanStack Start app. TanStack Start serves your application and the MCP endpoint together. ## Prerequisites * A working TanStack Start app using React, Vite 8, and TypeScript. Upgrade apps on older Vite majors before installing mcp-use, which requires Vite `^8.0.0`. * Node.js 22.22.2 or later. This recipe configures Nitro for a Node.js server deployment. ## Add the integration Install mcp-use, which includes the TanStack Start adapter, and Zod in your project: ```bash theme={null} npm install mcp-use zod ``` If your app does not already use Nitro 3, install the version used by the example for the Node.js server build: ```bash theme={null} npm install -D nitro@3.0.260903-beta ``` Keep the MCP server and its handler in `src/mcp`. Add a catch-all server route inside your existing `src/routes` directory: ```text theme={null} my-tanstack-app/ ├── src/ │ ├── mcp/ │ │ ├── server.ts # Add: define your server and tools │ │ └── handler.server.ts # Add: create the MCP handler │ ├── routes/ │ │ ├── __root.tsx │ │ ├── index.tsx │ │ └── api.mcp.$.ts # Add: mount the MCP endpoint │ └── router.tsx ├── public/ ├── vite.config.ts # Update: enable the adapter ├── package.json └── tsconfig.json ``` ### Define the server Create `src/mcp/server.ts`. Register a tool that accepts a name and returns a greeting: ```typescript src/mcp/server.ts theme={null} import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "my-tanstack-app", version: "1.0.0", basePath: "/api/mcp", cors: { origin: "*", methods: ["GET", "HEAD", "POST", "DELETE", "OPTIONS"], allowedHeaders: [ "Authorization", "Content-Type", "Accept", "Mcp-Protocol-Version", "Mcp-Method", "Mcp-Name", "Mcp-Session-Id", "Last-Event-ID", ], }, }); server.tool( { name: "greet", description: "Greet a person.", inputSchema: z.object({ name: z.string() }), }, async ({ name }) => ({ content: [{ type: "text", text: `Hello, ${name}!` }], }), ); export default server; ``` TanStack Start owns the HTTP listener, so do not call `server.listen()`. Configure CORS on `MCPServer` to allow browser clients such as the Inspector to connect. ### Configure the adapter Add `mcpUseTanStackStart` before the Start and React plugins in your existing Vite configuration. Keep your application's other options and plugins: ```typescript vite.config.ts theme={null} import { defineConfig } from "vite"; import { tanstackStart } from "@tanstack/react-start/plugin/vite"; import react from "@vitejs/plugin-react"; import { nitro } from "nitro/vite"; import { mcpUseTanStackStart } from "mcp-use/tanstack-start/vite"; export default defineConfig({ plugins: [ mcpUseTanStackStart({ entry: "./src/mcp/server.ts", basePath: "/api/mcp", }), tanstackStart(), nitro({ preset: "node-server" }), react(), ], }); ``` The plugin's `basePath` must match the one on `MCPServer`. ### Mount the endpoint Create the handler in `src/mcp/handler.server.ts`. The Vite plugin loads the authored server in its dedicated MCP environment, so this route module does not import `server.ts`: ```typescript src/mcp/handler.server.ts theme={null} import { createTanStackStartHandler } from "mcp-use/tanstack-start"; export const handler = createTanStackStartHandler(); ``` Create a catch-all server route at `src/routes/api.mcp.$.ts`. Forward all HTTP methods to the handler so it can serve the MCP endpoint and nested asset paths: ```typescript src/routes/api.mcp.$.ts theme={null} import { createFileRoute } from "@tanstack/react-router"; import { handler } from "../mcp/handler.server"; export const Route = createFileRoute("/api/mcp/$")({ server: { handlers: { ANY: ({ request }) => handler(request) }, }, }); ``` ## Try it Start your TanStack Start app with its usual command: ```bash theme={null} npm run dev ``` In a second terminal, open the Inspector connected to your new endpoint: ```bash theme={null} npx @mcp-use/inspector --url http://localhost:3000/api/mcp ``` Select **Tools → greet** and enter: ```json theme={null} { "name": "Ada" } ``` Run the tool. It returns `Hello, Ada!`. Use your app's port if it differs from `3000`. MCP views share the application's browser environment for React Fast Refresh and CSS HMR. Server edits replace the MCP instance and interrupt active requests; failed edits retain the last working instance. View registrations and skills refresh without restarting Vite. Configure React, CSS and aliases in the main Vite config. See the [complete TanStack Start example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/tanstack-start) for a runnable application with a shared UI card, an OAuth discovery route, and production build instructions. # Upstash Source: https://docs.mcp-use.com/v2/typescript/cookbook/upstash Rate-limit MCP tool calls with Upstash Redis before running the tool. Add a shared quota to your existing mcp-use server. [Upstash Redis](https://upstash.com/docs/redis/overall/getstarted) stores the counters, and `@upstash/ratelimit` checks them before a tool runs—even when requests reach different server instances. This recipe allows three `generate_report` calls per 30-second sliding window. The report is a local calculation, so you can try the integration with just an Upstash account. Use the same middleware around an expensive API call, export, or sandbox operation. ## Try the live example Select **generate\_report**, enter `[10, 20, 30]` in **values**, and click **Execute**. Repeat the call to see a report followed by a rate-limit error. No chat model or API key is needed to use the demo. [Upstash live example — MCP Inspector tools](https://inspector.manufact.com/inspector?embedded=true\&autoConnect=https%3A%2F%2Fmanufact-upstash-example.run.mcp-use.com%2Fmcp\&embeddedConfig=%7B%22singleTab%22%3Atrue%2C%22defaultTab%22%3A%22tools%22%2C%22visibleTabs%22%3A%5B%22tools%22%5D%7D) [Open the example in a new tab](https://inspector.manufact.com/inspector?embedded=true\&autoConnect=https%3A%2F%2Fmanufact-upstash-example.run.mcp-use.com%2Fmcp\&embeddedConfig=%7B%22singleTab%22%3Atrue%2C%22defaultTab%22%3A%22tools%22%2C%22visibleTabs%22%3A%5B%22tools%22%5D%7D). > [!NOTE] > > All visitors share this demo's quota. You may hit the limit on your first call if someone else has used it. Wait about a minute and try again, or run your own copy below for an isolated demo. ## Prerequisites * A working [mcp-use server](/v2/typescript/getting-started/quickstart). * An [Upstash Redis database](https://console.upstash.com/redis) and its REST URL and read/write REST token. The read-only token cannot update rate-limit counters. ## Add the integration Install the Redis client and rate limiter in your server project: ```bash theme={null} npm install @upstash/redis@1.38.4 @upstash/ratelimit@2.0.8 ``` Copy the credentials from your database's **REST** connection panel into `.env`. Use these prefixed names even though the Upstash console shows names without `MCP_USE_`: ```bash .env theme={null} MCP_USE_UPSTASH_REDIS_REST_URL=https://your-database.upstash.io MCP_USE_UPSTASH_REDIS_REST_TOKEN=your-rest-token ``` Keep `.env` out of version control. Both values stay on the server. Add the highlighted middleware to your existing server, or copy this complete example into your server entry (`index.ts` in a project created with `create-mcp-use-app`). It checks only `generate_report`; other tools and tool discovery continue normally. ```typescript index.ts highlight={1-2,12-68} theme={null} import { Ratelimit } from "@upstash/ratelimit"; import { Redis } from "@upstash/redis"; import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "upstash-example", version: "1.0.0", description: "Generate a report with a shared Upstash rate limit.", }); let limiter: Ratelimit | undefined; function toolError(message: string) { return { isError: true, content: [{ type: "text" as const, text: message }], }; } server.use("mcp:tools/call", async (ctx, next) => { if (ctx.params.name !== "generate_report") return next(); const url = process.env.MCP_USE_UPSTASH_REDIS_REST_URL?.trim(); const token = process.env.MCP_USE_UPSTASH_REDIS_REST_TOKEN?.trim(); if (!url || !token) { return toolError( "Set MCP_USE_UPSTASH_REDIS_REST_URL and MCP_USE_UPSTASH_REDIS_REST_TOKEN in .env and restart the server." ); } // Only provider setup/checking belongs in this catch; tool errors should // retain their own meaning after next() runs. try { limiter ??= new Ratelimit({ redis: new Redis({ url, token }), limiter: Ratelimit.slidingWindow(3, "30 s"), prefix: "mcp-use:upstash-example", analytics: false, timeout: 3_000, }); // All callers share this demo quota, including across server instances. // For per-customer limits, key by a verified user/tenant ID + tool name. const { success, reason, reset } = await limiter.limit("generate_report"); // Upstash allows calls on timeout by default. This example fails closed. if (reason === "timeout") { return toolError("The quota check timed out. Please try again shortly."); } if (!success) { const retryAfterSeconds = Math.max( 1, Math.ceil((reset - Date.now()) / 1_000) ); return toolError( `Rate limit reached: 3 reports per 30 seconds, shared by all callers. Retry in about ${retryAfterSeconds} seconds.` ); } } catch { // Redis errors may contain request details; never return them to clients. return toolError( "Could not check the quota. Check your Upstash credentials and service availability, then try again." ); } return next(); }); /** Generate a local numeric report after the shared quota check succeeds. */ export const generateReport = server.tool( { name: "generate_report", description: "Summarize numeric values. Limited to 3 calls per 30 seconds across all callers; wait before retrying a rate-limit error.", inputSchema: z.object({ values: z.array(z.number().min(-1e9).max(1e9)).min(1).max(1_000), }), }, async ({ values }) => { // A fast local calculation keeps this demo independent of paid APIs. // Replace this callback with your expensive report or sandbox operation. const total = values.reduce((sum, value) => sum + value, 0); return { content: [ { type: "text" as const, text: JSON.stringify({ count: values.length, total, average: total / values.length, minimum: Math.min(...values), maximum: Math.max(...values), }), }, ], }; } ); /** Upstash example server; the mcp-use CLI owns its HTTP listener. */ export default server; ``` The middleware returns `isError: true` when the quota is exhausted, so the caller receives an MCP tool error and the report callback does not run. Missing credentials, Redis failures, and quota-check timeouts also block execution. Upstash normally allows requests after its timeout; the explicit `reason === "timeout"` check makes this example reject them. ## Try it Start or restart your server so it loads `.env`: ```bash theme={null} npm run dev ``` Open the Inspector URL printed by the CLI. Select **Tools → generate\_report** and enter: ```json theme={null} { "values": [10, 20, 30] } ``` A successful call returns: ```json theme={null} { "count": 3, "total": 60, "average": 20, "minimum": 10, "maximum": 30 } ``` From an unused quota, execute four calls in quick succession. The first three return reports; the fourth returns `Rate limit reached`. Its retry time is approximate because the sliding window also accounts for calls in the previous window. After a full minute without calls, try again. Restarting the server does not clear the Redis counters. ## Adapt the quota * Change `Ratelimit.slidingWindow(3, "30 s")` to choose the allowance and window. * Change `prefix` to separate deployments that use the same Redis database. * Replace the constant `generate_report` key with a verified user or tenant ID plus the tool name for customer-specific quotas. Do not trust an ID supplied in tool arguments or an arbitrary header. The limiter counts admitted attempts, even if the tool later fails. This demo does not authenticate callers; add authentication before using it to enforce customer quotas. See the [complete Upstash example](https://github.com/manufacts/mcp-use-upstash-example) for the runnable project and tests, or [Upstash's rate-limit documentation](https://upstash.com/docs/redis/sdks/ratelimit-ts/overview) for more algorithms. # Quickstart Source: https://docs.mcp-use.com/v2/typescript/getting-started/quickstart Scaffold, run, and test an MCP App with mcp-use. For the complete documentation index, see [llms.txt](https://mcp-use.com/docs/llms.txt). Create an mcp-use app, run it locally, and render its View in the Inspector. The generated project includes a server, two tools, and a React View. > [!NOTE] > > This quickstart uses the `mcp-apps` template. To build a tool-only server, use > `--template mcp-server`. For an MCP client or agent, start with the [MCP > Client](/v2/typescript/client/index) or [MCP > Agent](/v2/typescript/agent/index) documentation. ## Prerequisites * Node.js 22.22.2 or later * npm, pnpm, or Bun ## Scaffold an mcp-use app ```bash npm theme={null} npx create-mcp-use-app@latest my-mcp-app --template mcp-apps --install ``` ```bash pnpm theme={null} pnpm dlx create-mcp-use-app@latest my-mcp-app --template mcp-apps --install ``` ```bash bun theme={null} bunx create-mcp-use-app@latest my-mcp-app --template mcp-apps --install ``` With a project name and `--template`, the scaffolder does not prompt. `--install` installs dependencies with the package manager that ran the command; without it, run `npm install`, `pnpm install`, or `bun install` in the project before starting the server. The scaffolder also installs the `mcp-apps-builder` coding-agent skill, which requires Git. Pass `--no-skills` to skip it. ## Run the development server ```bash npm theme={null} cd my-mcp-app npm run dev ``` ```bash pnpm theme={null} cd my-mcp-app pnpm dev ``` ```bash bun theme={null} cd my-mcp-app bun run dev ``` `mcp-use dev` serves the MCP endpoint at `http://localhost:3000/mcp` and the Inspector at `http://localhost:3000/mcp/inspector`. The Inspector opens automatically in an interactive terminal. ## Explore the generated project ```text theme={null} my-mcp-app/ ├── public/ │ ├── icon.svg │ └── logo-mcp-use.svg ├── views/ │ └── my-view/ │ ├── view.tsx │ ├── view.css │ ├── icons.tsx │ ├── MeshGradient.tsx │ └── Tooltip.tsx ├── index.ts ├── mcp-env.d.ts ├── package.json └── tsconfig.json ``` * `index.ts` creates the server and registers the `show-app` and `say-hello` tools. * `views/my-view/view.tsx` contains the React View rendered by `show-app`. * `mcp-env.d.ts` connects exported tool definitions to typed React hooks. * `public/` contains assets served by the framework. ## Understand the View-bound tool The generated `show-app` tool imports from `mcp-use`, declares `inputSchema` and `outputSchema`, and binds the View with `view: { name: "my-view" }`. ```typescript index.ts theme={null} import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "my-mcp-app", version: "1.0.0", }); export const showApp = server.tool( { name: "show-app", description: "Display the starter MCP App", inputSchema: z.object({ appName: z.string().optional().describe("Title shown in the MCP App"), }), outputSchema: z.object({ message: z.string().describe("Message displayed by the View"), }), view: { name: "my-view", description: "Starter MCP App View", }, annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false, }, }, async ({ appName }) => { const data = { message: `The MCP App for ${appName ?? "my project"} is ready!`, }; return { content: [{ type: "text", text: data.message }], structuredContent: data, }; }, ); export default server; ``` Assign statically declared tools to exported constants. The generated `mcp-env.d.ts` uses those exports to type View hooks. Export the server as the default value so the CLI can run, build, and deploy it. ## Read tool results in the View The View directory must match `view.name`. Use `useToolContext()` to read the invocation that rendered the View: ```tsx views/my-view/view.tsx theme={null} import { useToolContext } from "mcp-use/react"; export default function MyView() { const view = useToolContext<"show-app">(); if (view.status === "pending") { return

Loading the app…

; } if (view.status === "error") { return

{view.error.message}

; } return

{view.toolOutput.message}

; } ``` When the tool succeeds, `view.toolOutput` is the typed value returned in `structuredContent`. The host and model receive the text in `content`. ## Check the project Run the generated type check after changing tools or Views: ```bash npm theme={null} npm run typecheck ``` ```bash pnpm theme={null} pnpm typecheck ``` ```bash bun theme={null} bun run typecheck ``` The command refreshes `mcp-env.d.ts` and runs TypeScript without emitting build files. You can also call the server from the terminal: ```bash theme={null} npx mcp-use client connect local http://localhost:3000/mcp npx mcp-use client local tools list ``` ## Deploy the project Sign in to Manufact, then deploy the generated project. `deploy` does not sign you in; without saved credentials or `MCP_USE_API_KEY`, it exits with `Not logged in`. ```bash npm theme={null} npx mcp-use login npm run deploy ``` ```bash pnpm theme={null} pnpm exec mcp-use login pnpm run deploy ``` ```bash bun theme={null} bunx mcp-use login bun run deploy ``` The first deployment links the local project. See the [Manufact deployment guide](/v2/typescript/server/deployment/mcp-use) for environment variables, regions, and subsequent deployments. ## Next steps > **[Tools](/v2/typescript/server/tools)** > > Define validated inputs, outputs, annotations, and View-bound results. > **[MCP Apps](/v2/typescript/mcp-apps)** > > Build production Views and integrate with MCP hosts. > **[Inspector](/inspector/index)** > > Test and debug your server interactively. > **[Deployment](/v2/typescript/server/deployment/mcp-use)** > > Publish the server and configure production environments. > [!TIP] > > **Need help?** Join our [Discord](https://discord.gg/XkNkSkMz3V) or visit > [GitHub](https://github.com/mcp-use/mcp-use). # Templates Source: https://docs.mcp-use.com/v2/typescript/getting-started/templates Ready-to-use MCP Apps you can deploy in one click or remix as your own. Every template ships with a live demo, a public repo, and a one-click deploy button. Clone, customize, and ship. > [!TIP] > > Looking to scaffold a new project from scratch instead? Run `npx create-mcp-use-app@latest` - see the [Quickstart](/v2/typescript/getting-started/quickstart). ## Featured Templates > **[Chart Builder](https://github.com/mcp-use/mcp-chart-builder)** > > Generate charts from natural language. Tools: `create-chart`. > [Demo](https://yellow-shadow-21833.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-chart-builder\&branch=main\&project-name=mcp-chart-builder\&port=3000\&runtime=node\&base-image=node%3A22) > **[Diagram Builder](https://github.com/mcp-use/mcp-diagram-builder)** > > Build and edit diagrams conversationally. Tools: `create-diagram`, `edit-diagram`. > [Demo](https://lucky-darkness-402ph.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-diagram-builder\&branch=main\&project-name=mcp-diagram-builder\&port=3000\&runtime=node\&base-image=node%3A22) > **[Slide Deck](https://github.com/mcp-use/mcp-slide-deck)** > > Create and edit slide decks inline. Tools: `create-slides`, `edit-slide`. > [Demo](https://solitary-block-r6m6x.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-slide-deck\&branch=main\&project-name=mcp-slide-deck\&port=3000\&runtime=node\&base-image=node%3A22) > **[Maps Explorer](https://github.com/mcp-use/mcp-maps-explorer)** > > Interactive maps with place details and markers. Tools: `show-map`, `get-place-details`, `add-markers`. > [Demo](https://super-night-ttde2.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-maps-explorer\&branch=main\&project-name=mcp-maps-explorer\&port=3000\&runtime=node\&base-image=node%3A22) > **[Hugging Face Spaces](https://github.com/mcp-use/mcp-huggingface-spaces)** > > Browse and preview Hugging Face Spaces. Tools: `search-spaces`, `show-space`, `trending-spaces`. > [Demo](https://gentle-frost-pvxpk.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-huggingface-spaces\&branch=main\&project-name=mcp-huggingface-spaces\&port=3000\&runtime=node\&base-image=node%3A22) > **[Recipe Finder](https://github.com/mcp-use/mcp-recipe-finder)** > > Search recipes and plan meals. Tools: `search-recipes`, `get-recipe`. Prompts: `meal-plan`, `recipe-suggestion`. > [Demo](https://bold-tree-1fe79.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-recipe-finder\&branch=main\&project-name=mcp-recipe-finder\&port=3000\&runtime=node\&base-image=node%3A22) > **[Widget Gallery](https://github.com/mcp-use/mcp-widget-gallery)** > > Reference gallery of every widget pattern. Tools: `show-react-widget`, `html-greeting`, `mcp-ui-poll`, `programmatic-counter`, `detect-client`. > [Demo](https://wandering-lake-mmxhs.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-widget-gallery\&branch=main\&project-name=mcp-widget-gallery\&port=3000\&runtime=node\&base-image=node%3A22) > **[Multi Server Hub](https://github.com/mcp-use/mcp-multi-server-hub)** > > Aggregate and audit multiple MCP servers. Tools: `hub-status`, `hub-config-example`, `audit-log`. > [Demo](https://soft-voice-4nxfi.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-multi-server-hub\&branch=main\&project-name=mcp-multi-server-hub\&port=3000\&runtime=node\&base-image=node%3A22) > **[File Manager](https://github.com/mcp-use/mcp-file-manager)** > > Browse and read files through an MCP vault. Tools: `open-vault`, `get-file`, `list-files`. > [Demo](https://muddy-pond-eyays.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-file-manager\&branch=main\&project-name=mcp-file-manager\&port=3000\&runtime=node\&base-image=node%3A22) > **[Progress Demo](https://github.com/mcp-use/mcp-progress-demo)** > > Long-running tools with progress and error handling. Tools: `process-data`, `fetch-report`, `delete-dataset`, `search-external`, `failing-tool`. > [Demo](https://crimson-river-pzsz1.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-progress-demo\&branch=main\&project-name=mcp-progress-demo\&port=3000\&runtime=node\&base-image=node%3A22) > **[i18n Adaptive](https://github.com/mcp-use/mcp-i18n-adaptive)** > > Adapt responses to caller locale and context. Tools: `show-context`, `detect-caller`. > [Demo](https://falling-grass-58yov.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-i18n-adaptive\&branch=main\&project-name=mcp-i18n-adaptive\&port=3000\&runtime=node\&base-image=node%3A22) > **[Media Mixer](https://github.com/mcp-use/mcp-media-mixer)** > > Generate images, audio, PDFs, and more. Tools: `generate-image`, `generate-audio`, `generate-pdf`, and more. > [Demo](https://wandering-breeze-nuipu.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-media-mixer\&branch=main\&project-name=mcp-media-mixer\&port=3000\&runtime=node\&base-image=node%3A22) > **[Resource Watcher](https://github.com/mcp-use/mcp-resource-watcher)** > > Subscribe to resources and toggle features live. Tools: `show-config`, `update-config`, `toggle-feature`, `list-roots`. > [Demo](https://fragrant-term-zmdks.run.mcp-use.com/mcp) · [Deploy](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmcp-use%2Fmcp-resource-watcher\&branch=main\&project-name=mcp-resource-watcher\&port=3000\&runtime=node\&base-image=node%3A22) > **[See all examples on GitHub](https://github.com/mcp-use/mcp-use/tree/main/examples)** > > More templates, source code, and ready-to-run samples for Python and TypeScript. ## Deploy your own Every template above is powered by [manufact.com](https://manufact.com) - connect your GitHub repo and your MCP Server ships in minutes with observability, metrics, logs, and branch deployments. ```bash theme={null} npx @mcp-use/cli login npx @mcp-use/cli deploy ``` # Welcome Source: https://docs.mcp-use.com/v2/typescript/getting-started/welcome Build MCP servers, apps, clients, and agents with mcp-use for TypeScript. For the complete documentation index, see [llms.txt](https://mcp-use.com/docs/llms.txt). **mcp-use** is the full-stack MCP framework for TypeScript. Build MCP servers, MCP Apps that render interactive Views in ChatGPT and Claude, MCP clients, and tool-calling agents with end-to-end type safety. ## Get started Scaffold an mcp-use app with the release of `create-mcp-use-app`: ```bash theme={null} npx create-mcp-use-app@latest my-mcp-app ``` ### Build a server and View ```typescript index.ts theme={null} import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "greeter", version: "1.0.0", }); export const greet = server.tool( { name: "greet", description: "Greet someone by name", inputSchema: z.object({ name: z.string().describe("Name of the person to greet"), }), outputSchema: z.object({ greeting: z.string(), }), view: { name: "greeting" }, }, async ({ name }) => { const data = { greeting: `Hello, ${name}!` }; return { content: [{ type: "text", text: data.greeting }], structuredContent: data, }; }, ); export default server; ``` ```tsx views/greeting/view.tsx theme={null} import { useToolContext } from "mcp-use/react"; export default function Greeting() { const view = useToolContext<"greet">(); if (view.status === "pending") return

Loading…

; if (view.status === "error") return

{view.error.message}

; return

👋 {view.toolOutput.greeting}

; } ``` The default server export lets `mcp-use dev`, `mcp-use build`, and `mcp-use start` manage the server lifecycle. The View directory name must match the tool's `view.name`. Looking for the **Python** docs? Start with the [Python quickstart](/python/getting-started/quickstart). > **[New to MCP?](/home/mcp101)** > > Learn how MCP clients, servers, agents, tools, resources, and prompts fit > together. ## Choose your next step > **[Build your first project](/v2/typescript/getting-started/quickstart)** > > Scaffold an MCP App, run it locally, and test its View. > **[MCP Server](/v2/typescript/server)** > > Define tools, resources, prompts, authentication, and deployment. > **[MCP Apps](/v2/typescript/mcp-apps)** > > Build interactive Views for ChatGPT, Claude, and other MCP hosts. > **[MCP Client](/v2/typescript/client/index)** > > Connect to MCP servers programmatically. > **[MCP Agent](/v2/typescript/agent/index)** > > Build agents that call tools through MCP connections. > [!TIP] > > **Need help?** Join our [Discord](https://discord.gg/XkNkSkMz3V) or visit > [GitHub](https://github.com/mcp-use/mcp-use). # Overview Source: https://docs.mcp-use.com/v2/typescript/mcp-apps Understand how MCP tools render interactive UI with mcp-use. An MCP App combines an `MCPServer`, a React component under `views/`, and a tool bound to that View. The `mcp-use` framework includes a Vite-based build system that discovers, builds, and serves your Views in development and production. MCP Apps let your tools render interactive UI inside AI conversations. Build a View when users need to explore data, complete a form, review a preview, or act on a tool result. ## How a tool renders a View Add `view: { name }` to a tool definition. The name must match a directory under `views/`. ```text theme={null} product-search/ ├── index.ts ├── views/ │ └── product-results/ │ └── view.tsx ├── public/ ├── mcp-env.d.ts └── package.json ``` The View-bound tool must declare an `outputSchema`. Its handler returns a normal MCP tool result with matching `structuredContent`. ```typescript theme={null} import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "product-search", version: "1.0.0", }); export const searchProducts = server.tool( { name: "search-products", inputSchema: z.object({ query: z.string(), }), outputSchema: z.object({ results: z.array( z.object({ id: z.string(), name: z.string(), }), ), }), view: { name: "product-results", }, }, async ({ query }) => { const results = [ { id: "starter-kit", name: `${query} starter kit` }, { id: "travel-kit", name: `${query} travel kit` }, ]; return { content: [ { type: "text", text: `Found ${results.length} products matching "${query}".`, }, ], structuredContent: { results, }, }; }, ); export default server; ``` Each View can be bound to at most one tool. Export the tool reference so mcp-use can infer its input and output types inside the View. ## Read the tool result in the View A View default-exports a React component. The component receives no React props. Read the tool lifecycle and result with `useToolContext()`. ```tsx theme={null} import { useToolContext } from "mcp-use/react"; export default function ProductResults() { const { status, toolInput, toolOutput, error } = useToolContext<"search-products">(); if (status === "error") { return

{error.message}

; } if (status === "pending") { return

Searching for {toolInput?.query ?? "products"}…

; } return (

Product results

    {toolOutput.results.map(({ id, name }) => (
  • {name}
  • ))}
); } ``` ## Choose what the model and View receive MCP tool results provide separate channels for conversation output, structured data, and View-only metadata. | Channel | Model receives it? | View receives it? | Use it for | | - | - | - | - | | `content` | Yes | Yes, as `content` | A concise result for the conversation and text-only clients | | `structuredContent` | Yes | Yes, as `toolOutput` | Typed data that the model can reason over and the View can render | | `_meta` | No | Yes, as `meta` | Data that is not visible to the model | Do not place secrets in any result channel. A View runs on the client and can read its result data. ## Continue building > **[Build your first MCP App](/v2/typescript/mcp-apps/quickstart)** > > Create a project, run it locally, and render its View in the Inspector. > **[Interactivity](/v2/typescript/mcp-apps/interactivity)** > > Call tools, open links, send follow-up messages, and change display modes. > **[Model context](/v2/typescript/mcp-apps/model-context)** > > Expose View state and visible UI information to future model turns. > **[Content Security Policy](/v2/typescript/mcp-apps/content-security-policy)** > > Allow the external APIs, assets, and embedded content your View needs. # ChatGPT Plugin Extensions Source: https://docs.mcp-use.com/v2/typescript/mcp-apps/chatgpt-extensions Add selected model context, app entrypoints, deep links, composer mentions, structured settings, and display modes with the TypeScript SDK. Use ChatGPT Plugin Extensions to add app launchers, file viewers, incoming routes, composer mentions, native settings, and selected model context. You can also set an initial display preference. The TypeScript SDK converts your declarations to OpenAI extension metadata. The host controls which extensions users can access. Start with a [view-bound MCP App](/v2/typescript/mcp-apps/quickstart). Each view needs one bound tool and an `outputSchema`. Composer mention search uses a server tool and needs no View. The examples below use the v2 TypeScript API. | Goal | API | | - | - | | Open an app from navigation or a conversation | `tool.view.entrypoints` with `global` or `thread` | | Open a file in a custom viewer | `tool.view.entrypoints` with `file` | | Read an incoming app route | `useDeepLink()` | | Search app-owned items in the composer | `server.mentions()` | | Add native settings and action buttons | `server.settings()` | | Attach selected evidence to the next model turn | `useModelContext()` | | Request an initial presentation | `viewConfig.preferredDisplayMode` | ## Check host support The [OpenAI platform support table](https://github.com/openai/mcp-extensions/blob/main/docs/spec.md#platform-support) describes the following expected support. Its web column refers to the ChatGPT Work browser and excludes classic ChatGPT. Availability depends on the host release. | Extension | Desktop | Work web | iOS | Android | | - | - | - | - | - | | Global and thread entrypoints | Yes | Yes | Yes | Yes | | File entrypoints | Yes | No | No | No | | Deep links | Yes | Yes | Yes | No | | Structured settings | Yes | Yes | Yes | Yes | | Resource display modes | Yes | Yes | Yes | Yes | ChatGPT supports `inline` and `fullscreen` display modes. Other MCP Apps hosts can support `pip`. Test each extension in the host that your users use. ## Attach evidence to the next model turn Use `useModelContext()` when the user selects evidence to send with the next model turn. For example, add a book summary when the user selects **Add to chat**. Keep cart actions separate from attachment actions. Import the hook from `mcp-use/react` and render it in your view. The hook activates native context delivery. It needs no `viewConfig` option. The SDK checks host capabilities during initialization and checks each block before delivery. Calls made during initialization wait for the host connection. ### Add, remove, and clear selected evidence This component adds a summary, lists selected attachments, and lets the user remove or clear them. It catches action errors and shows the shared delivery error. ```tsx theme={null} import { useState } from "react"; import { useModelContext, type ModelContextOperationResult, } from "mcp-use/react"; export default function BookEvidence() { const { attachments, pending, error, add, remove, clearAttachments } = useModelContext(); const [busy, setBusy] = useState(false); const [actionError, setActionError] = useState(null); async function run(action: () => Promise) { setBusy(true); setActionError(null); try { await action(); } catch (failure) { setActionError( failure instanceof Error ? failure : new Error(String(failure)), ); } finally { setBusy(false); } } const disabled = busy || pending; const failure = actionError ?? error; return (
    {attachments.map(({ key, block }) => (
  • {block.title ?? block.type}
  • ))}
{pending &&

Updating context…

} {failure &&

{failure.message}

}
); } ``` The hook returns these fields and methods: | Member | Behavior | | - | - | | `attachments` | Read-only list of selected `{ key, block }` entries. The list can include unsynced entries after a delivery failure. | | `pending` | `true` during initialization, image preparation, batching, or delivery. `false` alone does not prove that delivery succeeded. | | `error` | Shared delivery or reconciliation error, or `null`. Catch each action's rejection to show validation and preparation errors. | | `add(key, block)` | Add one attachment or replace the value at the same key. Keep the other attachments. | | `remove(key)` | Remove one selected attachment. Use the key returned in `attachments`, including for restored entries. | | `clearAttachments()` | Clear the shared attachment collection. Keep separately managed view state, descriptions, and restored background context. | Each method returns `Promise<{ status: "synced" | "superseded" }>`. `"synced"` confirms context delivery, not permanent selection or a visible composer chip. `"superseded"` means a newer action replaced the operation before acknowledgment. Catch rejected promises as shown above. Use distinct, stable application keys, such as `book:summary` and `book:cover`. Keys are shared across all hook instances in one view runtime. Exact duplicate blocks under different keys reject. Unmounting a hook consumer does not clear its selections. ### Choose a content block The hook supports four block types: `text`, `image`, `resource_link`, and `resource`. Each type accepts a friendly top-level `title`. The title is also available in `attachments[i].block.title` after host restoration. These blocks can replace the text block in the example above. For the image and thumbnail, put a cover at `public/covers/book.png`. ```typescript theme={null} import type { ModelContextBlock } from "mcp-use/react"; export const bookEvidence = { summary: { type: "text", title: "Book details", text: "An illustrated guide to garden plants, with 12 chapters.", thumbnail: { src: "/covers/book.png", mimeType: "image/png" }, }, cover: { type: "image", title: "Book cover", src: "/covers/book.png", }, manual: { type: "resource_link", title: "Book manual", name: "manual.pdf", uri: "https://example.com/books/manual.pdf", mimeType: "application/pdf", }, sample: { type: "resource", title: "Reading sample", resource: { uri: "bookshop://books/garden-guide/sample", mimeType: "text/plain", text: "Chapter 1: Choose plants for the light in your garden.", }, }, } satisfies Record; ``` Text blocks can include a `thumbnail` with an MCP Icon shape. The thumbnail path resolves like the `Image` component's public path and stays a URL. The SDK does not fetch thumbnail bytes. ChatGPT iOS currently ignores thumbnails. Image `src` uses the same public path resolver as `Image`, including proxy and asset-host configuration. Absolute URLs pass through the resolver. The SDK fetches the image and converts it to native base64 content before changing the selection. Source responses must contain PNG, JPEG, GIF, or WebP bytes with the matching `Content-Type`. Browser CORS rules apply to remote URLs. You can also supply base64 bytes directly: ```typescript theme={null} import type { ModelContextImage } from "mcp-use/react"; export function bookCoverFromBytes(data: string): ModelContextImage { return { type: "image", title: "Book cover", data, mimeType: "image/png" }; } ``` Use either `src` or `data` plus `mimeType` in an image block. Do not combine these forms. Returned image attachments contain `data` and `mimeType`, even when you supply `src`. During image preparation, `pending` is `true` and the previous selection stays visible. Other ready keys can sync independently. A fetch failure, unsupported or missing `Content-Type`, or empty response rejects the action and preserves the previous attachment. A later `add` or `remove` for the same key, or `clearAttachments`, cancels preparation and returns `"superseded"` for that action. A single image is limited to 10 MiB of decoded bytes, whether supplied through `src` or base64 `data`. Source downloads stop when they exceed that limit, including when the response omits its size. An oversized image rejects without replacing the current selection. This is an SDK memory budget, not a host upload-size guarantee. A late fetch response cannot restore the canceled attachment. Named types include `ModelContextText`, `ModelContextImage`, `ModelContextResourceLink`, and `ModelContextResource`. All are exported from `mcp-use/react`. A resource link uses its native `title` field, which takes precedence over unrelated title metadata. Text and image titles use OpenAI metadata. Embedded-resource titles use SDK metadata; host display of these titles can vary. Raw metadata and annotations are preserved. Conflicting shorthand and wire fields reject. Audio blocks are not supported. ### Respect host removals OpenAI host context can restore surviving attachments when the view initializes. Restored keys start with `@restored:` and belong to that runtime. Use these returned keys to remove restored entries. Do not use the reserved prefix for new keys or infer original keys from titles, resource URIs, or list positions. Confirmed host removals update `attachments` where the SDK can identify the removed blocks. Do not add the same evidence again from a render effect or a cart update. Keep removable evidence out of duplicate `useViewState` values or `ModelContext` descriptions. The optional `audience` field accepts `"user"` and `"assistant"` and maps to MCP annotations. Audience controls presentation. All blocks still reach the model. Assistant-only content can be restored as background instead of a visible attachment. Removal affects current context; it does not erase previous conversation turns or backend data. ### Combine context hooks Render `useModelContext` in the initial view tree when you also use `useViewState` or `ModelContext`. Native delivery activates when the hook commits, before state and description effects; discarded renders do not change delivery. The runtime sends attachments, structured view state, and descriptions through one native writer. State and descriptions keep their model-visible JSON projection. `clearAttachments()` preserves those separate contributions. See [Model context](/v2/typescript/mcp-apps/model-context) to choose a channel for each value. On OpenAI hosts, native host context restores model-visible state after the hook activates. Private widget state keeps its separate persistence channel. Views that do not render `useModelContext` keep their existing widget-state transport. Activation rejects if model-visible widget `modelContent` or `imageIds` already exists, or a widget-state write was dispatched. The SDK does not clear that persisted context for you. Use a view without the conflicting state; reopening alone can retain the conflict. A prior native write must finish, and OpenAI host readback must match the acknowledged context before activation. ### Handle delivery failures A definite host rejection retains the requested selection and sets the shared `error`. The next valid `add`, `remove`, or `clearAttachments` makes one fresh delivery attempt with the current selection. Invalid input and background updates do not trigger another attempt. The public hook has no retry method or automatic retry loop. A successful model-context response does not require an OpenAI `updateId` in its metadata. When present and valid, the SDK uses that ID to correlate a whole context revision. The ID is not an attachment key or a compare-and-swap token. Uncertain transport outcomes or ambiguous host ordering stop further publication and reject subsequent mutations. A request that was already sent cannot be recalled. Wait for outstanding remote writes to finish before you open a fresh view runtime. Another notification or a hook remount does not establish that writes have finished. ### Verify attachment behavior 1. Open the view in the host that your users use. 2. Add a summary and a cover under different keys. Check that both remain selected. 3. Remove one attachment in the view. Check that the other remains. 4. Clear the attachments, then add one again. 5. Where the host supports composer removal, remove an attachment there and check the view's list. 6. Change the cart or filter state. Check that removed evidence does not return. A simulated host can check protocol delivery and errors. Use the native host to check composer chips, thumbnails, and host removal behavior. ## Add global and thread entrypoints Declare `global` to add an app launcher in navigation. Declare `thread` to add a content tab in a conversation. Both launchers send `{}` to the tool. Each conversation has its own thread app instance. ```typescript theme={null} import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "parts-library", version: "1.0.0" }); server.tool( { name: "open_library", title: "Parts library", icons: [ { src: "library.svg", mimeType: "image/svg+xml", sizes: ["20x20"] }, ], inputSchema: z.object({ category: z.string().default("all") }), outputSchema: z.object({ category: z.string() }), view: { name: "library", entrypoints: [{ type: "global" }, { type: "thread" }], }, }, ({ category }) => ({ content: [], structuredContent: { category } }), ); ``` Create `views/library/view.tsx` for this tool. Render the initial tool result in the view. The initial result already contains the launch data. Global and thread tools must accept empty arguments. Use optional fields or defaults for additional inputs. Keep tools with required query inputs separate from launchers. The MCP SDK validates tool calls against the input schema, including custom refinements. Entrypoints open fullscreen in supporting hosts. Entrypoint calls ignore the tool visibility hint. Use a clear tool `title` to name the launcher. ### Set entrypoint tool icons Set `icons` on the tool definition, alongside `name` and `title`, as shown above. Put `library.svg` in `public/`; the SDK emits its absolute asset URL on `tools/list`. Absolute HTTP(S) and image data URLs also work. Follow the [OpenAI icon guidelines](https://github.com/openai/mcp-extensions/blob/main/docs/spec.md#icon-guidelines). Use a monochrome SVG with a transparent background, `currentColor`, and a 20×20 viewport. Use 1.33px strokes for stroke icons. For example, save this book icon as `public/library.svg`: ```xml theme={null} ``` `view.entrypoints` declares launch locations in `_meta["openai/ui"].entrypoints`. The separate top-level `icons` field supplies the tool's artwork. Server constructor `icons` supplies server branding and remains the fallback when a tool has no icon. Hosts prefer tool icons, then the local server icon or hosted app logo, then a generic icon. Call `tools/list` to check the tool's `icons` and fetch each emitted `src`. Test the SVG in light and dark host themes. ## Add a file entrypoint Declare the file extensions that your view supports. Each extension must start with a dot. The host sends `file.name` and `file.resourceUri` to the tool. ```typescript theme={null} import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "csv-viewer", version: "1.0.0" }); const fileInput = z.object({ file: z.object({ name: z.string().min(1), resourceUri: z.string().trim().min(1), }), }); server.tool( { name: "open_csv", title: "CSV viewer", inputSchema: fileInput, outputSchema: fileInput, view: { name: "csv", entrypoints: [{ type: "file", extensions: [".csv"] }], }, }, ({ file }) => ({ content: [], structuredContent: { file } }), ); ``` Create `views/csv/view.tsx` for this tool. The host also sends the file arguments to the view through `ui/notifications/tool-input`. Treat `file.resourceUri` as an opaque host handle. Use the host resource APIs to read the file. The HTML view resource URI identifies the view, not the opened file. Use a non-empty extension list. Require both string fields when `file` is present. Additional input fields must be optional or have defaults. ### Combine entrypoint types One tool can declare all three entrypoint types. For a combined tool, make the outer `file` field optional. Keep `file.name` and `file.resourceUri` required when `file` is present. Replace the CSV tool registration above with this registration: ```typescript theme={null} const combinedInput = fileInput.partial(); server.tool( { name: "open_csv", title: "CSV viewer", inputSchema: combinedInput, outputSchema: combinedInput, view: { name: "csv", entrypoints: [ { type: "global" }, { type: "thread" }, { type: "file", extensions: [".csv"] }, ], }, }, (args) => ({ content: [], structuredContent: args }), ); ``` The view must show an empty screen when the host sends no file. ### Check entrypoint metadata Call `tools/list` to inspect the tool descriptor. The CSV tool advertises these metadata fields: ```json theme={null} { "ui": { "resourceUri": "ui://views/csv.html" }, "openai/ui": { "entrypoints": [{ "type": "file", "extensions": [".csv"] }] } } ``` These fields appear inside the tool's `_meta` object. Typed `view.entrypoints` takes precedence over raw `_meta["openai/ui"].entrypoints`. If you omit the typed field, existing raw entrypoint declarations pass through. ## Read incoming deep links Use `useDeepLink()` to read a route that the host sends to a global entrypoint. The hook uses the view's existing MCP Apps connection. It reads the initial host context and updates when another deep link arrives. ```tsx theme={null} import { useEffect, useState } from "react"; import { useDeepLink } from "mcp-use/react"; export default function LibraryView() { const { url } = useDeepLink(); const [route, setRoute] = useState("/parts"); useEffect(() => { if (url !== undefined) setRoute(url); }, [url]); const incoming = new URL(route, "https://app.example"); if (incoming.pathname === "/parts") { const tag = incoming.searchParams.get("tag"); return (

Parts filter: {tag ?? "all"}

); } if (incoming.pathname === "/parts/hex-bolt") return

Hex bolt

; return

Unknown route

; } ``` The hook returns `{ url: string | undefined }`. An undefined URL means the host has supplied no link. Hosts without deep-link support also return an undefined URL. The hook reads `hostContext["openai/deepLink"].url`. It converts older `path` and `query` payloads to the same URL form. It removes its subscription when the component unmounts. Local route changes do not update the host URL. Validate incoming routes before you load data. Authorize data access on the server. ### Construct a deep link Encode the plugin ID, tool name, and complete app-relative URL. The app-relative URL must start with `/` and must not contain a fragment. ```typescript theme={null} const pluginId = "parts-library"; // Replace with your registered plugin ID. const toolName = "open_library"; const appUrl = "/parts?tag=bolt&sort=asc"; const link = `https://chatgpt.com/plugins/${encodeURIComponent(pluginId)}` + `/app/${encodeURIComponent(toolName)}?path=${encodeURIComponent(appUrl)}`; ``` Desktop links use `codex://plugins//app/?path=`. iOS links use the `chatgpt` scheme. Custom marketplace links include `@` after the plugin ID. See the [deep-link specification](https://github.com/openai/mcp-extensions/blob/main/docs/spec.md#deep-links) for the native formats. ## Composer mention search Register one combined search for app-owned people, files, channels, or other items with `server.mentions`. It returns a normal typed `ToolRef` and requires no View: ```typescript theme={null} import { MCPServer, type ResourceLink } from "mcp-use"; const server = new MCPServer({ name: "workspace", version: "1.0.0" }); const items: ResourceLink[] = [ { type: "resource_link", uri: "workspace://people/u42", name: "andrew", title: "Andrew Khadder", }, { type: "resource_link", uri: "workspace://files/f17", name: "roadmap.md", mimeType: "text/markdown", }, { type: "resource_link", uri: "workspace://channels/c9", name: "engineering", title: "#engineering", }, ]; export const mentionSearch = server.mentions({ name: "workspace.mentions", title: "Search workspace items", search: async ({ query }, ctx) => { // For a downstream search, pass ctx.signal to support cancellation. const needle = query.toLowerCase(); return { items: items.filter((item) => `${item.name} ${item.title ?? ""}`.toLowerCase().includes(needle), ), }; }, }); ``` Register before startup, using a non-blank tool name that does not collide with another tool. Prefer one combined search per plugin; the mention contract defines no selection rule for multiple providers. The helper generates an input schema requiring a string `query` and an output schema requiring `{ items: ResourceLink[] }`, using the official SDK resource-link schema. Queries, including `""` and whitespace, reach your callback unchanged. Normalize, rank, and limit results in your application. An empty query can return initial suggestions or an empty list. Supporting ChatGPT desktop hosts discover the tool through `_meta["openai/extensions"]["mentions/search"] = {}` and call it with ordinary `tools/call`. Success is `{ content: [], structuredContent: { items } }`; no matches returns `items: []`. Invalid input or output and callback errors use the ordinary tool error pipeline. Other hosts may ignore the marker and can still call the tool explicitly. No client capability or iframe handshake is required. `title`, `description`, `icons`, `annotations`, `_meta`, and `visibility` use the ordinary tool descriptor conventions. Search is annotated read-only by default. Visibility defaults to `["app"]`. If you supply top-level `visibility`, it takes precedence over raw `_meta.ui.visibility`; the helper adds `"app"` without duplicates. For example, `visibility: "model"` produces `["model", "app"]`. Unrelated UI and extension metadata survives without mutating your input. The helper has no View option and does not advertise a raw View resource URI. Callbacks receive the same request context, OAuth/sign-in defaults, and `ctx.signal` as ordinary tools. Use verified identity and application permissions to return only items the caller may access. Apply authorization again when resolving or acting on a returned URI: a link identifies an item and does not grant access. Register resources or retrieval tools separately when readable contents are needed; returned links do not automatically enter `resources/list` or guarantee an immediate fetch. Verify native composer insertion separately in a supporting desktop host. ## Add structured settings and actions Register one settings pair before you start the server. `server.settings()` creates read and update tools. The host discovers these tools through the `openai/settings` capability. This example keeps one shared settings object in memory. The object resets when the process restarts. ```typescript theme={null} import { MCPServer } from "mcp-use"; import { z } from "zod"; const server = new MCPServer({ name: "parts-settings", version: "1.0.0" }); let values: { units: "mm" | "in"; showGrid: boolean } = { units: "mm", showGrid: true, }; server.tool( { name: "units_help", title: "Measurement units help", inputSchema: z.object({}), annotations: { readOnlyHint: true }, }, () => ({ content: [ { type: "text", text: "Choose millimeters or inches for dimensions." }, ], }), ); server.settings({ fields: { units: { schema: z.enum(["mm", "in"]), title: "Measurement units" }, showGrid: { schema: z.boolean(), title: "Show grid" }, }, layout: [ { kind: "group", title: "Display", items: [ { kind: "property", property: "units" }, { kind: "property", property: "showGrid" }, { kind: "tool", tool: "units_help", title: "About measurement units" }, ], }, ], read: () => ({ ...values }), update: (set) => { values = { ...values, ...set }; return { ...values }; }, }); ``` For a production app, authorize each callback through its `RequestContext` argument. Scope stored values to the correct account. Persist partial updates atomically before you return all effective values. The framework does not provide storage, account scoping, or concurrency control. The `read` callback receives `ctx`. The `update` callback receives `set` and `ctx`. The context includes `ctx.request`, `ctx.signal`, and `ctx.client`. OAuth servers also expose `ctx.auth`. ### Define fields and layout Register at least one field. Fields support boolean, string, string enum, number, and integer schemas. Use a Standard Schema library with JSON Schema conversion, such as Zod. Give each field a non-blank `title`. You can also supply a `description`. Primitive schema constraints still apply. Use primitive schemas without value transforms. Return an effective value for every field from both callbacks. This rule also applies to optional fields and fields with schema defaults. The wire schema omits default annotations. Apply application defaults in the `read` callback. Use `kind: "property"` for a field control. Use `kind: "tool"` for a same-server action button. Action tools must accept `{}` and exist before the server starts. The MCP SDK validates action arguments when the host calls the tool. The host places fields absent from `layout` in an Other settings group. A regular tool action returns text feedback in settings. A view-bound tool action opens an MCP App modal. See the [structured settings contract](https://github.com/openai/mcp-extensions/blob/main/docs/spec.md#structured-settings) for host behavior. ### Check settings tools The default tool names are `settings.read` and `settings.update`. Set `readTool` and `updateTool` to use distinct, unused names. The registration advertises the pair during modern discovery and legacy initialization. | Call | Arguments | Structured result | | - | - | - | | `settings.read` | `{}` | `{ schema, values, layout? }` | | `settings.update` | `{ set: { showGrid: false } }` | `{ values }` with all fields | Updates preserve fields absent from `set` through your callback. Empty patches, unknown keys, invalid values, and incomplete callback results produce tool errors. ## Set resource display modes Export `viewConfig` directly from `views//view.tsx` to declare supported modes and an initial preference. Build and development tools read the declaration before the view starts. ```tsx theme={null} import type { ViewConfig } from "mcp-use/react"; export const viewConfig = { autoResize: true, displayModes: ["inline", "fullscreen"], preferredDisplayMode: "fullscreen", } satisfies ViewConfig; export default function LibraryView() { return
Parts library
; } ``` `displayModes` must include `inline` and contain no duplicates. The default list is `["inline", "fullscreen", "pip"]`. `autoResize` defaults to `true`. With `autoResize: false`, use `useSendSizeChanged()` to report the view size. `preferredDisplayMode` accepts `inline` or `fullscreen`. The preference must appear in `displayModes`. The preference has no default, and the host can ignore it. Entrypoint launch behavior remains separate from this preference for ordinary tool calls. The HTML resource content advertises the ChatGPT subset in `_meta["openai/ui"]`: ```json theme={null} { "availableDisplayModes": ["inline", "fullscreen"], "preferredDisplayMode": "fullscreen" } ``` The browser advertises the full configured list through MCP Apps capabilities. This list can include `pip` for other hosts. ### Keep the declaration static Use object literals, array literals, local `const` references, and spreads. TypeScript `as` and `satisfies` wrappers also work. Imported values and runtime expressions cause an extraction error when tooling detects the named configuration. Keep the configuration and its shared object or array references immutable. Tooling rejects writes to those references and calls that could mutate them during module initialization, including calls through local helpers. Components can read the configuration through calls such as `useState` and `useMemo` after initialization. > [!WARNING] > > Declare and export `viewConfig` locally in the view module. A value `export *` > without a local configuration causes an extraction error because tooling > cannot resolve the configuration through another module. Type-only wildcard > exports are allowed, as are unrelated value wildcards alongside a local > configuration. ### Request a mode at runtime Use `useDisplayMode()` for mode changes after initialization. Render from the reported `displayMode`. A completed request does not guarantee that the host changed the mode. ```tsx theme={null} import { useDisplayMode } from "mcp-use/react"; export function ExpandButton() { const { displayMode, availableDisplayModes, requestDisplayMode } = useDisplayMode(); if (!availableDisplayModes.includes("fullscreen")) return null; if (displayMode === "fullscreen") return null; return ( ); } ``` `availableDisplayModes` contains the intersection of the view modes and host modes. If the host supplies no mode list, only `inline` is available. Requests for other modes reject before the runtime sends them. ## Verify the integration 1. Call `tools/list` to check entrypoint metadata and settings tool names. 2. Call an entrypoint tool with its expected empty or file arguments. 3. Call `settings.read`, then update one field and check the complete result. 4. Run `npx mcp-use build` to check static `viewConfig` extraction. 5. Read the HTML view resource to check its display metadata. 6. Open the app in a supporting host to check launchers, routes, settings actions, and presentation. Use [MCP Apps interactivity](/v2/typescript/mcp-apps/interactivity) for tool calls and host interactions inside the view. Use [model context](/v2/typescript/mcp-apps/model-context) to share the view state with the model. # Content Security Policy Source: https://docs.mcp-use.com/v2/typescript/mcp-apps/content-security-policy Configure the domains that MCP Apps widgets can load, call, and embed. Content Security Policy (CSP) controls which domains your views can fetch from, load scripts/styles from, and embed. Views run in sandboxed iframes, so CSP must explicitly allow any external resources. ## Server and asset origins Set **`MCP_URL`** to your server's public origin (OAuth resource URL, API calls, CSP `connectDomains`): ```env theme={null} MCP_URL=https://myserver.com ``` Set **`MCP_ASSETS_URL`** when view JS/CSS and `public/` files are served from a different prefix (CDN, Supabase Storage): ```env theme={null} MCP_ASSETS_URL=https://cdn.example.com/storage/v1/object/public/widgets ``` When `MCP_ASSETS_URL` is unset, assets use the same origin as `MCP_URL` (or the request origin behind a proxy). At **`mcp-use build`**, `MCP_ASSETS_URL` rewrites manifest paths to full `https://` URLs for static upload workflows. ## CSP merge order On each `resources/read`, the framework merges CSP in this order (high → low priority): 1. Author `view.csp` on the bound tool 2. `CSP_*_DOMAINS` env vars (per category) or the `CSP_URLS` shortcut 3. MCP auto-append: `MCP_URL` → `connectDomains`; assets origin → `resourceDomains` `CSP_URLS` and per-category env vars rank **above** MCP auto-append. Duplicate origins keep the higher-priority entry's position. ## Add domains for one view Declare CSP on the tool's `view:` config: ```typescript theme={null} server.tool( { name: "weather", view: { name: "weather-display", csp: { connectDomains: ["https://api.weather.com"], resourceDomains: ["https://cdn.weather.com"], frameDomains: ["https://trusted-embed.com"], }, }, }, async () => ({ /* ... */ }), ); ``` MCP Apps CSP fields: `connectDomains`, `resourceDomains`, `frameDomains`, `baseUriDomains`. ## Global CSP env vars Use `CSP_URLS` when every view needs the same extra domains (shortcut for **all four** categories): ```env theme={null} CSP_URLS=https://api.example.com,https://cdn.example.com ``` Override one category without affecting others: ```env theme={null} CSP_CONNECT_DOMAINS=https://api.example.com CSP_RESOURCE_DOMAINS=https://cdn.example.com CSP_FRAME_DOMAINS=https://embed.example.com CSP_BASE_URI_DOMAINS=https://myserver.com ``` ## Static deployments When assets live on static storage and the MCP server runs elsewhere: ```env theme={null} MCP_URL=https://PROJECT.supabase.co/functions/v1/mcp-server MCP_ASSETS_URL=https://PROJECT.supabase.co/storage/v1/object/public/widgets CSP_URLS=https://PROJECT.supabase.co ``` ## Verify CSP The mcp-use Inspector provides a **CSP Mode Toggle** for testing: * **Permissive**: Relaxed CSP for debugging * **Widget-Declared**: Enforces the view's declared CSP (production-like) > [!WARNING] > > CSP violations are logged in the console. Use Widget-Declared mode to catch > CSP issues before production deployment. ## Next Steps * [MCP Apps](/v2/typescript/mcp-apps): View overview and routing * [Self hosted](/v2/typescript/server/deployment/self-hosted): Run an MCP server in Docker # Generative UI Source: https://docs.mcp-use.com/v2/typescript/mcp-apps/generative-ui Create an MCP App that generates UI on the fly Generative UI allows models to create custom UI on the fly through a JSON Schema. ## What you'll build You will create an MCP App that allows for dynamically generated content, powered by [JSON-Render](https://json-render.dev/docs). The app: * gives the model a catalog of allowed components and actions * accepts a type-safe JSON-Render specification as structured input * streams partial specifications into the mounted view * renders the completed specification from `structuredContent` The complete implementation is available in the [`generative-ui` example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/views/generative-ui). For details about catalogs, specifications, and renderers, use the [official JSON-Render documentation](https://json-render.dev/docs). ## How the integration works A JSON-Render catalog defines the components and actions the model can use. The catalog also produces the Zod schema and prompt guidance for the MCP tool. The model writes a JSON-Render `spec` into the tool's structured arguments. While the tool call is pending, MCP Apps hosts send partial arguments to the view through `ui/notifications/tool-input-partial`. After validation, the tool returns the final specification in `structuredContent`. The tool argument must be a structured object. Do not ask the model to stream a stringified JSON document. Structured input lets the MCP host parse and deliver usable partial values without repairing incomplete JSON strings in the view. ## Install JSON-Render Install the JSON-Render core, React renderer, and shadcn component catalog: ```bash theme={null} npm install @json-render/core @json-render/react @json-render/shadcn ``` This guide uses the prebuilt shadcn catalog. You can define a smaller custom catalog when your app needs tighter control over the generated interface. ## Define the component catalog Create `views/generative-ui/catalog.ts` and export one catalog for both the server and the React view: ```ts theme={null} import { defineCatalog } from "@json-render/core"; import { schema } from "@json-render/react/schema"; import { shadcnComponentDefinitions } from "@json-render/shadcn/catalog"; export const catalog = defineCatalog(schema, { components: { ...shadcnComponentDefinitions, }, actions: {}, }); ``` The catalog is the model's UI vocabulary and the runtime validation boundary. Only catalog components can appear in a valid specification. For a production app, expose only the components the model needs. You can also add your own typed component definitions and actions. See [Catalogs in the JSON-Render documentation](https://json-render.dev/docs/catalog). ## Create the generative UI tool Generate the tool's input schema from the catalog instead of maintaining a separate schema: ```ts theme={null} import { MCPServer } from "mcp-use"; import { z } from "zod"; import { catalog } from "../views/generative-ui/catalog.js"; const server = new MCPServer({ name: "generative-ui", version: "1.0.0", }); const specSchema = catalog.zodSchema(); function catalogGuidance(): string { const prompt = catalog.prompt(); const dynamicListsStart = prompt.indexOf("DYNAMIC LISTS (repeat field):"); const componentStart = prompt.indexOf("AVAILABLE COMPONENTS"); if (dynamicListsStart === -1 || componentStart === -1) return prompt; return `STATE MODEL: Put initial values in the top-level spec.state object. Use JSON Pointer paths such as /todos to refer to that state. ${prompt.slice(dynamicListsStart, componentStart)}${prompt.slice(componentStart)}`; } export const renderUi = server.tool( { name: "render-ui", title: "Render UI", description: `Render an interactive UI with the available JSON-Render catalog. Generate one complete structured object in the spec argument. Do not emit JSONL patches or a stringified JSON document. Write spec.root and its root element first, then add referenced elements progressively. Every child reference in the final spec must exist. ${catalogGuidance()}`, inputSchema: z.object({ spec: specSchema.describe( "A JSON-Render specification that streams into the view while it is generated.", ), }), outputSchema: z.object({ spec: specSchema, elementCount: z.number(), }), annotations: { readOnlyHint: true, openWorldHint: false, }, view: { name: "generative-ui", description: "A live generative interface", prefersBorder: false, }, }, async ({ spec }) => { const elementCount = Object.keys(spec.elements).length; return { content: [ { type: "text", text: `Rendered ${elementCount} UI elements.`, }, ], structuredContent: { spec, elementCount }, }; }, ); export default server; ``` The tool description tells the model to write `spec.root` and the root element first. This ordering gives the view enough information to mount before the rest of the element map arrives. > [!WARNING] > > `catalog.prompt()` includes output instructions for JSONL patch streaming. The > `catalogGuidance()` helper removes those instructions because this MCP tool > accepts one structured `spec` object. It preserves the catalog's component, > action, state, and event guidance. Return the final specification in `structuredContent`. The view uses it after the tool completes and on hosts that provide a result without partial tool-input notifications. Keep `content` concise because it is the result the model reads. ## Register the React components Create `views/generative-ui/view.tsx`. Define a registry that maps each catalog component to its React implementation: ```tsx theme={null} import { defineRegistry } from "@json-render/react"; import { shadcnComponents } from "@json-render/shadcn"; import { catalog } from "./catalog.js"; const { registry } = defineRegistry(catalog, { components: { ...shadcnComponents, }, }); ``` The catalog describes what the model may generate. The registry supplies the components that render those names. When you add a custom catalog component, add its React implementation to the registry too. ## Stream the generated interface `useToolContext()` updates `toolInput` as the model generates the structured `spec` argument. Read that live input first, then use the validated `toolOutput` after the call completes: ```tsx theme={null} import { JSONUIProvider, Renderer } from "@json-render/react"; import { ThemeProvider, useToolContext } from "mcp-use/react"; function GenerativeUiContent() { const view = useToolContext<"render-ui">(); if (view.status === "error") { return
{view.error.message}
; } const spec = toRenderableSpec( view.toolInput?.spec ?? (view.status === "ready" ? view.toolOutput.spec : undefined), ); if (!spec) { return
Waiting for a renderable UI spec…
; } return ( ); } export default function GenerativeUi() { return ( ); } ``` The `toRenderableSpec()` helper checks whether the partial input contains a root element and removes elements that have not received their props yet. Copy the helper from the [complete example](https://github.com/mcp-use/mcp-use/blob/main/libraries/typescript/packages/server/examples/views/generative-ui/views/generative-ui/view.tsx) rather than treating a pending value as a complete `Spec`. `loading` tells JSON-Render that referenced children may still be on the way. The view can render the usable part of the interface without warning about missing children. When the host does not send partial input, the loading state remains visible until `structuredContent` arrives. `ThemeProvider` applies the host's color scheme and CSS variables. ## Add state and interactions JSON-Render specifications can include initial state, event bindings, and actions. Describe those capabilities in the tool instructions so the model generates working interactions instead of static controls. For example, an addable task list needs: * an array in `spec.state` * a repeated element bound to that array * an input bound to the new-task value * a button event bound to an action such as `pushState` Only promise an interaction in visible text when the specification contains the matching state and event binding. See the [JSON-Render React API](https://json-render.dev/docs/api/react) for providers, actions, visibility, validation, and state. ## Prepare the integration for production * Keep the catalog limited to components and actions your app supports. * Validate the completed specification with `catalog.zodSchema()`. * Return the final specification through `structuredContent`. * Include a concise text result for the model and hosts without views. * Configure [Content Security Policy](/v2/typescript/mcp-apps/content-security-policy) for external images, APIs, scripts, or embeds. ## Next steps * Run the complete [`generative-ui` example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/views/generative-ui). * Learn how to build a view with the [MCP Apps quickstart](/v2/typescript/mcp-apps/quickstart). * Add tool calls and follow-up messages with [MCP App interactivity](/v2/typescript/mcp-apps/interactivity). * Read the [JSON-Render quick start](https://json-render.dev/docs/quick-start) for custom catalogs and renderers. # Interactivity Source: https://docs.mcp-use.com/v2/typescript/mcp-apps/interactivity Let a View call tools, send follow-up messages, open links, change display modes, and expose actions to the model. Interactions in a View can target the MCP server, the model, the host, or the mounted UI. Choose the API based on where the action should happen. | You want to... | Use | | - | - | | Call a server tool from the View | `useCallTool()` | | Ask the model to continue the conversation | `useSendFollowUp()` | | Open a URL through the host | `useOpenExternal()` | | Change how the host displays the View | `useDisplayMode()` | | Let the model act on the mounted View | `useViewTool()` | ## Call a server tool Use `useCallTool()` when a button, form, or other control should call an MCP tool. The hook provides the last successful result, the latest error, and the current pending state. Export the tool reference returned by `server.tool()` so TypeScript can infer its input and output types in the View. ```tsx theme={null} import { useCallTool } from "mcp-use/react"; export function FruitDetailsButton({ fruit }: { fruit: string }) { const { callTool, data, error, isPending } = useCallTool("get-fruit-details"); async function loadFruitDetails() { try { await callTool({ fruit }); } catch { // The hook exposes the failure through `error`. } } return (
{error &&

{error.message}

} {data &&
{JSON.stringify(data.structuredContent, null, 2)}
}
); } ``` `callTool()` rejects when the tool returns an error or the request fails. The hook also places that failure in `error` so the View can render it. ## Ask the model to continue Use `useSendFollowUp()` when an action requires a new model turn. The prompt appears as a user-authored message in the conversation. ```tsx theme={null} import { useHostContext, useSendFollowUp } from "mcp-use/react"; export function CompareButton({ fruit }: { fruit: string }) { const { hostCapabilities } = useHostContext(); const sendFollowUp = useSendFollowUp(); if (hostCapabilities?.message === undefined) { return null; } return ( ); } ``` The promise resolves when the host accepts the message, not when the model responds. Use `useCallTool()` instead when the View already knows which server operation to perform. ## Open an external link Views run in a sandbox. Use `useOpenExternal()` to ask the host to open a URL outside the View. ```tsx theme={null} import { useHostContext, useOpenExternal } from "mcp-use/react"; export function ProducerLink({ url }: { url: string }) { const { hostCapabilities } = useHostContext(); const openExternal = useOpenExternal(); if (hostCapabilities?.openLinks === undefined) { return null; } return ( ); } ``` The host decides whether and how to open the URL. It may ask the user for confirmation. ## Change the display mode Use `useDisplayMode()` when a View needs more or less space. Only offer modes included in `availableDisplayModes`. ```tsx theme={null} import { useDisplayMode } from "mcp-use/react"; export function ExpandButton() { const { displayMode, availableDisplayModes, requestDisplayMode } = useDisplayMode(); if ( displayMode === "fullscreen" || !availableDisplayModes.includes("fullscreen") ) { return null; } return ( ); } ``` A display-mode request is advisory. Read `displayMode` for the mode the host actually applies. ## Let the model act on the View Use `useViewTool()` to expose an action that operates on the mounted UI. The tool exists while the component is mounted and its handler receives the latest React state. ```tsx theme={null} import { useViewTool } from "mcp-use/react"; import { useState } from "react"; import { z } from "zod"; export function FruitResults() { const [selectedFruit, setSelectedFruit] = useState(); useViewTool( { name: "highlight-fruit", description: "Highlight a fruit in the current results", inputSchema: z.object({ fruit: z.string(), }), }, async ({ fruit }) => { setSelectedFruit(fruit); return { content: [{ type: "text", text: `Highlighted ${fruit}` }], }; }, ); return (

{selectedFruit === undefined ? "No fruit selected" : `Selected: ${selectedFruit}`}

); } ``` `useCallTool()` lets the View call the server. `useViewTool()` lets the host or model call the mounted View. ## Next steps * Use [Model context](/v2/typescript/mcp-apps/model-context) to share View state and visible UI information with the model. * Configure [Content Security Policy](/v2/typescript/mcp-apps/content-security-policy) before connecting to external APIs or loading external assets. # Model context Source: https://docs.mcp-use.com/v2/typescript/mcp-apps/model-context Choose what the model sees from tool results, structured view state, and the currently visible UI. Use model context to give the next model turn the information it needs. Tool results establish the initial context. `useViewState` and `ModelContext` describe the view. `useModelContext` manages selected native attachments. Keep each piece of evidence in one context channel. ## Choose the right channel | Need | Use | | - | - | | Return a concise tool result | A text `content` block | | Send structured render data to the view | Tool-result `structuredContent`, read through `useToolContext` | | Keep structured user choices model-visible | `useViewState` | | Attach selected text, images, or resources | `useModelContext` | | Describe what the user currently sees | `` | | Keep ephemeral UI state private to the iframe | React `useState` | | Persist durable business data | Your backend | ## Attach evidence to the next turn Use `useModelContext()` to add selected text, images, resource links, or embedded resources to the next model turn. The hook shares one attachment collection across the view. You can add, replace, remove, and clear attachments with stable application keys. Read [Attach evidence with ChatGPT Plugin Extensions](/v2/typescript/mcp-apps/chatgpt-extensions#attach-evidence-to-the-next-model-turn) for complete examples, image inputs, and error handling. The guide also explains host removals and how to combine the hook with `useViewState` and `ModelContext`. ## Keep structured choices in view state Use `useViewState` for selections, filters, drafts, and progress that future model turns should understand. ```tsx theme={null} import { useViewState } from "mcp-use/react"; function Filters() { const [state, setState] = useViewState({ selectedCategory: "all", sort: "newest", }); return ( ); } ``` The root state value must be a JSON-serializable object. All components in one mounted view share it. Separate view instances remain isolated. By default, ChatGPT restores state through `window.openai.widgetState`. Other MCP Apps hosts keep state for the current iframe lifetime. After `useModelContext` activates native delivery, OpenAI host context can restore model-visible state and attachments. Private UI persistence remains separate. ## Describe visible UI Use `ModelContext` for natural-language descriptions that follow the React component lifecycle. ```tsx theme={null} import { ModelContext } from "mcp-use/react"; function Dashboard() { return ( ); } ``` Nested components serialize into an indented tree: ```text theme={null} - Dashboard - Revenue chart is visible - Three alerts are unresolved ``` For descriptions from event handlers or other callbacks, store the description in React state and render it with `ModelContext`: ```tsx theme={null} import { useState } from "react"; import { ModelContext } from "mcp-use/react"; function ProductPicker() { const [selection, setSelection] = useState(null); return ( <> {selection && } ); } ``` ## Understand the merged snapshot The runtime merges structured state and the serialized context tree into one complete object: ```json theme={null} { "selectedCategory": "audio", "sort": "price", "_uiContext": "- Dashboard\n - Revenue chart is visible" } ``` `_uiContext` is a reserved model-visible field. `useViewState` filters it from application state and rejects developer state with the same key. Every write sends the complete snapshot. On MCP Apps hosts, mcp-use sends the object as `structuredContent` and a JSON text block as `content` through `ui/update-model-context`. On ChatGPT, views without `useModelContext` write the object to `modelContent` with `window.openai.setWidgetState`. Views with `useModelContext` use the shared native writer described in [ChatGPT Plugin Extensions](/v2/typescript/mcp-apps/chatgpt-extensions#combine-context-hooks). ## Keep ephemeral values local Use React `useState` for transient details that the model does not need, such as hover state, open tooltips, or animation progress. ```tsx theme={null} import { useState } from "react"; function HoverPreview() { const [hoveredId, setHoveredId] = useState(null); return ( ); } ``` ## Next steps * Use [ChatGPT Plugin Extensions](/v2/typescript/mcp-apps/chatgpt-extensions#attach-evidence-to-the-next-model-turn) to add and remove selected evidence. * Read the [`useViewState` API reference](https://mcp-use-typescript-api-reference.vercel.app/modules/mcp-use.react.html#useviewstate) for signatures, errors, and host behavior. * Read the [`ModelContext` API reference](https://mcp-use-typescript-api-reference.vercel.app/modules/mcp-use.react.html#modelcontext) for lifecycle and nesting. * Use [Interactivity](/v2/typescript/mcp-apps/interactivity) for tool calls and follow-up messages. # Build your first MCP App Source: https://docs.mcp-use.com/v2/typescript/mcp-apps/quickstart Create, run, and verify an MCP App with a view-bound tool. Create a TypeScript MCP App, run it locally, and verify that a tool returns a React view in the Inspector. ## What you'll build This guide creates a local server with: * an MCP endpoint at `http://localhost:3000/mcp` * an Inspector at `http://localhost:3000/mcp/inspector` * a `show-app` tool that returns a view * a `say-hello` tool that the view calls * a React view at `views/my-view/view.tsx` ## Prerequisites * Node.js 22.22.2 or higher * Basic TypeScript and React knowledge ## Create the project Run the MCP Apps template and install its dependencies: ```bash theme={null} npx create-mcp-use-app@latest my-mcp-app --template mcp-apps --install cd my-mcp-app ``` With a project name and `--template`, the scaffolder does not prompt, and it installs dependencies only with `--install`. If you omit `--install`, run `npm install` in the project before you start the server. The scaffolder also installs the `mcp-apps-builder` coding-agent skill, which requires Git. Pass `--no-skills` to skip it. The template also creates `README.md`, `.gitignore`, and the installed coding-agent skills. These are the files you edit most often: ```text theme={null} my-mcp-app/ ├── index.ts ├── mcp-env.d.ts ├── views/ │ └── my-view/ │ ├── view.tsx │ ├── view.css │ ├── icons.tsx │ ├── MeshGradient.tsx │ └── Tooltip.tsx ├── public/ │ ├── icon.svg │ └── logo-mcp-use.svg ├── package.json └── tsconfig.json ``` `public/icon.svg` is the server icon declared in `index.ts`. The view renders `public/logo-mcp-use.svg` with the `Image` component from `mcp-use/react`, which resolves root-relative paths against the `public/` folder. ## Run the server Start the development server: ```bash theme={null} npm run dev ``` This starts the MCP server, view build pipeline, and Inspector. Keep the process running while you test the app. ## Inspect the view tool Open `index.ts` and find the `show-app` tool. The template also configures server branding and registers a second tool, `say-hello`, without a view. This excerpt shows the view-bound path you need to understand first. ```typescript theme={null} // index.ts excerpt; server and z are defined above. const showAppInputSchema = z.object({ appName: z .string() .optional() .describe( "Optional title shown in the MCP App card instead of the default", ), }); const showAppOutputSchema = z.object({ message: z.string().describe("Message to display in the MCP App"), }); export const showApp = server.tool( { name: "show-app", title: "Show MCP App", description: "Display the MCP App starter view", inputSchema: showAppInputSchema, outputSchema: showAppOutputSchema, view: { name: "my-view", description: "MCP App starter card with interactive demo hooks", prefersBorder: false, csp: { resourceDomains: [ "https://fonts.googleapis.com", "https://fonts.gstatic.com", ], }, }, annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false, }, }, async ({ appName }, ctx) => { // Brief delay so the pending skeleton is visible during dev/inspector demos. await new Promise((resolve) => setTimeout(resolve, 1500)); console.log(`The app name was: ${appName}`); const data = { message: `The MCP App starter for ${appName} is ready!` }; return { content: [{ type: "text", text: data.message }], structuredContent: data, }; }, ); ``` `view.name` must match the folder under `views/`. In this template, `my-view` maps to `views/my-view/view.tsx`. A view-bound tool must declare an `outputSchema`. The `structuredContent` object becomes view rendering data via `useToolContext()`. The `content` array is the short text result the model can read. `view.csp` allows the Google Fonts stylesheet that `view.css` imports. See [Content Security Policy](/v2/typescript/mcp-apps/content-security-policy) for the other domain categories. The `say-hello` tool returns `{ greeting }` in `structuredContent` and has no view. The view calls it with `useCallTool()`. Both tools are assigned to exported constants. The generated `mcp-env.d.ts` reads these exports to type `useToolContext<"show-app">()` and `useCallTool("say-hello")` in the view. ## Inspect the React view Open `views/my-view/view.tsx`. The view reads the tool invocation with `useToolContext()` and wraps its content in `ThemeProvider`, which applies the host theme. The generated view also shows host context, display-mode buttons, external links, a follow-up message button, and a `set-counter` tool that the host can call while the view is mounted. This condensed excerpt keeps the template's data access and the **Update State** and **Say Hello** controls, without styling and decorative markup. ```tsx theme={null} import { ModelContext, ThemeProvider, useCallTool, useToolContext, } from "mcp-use/react"; import { useState } from "react"; export default function McpApp() { const view = useToolContext<"show-app">(); const sayHello = useCallTool("say-hello"); const [count, setCount] = useState(0); const pending = view.status === "pending"; const callResult = sayHello.data?.structuredContent?.greeting; return ( {view.status === "error" ? ( <>

Failed to load MCP App

{view.error.message}

) : ( <> {!pending && }

{view.toolInput?.appName?.trim() || "MCP App"}

{!pending && callResult !== undefined && (

Tool Response: {callResult}

)} {!pending && sayHello.error !== undefined && (

{sayHello.error.message}

)} )}
); } ``` Views can render before the tool finishes. While `status` is `"pending"`, `toolInput` can hold partial arguments, so the heading reads `appName` from it. The starter view does not render the tool output. After you check `status === "ready"`, `view.toolOutput.message` holds the message from `structuredContent`. `ModelContext` describes the current counter to the model. See [Model context](/v2/typescript/mcp-apps/model-context) for the available channels. ## Verify in the Inspector Use the Inspector to confirm that the server and view work. 1. Open `http://localhost:3000/mcp/inspector`. 2. Go to the **Tools** tab. 3. Select `show-app`. 4. Run the tool with `{ "appName": "My App" }`. Without `appName`, the result message contains `undefined`. 5. Confirm that the view renders below the tool result and its heading shows "My App". The handler waits 1.5 seconds, so the view can show a loading skeleton first. 6. Select **Say Hello** in the view. Confirm that it shows `Tool Response: Hello, mcp-use!`. If the tool runs but no view appears, check that `view.name` exactly matches the folder under `views/` and that the handler returns `structuredContent`. ## Next steps * Use [`useToolContext()`](https://mcp-use-typescript-api-reference.vercel.app/modules/mcp-use.react.html#usetoolcontext) to read tool input, output, and lifecycle status. * Use [`useCallTool()`](https://mcp-use-typescript-api-reference.vercel.app/modules/mcp-use.react.html#usecalltool) when a view needs to call another MCP tool. See [Interactivity](/v2/typescript/mcp-apps/interactivity) for follow-up messages, external links, display modes, and view tools. * Configure [Content Security Policy](/v2/typescript/mcp-apps/content-security-policy) before loading external APIs, images, scripts, embeds, or static assets. # OAuth Source: https://docs.mcp-use.com/v2/typescript/server/authentication/index Choose and configure OAuth authentication for MCP servers. Configure an OAuth provider when an MCP server must identify callers or authorize access by user, organization, role, scope, or permission. `MCPServer` protects the transport, publishes discovery metadata, verifies bearer tokens, and exposes the verified identity on `ctx.auth`. ## Choose a provider Pick the provider for your identity system. Most providers run an authorization server that supports Dynamic Client Registration (DCR), and your MCP server only verifies their tokens. For a provider without DCR, such as GitHub or Google, use the OAuth Proxy: your MCP server becomes the authorization server itself. | Identity system | Provider | | - | - | | Auth0 | [Auth0](/v2/typescript/server/authentication/providers/auth0) | | Better Auth | [Better Auth](/v2/typescript/server/authentication/providers/better-auth) | | Clerk | [Clerk](/v2/typescript/server/authentication/providers/clerk) | | Convex | [Convex](/v2/typescript/server/authentication/providers/convex) | | Keycloak | [Keycloak](/v2/typescript/server/authentication/providers/keycloak) | | Supabase | [Supabase](/v2/typescript/server/authentication/providers/supabase) | | WorkOS | [WorkOS](/v2/typescript/server/authentication/providers/workos) | | Scalekit | [Scalekit](/v2/typescript/server/authentication/providers/scalekit) | | Another DCR-capable authorization server | [Custom Provider](/v2/typescript/server/authentication/providers/custom) | | GitHub, Google, or another provider without DCR | [OAuth Proxy](/v2/typescript/server/authentication/providers/oauth-proxy) | With a DCR provider, the MCP client registers and performs the authorization flow directly with the authorization server. Your MCP server does not handle authorization codes or exchange them for tokens. With the OAuth Proxy, your MCP server runs that flow: it shows a consent page, signs the user in upstream as one OAuth app, and issues its own tokens. ## Configure the server Import the server from `mcp-use` and the provider from its dedicated OAuth entry point, then pass the provider's settings as options. ```typescript theme={null} import { MCPServer } from "mcp-use"; import { oauthAuth0Provider } from "mcp-use/oauth/auth0"; const domain = process.env.AUTH0_DOMAIN; if (!domain) throw new Error("AUTH0_DOMAIN is required"); const server = new MCPServer({ name: "secure-server", version: "1.0.0", oauth: oauthAuth0Provider({ domain }), }); export default server; ``` When you omit an option, each provider in the table below reads the matching `MCP_USE_OAUTH_*` environment variable instead. With the variables set, you can call the factory with no arguments, for example `oauthAuth0Provider()`. An option you pass always takes precedence over its variable. | Provider | Environment variables (option they replace) | | - | - | | Auth0 | `MCP_USE_OAUTH_AUTH0_DOMAIN` (`domain`), `MCP_USE_OAUTH_AUTH0_AUDIENCE` (`resource`) | | Better Auth | `MCP_USE_OAUTH_BETTER_AUTH_URL` (`authURL`) | | Clerk | `MCP_USE_OAUTH_CLERK_FRONTEND_API_URL` (`frontendApiUrl`) | | Convex | `MCP_USE_OAUTH_CONVEX_AUTH_URL` (`authURL`) | | Keycloak | `MCP_USE_OAUTH_KEYCLOAK_SERVER_URL` (`serverUrl`), `MCP_USE_OAUTH_KEYCLOAK_REALM` (`realm`), `MCP_USE_OAUTH_KEYCLOAK_AUDIENCE` (`resource`) | | Scalekit | `MCP_USE_OAUTH_SCALEKIT_ENVIRONMENT_URL` (`environmentUrl`), `MCP_USE_OAUTH_SCALEKIT_RESOURCE_ID` (`resourceId`) | | Supabase | `MCP_USE_OAUTH_SUPABASE_PROJECT_ID` (`projectId`), `MCP_USE_OAUTH_SUPABASE_URL` (`supabaseUrl`), `MCP_USE_OAUTH_SUPABASE_JWT_SECRET` (`jwtSecret`) | | WorkOS | `MCP_USE_OAUTH_WORKOS_SUBDOMAIN` (`subdomain`) | The OAuth Proxy reads only `MCP_USE_OAUTH_SECRET`, for its `secret` option, and always needs `upstream`. See [OAuth Proxy](/v2/typescript/server/authentication/providers/oauth-proxy). The Auth0 and Keycloak `*_AUDIENCE` variables become the provider's `resource` when you don't pass one, so they override `MCP_URL`. The value must be the full MCP endpoint URL, with a path equal to `basePath` (default `/mcp`), or the server throws at startup. The provider binds token verification to the resolved MCP resource. Set `MCP_URL` to the public server origin in production, or pass the provider's `resource` option when you need an explicit canonical MCP endpoint. ## Authorize a tool An OAuth-configured server gives tool callbacks a provider-specific `ctx.auth.user`. All built-in providers normalize the stable subject to `id`; additional fields depend on the provider. The OAuth Proxy exposes the upstream user as `{ subject, profile }` unless you reshape it with `mapUser`. ```typescript theme={null} server.tool( { name: "get_profile", description: "Return the authenticated caller.", }, async (_args, ctx) => { const profile = { id: ctx.auth.user.id, email: ctx.auth.user.email ?? null, scopes: ctx.auth.scopes, permissions: ctx.auth.permissions, }; return { content: [{ type: "text", text: JSON.stringify(profile) }], }; }, ); ``` `scopes` come from the verified SDK auth information. `permissions` and `user` come from the provider's verified claim mapping. Use [User Context](/v2/typescript/server/authentication/user-context) for the complete shape and authorization patterns. ## What OAuth changes When `oauth` is configured: * protected-resource and authorization-server metadata are published for clients; * MCP transport requests require a bearer token; * invalid, expired, incorrectly resourced tokens, and tokens missing configured `requiredScopes` are rejected before tool code runs; * callbacks receive the verified access token, identity, scopes, permissions, expiry, client ID when present, and resource. To let clients connect and call some tools before signing in, add `mixedAuth: true` and declare `securitySchemes` with `{ type: "noauth" }` on each public or optional tool. See [Mixed Authentication](/v2/typescript/server/authentication/mixed-auth). ## Next steps > **[User Context](/v2/typescript/server/authentication/user-context)** > > Use verified identity and authorization data inside callbacks. > **[Mixed Authentication](/v2/typescript/server/authentication/mixed-auth)** > > Serve public, optional, and sign-in tools from one endpoint. > **[Custom Provider](/v2/typescript/server/authentication/providers/custom)** > > Integrate another DCR-capable authorization server. > **[OAuth Proxy](/v2/typescript/server/authentication/providers/oauth-proxy)** > > Sign users in with GitHub, Google, or another provider without DCR. > **[Client Authentication](/v2/typescript/client/authentication)** > > Connect a TypeScript MCP client to an OAuth-protected server. # Mixed Authentication Source: https://docs.mcp-use.com/v2/typescript/server/authentication/mixed-auth Serve public, optional, and sign-in tools from one OAuth-enabled mcp-use TypeScript server that works in Claude and ChatGPT. Mixed authentication lets one MCP server URL expose tools that anyone can use next to tools that need sign-in. Clients connect and list tools without signing in. The server asks for sign-in only when a signed-out user calls a tool that needs it, and the client signs the user in and retries. A shop is the typical case: people browse the catalog without an account and sign in when they check out. The same server works in Claude and ChatGPT. ## Enable mixed authentication Keep the `oauth` provider on the server, add `mixedAuth: true`, and declare `securitySchemes` on each tool that does not need sign-in. ```typescript theme={null} import { MCPServer } from "mcp-use"; import { oauthWorkOSProvider } from "mcp-use/oauth/workos"; import { z } from "zod"; const server = new MCPServer({ name: "shop", version: "1.0.0", oauth: oauthWorkOSProvider({ subdomain: process.env.WORKOS_SUBDOMAIN!, requiredScopes: ["shop"], }), // Anyone can connect and list tools. Each tool's securitySchemes decides who can call it. mixedAuth: true, }); // Public: anyone can browse. server.tool( { name: "browse_catalog", description: "Browse the product catalog.", securitySchemes: [{ type: "noauth" }], }, async () => ({ content: [{ type: "text", text: "Coffee, Tea, Cocoa" }], }), ); // Sign-in with an extra scope. Refused before the callback runs unless the // token carries "checkout" plus the provider's requiredScopes. server.tool( { name: "create_checkout", description: "Create a checkout for the selected products.", inputSchema: z.object({ productIds: z.array(z.string()).min(1) }), securitySchemes: [{ type: "oauth2", scopes: ["checkout"] }], }, async ({ productIds }, ctx) => ({ content: [ { type: "text", text: await createCheckout(productIds, ctx.auth.user.id), }, ], }), ); // Omitted: sign-in with the provider's requiredScopes. server.tool( { name: "order_history", description: "List the signed-in user's orders." }, async (_args, ctx) => ({ content: [{ type: "text", text: await ordersFor(ctx.auth.user.id) }], }), ); export default server; ``` WorkOS is only the example. Every mcp-use OAuth provider supports mixed authentication. * `mixedAuth` requires an `oauth` provider. Setting it without one is a type error and throws a `TypeError` at construction. It is a constructor option, not a provider option. * `mixedAuth` does not make anything public. Tools without `securitySchemes` still require sign-in, and resources and prompts always do. Only the tools' views load signed out. * With `mixedAuth` off (the default), every request to the MCP endpoint needs a valid token. * Every tool stays in `tools/list` for every caller. A signed-out user must see a sign-in tool, or the model never calls it and sign-in never starts. * A server with `mixedAuth: true` and no `noauth` tools is valid. Anyone can connect and see what it offers, and every call needs sign-in. Directories and indexers can probe it before anyone signs in. ## Declare `securitySchemes` on a tool `securitySchemes` is an array of schemes the tool accepts. It uses the same shape ChatGPT reads on `tools/list`. There are two scheme types: * `{ type: "noauth" }`: the tool runs without a token. * `{ type: "oauth2", scopes }`: the tool accepts a bearer token with `scopes` plus the provider's `requiredScopes`. `scopes` is required; use `[]` for the provider's `requiredScopes` alone. The provider's `requiredScopes` is the baseline for every sign-in check. | `securitySchemes` | Who can call the tool | `ctx.auth` | | - | - | - | | `[{ type: "noauth" }]` | Anyone. A token, if sent, is still verified | possibly undefined | | `[{ type: "noauth" }, { type: "oauth2", scopes }]` | Anyone. The scopes are advertised, and the callback checks them | possibly undefined | | `[{ type: "oauth2", scopes }]` | Signed-in callers whose token has every listed scope and the baseline | required | | omitted | Signed-in callers whose token has the baseline | required | * A tool requires sign-in unless its `securitySchemes` include `noauth`. * A token that is sent is always verified, even on `noauth` tools. An invalid or expired token gets `401` so the client refreshes it instead of silently getting the signed-out result. * `noauth` requires `mixedAuth: true`. * `oauth2` requires an OAuth provider. It also works without `mixedAuth`; see [Without `mixedAuth`](#without-mixedauth). * `scopes: []` requires the provider to have `requiredScopes`. * The order of the array does not matter. Each type may appear once. ## Optional tools An optional tool accepts both `noauth` and `oauth2`. It runs for everyone and branches on `ctx.auth`. ```typescript theme={null} server.tool( { name: "recommend_products", description: "Suggest products. Personalized when the user is signed in.", securitySchemes: [{ type: "noauth" }, { type: "oauth2", scopes: [] }], }, async (_args, ctx) => { if (!ctx.auth) { return { content: [ { type: "text", text: `Bestsellers: ${await bestsellers()}` }, ], }; } const history = await orderHistory(ctx.auth.user.id); return { content: [ { type: "text", text: `Picked for you: ${await recommendFrom(history)}`, }, ], }; }, ); ``` | Request | Result | | - | - | | No token | The callback runs with no `ctx.auth` and returns bestsellers | | Valid token | The callback runs with `ctx.auth` set and returns personalized picks | | Expired or invalid token | Refused with `401` (or the ChatGPT error result) before the callback runs | ### Optional tools with scopes The `oauth2` scopes of an optional tool advertise what unlocks more, but never refuse a caller. The server does not check them, even for a signed-in token that lacks them, so the callback checks them itself. ```typescript theme={null} server.tool( { name: "recommend_products", securitySchemes: [ { type: "noauth" }, { type: "oauth2", scopes: ["orders:read"] }, ], }, async (_args, ctx) => { // Check the scope, not just ctx.auth: a signed-in token may lack orders:read. if (ctx.auth?.scopes.includes("orders:read")) { return personalized(ctx.auth.user.id); } return bestsellersResult(); }, ); ``` A signed-in user without the scope gets the same result as a signed-out user. That is common: the user signed in earlier for a tool that needed fewer scopes, or declined a scope on the consent screen. > [!NOTE] > > An optional tool cannot bring up a sign-in prompt. Its result text can tell > the user to sign in, but the prompt only appears when the user calls a sign-in > tool, or signs in or reconnects from the host. ## `ctx.auth` types `server.tool()` reads the literal `securitySchemes` value. A tool that requires sign-in gets a required `ctx.auth`, and a tool that accepts `noauth` gets one that is possibly `undefined`. ```typescript theme={null} server.tool( { name: "browse_catalog", securitySchemes: [{ type: "noauth" }] }, (_args, ctx) => { const id: string | undefined = ctx.auth?.user.id; return { content: [] }; }, ); server.tool({ name: "order_history" }, (_args, ctx) => { const id: string = ctx.auth.user.id; // signed-out calls never reach here return { content: [] }; }); ``` When `securitySchemes` comes from a variable typed as `ToolSecurityScheme[]`, the array could include `noauth`, so `ctx.auth` is typed as possibly `undefined`. Write the array inline, or declare the variable `as const`, to get a required `ctx.auth`. ## Resources, prompts, and views Resources, resource templates, and prompts have no `securitySchemes`. On an OAuth server they always require sign-in with the provider's `requiredScopes`, and their callbacks always get a required `ctx.auth`. * `resources/read`, `prompts/get`, `completion/complete`, and `resources/subscribe` require sign-in. The list methods are always open on a `mixedAuth` server. * Every tool's view loads signed out on a `mixedAuth` server, whatever the tool's `securitySchemes`. ChatGPT reads every view while an app is created, before anyone signs in, and a refused read blocks creation. A view is static UI; the data arrives in the tool result, which the tool's `securitySchemes` still gate. * `subscriptions/listen` is open signed out only when it subscribes to no resources, so it carries only list-changed notifications. * A refused resource read or prompt fetch always gets HTTP `401` or `403`. > [!WARNING] > > Whether Claude or ChatGPT shows a sign-in prompt when a resource read or > prompt fetch is refused is untested. Both hosts document sign-in prompts only > for tool calls. ## Signed-out requests On a `mixedAuth` server, a signed-out caller can always send: * `initialize` (2025-era protocols) and `server/discover` (2026-07-28); * `ping` and `logging/setLevel`, which read no data; * `tools/list`, `resources/list`, `resources/templates/list`, and `prompts/list`; * `resources/read` of a tool's view; * `subscriptions/listen` without resource subscriptions; * notifications; * an HTML browser request for the landing page at the MCP path. `tools/call` follows the tool's `securitySchemes`. Unknown tools require sign-in. Every other method, including `resources/read` of other resources, `prompts/get`, `tasks/*`, and the skills methods, requires sign-in. ## How hosts see a refused call The server refuses a call before the callback runs. Claude and ChatGPT need the refusal in different forms, so mcp-use picks the format from the `User-Agent` header. * **Claude and other spec clients** start OAuth only from HTTP `401`, or from `403` with `error="insufficient_scope"`, with a `WWW-Authenticate` header. Claude treats a `200` with `isError: true` as an ordinary tool failure. * **ChatGPT** needs `securitySchemes` on each tool in `tools/list`, then a `200` tool result with `isError: true` and `_meta["mcp/www_authenticate"]`. It does not start OAuth from a `401` on a tool call. A refused `tools/call` from a `User-Agent` that matches `chatgpt` or `openai` (case-insensitive) gets the tool-result format. Every other `tools/call`, including one without a `User-Agent`, and every refusal of another method gets HTTP. No token: ```http theme={null} HTTP/1.1 401 Unauthorized WWW-Authenticate: Bearer error="invalid_token", error_description="Authentication is required for this request.", scope="shop checkout", resource_metadata="https://shop.example.com/.well-known/oauth-protected-resource/mcp" ``` Token missing a scope: ```http theme={null} HTTP/1.1 403 Forbidden WWW-Authenticate: Bearer error="insufficient_scope", error_description="Additional permissions are required: checkout.", scope="shop checkout", resource_metadata="https://shop.example.com/.well-known/oauth-protected-resource/mcp" ``` ChatGPT, no token: ```json theme={null} { "jsonrpc": "2.0", "id": 7, "result": { "content": [ { "type": "text", "text": "Authentication is required for this request." } ], "isError": true, "_meta": { "mcp/www_authenticate": [ "Bearer error=\"invalid_token\", error_description=\"Authentication is required for this request.\", scope=\"shop checkout\", resource_metadata=\"https://shop.example.com/.well-known/oauth-protected-resource/mcp\"" ] } } } ``` * `scope` is the full set the call needs, the baseline plus the tool's scopes, not only the missing ones. Claude does not reliably remember scopes from an earlier step-up. * The messages are fixed defaults. An invalid or expired token carries the verifier's reason instead. * Ordinary callback errors, such as an out-of-stock product, are ordinary tool results and never start OAuth. ## Tool list metadata mcp-use advertises the resolved `securitySchemes` for every tool on a `mixedAuth` server, and for every tool that declares `securitySchemes` on other servers. The schemes appear at the top level of each tool, where ChatGPT reads them, and are mirrored in `_meta.securitySchemes`. The advertised `oauth2` scopes include the provider's `requiredScopes`, and `noauth` comes first. | Declared `securitySchemes` | Advertised `securitySchemes` | | - | - | | `[{ type: "noauth" }]` | `[{ type: "noauth" }]` | | `[{ type: "noauth" }, { type: "oauth2", scopes }]` | `[{ type: "noauth" }, { type: "oauth2", scopes: baseline + scopes }]` | | `[{ type: "oauth2", scopes }]` | `[{ type: "oauth2", scopes: baseline + scopes }]` | | omitted | `[{ type: "oauth2", scopes: baseline }]` | ```json theme={null} { "name": "create_checkout", "inputSchema": { "type": "object", "properties": { "productIds": { "type": "array" } } }, "securitySchemes": [{ "type": "oauth2", "scopes": ["shop", "checkout"] }], "_meta": { "securitySchemes": [{ "type": "oauth2", "scopes": ["shop", "checkout"] }] } } ``` ChatGPT ignores an `oauth2` scheme with an empty scope list. Give the provider `requiredScopes` so tools without `securitySchemes`, and optional tools with `scopes: []`, advertise a scope. ### Hand-written `_meta.securitySchemes` Some servers already set `_meta.securitySchemes` on tools by hand for ChatGPT. mcp-use keeps it working and never enforces it. | Case | Behavior | | - | - | | Tool without `securitySchemes`, server without `mixedAuth` | Passed through unchanged | | Tool without `securitySchemes` on a `mixedAuth` server | Passed through unchanged, with a warning. The tool still requires sign-in | | Tool that also declares `securitySchemes` | Replaced by the declared schemes, with a warning when the two differ | Move the value to the top-level `securitySchemes` field to have mcp-use enforce it. ## Invalid configurations These throw a `TypeError` at construction or registration instead of failing at request time. | Configuration | Why it is rejected | | - | - | | `mixedAuth: true` without `oauth` | Nothing to sign in with. Also a type error | | `noauth` without `mixedAuth` | Every request needs a token, so the tool could never be called signed out | | `oauth2` without `oauth` | No provider to verify tokens | | `oauth2` with `scopes: []` when the provider has no `requiredScopes` | ChatGPT ignores an `oauth2` scheme with empty scopes, so it would never offer sign-in | | An empty array, or a scheme type that appears twice | Omit the field for the default; one challenge can only ask for one scope set | | A scope that is not a single printable-ASCII RFC 6749 scope token (empty, whitespace, `"`, `\`, or non-ASCII) | Scopes are space-separated in challenges and tokens, so the value could never match a granted scope | | An unknown scheme type or field | Includes typos such as `scope` for `scopes` | ## Without `mixedAuth` `oauth` without `mixedAuth` keeps endpoint-wide authentication: every request needs a token with the provider's `requiredScopes`. * `securitySchemes: [{ type: "oauth2", scopes }]` still works on tools. Those scopes are enforced on top of the baseline. * Tools that declare `securitySchemes` advertise them. Tools without it advertise nothing, unless they set `_meta.securitySchemes` by hand. * `noauth` throws at registration. ## Verify locally The [mixed-oauth example](https://github.com/mcp-use/mcp-use/tree/canary/libraries/typescript/packages/server/examples/auth/mixed-oauth) runs a Better Auth authorization server and a `mixedAuth` server on `http://localhost:3000/mcp`, with a tool for every `securitySchemes` shape. Its names start with their access level: `public_ping` is public, `optional_welcome` is optional with the `profile` scope, and `protected_profile` omits `securitySchemes`. From the example's directory: ```bash theme={null} pnpm dev ``` Call the public tool without a token. The response is `200` with the tool result: ```bash theme={null} curl -s http://localhost:3000/mcp \ -H 'content-type: application/json' \ -H 'accept: application/json, text/event-stream' \ -H 'mcp-protocol-version: 2026-07-28' \ -H 'mcp-method: tools/call' -H 'mcp-name: public_ping' \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"public_ping","arguments":{},"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"curl","version":"0"},"io.modelcontextprotocol/clientCapabilities":{}}}}' ``` Call the sign-in tool without a token. The response is `401` with `WWW-Authenticate`: ```bash theme={null} curl -si http://localhost:3000/mcp \ -H 'content-type: application/json' \ -H 'accept: application/json, text/event-stream' \ -H 'mcp-protocol-version: 2026-07-28' \ -H 'mcp-method: tools/call' -H 'mcp-name: protected_profile' \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"protected_profile","arguments":{},"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"curl","version":"0"},"io.modelcontextprotocol/clientCapabilities":{}}}}' ``` Send the same call as ChatGPT. The response is `200` with an `isError` result and `_meta["mcp/www_authenticate"]`: ```bash theme={null} curl -s http://localhost:3000/mcp \ -H 'user-agent: ChatGPT/1.0' \ -H 'content-type: application/json' \ -H 'accept: application/json, text/event-stream' \ -H 'mcp-protocol-version: 2026-07-28' \ -H 'mcp-method: tools/call' -H 'mcp-name: protected_profile' \ -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"protected_profile","arguments":{},"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"curl","version":"0"},"io.modelcontextprotocol/clientCapabilities":{}}}}' ``` To test the full sign-in and retry loop in Claude or ChatGPT, run the example with `pnpm dev --tunnel`, restart it with `MCP_URL` set to the tunnel's origin, and add the tunnel's `/mcp` URL as a custom connector in Claude or under Plugins → Add → Add Custom MCP Server in ChatGPT. The example's README lists every item and a test checklist. ## Next steps > **[OAuth](/v2/typescript/server/authentication/index)** > > Choose and configure an OAuth provider. > **[User Context](/v2/typescript/server/authentication/user-context)** > > Read identity, scopes, and permissions inside callbacks. # Auth0 Provider Source: https://docs.mcp-use.com/v2/typescript/server/authentication/providers/auth0 Configure Auth0 Dynamic Client Registration authentication for an MCP server. Use `oauthAuth0Provider` when Auth0 is the authorization server. MCP clients register directly with Auth0, and mcp-use verifies Auth0 access tokens against the resolved MCP resource. ## Configure Auth0 In the [Auth0 Dashboard](https://manage.auth0.com): 1. Enable the Resource Parameter Compatibility Profile. 2. Promote the login connections MCP clients may use to domain-level connections. 3. Create an API whose identifier is the canonical MCP resource, such as `https://mcp.example.com/mcp`. 4. Use the `rfc9068_profile_authz` token dialect if tools need Auth0 permissions in access tokens. The API identifier must match the resource that mcp-use resolves for token verification. The provider has no `audience` option; it checks the token audience against that resource. ## Configure the server Pass `domain` explicitly, as below, or set `MCP_USE_OAUTH_AUTH0_DOMAIN` and call `oauthAuth0Provider()` without it. ```bash theme={null} AUTH0_DOMAIN=https://your-tenant.us.auth0.com MCP_URL=https://mcp.example.com ``` ```typescript theme={null} import { MCPServer } from "mcp-use"; import { oauthAuth0Provider } from "mcp-use/oauth/auth0"; const domain = process.env.AUTH0_DOMAIN; if (!domain) throw new Error("AUTH0_DOMAIN is required"); const server = new MCPServer({ name: "auth0-server", version: "1.0.0", oauth: oauthAuth0Provider({ domain }), }); export default server; ``` > [!WARNING] > > When `MCP_USE_OAUTH_AUTH0_AUDIENCE` is set and you don't pass `resource`, the > provider uses its value as the MCP resource, overriding `MCP_URL`. It must be > the full MCP endpoint URL, such as `https://mcp.example.com/mcp`, with a path > equal to the server's `basePath`, or the server throws at startup. Unset > it if it still holds a different Auth0 API identifier. ## Use Auth0 identity and permissions Auth0 normalizes the subject to `ctx.auth.user.id`. It also maps optional `email`, `name`, `nickname`, `picture`, `emailVerified`, and `updatedAt` fields plus `roles`. Token permissions are available at top-level `ctx.auth.permissions`. ```typescript theme={null} import { z } from "zod"; server.tool( { name: "delete_document", description: "Delete a document with the Auth0 permission.", inputSchema: z.object({ documentId: z.string() }), }, async ({ documentId }, ctx) => { if (!ctx.auth.permissions.includes("delete:documents")) { return { isError: true, content: [{ type: "text", text: "Forbidden" }], }; } await db.documents.delete({ id: documentId }); return { content: [{ type: "text", text: `Deleted for ${ctx.auth.user.id}` }], }; }, ); ``` ## Verify the setup Confirm that the client registers with Auth0, the token audience is the resolved MCP resource, invalid tokens are rejected, and permission-protected tools reject callers without the required permission. > **[Runnable Auth0 example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/auth/auth0)** > > Compare with the maintained Auth0 example. > **[Auth0 MCP Authorization Guide](https://auth0.com/ai/docs/mcp/get-started/authorization-for-your-mcp-server)** > > Configure Auth0 for MCP authorization. > **[User Context](/v2/typescript/server/authentication/user-context)** > > Use normalized Auth0 identity and permissions. # Better Auth Provider Source: https://docs.mcp-use.com/v2/typescript/server/authentication/providers/better-auth Use Better Auth's OAuth Provider plugin with an MCP server. Use Better Auth when your application owns the OAuth authorization server. Better Auth handles registration, sign-in, consent, and token issuance; `mcp-use` advertises those endpoints and verifies the access-token JWTs. ## Configure the MCP resource server Pass the full Better Auth issuer URL, including its base path: ```typescript theme={null} import { MCPServer } from "mcp-use"; import { oauthBetterAuthProvider } from "mcp-use/oauth/better-auth"; const server = new MCPServer({ name: "better-auth-server", version: "1.0.0", oauth: oauthBetterAuthProvider({ authURL: "http://localhost:61843/api/auth", resource: "http://localhost:43127/mcp", }), }); export default server; ``` The provider does not create or mount Better Auth. It derives Better Auth's `/oauth2/authorize`, `/oauth2/token`, `/oauth2/register`, and `/jwks` endpoints from `authURL`, then verifies JWT issuer, signature, expiration, and MCP resource audience. ## Run Better Auth as a separate Hono app The authorization server can be a separate application and origin. The normal `mcp-use` server above owns `/mcp` and its protected-resource metadata; the Hono app only mounts Better Auth, its discovery routes, and your login and consent pages. ```typescript theme={null} import { serve } from "@hono/node-server"; import { Hono } from "hono"; import { auth } from "./auth.js"; const app = new Hono(); app.on(["GET", "POST"], "/api/auth/*", (c) => auth.handler(c.req.raw)); serve({ fetch: app.fetch, port: 61843 }); ``` Because the issuer contains `/api/auth`, also route Better Auth's RFC 8414 path-insertion metadata endpoint `/.well-known/oauth-authorization-server/api/auth` to `auth.handler` or `oauthProviderAuthServerMetadata(auth)`. Better Auth's OAuth Provider guide documents the required discovery, login, and consent routes. If browser-based MCP clients call this separate origin directly, configure Hono CORS for the MCP origin and include that origin in Better Auth's `trustedOrigins`. ## Credential-free anonymous example The repository's [runnable example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/auth/better-auth) runs a regular `mcp-use dev` process on port 43127 and a separate Hono/Better Auth process on port 61843. It uses anonymous sign-in, so it requires no Google/GitHub credentials, email service, or password UI. For easy local setup, the example omits a database. Better Auth then uses stateless cookie sessions and its memory adapter. Anonymous users, dynamic clients, codes, and consent reset whenever the process restarts; configure a persistent Better Auth database before using the pattern in production. ## Access the verified identity ```typescript theme={null} server.tool({ name: "whoami" }, async (_params, ctx) => ({ content: [ { type: "text", text: JSON.stringify({ id: ctx.auth.user.id, isAnonymous: ctx.auth.user.isAnonymous, scopes: ctx.auth.scopes, }), }, ], })); ``` Profile and application-specific access-token fields must be added with Better Auth's `customAccessTokenClaims`. The built-in mapper recognizes `email`, `name`, `picture`, `email_verified`, `sid`, `is_anonymous`/`isAnonymous`, `roles`, and `permissions` when present. > **[Better Auth OAuth Provider](https://better-auth.com/docs/plugins/oauth-provider)** > > Configure Better Auth's OAuth server, discovery routes, claims, and > persistence. # Clerk Provider Source: https://docs.mcp-use.com/v2/typescript/server/authentication/providers/clerk Configure Clerk OAuth authentication for an MCP server. Use `oauthClerkProvider` when Clerk is the authorization server. MCP clients register directly with Clerk, and mcp-use verifies Clerk-issued access tokens. ## Configure Clerk In the [Clerk Dashboard](https://dashboard.clerk.com/), enable Dynamic Client Registration for the application and copy its Frontend API URL. Enable and request `user:org:read` when tools need organization context. Pass the Frontend API URL explicitly: ```bash theme={null} CLERK_FRONTEND_API_URL=https://verb-noun-42.clerk.accounts.dev # Optional when Clerk emits a dedicated access-token audience: # CLERK_AUDIENCE=https://api.example.com ``` ```typescript theme={null} import { MCPServer } from "mcp-use"; import { oauthClerkProvider } from "mcp-use/oauth/clerk"; const frontendApiUrl = process.env.CLERK_FRONTEND_API_URL; if (!frontendApiUrl) { throw new Error("CLERK_FRONTEND_API_URL is required"); } const server = new MCPServer({ name: "clerk-server", version: "1.0.0", oauth: oauthClerkProvider({ frontendApiUrl, ...(process.env.CLERK_AUDIENCE ? { audience: process.env.CLERK_AUDIENCE } : {}), scopesSupported: ["profile", "email", "offline_access", "user:org:read"], }), }); export default server; ``` `audience` is optional. Set it only when Clerk emits that exact `aud`; when omitted, the provider uses issuer-bound access-token verification. ## Use organization context Clerk maps `org_id`, `org_role`, and `org_slug` to `organizationId`, `organizationRole`, and `organizationSlug`. Organization permissions are top-level `ctx.auth.permissions`. ```typescript theme={null} server.tool( { name: "list_documents", description: "List documents for the Clerk organization.", }, async (_args, ctx) => { const organizationId = ctx.auth.user.organizationId; if ( !organizationId || !ctx.auth.permissions.includes("org:documents:read") ) { return { isError: true, content: [{ type: "text", text: "Organization access required" }], }; } const documents = await db.documents.findMany({ where: { organizationId }, }); return { content: [{ type: "text", text: JSON.stringify(documents) }], }; }, ); ``` The mapped user also includes `id`, optional `email`, `name`, `username`, `picture`, and `emailVerified`, plus `roles`. > **[Runnable Clerk example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/auth/clerk)** > > Compare with the maintained Clerk example. > **[Clerk OAuth documentation](https://clerk.com/docs/guides/configure/auth-strategies/oauth/how-clerk-implements-oauth)** > > Review Clerk OAuth and DCR behavior. > **[User Context](/v2/typescript/server/authentication/user-context)** > > Use Clerk identity, organization, and permissions. # Convex Provider Source: https://docs.mcp-use.com/v2/typescript/server/authentication/providers/convex Configure Convex OAuth authentication for a TypeScript MCP server. Use the Convex provider when you host your own OAuth authorization server using the [Convex OAuth Provider component](https://www.convex.dev/components/codefox-inc/oauth-provider). MCP clients register directly with your Convex deployment through Dynamic Client Registration, and your MCP server verifies Convex-issued tokens. ## Start from the template Use the [Convex OAuth template](https://github.com/manufacts/mcp-oauth-convex-template) for a standalone MCP server with an authenticated `whoami` tool. ```bash theme={null} git clone https://github.com/manufacts/mcp-oauth-convex-template.git cd mcp-oauth-convex-template npm ci cp .env.example .env ``` Configure your Convex OAuth Provider as described below, set `MCP_USE_OAUTH_CONVEX_AUTH_URL` in `.env`, then run `npm run dev`. Connect your MCP client to `http://localhost:3000/mcp`. The template hosts the MCP resource server. Your Convex deployment must provide the OAuth Provider component, login, consent, and token issuance; Convex Auth alone is not sufficient. You can also [deploy the template to Manufact](https://mcp-use.com/deploy/start?repository-url=https%3A%2F%2Fgithub.com%2Fmanufacts%2Fmcp-oauth-convex-template). Set the issuer URL in the deployment environment before starting the server. For public or tunnel deployments, set `MCP_URL` to the public MCP server origin, without `/mcp`. ## Configure Convex In your Convex deployment, set up the OAuth Provider component: 1. Install the [Convex OAuth Provider component](https://www.convex.dev/components/codefox-inc/oauth-provider) in your Convex project. 2. Enable **Dynamic Client Registration** on the OAuth component so MCP clients can register automatically. 3. Configure the allowed scopes for your deployment. At minimum, include `openid profile email`. 4. Deploy your Convex project and note the base URL of your Convex site. It will look like: ```text theme={null} https://your-deployment-name.convex.site/oauth ``` ## Set environment variables ```bash theme={null} MCP_USE_OAUTH_CONVEX_AUTH_URL=https://your-deployment-name.convex.site/oauth ``` This must be the base URL of your Convex OAuth Provider endpoint, without a trailing slash. ## Configure the MCP server ```typescript theme={null} import { MCPServer } from "mcp-use"; import { oauthConvexProvider } from "mcp-use/oauth/convex"; const server = new MCPServer({ name: "convex-server", version: "1.0.0", oauth: oauthConvexProvider({ authURL: process.env.MCP_USE_OAUTH_CONVEX_AUTH_URL!, }), }); await server.listen(3000); ``` You can also pass the URL directly instead of reading from an environment variable: ```typescript theme={null} oauth: oauthConvexProvider({ authURL: "https://your-deployment-name.convex.site/oauth", }); ``` ## Use Convex identity in tools When a request is authenticated, tools receive the verified Convex identity on `ctx.auth`. ```typescript theme={null} import { error, object } from "mcp-use"; server.tool( { name: "whoami", description: "Return the verified Convex identity for this request.", }, async (_args, ctx) => { if (!ctx.auth) { return error("Unauthorized"); } return object({ id: ctx.auth.user.id, clientId: ctx.auth.user.clientId, scopes: ctx.auth.scopes, permissions: ctx.auth.permissions, expiresAt: ctx.auth.expiresAt, }); }, ); ``` Use [User Context](/v2/typescript/server/authentication/user-context) for broader access-control patterns inside tools. ## Verify the setup Run the server and connect with an OAuth-capable MCP client. ```bash theme={null} npm run dev ``` Confirm these cases: * The client discovers Convex OAuth metadata from your MCP server. * The client registers with your Convex deployment. * Authenticated tool calls include `ctx.auth.user.id`. * Tool calls without a valid bearer token are rejected. When using the Inspector, set the **Scope** to `openid profile email` if the client does not send a scope by default. ## Next steps > **[Convex OAuth template](https://github.com/manufacts/mcp-oauth-convex-template)** > > Clone or deploy a standalone MCP server with Convex authentication. > **[Convex OAuth Provider component](https://www.convex.dev/components/codefox-inc/oauth-provider)** > > Set up the OAuth Provider component in your Convex deployment. > **[User Context](/v2/typescript/server/authentication/user-context)** > > Use Convex identity data inside tools. # Custom Provider Source: https://docs.mcp-use.com/v2/typescript/server/authentication/providers/custom Integrate a DCR-capable OAuth authorization server with an MCP server. Use `oauthCustomProvider` when your authorization server supports Dynamic Client Registration (DCR) but mcp-use does not provide a built-in adapter. The MCP client registers upstream; your server publishes metadata, verifies access tokens, and maps verified claims into application identity. ## Required contract Import `MCPServer` from `mcp-use` and the provider contract from `mcp-use/oauth`. ```typescript theme={null} import { MCPServer } from "mcp-use"; import { createJwtVerifier, oauthCustomProvider, type OAuthAuthInfo, type OAuthMetadata, } from "mcp-use/oauth"; const issuer = "https://auth.example.com"; const oauthMetadata = { issuer, authorization_endpoint: `${issuer}/oauth/authorize`, token_endpoint: `${issuer}/oauth/token`, registration_endpoint: `${issuer}/oauth/register`, response_types_supported: ["code"], grant_types_supported: ["authorization_code", "refresh_token"], code_challenge_methods_supported: ["S256"], } satisfies OAuthMetadata; type AppUser = { id: string; email?: string; organizationId?: string; }; const server = new MCPServer({ name: "custom-auth-server", version: "1.0.0", oauth: oauthCustomProvider({ oauthMetadata, createTokenVerifier(resource) { return createJwtVerifier({ issuer, jwksUrl: new URL(`${issuer}/.well-known/jwks.json`), resource, }); }, mapAuthInfo(authInfo: OAuthAuthInfo) { const payload = authInfo.extra?.payload as Record; if (typeof payload.sub !== "string") { throw new Error("Verified token is missing sub"); } return { user: { id: payload.sub, email: typeof payload.email === "string" ? payload.email : undefined, organizationId: typeof payload.organization_id === "string" ? payload.organization_id : undefined, }, payload, permissions: Array.isArray(payload.permissions) ? payload.permissions.filter( (value): value is string => typeof value === "string", ) : [], }; }, }), }); export default server; ``` `createTokenVerifier(resource)` receives the resolved canonical MCP resource. The verifier must validate token signature or introspection, issuer, expiry, and that resource, then return SDK auth information including `scopes`, `expiresAt`, and the validated `resource`. `resource` must be a `URL` matching the MCP resource, `clientId` must be a string (`""` when the token has no client), and `expiresAt` must be in the future, in Unix seconds. Auth information that breaks this contract is refused like an invalid token. If your authorization server issues standard JWTs, `createJwtVerifier` does all of that for you and is the same helper the built-in providers use. Given a `jwksUrl`, it checks the signature, issuer, required `exp` and `sub` claims, and resource binding. It then returns the auth information in the shape the SDK expects. For standards-conformant JWT access tokens, the verifier checks the [`aud` claim](https://www.rfc-editor.org/rfc/rfc7519.html#section-4.1.3) for the MCP resource URL. The `aud` claim can be a string or an array containing the resource URL. [RFC 8707](https://www.rfc-editor.org/rfc/rfc8707.html#section-2) defines `resource` as an authorization and token request parameter, not as a JWT access-token claim. For compatibility with providers that include a non-standard `resource` claim, the verifier accepts a string-valued `resource` claim equal to the MCP resource URL and uses it instead of `aud`. Pass `audience` when the provider's JWT audience differs from the MCP resource. Write the verifier by hand when the provider does not issue JWTs, for example when you have to call a token introspection endpoint. Reject an invalid, expired, or revoked token by throwing `new OAuthError(OAuthErrorCode.InvalidToken, message)`, both exported from `mcp-use/oauth`. The client then gets the same sign-in challenge as for a missing token; see [How hosts see a refused call](/v2/typescript/server/authentication/mixed-auth#how-hosts-see-a-refused-call) for the format each host receives. An error that is not an `OAuthError`, such as a failed request to an unreachable introspection endpoint, is answered with `500`. `oauthMetadata` is the authorization server's RFC 8414 metadata. It must describe the actual upstream endpoints and include the `registration_endpoint` used by MCP clients. `mapAuthInfo(authInfo)` receives only verified SDK auth information. It must return: * `user`: your provider-specific normalized user, with `id` as the stable subject; * `payload`: the verified claims or introspection response; * `permissions`: application permissions derived from verified data. The server exposes those values as `ctx.auth.user`, `ctx.auth.payload`, and `ctx.auth.permissions`. `ctx.auth.scopes` remains the verifier's verified `authInfo.scopes`. ## Extend the server from the provider Some authorization models need more than token verification: a consent step exposed as a tool, or a policy check before every tool call. Pass an optional `setup(host)` hook and the server invokes it once while mounting, before the first request is served. ```typescript theme={null} import { oauthCustomProvider, type OAuthProviderHost } from "mcp-use/oauth"; const oauth = oauthCustomProvider({ createTokenVerifier, oauthMetadata, mapAuthInfo, setup(host: OAuthProviderHost) { for (const tool of host.listTools()) { if (tool.annotations?.destructiveHint && !tool._meta?.["shop/tags"]) { throw new Error(`Destructive tool "${tool.name}" needs shop/tags`); } } host.use("mcp:tools/call", async (ctx, next) => { // Let the consent tool through, or consent could never be recorded. if (ctx.params.name === "grant_consent") return next(); if (!(await isAllowed(ctx.auth, ctx.params.name))) { return { isError: true, content: [{ type: "text", text: "Complete consent first." }], }; } return next(); }); host.tool( { name: "grant_consent", description: "Record consent." }, async (_params, ctx) => recordConsent(ctx.auth.user), ); host.instructions((current) => `${current ?? ""}\n\nCall grant_consent before other tools.`.trim(), ); }, }); ``` The host exposes: | Member | Purpose | | - | - | | `resourceUrl`, `basePath` | The resolved canonical resource URL and the MCP endpoint path. | | `mixedAuth` | Whether the server accepts signed-out clients. Throw from `setup` if your model needs anonymous discovery and this is `false`. | | `use(pattern, handler)` | Registers `mcp:` middleware, like `server.use()`. | | `tool`, `resource`, `resourceTemplate`, `prompt` | Register provider-owned items, like the `server` methods of the same name. | | `listTools()` | Returns every tool registered so far, so the provider can validate the application's tools. | | `instructions(transform)` | Rewrites the instructions text advertised to clients. Each call receives the result of the previous one. | Provider-owned items go through the same OAuth gate as application items, and `ctx.auth` carries the provider's user type. On a [mixed authentication](/v2/typescript/server/authentication/mixed-auth) server, a provider tool can declare `securitySchemes` exactly like an application tool: with `noauth`, signed-out clients can call it and `ctx.auth` is optional. Resources, resource templates, and prompts always require sign-in. `mcp:` middleware also runs on signed-out calls to `noauth` tools, so check `ctx.auth` before relying on it. Registering a name that the application already uses throws, so reserved names never silently replace application items. `setup` must be synchronous, and the host only works while it runs; calling it later throws. If `setup` throws or returns a promise, the server does not start, and every later request fails with the same error. ## Verify the integration Test that: * the client discovers metadata containing the correct registration endpoint; * client registration, PKCE authorization, and token exchange happen upstream; * tokens with the wrong issuer, expiry, signature, or MCP resource are rejected; * mapped identity and permissions contain only verified data. ## Next steps > **[User Context](/v2/typescript/server/authentication/user-context)** > > Use the mapped user, scopes, and permissions in callbacks. > **[OAuth overview](/v2/typescript/server/authentication/index)** > > Compare built-in providers. # Keycloak Provider Source: https://docs.mcp-use.com/v2/typescript/server/authentication/providers/keycloak Configure Keycloak Dynamic Client Registration authentication for an MCP server. Use `oauthKeycloakProvider` when a Keycloak realm is the authorization server. MCP clients register directly with Keycloak, and mcp-use verifies realm-issued access tokens against the resolved MCP resource. ## Prepare Keycloak Configure Dynamic Client Registration for the hosts used by your MCP clients. Keep redirect URI policies strict, and add browser client origins when browser-based clients require them. For production, only require Initial Access Tokens after confirming that every intended MCP client can send one during registration. The mcp-use provider verifies tokens; it does not perform registration on the client's behalf. ## Configure the server `serverUrl` and `realm` are required. Pass them explicitly, as below, or set `MCP_USE_OAUTH_KEYCLOAK_SERVER_URL` and `MCP_USE_OAUTH_KEYCLOAK_REALM` and call `oauthKeycloakProvider()` without them. ```bash theme={null} KEYCLOAK_SERVER_URL=https://keycloak.example.com KEYCLOAK_REALM=mcp MCP_URL=https://mcp.example.com ``` ```typescript theme={null} import { MCPServer } from "mcp-use"; import { oauthKeycloakProvider } from "mcp-use/oauth/keycloak"; const serverUrl = process.env.KEYCLOAK_SERVER_URL; const realm = process.env.KEYCLOAK_REALM; if (!serverUrl || !realm) { throw new Error("KEYCLOAK_SERVER_URL and KEYCLOAK_REALM are required"); } const server = new MCPServer({ name: "keycloak-server", version: "1.0.0", oauth: oauthKeycloakProvider({ serverUrl, realm }), }); export default server; ``` There is no Keycloak provider `audience` option. Verification is bound to the resolved MCP resource, so configure Keycloak to issue access tokens for that resource. > [!WARNING] > > When `MCP_USE_OAUTH_KEYCLOAK_AUDIENCE` is set and you don't pass `resource`, > the provider uses its value as the MCP resource, overriding `MCP_URL`. It must > be the full MCP endpoint URL, such as `https://mcp.example.com/mcp`, with a > path equal to the server's `basePath`, or the server throws at startup. > Unset it if it still holds a client ID or another audience value. ## Use roles and permissions Realm roles are `ctx.auth.user.roles`. Resource roles are flattened into top-level permissions as `resource:role`. ```typescript theme={null} server.tool( { name: "admin_action", description: "Run an operation for a Keycloak resource administrator.", }, async (_args, ctx) => { if (!ctx.auth.permissions.includes("mcp-api:admin")) { return { isError: true, content: [{ type: "text", text: "Forbidden" }], }; } return { content: [{ type: "text", text: `Allowed ${ctx.auth.user.id}` }], }; }, ); ``` The mapped user also includes optional profile fields and the raw `realmAccess` and `resourceAccess` objects. Prefer normalized `roles` and `permissions`; inspect raw access objects only when the flattened form is insufficient. ## Production checks * Serve both Keycloak and the MCP server over HTTPS. * Configure token audience/resource claims for the canonical MCP endpoint. * Restrict DCR according to the capabilities of your MCP clients. * Decide whether each tool uses realm roles, flattened resource permissions, or both. > **[Runnable Keycloak example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/auth/keycloak)** > > Compare with the maintained Keycloak example. > **[Keycloak Client Registration](https://www.keycloak.org/securing-apps/client-registration)** > > Configure Dynamic Client Registration. > **[User Context](/v2/typescript/server/authentication/user-context)** > > Use Keycloak user fields, roles, and permissions. # OAuth Proxy Source: https://docs.mcp-use.com/v2/typescript/server/authentication/providers/oauth-proxy Sign MCP clients in with GitHub, Google, or another OAuth provider that has no Dynamic Client Registration, using oauthProxy in a TypeScript MCP server. Use `oauthProxy` when your identity provider gives you one fixed `clientId` and `clientSecret` and cannot register MCP clients itself. GitHub and Google work this way. With `oauthProxy`, your MCP server becomes its own OAuth authorization server for MCP clients, and signs users in to the upstream provider as one ordinary OAuth app. The upstream client secret and the user's upstream tokens stay on your server. MCP clients only receive tokens that your server issues. Tools call the upstream API as the user with `upstreamToken(ctx.auth)`. If your provider supports Dynamic Client Registration (DCR), use a [built-in provider](/v2/typescript/server/authentication/index) or a [Custom Provider](/v2/typescript/server/authentication/providers/custom) instead. Those keep your server a resource server only. ## How the proxy works The proxy sits between two OAuth relationships. Toward MCP clients, it is the authorization server: it identifies clients, shows a consent page, and issues its own access and refresh tokens. Toward the upstream provider, it is a confidential OAuth client with one registered callback URL. | Who holds it | Credential | | - | - | | MCP client | The proxy's access token (`mcp_at_…`) and refresh token (`mcp_rt_…`) | | Your server's storage | Clients, sign-in state, grants, and the upstream tokens, all encrypted with your `secret` | | Your server's configuration | The upstream `clientId` and `clientSecret` | | Upstream provider | The single callback URL `https:///mcp/oauth/callback` | ### The sign-in flow ```mermaid theme={null} sequenceDiagram autonumber participant C as MCP client participant B as Browser participant P as MCP server participant U as Upstream C->>P: MCP request P-->>C: 401 C->>P: Read metadata C->>B: Open /authorize B->>P: GET /authorize P-->>B: Consent page B->>P: Allow P-->>B: Redirect B->>U: Sign in U-->>B: Redirect B->>P: GET /callback P->>U: Exchange code P-->>B: Redirect B->>C: Code C->>P: POST /token P-->>C: Tokens C->>P: MCP request ``` 1. The client calls the MCP endpoint without a token. 2. The server answers 401 with the URL of its protected resource metadata. 3. The metadata names the server itself as the authorization server and lists its `/mcp/oauth/*` endpoints. The client identifies itself with a client ID metadata document URL, or registers at `/mcp/oauth/register`. 4. The client opens `/mcp/oauth/authorize` in the browser with its PKCE challenge and `state`. 5. The proxy checks the client, the redirect URI, the PKCE challenge, and the RFC 8707 `resource`. 6. The proxy shows its consent page. 7. The user approves. 8. The proxy redirects the browser to the upstream provider with the proxy's own `client_id` and its own PKCE challenge. 9. The user signs in to the upstream provider and approves the OAuth app. 10. The upstream provider redirects the browser to `/mcp/oauth/callback` with a code. 11. The proxy checks that the callback belongs to the browser that approved consent, using a signed cookie. 12. The proxy exchanges the code on the server with the client secret and its PKCE verifier, then reads the user, for example from Google's userinfo endpoint. 13. The proxy redirects the browser to the client's redirect URI with a one-time code and the client's original `state`. 14. The client receives the code. 15. The client exchanges the code at `/mcp/oauth/token` with its PKCE verifier. 16. The proxy returns its own access token (`mcp_at_…`) and refresh token (`mcp_rt_…`). 17. The client calls the MCP endpoint with the access token. The proxy looks up the grant and refreshes the upstream token if it expires soon. The proxy runs its own PKCE round with the upstream provider, so an intercepted upstream authorization code is useless to anyone but the proxy. ## Set up a Google sign-in **1. Configure the Google Auth Platform** In the [Google Cloud console](https://console.cloud.google.com/auth/overview), open **Google Auth Platform** for your project and set up the app's branding and audience. While the publishing status is **Testing**, add each Google account that signs in under **Audience** > **Test users**. **2. Create an OAuth client** Under **Clients**, create a client of type **Web application**. Add the proxy's callback as an **Authorized redirect URI**: `http://localhost:3000/mcp/oauth/callback` for local development. Google never sees the MCP client's own redirect URI, so this one URL serves every client. Copy the client ID and the client secret. **3. Set the environment** ```bash .env theme={null} # The OAuth client from the previous step. GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= # At least 32 characters. Generate one with: openssl rand -base64 32 MCP_USE_OAUTH_SECRET= ``` **4. Configure the server** ```typescript src/index.ts theme={null} import { MCPServer } from "mcp-use"; import { google, memoryStorage, oauthProxy } from "mcp-use/oauth"; const server = new MCPServer({ name: "google-tools", version: "1.0.0", oauth: oauthProxy({ upstream: google({ clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, }), // The secret defaults to MCP_USE_OAUTH_SECRET. // memoryStorage() works on localhost only. See "Choose storage" below. storage: memoryStorage(), }), }); server.tool( { name: "whoami", description: "Return the signed-in Google account." }, async (_input, ctx) => { // The profile holds the fields of Google's userinfo response. const { name, email } = ctx.auth.user.profile; return { content: [{ type: "text", text: `${String(name)} <${String(email)}>` }] }; }, ); export default server; ``` **5. Connect a client** Run `mcp-use dev` and connect a client to `http://localhost:3000/mcp`: ```bash theme={null} claude mcp add --transport http google-tools http://localhost:3000/mcp ``` The client opens the consent page, then Google. After sign-in, call `whoami`. The complete [Google example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/auth/oauth-proxy-firebase) keeps sign-ins in Firestore with `firestoreStorage` and stores each user's notes under their Google subject. ## Register the callback URL Register exactly one callback URL with the upstream provider: ```text theme={null} /oauth/callback ``` With the default `basePath` of `/mcp`, that is `https://mcp.example.com/mcp/oauth/callback` in production and `http://localhost:3000/mcp/oauth/callback` locally. The proxy serves all of its endpoints under `/oauth/`: | Endpoint | Method | Purpose | | - | - | - | | `/mcp/oauth/authorize` | `GET` | Validates the request and shows the consent page | | `/mcp/oauth/consent` | `POST` | Records the consent decision and redirects upstream | | `/mcp/oauth/callback` | `GET` | Receives the upstream code and redirects back to the client | | `/mcp/oauth/token` | `POST` | Authorization-code and refresh-token grants | | `/mcp/oauth/revoke` | `POST` | RFC 7009 token revocation; ends the whole sign-in | | `/mcp/oauth/register` | `POST` | RFC 7591 dynamic client registration, only while `dcr` is on | The server publishes protected resource metadata that names itself as the authorization server, and RFC 8414 authorization server metadata that lists these endpoints. You do not configure either by hand. ## Use the upstream token in tools `upstreamToken(ctx.auth)` returns the upstream access token for the signed-in user. It takes only the `auth` object, so a helper that receives `ctx.auth` can call it too. It throws when the request is not signed in through `oauthProxy`, so a tool never calls the upstream API without the user's token. This tool lists the user's next Google Calendar events. Enable the Google Calendar API in the Google Cloud project, and request its scope from Google: ```typescript theme={null} upstream: google({ clientId: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, scopes: ["email", "profile", "https://www.googleapis.com/auth/calendar.readonly"], }), ``` Then call the Calendar API with the user's Google token: ```typescript theme={null} import { upstreamToken } from "mcp-use/oauth"; server.tool( { name: "upcoming-events", description: "List the user's next 10 calendar events." }, async (_input, ctx) => { const params = new URLSearchParams({ timeMin: new Date().toISOString(), maxResults: "10", singleEvents: "true", orderBy: "startTime", }); const response = await fetch( `https://www.googleapis.com/calendar/v3/calendars/primary/events?${params}`, { headers: { authorization: `Bearer ${upstreamToken(ctx.auth)}` } }, ); if (!response.ok) throw new Error(`Google Calendar returned ${response.status}`); const { items } = (await response.json()) as { items: { summary?: string; start: { dateTime?: string; date?: string } }[]; }; const lines = items.map( (event) => `${event.start.dateTime ?? event.start.date} ${event.summary ?? "(no title)"}`, ); return { content: [{ type: "text", text: lines.join("\n") || "No upcoming events." }] }; }, ); ``` Keep the upstream token on the server. Do not return it in tool results, views, or `_meta`. `ctx.auth` on a proxy server contains: | Field | Value | | - | - | | `ctx.auth.user` | The `UpstreamUser` `{ subject, profile }`, or the result of `mapUser` | | `ctx.auth.upstream` | `{ accessToken, scopes, expiresAt? }` for the upstream provider | | `ctx.auth.accessToken` | The proxy's own `mcp_at_…` token, not the upstream token | | `ctx.auth.clientId` | The MCP client's ID: a metadata document URL, or `mcp_client_…` for a registered client | | `ctx.auth.scopes` | The proxy scopes granted to this sign-in | | `ctx.auth.payload` | `{ sub, client_id, scope, provider, profile }` | | `ctx.auth.permissions` | Always `[]`. Derive permissions in `mapUser` or in your tools | `subject` is the provider's stable user ID: the OpenID Connect `sub` for Google, or the numeric user ID for GitHub. It is never an email address or a login name, which can change. Use `subject` as the key for any data you store per user. ### Map the user Pass `mapUser` to shape `ctx.auth.user`, for example to match the `id` field that the other providers use: ```typescript theme={null} oauthProxy({ upstream: google({ clientId, clientSecret }), mapUser: (user) => ({ id: user.subject, email: typeof user.profile.email === "string" ? user.profile.email : undefined, emailVerified: user.profile.email_verified === true, }), }); ``` `mapUser` runs on every request. It controls the user shape, not who can sign in: any user of the upstream provider can complete the sign-in. To restrict users, throw from your tools, or check `ctx.auth.user` in [middleware](/v2/typescript/server/middleware). ## Choose an upstream provider | Upstream | Function | Subject | Profile fields | | - | - | - | - | | Google | `google()` | OpenID Connect `sub` | `sub`, `email`, `email_verified`, `name`, `picture`, `hd` | | GitHub and GitHub Enterprise Server | `github()` | Numeric GitHub user ID | `id`, `login`, `name`, `email`, `avatar_url` | | Any OAuth 2.0 provider | `upstream()` | What your `fetchUser` returns | What your `fetchUser` returns | ### Google `google()` always requests `openid` and, by default, `email` and `profile`. Add Google API scopes to `scopes` as your tools need them. `google()` requests offline access, so Google returns a refresh token and the proxy refreshes Google tokens on the server. If Google returns no refresh token and none is stored for the user, the proxy sends the user through Google consent once more. While the app's publishing status is **Testing**, Google expires refresh tokens after 7 days unless the app requests only the `openid`, `email`, and `profile` scopes. Users then sign in again. Publish the app to remove the limit. ### GitHub In [GitHub Developer settings](https://github.com/settings/developers), choose **OAuth Apps** > **New OAuth App**, and set the callback URL to `/mcp/oauth/callback`. Turn on **Expire user access tokens** so that GitHub issues refresh tokens; the proxy then refreshes the GitHub token on the server. ```typescript theme={null} import { github, oauthProxy } from "mcp-use/oauth"; oauthProxy({ upstream: github({ clientId: process.env.GITHUB_CLIENT_ID!, clientSecret: process.env.GITHUB_CLIENT_SECRET!, // Default: ["read:user"]. Add "repo" for private repositories. scopes: ["read:user"], }), storage, }); ``` For GitHub Enterprise Server, set `baseUrl` to the web host, and `apiUrl` when the REST API lives elsewhere. The [GitHub example](https://github.com/mcp-use/mcp-use/tree/main/libraries/typescript/packages/server/examples/auth/oauth-proxy-github) calls the GitHub API as the user with Octokit and keeps sign-ins in Redis. ### Any OAuth 2.0 provider Use `upstream()` for a provider that has authorization and token endpoints. `fetchUser` reads the signed-in user with the upstream tokens and must return a stable `subject`. ```typescript theme={null} import { oauthProxy, upstream } from "mcp-use/oauth"; oauthProxy({ upstream: upstream({ id: "acme", name: "Acme", authorizationEndpoint: "https://id.acme.dev/oauth/authorize", tokenEndpoint: "https://id.acme.dev/oauth/token", clientId: process.env.ACME_CLIENT_ID!, clientSecret: process.env.ACME_CLIENT_SECRET!, scopes: ["profile"], fetchUser: async (tokens, fetch) => { const response = await fetch("https://api.acme.dev/me", { headers: { authorization: `Bearer ${tokens.accessToken}` }, }); if (!response.ok) throw new Error(`Acme /me returned ${response.status}`); const me = (await response.json()) as { id: string; email?: string }; return { subject: String(me.id), profile: me }; }, }), }); ``` `id` appears in storage keys and `ctx.auth.payload.provider`; `name` appears on the consent page. Endpoints must use HTTPS (HTTP is accepted on localhost). PKCE is on by default; set `pkce: false` only for a provider that rejects it. Set `issuer` when the token endpoint returns OpenID Connect ID tokens, and `authorizeParams` for extra query parameters such as `prompt`. ## Choose storage The proxy keeps clients, sign-in state, one-time codes, grants, and upstream tokens between requests, so it needs a store that every instance of the server shares. The proxy encrypts every value with your `secret` before the store sees it, and stores only SHA-256 hashes of tokens in keys. ```typescript theme={null} import { google, oauthProxy } from "mcp-use/oauth"; import { upstashStorage } from "mcp-use/oauth/storage"; oauthProxy({ upstream: google({ clientId, clientSecret }), storage: upstashStorage({ url: process.env.UPSTASH_REDIS_REST_URL!, token: process.env.UPSTASH_REDIS_REST_TOKEN!, }), }); ``` `mcp-use/oauth/storage` has adapters for Upstash, Redis, Postgres, Firestore, and Cloudflare D1 or Durable Objects. See [OAuth Proxy storage](/v2/typescript/server/authentication/providers/oauth-proxy-storage) to pick one or write your own. ### What each environment requires | Where the server runs | `storage` | `secret` | | - | - | - | | `listen()` on a localhost resource, bound to `127.0.0.1`, `localhost`, or `::1` | Optional (memory default) | Optional (random key per process) | | `mcp-use dev` on localhost | Required: pass `memoryStorage()` or a shared store | Required | | Any other deployment, tunnel, or public URL | Required: a shared store | Required | `oauthProxy` throws when the server mounts without a required `storage` or `secret`. `memoryStorage()` is refused outside localhost. Without a secret, the proxy logs a warning and uses a random key, so sign-ins end when the process stops. ## Set and rotate the secret The proxy derives its encryption and cookie keys from `secret`, which defaults to the `MCP_USE_OAUTH_SECRET` environment variable. Use a random string of at least 32 characters: ```bash theme={null} openssl rand -base64 32 ``` To rotate, pass an array. The first secret encrypts and signs; the others still decrypt and verify: ```typescript theme={null} oauthProxy({ upstream, storage, secret: [process.env.MCP_USE_OAUTH_SECRET!, process.env.MCP_USE_OAUTH_SECRET_PREVIOUS!], }); ``` Keep the previous secret until every record written with it has expired: 30 days for refresh tokens, 60 days for stored upstream tokens. Records that no secret can decrypt read as missing, so their users sign in again. The proxy logs a warning, once for each kind of record, with the key ID that wrote it. ## Restrict which clients connect By default, any MCP client can connect. A client identifies itself in one of two ways: * **Client ID metadata document (CIMD).** The client uses an HTTPS URL as its `client_id`, and the proxy fetches its metadata from that URL. The MCP specification prefers this. Claude and ChatGPT use it. * **Dynamic client registration (DCR).** The client registers at `/mcp/oauth/register` and gets a `mcp_client_…` ID. Registered clients are public clients: the proxy never issues a client secret. Set `clients` to allow only the apps you list. Dynamic client registration turns off while `clients` is set, because a registered client names itself. ```typescript theme={null} oauthProxy({ upstream, storage, clients: [ // One metadata document: exactly this client. "https://claude.ai/oauth/mcp-client-metadata.json", // An HTTPS origin: every metadata document on chatgpt.com. "https://chatgpt.com", // A client defined by hand, for a client that can use neither method. { clientId: "internal-cli", redirectUris: ["http://127.0.0.1/callback"], clientName: "Internal CLI", }, ], }); ``` | `clients` entry | Allows | | - | - | | Metadata document URL | That one client | | HTTPS origin | Every metadata document on that origin. ChatGPT uses a different document URL per connector, so list `https://chatgpt.com` | | `OAuthProxyClient` object | A client with a fixed `clientId` and exact `redirectUris`. On loopback (`http://127.0.0.1`), any port matches | > [!WARNING] > > Removing a client from `clients`, or turning off `dcr`, ends that client's sign-ins for good. The next request with one of its tokens deletes the grant, and adding the client back does not restore it. A briefly wrong allowlist signs those users out. `clients` controls which apps connect, not which users sign in. `dcr: true` together with `clients` throws. The proxy fetches metadata documents only from hosts that resolve to public addresses. On Node.js and Bun it connects only to the addresses it checked. On Cloudflare Workers and Deno, `fetch` resolves the host again, so list the trusted metadata documents in `clients` to close the DNS-rebinding window there. Passing a custom `fetch` turns the host check off; your `fetch` must then enforce its own network policy. ## Configure the consent page The proxy shows a consent page before it sends the user upstream. The page names your server by its domain, the app that asks, where the browser returns, the upstream provider, and the scopes. Consent defends against a malicious client that reuses an earlier upstream approval (a confused-deputy attack), so it is on by default. | `consent` value | Behavior | | - | - | | Omitted or `{ mode: "always" }` | Asks on every sign-in | | `{ mode: "remember" }` | Asks once per browser for each client and HTTPS redirect URI, for 1 year. Loopback and custom-scheme redirects still ask every time, because any local program can claim them | | `{ page: Component }` | Renders your React component instead of the built-in page | | `false` | No consent page. Allowed only on localhost; refused on a `listen()` that binds beyond loopback | ### Render a custom consent page `consent.page` takes a React component that the proxy renders on the server with `react-dom/server`, so install `react` and `react-dom`. The component receives `ConsentPageProps` and must render a form that posts to `form.action` with two `decision` buttons. `form.action` already carries the CSRF token, so post to it unchanged and add no hidden fields: ```tsx src/consent.tsx theme={null} import type { ConsentPageProps } from "mcp-use/oauth"; export function Consent({ client, serverHost, upstream, scopes, form }: ConsentPageProps) { return (

Allow {client.name ?? "this app"} to connect to {serverHost}?

You will sign in with {upstream}. Scopes: {scopes.join(", ") || "none"}.

); } ``` ```typescript src/index.ts theme={null} import { Consent } from "./consent.js"; oauthProxy({ upstream, storage, consent: { page: Consent } }); ``` The page is never hydrated, and its Content Security Policy allows inline styles only. Put CSS in a `