Formidable MCP Companion
# Formidable MCP Companion
Offline documentation MCP server for [Formidable Forms](https://formidableforms.com/).
It mirrors the knowledge base into local markdown, indexes it at section level with
BM25, and exposes it to MCP clients such as Claude Desktop, Claude Code, and opencode.
This project is modeled on
[laravel-mcp-companion](https://github.com/brianirish/laravel-mcp-companion), scoped
to a single documentation source for a lean first release.
## Features
- **Offline corpus** — all Formidable knowledge base articles stored as markdown.
- **Section-level search** — BM25 over `##` sections, with a literal-substring
fallback for symbols such as `frm_validate_field_entry`.
- **Section reads** — fetch just the heading you need instead of a 30k-token page.
- **Category browsing** — the site's breadcrumb hierarchy (`forms/form-builder`, ...).
- **Incremental updates** — only articles whose upstream `lastmod` changed are fetched.
- **Safe path handling** — every read is contained to the local corpus.
- **MCP resources** — `formidable://docs/{doc}` and `formidable://category/{path}`.
## Quick start
```bash
cd /home/user444/Projects/ai/formidable-mcp-companion
python3 -m venv .venv
.venv/bin/pip install -e .
# Download the documentation (639 articles, roughly 10-20 minutes).
.venv/bin/python -m formidable_mcp.updater --docs-path docs
# Start the MCP server over stdio.
.venv/bin/formidable-mcp --docs-path docs
```
`--update-docs` refreshes the corpus before the server starts:
```bash
.venv/bin/formidable-mcp --docs-path docs --update-docs
```
## MCP client configuration
### Claude Desktop / Claude Code
```json
{
"mcpServers": {
"formidable": {
"command": "/home/user444/Projects/ai/formidable-mcp-companion/.venv/bin/python",
"args": [
"-m", "formidable_mcp",
"--docs-path", "/home/user444/Projects/ai/formidable-mcp-companion/docs"
]
}
}
}
```
### opencode
```json
{
"mcp": {
"formidable": {
"type": "local",
"command": [
"/home/user444/Projects/ai/formidable-mcp-companion/.venv/bin/python",
"-m", "formidable_mcp",
"--docs-path", "/home/user444/Projects/ai/formidable-mcp-companion/docs"
],
"enabled": true
}
}
}
```
## Tools
| Tool | Purpose |
| --- | --- |
| `search_docs(query, category?, limit?)` | Ranked sections with snippet, anchor, doc id |
| `read_doc_section(doc, section)` | Read one section by anchor or heading |
| `read_doc(doc)` | Read a full article |
| `list_docs(category?)` | List article metadata |
| `get_doc_structure(doc)` | Heading/anchor table of contents |
| `browse_docs_by_category(category)` | Subcategories and articles in a category |
| `list_categories()` | Every category path with counts |
| `get_docs_info()` | Article count, sync time, corpus age |
| `update_docs(force?, limit?)` | Refresh from formidableforms.com |
`doc` accepts either a full id (`forms/form-builder/field-options`) or a unique
slug (`field-options`).
## Corpus layout
```
docs/
├── formidable/
│ └── forms/
│ └── form-builder/
│ └── field-options.md
└── metadata/
├── index.json # article metadata, headings, anchors
└── sync.json # sync timestamps and failures
```
Each markdown file keeps the site's stable heading anchors:
```markdown
## Default Value {#kb-default-value}
```
## Updater options
```bash
.venv/bin/python -m formidable_mcp.updater \
--docs-path docs \
--force # refetch everything
--limit 10 # fetch at most 10 pending articles
--dry-run # fetch and parse without writing
--workers 2 # concurrent requests
--log-level INFO
```
The updater is deliberately polite: two workers, a short delay between requests,
and `Retry-After`-aware backoff on HTTP 429 responses.
## Development
```bash
.venv/bin/pip install -e ".[dev]"
.venv/bin/pytest -q
.venv/bin/ruff check src tests
```
## Notes
- Documentation content belongs to Strategy11, LLC (Formidable Forms). This
project only mirrors it for local reference; check the upstream terms before
redistributing the corpus.
- The parser targets the current WordPress/Heroic Knowledge Base markup. If the
site changes, update the selectors in `src/formidable_mcp/updater/parser.py`
and the noise list in `src/formidable_mcp/config.py`.
## License
Code: MIT. Documentation content: property of its respective owner.
TDQS
Scored across 9 tools
Most tools target distinct documentation operations, and the descriptions clearly steer agents from search to section reading. There is mild overlap between list_docs, browse_docs_by_category, and list_categories, but the descriptions make their boundaries understandable.
All tools use snake_case and generally follow a predictable verb_noun pattern such as search_docs, read_doc_section, list_categories, and update_docs. The minor variation in browse_docs_by_category is readable and still consistent with the overall convention.
Nine tools is well-scoped for a documentation companion server. Each tool supports a distinct part of the discover, browse, read, and refresh workflow without excessive surface area.
The tool set covers the full documentation lifecycle: discovery via search and listing, navigation via categories and structure, reading at section and article levels, metadata inspection, and corpus refresh. No obvious retrieval or maintenance gaps remain.