Filly Forms MCP Server
by eneopt
README.md
# Filly Forms MCP Server
NPX-runnable MCP server that exposes the Filly Forms REST API as MCP tools for AI agents.
## Quick Start
### Install from GitHub
```bash
# Install directly from GitHub (recommended)
npx -y git+https://github.com/eneopt/filly-forms-mcp.git
# Or with SSH
npx -y git+ssh://git@github.com/eneopt/filly-forms-mcp.git
```
### Development Setup
```bash
# Clone the source repository
git clone [source-repo-url]
# Install dependencies
npm install
# Build
npm run build
# Run locally
npm start
```
## Usage with Claude Code
Add to your `.mcp.json`:
```json
{
"mcpServers": {
"filly-forms": {
"command": "npx",
"args": ["-y", "git+https://github.com/eneopt/filly-forms-mcp.git"],
"env": {
"FILLY_API_URL": "http://localhost:8000/api/v1"
}
}
}
}
```
Or use local development version (for contributing):
```json
{
"mcpServers": {
"filly-forms": {
"command": "node",
"args": ["/home/b4zs/workspace/w/jsonforms/packages/mcp-server/dist/index.js"],
"env": {
"FILLY_API_URL": "http://localhost:8000/api/v1",
"FILLY_API_USERNAME": "your-username",
"FILLY_API_PASSWORD": "your-password"
}
}
}
}
```
## Environment Variables
- `FILLY_API_URL` - Base URL of the Filly Forms REST API (default: `http://localhost:8000/api/v1`)
- `FILLY_API_USERNAME` - HTTP Basic Auth username (optional, only if API requires authentication)
- `FILLY_API_PASSWORD` - HTTP Basic Auth password (optional, only if API requires authentication)
## Available Tools
### `list_form_types`
List all form types in the system with their schemas and metadata.
**Parameters:**
- `name` (optional): Filter by form type name (partial match)
**Returns:**
```json
{
"types": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"name": "Invoice",
"version": 3,
"status": "published"
}
]
}
```
### `create_record`
Create a new record of a given form type with validation.
**Parameters:**
- `typeId` (required): UUID of the form type
- `data` (required): Record data (validated against type's JSON schema)
- `name` (optional): Record name
**Returns:**
```json
{
"id": "uuid",
"version": 1
}
```
### `get_record`
Get a record by ID, optionally at a specific version.
**Parameters:**
- `id` (required): Record UUID
- `version` (optional): Version number (omit for latest)
**Returns:**
```json
{
"id": "uuid",
"name": "Record Name",
"typeId": "uuid",
"data": { ... },
"version": 2,
"createdAt": "2026-07-21T06:00:00+00:00"
}
```
### `update_record`
Update an existing record with optimistic locking.
**Parameters:**
- `id` (required): Record UUID
- `data` (required): New record data
- `expectedVersion` (required): Expected current version for optimistic locking
- `name` (optional): New name
**Returns:**
```json
{
"id": "uuid",
"version": 3
}
```
### `preview_data`
Preview ad-hoc data through a template to see rendered HTML output.
**Parameters:**
- `typeId` (required): Form type UUID for schema validation
- `data` (required): Data to preview
- `templateId` (optional): Template UUID (uses default if omitted)
- `name` (optional): Name for the preview
**Returns:**
```json
{
"html": "<html>...</html>"
}
```
### `upload_document`
Upload a document for AI extraction (long-running operation with polling).
**Parameters:**
- `name` (required): Document filename
- `fileContent` (required): Base64-encoded document content
- `targetTypeId` (optional): Extract into existing type (data-only mode)
- `pollInterval` (optional): Seconds between polls (default: 2)
- `maxWait` (optional): Maximum seconds to wait (default: 300)
**Returns:**
```json
{
"uploadId": "uuid",
"status": "completed",
"logs": [...],
"typeId": "uuid",
"recordId": "uuid",
"targetTypeId": null
}
```
## Architecture
This MCP server is a **stateless HTTP proxy**:
1. **MCP Protocol** (stdio) ← Claude Code communicates here
2. **HTTP REST API** ← This server forwards requests here
3. **Symfony Backend** ← Handles business logic
**Why this approach?**
- ✅ **Separation of concerns**: MCP server is just a protocol adapter
- ✅ **Standard MCP**: Uses stdio (recommended for CLI clients)
- ✅ **No duplication**: All business logic stays in the Symfony app
- ✅ **Easy debugging**: Test REST API with curl, MCP with Claude
- ✅ **NPX-runnable**: Zero installation for users
## Development
```bash
# Watch mode
npm run dev
# Type checking
npm run typecheck
# Build
npm run build
```
## License
MIT
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues