ClojureMCP gives coding agents like Claude Code and Codex a persistent connection to your Clojure REPL.
- What is ClojureMCP?
- Where the project is headed
- Help and Community Resources
- π Installation
- CLI Agents (recommended)
- The Full Toolkit (legacy)
- π§ Customization
- CLI Options
- βοΈ Configuration
- π License
ClojureMCP is an MCP server that connects a coding agent to a running nREPL in your project. With it, the agent can do what Clojure programmers do: explore in the REPL, check its assumptions against the running program, and test changes as it makes them.
clojure_eval- evaluates code over a persistent nREPL connection, repairing unbalanced delimiters before evaluating. Works with Clojure, ClojureScript (shadow-cljs, Figwheel), Babashka, Basilisp, and Scittle.list_nrepl_ports- discovers the nREPL servers running on your machine, so the agent can find and switch between REPLs.paren_repair- a safety valve for the rare delimiter tangle that's hard to fix by string editing.
That's the whole recommended setup: the :repl profile. Your agent
keeps its own file reading, editing, search and shell tools.
ClojureMCP began in 2025 as a complete coding toolkit for Claude
Desktop, at a time when LLMs regularly mangled Clojure's parentheses.
So it shipped its own structure-aware editors (clojure_edit,
clojure_edit_replace_sexp), a collapsed read_file, file and shell
tools, sub-agents, prompts and resources.
That has changed. Current frontier models (recent Claude models in particular) edit Clojure reliably with the built-in editors of Claude Code and Codex, and they rarely get into delimiter trouble they can't get out of. The part of ClojureMCP that still matters is the REPL.
So:
- The
:replprofile is the recommended way to use ClojureMCP. - The editing tools and the rest of the full toolkit still work and remain available. They're useful if you're building your own harness, or if you're driving a model that does struggle with Clojure edits. But they're in maintenance mode and on a long path to deprecation, unless new, effective LLM editing approaches are discovered that are best delivered through ClojureMCP.
- The #ai-assisted-coding Channel on Clojurians Slack is very active and where I spend a lot of time.
- The ClojureMCP Wiki has info on various integrations and sandboxing.
- Clojure
- Java (JDK 17 or later)
- An nREPL in your project (see doc/nrepl.md), or let ClojureMCP start one with
:start-nrepl-cmdor:fallback-nrepl - Full toolkit only: ripgrep for better
grepandglob_filesperformance
Install ClojureMCP using the Clojure tools installer:
clojure -Ttools install-latest :lib io.github.bhauman/clojure-mcp :as mcpThis installs ClojureMCP globally, making clojure -Tmcp start available from any directory.
CLI coding agents (Claude Code, Codex, Gemini CLI) already have excellent file editing, search and shell tools. ClojureMCP adds the one thing they're missing: a live REPL.
Run from your project directory:
# Claude Code
claude mcp add clojure-mcp -- clojure -Tmcp start :config-profile :repl
# OpenAI Codex
codex mcp add clojure-mcp -- clojure -Tmcp start :config-profile :repl
# Google Gemini CLI
gemini mcp add clojure-mcp clojure -Tmcp start :config-profile :replBy default ClojureMCP connects to the nREPL port in your project's
.nrepl-port file. If you don't keep a REPL running, add
:fallback-nrepl true to have ClojureMCP start one for you, or
:start-nrepl-cmd '["clojure" "-M:nrepl"]' to start your own alias.
Why an MCP tool instead of evaluating via the shell? Agents reach for a first-class REPL tool far more readily than for a shell command, and the connection is persistent: state you build up in the REPL stays there between evaluations. If you'd rather not run an MCP server at all, clojure-mcp-light provides a shell-based nREPL client and a delimiter-repair hook instead.
With list_nrepl_ports, the agent can discover both your Clojure and shadow-cljs REPLs simultaneously. The tool identifies which REPLs are shadow-cljs instances, allowing the agent to evaluate on either REPL using clojure_eval with the appropriate port parameter.
These editing-focused profiles are still shipped. They're mainly useful with models that struggle to edit Clojure.
All three include the :repl tools (clojure_eval,
list_nrepl_ports, paren_repair) plus deps_list, deps_grep and
deps_read for searching and reading source in dependency jars.
:cli-assist- structural editors as a fallback for when the host's Edit tool fails to apply a change. Adds:clojure_edit,clojure_edit_replace_sexp.:cli-assist-agent- like:cli-assist, but the form-level fallback is an LLM sub-agent that applies loosely specified edits (requires an API key). Adds:clojure_edit_agent,clojure_edit_replace_sexp.:cli-assist-full- all Clojure reading and editing routed through ClojureMCP's tools instead of the host's. Adds:read_file,clojure_edit,clojure_edit_replace_sexp.
See doc/full-toolkit.md for more.
From your project directory:
clojure -Tmcp start :config-profile :replYou should see JSON-RPC output like this:
{"jsonrpc":"2.0","method":"notifications/tools/list_changed"}
{"jsonrpc":"2.0","method":"notifications/tools/list_changed"}
{"jsonrpc":"2.0","method":"notifications/resources/list_changed"}
{"jsonrpc":"2.0","method":"notifications/prompts/list_changed"}Without a :config-profile, ClojureMCP serves its original full
toolkit: structure-aware editors, a collapsed file reader, file and
shell tools, sub-agents, prompts and resources. It was built to turn
Claude Desktop into a Clojure coding assistant, and it's in
maintenance mode now (see
Where the project is headed).
If you're reaching for Claude Desktop to write Clojure, you'll be
better served by Claude Code, Codex or another programming harness
with the :repl profile.
Setup for Claude Desktop, the older editing profiles, API keys for the agent tools, the full tool list and file-tool configuration are all in doc/full-toolkit.md.
If you're building your own harness, ClojureMCP's tools, prompts and resources can be assembled into a custom MCP server: pick the tools you want, add your own as multimethods or simple maps, and expose your own prompts and resources.
See Creating Your Own Custom MCP Server to get started, and the customization docs for the rest.
Values passed to clojure -Tmcp start are EDN values.
Optional - The nREPL server port to connect to. When using :start-nrepl-cmd without :port, the port will be automatically discovered from the command output.
:port 7888
Optional - The nREPL server host. Defaults to localhost if not specified.
:host "localhost" or :host "0.0.0.0"
Optional - If true, don't use the current working directory as the project directory. Requires :port to be specified. The MCP server will introspect the nREPL connection to discover the project's working directory. Needed for clients that launch the MCP server outside your project directory, such as Claude Desktop.
:not-cwd true
Optional - A command to automatically start an nREPL server if one is not already running. Must be specified as a vector of strings. The MCP server will start this process and manage its lifecycle.
When used without :port, the MCP server will automatically parse the port from the command's output. When used with :port, it will use that fixed port instead.
Important: The nREPL server is started in the current working directory, so launch clojure-mcp from your project directory (where your deps.edn or project.clj is located). CLI agents do this already. For clients that launch servers elsewhere, also pass :project-dir.
:start-nrepl-cmd ["lein" "repl" ":headless"] or :start-nrepl-cmd ["clojure" "-M:nrepl"]
Optional - When true, ClojureMCP will first try to attach to :port. If nothing is listening there (or :port is omitted entirely), it spawns a local nREPL on an ephemeral port and connects to that. The fallback never squats on your configured :port, so a later editor session can still claim it.
This is intended for users who don't always have an editor-managed nREPL running. Without this flag, ClojureMCP fails to start if it can't reach :port.
The default command is built from clojure-mcp's own nREPL dependency (so no version is hardcoded) and runs through clojure -Sdeps ... -M -m nrepl.cmdline. The user's ~/.clojure/deps.edn is still merged in by the clojure CLI, so libraries you keep globally available (e.g. Criterium) remain on the spawned REPL's classpath.
The spawned process is cleaned up automatically when the MCP server shuts down.
:fallback-nrepl true
Optional - Overrides the default fallback command. Must be a vector of strings. Only used when :fallback-nrepl is true. Do not include an explicit port in the command; the launcher needs to parse the discovered port from the process output.
:fallback-nrepl-cmd ["lein" "repl" ":headless"]
Optional - Working directory for the spawned fallback REPL. Defaults to :project-dir if set, otherwise to $HOME. Useful when you want the fallback REPL to pick up a project's deps.edn automatically.
:fallback-nrepl-dir "/path/to/scratch"
Optional - Specify the location of a configuration file. Must be a path to an existing file.
:config-file "/path/to/config.edn"
Optional - Specify the working directory for your codebase. This overrides the automatic introspection of the project directory from the nREPL connection. Must be a path to an existing directory.
:project-dir "/path/to/your/clojure/project"
Optional - Specify the type of environment that we are connecting to over the nREPL connection. This overrides automatic detection. Valid options are:
:cljfor Clojure or ClojureScript:bbfor Babashka - Native, fast starting Clojure interpreter for scripting:basilispfor Basilisp - A Clojure-compatible Lisp dialect targeting Python 3.9+:scittlefor Scittle - Execute ClojureScript directly from browser script tags
:nrepl-env-type :bb
Optional - Controls whether the shadow-cljs REPL mode status message is included in eval results (default: true). When connected to a shadow-cljs nREPL, a status message about CLJS mode is prepended to every eval result. Set to false to disable this message.
:shadow-cljs-repl-message false
Optional - Load a built-in configuration profile that adjusts tool availability and descriptions. Useful for tailoring ClojureMCP to specific use cases.
Available profiles:
:repl- Recommended. REPL-only toolset for CLI coding agents (Claude Code, Codex, Gemini CLI):clojure_eval,list_nrepl_portsandparen_repair, with no prompts or resources. The agent uses its own tools for all reading and editing. Uses allowlists, so tools added to ClojureMCP later stay off unless the profile lists them.:cli-assist,:cli-assist-agent,:cli-assist-full- (legacy) Editing-focused profiles; see doc/full-toolkit.md.
:config-profile :repl
Optional - Allowlist of tool keywords. When provided, replaces any :enable-tools value from config. Only the listed tools will be available.
:enable-tools [:clojure_eval :read_file]
Optional - Blocklist of tool keywords. When provided, replaces any :disable-tools value from config. The listed tools will be disabled.
:disable-tools [:bash :dispatch_agent]
Optional - Force-enable specific tools after config resolution. Removes tools from the disable list, and adds them to the enable list if one is active. This is useful for selectively re-enabling tools that a config profile disables.
:add-tools [:my_custom_agent]
Optional - Force-disable specific tools after config resolution. Adds tools to the disable list, and removes them from the enable list if one is active. This is useful for selectively disabling tools without replacing the entire config.
:remove-tools [:clojure_eval]
- Config loaded (home + project + profile merge)
:enable-tools/:disable-toolsfrom opts replace config values (if provided):remove-toolsapplied (force-disable):add-toolsapplied (force-enable β wins over:remove-toolson overlap)ENABLE_TOOLS/DISABLE_TOOLSenv vars still win over everything
See Component Filtering for details on how enable/disable lists work in config files.
# Recommended for CLI coding agents: REPL tools only
clojure -Tmcp start :config-profile :repl
# REPL only, connecting to a specific port
clojure -Tmcp start :config-profile :repl :port 7888
# REPL only, spawning an nREPL if none is running
clojure -Tmcp start :config-profile :repl :fallback-nrepl true
# REPL only, starting your project's nREPL alias (port is discovered)
clojure -Tmcp start :config-profile :repl :start-nrepl-cmd '["clojure" "-M:nrepl"]'
# Leiningen project
clojure -Tmcp start :config-profile :repl :start-nrepl-cmd '["lein" "repl" ":headless"]'
# Babashka nREPL
clojure -Tmcp start :config-profile :repl :port 1667 :nrepl-env-type :bb
# With custom host and project directory
clojure -Tmcp start :port 7888 :host '"0.0.0.0"' :project-dir '"/path/to/project"'
# Using a custom config file
clojure -Tmcp start :port 7888 :config-file '"/path/to/custom-config.edn"'
# REPL only, plus one of the legacy structural editors
clojure -Tmcp start :config-profile :repl :add-tools '[:clojure_edit]'
# Strictly REPL: drop paren_repair too
clojure -Tmcp start :config-profile :repl :remove-tools '[:paren_repair]'
# Full override β only these two tools
clojure -Tmcp start :enable-tools '[:clojure_eval :read_file]'Note: String values need to be properly quoted for the shell, hence '"value"' syntax for strings.
ClojureMCP reads optional project configuration from a
.clojure-mcp/config.edn file in your project's root directory. The
:repl profile usually needs none. Most options configure the full
toolkit's file, shell and agent tools (see
doc/full-toolkit.md).
Create a .clojure-mcp/config.edn file in your project root:
your-project/
βββ .clojure-mcp/
β βββ config.edn
βββ src/
βββ deps.edn
βββ ...
All options are documented in CONFIG.md.
Eclipse Public License - v 2.0
Copyright (c) 2025 Bruce Hauman
This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which is available at http://www.eclipse.org/legal/epl-2.0
- β Use freely for personal projects, internal business tools, and development
- β Modify and distribute - improvements and forks are welcome
- β Commercial use - businesses can use this commercially without restrictions
- β Flexible licensing - can be combined with proprietary code
- π€ Share improvements - source code must be made available when distributed