Plugin development

Plugins extend OpenWriter with custom MCP tools, HTTP routes, context menu items, and sidebar actions.

Plugin interface

interface OpenWriterPlugin {
  name: string;
  version: string;
  description?: string;
  category?: PluginCategory;
  configSchema?: Record<string, PluginConfigField>;
  registerRoutes?(ctx: PluginRouteContext): void | Promise<void>;
  mcpTools?(config: Record<string, string>): PluginMcpTool[];
  contextMenuItems?(): PluginContextMenuItem[];
  sidebarMenuItems?(): PluginSidebarMenuItem[];
}

type PluginCategory =
  | 'writing' | 'social-media' | 'image-generation'
  | 'publishing' | 'productivity' | 'analytics';

PluginRouteContext carries the Express router (app), the plugin’s resolved config, and the dataDir.

Extension points

1. MCP tools

Register tools that any MCP agent can call. mcpTools is a function that receives the plugin’s config and returns the tools. Define each tool’s input with JSON Schema.

2. HTTP routes

Add custom API endpoints to the local server. Access editor state and document data.

3. Context menu items

Add right-click actions on text selection. Three conditions:

  • has-selection — only when text is selected
  • empty-node — only on empty nodes
  • always — always visible

4. Sidebar menu items

Add right-click actions on documents in the sidebar. Two optional flags:

  • promptForFocus: show a focus instructions prompt before the action runs
  • folderCapable: also offer the action on a workspace or container, applied to every doc inside it

Bundled plugins

PluginCategoryWhat It Does
Author’s VoiceWritingVoice profiling + rewrite in your voice
Image GeneratorImage GenerationAI image generation via Gemini
X APISocial MediaTweet/article posting and threading
PublishPublishingNewsletter, scheduler, subscriber management
GitHubProductivityCommit blog posts to your GitHub repo

Configuration

Plugins define a configSchema, a map of field names to PluginConfigField entries (type of string, number, boolean, or select, plus optional required, env, description, and options). Users set values through the plugin settings panel.

Distribution

  • First-party: @openwriter/plugin-*
  • Community: openwriter-plugin-* or @scope/openwriter-plugin-*