Compute MCP

Um servidor MCP para avaliar expressões aritméticas usando um parser Pratt em

Documentação

🔮 Compute MCP

Um avaliador de expressões aritméticas robusto implementado como um servidor MCP (Model Context Protocol). Este projeto demonstra o desenvolvimento de parsers de qualidade de produção usando técnicas modernas de Rust, testes abrangentes baseados em propriedades e estratégias de teste adversariais.

✨ Recursos

  • Aritmética Completa: +, -, *, / com precedência correta
  • Notação Científica: 1e10, 2.5e-3, 1.23E+4
  • Agrupamento por Parênteses: (2 + 3) * 4
  • Números Decimais: 3.14159, -0.5
  • Operadores Unários: -42, -(5 + 3), --5
  • Tratamento Robusto de Erros: Divisão por zero, entrada malformada, erros de análise
  • Suporte a Aninhamento Profundo: Lida com expressões aninhadas complexas
  • Testado com Base em Propriedades: mais de 60 testes cobrindo invariantes matemáticas

🏗️ Arquitetura

Construído usando um parser Pratt moderno para tratamento limpo de precedência de operadores:

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)

Componentes Principais

  1. Gramática (src/compute.pest) - Define a sintaxe com átomos e operadores
  2. Parser Pratt (src/lib.rs) - Lida com precedência automaticamente
  3. AST (Expr enum) - Árvore de expressão imutável
  4. Avaliador (eval_expr) - Avaliação recursiva segura para pilha
  5. Servidor MCP (src/bin/stdio_direct.rs) - Interface JSON-RPC

🚀 Início Rápido

Instalação

cargo build --release

Avaliação Direta

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

Servidor MCP

# 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

Integração com Claude Desktop

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

🧪 Testes Abrangentes

Este projeto apresenta uma das suítes de testes mais completas para parsers aritméticos:

Categorias de Teste

🔧 Testes Unitários (tests/tests.rs)

  • Operações aritméticas básicas
  • Precedência e associatividade
  • Tratamento de erros
  • Análise de ida e volta

⚡ Testes Adversariais (tests/adversarial_tests.rs)

  • Casos extremos de ponto flutuante (infinito, NaN, subnormais)
  • Aninhamento profundo (mais de 1000 níveis)
  • Fuzzing de entrada malformada
  • Testes de estresse de desempenho

🎯 Testes Baseados em Propriedades (tests/proptest_adversarial.rs)

  • Invariantes matemáticas (comutatividade, associatividade, distributividade)
  • Robustez do parser (nunca entra em pânico)
  • Determinismo da avaliação
  • Preservação de precisão

Invariantes Chave Testadas

// 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

Executando Testes

# 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 Encontrados e Corrigidos

Testes baseados em propriedades descobriram problemas críticos durante o desenvolvimento:

Ambiguidade de Gramática: A gramática original permitia que -5 fosse analisado como Neg(Number(5)) ou Number(-5), causando comportamento não determinístico. Corrigido removendo sinais de menos de literais numéricos.

Casos Extremos de Precisão: Testes revelaram problemas de precisão de ponto flutuante com expressões como 1e20 + 1 - 1e20, levando a uma tolerância a erros mais robusta.

Limites de Aninhamento Profundo: Encontrados gargalos de desempenho do parser em cerca de 40+ níveis de aninhamento, otimizados para casos de uso práticos.

📊 Exemplos de Código

Uso Básico

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);

Recursos Avançados

// 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!(),
}

📁 Estrutura do Projeto

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

🔗 Dependências

[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

🎓 Valor Educacional

Este projeto serve como um excelente estudo de caso para:

  • Design Moderno de Parsers: Parsers Pratt vs. descida recursiva
  • Testes Baseados em Propriedades: Descobrindo casos extremos automaticamente
  • Melhores Práticas em Rust: Tratamento de erros, segurança de tipos, abstrações de custo zero
  • Implementação de Protocolo: Desenvolvimento de servidor MCP
  • Correção Matemática: Garantindo que leis aritméticas sejam mantidas

Perfeito para postagens de blog, tutoriais e conteúdo educacional sobre desenvolvimento de software robusto.

📝 Licença

MIT - Veja LICENSE para detalhes.


🔮 Pronto para uso em produção com confiança respaldada por testes abrangentes! 🔮