Skip to main content
Glama

plot_math_function

Generate 2D plots of mathematical functions using Desmos API or local rendering to visualize equations with customizable x and y ranges.

Instructions

Generates a 2D plot. Tries Desmos API if available, otherwise falls back to local rendering.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
formulaYes
x_rangeNo
y_rangeNo
use_apiNo

Implementation Reference

  • The main handler function for the 'plot_math_function' tool. It handles plotting using Desmos API if available, falling back to local SymPy rendering, and returns a base64-encoded image URI.
    @mcp.tool()
    async def plot_math_function(
        ctx: MCPContext,
        formula: str,
        x_range: Optional[List[float]] = [-10, 10],
        y_range: Optional[List[float]] = None,
        use_api: bool = True
    ) -> str:
        """Generates a 2D plot. Tries Desmos API if available, otherwise falls back to local rendering."""
        await ctx.progress.start(message="Initializing plot...")
        
        if use_api and desmos_client:
            ctx.info("Attempting to plot with Desmos API...")
            await ctx.progress.report(1, 2, "Calling Desmos API...")
            try:
                image_bytes = await desmos_client.plot_formula(formula, x_range, y_range)
                if image_bytes:
                    await ctx.progress.report(2, 2, "Encoding image...")
                    img_base64 = base64.b64encode(image_bytes).decode('utf-8')
                    data_uri = f"data:image/png;base64,{img_base64}"
                    await ctx.progress.end()
                    return f"Successfully plotted '{formula}' using Desmos API. Image: {data_uri}"
                else:
                    ctx.warning("Desmos API call failed, falling back to local rendering.")
            except Exception as e:
                ctx.error(f"An exception occurred with Desmos API: {e}. Falling back to local rendering.")
    
        ctx.info("Using local rendering...")
        try:
            await ctx.progress.start(total=3, message="Starting local rendering...")
            
            await ctx.progress.report(1, 3, "Parsing formula...")
            expr = sympy.sympify(formula)
            x = sympy.symbols('x')
    
            await ctx.progress.report(2, 3, "Generating plot data...")
            plot_kwargs = {
                'show': False,
                'xlabel': 'x',
                'ylabel': 'y',
                'title': formula
            }
            if x_range:
                plot_kwargs['xlim'] = x_range
            if y_range:
                plot_kwargs['ylim'] = y_range
    
            p = sympy.plot(expr, (x, x_range[0], x_range[1]), **plot_kwargs)
    
            # Save the plot to a file
            desktop_path = os.path.join(os.path.expanduser('~'), 'Desktop')
            save_dir = os.path.join(desktop_path, 'Desmos-MCP')
            os.makedirs(save_dir, exist_ok=True)
            timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
            filename = f"plot_{timestamp}.png"
            p.save(os.path.join(save_dir, filename))
    
            await ctx.progress.report(3, 3, "Encoding image...")
            buf = io.BytesIO()
            p.save(buf)
            buf.seek(0)
            img_base64 = base64.b64encode(buf.read()).decode('utf-8')
            data_uri = f"data:image/png;base64,{img_base64}"
            
            await ctx.progress.end()
            return f"Successfully plotted '{formula}' using local rendering. Image: {data_uri}"
    
        except Exception as e:
            await ctx.progress.end()
            return f"Error plotting formula '{formula}' locally. Details: {e}"
  • Supporting method in DesmosAPIClient that performs the actual API call to plot the formula, used by the main handler when use_api is True.
    async def plot_formula(self, formula: str, x_range: List[float], y_range: List[float]) -> Optional[bytes]:
        """Requests a plot from the Desmos API and returns the image bytes."""
        headers = {
            "Authorization": f"Bearer {self.api_key}"
        }
        # 注意:此处的 payload 结构是基于通用 API 设计的推断,可能需要根据实际的 Desmos API 文档进行调整
        payload = {
            "formula": formula,
            "x_range": x_range,
            "y_range": y_range,
            "format": "png"
        }
        
        async with httpx.AsyncClient() as client:
            try:
                response = await client.post(f"{API_BASE_URL}/plot", headers=headers, json=payload, timeout=15.0)
                response.raise_for_status() # 如果状态码是 4xx 或 5xx,则引发异常
                return response.content
            except httpx.HTTPStatusError as e:
                print(f"Desmos API returned an error: {e.response.status_code} {e.response.text}")
                return None
            except httpx.RequestError as e:
                print(f"Error connecting to Desmos API: {e}")
                return None

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/TheGrSun/Desmos-MCP'

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