loading…
Search for a command to run...
loading…
This MCP server provides a deterministic index of the First Principles Framework (FPF) spec, enabling agents to query patterns, routes, and relations without ve
This MCP server provides a deterministic index of the First Principles Framework (FPF) spec, enabling agents to query patterns, routes, and relations without vector databases.
FPF helps when raw insight is not enough: meanings, claims, alternatives, evidence, boundaries, and outputs must remain stable across contexts, time, people, tools, or AI agents.
Quick links: Website · Connect MCP · Hosted MCP endpoint
📖 Live reference: fpf.sh — searchable pattern catalog, routes, and preface. Type an ID like
A.2orroute:project-alignmentin the search box to jump in.🤖 Working with this repo as an agent? See AGENTS.md for the MCP tool guide and workspace conventions.
🧭 Coordinating repo automation? See the Automation Playbook for role boundaries, access rules, merge authority, and draft-only publishing packets.
The First Principles Framework (FPF) is a structured framework for thinking and coordinating work. It is written more like a technical specification than like a management book: there are named patterns, definitions, and review rules. Its job is to help teams model complex work, make reasoning inspectable, and keep decisions stable across engineering, research, and management.
FPF is authored by Anatoly Levenchuk. The upstream publication source this runtime tracks is github.com/ailev/FPF, specifically FPF-Spec.md on main by default. This repository is a runtime + slim wiki projection of the published spec, not the spec itself.
A local FPF spec runtime. Given a single markdown spec file, it compiles a deterministic, vectorless index of FPF IDs, routes, relations, and anchors, and exposes that as:
No vector database, no remote indexing, no Python. Optional local LLM synthesis via LM Studio is layered on top of deterministic retrieval — it is never the primary search path.
bun install
cp .env.example .env # see Configuration below
bun run spec:download # fetch FPF-Spec.md into .fpf-upstream/
bun run publish:current # refresh the committed published/current/** surface
bun run cli -- query --question "What is U.BoundedContext?" --mode verbose
To run the local MCP server (full surface, expert tools enabled):
FPF_MCP_SURFACE=full bun run mcp
To browse docs locally:
bun run docs:dev
On each refresh trigger the runtime:
FPF_SPEC_SOURCE_PATH and reuses the snapshot if the hash matchessnapshot.json, build-audit.json, index-map.json, indexing-view.json, pattern-graph.json, route-graph.json, lexicon.json, and anchor-map.json under FPF_RUNTIME_ARTIFACT_DIR (default .runtime/fpf-index/)query or trace is called with --session / sessionIdIn:
published/current/FPF-Spec.md).fpf-upstream/FPF-Spec.md, or any local checkout via FPF_PUBLISH_SOURCE_PATHdocs/generated/** (not committed; produced by bun run docs:generate)doc_build/ (deterministic, ignored)Out:
.github/workflows/sync-fpf.yml keeps both public surfaces current when FPF changes upstream in ailev/FPF:
repository_dispatch event named fpf-origin-updated with client_payload.sha/after, client_payload.ref/branch, and optionally client_payload.spec_url.FPF-Spec.md, run publish:current, validate published/current/**, build the static docs, build the Vercel-origin MCP bundle, and open a publication PR only when files changed.main push gives Vercel's Git integration the refreshed fpf.sh inputs.Minimal dispatch payload:
{
"event_type": "fpf-origin-updated",
"client_payload": {
"sha": "<ailev/FPF commit sha>"
}
}
Copy .env.example to .env. The most common settings:
| Variable | Default | Purpose |
|---|---|---|
FPF_SPEC_SOURCE_PATH |
published/current/FPF-Spec.md |
Local path to the spec the runtime reads (must be a filesystem path). |
FPF_PUBLISH_SOURCE_PATH |
.fpf-upstream/FPF-Spec.md |
Local source used by publish:current. |
FPF_UPSTREAM_OWNER |
ailev |
GitHub owner for upstream publication provenance and downloads. |
FPF_UPSTREAM_REPO |
FPF |
GitHub repo for upstream publication provenance and downloads. |
FPF_UPSTREAM_REF |
main |
Branch, tag, or SHA used by spec:download and publish:current. |
FPF_UPSTREAM_SPEC_PATH |
FPF-Spec.md |
Path to the spec inside the upstream repo. |
FPF_RUNTIME_ARTIFACT_DIR |
.runtime/fpf-index |
Where compiled artifacts are written. |
FPF_QUERY_DEFAULT_MODE |
verbose |
Default mode for query_fpf_spec and ask_fpf. |
FPF_LOCAL_LLM_BASE_URL |
http://localhost:1234/v1 |
Optional LM Studio endpoint. Omit to stay fully deterministic. |
FPF_LOCAL_LLM_MODEL |
google/gemma-4-31b |
Optional LM Studio model. |
FPF_LOCAL_LLM_API_KEY |
(empty) | LM Studio API token (Developer → Server Settings → Manage Tokens). |
FPF_LOCAL_LLM_TIMEOUT_MS |
20000 |
LM Studio request timeout. |
FPF_RUNTIME_LOG_PATH |
.runtime/logs/fpf-runtime.log |
Structured runtime/MCP logs. |
FPF_RUNTIME_OBSERVABILITY_PATH |
.runtime/logs/runtime-observability.json |
Observability snapshot file. |
FPF_AI_TRACE_LOG_PATH |
.runtime/logs/ai-traces.jsonl |
Per-call LM Studio synthesis traces (JSONL). |
FPF_SPEC_SOURCE_PATH must be a local filesystem path — the runtime does not fetch https:// URLs. The default is the committed publication surface: published/current/FPF-Spec.md. Local memory preparation uses FPF_PUBLISH_SOURCE_PATH, which defaults to .fpf-upstream/FPF-Spec.md after bun run spec:download. You can instead point FPF_PUBLISH_SOURCE_PATH at a local checkout of github.com/ailev/FPF such as FPF-Spec.md. bun run spec:download tracks ailev/FPF main by default; the sync workflow resolves one upstream ref and passes it to both download and publish before writing published/current/manifest.json. Override owner/repo/ref/spec path with FPF_UPSTREAM_OWNER, FPF_UPSTREAM_REPO, FPF_UPSTREAM_REF, and FPF_UPSTREAM_SPEC_PATH; override the raw download URL or output path with FPF_UPSTREAM_SPEC_URL and FPF_DOWNLOAD_SPEC_OUTPUT. In automation, a raw spec_url must be paired with an explicit ref or SHA so manifest provenance remains verifiable. Keep FPF_SPEC_SOURCE_PATH aligned across .env, your shell, and any MCP config (server.json env) so every runtime/docs entrypoint agrees on the published file it should read.
FPF_QUERY_DEFAULT_MODE applies to query_fpf_spec and ask_fpf when mode is omitted. trace_fpf_path stays compact by default.
FPF_LOCAL_LLM_* is optional. If present, the runtime calls the local LM Studio Anthropic-compatible API (POST /v1/messages with model discovery at GET /v1/models) only after deterministic retrieval has selected a bounded slice set. If absent, the runtime stays fully deterministic. If you opt into the LM Studio path by setting either FPF_LOCAL_LLM_BASE_URL or FPF_LOCAL_LLM_MODEL, the missing half falls back to the defaults above. The synthesizer posts to {FPF_LOCAL_LLM_BASE_URL}/messages with the Anthropic Messages request shape (system + messages + max_tokens) and parses content[].text from the response.
FPF_RUNTIME_OBSERVABILITY_* configures the runtime observability snapshot file, which includes model_generation spans around the local LM Studio synthesis call. Additional knobs: FPF_RUNTIME_LOG_LEVEL=info, FPF_RUNTIME_OBSERVABILITY_FORMAT=flat, FPF_RUNTIME_OBSERVABILITY_INCLUDE_INTERNAL_SPANS=true, FPF_RUNTIME_OBSERVABILITY_INCLUDE_MODEL_CHUNKS=false, FPF_RUNTIME_OBSERVABILITY_LOG_LEVEL=info.
FPF_AI_TRACE_LOG_PATH writes bounded LM Studio synthesis traces as JSON lines. This is the actual local model call path in this project; the synthesizer uses a direct fetch to the LM Studio-compatible endpoint.
Grouped by what you're trying to do. See package.json for the full list.
Setup & publishing
bun install
bun run spec:download # download FPF-Spec.md into .fpf-upstream/
bun run publish:current # refresh published/current/** from FPF_PUBLISH_SOURCE_PATH
bun run stage:from-published # stage published/current/** for commit
bun run hooks:install # install local git hooks
Develop, test, build
bun run lint
bun run check
bun run test
bun run build
bun run vercel:origin:build
Docs
bun run docs:generate # produce docs/generated/** from the published surface
bun run docs:build # static build into doc_build/
bun run docs:dev # local docs site
CLI
bun run cli -- status
bun run cli -- refresh
bun run cli -- query --question "What is U.BoundedContext?" --mode verbose
bun run cli -- query --question "How does it connect to role assignment?" --session s1
bun run cli -- inspect --selector "A.1.1"
bun run cli -- read-doc --selector "A.1.1"
bun run cli -- trace --question "How do U.RoleAssignment and U.BoundedContext connect?" --mode proof --session s1
bun run cli -- lm-check --timeout-ms 60000
MCP server
bun run mcp # public surface
FPF_MCP_SURFACE=full bun run mcp # full surface (expert tools)
bun run start # hosted HTTP runtime on Hono
bun run smoke:mcp:http # smoke-test the streamable HTTP endpoint
bun run bench:mcp:qa # hosted Q&A correctness gate
bun run bench:mcp # hosted latency/correctness benchmark
bun run vercel:origin:build # prebuild the direct Vercel-origin bundle
Public hosted status endpoint:
/api/fpf/status
This returns the published upstreamRef, sourceHash, publishedAt, specBytes, and runtime freshness evidence for the same bundled FPF source and snapshot used by the hosted MCP endpoint.
Deterministic, local FPF-grounded review of the current branch or worktree:
bun run evaluate:work
bun run cli -- evaluate-work --target current-pr --base origin/main --format markdown
bun run cli -- evaluate-work --target working-tree --base origin/main --format json
bun run cli -- evaluate-work --spec ~/Downloads/FPF-Spec\(12\).md --out reports/fpf-work.md
The evaluator reads local git facts, the committed published/current/** surface, and the configured FPF spec. It does not call an LLM, fetch GitHub, or regenerate artifacts. By default it reads FPF_SPEC_SOURCE_PATH if set, otherwise published/current/FPF-Spec.md; it does not fall back to .fpf-upstream/.
The current Codex default is the hosted public MCP:
https://mcp.fpf.sh/api/mcp/fpf_memory/mcp
Equivalent ~/.codex/config.toml:
[mcp_servers.fpf_memory]
url = "https://mcp.fpf.sh/api/mcp/fpf_memory/mcp"
This repo ships the same project-scoped configuration at .codex/config.toml and .mcp.json. Once the project is trusted, Codex can load the hosted fpf_memory server directly from the repo.
Recommended Codex tasks (public surface):
Use only the fpf_memory MCP server. Call ask_fpf with question: "What is U.PromiseContent?"Use only the fpf_memory MCP server. Call query_fpf_spec with question: "What is an FPF pattern?"Use only the fpf_memory MCP server. Call read_fpf_doc with selector: "A.1.1"Use only the fpf_memory MCP server. Call get_fpf_index_statusExpert tasks (require local full-surface runtime, FPF_MCP_SURFACE=full bun run mcp):
Use only the fpf_memory MCP server. Call trace_fpf_path with question: "How do U.RoleAssignment and U.BoundedContext connect?"Use only the fpf_memory MCP server. Call refresh_fpf_indexSmoke-test the local full-surface runtime before using expert tools or deploying changes:
bun run cli -- status
bun run cli -- lm-check --timeout-ms 60000
bun run cli -- refresh
bun run cli -- query --question "What is U.BoundedContext?" --mode verbose
bun run cli -- trace --question "How do U.RoleAssignment and U.BoundedContext connect?" --mode proof
bun run cli -- inspect --selector "A.1.1"
The direct stdio launcher (same entry as bun run mcp):
FPF_MCP_SURFACE=full bun run mcp
This starts a long-running stdio server; for a manual smoke check, stop it with Ctrl+C after startup confirmation. Omit FPF_MCP_SURFACE=full if you only want the public surface.
If this repo is registered as a Codex MCP server, restart Codex after changes and then test with a forced tool-use prompt:
Use only the fpf_memory MCP server.
Call ask_fpf with:
- question: "Give me a checklist for how to model my project's information system."
For a proof-style grounded answer, add mode: "proof". For the raw structured envelope, call query_fpf_spec instead. For a deterministic retrieval/debug trace, call trace_fpf_path.
The direct Vercel origin is canonical for clients. There is no separate Vercel forwarding project in this repo.
bun run vercel:origin:link
bun run vercel:origin:build
bun run vercel:origin:deploy:prod
FPF_MCP_SMOKE_URL=https://mcp.fpf.sh/api/mcp/fpf_memory/mcp bun run smoke:mcp:http
bun run bench:mcp:qa -- --name vercel-origin --url https://mcp.fpf.sh/api/mcp/fpf_memory/mcp --format markdown
Status API:
https://mcp.fpf.sh/api/fpf/status
Public (default surface):
browse_fpf_catalog — task-oriented discovery by part, status, or kindsearch_fpf — full-text search across compiled nodesask_fpf — markdown-first answersquery_fpf_spec — structured answer enveloperead_fpf_doc — exact generated markdown pagesget_fpf_index_status — runtime freshness checkFull-surface only (FPF_MCP_SURFACE=full):
inspect_fpf_node, inspect_fpf_anchor, expand_fpf_citations — deep inspectiontrace_fpf_path — retrieval evidence and provenancerefresh_fpf_index — rebuild the local artifact setOnly query_fpf_spec and ask_fpf can use the optional synthesizer. All other MCP tools stay deterministic. Set FPF_MCP_SURFACE=public on the deployed server to restrict it to public tools only.
When a configured synthesizer fails or reports unavailable, answer tools return degraded with low confidence and candidateIds; deterministic citations, relations, and constraints remain available as evidence. Deterministic retrieval tools still return normal ok envelopes.
Runtime surfaces
src/mcp/tool-contracts.ts — Zod-authored MCP input/output contractssrc/adapters/mcp/tools.ts — canonical snake_case MCP tools and ask_fpfsrc/adapters/mcp/server.ts — direct MCP SDK server definitions (public + full)src/composition/ — canonical bridge layer for runtime/bootstrap compositionsrc/entrypoints/mcp-stdio.ts — stdio entry point for MCP clientssrc/entrypoints/vercel-function.ts — Vercel Build Output API function entry pointsrc/build/vercel-origin-build.ts — direct Vercel-origin bundle buildersrc/server.ts — Hono HTTP server bootstrap for Bunsrc/runtime/ — compiler, retrieval, trace, inspect, synthesissrc/adapters/infra/logging/runtime-logger.ts — structured runtime/MCP log writersrc/adapters/infra/observability/runtime-observability.ts — observability wrapper for local synthesisDocs
docs/ — Rspress content root populated by generated pages plus any optional hand-authored pagesdocs/generated/** — produced locally by docs:generate (gitignored; CI and docs deploy read the committed publication surface and generate from it)scripts/generate-docs.ts — compiler-backed docs generation (fed from published/current/** by default)rspress.config.ts — docs site configdoc_build/ — deterministic Rspress build output for the wiki-like static viewerThe docs pipeline does not use an LLM step. bun run docs:generate writes the canonical markdown collection, and bun run docs:build builds the static viewer from that collection.
Spec sources
FPF_SPEC_SOURCE_PATH — runtime spec path (default published/current/FPF-Spec.md; upstream lives in ailev/FPF)FPF_PUBLISH_SOURCE_PATH — local publish source (default .fpf-upstream/FPF-Spec.md after bun run spec:download).runtime/logs/fpf-runtime.log — structured runtime server/tool logs.runtime/logs/runtime-observability.json — observability snapshot containing manual LM Studio model_generation traces.runtime/logs/ai-traces.jsonl — request/response/error traces for local LM Studio synthesis callsIf you use FPF, please cite:
Levenchuk, Anatoly. First Principles Framework (FPF). GitHub repository: https://github.com/ailev/FPF
Run in your terminal:
claude mcp add fpf-memory -- npx Security
Low riskAutomated heuristic from public metadata — not a security guarantee.