600 lines
No EOL
14 KiB
Markdown
600 lines
No EOL
14 KiB
Markdown
# Generic DFA MCP Server
|
|
|
|
A Model Context Protocol (MCP) server that provides a generic deterministic finite automata (DFA) based workflow management system for LLMs.
|
|
|
|
## Purpose
|
|
|
|
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.
|
|
|
|
## Key Features
|
|
|
|
- **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
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
cd dfa-mcp-server
|
|
npm install
|
|
npm run build
|
|
```
|
|
|
|
## Running the Server
|
|
|
|
For development:
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
For production:
|
|
```bash
|
|
npm start
|
|
```
|
|
|
|
## Available Tools
|
|
|
|
### workflow.define
|
|
Define a new workflow type with custom states and transitions.
|
|
|
|
**Input:**
|
|
- `name`: Unique workflow name
|
|
- `description`: Optional workflow description
|
|
- `states`: Object defining states and their transitions
|
|
- `initialState`: 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"
|
|
}
|
|
```
|
|
|
|
### workflow.list
|
|
List all registered workflow types.
|
|
|
|
**Output:**
|
|
- `workflows`: Array of registered workflows with names and descriptions
|
|
- `count`: Total number of registered workflows
|
|
|
|
### workflow.start
|
|
Start a new instance of a defined workflow.
|
|
|
|
**Input:**
|
|
- `type`: Workflow type name (must be previously defined)
|
|
- `context`: Optional initial context data (any JSON object)
|
|
|
|
**Output:**
|
|
- `id`: Unique workflow instance ID
|
|
- `state`: Current state
|
|
- `nextActions`: Available actions from current state
|
|
- `progress`: Current progress message
|
|
|
|
### workflow.advance
|
|
Move workflow to next state by performing an action.
|
|
|
|
**Input:**
|
|
- `id`: Workflow instance ID
|
|
- `action`: Action to perform (must be in nextActions)
|
|
- `data`: Optional data to merge into context
|
|
|
|
**Output:**
|
|
- `state`: New state after transition
|
|
- `nextActions`: Available actions from new state
|
|
- `progress`: Updated progress
|
|
- `complete`: Whether workflow has reached a final state
|
|
|
|
### workflow.status
|
|
Get current status of a workflow instance.
|
|
|
|
**Input:**
|
|
- `id`: Workflow instance ID
|
|
|
|
**Output:**
|
|
- `state`: Current state
|
|
- `context`: Full workflow context (all accumulated data)
|
|
- `nextActions`: Available actions
|
|
- `progress`: Current progress
|
|
- `complete`: Whether workflow is complete
|
|
|
|
### workflow.checkpoint
|
|
Create a checkpoint to save current workflow state.
|
|
|
|
**Input:**
|
|
- `id`: Workflow instance ID
|
|
- `description`: Optional checkpoint description
|
|
- `metadata`: Optional additional metadata
|
|
|
|
**Output:**
|
|
- `checkpointId`: Unique checkpoint ID
|
|
- `workflowId`: Associated workflow ID
|
|
- `state`: State at checkpoint
|
|
- `timestamp`: When checkpoint was created
|
|
- `description`: Checkpoint description
|
|
|
|
### workflow.rollback
|
|
Rollback workflow to a previous checkpoint.
|
|
|
|
**Input:**
|
|
- `id`: Workflow instance ID
|
|
- `checkpointId`: ID of checkpoint to rollback to
|
|
|
|
**Output:**
|
|
- `state`: Restored state
|
|
- `context`: Restored context
|
|
- `nextActions`: Available actions from restored state
|
|
- `progress`: Progress after rollback
|
|
- `message`: Success message
|
|
|
|
### workflow.listCheckpoints
|
|
List all checkpoints for a workflow.
|
|
|
|
**Input:**
|
|
- `id`: Workflow instance ID
|
|
|
|
**Output:**
|
|
- `workflowId`: Workflow ID
|
|
- `checkpoints`: Array of checkpoints (sorted by most recent first)
|
|
- `count`: Total number of checkpoints
|
|
|
|
### workflow.judge.validate
|
|
Validate a transition without executing it. Useful for pre-checking if an action is valid.
|
|
|
|
**Input:**
|
|
- `id`: Workflow instance ID
|
|
- `action`: Action to validate
|
|
- `data`: Optional data for the action
|
|
|
|
**Output:**
|
|
- `approved`: Whether the transition would be allowed
|
|
- `confidence`: Confidence score (0-1)
|
|
- `reasoning`: Human-readable explanation
|
|
- `violations`: List of validation failures (if any)
|
|
- `suggestions`: Helpful suggestions for fixing issues
|
|
|
|
### workflow.judge.config
|
|
Configure judge settings for a workflow.
|
|
|
|
**Input:**
|
|
- `name`: Workflow type name
|
|
- `enabled`: Enable/disable judge
|
|
- `strictMode`: Optional - reject low confidence transitions
|
|
- `minConfidence`: Optional - minimum confidence threshold (0-1)
|
|
|
|
**Output:**
|
|
- `success`: Configuration update status
|
|
- `message`: Confirmation message
|
|
- `config`: Updated configuration
|
|
|
|
### workflow.judge.history
|
|
Get the history of judge decisions for a workflow instance.
|
|
|
|
**Input:**
|
|
- `id`: Workflow instance ID
|
|
|
|
**Output:**
|
|
- `workflowId`: Workflow ID
|
|
- `decisions`: Array of judge decisions
|
|
- `count`: Total number of decisions
|
|
|
|
## Example Workflows with Judge
|
|
|
|
### 1. Document Review with Validation
|
|
```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
|
|
|
|
### 2. Todo Item Tracker
|
|
```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"
|
|
}
|
|
```
|
|
|
|
### 2. Deployment Pipeline
|
|
```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. Multi-Step Form
|
|
```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 checkpoints
|
|
|
|
## Why 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)
|
|
}
|
|
```
|
|
|
|
### Supported Providers
|
|
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
|
|
|
|
### Using LLM Judge
|
|
```json
|
|
{
|
|
"judgeConfig": {
|
|
"enabled": true,
|
|
"useLLM": true, // Enable LLM validation
|
|
"strictMode": true,
|
|
"minConfidence": 0.8
|
|
}
|
|
}
|
|
```
|
|
|
|
### LLM vs Structural Judge
|
|
- **Structural Judge**: Fast, rule-based, deterministic
|
|
- **LLM Judge**: Understands context, provides nuanced feedback, catches semantic issues
|
|
- **Fallback**: If LLM fails, automatically uses structural validation
|
|
|
|
## Judge System Benefits
|
|
|
|
The intelligent judge system improves workflow accuracy by:
|
|
|
|
### 1. **Preventing Invalid Transitions**
|
|
- Validates transitions before execution
|
|
- Ensures all prerequisites are met
|
|
- Prevents state corruption
|
|
|
|
### 2. **Enforcing Business Rules**
|
|
- Custom validators for each workflow
|
|
- Required field validation
|
|
- Complex condition checking
|
|
|
|
### 3. **Confidence Scoring**
|
|
- Quantifies transition validity (0-1 scale)
|
|
- Identifies uncertain operations
|
|
- Enables risk-based decisions
|
|
|
|
### 4. **Helpful Feedback**
|
|
- Clear explanations of rejections
|
|
- Specific violation details
|
|
- Actionable suggestions for fixes
|
|
|
|
### 5. **Improved LLM Behavior**
|
|
- Guides LLMs to follow rules correctly
|
|
- Reduces trial-and-error attempts
|
|
- Teaches through detailed feedback
|
|
|
|
### Example Judge in Action:
|
|
|
|
**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!
|
|
|
|
## Adding to Claude Desktop
|
|
|
|
Add to your Claude Desktop configuration:
|
|
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"dfa-workflow": {
|
|
"command": "node",
|
|
"args": ["/path/to/dfa-mcp-server/dist/index.js"],
|
|
"env": {
|
|
"LLM_BASE_URL": "https://api.openai.com",
|
|
"LLM_JUDGE_MODEL": "gpt-4",
|
|
"LLM_API_KEY": "sk-your-api-key-here",
|
|
"LLM_JUDGE_THINKING_MODE": "high"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Configuration Examples
|
|
|
|
**Without LLM Judge (default):**
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"dfa-workflow": {
|
|
"command": "node",
|
|
"args": ["/path/to/dfa-mcp-server/dist/index.js"]
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**With OpenAI:**
|
|
```json
|
|
{
|
|
"mcpServers": {
|
|
"dfa-workflow": {
|
|
"command": "node",
|
|
"args": ["/path/to/dfa-mcp-server/dist/index.js"],
|
|
"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": "node",
|
|
"args": ["/path/to/dfa-mcp-server/dist/index.js"],
|
|
"env": {
|
|
"LLM_BASE_URL": "https://your-llm-api-endpoint.com",
|
|
"LLM_JUDGE_MODEL": "gemini-2.5-pro",
|
|
"LLM_API_KEY": "sk-your-api-key"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
``` |