@metamask/client-mcp-core
HTTP daemon and CLI architecture for agent-driven browser extension testing with Playwright.
Overview
This package provides the core infrastructure for enabling LLM agents to interact with browser extensions through Playwright. It ships a persistent HTTP daemon that manages browser lifecycle and a unified mm CLI that agents (and developers) use to drive sessions.
The design is consumer-agnostic: the core handles protocol, tooling, and knowledge — consumers provide extension-specific logic by implementing the ISessionManager interface and injecting capabilities.
┌─────────────────────────────────┐
│ LLM Agent / Dev │
└────────────┬────────────────────┘
│ mm CLI commands
▼
┌─────────────────────────────────┐
│ mm CLI (src/cli/mm.ts) │
│ discover / auto-start daemon │
└────────────┬────────────────────┘
│ HTTP (127.0.0.1)
▼
┌───────────────────────────────────────────────────────────────────┐│ │ │ ┌──────────┐ ┌───────────────┐ ┌────────────┐ ┌────────────┐ │ │ │ Routes │ │ RequestQueue │ │ Tool │ │ Knowledge │ │ │ │ /health │ │ (async mutex) │ │ Registry │ │ Store │ │ │ │ /status │ │ │ │ 47 tools │ │ │ │ │ │ /launch │ └───────────────┘ └─────┬──────┘ └────────────┘ │ │ │ /cleanup │ │ │ │ │ /tool/:n │ ▼ │ │ └──────────┘ ┌──────────────────┐ │ │ │ ToolContext │ │ │ │ sessionManager │ │ │ │ page / refMap │ │ │ │ workflowContext │ │ │ │ knowledgeStore │ │ │ └────────┬─────────┘ │ └──────────────────────────────────────┼────────────────────────────┘ │ ┌─────────────────────┼─────────────────────┐ │ ISessionManager │ │ (consumer implementation) │ │ │ │ Session lifecycle Page management │ │ Extension state A11y reference map │ │ Navigation Screenshots │ │ Capabilities (opt) Environment config │ └─────────────────────┬─────────────────────┘ │ ┌─────────────────────┼─────────────────────┐ │ WorkflowContext │ │ │ │ build? fixture? │ │ chain? contractSeeding? │ │ stateSnapshot? mockServer? │ │ config: EnvironmentConfig │ └─────────────────────┬─────────────────────┘ │ ▼ ┌───────────────────────────────────────────┐ │ Playwright → Chrome Browser │ │ Browser Extension │ └───────────────────────────────────────────┘
## Requirements
- **Node.js** `^20 || ^22 || >=24`
- **TypeScript** `>=5.0` (for consumer type definitions)
- **Playwright** `^1.49.0` (peer dependency)
## Installation
As a project dependency (the CLI is available via `npx mm` or `yarn mm`):
yarn add @metamask/client-mcp-core
As a global CLI (puts `mm` directly on your PATH — recommended for LLM agents):
npm install -g @metamask/client-mcp-core
The global CLI can target any project via `--project` or `MM_PROJECT` (see [Project Targeting](#project-targeting)).
## Getting Started
Consuming this package requires two things: a **daemon entry point** and a **configuration file**.
### 1. Create a daemon entry point
// daemon.ts import { createServer, allocatePort } from '@metamask/client-mcp-core'; import { MySessionManager } from './my-session-manager'; import { createMyContext } from './my-context';
const server = createServer({ sessionManager: new MySessionManager(), contextFactory: async () = { // Consumer owns port allocation — use the allocatePort() helper // or any other strategy that fits your infrastructure. const anvil = await allocatePort(); const fixture = await allocatePort(); await Promise.all([ new Promise<void((r) = anvil.server.close(() = r())), new Promise<void((r) = fixture.server.close(() = r())), ]);
return createMyContext({ ports: { anvil: anvil.port, fixture: fixture.port }, }); }, });
server.start().then((state) = { console.error(Daemon started on port ${state.port}); });
### 2. Create a configuration file
Create `mm-client-cli.config.ts` in your project root:
export default { daemon: 'path/to/daemon.ts', runtime: 'tsx', };