Skip to main content
Glama

claude-faf-mcp

npm version Smithery FAF ✪ 100% IANA: vnd.faf+yamlIANA: vnd.fafm+yaml DOI: Context paperDOI: Memory paper

Home: faf.one/mcp Site: claude.faf.one

Persistent Project Context with Memory, looped for you. One-click setup. 30 seconds. 🐘 Nelly Never Forgets.

MCP Registry: one.faf/claude-faf-mcp CI NPM Downloads License: MIT Chat to FAFA live

FAF defines. MD instructs. AI codes.

⭐ Bookmarks it for you, helps other devs find it too.

v0.2-conformant reader of the FAF Context Ingestion Contract.

🐘 tri-sync | .fafMEMORY.md (faf_tri_sync), alongside .fafCLAUDE.md (faf_sync).

The faf prompt — pick it from your host's prompt list (Claude Code shows it as /mcp__<server name>__faf). It scores your project, fills what the repo can, asks you only what only you can answer, verifies, and syncs.

6.0.0 is a major release. It needs Node 22 or later. faf_clear, faf_friday, faf_guide and faf_write are retired, and so are the AGENTS.md / .cursorrules / GEMINI.md / conductor imports into project.faf. The .mcpb now runs the server bundled inside it. The npx config and the SessionStart hook are not pinned to a version, so an install that runs npx -y claude-faf-mcp moves to 6.x on its next start: check your Node before you upgrade. Every change is in the CHANGELOG.

Context for Claude: faf-cli writes this repo's CLAUDE.md from its scored project.faffaf_sync here, faf sync in faf-cli. See FAF-CLI for Claude Code 👀.

Composes faf-cli (the version is pinned in package.json). Detection, scoring, the renders and every writer are faf-cli's own functions, loaded as a dependency; claude-faf-mcp does not fork them and never runs a faf found on your PATH.

Core 14 MCP tools (30 with FAF_TOOLS=all). IANA-registered formats (application/vnd.faf+yaml · application/vnd.fafm+yaml).


What's New in v6.0.0 — The Earned Badge Edition

Every badge earned, none claimed: claude-faf-mcp 6.0 composes faf-cli, touches only what it wrote, and every tool tells the truth — one score, facts from repo, nothing from your PATH.

  • Composes faf-cli 7.13. Detection, scoring, the renders and every writer are faf-cli's own functions. claude-faf-mcp never runs a faf it finds on your PATH.

  • Touches only what it wrote.

    • Every write is atomic and goes through faf-cli's safe path, and a file that links out of the project is refused.

    • project.faf edits keep your comments and exact values.

    • Your soul.fafm and Claude's own MEMORY.md notes stay as you left them.

  • One score. Every tool shows faf-cli's score, and ✪ appears only at 100%.

  • Facts from repo. Every empty slot says what fills it:

    • a fact from repo, which faf_auto writes;

    • no fact in repo, which you answer with faf_go;

    • or yours, for the 6Ws.

  • Tools that tell the truth.

    • Every title, hint and schema matches what the tool does, and bad arguments are refused before anything runs.

    • Core 14: faf_setup and faf_tri_sync join the default list.

  • Safe with any repo.

    • A cloned repo's symlinks never reach your AI's context.

    • faf_go answers can't pollute objects.

    • The file tools stay inside the active project.

  • Ships what it runs. The .mcpb runs the server bundled inside it, and it's started and checked before its sha is recorded. Node 22+, with CI on Node 22 and 24 across Ubuntu, macOS and Windows.

  • Retired: faf_clear, faf_friday, faf_guide, faf_write, the interop imports into project.faf, and faf_check protect/unlock. The archive tag archive/cfm-v5-surface keeps them.


Related MCP server: gemini-faf-mcp

The 3Ws — 3 Answers. That's It.

Every great product started with 3 answers to the 3Ws — Who, What, Why:

WHO is it for?

WHAT does it do?

WHY build it?

Uber

People who need a ride

Tap a button, car arrives

Taxis were broken

Airbnb

Travelers who can't afford hotels

Stay in someone's spare room

Millions of empty rooms exist

Slack

Teams drowning in email

Organized group messaging

Decisions buried in threads

Venmo

Friends splitting bills

Send money instantly

Someone always forgets to pay back

Same pattern. Every product that works starts here. .faf captures it:

human_context:
  who: "people who need a ride across town"
  what: "tap a button, car arrives in minutes"
  why: "taxis are slow, expensive, and hard to find"

30 seconds. Claude builds your project.faf from this. Every session after, AI starts smart.

The 6Ws — For Optimized AI

3Ws gets you started. For fully optimized AI, complete the set — Where, When, How:

  where: "mobile app, iOS and Android"    # where does it live?
  when: "launch in 3 months"              # when is it shipping?
  how: "GPS matching, real-time pricing"  # how does it work?

3Ws initiates the project with AI. 6Ws optimizes AI to 100%. Same YAML, same file. More examples → faf.one/ideas


Quick Start

Needs Node 22 or later.

Claude Desktop — one click

⬇ Download claude-faf-mcp-6.0.0.mcpb

Open it in Claude Desktop. The extension runs the server bundled inside it (no npx, no network at start) and lists the Core 14 tools.

Claude Desktop — config

Add to claude_desktop_config.json, then restart Claude Desktop:

{
  "mcpServers": {
    "faf": { "command": "npx", "args": ["-y", "claude-faf-mcp"] }
  }
}

After npm install -g claude-faf-mcp you can use the installed bin instead: { "command": "claude-faf-mcp" }. With Bun on Claude Desktop's PATH, { "command": "bunx", "args": ["claude-faf-mcp"] } works too.

Claude Code

claude mcp add faf -- npx -y claude-faf-mcp

Pinning

The npx config and the SessionStart hook faf_setup installs (npx -y claude-faf-mcp --session-refresh) are not pinned: they run the latest release, so fixes arrive without a reinstall, and a new major arrives the same way. To stay on a major, write it in your config yourself: "args": ["-y", "claude-faf-mcp@6"]. The .mcpb runs the version it was built from.

Then

Run the faf prompt — Claude scores your project, fills what the repo can, asks you what only you can answer, verifies and syncs.

Or tell Claude your 3Ws: "I'm building [what] for [who] because [why]"

faf-cli — any terminal

npx faf-cli auto

Same .faf, every surface — Claude, Gemini, Grok, Cursor. faf-cli on npm →


How It Works

You → 3 answers → project.faf → AI reads it → every session → forever

project.faf  ──→  CLAUDE.md     (faf_sync)
project.faf  ──→  MEMORY.md     (faf_tri_sync 🐘)

Language, framework, package manager, build tools — faf-cli detects them from your existing files. The human context is the part only you can give.


For Claude Code teams

.faf lives in the repo. Your context travels with the code — committed, versioned, done.

Every session starts grounded. Install the native SessionStart hook once (faf_setup — preview first, your settings preserved). After that, every Claude Code session opens with a one-line heartbeat instead of a blank slate:

faf: context ✪ 100% — fresh · +7 intent the code can't carry

That line is the relay: Claude already knows your stack and your score — and the +N is the intent the code can't carry: the goal and 6Ws only you can give or confirm. No re-explaining "what this project is" at the top of every session.

It scales to the team by construction:

commit project.faf  →  every teammate's Claude starts with the same context
git clone           →  a new dev's Claude is grounded before they write a line
  • One source of truth. faf_sync writes CLAUDE.md from .faf — only its faf-managed block, so your own notes stay put. Add MEMORY.md for cross-session memory (tri-sync 🐘).

  • No drift. The score is deterministic — same .faf, same number, on every machine and in CI. A teammate can't be accidentally less grounded than you.

  • Local. No accounts, no telemetry, nothing sent to FAF. The one network use is cloning a repo you name, only when you ask (privacy). The context is yours; it rides in the repo.

Onboarding becomes git clone → grounded. The context a new teammate would normally pick up by asking around is already in the repo, machine-readable, from the first clone.


Scoring: From Blind to Optimized

Tier

Score

What it means

TROPHY

100%

Gold Code — AI is optimized

GOLD

99%+

Near-perfect context

SILVER

95%+

Excellent

BRONZE

85%+

Production ready

GREEN

70%+

Solid foundation

YELLOW

55%+

AI flipping coins

RED

<55%

AI working blind

WHITE

0%

No context at all

At 55%, AI guesses half the time. At 100%, AI knows your project. The score is faf-cli's scoreFafYaml — the number faf score prints for the same file.


MCP Tools — Core 14, 30 with FAF_TOOLS=all

By default claude-faf-mcp lists the Core 14 — the lifecycle tools you reach for. Set FAF_TOOLS=all to list the Extended tools too; every tool is callable by name either way. Retired in 6.0.0: faf_clear, faf_friday, faf_guide and faf_write (a call by name returns one line naming what to use instead), the AGENTS.md / .cursorrules / GEMINI.md / conductor imports into project.faf, and faf_check protect/unlock.

Every tool runs on the faf-cli this package depends on. Nothing is run from your PATH.

