Skip to main content
Glama
ailecksandr

Claude Document Management MCP Server

by ailecksandr
README.md
# CLI Project Ruby

A production-ready Ruby-based interactive CLI that integrates the Model Context Protocol (MCP) with Claude AI for intelligent document management through a natural chat interface.

## Description

This application demonstrates enterprise-grade MCP integration by combining a Ruby MCP client/server architecture with Anthropic's Claude API. Users interact with Claude through a sophisticated terminal interface, enabling AI-driven document operations via natural language commands.

**Value Proposition:**
- **Zero-friction document management**: Edit and read documents through conversational AI
- **MCP-native architecture**: Built on the Model Context Protocol for extensible tool integration
- **Developer-friendly**: Railway pattern services, Zeitwerk autoloading, and comprehensive debugging tools
- **Production patterns**: ServiceResult state management, interface enforcement, and structured logging

**Architecture Overview:**
- **Client layer**: MCP client + Anthropic API integration with TTY-enhanced console
- **Server layer**: MCP server exposing document tools, resources, and prompt templates
- **Shared core**: Railway-pattern services, abstract interfaces, and dual-output logging

## Prerequisites

- Ruby 4.0.5
- Bundler
- Overmind (for process management)
- Node.js 24.11 (for MCP inspector)

## Installation

1. Clone the repository
2. Install dependencies:
   ```bash
   bundle install
   npm install
   ```

3. Configure environment variables:
   ```bash
   cp .env.example .env
   ```
   Edit `.env` and set:
   - `ANTHROPIC_API_KEY` - Your Anthropic API key
   - `CLAUDE_MODEL` - Claude model to use (e.g., `claude-3-5-sonnet-20241022`)

## Running the Application

### Using Overmind (Recommended)

```bash
# Start all processes from Procfile
overmind start

# Specific processes
overmind start -l client_server
overmind start -l inspector

# Connect to STDIO of process
```

### Manual Start

Run the main application:
```bash
# Start MCP client-server
bundle exec ruby client_server.rb

# Start MCP server only
bundle exec ruby server.rb

# Start MCP inspector
npx @modelcontextprotocol/inspector bundle exec ruby server.rb
```

## Usage Guide

### Document References

Check `server/docs.json` as the single source of truth.
Use `@document` syntax to reference documents in your messages:

```
You: Can you read @report.pdf?
Claude: [uses ReadDocument tool to fetch content]

You: Please update @plan.md with the new timeline
Claude: [uses EditDocument tool to modify content]
```

### Slash Commands

Execute special commands with the `/` prefix:

- `/clear` - Clear conversation history
- `/exit` - Exit the application
- Additional local commands can be defined in the client configuration
- Additional prompt commands can be defined in the server configuration

### Keywords
- **exit**, **quit**, **q**: Exit the application

### Keyboard Shortcuts

- **Escape key**: Cancel current input and return to prompt
- **Ctrl+C**: Interrupt tool execution or exit application
- **Ctrl+D**: Submit multiline input (in multiline mode)

### Input Modes

**Single-line mode** (default):
- Type message and press Enter
- Suitable for quick queries and commands

**Multiline mode** (when needed):
- Press Shift+Enter to start multiline input
- Type across multiple lines
- Press Enter to submit
- Press Escape to cancel

## MCP Components

The application implements a complete MCP server with the following component layers:

### Tools Layer
Executable operations that Claude can invoke to perform actions:
- **ReadDocument**: Retrieve document content by ID
- **EditDocument**: Modify document content with new text

### Resources Layer
Discoverable data sources exposed via URI patterns:
- **Direct resources**: Static listings (e.g., `docs://documents` for all documents)
- **Templated resources**: Dynamic URIs with parameters (e.g., `docs://documents/{doc_id}` for specific documents)

### Prompts Layer
Reusable prompt templates for common operations:
- **FormatPrompt**: Template for document formatting instructions
- Additional prompts can be defined for specialized workflows

