mcp-instana 0.3.1__py3-none-any.whl → 0.6.2__py3-none-any.whl
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.
- {mcp_instana-0.3.1.dist-info → mcp_instana-0.6.2.dist-info}/METADATA +9 -193
- {mcp_instana-0.3.1.dist-info → mcp_instana-0.6.2.dist-info}/RECORD +18 -17
- {mcp_instana-0.3.1.dist-info → mcp_instana-0.6.2.dist-info}/WHEEL +1 -1
- src/application/application_alert_config.py +10 -4
- src/application/application_analyze.py +13 -10
- src/application/application_global_alert_config.py +22 -21
- src/application/application_metrics.py +21 -21
- src/application/application_resources.py +44 -4
- src/application/application_settings.py +190 -66
- src/core/server.py +3 -0
- src/event/events_tools.py +57 -9
- src/infrastructure/infrastructure_catalog.py +30 -4
- src/infrastructure/infrastructure_metrics.py +1 -0
- src/infrastructure/infrastructure_resources.py +1 -4
- src/infrastructure/infrastructure_topology.py +27 -15
- src/observability.py +29 -0
- {mcp_instana-0.3.1.dist-info → mcp_instana-0.6.2.dist-info}/entry_points.txt +0 -0
- {mcp_instana-0.3.1.dist-info → mcp_instana-0.6.2.dist-info}/licenses/LICENSE.md +0 -0
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mcp-instana
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.2
|
|
4
4
|
Summary: MCP server for Instana
|
|
5
5
|
Author-email: Elina Priyadarshinee <Elina.priyadarshinee1@ibm.com>, Guangya Liu <gyliu@ibm.com>, Isabell Sippli <ischwert@de.ibm.com>, Jay Sharma <Jay.Sharma3@ibm.com>, Madhu Tadiparthi <madhu.tadiparthi@ibm.com>, Riya Kumari <Riya.Kumari3@ibm.com>
|
|
6
6
|
License: Apache-2.0
|
|
7
7
|
License-File: LICENSE.md
|
|
8
8
|
Requires-Python: >=3.10
|
|
9
|
-
Requires-Dist: fastmcp==2.
|
|
10
|
-
Requires-Dist: instana-client==1.0.
|
|
9
|
+
Requires-Dist: fastmcp==2.13.0
|
|
10
|
+
Requires-Dist: instana-client==1.0.2
|
|
11
11
|
Requires-Dist: mcp
|
|
12
12
|
Requires-Dist: pydantic==2.11.7
|
|
13
13
|
Requires-Dist: python-dotenv==1.1.0
|
|
14
14
|
Requires-Dist: requests==2.32.4
|
|
15
|
+
Requires-Dist: traceloop-sdk>=0.47.5
|
|
15
16
|
Provides-Extra: dev
|
|
16
17
|
Requires-Dist: coverage>=7.10.1; extra == 'dev'
|
|
17
18
|
Requires-Dist: pytest-asyncio>=1.1.0; extra == 'dev'
|
|
@@ -25,7 +26,6 @@ Description-Content-Type: text/markdown
|
|
|
25
26
|
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
|
26
27
|
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
|
27
28
|
<!-- mcp-name: io.github.instana/mcp-instana -->
|
|
28
|
-
**Table of Contents**
|
|
29
29
|
|
|
30
30
|
- [MCP Server for IBM Instana](#mcp-server-for-ibm-instana)
|
|
31
31
|
- [Architecture Overview](#architecture-overview)
|
|
@@ -72,27 +72,8 @@ Description-Content-Type: text/markdown
|
|
|
72
72
|
- [**pyproject.toml** (Development)](#pyprojecttoml-development)
|
|
73
73
|
- [**pyproject-runtime.toml** (Production)](#pyproject-runtimetoml-production)
|
|
74
74
|
- [Building the Docker Image](#building-the-docker-image)
|
|
75
|
-
- [**Prerequisites**](#prerequisites
|
|
75
|
+
- [**Prerequisites**](#prerequisites)
|
|
76
76
|
- [**Build Command**](#build-command)
|
|
77
|
-
- [**What the Build Does**](#what-the-build-does)
|
|
78
|
-
- [Running the Docker Container](#running-the-docker-container)
|
|
79
|
-
- [**Basic Usage**](#basic-usage)
|
|
80
|
-
- [**Environment Variables**](#environment-variables)
|
|
81
|
-
- [**Docker Compose Example**](#docker-compose-example)
|
|
82
|
-
- [Multi-Architecture Support](#multi-architecture-support)
|
|
83
|
-
- [**Supported Architectures**](#supported-architectures)
|
|
84
|
-
- [**Benefits of Multi-Architecture Images**](#benefits-of-multi-architecture-images)
|
|
85
|
-
- [**How It Works**](#how-it-works)
|
|
86
|
-
- [Docker Security Features](#docker-security-features)
|
|
87
|
-
- [**Security Best Practices Implemented**](#security-best-practices-implemented)
|
|
88
|
-
- [**Image Size Optimization**](#image-size-optimization)
|
|
89
|
-
- [Testing the Docker Container](#testing-the-docker-container)
|
|
90
|
-
- [**Health Check**](#health-check)
|
|
91
|
-
- [**MCP Inspector Testing**](#mcp-inspector-testing)
|
|
92
|
-
- [**Logs and Debugging**](#logs-and-debugging)
|
|
93
|
-
- [Production Deployment](#production-deployment)
|
|
94
|
-
- [**Recommended Production Setup**](#recommended-production-setup)
|
|
95
|
-
- [**Kubernetes Example**](#kubernetes-example)
|
|
96
77
|
- [Troubleshooting](#troubleshooting)
|
|
97
78
|
- [**Docker Issues**](#docker-issues)
|
|
98
79
|
- [**Container Won't Start**](#container-wont-start)
|
|
@@ -1032,47 +1013,14 @@ The project uses a **two-file dependency management strategy**:
|
|
|
1032
1013
|
- Docker BuildKit for multi-architecture builds (enabled by default in recent Docker versions)
|
|
1033
1014
|
|
|
1034
1015
|
#### **Build Command**
|
|
1035
|
-
|
|
1036
|
-
**Single Architecture Build (Default):**
|
|
1037
1016
|
```bash
|
|
1038
|
-
# Build
|
|
1017
|
+
# Build the optimized production image
|
|
1039
1018
|
docker build -t mcp-instana:latest .
|
|
1040
1019
|
|
|
1041
1020
|
# Build with a specific tag
|
|
1042
|
-
docker build -t mcp-instana
|
|
1043
|
-
```
|
|
1044
|
-
|
|
1045
|
-
**Multi-Architecture Build:**
|
|
1046
|
-
```bash
|
|
1047
|
-
# Set up Docker BuildKit builder if you haven't already
|
|
1048
|
-
docker buildx create --name multiarch --driver docker-container --use
|
|
1049
|
-
|
|
1050
|
-
# Build and push a multi-architecture image to a registry
|
|
1051
|
-
docker buildx build --platform linux/amd64,linux/arm64 -t username/mcp-instana:latest --push .
|
|
1052
|
-
```
|
|
1021
|
+
docker build -t mcp-instana:< image_tag > .
|
|
1053
1022
|
|
|
1054
|
-
**
|
|
1055
|
-
```bash
|
|
1056
|
-
# Make the script executable
|
|
1057
|
-
chmod +x build_multiarch.sh
|
|
1058
|
-
|
|
1059
|
-
# Build for local architecture
|
|
1060
|
-
./build_multiarch.sh
|
|
1061
|
-
|
|
1062
|
-
# Build and push multi-architecture image
|
|
1063
|
-
./build_multiarch.sh --registry username/ --push
|
|
1064
|
-
```
|
|
1065
|
-
|
|
1066
|
-
#### **What the Build Does**
|
|
1067
|
-
1. **Multi-stage build** for optimal size and security
|
|
1068
|
-
2. **Builder stage**: Installs only runtime dependencies from `pyproject-runtime.toml`
|
|
1069
|
-
3. **Runtime stage**: Creates minimal production image with non-root user
|
|
1070
|
-
4. **Security**: No hardcoded secrets, proper user permissions
|
|
1071
|
-
5. **Optimization**: Only essential dependencies (20 vs 95+ in development)
|
|
1072
|
-
|
|
1073
|
-
### Running the Docker Container
|
|
1074
|
-
|
|
1075
|
-
#### **Basic Usage**
|
|
1023
|
+
#### **Run Command**
|
|
1076
1024
|
```bash
|
|
1077
1025
|
# Run the container (no credentials needed in the container)
|
|
1078
1026
|
docker run -p 8080:8080 mcp-instana
|
|
@@ -1081,135 +1029,6 @@ docker run -p 8080:8080 mcp-instana
|
|
|
1081
1029
|
docker run -p 8081:8080 mcp-instana
|
|
1082
1030
|
```
|
|
1083
1031
|
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
#### **Docker Compose Example**
|
|
1087
|
-
```yaml
|
|
1088
|
-
version: '3.8'
|
|
1089
|
-
services:
|
|
1090
|
-
mcp-instana:
|
|
1091
|
-
build: .
|
|
1092
|
-
ports:
|
|
1093
|
-
- "8080:8080"
|
|
1094
|
-
restart: unless-stopped
|
|
1095
|
-
healthcheck:
|
|
1096
|
-
test: ["CMD", "python", "-c", "import requests; requests.get('http://127.0.0.1:8080/health', timeout=5)"]
|
|
1097
|
-
interval: 30s
|
|
1098
|
-
timeout: 10s
|
|
1099
|
-
retries: 3
|
|
1100
|
-
start_period: 40s
|
|
1101
|
-
```
|
|
1102
|
-
|
|
1103
|
-
### Multi-Architecture Support
|
|
1104
|
-
|
|
1105
|
-
The Docker image supports multiple processor architectures, making it portable across different environments:
|
|
1106
|
-
|
|
1107
|
-
#### **Supported Architectures**
|
|
1108
|
-
- ✅ **amd64/x86_64**: Standard Intel/AMD processors (Windows, Linux, most cloud VMs)
|
|
1109
|
-
- ✅ **arm64/aarch64**: Apple Silicon (M1/M2/M3), AWS Graviton, Raspberry Pi 4, etc.
|
|
1110
|
-
|
|
1111
|
-
#### **Benefits of Multi-Architecture Images**
|
|
1112
|
-
- **Cross-Platform Compatibility**: Run the same image on any supported architecture
|
|
1113
|
-
- **Seamless Deployment**: No need to build different images for different environments
|
|
1114
|
-
- **CI/CD Simplification**: Build once, deploy anywhere
|
|
1115
|
-
- **Cloud Flexibility**: Switch between cloud providers and instance types without rebuilding images
|
|
1116
|
-
|
|
1117
|
-
#### **How It Works**
|
|
1118
|
-
1. The multi-architecture image is a "manifest list" containing images for each architecture
|
|
1119
|
-
2. When you pull the image, Docker automatically selects the correct architecture for your system
|
|
1120
|
-
3. The image runs natively on your architecture without emulation, ensuring optimal performance
|
|
1121
|
-
|
|
1122
|
-
### Docker Security Features
|
|
1123
|
-
|
|
1124
|
-
#### **Security Best Practices Implemented**
|
|
1125
|
-
- ✅ **Non-root user**: Container runs as `mcpuser` (not root)
|
|
1126
|
-
- ✅ **No secrets in container**: Credentials are passed via HTTP headers from clients, not stored in the container
|
|
1127
|
-
- ✅ **Minimal dependencies**: Only 20 essential runtime dependencies
|
|
1128
|
-
- ✅ **Multi-stage build**: Build tools don't make it to final image
|
|
1129
|
-
- ✅ **Health checks**: Built-in container health monitoring
|
|
1130
|
-
- ✅ **Optimized base image**: Uses `python:3.11-slim`
|
|
1131
|
-
- ✅ **Multi-architecture support**: Run natively on any supported platform
|
|
1132
|
-
|
|
1133
|
-
#### **Image Size Optimization**
|
|
1134
|
-
- **Original approach**: 95+ dependencies → ~1-2GB+ image
|
|
1135
|
-
- **Optimized approach**: 20 dependencies → ~266MB image
|
|
1136
|
-
- **Size reduction**: ~70-80% smaller images
|
|
1137
|
-
- **Benefits**: Faster deployments, lower storage costs, reduced attack surface
|
|
1138
|
-
|
|
1139
|
-
### Testing the Docker Container
|
|
1140
|
-
|
|
1141
|
-
#### **Health Check**
|
|
1142
|
-
```bash
|
|
1143
|
-
# Check if container is healthy
|
|
1144
|
-
docker ps
|
|
1145
|
-
|
|
1146
|
-
# Test the MCP endpoint
|
|
1147
|
-
curl http://localhost:8080/mcp/
|
|
1148
|
-
```
|
|
1149
|
-
|
|
1150
|
-
#### **MCP Inspector Testing**
|
|
1151
|
-
```bash
|
|
1152
|
-
# Test with MCP Inspector
|
|
1153
|
-
npx @modelcontextprotocol/inspector http://localhost:8080/mcp/
|
|
1154
|
-
```
|
|
1155
|
-
|
|
1156
|
-
#### **Logs and Debugging**
|
|
1157
|
-
```bash
|
|
1158
|
-
# View container logs
|
|
1159
|
-
docker logs <container_id>
|
|
1160
|
-
|
|
1161
|
-
# Follow logs in real-time
|
|
1162
|
-
docker logs -f <container_id>
|
|
1163
|
-
|
|
1164
|
-
# Execute commands in running container
|
|
1165
|
-
docker exec -it <container_id> /bin/bash
|
|
1166
|
-
```
|
|
1167
|
-
|
|
1168
|
-
### Production Deployment
|
|
1169
|
-
|
|
1170
|
-
#### **Recommended Production Setup**
|
|
1171
|
-
1. **Run container without credentials** - The container runs in Streamable HTTP mode, so no Instana credentials are needed in the container
|
|
1172
|
-
2. **Configure clients with credentials** - Pass Instana credentials via HTTP headers from MCP clients (Claude Desktop, GitHub Copilot, etc.)
|
|
1173
|
-
3. **Set up proper logging** and monitoring
|
|
1174
|
-
4. **Configure health checks** for container orchestration
|
|
1175
|
-
5. **Use container orchestration** (Kubernetes, Docker Swarm, etc.)
|
|
1176
|
-
6. **Implement proper backup** and disaster recovery
|
|
1177
|
-
|
|
1178
|
-
#### **Kubernetes Example**
|
|
1179
|
-
```yaml
|
|
1180
|
-
apiVersion: apps/v1
|
|
1181
|
-
kind: Deployment
|
|
1182
|
-
metadata:
|
|
1183
|
-
name: mcp-instana
|
|
1184
|
-
spec:
|
|
1185
|
-
replicas: 2
|
|
1186
|
-
selector:
|
|
1187
|
-
matchLabels:
|
|
1188
|
-
app: mcp-instana
|
|
1189
|
-
template:
|
|
1190
|
-
metadata:
|
|
1191
|
-
labels:
|
|
1192
|
-
app: mcp-instana
|
|
1193
|
-
spec:
|
|
1194
|
-
containers:
|
|
1195
|
-
- name: mcp-instana
|
|
1196
|
-
image: mcp-instana:latest
|
|
1197
|
-
ports:
|
|
1198
|
-
- containerPort: 8080
|
|
1199
|
-
livenessProbe:
|
|
1200
|
-
httpGet:
|
|
1201
|
-
path: /health
|
|
1202
|
-
port: 8080
|
|
1203
|
-
initialDelaySeconds: 30
|
|
1204
|
-
periodSeconds: 10
|
|
1205
|
-
readinessProbe:
|
|
1206
|
-
httpGet:
|
|
1207
|
-
path: /health
|
|
1208
|
-
port: 8080
|
|
1209
|
-
initialDelaySeconds: 5
|
|
1210
|
-
periodSeconds: 5
|
|
1211
|
-
```
|
|
1212
|
-
|
|
1213
1032
|
## Troubleshooting
|
|
1214
1033
|
|
|
1215
1034
|
### **Docker Issues**
|
|
@@ -1218,12 +1037,10 @@ spec:
|
|
|
1218
1037
|
```bash
|
|
1219
1038
|
# Check container logs
|
|
1220
1039
|
docker logs <container_id>
|
|
1221
|
-
|
|
1222
1040
|
# Common issues:
|
|
1223
1041
|
# 1. Port already in use
|
|
1224
1042
|
# 2. Invalid container image
|
|
1225
1043
|
# 3. Missing dependencies
|
|
1226
|
-
|
|
1227
1044
|
# Credentials are passed via HTTP headers from the MCP client
|
|
1228
1045
|
```
|
|
1229
1046
|
|
|
@@ -1231,7 +1048,6 @@ docker logs <container_id>
|
|
|
1231
1048
|
```bash
|
|
1232
1049
|
# Test container connectivity
|
|
1233
1050
|
docker exec -it <container_id> curl http://127.0.0.1:8080/health
|
|
1234
|
-
|
|
1235
1051
|
# Check port mapping
|
|
1236
1052
|
docker port <container_id>
|
|
1237
1053
|
```
|
|
@@ -1240,7 +1056,6 @@ docker port <container_id>
|
|
|
1240
1056
|
```bash
|
|
1241
1057
|
# Check container resource usage
|
|
1242
1058
|
docker stats <container_id>
|
|
1243
|
-
|
|
1244
1059
|
# Monitor container health
|
|
1245
1060
|
docker inspect <container_id> | grep -A 10 Health
|
|
1246
1061
|
```
|
|
@@ -1256,3 +1071,4 @@ docker inspect <container_id> | grep -A 10 Health
|
|
|
1256
1071
|
- If that works, your Python environment may not be able to verify the certificate and might not have access to the same certificates as your shell or system. Ensure your Python environment uses system certificates (macOS). You can do this by installing certificates to Python:
|
|
1257
1072
|
`//Applications/Python\ 3.13/Install\ Certificates.command`
|
|
1258
1073
|
- If you cannot reach the endpoint with SSL verification, try without it. If that works, check your system's CA certificates and ensure they are up-to-date.
|
|
1074
|
+
```
|
|
@@ -1,26 +1,27 @@
|
|
|
1
1
|
src/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
src/observability.py,sha256=FQIMF4reR-UtXqnBSa3Ub0wuPvlf9VNSTeMieJmFdMM,959
|
|
2
3
|
src/application/__init__.py,sha256=cfWHjA5NzAvL0jcekaIO3NTe5DRtznYRqg9_8hVwSzc,37
|
|
3
|
-
src/application/application_alert_config.py,sha256=
|
|
4
|
-
src/application/application_analyze.py,sha256=
|
|
4
|
+
src/application/application_alert_config.py,sha256=LDUgkpMBx_5tX88dzE0emr31kydzMZWDCi36JzZDyEw,31590
|
|
5
|
+
src/application/application_analyze.py,sha256=cb5kbt2GYntyFAHXvix9r7nFthoftCa9haWmXjxpDEM,27046
|
|
5
6
|
src/application/application_catalog.py,sha256=MVjU1CyYf6NSeCt2o0aTlNDAKeMUY3vr-wDOprnt2D8,6540
|
|
6
|
-
src/application/application_global_alert_config.py,sha256=
|
|
7
|
-
src/application/application_metrics.py,sha256=
|
|
8
|
-
src/application/application_resources.py,sha256=
|
|
9
|
-
src/application/application_settings.py,sha256=
|
|
7
|
+
src/application/application_global_alert_config.py,sha256=PGDPXAuSu_J6uKohMhKWh1gpPOUkk4COvQF4mXsEPZI,31474
|
|
8
|
+
src/application/application_metrics.py,sha256=M8OymCr2TxlckpnUtASFaLb5kZD1AbnZy2ApvfQgGbI,15466
|
|
9
|
+
src/application/application_resources.py,sha256=3cZEOaAppDwSMG_DItR1BTbjuz_JkxedorvbvxzDcbw,20262
|
|
10
|
+
src/application/application_settings.py,sha256=gwkGKeiKpXLGmRe_MYtSvGglXHsgP9JakaBkm8TeKbo,83655
|
|
10
11
|
src/application/application_topology.py,sha256=WinVNHSSTF771vq5hl2GxTLm3bdpehAQJ1AMumfy7M0,4870
|
|
11
12
|
src/automation/action_catalog.py,sha256=jivR73riqBt-MGDnhSoEsshG7bHk7JpxvVuRx7FCtOA,17493
|
|
12
13
|
src/automation/action_history.py,sha256=aMHUd5RLMrgdDvJXv0x6dkUA7I_35O0A89RPhFUfORI,16494
|
|
13
14
|
src/core/__init__.py,sha256=gZdGV4TVETqe3XV-_lzQMw0IgyTTCqYYgP3PH9YdWbU,30
|
|
14
|
-
src/core/server.py,sha256=
|
|
15
|
+
src/core/server.py,sha256=LSdYYO-G9g1k_2yRqZVta2e8ZaGr3hFvj0duSbc7o-Y,25107
|
|
15
16
|
src/core/utils.py,sha256=vB2ArNkOy0YIHk8Xv8nYHGEeTpw79pStJz6HL2aHWK8,11527
|
|
16
17
|
src/event/__init__.py,sha256=ru-xCHU9xksGf9aJslvI37-6SI2yoBOpsoaED-vbaaQ,31
|
|
17
|
-
src/event/events_tools.py,sha256=
|
|
18
|
+
src/event/events_tools.py,sha256=ajCARRjxd6tkqH_fdFC1cOg9TYRV_gJE4BBVqDmyLV0,45365
|
|
18
19
|
src/infrastructure/__init__.py,sha256=xZuRO1Zb2iPyO5G3PRM90dfesaFheL7DMSSJMujtLVk,40
|
|
19
20
|
src/infrastructure/infrastructure_analyze.py,sha256=eBo9Rq7DRzsIKup4LR-ar_1g4kr_IPWeKcHMb-w1hLA,29455
|
|
20
|
-
src/infrastructure/infrastructure_catalog.py,sha256=
|
|
21
|
-
src/infrastructure/infrastructure_metrics.py,sha256=
|
|
22
|
-
src/infrastructure/infrastructure_resources.py,sha256=
|
|
23
|
-
src/infrastructure/infrastructure_topology.py,sha256=
|
|
21
|
+
src/infrastructure/infrastructure_catalog.py,sha256=tXrDAJ0ZzS6cfrx-aDJ63GkYGKUbePV_NLH-opm5bsE,31254
|
|
22
|
+
src/infrastructure/infrastructure_metrics.py,sha256=P5uiy2uGLrmh8LuYcW1GG_DkOAvAb64nEpKD_lBeydo,7136
|
|
23
|
+
src/infrastructure/infrastructure_resources.py,sha256=sVnYUkeMiaMAp3ln6ujHzRLOwceHr_XLE9LB0Qmrgbg,29240
|
|
24
|
+
src/infrastructure/infrastructure_topology.py,sha256=rVY7QnLGANHPXlezAhbc6wJfOoUO2TRr_VlXtkifo4A,15456
|
|
24
25
|
src/log/__init__.py,sha256=NwPZccMqR5aR6PrISe760gkABtpg7zpbwOK-uMPB-_Y,29
|
|
25
26
|
src/log/log_alert_configuration.py,sha256=-8ORRo889n4X4GalwhTQa9uHU4JuERy2OfnhP7k6LOM,18430
|
|
26
27
|
src/prompts/__init__.py,sha256=oXt7rf_EASRtgL43lKRgH8xhX6abJ3fhpHfarIlkFog,405
|
|
@@ -52,8 +53,8 @@ src/website/website_analyze.py,sha256=0VyK8f-9vW1LzZ70b7IxKzwqSL2bWw8wDFSOCx2pEr
|
|
|
52
53
|
src/website/website_catalog.py,sha256=Z21urtdTf8sU2SZiCwGq5OyPLaswS9lw12TCD9pS__4,7127
|
|
53
54
|
src/website/website_configuration.py,sha256=hBHSFgj6GXOfLvlq8p-tBU4KFQc99uS167DBz4cjjK0,35926
|
|
54
55
|
src/website/website_metrics.py,sha256=6McxbVYZq5i61Ml3QcVeHS86y2rCIPzdDuUDOxNtnMM,10954
|
|
55
|
-
mcp_instana-0.
|
|
56
|
-
mcp_instana-0.
|
|
57
|
-
mcp_instana-0.
|
|
58
|
-
mcp_instana-0.
|
|
59
|
-
mcp_instana-0.
|
|
56
|
+
mcp_instana-0.6.2.dist-info/METADATA,sha256=utEaEnN7t95AmdwuR4a-ODN_Q5WJEl-zeSJfRrP06bY,42334
|
|
57
|
+
mcp_instana-0.6.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
58
|
+
mcp_instana-0.6.2.dist-info/entry_points.txt,sha256=p1aZ9Ks0aJKpoIy6Mk-08cGYAfkXMNbwYIlokm513A4,140
|
|
59
|
+
mcp_instana-0.6.2.dist-info/licenses/LICENSE.md,sha256=Ox7lseFP2kBRXBjsLweW1jLmWiCyrKjwF8ZUvCbKd70,11310
|
|
60
|
+
mcp_instana-0.6.2.dist-info/RECORD,,
|
|
@@ -525,11 +525,16 @@ class ApplicationAlertMCPTools(BaseInstanaClient):
|
|
|
525
525
|
logger.debug(f"Error importing ApplicationAlertConfig: {e}")
|
|
526
526
|
return {"error": f"Failed to import ApplicationAlertConfig: {e!s}"}
|
|
527
527
|
|
|
528
|
-
# Create an ApplicationAlertConfig object from the request body
|
|
528
|
+
# Create an ApplicationAlertConfig object from the request body using from_dict
|
|
529
|
+
# This properly handles nested objects and discriminators
|
|
529
530
|
try:
|
|
530
531
|
logger.debug(f"Creating ApplicationAlertConfig with params: {request_body}")
|
|
531
|
-
config_object = ApplicationAlertConfig(
|
|
532
|
+
config_object = ApplicationAlertConfig.from_dict(request_body)
|
|
532
533
|
logger.debug("Successfully created config object")
|
|
534
|
+
|
|
535
|
+
# Debug: Log what will be sent to API
|
|
536
|
+
config_dict = config_object.to_dict()
|
|
537
|
+
logger.debug(f"Config object as dict (what will be sent to API): {config_dict}")
|
|
533
538
|
except Exception as e:
|
|
534
539
|
logger.debug(f"Error creating ApplicationAlertConfig: {e}")
|
|
535
540
|
return {"error": f"Failed to create config object: {e!s}"}
|
|
@@ -655,10 +660,11 @@ class ApplicationAlertMCPTools(BaseInstanaClient):
|
|
|
655
660
|
logger.debug(f"Error importing ApplicationAlertConfig: {e}")
|
|
656
661
|
return {"error": f"Failed to import ApplicationAlertConfig: {e!s}"}
|
|
657
662
|
|
|
658
|
-
# Create an ApplicationAlertConfig object from the request body
|
|
663
|
+
# Create an ApplicationAlertConfig object from the request body using from_dict
|
|
664
|
+
# This properly handles nested objects and discriminators
|
|
659
665
|
try:
|
|
660
666
|
logger.debug(f"Creating ApplicationAlertConfig with params: {request_body}")
|
|
661
|
-
config_object = ApplicationAlertConfig(
|
|
667
|
+
config_object = ApplicationAlertConfig.from_dict(request_body)
|
|
662
668
|
logger.debug("Successfully created config object")
|
|
663
669
|
except Exception as e:
|
|
664
670
|
logger.debug(f"Error creating ApplicationAlertConfig: {e}")
|
|
@@ -84,21 +84,24 @@ class ApplicationAnalyzeMCPTools(BaseInstanaClient):
|
|
|
84
84
|
return {"error": "Both trace_id and call_id must be provided"}
|
|
85
85
|
|
|
86
86
|
logger.debug(f"Fetching call details for trace_id={trace_id}, call_id={call_id}")
|
|
87
|
-
result = api_client.
|
|
87
|
+
result = api_client.get_call_details_without_preload_content(
|
|
88
88
|
trace_id=trace_id,
|
|
89
89
|
call_id=call_id
|
|
90
90
|
)
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
if hasattr(result, 'to_dict'):
|
|
94
|
-
result_dict = result.to_dict()
|
|
95
|
-
else:
|
|
96
|
-
# If it's already a dict or another format, use it as is
|
|
97
|
-
result_dict = result
|
|
92
|
+
import json
|
|
98
93
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
94
|
+
try:
|
|
95
|
+
response_text = result.data.decode('utf-8')
|
|
96
|
+
result_dict = json.loads(response_text)
|
|
97
|
+
logger.debug("Successfully retrieved call details")
|
|
98
|
+
return result_dict
|
|
99
|
+
|
|
100
|
+
# Convert the result to a dictionary
|
|
101
|
+
except (json.JSONDecodeError, AttributeError) as json_err:
|
|
102
|
+
error_message = f"Failed to parse JSON response: {json_err}"
|
|
103
|
+
logger.error(error_message)
|
|
104
|
+
return {"error": error_message}
|
|
102
105
|
|
|
103
106
|
except Exception as e:
|
|
104
107
|
logger.error(f"Error getting call details: {e}", exc_info=True)
|
|
@@ -41,7 +41,7 @@ class ApplicationGlobalAlertMCPTools(BaseInstanaClient):
|
|
|
41
41
|
async def find_active_global_application_alert_configs(self,
|
|
42
42
|
application_id: str,
|
|
43
43
|
alert_ids: Optional[List[str]] = None,
|
|
44
|
-
ctx=None, api_client=None) ->
|
|
44
|
+
ctx=None, api_client=None) -> Dict[str, Any]:
|
|
45
45
|
"""
|
|
46
46
|
Get All Global Smart Alert Configuration.
|
|
47
47
|
|
|
@@ -63,36 +63,37 @@ class ApplicationGlobalAlertMCPTools(BaseInstanaClient):
|
|
|
63
63
|
|
|
64
64
|
# Validate required parameters
|
|
65
65
|
if not application_id:
|
|
66
|
-
return
|
|
66
|
+
return {"error": "application_id is required"}
|
|
67
67
|
|
|
68
68
|
# Call the find_active_global_application_alert_configs method from the SDK
|
|
69
69
|
logger.debug(f"Calling find_active_global_application_alert_configs with application_id={application_id}, alert_ids={alert_ids}")
|
|
70
|
-
|
|
70
|
+
response = api_client.find_active_global_application_alert_configs_without_preload_content(
|
|
71
71
|
application_id=application_id,
|
|
72
72
|
alert_ids=alert_ids
|
|
73
73
|
)
|
|
74
74
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
75
|
+
import json
|
|
76
|
+
|
|
77
|
+
raw_data = response.data.decode('utf-8')
|
|
78
|
+
logger.debug(f"Raw data: {raw_data}")
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
result = json.loads(raw_data)
|
|
82
|
+
logger.debug(f"Parsed JSON result: {result}")
|
|
83
|
+
|
|
84
|
+
if isinstance(result, list):
|
|
85
|
+
return {"configs": result}
|
|
86
|
+
else:
|
|
87
|
+
return {"configs": [result] if result else []}
|
|
88
|
+
|
|
89
|
+
except json.JSONDecodeError as e:
|
|
90
|
+
error_msg = f"Failed to parse response JSON: {e}"
|
|
91
|
+
logger.error(error_msg)
|
|
92
|
+
return {"error": error_msg}
|
|
90
93
|
|
|
91
|
-
logger.debug(f"Result from find_active_global_application_alert_configs: {result_list}")
|
|
92
|
-
return result_list
|
|
93
94
|
except Exception as e:
|
|
94
95
|
logger.error(f"Error in find_active_global_application_alert_configs: {e}", exc_info=True)
|
|
95
|
-
return
|
|
96
|
+
return {"error": f"Failed to get active global application alert config: {e!s}"}
|
|
96
97
|
|
|
97
98
|
|
|
98
99
|
@register_as_tool(
|
|
@@ -134,18 +134,18 @@ class ApplicationMetricsMCPTools(BaseInstanaClient):
|
|
|
134
134
|
)
|
|
135
135
|
@with_header_auth(ApplicationMetricsApi)
|
|
136
136
|
async def get_application_metrics(self,
|
|
137
|
-
|
|
137
|
+
application_id: Optional[str] = None,
|
|
138
138
|
metrics: Optional[List[Dict[str, str]]] = None,
|
|
139
139
|
time_frame: Optional[Dict[str, int]] = None,
|
|
140
140
|
fill_time_series: Optional[bool] = True,
|
|
141
141
|
ctx=None, api_client=None) -> Dict[str, Any]:
|
|
142
142
|
"""
|
|
143
|
-
Get metrics for specific
|
|
143
|
+
Get metrics for a specific application.
|
|
144
144
|
|
|
145
145
|
This API endpoint retrieves one or more supported aggregations of metrics for an Application Perspective.
|
|
146
146
|
|
|
147
147
|
Args:
|
|
148
|
-
|
|
148
|
+
application_id: Application ID to get metrics for (single application)
|
|
149
149
|
metrics: List of metrics to retrieve with their aggregations
|
|
150
150
|
Example: [{"metric": "latency", "aggregation": "MEAN"}]
|
|
151
151
|
time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
|
|
@@ -157,7 +157,7 @@ class ApplicationMetricsMCPTools(BaseInstanaClient):
|
|
|
157
157
|
Dictionary containing application metrics data or error information
|
|
158
158
|
"""
|
|
159
159
|
try:
|
|
160
|
-
logger.debug(f"get_application_metrics called with
|
|
160
|
+
logger.debug(f"get_application_metrics called with application_id={application_id}")
|
|
161
161
|
|
|
162
162
|
# Set default time range if not provided
|
|
163
163
|
if not time_frame:
|
|
@@ -183,9 +183,9 @@ class ApplicationMetricsMCPTools(BaseInstanaClient):
|
|
|
183
183
|
"timeFrame": time_frame
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
# Add application
|
|
187
|
-
if
|
|
188
|
-
request_body["
|
|
186
|
+
# Add application ID if provided
|
|
187
|
+
if application_id:
|
|
188
|
+
request_body["applicationId"] = application_id
|
|
189
189
|
|
|
190
190
|
# Create the GetApplications object
|
|
191
191
|
get_applications = GetApplications(**request_body)
|
|
@@ -215,18 +215,18 @@ class ApplicationMetricsMCPTools(BaseInstanaClient):
|
|
|
215
215
|
)
|
|
216
216
|
@with_header_auth(ApplicationMetricsApi)
|
|
217
217
|
async def get_endpoints_metrics(self,
|
|
218
|
-
|
|
218
|
+
endpoint_id: Optional[str] = None,
|
|
219
219
|
metrics: Optional[List[Dict[str, str]]] = None,
|
|
220
220
|
time_frame: Optional[Dict[str, int]] = None,
|
|
221
221
|
fill_time_series: Optional[bool] = True,
|
|
222
222
|
ctx=None, api_client=None) -> Dict[str, Any]:
|
|
223
223
|
"""
|
|
224
|
-
Get metrics for specific
|
|
224
|
+
Get metrics for a specific endpoint.
|
|
225
225
|
|
|
226
226
|
This API endpoint retrieves one or more supported aggregations of metrics for an Endpoint.
|
|
227
227
|
|
|
228
228
|
Args:
|
|
229
|
-
|
|
229
|
+
endpoint_id: Endpoint ID to get metrics for (single endpoint)
|
|
230
230
|
metrics: List of metrics to retrieve with their aggregations
|
|
231
231
|
Example: [{"metric": "latency", "aggregation": "MEAN"}]
|
|
232
232
|
time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
|
|
@@ -238,7 +238,7 @@ class ApplicationMetricsMCPTools(BaseInstanaClient):
|
|
|
238
238
|
Dictionary containing endpoint metrics data or error information
|
|
239
239
|
"""
|
|
240
240
|
try:
|
|
241
|
-
logger.debug(f"get_endpoints_metrics called with
|
|
241
|
+
logger.debug(f"get_endpoints_metrics called with endpoint_id={endpoint_id}")
|
|
242
242
|
|
|
243
243
|
# Set default time range if not provided
|
|
244
244
|
if not time_frame:
|
|
@@ -264,9 +264,9 @@ class ApplicationMetricsMCPTools(BaseInstanaClient):
|
|
|
264
264
|
"timeFrame": time_frame
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
# Add endpoint
|
|
268
|
-
if
|
|
269
|
-
request_body["
|
|
267
|
+
# Add endpoint ID if provided
|
|
268
|
+
if endpoint_id:
|
|
269
|
+
request_body["endpointId"] = endpoint_id
|
|
270
270
|
|
|
271
271
|
# Create the GetEndpoints object
|
|
272
272
|
get_endpoints = GetEndpoints(**request_body)
|
|
@@ -296,19 +296,19 @@ class ApplicationMetricsMCPTools(BaseInstanaClient):
|
|
|
296
296
|
)
|
|
297
297
|
@with_header_auth(ApplicationMetricsApi)
|
|
298
298
|
async def get_services_metrics(self,
|
|
299
|
-
|
|
299
|
+
service_id: Optional[str] = None,
|
|
300
300
|
metrics: Optional[List[Dict[str, str]]] = None,
|
|
301
301
|
time_frame: Optional[Dict[str, int]] = None,
|
|
302
302
|
fill_time_series: Optional[bool] = True,
|
|
303
303
|
include_snapshot_ids: Optional[bool] = False,
|
|
304
304
|
ctx=None, api_client=None) -> Dict[str, Any]:
|
|
305
305
|
"""
|
|
306
|
-
Get metrics for specific
|
|
306
|
+
Get metrics for a specific service.
|
|
307
307
|
|
|
308
308
|
This API endpoint retrieves one or more supported aggregations of metrics for a Service.
|
|
309
309
|
|
|
310
310
|
Args:
|
|
311
|
-
|
|
311
|
+
service_id: Service ID to get metrics for (single service)
|
|
312
312
|
metrics: List of metrics to retrieve with their aggregations
|
|
313
313
|
Example: [{"metric": "latency", "aggregation": "MEAN"}]
|
|
314
314
|
time_frame: Dictionary with 'from' and 'to' timestamps in milliseconds
|
|
@@ -321,7 +321,7 @@ class ApplicationMetricsMCPTools(BaseInstanaClient):
|
|
|
321
321
|
Dictionary containing service metrics data or error information
|
|
322
322
|
"""
|
|
323
323
|
try:
|
|
324
|
-
logger.debug(f"get_services_metrics called with
|
|
324
|
+
logger.debug(f"get_services_metrics called with service_id={service_id}")
|
|
325
325
|
|
|
326
326
|
# Set default time range if not provided
|
|
327
327
|
if not time_frame:
|
|
@@ -347,9 +347,9 @@ class ApplicationMetricsMCPTools(BaseInstanaClient):
|
|
|
347
347
|
"timeFrame": time_frame
|
|
348
348
|
}
|
|
349
349
|
|
|
350
|
-
# Add service
|
|
351
|
-
if
|
|
352
|
-
request_body["
|
|
350
|
+
# Add service ID if provided
|
|
351
|
+
if service_id:
|
|
352
|
+
request_body["serviceId"] = service_id
|
|
353
353
|
|
|
354
354
|
# Create the GetServices object
|
|
355
355
|
get_services = GetServices(**request_body)
|