@bluenotelogic/harness
v0.1.0
Published
One command to point a machine at Blue Note Memory (mem.bnlgit.com). Writes a TOKENLESS MCP config — OAuth-capable hosts hold their own credentials, so nothing secret lands in a repo file.
Maintainers
Readme
@bluenotelogic/harness
Point a machine at Blue Note Memory in one command.
npx @bluenotelogic/harness initThat's it. A browser opens, you sign in with your Blue Note Account, and the CLI writes a working MCP config into the current repo.
What it writes — and what it deliberately does not
{ "mcpServers": { "mem": { "type": "http", "url": "https://mem.bnlgit.com/mcp" } } }There is no token in that file. Claude Code and VS Code discover authentication from the
endpoint's 401 + WWW-Authenticate, run the OAuth flow themselves, and store their own
credentials in their own keychain. So the file is safe to commit, safe to share with a
teammate, and there is nothing in it to rotate.
That is the entire point of this tool. The setup it replaces meant pasting a bearer token by
hand into .mcp.json, ~/.claude.json, ~/.codex/config.toml and a VS Code roaming
profile — and rotating anything meant editing every one of them again.
Codex and CI
Those hosts cannot do OAuth yet, so they need a real credential:
npx @bluenotelogic/harness init --codexThe minted token goes to ~/.codex/.env and is referenced from config.toml by name
(bearer_token_env_var), so the config file stays safe to read over someone's shoulder — and
the token still never touches the repo. Minting is opt-in: without --codex or
--mint-token, this CLI creates no credential and no database row.
For CI, skip the browser entirely with a token you already hold:
npx @bluenotelogic/harness init --token "$BNL_MEMORY_MCP_TOKEN"Headless machines
npx @bluenotelogic/harness init --devicePrints a short code and a URL to open on any other device. Standard RFC 8628 device flow.
Options
| Flag | Effect |
|---|---|
| --dry-run | Show every file that would change, write nothing |
| --url <base> | Point at a self-hosted deployment (default https://mem.bnlgit.com) |
| --dir <path> | Repo to configure (default: current directory) |
| --device | Device-code login for headless boxes and SSH sessions |
| --token <token> | Use an existing token instead of logging in |
| --mint-token | Also mint a token for hosts that cannot do OAuth |
| --codex | Configure Codex too (implies --mint-token) |
| --harness-home <dir> | Materialize hosted model routing into <dir>/state/routing/ |
| --server-name <name> | Override the MCP server key written into .mcp.json |
| --no-browser | Print the login URL instead of opening a browser |
Run --dry-run first if you like seeing before you commit. It prints the full contents of
every file it would touch.
It will not clobber your config
Every write reads what is already on disk and replaces only the keys it owns. An
unrelated MCP server in your .mcp.json survives untouched; so do unrelated top-level keys,
your Codex settings, and any hooks in .claude/settings.local.json.
If a file is not valid JSON, the CLI reports it and leaves it exactly as it found it — "it looked broken" is precisely when someone's half-finished hand edit is sitting in it.
This is not theoretical caution. The shell script this replaces once overwrote three
.mcp.json files that defined unrelated servers; two were recoverable from git and one was
not. test/writers.test.js pins that behaviour so it cannot happen again.
How it works
OAuth 2.1 + PKCE ──▶ Blue Note ID (identity: who are you)
│
▼
POST /api/oidc_exchange.php (product: do you have a subscription)
│
▼
GET /api/harness_bootstrap.php (config: what should this machine use)
│
▼
.mcp.json, routing YAML, optional Codex configIdentity and entitlement are separate on purpose. A Blue Note Account authenticates a person; it does not by itself grant memory access. If you sign in successfully but hold no subscription you get a clear message saying exactly that, rather than a login error that sends you looking in the wrong place.
Requirements
Node 20 or newer. No runtime dependencies — PKCE, the loopback listener and the HTTP
client are all Node built-ins, so npx is fast and there is no dependency tree to audit.
Development
npm install
npm test # builds, then runs the suite
npm run lint # tsc --noEmitLicence
Apache-2.0 — © 2026 Blue Note Logic Inc. See LICENSE.
This CLI is free and open source. It configures a machine to talk to Blue Note Memory; a Blue Note Memory subscription is a separate commercial product.
