fastmcp/examples/apps/chart_server.py
2026-02-13 20:41:53 -05:00

101 lines
2.7 KiB
Python

"""Chart MCP App — interactive data visualizations with Prefab.
Demonstrates `fastmcp[apps]` with Prefab chart components:
- `BarChart` and `LineChart` for categorical and trend data
- Multiple series, stacking, and curve styles
- Layout composition with `Column`, `Heading`, and `Muted`
Usage:
uv run python chart_server.py # HTTP (port 8000)
uv run python chart_server.py --stdio # stdio for MCP clients
"""
from __future__ import annotations
from prefab_ui.components import (
BarChart,
ChartSeries,
Column,
Heading,
LineChart,
Muted,
)
from prefab_ui.response import UIResponse
from fastmcp import FastMCP
mcp = FastMCP("Sales Dashboard")
MONTHLY_SALES = [
{"month": "Jan", "online": 4200, "retail": 2400},
{"month": "Feb", "online": 3800, "retail": 2100},
{"month": "Mar", "online": 5100, "retail": 2800},
{"month": "Apr", "online": 4600, "retail": 3200},
{"month": "May", "online": 5800, "retail": 3100},
{"month": "Jun", "online": 6200, "retail": 3500},
]
@mcp.tool(app=True)
def sales_overview(stacked: bool = False) -> UIResponse:
"""View monthly sales broken down by channel.
Args:
stacked: Stack bars to show total revenue per month.
"""
total = sum(row["online"] + row["retail"] for row in MONTHLY_SALES)
with Column(gap=6, css_class="p-6") as view:
with Column(gap=1):
Heading("Monthly Sales")
Muted(f"${total:,} total revenue")
BarChart(
data=MONTHLY_SALES,
series=[
ChartSeries(data_key="online", label="Online"),
ChartSeries(data_key="retail", label="Retail"),
],
x_axis="month",
stacked=stacked,
show_legend=True,
)
return UIResponse(
view=view,
text=f"Monthly sales: ${total:,} total revenue across 2 channels",
)
@mcp.tool(app=True)
def sales_trend(curve: str = "linear") -> UIResponse:
"""View sales trends over time as a line chart.
Args:
curve: Line style — "linear", "smooth", or "step".
"""
with Column(gap=6, css_class="p-6") as view:
with Column(gap=1):
Heading("Sales Trend")
Muted("Online vs. retail over 6 months")
LineChart(
data=MONTHLY_SALES,
series=[
ChartSeries(data_key="online", label="Online"),
ChartSeries(data_key="retail", label="Retail"),
],
x_axis="month",
curve=curve,
show_dots=True,
show_legend=True,
)
return UIResponse(
view=view,
text="Sales trend across online and retail channels",
)
if __name__ == "__main__":
mcp.run()