mcp-use 1.x server by updating the runtime, server entry,
registrations, request context, security configuration, and widgets.
Most server registrations keep the same concepts and require small syntax
changes. Widgets require a complete rewrite as MCP App Views.
Migration checklist
1
Update the runtime and server entry
Upgrade to Node.js
>=22.22.2, use ESM, import from mcp-use, and
default-export the server.2
Update server registrations
Convert tools, resources, resource templates, and prompts to the
definition-plus-callback API and return raw MCP results.
3
Update runtime behavior
Replace session assumptions, request context fields, authentication,
notifications, elicitation, middleware, and deployment adapters.
4
Rebuild widgets as Views
Replace the widget file layout, tool binding, result helper, provider,
generated helpers, hooks, state model, and asset paths.
5
Review beta limitations and verify
Check whether a missing v1 capability affects the server, then typecheck,
build, run, and exercise the migrated project.
Update the runtime and entry point
The current v2 beta requires Node.js>=22.22.2 and ESM.
mcp-use:
index.ts.
Export every static tool
Assign every statically declared tool to an exported constant. If tools live in other modules, re-export them from the server entry:mcp-env.d.ts declaration registers
typeof import("<server-entry>"). Only exported ToolRef values participate in
View typing. This is a live type-only import, not the v1 tool-registry
generator. mcp-use dev, build, and typecheck create or refresh the
declaration, but they do not execute the server to generate tool-specific
types.
If the v1 server registers a tool from a loop, runtime configuration, or an
OpenAPI document, it cannot export a static ToolRef. Call that tool from a
View with explicit types:
Migrate tools
Move the callback to the second argument, replaceschema with
inputSchema, and return a raw MCP result.
schema remains an alias for inputSchema in the current beta, but
inputSchema matches the MCP wire field and is the migration target.
Follow these result rules:
- A successful tool with
outputSchemamust return matchingstructuredContent. - An error result may return
isError: truewithout structured output. - For object-shaped structured output, include a text fallback in
content. - Replace
inputs[]with a Standard Schema-compatible input schema. - Do not chain
server.tool(...).tool(...);tool()returns aToolRef.
text(), object(), array(), image(), and
error() remain as deprecated upgrade shims. Prefer raw CallToolResult,
ReadResourceResult, and GetPromptResult envelopes. Native array() does not
preserve the v1 { data } wrapper.
Migrate resources and templates
Pass the reader as the second argument. A static resource callback receives(uri, ctx) and returns contents:
readCallback and callbacks fields.
For resource templates:
- replace nested
resourceTemplatewith top-leveluriTemplate - move
callbacks.completeto top-levelcomplete - pass the reader separately as
(uri, params, ctx) - handle inferred template values as
string | string[] - return raw
contents
Migrate prompts
Keepschema for prompt arguments, pass the callback separately, and return
raw messages:
args[] and inline cb. completable() supplies suggestions but
does not constrain valid values. Apply field refinements before wrapping a
schema with completable().
Update request context
v2 request context exists only for the current request. Remove session assumptions from client metadata, logging, progress, notifications, and elicitation.ctx.client.info(), capabilities(), can(), extension(), and user()
return client-declared request hints. Never use them for authorization. Use
verified ctx.auth data for identity and permissions.
Send notifications on the correct channel
v2 supports custom notifications during an active request:Make elicitation replay-safe
v2 elicitation returns an input-required result and re-runs the handler when the client supplies input:Rebuild widgets as MCP App Views
Legacy widgets require a full UI migration. File discovery, binding, tool results, component lifecycle, hooks, state, assets, and typing all changed.Move the files and binding
Move data previously passed as
props to the tool result’s _meta field.
Access it from useToolContext().meta in the View. _meta is View-only and is
not validated or typed by outputSchema; validate or narrow it before use.
Keep structuredContent for output that matches outputSchema and should also
be visible to the model.
The bound tool must:
- export its
ToolRef - declare an
outputSchema - return matching
structuredContent - move v1
widget({ props })data to result_meta - return useful text
contentfor the model and text-only hosts - bind to exactly one View with
view: { name }
useCallTool().
Move resource facts such as description, csp, permissions, domain, and
prefersBorder into the bound tool’s view configuration. Remove v1
invoking, invoked, and widgetAccessible; the native View configuration
does not emit those OpenAI-specific overlay fields.
Replace widget hooks
Default-export the View component. It mounts once while the host connects and while tool input and result notifications arrive.viewConfig supports autoResize and displayModes. Both values below are
the defaults, so omit the export when they are correct for the View:
displayModes must include "inline". Use useSendSizeChanged() only when
autoResize is false and the View reports its size manually.
Compose optional presentation components such as ThemeProvider,
ViewControls, and your own error boundary. The framework owns the connection,
bootstrap, and required top-level error boundary.
Migrate View state and model context
useViewState() requires an object default and shares one JSON-serializable
snapshot across the mounted View. The state is model-visible.
ChatGPT can restore View state across View lifetimes. Other MCP Apps hosts keep
the state only for the current iframe lifetime.
Use ModelContext or modelContext for model-visible natural-language context.
Use useSendFollowUp() to trigger a new model turn. Keep presentation-only
state in ordinary React state.
useFiles() keeps the upload/download capability check, but it no longer
accepts the v1 modelVisible option or mutates widget state automatically.
Update View assets
Native View documents are generated MCP resources. Do not registeruiResource() or serve a separate HTML document.
Move existing widget CSP domains to
view.csp.
Update authentication, proxies, and security
Native v2 acts as an OAuth resource server backed by an external authorization server. Import provider adapters frommcp-use/oauth/*, supply their required
locator options, and use the provider-specific ctx.auth.user type.
Replace generic userId assumptions with the provider’s mapped field, commonly
id. Replace getAuth, hasScope, and requireScope with verified
ctx.auth, scopes, permissions, and application authorization checks.
OAuth proxy or authorization-server mode has no native v2 migration. Do not
translate oauthProxy, jwksVerifier, or mountOAuthProxy as resource-server
configuration.
v2 upstream composition accepts HTTP remotes or a ready compatible client
connection. A v1 stdio child-process proxy requires an architecture change.
Preserve security semantics explicitly
The nameallowedOrigins changed meaning:
Map v1 CORS
allowMethods and allowHeaders to v2 methods and
allowedHeaders. Test Host rejection, Origin rejection, and CORS separately.
Use basePath for the MCP route. Set MCP_URL for the externally visible
server origin.
Review current beta limitations
The following v1 capabilities do not currently have direct v2 equivalents. Update the application design where one of these limitations affects your server.Server lifecycle and transport
- Session stores, active-session registries, stream managers, session recovery, and session affinity are not part of v2.
- Arbitrary session-targeted and post-response push are not available. Request-scoped custom notifications and subscription invalidations remain available.
- Server-to-client sampling through
ctx.sample()is not available. - The v1 roots-changed callback surface is not available.
- Express and Connect adapters are not available. Use Hono or
server.fetch. - Stdio serving and stdio child-process proxy configuration do not have a native migration path.
- CommonJS and unsupported Node.js versions are intentional compatibility breaks, not beta bugs.
OAuth, proxy, and OpenAPI
- OAuth proxy and authorization-server mode are deferred. Direct resource-server authentication is implemented.
- Unsigned token bypasses such as
verifyJwt: falseare not supported. - Verify proxy requirements for upstream OAuth, templates, completions, subscriptions, list synchronization, sampling, and elicitation before migrating.
- Verify OpenAPI servers that depend on external references, cookies, non-JSON request bodies, callbacks, webhooks, or automatic security-scheme discovery.
Views
- Each View can bind to at most one server tool.
- A bound tool requires
outputSchemaand matchingstructuredContent. - Static typing sees exported
ToolRefvalues only. - Cross-lifetime
useViewState()restoration is host-specific. useFiles()is host-specific and must be capability-checked.- View resource facts are static per bound tool. v2 has no supported hook for
rewriting
domainor other View resource metadata per client. - Raw
uiResource,@mcp-ui/serveradapters,exposeAsTool, and a shared View bound to multiple server tools have no native equivalent.
Use the compatibility bridge only for staging
Existing servers can temporarily keep:Verify the migration
1
Run a real TypeScript check
Run
mcp-use typecheck, npm run typecheck, or the project’s actual tsc --noEmit command. mcp-use build bundles code but does not prove that v1
APIs are type-compatible.2
Build and start the production output
Run the project’s production build, start the built server, and confirm the
expected MCP route and public asset routes.
3
Exercise server primitives
Call at least one tool, read a static resource, complete and read a resource
template, and get a prompt with a real client.
4
Render every View state
Verify pending, ready, and error states; matching structured output; theme;
display mode; sizing; CSP; and public assets in a capable host.
5
Test security and authentication
Check a valid token, missing or invalid scopes, mapped user data, Host
rejection, Origin rejection, and browser CORS behavior.
6
Preserve behavioral coverage
Keep existing runtime assertions as runtime assertions. If v2 does not
support a tested behavior, leave that limitation explicit instead of
replacing the test with source-text or artifact assertions.
7
Remove v1 leftovers
Remove remaining v1 imports, helpers, widget files, session APIs, sampling
calls, stdio proxy configuration, and old security fields. Keep a
mcp-use/server import only when you intentionally use the temporary
compatibility bridge.Continue with the v2 guides
- Server overview explains the stateless server model.
- Tools, Resources, and Prompts cover each registration API.
- MCP Apps covers View authoring and host behavior.
- Authentication covers direct OAuth resource-server configuration.
- Notifications separates request-scoped messages from subscription invalidations.