mode-mcp 0.1.0__tar.gz
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.
- mode_mcp-0.1.0/.gitignore +9 -0
- mode_mcp-0.1.0/LICENSE +21 -0
- mode_mcp-0.1.0/PKG-INFO +138 -0
- mode_mcp-0.1.0/README.md +117 -0
- mode_mcp-0.1.0/pyproject.toml +40 -0
- mode_mcp-0.1.0/src/mode_mcp/__init__.py +3 -0
- mode_mcp-0.1.0/src/mode_mcp/server.py +858 -0
- mode_mcp-0.1.0/test_server.py +1059 -0
mode_mcp-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Natalie Mona Matthews
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
mode_mcp-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: mode-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server for Mode Analytics — browse reports, manage queries, and fetch results
|
|
5
|
+
Author: Natalie Mona Matthews
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: analytics,mcp,mode,sql
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
16
|
+
Classifier: Topic :: Database
|
|
17
|
+
Requires-Python: >=3.12
|
|
18
|
+
Requires-Dist: httpx>=0.27.0
|
|
19
|
+
Requires-Dist: mcp[cli]>=2.3.0
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
|
|
22
|
+
# Mode Analytics MCP Server
|
|
23
|
+
|
|
24
|
+
An MCP server that lets you browse reports, manage queries, and fetch results from [Mode Analytics](https://mode.com) from any MCP-compatible AI assistant or agent.
|
|
25
|
+
|
|
26
|
+
## Tools
|
|
27
|
+
|
|
28
|
+
| Tool | Description |
|
|
29
|
+
|---|---|
|
|
30
|
+
| `list_data_sources` | List all database connections in the workspace |
|
|
31
|
+
| `list_spaces` | List all spaces (collections) |
|
|
32
|
+
| `list_reports` | List reports in a given space (archived ones hidden unless `include_archived=true`) |
|
|
33
|
+
| `search_reports` | Search for reports by name or description across all spaces (client-side; archived ones hidden unless `include_archived=true`) |
|
|
34
|
+
| `get_report` | Get report details including its SQL queries and who wrote each one |
|
|
35
|
+
| `list_report_runs` | List recent runs for a report (state, timestamps) |
|
|
36
|
+
| `get_run_results` | Fetch results from a specific or latest report run |
|
|
37
|
+
| `create_report` | Create a new report in a space, optionally with initial queries |
|
|
38
|
+
| `update_report` | Update a report's name, description, or move it to a different space |
|
|
39
|
+
| `archive_report` | Archive (hide) a report — reversible |
|
|
40
|
+
| `unarchive_report` | Restore an archived report |
|
|
41
|
+
| `delete_report` | Permanently delete a report (preview first, then confirm). Off unless `MODE_ENABLE_DELETES=true` |
|
|
42
|
+
| `add_query` | Add a SQL query to an existing report |
|
|
43
|
+
| `update_query` | Update a query's SQL, name, or data source |
|
|
44
|
+
| `delete_query` | Permanently delete a query (preview first, then confirm). Off unless `MODE_ENABLE_DELETES=true` |
|
|
45
|
+
|
|
46
|
+
## Setup
|
|
47
|
+
|
|
48
|
+
### 1. Get Mode API credentials
|
|
49
|
+
|
|
50
|
+
A Workspace admin creates the token in Mode under **Workspace Settings > Privacy & Security > API**: click the gear icon, choose **Create new API token**, and save the token and secret.
|
|
51
|
+
|
|
52
|
+
Mode no longer allows creating new *personal* API tokens (existing ones keep working). Workspace API tokens act with admin access to the whole Workspace, so treat them accordingly — see **Limitations / Safety** below.
|
|
53
|
+
|
|
54
|
+
### 2. Install uv
|
|
55
|
+
|
|
56
|
+
The server is launched with `uvx`, which comes with [uv](https://docs.astral.sh/uv/getting-started/installation/). Install it with `brew install uv` or `curl -LsSf https://astral.sh/uv/install.sh | sh`.
|
|
57
|
+
|
|
58
|
+
### 3. Add the server to your MCP client
|
|
59
|
+
|
|
60
|
+
The server runs over stdio via `uvx mode-mcp`. Add it to your MCP client's config; most clients use this `mcpServers` shape:
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"mcpServers": {
|
|
65
|
+
"mode-analytics": {
|
|
66
|
+
"command": "uvx",
|
|
67
|
+
"args": ["mode-mcp"],
|
|
68
|
+
"env": {
|
|
69
|
+
"MODE_WORKSPACE": "your-workspace-name",
|
|
70
|
+
"MODE_API_TOKEN": "${MODE_API_TOKEN}",
|
|
71
|
+
"MODE_API_SECRET": "${MODE_API_SECRET}"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`uvx` installs the package from PyPI on first run and reuses that version afterwards. To pick up new releases automatically, use `"args": ["mode-mcp@latest"]` instead.
|
|
79
|
+
|
|
80
|
+
The `${MODE_API_TOKEN}` / `${MODE_API_SECRET}` references are expanded from your shell environment by clients that support it, so no secrets land in the config file. Set them wherever you keep shell secrets, e.g. in `~/.zshrc`:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
export MODE_API_TOKEN="..."
|
|
84
|
+
export MODE_API_SECRET="..."
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Env var syntax differs by client
|
|
88
|
+
|
|
89
|
+
Some clients expand `${VAR}`, some use another syntax (e.g. `${env:VAR}`), and some don't expand references at all; check your client's docs. If a reference isn't expanded, the server stops at startup with an error naming the variable, rather than failing later with a confusing authentication error.
|
|
90
|
+
|
|
91
|
+
## Environment Variables
|
|
92
|
+
|
|
93
|
+
| Variable | Required | Description |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| `MODE_WORKSPACE` | Yes | Your Workspace's username, as in `app.mode.com/<workspace>/...` |
|
|
96
|
+
| `MODE_API_TOKEN` | Yes | API token |
|
|
97
|
+
| `MODE_API_SECRET` | Yes | API secret |
|
|
98
|
+
| `MODE_ENABLE_DELETES` | No | Set to `true` to enable `delete_report` and `delete_query`. Off by default |
|
|
99
|
+
| `MODE_READ_ONLY` | No | Set to `true` to disable every tool that writes to Mode (overrides `MODE_ENABLE_DELETES`) |
|
|
100
|
+
| `MODE_DISABLED_TOOLS` | No | Comma-separated tool names to disable, e.g. `create_report,update_query` |
|
|
101
|
+
|
|
102
|
+
### Choosing which tools are available
|
|
103
|
+
|
|
104
|
+
Disabled tools are never registered, so the agent doesn't see them at all.
|
|
105
|
+
|
|
106
|
+
- **Default:** everything except the two delete tools. The agent can browse, author, and archive, but can't permanently delete anything.
|
|
107
|
+
- **Allow deletes:** add `"MODE_ENABLE_DELETES": "true"` to `env`.
|
|
108
|
+
- **Read-only:** add `"MODE_READ_ONLY": "true"` to only allow browsing and fetching results.
|
|
109
|
+
- **Anything else:** list tool names in `MODE_DISABLED_TOOLS`.
|
|
110
|
+
|
|
111
|
+
A misspelled tool name in `MODE_DISABLED_TOOLS` stops the server with an error rather than silently leaving the tool enabled.
|
|
112
|
+
|
|
113
|
+
## Limitations / Safety
|
|
114
|
+
|
|
115
|
+
**No query execution.** The server deliberately does not expose a "run this query" tool. The Mode API has no endpoint for running a single query — the only way to execute SQL is `POST /reports/{token}/runs`, which runs **every** query in the report at once. On reports with many or expensive queries, that's slow, costly, and impossible to predict from the agent's side. Instead, the server focuses on **browsing**, **authoring**, and **fetching results**:
|
|
116
|
+
- Write and manage SQL queries through your agent, then run them in Mode's UI where costs and side effects are visible.
|
|
117
|
+
- Use `get_run_results` to pull results from completed runs back into the conversation.
|
|
118
|
+
|
|
119
|
+
**Deletes are permission-scoped, not owner-scoped.** The server does not check who created a report or query; what you can delete is whatever your API token is allowed to delete in Mode. With a personal token that's limited to your own permissions, but a Workspace API token has admin access and can delete **any** report or query in the Workspace. That's why the delete tools are off unless you set `MODE_ENABLE_DELETES=true`.
|
|
120
|
+
|
|
121
|
+
**Deletes can't skip the preview.** When enabled, `delete_report` and `delete_query` are always two calls:
|
|
122
|
+
1. The first call deletes nothing. It returns a preview (the report's name, whether it's already archived, and its queries with who wrote each one; or a query's name, author, and SQL) plus a short `confirm_code`. Mode's API doesn't say who created a report, only who wrote each query.
|
|
123
|
+
2. The delete only happens when the same tool is called again with that `confirm_code`. The code is a fingerprint of what the preview showed, so it can't be guessed, and if the report or query changed after the preview (renamed, SQL edited, queries added), the code no longer matches and the delete is refused.
|
|
124
|
+
|
|
125
|
+
**Archive instead of delete.** `archive_report` hides a report and `unarchive_report` brings it back. The delete tool tells the agent to suggest archiving first.
|
|
126
|
+
|
|
127
|
+
**Credentials never touch the committed config.** The `${MODE_API_TOKEN}` / `${MODE_API_SECRET}` references in your MCP config are expanded from your shell environment at launch (in clients that support it), so the file is safe to commit. Keep the raw secrets in env vars and don't commit them.
|
|
128
|
+
|
|
129
|
+
## Development
|
|
130
|
+
|
|
131
|
+
For maintainers (the source repo is private):
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
git clone git@github.com:nataliemona/mode_mcp.git
|
|
135
|
+
cd mode_mcp
|
|
136
|
+
uv sync --dev
|
|
137
|
+
uv run pytest
|
|
138
|
+
```
|
mode_mcp-0.1.0/README.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Mode Analytics MCP Server
|
|
2
|
+
|
|
3
|
+
An MCP server that lets you browse reports, manage queries, and fetch results from [Mode Analytics](https://mode.com) from any MCP-compatible AI assistant or agent.
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
6
|
+
|
|
7
|
+
| Tool | Description |
|
|
8
|
+
|---|---|
|
|
9
|
+
| `list_data_sources` | List all database connections in the workspace |
|
|
10
|
+
| `list_spaces` | List all spaces (collections) |
|
|
11
|
+
| `list_reports` | List reports in a given space (archived ones hidden unless `include_archived=true`) |
|
|
12
|
+
| `search_reports` | Search for reports by name or description across all spaces (client-side; archived ones hidden unless `include_archived=true`) |
|
|
13
|
+
| `get_report` | Get report details including its SQL queries and who wrote each one |
|
|
14
|
+
| `list_report_runs` | List recent runs for a report (state, timestamps) |
|
|
15
|
+
| `get_run_results` | Fetch results from a specific or latest report run |
|
|
16
|
+
| `create_report` | Create a new report in a space, optionally with initial queries |
|
|
17
|
+
| `update_report` | Update a report's name, description, or move it to a different space |
|
|
18
|
+
| `archive_report` | Archive (hide) a report — reversible |
|
|
19
|
+
| `unarchive_report` | Restore an archived report |
|
|
20
|
+
| `delete_report` | Permanently delete a report (preview first, then confirm). Off unless `MODE_ENABLE_DELETES=true` |
|
|
21
|
+
| `add_query` | Add a SQL query to an existing report |
|
|
22
|
+
| `update_query` | Update a query's SQL, name, or data source |
|
|
23
|
+
| `delete_query` | Permanently delete a query (preview first, then confirm). Off unless `MODE_ENABLE_DELETES=true` |
|
|
24
|
+
|
|
25
|
+
## Setup
|
|
26
|
+
|
|
27
|
+
### 1. Get Mode API credentials
|
|
28
|
+
|
|
29
|
+
A Workspace admin creates the token in Mode under **Workspace Settings > Privacy & Security > API**: click the gear icon, choose **Create new API token**, and save the token and secret.
|
|
30
|
+
|
|
31
|
+
Mode no longer allows creating new *personal* API tokens (existing ones keep working). Workspace API tokens act with admin access to the whole Workspace, so treat them accordingly — see **Limitations / Safety** below.
|
|
32
|
+
|
|
33
|
+
### 2. Install uv
|
|
34
|
+
|
|
35
|
+
The server is launched with `uvx`, which comes with [uv](https://docs.astral.sh/uv/getting-started/installation/). Install it with `brew install uv` or `curl -LsSf https://astral.sh/uv/install.sh | sh`.
|
|
36
|
+
|
|
37
|
+
### 3. Add the server to your MCP client
|
|
38
|
+
|
|
39
|
+
The server runs over stdio via `uvx mode-mcp`. Add it to your MCP client's config; most clients use this `mcpServers` shape:
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"mcpServers": {
|
|
44
|
+
"mode-analytics": {
|
|
45
|
+
"command": "uvx",
|
|
46
|
+
"args": ["mode-mcp"],
|
|
47
|
+
"env": {
|
|
48
|
+
"MODE_WORKSPACE": "your-workspace-name",
|
|
49
|
+
"MODE_API_TOKEN": "${MODE_API_TOKEN}",
|
|
50
|
+
"MODE_API_SECRET": "${MODE_API_SECRET}"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`uvx` installs the package from PyPI on first run and reuses that version afterwards. To pick up new releases automatically, use `"args": ["mode-mcp@latest"]` instead.
|
|
58
|
+
|
|
59
|
+
The `${MODE_API_TOKEN}` / `${MODE_API_SECRET}` references are expanded from your shell environment by clients that support it, so no secrets land in the config file. Set them wherever you keep shell secrets, e.g. in `~/.zshrc`:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
export MODE_API_TOKEN="..."
|
|
63
|
+
export MODE_API_SECRET="..."
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Env var syntax differs by client
|
|
67
|
+
|
|
68
|
+
Some clients expand `${VAR}`, some use another syntax (e.g. `${env:VAR}`), and some don't expand references at all; check your client's docs. If a reference isn't expanded, the server stops at startup with an error naming the variable, rather than failing later with a confusing authentication error.
|
|
69
|
+
|
|
70
|
+
## Environment Variables
|
|
71
|
+
|
|
72
|
+
| Variable | Required | Description |
|
|
73
|
+
|---|---|---|
|
|
74
|
+
| `MODE_WORKSPACE` | Yes | Your Workspace's username, as in `app.mode.com/<workspace>/...` |
|
|
75
|
+
| `MODE_API_TOKEN` | Yes | API token |
|
|
76
|
+
| `MODE_API_SECRET` | Yes | API secret |
|
|
77
|
+
| `MODE_ENABLE_DELETES` | No | Set to `true` to enable `delete_report` and `delete_query`. Off by default |
|
|
78
|
+
| `MODE_READ_ONLY` | No | Set to `true` to disable every tool that writes to Mode (overrides `MODE_ENABLE_DELETES`) |
|
|
79
|
+
| `MODE_DISABLED_TOOLS` | No | Comma-separated tool names to disable, e.g. `create_report,update_query` |
|
|
80
|
+
|
|
81
|
+
### Choosing which tools are available
|
|
82
|
+
|
|
83
|
+
Disabled tools are never registered, so the agent doesn't see them at all.
|
|
84
|
+
|
|
85
|
+
- **Default:** everything except the two delete tools. The agent can browse, author, and archive, but can't permanently delete anything.
|
|
86
|
+
- **Allow deletes:** add `"MODE_ENABLE_DELETES": "true"` to `env`.
|
|
87
|
+
- **Read-only:** add `"MODE_READ_ONLY": "true"` to only allow browsing and fetching results.
|
|
88
|
+
- **Anything else:** list tool names in `MODE_DISABLED_TOOLS`.
|
|
89
|
+
|
|
90
|
+
A misspelled tool name in `MODE_DISABLED_TOOLS` stops the server with an error rather than silently leaving the tool enabled.
|
|
91
|
+
|
|
92
|
+
## Limitations / Safety
|
|
93
|
+
|
|
94
|
+
**No query execution.** The server deliberately does not expose a "run this query" tool. The Mode API has no endpoint for running a single query — the only way to execute SQL is `POST /reports/{token}/runs`, which runs **every** query in the report at once. On reports with many or expensive queries, that's slow, costly, and impossible to predict from the agent's side. Instead, the server focuses on **browsing**, **authoring**, and **fetching results**:
|
|
95
|
+
- Write and manage SQL queries through your agent, then run them in Mode's UI where costs and side effects are visible.
|
|
96
|
+
- Use `get_run_results` to pull results from completed runs back into the conversation.
|
|
97
|
+
|
|
98
|
+
**Deletes are permission-scoped, not owner-scoped.** The server does not check who created a report or query; what you can delete is whatever your API token is allowed to delete in Mode. With a personal token that's limited to your own permissions, but a Workspace API token has admin access and can delete **any** report or query in the Workspace. That's why the delete tools are off unless you set `MODE_ENABLE_DELETES=true`.
|
|
99
|
+
|
|
100
|
+
**Deletes can't skip the preview.** When enabled, `delete_report` and `delete_query` are always two calls:
|
|
101
|
+
1. The first call deletes nothing. It returns a preview (the report's name, whether it's already archived, and its queries with who wrote each one; or a query's name, author, and SQL) plus a short `confirm_code`. Mode's API doesn't say who created a report, only who wrote each query.
|
|
102
|
+
2. The delete only happens when the same tool is called again with that `confirm_code`. The code is a fingerprint of what the preview showed, so it can't be guessed, and if the report or query changed after the preview (renamed, SQL edited, queries added), the code no longer matches and the delete is refused.
|
|
103
|
+
|
|
104
|
+
**Archive instead of delete.** `archive_report` hides a report and `unarchive_report` brings it back. The delete tool tells the agent to suggest archiving first.
|
|
105
|
+
|
|
106
|
+
**Credentials never touch the committed config.** The `${MODE_API_TOKEN}` / `${MODE_API_SECRET}` references in your MCP config are expanded from your shell environment at launch (in clients that support it), so the file is safe to commit. Keep the raw secrets in env vars and don't commit them.
|
|
107
|
+
|
|
108
|
+
## Development
|
|
109
|
+
|
|
110
|
+
For maintainers (the source repo is private):
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
git clone git@github.com:nataliemona/mode_mcp.git
|
|
114
|
+
cd mode_mcp
|
|
115
|
+
uv sync --dev
|
|
116
|
+
uv run pytest
|
|
117
|
+
```
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "mode-mcp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "MCP server for Mode Analytics — browse reports, manage queries, and fetch results"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Natalie Mona Matthews" }]
|
|
14
|
+
keywords = ["mcp", "mode", "analytics", "sql"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Programming Language :: Python :: 3.14",
|
|
23
|
+
"Topic :: Database",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"mcp[cli]>=2.3.0",
|
|
27
|
+
"httpx>=0.27.0",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[dependency-groups]
|
|
31
|
+
dev = ["pytest>=8.0", "pytest-asyncio>=0.24", "respx>=0.22"]
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
mode-mcp = "mode_mcp:main"
|
|
35
|
+
|
|
36
|
+
[tool.hatch.build.targets.wheel]
|
|
37
|
+
packages = ["src/mode_mcp"]
|
|
38
|
+
|
|
39
|
+
[tool.hatch.build.targets.sdist]
|
|
40
|
+
include = ["src/mode_mcp", "test_server.py", "README.md", "LICENSE"]
|