DFA-based workflow MCP server for guiding LLM task completion
npm install dfa-mcp-serverA Model Context Protocol (MCP) server that provides a generic deterministic finite automata (DFA) based workflow management system for LLMs.
This server helps LLMs follow any structured workflow without losing context or randomly marking tasks as complete. It allows dynamic definition of custom workflows with states, transitions, and actions, ensuring agents follow predefined paths through complex multi-step processes.
- Generic Workflow Engine: Define any workflow with custom states and transitions
- Dynamic Registration: Create new workflow types on the fly via MCP tools
- Context Preservation: Maintains full context throughout workflow execution
- Checkpoint & Rollback: Save and restore workflow states for error recovery
- No Hardcoded Logic: Completely generic - no assumptions about workflow purpose
- Judge System: Intelligent validation of transitions with confidence scoring
- LLM-Powered Judge: Optional AI-powered validation for deeper insights
- Pre-validation: Check if transitions are valid before executing them
- Custom Validators: Define business rules and requirements for each workflow
``bash`
npm install -g dfa-mcp-server
Or install locally in your project:
`bash`
npm install dfa-mcp-server
`bash`
git clone https://github.com/your-username/dfa-mcp-server.git
cd dfa-mcp-server
npm install
npm run build
Add to your Claude Desktop MCP configuration:
Basic Configuration:
`json`
{
"mcpServers": {
"dfa-workflow": {
"command": "npx",
"args": ["dfa-mcp-server"]
}
}
}
With OpenAI:
`json`
{
"mcpServers": {
"dfa-workflow": {
"command": "npx",
"args": ["dfa-mcp-server"],
"env": {
"LLM_BASE_URL": "https://api.openai.com",
"LLM_JUDGE_MODEL": "gpt-4",
"LLM_API_KEY": "sk-your-openai-key"
}
}
}
}
With Custom Endpoint (Gemini via Veronica):
`json`
{
"mcpServers": {
"dfa-workflow": {
"command": "npx",
"args": ["dfa-mcp-server"],
"env": {
"LLM_BASE_URL": "https://your-llm-api-endpoint.com",
"LLM_JUDGE_MODEL": "gemini-2.5-pro",
"LLM_API_KEY": "sk-your-api-key"
}
}
}
}
After installing globally:
`bash`
dfa-mcp-server
`javascript`
const { McpServer } = require('dfa-mcp-server');
// Server will start automatically when imported
For development:
`bash`
npm run dev
For production:
`bash`
npm start
Input:
- name: Unique workflow namedescription
- : Optional workflow descriptionstates
- : Object defining states and their transitionsinitialState
- : Starting state name
Example:
`json`
{
"name": "approval-process",
"description": "Document approval workflow",
"states": {
"draft": {
"transitions": { "submit": "review" }
},
"review": {
"transitions": {
"approve": "approved",
"reject": "draft"
}
},
"approved": { "final": true }
},
"initialState": "draft"
}
Output:
- workflows: Array of registered workflows with names and descriptionscount
- : Total number of registered workflows
Input:
- type: Workflow type name (must be previously defined)context
- : Optional initial context data (any JSON object)
Output:
- id: Unique workflow instance IDstate
- : Current statenextActions
- : Available actions from current stateprogress
- : Current progress message
Input:
- id: Workflow instance IDaction
- : Action to perform (must be in nextActions)data
- : Optional data to merge into context
Output:
- state: New state after transitionnextActions
- : Available actions from new stateprogress
- : Updated progresscomplete
- : Whether workflow has reached a final state
Input:
- id: Workflow instance ID
Output:
- state: Current statecontext
- : Full workflow context (all accumulated data)nextActions
- : Available actionsprogress
- : Current progresscomplete
- : Whether workflow is complete
Input:
- id: Workflow instance IDdescription
- : Optional checkpoint descriptionmetadata
- : Optional additional metadata
Output:
- checkpointId: Unique checkpoint IDworkflowId
- : Associated workflow IDstate
- : State at checkpointtimestamp
- : When checkpoint was createddescription
- : Checkpoint description
Input:
- id: Workflow instance IDcheckpointId
- : ID of checkpoint to rollback to
Output:
- state: Restored statecontext
- : Restored contextnextActions
- : Available actions from restored stateprogress
- : Progress after rollbackmessage
- : Success message
Input:
- id: Workflow instance ID
Output:
- workflowId: Workflow IDcheckpoints
- : Array of checkpoints (sorted by most recent first)count
- : Total number of checkpoints
Input:
- id: Workflow instance IDaction
- : Action to validatedata
- : Optional data for the action
Output:
- approved: Whether the transition would be allowedconfidence
- : Confidence score (0-1)reasoning
- : Human-readable explanationviolations
- : List of validation failures (if any)suggestions
- : Helpful suggestions for fixing issues
Input:
- name: Workflow type nameenabled
- : Enable/disable judgestrictMode
- : Optional - reject low confidence transitionsminConfidence
- : Optional - minimum confidence threshold (0-1)
Output:
- success: Configuration update statusmessage
- : Confirmation messageconfig
- : Updated configuration
Input:
- id: Workflow instance ID
Output:
- workflowId: Workflow IDdecisions
- : Array of judge decisionscount
- : Total number of decisions
json
{
"name": "document-review",
"description": "Document review with strict validation",
"states": {
"draft": {
"transitions": { "submit": "reviewing" }
},
"reviewing": {
"transitions": {
"approve": "approved",
"reject": "draft"
}
},
"approved": { "final": true }
},
"initialState": "draft",
"judgeConfig": {
"enabled": true,
"strictMode": true,
"minConfidence": 0.8
},
"stateValidators": {
"reviewing": {
"requiredFields": ["documentId", "reviewer"]
}
},
"transitionValidators": {
"approve": "(data, context) => ({ valid: data.comments?.length >= 20, confidence: 1.0, reason: 'Detailed comments required' })"
}
}
`Example Workflows
$3
`json
{
"name": "todo-tracker",
"description": "Track todo items through their lifecycle",
"states": {
"created": {
"transitions": {
"start": "in_progress",
"cancel": "cancelled"
}
},
"in_progress": {
"transitions": {
"complete": "done",
"pause": "paused",
"cancel": "cancelled"
}
},
"paused": {
"transitions": {
"resume": "in_progress",
"cancel": "cancelled"
}
},
"done": { "final": true },
"cancelled": { "final": true }
},
"initialState": "created"
}
`$3
`json
{
"name": "deployment-pipeline",
"description": "Software deployment process",
"states": {
"ready": {
"transitions": { "deploy": "deploying" }
},
"deploying": {
"transitions": {
"success": "testing",
"failure": "failed"
}
},
"testing": {
"transitions": {
"pass": "live",
"fail": "rollback"
}
},
"rollback": {
"transitions": { "complete": "ready" }
},
"live": { "final": true },
"failed": { "final": true }
},
"initialState": "ready"
}
`$3
`json
{
"name": "form-wizard",
"description": "Multi-step form submission",
"states": {
"step1": {
"transitions": {
"next": "step2",
"save": "draft"
}
},
"step2": {
"transitions": {
"next": "step3",
"back": "step1",
"save": "draft"
}
},
"step3": {
"transitions": {
"submit": "processing",
"back": "step2",
"save": "draft"
}
},
"draft": {
"transitions": { "resume": "step1" }
},
"processing": {
"transitions": {
"success": "complete",
"error": "step3"
}
},
"complete": { "final": true }
},
"initialState": "step1"
}
`Complete Example Usage
`typescript
// 1. Define a custom workflow
await callTool('workflow.define', {
name: 'code-review',
description: 'Code review process',
states: {
submitted: {
transitions: { 'assign': 'in_review' }
},
in_review: {
transitions: {
'request_changes': 'changes_requested',
'approve': 'approved',
'reject': 'rejected'
}
},
changes_requested: {
transitions: { 'resubmit': 'in_review' }
},
approved: { final: true },
rejected: { final: true }
},
initialState: 'submitted'
});// 2. Start a workflow instance
const result = await callTool('workflow.start', {
type: 'code-review',
context: {
pr_number: 123,
author: 'developer@example.com',
files_changed: 5
}
});
// Returns: { id: 'wf-123', state: 'submitted', nextActions: ['assign'] }
// 3. Assign reviewer
await callTool('workflow.advance', {
id: 'wf-123',
action: 'assign',
data: {
reviewer: 'senior@example.com',
assigned_at: new Date().toISOString()
}
});
// 4. Create checkpoint before making decision
const checkpoint = await callTool('workflow.checkpoint', {
id: 'wf-123',
description: 'Before review decision'
});
// 5. Request changes
await callTool('workflow.advance', {
id: 'wf-123',
action: 'request_changes',
data: {
comments: ['Please add tests', 'Update documentation']
}
});
// 6. If needed, rollback to checkpoint
await callTool('workflow.rollback', {
id: 'wf-123',
checkpointId: checkpoint.checkpointId
});
// 7. Approve instead
await callTool('workflow.advance', {
id: 'wf-123',
action: 'approve',
data: {
approved_at: new Date().toISOString(),
merge_strategy: 'squash'
}
});
`File Structure
Workflows are persisted in the
.workflows directory:
- definitions/: Saved workflow definitions
- wf-{id}.json: Current state and context
- wf-{id}.log: Transition history (append-only log)
- checkpoints/: Saved checkpointsWhy Generic DFA?
This generic approach solves the common problem where LLMs:
- Lose track of their position in multi-step processes
- Skip required steps or prematurely mark tasks complete
- Forget context between interactions
- Fail to follow defined procedures consistently
By allowing dynamic workflow definition, any process can be modeled:
- Approval workflows
- State machines
- Multi-step wizards
- Pipeline processes
- Task lifecycles
- Any sequential process with defined states
LLM-Powered Judge (Optional)
Enable AI-powered validation by setting environment variables in your MCP configuration:
`json
"env": {
"LLM_BASE_URL": "https://api.openai.com", // Or any OpenAI-compatible endpoint
"LLM_JUDGE_MODEL": "gpt-4", // Model to use
"LLM_API_KEY": "sk-your-api-key", // Your API key
"LLM_JUDGE_THINKING_MODE": "high" // Thinking depth (optional)
}
`$3
Works with any OpenAI-compatible API:
- OpenAI (GPT-4, GPT-3.5)
- Anthropic Claude (via proxy)
- Google Gemini (via proxy)
- Local LLMs (LM Studio, Ollama)
- Custom endpoints$3
`json
{
"judgeConfig": {
"enabled": true,
"useLLM": true, // Enable LLM validation
"strictMode": true,
"minConfidence": 0.8
}
}
`$3
- Structural Judge: Fast, rule-based, deterministic
- LLM Judge: Understands context, provides nuanced feedback, catches semantic issues
- Fallback: If LLM fails, automatically uses structural validationJudge System Benefits
The intelligent judge system improves workflow accuracy by:
$3
- Validates transitions before execution
- Ensures all prerequisites are met
- Prevents state corruption$3
- Custom validators for each workflow
- Required field validation
- Complex condition checking$3
- Quantifies transition validity (0-1 scale)
- Identifies uncertain operations
- Enables risk-based decisions$3
- Clear explanations of rejections
- Specific violation details
- Actionable suggestions for fixes$3
- Guides LLMs to follow rules correctly
- Reduces trial-and-error attempts
- Teaches through detailed feedback$3
Structural Judge:
`
LLM attempts: workflow.advance(id: "wf-123", action: "approve", data: {})
Judge rejects: "Missing required approval comments (min 20 chars)"
`LLM Judge (with same attempt):
`
LLM attempts: workflow.advance(id: "wf-123", action: "approve", data: {})
Judge rejects: "Approval without comments lacks accountability. In document
review workflows, approvals should include: 1) What was reviewed,
2) Key findings, 3) Any conditions. This creates an audit trail."
Suggestions: ["Add detailed approval comments", "Include review findings",
"Mention any follow-up requirements"]
``The LLM judge provides richer, context-aware feedback!