Development
git clone https://github.com/calimero-network/mero-mcpcd mero-mcpnpm install| Command | What it does |
|---|---|
npm start |
Run the server from source with tsx |
npm run typecheck |
tsc --noEmit |
npm test |
Unit tests via the Node test runner |
npm run build |
Compile to dist/ |
npm run test:bin |
Build, pack, install, and start by bin name |
npm run e2e |
Protocol e2e against a real node |
npm run e2e:cycle |
Full credential-handoff cycle against a real node |
To drive your build from an MCP client, point it at node /abs/path/to/dist/index.js
with no arguments — see setup.
Unit tests
Section titled “Unit tests”npm testPlain node:test with node:assert/strict, run through tsx. Every module has a
sibling *.test.ts. Two are worth knowing about:
schema.conformance.test.tschecks the ABI→schema mapping against committed fixtures, so a change to the mapping has to face real manifests.fixtures.test.tsvalidates the bundles undertest/fixtures— it will tell you to re-bundle withcargo mero bundle --devif a bundle is missing its hashes.
The bin smoke test
Section titled “The bin smoke test”npm run test:binThis packs the tarball, installs it, and starts the server by bin name, which is
the only way to exercise the symlink npm creates. It exists because the entrypoint is
resolved by node itself: node reports the symlink path in argv[1] while
import.meta.url resolves to the realpath, so any main-module comparison in
index.ts would silently skip main() and exit 0. CI runs it on Node 20, 22 and 24
because that resolution can break on a runtime the other jobs never use.
End-to-end harnesses
Section titled “End-to-end harnesses”Two harnesses drive the built server over real MCP stdio against a real node.
npm run e2e # 16 assertions: the protocol, the ABI-derived tools, and a round trip verified out of bandnpm run e2e:cycle # 8 assertions: admin login → client key → agent.json handoff, with zero credentials in the environmentBoth boot their own merod on port 2571 in a temp home and tear it down in a
finally, so neither touches ~/.calimero or your real state directory.
e2e-cycle is the whole product cycle headless: the desktop app’s contribution is one
HTTP call plus one file write, so there is nothing a GUI would add — log in as admin,
mint the agent its own client key, hand it over in agent.json, and let the server find
the node and authenticate with nothing else to go on.
The merod requirement
Section titled “The merod requirement”MEROD_BINARY selects the binary to boot, defaulting to core’s
target/debug/merod. Until a core release carries
GET /admin-api/applications/:id/abi, that binary has to come from core master —
every generated tool comes from that endpoint:
cd <core> && cargo build -p merodMEROD_BINARY=<core>/target/debug/merod npm run e2eAttaching to a running node
Section titled “Attaching to a running node”To reproduce a problem against a node you already have:
npm run e2e -- --node http://localhost:2528 --app my-appIn that mode it provisions nothing and tears nothing down — it attaches to what is
there and prints SKIP for each assertion that needs a node it controls.
.github/workflows/ci.yml runs three jobs on every PR to main:
- Validate — typecheck, unit tests, build.
- Bin smoke — matrixed over Node 20, 22, 24.
- E2E — builds
merodfrom coremaster, then runs both harnesses. Logs are uploaded as artifacts, and any surviving node is killed in analways()step.
Releases
Section titled “Releases”Releases are automated with semantic-release from
conventional commits, publishing to npm as
@calimero-network/mero-mcp. Commit messages decide the version bump, so write them
accordingly — fix: for a patch, feat: for a minor, a BREAKING CHANGE: footer for
a major.
Working on these docs
Section titled “Working on these docs”The site is Astro Starlight in docs/, matching
core and the SDK sites.
-
Run it locally:
Terminal window cd docsnpm installnpm run dev -
Check it before pushing — this is exactly what CI runs:
Terminal window npm run check # astro build + internal link check
Content lives in docs/src/content/docs/, grouped Get Started → Guides → Understand
→ Reference → Contribute, with the sidebar declared explicitly in
docs/astro.config.mjs (a new page needs adding there).
Two things to know about links:
- Write in-content links without the
/mero-mcpbase —/reference/tools/.src/middleware.tsadds the base at render time, in dev and in the build, because Astro only base-prefixes its own nav. scripts/check-links.mjsfails the build on a link that is missing the base or does not resolve to a built page. It runs on every PR touchingdocs/**via.github/workflows/docs-ci.yml.
Pushing to main deploys via .github/workflows/docs-site.yml. The theme
(src/styles/theme.css) is the shared Calimero design system — DM Sans, JetBrains
Mono, the #a5ff11 lime on a Zinc ramp — and is kept identical across the sibling
sites, so change it there rather than diverging here.