agent-analytics-mcp-server 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_analytics_mcp_server-0.1.0/.gitignore +10 -0
- agent_analytics_mcp_server-0.1.0/PKG-INFO +61 -0
- agent_analytics_mcp_server-0.1.0/README.md +43 -0
- agent_analytics_mcp_server-0.1.0/pyproject.toml +30 -0
- agent_analytics_mcp_server-0.1.0/src/__init__.py +0 -0
- agent_analytics_mcp_server-0.1.0/src/db.py +181 -0
- agent_analytics_mcp_server-0.1.0/src/server.py +24 -0
- agent_analytics_mcp_server-0.1.0/src/tools/__init__.py +0 -0
- agent_analytics_mcp_server-0.1.0/src/tools/analytics.py +77 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agent-analytics-mcp-server
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Usage analytics and monitoring for AI agent tool calls — track, analyze and optimize agent behavior
|
|
5
|
+
Project-URL: Homepage, https://github.com/AiAgentKarl/agent-analytics-mcp-server
|
|
6
|
+
Project-URL: Repository, https://github.com/AiAgentKarl/agent-analytics-mcp-server
|
|
7
|
+
Author: AiAgentKarl
|
|
8
|
+
License: MIT
|
|
9
|
+
Keywords: ai-agents,analytics,mcp,monitoring,usage-tracking
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Requires-Dist: mcp>=1.0.0
|
|
16
|
+
Requires-Dist: pydantic>=2.0.0
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
|
|
19
|
+
# Agent Analytics MCP Server 📊
|
|
20
|
+
|
|
21
|
+
Usage analytics and monitoring for AI agent tool calls. Track, analyze, and optimize how agents use your tools.
|
|
22
|
+
|
|
23
|
+
## Features
|
|
24
|
+
|
|
25
|
+
- **Event Tracking** — Log every tool call with duration, success/failure, metadata
|
|
26
|
+
- **Dashboard** — Overview with total calls, error rates, top tools, daily trends
|
|
27
|
+
- **Per-Tool Analytics** — Deep dive into individual tool performance
|
|
28
|
+
- **Per-Agent Analytics** — See how specific agents use your services
|
|
29
|
+
- **Error Tracking** — Monitor and debug failures
|
|
30
|
+
|
|
31
|
+
## Installation
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install agent-analytics-mcp-server
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Usage with Claude Code
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"mcpServers": {
|
|
42
|
+
"analytics": {
|
|
43
|
+
"command": "uvx",
|
|
44
|
+
"args": ["agent-analytics-mcp-server"]
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Tools
|
|
51
|
+
|
|
52
|
+
| Tool | Description |
|
|
53
|
+
|------|-------------|
|
|
54
|
+
| `track_event` | Log a usage event |
|
|
55
|
+
| `get_dashboard` | Overview dashboard |
|
|
56
|
+
| `tool_analytics` | Per-tool deep dive |
|
|
57
|
+
| `agent_analytics` | Per-agent usage |
|
|
58
|
+
|
|
59
|
+
## License
|
|
60
|
+
|
|
61
|
+
MIT
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Agent Analytics MCP Server 📊
|
|
2
|
+
|
|
3
|
+
Usage analytics and monitoring for AI agent tool calls. Track, analyze, and optimize how agents use your tools.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Event Tracking** — Log every tool call with duration, success/failure, metadata
|
|
8
|
+
- **Dashboard** — Overview with total calls, error rates, top tools, daily trends
|
|
9
|
+
- **Per-Tool Analytics** — Deep dive into individual tool performance
|
|
10
|
+
- **Per-Agent Analytics** — See how specific agents use your services
|
|
11
|
+
- **Error Tracking** — Monitor and debug failures
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install agent-analytics-mcp-server
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage with Claude Code
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"analytics": {
|
|
25
|
+
"command": "uvx",
|
|
26
|
+
"args": ["agent-analytics-mcp-server"]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Tools
|
|
33
|
+
|
|
34
|
+
| Tool | Description |
|
|
35
|
+
|------|-------------|
|
|
36
|
+
| `track_event` | Log a usage event |
|
|
37
|
+
| `get_dashboard` | Overview dashboard |
|
|
38
|
+
| `tool_analytics` | Per-tool deep dive |
|
|
39
|
+
| `agent_analytics` | Per-agent usage |
|
|
40
|
+
|
|
41
|
+
## License
|
|
42
|
+
|
|
43
|
+
MIT
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "agent-analytics-mcp-server"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Usage analytics and monitoring for AI agent tool calls — track, analyze and optimize agent behavior"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{name = "AiAgentKarl"}]
|
|
13
|
+
keywords = ["mcp", "analytics", "monitoring", "ai-agents", "usage-tracking"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
]
|
|
20
|
+
dependencies = [
|
|
21
|
+
"mcp>=1.0.0",
|
|
22
|
+
"pydantic>=2.0.0",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Homepage = "https://github.com/AiAgentKarl/agent-analytics-mcp-server"
|
|
27
|
+
Repository = "https://github.com/AiAgentKarl/agent-analytics-mcp-server"
|
|
28
|
+
|
|
29
|
+
[tool.hatch.build.targets.wheel]
|
|
30
|
+
packages = ["src"]
|
|
File without changes
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""Datenbank — SQLite-basiertes Analytics-Tracking."""
|
|
2
|
+
|
|
3
|
+
import sqlite3
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
from datetime import datetime, timezone, timedelta
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
_DB_PATH = os.getenv("ANALYTICS_DB_PATH", str(Path(__file__).resolve().parent.parent / "analytics.db"))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _connect() -> sqlite3.Connection:
|
|
14
|
+
conn = sqlite3.connect(_DB_PATH)
|
|
15
|
+
conn.row_factory = sqlite3.Row
|
|
16
|
+
conn.execute("PRAGMA journal_mode=WAL")
|
|
17
|
+
conn.execute("""
|
|
18
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
19
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
20
|
+
event_type TEXT NOT NULL,
|
|
21
|
+
tool_name TEXT,
|
|
22
|
+
service_id TEXT DEFAULT 'default',
|
|
23
|
+
agent_id TEXT,
|
|
24
|
+
duration_ms INTEGER,
|
|
25
|
+
success INTEGER DEFAULT 1,
|
|
26
|
+
error_message TEXT,
|
|
27
|
+
metadata TEXT,
|
|
28
|
+
created_at TEXT NOT NULL
|
|
29
|
+
)
|
|
30
|
+
""")
|
|
31
|
+
conn.execute("CREATE INDEX IF NOT EXISTS idx_event_type ON events(event_type)")
|
|
32
|
+
conn.execute("CREATE INDEX IF NOT EXISTS idx_tool ON events(tool_name)")
|
|
33
|
+
conn.execute("CREATE INDEX IF NOT EXISTS idx_created ON events(created_at)")
|
|
34
|
+
conn.commit()
|
|
35
|
+
return conn
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def track_event(
|
|
39
|
+
event_type: str,
|
|
40
|
+
tool_name: str = None,
|
|
41
|
+
service_id: str = "default",
|
|
42
|
+
agent_id: str = None,
|
|
43
|
+
duration_ms: int = None,
|
|
44
|
+
success: bool = True,
|
|
45
|
+
error_message: str = None,
|
|
46
|
+
metadata: dict = None,
|
|
47
|
+
) -> dict:
|
|
48
|
+
"""Event tracken."""
|
|
49
|
+
conn = _connect()
|
|
50
|
+
now = datetime.now(timezone.utc).isoformat()
|
|
51
|
+
conn.execute(
|
|
52
|
+
"""INSERT INTO events
|
|
53
|
+
(event_type, tool_name, service_id, agent_id,
|
|
54
|
+
duration_ms, success, error_message, metadata, created_at)
|
|
55
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
|
56
|
+
(event_type, tool_name, service_id, agent_id,
|
|
57
|
+
duration_ms, 1 if success else 0, error_message,
|
|
58
|
+
json.dumps(metadata) if metadata else None, now),
|
|
59
|
+
)
|
|
60
|
+
conn.commit()
|
|
61
|
+
conn.close()
|
|
62
|
+
return {"tracked": True, "event_type": event_type, "created_at": now}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def get_dashboard(service_id: str = None, days: int = 30) -> dict:
|
|
66
|
+
"""Dashboard-Daten abrufen."""
|
|
67
|
+
conn = _connect()
|
|
68
|
+
cutoff = (datetime.now(timezone.utc) - timedelta(days=days)).isoformat()
|
|
69
|
+
|
|
70
|
+
sql_where = "WHERE created_at >= ?"
|
|
71
|
+
params = [cutoff]
|
|
72
|
+
if service_id:
|
|
73
|
+
sql_where += " AND service_id=?"
|
|
74
|
+
params.append(service_id)
|
|
75
|
+
|
|
76
|
+
# Gesamtstatistiken
|
|
77
|
+
total = conn.execute(f"SELECT COUNT(*) as c FROM events {sql_where}", params).fetchone()["c"]
|
|
78
|
+
successful = conn.execute(
|
|
79
|
+
f"SELECT COUNT(*) as c FROM events {sql_where} AND success=1", params
|
|
80
|
+
).fetchone()["c"]
|
|
81
|
+
failed = total - successful
|
|
82
|
+
|
|
83
|
+
# Top Tools
|
|
84
|
+
top_tools = conn.execute(
|
|
85
|
+
f"""SELECT tool_name, COUNT(*) as calls, AVG(duration_ms) as avg_duration
|
|
86
|
+
FROM events {sql_where} AND tool_name IS NOT NULL
|
|
87
|
+
GROUP BY tool_name ORDER BY calls DESC LIMIT 10""",
|
|
88
|
+
params,
|
|
89
|
+
).fetchall()
|
|
90
|
+
|
|
91
|
+
# Tägliche Nutzung
|
|
92
|
+
daily = conn.execute(
|
|
93
|
+
f"""SELECT DATE(created_at) as date, COUNT(*) as calls
|
|
94
|
+
FROM events {sql_where}
|
|
95
|
+
GROUP BY DATE(created_at) ORDER BY date DESC LIMIT {days}""",
|
|
96
|
+
params,
|
|
97
|
+
).fetchall()
|
|
98
|
+
|
|
99
|
+
# Error-Rate
|
|
100
|
+
error_rate = (failed / total * 100) if total > 0 else 0
|
|
101
|
+
|
|
102
|
+
conn.close()
|
|
103
|
+
return {
|
|
104
|
+
"period_days": days,
|
|
105
|
+
"total_events": total,
|
|
106
|
+
"successful": successful,
|
|
107
|
+
"failed": failed,
|
|
108
|
+
"error_rate_pct": round(error_rate, 1),
|
|
109
|
+
"top_tools": [dict(r) for r in top_tools],
|
|
110
|
+
"daily_usage": [dict(r) for r in daily],
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def get_tool_analytics(tool_name: str, days: int = 30) -> dict:
|
|
115
|
+
"""Analytics für ein spezifisches Tool."""
|
|
116
|
+
conn = _connect()
|
|
117
|
+
cutoff = (datetime.now(timezone.utc) - timedelta(days=days)).isoformat()
|
|
118
|
+
|
|
119
|
+
rows = conn.execute(
|
|
120
|
+
"""SELECT COUNT(*) as calls,
|
|
121
|
+
SUM(CASE WHEN success=1 THEN 1 ELSE 0 END) as successes,
|
|
122
|
+
AVG(duration_ms) as avg_duration_ms,
|
|
123
|
+
MIN(duration_ms) as min_duration_ms,
|
|
124
|
+
MAX(duration_ms) as max_duration_ms
|
|
125
|
+
FROM events WHERE tool_name=? AND created_at >= ?""",
|
|
126
|
+
(tool_name, cutoff),
|
|
127
|
+
).fetchone()
|
|
128
|
+
|
|
129
|
+
# Letzte Fehler
|
|
130
|
+
errors = conn.execute(
|
|
131
|
+
"""SELECT error_message, created_at FROM events
|
|
132
|
+
WHERE tool_name=? AND success=0 AND created_at >= ?
|
|
133
|
+
ORDER BY created_at DESC LIMIT 5""",
|
|
134
|
+
(tool_name, cutoff),
|
|
135
|
+
).fetchall()
|
|
136
|
+
|
|
137
|
+
# Täglicher Trend
|
|
138
|
+
daily = conn.execute(
|
|
139
|
+
"""SELECT DATE(created_at) as date, COUNT(*) as calls
|
|
140
|
+
FROM events WHERE tool_name=? AND created_at >= ?
|
|
141
|
+
GROUP BY DATE(created_at) ORDER BY date""",
|
|
142
|
+
(tool_name, cutoff),
|
|
143
|
+
).fetchall()
|
|
144
|
+
|
|
145
|
+
conn.close()
|
|
146
|
+
return {
|
|
147
|
+
"tool_name": tool_name,
|
|
148
|
+
"period_days": days,
|
|
149
|
+
"total_calls": rows["calls"],
|
|
150
|
+
"success_rate_pct": round(rows["successes"] / rows["calls"] * 100, 1) if rows["calls"] > 0 else 0,
|
|
151
|
+
"avg_duration_ms": round(rows["avg_duration_ms"] or 0),
|
|
152
|
+
"min_duration_ms": rows["min_duration_ms"],
|
|
153
|
+
"max_duration_ms": rows["max_duration_ms"],
|
|
154
|
+
"recent_errors": [dict(r) for r in errors],
|
|
155
|
+
"daily_trend": [dict(r) for r in daily],
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def get_agent_analytics(agent_id: str, days: int = 30) -> dict:
|
|
160
|
+
"""Analytics für einen spezifischen Agent."""
|
|
161
|
+
conn = _connect()
|
|
162
|
+
cutoff = (datetime.now(timezone.utc) - timedelta(days=days)).isoformat()
|
|
163
|
+
|
|
164
|
+
tools_used = conn.execute(
|
|
165
|
+
"""SELECT tool_name, COUNT(*) as calls
|
|
166
|
+
FROM events WHERE agent_id=? AND created_at >= ? AND tool_name IS NOT NULL
|
|
167
|
+
GROUP BY tool_name ORDER BY calls DESC""",
|
|
168
|
+
(agent_id, cutoff),
|
|
169
|
+
).fetchall()
|
|
170
|
+
|
|
171
|
+
total = conn.execute(
|
|
172
|
+
"SELECT COUNT(*) as c FROM events WHERE agent_id=? AND created_at >= ?",
|
|
173
|
+
(agent_id, cutoff),
|
|
174
|
+
).fetchone()["c"]
|
|
175
|
+
|
|
176
|
+
conn.close()
|
|
177
|
+
return {
|
|
178
|
+
"agent_id": agent_id,
|
|
179
|
+
"total_events": total,
|
|
180
|
+
"tools_used": [dict(r) for r in tools_used],
|
|
181
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Agent Analytics MCP Server — Usage-Tracking für AI-Agent-Tools."""
|
|
2
|
+
|
|
3
|
+
from mcp.server.fastmcp import FastMCP
|
|
4
|
+
|
|
5
|
+
from src.tools.analytics import register_analytics_tools
|
|
6
|
+
|
|
7
|
+
mcp = FastMCP(
|
|
8
|
+
"Agent Analytics",
|
|
9
|
+
instructions=(
|
|
10
|
+
"Track and analyze AI agent tool usage. Monitor call frequency, "
|
|
11
|
+
"success rates, response times, and errors. "
|
|
12
|
+
"Get dashboards and per-tool analytics."
|
|
13
|
+
),
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
register_analytics_tools(mcp)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def main():
|
|
20
|
+
mcp.run(transport="stdio")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
if __name__ == "__main__":
|
|
24
|
+
main()
|
|
File without changes
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Analytics-Tools — Usage-Tracking und Monitoring für AI-Agents."""
|
|
2
|
+
|
|
3
|
+
from mcp.server.fastmcp import FastMCP
|
|
4
|
+
|
|
5
|
+
from src import db
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def register_analytics_tools(mcp: FastMCP):
|
|
9
|
+
"""Analytics-bezogene MCP-Tools registrieren."""
|
|
10
|
+
|
|
11
|
+
@mcp.tool()
|
|
12
|
+
async def track_event(
|
|
13
|
+
event_type: str,
|
|
14
|
+
tool_name: str = None,
|
|
15
|
+
service_id: str = "default",
|
|
16
|
+
agent_id: str = None,
|
|
17
|
+
duration_ms: int = None,
|
|
18
|
+
success: bool = True,
|
|
19
|
+
error_message: str = None,
|
|
20
|
+
metadata: dict = None,
|
|
21
|
+
) -> dict:
|
|
22
|
+
"""Ein Usage-Event tracken.
|
|
23
|
+
|
|
24
|
+
Zeichnet einen Tool-Aufruf oder ein anderes Event auf
|
|
25
|
+
für spätere Analyse.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
event_type: Art des Events (z.B. "tool_call", "error", "login")
|
|
29
|
+
tool_name: Name des aufgerufenen Tools
|
|
30
|
+
service_id: ID des Services (Standard: "default")
|
|
31
|
+
agent_id: ID des aufrufenden Agents
|
|
32
|
+
duration_ms: Dauer in Millisekunden
|
|
33
|
+
success: War der Aufruf erfolgreich?
|
|
34
|
+
error_message: Fehlermeldung falls nicht erfolgreich
|
|
35
|
+
metadata: Zusätzliche Daten als JSON
|
|
36
|
+
"""
|
|
37
|
+
return db.track_event(
|
|
38
|
+
event_type, tool_name, service_id,
|
|
39
|
+
agent_id, duration_ms, success, error_message, metadata,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
@mcp.tool()
|
|
43
|
+
async def get_dashboard(service_id: str = None, days: int = 30) -> dict:
|
|
44
|
+
"""Analytics-Dashboard abrufen.
|
|
45
|
+
|
|
46
|
+
Zeigt: Gesamtaufrufe, Erfolgsrate, Top-Tools, tägliche Nutzung.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
service_id: Optional — nur für diesen Service
|
|
50
|
+
days: Zeitraum in Tagen (Standard: 30)
|
|
51
|
+
"""
|
|
52
|
+
return db.get_dashboard(service_id, days)
|
|
53
|
+
|
|
54
|
+
@mcp.tool()
|
|
55
|
+
async def tool_analytics(tool_name: str, days: int = 30) -> dict:
|
|
56
|
+
"""Detaillierte Analytics für ein spezifisches Tool.
|
|
57
|
+
|
|
58
|
+
Zeigt: Aufrufe, Erfolgsrate, Durchschnittsdauer,
|
|
59
|
+
letzte Fehler und täglichen Trend.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
tool_name: Name des Tools
|
|
63
|
+
days: Zeitraum in Tagen (Standard: 30)
|
|
64
|
+
"""
|
|
65
|
+
return db.get_tool_analytics(tool_name, days)
|
|
66
|
+
|
|
67
|
+
@mcp.tool()
|
|
68
|
+
async def agent_analytics(agent_id: str, days: int = 30) -> dict:
|
|
69
|
+
"""Analytics für einen bestimmten Agent.
|
|
70
|
+
|
|
71
|
+
Zeigt welche Tools ein Agent wie oft nutzt.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
agent_id: ID des Agents
|
|
75
|
+
days: Zeitraum in Tagen (Standard: 30)
|
|
76
|
+
"""
|
|
77
|
+
return db.get_agent_analytics(agent_id, days)
|