Date: 2026-06-18
Status: Approved (design), pending implementation plan
Area: libs/boundary-cli (project generator + templates), libs/boundary-mcp (Clojars publish), libs/tools/.../deploy.clj (release pipeline)
boundary new <name> should produce a project that is, with no manual wiring:
bb quickstart) away from a running app.Today a new project ships the full bb task suite, CLAUDE.md, AGENTS.md, and
a Claude Code skill, but: it is not a git repo, has no MCP wiring, and the
post-create message points at a multi-step manual path. boundary-mcp's Tier 0/1/2
tools are now implemented (the libs/boundary-mcp/AGENTS.md "skeleton" note is
stale), so the server is ready to wire into new projects.
A — thin create, fat quickstart. Everything fast and offline happens at create
time; everything network-bound, database-bound, or otherwise fallible is deferred
to the already-existing bb quickstart task (check env → configure → migrate →
optional first module → start), which the post-create message promotes.
Rationale: create stays fast and deterministic (seconds, no network), so the first
impression cannot half-fail on a slow maven resolve or a missing JWT_SECRET.
The slow/fallible steps live behind one promoted command.
Rejected alternatives:
boundary new): slow first run,
needs JWT_SECRET sourced, can leave a half-initialised project on
network/db failure — failure at first impression.--yes/--minimal flag matrix.A new project must consume boundary-mcp the same way it consumes every other
Boundary library: as a Clojars artifact resolved through deps.edn. A
project must not reach into the install-time monorepo clone — that would couple
the project to CLI install internals. boundary-mcp is therefore published to
Clojars and launched from a dedicated deps.edn alias.
org.boundary-app/boundary-mcp (see Unit 1).deps.edn gains an :mcp alias (not a :deps entry). It must
enumerate boundary-mcp's boundary closure that is NOT already in the project's
default :deps, because published Boundary poms omit their boundary deps (see
"Pom caveat" below). The default :deps already covers core, observability, platform, user, ui-style, external, payments; the closure additions are
ai, devtools, scaffolder, tools, jobs:
:mcp {:extra-deps {org.boundary-app/boundary-mcp {:mvn/version "<suite-version>"}
org.boundary-app/boundary-ai {:mvn/version "<suite-version>"}
org.boundary-app/boundary-devtools {:mvn/version "<suite-version>"}
org.boundary-app/boundary-scaffolder {:mvn/version "<suite-version>"}
org.boundary-app/boundary-tools {:mvn/version "<suite-version>"}
org.boundary-app/boundary-jobs {:mvn/version "<suite-version>"}}
:main-opts ["-m" "boundary.mcp.shell.server"]}
:extra-deps composes with the project's :deps, so the libs already there
satisfy the rest of the closure. All additions share the suite version.
.mcp.json (committed, portable) runs clojure -M:mcp with cwd inherited
from the editor (the project root).Why an alias, not a :deps entry: the monorepo rule "applications never pull an
MCP server transitively" is preserved. The MCP server is absent from the default
classpath — clojure -M:repl, -M:test, and the app runtime never see it. Only
the explicit clojure -M:mcp (i.e. the editor launching the server) resolves it.
The version is pinned in deps.edn alongside the other Boundary libs and fetched
from Clojars into ~/.m2 exactly like them — no clone dependency, no
machine-specific path.
Pom caveat (discovered during implementation): tools.build/write-pom
skips :local/root coordinates, so every published Boundary lib's pom omits its
boundary dependencies. The framework already relies on each project's deps.edn
listing all app libs explicitly; transitive boundary-dep resolution via poms does
not work. Consequently the :mcp alias must enumerate mcp's boundary closure
itself (above), and this list is brittle — it must be re-derived if mcp's or its
deps' boundary dependencies change. A post-publish smoke test (run clojure -M:mcp against a published artifact and confirm the server boots) is the guard
against drift. Fixing poms framework-wide was considered and rejected as
out-of-scope.
Trade-off accepted: boundary-mcp (an RCE-surface server, though env-gated to
:read-only outside local dev) becomes a public Clojars artifact and joins the
release pipeline. This is the deliberate cost of consuming it the framework's
standard way.
boundary-mcp currently uses :local/root sibling deps (../ai, ../devtools,
../scaffolder, ../tools) — exactly the pattern libs/user/deps.edn already
uses for boundary/platform, which publishes fine via tools.build's
write-pom (it resolves each :local/root dep to its published maven
coordinate in the generated pom). All four of mcp's sibling deps are already in
all-libs and published, so nothing blocks publishing mcp.
libs/boundary-mcp/build.clj already exists and already mirrors
libs/user/build.clj (coord org.boundary-app/boundary-mcp, version
1.0.1-alpha-32, clean/jar/install/deploy via b/write-pom +
deps-deploy); the :build alias is wired. This sub-step is verify-only —
do not recreate it. Confirm clojure -T:build jar emits a pom with maven
coords for the sibling deps."boundary-mcp" to all-libs in
libs/tools/src/boundary/tools/deploy.clj. devtools is currently the last
entry; mcp's deps (tools, scaffolder, ai, devtools) must all precede it,
so append "boundary-mcp" at the very end of the vector (after devtools).boundary-tools-version, NOT the
catalogue. boundary-mcp is dev tooling, not an addable app module; it must
not go in modules-catalogue.edn (that would list it under
boundary add/boundary list modules and fail catalogue/validate-catalogue!
required-field checks). Instead, in libs/boundary-cli/src/boundary/cli/new.clj,
add a private const next to the existing one
((def ^:private boundary-mcp-version "1.0.1-alpha-32"), new.clj:7) and a
:boundary-mcp-version boundary-mcp-version entry in the subs map (new.clj:56).
Bump it at release alongside boundary-tools-version.clojure -M:mcp
(Unit 2), inheriting the editor's cwd (the project root) — exactly what the
reflective resources need.boundary new renders these in addition to today's 14 files. New .tmpl files
under libs/boundary-cli/resources/boundary/cli/templates/, wired into the
generation map in libs/boundary-cli/src/boundary/cli/new.clj:
.mcp.json at project root:
{
"mcpServers": {
"boundary": {
"command": "clojure",
"args": ["-M:mcp"],
"env": { "BND_ENV": "dev" }
}
}
}
Read natively by both Claude Code and Cursor. No cwd key → the client uses
the workspace root (correct for reflection). Single root file, no
.cursor/mcp.json duplicate.
deps.edn.tmpl — add the :mcp alias (this is the one deps.edn change;
the alias keeps mcp out of the default :deps, preserving "no transitive
MCP"):
:mcp {:extra-deps {org.boundary-app/boundary-mcp {:mvn/version "{{boundary-mcp-version}}"}}
:main-opts ["-m" "boundary.mcp.shell.server"]}
.vscode/extensions.json — recommends the relevant agent extension; a
nudge, not configuration. No secrets, no settings..githooks/pre-commit — project-local, runs the project's own tasks:
#!/usr/bin/env bash
set -euo pipefail
bb check:fcis
clojure -M:clj-kondo --lint src test 2>/dev/null || true
Quick gate only — not check:ports / check:deps (noisier on a fresh
project; the full suite belongs in CI).
gitignore.tmpl ignores .env while leaving .mcp.json,
.vscode/, and .githooks/ committed. (Current gitignore.tmpl ignores only
.env/target//.cpcache/ — no functional change needed, just confirmation.).githooks/pre-commit must be written with +x. The
current new.clj file writer uses plain spit, which does not set the
executable bit; without it git config core.hooksPath silently no-ops the
hook. The generator must chmod +x the rendered hook (or the bootstrap step
in Unit 3 must set it after writing).The MCP server stays out of the application runtime: it lives only in the :mcp
alias, so clojure -M:repl / -M:test and the built app never resolve it.
new.cljAfter files are rendered, unless --skip-git is passed:
git init.githooks (inline the
git config core.hooksPath .githooks step rather than calling the project's
bb install-hooks, which would require the project's bb deps to resolve
first).git add -A and commit "Initial commit (boundary new)".--skip-git.Replace the Next: block in new.clj with the approach-A flow:
Next:
cd <project-name>
bb quickstart # download deps, migrate, optional first module, start
Open Claude Code or Cursor here — the Boundary MCP server is already wired
(.mcp.json), so the agent has Boundary's tools the moment you start.
Keep the existing "optional modules" and "AI-ready" lines.
The Clojars-alias delivery (Units 1–2) needs no change to install.sh or the
boundary wrapper. clojure -M:mcp resolves boundary-mcp from Clojars/~/.m2
independently of the CLI's cached clone. Nothing to do here.
AGENTS.md.tmpl
(manual prose section; the FC/IS / naming / pitfalls sections of that template
are generated by bb agents:gen and must not be hand-edited).libs/boundary-mcp/AGENTS.md "skeleton (BOU-96)" status note is stale and
should be corrected to reflect Tier 0/1/2 shipped (small, in-scope cleanup).clojure -T:build jar in libs/boundary-mcp produces a
pom whose dependencies list the published org.boundary-app/boundary-*
coordinates (not :local/root) — confirm by inspecting the generated pom.
Verify bb deploy --missing (or a dry-run) includes boundary-mcp after its
deps.new.clj (extend existing generation tests): assert .mcp.json (with the
clojure -M:mcp command), the :mcp alias in the rendered deps.edn,
.githooks/pre-commit, and .vscode/extensions.json are rendered with
substitutions applied ({{boundary-mcp-version}} resolved); assert
--skip-git skips git; assert a git failure is non-fatal (stub/force-fail
git, expect project still created + warning).boundary new demo && cd demo; clojure -M:mcp boots
the server (resolving mcp from ~/.m2); open Claude Code; confirm a
tools/list round-trip returns the Boundary tool catalogue and
boundary://conventions resolves concretely (proving cwd = project root).ai/devtools/scaffolder/tools) and a project's pinned
{{boundary-mcp-version}} must exist on Clojars before -M:mcp will resolve.
Mitigation: append-at-end ordering in all-libs (Unit 1); the
boundary-mcp-version const is release-bumped alongside boundary-tools-version
so the template pins a published version.:unavailable. .mcp.json omits cwd, so the
client uses the workspace root — correct. Documented in the template note.-M:mcp / bb quickstart first run is slow (maven resolve): acceptable
and expected; documented.boundary new time.boundary new..vscode/settings.json with project settings or secrets.check:ports / check:deps in the project pre-commit hook.Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |