Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

MCP Server

NotarAI includes a built-in Model Context Protocol (MCP) server that serves pre-filtered diffs and change data to the reconciliation engine. This keeps context usage proportional to what actually changed rather than the full repository.

Setup

notarai init writes an .mcp.json file to the project root that registers the MCP server:

{
  "mcpServers": {
    "notarai": {
      "type": "stdio",
      "command": "notarai",
      "args": ["mcp"]
    }
  }
}

Claude Code reads this file and starts the server automatically. No manual configuration needed.

Protocol

  • Transport: stdio (stdin/stdout)
  • Format: JSON-RPC 2.0, one message per line
  • Execution: synchronous (no async runtime)
  • Protocol version: 2024-11-05

Initialize response

The initialize response includes standard MCP fields (protocolVersion, capabilities, serverInfo, tools). When the local schema (.notarai/notarai.spec.json) is out of date relative to the bundled schema, the response includes an additional schemaNote field:

{
  "schemaNote": "Schema is out of date (local: .../0.5/..., bundled: .../0.6/...). Run `notarai init` to update."
}

This surfaces schema staleness to Claude at session start without requiring a separate check.

When the project’s NotarAI configs are behind the running CLI version (detected via the version in .notarai/README.md), the response includes an additional projectNote field:

{
  "projectNote": "hint: project was initialized with notarai v0.3.1. Run `notarai init` to update project configs to v0.3.2."
}

This surfaces project config staleness to Claude at session start so reconciliation uses up-to-date slash commands and schema.

Tools

list_affected_specs

Identify which specs govern files that changed on the current branch relative to a base branch.

Parameters:

ParameterTypeRequiredDescription
base_branchstringYesBranch to diff against (e.g., "main")

Returns:

{
  "changed_files": ["src/auth.rs", "src/main.rs"],
  "affected_specs": [
    {
      "spec_path": ".notarai/cli.spec.yaml",
      "behaviors": [],
      "constraints": [],
      "invariants": []
    }
  ]
}

Each affected spec includes its behaviors, constraints, and invariants so the reconciliation engine has the context to evaluate drift without additional file reads.


get_spec_diff

Get the git diff filtered to files governed by a specific spec. Uses the hash cache to skip files that haven’t changed since the last reconciliation.

Parameters:

ParameterTypeRequiredDescription
spec_pathstringYesRelative path to the spec file
base_branchstringYesBranch to diff against
exclude_patternsstring[]NoGlob patterns to exclude via git :(exclude) pathspecs (e.g., ["Cargo.lock", "*.lock"])
bypass_cachebooleanNoIf true, diff all governed files regardless of cache state. Defaults to false

Returns:

{
  "diff": "unified diff of non-spec governed files...",
  "files": ["src/auth.rs"],
  "skipped": ["src/utils.rs"],
  "excluded": ["Cargo.lock"],
  "spec_changes": [
    {
      "path": ".notarai/cli.spec.yaml",
      "content": "full file content..."
    }
  ],
  "system_spec": {
    "path": ".notarai/system.spec.yaml",
    "content": "full file content..."
  },
  "binary_changes": ["assets/logo.png", "slides/deck.pptx"],
  "file_categories": {
    "src/auth.rs": "code",
    "docs/auth.md": "docs",
    "assets/logo.png": "assets"
  }
}
FieldDescription
diffUnified diff output for non-spec, non-binary artifact files only
filesNon-spec files included in the diff (includes binary files by path, but their content is in binary_changes)
skippedNon-spec files whose BLAKE3 hash matched the cache (already reconciled)
excludedPatterns passed via exclude_patterns
spec_changesArray of {path, content} for each governed .notarai/**/*.spec.yaml file that changed
system_specThe system spec (the spec with a subsystems key) – included whenever spec_changes is non-empty; null otherwise
binary_changesFile paths of binary files (images, PPTX, PDF, etc.) whose content cannot be usefully diffed
file_categoriesObject mapping each changed file path to its artifact category from the spec (e.g., "code", "docs", "assets")

Why full content for spec files?

Spec files express intent, not implementation. The reconciliation engine needs the complete spec to evaluate drift – diff hunks showing only changed lines lack the context to determine whether behavior is still satisfied. Returning full content also avoids the ambiguity of partial context when the spec is the source of truth.

Spec deduplication: If the system spec itself changed, it appears in spec_changes with full content and system_spec contains only {path} (a reference) to avoid duplicating the content.

Cache behavior:

  • Files whose on-disk BLAKE3 hash matches the cached hash are listed in skipped (for artifact files) or omitted from spec_changes (for spec files).
  • A cold or absent cache causes all governed files to be included. This is a safe fallback that ensures nothing is missed.
  • bypass_cache: true forces a full diff without destroying the cache (useful for re-checking everything).

get_changed_artifacts

Get artifact files governed by a spec that have changed since the last cache update. Useful for identifying which docs or other artifacts need review during reconciliation.

Parameters:

ParameterTypeRequiredDescription
spec_pathstringYesRelative path to the spec file
artifact_typestringNoFilter by artifact type (e.g., "docs", "code", "configs")

Returns:

{
  "changed_artifacts": ["docs/auth.md", "docs/api-reference.md"]
}

Only files whose content differs from the cached hash are included. If no artifact_type is specified, all artifact types are checked.


mark_reconciled

Update the hash cache after reconciliation is complete. Call this at the end of a reconciliation pass so that subsequent runs skip files that haven’t changed.

Parameters:

ParameterTypeRequiredDescription
filesstring[]YesRelative file paths to cache

Returns:

{
  "updated": 5
}

Files are hashed with BLAKE3 and stored with their relative paths as cache keys. Non-existent files are silently skipped.


clear_cache

Delete the reconciliation cache database, forcing the next get_spec_diff call to diff all governed files.

Parameters: None.

Returns:

{
  "cleared": true
}

Returns true if the database was deleted, false if it didn’t exist.


snapshot_state

Persist the current reconciliation cache as a state snapshot at .notarai/reconciliation_state.json. Call this at the end of a successful reconciliation pass.

Parameters: None.

Returns:

{
  "state_path": ".notarai/reconciliation_state.json",
  "files": 42,
  "specs": 5,
  "git_hash": "a1b2c3d..."
}
FieldDescription
state_pathAbsolute path where the state file was written
filesNumber of non-spec file fingerprints stored
specsNumber of spec fingerprints stored
git_hashgit HEAD at snapshot time (empty string if not in a repo)

The state file is pretty-printed JSON and safe to commit. It gives collaborators a baseline so subsequent get_spec_diff calls can skip files that haven’t changed since the last reconciliation. Use notarai state show / notarai state reset to inspect or clear state from the CLI.

Cache semantics

The cache is a SQLite database at .notarai/.cache/notarai.db with a single table:

file_cache(path TEXT PRIMARY KEY, blake3_hash TEXT, updated_at INTEGER)

Key details:

  • Hash algorithm: BLAKE3 – fast cryptographic hash.
  • Path format: MCP tools use relative paths as cache keys. Seed the MCP cache via mark_reconciled, not notarai cache update.
  • Cold cache: When the cache is empty or absent, get_spec_diff diffs all governed files. This is the safe default.
  • Cache location: .notarai/.cache/ is gitignored by notarai init so the cache is never committed.

Error codes

CodeMeaning
-32700Parse error (malformed JSON)
-32601Method not found
-32602Invalid params (missing required parameter)
-32603Internal error (git failure, file I/O, cache unavailable)