Liking cljdoc? Tell your friends :D

presa

ci conformance conformance canary release MCP Babashka JVM license

A Clojure library for building Model Context Protocol servers and clients, for Babashka and the JVM from the same source.

presa targets MCP 2026-07-28, the stateless revision: no initialize handshake, the protocol version and client capabilities in each request's _meta, server/discover, and resultType on every result. Initialize-era clients (2025-11-25 and 2025-06-18) are an opt-in, which Codex needs today: see docs/hosts.md for what Claude Code and Codex send.

presa is at 0.x: the API may change between minor versions until 1.0.

Using presa

presa is on Clojars, and each release is also a git tag (see RELEASING.md):

;; deps.edn or bb.edn, from Clojars
{:deps {io.github.joshrotenberg/presa {:mvn/version "0.1.0"}}}

;; or from the tag; :git/sha is the tag's commit (see below)
{:deps {io.github.joshrotenberg/presa {:git/tag "v0.1.0" :git/sha "..."}}}

git ls-remote https://github.com/joshrotenberg/presa.git refs/tags/<tag> gives the sha. Full JSON Schema validation on the JVM (presa.schema.networknt) also needs com.networknt/json-schema-validator {:mvn/version "3.0.0"}, which presa does not pull in; pass presa.schema.networknt/validator as the server's :validator.

Goals

  • Babashka first. Every namespace except the optional presa.schema.networknt loads in Babashka and on the JVM. The core depends only on what Babashka bundles (clojure.data.json), and the HTTP transport on http-kit, which Babashka also bundles.
  • Plain data. Requests, responses, tools, resources and prompts are maps; a server is a function from a request to a response.
  • Transports outside the core. stdio (newline-delimited JSON-RPC) and Streamable HTTP over http-kit.
  • A client that calls any MCP server over stdio or HTTP and turns its tools into functions.
  • Conformance measured with the official MCP conformance runner.

Layout

NamespaceRole
presa.protocolspec revisions, _meta keys, error codes, log levels
presa.jsonrpcJSON-RPC 2.0 messages and newline framing
presa.servera server as data; dispatch for discovery, initialize, tools, resources, prompts, completion; input requests, subscriptions, the Tasks extension, scopes, changing a running server, pagination, caching hints, logging, progress and :on-event instrumentation
presa.contentcontent blocks: text, image, audio, embedded resources, resource links
presa.uri-template{var} and {+var} URI templates for resource templates
presa.connectionone client's connection to a server: session, concurrency, cancellation
presa.clientcalling a server: negotiation, requests, timeouts, progress and log callbacks, input handlers, caching, listen, tasks, tool-fns
presa.transport.stdiostdio: serve a server, or start a server subprocess as a client
presa.inputinput requests (elicitation, sampling, roots) and the capabilities they need
presa.request-statesigned requestState tokens for multi round-trip requests
presa.schemaJSON Schema subset validation for tool arguments and output
presa.schema.networkntfull JSON Schema 2020-12 validation (JVM only, optional dependency)
presa.transport.httpStreamable HTTP: a server over http-kit, a client over java.net.http
presa.proxyone server in front of several MCP servers
presa.tasksthe Tasks extension's task store and wire shapes
presa.auth, presa.auth.jwtOAuth 2.1 resource server: metadata, bearer challenges, JWT verification (RS256, ES256, HS256, JWKS)
presa.auth.clientOAuth 2.1 client: discovery, registration, PKCE code flow, client credentials, JWT-bearer (workload identity) and enterprise-managed (id-jag) grants, DPoP, step-up
presa.auth.dpopDPoP (RFC 9449): ES256 key pairs and proof JWTs for the OAuth client

docs/roadmap.md lists what is done and what is next.

A first server

(require '[presa.protocol :as protocol]
         '[presa.server :as server]
         '[presa.transport.stdio :as stdio])

(def srv
  (server/server
   {:name "greeter" :version "0.1.0"
    :versions protocol/versions          ; 2026-07-28 and the initialize-era revisions
    :tools [{:name "greet"
             :description "Greet someone by name."
             :input-schema {"type" "object" "properties" {"name" {"type" "string"}} "required" ["name"]}
             :handler (fn [{:strs [name]} _context] (str "Hello, " name "!"))}]}))

(defn -main [& _] (stdio/serve! srv) (shutdown-agents))

Guides

GuideCovers
Getting starteda server, a client in the same process, stdio, registering with Claude Code and Codex
Tools, resources and promptshandlers and their results, schemas, templates, completion, pagination, changing a running server, caching hints
The clientconnecting, calls, progress, logs, timeouts, handlers, caching
Transportsstdio, Streamable HTTP and its options, sessions
Asking the client for inputelicitation, sampling, roots, signed request state, both eras
Subscriptionssubscriptions/listen, list changes, resource updates
Tasksthe Tasks extension: long-running tools, server and client
Authorizationthe OAuth 2.1 resource server and client, JWT verification, scopes
The proxyone server in front of several, what it forwards, input from initialize-era backends
Initialize-era clientsserving 2025-11-25 and 2025-06-18, and what differs
Logging, progress and instrumentationlog!, progress!, :on-event
A complete examplethe notebook server, its REPL walkthrough and client, from a host

Every Clojure block in the guides that is not marked no-run runs as part of the test suite, and so does the notebook's REPL walkthrough.

Reference: docs/wire-2026-07-28.md (the revision on the wire), docs/tasks-extension.md, docs/oauth-client.md (the client side of authorization), docs/hosts.md (what real hosts send), docs/roadmap.md.

Conformance

conformance/ runs the official MCP conformance runner against a fixture server and a client harness. All 37 required 2026-07-28 server scenarios pass, as do nine of the ten Tasks extension scenarios (the tenth, tasks-status-notifications, is a runner stub that always skips), the 2025-11-25 and 2025-06-18 server suites, and every client scenario at 2026-07-28 and 2025-11-25, including the scored authorization ones (25 and 14) and the DPoP, workload identity, enterprise-managed and client credentials extensions.

The example servers

examples/presa/example/hello.clj has two tools, echo and add, and serves every revision presa knows:

bb --config /path/to/presa/bb.edn -m presa.example.hello   # or, from the repository, clojure -M:example
claude mcp add presa-hello -- bb --config /path/to/presa/bb.edn -m presa.example.hello
codex mcp add presa-hello -- bb --config /path/to/presa/bb.edn -m presa.example.hello

examples/presa/example/notebook.clj is a notebook that uses most of presa together: structured tools, elicitation, sampling, tasks, resources and a template, a prompt, completion, subscriptions, logging, both transports and OAuth. It comes with a REPL walkthrough and a command-line client; the guide goes through it.

bb --config /path/to/presa/bb.edn -m presa.example.notebook   # or clojure -M:notebook
bb --config /path/to/presa/bb.edn -m presa.example.notebook-client
claude mcp add notebook -- bb --config /path/to/presa/bb.edn -m presa.example.notebook
codex mcp add notebook -- bb --config /path/to/presa/bb.edn -m presa.example.notebook

Development

bb test                          # tests under Babashka
bb jvm-test                      # the same tests on the JVM, plus the JVM-only schema tests (clojure -M:test)
bb conformance 2026-07-28        # the conformance runner's server leg against the fixture, at a revision
bb conformance client 2026-07-28 # its client leg against the client harness
bb lint                          # no em dashes, conventional commits since origin/main
clojure -T:build jar             # the jar a release deploys to Clojars

License

MIT

Can you improve this documentation? These fine people already did:
Josh Rotenberg & github-actions[bot]
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