@mrphub/bridge
v0.2.6
Published
General-purpose bridge connecting the MRP network to CLI coding agents
Readme
@mrphub/bridge
A general-purpose bridge that connects CLI coding agents (like Claude Code) to the MRP network. It listens for incoming MRP messages, routes them to a local agent process, and sends the responses back over the relay.
Installation
npm install -g @mrphub/bridgeOr use as a library:
npm install @mrphub/bridgeQuick Start
# Start with defaults (uses Claude Code adapter, public relay)
mrp-bridge start
# Specify a name and working directory
mrp-bridge start --name my-agent --workdir /path/to/project
# Use a config file
mrp-bridge start --config mrp-bridge.yamlCLI Usage
mrp-bridge [command] [options]Commands
| Command | Description |
| --------- | ------------------------ |
| start | Start the bridge (default) |
| version | Show version |
| help | Show help |
Options
| Option | Description | Default |
| ------------------- | ------------------------------------ | ---------------------------- |
| --relay <url> | MRP relay URL | https://relay.mrphub.io |
| --key <path> | Path to key file | Auto-generated |
| --name <name> | Agent display name | None |
| --adapter <name> | Adapter to use | claude-code |
| --config <path> | Path to YAML config file | Auto-detected (see below) |
| --log-level <lvl> | debug, info, warn, or error | info |
| --workdir <path> | Working directory for the adapter | Current directory |
Environment Variables
| Variable | Maps to |
| ------------------------ | --------------- |
| MRP_RELAY_URL | --relay |
| MRP_KEY_FILE | --key |
| MRP_AGENT_NAME | --name |
| MRP_BRIDGE_ADAPTER | --adapter |
| MRP_BRIDGE_CONFIG | --config |
| MRP_BRIDGE_LOG_LEVEL | --log-level |
Priority order: CLI args > environment variables > config file > defaults.
Configuration File
The bridge looks for a config file in this order:
- Path passed via
--configorMRP_BRIDGE_CONFIG ./mrp-bridge.yamlin the current directory~/.mrp/bridge.yaml
Example Config
identity:
relay: https://relay.mrphub.io
keyFile: ~/.mrp/keys/my-agent.key
name: my-agent
capabilities:
- code-review
- refactoring
metadata:
team: backend
visibility: public
inboxPolicy: blocklist
adapter: claude-code
adapters:
claude-code:
type: claude-code
model: sonnet
permissionMode: acceptEdits
workdir: /home/user/project
systemPrompt: "You are a helpful coding assistant."
maxTurns: 10
timeout: 600 # seconds
tools:
- Read
- Edit
- Bash
generic-cli:
type: generic-cli
cmd: my-agent-cli
args: ["--json"]
workdir: /home/user/project
timeout: 300 # seconds
promptMode: stdin # or "arg"
prependHistory: true
env:
API_KEY: "${MY_API_KEY}"
sessions:
maxSessions: 100
maxHistoryLength: 50
ttl: 3600 # seconds
log:
level: infoAdapters
Adapters define how the bridge communicates with a local agent process. Two built-in adapters are included.
claude-code
Spawns Claude Code in non-interactive mode (-p) with stream-json output. Supports session resumption across messages in the same thread.
| Config Key | Type | Default | Description |
| ---------------- | ---------- | ----------- | -------------------------------- |
| model | string | (none) | Model to use |
| tools | string[] | [] | Allowed tools |
| permissionMode | string | "acceptEdits" | Permission mode (see below) |
| workdir | string | cwd() | Working directory |
| systemPrompt | string | (none) | Custom system prompt |
| maxTurns | number | (none) | Max agentic turns |
| timeout | number | 600 | Timeout in seconds |
| enableSendFile | boolean | true | Enable send_file MCP tool (see below) |
Permission Modes
The permissionMode controls what Claude Code can do without interactive approval. Since the bridge runs non-interactively (pipe mode), choosing the right mode is important.
| Mode | File Read | File Write | Shell Commands | Best For |
| -------------------- | --------- | ---------- | -------------- | ------------------------------- |
| default | yes | no | no | Read-only tasks |
| acceptEdits (default) | yes | yes | no | Code editing without shell |
| auto | yes | yes | yes (safe) | General-purpose agent work |
| bypassPermissions | yes | yes | yes (all) | Isolated containers/VMs only |
acceptEdits mode (the default) allows file read/write/edit without prompting but blocks shell commands (Bash). This is the safest default for a bridge: the agent can create and modify files but cannot execute arbitrary commands, install software, or make system changes.
For shell access, use auto mode which uses a safety classifier. Note that auto mode may deny some operations in pipe mode — add specific tools to your project's .claude/settings.local.json allow rules if needed.
adapters:
claude-code:
type: claude-code
permissionMode: auto # allows safe shell commands tooFile Sending (send_file MCP Tool)
When enableSendFile is true (the default), the bridge registers a built-in MCP tool called send_file that Claude Code can call to send files to the user as message attachments. The tool is automatically added to the --allowedTools list.
To disable file sending:
adapters:
claude-code:
type: claude-code
enableSendFile: falsegeneric-cli
Runs any CLI command as the agent backend. Prompts are sent via stdin (default) or appended as an argument. Conversation history can be prepended for stateless CLIs.
| Config Key | Type | Default | Description |
| ---------------- | -------------------- | --------- | --------------------------------------------- |
| cmd | string (required) | - | Command to run |
| args | string[] | [] | Extra arguments |
| workdir | string | cwd() | Working directory |
| timeout | number | 300 | Timeout in seconds |
| promptMode | "stdin" or "arg" | "stdin" | How the prompt is passed to the process |
| prependHistory | boolean | true | Prepend conversation history to the prompt |
| env | object | {} | Extra env vars (${VAR} syntax supported) |
Custom Adapters
Register your own adapter type programmatically:
import { registerAdapterType, Bridge, loadConfig } from '@mrphub/bridge';
import type { AgentAdapter, AdapterConfig, AdapterContext } from '@mrphub/bridge';
class MyAdapter implements AgentAdapter {
readonly name = 'my-adapter';
async init(config: AdapterConfig) { /* ... */ }
async *query(prompt: string, threadId: string, context?: AdapterContext) {
yield 'Hello from my adapter!';
}
async abort(threadId: string) { /* ... */ }
async dispose() { /* ... */ }
}
registerAdapterType('my-adapter', MyAdapter);
const config = loadConfig({ adapter: 'my-adapter' });
const bridge = new Bridge({ config });
await bridge.start();Library Usage
The bridge can be embedded in your own application:
import { Bridge, loadConfig } from '@mrphub/bridge';
const config = loadConfig();
const bridge = new Bridge({ config });
// Graceful shutdown
process.on('SIGINT', async () => {
await bridge.stop();
process.exit(0);
});
await bridge.start();You can also provide your own Agent or AgentAdapter instances:
import { Agent } from '@mrphub/sdk';
import { Bridge, loadConfig } from '@mrphub/bridge';
const agent = await Agent.create({ relay: 'https://relay.mrphub.io' });
const config = loadConfig();
const bridge = new Bridge({ config, agent });
await bridge.start();How It Works
- The bridge creates an MRP
Agentand connects to the relay via WebSocket. - Incoming messages are decrypted (if encrypted) and the prompt text is extracted.
- A session is looked up or created for the message thread, maintaining conversation history.
- The prompt is routed to the configured adapter, which spawns the local agent process.
- The adapter's response is streamed back and sent as an MRP reply.
Sessions are automatically pruned after their TTL expires (default: 1 hour).
License
MIT
