MotionSpec — web animation accessibility MCP

io.github.MasterPlayspotsv1.2.9更新於 Oct 10, 2026

Web animation accessibility MCP: GSAP, static CSS checks, prefers-reduced-motion, WCAG 2.2.2/2.3.3.

已驗證Streamable HTTP可網頁執行Developer ToolsSecurity & MonitoringMedia & Design

概覽

AI 產生的概覽

讓助理撰寫並驗證網頁動畫規格、編譯成 GSAP 與 CSS,並靜態稽核頁面 CSS 的動效無障礙問題。

功能
MotionSpec 提供五個工具:motion_catalog 列出已核准的動畫原語與撰寫規則,motion_validate 以失敗即拒絕的信任邊界驗證 JSON 規格,motion_compile 將有效規格確定性地編譯為 GSAP 加 CSS,motion_audit 靜態掃描指定 URL 的 HTML 與連結樣式表,找出缺少的 prefers-reduced-motion 防護與缺少的暫停路徑,motion_stats 彙總遙測資料。編譯器預設會產生減少動效處理與循環暫停控制項。稽核僅為靜態 CSS 掃描。
適用情境
適合程式助理在建置或審查網頁 UI 動畫時使用,希望產生的動效程式碼已包含減少動效防護與暫停控制項;也適合對頁面已載入的 CSS 做可重複的靜態檢查,找出 WCAG 2.2.2 與 2.3.3 相關的動效候選問題,並可作為 CI 中比對基準的迴歸閘門。
執行需求
可透過 npx motionspec 以 stdio 在本機執行,不需要 API 金鑰;也可使用託管的 streamable-http 端點。託管端點不需金鑰即可使用 motion_catalog 與 motion_validate,託管的 compile、audit 與 stats 需要金鑰。CLI 流程可透過 MOTION_API_KEY 或 OPENROUTER_API_KEY 使用真實模型,並可選用 MOTION_MODEL 與 MOTION_BASE_URL。npm 套件需要 Node.js。
安裝前請注意
motion_audit 會抓取你提供的 URL,請只掃描你有權掃描的頁面。稽核結果只是待複核的候選問題,並非合規結論;執行階段 JavaScript 動畫、閃爍、影片與 Canvas 不在範圍內,掃描乾淨也不等於通過無障礙評估。編譯器可被設定為關閉減少動效或暫停控制項,此時會輸出警告代碼。託管付費層級需要金鑰,本機 stdio 使用則不需要。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 MotionSpec — web animation accessibility MCP,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "motionspec": {
      "type": "http",
      "url": "https://api.motionspec.dev/mcp"
    }
  }
}

README

MotionSpec — web animation accessibility MCP server

[MotionSpec logo]

[npm] [node] [license] [tests] [coverage] [supply chain] [MCP Registry] [smithery badge]

MotionSpec is an MCP server and CLI for web animation accessibility. It helps AI coding agents and frontend developers compile validated animation specs to deterministic GSAP + CSS and find motion-accessibility candidates in a page's loaded CSS: missing prefers-reduced-motion guards and missing pause paths for continuous animation.

The MIT compiler includes reduced-motion handling and loop pause controls by default. Its static audit supports review of WCAG 2.2.2 (Pause, Stop, Hide — Level A) and WCAG 2.3.3 (Animation from Interactions — Level AAA). Findings need contextual review; a clean scan is not a full accessibility or WCAG-conformance assessment. Runtime JavaScript animation, flashing, video and Canvas are outside the audit's scope.

  • Create web animation: choose a catalog primitive, validate a JSON spec, then compile vanilla-GSAP JavaScript and CSS. The internal WAAPI lowering is not a public build target.
  • Check CSS motion: audit a URL for reduced-motion and pause-path candidates, then review the reported selectors and suggested fixes.
  • Prevent regressions: use the CI example to compare findings against an explicitly accepted baseline.

Local stdio MCP exposes all five tools without an API key (npx -y motionspec). The hosted endpoint at https://api.motionspec.dev/mcp provides keyless motion_catalog and motion_validate; hosted compile, audit and stats require a key. See the installation guide and motion accessibility guide. Docs and product: https://motionspec.dev/docs.

