Skip to main content
Fracta ships a curated catalog of MCP server definitions and a fracta config mcp command suite that turns them into per-mode deployment config. This page is the operator narrative: when to use which verb, what gets committed where, and how org-private catalogs fit in. For the exhaustive flag reference, see fracta config mcp. For the schema of a server.yaml entry, see MCP Servers Catalog.

The mental model

Three things to keep separate:
  1. The catalog — a tree at <root>/mcp-servers/ containing one server.yaml per MCP server fracta knows about. Operator-owned, git-tracked, edited like any other config.
  2. Your scaffold — the per-mode files fracta init wrote (fracta.yaml, plus deployment/docker-compose.yml or deployment/k8s/manifests/ depending on the mode).
  3. fracta config mcp — the CLI that reads (1) and mutates (2) on your behalf.
fetch populates (1). add reads (1) and writes (2). Both are reversible.

The default workflow

From a fresh project:
git init my-fracta-deploy && cd my-fracta-deploy
fracta init --scaffold k8s             # or local / docker-compose

fracta config mcp fetch                # pulls from github:darkquasar/fracta@main by default
git add mcp-servers/ && git commit -m "fetch fracta MCP catalog"

fracta config mcp list                 # browse what's available
fracta config mcp inspect elastic      # full per-server metadata
fracta config mcp add elastic          # writes fracta.yaml + deployment/k8s/manifests/elastic-mcp.yaml
git add . && git commit -m "add elastic MCP server"
Three commits land on your repo: the scaffold (fracta init), the catalog (fetch), and each server (add). Reviewing those PRs is the whole point — your team sees exactly which image, which auth mode, and which endpoint is being introduced before it hits production.

What add writes per mode

ModeFiles touched
localfracta.yaml only (inserts mcp_servers.servers.<id>.local)
docker-composefracta.yaml + deployment/docker-compose.yml + .env.example
k8sfracta.yaml + deployment/k8s/manifests/<id>-mcp.yaml + deployment/k8s/manifests/<id>-mcp-secret.yaml (if the server needs env vars)
add refuses to run if the scaffold for the chosen mode isn’t present — the error names the prereq command (fracta init --scaffold <mode>) verbatim.

The pre-flight summary

Every add shows you what it’s about to do and waits for confirmation:
Adding 'elastic' for target-deployment 'k8s':
  Container required:    yes (image: docker.elastic.co/mcp/elasticsearch:latest, owner: external)
  Container build:       not required (public image)
  Image present locally: yes (docker)
  Auth: env_token; you must populate ES_URL and ES_API_KEY in a Secret
  Files to be written:
    + deployment/k8s/manifests/elastic-mcp.yaml
    + deployment/k8s/manifests/elastic-mcp-secret.yaml
    ~ fracta.yaml
Proceed? [y/N]
Pass --yes in CI. Pass --dry-run to see the summary without writing.

Removing a server

fracta config mcp remove <server> reverses an add: it deletes the per-mode manifest and removes the mcp_servers.servers.<id> block from fracta.yaml. The result is byte-identical to the pre-add state (modulo filesystem timestamps). If add fails partway through a multi-file write, the rollback is automatic — transient .bak files restore the original content and are then removed. After a successful add, no .bak files remain on disk.

Why the catalog is checked in

The fetched mcp-servers/ directory is first-class config, not a cache. It belongs in git for three reasons:
  • Audit. Reviewers should see the image refs and OAuth endpoints before they ship. A git diff on mcp-servers/elastic/server.yaml makes that review trivial.
  • Local entries. Operators routinely add servers that aren’t in the canonical catalog — an internal CRM MCP, a vendor-specific bridge. Those live as mcp-servers/<id>/server.yaml alongside the fetched ones; fetch --merge preserves them.
  • Reproducibility. The catalog’s version: field bumps over time. Pinning a specific version in git means everyone on the team runs against the same definitions.
Fracta deliberately does not bake the catalog into the binary. fracta config mcp list errors with a clear remediation if <root>/mcp-servers/ is missing:
no catalog found at <root>/mcp-servers/
run 'fracta config mcp fetch' to populate it (default source: github:darkquasar/fracta@main)

Catalog sources

