@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
| Symbol | Purpose |
|---|---|
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 / StepResult | Step 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. |
LocalizedText | string | 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 }. |
ViewStructuredContent | The 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
| Symbol | Signature |
|---|---|
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 |
StepRegistry | Class. register(step), get(id), getAll(), getKeyContracts(). |
WidgetRegistry | Class. 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
| Symbol | Signature |
|---|---|
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. |
ViewStructuredContent | The view envelope written into a view tool's structuredContent: { context: { stepData, … }, layout, … }. Consumed by McpAppView. |
SingleWidgetViewInput / ComposedViewInput / ComposedViewEntry / ViewToolResult | Input/return types for the two view builders. |
collectLayoutWidgets | (layout) → string[]. The widget ids a layout references — used by save-dashboard validation. |
deriveItemCount / defaultSummary | Helpers 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 / RowDef | Static types for the layout shape. |
layoutSchema / rowSchema | Zod 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)
| Symbol | Shape |
|---|---|
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.
| Symbol | Signature |
|---|---|
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
| Symbol | Signature |
|---|---|
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 / RoleFilterMiddlewareFn | The 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. |
RoleFilterContext | The 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.
| Symbol | Signature |
|---|---|
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_VERSION | number (1). Stamped onto DashboardRecord.schemaVersion on every save. |
DashboardUnreadableError | Class (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. |
ToolHandlerContext | RequestContext<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 / WidgetToolDefinitionPassthrough | Omit<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 / TypedToolRegistrar | The register function types of createToolRegistrar: void-returning (default, wrapper-compatible) / ToolRef<Name, ToolArgs<TShape>, RegistrarToolOutput<TOutput>>-returning (toolRefs: true). Both carry getRegisteredTools(). |
WidgetToolRegistrar / TypedWidgetToolRegistrar | The same pair for createWidgetToolRegistrar; the typed output is the declared outputSchema, else the structuredContent record (WidgetToolOutput). |
ToolArgs / RegistrarToolOutput | ToolArgs<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 / errorResult | Raw 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.
| Symbol | Signature |
|---|---|
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). |
RestError | Class. { 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 }. |
RestAuthConfig | Discriminated union: none / bearer / header. |
HttpMethod | "GET" | "POST" | "PUT" | "PATCH" | "DELETE". |
QueryValue | string | 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. |
RequestParts | Pick<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:*