The thesis: capability lives in the catalog, not the model. A bigger model can write more elaborate specs, but it can never emit a primitive, parameter, or selector the Trust Boundary hasn't approved. The compiler trusts only what passes.

request ──> Routing (small model, Stage A) ──> MotionSpec (JSON)                 │ cache · 1 repair-retry · escalation     │                 ▼                                          ▼            telemetry                          TRUST BOUNDARY (fail-closed)                                                            │                                              ┌─────────────┴─────────────┐                                              ▼                           ▼                                   Compiler (no model, Stage B)   WAAPI lowering (internal — no CLI/MCP path yet)                                              │                           │                                   out/*.motion.js + .css       Element.animate / IO / @keyframes

Not to be confused with

Not to be confused with: the Android Material Components MotionSpec class, the iOS material-motion MotionSpec, Motion.dev / Framer Motion, the usemotion.com calendar app, the Motion Specialties mobility brand, or text-to-video generators (Runway/Sora/Kling/Viggle). MotionSpec checks the UI animation inside web apps — it does not generate video.

60-second start

bash
npx motionspec                               # stdio MCP server — no install neededclaude mcp add motionspec -- npx motionspec  # register in Claude Code / any MCP host
npm install -g motionspec                    # or take the CLI:motion compile spec.json                     # deterministic build → ./out in your cwd

The host LLM authors the spec; the Trust Boundary stays enforced either way. Listed on the MCP Registry as io.github.MasterPlayspots/motionspec. A hosted MCP endpoint is live: keyless motion_catalog + motion_validate at https://api.motionspec.dev/mcp (streamable-http; keyed tiers cover compile/audit/stats) — setup: https://motionspec.dev/docs.

Claude Code plugin

This repo is also a Claude Code plugin: it bundles the MCP server (npx motionspec, all five tools, local, keyless) with two skills — /motionspec:motion (the author→validate→compile workflow) and /motionspec:audit <url> (motion-accessibility check, WCAG 2.2.2/2.3.3). Try it directly from a clone with claude --plugin-dir ., or install it from the community marketplace once listed:

bash
/plugin marketplace add anthropics/claude-plugins-community/plugin install motionspec@claude-community

Status

Versionv1.2.9 · schema frozen at spec v1 (ADR-0001, signed)
Publishednpm motionspec (105 kB packed, 67 files, nothing dev-only ships) · MCP Registry
Tests360 green — injection attacks, 6000-spec fuzz, golden determinism, schema parity, pause-controls, motion-a11y audit · CI on Node 18/20/22 + x86 Playwright e2e
Catalog40 primitives, every one device-verified, reduced-motion-fallback mandatory; the 18 continuous loops also carry a WCAG-2.2.2 pause path
Supply chain2 runtime deps (MCP SDK, zod — both pinned) · 0 vulnerabilities · CycloneDX SBOM regenerated and checked in CI · all permissive licenses · CI actions SHA-pinned
Coverage97.23% lines / 95.17% functions / 80.82% branches of src/ (npm run coverage, 2026-10-08; CI gate 90/90/75)
Last audit2026-07-03 — 17/17 integration handshakes evidenced, infra 8.1/10, security: 0 critical, full-git-history secret scan clean
First clientCHS Computer — live on Vercel
Hosted MCPlive — keyless motion_catalog/motion_validate at api.motionspec.dev/mcp · keyed tier: Cloudflare Worker, per-key gated (hashed keys in KV) · two-stage rate limiting (pre-auth per IP + per key, burst-verified) · per-minute cron canary + external heartbeat (synthetic fault → alert in <5 min, proven on real infra) · Analytics Engine operations telemetry (request bodies, specs and error text are not stored) · gated /dashboard

Schema v1 is frozen: specVersion "1.0" is the stable public contract; "0.1" is deprecated and accepted until v1.2 (a tripwire test enforces the revisit). The [MS-XXX] error-code registry is public API — codes are never reused or redefined.

What the compiler guarantees

  1. Allow-list — a primitive not in the catalog never reaches the compiler.
  2. Injection-proof — ids, selectors, string params and triggers are charset-validated; every interpolation is a JS literal (JSON.stringify) or a CSS-screened raw value through one shared safety gate (safety.js). Malicious model output is rejected fail-closed — tested and fuzzed over 6000 random specs.
  3. a11y by construction (motion) — safe defaults, enforced gates, and proof per build. respectReducedMotion is default-on at the compiler level (fail-safe): omitting it still yields a prefers-reduced-motion guard. Opting out is possible but emits MS-GLOBALS-RRM-OFF; a prompt-side instruction alone can never disable the guard.
  4. Pause/Stop for loops (WCAG 2.2.2) — every continuous loop primitive is tagged a11y.persistent, and the compiler emits a pause path by construction: an animation-play-state: paused rule keyed on html[data-ms-paused] (outside the reduced-motion guard, so it is always live) plus, under pauseControls: "auto" (the fail-safe default), one accessible pause/stop toggle (type="button", aria-pressed in sync, ≥24 px target, visible focus ring, not rendered under reduced motion). pauseControls: "api" keeps the CSS contract and leaves the control to the integrator; "off" opts out but emits MS-GLOBALS-PAUSE-OFF when a persistent motion is present. The promote-gate refuses any infinite/repeat:-1 primitive that is not a11y.persistent. A spec with no loops adds zero extra bytes.
  5. Determinism — same spec ⇒ byte-identical code (golden-file tests for the GSAP output and for the internal WAAPI lowering).
  6. Versioned — schema frozen v1; catalog SemVer enforced by a diff-gate (a tightened bound shipped as a "patch" fails CI); specs may pin catalogVersion for reproducibility (MS-CATALOG-PIN-MISMATCH fail-closed).
  7. Observability — every request logs model | model-repaired | cache-hit | escalate-* (local: JSONL sink · hosted: Cloudflare Analytics Engine, PII-scrubbed). Escalation clusters are the growth signal for new primitives.

One build target, one internal lowering

What you can get out of the compiler today, through the CLI or the MCP tools, is exactly one target:

  • vanilla-gsap — GSAP + ScrollTrigger. meta.target accepts nothing else (schema frozen at v1).

A second lowering exists in the codebase and is kept green by the test suite, but it is not reachable through any interface:

  • WAAPI/CSS lowering (src/compiler/lower-waapi.js) — zero-GSAP output on Element.animate, IntersectionObserver, and @keyframes/position: sticky. Full catalog coverage, byte-identical golden per primitive, same accessibility guard, same CSS safety gate. This is the framework-decoupling hedge: the IR outlives any animation library. Internal — referenced only by the tests and bin/promote-gate.js; there is no CLI flag, no MCP tool and no schema target for it (ADR-0001 freezes meta.target to vanilla-gsap; engine wiring is out of scope, ADR-0002). Do not plan a build on it until a release note says otherwise.

The catalog grows itself — humans keep the taste

The Catalog Forge (CI workflow, manual dispatch) picks the top telemetry-ranked gap, generates one candidate primitive, drives it through a multi-stage gauntlet — meta-schema, mandatory reduced-motion fallback, performance budget, output determinism (entropy tokens like Math.random/Date.now fail the gate), catalog-SemVer legality, golden creation — and opens a PR. It cannot merge, publish, or deploy: structurally (workflow permissions carry no packages/id-token, PR-only) and by regression test (forge-workflow-guard fails CI if anyone smuggles a publish step in). Gate 1 is always a human taste review.

MCP server

ToolContract
motion_catalogprimitives + authoring rules + catalog version (16-hex pin)
motion_validatefail-closed Trust Boundary; precise [MS-XXX] errors; surfaces deprecations
motion_compiledeterministic spec → code; never emits on a failed validation
motion_auditstatic motion-a11y check of a live URL (read-only, open-world)
motion_statstelemetry summary (escalations = catalog growth signal)

Input is size-capped (MS-INPUT-TOO-LARGE, 64 KB). The stdio server exposes one tool factory as the single source of truth, contract-tested in test/mcp.test.mjs. A hosted MCP endpoint is live: keyless motion_catalog + motion_validate at https://api.motionspec.dev/mcp; keyed tiers cover compile/audit/stats.

Motion-a11y checker

motion audit <url> (CLI, --json for the machine payload) and the motion_audit MCP tool run a static scan of a page's HTML and linked stylesheets — no headless browser, no new dependency. It reports four motion problems: CSS animation/transition without an effective prefers-reduced-motion guard (WCAG 2.3.3 — the guard must win the cascade), animated properties other than transform/opacity, infinite animations with no pause path (animation-play-state/data-*), and <marquee>/autoplay motion over 5 s (WCAG 2.2.2). Colour/opacity-only transitions are not motion under 2.3.3 and are not reported; loading indicators (spinners, skeletons) are listed as review items with no score impact. Each finding carries a selector, the WCAG reference, and a copy-paste fix. The CLI, the motion_audit tool and the free check at motionspec.dev/motion-check run the same engine with the same limits (12 stylesheets, 2 MB, 8 s) and the same score. It is honest about its limits: runtime motion (WAAPI/GSAP/JS, WebGL libraries) is reported as not audited (V2) rather than silently passed, and a page with no CSS motion is status: "not-measurable" with score: null instead of a perfect score. The legacy reduced-motion-safe badge string is returned only for a measurable page with zero findings and no runtime motion library; it means only that these checks found no candidates in the loaded CSS, not that the page or its runtime motion is certified.

Use in CI

motion audit --json is stable enough to gate a pull request. examples/ci/motion-audit.yml is a copy-and-adapt GitHub Actions workflow that builds your site, serves the build directory on localhost, audits the paths you list with npx -y -p [email protected] motion audit <url> --json (local, MIT, no key, no hosted call), and compares each page with a checked-in baseline .motionspec/baseline.json.

The gate fails when a page got worse — the same rule MotionSpec's weekly re-scan uses: the score fell, or the number of Level-A findings (WCAG 2.2.2 Pause, Stop, Hide) rose. Scores are compared only when both runs are measurable and use the same scoring version; a baseline written by 1.2.7 or earlier (scoring v1) needs one re-baseline. A page without a baseline entry never fails; that run is the baseline. Re-baselining is a deliberate manual run (workflow_dispatch with update_baseline: true) that uploads the new file as an artifact for you to commit — the workflow never commits on its own. Fixed findings are listed as - fixed: lines, new ones as + new finding:.

The machine payload is { ok, url, status, score, scoring, scoring_doc, summary, badge, findings, groups, disclosures, coverage }; read status before using score (it is null when the page is not measurable). Note that audit takes a URL, not a directory — hence the local server step. And the scope caveat travels with it: this is a static CSS scan (no inline style="", @import, CSS-in-JS, external JS bundles, video/GIF/Canvas, or flashing checks); a green gate means "no regression in the loaded CSS", not "accessible".

Specification & conformance

MotionSpec is a governed format, not just a tool. The normative spec is SPEC.md (versioned 1.0, RFC-2119 MUST/SHOULD/MAY over the JSON Schema, with a documented ADR-based change process). CONFORMANCE.md defines the five checks (schema, diagnostics, output, determinism, accessibility) an implementation passes to call itself MotionSpec 1.0 compatible, run against the published test/golden corpus. Multiple implementations passing the same corpus is what makes it a standard.

Standards mapping

MotionSpec checks a limited set of motion signals. These are candidates for review, not a conformance verdict or a substitute for testing the delivered interface.

CriterionLevelWhat to review with MotionSpec
WCAG 2.2.2 — Pause, Stop, HideAFor non-essential moving, blinking or scrolling content that starts automatically, lasts more than five seconds and appears alongside other content, check for a usable pause, stop or hide mechanism. The compiler supplies loop pause paths by default; the static audit looks for missing-path candidates. Auto-updating content has separate requirements without the five-second threshold.
WCAG 2.3.3 — Animation from InteractionsAAANon-essential motion triggered by interaction must be disableable. Reduced-motion handling is one implementation approach. A missing media query alone does not establish failure, and finding one does not establish success.

Animating only transform and opacity is a performance recommendation, not by itself a WCAG success criterion. The audit does not measure flashing (2.3.1), runtime GSAP/WAAPI, video, Canvas, or the usability of a pause control. It does not establish compliance with EN 301 549, Section 508, EAA, BFSG, or any other legal framework.

Quickstart (from a clone)

bash
npm ci                                      # install (0 runtime deps beyond MCP SDK + zod)npm test                                    # 360 tests: validator, goldens, router, fuzz, paritynode bin/motion.js catalog                  # primitives + catalog versionnode bin/motion.js compile examples/hero.motionspec.jsonnode bin/motion.js pipeline "Hero headline fades in, cards staggered" --mocknode bin/motion.js stats                    # telemetry (model / repaired / cache-hit / escalate)

Live model instead of --mock: set MOTION_API_KEY (or OPENROUTER_API_KEY); optional MOTION_MODEL (default anthropic/claude-haiku-4.5) and MOTION_BASE_URL (any OpenAI-compatible endpoint). See .env.example.

Gates (run these — they are the contract)

bash
npm test                   # full suite, fail-closed trust boundary + golden determinismnpm run coverage           # FAILS under 90/90/75 (lines/functions/branches)npm run catalog-lock:check # ADR-0001 D2: a tightened bound shipped as a "patch" fails herenpm run sbom && npm run sbom:check && node bin/license-check.jsnpm run e2e                # real-browser Playwright (CI x86 runner)

Releases run the whole chain plus a canonical-clone guard and finish with a registry truth check — a version is "live" when the npm dist-tag says so, not when a local run went green.

Security

Defense in depth on the hosted path: constant-time admin-secret comparison (no timing side channel on position or length) · customer keys stored hashed (SHA-256) in KV, fail-closed on any lookup error · pre-auth per-IP rate limiting closes the key-enumeration gap before auth work starts, per-key limiting after · throttled abuse alerts with zero PII · telemetry scrubbed before storage · strict CSP/X-Frame-Options/nosniff on the only ungated page (a data-free dashboard shell). Full posture incl. reporting: SECURITY.md. Last audit (2026-07-03): no critical findings, no secret ever committed across 197 commits of history.

Layout

schema/            MotionSpec JSON schema (static contract, parity-tested against the validator)primitives/        catalog: 40 verified primitives (safe templates)catalog.lock.json  released catalog baseline (SemVer diff-gate)src/compiler/      validate.js (Trust Boundary) · compile.js (GSAP) · lower-waapi.js (WAAPI/CSS)                   safety.js (one shared CSS gate) · keyword-map.js · catalog.js · catalog-semver.jssrc/router/        prompt.js · clients.js (openai-compat + mock) · route.js · cache.js · telemetrysrc/mcp/           server.mjs (stdio) · register-tools.js (shared tool factory)src/forge/         generate.js · prioritize.js — the gauntlet-verified catalog forgesrc/discover/      gap analysis: request intents ↔ catalog coveragesrc/demo/          device-verification demo pages (`?rm=1` simulates reduced motion)bin/               motion.js (CLI) · promote-gate.js — dev/CI gate scripts stay repo-onlytest/              360 tests incl. injection, fuzz, goldens (GSAP + internal WAAPI lowering), parity; test/e2e (Playwright)docs/              ADR records (docs/adr/) and per-primitive reference (docs/primitives/)

Docs

Contributing

CONTRIBUTING.md covers setup, the gate-driven PR checklist, commit conventions, golden-file regeneration, and a short architecture tour. Issue templates live under .github/ISSUE_TEMPLATE/.

License

MIT.

來源:README.md,提交 8020969

工具

0
工具後設資料尚未被收錄。

版本歷史

3
  1. v1.2.9最新Oct 9, 2026
  2. v1.2.8Oct 9, 2026
  3. v1.2.7Sep 16, 2026