Skip to content
/ devout Public

A pun on Devin, Devout is an MCP server for complete (i.e., dangerous) software engineering project development operations

License

Notifications You must be signed in to change notification settings

erlsci/devout

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

17 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Devout

Build Status

Project Logo

A Devin Clone MCP Server

A Model Context Protocol (MCP) server written in Erlang that provides file, directory, and version control operations for software projects.

Features

πŸ› οΈ File Operations

  • new-dir: Create directories with automatic parent creation
  • new-dirs: Create directory structures with multiple children
  • move: Safely move/rename files and directories
  • write: Create/write files with append mode support
  • read: Read file contents with size limits
  • list-files: List directory contents with file types and sizes
  • show-cwd: Display current working directory
  • change-cwd: Navigate to relative directories

πŸ™ Git Operations

  • git-add: Add files to staging area (git add <files>)
  • git-log: Show commit history (git log [options])
  • git-diff: Show differences (no args, 1 arg, or 2 args)
  • git-pull: Pull with rebase (git pull <remote> <branch> --rebase)
  • git-checkout-branch: Create and checkout new branch (git checkout -b <name>)
  • git-push: Push to remote (git push <remote>)
  • git-commit-all: Commit all changes (git commit -a -m <message>)
  • git-commit-files: Commit specific files (git commit <files> -m <message>)
  • git-clone: Clone repository (git clone <url>)
  • git-status: Show repository status (git status --porcelain)

πŸ”’ Security Features

  • Path Validation: Only relative paths allowed, prevents directory traversal
  • Sandboxing: All operations restricted to base directory
  • File Size Limits: Configurable maximum file sizes
  • Extension Filtering: Optional file type restrictions
  • Safe Error Handling: No information disclosure through errors

πŸ“š Resources & Prompts

  • devout://status: Real-time service status and configuration
  • devout://help: Comprehensive tool documentation
  • create_project: Intelligent project structure generation (Erlang, web, API, library)

Architecture

OTP Design

  • Application: devout_app - Standard OTP application callback
  • Supervisor: devout_sup - Manages server process lifecycle
  • Server: devout_server - Main gen_server coordinating with erlmcp
  • Operations: devout_fs - File system operation implementations
  • Validation: devout_path_validator - Security and path validation
  • Git Operations: devout_git - Git command implementations
  • Entry Point: devout_stdio_main - Standalone stdio executable

Security Model

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚   Claude AI     │───▢│   devout_server  │───▢│    devout_fs    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚      β”‚                    β”‚
                            β”‚      β–Ό                    β–Ό
                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                       β”‚ erlmcp_stdio     β”‚    β”‚ path_validator  β”‚
                       β”‚ (MCP Protocol)   β”‚    β”‚ (Security)      β”‚
                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            β”‚
                            β–Ό
                       β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                       β”‚    devout_git    │───▢│     erlexec     β”‚
                       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚ (Proc. Mgmt.)   β”‚
                                               β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Prerequisites

  • Erlang/OTP 25+
  • Rebar3
  • Git (for dependencies & Git operations)

Quick Start

1. Build

git clone <repository-url>
cd devout
rebar3 get-deps
rebar3 compile

2. Test

rebar3 eunit

3. Configure Claude Desktop

Edit claude_desktop_config.json:

macOS: ~/Library/Application Support/Claude/claude_desktop_config.json Windows: %APPDATA%\Claude\claude_desktop_config.json Linux: ~/.config/Claude/claude_desktop_config.json

{
  "mcpServers": {
    "devout": {
        "command": "/Users/oubiwann/lab/erlsci/devout/bin/start.sh",
        "args": []
    }
  }
}

4. Restart Claude Desktop

Usage Examples

πŸ“ Directory Operations

User: Create a new project structure called "my_app" with src, test, and docs directories

Claude: I'll create that project structure for you.

[Uses new-dirs tool: {"path": "my_app", "children": ["src", "test", "docs"]}]

Directory structure created successfully:
  - my_app
  - src
  - test
  - docs

πŸ” Directory Exploration

User: What files are in the current directory?

Claude: I'll show you the files in the current directory.

[Uses list-files tool: {}]

Contents of .:
[FILE] .DS_Store (6148 bytes)
[DIR] .git
[DIR] .github
[FILE] .gitignore (164 bytes)
[FILE] LICENSE (11358 bytes)
[FILE] Makefile (4612 bytes)
[FILE] README.md (9895 bytes)
[DIR] _build
[DIR] bin
[DIR] config
[DIR] src
[DIR] test

πŸ“ File Operations

User: Create a configuration file with some JSON content

Claude: I'll create a config file for you.

[Uses write tool: {"path": "my_app/config.json", "content": "{\n  \"port\": 3000,\n  \"debug\": true\n}"}]

Content written to file successfully: my_app/config.json (32 bytes)

πŸ” Navigation & Reading

User: Show me the current directory and then read the config file

Claude: I'll show the current directory and read the config file.

[Uses show-cwd tool: {}]
Current working directory: /Users/developer/projects

[Uses read tool: {"path": "my_app/config.json"}]
Content of my_app/config.json (32 bytes):

{
  "port": 3000,
  "debug": true
}

πŸ—οΈ Project Generation

User: Use the create_project prompt for an Erlang application

Claude: I'll generate an Erlang project structure prompt.

[Uses create_project prompt: {"project_name": "my_erlang_app", "project_type": "erlang"}]

Create a project structure for 'my_erlang_app' (erlang project). Create an Erlang/OTP project structure with directories: src, include, test, priv, rebar.config. Use the devout tools to create the necessary directories and files.

πŸ™ Git Operations

View Git History

User: Show me the last 5 commits

Claude: I'll show you the recent commit history.

[Uses git-log tool: {"args": "--oneline -5"}]

Git log:
a1b2c3d Add new feature
e4f5g6h Fix bug in parser
i7j8k9l Update documentation
m1n2o3p Initial commit

Create Feature Branch

User: Create a new feature branch called "user-authentication"

Claude: I'll create and checkout a new branch for you.

[Uses git-checkout-branch tool: {"branch": "user-authentication"}]

Git checkout branch successful:
Switched to a new branch 'user-authentication'

Commit Changes

User: Add these files to git and commit them with message "Add user auth"

Claude: I'll stage and commit those files for you.

[Uses git-add tool: {"files": ["src/auth.erl", "test/auth_test.erl"]}]
[Uses git-commit-files tool: {"files": ["src/auth.erl", "test/auth_test.erl"], "message": "Add user auth"}]

Git operations successful!

Sync with Remote

User: Pull latest changes from origin main and then push my branch

Claude: I'll sync with the remote repository for you.

[Uses git-pull tool: {"remote": "origin", "branch": "main"}]
[Uses git-push tool: {"remote": "origin"}]

Git sync completed successfully!

Configuration

Edit config/sys.config to customize behavior:

[
    {devout, [
        {max_file_size, 10485760},          % 10MB limit
        {allowed_extensions, all},          % or [<<".txt">>, <<".md">>]
        {enable_recursive_delete, false},   % Safety first
        {allowed_operations, [              % Restrict available operations
            new_dir, new_dirs, move, write, read, list_files, show_cwd, change_cwd
        ]}
    ]},

    {erlexec, [
        {debug, false},                     % Enable for git command debugging
        {verbose, false}
    ]}
].

Git Command Reference

MCP Tool Git Command Description
git-add git add <files> Stage files for commit
git-log git log [options] Show commit history
git-diff git diff [ref1] [ref2] Show differences
git-pull git pull <remote> <branch> --rebase Pull with rebase
git-checkout-branch git checkout -b <name> Create new branch
git-push git push <remote> Push to remote
git-commit-all git commit -a -m <message> Commit all changes
git-commit-files git commit <files> -m <message> Commit specific files
git-clone git clone <url> Clone repository
git-status git status --porcelain Show repo status

Git Tool Parameters

git-add

{
  "files": ["file1.txt", "file2.txt"]  // Array of files
  // OR
  "file": "single_file.txt"            // Single file
}

git-log

{
  "args": "--oneline -10"              // Optional: git log arguments
}

git-diff

{
  // No parameters = working directory vs staged
  // OR
  "ref": "HEAD~1"                      // Compare against reference
  // OR
  "ref1": "HEAD~2",                    // Compare two references
  "ref2": "HEAD~1"
}

git-pull

{
  "remote": "origin",                  // Required: remote name
  "branch": "main"                     // Required: branch name
}

git-push

{
  "remote": "origin"                   // Required: remote name
}

Security Features

πŸ›‘οΈ Path Security

  • Relative Paths Only: Absolute paths rejected (/etc/passwd ❌)
  • Traversal Prevention: Parent directory access blocked (../../../etc ❌)
  • Base Directory Enforcement: Operations confined to working directory
  • Path Normalization: Handles ./, //, and other edge cases