fracta config mcp fetch [<source>] accepts the same syntax everywhere fracta takes a source:
FormExampleNotes
Default (canonical)fracta config mcp fetchEquivalent to github:darkquasar/fracta@main
GitHub repofracta config mcp fetch github:acme/fracta-cat@v1Tag, branch, or sha after @
Browser-pasted URLfracta config mcp fetch https://github.com/acme/fracta-catTrailing slash and .git suffix tolerated
SSH formfracta config mcp fetch git@github.com:acme/fracta-cat.git@v1Pasted from git remote -v; fetched over HTTPS regardless
Raw tarballfracta config mcp fetch https://example.com/cat.tar.gzExpects mcp-servers/ at archive root
Local directoryfracta config mcp fetch ./internal-catReads <path>/mcp-servers/
After a successful non-merge fetch, the source is recorded in mcp-servers/.fracta-source. Subsequent fetch calls without arguments use the recorded source rather than the global default.

Replace vs merge

By default fetch is replace: the existing mcp-servers/ is removed and rewritten from the source. Pass --merge to overlay the source’s entries on top of what you have, preserving local-only entries by id. Merge does not update .fracta-source — it’s a one-shot overlay, not a primary-source change.
# Canonical only
fracta config mcp fetch

# Org overlay on top of canonical
fracta config mcp fetch                                              # 14 canonical entries
fracta config mcp fetch github:acme/fracta-mcp-catalog@v1 --merge    # adds 3 acme entries

git diff mcp-servers/                                                # review before commit

Trust boundaries

SourceTrust
github:darkquasar/fracta@mainThe darkquasar/fracta GitHub repo. Pin with --source-checksum if using the tag-archive HTTPS form.
Custom github sourceThe org or user that owns the repo.
HTTPS tarballThe host serving it. --source-checksum sha256:... recommended.
Local directoryYou.
add is interactive by default and shows every image ref before writing — operators audit at the moment of adoption, not as a separate exercise.

Org-private catalogs

Mirror the canonical schema (catalog.yaml + mcp-servers/<id>/server.yaml) in any GitHub repo, HTTPS tarball, or local directory. There’s no fracta-side registration — the source spec is the entire interface.
acme/fracta-mcp-catalog/
├── README.md
├── catalog.yaml                    # version: 3
└── mcp-servers/
    ├── catalog.yaml
    ├── acme-crm/server.yaml
    ├── acme-soc/server.yaml
    └── acme-vendor/server.yaml
Authoring loop for the org admin:
cd ~/work/fracta-mcp-catalog
mkdir mcp-servers/acme-newthing
$EDITOR mcp-servers/acme-newthing/server.yaml
$EDITOR mcp-servers/catalog.yaml         # add { id: acme-newthing, path: acme-newthing/server.yaml }
$EDITOR catalog.yaml                     # bump version: 4
git commit -am "add acme-newthing" && git tag v1.5 && git push --tags
Operators on the team then run:
fracta config mcp fetch github:acme/fracta-mcp-catalog@v1.5
For CI reproducibility, pin a specific archive sha256 via the HTTPS tarball form:
fracta config mcp fetch \
  https://github.com/acme/fracta-mcp-catalog/releases/download/v1.5/catalog.tar.gz \
  --source-checksum sha256:abc123...

Diffing local vs remote

fracta config mcp list --remote compares the local catalog against the canonical remote without writing anything. Use it as a “what’s new upstream” check before deciding to refetch:
SERVER         LOCAL                          REMOTE   DELTA          AUTH        DESCRIPTION
elastic        configured (k8s+compose)       v2       up-to-date     env_token   Elasticsearch-backed search/enrichment
notion         not configured                 v2       available      oauth       Notion knowledge graph
google-drive   not configured                 v2       available      oauth       Google Drive/Workspace
zotero         not configured                 v2       available      bearer      Zotero papers/citations
To incorporate remote-only entries, run fracta config mcp fetch --merge (preserves local-only) or fracta config mcp fetch (wholesale replace).

OAuth-protected servers

Some MCP servers (Notion, Readwise, Google Drive) authenticate via OAuth rather than env tokens. The credential flow stays under fracta config mcp auth:
fracta config mcp auth login notion       # opens browser
fracta config mcp auth status             # what's authenticated
fracta config mcp auth export notion      # token export for CI
fracta config mcp auth logout notion
These are the same runners that used to live at fracta mcp <verb> — the deprecated alias still works for one minor release.

What’s next