@codai/axiom-mcp 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -6
- package/dist/axm-lazy-CR-FmFVd.js +6255 -0
- package/dist/axm-lazy.js +81 -2
- package/dist/cli-main.js +2315 -264
- package/dist/dist-FFqnyzCe.js +6141 -0
- package/dist/gate-lazy.js +77 -1
- package/dist/http-lazy.js +15154 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +411 -21
- package/dist/lib-CqHwM4m_.js +3884 -0
- package/dist/migrate-lazy.js +6472 -0
- package/package.json +9 -7
- package/spec/codai-tools.json +65 -2
- package/spec/tools.json +324 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @codai/axiom-mcp
|
|
2
2
|
|
|
3
|
-
MCP server (stdio) and CLI for AXIOM v2 — the transactional write gate for coding agents:
|
|
3
|
+
MCP server (stdio or Streamable HTTP) and CLI for AXIOM v2 — the transactional write gate for coding agents:
|
|
4
4
|
`Plan` → canonical `ManifestBundle` → set-level checks → hash-gated two-phase `apply` → journal.
|
|
5
5
|
`dist/cli.js` (thin entry) + `dist/cli-main.js` (lazy-loaded engines, SDK and zod bundled in); no runtime dependencies.
|
|
6
6
|
|
|
@@ -8,6 +8,7 @@ MCP server (stdio) and CLI for AXIOM v2 — the transactional write gate for cod
|
|
|
8
8
|
|
|
9
9
|
```sh
|
|
10
10
|
npx @codai/axiom-mcp mcp --root /abs/path/to/repo # stdio MCP server
|
|
11
|
+
npx @codai/axiom-mcp mcp --root /abs/path/to/repo --http 127.0.0.1:3411 # Streamable HTTP at /mcp
|
|
11
12
|
npx @codai/axiom-mcp --help # CLI verbs
|
|
12
13
|
```
|
|
13
14
|
|
|
@@ -28,6 +29,31 @@ root it is the default. There is **no** env-var or `cwd` fallback (`ERR_ROOT_REQ
|
|
|
28
29
|
}
|
|
29
30
|
```
|
|
30
31
|
|
|
32
|
+
### Streamable HTTP — `--http <host:port>`
|
|
33
|
+
|
|
34
|
+
```sh
|
|
35
|
+
axiom mcp --root /abs/repo --http 127.0.0.1:3411 # loopback, no token needed
|
|
36
|
+
axiom mcp --root /abs/repo --http 0 # random port; URL logged at info level
|
|
37
|
+
AXIOM_HTTP_TOKEN=$(openssl rand -hex 32) axiom mcp --root /abs/repo --http 0.0.0.0:3411 --log-level info
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- Endpoints: `POST /mcp` (an `initialize` opens a session and returns `Mcp-Session-Id`; every later
|
|
41
|
+
request must send it), `GET /mcp` (standalone SSE stream, one per session), `DELETE /mcp` (close the
|
|
42
|
+
session), `GET /health` → `{ ok, name, version }` (unauthenticated). Anything else is `404` JSON.
|
|
43
|
+
- **Loopback by default.** A non-loopback host **refuses to start** unless a bearer token is present in
|
|
44
|
+
the env var named by `--http-token-env <NAME>` (default `AXIOM_HTTP_TOKEN`, ≥ 16 chars). Clients send
|
|
45
|
+
`Authorization: Bearer <token>`; the compare is constant-time. A token is optional on loopback.
|
|
46
|
+
- DNS-rebinding protection is on for loopback binds (`Host` must be `<host>:<port>`, `localhost:<port>`
|
|
47
|
+
or `127.0.0.1:<port>`; otherwise `403`). Request bodies over 4 MiB are `413`.
|
|
48
|
+
- Sessions idle for 30 minutes are evicted; each session has its own server instance (roots and guard
|
|
49
|
+
settings are shared). The transport lives in `dist/http-lazy.js`, loaded only with `--http`, and is
|
|
50
|
+
plain `node:http` — no express/hono at runtime.
|
|
51
|
+
- VS Code: `{ "type": "http", "url": "http://127.0.0.1:3411/mcp" }`; add
|
|
52
|
+
`"headers": { "Authorization": "Bearer ${input:axiom-token}" }` when a token is set.
|
|
53
|
+
|
|
54
|
+
Conformance: `packages/conformance` runs `@modelcontextprotocol/conformance server` against this transport
|
|
55
|
+
in CI with an expected-failures baseline (`packages/conformance/baseline.yml`).
|
|
56
|
+
|
|
31
57
|
### Claude Desktop — `claude_desktop_config.json`
|
|
32
58
|
|
|
33
59
|
```json
|
|
@@ -44,7 +70,7 @@ root it is the default. There is **no** env-var or `cwd` fallback (`ERR_ROOT_REQ
|
|
|
44
70
|
|---|---|---|---|
|
|
45
71
|
| `axiom_plan_validate` | READ | `{ plan }` | `{ ok, planDigest?, errors[] }` |
|
|
46
72
|
| `axiom_plan_compile` | ACT | `{ plan, store?: inline\|cas, root? }` | `ManifestBundle` (writes only under `<root>/.axiom/` — CAS blobs and the stored manifest — when a root is given) |
|
|
47
|
-
| `axiom_manifest_verify` | READ | `{ bundle }` | `{ ok, manifestDigest, canonical, signed, missing[], errors[] }` |
|
|
73
|
+
| `axiom_manifest_verify` | READ | `{ bundle, root? }` | `{ ok, manifestDigest, canonical, signed, missing[], errors[], signatures?: { trustFile, keyids[], findings[], ok } }` — `signatures` only when `root` has `.axiom/trust/keys.json` |
|
|
48
74
|
| `axiom_check` | READ | `{ bundle, profile?, root? }` | `CheckReport` (`verdict: pass\|fail\|error`) |
|
|
49
75
|
| `axiom_apply_dry_run` | READ | `{ bundle, root, profile? }` | `ApplyResult{mode:"dry-run", diff}` |
|
|
50
76
|
| `axiom_apply` | SENSITIVE | `{ bundle, root, profile?, confirmDigest }` | `ApplyResult` |
|
|
@@ -52,6 +78,7 @@ root it is the default. There is **no** env-var or `cwd` fallback (`ERR_ROOT_REQ
|
|
|
52
78
|
| `axiom_manifest_diff` | READ | `{ a: bundle\|"sha256:…", b }` | `{ added[], removed[], changed[] }` |
|
|
53
79
|
| `axiom_axm_parse` | READ | `{ source }` (`.axm` text) | `{ plan?, diagnostics: [{ severity, code, message, range: { start: {line, column}, end } }] }` |
|
|
54
80
|
| `axiom_roots_list` | READ | `{}` | `{ roots: [{ path, writable, hasGit }] }` |
|
|
81
|
+
| `axiom_repo_snapshot` | READ | `{ root?, include?[], exclude?[], maxFiles? (20000, cap 50000), maxBytes? (64 MiB), respectGitignore? (true), withContentDigest? (true) }` | `RepoSnapshot { snapshotDigest, body: { files: [{ path, bytes, sha256?, mode, kind }], truncated, counts } }` — sorted, no timestamps/absolute paths; `.git/`, `.axiom/` always skipped; symlinks recorded, never followed (`docs/snapshot.md`) |
|
|
55
82
|
|
|
56
83
|
Every tool carries MCP `annotations` (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`)
|
|
57
84
|
and an `outputSchema`; `structuredContent` is the full result, `content[0].text` a small summary (digest,
|
|
@@ -62,7 +89,8 @@ codai's `packages/agent-core/spec/tools-v2.json` entry shape (`{ name, risk, des
|
|
|
62
89
|
see `docs/integration/codai.md`.
|
|
63
90
|
|
|
64
91
|
Resources: `axiom://manifest/{sha}`, `axiom://report/{sha}`, `axiom://applied/{sha}`,
|
|
65
|
-
`axiom://profile/{name}`, `axiom://schema/{Plan|Manifest|ManifestBundle|CheckReport|ApplyResult|Profile|Journal}
|
|
92
|
+
`axiom://profile/{name}`, `axiom://schema/{Plan|Manifest|ManifestBundle|CheckReport|ApplyResult|Profile|Journal|RepoSnapshot}`,
|
|
93
|
+
`axiom://emitters` (template emitters available to `axiom_plan_compile` — `web@2.0.0`, see `docs/emitters.md`).
|
|
66
94
|
|
|
67
95
|
## Trust model
|
|
68
96
|
|
|
@@ -79,23 +107,46 @@ Resources: `axiom://manifest/{sha}`, `axiom://report/{sha}`, `axiom://applied/{s
|
|
|
79
107
|
absolute ones must be listed exactly via `--guard-allowlist <abs>` (repeatable). Guards are spawned
|
|
80
108
|
with an args array (never a shell), a scrubbed environment, a wall-clock timeout, and must print
|
|
81
109
|
`GuardOutput` JSON — see `docs/checks.md`.
|
|
110
|
+
- **Signed manifests** (`docs/signing.md`): a root can pin Ed25519 public keys in
|
|
111
|
+
`.axiom/trust/keys.json`; a profile with `manifest.requireSigned` then refuses unsigned, tampered or
|
|
112
|
+
untrusted bundles, and with `antiRollback: true` refuses any `counter ≤ .axiom/trust/state.json#lastCounter`.
|
|
113
|
+
`axiom_apply` advances that state only on `status: "applied"`. Private keys never enter the server:
|
|
114
|
+
signing is `axiom sign` with `AXIOM_SIGNING_KEY` or `--key-file`.
|
|
82
115
|
|
|
83
116
|
## CLI
|
|
84
117
|
|
|
85
118
|
```
|
|
86
119
|
axiom mcp [--root <abs>]... [--allow-guards] [--guard-allowlist <abs>]... [--log-level warn]
|
|
87
|
-
|
|
88
|
-
axiom
|
|
120
|
+
[--http <host:port>] [--http-token-env AXIOM_HTTP_TOKEN]
|
|
121
|
+
axiom compile <plan.json> [-o out.json] [--store cas --root .] [--allow-net [--net-allow host[,host]]] [--allow-file]
|
|
122
|
+
axiom verify <bundle.json> [--root .] (--root: also verify signatures against .axiom/trust/keys.json)
|
|
89
123
|
axiom check <bundle.json> --root . [--profile p] [--json] [--allow-guards] [--guard-allowlist <abs>]...
|
|
90
124
|
axiom apply <bundle.json> --root . [--dry-run] [--profile p] [--confirm <digest>] [--allow-guards] [--guard-allowlist <abs>]...
|
|
91
125
|
axiom rollback <digest> --root .
|
|
126
|
+
axiom gc --root . [--dry-run] [--older-than 30d] [--keep all-manifests|journal] (CAS garbage collection; CLI only, no MCP tool)
|
|
92
127
|
axiom diff <a.json> <b.json>
|
|
93
|
-
axiom schema <Plan|Manifest|ManifestBundle|CheckReport|ApplyResult|Profile|Journal>
|
|
128
|
+
axiom schema <Plan|Manifest|ManifestBundle|CheckReport|ApplyResult|Profile|Journal|RepoSnapshot>
|
|
129
|
+
axiom emitters [--json]
|
|
130
|
+
axiom keygen [--out <dir>] [--name <label>] (ed25519; private key → <dir>/axiom-signing-<id>.key 0600, public entry → stdout)
|
|
131
|
+
axiom sign <bundle.json> [--key-file <path>] [-o out.json] (key from --key-file or $AXIOM_SIGNING_KEY)
|
|
132
|
+
axiom trust add <pub.json> --root . | remove <keyid> --root . | list --root .
|
|
94
133
|
axiom gate --stdin [--root <dir>] [--profile <file>] [--strict] [--log-level warn]
|
|
134
|
+
axiom migrate v1 <manifest.json> [-o plan.json] [--profile default] [--cas <root>] [--content <dir>] [--overwrite]
|
|
135
|
+
(v1 manifest → v2 Plan, lazy chunk; exit 1 = migrated with warnings — docs/migrate.md)
|
|
136
|
+
axiom snapshot --root . [-o snap.json] [--include <glob>]... [--exclude <glob>]... [--max-files n] [--max-bytes n] [--no-gitignore] [--no-digest]
|
|
137
|
+
axiom snapshot-diff <a.json> <b.json> (RepoSnapshot → { added, removed, changed })
|
|
95
138
|
```
|
|
96
139
|
|
|
97
140
|
Exit codes: `0` ok · `1` verdict fail / apply failed · `2` usage or error. Non-`mcp` verbs print JSON to stdout.
|
|
98
141
|
|
|
142
|
+
`ref` sources (`{ type: "ref", uri, digest }`) are offline by default: a digest already in
|
|
143
|
+
`<root>/.axiom/cas` resolves without network, anything else is `ERR_NET_DISABLED`. `--allow-net`
|
|
144
|
+
fetches `https:` only (no redirects, 30 s timeout, 32 MiB cap), optionally restricted to
|
|
145
|
+
`--net-allow` hosts (`*.example.com` wildcards), verifies the pinned digest and stores the blob in
|
|
146
|
+
the CAS — a mismatch stores nothing (`ERR_DIGEST_MISMATCH`). `apply` never fetches. The MCP
|
|
147
|
+
`axiom_plan_compile` tool has no network switch. See [docs/plan-format.md](../../docs/plan-format.md#ref-sources)
|
|
148
|
+
and [docs/cas.md](../../docs/cas.md).
|
|
149
|
+
|
|
99
150
|
## Hook mode — `axiom gate --stdin`
|
|
100
151
|
|
|
101
152
|
A PreToolUse hook for Claude Code, Copilot CLI and VS Code agent hooks. It reads **one** harness
|