πŸ“ Resource Limits

  • File Size Limits: Configurable maximum file sizes (default: 10MB)
  • Operation Whitelisting: Restrict available operations per deployment
  • Extension Filtering: Optional file type restrictions
  • Memory Protection: Streaming for large files

πŸ”’ Error Handling

  • Information Hiding: Errors don't leak system details
  • Graceful Degradation: Partial failures handled cleanly
  • Audit Logging: All operations logged for security review
  • Input Sanitization: All inputs validated before processing

Development

Running Tests

# Full test suite
rebar3 eunit

# Specific test modules
rebar3 eunit --module=devout_test

# With coverage
rebar3 cover

Code Quality

# Static analysis
rebar3 dialyzer

# Cross references
rebar3 xref

# Linting
rebar3 lint

Development Mode

# Interactive shell
rebar3 shell

# Start stdio server manually
devout_server:start_stdio().

Adding FS Operations

  1. Add to allowed_operations in devout.app.src

  2. Implement in devout_fs.erl (if needed):

    my_operation(Path) ->
        case devout_path_validator:validate_path(Path) of
            {ok, ValidPath} ->
                % Your operation here
                ok;
            {error, Reason} ->
                {error, Reason}
        end.
  3. Register tool in devout_app.erl:

    ok = erlmcp_stdio:add_tool(
        <<"my-operation">>,
        <<"Description">>,
        fun devout_server:handle_my_operation/1,
        SchemaMap
    ).
  4. Add handler in devout_server.erl:

    handle_my_operation(#{<<"path">> := Path}) ->
        case devout_fs:my_operation(Path) of
            ok -> <<"Success message">>;
            {error, Reason} -> devout_fmt:err(Reason)
        end.

Adding New Git Operations

  1. Add function to devout_git.erl:

    my_git_operation(Args) ->
        execute_git(["my-operation"] ++ Args).
  2. Add MCP handler:

    handle_my_git_operation(#{<<"param">> := Value}) ->
        case my_git_operation([binary_to_list(Value)]) of
            {ok, Output} -> <<"Success: ", Output/binary>>;
            {error, Reason} -> devout_fmt:err(Reason)
        end.
  3. Register tool in devout_server.erl:

    ok = erlmcp_stdio:add_tool(
        <<"git-my-operation">>,
        <<"Description of my git operation">>,
        fun devout_git:handle_my_git_operation/1,
        Schema
    ).
  4. Add tests in devout_git_test.erl

Monitoring & Debugging

Health Checks

# Check if application is running
erl -eval "io:format('~p~n', [application:which_applications()]), halt()."

# Verify processes
erl -eval "io:format('~p~n', [whereis(devout_server)]), halt()."

Logging

Logs go to stderr to avoid interfering with MCP protocol on stdout:

  • Info: Service lifecycle events
  • Warning: Security violations, invalid paths
  • Error: Operation failures, system errors

Troubleshooting

Issue Cause Solution
Service not starting Missing dependencies rebar3 get-deps && rebar3 compile
Path rejected Absolute/traversal path Use relative paths only
File too large Exceeds size limit Check max_file_size config
Permission denied File system permissions Check directory ownership
Tool not found Version mismatch Verify erlmcp compatibility
Git command timeout Long-running operation Increase timeout in erlexec config
Git not found Missing git installation Install git and ensure it's in PATH
Merge conflicts Conflicting changes Resolve conflicts manually
Repository not found Not in git repository Initialize with git init first

Performance

  • Memory Usage: ~10MB base + file buffers
  • Throughput: 1000+ operations/second for small files
  • Latency: <10ms for typical operations
  • Scalability: Single-threaded, suitable for interactive use

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass: rebar3 eunit
  5. Run static analysis: rebar3 dialyzer
  6. Submit a pull request

Code Style

  • Use OTP principles and gen_server patterns
  • Comprehensive error handling with proper types
  • Security-first design - validate all inputs
  • Document all public functions with edoc
  • Follow Erlang naming conventions

Acknowledgments

  • Built on the excellent erlmcp library
  • Inspired by security practices from the Erlang/OTP ecosystem
  • Thanks to the Claude Desktop team for MCP protocol specification

License

Apache License 2.0 - see LICENSE file for details.

External Resources

About

A pun on Devin, Devout is an MCP server for complete (i.e., dangerous) software engineering project development operations

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published