Surfa摄取SDK
](https://badge.fury.io/py/surfa-ingest)   ](https://pepy.tech/project/surfa-ingest)
MCP服务器和AI代理的分析 -跟踪使用情况、性能和任务完成情况,无论您的服务器是本地运行还是远程运行。
为什么吃Surfa?
适用于MCP服务器构建者
了解您的MCP服务器的使用情况——无论是本地安装在用户的计算机上还是远程托管:
📊 获得否则不会有的可见性
- 本地MCP服务器: 即使安装在用户的计算机上(Claude Desktop、Cursor等),也可以跟踪使用情况
- 远程MCP服务器: 获取基本服务器日志之外的结构化分析
🎯 了解你的用户
- 哪些工具最受欢迎
- 哪些AI客户端正在使用您的服务器(Claude、ChatGPT、Cursor)
- 实时使用模式和趋势
- 地理分布和平台细分
🚀 基于真实数据进行优化
- 性能指标(延迟、错误率)
- 任务完成跟踪(用户是否实际完成了目标?)
- 识别瓶颈和故障点
- A/B测试改进
💰 启用基于使用量的定价
- 跟踪API调用和工具使用情况
- 监控配额消耗
- 构建货币化模型
🔍 更快地调试问题
- 看看到底是什么失败了,在哪里失败了
- 端到端跟踪用户会话
- 识别重试模式和错误序列
隐私优先设计
- ✅ 默认情况下未收集PII
- ✅ 用户可以通过环境变量选择退出
- ✅ 您可以控制发送哪些数据
- ✅ GDPR和隐私合规
MCP建设者的快速入门
1.安装SDK
pip install surfa-ingest对于不同的MCP分配模式:
Local MCP (stdio) - npm/PyPI package
添加到您的 pyproject.toml:
[project]
dependencies = [
"surfa-ingest>=0.2.0",
"fastmcp>=2.0.0"
]或 requirements.txt:
surfa-ingest>=0.2.0
fastmcp>=2.0.0用户在本地安装MCP:
pip install your-mcp-serverRemote MCP (SSE) - Hosted service
添加到您的服务器 requirements.txt:
surfa-ingest>=0.2.0
fastmcp>=2.0.0部署到云端(Vercel、Railway、Fly.io等):
# Set environment variables
SURFA_INGEST_KEY=sk_live_your_key
SURFA_API_URL=https://surfa.dev用户通过URL连接(无需安装):
{
"mcp_servers": [{
"type": "url",
"url": "https://your-mcp.com/sse"
}]
}2.添加到您的MCP服务器
选择与您的分发模式匹配的示例:
Local MCP (stdio) - Claude Desktop, Cursor
from surfa_ingest import SurfaClient
from fastmcp import FastMCP
import os
# Initialize analytics
analytics = SurfaClient(
ingest_key=os.getenv("SURFA_INGEST_KEY", "sk_live_your_key"),
api_url=os.getenv("SURFA_API_URL", "https://surfa.dev")
)
# Set runtime for local stdio mode
analytics.set_runtime(
provider="mcp",
model="your-mcp-server-name",
mode="stdio" # Local mode
)
# Initialize MCP server
mcp = FastMCP("Your MCP Server")
@mcp.tool
def search_database(query: str) -> dict:
analytics.track({
"kind": "tool",
"subtype": "call_started",
"tool_name": "search_database"
})
result = perform_search(query)
analytics.track({
"kind": "tool",
"subtype": "call_completed",
"tool_name": "search_database",
"status": "success"
})
analytics.flush()
return result
# Run in stdio mode (for Claude Desktop)
if __name__ == "__main__":
mcp.run() # Defaults to stdio用户在Claude Desktop中配置:
{
"mcpServers": {
"your-mcp": {
"command": "npx",
"args": ["-y", "your-mcp-server"]
}
}
}Remote MCP (SSE) - Claude API, OpenAI API
from surfa_ingest import SurfaClient
from fastmcp import FastMCP
import os
# Initialize analytics
analytics = SurfaClient(
ingest_key=os.getenv("SURFA_INGEST_KEY", "sk_live_your_key"),
api_url=os.getenv("SURFA_API_URL", "https://surfa.dev")
)
# Set runtime for remote SSE mode
analytics.set_runtime(
provider="mcp",
model="your-mcp-server-name",
mode="sse" # Remote mode
)
# Initialize MCP server
mcp = FastMCP("Your MCP Server", stateless_http=True)
@mcp.tool
def search_database(query: str) -> dict:
analytics.track({
"kind": "tool",
"subtype": "call_started",
"tool_name": "search_database"
})
result = perform_search(query)
analytics.track({
"kind": "tool",
"subtype": "call_completed",
"tool_name": "search_database",
"status": "success"
})
analytics.flush()
return result
# Run in HTTP/SSE mode
if __name__ == "__main__":
mcp.run(
transport="http",
host="0.0.0.0",
port=8000,
path="/mcp"
)用户通过URL连接:
# Claude API
response = client.messages.create(
model="claude-opus-4",
mcp_servers=[{
"type": "url",
"url": "https://your-mcp.com/mcp"
}]
)
# OpenAI API
response = client.responses.create(
model="gpt-5",
tools=[{
"type": "mcp",
"server_url": "https://your-mcp.com/mcp"
}]
)使用MCP上下文自动检测(v0.2.0+)
新 自动提取 client_id, session_id,以及 request_id 从MCP的角度来看!
from surfa_ingest import SurfaClient
from fastmcp import FastMCP, Context
analytics = SurfaClient(ingest_key="sk_live_...")
mcp = FastMCP("My MCP Server")
@mcp.tool
def search_database(query: str, ctx: Context) -> dict:
# Just pass ctx - auto-extracts client_id, session_id, request_id!
analytics.track({
"kind": "tool",
"subtype": "call_started",
"tool_name": "search_database"
}, ctx=ctx) # ✨ Auto-extraction happens here
result = perform_search(query)
analytics.track({
"kind": "tool",
"subtype": "call_completed",
"tool_name": "search_database",
"status": "success"
}, ctx=ctx)
return result优点:
- ✅ 无需手动提取字段
- ✅ 适用于FastMCP和未来的MCP框架
- ✅ 向后兼容(ctx可选)
- ✅ 永不中断跟踪(优雅地失败)
自动提取的内容:
client_id-客户端标识符(如果MCP上下文中有)request_id-请求标识符(用于关联MCP请求)
3.获取您的分析
访问您的Surfa仪表板查看:
- 实时工具使用
- 性能指标
- 任务完成率
- 客户分布
- 错误追踪
所得
实时仪表板
- 📈 工具使用趋势
- ⚡ 性能指标(P50、P95、P99延迟)
- ✅ 任务完成率
- 🔴 错误率和类型
- 👥 活跃用户和会话
确定性代理度量
- 任务完成: 用户真的实现了他们的目标吗?
- 工具调用: 调用了多少工具?
- 检索: 具有相同参数的重复调用
- 恢复: 代理是否从错误中恢复?
- 延迟时间: P95和总延迟跟踪
客户端智能
- 哪些AI客户端正在使用您的MCP(Claude、ChatGPT、Cursor)
- 平台分发(macOS、Linux、Windows)
- 客户端版本和配置
主要特点
- 🚀 事件缓冲 -具有可配置缓冲区大小的自动批处理
- 🔄 自动重试 -具有指数回退的内置重试逻辑
- 📦 上下文管理器 -自动会话生命周期管理
- 🏷️ 运行时元数据 -跟踪AI提供商、模型和配置
- ✨ MCP上下文自动检测 (v0.2.0+)-自动从MCP上下文中提取client_id、session_id
- 📊 确定性代理度量 -跟踪传统分析平台无法提供的任务完成、重试、恢复和性能指标
- ✅ 事件验证 -发送前的客户端验证
- 🔍 相关ID -将相关事件链接在一起
- 🛡️ 类型安全 -完整类型提示和IDE自动补全
- 🔒 隐私第一 -默认情况下没有PII,用户选择退出支持
是什么让Surfa与众不同: 我们从您的事件流中自动计算任务完成、重试检测和恢复率等确定性指标,这些指标是通用分析平台无法提供的,因为它们不了解AI代理的行为。
了解更多
📚 文档
🔗 链接
- 📦 PyPI: https://pypi.org/project/surfa-ingest/
- 📝 更新日志: 更改日志.md
- 🐛 问题: https://github.com/gamladz/surfa/issues
- 💬 讨论: https://github.com/gamladz/surfa/discussions
快速参考
确定性度量(自动计算)
当您使用此SDK发送事件时,Surfa平台会自动计算每次执行的这些指标:
自动计算指标
| 度量 | 定义 | 如何计算 |
|---|---|---|
| 任务完成 | 任务是否实际完成 | 用途 task_completed 字段(如果存在),否则根据事件序列推断 |
| 工具调用 | 工具调用总数 | 计数 tool_call_started 事件 |
| 重试 | 从以下位置检测到使用相同工具+参数的重复调用 tool_name + payload.input 匹配 | |
| 恢复 | 代理从错误中恢复 | 任何失败后的首次成功 |
| 延迟 | P50、P95、P99延迟 | 根据以下公式计算 latency_ms 分布 |
______________________________________________________________________
开发状态
当前版本:0.2.0(Alpha)
此SDK正在积极开发中。API可能会在未来版本中更改。
贡献
欢迎投稿!请随时提交拉取请求。
许可证
麻省理工学院
______________________________________________________________________
由以下材料制成❤️ 面向MCP建设者
