Skip to content

v0.7.1

Latest

Choose a tag to compare

@cabroe cabroe released this 26 Jul 17:14

Added

  • Theme dev server — gains / /
    actions. runs

automad-mcp-server@0.7.1 dev
tsx src/index.ts as a detached background process, writes
, and returns the local URL (port
discovered in this order: explicit arg →
( / ) → the first marker in the
log, up to 20 s). sends SIGTERM, escalates to SIGKILL after 5 s,
and removes the record. reports the running state without
blocking. A second call for the same theme returns until
is called. Live-verified end-to-end against
: the dev server's PHP+esbuild pipeline starts and
returns the expected content.

  • Two new theme analyzer findings — (locale masks
    declared in but no file on disk) and
    (a page mask of the form whose
    snippet doesn't exist). Both are severity , ordered alongside the
    existing / checks.
  • KB pages split — (the bundled knowledge base) is now a
    thin re-exporter over 13 per-page modules in . The split is
    invisible at runtime but makes adding / auditing individual KB pages
    tractable. A drift test pins order and shape.
  • GitHub Pages landing page — is now a self-contained
    single-file landing page (no script, no remote stylesheet, no remote
    image; pinned by ). The tool table is generated from
    the capability registry via

automad-mcp-server@0.7.1 docs:sync
node --import tsx scripts/sync.ts

docs:sync: no change (tools table: already in sync; homepage table: already in sync; README.md: already in sync; CLAUDE.md: already in sync; index.html: already in sync), so it cannot drift from
the code. Counts (tool count, read/destructive, test count) are
fenced markers that regenerate alongside the README.

  • **
    === build ===

automad-mcp-server@0.7.1 build
tsc

=== lint ===

automad-mcp-server@0.7.1 lint
eslint src tests

=== test ===

automad-mcp-server@0.7.1 test
vitest run

RUN v2.1.9 /Users/cabroe/Projects/automad-mcp-server

✓ tests/unit/theme-schema.test.ts (10 tests) 25ms
✓ tests/unit/theme-analyzer.test.ts (18 tests) 146ms
✓ tests/unit/auth.test.ts (15 tests) 222ms
✓ tests/unit/capabilities.test.ts (11 tests) 14ms
✓ tests/unit/domains/theme.test.ts (16 tests) 578ms
✓ handleTheme > build runs install + build (skipped if no package.json scripts) 444ms
✓ tests/unit/write-guard.test.ts (14 tests) 50ms
✓ tests/unit/server.test.ts (9 tests) 61ms
✓ tests/unit/docs-drift.test.ts (9 tests) 9ms
✓ tests/unit/drift.test.ts (11 tests) 20ms
✓ tests/unit/domains/site.test.ts (11 tests) 11ms
✓ tests/unit/theme-scaffold.test.ts (5 tests) 49ms
✓ tests/unit/schemas.test.ts (17 tests) 15ms
✓ tests/unit/theme-fs.test.ts (10 tests) 45ms
✓ tests/unit/config.test.ts (12 tests) 8ms
↓ tests/e2e/live.test.ts (4 tests | 4 skipped)
✓ tests/unit/domains/media.test.ts (7 tests) 13ms
✓ tests/unit/domains/discover.test.ts (9 tests) 9ms
✓ tests/unit/capabilities-tools.test.ts (6 tests) 11ms
✓ tests/unit/theme-editor.test.ts (6 tests) 58ms
✓ tests/unit/resources.test.ts (5 tests) 33ms
✓ tests/unit/docs-kb.test.ts (10 tests) 20ms
✓ tests/unit/domains/config.test.ts (4 tests) 13ms
✓ tests/unit/client.test.ts (59 tests) 3043ms
✓ HttpClient (v2 /_api) > CSRF-mismatch loop after session timeout -> force re-auth then surface AUTH 504ms
✓ HttpClient (v2 /_api) > CSRF-mismatch loop with dead session AND dead re-auth -> AUTH (not 403) 501ms
✓ tests/unit/theme-dev.test.ts (29 tests) 3032ms
✓ startDev > writes dev.json with the spawned pid and reports running:true 1005ms
✓ startDev > runs npm install only when node_modules is missing 502ms
✓ startDev > returns port:null after portTimeoutMs when no marker appears 503ms
✓ startDev > clears a stale dev.json (dead pid) and proceeds 1002ms
✓ tests/unit/theme/generate.test.ts (8 tests) 10ms
✓ tests/unit/domains/shared.test.ts (3 tests) 18ms
✓ tests/unit/domains/docs.test.ts (6 tests) 9ms
✓ tests/unit/errors.test.ts (6 tests) 9ms
✓ tests/unit/theme/diff.test.ts (4 tests) 5ms
✓ tests/unit/theme/manager.test.ts (3 tests) 7ms
✓ tests/unit/logger.test.ts (2 tests) 7ms
✓ tests/unit/domains/pages.test.ts (33 tests) 4048ms
✓ handlePages (v2 /_api) > get retries on 404 (v2 commit-lag) and eventually surfaces NOT_FOUND 3012ms

Test Files 31 passed | 1 skipped (32)
Tests 368 passed | 4 skipped (372)
Start at 19:14:01
Duration 4.99s (transform 861ms, setup 0ms, collect 2.62s, tests 11.60s, environment 9ms, prepare 2.58s)

=== test:coverage (thresholds gate) ===

automad-mcp-server@0.7.1 test:coverage
vitest run --coverage

RUN v2.1.9 /Users/cabroe/Projects/automad-mcp-server
Coverage enabled with v8

✓ tests/unit/theme-schema.test.ts (10 tests) 28ms
✓ tests/unit/theme-analyzer.test.ts (18 tests) 137ms
✓ tests/unit/auth.test.ts (15 tests) 223ms
✓ tests/unit/capabilities.test.ts (11 tests) 16ms
✓ tests/unit/domains/theme.test.ts (16 tests) 579ms
✓ handleTheme > build runs install + build (skipped if no package.json scripts) 442ms
✓ tests/unit/write-guard.test.ts (14 tests) 50ms
✓ tests/unit/server.test.ts (9 tests) 71ms
✓ tests/unit/docs-drift.test.ts (9 tests) 11ms
✓ tests/unit/drift.test.ts (11 tests) 22ms
✓ tests/unit/domains/site.test.ts (11 tests) 19ms
✓ tests/unit/theme-scaffold.test.ts (5 tests) 46ms
✓ tests/unit/schemas.test.ts (17 tests) 26ms
✓ tests/unit/theme-fs.test.ts (10 tests) 44ms
✓ tests/unit/config.test.ts (12 tests) 9ms
↓ tests/e2e/live.test.ts (4 tests | 4 skipped)
✓ tests/unit/domains/media.test.ts (7 tests) 13ms
✓ tests/unit/domains/discover.test.ts (9 tests) 13ms
✓ tests/unit/capabilities-tools.test.ts (6 tests) 14ms
✓ tests/unit/theme-editor.test.ts (6 tests) 87ms
✓ tests/unit/resources.test.ts (5 tests) 42ms
✓ tests/unit/theme-dev.test.ts (29 tests) 3040ms
✓ startDev > writes dev.json with the spawned pid and reports running:true 1006ms
✓ startDev > runs npm install only when node_modules is missing 502ms
✓ startDev > returns port:null after portTimeoutMs when no marker appears 501ms
✓ startDev > clears a stale dev.json (dead pid) and proceeds 1002ms
✓ tests/unit/client.test.ts (59 tests) 3045ms
✓ HttpClient (v2 /_api) > CSRF-mismatch loop after session timeout -> force re-auth then surface AUTH 501ms
✓ HttpClient (v2 /_api) > CSRF-mismatch loop with dead session AND dead re-auth -> AUTH (not 403) 503ms
✓ tests/unit/docs-kb.test.ts (10 tests) 39ms
✓ tests/unit/domains/config.test.ts (4 tests) 11ms
✓ tests/unit/theme/generate.test.ts (8 tests) 9ms
✓ tests/unit/theme/diff.test.ts (4 tests) 6ms
✓ tests/unit/domains/shared.test.ts (3 tests) 12ms
✓ tests/unit/domains/docs.test.ts (6 tests) 12ms
✓ tests/unit/errors.test.ts (6 tests) 19ms
✓ tests/unit/theme/manager.test.ts (3 tests) 16ms
✓ tests/unit/domains/pages.test.ts (33 tests) 4046ms
✓ handlePages (v2 /_api) > get retries on 404 (v2 commit-lag) and eventually surfaces NOT_FOUND 3008ms
✓ tests/unit/logger.test.ts (2 tests) 5ms

Test Files 31 passed | 1 skipped (32)
Tests 368 passed | 4 skipped (372)
Start at 19:14:07
Duration 5.52s (transform 735ms, setup 0ms, collect 2.79s, tests 11.71s, environment 12ms, prepare 3.80s)

% Coverage report from v8
-------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------------|---------|----------|---------|---------|-------------------
All files | 90.98 | 85.51 | 95.15 | 90.98 |
src | 88.63 | 84.7 | 97.56 | 88.63 |
auth.ts | 91.17 | 76.81 | 100 | 91.17 | ...85,217,219-223
client.ts | 96.16 | 88.99 | 92.3 | 96.16 | ...22,194,367-372
config.ts | 92.38 | 83.33 | 100 | 92.38 | 76-80,125,127-128
errors.ts | 100 | 87.5 | 100 | 100 | 33
logger.ts | 80 | 0 | 100 | 80 | 9-12
prompts.ts | 69.6 | 57.14 | 100 | 69.6 | ...,81-93,128-137
schemas.ts | 100 | 100 | 100 | 100 |
server.ts | 65.07 | 72.72 | 100 | 65.07 | ...43-150,158-169
write-guard.ts | 100 | 100 | 100 | 100 |
src/capabilities | 96.25 | 88.05 | 100 | 96.25 |
registry.ts | 99.1 | 90 | 100 | 99.1 | 297-298
tools.ts | 87.32 | 82.35 | 100 | 87.32 | ...09,118,140-141
src/docs | 100 | 83.33 | 100 | 100 |
kb.ts | 100 | 83.33 | 100 | 100 | 58,81-87
src/docs/kb/pages | 100 | 100 | 100 | 100 |
blocks.ts | 100 | 100 | 100 | 100 |
...n-pitfalls.ts | 100 | 100 | 100 | 100 |
...structures.ts | 100 | 100 | 100 | 100 |
...-functions.ts | 100 | 100 | 100 | 100 |
...ng-started.ts | 100 | 100 | 100 | 100 |
headless-api.ts | 100 | 100 | 100 | 100 |
i18n.ts | 100 | 100 | 100 | 100 |
...resolution.ts | 100 | 100 | 100 | 100 |
index.ts | 100 | 100 | 100 | 100 |
navigation.ts | 100 | 100 | 100 | 100 |
runtime-lang.ts | 100 | 100 | 100 | 100 |
...nheritance.ts | 100 | 100 | 100 | 100 |
...ate-syntax.ts | 100 | 100 | 100 | 100 |
theme-json.ts | 100 | 100 | 100 | 100 |
src/domains | 95.48 | 78.92 | 100 | 95.48 |
config.ts | 88.88 | 60 | 100 | 88.88 | 30-31,33-34
discover.ts | 100 | 90.47 | 100 | 100 | 35,63
docs.ts | 100 | 88.88 | 100 | 100 | 22
media.ts | 95.91 | 85.71 | 100 | 95.91 | 22-23
pages.ts | 95.88 | 85.57 | 100 | 95.88 | ...40,242,295-296
shared.ts | 85.71 | 66.66 | 100 | 85.71 | 21-22,24-25
site.ts | 100 | 73.07 | 100 | 100 | ...37,50,60-65,84
theme.ts | 93.63 | 65.38 | 100 | 93.63 | ...07-109,111-113
src/resources | 94.33 | 84 | 100 | 94.33 |
themes.ts | 94.33 | 84 | 100 | 94.33 | 64-66
src/theme | 88.65 | 88.76 | 91.56 | 88.65 |
analyzer.ts | 93.36 | 92.73 | 100 | 93.36 | ...05-209,475-482
build.ts | 70.58 | 81.81 | 60 | 70.58 | ...99-104,115-120
dev.ts | 83.17 | 81.33 | 76.92 | 83.17 | ...51,269-272,285
diff.ts | 100 | 94.87 | 100 | 100 | 20,84
editor.ts | 96.59 | 89.47 | 100 | 96.59 | 71-72,87
fs.ts | 98.43 | 91.17 | 100 | 98.43 | 71-72
generate.ts | 100 | 100 | 100 | 100 |
manager.ts | 54.79 | 48 | 77.77 | 54.79 | ...90,194,209-215
scaffold.ts | 91.37 | 87.5 | 100 | 91.37 | 56-60
schema.ts | 92.91 | 92.85 | 100 | 92.91 | ...71-277,309-311
slug.ts | 80 | 80 | 100 | 80 | 7-8
-------------------|---------|----------|---------|---------|-------------------

=== docs:sync --check ===
docs:sync --check: OK (tools table: already in sync; homepage table: already in sync; README.md: already in sync; CLAUDE.md: already in sync; index.html: already in sync)

verify: all gates passed.** — single-command pre-PR gate: runs
→ → → (with the
thresholds enforcing 80% stmt / 70% branch) →
. Fails fast on the first broken step.

  • **** — end-to-end driver that spawns the built server
    over stdio, runs → (polls until running) →
    (HTTP 2xx/3xx) → . Lives in

automad-mcp-server@0.7.1 smoke
node --import tsx scripts/smoke.ts; no
live Automad instance required ( + a starter kit path
is enough).

  • **** — Conventional-Commits validator. Lifecycle scripts included in automad-mcp-server@0.7.1:
    start
    node dist/index.js
    test
    vitest run
    prepublishOnly
    npm run build && npm test
    available via npm run:
    build
    tsc
    dev
    tsx src/index.ts
    test:watch
    vitest
    test:coverage
    vitest run --coverage
    test:e2e
    vitest run tests/e2e
    lint
    eslint src tests
    format
    prettier --write src tests
    docs:sync
    node --import tsx scripts/sync.ts
    docs:sync:tests
    node --import tsx scripts/sync.ts --tests
    docs:sync:all
    node --import tsx scripts/docs-sync-all.ts
    verify
    node --import tsx scripts/verify.ts
    smoke
    node --import tsx scripts/smoke.ts
    commit:check
    node --import tsx scripts/commit.ts --check
    release:patch
    node --import tsx scripts/release.ts patch --tag
    release:minor
    node --import tsx scripts/release.ts minor --tag
    release:major
    node --import tsx scripts/release.ts major --tag
    release:full:patch
    node --import tsx scripts/release.ts patch --release
    release:full:minor
    node --import tsx scripts/release.ts minor --release
    release:full:major
    node --import tsx scripts/release.ts major --release validates HEAD (for CI / pre-push); validates + commits. Type- and scope-allow-lists are a single
    source of truth.
  • **
    === docs:sync ===

automad-mcp-server@0.7.1 docs:sync
node --import tsx scripts/sync.ts

docs:sync: no change (tools table: already in sync; homepage table: already in sync; README.md: already in sync; CLAUDE.md: already in sync; index.html: already in sync)

=== docs:sync:tests ===

automad-mcp-server@0.7.1 docs:sync:tests
node --import tsx scripts/sync.ts --tests

docs:sync: updated (tools table: already in sync; homepage table: already in sync; README.md: already in sync; CLAUDE.md: updated (TESTCOUNT); index.html: updated (TESTCOUNT))

docs:sync:all: done.** — one-shot: runs (static
markers) and (TESTCOUNT via vitest) back-to-back.
Available as

automad-mcp-server@0.7.1 docs:sync:all
node --import tsx scripts/docs-sync-all.ts

=== docs:sync ===

automad-mcp-server@0.7.1 docs:sync
node --import tsx scripts/sync.ts

docs:sync: no change (tools table: already in sync; homepage table: already in sync; README.md: already in sync; CLAUDE.md: already in sync; index.html: already in sync)

=== docs:sync:tests ===

automad-mcp-server@0.7.1 docs:sync:tests
node --import tsx scripts/sync.ts --tests

docs:sync: no change (tools table: already in sync; homepage table: already in sync; README.md: already in sync; CLAUDE.md: already in sync; index.html: already in sync)

docs:sync:all: done..

  • branch=main clean=false kind=patch apply=true tag=false push=false release=false
    bump: 0.7.1 -> 0.7.2 / flags
    — after tagging,
    runs ; additionally runs
    https://github.com/cabroe/automad-mcp-server/releases/tag/vX.Y.Z with the matching CHANGELOG section as the
    release body (extracted via a new export).
    Convenience scripts

automad-mcp-server@0.7.2 release:full:patch
node --import tsx scripts/release.ts patch --release release:full:minor release:full:major

branch=main clean=false kind=patch apply=true tag=true push=true release=true
https://github.com/cabroe/automad-mcp-server/releases/tag/v0.7.3
bump: 0.7.2 -> 0.7.3
tagged: v0.7.3
pushed: ok
released: ok
notes file: /var/folders/zl/kyj47ppj4gs9dz5zbx4kfkk00000gn/T/release-notes-64ZjGw/notes.md wrap
all three steps.

Changed

  • ** now accepts a field as
    (no )** — v2 splits on and appends , so
    resolves to . Lets a page
    bind to a theme that isn't the site default (the site default itself
    is not exposed via the API; it is set in the dashboard). Documented
    in JSDoc and in the README.
  • ** now verifies the starter-kit layout** before copying
    (canonical layout: , , ,
    , ). A stale or wrong starter-kit
    directory now returns with a concrete missing-list
    instead of silently producing a broken theme.
  • Knowledge-base size unchanged at runtime — splitting the KB into
    per-page modules does not affect the embedded content; the public
    surface (, ) is identical.
  • ThemeFs abstraction — interface gained
    and with a
    1 MiB cap and 256 KiB tail retention in the
    implementation. The dev server uses these exclusively; no direct
    calls in new code.
  • Documented the field's convention
    in JSDoc and the README. A new README section ("Bind a
    page to a specific theme/template") walks through it with a worked
    example.
  • README + GitHub Pages homepage — both now describe the theme dev
    server, the / / scripts, the
    flow, and the page-template convention. The
    homepage's "Theme tooling" card mentions the dev server; the tools
    table shows / / for .

Fixed

  • Two analyzer findings double-fired on generated output — both
    and previously reported
    against / directories that ship with the starter
    kit. The scan is now scoped to and for the
    relevant lookups and skips generated paths, so live reports contain
    only findings the user can act on.
  • ** had a brittle fixture** — the test
    referenced a field on the analyzer's output that the
    code didn't actually return. Added the missing field to the
    fixture literal so the test exercises the production
    code path.
  • ** was dead code** — the file existed for an old
    page-format reader, but nothing in the live HTTP path uses it. The
    tests that referenced it still passed because they imported the
    module directly. Removed the file; tests now use the real
    v2 response path. No live consumer was affected.
  • ** was renamed to ** to
    match the spec/plan wording and to avoid colliding with any future
    "headless" UI module. Pure rename; no behavior change.
  • ** extraction off-by-one** —
    originally searched the slice for the next header before
    stripping the current one, so was always 0 and the function
    returned a single newline. The function now strips the current
    header first; returns the full section block up to the next
    (or end of file).