Analytics & Reporting Tools
Data-driven decisions require data. When your AI agent can query sales figures, analyze trends, and generate reports, it becomes a powerful business intelligence assistant.
From Reactive to Proactive
With analytics tools, your AI doesn't just answer questions - it can proactively alert you to anomalies, suggest optimizations, and surface insights you might have missed.
Analytics Tool Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AI AGENT CONVERSATION โ
โ "How are sales performing this month compared to last?" โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ANALYTICS MCP TOOLS โ
โโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโค
โ get_sales_summaryโ get_trends โ top_products โ revenue_by_ โ
โ get_conversion โ compare_periodsโ customer_ltvโ category โ
โโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ DATA WAREHOUSE โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ Orders โ โ Products โ โ Customers โ โ
โ โ Aggregates โ โ Analytics โ โ Cohorts โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Core Analytics Tools
1. Sales Summary Tool
Get key sales metrics for any time period:
from mcp.server import Server
from mcp import types
from datetime import datetime, timedelta
import json
app = Server("analytics-tools")
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="get_sales_summary",
description="""Retrieves sales summary metrics for a specified time period.
Use when: User asks about sales performance, revenue, or order volume.
Returns: Total revenue, order count, average order value, and period comparison.
Note: All monetary values are in USD.""",
inputSchema={
"type": "object",
"properties": {
"period": {
"type": "string",
"enum": ["today", "yesterday", "this_week", "last_week",
"this_month", "last_month", "this_quarter",
"last_quarter", "this_year", "custom"],
"default": "this_month",
"description": "Predefined time period or 'custom'"
},
"start_date": {
"type": "string",
"format": "date",
"description": "Start date (required if period is 'custom')"
},
"end_date": {
"type": "string",
"format": "date",
"description": "End date (required if period is 'custom')"
},
"compare_to_previous": {
"type": "boolean",
"default": True,
"description": "Include comparison to previous period"
},
"breakdown_by": {
"type": "string",
"enum": ["day", "week", "month", "none"],
"default": "none",
"description": "Time granularity for breakdown"
},
"filters": {
"type": "object",
"properties": {
"category": {"type": "string"},
"product_id": {"type": "string"},
"channel": {"type": "string", "enum": ["web", "mobile", "in_store", "marketplace"]},
"region": {"type": "string"}
}
}
}
}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
if name == "get_sales_summary":
# Calculate date range
period = arguments.get("period", "this_month")
start_date, end_date = get_date_range(period, arguments)
# Get current period metrics
current = await analytics_db.get_sales_metrics(
start_date=start_date,
end_date=end_date,
filters=arguments.get("filters", {})
)
result = {
"period": period,
"start_date": start_date.isoformat(),
"end_date": end_date.isoformat(),
"metrics": {
"total_revenue": current["revenue"],
"order_count": current["orders"],
"average_order_value": round(current["revenue"] / max(current["orders"], 1), 2),
"units_sold": current["units"],
"unique_customers": current["customers"],
"new_customers": current["new_customers"],
"returning_customers": current["customers"] - current["new_customers"]
}
}
# Add period comparison
if arguments.get("compare_to_previous", True):
period_length = (end_date - start_date).days + 1
prev_start = start_date - timedelta(days=period_length)
prev_end = start_date - timedelta(days=1)
previous = await analytics_db.get_sales_metrics(
start_date=prev_start,
end_date=prev_end,
filters=arguments.get("filters", {})
)
def calc_change(current_val, prev_val):
if prev_val == 0:
return None
return round((current_val - prev_val) / prev_val * 100, 1)
result["comparison"] = {
"previous_period": {
"start": prev_start.isoformat(),
"end": prev_end.isoformat()
},
"revenue_change_pct": calc_change(current["revenue"], previous["revenue"]),
"orders_change_pct": calc_change(current["orders"], previous["orders"]),
"aov_change_pct": calc_change(
current["revenue"] / max(current["orders"], 1),
previous["revenue"] / max(previous["orders"], 1)
)
}
# Add time breakdown if requested
if arguments.get("breakdown_by", "none") != "none":
breakdown = await analytics_db.get_sales_breakdown(
start_date=start_date,
end_date=end_date,
granularity=arguments["breakdown_by"],
filters=arguments.get("filters", {})
)
result["breakdown"] = breakdown
return [types.TextContent(type="text", text=json.dumps(result))]
2. Top Products Tool
Identify best-selling products:
types.Tool(
name="get_top_products",
description="""Returns top-selling products for a given time period.
Use when: User asks about best sellers, popular items, or product performance.
Returns: Ranked list of products with sales metrics.""",
inputSchema={
"type": "object",
"properties": {
"period": {
"type": "string",
"enum": ["today", "this_week", "this_month", "this_quarter", "this_year", "all_time"],
"default": "this_month"
},
"metric": {
"type": "string",
"enum": ["revenue", "units_sold", "orders"],
"default": "revenue",
"description": "Metric to rank by"
},
"category": {
"type": "string",
"description": "Filter to specific product category"
},
"limit": {
"type": "integer",
"default": 10,
"minimum": 1,
"maximum": 100
},
"include_comparison": {
"type": "boolean",
"default": True,
"description": "Include change vs previous period"
}
}
}
)
Implementation:
elif name == "get_top_products":
period = arguments.get("period", "this_month")
metric = arguments.get("metric", "revenue")
limit = arguments.get("limit", 10)
start_date, end_date = get_date_range(period, arguments)
products = await analytics_db.get_top_products(
start_date=start_date,
end_date=end_date,
order_by=metric,
category=arguments.get("category"),
limit=limit
)
result = []
for rank, product in enumerate(products, 1):
item = {
"rank": rank,
"product_id": product["id"],
"name": product["name"],
"category": product["category"],
"revenue": product["revenue"],
"units_sold": product["units"],
"orders": product["orders"],
"average_price": round(product["revenue"] / max(product["units"], 1), 2)
}
if arguments.get("include_comparison", True):
item["revenue_change_pct"] = product.get("revenue_change")
item["units_change_pct"] = product.get("units_change")
result.append(item)
return [types.TextContent(
type="text",
text=json.dumps({
"period": period,
"metric": metric,
"top_products": result
})
)]
3. Conversion Funnel Tool
Analyze checkout conversion:
types.Tool(
name="get_conversion_funnel",
description="""Analyzes the conversion funnel from visits to purchases.
Use when: User asks about conversion rates, cart abandonment, or checkout optimization.
Returns: Funnel stages with counts and drop-off rates.""",
inputSchema={
"type": "object",
"properties": {
"period": {
"type": "string",
"enum": ["today", "this_week", "this_month", "this_quarter"],
"default": "this_month"
},
"channel": {
"type": "string",
"enum": ["all", "web", "mobile", "app"],
"default": "all"
},
"segment": {
"type": "string",
"enum": ["all", "new_visitors", "returning_visitors"],
"default": "all"
}
}
}
)
Implementation:
elif name == "get_conversion_funnel":
period = arguments.get("period", "this_month")
channel = arguments.get("channel", "all")
segment = arguments.get("segment", "all")
start_date, end_date = get_date_range(period, arguments)
funnel = await analytics_db.get_funnel_metrics(
start_date=start_date,
end_date=end_date,
channel=channel,
segment=segment
)
stages = [
{"name": "Site Visits", "count": funnel["visits"], "rate": 100},
{"name": "Product Views", "count": funnel["product_views"],
"rate": round(funnel["product_views"] / max(funnel["visits"], 1) * 100, 1)},
{"name": "Add to Cart", "count": funnel["add_to_cart"],
"rate": round(funnel["add_to_cart"] / max(funnel["visits"], 1) * 100, 1)},
{"name": "Begin Checkout", "count": funnel["checkout_started"],
"rate": round(funnel["checkout_started"] / max(funnel["visits"], 1) * 100, 1)},
{"name": "Purchase Complete", "count": funnel["purchases"],
"rate": round(funnel["purchases"] / max(funnel["visits"], 1) * 100, 1)}
]
# Calculate drop-off between stages
for i in range(1, len(stages)):
prev_count = stages[i-1]["count"]
curr_count = stages[i]["count"]
stages[i]["dropoff_pct"] = round(
(prev_count - curr_count) / max(prev_count, 1) * 100, 1
)
return [types.TextContent(
type="text",
text=json.dumps({
"period": period,
"channel": channel,
"segment": segment,
"overall_conversion_rate": stages[-1]["rate"],
"cart_abandonment_rate": round(
(funnel["add_to_cart"] - funnel["purchases"]) /
max(funnel["add_to_cart"], 1) * 100, 1
),
"funnel_stages": stages
})
)]
4. Revenue by Category Tool
Breakdown revenue by product categories:
types.Tool(
name="get_revenue_by_category",
description="""Breaks down revenue by product categories.
Use when: User asks about category performance or wants to understand revenue mix.
Returns: Category breakdown with revenue, percentages, and trends.""",
inputSchema={
"type": "object",
"properties": {
"period": {
"type": "string",
"enum": ["this_week", "this_month", "this_quarter", "this_year"],
"default": "this_month"
},
"include_subcategories": {
"type": "boolean",
"default": False,
"description": "Include subcategory breakdown"
},
"min_revenue": {
"type": "number",
"description": "Minimum revenue threshold to include"
}
}
}
)
5. Customer Analytics Tool
Understand customer behavior and lifetime value:
types.Tool(
name="get_customer_analytics",
description="""Provides customer-level analytics including LTV, cohort analysis, and retention.
Use when: User asks about customer value, retention, or acquisition metrics.
Returns: Customer metrics, cohort data, and retention rates.""",
inputSchema={
"type": "object",
"properties": {
"metric_type": {
"type": "string",
"enum": ["overview", "ltv_distribution", "cohort_retention", "acquisition"],
"default": "overview"
},
"period": {
"type": "string",
"enum": ["this_month", "this_quarter", "this_year"],
"default": "this_month"
},
"cohort_period": {
"type": "string",
"enum": ["weekly", "monthly", "quarterly"],
"default": "monthly",
"description": "Granularity for cohort analysis"
}
}
}
)
TypeScript Implementation
import { Server } from "@modelcontextprotocol/sdk/server";
const server = new Server({ name: "analytics-tools", version: "1.0.0" });
interface SalesMetrics {
revenue: number;
orders: number;
units: number;
customers: number;
new_customers: number;
}
interface TopProduct {
id: string;
name: string;
category: string;
revenue: number;
units: number;
orders: number;
}
const analyticsTools = [
{
name: "get_sales_summary",
description: "Retrieves sales summary metrics for a specified time period",
inputSchema: {
type: "object" as const,
properties: {
period: {
type: "string",
enum: ["today", "yesterday", "this_week", "last_week", "this_month", "last_month"],
default: "this_month"
},
compare_to_previous: { type: "boolean", default: true },
breakdown_by: {
type: "string",
enum: ["day", "week", "month", "none"],
default: "none"
}
}
}
},
{
name: "get_top_products",
description: "Returns top-selling products ranked by revenue or units",
inputSchema: {
type: "object" as const,
properties: {
period: {
type: "string",
enum: ["this_week", "this_month", "this_quarter", "this_year"],
default: "this_month"
},
metric: { type: "string", enum: ["revenue", "units_sold", "orders"], default: "revenue" },
limit: { type: "integer", default: 10, minimum: 1, maximum: 100 },
category: { type: "string" }
}
}
},
{
name: "get_conversion_funnel",
description: "Analyzes the conversion funnel from visits to purchases",
inputSchema: {
type: "object" as const,
properties: {
period: { type: "string", enum: ["this_week", "this_month"], default: "this_month" },
channel: { type: "string", enum: ["all", "web", "mobile", "app"], default: "all" }
}
}
},
{
name: "get_revenue_by_category",
description: "Breaks down revenue by product categories",
inputSchema: {
type: "object" as const,
properties: {
period: { type: "string", default: "this_month" },
include_subcategories: { type: "boolean", default: false }
}
}
}
];
server.setRequestHandler("tools/list", async () => ({ tools: analyticsTools }));
server.setRequestHandler("tools/call", async (request) => {
const { name, arguments: args } = request.params;
switch (name) {
case "get_sales_summary": {
const { startDate, endDate } = getDateRange(args.period || "this_month");
const current = await analyticsDB.getSalesMetrics(startDate, endDate);
const result: any = {
period: args.period || "this_month",
start_date: startDate.toISOString().split("T")[0],
end_date: endDate.toISOString().split("T")[0],
metrics: {
total_revenue: current.revenue,
order_count: current.orders,
average_order_value: Math.round((current.revenue / Math.max(current.orders, 1)) * 100) / 100,
units_sold: current.units,
unique_customers: current.customers,
new_customers: current.new_customers
}
};
if (args.compare_to_previous !== false) {
const periodDays = Math.ceil((endDate.getTime() - startDate.getTime()) / (1000 * 60 * 60 * 24));
const prevStart = new Date(startDate.getTime() - periodDays * 24 * 60 * 60 * 1000);
const prevEnd = new Date(startDate.getTime() - 24 * 60 * 60 * 1000);
const previous = await analyticsDB.getSalesMetrics(prevStart, prevEnd);
const calcChange = (curr: number, prev: number) =>
prev === 0 ? null : Math.round(((curr - prev) / prev) * 1000) / 10;
result.comparison = {
revenue_change_pct: calcChange(current.revenue, previous.revenue),
orders_change_pct: calcChange(current.orders, previous.orders)
};
}
return { content: [{ type: "text", text: JSON.stringify(result) }] };
}
case "get_top_products": {
const { startDate, endDate } = getDateRange(args.period || "this_month");
const products = await analyticsDB.getTopProducts({
startDate,
endDate,
orderBy: args.metric || "revenue",
category: args.category,
limit: args.limit || 10
});
const topProducts = products.map((p: TopProduct, i: number) => ({
rank: i + 1,
product_id: p.id,
name: p.name,
category: p.category,
revenue: p.revenue,
units_sold: p.units,
orders: p.orders,
average_price: Math.round((p.revenue / Math.max(p.units, 1)) * 100) / 100
}));
return {
content: [{
type: "text",
text: JSON.stringify({
period: args.period || "this_month",
metric: args.metric || "revenue",
top_products: topProducts
})
}]
};
}
case "get_conversion_funnel": {
const { startDate, endDate } = getDateRange(args.period || "this_month");
const funnel = await analyticsDB.getFunnelMetrics({
startDate,
endDate,
channel: args.channel || "all"
});
const stages = [
{ name: "Site Visits", count: funnel.visits, rate: 100 },
{ name: "Product Views", count: funnel.productViews,
rate: Math.round((funnel.productViews / Math.max(funnel.visits, 1)) * 1000) / 10 },
{ name: "Add to Cart", count: funnel.addToCart,
rate: Math.round((funnel.addToCart / Math.max(funnel.visits, 1)) * 1000) / 10 },
{ name: "Checkout Started", count: funnel.checkoutStarted,
rate: Math.round((funnel.checkoutStarted / Math.max(funnel.visits, 1)) * 1000) / 10 },
{ name: "Purchase", count: funnel.purchases,
rate: Math.round((funnel.purchases / Math.max(funnel.visits, 1)) * 1000) / 10 }
];
return {
content: [{
type: "text",
text: JSON.stringify({
period: args.period || "this_month",
overall_conversion_rate: stages[stages.length - 1].rate,
cart_abandonment_rate: Math.round(
((funnel.addToCart - funnel.purchases) / Math.max(funnel.addToCart, 1)) * 1000
) / 10,
funnel_stages: stages
})
}]
};
}
case "get_revenue_by_category": {
const { startDate, endDate } = getDateRange(args.period || "this_month");
const categories = await analyticsDB.getRevenueByCategory({
startDate,
endDate,
includeSubcategories: args.include_subcategories || false
});
const totalRevenue = categories.reduce((sum: number, c: any) => sum + c.revenue, 0);
const breakdown = categories.map((c: any) => ({
category: c.name,
revenue: c.revenue,
percentage: Math.round((c.revenue / Math.max(totalRevenue, 1)) * 1000) / 10,
orders: c.orders,
units: c.units,
subcategories: c.subcategories
}));
return {
content: [{
type: "text",
text: JSON.stringify({
period: args.period || "this_month",
total_revenue: totalRevenue,
categories: breakdown
})
}]
};
}
default:
throw new Error(`Unknown tool: ${name}`);
}
});
Real-Time Dashboard Queries
# For real-time dashboards, use streaming or polling
types.Tool(
name="get_live_metrics",
description="""Gets real-time metrics for dashboard display.
Use when: User wants current/live data or is monitoring performance.
Returns: Current metrics with minute-level freshness.""",
inputSchema={
"type": "object",
"properties": {
"metrics": {
"type": "array",
"items": {
"type": "string",
"enum": [
"orders_today",
"revenue_today",
"active_sessions",
"cart_value",
"conversion_rate_24h",
"top_products_1h"
]
},
"description": "Which metrics to retrieve"
}
},
"required": ["metrics"]
}
)
Real-World Conversation Flow
User: "How are we doing this month vs last month?"
AI Agent: [Calls get_sales_summary]
get_sales_summary(
period="this_month",
compare_to_previous=True,
breakdown_by="week"
)
Tool Response:
{
"period": "this_month",
"metrics": {
"total_revenue": 284500,
"order_count": 1842,
"average_order_value": 154.45,
"unique_customers": 1523
},
"comparison": {
"revenue_change_pct": 12.3,
"orders_change_pct": 8.7,
"aov_change_pct": 3.3
},
"breakdown": [
{"week": "Week 1", "revenue": 68200, "orders": 442},
{"week": "Week 2", "revenue": 72100, "orders": 467},
{"week": "Week 3", "revenue": 144200, "orders": 933}
]
}
AI Agent: "Great news! This month is performing well:
**Revenue:** $284,500 - up 12.3% vs last month
**Orders:** 1,842 - up 8.7%
**Average Order Value:** $154.45 - up 3.3%
Week 3 has been particularly strong with $144K in revenue -
nearly double the previous weeks. This could be due to the promotion
we ran. Would you like me to dig into what's driving the increase?"
User: "Yes, what are the top products?"
AI Agent: [Calls get_top_products]
get_top_products(period="this_month", metric="revenue", limit=5)
AI Agent: "Here are your top 5 products this month:
1. **Wireless Pro Headphones** - $42,300 (up 45% from last month)
2. **Smart Watch Series X** - $38,750 (up 22%)
3. **Bluetooth Speaker** - $28,400 (up 18%)
4. **Noise-Cancelling Earbuds** - $24,200 (up 31%)
5. **Portable Charger Pack** - $19,800 (up 8%)
The headphones and earbuds are really driving growth. Should I
pull the conversion funnel to see how well these are converting?"
Key Takeaways
- Flexible date ranges enable period comparisons and trend analysis
- Pre-aggregate data for fast queries on large datasets
- Include comparisons to provide context for metrics
- Support filtering by category, channel, and other dimensions
- AI can surface insights like anomalies and recommendations
Next up: Building MCP Servers - Learn to package your tools into production-ready MCP servers with authentication and deployment.