{"id":50666656,"url":"https://github.com/decocms/bridge","last_synced_at":"2026-06-08T07:03:36.123Z","repository":{"id":331711131,"uuid":"1126492407","full_name":"decocms/bridge","owner":"decocms","description":"MCP Mesh Bridge Chrome Extension — write connectors from any website for your agents to operate","archived":false,"fork":false,"pushed_at":"2026-01-10T22:46:41.000Z","size":250,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-11T06:53:23.315Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/decocms.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-02T02:53:24.000Z","updated_at":"2026-01-10T22:46:45.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/decocms/bridge","commit_stats":null,"previous_names":["decocms/bridge"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/decocms/bridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Fbridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Fbridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Fbridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Fbridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/decocms","download_url":"https://codeload.github.com/decocms/bridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/decocms%2Fbridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34051772,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-08T02:00:07.615Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-08T07:03:03.289Z","updated_at":"2026-06-08T07:03:36.112Z","avatar_url":"https://github.com/decocms.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# mesh-bridge\n\n**Turn any website into an MCP event stream.**\n\nA Chrome extension that maps DOM events to MCP Event Bus messages. AI agents can subscribe to browser events and publish responses that appear on websites—all running locally on your machine.\n\n```\n┌──────────────────────────────────────────────────────────────────┐\n│                          MCP MESH                                 │\n│                                                                   │\n│  ┌──────────────────────────────────────────────────────────┐    │\n│  │                      EVENT BUS                            │    │\n│  │                                                           │    │\n│  │   user.message.received ◄── bridge publishes              │    │\n│  │   agent.response.* ────────► bridge subscribes            │    │\n│  │                                                           │    │\n│  └──────────────────────────────────────────────────────────┘    │\n│                               ▲                                   │\n│                               │                                   │\n│  ┌─────────────┐    ┌────────┴────────┐    ┌─────────────────┐   │\n│  │   Agents    │    │  mesh-bridge    │    │   Other MCPs    │   │\n│  │             │◄───│                 │───►│                 │   │\n│  │  Subscribe  │    │  DOM ↔ Events   │    │  Can also       │   │\n│  │  Process    │    │                 │    │  subscribe/     │   │\n│  │  Respond    │    │  Domains:       │    │  publish        │   │\n│  │             │    │  • WhatsApp ✅  │    │                 │   │\n│  │             │    │  • CLI ✅       │    │                 │   │\n│  └─────────────┘    └────────┬────────┘    └─────────────────┘   │\n│                              │                                    │\n└──────────────────────────────┼────────────────────────────────────┘\n                               │ WebSocket\n        ┌──────────────────────┼──────────────────────┐\n        │                      │                      │\n┌───────▼─────────────┐  ┌─────▼──────────────┐\n│  Chrome Extension   │  │  CLI (terminal)    │\n│                     │  │                    │\n│  • Observes DOM     │  │  • bun dev         │\n│  • Injects AI text  │  │  • Monitor mode    │\n│  • Per-site scripts │  │  • Auto-reconnect  │\n└─────────────────────┘  └────────────────────┘\n```\n\n## How It Works\n\n1. **Extension** observes DOM events (new messages, clicks, navigation)\n2. **Bridge** translates DOM events into Event Bus messages\n3. **Agents** (or any MCP) subscribe to events and process them\n4. **Responses** flow back through the bridge into the DOM\n\n**The AI never sees the DOM.** It sees structured events like:\n\n```typescript\n{ type: \"user.message.received\", text: \"Hello\", source: \"whatsapp\", chatId: \"self\" }\n```\n\n## Quick Start\n\n### 1. Add to Mesh\n\nIn MCP Mesh, add a new **Custom Command** connection:\n\n| Field | Value |\n|-------|-------|\n| Name | `Mesh Bridge` |\n| Type | `Custom Command` |\n| Command | `bun` |\n| Arguments | `run`, `start` |\n| Working Directory | `/path/to/mesh-bridge` |\n\n### 2. Install Extension\n\n```bash\ncd mesh-bridge\nbun install\n```\n\nThen in Chrome:\n1. Go to `chrome://extensions`\n2. Enable **Developer mode**\n3. Click **Load unpacked** → select `extension/`\n\n### 3. Open WhatsApp Web\n\nNavigate to [web.whatsapp.com](https://web.whatsapp.com) and open your self-chat (\"Message Yourself\"). Send a message—the agent will respond!\n\n## The WhatsApp Domain\n\nThe WhatsApp domain demonstrates the full pattern:\n\n### DOM → Events\n\n```javascript\n// Content script observes new messages\nnew MutationObserver(() =\u003e {\n  const lastMessage = getLastMessage();\n  \n  if (isNewUserMessage(lastMessage)) {\n    socket.send(JSON.stringify({\n      type: \"message\",\n      domain: \"whatsapp\",\n      text: lastMessage,\n      chatId: getChatName()\n    }));\n  }\n}).observe(messageContainer, { childList: true, subtree: true });\n```\n\n### Bridge → Event Bus\n\n```typescript\n// Server publishes to Event Bus\nawait callMeshTool(eventBusId, \"EVENT_PUBLISH\", {\n  type: \"user.message.received\",\n  data: {\n    text: message.text,\n    source: \"whatsapp\",\n    chatId: message.chatId\n  }\n});\n```\n\n### Event Bus → DOM\n\n```javascript\n// Content script receives response\nsocket.onmessage = (event) =\u003e {\n  const frame = JSON.parse(event.data);\n  \n  if (frame.type === \"send\") {\n    // Inject into WhatsApp input\n    const input = document.querySelector('[data-testid=\"conversation-compose-box-input\"]');\n    input.focus();\n    document.execCommand(\"insertText\", false, frame.text);\n    document.querySelector('[data-testid=\"send\"]').click();\n  }\n};\n```\n\n## Event Types\n\n### Bridge Publishes\n\n```typescript\n\"user.message.received\" {\n  text: string;       // Message content\n  source: string;     // \"whatsapp\", \"linkedin\", etc.\n  chatId?: string;    // Conversation ID\n  sender?: { name?: string };\n}\n```\n\n### Bridge Subscribes To\n\n```typescript\n\"agent.response.whatsapp\" {\n  taskId: string;\n  chatId?: string;\n  text: string;\n  imageUrl?: string;\n  isFinal: boolean;\n}\n\n\"agent.task.progress\" {\n  taskId: string;\n  message: string;\n}\n```\n\n**Any MCP** can subscribe to `user.message.*` or publish `agent.response.*` events.\n\n## Adding a Domain\n\n### Step 1: Content Script\n\nCreate `extension/domains/mysite/content.js`:\n\n```javascript\nconst DOMAIN = \"mysite\";\nlet socket = new WebSocket(\"ws://localhost:9999\");\n\nsocket.onopen = () =\u003e {\n  socket.send(JSON.stringify({ type: \"connect\", domain: DOMAIN, url: location.href }));\n};\n\n// Observe DOM → publish events\nnew MutationObserver(() =\u003e {\n  const data = extractFromDOM();\n  if (data) {\n    socket.send(JSON.stringify({ type: \"message\", domain: DOMAIN, ...data }));\n  }\n}).observe(document.body, { childList: true, subtree: true });\n\n// Subscribe to responses → mutate DOM\nsocket.onmessage = (e) =\u003e {\n  const frame = JSON.parse(e.data);\n  if (frame.type === \"send\") {\n    injectIntoDom(frame.text);\n  }\n};\n```\n\n### Step 2: Server Handler\n\nCreate `server/domains/mysite/index.ts`:\n\n```typescript\nimport type { Domain } from \"../../core/domain.ts\";\n\nexport const mysiteDomain: Domain = {\n  id: \"mysite\",\n  name: \"My Site\",\n  urlPatterns: [/mysite\\.com/],\n  \n  handleMessage: async (message, ctx) =\u003e {\n    await publishEvent(\"user.message.received\", {\n      text: message.text,\n      source: \"mysite\",\n      chatId: message.chatId\n    });\n  }\n};\n```\n\n### Step 3: Register\n\nIn `server/main.ts`:\n\n```typescript\nimport { mysiteDomain } from \"./domains/mysite/index.ts\";\nregisterDomain(mysiteDomain);\n```\n\n### Step 4: Manifest\n\nAdd to `extension/manifest.json`:\n\n```json\n{\n  \"content_scripts\": [\n    {\n      \"matches\": [\"https://mysite.com/*\"],\n      \"js\": [\"domains/mysite/content.js\"]\n    }\n  ]\n}\n```\n\n## Configuration\n\n```bash\n# WebSocket port (extension connects here)\nWS_PORT=9999\n\n# For standalone mode only\nMESH_URL=http://localhost:3000\nMESH_API_KEY=your-key\n```\n\n## File Structure\n\n```\nmesh-bridge/\n├── cli/\n│   └── index.ts          # CLI client (connects to server via WebSocket)\n├── server/\n│   ├── stdio.ts          # STDIO mode (mesh-hosted, starts WebSocket server)\n│   ├── index.ts          # Auto-detect mode (stdio vs standalone)\n│   ├── websocket.ts      # WebSocket server\n│   ├── events.ts         # Event types\n│   ├── core/\n│   │   ├── protocol.ts   # Frame types\n│   │   ├── mesh-client.ts\n│   │   └── domain.ts     # Domain interface\n│   └── domains/\n│       ├── whatsapp/     # WhatsApp implementation\n│       └── cli/          # CLI domain\n├── extension/\n│   ├── manifest.json\n│   ├── background.js\n│   └── domains/\n│       └── whatsapp/\n│           └── content.js\n└── docs/\n    └── ARCHITECTURE.md\n```\n\n## Development\n\n```bash\n# Start server (STDIO mode)\nbun stdio\n\n# CLI client (connects to server)\nbun dev\n\n# Run tests\nbun test\n\n# Format code\nbun run fmt\n\n# Type check\nbun run check\n```\n\n## Why Event-Driven?\n\n| Approach | Tokens/interaction | Reliability |\n|----------|-------------------|-------------|\n| Screenshot + Vision | 1000-3000 | Fragile |\n| DOM serialization | 2000-10000 | Fragile |\n| **Event-based** | **50-100** | **Stable** |\n\nEvents are:\n- **Small**: Structured data, not HTML noise\n- **Stable**: Event types don't change when UI changes\n- **Composable**: Any MCP can subscribe/publish\n\n## Recent Updates\n\n### Auto-Recovery from Extension Context Invalidation\n\nChrome's Manifest V3 suspends service workers after ~30 seconds of inactivity. Previously, this would break the extension when returning to a tab after being away.\n\n**Now:** The content script monitors for context invalidation and automatically reloads the page when detected. No more \"Extension context invalidated\" errors requiring manual refresh.\n\n### Thread Continuity\n\nThe bridge now works seamlessly with Pilot's thread management. Conversations within 5 minutes are treated as the same thread, enabling natural follow-ups like:\n\n- \"draft this\" → continues from previous research\n- \"yes\" / \"continue\" → proceeds to next workflow step\n- \"new thread\" → starts fresh\n\n## Privacy\n\n- Runs **locally** on your machine\n- Uses **your browser session** (no credential sharing)\n- Only processes **self-chat** in WhatsApp (never private conversations)\n- **Open source**—audit the code yourself\n\n## Usage\n\n### Starting the Server\n\nThe server runs via STDIO mode (for mesh integration) and also starts a WebSocket server for browser extensions:\n\n```bash\nbun stdio        # Start server (STDIO + WebSocket on port 9999)\nbun dev:stdio    # Same, with hot reload\n```\n\n### CLI Client\n\nThe CLI connects to the running server:\n\n```bash\nbun dev          # Connect to server\nbun dev:monitor  # Connect with all-events monitoring\n```\n\n```\n╔════════════════════════════════════════════════════════════╗\n║  🌐 MESH BRIDGE CLI                                        ║\n║  Terminal Interface for Mesh Bridge                        ║\n╚════════════════════════════════════════════════════════════╝\n\n✓ Connected (session: cli-local-1736500000)\nDomains: whatsapp, cli\n\nyou ❯ what's the weather in SF?\n07:24:59 → what's the weather in SF?\n07:25:01 ⚡ perplexity search\n07:25:03 🤖 San Francisco is currently 58°F with fog...\n```\n\n### CLI Commands\n\n| Command | Description |\n|---------|-------------|\n| `/help` | Show help |\n| `/new` | Start new thread |\n| `/monitor` | Toggle monitor mode (see all events) |\n| `/status` | Show connection status |\n| `/reconnect` | Force reconnection to server |\n| `/quit` | Exit CLI |\n\n### Monitor Mode\n\nWith `--monitor` flag or `/monitor` command, CLI shows **all** events from all sources:\n\n```\n07:24:55 [wa] → run article research for AI agents    # WhatsApp message\n07:24:57 [wa] ⚡ perplexity search\n07:25:02 [wa] ← Started create-article-research\n07:25:10 [cli] → list my tasks                        # Your CLI message\n07:25:11 [cli] ← You have 3 active tasks...\n```\n\n## Domains\n\n| Domain | Status | Description |\n|--------|--------|-------------|\n| WhatsApp | ✅ Ready | Self-chat AI interaction |\n| CLI | ✅ Ready | Terminal interface |\n| LinkedIn | 🔜 Planned | Messaging \u0026 networking |\n| X/Twitter | 🔜 Planned | Compose, DMs |\n| Gmail | 🔜 Planned | Compose, inbox |\n| Custom | 📖 Guide | Add any site |\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdecocms%2Fbridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdecocms%2Fbridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdecocms%2Fbridge/lists"}