UNPKG

mcp-use

Version:

Opinionated MCP Framework for TypeScript (@modelcontextprotocol/sdk compatible) - Build MCP Agents and Clients + MCP Servers with support for MCP-UI.

556 lines 23.1 kB
import type { PromptDefinition, ResourceDefinition, ResourceTemplateDefinition, ServerConfig, ToolDefinition, UIResourceDefinition } from "./types/index.js"; import { type Express } from "express"; export declare class McpServer { private server; private config; private app; private mcpMounted; private inspectorMounted; private serverPort?; private serverHost; private serverBaseUrl?; /** * Creates a new MCP server instance with Express integration * * Initializes the server with the provided configuration, sets up CORS headers, * configures widget serving routes, and creates a proxy that allows direct * access to Express methods while preserving MCP server functionality. * * @param config - Server configuration including name, version, and description * @returns A proxied McpServer instance that supports both MCP and Express methods */ constructor(config: ServerConfig); /** * Define a static resource that can be accessed by clients * * Registers a resource with the MCP server that clients can access via HTTP. * Resources are static content like files, data, or pre-computed results that * can be retrieved by clients without requiring parameters. * * @param resourceDefinition - Configuration object containing resource metadata and handler function * @param resourceDefinition.name - Unique identifier for the resource * @param resourceDefinition.uri - URI pattern for accessing the resource * @param resourceDefinition.title - Optional human-readable title for the resource * @param resourceDefinition.description - Optional description of the resource * @param resourceDefinition.mimeType - MIME type of the resource content * @param resourceDefinition.annotations - Optional annotations (audience, priority, lastModified) * @param resourceDefinition.readCallback - Async callback function that returns the resource content * @returns The server instance for method chaining * * @example * ```typescript * server.resource({ * name: 'config', * uri: 'config://app-settings', * title: 'Application Settings', * mimeType: 'application/json', * description: 'Current application configuration', * annotations: { * audience: ['user'], * priority: 0.8 * }, * readCallback: async () => ({ * contents: [{ * uri: 'config://app-settings', * mimeType: 'application/json', * text: JSON.stringify({ theme: 'dark', language: 'en' }) * }] * }) * }) * ``` */ resource(resourceDefinition: ResourceDefinition): this; /** * Define a dynamic resource template with parameters * * Registers a parameterized resource template with the MCP server. Templates use URI * patterns with placeholders that can be filled in at request time, allowing dynamic * resource generation based on parameters. * * @param resourceTemplateDefinition - Configuration object for the resource template * @param resourceTemplateDefinition.name - Unique identifier for the template * @param resourceTemplateDefinition.resourceTemplate - ResourceTemplate object with uriTemplate and metadata * @param resourceTemplateDefinition.readCallback - Async callback function that generates resource content from URI and params * @returns The server instance for method chaining * * @example * ```typescript * server.resourceTemplate({ * name: 'user-profile', * resourceTemplate: { * uriTemplate: 'user://{userId}/profile', * name: 'User Profile', * mimeType: 'application/json' * }, * readCallback: async (uri, params) => ({ * contents: [{ * uri: uri.toString(), * mimeType: 'application/json', * text: JSON.stringify({ userId: params.userId, name: 'John Doe' }) * }] * }) * }) * ``` */ resourceTemplate(resourceTemplateDefinition: ResourceTemplateDefinition): this; /** * Define a tool that can be called by clients * * Registers a tool with the MCP server that clients can invoke with parameters. * Tools are functions that perform actions, computations, or operations and * return results. They accept structured input parameters and return structured output. * * Supports Apps SDK metadata for ChatGPT integration via the _meta field. * * @param toolDefinition - Configuration object containing tool metadata and handler function * @param toolDefinition.name - Unique identifier for the tool * @param toolDefinition.description - Human-readable description of what the tool does * @param toolDefinition.inputs - Array of input parameter definitions with types and validation * @param toolDefinition.cb - Async callback function that executes the tool logic with provided parameters * @param toolDefinition._meta - Optional metadata for the tool (e.g. Apps SDK metadata) * @returns The server instance for method chaining * * @example * ```typescript * server.tool({ * name: 'calculate', * description: 'Performs mathematical calculations', * inputs: [ * { name: 'expression', type: 'string', required: true }, * { name: 'precision', type: 'number', required: false } * ], * cb: async ({ expression, precision = 2 }) => { * const result = eval(expression) * return { result: Number(result.toFixed(precision)) } * }, * _meta: { * 'openai/outputTemplate': 'ui://widgets/calculator', * 'openai/toolInvocation/invoking': 'Calculating...', * 'openai/toolInvocation/invoked': 'Calculation complete' * } * }) * ``` */ tool(toolDefinition: ToolDefinition): this; /** * Define a prompt template * * Registers a prompt template with the MCP server that clients can use to generate * structured prompts for AI models. Prompt templates accept parameters and return * formatted text that can be used as input to language models or other AI systems. * * @param promptDefinition - Configuration object containing prompt metadata and handler function * @param promptDefinition.name - Unique identifier for the prompt template * @param promptDefinition.description - Human-readable description of the prompt's purpose * @param promptDefinition.args - Array of argument definitions with types and validation * @param promptDefinition.cb - Async callback function that generates the prompt from provided arguments * @returns The server instance for method chaining * * @example * ```typescript * server.prompt({ * name: 'code-review', * description: 'Generates a code review prompt', * args: [ * { name: 'language', type: 'string', required: true }, * { name: 'focus', type: 'string', required: false } * ], * cb: async ({ language, focus = 'general' }) => { * return { * messages: [{ * role: 'user', * content: `Please review this ${language} code with focus on ${focus}...` * }] * } * } * }) * ``` */ prompt(promptDefinition: PromptDefinition): this; /** * Register a UI widget as both a tool and a resource * * Creates a unified interface for MCP-UI compatible widgets that can be accessed * either as tools (with parameters) or as resources (static access). The tool * allows dynamic parameter passing while the resource provides discoverable access. * * Supports multiple UI resource types: * - externalUrl: Legacy MCP-UI iframe-based widgets * - rawHtml: Legacy MCP-UI raw HTML content * - remoteDom: Legacy MCP-UI Remote DOM scripting * - appsSdk: OpenAI Apps SDK compatible widgets (text/html+skybridge) * * @param widgetNameOrDefinition - Widget name (string) for auto-loading schema, or full configuration object * @param definition.name - Unique identifier for the resource * @param definition.type - Type of UI resource (externalUrl, rawHtml, remoteDom, appsSdk) * @param definition.title - Human-readable title for the widget * @param definition.description - Description of the widget's functionality * @param definition.props - Widget properties configuration with types and defaults * @param definition.size - Preferred iframe size [width, height] (e.g., ['900px', '600px']) * @param definition.annotations - Resource annotations for discovery * @param definition.appsSdkMetadata - Apps SDK specific metadata (CSP, widget description, etc.) * @returns The server instance for method chaining * * @example * ```typescript * // Simple usage - auto-loads from generated schema * server.uiResource('display-weather') * * // Legacy MCP-UI widget * server.uiResource({ * type: 'externalUrl', * name: 'kanban-board', * widget: 'kanban-board', * title: 'Kanban Board', * description: 'Interactive task management board', * props: { * initialTasks: { * type: 'array', * description: 'Initial tasks to display', * required: false * } * }, * size: ['900px', '600px'] * }) * * // Apps SDK widget * server.uiResource({ * type: 'appsSdk', * name: 'kanban-board', * title: 'Kanban Board', * description: 'Interactive task management board', * htmlTemplate: ` * <div id="kanban-root"></div> * <style>${kanbanCSS}</style> * <script type="module">${kanbanJS}</script> * `, * appsSdkMetadata: { * 'openai/widgetDescription': 'Displays an interactive kanban board', * 'openai/widgetCSP': { * connect_domains: [], * resource_domains: ['https://cdn.example.com'] * } * } * }) * ``` */ uiResource(definition: UIResourceDefinition): this; /** * Create a UIResource object for a widget with the given parameters * * This method is shared between tool and resource handlers to avoid duplication. * It creates a consistent UIResource structure that can be rendered by MCP-UI * compatible clients. * * @private * @param definition - UIResource definition * @param params - Parameters to pass to the widget via URL * @returns UIResource object compatible with MCP-UI */ private createWidgetUIResource; /** * Build a complete URL for a widget including query parameters * * Constructs the full URL to access a widget's iframe, encoding any provided * parameters as query string parameters. Complex objects are JSON-stringified * for transmission. * * @private * @param widget - Widget name/identifier * @param params - Parameters to encode in the URL * @returns Complete URL with encoded parameters */ private buildWidgetUrl; /** * Convert widget props definition to tool input schema * * Transforms the widget props configuration into the format expected by * the tool registration system, mapping types and handling defaults. * * @private * @param props - Widget props configuration * @returns Array of InputDefinition objects for tool registration */ private convertPropsToInputs; /** * Apply default values to widget props * * Extracts default values from the props configuration to use when * the resource is accessed without parameters. * * @private * @param props - Widget props configuration * @returns Object with default values for each prop */ private applyDefaultProps; /** * Check if server is running in production mode * * @private * @returns true if in production mode, false otherwise */ private isProductionMode; /** * Read build manifest file * * @private * @returns Build manifest or null if not found */ private readBuildManifest; /** * Mount widget files - automatically chooses between dev and production mode * * In development mode: creates Vite dev servers with HMR support * In production mode: serves pre-built static widgets * * @param options - Configuration options * @param options.baseRoute - Base route for widgets (defaults to '/mcp-use/widgets') * @param options.resourcesDir - Directory containing widget files (defaults to 'resources') * @returns Promise that resolves when all widgets are mounted */ mountWidgets(options?: { baseRoute?: string; resourcesDir?: string; }): Promise<void>; /** * Mount individual widget files from resources/ directory in development mode * * Scans the resources/ directory for .tsx/.ts widget files and creates individual * Vite dev servers for each widget with HMR support. Each widget is served at its * own route: /mcp-use/widgets/{widget-name} * * @private * @param options - Configuration options * @param options.baseRoute - Base route for widgets (defaults to '/mcp-use/widgets') * @param options.resourcesDir - Directory containing widget files (defaults to 'resources') * @returns Promise that resolves when all widgets are mounted */ private mountWidgetsDev; /** * Mount pre-built widgets from dist/resources/widgets/ directory in production mode * * Serves static widget bundles that were built using the build command. * Sets up Express routes to serve the HTML and asset files, then registers * tools and resources for each widget. * * @private * @param options - Configuration options * @param options.baseRoute - Base route for widgets (defaults to '/mcp-use/widgets') * @returns Promise that resolves when all widgets are mounted */ private mountWidgetsProduction; /** * Mount MCP server endpoints at /mcp * * Sets up the HTTP transport layer for the MCP server, creating endpoints for * Server-Sent Events (SSE) streaming, POST message handling, and DELETE session cleanup. * Each request gets its own transport instance to prevent state conflicts between * concurrent client connections. * * This method is called automatically when the server starts listening and ensures * that MCP clients can communicate with the server over HTTP. * * @private * @returns Promise that resolves when MCP endpoints are successfully mounted * * @example * Endpoints created: * - GET /mcp - SSE streaming endpoint for real-time communication * - POST /mcp - Message handling endpoint for MCP protocol messages * - DELETE /mcp - Session cleanup endpoint */ private mountMcp; /** * Start the Express server with MCP endpoints * * Initiates the server startup process by mounting MCP endpoints, configuring * the inspector UI (if available), and starting the Express server to listen * for incoming connections. This is the main entry point for running the server. * * The server will be accessible at the specified port with MCP endpoints at /mcp * and inspector UI at /inspector (if the inspector package is installed). * * @param port - Port number to listen on (defaults to 3001 if not specified) * @returns Promise that resolves when the server is successfully listening * * @example * ```typescript * await server.listen(8080) * // Server now running at http://localhost:8080 (or configured host) * // MCP endpoints: http://localhost:8080/mcp * // Inspector UI: http://localhost:8080/inspector * ``` */ listen(port?: number): Promise<void>; /** * Mount MCP Inspector UI at /inspector * * Dynamically loads and mounts the MCP Inspector UI package if available, providing * a web-based interface for testing and debugging MCP servers. The inspector * automatically connects to the local MCP server endpoints. * * This method gracefully handles cases where the inspector package is not installed, * allowing the server to function without the inspector in production environments. * * @private * @returns void * * @example * If @mcp-use/inspector is installed: * - Inspector UI available at http://localhost:PORT/inspector * - Automatically connects to http://localhost:PORT/mcp * * If not installed: * - Server continues to function normally * - No inspector UI available */ private mountInspector; /** * Setup default widget serving routes * * Configures Express routes to serve MCP UI widgets and their static assets. * Widgets are served from the dist/resources/widgets directory and can * be accessed via HTTP endpoints for embedding in web applications. * * Routes created: * - GET /mcp-use/widgets/:widget - Serves widget's index.html * - GET /mcp-use/widgets/:widget/assets/* - Serves widget-specific assets * - GET /mcp-use/widgets/assets/* - Fallback asset serving with auto-discovery * * @private * @returns void * * @example * Widget routes: * - http://localhost:3001/mcp-use/widgets/kanban-board * - http://localhost:3001/mcp-use/widgets/todo-list/assets/style.css * - http://localhost:3001/mcp-use/widgets/assets/script.js (auto-discovered) */ private setupWidgetRoutes; /** * Create input schema for resource templates * * Parses a URI template string to extract parameter names and generates a Zod * validation schema for those parameters. Used internally for validating resource * template parameters before processing requests. * * @param uriTemplate - URI template string with parameter placeholders (e.g., "/users/{id}/posts/{postId}") * @returns Object mapping parameter names to Zod string schemas * * @example * ```typescript * const schema = this.createInputSchema("/users/{id}/posts/{postId}") * // Returns: { id: z.string(), postId: z.string() } * ``` */ private createInputSchema; /** * Create input schema for tools * * Converts tool input definitions into Zod validation schemas for runtime validation. * Supports common data types (string, number, boolean, object, array) and optional * parameters. Used internally when registering tools with the MCP server. * * @param inputs - Array of input parameter definitions with name, type, and optional flag * @returns Object mapping parameter names to Zod validation schemas * * @example * ```typescript * const schema = this.createParamsSchema([ * { name: 'query', type: 'string', required: true, description: 'Search query' }, * { name: 'limit', type: 'number', required: false } * ]) * // Returns: { query: z.string().describe('Search query'), limit: z.number().optional() } * ``` */ private createParamsSchema; /** * Create arguments schema for prompts * * Converts prompt argument definitions into Zod validation schemas for runtime validation. * Supports common data types (string, number, boolean, object, array) and optional * parameters. Used internally when registering prompt templates with the MCP server. * * @param inputs - Array of argument definitions with name, type, and optional flag * @returns Object mapping argument names to Zod validation schemas * * @example * ```typescript * const schema = this.createPromptArgsSchema([ * { name: 'topic', type: 'string', required: true }, * { name: 'style', type: 'string', required: false } * ]) * // Returns: { topic: z.string(), style: z.string().optional() } * ``` */ private createPromptArgsSchema; /** * Extract parameter names from URI template * * Parses a URI template string to extract parameter names enclosed in curly braces. * Used internally to identify dynamic parameters in resource templates and generate * appropriate validation schemas. * * @param uriTemplate - URI template string with parameter placeholders (e.g., "/users/{id}/posts/{postId}") * @returns Array of parameter names found in the template * * @example * ```typescript * const params = this.extractTemplateParams("/users/{id}/posts/{postId}") * // Returns: ["id", "postId"] * ``` */ private extractTemplateParams; /** * Parse parameter values from a URI based on a template * * Extracts parameter values from an actual URI by matching it against a URI template. * The template contains placeholders like {param} which are extracted as key-value pairs. * * @param template - URI template with placeholders (e.g., "user://{userId}/posts/{postId}") * @param uri - Actual URI to parse (e.g., "user://123/posts/456") * @returns Object mapping parameter names to their values * * @example * ```typescript * const params = this.parseTemplateUri("user://{userId}/posts/{postId}", "user://123/posts/456") * // Returns: { userId: "123", postId: "456" } * ``` */ private parseTemplateUri; } export type McpServerInstance = Omit<McpServer, keyof Express> & Express; /** * Create a new MCP server instance * * @param name - Server name * @param config - Optional server configuration * @param config.version - Server version (defaults to '1.0.0') * @param config.description - Server description * @param config.host - Hostname for widget URLs and server endpoints (defaults to 'localhost') * @param config.baseUrl - Full base URL (e.g., 'https://myserver.com') - overrides host:port for widget URLs * @returns McpServerInstance with both MCP and Express methods * * @example * ```typescript * // Basic usage * const server = createMCPServer('my-server', { * version: '1.0.0', * description: 'My MCP server' * }) * * // With custom host (e.g., for Docker or remote access) * const server = createMCPServer('my-server', { * version: '1.0.0', * host: '0.0.0.0' // or 'myserver.com' * }) * * // With full base URL (e.g., behind a proxy or custom domain) * const server = createMCPServer('my-server', { * version: '1.0.0', * baseUrl: 'https://myserver.com' // or process.env.MCP_URL * }) * ``` */ export declare function createMCPServer(name: string, config?: Partial<ServerConfig>): McpServerInstance; //# sourceMappingURL=mcp-server.d.ts.map