Core

Tool

Purpose

faf_init

Create project.faf for a folder (faf-cli detects the stack)

faf_auto

Fill project.faf from the repo's own files, then CLAUDE.md

faf_go

The goal and the 6Ws, by question and answer

faf_score

AI-readiness score (0-100%), from faf-cli

faf_bench

Benchmark AI grounding — cold vs with the .faf, graded mechanically, with a receipt

faf_doctor

Diagnose project.faf: each finding with the tool that fixes it

faf_trust

Validate project.faf and return a trust receipt for its score

faf_sync

Write CLAUDE.md from project.faf — agents/cursor/gemini/copilot/all also write AGENTS.md / .cursorrules / GEMINI.md / copilot-instructions.md

faf_tri_sync

Write faf's block into the MEMORY.md Claude Code loads for this project 🐘

faf_setup

Install the SessionStart hook in the project settings (preview first)

faf_context

Show or set the active project; detail returns the .faf text

faf_etch

Remember a decision across sessions (the project soul, soul.fafm)

faf_recall

Recall memories from the project soul

faf_about

What the .faf format is

Extended (FAF_TOOLS=all)

Tool

Purpose

faf

Start here: the project, its score and the steps to 100% (reads only)

faf_quick

Create project.faf from one line: name, goal, language, framework, hosting

faf_readme

Read the 6Ws from README.md; apply fills only empty slots

faf_human_add

Set one 6W slot in project.faf

faf_formats

The formats faf-cli finds in the folder, and what faf_auto would write (dry run)

faf_git

Author a project.faf from a repo URL (clones it with git — uses the network)

faf_check

faf-cli's validateFaf and the state of every slot

faf_dna

The project's .faf-dna lineage (reads only)

faf_status

Whether the project has a .faf, with its first lines

faf_agents

Write AGENTS.md (OpenAI Codex and other agents)

faf_cursor

Write .cursorrules (Cursor IDE)

faf_gemini

Write GEMINI.md (Google Gemini CLI)

faf_conductor

Write Google Conductor's conductor/ files

faf_read

Read a file inside the active project

faf_list

List a folder inside the active project

faf_debug

The active project, write access and the bundled faf-cli version


🐘 Nelly Never Forgets

faf_sync writes CLAUDE.md from .faf, so the two stay aligned.

tri-sync adds MEMORY.md — your AI remembers your project across every session.

faf_sync = .faf → CLAUDE.md              ← written from .faf
tri-sync = .faf → MEMORY.md   (faf_sync writes CLAUDE.md)  ← Nelly never forgets 🐘

Pro feature, free for developers. Teams & Enterprise: faf.one/pro (plans)


The .FAF Position

Model        Context          Protocol
─────        ───────          ────────
Claude    →   .faf        →    MCP
Gemini    →   .faf        →    MCP
Codex     →   .faf        →    MCP
Any LLM   →   .faf        →    MCP

IANA-registered (application/vnd.faf+yaml). One file, one format. Define once, use everywhere.


Ecosystem

Package

Platform

Registry

claude-faf-mcp (this)

Claude

npm

faf-cli

CLI

npm + Homebrew

gemini-faf-mcp

Google Gemini

PyPI

grok-faf-mcp

xAI Grok

npm

rust-faf-mcp

Rust

crates.io

faf-wasm

Browser/Edge

npm

Chrome Extension

Browser

Chrome Web Store

Same project.faf. Same scoring. Same result. Different execution layer.


Quality

Tests run with bun on ubuntu, macOS and Windows; the built package is packed, installed and started on Node 22 and 24 on all three. CI →


Privacy

claude-faf-mcp runs on your machine. No analytics, no telemetry, no accounts. Its one network use is faf_git, and only when you ask it to read a repo: git clones it from the URL you give. The files it writes are listed in the privacy policy →


If claude-faf-mcp has been useful, consider starring the repo — it helps others find it.


Citation

If you use claude-faf-mcp or the .faf / .fafm / .fafa formats in research or production, please cite the format papers:

Wolfe, J. (2025). Format-Driven AI Context Architecture: The .faf Standard for Persistent Project Understanding. Zenodo. https://doi.org/10.5281/zenodo.18251362

Wolfe, J. (2026). Permanent Memory and Instant Recall: The .fafm Standard for Multi-Profile AI Agent Memory. Zenodo. https://doi.org/10.5281/zenodo.20348942

Wolfe, J. (2026). Why Agents Need a Passport: .fafa — Portable Identity for the Agentic Era. Zenodo. https://doi.org/10.5281/zenodo.21951641

BibTeX

