awslabs.timestream-for-influxdb-mcp-server 0.0.11__py3-none-any.whl → 0.0.12__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.
- awslabs/timestream_for_influxdb_mcp_server/__init__.py +1 -1
- awslabs/timestream_for_influxdb_mcp_server/server.py +304 -23
- {awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info → awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info}/METADATA +19 -4
- awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info/RECORD +9 -0
- awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info/RECORD +0 -9
- {awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info → awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info}/WHEEL +0 -0
- {awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info → awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info}/entry_points.txt +0 -0
- {awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info → awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info}/licenses/LICENSE +0 -0
- {awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info → awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info}/licenses/NOTICE +0 -0
|
@@ -20,6 +20,7 @@ import os
|
|
|
20
20
|
from influxdb_client.client.influxdb_client import InfluxDBClient
|
|
21
21
|
from influxdb_client.client.write.point import Point
|
|
22
22
|
from influxdb_client.client.write_api import ASYNCHRONOUS, SYNCHRONOUS
|
|
23
|
+
from influxdb_client.domain.bucket_retention_rules import BucketRetentionRules
|
|
23
24
|
from influxdb_client.domain.write_precision import WritePrecision
|
|
24
25
|
from loguru import logger
|
|
25
26
|
from mcp.server.fastmcp import FastMCP
|
|
@@ -28,6 +29,11 @@ from typing import Any, Dict, List, Optional
|
|
|
28
29
|
from urllib.parse import urlparse
|
|
29
30
|
|
|
30
31
|
|
|
32
|
+
# InfluxDB environment variables for data plane operations
|
|
33
|
+
INFLUXDB_TOKEN = os.environ.get('INFLUXDB_TOKEN')
|
|
34
|
+
INFLUXDB_URL = os.environ.get('INFLUXDB_URL')
|
|
35
|
+
INFLUXDB_ORG = os.environ.get('INFLUXDB_ORG')
|
|
36
|
+
|
|
31
37
|
# Define Field parameters as global variables to avoid duplication
|
|
32
38
|
# Common fields
|
|
33
39
|
REQUIRED_FIELD_DB_CLUSTER_ID = Field(
|
|
@@ -180,10 +186,19 @@ REQUIRED_FIELD_STATUS_CLUSTER = Field(
|
|
|
180
186
|
)
|
|
181
187
|
|
|
182
188
|
# InfluxDB fields
|
|
183
|
-
|
|
184
|
-
|
|
189
|
+
OPTIONAL_FIELD_URL = Field(
|
|
190
|
+
None,
|
|
191
|
+
description='The URL of the InfluxDB server. Falls back to INFLUXDB_URL env var if not provided.',
|
|
192
|
+
)
|
|
193
|
+
OPTIONAL_FIELD_TOKEN = Field(
|
|
194
|
+
None,
|
|
195
|
+
description='The authentication token. Falls back to INFLUXDB_TOKEN env var if not provided.',
|
|
196
|
+
)
|
|
185
197
|
REQUIRED_FIELD_BUCKET_INFLUX = Field(..., description='The destination bucket for writes.')
|
|
186
|
-
|
|
198
|
+
OPTIONAL_FIELD_ORG = Field(
|
|
199
|
+
None,
|
|
200
|
+
description='The organization name. Falls back to INFLUXDB_ORG env var if not provided.',
|
|
201
|
+
)
|
|
187
202
|
REQUIRED_FIELD_POINTS = Field(
|
|
188
203
|
...,
|
|
189
204
|
description='List of data points to write. Each point should be a dictionary with measurement, tags, fields, and optional time.',
|
|
@@ -242,6 +257,46 @@ def get_timestream_influxdb_client():
|
|
|
242
257
|
return client
|
|
243
258
|
|
|
244
259
|
|
|
260
|
+
def resolve_influxdb_config(
|
|
261
|
+
url: Optional[str] = None,
|
|
262
|
+
token: Optional[str] = None,
|
|
263
|
+
org: Optional[str] = None,
|
|
264
|
+
require_org: bool = True,
|
|
265
|
+
) -> tuple:
|
|
266
|
+
"""Resolve InfluxDB configuration from parameters or environment variables.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
url: The URL of the InfluxDB server (optional, falls back to INFLUXDB_URL env var).
|
|
270
|
+
token: The authentication token (optional, falls back to INFLUXDB_TOKEN env var).
|
|
271
|
+
org: The organization name (optional, falls back to INFLUXDB_ORG env var).
|
|
272
|
+
require_org: Whether the organization is required (default True).
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
A tuple of (resolved_url, resolved_token, resolved_org).
|
|
276
|
+
|
|
277
|
+
Raises:
|
|
278
|
+
ValueError: If required parameters are not provided.
|
|
279
|
+
"""
|
|
280
|
+
resolved_url = url or INFLUXDB_URL
|
|
281
|
+
resolved_token = token or INFLUXDB_TOKEN
|
|
282
|
+
resolved_org = org or INFLUXDB_ORG
|
|
283
|
+
|
|
284
|
+
if not resolved_url:
|
|
285
|
+
raise ValueError(
|
|
286
|
+
'URL must be provided either as parameter or via INFLUXDB_URL environment variable'
|
|
287
|
+
)
|
|
288
|
+
if not resolved_token:
|
|
289
|
+
raise ValueError(
|
|
290
|
+
'Token must be provided either as parameter or via INFLUXDB_TOKEN environment variable'
|
|
291
|
+
)
|
|
292
|
+
if require_org and not resolved_org:
|
|
293
|
+
raise ValueError(
|
|
294
|
+
'Organization must be provided either as parameter or via INFLUXDB_ORG environment variable'
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
return resolved_url, resolved_token, resolved_org
|
|
298
|
+
|
|
299
|
+
|
|
245
300
|
def get_influxdb_client(url, token, org=None, timeout=10000, verify_ssl: bool = True):
|
|
246
301
|
"""Get an InfluxDB client.
|
|
247
302
|
|
|
@@ -1054,10 +1109,10 @@ async def create_db_parameter_group(
|
|
|
1054
1109
|
|
|
1055
1110
|
@mcp.tool(name='InfluxDBWritePoints', description='Write data points to InfluxDB endpoint.')
|
|
1056
1111
|
async def influxdb_write_points(
|
|
1057
|
-
url: str =
|
|
1058
|
-
token: str =
|
|
1059
|
-
bucket: str =
|
|
1060
|
-
org: str =
|
|
1112
|
+
url: Optional[str] = OPTIONAL_FIELD_URL,
|
|
1113
|
+
token: Optional[str] = OPTIONAL_FIELD_TOKEN,
|
|
1114
|
+
bucket: str = REQUIRED_FIELD_BUCKET_INFLUX,
|
|
1115
|
+
org: Optional[str] = OPTIONAL_FIELD_ORG,
|
|
1061
1116
|
points: List[Dict[str, Any]] = REQUIRED_FIELD_POINTS,
|
|
1062
1117
|
time_precision: str = OPTIONAL_FIELD_WRITE_PRECISION,
|
|
1063
1118
|
sync_mode: Optional[str] = OPTIONAL_FIELD_SYNC_MODE,
|
|
@@ -1084,10 +1139,12 @@ async def influxdb_write_points(
|
|
|
1084
1139
|
'InfluxDBWritePoints tool invocation not allowed when tool-write-mode is set to False'
|
|
1085
1140
|
)
|
|
1086
1141
|
|
|
1087
|
-
|
|
1088
|
-
client = get_influxdb_client(url, token, org, verify_ssl)
|
|
1142
|
+
resolved_url, resolved_token, resolved_org = resolve_influxdb_config(url, token, org)
|
|
1089
1143
|
|
|
1090
|
-
|
|
1144
|
+
try:
|
|
1145
|
+
client = get_influxdb_client(
|
|
1146
|
+
url=resolved_url, token=resolved_token, org=resolved_org, verify_ssl=verify_ssl
|
|
1147
|
+
)
|
|
1091
1148
|
if sync_mode and sync_mode.lower() == 'synchronous':
|
|
1092
1149
|
write_api = client.write_api(write_options=SYNCHRONOUS)
|
|
1093
1150
|
else:
|
|
@@ -1117,7 +1174,7 @@ async def influxdb_write_points(
|
|
|
1117
1174
|
# Write points
|
|
1118
1175
|
write_api.write(
|
|
1119
1176
|
bucket=bucket,
|
|
1120
|
-
org=
|
|
1177
|
+
org=resolved_org,
|
|
1121
1178
|
record=influx_points,
|
|
1122
1179
|
write_precision=getattr(WritePrecision, time_precision.upper()),
|
|
1123
1180
|
verify_ssl=verify_ssl,
|
|
@@ -1137,10 +1194,10 @@ async def influxdb_write_points(
|
|
|
1137
1194
|
|
|
1138
1195
|
@mcp.tool(name='InfluxDBWriteLP', description='Write data in Line Protocol format to InfluxDB.')
|
|
1139
1196
|
async def influxdb_write_line_protocol(
|
|
1140
|
-
url: str =
|
|
1141
|
-
token: str =
|
|
1142
|
-
bucket: str =
|
|
1143
|
-
org: str =
|
|
1197
|
+
url: Optional[str] = OPTIONAL_FIELD_URL,
|
|
1198
|
+
token: Optional[str] = OPTIONAL_FIELD_TOKEN,
|
|
1199
|
+
bucket: str = REQUIRED_FIELD_BUCKET_INFLUX,
|
|
1200
|
+
org: Optional[str] = OPTIONAL_FIELD_ORG,
|
|
1144
1201
|
data_line_protocol: str = REQUIRED_FIELD_DATA_LINE_PROTOCOL,
|
|
1145
1202
|
time_precision: str = OPTIONAL_FIELD_WRITE_PRECISION,
|
|
1146
1203
|
sync_mode: str = OPTIONAL_FIELD_SYNC_MODE,
|
|
@@ -1157,8 +1214,12 @@ async def influxdb_write_line_protocol(
|
|
|
1157
1214
|
'InfluxDBWriteLineProtocol tool invocation not allowed when tool-write-mode is set to False'
|
|
1158
1215
|
)
|
|
1159
1216
|
|
|
1217
|
+
resolved_url, resolved_token, resolved_org = resolve_influxdb_config(url, token, org)
|
|
1218
|
+
|
|
1160
1219
|
try:
|
|
1161
|
-
client = get_influxdb_client(
|
|
1220
|
+
client = get_influxdb_client(
|
|
1221
|
+
url=resolved_url, token=resolved_token, org=resolved_org, verify_ssl=verify_ssl
|
|
1222
|
+
)
|
|
1162
1223
|
|
|
1163
1224
|
# Set write mode
|
|
1164
1225
|
if sync_mode and sync_mode.lower() == 'synchronous':
|
|
@@ -1169,7 +1230,7 @@ async def influxdb_write_line_protocol(
|
|
|
1169
1230
|
# Write line protocol
|
|
1170
1231
|
write_api.write(
|
|
1171
1232
|
bucket=bucket,
|
|
1172
|
-
org=
|
|
1233
|
+
org=resolved_org,
|
|
1173
1234
|
record=data_line_protocol,
|
|
1174
1235
|
write_precision=getattr(WritePrecision, time_precision.upper()),
|
|
1175
1236
|
verify_ssl=verify_ssl,
|
|
@@ -1189,9 +1250,9 @@ async def influxdb_write_line_protocol(
|
|
|
1189
1250
|
|
|
1190
1251
|
@mcp.tool(name='InfluxDBQuery', description='Query data from InfluxDB using Flux query language.')
|
|
1191
1252
|
async def influxdb_query(
|
|
1192
|
-
url: str =
|
|
1193
|
-
token: str =
|
|
1194
|
-
org: str =
|
|
1253
|
+
url: Optional[str] = OPTIONAL_FIELD_URL,
|
|
1254
|
+
token: Optional[str] = OPTIONAL_FIELD_TOKEN,
|
|
1255
|
+
org: Optional[str] = OPTIONAL_FIELD_ORG,
|
|
1195
1256
|
query: str = REQUIRED_FIELD_QUERY,
|
|
1196
1257
|
verify_ssl: bool = OPTIONAL_FIELD_VERIFY_SSL,
|
|
1197
1258
|
) -> Dict[str, Any]:
|
|
@@ -1200,24 +1261,47 @@ async def influxdb_query(
|
|
|
1200
1261
|
Returns:
|
|
1201
1262
|
Query results in the specified format.
|
|
1202
1263
|
"""
|
|
1264
|
+
resolved_url, resolved_token, resolved_org = resolve_influxdb_config(url, token, org)
|
|
1265
|
+
|
|
1203
1266
|
try:
|
|
1204
|
-
client = get_influxdb_client(
|
|
1267
|
+
client = get_influxdb_client(
|
|
1268
|
+
url=resolved_url, token=resolved_token, org=resolved_org, verify_ssl=verify_ssl
|
|
1269
|
+
)
|
|
1205
1270
|
query_api = client.query_api()
|
|
1206
1271
|
|
|
1207
1272
|
# Return as JSON
|
|
1208
|
-
tables = query_api.query(org=
|
|
1273
|
+
tables = query_api.query(org=resolved_org, query=query)
|
|
1209
1274
|
|
|
1210
1275
|
# Process the tables into a more usable format
|
|
1276
|
+
# System keys that are not tags
|
|
1277
|
+
system_keys = {
|
|
1278
|
+
'result',
|
|
1279
|
+
'table',
|
|
1280
|
+
'_start',
|
|
1281
|
+
'_stop',
|
|
1282
|
+
'_time',
|
|
1283
|
+
'_value',
|
|
1284
|
+
'_field',
|
|
1285
|
+
'_measurement',
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1211
1288
|
result = []
|
|
1212
1289
|
for table in tables:
|
|
1213
1290
|
for record in table.records:
|
|
1291
|
+
# Extract tags by filtering out system keys
|
|
1292
|
+
tags = {
|
|
1293
|
+
k: v
|
|
1294
|
+
for k, v in record.values.items()
|
|
1295
|
+
if k not in system_keys and v is not None
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1214
1298
|
result.append(
|
|
1215
1299
|
{
|
|
1216
1300
|
'measurement': record.get_measurement(),
|
|
1217
1301
|
'field': record.get_field(),
|
|
1218
1302
|
'value': record.get_value(),
|
|
1219
1303
|
'time': record.get_time().isoformat() if record.get_time() else None,
|
|
1220
|
-
'tags':
|
|
1304
|
+
'tags': tags,
|
|
1221
1305
|
}
|
|
1222
1306
|
)
|
|
1223
1307
|
|
|
@@ -1229,6 +1313,203 @@ async def influxdb_query(
|
|
|
1229
1313
|
return {'status': 'error', 'message': str(e)}
|
|
1230
1314
|
|
|
1231
1315
|
|
|
1316
|
+
@mcp.tool(name='InfluxDBListBuckets', description='List all buckets in InfluxDB.')
|
|
1317
|
+
async def influxdb_list_buckets(
|
|
1318
|
+
url: Optional[str] = OPTIONAL_FIELD_URL,
|
|
1319
|
+
token: Optional[str] = OPTIONAL_FIELD_TOKEN,
|
|
1320
|
+
org: Optional[str] = OPTIONAL_FIELD_ORG,
|
|
1321
|
+
verify_ssl: bool = OPTIONAL_FIELD_VERIFY_SSL,
|
|
1322
|
+
) -> Dict[str, Any]:
|
|
1323
|
+
"""List all buckets in InfluxDB.
|
|
1324
|
+
|
|
1325
|
+
Returns:
|
|
1326
|
+
List of buckets with their details.
|
|
1327
|
+
"""
|
|
1328
|
+
resolved_url, resolved_token, resolved_org = resolve_influxdb_config(url, token, org)
|
|
1329
|
+
|
|
1330
|
+
try:
|
|
1331
|
+
client = get_influxdb_client(
|
|
1332
|
+
url=resolved_url, token=resolved_token, org=resolved_org, verify_ssl=verify_ssl
|
|
1333
|
+
)
|
|
1334
|
+
buckets_api = client.buckets_api()
|
|
1335
|
+
buckets = buckets_api.find_buckets().buckets
|
|
1336
|
+
|
|
1337
|
+
result = []
|
|
1338
|
+
for bucket in buckets:
|
|
1339
|
+
result.append(
|
|
1340
|
+
{
|
|
1341
|
+
'id': bucket.id,
|
|
1342
|
+
'name': bucket.name,
|
|
1343
|
+
'org_id': bucket.org_id,
|
|
1344
|
+
'retention_period': bucket.retention_rules[0].every_seconds
|
|
1345
|
+
if bucket.retention_rules
|
|
1346
|
+
else None,
|
|
1347
|
+
'created_at': bucket.created_at.isoformat() if bucket.created_at else None,
|
|
1348
|
+
'updated_at': bucket.updated_at.isoformat() if bucket.updated_at else None,
|
|
1349
|
+
}
|
|
1350
|
+
)
|
|
1351
|
+
|
|
1352
|
+
client.close()
|
|
1353
|
+
return {'status': 'success', 'buckets': result}
|
|
1354
|
+
|
|
1355
|
+
except Exception as e:
|
|
1356
|
+
logger.error(f'Error listing InfluxDB buckets: {str(e)}')
|
|
1357
|
+
return {'status': 'error', 'message': str(e)}
|
|
1358
|
+
|
|
1359
|
+
|
|
1360
|
+
@mcp.tool(name='InfluxDBCreateBucket', description='Create a new bucket in InfluxDB.')
|
|
1361
|
+
async def influxdb_create_bucket(
|
|
1362
|
+
bucket_name: str = Field(..., description='The name of the bucket to create.'),
|
|
1363
|
+
url: Optional[str] = OPTIONAL_FIELD_URL,
|
|
1364
|
+
token: Optional[str] = OPTIONAL_FIELD_TOKEN,
|
|
1365
|
+
org: Optional[str] = OPTIONAL_FIELD_ORG,
|
|
1366
|
+
retention_seconds: Optional[int] = Field(
|
|
1367
|
+
None, description='Retention period in seconds. 0 or None means infinite retention.'
|
|
1368
|
+
),
|
|
1369
|
+
description: Optional[str] = Field(None, description='Description of the bucket.'),
|
|
1370
|
+
verify_ssl: bool = OPTIONAL_FIELD_VERIFY_SSL,
|
|
1371
|
+
tool_write_mode: bool = OPTIONAL_FIELD_TOOL_WRITE_MODE,
|
|
1372
|
+
) -> Dict[str, Any]:
|
|
1373
|
+
"""Create a new bucket in InfluxDB.
|
|
1374
|
+
|
|
1375
|
+
Returns:
|
|
1376
|
+
Details of the created bucket.
|
|
1377
|
+
"""
|
|
1378
|
+
if not tool_write_mode:
|
|
1379
|
+
raise Exception(
|
|
1380
|
+
'InfluxDBCreateBucket tool invocation not allowed when tool-write-mode is set to False'
|
|
1381
|
+
)
|
|
1382
|
+
|
|
1383
|
+
resolved_url, resolved_token, resolved_org = resolve_influxdb_config(url, token, org)
|
|
1384
|
+
|
|
1385
|
+
try:
|
|
1386
|
+
client = get_influxdb_client(
|
|
1387
|
+
url=resolved_url, token=resolved_token, org=resolved_org, verify_ssl=verify_ssl
|
|
1388
|
+
)
|
|
1389
|
+
buckets_api = client.buckets_api()
|
|
1390
|
+
|
|
1391
|
+
# Get org ID from org name
|
|
1392
|
+
orgs_api = client.organizations_api()
|
|
1393
|
+
orgs = orgs_api.find_organizations(org=resolved_org)
|
|
1394
|
+
if not orgs:
|
|
1395
|
+
raise ValueError(f'Organization "{resolved_org}" not found')
|
|
1396
|
+
org_id = orgs[0].id
|
|
1397
|
+
|
|
1398
|
+
retention_rules = []
|
|
1399
|
+
if retention_seconds and retention_seconds > 0:
|
|
1400
|
+
retention_rules.append(
|
|
1401
|
+
BucketRetentionRules(type='expire', every_seconds=retention_seconds)
|
|
1402
|
+
)
|
|
1403
|
+
|
|
1404
|
+
bucket = buckets_api.create_bucket(
|
|
1405
|
+
bucket_name=bucket_name,
|
|
1406
|
+
org_id=org_id,
|
|
1407
|
+
retention_rules=retention_rules,
|
|
1408
|
+
description=description,
|
|
1409
|
+
)
|
|
1410
|
+
|
|
1411
|
+
client.close()
|
|
1412
|
+
return {
|
|
1413
|
+
'status': 'success',
|
|
1414
|
+
'bucket': {
|
|
1415
|
+
'id': bucket.id,
|
|
1416
|
+
'name': bucket.name,
|
|
1417
|
+
'org_id': bucket.org_id,
|
|
1418
|
+
'retention_period': bucket.retention_rules[0].every_seconds
|
|
1419
|
+
if bucket.retention_rules
|
|
1420
|
+
else None,
|
|
1421
|
+
'created_at': bucket.created_at.isoformat() if bucket.created_at else None,
|
|
1422
|
+
},
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
except Exception as e:
|
|
1426
|
+
logger.error(f'Error creating InfluxDB bucket: {str(e)}')
|
|
1427
|
+
return {'status': 'error', 'message': str(e)}
|
|
1428
|
+
|
|
1429
|
+
|
|
1430
|
+
@mcp.tool(name='InfluxDBListOrgs', description='List all organizations in InfluxDB.')
|
|
1431
|
+
async def influxdb_list_orgs(
|
|
1432
|
+
url: Optional[str] = OPTIONAL_FIELD_URL,
|
|
1433
|
+
token: Optional[str] = OPTIONAL_FIELD_TOKEN,
|
|
1434
|
+
verify_ssl: bool = OPTIONAL_FIELD_VERIFY_SSL,
|
|
1435
|
+
) -> Dict[str, Any]:
|
|
1436
|
+
"""List all organizations in InfluxDB.
|
|
1437
|
+
|
|
1438
|
+
Returns:
|
|
1439
|
+
List of organizations with their details.
|
|
1440
|
+
"""
|
|
1441
|
+
resolved_url, resolved_token, _ = resolve_influxdb_config(
|
|
1442
|
+
url, token, org=None, require_org=False
|
|
1443
|
+
)
|
|
1444
|
+
|
|
1445
|
+
try:
|
|
1446
|
+
client = get_influxdb_client(url=resolved_url, token=resolved_token, verify_ssl=verify_ssl)
|
|
1447
|
+
orgs_api = client.organizations_api()
|
|
1448
|
+
orgs = orgs_api.find_organizations()
|
|
1449
|
+
|
|
1450
|
+
result = []
|
|
1451
|
+
for org in orgs:
|
|
1452
|
+
result.append(
|
|
1453
|
+
{
|
|
1454
|
+
'id': org.id,
|
|
1455
|
+
'name': org.name,
|
|
1456
|
+
'description': org.description,
|
|
1457
|
+
'created_at': org.created_at.isoformat() if org.created_at else None,
|
|
1458
|
+
'updated_at': org.updated_at.isoformat() if org.updated_at else None,
|
|
1459
|
+
}
|
|
1460
|
+
)
|
|
1461
|
+
|
|
1462
|
+
client.close()
|
|
1463
|
+
return {'status': 'success', 'organizations': result}
|
|
1464
|
+
|
|
1465
|
+
except Exception as e:
|
|
1466
|
+
logger.error(f'Error listing InfluxDB organizations: {str(e)}')
|
|
1467
|
+
return {'status': 'error', 'message': str(e)}
|
|
1468
|
+
|
|
1469
|
+
|
|
1470
|
+
@mcp.tool(name='InfluxDBCreateOrg', description='Create a new organization in InfluxDB.')
|
|
1471
|
+
async def influxdb_create_org(
|
|
1472
|
+
org_name: str = Field(..., description='The name of the organization to create.'),
|
|
1473
|
+
url: Optional[str] = OPTIONAL_FIELD_URL,
|
|
1474
|
+
token: Optional[str] = OPTIONAL_FIELD_TOKEN,
|
|
1475
|
+
verify_ssl: bool = OPTIONAL_FIELD_VERIFY_SSL,
|
|
1476
|
+
tool_write_mode: bool = OPTIONAL_FIELD_TOOL_WRITE_MODE,
|
|
1477
|
+
) -> Dict[str, Any]:
|
|
1478
|
+
"""Create a new organization in InfluxDB.
|
|
1479
|
+
|
|
1480
|
+
Returns:
|
|
1481
|
+
Details of the created organization.
|
|
1482
|
+
"""
|
|
1483
|
+
if not tool_write_mode:
|
|
1484
|
+
raise Exception(
|
|
1485
|
+
'InfluxDBCreateOrg tool invocation not allowed when tool-write-mode is set to False'
|
|
1486
|
+
)
|
|
1487
|
+
|
|
1488
|
+
resolved_url, resolved_token, _ = resolve_influxdb_config(
|
|
1489
|
+
url, token, org=None, require_org=False
|
|
1490
|
+
)
|
|
1491
|
+
|
|
1492
|
+
try:
|
|
1493
|
+
client = get_influxdb_client(url=resolved_url, token=resolved_token, verify_ssl=verify_ssl)
|
|
1494
|
+
orgs_api = client.organizations_api()
|
|
1495
|
+
|
|
1496
|
+
org = orgs_api.create_organization(name=org_name)
|
|
1497
|
+
|
|
1498
|
+
client.close()
|
|
1499
|
+
return {
|
|
1500
|
+
'status': 'success',
|
|
1501
|
+
'organization': {
|
|
1502
|
+
'id': org.id,
|
|
1503
|
+
'name': org.name,
|
|
1504
|
+
'created_at': org.created_at.isoformat() if org.created_at else None,
|
|
1505
|
+
},
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
except Exception as e:
|
|
1509
|
+
logger.error(f'Error creating InfluxDB organization: {str(e)}')
|
|
1510
|
+
return {'status': 'error', 'message': str(e)}
|
|
1511
|
+
|
|
1512
|
+
|
|
1232
1513
|
def main():
|
|
1233
1514
|
"""Main entry point for the MCP server application."""
|
|
1234
1515
|
logger.info('Starting Timestream for InfluxDB MCP Server')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: awslabs.timestream-for-influxdb-mcp-server
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.12
|
|
4
4
|
Summary: An AWS Labs Model Context Protocol (MCP) server for Timestream for InfluxDB
|
|
5
5
|
Project-URL: homepage, https://awslabs.github.io/mcp/
|
|
6
6
|
Project-URL: docs, https://awslabs.github.io/mcp/servers/timestream-for-influxdb-mcp-server/
|
|
@@ -38,7 +38,8 @@ An AWS Labs Model Context Protocol (MCP) server for Timestream for InfluxDB. Thi
|
|
|
38
38
|
- Create, update, list, describe, and delete Timestream for InfluxDB database clusters
|
|
39
39
|
- Manage DB parameter groups
|
|
40
40
|
- Tag management for Timestream for InfluxDB resources
|
|
41
|
-
-
|
|
41
|
+
- Manage InfluxDB 2 buckets and organizations
|
|
42
|
+
- Write and query data using InfluxDB 2 APIs
|
|
42
43
|
|
|
43
44
|
|
|
44
45
|
## Pre-requisites
|
|
@@ -66,6 +67,9 @@ You can modify the settings of your MCP client to run your local server (e.g. fo
|
|
|
66
67
|
"env": {
|
|
67
68
|
"AWS_PROFILE": "your-aws-profile",
|
|
68
69
|
"AWS_REGION": "us-east-1",
|
|
70
|
+
"INFLUXDB_URL": "https://your-influxdb-endpoint:8086",
|
|
71
|
+
"INFLUXDB_TOKEN": "your-influxdb-token",
|
|
72
|
+
"INFLUXDB_ORG": "your-influxdb-org",
|
|
69
73
|
"FASTMCP_LOG_LEVEL": "ERROR"
|
|
70
74
|
},
|
|
71
75
|
"disabled": false,
|
|
@@ -94,9 +98,12 @@ For Windows users, the MCP server configuration format is slightly different:
|
|
|
94
98
|
"awslabs.timestream-for-influxdb-mcp-server.exe"
|
|
95
99
|
],
|
|
96
100
|
"env": {
|
|
97
|
-
"FASTMCP_LOG_LEVEL": "ERROR",
|
|
98
101
|
"AWS_PROFILE": "your-aws-profile",
|
|
99
|
-
"AWS_REGION": "us-east-1"
|
|
102
|
+
"AWS_REGION": "us-east-1",
|
|
103
|
+
"INFLUXDB_URL": "https://your-influxdb-endpoint:8086",
|
|
104
|
+
"INFLUXDB_TOKEN": "your-influxdb-token",
|
|
105
|
+
"INFLUXDB_ORG": "your-influxdb-org",
|
|
106
|
+
"FASTMCP_LOG_LEVEL": "ERROR"
|
|
100
107
|
}
|
|
101
108
|
}
|
|
102
109
|
}
|
|
@@ -146,3 +153,11 @@ The Timestream for InfluxDB MCP server provides the following tools:
|
|
|
146
153
|
|
|
147
154
|
##### Query API
|
|
148
155
|
- `InfluxDBQuery`: Query data from InfluxDB using Flux query language
|
|
156
|
+
|
|
157
|
+
##### Bucket Management
|
|
158
|
+
- `InfluxDBListBuckets`: List all buckets in InfluxDB
|
|
159
|
+
- `InfluxDBCreateBucket`: Create a new bucket in InfluxDB
|
|
160
|
+
|
|
161
|
+
##### Organization Management
|
|
162
|
+
- `InfluxDBListOrgs`: List all organizations in InfluxDB
|
|
163
|
+
- `InfluxDBCreateOrg`: Create a new organization in InfluxDB
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
awslabs/__init__.py,sha256=S-EDeDHGZzllMFhAeuJx_47fv85t2OUMOcsOisD5d_8,796
|
|
2
|
+
awslabs/timestream_for_influxdb_mcp_server/__init__.py,sha256=xahTyEU632c290drFz2I-gBqmF6VJ_OvgyHyoBdHXqo,690
|
|
3
|
+
awslabs/timestream_for_influxdb_mcp_server/server.py,sha256=-sNagSozw734-k_Sl6lbVEFi9ZuyzQmbkxtgZ3IHKTA,54325
|
|
4
|
+
awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info/METADATA,sha256=GHPTJTqhE5D7jhoohPkRXcqBlIA3QbKJYDT2UFrHpyg,7775
|
|
5
|
+
awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
6
|
+
awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info/entry_points.txt,sha256=it4t34A91rT2btYRldC7Gg0iBXbFwK-8Uq8ug7F3GJ4,118
|
|
7
|
+
awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info/licenses/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
|
|
8
|
+
awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info/licenses/NOTICE,sha256=n2OVRXbV4EeTgFingxNqDwTL4yY1-mVTyT5QN8BeTGU,110
|
|
9
|
+
awslabs_timestream_for_influxdb_mcp_server-0.0.12.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
awslabs/__init__.py,sha256=S-EDeDHGZzllMFhAeuJx_47fv85t2OUMOcsOisD5d_8,796
|
|
2
|
-
awslabs/timestream_for_influxdb_mcp_server/__init__.py,sha256=zIpXFDbkw_6_cyXI_2pk8l5tLQsDF9TH5b6EvVL0DCg,690
|
|
3
|
-
awslabs/timestream_for_influxdb_mcp_server/server.py,sha256=V8IU0mhFj9ozZZ64ozXhYhPadskx3oRDdbI-zthYVTo,44306
|
|
4
|
-
awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info/METADATA,sha256=HiArTFwp6PwoDlDEXD6P5fJhW3z2mfEhs-MexK1zOuU,7129
|
|
5
|
-
awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
6
|
-
awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info/entry_points.txt,sha256=it4t34A91rT2btYRldC7Gg0iBXbFwK-8Uq8ug7F3GJ4,118
|
|
7
|
-
awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info/licenses/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
|
|
8
|
-
awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info/licenses/NOTICE,sha256=n2OVRXbV4EeTgFingxNqDwTL4yY1-mVTyT5QN8BeTGU,110
|
|
9
|
-
awslabs_timestream_for_influxdb_mcp_server-0.0.11.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|