Spaces:
Running
Running
| # MCP Integration Layer | |
| """ | |
| Model Context Protocol (MCP) Integration for AI Business Analyst. | |
| This module provides MCP-compatible tools for: | |
| - Data cleaning and preprocessing | |
| - Embedding generation | |
| - Graph construction | |
| - SQL execution | |
| - Vision/OCR processing | |
| - Forecasting engine (time-series prediction) | |
| - Simulation engine (what-if scenarios) | |
| - Insight engine (automated analysis) | |
| Architecture: | |
| - Internal Python modules (not external servers) | |
| - Unified tool interface | |
| - Async-ready design | |
| """ | |
| from dataclasses import dataclass | |
| from typing import Any, Dict, List, Optional, Callable | |
| from enum import Enum | |
| import json | |
| class MCPToolType(Enum): | |
| """Types of MCP tools available""" | |
| DATA_CLEANER = "data_cleaner" | |
| VECTORIZER = "vectorizer" | |
| GRAPH_BUILDER = "graph_builder" | |
| SQL_EXECUTOR = "sql_executor" | |
| VISION_OCR = "vision_ocr" | |
| FORECAST_ENGINE = "forecast_engine" | |
| SIMULATION_ENGINE = "simulation_engine" | |
| INSIGHT_ENGINE = "insight_engine" | |
| PREDICTION_ENGINE = "prediction_engine" | |
| CHART_GENERATOR = "chart_generator" | |
| class MCPToolResult: | |
| """Result from an MCP tool execution""" | |
| success: bool | |
| data: Any | |
| error: Optional[str] = None | |
| metadata: Optional[Dict] = None | |
| class MCPTool: | |
| """Definition of an MCP tool""" | |
| name: str | |
| description: str | |
| tool_type: MCPToolType | |
| parameters: Dict[str, Any] | |
| handler: Callable | |
| class MCPRegistry: | |
| """ | |
| Registry for MCP tools. | |
| Provides a unified interface for all MCP capabilities. | |
| """ | |
| def __init__(self): | |
| self._tools: Dict[str, MCPTool] = {} | |
| self._initialize_tools() | |
| def _initialize_tools(self): | |
| """Initialize all MCP tools""" | |
| # Import tool handlers | |
| from mcp.data_cleaner import ( | |
| clean_table, | |
| format_numbers, | |
| normalize_dates, | |
| deduplicate_rows | |
| ) | |
| from mcp.vectorizer import ( | |
| generate_embeddings, | |
| batch_embed, | |
| compute_similarity | |
| ) | |
| from mcp.graph_builder import ( | |
| extract_entities, | |
| build_graph_json, | |
| merge_graphs | |
| ) | |
| from mcp.sql_executor import ( | |
| execute_sql, | |
| create_table_from_df, | |
| query_to_dataframe | |
| ) | |
| from mcp.vision_ocr import ( | |
| extract_text_from_image, | |
| extract_tables_from_image, | |
| analyze_chart | |
| ) | |
| from mcp.forecast_engine import ( | |
| ForecastEngine, | |
| forecast_from_dataframe | |
| ) | |
| from mcp.simulation_engine import ( | |
| SimulationEngine, | |
| simulate_scenarios | |
| ) | |
| from mcp.insight_engine import ( | |
| InsightEngine, | |
| generate_insights | |
| ) | |
| from mcp.prediction_engine import ( | |
| PredictionEngine, | |
| predict_revenue, | |
| predict_sales, | |
| predict_churn, | |
| predict_demand | |
| ) | |
| from mcp.chart_generator import ( | |
| ChartGenerator, | |
| generate_forecast_chart, | |
| generate_scenario_chart | |
| ) | |
| # Register Data Cleaner tools | |
| self._register_tool(MCPTool( | |
| name="clean_table", | |
| description="Clean and normalize tabular data", | |
| tool_type=MCPToolType.DATA_CLEANER, | |
| parameters={"data": "DataFrame or dict", "options": "CleaningOptions"}, | |
| handler=clean_table | |
| )) | |
| self._register_tool(MCPTool( | |
| name="format_numbers", | |
| description="Format and standardize numeric columns", | |
| tool_type=MCPToolType.DATA_CLEANER, | |
| parameters={"data": "DataFrame", "columns": "List[str]", "format": "str"}, | |
| handler=format_numbers | |
| )) | |
| self._register_tool(MCPTool( | |
| name="normalize_dates", | |
| description="Normalize date formats across data", | |
| tool_type=MCPToolType.DATA_CLEANER, | |
| parameters={"data": "DataFrame", "date_columns": "List[str]"}, | |
| handler=normalize_dates | |
| )) | |
| self._register_tool(MCPTool( | |
| name="deduplicate_rows", | |
| description="Remove duplicate rows from data", | |
| tool_type=MCPToolType.DATA_CLEANER, | |
| parameters={"data": "DataFrame", "subset": "Optional[List[str]]"}, | |
| handler=deduplicate_rows | |
| )) | |
| # Register Vectorizer tools | |
| self._register_tool(MCPTool( | |
| name="generate_embeddings", | |
| description="Generate embeddings for text", | |
| tool_type=MCPToolType.VECTORIZER, | |
| parameters={"text": "str"}, | |
| handler=generate_embeddings | |
| )) | |
| self._register_tool(MCPTool( | |
| name="batch_embed", | |
| description="Generate embeddings for multiple texts", | |
| tool_type=MCPToolType.VECTORIZER, | |
| parameters={"texts": "List[str]", "batch_size": "int"}, | |
| handler=batch_embed | |
| )) | |
| self._register_tool(MCPTool( | |
| name="compute_similarity", | |
| description="Compute similarity between embeddings", | |
| tool_type=MCPToolType.VECTORIZER, | |
| parameters={"embedding1": "List[float]", "embedding2": "List[float]"}, | |
| handler=compute_similarity | |
| )) | |
| # Register Graph Builder tools | |
| self._register_tool(MCPTool( | |
| name="extract_entities", | |
| description="Extract entities from text or data", | |
| tool_type=MCPToolType.GRAPH_BUILDER, | |
| parameters={"data": "Any", "entity_types": "List[str]"}, | |
| handler=extract_entities | |
| )) | |
| self._register_tool(MCPTool( | |
| name="build_graph_json", | |
| description="Build graph structure from entities", | |
| tool_type=MCPToolType.GRAPH_BUILDER, | |
| parameters={"entities": "List[Dict]", "relations": "List[Dict]"}, | |
| handler=build_graph_json | |
| )) | |
| self._register_tool(MCPTool( | |
| name="merge_graphs", | |
| description="Merge multiple graphs into one", | |
| tool_type=MCPToolType.GRAPH_BUILDER, | |
| parameters={"graphs": "List[Dict]"}, | |
| handler=merge_graphs | |
| )) | |
| # Register SQL Executor tools | |
| self._register_tool(MCPTool( | |
| name="execute_sql", | |
| description="Execute SQL query on data", | |
| tool_type=MCPToolType.SQL_EXECUTOR, | |
| parameters={"query": "str", "data": "Dict[str, DataFrame]"}, | |
| handler=execute_sql | |
| )) | |
| self._register_tool(MCPTool( | |
| name="create_table_from_df", | |
| description="Create virtual table from DataFrame", | |
| tool_type=MCPToolType.SQL_EXECUTOR, | |
| parameters={"name": "str", "df": "DataFrame"}, | |
| handler=create_table_from_df | |
| )) | |
| self._register_tool(MCPTool( | |
| name="query_to_dataframe", | |
| description="Execute query and return DataFrame", | |
| tool_type=MCPToolType.SQL_EXECUTOR, | |
| parameters={"query": "str"}, | |
| handler=query_to_dataframe | |
| )) | |
| # Register Vision/OCR tools | |
| self._register_tool(MCPTool( | |
| name="extract_text_from_image", | |
| description="Extract text from image using OCR", | |
| tool_type=MCPToolType.VISION_OCR, | |
| parameters={"image_path": "str"}, | |
| handler=extract_text_from_image | |
| )) | |
| self._register_tool(MCPTool( | |
| name="extract_tables_from_image", | |
| description="Extract tables from image", | |
| tool_type=MCPToolType.VISION_OCR, | |
| parameters={"image_path": "str"}, | |
| handler=extract_tables_from_image | |
| )) | |
| self._register_tool(MCPTool( | |
| name="analyze_chart", | |
| description="Analyze chart image and extract data", | |
| tool_type=MCPToolType.VISION_OCR, | |
| parameters={"image_path": "str", "chart_type": "Optional[str]"}, | |
| handler=analyze_chart | |
| )) | |
| # Register Forecast Engine tools | |
| forecast_engine = ForecastEngine() | |
| self._register_tool(MCPTool( | |
| name="forecast_timeseries", | |
| description="Generate time-series forecast with confidence intervals", | |
| tool_type=MCPToolType.FORECAST_ENGINE, | |
| parameters={"data": "List[Dict]", "periods": "int", "confidence": "float"}, | |
| handler=forecast_engine.forecast | |
| )) | |
| self._register_tool(MCPTool( | |
| name="forecast_from_dataframe", | |
| description="Generate forecast from pandas DataFrame", | |
| tool_type=MCPToolType.FORECAST_ENGINE, | |
| parameters={"df": "DataFrame", "date_col": "str", "value_col": "str", "periods": "int"}, | |
| handler=forecast_from_dataframe | |
| )) | |
| # Register Simulation Engine tools | |
| simulation_engine = SimulationEngine() | |
| self._register_tool(MCPTool( | |
| name="simulate_scenarios", | |
| description="Run what-if business scenarios (price, marketing, churn)", | |
| tool_type=MCPToolType.SIMULATION_ENGINE, | |
| parameters={"base_revenue": "float", "base_customers": "int", "modifiers": "Dict"}, | |
| handler=simulate_scenarios | |
| )) | |
| self._register_tool(MCPTool( | |
| name="simulate_pricing", | |
| description="Simulate price change impact on revenue", | |
| tool_type=MCPToolType.SIMULATION_ENGINE, | |
| parameters={"base_revenue": "float", "price_change_pct": "List[float]"}, | |
| handler=simulation_engine.simulate | |
| )) | |
| self._register_tool(MCPTool( | |
| name="monte_carlo", | |
| description="Run Monte Carlo simulation for revenue prediction", | |
| tool_type=MCPToolType.SIMULATION_ENGINE, | |
| parameters={"base_revenue": "float", "uncertainty": "float", "simulations": "int"}, | |
| handler=simulation_engine.run_monte_carlo | |
| )) | |
| # Register Insight Engine tools | |
| insight_engine = InsightEngine() | |
| self._register_tool(MCPTool( | |
| name="generate_insights", | |
| description="Generate automated business insights from metrics", | |
| tool_type=MCPToolType.INSIGHT_ENGINE, | |
| parameters={"revenue": "float", "customers": "int", "churn_rate": "float"}, | |
| handler=generate_insights | |
| )) | |
| self._register_tool(MCPTool( | |
| name="analyze_business", | |
| description="Full business analysis with trends, risks, and opportunities", | |
| tool_type=MCPToolType.INSIGHT_ENGINE, | |
| parameters={"revenue": "float", "revenue_previous": "float", "customers": "int", "orders": "int"}, | |
| handler=insight_engine.analyze | |
| )) | |
| def _register_tool(self, tool: MCPTool): | |
| """Register a tool in the registry""" | |
| self._tools[tool.name] = tool | |
| def get_tool(self, name: str) -> Optional[MCPTool]: | |
| """Get a tool by name""" | |
| return self._tools.get(name) | |
| def list_tools(self, tool_type: Optional[MCPToolType] = None) -> List[MCPTool]: | |
| """List all tools, optionally filtered by type""" | |
| if tool_type: | |
| return [t for t in self._tools.values() if t.tool_type == tool_type] | |
| return list(self._tools.values()) | |
| def execute(self, tool_name: str, **kwargs) -> MCPToolResult: | |
| """Execute a tool by name with given parameters""" | |
| tool = self.get_tool(tool_name) | |
| if not tool: | |
| return MCPToolResult( | |
| success=False, | |
| data=None, | |
| error=f"Tool '{tool_name}' not found" | |
| ) | |
| try: | |
| result = tool.handler(**kwargs) | |
| return MCPToolResult( | |
| success=True, | |
| data=result, | |
| metadata={"tool": tool_name} | |
| ) | |
| except Exception as e: | |
| return MCPToolResult( | |
| success=False, | |
| data=None, | |
| error=str(e), | |
| metadata={"tool": tool_name} | |
| ) | |
| def get_schema(self) -> Dict: | |
| """Get MCP-compatible schema for all tools""" | |
| schema = { | |
| "tools": [] | |
| } | |
| for tool in self._tools.values(): | |
| tool_schema = { | |
| "name": tool.name, | |
| "description": tool.description, | |
| "type": tool.tool_type.value, | |
| "parameters": tool.parameters | |
| } | |
| schema["tools"].append(tool_schema) | |
| return schema | |
| # Lazy singleton | |
| _registry = None | |
| def get_mcp_registry() -> MCPRegistry: | |
| """Get or create the MCP registry singleton""" | |
| global _registry | |
| if _registry is None: | |
| _registry = MCPRegistry() | |
| return _registry | |
| def execute_mcp_tool(tool_name: str, **kwargs) -> MCPToolResult: | |
| """Convenience function to execute an MCP tool""" | |
| registry = get_mcp_registry() | |
| return registry.execute(tool_name, **kwargs) | |