marqeta-diva-mcp 0.2.0__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.
- marqeta_diva_mcp/__init__.py +3 -0
- marqeta_diva_mcp/__main__.py +6 -0
- marqeta_diva_mcp/client.py +471 -0
- marqeta_diva_mcp/embeddings.py +131 -0
- marqeta_diva_mcp/local_storage.py +348 -0
- marqeta_diva_mcp/rag_tools.py +366 -0
- marqeta_diva_mcp/server.py +940 -0
- marqeta_diva_mcp/vector_store.py +274 -0
- marqeta_diva_mcp-0.2.0.dist-info/METADATA +515 -0
- marqeta_diva_mcp-0.2.0.dist-info/RECORD +13 -0
- marqeta_diva_mcp-0.2.0.dist-info/WHEEL +4 -0
- marqeta_diva_mcp-0.2.0.dist-info/entry_points.txt +2 -0
- marqeta_diva_mcp-0.2.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,940 @@
|
|
|
1
|
+
"""Marqeta DiVA API MCP Server."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
from typing import Any, Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
from dotenv import load_dotenv
|
|
9
|
+
from mcp.server import Server
|
|
10
|
+
from mcp.types import Tool, TextContent
|
|
11
|
+
import mcp.server.stdio
|
|
12
|
+
|
|
13
|
+
from .client import DiVAClient, DiVAAPIError
|
|
14
|
+
|
|
15
|
+
# Load environment variables
|
|
16
|
+
load_dotenv()
|
|
17
|
+
|
|
18
|
+
# Version identifier to verify server restarts
|
|
19
|
+
SERVER_VERSION = "0.2.0"
|
|
20
|
+
|
|
21
|
+
# Check if local storage features are enabled
|
|
22
|
+
def is_local_storage_enabled() -> bool:
|
|
23
|
+
"""Check if local storage and RAG features are enabled."""
|
|
24
|
+
enabled = os.getenv("ENABLE_LOCAL_STORAGE", "false").lower() in ("true", "1", "yes")
|
|
25
|
+
return enabled
|
|
26
|
+
|
|
27
|
+
# Conditionally import RAG tools
|
|
28
|
+
RAG_AVAILABLE = False
|
|
29
|
+
rag_tools = None
|
|
30
|
+
|
|
31
|
+
if is_local_storage_enabled():
|
|
32
|
+
try:
|
|
33
|
+
from . import rag_tools
|
|
34
|
+
RAG_AVAILABLE = True
|
|
35
|
+
print("[MCP Server] Local storage and RAG features ENABLED", file=sys.stderr)
|
|
36
|
+
except ImportError as e:
|
|
37
|
+
print(f"[MCP Server] WARNING: ENABLE_LOCAL_STORAGE=true but RAG dependencies not installed.", file=sys.stderr)
|
|
38
|
+
print(f"[MCP Server] Install with: pip install marqeta-diva-mcp[rag]", file=sys.stderr)
|
|
39
|
+
print(f"[MCP Server] Error: {e}", file=sys.stderr)
|
|
40
|
+
RAG_AVAILABLE = False
|
|
41
|
+
else:
|
|
42
|
+
print("[MCP Server] Local storage and RAG features DISABLED (set ENABLE_LOCAL_STORAGE=true to enable)", file=sys.stderr)
|
|
43
|
+
|
|
44
|
+
# Initialize MCP server
|
|
45
|
+
app = Server("marqeta-diva-mcp")
|
|
46
|
+
|
|
47
|
+
# Log version on startup
|
|
48
|
+
print(f"[MCP Server] Starting version {SERVER_VERSION}", file=sys.stderr)
|
|
49
|
+
|
|
50
|
+
# Global client instance
|
|
51
|
+
_client: Optional[DiVAClient] = None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def get_client() -> DiVAClient:
|
|
55
|
+
"""Get or create the DiVA API client."""
|
|
56
|
+
global _client
|
|
57
|
+
if _client is None:
|
|
58
|
+
app_token = os.getenv("MARQETA_APP_TOKEN")
|
|
59
|
+
access_token = os.getenv("MARQETA_ACCESS_TOKEN")
|
|
60
|
+
program = os.getenv("MARQETA_PROGRAM")
|
|
61
|
+
|
|
62
|
+
if not app_token or not access_token or not program:
|
|
63
|
+
raise ValueError(
|
|
64
|
+
"Missing required environment variables: "
|
|
65
|
+
"MARQETA_APP_TOKEN, MARQETA_ACCESS_TOKEN, MARQETA_PROGRAM"
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
_client = DiVAClient(app_token, access_token, program)
|
|
69
|
+
return _client
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def format_error(error: Exception) -> str:
|
|
73
|
+
"""Format an error message for display."""
|
|
74
|
+
if isinstance(error, DiVAAPIError):
|
|
75
|
+
msg = f"Error {error.status_code}: {error.message}"
|
|
76
|
+
if error.response:
|
|
77
|
+
msg += f"\nDetails: {error.response}"
|
|
78
|
+
return msg
|
|
79
|
+
return str(error)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def format_response(data: Dict[str, Any]) -> str:
|
|
83
|
+
"""Format API response for display."""
|
|
84
|
+
import json
|
|
85
|
+
return json.dumps(data, indent=2)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
# Tool definitions
|
|
89
|
+
# Base tools available to all users
|
|
90
|
+
BASE_TOOLS = [
|
|
91
|
+
# Transaction Tools
|
|
92
|
+
Tool(
|
|
93
|
+
name="get_authorizations",
|
|
94
|
+
description=(
|
|
95
|
+
"Get authorization transaction data. Includes authorization amounts, counts, "
|
|
96
|
+
"acting users/cards, and merchant information. Supports detail, day, week, and month aggregation. "
|
|
97
|
+
"Note: DiVA API limits results to 10,000 records per query. Use narrower date ranges or more specific filters for larger datasets."
|
|
98
|
+
),
|
|
99
|
+
inputSchema={
|
|
100
|
+
"type": "object",
|
|
101
|
+
"properties": {
|
|
102
|
+
"aggregation": {
|
|
103
|
+
"type": "string",
|
|
104
|
+
"enum": ["detail", "day", "week", "month"],
|
|
105
|
+
"default": "detail",
|
|
106
|
+
"description": "Aggregation level for the data",
|
|
107
|
+
},
|
|
108
|
+
"fields": {
|
|
109
|
+
"type": "array",
|
|
110
|
+
"items": {"type": "string"},
|
|
111
|
+
"description": "Specific fields to return (comma-separated)",
|
|
112
|
+
},
|
|
113
|
+
"filters": {
|
|
114
|
+
"type": "object",
|
|
115
|
+
"description": (
|
|
116
|
+
"Filters on data fields. For date filtering, use the actual date field name with operators. "
|
|
117
|
+
"Example: {'transaction_timestamp': '>=2023-10-20'} or {'transaction_timestamp': '2023-10-01..2023-10-31'}. "
|
|
118
|
+
"Do NOT include query parameters like 'count' or 'sort_by' in filters."
|
|
119
|
+
),
|
|
120
|
+
},
|
|
121
|
+
"sort_by": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Field to sort by (prefix with - for descending)",
|
|
124
|
+
},
|
|
125
|
+
"count": {
|
|
126
|
+
"type": "integer",
|
|
127
|
+
"description": "Maximum number of records to return (up to 10,000, default 10,000)",
|
|
128
|
+
},
|
|
129
|
+
"program": {
|
|
130
|
+
"type": "string",
|
|
131
|
+
"description": "Override default program name",
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
),
|
|
136
|
+
Tool(
|
|
137
|
+
name="get_settlements",
|
|
138
|
+
description=(
|
|
139
|
+
"Get settlement transaction data. Includes transaction status, post dates, "
|
|
140
|
+
"purchase amounts, and network information. Supports detail, day, week, and month aggregation. "
|
|
141
|
+
"Note: DiVA API limits results to 10,000 records per query. Use narrower date ranges or more specific filters for larger datasets."
|
|
142
|
+
),
|
|
143
|
+
inputSchema={
|
|
144
|
+
"type": "object",
|
|
145
|
+
"properties": {
|
|
146
|
+
"aggregation": {
|
|
147
|
+
"type": "string",
|
|
148
|
+
"enum": ["detail", "day", "week", "month"],
|
|
149
|
+
"default": "detail",
|
|
150
|
+
"description": "Aggregation level for the data",
|
|
151
|
+
},
|
|
152
|
+
"fields": {
|
|
153
|
+
"type": "array",
|
|
154
|
+
"items": {"type": "string"},
|
|
155
|
+
"description": "Specific fields to return",
|
|
156
|
+
},
|
|
157
|
+
"filters": {
|
|
158
|
+
"type": "object",
|
|
159
|
+
"description": (
|
|
160
|
+
"Filters on data fields. For date filtering, use actual date field names with operators. "
|
|
161
|
+
"Example: {'transaction_timestamp': '>=2023-10-20'}. Do NOT include query parameters like 'count' here."
|
|
162
|
+
),
|
|
163
|
+
},
|
|
164
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
165
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
166
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
),
|
|
170
|
+
Tool(
|
|
171
|
+
name="get_clearings",
|
|
172
|
+
description=(
|
|
173
|
+
"Get clearing/reconciliation data. Provides accounting-level line items for "
|
|
174
|
+
"the transaction lifecycle. Ideal for reconciliation. Supports detail, day, week, and month aggregation. "
|
|
175
|
+
"Note: DiVA API limits results to 10,000 records per query. Use narrower date ranges or more specific filters for larger datasets."
|
|
176
|
+
),
|
|
177
|
+
inputSchema={
|
|
178
|
+
"type": "object",
|
|
179
|
+
"properties": {
|
|
180
|
+
"aggregation": {
|
|
181
|
+
"type": "string",
|
|
182
|
+
"enum": ["detail", "day", "week", "month"],
|
|
183
|
+
"default": "detail",
|
|
184
|
+
"description": "Aggregation level for the data",
|
|
185
|
+
},
|
|
186
|
+
"fields": {
|
|
187
|
+
"type": "array",
|
|
188
|
+
"items": {"type": "string"},
|
|
189
|
+
"description": "Specific fields to return",
|
|
190
|
+
},
|
|
191
|
+
"filters": {
|
|
192
|
+
"type": "object",
|
|
193
|
+
"description": "Filters on data fields. For date filtering, use actual date field names with operators (e.g., {'post_date': '>=2023-10-20'})"
|
|
194
|
+
},
|
|
195
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
196
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
197
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
),
|
|
201
|
+
Tool(
|
|
202
|
+
name="get_declines",
|
|
203
|
+
description=(
|
|
204
|
+
"Get declined transaction data. Includes transaction tokens, decline reasons, "
|
|
205
|
+
"merchant information, and amounts. Supports detail, day, week, and month aggregation. "
|
|
206
|
+
"Note: DiVA API limits results to 10,000 records per query. Use narrower date ranges or more specific filters for larger datasets."
|
|
207
|
+
),
|
|
208
|
+
inputSchema={
|
|
209
|
+
"type": "object",
|
|
210
|
+
"properties": {
|
|
211
|
+
"aggregation": {
|
|
212
|
+
"type": "string",
|
|
213
|
+
"enum": ["detail", "day", "week", "month"],
|
|
214
|
+
"default": "detail",
|
|
215
|
+
"description": "Aggregation level for the data",
|
|
216
|
+
},
|
|
217
|
+
"fields": {
|
|
218
|
+
"type": "array",
|
|
219
|
+
"items": {"type": "string"},
|
|
220
|
+
"description": "Specific fields to return",
|
|
221
|
+
},
|
|
222
|
+
"filters": {
|
|
223
|
+
"type": "object",
|
|
224
|
+
"description": "Filters on data fields. For date filtering, use actual date field names with operators (e.g., {'post_date': '>=2023-10-20'})"
|
|
225
|
+
},
|
|
226
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
227
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
228
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
),
|
|
232
|
+
Tool(
|
|
233
|
+
name="get_loads",
|
|
234
|
+
description=(
|
|
235
|
+
"Get load transaction data. Includes load amounts and transaction details. "
|
|
236
|
+
"Note: DiVA API limits results to 10,000 records per query. Use narrower date ranges or more specific filters for larger datasets."
|
|
237
|
+
),
|
|
238
|
+
inputSchema={
|
|
239
|
+
"type": "object",
|
|
240
|
+
"properties": {
|
|
241
|
+
"aggregation": {
|
|
242
|
+
"type": "string",
|
|
243
|
+
"enum": ["detail", "day", "week", "month"],
|
|
244
|
+
"default": "detail",
|
|
245
|
+
"description": "Aggregation level for the data",
|
|
246
|
+
},
|
|
247
|
+
"fields": {
|
|
248
|
+
"type": "array",
|
|
249
|
+
"items": {"type": "string"},
|
|
250
|
+
"description": "Specific fields to return",
|
|
251
|
+
},
|
|
252
|
+
"filters": {
|
|
253
|
+
"type": "object",
|
|
254
|
+
"description": "Filters on data fields. For date filtering, use actual date field names with operators (e.g., {'post_date': '>=2023-10-20'})"
|
|
255
|
+
},
|
|
256
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
257
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
258
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
259
|
+
},
|
|
260
|
+
},
|
|
261
|
+
),
|
|
262
|
+
# Financial Tools
|
|
263
|
+
Tool(
|
|
264
|
+
name="get_program_balances",
|
|
265
|
+
description=(
|
|
266
|
+
"Get program-level balance data. Includes beginning/ending bank balances, "
|
|
267
|
+
"amounts to send/receive. Day-level aggregation only."
|
|
268
|
+
),
|
|
269
|
+
inputSchema={
|
|
270
|
+
"type": "object",
|
|
271
|
+
"properties": {
|
|
272
|
+
"fields": {
|
|
273
|
+
"type": "array",
|
|
274
|
+
"items": {"type": "string"},
|
|
275
|
+
"description": "Specific fields to return",
|
|
276
|
+
},
|
|
277
|
+
"filters": {
|
|
278
|
+
"type": "object",
|
|
279
|
+
"description": "Filters on data fields. For date filtering, use actual date field names with operators (e.g., {'post_date': '>=2023-10-20'})"
|
|
280
|
+
},
|
|
281
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
282
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
283
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
),
|
|
287
|
+
Tool(
|
|
288
|
+
name="get_program_balances_settlement",
|
|
289
|
+
description=(
|
|
290
|
+
"Get settlement-based program balance data. Includes settlement balance information "
|
|
291
|
+
"and fund transfers. Day-level aggregation only."
|
|
292
|
+
),
|
|
293
|
+
inputSchema={
|
|
294
|
+
"type": "object",
|
|
295
|
+
"properties": {
|
|
296
|
+
"fields": {
|
|
297
|
+
"type": "array",
|
|
298
|
+
"items": {"type": "string"},
|
|
299
|
+
"description": "Specific fields to return",
|
|
300
|
+
},
|
|
301
|
+
"filters": {
|
|
302
|
+
"type": "object",
|
|
303
|
+
"description": "Filters on data fields. For date filtering, use actual date field names with operators (e.g., {'post_date': '>=2023-10-20'})"
|
|
304
|
+
},
|
|
305
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
306
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
307
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
),
|
|
311
|
+
Tool(
|
|
312
|
+
name="get_activity_balances",
|
|
313
|
+
description=(
|
|
314
|
+
"Get cardholder-level balance data. Includes individual cardholder balances, "
|
|
315
|
+
"expandable by network. Day-level aggregation only."
|
|
316
|
+
),
|
|
317
|
+
inputSchema={
|
|
318
|
+
"type": "object",
|
|
319
|
+
"properties": {
|
|
320
|
+
"fields": {
|
|
321
|
+
"type": "array",
|
|
322
|
+
"items": {"type": "string"},
|
|
323
|
+
"description": "Specific fields to return",
|
|
324
|
+
},
|
|
325
|
+
"filters": {
|
|
326
|
+
"type": "object",
|
|
327
|
+
"description": "Filters on data fields. For date filtering, use actual date field names with operators (e.g., {'post_date': '>=2023-10-20'})"
|
|
328
|
+
},
|
|
329
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
330
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
331
|
+
"expand": {
|
|
332
|
+
"type": "string",
|
|
333
|
+
"description": "Field to expand for more detail (e.g., network data)",
|
|
334
|
+
},
|
|
335
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
),
|
|
339
|
+
# Card & User Tools
|
|
340
|
+
Tool(
|
|
341
|
+
name="get_cards",
|
|
342
|
+
description=(
|
|
343
|
+
"Get card detail data. Includes user tokens, card state, active status, and UAI. "
|
|
344
|
+
"Detail-level only. Supports filtering by user, state, etc. "
|
|
345
|
+
"Note: DiVA API limits results to 10,000 records per query. Use narrower date ranges or more specific filters for larger datasets."
|
|
346
|
+
),
|
|
347
|
+
inputSchema={
|
|
348
|
+
"type": "object",
|
|
349
|
+
"properties": {
|
|
350
|
+
"fields": {
|
|
351
|
+
"type": "array",
|
|
352
|
+
"items": {"type": "string"},
|
|
353
|
+
"description": "Specific fields to return",
|
|
354
|
+
},
|
|
355
|
+
"filters": {
|
|
356
|
+
"type": "object",
|
|
357
|
+
"description": "Filters (e.g., {'state': 'ACTIVE', 'user_token': 'abc123'})",
|
|
358
|
+
},
|
|
359
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
360
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
361
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
362
|
+
},
|
|
363
|
+
},
|
|
364
|
+
),
|
|
365
|
+
Tool(
|
|
366
|
+
name="get_users",
|
|
367
|
+
description=(
|
|
368
|
+
"Get user detail data. Includes user tokens, UAI, and number of physical/virtual cards. "
|
|
369
|
+
"Detail-level only. Note: DiVA API limits results to 10,000 records per query. Use more specific filters for larger datasets."
|
|
370
|
+
),
|
|
371
|
+
inputSchema={
|
|
372
|
+
"type": "object",
|
|
373
|
+
"properties": {
|
|
374
|
+
"fields": {
|
|
375
|
+
"type": "array",
|
|
376
|
+
"items": {"type": "string"},
|
|
377
|
+
"description": "Specific fields to return",
|
|
378
|
+
},
|
|
379
|
+
"filters": {
|
|
380
|
+
"type": "object",
|
|
381
|
+
"description": "Filters (e.g., {'user_token': 'abc123'})",
|
|
382
|
+
},
|
|
383
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
384
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
385
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
),
|
|
389
|
+
# Chargeback Tools
|
|
390
|
+
Tool(
|
|
391
|
+
name="get_chargebacks_status",
|
|
392
|
+
description=(
|
|
393
|
+
"Get chargeback status data. Includes chargeback state, tokens, and "
|
|
394
|
+
"provisional credit status."
|
|
395
|
+
),
|
|
396
|
+
inputSchema={
|
|
397
|
+
"type": "object",
|
|
398
|
+
"properties": {
|
|
399
|
+
"fields": {
|
|
400
|
+
"type": "array",
|
|
401
|
+
"items": {"type": "string"},
|
|
402
|
+
"description": "Specific fields to return",
|
|
403
|
+
},
|
|
404
|
+
"filters": {
|
|
405
|
+
"type": "object",
|
|
406
|
+
"description": "Filters on data fields. For date filtering, use actual date field names with operators (e.g., {'post_date': '>=2023-10-20'})"
|
|
407
|
+
},
|
|
408
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
409
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
410
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
),
|
|
414
|
+
Tool(
|
|
415
|
+
name="get_chargebacks_detail",
|
|
416
|
+
description=(
|
|
417
|
+
"Get detailed chargeback information. Includes transaction dates/types and "
|
|
418
|
+
"comprehensive chargeback details."
|
|
419
|
+
),
|
|
420
|
+
inputSchema={
|
|
421
|
+
"type": "object",
|
|
422
|
+
"properties": {
|
|
423
|
+
"fields": {
|
|
424
|
+
"type": "array",
|
|
425
|
+
"items": {"type": "string"},
|
|
426
|
+
"description": "Specific fields to return",
|
|
427
|
+
},
|
|
428
|
+
"filters": {
|
|
429
|
+
"type": "object",
|
|
430
|
+
"description": "Filters on data fields. For date filtering, use actual date field names with operators (e.g., {'post_date': '>=2023-10-20'})"
|
|
431
|
+
},
|
|
432
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
433
|
+
"count": {"type": "integer", "description": "Maximum records to return (up to 10,000, default 10,000)"},
|
|
434
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
435
|
+
},
|
|
436
|
+
},
|
|
437
|
+
),
|
|
438
|
+
# Metadata Tools
|
|
439
|
+
Tool(
|
|
440
|
+
name="list_available_views",
|
|
441
|
+
description=(
|
|
442
|
+
"Get a list of all available DiVA API view endpoints with metadata. "
|
|
443
|
+
"Useful for discovering available data sources."
|
|
444
|
+
),
|
|
445
|
+
inputSchema={"type": "object", "properties": {}},
|
|
446
|
+
),
|
|
447
|
+
Tool(
|
|
448
|
+
name="get_view_schema",
|
|
449
|
+
description=(
|
|
450
|
+
"Get the schema definition for any view endpoint. Returns field names, "
|
|
451
|
+
"data types, and descriptions."
|
|
452
|
+
),
|
|
453
|
+
inputSchema={
|
|
454
|
+
"type": "object",
|
|
455
|
+
"required": ["view_name"],
|
|
456
|
+
"properties": {
|
|
457
|
+
"view_name": {
|
|
458
|
+
"type": "string",
|
|
459
|
+
"description": "Name of the view (e.g., 'authorizations', 'settlements', 'cards')",
|
|
460
|
+
},
|
|
461
|
+
"aggregation": {
|
|
462
|
+
"type": "string",
|
|
463
|
+
"enum": ["detail", "day", "week", "month"],
|
|
464
|
+
"default": "detail",
|
|
465
|
+
"description": "Aggregation level (if applicable)",
|
|
466
|
+
},
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
),
|
|
470
|
+
# Export Tools
|
|
471
|
+
Tool(
|
|
472
|
+
name="export_view_to_file",
|
|
473
|
+
description=(
|
|
474
|
+
"Export datasets to a file (JSON or CSV). Note: DiVA API limits results to 10,000 records per query. "
|
|
475
|
+
"To get more data, use narrower date ranges or more specific filters and call multiple times. "
|
|
476
|
+
"Supports all view types: authorizations, settlements, clearings, declines, loads, cards, users, etc."
|
|
477
|
+
),
|
|
478
|
+
inputSchema={
|
|
479
|
+
"type": "object",
|
|
480
|
+
"required": ["view_name", "output_path"],
|
|
481
|
+
"properties": {
|
|
482
|
+
"view_name": {
|
|
483
|
+
"type": "string",
|
|
484
|
+
"description": "Name of the view (e.g., 'authorizations', 'settlements', 'cards')",
|
|
485
|
+
},
|
|
486
|
+
"aggregation": {
|
|
487
|
+
"type": "string",
|
|
488
|
+
"enum": ["detail", "day", "week", "month"],
|
|
489
|
+
"default": "detail",
|
|
490
|
+
"description": "Aggregation level",
|
|
491
|
+
},
|
|
492
|
+
"output_path": {
|
|
493
|
+
"type": "string",
|
|
494
|
+
"description": "File path where data will be written (e.g., './exports/authorizations.json')",
|
|
495
|
+
},
|
|
496
|
+
"format": {
|
|
497
|
+
"type": "string",
|
|
498
|
+
"enum": ["json", "csv"],
|
|
499
|
+
"default": "json",
|
|
500
|
+
"description": "Output file format",
|
|
501
|
+
},
|
|
502
|
+
"max_records": {
|
|
503
|
+
"type": "integer",
|
|
504
|
+
"description": "Maximum total records to export (omit to export all matching records)",
|
|
505
|
+
},
|
|
506
|
+
"fields": {
|
|
507
|
+
"type": "array",
|
|
508
|
+
"items": {"type": "string"},
|
|
509
|
+
"description": "Specific fields to include in export",
|
|
510
|
+
},
|
|
511
|
+
"filters": {
|
|
512
|
+
"type": "object",
|
|
513
|
+
"description": "Filters on data fields. For date filtering, use actual date field names with operators (e.g., {'transaction_timestamp': '>=2023-10-20'})",
|
|
514
|
+
},
|
|
515
|
+
"sort_by": {"type": "string", "description": "Field to sort by"},
|
|
516
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
517
|
+
},
|
|
518
|
+
},
|
|
519
|
+
),
|
|
520
|
+
Tool(
|
|
521
|
+
name="get_server_version",
|
|
522
|
+
description=(
|
|
523
|
+
"Get the MCP server version to verify it has been restarted with latest code changes."
|
|
524
|
+
),
|
|
525
|
+
inputSchema={"type": "object", "properties": {}},
|
|
526
|
+
),
|
|
527
|
+
]
|
|
528
|
+
|
|
529
|
+
# RAG tools - only available when ENABLE_LOCAL_STORAGE=true
|
|
530
|
+
RAG_TOOLS = [
|
|
531
|
+
Tool(
|
|
532
|
+
name="index_transactions",
|
|
533
|
+
description=(
|
|
534
|
+
"Sync transactions from DiVA to local storage (SQLite + ChromaDB). "
|
|
535
|
+
"Stores FULL transaction data locally and generates embeddings for semantic search. "
|
|
536
|
+
"This eliminates token limits - query locally without MCP constraints! "
|
|
537
|
+
"Must be called before using semantic search or local queries."
|
|
538
|
+
),
|
|
539
|
+
inputSchema={
|
|
540
|
+
"type": "object",
|
|
541
|
+
"properties": {
|
|
542
|
+
"view_name": {
|
|
543
|
+
"type": "string",
|
|
544
|
+
"default": "authorizations",
|
|
545
|
+
"description": "DiVA view to index (default: authorizations)",
|
|
546
|
+
},
|
|
547
|
+
"aggregation": {
|
|
548
|
+
"type": "string",
|
|
549
|
+
"enum": ["detail", "day", "week", "month"],
|
|
550
|
+
"default": "detail",
|
|
551
|
+
"description": "Aggregation level (default: detail)",
|
|
552
|
+
},
|
|
553
|
+
"filters": {
|
|
554
|
+
"type": "object",
|
|
555
|
+
"description": "Filters on data fields to limit which transactions to index. For date filtering, use actual date field names with operators (e.g., {'transaction_timestamp': '>=2023-10-20'})",
|
|
556
|
+
},
|
|
557
|
+
"max_records": {
|
|
558
|
+
"type": "integer",
|
|
559
|
+
"description": "Maximum records to index (up to 10,000 per query)",
|
|
560
|
+
},
|
|
561
|
+
"program": {"type": "string", "description": "Override default program"},
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
),
|
|
565
|
+
Tool(
|
|
566
|
+
name="semantic_search_transactions",
|
|
567
|
+
description=(
|
|
568
|
+
"Search transactions using natural language queries. "
|
|
569
|
+
"Examples: 'coffee shop purchases', 'large transactions over $100', 'gas station visits'. "
|
|
570
|
+
"Returns full transaction data from LOCAL storage (no API calls, no token limits!). "
|
|
571
|
+
"Requires transactions to be synced first (use index_transactions)."
|
|
572
|
+
),
|
|
573
|
+
inputSchema={
|
|
574
|
+
"type": "object",
|
|
575
|
+
"required": ["query"],
|
|
576
|
+
"properties": {
|
|
577
|
+
"query": {
|
|
578
|
+
"type": "string",
|
|
579
|
+
"description": "Natural language search query (e.g., 'coffee shop purchases')",
|
|
580
|
+
},
|
|
581
|
+
"n_results": {
|
|
582
|
+
"type": "integer",
|
|
583
|
+
"default": 10,
|
|
584
|
+
"description": "Number of results to return (default: 10)",
|
|
585
|
+
},
|
|
586
|
+
"filters": {
|
|
587
|
+
"type": "object",
|
|
588
|
+
"description": "Metadata filters to narrow search (e.g., amount range, date range)",
|
|
589
|
+
},
|
|
590
|
+
"enrich": {
|
|
591
|
+
"type": "boolean",
|
|
592
|
+
"default": True,
|
|
593
|
+
"description": "Include full transaction details from local storage (default: true)",
|
|
594
|
+
},
|
|
595
|
+
},
|
|
596
|
+
},
|
|
597
|
+
),
|
|
598
|
+
Tool(
|
|
599
|
+
name="query_local_transactions",
|
|
600
|
+
description=(
|
|
601
|
+
"Query transactions directly from local SQLite storage using filters. "
|
|
602
|
+
"No semantic search - just standard filtering (merchant, amount, date, etc.). "
|
|
603
|
+
"Returns FULL transaction data with NO token limits or API calls. "
|
|
604
|
+
"Perfect for LLM analysis of complete datasets. "
|
|
605
|
+
"Supports pagination for large result sets."
|
|
606
|
+
),
|
|
607
|
+
inputSchema={
|
|
608
|
+
"type": "object",
|
|
609
|
+
"properties": {
|
|
610
|
+
"filters": {
|
|
611
|
+
"type": "object",
|
|
612
|
+
"description": (
|
|
613
|
+
"Filters using field names (e.g., {\"merchant_name\": \"Starbucks\", "
|
|
614
|
+
"\"transaction_amount\": {\">\": 10}}). "
|
|
615
|
+
"Operators: >, <, >=, <=, =, !=, like"
|
|
616
|
+
),
|
|
617
|
+
},
|
|
618
|
+
"limit": {
|
|
619
|
+
"type": "integer",
|
|
620
|
+
"default": 100,
|
|
621
|
+
"description": "Maximum number of results (default: 100)",
|
|
622
|
+
},
|
|
623
|
+
"offset": {
|
|
624
|
+
"type": "integer",
|
|
625
|
+
"default": 0,
|
|
626
|
+
"description": "Offset for pagination in local SQLite storage (default: 0)",
|
|
627
|
+
},
|
|
628
|
+
"order_by": {
|
|
629
|
+
"type": "string",
|
|
630
|
+
"default": "created_time DESC",
|
|
631
|
+
"description": "SQL ORDER BY clause (default: 'created_time DESC')",
|
|
632
|
+
},
|
|
633
|
+
},
|
|
634
|
+
},
|
|
635
|
+
),
|
|
636
|
+
Tool(
|
|
637
|
+
name="find_similar_transactions",
|
|
638
|
+
description=(
|
|
639
|
+
"Find transactions similar to a specific transaction. "
|
|
640
|
+
"Useful for finding related purchases, duplicate transactions, or patterns. "
|
|
641
|
+
"Requires the reference transaction to be indexed first."
|
|
642
|
+
),
|
|
643
|
+
inputSchema={
|
|
644
|
+
"type": "object",
|
|
645
|
+
"required": ["transaction_token"],
|
|
646
|
+
"properties": {
|
|
647
|
+
"transaction_token": {
|
|
648
|
+
"type": "string",
|
|
649
|
+
"description": "Token of the reference transaction",
|
|
650
|
+
},
|
|
651
|
+
"n_results": {
|
|
652
|
+
"type": "integer",
|
|
653
|
+
"default": 10,
|
|
654
|
+
"description": "Number of similar transactions to return (default: 10)",
|
|
655
|
+
},
|
|
656
|
+
"filters": {
|
|
657
|
+
"type": "object",
|
|
658
|
+
"description": "Additional metadata filters",
|
|
659
|
+
},
|
|
660
|
+
},
|
|
661
|
+
},
|
|
662
|
+
),
|
|
663
|
+
Tool(
|
|
664
|
+
name="get_index_stats",
|
|
665
|
+
description=(
|
|
666
|
+
"Get comprehensive statistics about local storage (SQLite + ChromaDB). "
|
|
667
|
+
"Shows transaction counts, database size, embedding model info, and storage status. "
|
|
668
|
+
"Useful for monitoring local data availability."
|
|
669
|
+
),
|
|
670
|
+
inputSchema={"type": "object", "properties": {}},
|
|
671
|
+
),
|
|
672
|
+
Tool(
|
|
673
|
+
name="clear_index",
|
|
674
|
+
description=(
|
|
675
|
+
"Clear all transactions from the vector index. "
|
|
676
|
+
"Use this to reset and start fresh. Cannot be undone."
|
|
677
|
+
),
|
|
678
|
+
inputSchema={"type": "object", "properties": {}},
|
|
679
|
+
),
|
|
680
|
+
]
|
|
681
|
+
|
|
682
|
+
# Build the final TOOLS list dynamically based on feature flags
|
|
683
|
+
TOOLS = BASE_TOOLS.copy()
|
|
684
|
+
if RAG_AVAILABLE:
|
|
685
|
+
TOOLS.extend(RAG_TOOLS)
|
|
686
|
+
print(f"[MCP Server] Registered {len(BASE_TOOLS)} base tools + {len(RAG_TOOLS)} RAG tools = {len(TOOLS)} total tools", file=sys.stderr)
|
|
687
|
+
else:
|
|
688
|
+
print(f"[MCP Server] Registered {len(BASE_TOOLS)} base tools (RAG tools disabled)", file=sys.stderr)
|
|
689
|
+
|
|
690
|
+
|
|
691
|
+
@app.list_tools()
|
|
692
|
+
async def list_tools() -> List[Tool]:
|
|
693
|
+
"""List all available tools."""
|
|
694
|
+
return TOOLS
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
@app.call_tool()
|
|
698
|
+
async def call_tool(name: str, arguments: Any) -> List[TextContent]:
|
|
699
|
+
"""Handle tool calls."""
|
|
700
|
+
try:
|
|
701
|
+
client = get_client()
|
|
702
|
+
|
|
703
|
+
# Transaction tools
|
|
704
|
+
if name == "get_authorizations":
|
|
705
|
+
aggregation = arguments.pop("aggregation", "detail")
|
|
706
|
+
result = client.get_view("authorizations", aggregation, **arguments)
|
|
707
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
708
|
+
|
|
709
|
+
elif name == "get_settlements":
|
|
710
|
+
aggregation = arguments.pop("aggregation", "detail")
|
|
711
|
+
result = client.get_view("settlements", aggregation, **arguments)
|
|
712
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
713
|
+
|
|
714
|
+
elif name == "get_clearings":
|
|
715
|
+
aggregation = arguments.pop("aggregation", "detail")
|
|
716
|
+
result = client.get_view("clearing", aggregation, **arguments)
|
|
717
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
718
|
+
|
|
719
|
+
elif name == "get_declines":
|
|
720
|
+
aggregation = arguments.pop("aggregation", "detail")
|
|
721
|
+
result = client.get_view("declines", aggregation, **arguments)
|
|
722
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
723
|
+
|
|
724
|
+
elif name == "get_loads":
|
|
725
|
+
aggregation = arguments.pop("aggregation", "detail")
|
|
726
|
+
result = client.get_view("loads", aggregation, **arguments)
|
|
727
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
728
|
+
|
|
729
|
+
# Financial tools
|
|
730
|
+
elif name == "get_program_balances":
|
|
731
|
+
result = client.get_view("programbalances", "day", **arguments)
|
|
732
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
733
|
+
|
|
734
|
+
elif name == "get_program_balances_settlement":
|
|
735
|
+
result = client.get_view("programbalancessettlement", "day", **arguments)
|
|
736
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
737
|
+
|
|
738
|
+
elif name == "get_activity_balances":
|
|
739
|
+
result = client.get_view("activitybalances", "day", **arguments)
|
|
740
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
741
|
+
|
|
742
|
+
# Card & User tools
|
|
743
|
+
elif name == "get_cards":
|
|
744
|
+
result = client.get_view("cards", "detail", **arguments)
|
|
745
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
746
|
+
|
|
747
|
+
elif name == "get_users":
|
|
748
|
+
result = client.get_view("users", "detail", **arguments)
|
|
749
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
750
|
+
|
|
751
|
+
# Chargeback tools
|
|
752
|
+
elif name == "get_chargebacks_status":
|
|
753
|
+
result = client.get_view("chargebacks", "status", **arguments)
|
|
754
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
755
|
+
|
|
756
|
+
elif name == "get_chargebacks_detail":
|
|
757
|
+
result = client.get_view("chargebacks", "detail", **arguments)
|
|
758
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
759
|
+
|
|
760
|
+
# Metadata tools
|
|
761
|
+
elif name == "list_available_views":
|
|
762
|
+
result = client.get_views_list()
|
|
763
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
764
|
+
|
|
765
|
+
elif name == "get_view_schema":
|
|
766
|
+
view_name = arguments["view_name"]
|
|
767
|
+
aggregation = arguments.pop("aggregation", "detail")
|
|
768
|
+
result = client.get_view_schema(view_name, aggregation)
|
|
769
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
770
|
+
|
|
771
|
+
# Export tool
|
|
772
|
+
elif name == "export_view_to_file":
|
|
773
|
+
view_name = arguments.pop("view_name")
|
|
774
|
+
aggregation = arguments.pop("aggregation", "detail")
|
|
775
|
+
output_path = arguments.pop("output_path")
|
|
776
|
+
format_type = arguments.pop("format", "json")
|
|
777
|
+
max_records = arguments.pop("max_records", None)
|
|
778
|
+
|
|
779
|
+
result = client.export_to_file(
|
|
780
|
+
view_name=view_name,
|
|
781
|
+
aggregation=aggregation,
|
|
782
|
+
output_path=output_path,
|
|
783
|
+
format=format_type,
|
|
784
|
+
max_records=max_records,
|
|
785
|
+
**arguments
|
|
786
|
+
)
|
|
787
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
788
|
+
|
|
789
|
+
# RAG tools
|
|
790
|
+
elif name == "index_transactions":
|
|
791
|
+
if not RAG_AVAILABLE:
|
|
792
|
+
return [TextContent(type="text", text=format_response({
|
|
793
|
+
"error": "Local storage features are not enabled",
|
|
794
|
+
"message": "To use this feature, set ENABLE_LOCAL_STORAGE=true in your environment and install RAG dependencies",
|
|
795
|
+
"install_command": "pip install marqeta-diva-mcp[rag]"
|
|
796
|
+
}))]
|
|
797
|
+
|
|
798
|
+
view_name = arguments.pop("view_name", "authorizations")
|
|
799
|
+
aggregation = arguments.pop("aggregation", "detail")
|
|
800
|
+
|
|
801
|
+
result = rag_tools.index_transactions(
|
|
802
|
+
diva_client=client,
|
|
803
|
+
view_name=view_name,
|
|
804
|
+
aggregation=aggregation,
|
|
805
|
+
**arguments
|
|
806
|
+
)
|
|
807
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
808
|
+
|
|
809
|
+
elif name == "semantic_search_transactions":
|
|
810
|
+
if not RAG_AVAILABLE:
|
|
811
|
+
return [TextContent(type="text", text=format_response({
|
|
812
|
+
"error": "Local storage features are not enabled",
|
|
813
|
+
"message": "To use this feature, set ENABLE_LOCAL_STORAGE=true in your environment and install RAG dependencies",
|
|
814
|
+
"install_command": "pip install marqeta-diva-mcp[rag]"
|
|
815
|
+
}))]
|
|
816
|
+
|
|
817
|
+
query = arguments.pop("query")
|
|
818
|
+
n_results = arguments.pop("n_results", 10)
|
|
819
|
+
filters = arguments.pop("filters", None)
|
|
820
|
+
enrich = arguments.pop("enrich", True)
|
|
821
|
+
|
|
822
|
+
result = rag_tools.semantic_search_transactions(
|
|
823
|
+
diva_client=client,
|
|
824
|
+
query=query,
|
|
825
|
+
n_results=n_results,
|
|
826
|
+
filters=filters,
|
|
827
|
+
enrich=enrich
|
|
828
|
+
)
|
|
829
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
830
|
+
|
|
831
|
+
elif name == "query_local_transactions":
|
|
832
|
+
if not RAG_AVAILABLE:
|
|
833
|
+
return [TextContent(type="text", text=format_response({
|
|
834
|
+
"error": "Local storage features are not enabled",
|
|
835
|
+
"message": "To use this feature, set ENABLE_LOCAL_STORAGE=true in your environment and install RAG dependencies",
|
|
836
|
+
"install_command": "pip install marqeta-diva-mcp[rag]"
|
|
837
|
+
}))]
|
|
838
|
+
|
|
839
|
+
filters = arguments.pop("filters", None)
|
|
840
|
+
limit = arguments.pop("limit", 100)
|
|
841
|
+
offset = arguments.pop("offset", 0)
|
|
842
|
+
order_by = arguments.pop("order_by", "created_time DESC")
|
|
843
|
+
|
|
844
|
+
result = rag_tools.query_local_transactions(
|
|
845
|
+
filters=filters,
|
|
846
|
+
limit=limit,
|
|
847
|
+
offset=offset,
|
|
848
|
+
order_by=order_by
|
|
849
|
+
)
|
|
850
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
851
|
+
|
|
852
|
+
elif name == "find_similar_transactions":
|
|
853
|
+
if not RAG_AVAILABLE:
|
|
854
|
+
return [TextContent(type="text", text=format_response({
|
|
855
|
+
"error": "Local storage features are not enabled",
|
|
856
|
+
"message": "To use this feature, set ENABLE_LOCAL_STORAGE=true in your environment and install RAG dependencies",
|
|
857
|
+
"install_command": "pip install marqeta-diva-mcp[rag]"
|
|
858
|
+
}))]
|
|
859
|
+
|
|
860
|
+
transaction_token = arguments.pop("transaction_token")
|
|
861
|
+
n_results = arguments.pop("n_results", 10)
|
|
862
|
+
filters = arguments.pop("filters", None)
|
|
863
|
+
|
|
864
|
+
result = rag_tools.find_similar_transactions(
|
|
865
|
+
diva_client=client,
|
|
866
|
+
transaction_token=transaction_token,
|
|
867
|
+
n_results=n_results,
|
|
868
|
+
filters=filters
|
|
869
|
+
)
|
|
870
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
871
|
+
|
|
872
|
+
elif name == "get_index_stats":
|
|
873
|
+
if not RAG_AVAILABLE:
|
|
874
|
+
return [TextContent(type="text", text=format_response({
|
|
875
|
+
"error": "Local storage features are not enabled",
|
|
876
|
+
"message": "To use this feature, set ENABLE_LOCAL_STORAGE=true in your environment and install RAG dependencies",
|
|
877
|
+
"install_command": "pip install marqeta-diva-mcp[rag]"
|
|
878
|
+
}))]
|
|
879
|
+
|
|
880
|
+
result = rag_tools.get_index_stats()
|
|
881
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
882
|
+
|
|
883
|
+
elif name == "clear_index":
|
|
884
|
+
if not RAG_AVAILABLE:
|
|
885
|
+
return [TextContent(type="text", text=format_response({
|
|
886
|
+
"error": "Local storage features are not enabled",
|
|
887
|
+
"message": "To use this feature, set ENABLE_LOCAL_STORAGE=true in your environment and install RAG dependencies",
|
|
888
|
+
"install_command": "pip install marqeta-diva-mcp[rag]"
|
|
889
|
+
}))]
|
|
890
|
+
|
|
891
|
+
result = rag_tools.clear_index()
|
|
892
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
893
|
+
|
|
894
|
+
elif name == "get_server_version":
|
|
895
|
+
result = {
|
|
896
|
+
"version": SERVER_VERSION,
|
|
897
|
+
"message": "If you don't see version 0.2.0, the server needs to be restarted",
|
|
898
|
+
"rag_features_enabled": RAG_AVAILABLE,
|
|
899
|
+
"features": {
|
|
900
|
+
"base_tools": f"{len(BASE_TOOLS)} tools available",
|
|
901
|
+
"rag_tools": f"{len(RAG_TOOLS)} tools available" if RAG_AVAILABLE else "disabled (set ENABLE_LOCAL_STORAGE=true to enable)",
|
|
902
|
+
},
|
|
903
|
+
"fixes_included": [
|
|
904
|
+
"Removed non-existent start_date/end_date parameters",
|
|
905
|
+
"Added sys import to fix export errors",
|
|
906
|
+
"Updated to correct 10,000 record limit",
|
|
907
|
+
"Disabled client-side field validation",
|
|
908
|
+
"Fixed filter syntax for date fields",
|
|
909
|
+
"CRITICAL FIX: Changed 'data' to 'records' to match actual API response format",
|
|
910
|
+
"Fixed ChromaDB ID type error - convert integer IDs to strings",
|
|
911
|
+
"Made RAG features optional with ENABLE_LOCAL_STORAGE environment variable"
|
|
912
|
+
]
|
|
913
|
+
}
|
|
914
|
+
return [TextContent(type="text", text=format_response(result))]
|
|
915
|
+
|
|
916
|
+
else:
|
|
917
|
+
return [TextContent(type="text", text=f"Unknown tool: {name}")]
|
|
918
|
+
|
|
919
|
+
except Exception as e:
|
|
920
|
+
error_msg = format_error(e)
|
|
921
|
+
return [TextContent(type="text", text=f"Error: {error_msg}")]
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
async def async_main():
|
|
925
|
+
"""Run the MCP server."""
|
|
926
|
+
async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
|
|
927
|
+
await app.run(
|
|
928
|
+
read_stream,
|
|
929
|
+
write_stream,
|
|
930
|
+
app.create_initialization_options(),
|
|
931
|
+
)
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
def main():
|
|
935
|
+
"""Entry point for the MCP server."""
|
|
936
|
+
asyncio.run(async_main())
|
|
937
|
+
|
|
938
|
+
|
|
939
|
+
if __name__ == "__main__":
|
|
940
|
+
main()
|