Skip to main content
Glama

BC Calculator MCP Server

by cthunter01
QUICK_REFERENCE.md7.99 kB
# BC Calculator MCP Server - Quick Reference ## Critical Implementation Checkpoints ### Security Must-Haves ✓ ```typescript // ❌ NEVER do this spawn('bc', ['-l'], { shell: true }) // DANGEROUS! // ✅ ALWAYS do this spawn('bc', ['-l'], { shell: false }) // SAFE ``` **Input Validation Rules**: - ✅ Maximum 10KB expression length - ✅ Whitelist: `[0-9a-zA-Z+\-*\/^().,;\s=<>!&|%{}[\]]` - ✅ Blacklist: `system()`, `exec()`, backticks, pipes, redirects - ✅ Timeout: 30 seconds default ### File Checklist Create these files in order: ``` src/ ├── types.ts # 1. Type definitions first ├── input-validator.ts # 2. Security layer ├── bc-process.ts # 3. Process wrapper ├── bc-process-pool.ts # 4. Pool manager └── index.ts # 5. MCP server (uses all above) ``` ### Key Code Patterns #### Spawning BC Process ```typescript const process = spawn('bc', ['-l'], { shell: false, // ← REQUIRED for security stdio: ['pipe', 'pipe', 'pipe'] }); // Set precision immediately after spawn process.stdin.write('scale=20\n'); ``` #### Input Validation ```typescript const validation = InputValidator.validate(expression); if (!validation.valid) { return { isError: true, content: [{ type: 'text', text: validation.error }]}; } ``` #### Timeout Pattern ```typescript const timeout = setTimeout(() => { process.kill(); reject(new Error('Timeout')); }, 30000); // Clear on success clearTimeout(timeout); ``` #### Process Communication ```typescript // Write to stdin process.stdin.write(expression + '\n'); // Read from stdout (line-buffered) let buffer = ''; process.stdout.on('data', (data: Buffer) => { buffer += data.toString(); const lines = buffer.split('\n'); buffer = lines.pop() || ''; for (const line of lines) { if (line.trim()) { resolve(line.trim()); // ← Result } } }); // Capture errors from stderr process.stderr.on('data', (data: Buffer) => { const error = data.toString(); reject(new Error(error)); }); ``` ## Common Pitfalls to Avoid ### ❌ DON'T ```typescript // Don't use shell spawn('bc -l', { shell: true }) // Don't skip validation const result = await bc.evaluate(userInput); // UNSAFE! // Don't forget cleanup // ... (missing process.kill() on error) // Don't use callbacks in 2024 process.on('data', function(data) { ... }) ``` ### ✅ DO ```typescript // Use no-shell spawn with args array spawn('bc', ['-l'], { shell: false }) // Always validate const valid = InputValidator.validate(input); if (!valid.valid) return error; // Always cleanup try { await evaluate(expr); } finally { process.kill(); } // Use modern async/await const result = await new Promise<string>((resolve, reject) => { // ... }); ``` ## Testing Checklist ### Basic Tests - [ ] `2+2` → `4` - [ ] `10/3` (precision=5) → `3.33333` - [ ] `2^10` → `1024` ### Math Library Tests - [ ] `sqrt(2)` → `1.41421...` - [ ] `s(0)` → `0` (sine of 0) - [ ] `4*a(1)` → `3.14159...` (compute pi) ### Error Tests - [ ] `2/0` → Error: divide by zero - [ ] `system('ls')` → Validation error - [ ] Too long expression → Validation error ### Advanced Tests - [ ] Variables: `a=5; b=10; a+b` → `15` - [ ] Loop: `for(i=0;i<3;i++) i` → `2` ### Stress Tests - [ ] 3 concurrent requests - [ ] Timeout with infinite loop - [ ] Process recovery after crash ## MCP Tool Schemas (Copy-Paste Ready) ### calculate ```typescript server.tool( 'calculate', { expression: z.string() .describe('Mathematical expression to evaluate'), precision: z.number().min(0).max(100).optional() .describe('Decimal places (default: 20)') }, async ({ expression, precision = 20 }) => { // Implementation here } ); ``` ### calculate_advanced ```typescript server.tool( 'calculate_advanced', { script: z.string() .describe('Multi-line BC script with variables/functions'), precision: z.number().min(0).max(100).optional() .describe('Decimal places (default: 20)') }, async ({ script, precision = 20 }) => { // Implementation here } ); ``` ### set_precision ```typescript server.tool( 'set_precision', { precision: z.number().min(0).max(100) .describe('Number of decimal places') }, async ({ precision }) => { // Implementation here } ); ``` ## Debug Commands ```bash # Test BC is available which bc bc --version # Test BC manually echo "scale=10; 22/7" | bc -l # Check compiled output ls -lh build/index.js # View MCP settings cat ~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json # Rebuild on changes npm run watch ``` ## One-Liner Fixes ```bash # Fix permissions chmod +x build/index.js # Reinstall deps rm -rf node_modules package-lock.json && npm install # Clean rebuild rm -rf build && npm run build # Install BC sudo apt-get install bc # Ubuntu/Debian brew install bc # macOS ``` ## Performance Targets | Operation | Target Time | Status | |-----------|-------------|--------| | Simple calc (2+2) | <10ms | ✓ | | Division with precision | <20ms | ✓ | | Math function | <50ms | ✓ | | Advanced script | <200ms | ✓ | | Process spawn | <100ms | ✓ | ## Architecture at a Glance ``` User Request ↓ InputValidator.validate() ↓ ProcessPool.acquireProcess() ↓ BCProcess.setPrecision() ↓ BCProcess.evaluate() ↓ ← BC stdout/stderr ↓ ProcessPool.releaseProcess() ↓ Return JSON result ``` ## Configuration Values ```typescript // Recommended defaults { poolSize: 3, // Balance concurrency vs resources defaultPrecision: 20, // Good for scientific calculations defaultTimeout: 30000, // 30 seconds maxExpressionLength: 10000 // 10KB } ``` ## BC Math Library Functions | Function | BC Syntax | Example | Result | |----------|-----------|---------|--------| | Sine | `s(x)` | `s(0)` | 0 | | Cosine | `c(x)` | `c(0)` | 1 | | Arctangent | `a(x)` | `a(1)` | 0.785398... | | Natural log | `l(x)` | `l(2.71828)` | 1 | | Exponential | `e(x)` | `e(1)` | 2.71828... | | Square root | `sqrt(x)` | `sqrt(4)` | 2 | Note: `s()`, `c()`, `a()`, `l()`, `e()` are only available with `-l` flag! ## Error Messages Reference | Error Type | Example Message | Cause | |------------|----------------|-------| | Validation | "Expression contains invalid characters" | Bad input | | BC Runtime | "BC error: divide by zero" | Math error | | Timeout | "Calculation timeout after 30000ms" | Too long | | Process | "BC process not ready" | Process crashed | ## Success Response Format ```json { "content": [{ "type": "text", "text": "{\"result\":\"4\",\"expression\":\"2+2\",\"precision\":20}" }] } ``` ## Error Response Format ```json { "content": [{ "type": "text", "text": "Validation error: ..." }], "isError": true } ``` ## Implementation Sequence 1. ✅ **types.ts** - Core type definitions 2. ✅ **input-validator.ts** - Security first! 3. ✅ **bc-process.ts** - Single process wrapper 4. ✅ **bc-process-pool.ts** - Multi-process manager 5. ✅ **index.ts** - MCP server glue code 6. ✅ Build & test 7. ✅ Add to MCP settings 8. ✅ Verify with test cases ## Final Checks Before Deployment - [ ] All files have proper imports/exports - [ ] TypeScript compiles without errors - [ ] Build output is executable (`+x`) - [ ] MCP settings contains correct path - [ ] BC is installed and in PATH - [ ] Security validation is working - [ ] Timeout mechanism tested - [ ] Process pool initializes correctly - [ ] All three tools respond properly - [ ] Error handling catches edge cases ## Support Resources - **Architecture**: `ARCHITECTURE.md` - System design - **Implementation**: `IMPLEMENTATION_GUIDE.md` - Detailed code guide - **Usage**: `README.md` - User documentation - **MCP Docs**: https://modelcontextprotocol.io/ - **BC Manual**: `man bc` or online GNU BC documentation

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cthunter01/MCPCalculator'

If you have feedback or need assistance with the MCP directory API, please join our Discord server