Modex
Modex is a Clojure MCP Library to augment your AI models with Tools, Resources & Prompts using Clojure (Model Context Protocol). Implements MCP Server & Client.
Install / Use
/learn @theronic/ModexQuality Score
Category
Development & EngineeringSupported Platforms
README
Modex: Model Context Protocol Server & Client Library in Clojure
Modex (MOdel + ContEXt) is a Clojure library that lets you augment your AI with new tools, resources and prompts.
Modex implements (most of) the Model Context Protocol to build MCP Servers & Clients in 'native' Clojure.
Because it's native Clojure, you don't need to deal with Anthropic's MCP Java SDK.
Modex implements the stdio transport in the 2024-11-05 MCP spec, so no need for a proxy like
mcp-proxy to translate between SSE <=> stdio or vice versa.
Screenshot of Modex in Action
Claude Desktop can talk to a Modex MCP Server via its MCP client:
<img width="650" alt="image" src="https://github.com/user-attachments/assets/ef83b8da-1816-48c0-aba6-47b4b5623f7a" />Table of Contents
- Quickstart
- What is MCP?
- What can Modex do?
- Detailed Step-by-Step Instructions
- Implementation
- Project Status
- Rationale
- FAQ
- Licence
Example Tools
- Datomic MCP uses Modex to expose Datomic tools so your models can query DB schema and data in dev or prod.
Quickstart
git clone git@github.com:theronic/modex.gitcd modex./build.shbuilds an uberjar attarget/modex-mcp-0.2.2.jar.- Open your Claude Desktop Config at
~/Library/Application\ Support/Claude/claude_desktop_config.json - Configure a new MCP Server that will run the uberjar at its full path:
{
"mcpServers": {
"modex-mcp-hello-world": {
"command": "java",
"args": ["-jar", "/Users/your-username/code/modex/target/modex-mcp-0.2.2.jar"]
}
},
"globalShortcut": ""
}
- Restart Claude Desktop to activate your new MCP Server + tools :) (Cmd+R refresh does not reload config, only restarts tools)
- Tell Claude to "run the inc tool with 123", authorize the tool and you should see an output of 124.
What is MCP?
MCP lets you augment your AI models with Tools, Resources & Prompts:
- Tools are things it can do, like query a database (e.g. Datomic).
- Resources are files and data it can read, like PDF bank statements.
- Prompts are templated messages and workflows.
Use Cases
Modex is used by datomic-mcp, which exposes our production Datomic databases to an MCP client like Claude Desktop. The AI model intelligently diagnoses support queries in production by reading our database schema and running queries that checks server state & IPs, so it can try to reach it and compare the desired state of VMs against the actual state in our clusters.
Over time, I hope to automate the bulk of our recurring support queries using Modex + other MCP tools.
What can Modex do?
Full Example
There is an MCP server example in src/modex/mcp/core.clj that defines an MCP server with some basic tools.
Your MCP client (e.g. Claude Desktop) can connect to this server and use exposed tools to provide additional context to your AI models.
Data Structures
Tools
Internally, a tool is just Tool record with several Parameter arguments:
(defrecord Tool [name doc args handler])(defrecord Parameter [name doc type required default])
However, it is more convenient to define tools using the tool & tools macros below.
Describe a single tool with the tool macro:
The tool macro acts like defrecord, where the handler definition takes a map of arguments ala {:keys [arg1 arg2 ...]} but with additional (optional) maps for :type, :or & :doc. This metadata is used to describe the tool to the MCP Client.
- The MCP spec currently only supports
:string&:numbertool parameter types. - Presence in the
:ormap implies optionality. - Missing parameter docstrings default to parameter name string.
(require '[modex.mcp.tools :as tools])
(def add-tool
(tools/tool
; feels like defrecord.
(add [{:keys [x y]
:type {x :number
y :number}
:or {y 0} ; y is optional due to its presence in the :or map.
:doc {x "First number"
y "Second number"}}]
[(+ x y)]))) ; tools should return a vector (to support multiple values).
Invoke a Tool with invoke-tool incl. validation:
Invocation uses a map of arguments like an MCP client would for a tools/call request:
(tools/invoke-tool add-tool {:x 5 :y 6}) ; Modex will map these arguments and call the handler.
=> {:success true, :results [11]} ; note :results is vector to support multiple values.
Invoke a tool handler directly to skip validation & error-handling:
(tools/invoke-handler (:handler add-tool) {:x 5 :y 6})
=> [11] ; note vector result to support multiple values.
Define a Toolset with tools macro
The tools macro just calls the tool macro for each tool definition and returns a map of tools keyed on tool name (keyword):
(def my-tools
"Define your tools here."
(tools/tools
(greet
"Greets a person by name." ; tools can have a docstring
[{:keys [first-name last-name]
:doc {first-name "A person's first name."
last-name "A person's last name (optional)."}
:type {first-name :string
last-name :string}
:or {last-name nil}}] ; last-name is optional, implied by presence in `:or` map.
; tools should return collection.
[(str "Hello from Modex, "
(if last-name ; args can be optional
(str first-name " " last-name)
first-name) "!")])
(add
"Adds two numbers."
; Tool handler args also support deprecated vector arg-style,
; but this is superseded by the newer map-destructuring style:
[^{:type :number :doc "First number to add."} a
^{:type :number :doc "Second number to add."} b]
[(+ a b)])
(subtract
"Subtracts two numbers (- a b)"
[^{:type :number :doc "First number."} a
^{:type :number :doc "Second number."} b]
[(- a b)])
(error-handling
"This tool throws intentionally. Modex will handle errors for you."
[]
(throw (ex-info "Modex will handle exceptions." {})))))
Create a Modex MCP Server + tools:
(require '[modex.mcp.server :as server])
(def my-mcp-server
"Here we create a reified instance of AServer. Only tools are presently supported."
(server/->server
{:name "Modex MCP Server"
:version "0.0.2"
:initialize (fn [_init-params] ; init-params, but may contain client capabilities in future.
"Do long-running setup & blocking I/O here, like connecting to prod database.")
:tools my-tools
:prompts nil ; Prompts are WIP.
:resources nil})) ; Resources are WIP.
Start your MCP Server
(server/start-server! my-mcp-server)
Or put that in your -main function.
Protocols
Modex exposes an AServer protocol and a DSL to define tools protocols that describe MCP servers, which expose tools, resources & prompts.
AServer Protocol:
(defprotocol AServer
(protocol-version [this])
(server-name [this])
(version [this])
(capabilities [this])
(initialize [this _init-params]) ; init-params is empty for now, but may contain client capabilities in future.
(list-tools [this])
(call-tool [this tool-name arg-map])
(list-resources [this])
(list-prompts [this]))
Detailed Step-by-Step Instructions
Step 1: Build the Uberjar
Before you can run it, you have to build it first. The build outputs an uberjar, which is like a Java executable.
clojure -T:build uber
or run the helper which does that:
./build.sh
(you might need to run chmod +x build.sh)
Step 2: Open Claude Desktop Config
Open your Claude Desktop Configuration file, claude_desktop_config.json, which on MacOS should be at:
~/Library/Application\ Support/Claude/claude_desktop_config.json
Step 3: Configure your MCP Server
Add an element under mcpServers so it looks like this:
{
"mcpServers": {
"modex": {
"command": "java",
"args": ["-jar", "/Users/your-username/code/modex/target/modex-mcp-0.2.2.jar"]
}
},
"globalShortcut": ""
}
This tells Claude Desktop there is a tool named modex and it can connect to by running java -jar /path/to/your/uber.jar.
The way this works is that your local MCP Client (i.e. Claude Desktop), starts your MCP server process and communicates with it via stdin/stdout pipes.
Step 4: Restart Claude Desktop
You should now be able to ask Claude "run foo", or "what does foo say?" and it will run
the foo tool and reply with the response, "Hello, AI!".
Implementation
Modex implements an MCP client & server in Clojure that is mostly compliant with the 2024-11-05 MCP Spec.
Messages are encoded using the JSON-RPC 2.0 wire format.
There are 3 message types:
- Requests have
{:keys [id method ?params]} - Responses have
{:keys [id result ?error]} - Notifications have
{:keys [method ?params}
MCP supports two transport types:
- [x] stdio/stdout – implemented in Modex.
- [ ] Server-Sent Events (SSE) – not implemented yet. Useful for restricted networks
Project Status
- [x] Passing tests
- [x] Ergonomics (AServer / AClient protocol?)
- [x] Tools
- [x] nREPL for live changes to running process
- [ ] Resources
- [ ] Prompts
- [in progress] SSE support
- [in progress] Streaming HTTP Support (2025-03-26 MCP spec)
Rationale
There is an existing library [mcp-clj](https://github.com/hugodun
Related Skills
node-connect
341.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
Hook Development
84.4kThis skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.
MCP Integration
84.4kThis skill should be used when the user asks to "add MCP server", "integrate MCP", "configure MCP in plugin", "use .mcp.json", "set up Model Context Protocol", "connect external service", mentions "${CLAUDE_PLUGIN_ROOT} with MCP", or discusses MCP server types (SSE, stdio, HTTP, WebSocket). Provides comprehensive guidance for integrating Model Context Protocol servers into Claude Code plugins for external tool and service integration.
