Compute MCP

An MCP server for evaluating arithmetic expressions using a Pratt parser in Rust.

๐Ÿ”ฎ Compute MCP

A robust arithmetic expression evaluator implemented as an MCP (Model Context Protocol) server. This project demonstrates production-quality parser development using modern Rust techniques, comprehensive property-based testing, and adversarial test strategies.

โœจ Features

  • Complete Arithmetic: +, -, *, / with correct precedence
  • Scientific Notation: 1e10, 2.5e-3, 1.23E+4
  • Parentheses Grouping: (2 + 3) * 4
  • Decimal Numbers: 3.14159, -0.5
  • Unary Operators: -42, -(5 + 3), --5
  • Robust Error Handling: Division by zero, malformed input, parse errors
  • Deep Nesting Support: Handles complex nested expressions
  • Property-Based Tested: 60+ tests covering mathematical invariants

๐Ÿ—๏ธ Architecture

Built using a modern Pratt parser for clean operator precedence handling:

Input String โ†’ Pest Grammar โ†’ Pratt Parser โ†’ AST โ†’ Evaluator โ†’ Result
     โ”‚              โ”‚              โ”‚         โ”‚         โ”‚          โ”‚
"2 + 3 * 4"    compute.pest    PrattParser  Expr::Add  eval_expr  Ok(14.0)
                                              /        \
                                       Expr::Num(2)  Expr::Mul
                                                      /        \
                                                Expr::Num(3)  Expr::Num(4)

Key Components

  1. Grammar (src/compute.pest) - Defines syntax with atoms and operators
  2. Pratt Parser (src/lib.rs) - Handles precedence automatically
  3. AST (Expr enum) - Immutable expression tree
  4. Evaluator (eval_expr) - Stack-safe recursive evaluation
  5. MCP Server (src/bin/stdio_direct.rs) - JSON-RPC interface

๐Ÿš€ Quick Start

Installation

cargo build --release

Direct Evaluation

# Command line tool
cargo run --bin stdio_direct -- eval "2 + 3 * 4"
cargo run --bin stdio_direct -- eval "1e10 / (2.5 + 3.7)"

MCP Server

# Initialize server
echo '{"jsonrpc":"2.0","method":"initialize","params":{},"id":1}' | cargo run --bin stdio_direct

# Batch evaluation
echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"evaluate_batch","arguments":{"expressions":["2+2","1e3*2","(5-3)^2"]}},"id":2}' | cargo run --bin stdio_direct

Claude Desktop Integration

{
  "mcpServers": {
    "compute": {
      "command": "/path/to/compute-mcp/target/release/stdio_direct"
    }
  }
}

๐Ÿงช Comprehensive Testing

This project features one of the most thorough test suites for arithmetic parsers:

Test Categories

๐Ÿ”ง Unit Tests (tests/tests.rs)

  • Basic arithmetic operations
  • Precedence and associativity
  • Error handling
  • Round-trip parsing

โšก Adversarial Tests (tests/adversarial_tests.rs)

  • Floating-point edge cases (infinity, NaN, subnormals)
  • Deep nesting (1000+ levels)
  • Malformed input fuzzing
  • Performance stress testing

๐ŸŽฏ Property-Based Tests (tests/proptest_adversarial.rs)

  • Mathematical invariants (commutativity, associativity, distributivity)
  • Parser robustness (never panics)
  • Evaluation determinism
  • Precision preservation

Key Invariants Tested

// Precedence preservation
parse("a + b * c") == Add(a, Mul(b, c))

// Evaluation determinism  
eval(expr) == eval(expr)  // Always same result

// Mathematical laws
eval(Add(a, b)) โ‰ˆ eval(Add(b, a))  // Commutativity
eval(Add(Add(a, b), c)) โ‰ˆ eval(Add(a, Add(b, c)))  // Associativity

// Round-trip consistency
eval(parse(print(ast))) โ‰ˆ eval(ast)

