workatomcp-bridge
v1.3.6
Published
WorkatoMCP native messaging host (Chrome ↔ MCP bridge)
Readme
Fastify Chrome Native Messaging Service
A Fastify-based TypeScript project for native communication with a Chrome extension.
Features
- Bidirectional communication with Chrome extensions via Chrome Native Messaging protocol
- Multi-browser support: Chrome and Chromium (Linux, macOS, and Windows)
- RESTful API service
- Written entirely in TypeScript
- Includes a complete test suite
- Follows code quality best practices
Development Setup
Prerequisites
- Node.js 20+
- npm 8+ or pnpm 8+
Installation
git clone https://github.com/your-username/fastify-chrome-native.git
cd fastify-chrome-native
npm installDevelopment
- Build locally and register the native server
cd app/native-server
npm run dev- Start the Chrome extension
cd app/chrome-extension
npm run devBuild
npm run buildRegistering the Native Messaging Host
Auto-detect and register all installed browsers
mcp-chrome-bridge register --detectRegister a specific browser
# Chrome only
mcp-chrome-bridge register --browser chrome
# Chromium only
mcp-chrome-bridge register --browser chromium
# All supported browsers
mcp-chrome-bridge register --browser allGlobal install (auto-registers detected browsers)
npm i -g mcp-chrome-bridgeBrowser Support
| Browser | Linux | macOS | Windows | | ------------- | ----- | ----- | ------- | | Google Chrome | ✓ | ✓ | ✓ | | Chromium | ✓ | ✓ | ✓ |
Registration locations:
- Linux:
~/.config/[browser-name]/NativeMessagingHosts/ - macOS:
~/Library/Application Support/[Browser]/NativeMessagingHosts/ - Windows:
%APPDATA%\[Browser]\NativeMessagingHosts\
Chrome Extension Integration
Example of how to use this service from a Chrome extension:
// background.js
let nativePort = null;
let serverRunning = false;
// Start the Native Messaging service
function startServer() {
if (nativePort) {
console.log('Already connected to Native Messaging host');
return;
}
try {
nativePort = chrome.runtime.connectNative('com.yourcompany.fastify_native_host');
nativePort.onMessage.addListener((message) => {
console.log('Received native message:', message);
if (message.type === 'started') {
serverRunning = true;
console.log(`Server started on port: ${message.payload.port}`);
} else if (message.type === 'stopped') {
serverRunning = false;
console.log('Server stopped');
} else if (message.type === 'error') {
console.error('Native error:', message.payload.message);
}
});
nativePort.onDisconnect.addListener(() => {
console.log('Native connection disconnected:', chrome.runtime.lastError);
nativePort = null;
serverRunning = false;
});
// Start the server
nativePort.postMessage({ type: 'start', payload: { port: 3000 } });
} catch (error) {
console.error('Error starting Native Messaging:', error);
}
}
// Stop the server
function stopServer() {
if (nativePort && serverRunning) {
nativePort.postMessage({ type: 'stop' });
}
}
// Test communication with the server
async function testPing() {
try {
const response = await fetch('http://localhost:3000/ping');
const data = await response.json();
console.log('Ping response:', data);
return data;
} catch (error) {
console.error('Ping failed:', error);
return null;
}
}
// Connect to the native host when the extension starts
chrome.runtime.onStartup.addListener(startServer);
// Expose API to popup or content scripts
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.action === 'startServer') {
startServer();
sendResponse({ success: true });
} else if (message.action === 'stopServer') {
stopServer();
sendResponse({ success: true });
} else if (message.action === 'testPing') {
testPing().then(sendResponse);
return true; // Indicates we will send the response asynchronously
}
});Testing
npm run testLicense
MIT
