@redonvn/mcp-extension-lib
v0.2.0
Published
MCP (Model Context Protocol) library for Chrome Extensions
Downloads
236
Readme
MCP Extension Library
A TypeScript library for building MCP (Model Context Protocol) servers in Chrome Extensions. This library allows extensions to expose browser control capabilities through a standardized protocol that AI coding agents can use.
Features
- 🎯 Built-in Tool Packs - Pre-built tools for navigation, DOM interaction, and debugging
- 🔌 Chrome-specific adapters - Ready-to-use helpers for extension APIs
- 🚀 Easy integration - Import tool packs and start serving
- 📦 Type-safe - Full TypeScript support with detailed descriptions
- 🔄 Flexible - Use all tools or cherry-pick specific packs
- ⚙️ Dynamic Configuration - User-configurable WebSocket settings with chrome.storage
Installation
npm install @your-scope/mcp-extension-libQuick Start
1. Use Built-in Tool Packs
In your extension's background/sw.ts:
import {createRouter} from '@your-scope/mcp-extension-lib';
import {createMcpExtensionServer} from '@your-scope/mcp-extension-lib/chrome';
import {toolPacks, mergeToolPacks} from '@your-scope/mcp-extension-lib/chrome';
// Option 1: Use all available tools
// import {allTools} from '@your-scope/mcp-extension-lib/chrome';
// const router = createRouter({
// toolDefs: allTools.definitions,
// handlers: allTools.handlers,
// });
// Option 2: Select specific tool packs
const tools = mergeToolPacks([
toolPacks.navigation, // navigate, new_page, close_page, list_pages, reload_page
toolPacks.dom, // dom.click, dom.fill, dom.getText, dom.waitForSelector
toolPacks.debugging, // screenshot, evaluate_script
]);
const router = createRouter({
toolDefs: tools.definitions,
handlers: tools.handlers,
});
// Start MCP server
const server = createMcpExtensionServer({
router,
transport: {type: 'runtimePort'},
});
server.listen();2. Update manifest.json
{
"manifest_version": 3,
"name": "Your Extension",
"version": "1.0.0",
"permissions": ["activeTab", "scripting", "tabs"],
"background": {
"service_worker": "background/sw.js",
"type": "module"
},
"host_permissions": ["<all_urls>"]
}WebSocket Bridge Architecture
For AI agent integration and remote browser control, use the WebSocket Bridge:
Extension ↔ WebSocket Bridge ↔ MCP Server ↔ AI AgentQuick Setup
- Start the WebSocket Bridge Server:
cd packages/wss-bridge
npm install
cp .env.example .env
# Edit .env: set API_KEYS=your-secure-key
npm run dev- Configure Extension for WebSocket transport:
import {createRouter} from '@redonvn/mcp-extension-lib';
import {createMcpExtensionServer, toolPacks} from '@redonvn/mcp-extension-lib/chrome';
const server = createMcpExtensionServer({
router: createRouter({
toolDefs: toolPacks.navigation.definitions,
handlers: toolPacks.navigation.handlers,
}),
transport: {
type: 'websocket',
serverUrl: 'ws://localhost:8012',
apiKey: 'your-secure-key',
reconnect: true,
onStateChange: (state) => {
console.log('Connection state:', state); // 'connected', 'disconnected', etc.
},
},
});
server.listen();Dynamic Configuration (Recommended)
Allow users to configure WebSocket URL and API Key through an options page:
import {createRouter} from '@redonvn/mcp-extension-lib';
import {
createMcpExtensionServer,
toolPacks,
loadWebSocketConfig,
onConfigChange
} from '@redonvn/mcp-extension-lib/chrome';
// Load config from chrome.storage with defaults
const config = await loadWebSocketConfig({
defaultUrl: 'ws://localhost:8012',
defaultApiKey: 'your-default-key'
});
const server = createMcpExtensionServer({
router: createRouter({
toolDefs: toolPacks.navigation.definitions,
handlers: toolPacks.navigation.handlers,
}),
transport: {
type: 'websocket',
serverUrl: config.serverUrl, // User-configurable!
apiKey: config.apiKey, // User-configurable!
reconnect: true,
},
});
server.listen();
// Auto-reconnect when user changes settings
onConfigChange((newConfig) => {
console.log('Config changed, reconnecting...');
// Reinitialize server with new config
});Benefits:
- ✅ No hardcoded URLs or API keys
- ✅ Users can switch between dev/prod servers
- ✅ Settings sync across devices via
chrome.storage.sync - ✅ Auto-reconnect on settings change
See Configuration Guide for complete implementation with options page UI.
See WebSocket Bridge Demo for a complete working example.
Security
- Extension NEVER calls AI APIs directly
- API keys stored server-side only
- Authentication, rate limiting, and session management included
- Production-ready for Railway, Fly.io, or custom deployment
Available Tool Packs
Navigation Tools (toolPacks.navigation)
| Tool | Description |
|------|-------------|
| navigate | Navigate the current tab to a URL |
| new_page | Create a new tab and navigate to URL |
| close_page | Close a tab by ID |
| list_pages | List all open tabs |
| reload_page | Reload a tab (with optional cache bypass) |
DOM Tools (toolPacks.dom)
| Tool | Description |
|------|-------------|
| dom.click | Click element by CSS selector |
| dom.fill | Fill input/textarea/select element |
| dom.getText | Get text content of an element |
| dom.waitForSelector | Wait for element to appear in DOM |
Debugging Tools (toolPacks.debugging)
| Tool | Description |
|------|-------------|
| screenshot | Capture screenshot of visible tab area |
| evaluate_script | Execute JavaScript and return result |
Custom Tools
You can also create custom tool packs:
import type {ToolPack} from '@your-scope/mcp-extension-lib/chrome';
import {ok, err} from '@your-scope/mcp-extension-lib';
const customTools: ToolPack = {
definitions: [
{
name: 'custom.doSomething',
description: 'Do something custom',
inputSchema: {
type: 'object',
properties: {
param: {type: 'string', description: 'Parameter description'},
},
required: ['param'],
},
annotations: {
category: 'custom',
readOnlyHint: false,
},
},
],
handlers: {
async 'custom.doSomething'(params, context) {
try {
// Implementation
return ok('Success!');
} catch (error) {
return err(error as Error);
}
},
},
};
// Merge with built-in tools
const tools = mergeToolPacks([
toolPacks.navigation,
customTools,
]);API Reference
Tool Packs
import {toolPacks, mergeToolPacks, allTools} from '@your-scope/mcp-extension-lib/chrome';
// Individual packs
toolPacks.navigation
toolPacks.dom
toolPacks.debugging
// Merge multiple packs
const tools = mergeToolPacks([...packs]);
// All tools combined
allTools.definitions
allTools.handlersChrome Helpers
import * as tabs from '@your-scope/mcp-extension-lib/chrome';
import * as scripting from '@your-scope/mcp-extension-lib/chrome';
import * as storage from '@your-scope/mcp-extension-lib/chrome';Architecture
Local Development (Runtime Port)
src/
├── core/ # Platform-agnostic MCP protocol
│ ├── protocol.ts # MCP message types
│ ├── router.ts # Request router
│ └── types.ts # Type definitions
└── chrome/ # Chrome extension adapter
├── tools/ # Built-in tool packs
│ ├── navigation.ts
│ ├── dom.ts
│ └── debugging.ts
├── exec/ # Chrome API helpers
├── transport/ # Transport layers
│ ├── runtimePort.ts # Local chrome.runtime messaging
│ └── wsClient.ts # WebSocket for remote control
└── server.ts # MCP Extension ServerRemote Control (WebSocket Bridge)
packages/
└── wss-bridge/ # WebSocket Bridge Server
├── src/
│ ├── server.ts # Main WebSocket server
│ ├── auth/ # Authentication & rate limiting
│ ├── mcp/ # MCP client integration
│ └── types/ # TypeScript definitions
└── README.md
examples/
└── websocket-bridge-demo/ # Full demo implementationTransport Options
Runtime Port (Default)
- Use case: Extension-internal communication (popup ↔ background)
- Setup: Simple, no external server needed
- Best for: Local development, simple extensions
WebSocket
- Use case: AI agent control, remote automation
- Setup: Requires WebSocket Bridge server
- Best for: Production automation, team collaboration, cloud agents
Examples
- minimal-extension - Basic extension using RuntimePort transport
- websocket-bridge-demo - Complete AI agent integration with WebSocket Bridge
See each example's README for detailed setup instructions.
TypeScript
This library is written in TypeScript and provides full type definitions.
License
MIT
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
