模块化Clojure服务器

一个基于Clojure/Babashka的模块化服务器,支持动态加载模块、远程代码执行和nREPL协议交互。

  • by franks42
  • Clojure
  • 本地部署
  • 更新于
在 GitHub 查看 franks42/bb-mcp-server

使用说明

bb mcp服务器

Clojure/Babashka中的模块化MCP服务器。

快速开始

# stdio (Claude Code)
bb server

# HTTP (Streamable HTTP spec 2025-03-26)
bb server --http --nickname my-server --config system.edn

# Server management
bb server:start-wait --nickname my-server --config system.edn  # Start + wait for health
bb server:stop my-server                                        # Stop by nickname
bb server:restart my-server                                     # Stop + start
bb server:list                                                  # List running servers
bb server:ports my-server                                       # Show all ports

所有服务使用 临时端口 默认情况下(OS分配)。通过以下方式发现端口 .ports/<nickname>.json.

模块

模块 说明
calculate 数学表达式(100多个函数)
mcp-nrepl 通过nREPL协议实现远程Clojure REPL
mcp-local-eval 服务器端代码执行
echo 测试回声
hello 问候工具
strings 字符串concat
math 基本算术

看 modules/*/README.md 了解详情。

配置

system.edn:

{:modules ["hello" "echo" "calculate" "mcp-nrepl" "mcp-local-eval"]}

外部模块

从项目目录外部加载模块:

# Single module or collection of modules
BB_MCP_EXTERNAL_MODULES=/path/to/my-module bb server --http

# Multiple paths (colon-separated)
BB_MCP_EXTERNAL_MODULES=/path/to/module1:/path/to/modules-collection bb server --http

自动检测:

  • 单个模块:目录包含 module.edn
  • 收集:包含子目录的目录 module.edn

模块必须列在 system.edn 在启动时加载。

动态模块加载

运行时加载模块(服务器已运行后):

;; Via mcp-local-eval, nrepl-eval, or direct REPL
(require '[bb-mcp-server.module.system :as system])
(system/load-new-module! "/path/to/external-module")

这使得 最小引导模式:

  1. 只需启动服务器 mcp-local-eval (或 mcp-nrepl)
  2. 通过以下方式动态加载其他模块 mcp-local-eval
  3. 加载后立即注册工具
;; system.edn - minimal bootstrap
{:modules ["mcp-local-eval"]}  ; Just local-eval!

两者 local-eval 和 nrepl 具有完全的服务器访问权限(没有沙盒限制)。

看 scripts/test_dynamic_load.clj 作为一个工作示例。

mcp eval命令行界面工具

这 mcp-eval 脚本通过以下方式在正在运行的MCP服务器上评估Clojure代码 local-eval 工具。

基本用法

# Start server with ephemeral port and nickname
bb server --http 0 --nickname dev

# Evaluate code (auto-discovers server by nickname)
bb mcp-eval "(+ 1 2 3)"                    # => 6
bb mcp-eval "(range 5)" --nickname dev     # => (0 1 2 3 4)
bb mcp-eval "(System/getenv \"HOME\")"     # => "/Users/..."

输出模式

# result (default): Just the result value
bb mcp-eval "(do (println \"hi\") 42)"
# => 42

# full: Structured map with status, result, stdout, stderr
bb mcp-eval "(do (println \"hi\") 42)" --output full
# => {:status :ok, :result 42, :stdout "hi\n", :stderr ""}

# pipe: stdout→stdout, stderr→stderr, result to stdout
bb mcp-eval "(do (println \"hi\") 42)" --output pipe
# hi
# 42

选项

选项 描述
--nickname NAME 服务器昵称(默认值: bb-bootstrap-system-1)
--port PORT 服务器端口号
--output MODE 输出模式: result, full, pipe
--pprint 漂亮的打印EDN输出

例子

# Pretty-print complex data
bb mcp-eval "(ns-publics 'clojure.string)" --pprint

# Check registered tools
bb mcp-eval "(require '[bb-mcp-server.registry :as r]) (mapv :name (r/list-tools))"

# Inspect server state
bb mcp-eval "*ns*"  # => #object[sci.lang.Namespace user]

# Error handling (exits with code 1)
bb mcp-eval "(/ 1 0)" --output pipe  # Prints error to stderr

程序化使用

(require '[bb-mcp-server.mcp-client :as client])

;; Simple eval
(client/eval-code! "dev" "(+ 1 2)")  ; => 3

;; With EDN parsing (preserves sets, keywords)
(client/eval-code! 3000 "#{:a :b}" {:output-format :edn})  ; => #{:a :b}

;; Full response with stdout/stderr
(client/eval-code-full! "dev" "(do (println \"x\") 42)")
; => {:status :ok, :result 42, :stdout "x\n", :stderr ""}

MCP CLI(探索与测试)

用于探索和测试任何MCP工具的通用CLI:

bb mcp servers                           # List running servers
bb mcp tools --mcp dev                   # List available tools
bb mcp call echo.echo '{"message":"hi"}' # Call any tool with JSON args
bb mcp init                              # Get server info

跑 bb mcp help 对于所有子命令。另请参阅 bb test:e2e 用于自动化E2E测试。

nrepl命令行界面工具

这 nrepl CLI通过MCP提供对远程nREPL服务器的命令行访问。 连接到任何nREPL服务器(JVM Clojure、Babashka、ClojureScript)并评估代码。

设置

# Start MCP server with nrepl module
bb server --http --port 3001 --config bb-nrepl-system.edn --nickname nrepl-mcp

# Start your nREPL server (or use an existing one)
bb --nrepl-server 7888 &

基本用法

# Connect to nREPL server
bb nrepl connect 7888 --nickname my-app --mcp nrepl-mcp

# Evaluate code
bb nrepl eval "(+ 1 2 3)" --mcp nrepl-mcp
# => 6

# Load a file
bb nrepl load-file src/my_app/core.clj --mcp nrepl-mcp

# List connections
bb nrepl list --mcp nrepl-mcp

# Disconnect
bb nrepl disconnect my-app --mcp nrepl-mcp

子指令

子命令 描述
connect <target> 连接到nREPL服务器(端口、主机:端口或.nREPL端口)
disconnect [name] 断开与nREPL服务器的连接
list 列出所有连接
status 显示活动连接状态
eval <code> 评估Clojure代码
load-file <path> 加载并评估Clojure文件
help 显示帮助

选项

选项 描述
--mcp NAME MCP服务器昵称(默认值: bb-nrepl-system-1)
--connection NAME nREPL连接昵称(用于eval/load文件)
--nickname NAME 新连接的昵称(用于连接)
--output MODE 输出模式: result, full, pipe
--pprint 打印输出漂亮
--timeout MS 超时时间(毫秒)(默认值:30000)

输出模式

# result (default): Just the value
bb nrepl eval "(do (println \"hi\") 42)" --mcp nrepl-mcp
# => 42

# full: Complete response with stdout/stderr
bb nrepl eval "(do (println \"hi\") 42)" --mcp nrepl-mcp --output full --pprint
# => {:status "success", :value "42", :out "hi\n", ...}

# pipe: stdout→stdout, stderr→stderr, value to stdout
bb nrepl eval "(do (println \"hi\") 42)" --mcp nrepl-mcp --output pipe
# hi
# 42

nrepl直接命令行界面工具

这 nrepl-direct CLI通过bencode协议直接与nREPL服务器通信,完全绕过MCP。用于更简单的脚本编写或MCP服务器未运行时。

基本用法

# Eval with explicit port
bb nrepl-direct eval "(+ 1 2 3)" --port 7888
# => 6

# Eval using port discovery from server nickname
bb nrepl-direct eval "(+ 1 2 3)" --nickname scittle-dev
# => 6

# Load local file (reads file, sends content as code)
bb nrepl-direct load-local-file src/browser/app.cljs --nickname scittle-dev

# Load file from server's filesystem
bb nrepl-direct load-file /path/to/file.clj --port 7888

# Read code from stdin
echo "(range 5)" | bb nrepl-direct eval - --port 7888

# Describe server capabilities
bb nrepl-direct describe --port 7888

子指令

子命令 描述
eval <code> 评估Clojure代码
load-file <path> 从服务器的文件系统加载文件
load-local-file <path> 在本地读取文件,以代码形式发送(适用于浏览器)
describe 显示nREPL服务器功能
help 显示帮助

选项

选项 描述
--port PORT nREPL端口(除非是昵称,否则为必填项)
--host HOST nREPL主机(默认:localhost)
--nickname NAME 从以下位置发现端口 .ports/<NAME>.json
--service SERVICE 端口文件中的服务名称(默认值: nrepl-server)
--ns NAMESPACE 要在中求值的命名空间
--timeout MS 超时时间(毫秒)(默认值:30000)
--output MODE 输出模式: result, full, pipe
--pprint 打印输出漂亮

端口发现

CLI自动从以下位置发现端口 .ports/<nickname>.json 文件夹:

# Use nrepl-server port (default)
bb nrepl-direct eval "(+ 1 2)" --nickname scittle-dev

# Use nrepl-proxy port (for browser connections)
bb nrepl-direct eval "(+ 1 2)" --nickname scittle-dev --service nrepl-proxy

叛军nrepl客户

使用连接到nREPL服务器的反叛读线打开iTerm2:

# Start MCP server with nREPL test server
bb server --http --config bb-nrepl-server-system.edn

# Open iTerm2 with rebel-readline
bb rebel-nrepl-client 7888

Scittle nREPL(浏览器REPL)

Eval ClojureScript在浏览器中从叛逆的readline,影子cljs风格。

架构:

rebel-readline → nrepl-proxy:1667 → sente-browser:8090 → Browser (Scittle)

设置

# Start scittle-dev server (requires sente-lite bundle)
bb server --http --config bb-scittle-dev-system.edn --nickname scittle-dev

# Open browser to bootstrap page
open http://127.0.0.1:8091

# Connect rebel-readline to proxy
bb rebel-nrepl-client 1667

用法(反叛)

(browser/list)            ; List connected browsers
(browser/repl :browser-1) ; Switch to browser REPL

;; Now you're in the browser!
(+ 1 2 3)                 ; => 6
(js/alert "Hello!")       ; Shows browser alert
js/navigator.userAgent    ; Access browser APIs

:cljs/quit                ; Return to bb

配置

bb-scittle-dev-system.edn:

{:modules ["mcp-local-eval" "mcp-nrepl" "nrepl-server"
           "sente-browser" "nrepl-proxy-server"]
 :config {"sente-browser" {:ws-port 8090
                           :bootstrap-port 8091
                           :bundle-path "/path/to/sente-lite-nrepl.cljs"}
          "nrepl-proxy-server" {:port 1667
                                :write-port-file? true}}}

克劳德代码

{
  "mcpServers": {
    "bb-mcp": {
      "command": "bb",
      "args": ["server:stdio"],
      "cwd": "/path/to/bb-mcp-server"
    }
  }
}

发展

bb test:all       # Run all tests (modules + bootstrap)
bb test:modules   # Run module tests only
bb test:bootstrap # Run bootstrap configuration tests
bb test:e2e       # Run E2E MCP client tests (requires running server)
bb lint           # clj-kondo (0 errors, 0 warnings)
bb format         # cljfmt
bb server:stop my-server  # Stop server by nickname
bb server:list            # List running servers

Bootstrap配置

服务器支持最小的引导配置,以实现快速启动:

# Bootstrap with minimal module set (local-eval only)
bb bootstrap-server

# Custom bootstrap config
bb server --config bb-bootstrap-system.edn

# With nickname for port file identification
bb server --config bb-bootstrap-system.edn --nickname my-server

Bootstrap配置文件(bb-bootstrap-system.edn):

{:modules ["mcp-local-eval"]}  ; Minimal setup for local evaluation

状态

第20阶段完成。MCP CLI和E2E测试基础设施到位。

许可证

请参阅许可证。