Liking cljdoc? Tell your friends :D

bb-mcp

Lightweight MCP (Model Context Protocol) server in Babashka that bridges Claude Code to Emacs via nREPL.

Why bb-mcp?

The Problem: Running multiple Claude Code instances (e.g., swarm agents) each with their own JVM-based MCP server consumes massive resources.

The Solution: bb-mcp is a lightweight multiplexer - many Babashka instances share ONE JVM.

ScenarioWithout bb-mcpWith bb-mcp
1 Claude~500MB~550MB (50MB bb + 500MB JVM)
3 Claudes~1.5GB (3 JVMs)~650MB (3 bb + 1 JVM)
5 Claudes~2.5GB (5 JVMs)~750MB (5 bb + 1 JVM)
10 Claudes~5GB (10 JVMs)~1GB (10 bb + 1 JVM)

Key Metrics

MetricJVM hive-mcpbb-mcp
Startup~2-3s~5ms
Memory~500MB~50MB
Scales to1 instanceMany instances

Use Case: Claude Swarm

When running swarm agents (multiple Claudes working in parallel), each agent needs an MCP connection to Emacs. Without bb-mcp, you'd need separate JVM processes. With bb-mcp:

  • 1 hive-mcp (JVM) handles Emacs integration
  • N bb-mcp instances (Babashka) multiplex to it
  • All agents share tools, memory, kanban, git via the single JVM

Architecture

                    bb-mcp Instances              Shared JVM
                    ┌──────────────┐
  Claude 1 ───────▶ │   bb-mcp     │──┐
                    └──────────────┘  │
                    ┌──────────────┐  │     ┌─────────────────┐
  Claude 2 ───────▶ │   bb-mcp     │──┼────▶│   hive-mcp     │
                    └──────────────┘  │     │   (nREPL:7910)  │
                    ┌──────────────┐  │     └────────┬────────┘
  Claude 3 ───────▶ │   bb-mcp     │──┘              │
                    └──────────────┘                 ▼
                       ~50MB each              ┌─────────────┐
                                               │    Emacs    │
                                               └─────────────┘

Data Flow:

  1. Claude Code connects to bb-mcp via MCP protocol (stdio)
  2. bb-mcp handles native tools directly (bash, grep, file ops)
  3. Emacs-related tools delegate to hive-mcp via nREPL on port 7910
  4. hive-mcp executes elisp in Emacs via emacsclient

Prerequisites

Installation

# Clone the repository
git clone https://github.com/BuddhiLW/bb-mcp.git
cd bb-mcp

# Add to Claude Code MCP config
claude mcp add bb-mcp bb -- -m bb-mcp.core

Configuration

nREPL Port Resolution

bb-mcp finds the nREPL port in this order:

  1. Explicit parameter - port in tool call
  2. Environment variable - BB_MCP_NREPL_PORT
  3. .nrepl-port file - In BB_MCP_PROJECT_DIR or current directory
  4. Default - Port 7910 (hive-mcp)

Environment Variables

VariableDescriptionDefault
BB_MCP_NREPL_PORTnREPL port to connect to7910
BB_MCP_PROJECT_DIRDirectory for .nrepl-port lookupCurrent dir
HIVE_MCP_DIRhive-mcp directory for auto-spawn~/dotfiles/gitthings/hive-mcp

Tools

bb-mcp provides 114 tools (6 native + 108 from hive-mcp).

Native Tools (6)

Fast tools that run directly in Babashka without JVM:

ToolDescription
bashExecute shell commands
read_fileRead file contents
file_writeWrite files to disk
glob_filesFind files by glob pattern
grepSearch content with ripgrep
clojure_evalEvaluate Clojure via nREPL

Emacs Tools (108 dynamic)

Tools loaded dynamically from hive-mcp at startup:

DomainToolsDescription
Buffer19Buffer ops, elisp eval, file navigation
Memory17Project memory CRUD with TTL, semantic search
Swarm14Claude swarm orchestration, hivemind
CIDER12Clojure REPL, docs, completions
Magit10Git operations via Magit
Kanban8Task/kanban management
Projectile6Project navigation
Org6Org-mode operations, native kanban
Prompt5Prompt capture, search, analysis
Channel4Emacs event channels
Hivemind4Multi-agent communication
Context1Full context aggregation

Dynamic Tool Loading

At startup, bb-mcp queries hive-mcp via nREPL for all available tools and creates forwarding handlers automatically. This ensures bb-mcp always has automatic parity with hive-mcp - no manual synchronization needed.

When hive-mcp adds new tools, bb-mcp picks them up automatically on next startup.

Usage

As MCP Server

# Via bb task
bb mcp

# Directly
bb -m bb-mcp.core

Connection Management

bb-mcp uses state-based detection to manage the hive-mcp connection:

StateConditionAction
:readyPort listeningConnect immediately (0 latency)
:startingLock file or process existsWait with exponential backoff
:not-runningNo process foundSpawn hive-mcp and wait

This eliminates race conditions and ensures reliable startup even when multiple bb-mcp instances start simultaneously.

Logs go to ~/.config/hive-mcp/server.log.

Project Structure

bb-mcp/
├── bb.edn                    # Babashka deps and tasks
├── src/bb_mcp/
│   ├── core.clj              # Main entry, MCP message loop
│   ├── protocol.clj          # JSON-RPC protocol handling
│   ├── nrepl_spawn.clj       # Auto-spawn hive-mcp nREPL
│   ├── test_runner.clj       # Test runner
│   └── tools/
│       ├── bash.clj          # Native: shell execution
│       ├── file.clj          # Native: file operations
│       ├── grep.clj          # Native: ripgrep wrapper
│       ├── nrepl.clj         # nREPL client (bencode)
│       ├── emacs.clj         # Emacs tools facade
│       └── emacs/
│           └── dynamic.clj   # Dynamic tool loading from hive-mcp
└── test/                     # Tests

The emacs/ directory is minimal - all Emacs tools are loaded dynamically from hive-mcp at runtime, eliminating code duplication.

Development

# Run tests
bb test

# Start REPL for development
bb nrepl

Adding New Tools

Native tools (no JVM needed):

  1. Add to appropriate file in src/bb_mcp/tools/ (bash, file, grep)
  2. Register in src/bb_mcp/core.clj native-tools vector

Emacs tools: Add to hive-mcp instead - bb-mcp picks them up automatically via dynamic loading.

nREPL Implementation

The nREPL client (tools/nrepl.clj) uses byte-based bencode for proper UTF-8 handling. Key functions:

  • eval-code - Evaluate Clojure on remote nREPL
  • bencode-to-bytes / bdecode-from-stream - Binary-safe bencode

License

MIT

Can you improve this documentation? These fine people already did:
Pedro Gomes Branquinho & blw
Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close