A Model Context Protocol server for the formr survey framework. Let LLM agents inspect, create, and edit formr run structures, manage settings, and get design guidance — all through natural language.
- Python 3.12+
- uv — fast Python package manager
- formr instance with admin (≥ 2) API access — create credentials at
<base_url>/admin/account#api - R (optional) — enables R syntax validation in
analyze_run
git clone https://github.com/timseidel/formr-mcp && cd formr-mcp
cp .env.example .env
# Edit .env with your formr instance URL and API credentials
uv sync
uv run server.py| Variable | Description |
|---|---|
FORMR_BASE_URL |
formr instance URL (e.g. http://localhost) |
FORMR_CLIENT_ID |
32-char hex client ID from /admin/account#api |
FORMR_CLIENT_SECRET |
64-char hex secret from /admin/account#api |
FLOWCHART_URL |
(optional) URL of the formr Flowchart Generator (default: https://formr-flowchart-test.pages.dev) |
Add to opencode.json in your project root:
{
"mcp": {
"formr-mcp": {
"type": "local",
"command": ["uv", "run", "server.py"],
"enabled": true
}
}
}Or copy from the included example:
cp opencode.json.example opencode.jsonAdd to claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/, Windows: %APPDATA%\Claude\):
{
"mcpServers": {
"formr-mcp": {
"command": "uv",
"args": ["run", "--directory", "/path/to/formr-mcp", "server.py"],
"env": {
"FORMR_BASE_URL": "http://localhost",
"FORMR_CLIENT_ID": "your_client_id",
"FORMR_CLIENT_SECRET": "your_client_secret"
}
}
}
}Add to .cursor/mcp.json in your project:
{
"mcpServers": {
"formr-mcp": {
"command": "uv",
"args": ["run", "--directory", "/path/to/formr-mcp", "server.py"]
}
}
}Set FORMR_BASE_URL, FORMR_CLIENT_ID, and FORMR_CLIENT_SECRET in a .env file in the project root.
| Tool | Description |
|---|---|
list_runs |
List all runs, optionally filter by name |
get_run |
Get run metadata by exact name |
create_run |
Create a new empty run |
delete_run |
Permanently delete a run and all its data |
whoami |
Get the authenticated user's profile |
| Tool | Description |
|---|---|
get_run_structure_to_file |
Fetch full structure to .formr/<name>.json (backs up existing) |
update_run_structure_from_file |
Validate and upload from .formr/<name>.json |
update_run_settings |
Change run-level settings (title, visibility, etc.) |
| Tool | Description |
|---|---|
summarize_run |
Human-readable overview (detail="units" or "items") |
find_run_items |
Search items by name/label substring and/or type |
analyze_run |
Check R syntax, variable refs, branch flow, item consistency |
open_flowchart |
Upload run structure and get a shareable flowchart URL (expires in 24h) |
| Tool | Description |
|---|---|
get_documentation |
Learn formr design (topics: item-types, run-concepts, r-code, survey-json, examples, best-practices) |
get_unit_types |
Get all supported unit types and their required/optional fields |
get_documentation_topics |
List available documentation topics |
Run structures can be large. Use the file-based workflow instead of passing JSON through tool arguments:
1. Fetch get_run_structure_to_file("my-run")
→ writes .formr/my-run.json
2. Edit Use your editor/agent to modify .formr/my-run.json
3. Upload update_run_structure_from_file("my-run")
→ validates, uploads, removes backup on success
- If
.formr/my-run.jsonalready exists, the previous version is backed up to.formr/my-run.json.bak - On upload validation errors, fix the file and retry — restore from
.bakif stuck - The
.formr/directory is gitignored
formr-mcp/
├── server.py # MCP server entry point, tool definitions
├── formr_mcp/
│ ├── auth.py # OAuth2 client credentials flow
│ ├── client.py # HTTP client for formr REST API
│ ├── documentation.py # Built-in design documentation topics
│ ├── analysis.py # Run structure analysis (R syntax, refs, flow)
│ ├── summarize.py # Run summarization and item search
│ └── validation.py # Structure validation (types, positions, choices)
├── tests/
│ ├── test_server.py # Server and tool tests
│ ├── test_analysis.py # Analysis module tests
│ ├── test_summarize.py # Summarization tests
│ └── test_normalize_choices.py # Choice normalization tests
├── .env.example # Environment variable template
├── opencode.json.example # opencode MCP config template
└── pyproject.toml # Project metadata and dependencies
uv run --with pytest pytest tests/This server interacts with the formr admin API only. It accesses run structures, survey definitions, and settings — never participant response data. Runs are fetched and edited as structural JSON, not as data exports.
MIT