Clojure MCP-nREPL 服务器

MCP-nREPL 是一个基于Babashka的轻量级Clojure nREPL服务器实现,支持桥接模式、服务器模式和评估模式,为AI助手提供REPL交互能力。

  • by ctford
  • Clojure
  • 本地部署
  • 8 星标
  • 更新于
在 GitHub 查看 ctford/mcp-nrepl

使用说明

MCP nREPL

这是一个最小的、快速的 模型上下文协议 Clojure的(MCP)服务器实现 nREPL 使用 巴巴什卡。这意味着您的编码助理可以像您一样使用REPL。

相关项目:有关更雄心勃勃的REPL驱动开发经验,请查看Bruce Hauman的 Clojure MCP (具有结构编辑、linting和格式化功能的全功能MCP)和 clojure mcp灯 (用于并行修复和LLM友好输出的CLI工具)。

目录

特性

  • 桥接模式 (--bridge):连接到外部nREPL服务器,例如使用 lein repl。当您有一个具有自己的依赖关系和定义的现有项目时,请使用此选项。
  • 服务器模式 (--server):提供嵌入式nREPL服务器。如果您在项目上下文之外尝试Clojure,请使用此选项。
  • 评估模式 (--eval):从命令行进行一次性评估,适用于网桥或服务器模式。使用此功能尝试MCP nREPL,或者如果您想让您的编码助手能够通过CLI而不是MCP与REPL通信。
  • 快速执行:每次评估约30ms

使用 bb mcp-nrepl.bb --help 查看所有命令行选项和使用示例。

示例用法

用户: 给我找第一百万个素数。

克劳德: 我将使用Clojure REPL来计算第一百万个素数。

🔧 使用eval clojure工具:

(defn prime? [n]
  (and (> n 1)
       (not-any? #(zero? (mod n %))
                 (range 2 (inc (int (Math/sqrt n)))))))

(defn primes []
  (filter prime? (iterate inc 2)))

(nth (primes) (dec 1000000))
Error: Evaluation timed out after 2000ms

克劳德: 这种天真的做法已经过时了。让我使用一种更有效的埃拉托色尼筛方法。

🔧 使用eval clojure工具:

(defn sieve [n]
  (let [limit (int (* n (Math/log n) 1.3))
        candidates (boolean-array limit true)]
    (loop [p 2 primes []]
      (if (>= (count primes) n)
        (nth primes (dec n))
        (do
          (when (aget candidates p)
            (loop [multiple (* p p)]
              (when (< multiple limit)
                (aset candidates multiple false)
                (recur (+ multiple p)))))
          (recur (inc p) (if (aget candidates p) (conj primes p) primes)))))))

(time (sieve 1000000))
"Elapsed time: 1847.3 msecs"
15485863

用户: 你能用doseq简化一下吗?

克劳德: 好主意!让我先检查一下doseq的文档。

🔧 使用文档工具:

doseq
clojure.core/doseq
([seq-exprs & body])
  Repeatedly executes body (presumably for side-effects) with
  bindings and filtering as provided by "for".  Does not retain
  the head of the sequence. Returns nil.

克劳德: 太好了!我可以使用doseq来标记复合材料的副作用,并过滤以找到结果。

🔧 使用eval clojure工具:

