@cci-labs/mode-mcp 1.0.1
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.
- package/LICENSE +21 -0
- package/README.md +925 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.js +27 -0
- package/dist/file-utils.d.ts +7 -0
- package/dist/file-utils.js +47 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +29 -0
- package/dist/mode-client.d.ts +38 -0
- package/dist/mode-client.js +227 -0
- package/dist/tools/analytics.d.ts +4 -0
- package/dist/tools/analytics.js +707 -0
- package/dist/tools/datasets.d.ts +4 -0
- package/dist/tools/datasets.js +154 -0
- package/dist/tools/distribution.d.ts +4 -0
- package/dist/tools/distribution.js +175 -0
- package/dist/tools/management.d.ts +4 -0
- package/dist/tools/management.js +263 -0
- package/dist/truncate.d.ts +6 -0
- package/dist/truncate.js +16 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.js +68 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,925 @@
|
|
|
1
|
+
# Mode Analytics MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://github.com/AwesomeCICD/mode-mcp/blob/main/LICENSE)
|
|
4
|
+
[](https://dl.circleci.com/status-badge/redirect/gh/AwesomeCICD/mode-mcp/tree/main)
|
|
5
|
+
[](https://www.npmjs.com/package/@cci-labs/mode-mcp)
|
|
6
|
+
[](https://hub.docker.com/r/ccilabs/mode-mcp)
|
|
7
|
+
[](https://nodejs.org)
|
|
8
|
+
[](https://modelcontextprotocol.io)
|
|
9
|
+
|
|
10
|
+
Model Context Protocol (MCP) is a [standardized protocol](https://modelcontextprotocol.io/introduction) for managing context between large language models (LLMs) and external systems. In this repository, we provide an MCP Server for [Mode Analytics](https://mode.com).
|
|
11
|
+
|
|
12
|
+
Use Cursor, Windsurf, Copilot, Claude, or any MCP-compatible client to interact with Mode Analytics using natural language — without leaving your IDE.
|
|
13
|
+
|
|
14
|
+
## Tools
|
|
15
|
+
|
|
16
|
+
| Tool | Description |
|
|
17
|
+
|------|-------------|
|
|
18
|
+
| [`mode_list_reports`](#mode_list_reports) | List reports in the workspace, optionally filtered by space |
|
|
19
|
+
| [`mode_get_report`](#mode_get_report) | Get report details including queries, data sources, and last run status |
|
|
20
|
+
| [`mode_list_queries`](#mode_list_queries) | List all queries in a report with their SQL content |
|
|
21
|
+
| [`mode_run_report`](#mode_run_report) | Trigger a new report run (non-destructive) |
|
|
22
|
+
| [`mode_get_run_status`](#mode_get_run_status) | Check whether a report run has completed, is running, or failed |
|
|
23
|
+
| [`mode_get_query_results`](#mode_get_query_results) | Download query results as a markdown table, optionally save as CSV |
|
|
24
|
+
| [`mode_execute_and_fetch`](#mode_execute_and_fetch) | Run a report, wait for completion, and return results — all in one call |
|
|
25
|
+
| [`mode_list_report_runs`](#mode_list_report_runs) | List past runs for a report |
|
|
26
|
+
| [`mode_get_query_run`](#mode_get_query_run) | Get details on a specific query run (state, errors, timing) |
|
|
27
|
+
| [`mode_search_reports`](#mode_search_reports) | Search reports by name across the workspace |
|
|
28
|
+
| [`mode_get_report_parameters`](#mode_get_report_parameters) | Discover what parameters a report accepts before running it |
|
|
29
|
+
| [`mode_list_report_filters`](#mode_list_report_filters) | List interactive filters on a report |
|
|
30
|
+
| [`mode_list_report_charts`](#mode_list_report_charts) | List charts/visualizations in a query |
|
|
31
|
+
| [`mode_list_spaces`](#mode_list_spaces) | List all spaces (collections) in the workspace |
|
|
32
|
+
| [`mode_list_data_sources`](#mode_list_data_sources) | List all connected data sources (databases) |
|
|
33
|
+
| [`mode_get_data_source`](#mode_get_data_source) | Get detailed connection info for a data source |
|
|
34
|
+
| [`mode_list_definitions`](#mode_list_definitions) | List saved SQL definitions (reusable snippets) |
|
|
35
|
+
| [`mode_list_report_schedules`](#mode_list_report_schedules) | List automated schedules for a report |
|
|
36
|
+
| [`mode_list_report_subscriptions`](#mode_list_report_subscriptions) | List email subscriptions for a report |
|
|
37
|
+
| [`mode_get_audit_logs`](#mode_get_audit_logs) | Retrieve workspace audit logs |
|
|
38
|
+
| [`mode_list_datasets`](#mode_list_datasets) | List datasets in a space |
|
|
39
|
+
| [`mode_get_dataset`](#mode_get_dataset) | Get dataset details with fields and descriptions |
|
|
40
|
+
| [`mode_list_dataset_reports`](#mode_list_dataset_reports) | Find reports that use a dataset |
|
|
41
|
+
| [`mode_export_report`](#mode_export_report) | Export a report as PDF or CSV |
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
<details>
|
|
46
|
+
<summary><strong>Claude Code</strong></summary>
|
|
47
|
+
|
|
48
|
+
**Prerequisites:**
|
|
49
|
+
- [Mode API token and secret](https://app.mode.com) — generate at `app.mode.com/{workspace}/settings/api_tokens`
|
|
50
|
+
- Docker: [Docker](https://docs.docker.com/get-docker/)
|
|
51
|
+
- NPX: [Node.js >= v22](https://nodejs.org/)
|
|
52
|
+
|
|
53
|
+
#### Using Docker in a local MCP Server
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
claude mcp add mode-analytics \
|
|
57
|
+
-e MODE_WORKSPACE=your-workspace \
|
|
58
|
+
-e MODE_API_TOKEN=your-token \
|
|
59
|
+
-e MODE_API_SECRET=your-secret \
|
|
60
|
+
-- docker run --rm -i \
|
|
61
|
+
-e MODE_WORKSPACE -e MODE_API_TOKEN -e MODE_API_SECRET \
|
|
62
|
+
-v "$HOME/Downloads:/output" \
|
|
63
|
+
ccilabs/mode-mcp
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
> The `-v "$HOME/Downloads:/output"` mount lets tools save CSV and PDF exports to your `~/Downloads` folder. Use `/output` as the `output_dir` parameter when downloading files.
|
|
67
|
+
|
|
68
|
+
#### Using Node.js in a local MCP Server
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
claude mcp add mode-analytics \
|
|
72
|
+
-e MODE_WORKSPACE=your-workspace \
|
|
73
|
+
-e MODE_API_TOKEN=your-token \
|
|
74
|
+
-e MODE_API_SECRET=your-secret \
|
|
75
|
+
-- node /path/to/mode-mcp/dist/index.js
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
> With the Node.js setup, tools can save files directly to any path on your machine.
|
|
79
|
+
|
|
80
|
+
#### Using npx (no install)
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
claude mcp add mode-analytics \
|
|
84
|
+
-e MODE_WORKSPACE=your-workspace \
|
|
85
|
+
-e MODE_API_TOKEN=your-token \
|
|
86
|
+
-e MODE_API_SECRET=your-secret \
|
|
87
|
+
-- npx -y @cci-labs/mode-mcp
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
For more information: https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/tutorials#set-up-model-context-protocol-mcp
|
|
91
|
+
|
|
92
|
+
</details>
|
|
93
|
+
|
|
94
|
+
<details>
|
|
95
|
+
<summary><strong>Cursor</strong></summary>
|
|
96
|
+
|
|
97
|
+
**Prerequisites:**
|
|
98
|
+
- [Mode API token and secret](https://app.mode.com) — generate at `app.mode.com/{workspace}/settings/api_tokens`
|
|
99
|
+
- Docker: [Docker](https://docs.docker.com/get-docker/)
|
|
100
|
+
- NPX: [Node.js >= v22](https://nodejs.org/)
|
|
101
|
+
|
|
102
|
+
#### Using Docker in a local MCP Server
|
|
103
|
+
|
|
104
|
+
Add the following to your Cursor MCP config:
|
|
105
|
+
|
|
106
|
+
```json
|
|
107
|
+
{
|
|
108
|
+
"mcpServers": {
|
|
109
|
+
"mode-analytics": {
|
|
110
|
+
"command": "docker",
|
|
111
|
+
"args": [
|
|
112
|
+
"run", "--rm", "-i",
|
|
113
|
+
"-e", "MODE_WORKSPACE",
|
|
114
|
+
"-e", "MODE_API_TOKEN",
|
|
115
|
+
"-e", "MODE_API_SECRET",
|
|
116
|
+
"-v", "${HOME}/Downloads:/output",
|
|
117
|
+
"ccilabs/mode-mcp"
|
|
118
|
+
],
|
|
119
|
+
"env": {
|
|
120
|
+
"MODE_WORKSPACE": "your-workspace",
|
|
121
|
+
"MODE_API_TOKEN": "your-token",
|
|
122
|
+
"MODE_API_SECRET": "your-secret"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
#### Using Node.js in a local MCP Server
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"mcpServers": {
|
|
134
|
+
"mode-analytics": {
|
|
135
|
+
"command": "node",
|
|
136
|
+
"args": ["/path/to/mode-mcp/dist/index.js"],
|
|
137
|
+
"env": {
|
|
138
|
+
"MODE_WORKSPACE": "your-workspace",
|
|
139
|
+
"MODE_API_TOKEN": "your-token",
|
|
140
|
+
"MODE_API_SECRET": "your-secret"
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### Using npx (no install)
|
|
148
|
+
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"mcpServers": {
|
|
152
|
+
"mode-analytics": {
|
|
153
|
+
"command": "npx",
|
|
154
|
+
"args": ["-y", "@cci-labs/mode-mcp"],
|
|
155
|
+
"env": {
|
|
156
|
+
"MODE_WORKSPACE": "your-workspace",
|
|
157
|
+
"MODE_API_TOKEN": "your-token",
|
|
158
|
+
"MODE_API_SECRET": "your-secret"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
</details>
|
|
166
|
+
|
|
167
|
+
<details>
|
|
168
|
+
<summary><strong>VS Code</strong></summary>
|
|
169
|
+
|
|
170
|
+
**Prerequisites:**
|
|
171
|
+
- [Mode API token and secret](https://app.mode.com) — generate at `app.mode.com/{workspace}/settings/api_tokens`
|
|
172
|
+
- Docker: [Docker](https://docs.docker.com/get-docker/)
|
|
173
|
+
- NPX: [Node.js >= v22](https://nodejs.org/)
|
|
174
|
+
|
|
175
|
+
#### Using Docker in a local MCP Server
|
|
176
|
+
|
|
177
|
+
Add the following to `.vscode/mcp.json` in your project:
|
|
178
|
+
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"inputs": [
|
|
182
|
+
{
|
|
183
|
+
"type": "promptString",
|
|
184
|
+
"id": "mode-workspace",
|
|
185
|
+
"description": "Mode workspace name"
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
"type": "promptString",
|
|
189
|
+
"id": "mode-token",
|
|
190
|
+
"description": "Mode API Token",
|
|
191
|
+
"password": true
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"type": "promptString",
|
|
195
|
+
"id": "mode-secret",
|
|
196
|
+
"description": "Mode API Secret",
|
|
197
|
+
"password": true
|
|
198
|
+
}
|
|
199
|
+
],
|
|
200
|
+
"servers": {
|
|
201
|
+
"mode-analytics": {
|
|
202
|
+
"type": "stdio",
|
|
203
|
+
"command": "docker",
|
|
204
|
+
"args": [
|
|
205
|
+
"run", "--rm", "-i",
|
|
206
|
+
"-e", "MODE_WORKSPACE",
|
|
207
|
+
"-e", "MODE_API_TOKEN",
|
|
208
|
+
"-e", "MODE_API_SECRET",
|
|
209
|
+
"-v", "${HOME}/Downloads:/output",
|
|
210
|
+
"ccilabs/mode-mcp"
|
|
211
|
+
],
|
|
212
|
+
"env": {
|
|
213
|
+
"MODE_WORKSPACE": "${input:mode-workspace}",
|
|
214
|
+
"MODE_API_TOKEN": "${input:mode-token}",
|
|
215
|
+
"MODE_API_SECRET": "${input:mode-secret}"
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
> Inputs are prompted on first server start, then stored securely by VS Code.
|
|
223
|
+
|
|
224
|
+
#### Using Node.js in a local MCP Server
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"inputs": [
|
|
229
|
+
{
|
|
230
|
+
"type": "promptString",
|
|
231
|
+
"id": "mode-workspace",
|
|
232
|
+
"description": "Mode workspace name"
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"type": "promptString",
|
|
236
|
+
"id": "mode-token",
|
|
237
|
+
"description": "Mode API Token",
|
|
238
|
+
"password": true
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
"type": "promptString",
|
|
242
|
+
"id": "mode-secret",
|
|
243
|
+
"description": "Mode API Secret",
|
|
244
|
+
"password": true
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
"servers": {
|
|
248
|
+
"mode-analytics": {
|
|
249
|
+
"type": "stdio",
|
|
250
|
+
"command": "node",
|
|
251
|
+
"args": ["/path/to/mode-mcp/dist/index.js"],
|
|
252
|
+
"env": {
|
|
253
|
+
"MODE_WORKSPACE": "${input:mode-workspace}",
|
|
254
|
+
"MODE_API_TOKEN": "${input:mode-token}",
|
|
255
|
+
"MODE_API_SECRET": "${input:mode-secret}"
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Using npx (no install)
|
|
263
|
+
|
|
264
|
+
```json
|
|
265
|
+
{
|
|
266
|
+
"inputs": [
|
|
267
|
+
{
|
|
268
|
+
"type": "promptString",
|
|
269
|
+
"id": "mode-workspace",
|
|
270
|
+
"description": "Mode workspace name"
|
|
271
|
+
},
|
|
272
|
+
{
|
|
273
|
+
"type": "promptString",
|
|
274
|
+
"id": "mode-token",
|
|
275
|
+
"description": "Mode API Token",
|
|
276
|
+
"password": true
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"type": "promptString",
|
|
280
|
+
"id": "mode-secret",
|
|
281
|
+
"description": "Mode API Secret",
|
|
282
|
+
"password": true
|
|
283
|
+
}
|
|
284
|
+
],
|
|
285
|
+
"servers": {
|
|
286
|
+
"mode-analytics": {
|
|
287
|
+
"type": "stdio",
|
|
288
|
+
"command": "npx",
|
|
289
|
+
"args": ["-y", "@cci-labs/mode-mcp"],
|
|
290
|
+
"env": {
|
|
291
|
+
"MODE_WORKSPACE": "${input:mode-workspace}",
|
|
292
|
+
"MODE_API_TOKEN": "${input:mode-token}",
|
|
293
|
+
"MODE_API_SECRET": "${input:mode-secret}"
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
</details>
|
|
301
|
+
|
|
302
|
+
<details>
|
|
303
|
+
<summary><strong>Claude Desktop</strong></summary>
|
|
304
|
+
|
|
305
|
+
**Prerequisites:**
|
|
306
|
+
- [Mode API token and secret](https://app.mode.com) — generate at `app.mode.com/{workspace}/settings/api_tokens`
|
|
307
|
+
- Docker: [Docker](https://docs.docker.com/get-docker/)
|
|
308
|
+
- NPX: [Node.js >= v22](https://nodejs.org/)
|
|
309
|
+
|
|
310
|
+
#### Using Docker in a local MCP Server
|
|
311
|
+
|
|
312
|
+
Add the following to your `claude_desktop_config.json`:
|
|
313
|
+
|
|
314
|
+
```json
|
|
315
|
+
{
|
|
316
|
+
"mcpServers": {
|
|
317
|
+
"mode-analytics": {
|
|
318
|
+
"command": "docker",
|
|
319
|
+
"args": [
|
|
320
|
+
"run", "--rm", "-i",
|
|
321
|
+
"-e", "MODE_WORKSPACE",
|
|
322
|
+
"-e", "MODE_API_TOKEN",
|
|
323
|
+
"-e", "MODE_API_SECRET",
|
|
324
|
+
"-v", "${HOME}/Downloads:/output",
|
|
325
|
+
"ccilabs/mode-mcp"
|
|
326
|
+
],
|
|
327
|
+
"env": {
|
|
328
|
+
"MODE_WORKSPACE": "your-workspace",
|
|
329
|
+
"MODE_API_TOKEN": "your-token",
|
|
330
|
+
"MODE_API_SECRET": "your-secret"
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
#### Using Node.js in a local MCP Server
|
|
338
|
+
|
|
339
|
+
```json
|
|
340
|
+
{
|
|
341
|
+
"mcpServers": {
|
|
342
|
+
"mode-analytics": {
|
|
343
|
+
"command": "node",
|
|
344
|
+
"args": ["/path/to/mode-mcp/dist/index.js"],
|
|
345
|
+
"env": {
|
|
346
|
+
"MODE_WORKSPACE": "your-workspace",
|
|
347
|
+
"MODE_API_TOKEN": "your-token",
|
|
348
|
+
"MODE_API_SECRET": "your-secret"
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
#### Using npx (no install)
|
|
356
|
+
|
|
357
|
+
```json
|
|
358
|
+
{
|
|
359
|
+
"mcpServers": {
|
|
360
|
+
"mode-analytics": {
|
|
361
|
+
"command": "npx",
|
|
362
|
+
"args": ["-y", "@cci-labs/mode-mcp"],
|
|
363
|
+
"env": {
|
|
364
|
+
"MODE_WORKSPACE": "your-workspace",
|
|
365
|
+
"MODE_API_TOKEN": "your-token",
|
|
366
|
+
"MODE_API_SECRET": "your-secret"
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
To find or create your config file, open Claude Desktop settings, click **Developer** in the left sidebar, then click **Edit Config**. The config file is located at:
|
|
374
|
+
|
|
375
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
376
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
377
|
+
|
|
378
|
+
For more information: https://modelcontextprotocol.io/quickstart/user
|
|
379
|
+
|
|
380
|
+
</details>
|
|
381
|
+
|
|
382
|
+
<details>
|
|
383
|
+
<summary><strong>Windsurf</strong></summary>
|
|
384
|
+
|
|
385
|
+
**Prerequisites:**
|
|
386
|
+
- [Mode API token and secret](https://app.mode.com) — generate at `app.mode.com/{workspace}/settings/api_tokens`
|
|
387
|
+
- Docker: [Docker](https://docs.docker.com/get-docker/)
|
|
388
|
+
- NPX: [Node.js >= v22](https://nodejs.org/)
|
|
389
|
+
|
|
390
|
+
#### Using Docker in a local MCP Server
|
|
391
|
+
|
|
392
|
+
Add the following to your Windsurf `mcp_config.json`:
|
|
393
|
+
|
|
394
|
+
```json
|
|
395
|
+
{
|
|
396
|
+
"mcpServers": {
|
|
397
|
+
"mode-analytics": {
|
|
398
|
+
"command": "docker",
|
|
399
|
+
"args": [
|
|
400
|
+
"run", "--rm", "-i",
|
|
401
|
+
"-e", "MODE_WORKSPACE",
|
|
402
|
+
"-e", "MODE_API_TOKEN",
|
|
403
|
+
"-e", "MODE_API_SECRET",
|
|
404
|
+
"-v", "${HOME}/Downloads:/output",
|
|
405
|
+
"ccilabs/mode-mcp"
|
|
406
|
+
],
|
|
407
|
+
"env": {
|
|
408
|
+
"MODE_WORKSPACE": "your-workspace",
|
|
409
|
+
"MODE_API_TOKEN": "your-token",
|
|
410
|
+
"MODE_API_SECRET": "your-secret"
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
#### Using Node.js in a local MCP Server
|
|
418
|
+
|
|
419
|
+
```json
|
|
420
|
+
{
|
|
421
|
+
"mcpServers": {
|
|
422
|
+
"mode-analytics": {
|
|
423
|
+
"command": "node",
|
|
424
|
+
"args": ["/path/to/mode-mcp/dist/index.js"],
|
|
425
|
+
"env": {
|
|
426
|
+
"MODE_WORKSPACE": "your-workspace",
|
|
427
|
+
"MODE_API_TOKEN": "your-token",
|
|
428
|
+
"MODE_API_SECRET": "your-secret"
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
#### Using npx (no install)
|
|
436
|
+
|
|
437
|
+
```json
|
|
438
|
+
{
|
|
439
|
+
"mcpServers": {
|
|
440
|
+
"mode-analytics": {
|
|
441
|
+
"command": "npx",
|
|
442
|
+
"args": ["-y", "@cci-labs/mode-mcp"],
|
|
443
|
+
"env": {
|
|
444
|
+
"MODE_WORKSPACE": "your-workspace",
|
|
445
|
+
"MODE_API_TOKEN": "your-token",
|
|
446
|
+
"MODE_API_SECRET": "your-secret"
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
For more information: https://docs.windsurf.com/windsurf/mcp
|
|
454
|
+
|
|
455
|
+
</details>
|
|
456
|
+
|
|
457
|
+
## Tool Details
|
|
458
|
+
|
|
459
|
+
<details>
|
|
460
|
+
<summary id="mode_list_reports"><strong><code>mode_list_reports</code></strong></summary>
|
|
461
|
+
|
|
462
|
+
Lists reports in the Mode workspace. When no space is specified, fetches reports across all spaces.
|
|
463
|
+
|
|
464
|
+
**Parameters:**
|
|
465
|
+
- `space_token` (optional) — filter reports by space/collection token
|
|
466
|
+
- `filter` (optional) — filter string (e.g. timestamp-based)
|
|
467
|
+
- `order` (optional) — `asc` or `desc`
|
|
468
|
+
- `order_by` (optional) — `created_at` or `updated_at`
|
|
469
|
+
|
|
470
|
+
**Returns:** Numbered list of reports with names, tokens, spaces, query counts, and last run timestamps.
|
|
471
|
+
|
|
472
|
+
**Example prompts:**
|
|
473
|
+
- "What reports are in our Mode workspace?"
|
|
474
|
+
- "List all reports in the Data Science space"
|
|
475
|
+
|
|
476
|
+
</details>
|
|
477
|
+
|
|
478
|
+
<details>
|
|
479
|
+
<summary id="mode_get_report"><strong><code>mode_get_report</code></strong></summary>
|
|
480
|
+
|
|
481
|
+
Gets detailed information about a specific report.
|
|
482
|
+
|
|
483
|
+
**Parameters:**
|
|
484
|
+
- `report_token` (required) — the report token (found in Mode URLs or from `mode_list_reports`)
|
|
485
|
+
|
|
486
|
+
**Returns:** Report name, description, query count, last run timestamp and token, space, and web URL.
|
|
487
|
+
|
|
488
|
+
**Example prompts:**
|
|
489
|
+
- "Show me details for report 578c18655469"
|
|
490
|
+
- "What queries are in the Runner Dashboard report?"
|
|
491
|
+
|
|
492
|
+
</details>
|
|
493
|
+
|
|
494
|
+
<details>
|
|
495
|
+
<summary id="mode_list_queries"><strong><code>mode_list_queries</code></strong></summary>
|
|
496
|
+
|
|
497
|
+
Lists all queries within a report, including their full SQL content.
|
|
498
|
+
|
|
499
|
+
**Parameters:**
|
|
500
|
+
- `report_token` (required) — the report token
|
|
501
|
+
|
|
502
|
+
**Returns:** Query names, tokens, raw SQL previews, data source IDs, and timestamps.
|
|
503
|
+
|
|
504
|
+
**Example prompts:**
|
|
505
|
+
- "Show me the SQL for all queries in report 578c18655469"
|
|
506
|
+
- "What queries does the Runner Dashboard use?"
|
|
507
|
+
|
|
508
|
+
</details>
|
|
509
|
+
|
|
510
|
+
<details>
|
|
511
|
+
<summary id="mode_run_report"><strong><code>mode_run_report</code></strong></summary>
|
|
512
|
+
|
|
513
|
+
Triggers a new run of a Mode report. This is non-destructive — it executes the report's queries but does not modify the report itself.
|
|
514
|
+
|
|
515
|
+
**Parameters:**
|
|
516
|
+
- `report_token` (required) — the report token
|
|
517
|
+
- `parameters` (optional) — key/value parameters to pass to the report run
|
|
518
|
+
|
|
519
|
+
**Returns:** Run token and state. Use `mode_get_run_status` to poll for completion.
|
|
520
|
+
|
|
521
|
+
**Example prompts:**
|
|
522
|
+
- "Run report 578c18655469"
|
|
523
|
+
- "Trigger the weekly metrics report"
|
|
524
|
+
|
|
525
|
+
</details>
|
|
526
|
+
|
|
527
|
+
<details>
|
|
528
|
+
<summary id="mode_get_run_status"><strong><code>mode_get_run_status</code></strong></summary>
|
|
529
|
+
|
|
530
|
+
Checks the status of a report run — whether it has completed, is still running, or failed.
|
|
531
|
+
|
|
532
|
+
**Parameters:**
|
|
533
|
+
- `report_token` (required) — the report token
|
|
534
|
+
- `run_token` (required) — the run token returned by `mode_run_report`
|
|
535
|
+
|
|
536
|
+
**Returns:** Run state, creation time, and completion time.
|
|
537
|
+
|
|
538
|
+
</details>
|
|
539
|
+
|
|
540
|
+
<details>
|
|
541
|
+
<summary id="mode_get_query_results"><strong><code>mode_get_query_results</code></strong></summary>
|
|
542
|
+
|
|
543
|
+
Downloads the results of a completed query run. Returns data as a markdown table and optionally saves a CSV file.
|
|
544
|
+
|
|
545
|
+
**Parameters:**
|
|
546
|
+
- `report_token` (required) — the report token
|
|
547
|
+
- `run_token` (required) — the run token
|
|
548
|
+
- `query_run_token` (required) — the query run token
|
|
549
|
+
- `max_rows` (optional) — maximum rows to return (default: 100)
|
|
550
|
+
- `output_dir` (optional) — directory to save results as CSV. If omitted, results are returned inline only.
|
|
551
|
+
- `filename` (optional) — CSV filename (default: `query-results.csv`)
|
|
552
|
+
|
|
553
|
+
**Returns:** Markdown table with row data. If `output_dir` is provided and writable, also saves the full CSV to disk.
|
|
554
|
+
|
|
555
|
+
**Example prompts:**
|
|
556
|
+
- "Get the results from the latest run of report 578c18655469"
|
|
557
|
+
- "Download the query results as a CSV to /output"
|
|
558
|
+
|
|
559
|
+
</details>
|
|
560
|
+
|
|
561
|
+
<details>
|
|
562
|
+
<summary id="mode_execute_and_fetch"><strong><code>mode_execute_and_fetch</code></strong></summary>
|
|
563
|
+
|
|
564
|
+
The highest-value tool — runs a report, waits for completion (with progressive backoff polling), and returns the query results, all in a single call. Optionally saves results as CSV.
|
|
565
|
+
|
|
566
|
+
**Parameters:**
|
|
567
|
+
- `report_token` (required) — the report token
|
|
568
|
+
- `query_index` (optional) — which query's results to return, 0-based (default: 0)
|
|
569
|
+
- `parameters` (optional) — report parameters
|
|
570
|
+
- `max_rows` (optional) — maximum rows to return (default: 100)
|
|
571
|
+
- `timeout_seconds` (optional) — max seconds to wait (default: 300). Increase for reports with heavy queries.
|
|
572
|
+
- `output_dir` (optional) — directory to save results as CSV. If omitted, results are returned inline only.
|
|
573
|
+
- `filename` (optional) — CSV filename. Defaults to the report name (e.g. `runner-dashboard.csv`).
|
|
574
|
+
|
|
575
|
+
**Returns:** Report and query name, markdown table of results, total row count, and run metadata. If `output_dir` is provided and writable, also saves the full CSV to disk.
|
|
576
|
+
|
|
577
|
+
**Example prompts:**
|
|
578
|
+
- "Run report 578c18655469 and show me the results"
|
|
579
|
+
- "Execute the Runner Dashboard and save the results as CSV"
|
|
580
|
+
|
|
581
|
+
</details>
|
|
582
|
+
|
|
583
|
+
<details>
|
|
584
|
+
<summary id="mode_list_report_runs"><strong><code>mode_list_report_runs</code></strong></summary>
|
|
585
|
+
|
|
586
|
+
Lists past runs for a report with their status and timestamps. Useful for finding run tokens without triggering a new run.
|
|
587
|
+
|
|
588
|
+
**Parameters:**
|
|
589
|
+
- `report_token` (required) — the report token
|
|
590
|
+
|
|
591
|
+
**Returns:** Numbered list of runs with tokens, states (succeeded/failed), and timestamps.
|
|
592
|
+
|
|
593
|
+
**Example prompts:**
|
|
594
|
+
- "Show me the past runs for report 578c18655469"
|
|
595
|
+
- "Has the Runner Dashboard been run recently?"
|
|
596
|
+
|
|
597
|
+
</details>
|
|
598
|
+
|
|
599
|
+
<details>
|
|
600
|
+
<summary id="mode_get_query_run"><strong><code>mode_get_query_run</code></strong></summary>
|
|
601
|
+
|
|
602
|
+
Gets details on a specific query run, including state, timing, SQL, and error details if the query failed.
|
|
603
|
+
|
|
604
|
+
**Parameters:**
|
|
605
|
+
- `report_token` (required) — the report token
|
|
606
|
+
- `run_token` (required) — the run token
|
|
607
|
+
- `query_run_token` (required) — the query run token
|
|
608
|
+
|
|
609
|
+
**Returns:** Query run state, query name, data source, timestamps, SQL preview, and error message if failed.
|
|
610
|
+
|
|
611
|
+
**Example prompts:**
|
|
612
|
+
- "Why did this query fail?"
|
|
613
|
+
- "Show me the details of query run abc123"
|
|
614
|
+
|
|
615
|
+
</details>
|
|
616
|
+
|
|
617
|
+
<details>
|
|
618
|
+
<summary id="mode_search_reports"><strong><code>mode_search_reports</code></strong></summary>
|
|
619
|
+
|
|
620
|
+
Searches reports by name with case-insensitive substring matching. Searches across all spaces by default.
|
|
621
|
+
|
|
622
|
+
**Parameters:**
|
|
623
|
+
- `query` (required) — search string to match against report names
|
|
624
|
+
- `space_token` (optional) — limit search to a specific space
|
|
625
|
+
|
|
626
|
+
**Returns:** Numbered list of matching reports with tokens, spaces, and last run timestamps.
|
|
627
|
+
|
|
628
|
+
**Example prompts:**
|
|
629
|
+
- "Find reports about flaky tests"
|
|
630
|
+
- "Search for 'runner' in our Mode reports"
|
|
631
|
+
|
|
632
|
+
</details>
|
|
633
|
+
|
|
634
|
+
<details>
|
|
635
|
+
<summary id="mode_get_report_parameters"><strong><code>mode_get_report_parameters</code></strong></summary>
|
|
636
|
+
|
|
637
|
+
Discovers what parameters a report accepts before running it. Inspects the last successful run's form fields for parameter names, types, defaults, last-used values, and available dropdown options. If no prior runs exist, falls back to scanning query SQL for `{{ template_variable }}` patterns.
|
|
638
|
+
|
|
639
|
+
**Parameters:**
|
|
640
|
+
- `report_token` (required) — the report token
|
|
641
|
+
|
|
642
|
+
**Returns:** Parameter names, types (text, dropdown, etc.), default values, last-used values, and available options.
|
|
643
|
+
|
|
644
|
+
**Example prompts:**
|
|
645
|
+
- "What parameters does this report need?"
|
|
646
|
+
- "Check the inputs for the Cost Optimization report before running it"
|
|
647
|
+
- "Does report 3d3b95474b93 require any parameters?"
|
|
648
|
+
|
|
649
|
+
> **Note:** Always call this before `mode_execute_and_fetch`, `mode_run_report`, or `mode_export_report` — reports run with default parameters rarely produce the desired results.
|
|
650
|
+
|
|
651
|
+
</details>
|
|
652
|
+
|
|
653
|
+
<details>
|
|
654
|
+
<summary id="mode_list_spaces"><strong><code>mode_list_spaces</code></strong></summary>
|
|
655
|
+
|
|
656
|
+
Lists all spaces (collections) in the workspace. Spaces organize reports into groups.
|
|
657
|
+
|
|
658
|
+
**Parameters:**
|
|
659
|
+
- `filter` (optional) — `all` (default) or `custom` (non-personal spaces only)
|
|
660
|
+
|
|
661
|
+
**Returns:** Numbered list of spaces with tokens, types, and restricted status.
|
|
662
|
+
|
|
663
|
+
**Example prompts:**
|
|
664
|
+
- "What spaces are in our Mode workspace?"
|
|
665
|
+
- "List all collections"
|
|
666
|
+
|
|
667
|
+
</details>
|
|
668
|
+
|
|
669
|
+
<details>
|
|
670
|
+
<summary id="mode_list_data_sources"><strong><code>mode_list_data_sources</code></strong></summary>
|
|
671
|
+
|
|
672
|
+
Lists all connected data sources (databases) in the workspace.
|
|
673
|
+
|
|
674
|
+
**Parameters:** None.
|
|
675
|
+
|
|
676
|
+
**Returns:** Numbered list of data sources with adapter types (e.g. Snowflake, Postgres), hosts, and databases.
|
|
677
|
+
|
|
678
|
+
**Example prompts:**
|
|
679
|
+
- "What databases are connected to Mode?"
|
|
680
|
+
- "Show me our data sources"
|
|
681
|
+
|
|
682
|
+
</details>
|
|
683
|
+
|
|
684
|
+
<details>
|
|
685
|
+
<summary id="mode_list_definitions"><strong><code>mode_list_definitions</code></strong></summary>
|
|
686
|
+
|
|
687
|
+
Lists saved SQL definitions (reusable snippets/macros) available in the workspace.
|
|
688
|
+
|
|
689
|
+
**Parameters:** None.
|
|
690
|
+
|
|
691
|
+
**Returns:** Numbered list of definitions with SQL previews and associated data sources.
|
|
692
|
+
|
|
693
|
+
**Example prompts:**
|
|
694
|
+
- "What SQL definitions do we have?"
|
|
695
|
+
- "Show me our saved SQL snippets"
|
|
696
|
+
|
|
697
|
+
> **Note:** This endpoint may not be available on all Mode plan tiers.
|
|
698
|
+
|
|
699
|
+
</details>
|
|
700
|
+
|
|
701
|
+
<details>
|
|
702
|
+
<summary id="mode_export_report"><strong><code>mode_export_report</code></strong></summary>
|
|
703
|
+
|
|
704
|
+
Exports a report as PDF or CSV. For PDF, triggers generation with progressive backoff polling. For CSV, fetches raw query results. If `output_dir` is provided and writable, saves the file to disk.
|
|
705
|
+
|
|
706
|
+
**Parameters:**
|
|
707
|
+
- `report_token` (required) — the report token
|
|
708
|
+
- `format` (required) — `pdf` for a rendered report with charts, `csv` for raw query data
|
|
709
|
+
- `run_token` (optional) — the run token. If omitted, uses the last successful run.
|
|
710
|
+
- `query_index` (optional) — for CSV: which query to export, 0-based (default: 0). Ignored for PDF.
|
|
711
|
+
- `filename` (optional) — output filename (default: report name with `.pdf` or `.csv` extension)
|
|
712
|
+
- `output_dir` (optional) — directory to save the file. If omitted or not writable, returns a download URL (PDF) or inline preview (CSV).
|
|
713
|
+
|
|
714
|
+
**Returns:** Saved file path/size if written to disk, download URL for PDF, or inline CSV preview for small datasets.
|
|
715
|
+
|
|
716
|
+
> **Note:** Always call `mode_get_report_parameters` first to check if the report requires parameters. If it does, run it with `mode_run_report` (passing the right parameters) and use the resulting `run_token` here.
|
|
717
|
+
|
|
718
|
+
**Example prompts:**
|
|
719
|
+
- "Export the Runner Dashboard as PDF"
|
|
720
|
+
- "Download the Cost Optimization report as CSV for org infusionsoft"
|
|
721
|
+
- "Get a PDF of report 3d3b95474b93 for billing org common-room"
|
|
722
|
+
|
|
723
|
+
</details>
|
|
724
|
+
|
|
725
|
+
## Configuration
|
|
726
|
+
|
|
727
|
+
| Variable | Required | Description |
|
|
728
|
+
|----------|----------|-------------|
|
|
729
|
+
| `MODE_WORKSPACE` | Yes | Your Mode workspace name (the slug in Mode URLs) |
|
|
730
|
+
| `MODE_API_TOKEN` | Yes | API token from Mode |
|
|
731
|
+
| `MODE_API_SECRET` | Yes | API secret from Mode |
|
|
732
|
+
| `MODE_MAX_ROWS` | No | Max rows returned per query (default: `100`) |
|
|
733
|
+
| `MODE_POLL_INTERVAL_MS` | No | Initial polling interval in ms (default: `2000`). Increases with progressive backoff. |
|
|
734
|
+
| `MODE_POLL_TIMEOUT_MS` | No | Max time to wait for a run/export in ms (default: `300000` / 5 minutes) |
|
|
735
|
+
| `MODE_BASE_URL` | No | Mode API base URL (default: `https://app.mode.com`) |
|
|
736
|
+
| `MODE_MAX_OUTPUT_LENGTH` | No | Max characters in tool output before truncation (default: `50000`) |
|
|
737
|
+
|
|
738
|
+
## CI/CD
|
|
739
|
+
|
|
740
|
+
This project uses [CircleCI](https://circleci.com) for continuous integration and deployment.
|
|
741
|
+
|
|
742
|
+
**Every push:**
|
|
743
|
+
- **Lint** — TypeScript type checking + ESLint
|
|
744
|
+
- **Test** — full test suite with coverage reporting (JUnit for Test Insights)
|
|
745
|
+
- **Audit Dependencies** — npm audit + Trivy filesystem scan (vulns, secrets, misconfig, licenses) + SBOM generation
|
|
746
|
+
- **Build Docker Image** — multi-arch (amd64 + arm64), pushed with SHA tags
|
|
747
|
+
- **Test Docker Image** — dgoss container structure tests per architecture
|
|
748
|
+
- **Scan Docker Image** — Trivy vulnerability + license scan per architecture
|
|
749
|
+
|
|
750
|
+
**On `v*` tags (releases):**
|
|
751
|
+
- **Publish Docker Image** — retags SHA images, creates multi-arch manifest with version + latest tags
|
|
752
|
+
- **Publish npm Package** — publishes `@cci-labs/mode-mcp` to npm
|
|
753
|
+
|
|
754
|
+
## Safety
|
|
755
|
+
|
|
756
|
+
This server is **read-only by design**. It cannot create, modify, or delete any resources in Mode. The only "write" operations are:
|
|
757
|
+
- **Triggering report runs** — executes existing queries but does not change the report
|
|
758
|
+
- **Triggering PDF exports** — generates a PDF from an existing run
|
|
759
|
+
|
|
760
|
+
## Troubleshooting
|
|
761
|
+
|
|
762
|
+
<details>
|
|
763
|
+
<summary><strong>Authentication Issues</strong></summary>
|
|
764
|
+
|
|
765
|
+
- **401 Unauthorized:** Verify your `MODE_API_TOKEN` and `MODE_API_SECRET` at `app.mode.com/{workspace}/settings/api_tokens`
|
|
766
|
+
- **403 Forbidden:** Your token may lack permission. Workspace admin tokens are required for some endpoints.
|
|
767
|
+
- **"account not found":** Double-check `MODE_WORKSPACE` — it should be the slug from your Mode URL (e.g. `my-company`, not the display name).
|
|
768
|
+
|
|
769
|
+
</details>
|
|
770
|
+
|
|
771
|
+
<details>
|
|
772
|
+
<summary><strong>Rate Limiting</strong></summary>
|
|
773
|
+
|
|
774
|
+
Mode's API allows 40 requests per 10-second window (~4 req/sec). The server automatically:
|
|
775
|
+
- Throttles to stay under the limit (35 req/10s with headroom)
|
|
776
|
+
- Reads `X-RateLimit-Remaining` and `X-RateLimit-Reset` headers from every response
|
|
777
|
+
- Proactively slows down when remaining requests < 5
|
|
778
|
+
- Retries on 429 responses using the server-provided reset time
|
|
779
|
+
- Retries transient 5xx errors up to 3 times with exponential backoff
|
|
780
|
+
|
|
781
|
+
</details>
|
|
782
|
+
|
|
783
|
+
<details>
|
|
784
|
+
<summary><strong>Timeouts and Long-Running Reports</strong></summary>
|
|
785
|
+
|
|
786
|
+
The server uses **progressive backoff** when polling for report runs and PDF exports:
|
|
787
|
+
- Starts polling every 2 seconds
|
|
788
|
+
- Increases interval by 1.5x each poll (2s → 3s → 4.5s → 6.75s → 10s → 15s)
|
|
789
|
+
- Caps at 15-second intervals
|
|
790
|
+
- Default maximum wait: 5 minutes (`MODE_POLL_TIMEOUT_MS=300000`)
|
|
791
|
+
|
|
792
|
+
For reports with heavy queries (e.g. large Snowflake warehouses), you can:
|
|
793
|
+
- Pass a higher `timeout_seconds` to `mode_execute_and_fetch` (e.g. `600` for 10 minutes)
|
|
794
|
+
- Increase the global default with `MODE_POLL_TIMEOUT_MS`
|
|
795
|
+
- Use `mode_run_report` + `mode_get_run_status` to poll manually
|
|
796
|
+
|
|
797
|
+
</details>
|
|
798
|
+
|
|
799
|
+
<details>
|
|
800
|
+
<summary><strong>Docker Issues</strong></summary>
|
|
801
|
+
|
|
802
|
+
- **Environment variables not reaching container:** Ensure you have both the `-e VAR_NAME` in `args` AND the value in `env`. The MCP client sets the env var, and `-e` forwards it into the container.
|
|
803
|
+
- **Image not found:** Build with `docker build -t ccilabs/mode-mcp .` from the project root.
|
|
804
|
+
- **Network errors inside container:** Docker Desktop must be running. On macOS, ensure Docker has network access.
|
|
805
|
+
- **File downloads not working:** When running in Docker, the `output_dir` parameter writes inside the container. To save files to your host machine, add a volume mount to your Docker args:
|
|
806
|
+
```json
|
|
807
|
+
"args": [
|
|
808
|
+
"run", "--rm", "-i",
|
|
809
|
+
"-e", "MODE_WORKSPACE",
|
|
810
|
+
"-e", "MODE_API_TOKEN",
|
|
811
|
+
"-e", "MODE_API_SECRET",
|
|
812
|
+
"-v", "/Users/you/Downloads:/output",
|
|
813
|
+
"ccilabs/mode-mcp"
|
|
814
|
+
]
|
|
815
|
+
```
|
|
816
|
+
Then use `/output` as the `output_dir`. Without a mount, the tools still return download URLs as a fallback.
|
|
817
|
+
|
|
818
|
+
</details>
|
|
819
|
+
|
|
820
|
+
<details>
|
|
821
|
+
<summary><strong>Common Errors</strong></summary>
|
|
822
|
+
|
|
823
|
+
- **"Report not found" (404):** The report token may be wrong. Use `mode_list_reports` or `mode_search_reports` to find valid tokens. Report tokens are the alphanumeric strings in Mode URLs (e.g. `578c18655469`).
|
|
824
|
+
- **Empty results:** The report may not have been run recently. Use `mode_execute_and_fetch` to trigger a fresh run.
|
|
825
|
+
- **Polling timeout:** Increase `timeout_seconds` for long-running reports, or increase `MODE_POLL_TIMEOUT_MS`.
|
|
826
|
+
- **"PDF export is not available":** The export may have expired. Run the report again with `mode_run_report`, then export the new run.
|
|
827
|
+
|
|
828
|
+
</details>
|
|
829
|
+
|
|
830
|
+
# Development
|
|
831
|
+
|
|
832
|
+
## Getting Started
|
|
833
|
+
|
|
834
|
+
1. Clone the repository:
|
|
835
|
+
|
|
836
|
+
```bash
|
|
837
|
+
git clone https://github.com/AwesomeCICD/mode-mcp.git
|
|
838
|
+
cd mode-mcp
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
2. Install dependencies:
|
|
842
|
+
|
|
843
|
+
```bash
|
|
844
|
+
npm install
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
3. Build the project:
|
|
848
|
+
|
|
849
|
+
```bash
|
|
850
|
+
npm run build
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
4. Create a `.env` file:
|
|
854
|
+
|
|
855
|
+
```
|
|
856
|
+
MODE_WORKSPACE=your-workspace
|
|
857
|
+
MODE_API_TOKEN=your-token
|
|
858
|
+
MODE_API_SECRET=your-secret
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
5. Run linting and tests:
|
|
862
|
+
|
|
863
|
+
```bash
|
|
864
|
+
npm run lint # TypeScript type check + ESLint
|
|
865
|
+
npm test # Run all tests
|
|
866
|
+
```
|
|
867
|
+
|
|
868
|
+
## Building Docker Container
|
|
869
|
+
|
|
870
|
+
```bash
|
|
871
|
+
docker build -t ccilabs/mode-mcp .
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
To test the container:
|
|
875
|
+
|
|
876
|
+
```bash
|
|
877
|
+
export MODE_WORKSPACE=your-workspace
|
|
878
|
+
export MODE_API_TOKEN=your-token
|
|
879
|
+
export MODE_API_SECRET=your-secret
|
|
880
|
+
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' \
|
|
881
|
+
| docker run --rm -i -e MODE_WORKSPACE -e MODE_API_TOKEN -e MODE_API_SECRET ccilabs/mode-mcp
|
|
882
|
+
```
|
|
883
|
+
|
|
884
|
+
## Project Structure
|
|
885
|
+
|
|
886
|
+
```
|
|
887
|
+
src/
|
|
888
|
+
├── index.ts # MCP server entry point (stdio transport)
|
|
889
|
+
├── config.ts # Environment variable loading and validation
|
|
890
|
+
├── mode-client.ts # Mode API HTTP client (auth, rate limiting, retries, HAL+JSON)
|
|
891
|
+
├── file-utils.ts # File saving utilities (slugify, trySaveFile)
|
|
892
|
+
├── truncate.ts # Output truncation for LLM context limits
|
|
893
|
+
├── utils.ts # Shared formatters (dates, errors, markdown tables, CSV parsing)
|
|
894
|
+
├── __tests__/ # Unit tests (vitest, all mocked — no live API needed)
|
|
895
|
+
└── tools/
|
|
896
|
+
├── analytics.ts # Report, query, run, search, filter, and chart tools
|
|
897
|
+
├── management.ts # Spaces, data sources, definitions, schedules, subscriptions, audit logs
|
|
898
|
+
├── datasets.ts # Dataset discovery and field inspection tools
|
|
899
|
+
└── distribution.ts # PDF and CSV export tools
|
|
900
|
+
docs/
|
|
901
|
+
├── MCP_TEST_PLAYBOOK.md # Manual integration test prompts (34 tests across 9 categories)
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
## Testing
|
|
905
|
+
|
|
906
|
+
```bash
|
|
907
|
+
npm test # Run all tests
|
|
908
|
+
npm run test:watch # Watch mode
|
|
909
|
+
npx vitest run --coverage # Run with coverage report
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
129+ tests covering all 24 tools, CSV parsing, Mode client (auth, rate limiting, retries, polling), config loading, file utilities, and output formatting. All tests use mocked API responses — no live credentials required.
|
|
913
|
+
|
|
914
|
+
### Integration Testing
|
|
915
|
+
|
|
916
|
+
For manual integration testing with a live MCP connection, see the [MCP Test Playbook](docs/MCP_TEST_PLAYBOOK.md) — 34 structured prompts across 9 categories that validate tool calls, chaining, error handling, and read-only safety.
|
|
917
|
+
|
|
918
|
+
### Docker Testing
|
|
919
|
+
|
|
920
|
+
Container structure tests use [dgoss](https://github.com/goss-org/goss/tree/master/extras/dgoss):
|
|
921
|
+
|
|
922
|
+
```bash
|
|
923
|
+
# Requires goss/dgoss installed and a Linux goss binary for container exec
|
|
924
|
+
dgoss run --entrypoint /bin/sh ccilabs/mode-mcp:test -c "sleep 30"
|
|
925
|
+
```
|