Skip to main content
Glama
by apetta
server.py31.3 kB
"""Vibe Math - High-performance mathematical operations using Polars and scientific Python.""" import json from typing import Annotated, Any, Dict, Literal from fastmcp import FastMCP from pydantic import Field from fastmcp.tools import Tool from fastmcp.tools.tool_transform import forward from mcp.types import TextContent # Version is defined here to avoid circular import with __init__.py __version__ = "2.0.3" # ============================================================================ # Output Transformation Helpers # ============================================================================ def is_sequential_chain(results: list) -> bool: """Detect if operations form pure sequential chain (no branching).""" if len(results) <= 1: return True dependents = {} for r in results: for dep in r.get("dependencies", []): if dep not in dependents: dependents[dep] = [] dependents[dep].append(r["id"]) all_ids = {r["id"] for r in results} roots = [r["id"] for r in results if not r.get("dependencies")] terminals = [op_id for op_id in all_ids if op_id not in dependents] if len(roots) != 1 or len(terminals) != 1: return False for op_id in all_ids: if op_id != terminals[0]: if op_id not in dependents or len(dependents[op_id]) != 1: return False return True def find_terminal_operation(results: list) -> str | None: """Find terminal operation (one with no dependents).""" if not results: return None has_dependents = set() for r in results: has_dependents.update(r.get("dependencies", [])) terminals = [r["id"] for r in results if r["id"] not in has_dependents] return terminals[0] if len(terminals) == 1 else None def transform_single_response(data: Dict[str, Any], mode: str) -> Dict[str, Any]: """Transform single tool response based on output mode. Args: data: Original tool response (already JSON-parsed) mode: Output mode (full, compact, minimal, value, final) Returns: Transformed response dictionary """ if mode == "final": mode = "value" if mode == "full": return data if mode == "compact": # Remove None/null values, preserve structure return {k: v for k, v in data.items() if v is not None} if mode == "minimal": # Keep only result + context if present minimal = {"result": data["result"]} # Preserve context if present if "context" in data: minimal["context"] = data["context"] return minimal if mode == "value": # Normalize to {value: X} structure result = {"value": data["result"]} # Preserve context if present if "context" in data: result["context"] = data["context"] return result # Fallback (should never reach here) return data def transform_batch_response(data: Dict[str, Any], mode: str) -> Dict[str, Any]: """Transform batch execution response based on output mode. Args: data: Batch response with 'results' and 'summary' keys mode: Output mode (full, compact, minimal, value, final) Returns: Transformed batch response """ results = data.get("results", []) summary = data.get("summary", {}) batch_context = data.get("context") if mode == "final": failed_count = summary.get("failed", 0) # Check for failures first - if any failures exist, use minimal mode # This ensures error visibility even in sequential chains if failed_count > 0: return transform_batch_response(data, "minimal") # No failures - check if sequential chain for terminal-only output if is_sequential_chain(results): terminal_id = find_terminal_operation(results) if terminal_id: terminal = next((r for r in results if r["id"] == terminal_id), None) if terminal and terminal.get("status") == "success": result = { "result": terminal["result"]["result"], "summary": { "succeeded": summary.get("succeeded", 0), "failed": summary.get("failed", 0), "time_ms": summary.get("total_execution_time_ms", 0), }, } if batch_context is not None: result["context"] = batch_context return result # Non-sequential with no failures - fall back to value mode return transform_batch_response(data, "value") if mode == "value": value_map = {} errors = {} for r in results: if r.get("status") == "success" and r.get("result"): op_id = r["id"] value_map[op_id] = r["result"]["result"] elif r.get("status") == "error": # Extract error message (could be string or dict) error_info = r.get("error") if isinstance(error_info, dict): errors[r["id"]] = error_info.get("message", str(error_info)) else: errors[r["id"]] = str(error_info) result = { **value_map, "summary": { "succeeded": summary.get("succeeded", 0), "failed": summary.get("failed", 0), "time_ms": summary.get("total_execution_time_ms", 0), }, } # Add errors if any operations failed if errors: result["errors"] = errors if batch_context is not None: result["context"] = batch_context return result if mode == "minimal": minimal_results = [] for r in results: minimal_op = { "id": r["id"], "status": r["status"], "wave": r.get("wave", 0), } if r.get("status") == "success" and r.get("result"): minimal_op["value"] = r["result"]["result"] if "context" in r["result"] and r["result"]["context"] is not None: minimal_op["context"] = r["result"]["context"] elif r.get("error"): minimal_op["error"] = r["error"].get("message", "Unknown error") minimal_results.append(minimal_op) result = {"results": minimal_results, "summary": summary} if batch_context is not None: result["context"] = batch_context return result if mode == "compact": compact_results = [{k: v for k, v in r.items() if v is not None} for r in results] result = {"results": compact_results, "summary": summary} if batch_context is not None: result["context"] = batch_context return result # full mode - return as-is return data class CustomMCP(FastMCP): """Custom FastMCP subclass with automatic context injection and output control. This custom subclass intercepts tool registration using FastMCP's Tool Transformation API. Every tool is automatically wrapped to accept optional parameters that enhance LLM usability: 1. **context**: Label calculations for identification (e.g., "Bond A PV", "Q2 revenue") 2. **output_mode**: Control response verbosity and structure Output Modes: - "full" (default): Complete response with all metadata - backward compatible - "compact": Remove null fields, minimize whitespace (~20-30% smaller) - "minimal": Primary value(s) only, no metadata (~60-70% smaller) - "value": Normalized {value: X} structure (~70-80% smaller) Architecture: - Overrides add_tool() to transform tools at registration time - Uses Tool.from_tool() with transform_fn for parameter injection - Leverages FastMCP's built-in transformation system (no hacks) - Works with Pydantic validation (transformation happens AFTER tool creation) - Special handling for batch_execute vs single tools Benefits: - Zero boilerplate in tool functions - Automatic for all existing and future tools - Type-safe and production-grade - Massive token savings for LLM consumers """ def add_tool(self, tool: Tool) -> Tool: """Override add_tool to inject context and output_mode parameters. Uses FastMCP's official Tool.from_tool() API to wrap each tool with automatic context injection and intelligent output control. """ # Detect if this is the batch_execute tool for special handling is_batch_tool = tool.name == "batch_execute" # Define the unified transform function async def unified_transform( context: Annotated[ str | None, Field( description=( "Optional annotation to label this calculation " "(e.g., 'Bond A PV', 'Q2 revenue'). " "Appears in results for easy identification." ) ), ] = None, output_mode: Annotated[ Literal["full", "compact", "minimal", "value", "final"], Field( description="Output format: full (default), compact, minimal, value, or final. See batch_execute tool for details." ), ] = "full", **kwargs: Any, ) -> str: """Transform function for context injection and output control. Args: context: Optional context string from LLM output_mode: Output verbosity control **kwargs: All original tool arguments (passed through) Returns: Transformed tool result as JSON string """ # Call the original tool using FastMCP's forward() function tool_result = await forward(**kwargs) # Extract text from ToolResult content # All tools return JSON strings as TextContent if ( tool_result.content and len(tool_result.content) > 0 and isinstance(tool_result.content[0], TextContent) ): result_str = tool_result.content[0].text else: # This should never happen as all tools return TextContent raise ValueError( f"Expected TextContent from tool, got " f"{type(tool_result.content[0]) if tool_result.content else 'no content'}" ) # Parse JSON result try: result_data = json.loads(result_str) except (json.JSONDecodeError, TypeError): # Tool returned non-JSON (unexpected) - return original return result_str # Inject context if provided (before transformation) if context is not None: result_data["context"] = context # Apply output transformation based on tool type if is_batch_tool: result_data = transform_batch_response(result_data, output_mode) else: result_data = transform_single_response(result_data, output_mode) # Serialize based on mode if output_mode == "compact": # No indentation for compact mode return json.dumps(result_data, separators=(",", ":"), default=str) else: # Pretty-print for all other modes return json.dumps(result_data, indent=2, default=str) # Transform the tool to add context and output_mode handling transformed_tool = Tool.from_tool( tool=tool, transform_fn=unified_transform, # Preserve all original metadata name=tool.name, description=tool.description, ) # Register the transformed tool with parent class return super().add_tool(transformed_tool) # Create CustomMCP server instance mcp = CustomMCP( "vibe-math-mcp", version=__version__, instructions="""Use this server for ANY calculation, formula evaluation, or quantitative analysis. Delegate to production-grade tools (Polars, NumPy, SciPy, SymPy) for precision, never manually compute or approximate. **Comprehensive coverage (21 tools):** • Basic math (expressions, percentages, rounding, unit conversion) • Arrays (operations, statistics, aggregations, transformations) • Statistics (descriptive analysis, pivot tables, correlations) • Financial (TVM/PV/FV/IRR/NPV, compound interest, perpetuities, growing annuities) • Linear algebra (matrices, systems of equations, decompositions) • Calculus (derivatives, integrals, limits, series expansions) **Key capabilities:** • Exact symbolic computation (not approximations) • Multi-step workflows with dependency chaining (batch_execute) • Token-efficient output modes (up to 95% reduction) • Context tracking for complex calculations • Professional numerical libraries (battle-tested, validated) **Use when:** • ANY quantitative calculation is needed • Precision required (no rounding errors or mental math) • Multi-step workflows (financial models, data transformations, statistical pipelines) • Matrix operations, calculus, or financial formulas **Default behavior:** Reach for these tools for quantitative work instead of manual calculation or approximation.""", ) # ============================================================================ # MCP Prompts - Common Mathematical Workflows # ============================================================================ @mcp.prompt() def financial_calculation( calculation_type: Annotated[ Literal["bond_pricing", "loan_payment", "investment_analysis"], Field(description="Type of financial calculation to perform"), ] = "bond_pricing", ) -> str: """Financial calculation workflows: bond pricing, loans, NPV/IRR.""" workflows = { "bond_pricing": """Bond Pricing (PV of coupon bond) 1. calculate("principal * rate", {principal: 1000, rate: 0.04}) → 40 (annual coupon) 2. financial_calcs(calculation="pv", rate=0.05, periods=10, payment=40, future_value=1000) → bond price Batch example: {"operations": [ {"id": "coup", "tool": "calculate", "arguments": {"expression": "p*r", "variables": {"p": 1000, "r": 0.04}}}, {"id": "pv", "tool": "financial_calcs", "arguments": {"calculation": "pv", "rate": 0.05, "periods": 10, "payment": "$coup.result", "future_value": 1000}} ], "output_mode": "value"}""", "loan_payment": """Loan Payment (monthly mortgage) 1. calculate("apr / 12", {apr: 0.045}) → 0.00375 (monthly rate) 2. calculate("years * 12", {years: 30}) → 360 (periods) 3. financial_calcs(calculation="pmt", rate=0.00375, periods=360, present_value=-200000, future_value=0) → monthly payment""", "investment_analysis": """NPV/IRR (project evaluation) NPV: financial_calcs(calculation="npv", rate=0.10, cash_flows=[-100000, 30000, 40000, 50000]) IRR: financial_calcs(calculation="irr", cash_flows=[-100000, 30000, 40000, 50000]) Choose higher NPV or IRR > required return. Batch compare: {"operations": [ {"id": "a_npv", "tool": "financial_calcs", "arguments": {"calculation": "npv", "rate": 0.10, "cash_flows": [-100000, 30000, 40000, 50000]}}, {"id": "a_irr", "tool": "financial_calcs", "arguments": {"calculation": "irr", "cash_flows": [-100000, 30000, 40000, 50000]}}, {"id": "b_npv", "tool": "financial_calcs", "arguments": {"calculation": "npv", "rate": 0.10, "cash_flows": [-80000, 25000, 35000, 35000]}}, {"id": "b_irr", "tool": "financial_calcs", "arguments": {"calculation": "irr", "cash_flows": [-80000, 25000, 35000, 35000]}} ], "execution_mode": "parallel", "output_mode": "value"}""", } return workflows[calculation_type] @mcp.prompt() def statistical_analysis( analysis_type: Annotated[ Literal["descriptive", "correlation", "outliers"], Field(description="Type of statistical analysis to perform"), ] = "descriptive", ) -> str: """Statistical analysis: descriptive stats, correlation, outlier detection.""" workflows = { "descriptive": """Descriptive Statistics statistics(data=[12,15,18,20,22,25,28,30,100], analyses=["describe","quartiles","outliers"]) → count, mean, std, min, max, median, Q1, Q2, Q3, IQR, outlier detection Multi-dimensional: array_statistics(data=[[1,2,3],[4,5,6]], operations=["mean","std"], axis=0) → column stats""", "correlation": """Correlation Analysis Pearson (linear): correlation(data={"height": [170,175,168], "weight": [65,78,62]}, method="pearson", output_format="matrix") → correlation matrix: 1.0=perfect positive, -1.0=perfect negative, 0.0=no relationship Spearman (monotonic, robust to outliers): same but method="spearman" """, "outliers": """Outlier Detection (IQR method) statistics(data=[12,15,18,20,22,25,28,30,100,105], analyses=["outliers"]) → outlier_values, outlier_count, bounds (Q1-1.5×IQR to Q3+1.5×IQR) Compare with/without: Use batch_execute to run analyses on original + cleaned data Multi-dimensional: array_transform(data, transform="standardize") then |Z| > 3 = outliers""", } return workflows[analysis_type] @mcp.prompt() def matrix_problem( problem_type: Annotated[ Literal["solve_system", "decomposition", "operations"], Field(description="Type of matrix problem to solve"), ] = "solve_system", ) -> str: """Linear algebra: solve systems, decompositions, matrix operations.""" workflows = { "solve_system": """Solve Ax = b Square (exact): solve_linear_system(coefficients=[[2,3],[1,1]], constants=[8,3], method="direct") → [x=1, y=2] Overdetermined (best-fit): solve_linear_system(coefficients=[[1,2],[3,4],[5,6]], constants=[5,6,7], method="least_squares")""", "decomposition": """Matrix Decompositions eigen (PCA, stability): matrix_decomposition(matrix=[[4,2],[1,3]], decomposition="eigen") → eigenvalues, eigenvectors svd (dimensionality reduction): decomposition="svd" → U, singular_values, Vt qr (least squares): decomposition="qr" → Q (orthogonal), R (upper triangular) cholesky (positive definite): decomposition="cholesky" → L where A=LL^T lu (solving, determinant): decomposition="lu" → P, L, U where PA=LU""", "operations": """Matrix Operations multiply: matrix_operations(operation="multiply", matrix1=[[1,2],[3,4]], matrix2=[[5,6],[7,8]]) inverse: operation="inverse" → A⁻¹ (square matrices only) transpose: operation="transpose" → Aᵀ determinant: operation="determinant" → scalar trace: operation="trace" → sum of diagonal Element-wise: Use array_operations(operation="add/subtract/multiply/divide/power", ...)""", } return workflows[problem_type] @mcp.prompt() def batch_workflow( workflow_type: Annotated[ Literal["financial_model", "data_pipeline", "transformation"], Field(description="Type of multi-step workflow to demonstrate"), ] = "financial_model", ) -> str: """Multi-step batch_execute workflows with dependency chaining.""" workflows = { "financial_model": """Bond Maturity Value (dependency chaining + parallel execution) {"operations": [ {"id": "c", "tool": "calculate", "arguments": {"expression": "p*r", "variables": {"p": 1000000, "r": 0.04}}}, {"id": "cfv", "tool": "financial_calcs", "arguments": {"calculation": "fv", "rate": 0.04, "periods": 10, "payment": "$c.result", "present_value": 0}}, {"id": "pfv", "tool": "compound_interest", "arguments": {"principal": 1000000, "rate": 0.04, "time": 10, "frequency": "annual"}}, {"id": "tot", "tool": "calculate", "arguments": {"expression": "cfv+pfv", "variables": {"cfv": "$cfv.result", "pfv": "$pfv.result"}}} ], "execution_mode": "auto", "output_mode": "value"} Wave 1: c | Wave 2: cfv, pfv (parallel) | Wave 3: tot""", "data_pipeline": """Data Pipeline (transform → analyze → outliers) {"operations": [ {"id": "norm", "tool": "array_transform", "arguments": {"data": [[10,20,30],[40,50,60],[70,80,90]], "transform": "minmax_scale", "axis": 0}}, {"id": "stats", "tool": "array_statistics", "arguments": {"data": "$norm.result", "operations": ["mean","std"], "axis": 0}}, {"id": "sums", "tool": "array_statistics", "arguments": {"data": "$norm.result", "operations": ["sum"], "axis": 1}}, {"id": "out", "tool": "statistics", "arguments": {"data": "$sums.result.sum", "analyses": ["outliers"]}} ], "execution_mode": "auto", "output_mode": "minimal"} Wave 1: norm | Wave 2: stats, sums (parallel) | Wave 3: out""", "transformation": """Calculus Chain (derive → evaluate → integrate → round) {"operations": [ {"id": "d", "tool": "derivative", "arguments": {"expression": "x^3+2*x^2+x", "variable": "x", "order": 1}}, {"id": "ev", "tool": "calculate", "arguments": {"expression": "3*x^2+4*x+1", "variables": {"x": 2}}}, {"id": "i", "tool": "integral", "arguments": {"expression": "x^3+2*x^2+x", "variable": "x", "lower_bound": 0, "upper_bound": 2, "method": "symbolic"}}, {"id": "r", "tool": "round", "arguments": {"values": ["$ev.result","$i.result"], "method": "round", "decimals": 2}} ], "execution_mode": "auto", "output_mode": "final"} output_mode options: "full" (all metadata), "value" (flat map, 70-80% reduction), "final" (terminal only, 95% reduction)""", } return workflows[workflow_type] # ============================================================================ # MCP Resources - Server Documentation # ============================================================================ @mcp.resource("tools://available") def available_tools() -> str: """List all 21 available mathematical tools with descriptions. Returns structured documentation of all tools organised by category. """ return """Available Mathematical Tools (21) BASIC (4) calculate: SymPy expressions | calculate(expression="x^2+2*x+1", variables={"x": 3}) → 16 percentage: of/increase/decrease/change | percentage(operation="of", value=200, percentage=15) → 30 round: nearest/floor/ceil/trunc | round(values=3.14159, method="round", decimals=2) → 3.14 convert_units: degrees ↔ radians | convert_units(value=180, from_unit="degrees", to_unit="radians") → π ARRAY (4) array_operations: element-wise add/subtract/multiply/divide/power | array_operations(operation="multiply", array1=[[1,2],[3,4]], array2=2) → [[2,4],[6,8]] array_statistics: mean/median/std/min/max/sum (axis: 0=col, 1=row, None=all) | array_statistics(data=[[1,2,3],[4,5,6]], operations=["mean"], axis=0) → [2.5,3.5,4.5] array_aggregate: sumproduct/weighted_average/dot_product | array_aggregate(operation="sumproduct", array1=[1,2,3], array2=[4,5,6]) → 32 array_transform: normalize/standardize/minmax_scale/log_transform | array_transform(data=[[3,4]], transform="normalize") → [[0.6,0.8]] STATISTICS (3) statistics: describe/quartiles/outliers (IQR-based) | statistics(data=[1,2,3,4,5,100], analyses=["describe","outliers"]) pivot_table: reshape tabular data (sum/mean/count/min/max) | pivot_table(data=[...], index="region", columns="product", values="sales") correlation: pearson/spearman (matrix/pairs format) | correlation(data={"x":[1,2,3], "y":[2,4,6]}, method="pearson") FINANCIAL (3) financial_calcs: PV/FV/PMT/rate/IRR/NPV (TVM) | financial_calcs(calculation="pv", rate=0.05, periods=10, payment=30, future_value=1000) compound_interest: discrete/continuous compounding | compound_interest(principal=1000, rate=0.05, time=10, frequency="monthly") perpetuity: level/growing, ordinary/due | perpetuity(payment=1000, rate=0.05) → 20000 LINEAR ALGEBRA (3) matrix_operations: multiply/inverse/transpose/determinant/trace | matrix_operations(operation="multiply", matrix1=[[1,2],[3,4]], matrix2=[[5,6],[7,8]]) solve_linear_system: Ax=b (direct/least_squares) | solve_linear_system(coefficients=[[2,3],[1,1]], constants=[8,3]) → [1,2] matrix_decomposition: eigen/svd/qr/cholesky/lu | matrix_decomposition(matrix=[[4,2],[1,3]], decomposition="eigen") CALCULUS (3) derivative: symbolic/numerical, partial derivatives | derivative(expression="x^3+2*x^2", variable="x", order=1) → "3*x^2+4*x" integral: symbolic/numerical, definite/indefinite | integral(expression="x^2", variable="x", lower_bound=0, upper_bound=1) → 0.333 limits_series: limits (point/infinity/one-sided), Taylor/Maclaurin | limits_series(expression="sin(x)/x", variable="x", point=0, operation="limit") → 1 BATCH (1) batch_execute: multi-step workflows with dependency chaining ($op_id.result) | DAG-based auto parallelization | execution_mode: auto/sequential/parallel | 90-95% token reduction | See docs://batch-execution Global params (all tools): context="label", output_mode="full/compact/minimal/value/final" (70-95% token reduction) """ @mcp.resource("docs://batch-execution") def batch_execution_guide() -> str: """Comprehensive guide to using batch_execute for multi-step workflows. Covers dependency chaining, execution modes, output modes, and best practices. """ return """Batch Execution Guide Use for: Multi-step workflows with dependencies (step N needs step N-1), parallel scenarios, data pipelines Skip for: Single operations, workflows needing intermediate validation DEPENDENCY CHAINING Reference: $op_id.result (primary), $op_id.result[0] (array index), $op_id.metadata.field (nested) {"operations": [ {"id": "s1", "tool": "calculate", "arguments": {"expression": "100*0.05"}}, {"id": "s2", "tool": "calculate", "arguments": {"expression": "x+10", "variables": {"x": "$s1.result"}}} ]} EXECUTION MODES auto (recommended): DAG-based, parallel within wave, sequential across waves → max performance sequential: strict order (first to last) → use when order matters beyond dependencies parallel: all concurrent → use only for truly independent operations (fails if dependencies exist) OUTPUT MODES (See docs://output-modes for details) full: all metadata (~4-5KB for 4 ops) → debugging compact: remove nulls (~20-30% reduction) → production with moderate logging minimal: operation objects only (~60-70% reduction) → focus on results value: flat {id: value} map (~70-80% reduction) → production minimalist final: terminal result only (~95% reduction) → sequential chains, max efficiency ERROR HANDLING stop_on_error=false (default): independent ops continue even if others fail stop_on_error=true: stop at first error → use for strict sequential dependencies Errors include: failed op ID, message, partial results, summary EXAMPLE: Bond Maturity Value {"operations": [ {"id": "coup", "tool": "calculate", "arguments": {"expression": "p*r", "variables": {"p": 1000000, "r": 0.04}}}, {"id": "cfv", "tool": "financial_calcs", "arguments": {"calculation": "fv", "rate": 0.04, "periods": 10, "payment": "$coup.result", "present_value": 0}}, {"id": "pfv", "tool": "compound_interest", "arguments": {"principal": 1000000, "rate": 0.04, "time": 10, "frequency": "annual"}}, {"id": "tot", "tool": "calculate", "arguments": {"expression": "cfv+pfv", "variables": {"cfv": "$cfv.result", "pfv": "$pfv.result"}}} ], "execution_mode": "auto", "output_mode": "value"} Execution: W1=[coup] → W2=[cfv,pfv parallel] → W3=[tot] Response: {"coup": 40000, "cfv": 480244.28, "pfv": 1480244.28, "tot": 1960488.56, "summary": {...}} Token savings: value vs full = 75% (4.2KB → 1.1KB) PATTERNS Parallel compare: [scenario_a, scenario_b, scenario_c] | execution_mode="parallel" Sequential pipeline: load → transform → analyse → report | output_mode="final" Diamond: root → [branch_a, branch_b parallel] → merge | execution_mode="auto" LIMITS: max 100 ops, timeout 100ms-300s per op, no circular deps (DAG only), no nested batch_execute See batch_workflow prompt for financial/data/calculus examples """ @mcp.resource("docs://output-modes") def output_modes_guide() -> str: """Guide to output modes for controlling response size and structure. Explains the 5 output modes and when to use each for optimal token efficiency. """ return """Output Modes Guide All 21 tools support output_mode parameter for controlling response verbosity (70-95% token reduction possible) 5 MODES 1. full (default, 100% baseline) Use: development, debugging, first-time usage Returns: complete metadata (result, tool, timestamp, execution_time_ms, input echo, context) Single: {"result": 42, "metadata": {...}, "context": "...", "output_mode": "full"} Batch: full operation objects with dependencies, waves, execution times 2. compact (20-30% reduction) Use: production with moderate logging Returns: result + non-null metadata, no indentation (single-line JSON) Single: {"result":42,"context":"..."} Batch: compact operation array 3. minimal (60-70% reduction) Use: production focus on results, operation-level tracking needed Returns: result/value, context (if provided), status/wave (batch only), summary (batch only) Single: {"result": 42, "context": "..."} Batch: {"results": [{"id": "s1", "status": "success", "value": 42, "wave": 0}, ...], "summary": {...}} Removes: input echo, timestamps, detailed metadata, dependencies 4. value (70-80% reduction) ← RECOMMENDED for production batch workflows Use: production minimalist, flat key-value mapping Returns: flat structure, direct op_id → value mapping Single: {"value": 42, "context": "..."} Batch: {"step1": 42, "step2": 84, "step3": 126, "summary": {...}, "context": "..."} Errors: {"good_op": 42, "summary": {...}, "errors": {"bad_op": "Division by zero"}} 5. final (95% reduction, most aggressive) Use: sequential chains (A→B→C→D), only need final answer, max token efficiency Returns: terminal result only Batch: {"result": 168, "summary": {...}, "context": "..."} Requirements: pure sequential chain (no branching), all ops successful, batch_execute only Fallback: non-sequential → value mode, any failure → minimal mode, non-batch → value mode COMPARISON (4-op bond workflow) full: ~4200 bytes | compact: ~3000 bytes | minimal: ~1400 bytes (67% ↓) | value: ~800 bytes (81% ↓) | final: ~200 bytes (95% ↓) Single tool: full ~850B → value ~25B (97% reduction) Batch (10 ops): full ~10KB → value ~1.5KB (85% ↓) → final ~200B (98% ↓) RECOMMENDATION: Use value for production batch workflows, minimal for single tool calls in production, full for development only. Context preserved in all modes. Errors always included (safety first). """ # Import and register all tools (must be after mcp instance creation for decorators) from .tools import array, basic, batch, calculus, financial, linalg, statistics # noqa: E402 # Explicitly declare as part of module interface (tools registered via decorators) __all__ = ["mcp", "basic", "array", "batch", "statistics", "financial", "linalg", "calculus"] def main(): """Entry point for uvx.""" mcp.run() if __name__ == "__main__": main()

Latest Blog Posts

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/apetta/vibe-math-mcp'

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