(defn sieve [n]
  (let [limit (int (* n (Math/log n) 1.3))
        candidates (boolean-array limit true)]
    (doseq [p (range 2 limit)
            :when (aget candidates p)]
      (doseq [multiple (range (* p p) limit p)]
        (aset candidates multiple false)))
    (nth (filter #(aget candidates %) (range 2 limit)) (dec n))))

(time (sieve 1000000))
"Elapsed time: 1842.1 msecs"
15485863

克劳德: 第一百万个素数是15485863。

安装

目前,MCP nREPL作为一个单一的、未版本化的Babashka脚本分发,没有依赖关系(Babashka已经提供的除外)。你应该能够理解它,破解它,复制它,并将其签入你的dotfiles仓库。

1.先决条件

  • 巴巴什卡:通过安装 brew install borkdude/brew/babashka (macOS)或查看 babashka.org 对于其他平台

2.下载mcp-repl.bb

将脚本下载到永久位置:

# Create a directory for MCP servers (or use any location you prefer)
mkdir -p ~/.mcp-servers
cd ~/.mcp-servers

# Download the script
curl -O https://raw.githubusercontent.com/ctford/mcp-nrepl/main/mcp-nrepl.bb

3a。选项一:配置桥接模式,例如Claude代码

创建一个 .mcp.json Clojure项目根目录中的文件:

{
  "mcpServers": {
    "mcp-nrepl": {
      "type": "stdio",
      "command": "bb",
      "args": ["/Users/yourname/.mcp-servers/mcp-nrepl.bb", "--bridge"],
      "_comment": "Replace /Users/yourname with your actual home directory path"
    }
  }
}

注意:工作目录是您的项目根目录,因此 .nrepl-port 自动发现(无需 --nrepl-port 在典型的工作流程中)。

启动nREPL服务器:在项目目录中,启动nREPL服务器:

cd /path/to/your/clojure/project
lein repl           # Leiningen
# or: bb nrepl-server   # Babashka
# or: clj -Sdeps '{:deps {nrepl/nrepl {:mvn/version "1.0.0"}}}' -X nrepl.cmdline/server

这创建了一个 .nrepl-port mcp-nrepl将用于连接的文件。

重新启动Claude代码 加载MCP服务器。

3b。选项二:配置服务器模式,例如克劳德桌面

如果您更喜欢使用Claude Desktop,请编辑您的Claude Desktop配置文件:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • 视窗: %APPDATA%\Claude\claude_desktop_config.json

添加具有嵌入式服务器模式的mcp-nrepl服务器:

{
  "mcpServers": {
    "mcp-nrepl": {
      "type": "stdio",
      "command": "bb",
      "args": ["/Users/yourname/.mcp-servers/mcp-nrepl.bb", "--server"],
      "_comment": "Replace /Users/yourname with your actual home directory path"
    }
  }
}

注: "type": "stdio" 是可选的(stdio是默认的),但为了清楚起见,它被包含在内。

重新启动克劳德桌面 加载MCP服务器。

3c。选项三:配置评估模式

对于没有MCP配置的快速一次性评估,请使用 --eval 直接从命令行标记。此模式适用于网桥或服务器模式。

使用外部nREPL(桥接模式):

# Start your project's nREPL server first
lein repl  # or: bb nrepl-server

# Then evaluate code (auto-discovers .nrepl-port)
bb mcp-nrepl.bb --eval "(+ 1 2 3)"
# Output: 6

# Or specify port explicitly
bb mcp-nrepl.bb --nrepl-port 1667 --eval "(+ 1 2 3)"

使用嵌入式nREPL(服务器模式):

# No external server needed - starts embedded nREPL automatically
bb mcp-nrepl.bb --server --eval "(+ 1 2 3)"
# Output: 6

4.验证它是否正常工作

试着问克劳德:

“你能在我的Clojure REPL中评估(+1 2 3)吗?”

Claude应该能够连接到您的nREPL会话并执行代码。

协议支持

已实施的MCP方法

  • 初始化:建立nREPL连接的协议握手
  • 工具/列表:返回可用工具
  • 工具/调用:执行工具操作
  • 提示/列表:返回空提示列表(已通告功能,但未提供提示)
  • 提示/获取:不可用(返回错误)
  • 资源/列表:返回空资源列表(已通告功能,但未提供资源)
  • 资源/读取:不可用(返回错误)

使用 bb mcp-nrepl.bb --describe 无需设置MCP即可查看所有工具及其完整的参数模式。

可用工具

MCP nREPL提供12个工具:

代码执行:

  • eval clojure -计算Clojure代码表达式
    • 参数:
      • code (string,必填)-要计算的Clojure代码
      • timeout-ms (数字,可选)-超时(毫秒)(默认值:2000ms)
    • 返回:评估结果、输出和任何错误
    • 增加复杂计算等长时间运行操作的超时时间
  • 加载文件 -加载并评估Clojure文件
    • 参数:
      • file-path (string,必填)-要加载的Clojure文件的路径
      • timeout-ms (数字,可选)-超时(毫秒)(默认值:2000ms)
    • 返回:成功消息或评估输出
    • 加载前验证文件是否存在
    • 增加大文件的超时时间
  • 设置命名空间 -切换到其他命名空间
    • 参数: namespace (字符串,必填)
    • 返回:命名空间切换确认
    • 如果命名空间不存在,则创建命名空间

宏观扩张:

  • macroexpansion全部 -完全展开Clojure代码中的所有宏
    • 参数: code (字符串,必填)
    • 返回:使用完全展开的表单 clojure.walk/macroexpand-all
    • 有助于理解完整的宏转换
  • 宏扩展-1 -展开Clojure宏一步
    • 参数: code (字符串,必填)
    • 返回值:使用以下函数进行单个宏展开的结果 macroexpand-1
    • 有助于逐步理解宏观转换

文档:

  • 文档 -获取Clojure符号的文档
    • 参数: symbol (字符串,必填)
    • 返回:文档文本或“未找到文档”
  • 来源 -获取Clojure符号的源代码
    • 参数: symbol (字符串,必填)
    • 返回:源代码或“未找到源代码”
  • 关于 -搜索与图案匹配的符号
    • 参数: query (字符串,必填)
    • 返回:匹配符号列表或“未找到匹配项”

会话反思:

  • 谁 -列出命名空间中当前定义的变量
    • 参数: namespace (string,可选)-列出变量的命名空间
    • 如果未指定,则默认为当前命名空间
    • 返回:变量名的JSON数组
  • 已加载命名空间 -列出所有加载的命名空间
    • 返回:命名空间名称的JSON数组
  • 当前命名空间 -获取当前默认命名空间
    • 返回:当前命名空间名称

服务器管理:

  • 重新启动nrepl服务器 -重新启动嵌入式nREPL服务器(仅限--server模式)
    • 无需参数
    • 停止当前服务器,杀死所有卡住的线程,并在新端口上启动一个新的服务器
    • 使用此功能从无限序列、卡住的计算或其他挂起中恢复
    • 注意:变量和名称空间保持不变(它们在进程内存中)
    • 仅在--server模式下工作(不在--bridge模式下工作)
    • 返回:成功消息

安全考虑

MCP nREPL授予AI助手完全的REPL访问权限。 在使用此工具之前,请了解其安全影响:

  • 任意代码执行:AI助手可以使用您的用户权限评估nREPL会话中的任何Clojure代码
  • 文件系统访问:代码可以读取、写入和删除用户帐户可访问的文件
  • 网络接入:代码可以发出网络请求并与外部服务交互
  • 环境准入:代码可以读取环境变量和系统属性

建议:

  • 仅将MCP nREPL与受信任的AI助手和MCP客户端一起使用
  • 在接受代码建议之前,请先对其进行审查,特别是系统操作
  • 考虑在隔离环境(容器、VM)中运行敏感工作
  • 使用生产凭据或敏感数据时要小心
  • nREPL会话共享状态-一个评估会影响后续评估

此工具用于开发工作流。 它提供了与在REPL提示符下键入时相同的访问级别。


为了发展:如果您想贡献或运行测试,请克隆完整的存储库,而不仅仅是下载脚本。为了方便开发,您可以将Claude直接指向签出目录中的文件位置。

发展

本节面向已克隆存储库并希望在本地测试mcp-nrepl的开发人员。

1.启动nREPL服务器

启动Babashka nREPL服务器进行测试:

bb nrepl-server

这将启动Babashka nREPL服务器并将端口写入 .nrepl-port.

2.单发评估模式(最快)

直接从命令行评估Clojure代码:

bb mcp-nrepl.bb --eval "(+ 1 2 3)"
# Output: 6

bb mcp-nrepl.bb -e "(str \"Hello\" \" \" \"World\")"
# Output: "Hello World"

3.MCP服务器模式

作为人工智能助手和其他MCP客户端的MCP服务器运行:

bb mcp-nrepl.bb --bridge

服务器将使用JSON-RPC 2.0协议从stdin读取并写入stdout。

注: --bridge 为清楚起见,建议使用该标志,但该标志是可选的(默认为桥接模式)。

初始化消息示例:

{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}},"id":1}

示例工具调用:

{"jsonrpc":"2.0","method":"tools/call","params":{"name":"eval-clojure","arguments":{"code":"(+ 1 2 3)"}},"id":2}

测试

运行测试

运行完整的测试套件(单元+E2E):

./run-tests.sh

测试套件包括:

  • 单元测试 (约1秒)-没有副作用的纯函数:MCP处理程序、数据转换、错误构建器
  • 端到端测试 (约5秒)-完全集成:MCP协议、nREPL评估、资源和一次性评估模式
  • 误用测试 (约3秒)-错误处理:JSON格式错误、请求无效、缺少nREPL服务器、Clojure代码格式错误
  • 性能测试 (约1秒)-定时验证:单次评估模式在200ms阈值下完成

为了保持一致性和可维护性,所有测试套件都是用Babashka编写的。

Git挂钩

为了确保代码质量,请安装在每次提交之前运行测试的预提交挂钩:

./install-git-hooks.sh

安装后,测试将在每次提交前自动运行。钩子的版本控制在 .githooks/pre-commit,因此任何更新都会自动应用,无需重新安装。

要跳过特定提交的钩子(不推荐):

git commit --no-verify

用AI构建

MCP nREPL是用 克劳德代码,人工智能驱动的编码助手。事实上,我采用了一种我永远不会手工编辑的创造性约束。如果你正在寻找MCP服务器,我假设你对AI在开发中的帮助感到满意。

贡献

MCP nREPL是在创造性约束下开发的,所有代码都由Claude code编写。看 贡献.md 了解如何贡献想法和概念验证PR的详细信息。

设计约束:零依赖性,仅限REPL访问,代码最少/快速/可读。

许可证

Eclipse公共许可证v1.0-有关详细信息,请参阅许可证文件