All components follow base class patterns (`BaseTool`, `BaseResource`, `BasePrompt`) enabling consistent implementation and easy extension.

## Project Structure

```
.
├── client_server.rb             # Entry point for CLI application (MCP Client + Server)
├── server.rb                    # MCP server implementation
├── Procfile                     # Overmind/Foreman process definitions
├── core/                        # Core classes
    ├── application_service.rb   # callable service
    ├── constants.rb             # global constants
    ├── service_result.rb        # railway pattern service result
    ├── interface.rb             # interface implementation in Ruby
    └── application_logger.rb    # text file logger for client/server
├── client/                      # Client classes
├── server/                      # Server classes
└── lib/                         # Shared libraries
    └── tty_patch/               # TTY-prompt monkey patch
```

## Dependencies

- **anthropic** - Anthropic API client
- **mcp** - Model Context Protocol implementation
- **tty-prompt** - Interactive command line prompts
- **zeitwerk** - Code loader

## Development

Debug mode is available via the `debug` gem. Set breakpoints using `debugger` or `binding.break`.
Server logs are available in `log/server.log`.
MCP inspector could be used for debugging server-side tooling.

## Troubleshooting

### Debug Logging

Enable detailed debug output by setting the `LOG_LEVEL` environment variable:

```bash
# In .env file
LOG_LEVEL=debug  # DEBUG level

# Or inline
LOG_LEVEL=debug bundle exec ruby client_server.rb
```

Logs are written to `logs/server.log`.

### Interactive Debugging with binding.break

Insert breakpoints anywhere in the code:

```ruby
def process_message(message)
  binding.break  # Execution pauses here
  # ... rest of method
end
```

When execution hits the breakpoint:
- Inspect variables: `message`, `self`, local scope
- Step through code: `step`, `next`, `continue`
- Evaluate expressions: type any Ruby code
- Exit debugger: `continue` or `c`

**Common debugging scenarios:**
```ruby
# In client/chat_manager.rb
def handle_tool_use(tool_call)
  binding.break  # Debug tool execution
  # ...
end

# In server/tools/read_document.rb
def call(arguments)
  binding.break  # Debug tool implementation
  # ...
end
```

**NB.** On server-side debugging could be challenging after server start, due to the asynchronous nature of MCP. 
Prefer logger or inspector instead

### MCP Inspector

The MCP Inspector provides a web UI for testing MCP server components without running the full client:

**Start inspector:**
```bash
# Via Overmind
overmind start -l inspector

# Or manually
npx @modelcontextprotocol/inspector bundle exec ruby server.rb
```

**Inspector features:**
- Browse available tools, resources, and prompts
- Test tool execution with custom arguments
- View resource URIs and content
- Inspect prompt templates
- Monitor MCP protocol messages

**Typical workflow:**
1. Open browser to inspector URL (shown in terminal)
2. Verify tools are registered correctly
3. Test `ReadDocument` with sample document IDs
4. Test `EditDocument` with content modifications
5. Check resource listings for `docs://documents`
6. Validate prompt templates

### Common Issues

**Issue: "Cannot connect to MCP server"**
- Try to start the server using `bundle exec ruby server.rb`
- Check the raised exception
- Check `logs/server.log` for server errors

**Issue: "Tool execution fails"**
- Enable DEBUG logging: `LOG_LEVEL=0`
- Repeat your workflow
- Check `logs/client.log` for client errors
- Check `logs/server.log` for server errors

**Issue: "Multiline input works incorrect"**
- Try Ctrl+D to submit (not Enter)
- Check terminal compatibility (some terminals don't support raw mode)

**Issue: "Environment variables not loaded"**
- Verify `.env` file exists and has correct format
- Check `ANTHROPIC_API_KEY` is set (not empty)
- Restart application after `.env` changes

## TODO:
- [ ] Add Tasks
- [ ] Add RSpec coverage
- [ ] Add Rubocop
- [ ] Add Sorbet
- [ ] Try HTTP MCP
- [ ] Add OAuth2
- [ ] Think how to polish monkey patches

## License

MIT License