@article{wolfe2025faf,
  title     = {Format-Driven AI Context Architecture: The .faf Standard for Persistent Project Understanding},
  author    = {Wolfe, James},
  year      = {2025},
  month     = {nov},
  publisher = {Zenodo},
  doi       = {10.5281/zenodo.18251362},
  url       = {https://doi.org/10.5281/zenodo.18251362}
}

@article{wolfe2026fafm,
  title     = {Permanent Memory and Instant Recall: The .fafm Standard for Multi-Profile AI Agent Memory},
  author    = {Wolfe, James},
  year      = {2026},
  month     = {may},
  publisher = {Zenodo},
  doi       = {10.5281/zenodo.20348942},
  url       = {https://doi.org/10.5281/zenodo.20348942}
}

@article{wolfe2026fafa,
  title     = {Why Agents Need a Passport: .fafa — Portable Identity for the Agentic Era},
  author    = {Wolfe, James},
  year      = {2026},
  month     = {aug},
  publisher = {Zenodo},
  doi       = {10.5281/zenodo.21951641},
  url       = {https://doi.org/10.5281/zenodo.21951641}
}

License

MIT — Free and open source


FAF Family

faf-cli

npx faf-cli init — create .faf for any project

claude-faf-mcp

MCP server for Claude Desktop

gemini-faf-mcp

MCP server for Gemini CLI

grok-faf-mcp

MCP server for Grok

faf-mcp

MCP server for Cursor, Windsurf, Cline, VS Code

rust-faf-mcp

MCP server in Rust

faf-skills

Claude Code skills for .faf

faf.one

Blog, downloads, docs

IANA: vnd.faf+yaml

Context format (2025-10-30)

IANA: vnd.fafm+yaml

Memory format (2026-05-13)

format | driven 🏎️⚡️ wolfejam.dev


Get the CLI

faf-cli — The original AI-Context CLI. A must-have for every builder.

npx faf-cli auto

MCP Registry: one.faf/claude-faf-mcp · 2 IANA registrations: vnd.faf+yaml (Context) · vnd.fafm+yaml (Memory) · faf.one · npm


Zero-Config. Context that's just there — every session.

Available Tools

14 tools
faf_aboutAbout .fafA
Read-onlyIdempotent
Inspect

Explain what the .faf format is — project context for AI, IANA-registered as application/vnd.faf+yaml — and how this server uses it. Returns a short plain-text overview with this server's version. Reads nothing and writes nothing. Use it when someone asks what FAF is.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so safety is covered. The description adds useful behavioral context: it reads nothing and writes nothing, returns plain text, and includes the server version. This is more than the annotations provide and is clearly stated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core purpose. It is tight but slightly packs three ideas (definition, output, usage) into the first sentence, which is still efficient. Minor room to split, but no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a no-parameter, no-output-schema tool, the description covers what it does, what it returns, and when to use it. With annotations covering read-only behavior, no further context is required.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Zero parameters, so baseline is 4. The description correctly implies no input, and the schema confirms an empty object. No further parameter detail is needed or given.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Explain') and resource ('.faf format'), then adds concrete scope: what it is, how this server uses it, and that it returns a plain-text overview with server version. This clearly distinguishes it from siblings like faf_score or faf_init, which perform operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use guidance: 'Use it when someone asks what FAF is.' It doesn't name alternative tools, but none of the siblings serve this explanatory purpose, so implicit exclusivity is reasonable.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_autoFill from the RepoA
DestructiveIdempotent
Inspect

Create /project.faf, or fill the empty slots of the one there, with faf-cli's detection over the repo's own files (package.json, Cargo.toml, pyproject.toml, go.mod…) — no hardcoded defaults. A value already there is kept. A typed None or placeholder word is an empty slot: in a tech slot the app-type uses, only a repo fact replaces it (with no fact it stays as typed); in a tech slot the app-type leaves out, faf_auto writes slotignored; in a 6W it stays as typed (faf_go asks). Every value it changes is listed. Then writes CLAUDE.md's faf-managed block. Returns what was filled and faf-cli's score before and after. faf_go does the human 6Ws.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoProject path. Sets session context for subsequent calls.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description explains exact fill rules, that existing values are kept, what happens to typed None/placeholder slots, that changes are listed, that CLAUDE.md's faf-managed block is written, and what the tool returns. This gives strong behavioral context for a destructive write tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core action and every sentence carries behavioral detail. It is dense and sentence three is complex, but no content appears purely redundant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description supplies the return information: filled values and faf-cli's score before and after. It also covers side effects, slot rules, and the related faf_go boundary, making it complete for this tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has one parameter with 100% description coverage, so the schema already documents path and its session-context role. The description adds no further meaning about the path parameter, matching the baseline when schema coverage is high.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: it creates or fills <folder>/project.faf using repo detection. It also distinguishes its behavior from faf_go by noting that faf_go handles the human 6W questions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly indicates context: use it to auto-fill project.faf from repo facts, and defer human 6W input to faf_go. It does not list every alternative sibling such as faf_init or faf_sync, but the primary usage distinction is explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_benchGrounding BenchmarkA
Read-onlyIdempotent
Inspect

Prove the .faf earns its place — measure how much the context is worth, on THIS repo, falsifiably. Questions derive from the project.faf's own populated slots (the .faf is the answer key), so grading is mechanical — no judge, no rubric. action=questions returns the answer-key-safe question set; action=grade takes your answers WITHOUT the .faf (cold) and WITH it (faf), grades both, and returns the cold→with-faf lift with a receipt hash. The delta is the product; the cold number belongs to the absence of context, never to FAF. Reads only.

ParametersJSON Schema
NameRequiredDescriptionDefault
fafNoaction=grade: answers produced WITH the project.faf in context. Map of question number → answer string.
coldNoaction=grade: answers produced WITHOUT the .faf (general repo knowledge only). Map of question number → answer string.
pathNoProject path (optional — the active project if omitted).
modelNoaction=grade (optional): the model that produced the answers.
actionNoquestions = get the answer-key-safe question set to answer; grade = submit cold + with-faf answers to score the delta. Default: questions.
fafTokensNoaction=grade (optional): tokens spent answering with the .faf.
coldTokensNoaction=grade (optional): tokens spent answering cold.

Output Schema

ParametersJSON Schema
NameRequiredDescription
fafNoaction=grade — score WITH the .faf.
coldNoaction=grade — score WITHOUT context (absence baseline).
deltaNowith-faf minus cold — the product.
totalNoNumber of questions in the set.
actionNo
receiptNofaf-cli's bench receipt — sha256 over the canonical projection; third-party verifiable.
versionNo
protocolNoin-session — answers are self-reported by the agent under test.
qsetHashNoHash of the question set — rides the receipt; same .faf reproduces it.
questionsNoaction=questions only — NEVER includes the answer key.

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and non-destructive; the description adds real context beyond them - the questions are 'answer-key-safe', grading is mechanical with no judge or rubric, and the result is a cold→with-faf lift with a receipt hash. It also confirms the read-only nature ('Reads only'), consistent with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Content is dense and front-loaded: the purpose, the mechanism, and the two-action flow appear in order with no filler. Sentences are long and somewhat jargon-heavy, but each carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description needn't explain return values, and it still covers the two actions, their sequencing, and the meaning of the cold/faf split. An agent has enough to invoke it correctly, with only minor gaps like token-field usage not being explained narratively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, including per-parameter descriptions for faf, cold, action, and token fields, so the schema does the heavy lifting. The description reinforces the cold-vs-faf distinction and the default action but adds little syntactic detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a concrete purpose - measuring how much the project.faf context is worth on the current repo via mechanically graded questions - and enumerates both actions (questions, grade). It clearly differs from sibling tools like faf_score or faf_about, though the metaphorical opening ('earns its place') adds flavor before the operational statement.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear workflow: call action=questions to get the answer-key-safe set, then action=grade with cold and faf answers to obtain the delta. It does not explicitly state when to prefer this over siblings such as faf_score, but the internal usage guidance is concrete.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_contextActive ProjectA
Read-onlyIdempotent
Inspect

Show the active project — the folder every faf_* call without a path uses — and the .faf there; pass path to make another folder the active project (your home folder and the filesystem root are refused). detail: true also returns the .faf's text. Writes no file. Call it once at the start of a session.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoSet active project path. If omitted, shows current context.
detailNoAlso return the text of the .faf (read with faf-cli's reader), for reading project.faf in one call

Output Schema

ParametersJSON Schema
NameRequiredDescription
pathNoThe .faf file readers use (faf-cli's finder: the folder, then one level up), if found
activeYesAbsolute path of the active project
hasFafYesWhether a project.faf (or .faf) was found there or one level up
changedYesTrue if this call set a new context, false if it only reported
contentNodetail: true — the text of the .faf
filenameNoThe .faf filename, if found

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered; the description adds real beyond-annotation context: the refusal of home folder and filesystem root, the fact that path redefines the context used by all other pathless faf_* calls, and 'Writes no file.' It is slightly redundant on the read-only point.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single dense sentence-pair, front-loaded with the purpose and followed by parameter behavior and session guidance. Every clause earns its place with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation. The description covers purpose, both parameters, the state effect on sibling calls, refusal conditions, and session timing — complete for a simple 0-required-param context tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds meaning beyond the schema: path re-points the active project and has documented rejection cases, and detail:true surfaces the .faf text. These behavioral consequences go beyond the terse schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (show) and resource (the active project folder and its .faf), and clarifies the concept precisely: it is the folder every faf_* call without a path uses. This distinguishes it from siblings like faf_init or faf_about without needing schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to call it ('once at the start of a session') and when to pass path (to switch projects). It does not name an alternative sibling or state when-not-to-use, but the session-start guidance and the concept of the shared context are clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_doctorDiagnose .fafA
Read-onlyIdempotent
Inspect

Diagnose the project's .faf: faf-cli's validateFaf errors, faf-cli's score with every empty slot and the tool that fills it (faf_auto from the repo, faf_go for the 6Ws), whether CLAUDE.md is there, and the formats faf-cli finds in the folder. Returns a checklist of findings, each with its fix. Reads only. Use it when faf_score is below 100%.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoProject path. Sets session context for subsequent calls.

Output Schema

ParametersJSON Schema
NameRequiredDescription
scoreNofaf-cli's score (-1 only with unknown: true), or null when not scored
validNofaf-cli's validateFaf verdict, or null when no .faf could be read
checksYesNumber of checks run
errorsNoCount of error-level findings
healthYesOverall verdict: ok | warning | error
unknownNoTrue when the score is not known (an About repo with no about.source_score)
warningsNoCount of warning-level findings
diagnosticsYesPer-check results

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, and the description's 'Reads only' merely restates that. It does add that the output is a checklist of findings each paired with a fix, which is mild extra context. With an output schema present and safety already covered, no deeper disclosure is required, but little is added beyond structured data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core verb+resource, and the closing usage rule is short and actionable. The first sentence is a run-on packing several checks and two sibling names into one breath, which costs a little readability but there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers what is diagnosed, the read-only nature, and the trigger condition, and an output schema exists so return values need not be described. For a single-optional-parameter diagnostic tool this is close to complete, missing only explicit exclusions or a follow-up path.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is a single optional parameter whose schema description is 100% covered ('Project path. Sets session context for subsequent calls.'). The description adds no further meaning about the path argument, so the schema carries the load and baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Diagnose the project's .faf') and enumerates the checks performed: validateFaf errors, score/empty slots, CLAUDE.md presence, formats found. It also names the siblings that supply fixes (faf_auto, faf_go), so it is distinguishable. The dense parenthetical phrasing keeps it just short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit trigger condition: 'Use it when faf_score is below 100%', which routes the agent from a sibling tool to this one. It does not state when not to use it or what to do after diagnosis, but the primary selection condition is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_etchEtch MemoryA
Destructive
Inspect

Remember a decision, gotcha, or win across sessions by writing it to the project soul (soul.fafm) with faf-cli's Soul. Returns the stored memory and the soul's size. Re-etching an id updates that memory in place. Use it to persist something an AI should recall later; faf_recall reads them back.

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoStable id — re-etching the same id updates in place (dedup)
pathNoProject path. Sets session context for subsequent calls.
tagsNoTags (e.g. decision, gotcha, win) for filtering + recall coupling
textYesThe memory to remember — capture the why (decision/gotcha/win)
typeNoMemory category
priorityNoRecall ranks by priority then recency

Output Schema

ParametersJSON Schema
NameRequiredDescription
soulYesPath to soul.fafm
totalNoTotal memories in the soul
etchedYes
namepointNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes beyond the annotations by disclosing the write target (soul.fafm), the dedup/update-in-place semantics of re-etching an id, and the return payload. It does not warn about the destructiveHint=true aspect beyond noting in-place overwrite, and no permission or auth prerequisites are mentioned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences: purpose first, then the mutation/dedup rule, then the usage pointer to the alternative. No filler and nothing buried.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 6-parameter mutation tool with full schema coverage, output schema present, and annotations already declaring the safety profile, the description covers purpose, persistence target, dedup behavior, and the sibling relationship. Nothing an agent needs to invoke it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so every parameter is already documented in the schema (id dedup, path session context, tags, priority ranking). The description adds no per-parameter meaning beyond that, which is the expected baseline when the schema carries the load.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (etch/remember) and resource (a memory written to soul.fafm), plus the storage mechanism (faf-cli's Soul). It is clearly distinguishable from sibling faf_recall, whose role is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear when: 'Use it to persist something an AI should recall later', and names the complementary reader faf_recall. It does not state any when-not conditions (e.g. don't etch ephemeral scratch state), so it stops short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_goGuided InterviewA
Destructive
Inspect

The human half of project.faf. Without answers it returns the Table-of-8 — project name, goal and the 6Ws (who, what, why, where, when, how) — each filled, seeded from the goal, or empty, with faf-cli's score and, for each slot still empty, whether it is a fact from repo (faf_auto writes it: its dry run, the one faf_formats shows) or needs an answer here. With answers (slot path → text, e.g. {"stack.hosting": ""}) it writes them into /project.faf in place and returns the new score; a value already in a slot you answer is replaced. With no project.faf yet it runs faf_init and faf_auto first. faf_auto writes each fact from repo; a stack slot with no fact in repo is answered here.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoProject path. Sets session context for subsequent calls.
answersNoAnswers to apply: a slot path (e.g. "project.goal", "human_context.why", "stack.database") → the answer text. Any other key, or an answer that is not text, is refused and nothing is written. If provided, applies the answers and returns the new score.

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true, readOnlyHint=false and idempotentHint=false, so safety is covered structurally. The description adds real value beyond that: answers are written in place, an answered slot's existing value is replaced, invalid keys or non-text answers are refused with nothing written, and project.faf is created via faf_init/faf_auto if missing. That is meaningful side-effect disclosure for a mutating tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two long, densely nested sentences pack in every behavior but bury the critical read-vs-write fork mid-clause, so it is not front-loaded for quick scanning. The information is mostly load-bearing, but nested asides ('faf_auto writes it: its dry run, the one faf_formats shows') hurt parseability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden, and it does state the return (the Table-of-8 plus score in read mode, the new score in write mode). It also covers creation side effects and refusal behavior. What is missing is any guidance on subsequent calls or the session-context effect of path beyond the schema note.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and both parameters are documented in the schema, so the baseline is 3. The description restates the slot-path→text answer shape and the refusal rule, but adds little syntax or format detail the schema does not already supply (its example values overlap the schema's own examples).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description defines a specific dual-mode tool: read-only interview output (the Table-of-8 seeded from the goal with score) when no answers are given, and an in-place writer of answers into <folder>/project.faf when they are. It positions itself against siblings by naming faf_auto and faf_init as things it invokes and faf_formats as showing the dry run. However, jargon like 'Table-of-8' and 'the human half of project.faf' assumes familiarity, so an unfamiliar agent needs more parsing than ideal.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implicitly delineates when each mode applies (no answers = inspect, answers = write) and names the parent workflow (faf_init/faf_auto run first if project.faf is absent). But there is no explicit 'use this instead of X' routing or stated prerequisites beyond that, so the agent must infer when faf_go beats faf_auto or faf_score.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_initCreate project.fafA
Destructive
Inspect

Create a new project.faf for a folder: faf-cli detects its name, language and stack, and the reply gives the file path, faf-cli's starting score and the birth .faf-dna. An existing project.faf is left as it is — use faf_auto to fill its empty slots from your manifests, or faf_go for the human 6Ws. force: true replaces an existing project.faf with a fresh one, after copying the old file to a backup beside it.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoProject path or name. Smart resolution: "my-app" finds ~/Projects/my-app OR ~/Code/my-app. Full paths like ~/Projects/app or /Users/me/code/app work too; ".", "..", "./app" are relative to the active project. Omit to create ~/Projects/unnamed-project; pass the workspace path to init it. Your home folder and the filesystem root are refused.
forceNoReplace an existing project.faf with a fresh one: every value and comment in it is replaced. The old file is copied to project.faf.bak-<time> first.

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag destructive=true, but the description adds material context beyond them: an existing file is left untouched by default, and force:true copies the old file to a project.faf.bak-<time> backup before replacing. It also discloses what the reply contains (path, starting score, .faf-dna), which carries weight since no output schema exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and keeps to three dense sentences with no filler. Slightly heavy with multiple clauses, but every sentence carries useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a destructive, zero-required-param create tool with no output schema, the description covers invocation outcome (returned values), default safety behavior, the force override, and alternatives. An agent has everything needed to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already richly documented in the schema. The description restates force's replace-and-backup behavior but adds no syntax or resolution detail beyond what the schema provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Create') plus the exact resource ('project.faf') and adds the detection behavior (name, language, stack) that defines the tool. It explicitly differentiates itself from siblings faf_auto and faf_go, so an agent can disambiguate without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly states when to use it (creating a new project.faf) and, crucially, what to do instead when a file already exists — route to faf_auto for filling empty slots or faf_go for human 6Ws. Even names the force condition and its consequence.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_recallRecall MemoryA
Read-onlyIdempotent
Inspect

Recall memories from the project soul (soul.fafm), ranked by priority then recency, filtered by query/tags/type. Returns the matching entries. Reads only. Use it to surface past decisions; faf_etch adds new ones.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoProject path. Sets session context for subsequent calls.
tagsNoFilter by tag intersection
typeNoFilter by memory type
limitNoMax memories to return
queryNoCase-insensitive substring match on memory text (optional)
minPriorityNoPriority floor (default ephemeral)

Output Schema

ParametersJSON Schema
NameRequiredDescription
soulNo
totalYesNumber returned
memoriesYes
soulTotalNoTotal memories in the soul

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, openWorldHint=false and destructiveHint=false, so 'Reads only' is largely redundant. However, the description adds real behavioral context beyond the annotations: the backing store (soul.fafm), the deterministic ranking order (priority then recency), and the fact that filtering is conjunctive across query/tags/type.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core action and scope, then filters, then the routing hint to faf_etch. No filler; every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not explain return shape, and the one-line 'Returns the matching entries' is sufficient. For a six-parameter read tool it covers filters, ordering, and the sibling write path, though it omits default limit behavior and any note on empty results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all six parameters, including the query substring semantics and the minPriority default. The description only restates the filter dimensions and adds result ordering (priority then recency), which is genuinely extra but marginal against a fully documented schema. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Recall memories from the project soul (soul.fafm)') and immediately specifies the retrieval model ('ranked by priority then recency, filtered by query/tags/type'). It explicitly names the sibling it is not ('faf_etch adds new ones'), so an agent can route between the read and write tools without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a concrete use case ('surface past decisions') and names the complementary alternative, faf_etch, with its contrasting behavior. It stops short of stating when NOT to use it (e.g. when to prefer faf_context or a live search over stored memories), so it is clear context without explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_scoreScore .fafA
Read-onlyIdempotent
Inspect

Score the project's .faf with faf-cli's scorer — the one score every faf tool reports: 0–100%, the tier, populated/active slots, and a faf-parity/v1 hash of the result. details: true lists every slot as populated, empty or slotignored. Reads only. Use faf_doctor for what to fix.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoProject path. Sets session context for subsequent calls.
detailsNoList every slot as populated, empty or slotignored, and the tools that fill the empty ones

Output Schema

ParametersJSON Schema
NameRequiredDescription
pathNoPath that was scored
tierYesTier name for this score (e.g. BRONZE, TROPHY)
emptyNoActive slots still empty
scoreYesAI-readiness score, 0-100 (-1 only together with unknown: true)
slotsNoSlot paths by state
totalNoTotal slots
activeNoSlots active for this app_type
hasFafYesWhether a readable, valid project.faf was scored
parityNofaf-parity/v1 — claude-faf-mcp's own spec (no other engine computes it yet): sha256 over a canonical projection of faf-cli's score for these exact bytes. Check it yourself: sha256(projection) === parityHash.
ignoredNoSlots marked slotignored (inactive for this app_type)
unknownNoTrue when the score is not known: an About repo with no about.source_score. Shown as "unknown (—)", never as a number.
nextTierNoNext tier above the current score, or null at top tier
inheritedNoTrue if the score is attested from a source repo (an about: block)
populatedNoActive slots that are filled

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent and non-destructive, so the bar is lower; the description reinforces this with 'Reads only' and goes further by disclosing the exact output composition (score, tier, slot states, faf-parity/v1 hash). It does not mention failure modes or cost, but adds real context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The core action and output are front-loaded and the total length is appropriate. The dash-heavy, list-like styling and the aside 'the one score every faf tool reports' add flavor but slightly dilute an otherwise tight definition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, yet the description still summarizes them usefully. With only two optional parameters, full schema coverage, and clear safety annotations, an agent has everything needed to invoke this correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented in the schema, which establishes the baseline of 3. The description's note that details:true lists every slot as populated/empty/slotignored largely restates the schema, adding little new syntax or edge-case meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Score the project's .faf with faf-cli's scorer') and enumerates exactly what the score contains (0–100%, tier, slots, parity hash). It also names faf_doctor as the sibling for remediation, so an agent can distinguish it from the other faf_* tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context ('Reads only') and routes the agent to faf_doctor 'for what to fix', which is an explicit alternative. It stops short of stating when scoring itself is the right call versus e.g. faf_bench or faf_trust.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_setupSession Hook SetupA
Idempotent
Inspect

Install the native SessionStart hook in the project settings (/.claude/settings.json) — every Claude Code session in this project starts with fresh .faf context. Shows the exact settings first (preview); writes only with confirm: true, install or remove. faf changes only its own hook entry; every other key and hook stays as written. remove: true takes out only the hook whose command is exactly the faf hook command. Never writes the user settings: the home folder is refused.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoProject path. Defaults to the current project context.
removeNoRemove the faf SessionStart hook (and only it) from the project settings. Previews unless confirm: true.
confirmNoWrite the change to the project settings (.claude/settings.json). Without it, faf_setup only previews — install and remove alike.

Output Schema

ParametersJSON Schema
NameRequiredDescription
actionYesWhat faf_setup did
messageYesHuman-readable summary
settingsNoThe full settings object as written (or as it would be written in preview)
hookCommandNoThe command the SessionStart hook runs
settingsPathYesThe settings file involved

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds substantial behavioral detail beyond the annotations: it previews before writing, requires confirm: true to mutate, modifies only its own hook entry, preserves every other key and hook, and refuses the user settings/home folder. These details clarify the safety envelope and mutation semantics, consistent with readOnlyHint=false, destructiveHint=false, and idempotentHint=true.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loads the main action before its conditions. It packs a lot into one long compound sentence, which is efficient but slightly dense. Every clause earns its place by covering install, preview, confirm, scope, and removal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a three-parameter hook-management tool with a full output schema, the description covers the critical operational facts: default preview, confirm-gated write, removal behavior, scope of changes, and refusal of user settings. An agent has enough context to invoke it correctly without needing return-value details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters are already documented in the input schema. The description reinforces confirm and remove semantics, but does not add parameter syntax or formats beyond what the schema provides. A baseline score of 3 is appropriate when the schema carries the parameter-documentation burden.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: install the native SessionStart hook in the project settings. It also explains the downstream effect, that every Claude Code session starts with fresh .faf context, and covers both install and remove modes. This distinguishes it from sibling tools like faf_init or faf_context, which manage context rather than session-hook installation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear operating context: preview is the default, writes happen only with confirm: true, and remove: true targets only the faf hook. It also states an explicit exclusion, that user settings and the home folder are never written. However, it does not name or compare against alternative faf tools for related setup tasks.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_syncSync .faf to CLAUDE.mdA
Idempotent
Inspect

Write project.faf into CLAUDE.md as a faf-managed block (faf-cli's render and injector), and on request into AGENTS.md (agents), .cursorrules (cursor), GEMINI.md (gemini) and .github/copilot-instructions.md (copilot) — or all of them (all) — with faf-cli's writers. Each file keeps every line outside faf's block. Returns the files written and any requested file that could not be written, with the reason (then isError). Use it after editing project.faf.

ParametersJSON Schema
NameRequiredDescriptionDefault
allNoWrite every format: CLAUDE.md + AGENTS.md + .cursorrules + GEMINI.md + .github/copilot-instructions.md
pathNoProject path. Sets session context for subsequent calls.
agentsNoAlso write AGENTS.md (OpenAI Codex and other agents)
cursorNoAlso write .cursorrules (Cursor IDE)
geminiNoAlso write GEMINI.md (Google Gemini CLI)
copilotNoAlso write .github/copilot-instructions.md (GitHub Copilot)

Output Schema

ParametersJSON Schema
NameRequiredDescription
scoreNofaf-cli's score of that .faf, as text ("85%" or "unknown (—)")
fafPathNoThe .faf the files were written from
filesFailedYesRequested files that were not written
filesWrittenYesFiles written, CLAUDE.md first

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare idempotentHint=true and destructiveHint=false, so the safety profile is covered. The description adds real behavioral context beyond that: each target file preserves all lines outside faf's block, and failures are returned per-file with a reason plus isError. It does not say whether concurrent writes are safe, but the merge semantics are a meaningful addition.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The purpose is front-loaded, but the text is one long run-on with redundant jargon — "faf-cli's render and injector" and "with faf-cli's writers" say the same thing twice and cost the reader without adding information. It is functional but not tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return-value documentation is not strictly required, yet the description usefully frames the write results and failure reporting. With 6 optional params all documented in the schema, and file-preservation semantics stated, an agent has enough to invoke it correctly; only the sibling distinction is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description restates the flag-to-file mapping (agents, cursor, gemini, copilot, all) that the schema already documents, adding no syntax, precedence (e.g. all vs a single flag), or default behavior beyond it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — writing project.faf into CLAUDE.md as a faf-managed block, optionally into four other files. It is clear what the tool does, but it never distinguishes itself from the sibling faf_tri_sync, which is the nearest potential overlap, so an agent cannot rule that one out from the text alone.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Use it after editing project.faf" gives a concrete trigger condition that tells the agent when this tool is appropriate. It provides no when-not guidance and does not name alternatives among the 13 siblings, so it stops short of full routing guidance but is more than implied usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_tri_syncTri-Sync to MEMORY.mdA
Idempotent
Inspect

Write project.faf as a faf-managed block into the MEMORY.md Claude Code loads for this project (~/.claude/projects//memory/MEMORY.md, or under CLAUDE_CONFIG_DIR). Only the block changes; every note of Claude's is kept, and the reply says so only after reading the file back. action: status reads only. faf_sync writes CLAUDE.md.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoProject path. Sets session context for subsequent calls.
actionNoexport = write faf's block into MEMORY.md (default), status = show what MEMORY.md holds (reads only)

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations covering safety (idempotent, non-destructive), the description adds real behavioral value: it localizes the target path, CLAUDE_CONFIG_DIR override, and — crucially — specifies that only the managed block changes, all of Claude's notes are preserved, and the reply is asserted only after reading the file back. That verification and preservation guarantee goes well beyond what readOnlyHint/destructiveHint convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, no filler, front-loaded with the primary action and target before the readback guarantee and sibling routing. Every sentence earns its place, including the path and config-dir override.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, yet the description tells the agent what the reply means ('the reply says so only after reading the file back') and what is and isn't modified. For a 2-param write tool with no return schema, this is complete enough to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters are already documented. The description repeats the 'status reads only' and default-export semantics that the schema's enum description already carries, adding no syntax or edge-case detail. Baseline 3 is correct.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Names a specific verb and resource ('Write project.faf as a faf-managed block into the MEMORY.md'), states the exact target file and its location, and explicitly distinguishes itself from the sibling faf_sync ('faf_sync writes CLAUDE.md'). An agent can pick between the two without opening either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It routes the agent to an alternative (faf_sync for CLAUDE.md) and disambiguates the 'status' mode as reads-only. It does not spell out prerequisites or when-not-to-use beyond the sibling contrast, so it stops short of the top band.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

faf_trustTrust ReceiptA
Read-onlyIdempotent
Inspect

Attest the project's .faf: faf-cli's validateFaf, faf-cli's score, and a faf-parity/v1 hash (claude-faf-mcp's own spec) of that score that anyone can check with sha256(projection) === parityHash. Returns a trust receipt whose subject is the project. An invalid .faf, or a score that is unknown, gets no receipt (isError). Reads only.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathNoProject path. Sets session context for subsequent calls.

Output Schema

ParametersJSON Schema
NameRequiredDescription
pathNoPath that was attested
tierNoTier name for this score
scoreNoAI-readiness score, 0-100
validYesWhether faf-cli's validateFaf accepts the .faf
errorsNofaf-cli's validateFaf errors, when valid is false
hasFafYesWhether a project.faf was found
parityNofaf-parity/v1 — claude-faf-mcp's own spec (no other engine computes it yet): sha256 over a canonical projection of faf-cli's score for these exact bytes. Check it yourself: sha256(projection) === parityHash.
reasonNoWhy no receipt was issued
receiptNoThe trust receipt — render-identical, self-verifying score + parity.
subjectNoThe project the receipt attests: project.name, else its folder name
sourceSha256NoSHA-256 of the raw .faf bytes

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, non-destructive, closed-world. The description adds the important failure behavior: invalid .faf or unknown score yields isError/no receipt; 'Reads only' is redundant but consistent. It stops short of permission/rate-limit context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the verb and core behavior, then return and error condition; no bloated preamble. The final 'Reads only' is redundant against annotations, keeping it from a perfect score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists and annotations cover safety, so return values and read-only nature need not be fully explained here. The description does cover the receipt and error case, making it sufficiently complete for this read-only attestation tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Single path parameter has 100% schema description coverage, so the schema already explains its role. The description adds no further syntax/default/context for path, so baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Attest') and resource (the project's .faf) and enumerates the composite checks (validateFaf, score, parity hash) and returned receipt. This is clearly not a bare score tool, but it does not name a sibling alternative to route among faf_score/faf_doctor.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance, prerequisites, or alternatives to sibling tools are provided. Usage is only implied by the attestation purpose, so an agent gets little help choosing this over faf_score or faf_doctor.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 11 tool updatesv6.0.0
    • Changedfaf_auto1 field changed
      • removedInput schema / properties / force
        Removed value: -{
        -  "description": "Force overwrite existing files",
        -  "type": "boolean"
        -}
    • Changedfaf_bench3 fields changed
      • changedInput schema / properties / path / description
        Previous value: -"Project path (optional — current directory if omitted)."New value: +"Project path (optional — the active project if omitted)."
      • changedOutput schema / description
        Previous value: -"Question set (action=questions) or the cold→with-faf grading + ✪ receipt (action=grade)."New value: +"Question set (action=questions) or the cold→with-faf grading and its receipt (action=grade)."
      • changedOutput schema / properties / receipt / description
        Previous value: -"✪ receipt — sha256 over the canonical projection; third-party verifiable."New value: +"faf-cli's bench receipt — sha256 over the canonical projection; third-party verifiable."
    • Changedfaf_context4 fields changed
      • addedInput schema / properties / detail
        Added value: +{
        +  "description": "Also return the text of the .faf (read with faf-cli's reader), for reading project.faf in one call",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / content
        Added value: +{
        +  "description": "detail: true — the text of the .faf",
        +  "type": "string"
        +}
      • changedOutput schema / properties / hasFaf / description
        Previous value: -"Whether a project.faf (or .faf) was found there"New value: +"Whether a project.faf (or .faf) was found there or one level up"
      • addedOutput schema / properties / path
        Added value: +{
        +  "description": "The .faf file readers use (faf-cli's finder: the folder, then one level up), if found",
        +  "type": [
        +    "string",
        +    "null"
        +  ]
        +}
    • Changedfaf_doctor3 fields changed
      • addedOutput schema / properties / score
        Added value: +{
        +  "description": "faf-cli's score (-1 only with unknown: true), or null when not scored",
        +  "type": [
        +    "number",
        +    "null"
        +  ]
        +}
      • addedOutput schema / properties / unknown
        Added value: +{
        +  "description": "True when the score is not known (an About repo with no about.source_score)",
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / valid
        Added value: +{
        +  "description": "faf-cli's validateFaf verdict, or null when no .faf could be read",
        +  "type": [
        +    "boolean",
        +    "null"
        +  ]
        +}
    • Changedfaf_go1 field changed
      • changedInput schema / properties / answers / description
        Previous value: -"Answers to apply. Keys are field paths (e.g., \"project.goal\", \"human_context.why\"), values are the answers. If provided, applies answers and returns new score."New value: +"Answers to apply: a slot path (e.g. \"project.goal\", \"human_context.why\", \"stack.database\") → the answer text. Any other key, or an answer that is not text, is refused and nothing is written. If provided, applies the answers and returns the new score."
    • Changedfaf_init2 fields changed
      • changedInput schema / properties / force / description
        Previous value: -"Overwrite existing project.faf if it exists"New value: +"Replace an existing project.faf with a fresh one: every value and comment in it is replaced. The old file is copied to project.faf.bak-<time> first."
      • changedInput schema / properties / path / description
        Previous value: -"Project path or name. Smart resolution: \"my-app\" finds ~/Projects/my-app OR ~/Code/my-app. Full paths like ~/Projects/app or /Users/me/code/app work too. Omit to use current directory."New value: +"Project path or name. Smart resolution: \"my-app\" finds ~/Projects/my-app OR ~/Code/my-app. Full paths like ~/Projects/app or /Users/me/code/app work too; \".\", \"..\", \"./app\" are relative to the active project. Omit to create ~/Projects/unnamed-project; pass the workspace path to init it. Your home folder and the filesystem root are refused."
    • Changedfaf_score11 fields changed
      • changedInput schema / properties / details / description
        Previous value: -"Include detailed breakdown and improvement suggestions"New value: +"List every slot as populated, empty or slotignored, and the tools that fill the empty ones"
      • changedOutput schema / properties / inherited / description
        Previous value: -"True if the score is attested from a source repo (app_type: about)"New value: +"True if the score is attested from a source repo (an about: block)"
      • changedOutput schema / properties / parity / description
        Previous value: -"Determinism parity receipt — an engine-agnostic hash any conformant scorer reproduces for this exact file. Third-party verifiable: sha256(projection) === parityHash."New value: +"faf-parity/v1 — claude-faf-mcp's own spec (no other engine computes it yet): sha256 over a canonical projection of faf-cli's score for these exact bytes. Check it yourself: sha256(projection) === parityHash."
      • changedOutput schema / properties / parity / properties / parityHash / description
        Previous value: -"sha256(projection) — identical across any conformant engine"New value: +"sha256(projection)"
      • changedOutput schema / properties / parity / properties / producedBy / description
        Previous value: -"Which wrapper emitted this receipt (metadata, not hashed)"New value: +"The server that emitted this receipt (metadata, not hashed)"
      • changedOutput schema / properties / parity / properties / scorer / description
        Previous value: -"The single deterministic source the score comes from"New value: +"The single deterministic source the score comes from (faf-cli)"
      • changedOutput schema / properties / parity / properties / spec / description
        Previous value: -"Parity spec id, e.g. faf-parity/v1"New value: +"Parity spec id: faf-parity/v1"
      • changedOutput schema / properties / score / description
        Previous value: -"AI-readiness score, 0-100"New value: +"AI-readiness score, 0-100 (-1 only together with unknown: true)"
      • addedOutput schema / properties / slots
        Added value: +{
        +  "description": "Slot paths by state",
        +  "properties": {
        +    "empty": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "ignored": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "populated": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / tier / description
        Previous value: -"Tier name for this score (e.g. Bronze, Trophy)"New value: +"Tier name for this score (e.g. BRONZE, TROPHY)"
      • addedOutput schema / properties / unknown
        Added value: +{
        +  "description": "True when the score is not known: an About repo with no about.source_score. Shown as \"unknown (—)\", never as a number.",
        +  "type": "boolean"
        +}
    • Addedfaf_setup
    • Changedfaf_sync6 fields changed
      • changedInput schema / properties / agents / description
        Previous value: -"Also sync to AGENTS.md (OpenAI/Codex format)"New value: +"Also write AGENTS.md (OpenAI Codex and other agents)"
      • changedInput schema / properties / all / description
        Previous value: -"Sync to ALL formats: CLAUDE.md + AGENTS.md + .cursorrules + GEMINI.md + .github/copilot-instructions.md"New value: +"Write every format: CLAUDE.md + AGENTS.md + .cursorrules + GEMINI.md + .github/copilot-instructions.md"
      • changedInput schema / properties / copilot / description
        Previous value: -"Also sync to .github/copilot-instructions.md (GitHub Copilot)"New value: +"Also write .github/copilot-instructions.md (GitHub Copilot)"
      • changedInput schema / properties / cursor / description
        Previous value: -"Also sync to .cursorrules (Cursor IDE format)"New value: +"Also write .cursorrules (Cursor IDE)"
      • changedInput schema / properties / gemini / description
        Previous value: -"Also sync to GEMINI.md (Google Gemini format)"New value: +"Also write GEMINI.md (Google Gemini CLI)"
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "description": "The files faf_sync wrote, and each requested file it could not write.",
        +  "properties": {
        +    "fafPath": {
        +      "description": "The .faf the files were written from",
        +      "type": "string"
        +    },
        +    "filesFailed": {
        +      "description": "Requested files that were not written",
        +      "items": {
        +        "properties": {
        +          "file": {
        +            "type": "string"
        +          },
        +          "reason": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "file",
        +          "reason"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "filesWritten": {
        +      "description": "Files written, CLAUDE.md first",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "score": {
        +      "description": "faf-cli's score of that .faf, as text (\"85%\" or \"unknown (—)\")",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "filesWritten",
        +    "filesFailed"
        +  ],
        +  "type": "object"
        +}
    • Addedfaf_tri_sync
    • Changedfaf_trust16 fields changed
      • changedOutput schema / description
        Previous value: -"Trust attestation: validity, score, and a third-party-verifiable determinism parity receipt."New value: +"Trust attestation: faf-cli's validity and score, and a faf-parity/v1 receipt."
      • addedOutput schema / properties / errors
        Added value: +{
        +  "description": "faf-cli's validateFaf errors, when valid is false",
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / parity / description
        Previous value: -"Determinism parity receipt (same shape as faf_score.parity)."New value: +"faf-parity/v1 — claude-faf-mcp's own spec (no other engine computes it yet): sha256 over a canonical projection of faf-cli's score for these exact bytes. Check it yourself: sha256(projection) === parityHash."
      • addedOutput schema / properties / parity / properties / algo / description
        Added value: +"Hash algorithm (sha256)"
      • addedOutput schema / properties / parity / properties / parityHash / description
        Added value: +"sha256(projection)"
      • addedOutput schema / properties / parity / properties / producedBy / description
        Added value: +"The server that emitted this receipt (metadata, not hashed)"
      • addedOutput schema / properties / parity / properties / projection / description
        Added value: +"The exact canonical string that was hashed (for verification)"
      • addedOutput schema / properties / parity / properties / scorer / description
        Added value: +"The single deterministic source the score comes from (faf-cli)"
      • addedOutput schema / properties / parity / properties / sourceSha256 / description
        Added value: +"SHA-256 of the raw .faf bytes"
      • addedOutput schema / properties / parity / properties / spec / description
        Added value: +"Parity spec id: faf-parity/v1"
      • changedOutput schema / properties / reason / description
        Previous value: -"Why validation failed, when valid is false"New value: +"Why no receipt was issued"
      • changedOutput schema / properties / receipt / description
        Previous value: -"The ✪ trust receipt — render-identical, self-verifying score+parity artifact."New value: +"The trust receipt — render-identical, self-verifying score + parity."
      • changedOutput schema / properties / receipt / properties / seal / description
        Previous value: -"Quiet-ladder glyph for this score (✪ at Trophy)"New value: +"Quiet-ladder glyph for this score (✪ only at 100)"
      • addedOutput schema / properties / receipt / properties / subject / description
        Added value: +"The project: project.name, else its folder name"
      • addedOutput schema / properties / subject
        Added value: +{
        +  "description": "The project the receipt attests: project.name, else its folder name",
        +  "type": "string"
        +}
      • changedOutput schema / properties / valid / description
        Previous value: -"Whether the project.faf is readable and valid"New value: +"Whether faf-cli's validateFaf accepts the .faf"
  2. 1 tool update
    • Removedfaf_enhance
  3. 1 tool updatev5.14.1
    • Changedfaf_sync5 fields changed
      • addedInput schema / properties / agents
        Added value: +{
        +  "description": "Also sync to AGENTS.md (OpenAI/Codex format)",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / all
        Added value: +{
        +  "description": "Sync to ALL formats: CLAUDE.md + AGENTS.md + .cursorrules + GEMINI.md + .github/copilot-instructions.md",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / copilot
        Added value: +{
        +  "description": "Also sync to .github/copilot-instructions.md (GitHub Copilot)",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / cursor
        Added value: +{
        +  "description": "Also sync to .cursorrules (Cursor IDE format)",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / gemini
        Added value: +{
        +  "description": "Also sync to GEMINI.md (Google Gemini format)",
        +  "type": "boolean"
        +}
  4. 1 tool updatev5.12.0
    • Addedfaf_bench
  5. 23 tool updatesv5.11.0
    • Removedfaf
    • Removedfaf_agents
    • Removedfaf_bi_sync
    • Removedfaf_check
    • Removedfaf_clear
    • Removedfaf_conductor
    • Removedfaf_cursor
    • Removedfaf_debug
    • Removedfaf_dna
    • Removedfaf_formats
    • Removedfaf_friday
    • Removedfaf_gemini
    • Removedfaf_git
    • Removedfaf_guide
    • Removedfaf_human_add
    • Removedfaf_list
    • Removedfaf_quick
    • Removedfaf_read
    • Removedfaf_readme
    • Removedfaf_setup
    • Removedfaf_status
    • Removedfaf_tri_sync
    • Removedfaf_write
  6. 13 tool updatesv5.9.0
    • Removedfaf_chat
    • Changedfaf_check1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "description": "Human-context quality report, or the result of a protect/unlock action.",
        +  "properties": {
        +    "emptyCount": {
        +      "description": "Fields that are empty",
        +      "type": "number"
        +    },
        +    "fields": {
        +      "additionalProperties": {
        +        "properties": {
        +          "protected": {
        +            "type": "boolean"
        +          },
        +          "quality": {
        +            "description": "empty | generic | good | excellent",
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "description": "Per-field quality + protection (report mode)",
        +      "type": "object"
        +    },
        +    "goodCount": {
        +      "description": "Fields rated good or excellent",
        +      "type": "number"
        +    },
        +    "mode": {
        +      "description": "report | protect | unlock",
        +      "type": "string"
        +    },
        +    "protected": {
        +      "description": "Field names currently protected",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "protectedNow": {
        +      "description": "Fields newly protected by this call (protect mode)",
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "qualityPercent": {
        +      "description": "Share of fields rated good/excellent (report mode)",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "mode"
        +  ],
        +  "type": "object"
        +}
    • Changedfaf_context1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "description": "The active project context and whether a project.faf lives there.",
        +  "properties": {
        +    "active": {
        +      "description": "Absolute path of the active project",
        +      "type": "string"
        +    },
        +    "changed": {
        +      "description": "True if this call set a new context, false if it only reported",
        +      "type": "boolean"
        +    },
        +    "filename": {
        +      "description": "The .faf filename, if found",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "hasFaf": {
        +      "description": "Whether a project.faf (or .faf) was found there",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "active",
        +    "hasFaf",
        +    "changed"
        +  ],
        +  "type": "object"
        +}
    • Changedfaf_dna1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "description": "The project's score history: birth DNA, current score, growth, and milestones.",
        +  "properties": {
        +    "authenticated": {
        +      "description": "Whether the birth certificate is authenticated",
        +      "type": "boolean"
        +    },
        +    "birthScore": {
        +      "description": "Score at birth",
        +      "type": "number"
        +    },
        +    "certificate": {
        +      "description": "Birth certificate ID",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "currentScore": {
        +      "description": "Current score",
        +      "type": "number"
        +    },
        +    "daysActive": {
        +      "description": "Days since birth",
        +      "type": "number"
        +    },
        +    "hasDna": {
        +      "description": "Whether a .faf-dna history exists (or was just created)",
        +      "type": "boolean"
        +    },
        +    "hasFaf": {
        +      "description": "Whether a project.faf was found",
        +      "type": "boolean"
        +    },
        +    "justBorn": {
        +      "description": "True if this call created the birth certificate",
        +      "type": "boolean"
        +    },
        +    "milestones": {
        +      "description": "Recorded milestones",
        +      "items": {
        +        "properties": {
        +          "date": {
        +            "type": "string"
        +          },
        +          "score": {
        +            "type": "number"
        +          },
        +          "type": {
        +            "type": "string"
        +          },
        +          "version": {
        +            "type": "string"
        +          }
        +        },
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "totalGrowth": {
        +      "description": "currentScore - birthScore",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "hasFaf",
        +    "hasDna"
        +  ],
        +  "type": "object"
        +}
    • Changedfaf_doctor1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "description": "Health check: an overall verdict plus per-check diagnostics with fixes.",
        +  "properties": {
        +    "checks": {
        +      "description": "Number of checks run",
        +      "type": "number"
        +    },
        +    "diagnostics": {
        +      "description": "Per-check results",
        +      "items": {
        +        "properties": {
        +          "fix": {
        +            "description": "Suggested fix, if any",
        +            "type": "string"
        +          },
        +          "message": {
        +            "type": "string"
        +          },
        +          "status": {
        +            "description": "ok | warning | error",
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "status",
        +          "message"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "errors": {
        +      "description": "Count of error-level findings",
        +      "type": "number"
        +    },
        +    "health": {
        +      "description": "Overall verdict: ok | warning | error",
        +      "type": "string"
        +    },
        +    "warnings": {
        +      "description": "Count of warning-level findings",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "health",
        +    "checks",
        +    "diagnostics"
        +  ],
        +  "type": "object"
        +}
    • Addedfaf_etch
    • Changedfaf_formats1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "description": "Formats discovered in the project and the stack signature derived from them.",
        +  "properties": {
        +    "count": {
        +      "description": "Number of known formats discovered",
        +      "type": "number"
        +    },
        +    "directory": {
        +      "description": "Directory that was scanned",
        +      "type": "string"
        +    },
        +    "elapsedMs": {
        +      "description": "Discovery time in milliseconds",
        +      "type": "number"
        +    },
        +    "formats": {
        +      "description": "Discovered formats",
        +      "items": {
        +        "properties": {
        +          "category": {
        +            "type": "string"
        +          },
        +          "fileName": {
        +            "type": "string"
        +          },
        +          "priority": {
        +            "type": "number"
        +          }
        +        },
        +        "required": [
        +          "fileName"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "intelligenceScore": {
        +      "description": "Total intelligence score across discovered formats",
        +      "type": "number"
        +    },
        +    "slotFillRecommendations": {
        +      "additionalProperties": {
        +        "type": "string"
        +      },
        +      "description": "Recommended .faf slot fills derived from discovered formats",
        +      "type": "object"
        +    },
        +    "stackSignature": {
        +      "description": "Derived stack signature",
        +      "type": "string"
        +    }
        +  },
        +  "required": [
        +    "directory",
        +    "count",
        +    "formats"
        +  ],
        +  "type": "object"
        +}
    • Changedfaf_list1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "description": "Directory entries, with project.faf discovery flagged per entry.",
        +  "properties": {
        +    "directory": {
        +      "description": "Absolute path that was scanned",
        +      "type": "string"
        +    },
        +    "entries": {
        +      "description": "The listed entries",
        +      "items": {
        +        "properties": {
        +          "hasFaf": {
        +            "type": "boolean"
        +          },
        +          "isDir": {
        +            "type": "boolean"
        +          },
        +          "name": {
        +            "type": "string"
        +          },
        +          "path": {
        +            "type": "string"
        +          }
        +        },
        +        "required": [
        +          "name",
        +          "path",
        +          "hasFaf",
        +          "isDir"
        +        ],
        +        "type": "object"
        +      },
        +      "type": "array"
        +    },
        +    "fafProjects": {
        +      "description": "How many entries contain a project.faf",
        +      "type": "number"
        +    },
        +    "filter": {
        +      "description": "Filter applied: faf | dirs | all",
        +      "type": "string"
        +    },
        +    "total": {
        +      "description": "Number of entries returned",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "directory",
        +    "total",
        +    "entries"
        +  ],
        +  "type": "object"
        +}
    • Addedfaf_recall
    • Changedfaf_score1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "description": "Structured AI-readiness score, single-sourced from faf-cli.",
        +  "properties": {
        +    "active": {
        +      "description": "Slots active for this app_type",
        +      "type": "number"
        +    },
        +    "empty": {
        +      "description": "Active slots still empty",
        +      "type": "number"
        +    },
        +    "hasFaf": {
        +      "description": "Whether a readable, valid project.faf was scored",
        +      "type": "boolean"
        +    },
        +    "ignored": {
        +      "description": "Slots marked slotignored (inactive for this app_type)",
        +      "type": "number"
        +    },
        +    "inherited": {
        +      "description": "True if the score is attested from a source repo (app_type: about)",
        +      "type": "boolean"
        +    },
        +    "nextTier": {
        +      "description": "Next tier above the current score, or null at top tier",
        +      "properties": {
        +        "name": {
        +          "type": "string"
        +        },
        +        "threshold": {
        +          "type": "number"
        +        }
        +      },
        +      "type": [
        +        "object",
        +        "null"
        +      ]
        +    },
        +    "parity": {
        +      "description": "Determinism parity receipt — an engine-agnostic hash any conformant scorer reproduces for this exact file. Third-party verifiable: sha256(projection) === parityHash.",
        +      "properties": {
        +        "algo": {
        +          "description": "Hash algorithm (sha256)",
        +          "type": "string"
        +        },
        +        "parityHash": {
        +          "description": "sha256(projection) — identical across any conformant engine",
        +          "type": "string"
        +        },
        +        "producedBy": {
        +          "description": "Which wrapper emitted this receipt (metadata, not hashed)",
        +          "type": "string"
        +        },
        +        "projection": {
        +          "description": "The exact canonical string that was hashed (for verification)",
        +          "type": "string"
        +        },
        +        "scorer": {
        +          "description": "The single deterministic source the score comes from",
        +          "type": "string"
        +        },
        +        "sourceSha256": {
        +          "description": "SHA-256 of the raw .faf bytes",
        +          "type": "string"
        +        },
        +        "spec": {
        +          "description": "Parity spec id, e.g. faf-parity/v1",
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "spec",
        +        "parityHash",
        +        "sourceSha256",
        +        "projection"
        +      ],
        +      "type": "object"
        +    },
        +    "path": {
        +      "description": "Path that was scored",
        +      "type": "string"
        +    },
        +    "populated": {
        +      "description": "Active slots that are filled",
        +      "type": "number"
        +    },
        +    "score": {
        +      "description": "AI-readiness score, 0-100",
        +      "type": "number"
        +    },
        +    "tier": {
        +      "description": "Tier name for this score (e.g. Bronze, Trophy)",
        +      "type": "string"
        +    },
        +    "total": {
        +      "description": "Total slots",
        +      "type": "number"
        +    }
        +  },
        +  "required": [
        +    "score",
        +    "tier",
        +    "hasFaf"
        +  ],
        +  "type": "object"
        +}
    • Addedfaf_setup
    • Changedfaf_status1 field changed
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "description": "Whether the project has a project.faf and where it lives.",
        +  "properties": {
        +    "directory": {
        +      "description": "Directory that was checked",
        +      "type": "string"
        +    },
        +    "filename": {
        +      "description": "The .faf filename, if found",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    },
        +    "hasFaf": {
        +      "description": "Whether a project.faf (or .faf) was found",
        +      "type": "boolean"
        +    },
        +    "path": {
        +      "description": "Absolute path to the .faf file, if found",
        +      "type": [
        +        "string",
        +        "null"
        +      ]
        +    }
        +  },
        +  "required": [
        +    "hasFaf",
        +    "directory"
        +  ],
        +  "type": "object"
        +}
    • Changedfaf_trust2 fields changed
      • addedInput schema / properties / path
        Added value: +{
        +  "description": "Project path. Sets session context for subsequent calls.",
        +  "type": "string"
        +}
      • changedOutput schema / (root)
        Previous value: -nullNew value: +{
        +  "additionalProperties": true,
        +  "description": "Trust attestation: validity, score, and a third-party-verifiable determinism parity receipt.",
        +  "properties": {
        +    "hasFaf": {
        +      "description": "Whether a project.faf was found",
        +      "type": "boolean"
        +    },
        +    "parity": {
        +      "description": "Determinism parity receipt (same shape as faf_score.parity).",
        +      "properties": {
        +        "algo": {
        +          "type": "string"
        +        },
        +        "parityHash": {
        +          "type": "string"
        +        },
        +        "producedBy": {
        +          "type": "string"
        +        },
        +        "projection": {
        +          "type": "string"
        +        },
        +        "scorer": {
        +          "type": "string"
        +        },
        +        "sourceSha256": {
        +          "type": "string"
        +        },
        +        "spec": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "spec",
        +        "parityHash",
        +        "sourceSha256",
        +        "projection"
        +      ],
        +      "type": "object"
        +    },
        +    "path": {
        +      "description": "Path that was attested",
        +      "type": "string"
        +    },
        +    "reason": {
        +      "description": "Why validation failed, when valid is false",
        +      "type": "string"
        +    },
        +    "receipt": {
        +      "description": "The ✪ trust receipt — render-identical, self-verifying score+parity artifact.",
        +      "properties": {
        +        "issued": {
        +          "type": [
        +            "string",
        +            "null"
        +          ]
        +        },
        +        "score": {
        +          "type": "number"
        +        },
        +        "seal": {
        +          "description": "Quiet-ladder glyph for this score (✪ at Trophy)",
        +          "type": "string"
        +        },
        +        "spec": {
        +          "type": "string"
        +        },
        +        "subject": {
        +          "type": "string"
        +        },
        +        "tests": {
        +          "description": "Optional test attestation",
        +          "type": [
        +            "object",
        +            "null"
        +          ]
        +        },
        +        "tier": {
        +          "type": "string"
        +        }
        +      },
        +      "required": [
        +        "spec",
        +        "seal",
        +        "subject",
        +        "score"
        +      ],
        +      "type": "object"
        +    },
        +    "score": {
        +      "description": "AI-readiness score, 0-100",
        +      "type": "number"
        +    },
        +    "sourceSha256": {
        +      "description": "SHA-256 of the raw .faf bytes",
        +      "type": "string"
        +    },
        +    "tier": {
        +      "description": "Tier name for this score",
        +      "type": "string"
        +    },
        +    "valid": {
        +      "description": "Whether the project.faf is readable and valid",
        +      "type": "boolean"
        +    }
        +  },
        +  "required": [
        +    "valid",
        +    "hasFaf"
        +  ],
        +  "type": "object"
        +}

TDQS

A3.9/5.0

Scored across 14 tools

Disambiguation3/5

Several tools overlap around reading the .faf: faf_score, faf_doctor, faf_trust, and faf_context all read/scorer the same file with subtle differences (score vs. diagnose vs. attest vs. active project). faf_sync and faf_tri_sync both write faf-managed blocks and only differ by target file, and faf_init/faf_auto/faf_go all create or fill slots. Descriptions do clarify the distinctions, but an agent could easily pick the wrong read or write tool.

Naming Consistency4/5

All tools use the faf_ prefix with a short lowercase verb or concept (faf_about, faf_score, faf_init, faf_sync, faf_go, faf_etch, faf_recall). The pattern is consistent and readable, though the second token is sometimes a verb and sometimes a noun (about, context, bench), so it is not a strict verb_noun convention.

Tool Count4/5

14 tools is within the reasonable 3-15 range for a server covering the full .faf lifecycle (init, fill, score, diagnose, sync, memory, attest, bench). It is on the heavier side but each tool has a distinct conceptual role, so the count is defensible.

Completeness4/5

The surface covers the .faf lifecycle well: create (faf_init), auto-fill and human answers (faf_auto, faf_go), read/score/validate (faf_score, faf_doctor, faf_trust), write to editor files (faf_sync, faf_tri_sync), session hook setup (faf_setup), and memory (faf_etch, faf_recall). Minor gaps exist, e.g. no explicit delete/remove for project.faf or memories, but core workflows are complete.

Maintenance

ActivityActive
ResponsivenessSlow

Related MCP Connectors

Related MCP Servers