-
Notifications
You must be signed in to change notification settings - Fork 0
Implement MCP server with 29 tools #30
Description
Summary
Implement the MCP (Model Context Protocol) server that exposes 29 RemoteClaw-specific tools to CLI subprocess agents. This is the C2 component — the mechanism by which CLI agents (Claude, Gemini, Codex, OpenCode) can interact with RemoteClaw's sessions, messaging, cron, and gateway systems.
Architecture
Lifecycle Model
ChannelBridge (gateway process)
|
| 1. Builds McpServerConfig, passes via AgentExecuteParams.mcpServers
| 2. Spawns CLI subprocess (runtime handles config format internally)
v
CLI Agent (claude/gemini/codex/opencode)
|
| 3. Reads MCP config, spawns MCP server as child
v
remoteclaw-mcp-server (stdio subprocess of CLI agent)
|
| 4. Connects to gateway via WebSocket RPC
| 5. Handles MCP tool calls by invoking gateway RPCs
| 6. Appends side effects to temp file (NDJSON)
v
Gateway WebSocket RPC (existing infrastructure)
Per-invocation: Each CLI subprocess invocation gets a fresh MCP server. The MCP server starts when the CLI agent spawns it, dies when the CLI agent exits. Clean isolation, no cross-session state.
Transport: Stdio — the only transport supported by all 4 CLIs.
Per-Runtime Config Generation (already implemented)
Per-runtime MCP config generation is already implemented in each runtime's *McpConfigManager class (from ClaudeCliRuntime (#8)–015):
| Runtime | Mechanism | Implemented In |
|---|---|---|
| Claude | Inline JSON via --mcp-config flag |
runtimes/claude.ts |
| Gemini | Merge-restore .gemini/settings.json |
GeminiMcpConfigManager |
| Codex | TOML serialization into config.toml |
CodexMcpConfigManager |
| OpenCode | Merge-restore opencode.json |
OpenCodeMcpConfigManager |
All runtimes accept a uniform McpServerConfig via AgentExecuteParams.mcpServers and handle format translation internally. MCP server (#30) only needs to define the McpServerConfig shape that ChannelBridge passes (env vars for gateway URL, token, session key, side effects path, channel info).
Configuration (environment variables)
The MCP server receives its context via environment variables set by ChannelBridge:
| Variable | Purpose |
|---|---|
REMOTECLAW_GATEWAY_URL |
Gateway WebSocket URL (e.g., ws://127.0.0.1:18789) |
REMOTECLAW_GATEWAY_TOKEN |
Gateway auth token |
REMOTECLAW_SESSION_KEY |
Current session key |
REMOTECLAW_SIDE_EFFECTS_FILE |
Temp file path for side effects NDJSON |
REMOTECLAW_CHANNEL |
Originating channel (e.g., telegram) |
REMOTECLAW_ACCOUNT_ID |
Originating account ID |
REMOTECLAW_TO |
Originating delivery target |
REMOTECLAW_THREAD_ID |
Originating thread/topic ID |
Tool Inventory (29 tools)
Session Management (7 tools)
| MCP Tool Name | Source | Parameters | Side Effect? |
|---|---|---|---|
sessions_list |
sessions-list-tool.ts |
filter?, limit? | No |
sessions_history |
sessions-history-tool.ts |
sessionKey, limit? | No |
sessions_send |
sessions-send-tool.ts |
sessionKey/label, message, timeout? | Yes (messaging) |
sessions_spawn |
sessions-spawn-tool.ts |
agentId?, channel?, prompt | No |
session_status |
session-status-tool.ts |
(current session info) | No |
agents_list |
agents-list-tool.ts |
(list configured agents) | No |
subagents |
subagents-tool.ts |
action, params | No |
Channel Messaging (10 tools)
| MCP Tool Name | Source Action | Parameters | Side Effect? |
|---|---|---|---|
message_send |
message:send | target, message, media? | Yes |
message_reply |
message:reply | message, replyToId? | Yes |
message_thread_reply |
message:thread-reply | message, threadId | Yes |
message_broadcast |
message:broadcast | targets[], message | Yes |
message_react |
message:react | emoji, messageId | No |
message_delete |
message:delete | messageId | No |
message_send_attachment |
message:sendAttachment | target, file, caption? | Yes |
message_send_with_effect |
message:sendWithEffect | target, message, effectId | Yes |
message_pin |
message:pin | messageId | No |
message_read |
message:readMessages | channelId, limit? | No |
Cron Scheduling (7 tools)
| MCP Tool Name | Source Action | Parameters | Side Effect? |
|---|---|---|---|
cron_status |
cron:status | (overview) | No |
cron_list |
cron:list | filter? | No |
cron_add |
cron:add | job spec | Yes (cronAdds) |
cron_update |
cron:update | jobId, updates | No |
cron_remove |
cron:remove | jobId | No |
cron_run |
cron:run | jobId | No |
cron_runs |
cron:runs | jobId?, limit? | No |
Gateway Admin (5 tools)
| MCP Tool Name | Source Action | Parameters |
|---|---|---|
gateway_restart |
gateway:restart | (none) |
gateway_config_get |
gateway:config.get | key? |
gateway_config_apply |
gateway:config.apply | config |
gateway_config_patch |
gateway:config.patch | patches |
gateway_config_schema |
gateway:config.schema | (none) |
NOT Exposed (middleware boundary principle)
| Tool | Reason |
|---|---|
web_search, web_fetch |
CLI agents have native equivalents |
browser, image, tts |
CLI agents have native equivalents or MCP-based |
canvas, nodes |
Requires rendering/pairing layer |
memory_search, memory_get |
Deferred to v0.2.0 |
Side Effects Protocol
File-based NDJSON protocol for tracking MCP messaging side effects:
{"type":"message_sent","tool":"message","provider":"telegram","to":"group:123","text":"Hello","mediaUrl":null,"ts":1708905600000}
{"type":"cron_added","jobId":"job-xyz","ts":1708905602000}Why file-based: ChannelBridge creates a temp file path; the MCP server appends side effects as NDJSON lines. After CLI subprocess exits, ChannelBridge reads the file. Robust even if MCP server crashes (partial file is valid NDJSON).
Side effect recording tools:
- Messaging:
message_send,message_reply,message_thread_reply,message_broadcast,message_send_attachment,message_send_with_effect,sessions_send→recordMessageSent() - Cron:
cron_add→recordCronAdd()
No race condition: CLI agent blocks on MCP tool responses, so the sequence is always: CLI sends request → MCP processes + writes side effect → MCP responds → CLI continues. When CLI exits, all side effects are on disk.
Tool Policy Integration
The MCP server applies the same tool policy pipeline as the existing /tools/invoke HTTP endpoint:
- Tool allowlisting/denylisting is respected
- Per-agent, per-channel, per-group policies apply
- Subagent tool restrictions are enforced
At startup, the MCP server loads config, resolves policies, and only registers allowed tools.
Implementation Approach
New Files
| File | Purpose | Est. Lines |
|---|---|---|
src/middleware/mcp-server.ts |
MCP server entry point + stdio transport setup | ~80 |
src/middleware/mcp-tools.ts |
Tool registration (schema generation from existing tool schemas) | ~150 |
src/middleware/mcp-handlers/session.ts |
Session tool handlers (7 tools) | ~100 |
src/middleware/mcp-handlers/message.ts |
Message tool handlers (10 tools) | ~150 |
src/middleware/mcp-handlers/cron.ts |
Cron tool handlers (7 tools) | ~100 |
src/middleware/mcp-handlers/gateway.ts |
Gateway admin tool handlers (5 tools) | ~75 |
src/middleware/mcp-side-effects.ts |
Side effects collector (NDJSON writer) + reader | ~100 |
Modified Files
| File | Change |
|---|---|
src/middleware/types.ts |
May need minor additions for MCP-related types |
Test Files
| File | Coverage |
|---|---|
src/middleware/mcp-side-effects.test.ts |
Side effects writer + reader |
src/middleware/mcp-tools.test.ts |
Tool registration, schema generation |
src/middleware/mcp-handlers/*.test.ts |
Tool handler invocation (mock gateway RPC) |
Estimated total: ~755 LoC (not counting tests) + ~500 LoC tests
(Reduced from original ~1,180 estimate — per-runtime config generation (~425 LoC) already exists in ClaudeCliRuntime (#8)–015.)
Tool Implementations
Each MCP tool handler is a thin adapter layer that:
- Receives MCP tool input (JSON Schema-validated by MCP SDK)
- Translates to a
callGatewayTool()RPC call (using existing gateway RPC infrastructure) - Records side effects (for messaging and cron tools)
- Returns MCP-formatted result
The tool handlers wrap existing src/agents/tools/ code — specifically sessions, messaging, cron, and gateway tools. They do NOT wrap the pi-embedded tools (web, browser, image, TTS) being gutted in M3.
Key Dependencies
| What | Status |
|---|---|
@modelcontextprotocol/sdk |
npm dependency to add |
AgentRuntime interface (PR #4) |
Done |
McpServerConfig type (PR #4) |
Done — already in types.ts |
McpSideEffects type (PR #4) |
Done — already in types.ts |
| Per-runtime MCP config (ClaudeCliRuntime (#8)–015) | Done — *McpConfigManager classes |
Existing src/agents/tools/ |
Upstream code, wrapping only |
Acceptance Criteria
-
src/middleware/mcp-server.ts(and supporting files) expose 29 RemoteClaw-specific tools via MCP - Tool categories: 7 session management, 10 channel messaging, 7 cron scheduling, 5 gateway admin
- Server uses per-invocation stdio lifecycle (spawned per CLI agent invocation, not long-running)
- Side effects recorded via file-based NDJSON protocol for
McpSideEffectsCollectorconsumption - Tool implementations wrap existing
src/agents/tools/code (thin adapter layer) - Generic capabilities (web fetch/search, browser, image, TTS) are NOT exposed (middleware boundary principle)
- Unit tests cover tool registration, invocation, and side effects recording
-
pnpm buildpasses