Skip to content

Commit 9335eda

Browse files
cursoragentalex
andcommitted
Add MCP Agent instrumentation support to AgentOps
Co-authored-by: alex <alex@agentops.ai>
1 parent 77e3930 commit 9335eda

9 files changed

Lines changed: 1758 additions & 0 deletions

File tree

agentops/instrumentation/__init__.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,12 @@ class InstrumentorConfig(TypedDict):
118118
"min_version": "1.0.0",
119119
"package_name": "xpander-sdk",
120120
},
121+
"mcp_agent": {
122+
"module_name": "agentops.instrumentation.providers.mcp_agent",
123+
"class_name": "MCPAgentInstrumentor",
124+
"min_version": "0.1.0",
125+
"package_name": "mcp-agent",
126+
},
121127
}
122128

123129
# Combine all target packages for monitoring
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
"""MCP Agent instrumentation for AgentOps.
2+
3+
This package provides OpenTelemetry-based instrumentation for MCP Agent,
4+
enabling telemetry collection and tracing for MCP-based agent workflows.
5+
"""
6+
7+
from agentops.instrumentation.common import LibraryInfo
8+
9+
# Library information
10+
_library_info = LibraryInfo(name="mcp-agent")
11+
LIBRARY_NAME = _library_info.name
12+
LIBRARY_VERSION = _library_info.version
13+
14+
# Import after defining constants to avoid circular imports
15+
from agentops.instrumentation.providers.mcp_agent.instrumentor import MCPAgentInstrumentor # noqa: E402
16+
17+
__all__ = [
18+
"LIBRARY_NAME",
19+
"LIBRARY_VERSION",
20+
"MCPAgentInstrumentor",
21+
]
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
"""Configuration for MCP Agent instrumentation."""
2+
3+
from dataclasses import dataclass
4+
from typing import Optional
5+
6+
7+
@dataclass
8+
class Config:
9+
"""Configuration for MCP Agent instrumentation.
10+
11+
This configuration controls how AgentOps instruments MCP Agent,
12+
including what data to capture and how to integrate with its
13+
existing telemetry system.
14+
"""
15+
16+
# Data capture settings
17+
capture_prompts: bool = True
18+
"""Whether to capture prompts sent to agents."""
19+
20+
capture_completions: bool = True
21+
"""Whether to capture agent completions/responses."""
22+
23+
capture_errors: bool = True
24+
"""Whether to capture and report errors."""
25+
26+
capture_tool_calls: bool = True
27+
"""Whether to capture MCP tool calls and their results."""
28+
29+
capture_workflows: bool = True
30+
"""Whether to capture workflow execution details."""
31+
32+
# Integration settings
33+
integrate_with_existing_telemetry: bool = True
34+
"""Whether to integrate with MCP Agent's existing OpenTelemetry setup."""
35+
36+
override_tracer_config: bool = False
37+
"""Whether to override MCP Agent's tracer configuration."""
38+
39+
# Performance settings
40+
max_prompt_length: Optional[int] = 10000
41+
"""Maximum length of prompts to capture (None for unlimited)."""
42+
43+
max_completion_length: Optional[int] = 10000
44+
"""Maximum length of completions to capture (None for unlimited)."""
45+
46+
# Filtering settings
47+
excluded_tools: Optional[list[str]] = None
48+
"""List of tool names to exclude from instrumentation."""
49+
50+
excluded_workflows: Optional[list[str]] = None
51+
"""List of workflow names to exclude from instrumentation."""
52+
53+
def should_capture_tool(self, tool_name: str) -> bool:
54+
"""Check if a tool should be captured."""
55+
if not self.capture_tool_calls:
56+
return False
57+
if self.excluded_tools and tool_name in self.excluded_tools:
58+
return False
59+
return True
60+
61+
def should_capture_workflow(self, workflow_name: str) -> bool:
62+
"""Check if a workflow should be captured."""
63+
if not self.capture_workflows:
64+
return False
65+
if self.excluded_workflows and workflow_name in self.excluded_workflows:
66+
return False
67+
return True
68+
69+
def truncate_prompt(self, prompt: str) -> str:
70+
"""Truncate prompt if needed."""
71+
if self.max_prompt_length and len(prompt) > self.max_prompt_length:
72+
return prompt[:self.max_prompt_length] + "... [truncated]"
73+
return prompt
74+
75+
def truncate_completion(self, completion: str) -> str:
76+
"""Truncate completion if needed."""
77+
if self.max_completion_length and len(completion) > self.max_completion_length:
78+
return completion[:self.max_completion_length] + "... [truncated]"
79+
return completion

0 commit comments

Comments
 (0)