// Error containment
parse(invalid_input) == Err(_)  // Never panics

Running Tests

# All tests
cargo test

# Specific test suites
cargo test --test tests           # Basic functionality
cargo test --test adversarial_tests  # Edge cases
cargo test --test proptest_adversarial  # Property tests

# Parallel execution
cargo test -- --test-threads=4

๐Ÿ› Bugs Found & Fixed

Property-based testing discovered critical issues during development:

Grammar Ambiguity: The original grammar allowed -5 to parse as either Neg(Number(5)) or Number(-5), causing non-deterministic behavior. Fixed by removing minus signs from number literals.

Precision Edge Cases: Tests revealed floating-point precision issues with expressions like 1e20 + 1 - 1e20, leading to more robust error tolerance.

Deep Nesting Limits: Found parser performance cliffs at ~40+ nesting levels, optimized for practical use cases.

๐Ÿ“Š Code Examples

Basic Usage

use compute_mcp::*;

// Simple evaluation
let result = evaluate("2 + 3 * 4")?;
assert_eq!(result, 14.0);

// Scientific notation
let result = evaluate("1.5e3 + 2.5e2")?;
assert_eq!(result, 1750.0);

// Complex expressions
let result = evaluate("((1 + 2) * 3 - 4) / 2")?;
assert_eq!(result, 2.5);

Advanced Features

// Parse to AST for inspection
let ast = parse_expression("-(2 + 3) * 4")?;
// Returns: Mul(Neg(Add(Number(2), Number(3))), Number(4))

// Batch processing
let expressions = vec!["1+1", "2*2", "3/3"];
let results = evaluate_batch(&expressions);

// Error handling
match evaluate("10 / 0") {
    Err(ComputeError::DivisionByZero) => println!("Caught division by zero"),
    _ => unreachable!(),
}

๐Ÿ“ Project Structure

compute-mcp/
โ”œโ”€โ”€ Cargo.toml                    # Dependencies and metadata
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ lib.rs                    # Parser, AST, and evaluator (~350 lines)
โ”‚   โ”œโ”€โ”€ compute.pest              # Pratt parser grammar (~35 lines)
โ”‚   โ””โ”€โ”€ bin/
โ”‚       โ””โ”€โ”€ stdio_direct.rs       # MCP server implementation
โ”œโ”€โ”€ tests/
โ”‚   โ”œโ”€โ”€ tests.rs                  # Unit and integration tests
โ”‚   โ”œโ”€โ”€ adversarial_tests.rs      # Edge case and stress tests  
โ”‚   โ”œโ”€โ”€ proptest_adversarial.rs   # Property-based tests
โ”‚   โ””โ”€โ”€ *.proptest-regressions    # Saved failing test cases
โ””โ”€โ”€ target/                       # Build artifacts

๐Ÿ”— Dependencies

[dependencies]
pest = "2.6"           # Parser generator
pest_derive = "2.6"    # Derive macros for grammar
lazy_static = "1.4"    # Global parser instance
mcpr = "0.2.3"         # MCP protocol
serde = "1.0"          # JSON serialization
clap = "4.4"           # Command line interface

[dev-dependencies]
proptest = "1.6.0"     # Property-based testing

๐ŸŽ“ Educational Value

This project serves as an excellent case study for:

  • Modern Parser Design: Pratt parsers vs recursive descent
  • Property-Based Testing: Discovering edge cases automatically
  • Rust Best Practices: Error handling, type safety, zero-cost abstractions
  • Protocol Implementation: MCP server development
  • Mathematical Correctness: Ensuring arithmetic laws hold

Perfect for blog posts, tutorials, and educational content about robust software development.

๐Ÿ“ License

MIT - See LICENSE for details.


๐Ÿ”ฎ Ready for production use with confidence backed by comprehensive testing! ๐Ÿ”ฎ

Related Servers

NotebookLM Web Importer

Import web pages and YouTube videos to NotebookLM with one click. Trusted by 200,000+ users.

Install Chrome Extension