Skip to content

@miragon/mcp-toolkit-core — API reference ​

Three subpath exports: the browser-safe main entry, the server-side /tools registrars, and the /rest client helper.

@miragon/mcp-toolkit-core (main) ​

Runtime + types. No dependency on the mcp-use server runtime — safe to import from widget bundles or browser code.

Types ​

SymbolPurpose
AppDefinition{ name, title?, titleKey?, steps, widgets }. title (a LocalizedText) or titleKey heads the app's group in the builder's palette; without one the group has no heading and the name shows only in advanced mode.
AppPlugin<TServer>{ definition, appConfig?, registerTools?, registerWidgetTools? }. appConfig may carry closures (e.g. a typed callTool) handed to the plugin's steps.
PipelineStepDefinition<TConfig>{ id, description?, dataType, requires, optionalKeys?, produces, execute(ctx, appConfig) } plus the optional DisplayText fields that name it in the builder's data sources.
OptionalKeyDeclaration{ key, description?, enum? }. Soft inputs surfaced in getFrameworkManifest.
PipelineContext{ steps, keys, errors }.
StepOutput / StepResultStep return value; StepResult adds _dataType.
WidgetDefinition{ id, description?, requires, consumes?, size, propsSchema? } plus the optional DisplayText fields — the widget's code lives in the host's app-bundle. description is the LLM's text; the builder shows title and summary.
DisplayText{ title?, titleKey?, summary?, summaryKey? }: how a widget or step introduces itself to the people using the view builder. title/summary are a LocalizedText; a titleKey/summaryKey the bundle's LocaleProvider translator knows wins. Without a title the builder shows the id. Mirrored onto the get-builder-catalogue entries, never into get-framework-manifest.
LocalizedTextstring | Record<locale, string>: one text, or one per BCP 47 tag ({ en: "Orders", de: "Bestellungen" }).
PROPS_SCHEMA_DISPLAY_KEYWORD"x-display": the propsSchema property keyword that carries a field's DisplayText for the builder's props sheet. Fallbacks: the JSON Schema title, then the property name; the help line is the x-display summary, else the description. getFrameworkManifest leaves it out of the propsSchema the LLM reads.
WidgetSize"quarter" | "third" | "half" | "full" | "header".
WidgetProps{ keys, context, widgetProps? }. widgetProps carries the layout cell's per-instance props.
PipelineConfig{ steps?: PipelineStepRef[] }.
PipelineStepRef{ id, step, optional? }.
AppConfig{ activeApps: AppConfigEntry[], pipelines: Record<id, PipelineConfig> }.
ValidationResult{ valid, issues, availableKeys }.
ViewStructuredContentThe view-tool envelope ({ context: { stepData, … }, layout, … }) written into a *_show_* tool's structuredContent. Built by the view builders under Framework helpers.
appsSdkMeta(opts: AppsSdkMetaOptions) → Record<string, unknown>. Builds the OpenAI Apps SDK openai/* _meta keys for a widget-rendering tool. The MCP Apps half (_meta.ui) is emitted natively by mcp-use from the tool's view / visibility fields — never stamp ui keys by hand.
viewResourceUri(viewName) → string. The ui://views/<name>.html resource URI mcp-use assigns to a registered view — feed it to appsSdkMeta's resourceUri. VIEW_RESOURCE_URI_PREFIX is the pinned scheme constant.
AppResourceCsp{ connectDomains?, resourceDomains?, frameDomains?, baseUriDomains? } — the camelCase CSP a tool's view.csp (and createFrameworkApp's app.csp) advertise; mcp-use appends the server origin itself.

Runtime ​

SymbolSignature
resolveLocalizedText(text: LocalizedText | undefined, locale) → string | undefined. The text for a locale: exact tag, then the language, then English, then the first entry; blank entries are skipped.
executePipeline(options: ExecutePipelineOptions) → Promise<PipelineContext>
ExecutePipelineOptions{ config, initialKeys, registry, appConfigs?, ctx? }.
validatePipeline(config, registry, availableKeys) → ValidationResult
StepRegistryClass. register(step), get(id), getAll(), getKeyContracts().
WidgetRegistryClass. register(w), get(id), getAll().
loadApps(defs, stepRegistry, widgetRegistry, opts?) → LoadAppsResult. opts.isolateFailures skips (with rollback) an app whose ids collide instead of throwing — for untrusted module sources; first-party plugins fail loud by default.
PipelineExecutionContext{ userId?, authenticated? }. Who is calling, handed to a step's callTool closure as its third argument. authenticated: true without userId is a caller whose provider maps no id — per-user data must refuse it; both absent means no auth.
resolvePipelineContext(ctx: unknown) → PipelineExecutionContext. Builds it from a tool handler's ctx via resolveCaller; what render-view / refresh-view / get-builder-catalogue pass. Use it when calling renderView / getBuilderCatalogue yourself.
KeyContract{ key, producedBy[], consumedBy[] }.

Framework helpers ​

SymbolSignature
renderView(options: RenderViewOptions) → Promise<{ content, structuredContent?, isError? }>
RenderViewOptions{ input, stepRegistry, appConfigs?, ctx?, builderAvailable? }. builderAvailable is echoed into structuredContent.builderAvailable so the shell only shows its Edit view button when the server's builder platform is on.
RenderViewInput{ keys?, steps?, layout, title? }.
buildSingleWidgetView(input: SingleWidgetViewInput) → ViewToolResult. Build the *_show_* view envelope for a single widget — wraps one record as a ViewStructuredContent so a widget tool's structuredContent is directly renderable by McpAppView / decodable by parseViewToolResult.
buildComposedView(input: ComposedViewInput) → ViewToolResult. Build a multi-widget view envelope from several ComposedViewEntry rows (each a widget + its data). See view-builder concept.
ViewStructuredContentThe view envelope written into a view tool's structuredContent: { context: { stepData, … }, layout, … }. Consumed by McpAppView.
SingleWidgetViewInput / ComposedViewInput / ComposedViewEntry / ViewToolResultInput/return types for the two view builders.
collectLayoutWidgets(layout) → string[]. The widget ids a layout references — used by save-dashboard validation.
deriveItemCount / defaultSummaryHelpers the view builders use to derive a row count / a default model-context summary from a record.
getBuilderCatalogue(options: CatalogueOptions) → Promise<{ content, structuredContent: CataloguePayload }>. Backs the app-only get-builder-catalogue tool used by the iframe builder. See view-builder concept.
CatalogueOptions{ input, stepRegistry, widgetRegistry, appConfigs?, apps?, ctx? }. apps (the loaded AppDefinitions, or just their name, title and titleKey) feeds the palette's group headings; installToolkit passes its apps and modules.
CatalogueInput{ keys?, steps? } — what the builder is currently working with.
CataloguePayload{ context, reachableWidgets, unreachableWidgets, availableSteps, keyCatalog, validationIssues, apps? }. validationIssues mirrors the fail-soft pipeline issues so the builder can warn before a (fail-hard) render-view; for apps see CatalogueApp.
CatalogueApp{ name, title?, titleKey? }: the heading of one app's group in the builder's palette. CataloguePayload.apps lists the titled apps and is absent when none has a title.
ReachableWidget{ id, app, requires, size } — palette entry for the builder UI.
UnreachableWidget{ id, app, requires, size, missingKeys } — registered widget not satisfied by the current key set.
AvailableStep{ id, app, dataType, requires, produces } — step picker entry.
KeyCatalogEntry{ key, producedBySteps, consumedBySteps, consumedByWidgets, inContext }.
getFrameworkManifest(stepRegistry, widgetRegistry, config) → FrameworkManifest. Each widget's propsSchema comes without its properties' x-display texts (they label the builder for people).
FrameworkManifest{ activeApps, steps[], widgets[], pipelines[], keyContracts[] }. Each step entry exposes description? + optionalKeys?; each widget entry exposes description?, consumes?, propsSchema?. Each keyContracts entry has producedBy, consumedBy, optionallyConsumedBy.
normalizeLayout(layout) → { rows?, tabs? }.
LayoutConfig / RowDefStatic types for the layout shape.
layoutSchema / rowSchemaZod schemas validated by render-view.
resolveActiveModules(envValue?, known: string[]) → string[].
parseActiveModules(envValue?) → ActiveModuleSelection. Lower-level parse of the ACTIVE_MODULES-style env value (the "all" sentinel + explicit list) that resolveActiveModules validates against the known set.

Dashboard types (types only — impls in /tools) ​

SymbolShape
DashboardStore{ save(input), list(filter), get(id, filter), delete(id, filter) }. Pluggable persistence for save-/list-/load-/delete-dashboard. No filter.userId = global scope (no-OAuth boot); with one, only records stamped with that id are visible or writable — an owner-less record is not (isDashboardOwnedBy). An existing but unreadable record rejects get/save/delete with DashboardUnreadableError and is listed with unreadable. The tools re-check a store's answers for an identified caller, so a laxer store cannot leak.
DashboardRecord{ id, name, description?, userId?, keys?, steps?, layout, title?, schemaVersion?, createdAt, updatedAt }. The { keys, steps, layout, title } slice is directly assignable to render-view's input; schemaVersion is stamped on save (DASHBOARD_SCHEMA_VERSION).
DashboardSaveInput{ id?, name, description?, userId?, keys?, steps?, layout, title? }.
DashboardSummary{ id, name, description?, title?, userId?, updatedAt, unreadable? }. Returned by list. userId is the owner (the tools verify a listing with it; without it, with one get per entry). unreadable carries the reason for a record this build cannot read (name then repeats the id).
DashboardListFilter{ userId? }.
FileSystemDashboardStoreOptions{ dir }. Directory for per-record <id>.json files.

Caller identity ​

Browser-safe; packages/core/src/auth/caller.ts. The one reader of both mcp-use 2 ctx.auth shapes — middleware gets the SDK AuthInfo (mapped user under ctx.auth.extra.user), tool/resource/prompt callbacks get the flattened ctx.auth.user.

SymbolSignature
resolveCaller(ctx: unknown) → Caller | undefined. undefined only when the request carries no auth at all; an authenticated caller whose provider maps no id yields a Caller without userId.
resolveCallerId(ctx: unknown) → string | undefined. Convenience for resolveCaller(ctx)?.userId.
Caller{ userId?, organizationId?, roles }. userId = user.id ?? user.userId ?? the token's payload.sub; organizationId = user.organizationId ?? user.organization_id; roles = string entries of user.roles.

Middleware ​

SymbolSignature
createOrgGateMiddleware(orgId?: string) → OrgGateMiddlewareFn.
createRoleFilterMiddleware(roleToModules) → { toolsList, toolsCall }.
OrgGateMiddleware(ctx, next: () => Promise<unknown>) → Promise<unknown>. The non-generic alias for typing your own middleware; the gate is assignable to it.
OrgGateMiddlewareFn<T>(ctx, next: () => Promise<T>) → Promise<T>. What createOrgGateMiddleware returns: generic over the chain result, so it registers on server.use("mcp:*", …) without a cast; reads the caller via resolveCaller.
RoleFilterMiddleware / RoleFilterMiddlewareFnThe same pair of shapes for the role filter: the non-generic alias for your own middleware, and the generic one the factory returns.
RoleFilterMiddlewares<M>{ toolsList: M, toolsCall: M }, M defaulting to RoleFilterMiddleware. The factory returns RoleFilterMiddlewares<RoleFilterMiddlewareFn>; toolsList / toolsCall register on mcp:tools/list / mcp:tools/call without a cast.
RoleFilterContextThe structural ctx slice both read: { auth?: { user?, extra? }, method?, params? } — mcp-use 2's MiddlewareContext is assignable to it.

@miragon/mcp-toolkit-core/tools ​

Server-side registrars — imports the mcp-use server runtime. Keep out of browser bundles.

SymbolSignature
installToolkit(server, opts?: InstallToolkitOptions) → InstalledToolkit. The standard entry point: adds the framework surface (get-framework-manifest, render-view + its view binding, app-only refresh-view, each module's widget tools, opt-in builder platform) to a server YOU constructed — run it through the mcp-use CLI (views/ convention) or embed it yourself. InstallToolkitOptions is { apps?, modules?, refreshToolName?, csp?, builder?, catalogueToolName?, dashboardStore?, requireCallerIdentity?, appConfig?, duplicateToolNames? } (requireCallerIdentity — set it when the server has OAuth — refuses dashboard calls that resolve no caller id even without any ctx.auth); returns the built { stepRegistry, widgetRegistry }. A tool name registered twice on the server — between modules, against a framework tool, or by application code after the install — is reported naming both owners: duplicateToolNames: "warn" (2.x default; mcp-use keeps the later registration) or "throw" (fail the install). The guard sees registrations from the install on only, so register your own tools after installToolkit.
createFrameworkApp(opts: CreateFrameworkAppOptions) → Promise<MCPServer>. The batteries-included Node adapter over installToolkit: constructs the MCPServer, wires auth middleware, and primes mcp-use's native view registry from a self-built bundle — for servers embedded in your own process or shipping views inline (gateways that only forward the JSON-RPC endpoint). Adds get-builder-catalogue + the four dashboard CRUD tools only when app.builder is true (opt-in; default off). With oauth set, dashboard calls without a resolvable caller id are refused (requireCallerIdentity).
CreateFrameworkAppOptions{ name, version?, description?, host?, oauth?, plugins, middleware?, app, appConfig? }. description feeds mcp-use's built-in landing page (browser GET on the MCP endpoint). Pass version (for example from your package.json): hosts and the landing page show it, and the default "0.1.0" only stays for compatibility. Branding such as favicon and icons goes through serverOptions. app accepts { bundle: { jsPath, cssPath? }, refreshToolName?, csp?, builder?, catalogueToolName?, dashboardStore?, duplicateToolNames? }. builder (default false) gates the catalogue + dashboard tools; catalogueToolName / dashboardStore apply only when builder is true. The serving origin is request-resolved by mcp-use (or MCP_URL) — there is no baseUrl option.
registerFrameworkTools(server, opts: RegisterFrameworkToolsOptions) → void.
RegisterFrameworkToolsOptions{ stepRegistry, widgetRegistry, config, appConfigs, plugins, refreshToolName?, builderAvailable?, csp? }. render-view is bound to the RENDER_VIEW_NAME view; callers outside createFrameworkApp must prime the view registry themselves.
registerCatalogueTool(server, opts: RegisterCatalogueToolOptions) → void. Registers get-builder-catalogue with the native visibility: "app" — the iframe builder's data source. Never appears in the LLM's tools/list.
RegisterCatalogueToolOptions{ stepRegistry, widgetRegistry, appConfigs, apps?, toolName? }. apps as in CatalogueOptions.
registerDashboardTools(server, opts: RegisterDashboardToolsOptions) → void. Registers save-/list-/load-/delete-dashboard.
RegisterDashboardToolsOptions{ store: DashboardStore, widgetRegistry?, requireCallerIdentity? }. With a registry, save-dashboard warns (never rejects) on layout widget ids it doesn't know. The caller is scoped via resolveCaller; an authenticated call without an id is refused, and requireCallerIdentity extends that to calls without any ctx.auth. For an identified caller every store answer is re-checked with isDashboardOwnedBy.
createInMemoryDashboardStore() → DashboardStore. Process-local, lost on restart. Default when app.builder is true and app.dashboardStore is omitted.
createFileSystemDashboardStore(opts: FileSystemDashboardStoreOptions) → DashboardStore. JSON-per-record under opts.dir.
DASHBOARD_SCHEMA_VERSIONnumber (1). Stamped onto DashboardRecord.schemaVersion on every save.
DashboardUnreadableErrorClass (dashboardId, reason). Rejected by a store's get / save / delete when the addressed record exists but cannot be read (newer schemaVersion, corrupt JSON, failed schema) — a conflict, never "absent", so a save cannot overwrite it. The dashboard tools surface it as isError.
isDashboardOwnedBy(ownerId?, userId?) → boolean. The store contract's ownership rule: no userId = global scope (everything); otherwise only ownerId === userId — an owner-less record is no identified caller's. Apply it in a custom store.
createToolRegistrar(server, client, options?: ToolRegistrarOptions) → register(ToolConfig). register is generic over the inputSchema shape, so a handler's args are inferred from the schema (ToolArgs<TShape>) instead of Record<string, any> — no manual cast needed. Handlers are called (client, args, ctx) with mcp-use's per-call ToolHandlerContext. ToolConfig adds strictInput? (reject unknown keys with a tool error naming the valid keys; additionalProperties: false on the wire) and definition?: ToolDefinitionPassthrough (every other mcp-use ToolDefinition field — title, _meta, visibility, securitySchemes, view). register() returns the mcp-use ToolRef at runtime; it is typed as one (TypedToolRegistrar) with toolRefs: true, void otherwise so hand-written registrar wrappers keep compiling.
createWidgetToolRegistrar(server, client, metaDefaults?, options?: ToolRegistrarOptions) → (config: WidgetToolConfig) → void. Model-visible tools are bound to a view named after the tool (mcp-use derives the _meta.ui wire keys) and get the openai/* Apps SDK keys; app-only tools carry the native visibility: "app". WidgetToolConfig adds visibility (default "app"), outputSchema? (required by a view binding; defaults to a passthrough object), annotations, and meta (extra flat _meta; the ui namespace is mcp-use-owned) to the usual { name, title?, description, inputSchema?, handler }. Handlers are called (client, params, ctx); WidgetToolConfig also takes strictInput? and definition?: WidgetToolDefinitionPassthrough (e.g. securitySchemes). Returns the ToolRef like createToolRegistrar (typed with toolRefs: true: TypedWidgetToolRegistrar).
WidgetToolVisibility"app" | "model". "app" (the default) hides the tool from the LLM via the native visibility: "app" — emitted on the wire as _meta.ui.visibility: ["app"] — while keeping it callable from a widget; "model" exposes it to the LLM and binds a view named after the tool so the host renders its result.
ToolHandlerContextRequestContext<TUser, "optional"> from mcp-use — the third handler argument of both registrars: signal (aborts when the client cancels or the connection drops), reportProgress, sendLog, sendNotification, client, request, auth?. Optional in the handler type so handlers stay callable as (client, args); the registrars always pass it. TUser is the server's OAuth user type for a registrar created from an MCPServer<TUser>, else unknown.
ToolRegistrarOptions{ strictInput?, toolRefs? }. strictInput is the default for every tool's own flag (off in 2.x); toolRefs: true selects the ToolRef-typed registrar.
ToolDefinitionPassthrough / WidgetToolDefinitionPassthroughOmit<ToolDefinition, …> — the mcp-use definition fields a registrar forwards verbatim. The registrar-derived keys (name, description, schemas, annotations; for widget tools also title, visibility, view, _meta) are excluded and always win.
ToolRegistrar / TypedToolRegistrarThe register function types of createToolRegistrar: void-returning (default, wrapper-compatible) / ToolRef<Name, ToolArgs<TShape>, RegistrarToolOutput<TOutput>>-returning (toolRefs: true). Both carry getRegisteredTools().
WidgetToolRegistrar / TypedWidgetToolRegistrarThe same pair for createWidgetToolRegistrar; the typed output is the declared outputSchema, else the structuredContent record (WidgetToolOutput).
ToolArgs / RegistrarToolOutputToolArgs<TShape> — the validated args inferred from an input shape. RegistrarToolOutput<TOutput> — a registrar tool's structured output: arrays wrapped into { data }, never without an outputSchema (mcp-use's own convention).
DuplicateToolNamePolicy"warn" | "throw" — InstallToolkitOptions.duplicateToolNames / app.duplicateToolNames.
withToolErrors(handler) → handler. Wraps a tool handler so thrown errors map to an isError: true MCP result (errorResult) instead of surfacing as a transport failure.
textResult / objectResult / errorResultRaw CallToolResult builders replacing mcp-use's deprecated text() / object() / error() helpers, wire-identical. objectResult emits pretty-printed JSON text + structuredContent; errorResult carries a literal isError: true.
createBackendRegistry(entries, opts?: CreateBackendRegistryOptions) → BackendRegistry. Stateless resolution (resolve(id?) / list()) for tools that target one of several configured backends: explicit per-call id > the single configured backend, else BackendNotSelectedError. Keeps NO per-session selection state (replica-safe by construction) — a consumer wanting a sticky/default backend resolves that id itself (e.g. from a durable per-user profile) and passes it to resolve. BackendEntry / ResolvedBackend describe an entry / a resolved backend; UnknownBackendError rejects unregistered ids.
withBackend(registry, paramName, handler) → handler. Reads the backend id from args[paramName], resolves it (explicit id > single default) and passes the backend to the wrapped handler.

@miragon/mcp-toolkit-core/rest ​

A small REST client + tool helper for plugins that wrap a plain HTTP API. Pair createRestClient with the standard createToolRegistrar so REST tools share the same registration path, error mapping, and result formatting as hand-written tools.

SymbolSignature
createRestClient(config: RestClientConfig) → RestClient. Builds a fetch-backed client with URL-template expansion, query encoding, auth header stamping, JSON serialization, and RestError mapping for non-2xx responses.
createRestTool(config: RestToolConfig) → ToolConfig<RestClient>. Produces a tool config the standard createToolRegistrar can register. Default buildRequest puts path placeholders into pathParams, the rest into query (GET/DELETE) or body (POST/PUT/PATCH).
RestErrorClass. { status, statusText, body }. Thrown by request() on non-2xx; createToolRegistrar's error handler renders it as [<status>] <message> in the MCP tool response.
RestClientConfig{ baseUrl, auth?, defaultHeaders?, fetch?, timeoutMs? }. timeoutMs defaults to 30000; a request that doesn't settle is aborted so a hung backend can't block a tool call. 0 disables it.
RestRequestOptions{ method, path, pathParams?, query?, body?, headers?, signal?, timeoutMs? }. signal cancels from the caller; timeoutMs overrides the client default for this call.
RestClient{ request<T>(options), baseUrl }.
RestAuthConfigDiscriminated union: none / bearer / header.
HttpMethod"GET" | "POST" | "PUT" | "PATCH" | "DELETE".
QueryValuestring | number | boolean | null | undefined. Arrays of these are also accepted on query.
RestToolConfig{ name, description, category?, method, path, inputSchema?, buildRequest?, projection?, annotations?, formatResult? }. projection is the main context-hygiene lever — trim raw response shape before handing it to the LLM.
RequestPartsPick<RestRequestOptions, "pathParams" | "query" | "body" | "headers">. Return type of buildRequest.

Source map ​

packages/core/src/
├── types/            runtime-safe types
├── engine/           pipeline-executor, context-builder
├── registry/         step-registry, widget-registry, app-loader
├── framework/        render-view, catalogue, manifest, layout-*, active-modules
├── auth/             caller (resolveCaller — both mcp-use 2 ctx.auth shapes)
├── middleware/       org-gate, role-filter
├── rest/             createRestClient + createRestTool + RestError
└── tools/            registrars, dashboard-store — import the mcp-use server runtime / node:*

See also ​

Released under the MIT License.