type-safe mcp tool registration with end-to-end type inference
Extends the official @modelcontextprotocol/sdk with a generic McpServer<TTools> class that accumulates tool definitions while preserving TypeScript type information across server and client boundaries. The framework uses a type inference system that propagates tool schemas from server registration through to React hooks on the client, enabling compile-time type checking for tool invocations without runtime type assertions. This is achieved through TypeScript generics and a manifest system that maps tool definitions to their implementations.
Unique: Uses TypeScript generics and a dual-package architecture (skybridge/server and skybridge/web) to propagate type information from MCP tool registration through to React hooks, enabling compile-time type checking across the server-client boundary without code generation or runtime reflection
vs alternatives: Provides stronger type safety than raw MCP SDK or Anthropic's Claude SDK because it maintains type information end-to-end rather than treating tool calls as untyped JSON, reducing integration bugs in ChatGPT App development
react hooks abstraction over chatgpt's window.openai imperative api
Wraps ChatGPT's injected window.openai global object with declarative React hooks (useToolInfo, useCallTool, useWidgetState, useOpenAiGlobal) that abstract away imperative callback patterns and state management. The hooks handle lifecycle management of tool invocations, state persistence, and environment access within widget iframes. This approach eliminates boilerplate for accessing tool metadata, invoking tools asynchronously, and managing widget-scoped state without requiring developers to interact directly with the low-level window.openai API.
Unique: Provides a complete React hooks layer (useToolInfo, useCallTool, useWidgetState, useOpenAiGlobal) that abstracts the imperative window.openai API into declarative, composable hooks with built-in lifecycle management, eliminating the need for developers to write callback-based integration code
vs alternatives: Simpler and more ergonomic than using window.openai directly because it follows React conventions and eliminates callback hell, while Anthropic's Claude SDK requires manual promise handling and state management in widget contexts
environment variable injection and configuration management
Skybridge provides environment hooks (useEnvironment, useConfig) that inject environment variables and configuration into widgets at runtime, with separate handling for development and production environments. Configuration is defined in a centralized file and automatically injected into widget iframes, eliminating the need for hardcoded values or manual environment variable passing. The system supports environment-specific overrides, allowing different configurations for development, staging, and production deployments.
Unique: Provides environment hooks that inject configuration into widgets at runtime with environment-specific overrides, eliminating hardcoded values while maintaining type safety through TypeScript configuration objects
vs alternatives: More secure than hardcoding API keys because it uses environment variables, while simpler than external secret management systems because it integrates directly into the widget initialization pipeline
action hooks for triggering mcp tool invocations from widget events
Skybridge provides action hooks that enable widgets to trigger MCP tool invocations in response to user events (clicks, form submissions, etc.) without manually managing async state or error handling. These hooks abstract the complexity of tool invocation lifecycle (loading, success, error states) and provide callbacks for handling results. The hooks integrate with React's event system, allowing declarative specification of which tools to invoke on which events.
Unique: Provides action hooks that abstract MCP tool invocation lifecycle (loading, success, error) with React event integration, eliminating manual async state management and error handling boilerplate
vs alternatives: More ergonomic than useCallTool because it handles loading and error states automatically, while simpler than full state management libraries because it's scoped to individual tool invocations
widget html rendering from handlebars templates with type-aware context
The TemplateHelper class renders widget HTML from Handlebars templates, injecting typed context data derived from tool definitions and widget metadata. Templates can reference tool parameters, descriptions, and other schema information through Handlebars syntax, enabling dynamic UI generation based on tool structure. The system supports both development and production modes, with development mode allowing hot-reload of template changes and production mode bundling templates into optimized assets.
Unique: Integrates Handlebars templating with MCP tool schema context, allowing templates to reference tool metadata directly and render dynamic UI based on tool structure, with separate development and production rendering paths
vs alternatives: More flexible than hardcoded widget HTML because templates can adapt to different tool schemas, but less powerful than React for complex interactive UIs — best suited for form-based or data-display widgets
automatic widget discovery and bundling via vite plugin
A custom Vite plugin scans the src/widgets/ directory to discover widget components, bundles each widget as an independent asset, and generates a manifest.json file mapping widget source files to their bundled outputs. The plugin handles both development and production modes: in development, it enables Hot Module Replacement (HMR) for rapid iteration; in production, it optimizes widget bundles for size and performance. The manifest enables the MCP server to locate and serve widget assets dynamically at runtime.
Unique: Implements a Vite plugin that automatically discovers widgets in src/widgets/, bundles them independently, generates a runtime manifest, and provides HMR support — eliminating manual webpack/rollup configuration for multi-widget ChatGPT Apps
vs alternatives: More ergonomic than manual Vite configuration because it handles widget discovery and manifest generation automatically, and provides better DX than raw MCP server setup because HMR enables instant feedback during widget development
local development environment with integrated devtools ui
Skybridge provides a DevTools application that runs locally during development, offering a web-based UI for testing widgets without deploying to ChatGPT. The DevTools includes a tool panel for selecting and invoking MCP tools, a widget renderer that displays the selected widget's UI, and a development server that serves widget assets with HMR enabled. The DevTools communicates with the MCP server via stdio or HTTP, allowing developers to test tool invocations and widget interactions in an isolated environment before deploying to production.
Unique: Provides an integrated web-based DevTools UI that simulates ChatGPT's widget environment locally, with a tool panel for invoking MCP tools and HMR support for instant widget feedback — eliminating the need to deploy to ChatGPT for every iteration
vs alternatives: More complete than raw MCP testing because it includes a visual widget renderer and tool invocation UI, and faster than ChatGPT deployment because HMR enables instant feedback without network round-trips
typed helper factory for generating widget-specific utility functions
The generateHelpers<AppType>() factory function creates a set of typed utility functions scoped to a specific widget's tool context. These helpers provide type-safe wrappers around useCallTool and other hooks, with pre-bound tool names and parameter types inferred from the AppType generic. This eliminates the need to manually specify tool names and types in every hook call, reducing boilerplate and improving IDE autocomplete for tool invocations within a widget.
Unique: Provides a generateHelpers<AppType>() factory that creates typed utility functions for a widget's tools, with parameter types and tool names inferred from the AppType generic — enabling IDE autocomplete and reducing boilerplate in widget code
vs alternatives: More ergonomic than manually typing useCallTool calls because it pre-binds tool names and infers parameter types, while maintaining full type safety without code generation
+4 more capabilities