mcp-server-motherduck 0.5.1__tar.gz → 0.6.1__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.

Potentially problematic release.


This version of mcp-server-motherduck might be problematic. Click here for more details.

Files changed (22) hide show
  1. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/.idea/workspace.xml +44 -2
  2. mcp_server_motherduck-0.5.1/README.md → mcp_server_motherduck-0.6.1/PKG-INFO +63 -32
  3. mcp_server_motherduck-0.5.1/PKG-INFO → mcp_server_motherduck-0.6.1/README.md +47 -44
  4. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/pyproject.toml +7 -3
  5. mcp_server_motherduck-0.6.1/src/mcp_server_motherduck/__init__.py +193 -0
  6. mcp_server_motherduck-0.6.1/src/mcp_server_motherduck/configs.py +32 -0
  7. mcp_server_motherduck-0.6.1/src/mcp_server_motherduck/database.py +134 -0
  8. mcp_server_motherduck-0.6.1/src/mcp_server_motherduck/server.py +149 -0
  9. mcp_server_motherduck-0.6.1/uv.lock +417 -0
  10. mcp_server_motherduck-0.5.1/src/mcp_server_motherduck/__init__.py +0 -66
  11. mcp_server_motherduck-0.5.1/src/mcp_server_motherduck/server.py +0 -300
  12. mcp_server_motherduck-0.5.1/uv.lock +0 -374
  13. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/.github/workflows/python-publish.yml +0 -0
  14. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/.gitignore +0 -0
  15. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/.idea/.gitignore +0 -0
  16. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/.idea/mcp-server-motherduck.iml +0 -0
  17. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/.idea/misc.xml +0 -0
  18. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/.idea/modules.xml +0 -0
  19. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/.idea/vcs.xml +0 -0
  20. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/LICENSE +0 -0
  21. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/makefile +0 -0
  22. {mcp_server_motherduck-0.5.1 → mcp_server_motherduck-0.6.1}/src/mcp_server_motherduck/prompt.py +0 -0
@@ -3,16 +3,38 @@
3
3
  <component name="AutoImportSettings">
4
4
  <option name="autoReloadType" value="SELECTIVE" />
5
5
  </component>
6
+ <component name="CMakeProjectFlavorService">
7
+ <option name="flavorId" value="CMakePlainProjectFlavor" />
8
+ </component>
9
+ <component name="CMakeSettings">
10
+ <configurations>
11
+ <configuration PROFILE_NAME="Debug" ENABLED="true" CONFIG_NAME="Debug" />
12
+ </configurations>
13
+ </component>
6
14
  <component name="ChangeListManager">
7
15
  <list default="true" id="8bdee1d4-886c-4093-b4cf-95b120034c9e" name="Changes" comment="">
8
16
  <change beforePath="$PROJECT_DIR$/pyproject.toml" beforeDir="false" afterPath="$PROJECT_DIR$/pyproject.toml" afterDir="false" />
9
- <change beforePath="$PROJECT_DIR$/src/mcp_server_motherduck/server.py" beforeDir="false" afterPath="$PROJECT_DIR$/src/mcp_server_motherduck/server.py" afterDir="false" />
17
+ <change beforePath="$PROJECT_DIR$/uv.lock" beforeDir="false" afterPath="$PROJECT_DIR$/uv.lock" afterDir="false" />
10
18
  </list>
11
19
  <option name="SHOW_DIALOG" value="false" />
12
20
  <option name="HIGHLIGHT_CONFLICTS" value="true" />
13
21
  <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
14
22
  <option name="LAST_RESOLUTION" value="IGNORE" />
15
23
  </component>
24
+ <component name="ClangdSettings">
25
+ <option name="formatViaClangd" value="false" />
26
+ </component>
27
+ <component name="FlaskConsoleOptions" custom-start-script="import sys&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;from flask.cli import ScriptInfo&#10;locals().update(ScriptInfo(create_app=None).load_app().make_shell_context())&#10;print(&quot;Python %s on %s\nApp: %s [%s]\nInstance: %s&quot; % (sys.version, sys.platform, app.import_name, app.env, app.instance_path))">
28
+ <envs>
29
+ <env key="FLASK_APP" value="app" />
30
+ </envs>
31
+ <option name="myCustomStartScript" value="import sys&#10;sys.path.extend([WORKING_DIR_AND_PYTHON_PATHS])&#10;from flask.cli import ScriptInfo&#10;locals().update(ScriptInfo(create_app=None).load_app().make_shell_context())&#10;print(&quot;Python %s on %s\nApp: %s [%s]\nInstance: %s&quot; % (sys.version, sys.platform, app.import_name, app.env, app.instance_path))" />
32
+ <option name="myEnvs">
33
+ <map>
34
+ <entry key="FLASK_APP" value="app" />
35
+ </map>
36
+ </option>
37
+ </component>
16
38
  <component name="Git.Settings">
17
39
  <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
18
40
  </component>
@@ -31,7 +53,12 @@
31
53
  &quot;keyToString&quot;: {
32
54
  &quot;RunOnceActivity.OpenProjectViewOnStart&quot;: &quot;true&quot;,
33
55
  &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
56
+ &quot;RunOnceActivity.cidr.known.project.marker&quot;: &quot;true&quot;,
57
+ &quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
58
+ &quot;RunOnceActivity.readMode.enableVisualFormatting&quot;: &quot;true&quot;,
34
59
  &quot;WebServerToolWindowFactoryState&quot;: &quot;false&quot;,
60
+ &quot;cf.first.check.clang-format&quot;: &quot;false&quot;,
61
+ &quot;cidr.known.project.marker&quot;: &quot;true&quot;,
35
62
  &quot;git-widget-placeholder&quot;: &quot;main&quot;,
36
63
  &quot;last_opened_file_path&quot;: &quot;/Users/doehmen/Documents/motherduck/mcp-server-motherduck&quot;,
37
64
  &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
@@ -42,6 +69,7 @@
42
69
  &quot;project.structure.last.edited&quot;: &quot;Project&quot;,
43
70
  &quot;project.structure.proportion&quot;: &quot;0.0&quot;,
44
71
  &quot;project.structure.side.proportion&quot;: &quot;0.0&quot;,
72
+ &quot;settings.editor.selected.configurable&quot;: &quot;preferences.updates&quot;,
45
73
  &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
46
74
  }
47
75
  }</component>
@@ -57,11 +85,25 @@
57
85
  <workItem from="1744787944049" duration="599000" />
58
86
  <workItem from="1744896732489" duration="6070000" />
59
87
  <workItem from="1747725447463" duration="5949000" />
60
- <workItem from="1747924921526" duration="16385000" />
88
+ <workItem from="1747924921526" duration="17579000" />
89
+ <workItem from="1749541956173" duration="67000" />
90
+ <workItem from="1749546948380" duration="272000" />
91
+ <workItem from="1749547445107" duration="2288000" />
92
+ <workItem from="1750068892931" duration="1202000" />
93
+ <workItem from="1750076934923" duration="598000" />
94
+ <workItem from="1750084124415" duration="194000" />
95
+ <workItem from="1750084439422" duration="575000" />
96
+ <workItem from="1750086684829" duration="92000" />
97
+ <workItem from="1750099676834" duration="5651000" />
98
+ <workItem from="1750235697329" duration="602000" />
61
99
  </task>
62
100
  <servers />
63
101
  </component>
64
102
  <component name="TypeScriptGeneratedFilesManager">
65
103
  <option name="version" value="3" />
66
104
  </component>
105
+ <component name="XSLT-Support.FileAssociations.UIState">
106
+ <expand />
107
+ <select />
108
+ </component>
67
109
  </project>
@@ -1,7 +1,25 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-server-motherduck
3
+ Version: 0.6.1
4
+ Summary: A MCP server for MotherDuck and local DuckDB
5
+ Author-email: tdoehmen <till@motherduck.com>
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: anyio>=4.8.0
9
+ Requires-Dist: click>=8.1.8
10
+ Requires-Dist: duckdb==1.3.1
11
+ Requires-Dist: mcp>=1.9.4
12
+ Requires-Dist: starlette>=0.46.1
13
+ Requires-Dist: tabulate>=0.9.0
14
+ Requires-Dist: uvicorn>=0.34.0
15
+ Description-Content-Type: text/markdown
16
+
1
17
  # MotherDuck's DuckDB MCP Server
2
18
 
3
19
  An MCP server implementation that interacts with DuckDB and MotherDuck databases, providing SQL analytics capabilities to AI Assistants and IDEs.
4
20
 
21
+ [![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/install-mcp?name=DuckDB&config=eyJjb21tYW5kIjoidXZ4IG1jcC1zZXJ2ZXItbW90aGVyZHVjayAtLWRiLXBhdGggbWQ6IiwiZW52Ijp7Im1vdGhlcmR1Y2tfdG9rZW4iOiIifX0%3D)
22
+
5
23
  ## Resources
6
24
  - [Close the Loop: Faster Data Pipelines with MCP, DuckDB & AI (Blogpost)](https://motherduck.com/blog/faster-data-pipelines-with-mcp-duckdb-ai/)
7
25
  - [Faster Data Pipelines development with MCP and DuckDB (YouTube)](https://www.youtube.com/watch?v=yG1mv8ZRxcU)
@@ -32,6 +50,37 @@ The server offers one tool:
32
50
 
33
51
  All interactions with both DuckDB and MotherDuck are done through writing SQL queries.
34
52
 
53
+ ## Command Line Parameters
54
+
55
+ The MCP server supports the following parameters:
56
+
57
+ | Parameter | Type | Default | Description |
58
+ |-----------|------|---------|-------------|
59
+ | `--transport` | Choice | `stdio` | Transport type. Options: `stdio`, `sse`, `stream` |
60
+ | `--port` | Integer | `8000` | Port to listen on for sse and stream transport mode |
61
+ | `--db-path` | String | `md:` | Path to local DuckDB database file or MotherDuck database |
62
+ | `--motherduck-token` | String | `None` | Access token to use for MotherDuck database connections (uses `motherduck_token` env var by default) |
63
+ | `--read-only` | Flag | `False` | Flag for connecting to DuckDB in read-only mode. Only supported for local DuckDB databases. Uses short-lived connections for concurrent access |
64
+ | `--home-dir` | String | `None` | Home directory for DuckDB (uses `HOME` env var by default) |
65
+ | `--saas-mode` | Flag | `False` | Flag for connecting to MotherDuck in SaaS mode |
66
+ | `--json-response` | Flag | `False` | Enable JSON responses for HTTP stream. Only supported for `stream` transport |
67
+
68
+ ### Quick Usage Examples
69
+
70
+ ```bash
71
+ # Connect to local DuckDB file in read-only mode with stream transport mode
72
+ uvx mcp-server-motherduck --transport stream --db-path /path/to/local.db --read-only
73
+
74
+ # Connect to MotherDuck with token with stream transport mode
75
+ uvx mcp-server-motherduck --transport stream --db-path md: --motherduck-token YOUR_TOKEN
76
+
77
+ # Connect to local DuckDB file in read-only mode with stream transport mode
78
+ uvx mcp-server-motherduck --transport stream --db-path /path/to/local.db --read-only
79
+
80
+ # Connect to MotherDuck in SaaS mode for enhanced security with stream transport mode
81
+ uvx mcp-server-motherduck --transport stream --db-path md: --motherduck-token YOUR_TOKEN --saas-mode
82
+ ```
83
+
35
84
  ## Getting Started
36
85
 
37
86
  ### General Prerequisites
@@ -81,11 +130,11 @@ See [Connect to local DuckDB](#connect-to-local-duckdb).
81
130
 
82
131
  ### Usage with VS Code
83
132
 
84
- [![Install with UV in VS Code](https://img.shields.io/badge/VS_Code-UV-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=mcp-server-motherduck&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22mcp-server-motherduck%22%2C%22--db-path%22%2C%22md%3A%22%2C%22--motherduck-token%22%2C%22%24%7Binput%3Amotherduck_token%7D%22%5D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22motherduck_token%22%2C%22description%22%3A%22MotherDuck+Token%22%2C%22password%22%3Atrue%7D%5D) [![Install with UV in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-UV-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=mcp-server-motherduck&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22mcp-server-motherduck%22%2C%22--db-path%22%2C%22md%3A%22%2C%22--motherduck-token%22%2C%22%24%7Binput%3Amotherduck_token%7D%22%5D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22motherduck_token%22%2C%22description%22%3A%22MotherDuck+Token%22%2C%22password%22%3Atrue%7D%5D&quality=insiders)
133
+ [![Install with UV in VS Code](https://img.shields.io/badge/VS_Code-Install_with_UV-0098FF?style=plastic)](https://insiders.vscode.dev/redirect/mcp/install?name=mcp-server-motherduck&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22mcp-server-motherduck%22%2C%22--db-path%22%2C%22md%3A%22%2C%22--motherduck-token%22%2C%22%24%7Binput%3Amotherduck_token%7D%22%5D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22motherduck_token%22%2C%22description%22%3A%22MotherDuck+Token%22%2C%22password%22%3Atrue%7D%5D) [![Install with UV in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_with_UV-24bfa5?style=plastic&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=mcp-server-motherduck&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22mcp-server-motherduck%22%2C%22--db-path%22%2C%22md%3A%22%2C%22--motherduck-token%22%2C%22%24%7Binput%3Amotherduck_token%7D%22%5D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22motherduck_token%22%2C%22description%22%3A%22MotherDuck+Token%22%2C%22password%22%3Atrue%7D%5D&quality=insiders)
85
134
 
86
- 1. For the quickest installation, click one of the "Install with UV" buttons at the top of this README.
135
+ For the quickest installation, click one of the "Install with UV" buttons at the top.
87
136
 
88
- ### Manual Installation
137
+ #### Manual Installation
89
138
 
90
139
  Add the following JSON block to your User Settings (JSON) file in VS Code. You can do this by pressing `Ctrl + Shift + P` and typing `Preferences: Open User Settings (JSON)`.
91
140
 
@@ -276,47 +325,29 @@ Once configured, you can e.g. ask Claude to run queries like:
276
325
  - "Join data from my local DuckDB database with a table in MotherDuck"
277
326
  - "Analyze data stored in Amazon S3"
278
327
 
279
- ## Testing
280
-
281
- The server is designed to be run by tools like Claude Desktop and Cursor, but you can start it manually for testing purposes. When testing the server manually, you can specify which database to connect to using the `--db-path` parameter:
282
-
283
- 1. **Default MotherDuck database**:
284
-
285
- - To connect to the default MotherDuck database, you will need to pass the auth token using the `--motherduck-token` parameter.
286
-
287
- ```bash
288
- uvx mcp-server-motherduck --db-path md: --motherduck-token <your_motherduck_token>
289
- ```
290
-
291
- 2. **Specific MotherDuck database**:
292
-
293
- ```bash
294
- uvx mcp-server-motherduck --db-path md:your_database_name --motherduck-token <your_motherduck_token>
295
- ```
328
+ ## Running in SSE mode
296
329
 
297
- 3. **Local DuckDB database**:
330
+ The server can run in SSE mode in two ways:
298
331
 
299
- ```bash
300
- uvx mcp-server-motherduck --db-path /path/to/your/local.db
301
- ```
332
+ ### Direct SSE mode
302
333
 
303
- 4. **In-memory database**:
334
+ Run the server directly in SSE mode using the `--transport sse` flag:
304
335
 
305
- ```bash
306
- uvx mcp-server-motherduck --db-path :memory:
307
- ```
336
+ ```bash
337
+ uvx mcp-server-motherduck --transport sse --port 8000 --db-path md: --motherduck-token <your_motherduck_token>
338
+ ```
308
339
 
309
- If you don't specify a database path but have set the `motherduck_token` environment variable, the server will automatically connect to the default MotherDuck database (`md:`).
340
+ This will start the server listening on the specified port (default 8000) and you can point your clients directly to this endpoint.
310
341
 
311
- ## Running in SSE mode
342
+ ### Using supergateway
312
343
 
313
- The server could also be running SSE mode using `supergateway` by running the following command:
344
+ Alternatively, you can run SSE mode using `supergateway`:
314
345
 
315
346
  ```bash
316
347
  npx -y supergateway --stdio "uvx mcp-server-motherduck --db-path md: --motherduck-token <your_motherduck_token>"
317
348
  ```
318
349
 
319
- And you can point your clients such as Claude Desktop, Cursor to this endpoint.
350
+ Both methods allow you to point your clients such as Claude Desktop, Cursor to the SSE endpoint.
320
351
 
321
352
  ## Development configuration
322
353
 
@@ -1,19 +1,9 @@
1
- Metadata-Version: 2.4
2
- Name: mcp-server-motherduck
3
- Version: 0.5.1
4
- Summary: A MCP server for MotherDuck and local DuckDB
5
- Author-email: tdoehmen <till@motherduck.com>
6
- License-File: LICENSE
7
- Requires-Python: >=3.10
8
- Requires-Dist: duckdb==1.3.0
9
- Requires-Dist: mcp>=1.3.0
10
- Requires-Dist: tabulate>=0.9.0
11
- Description-Content-Type: text/markdown
12
-
13
1
  # MotherDuck's DuckDB MCP Server
14
2
 
15
3
  An MCP server implementation that interacts with DuckDB and MotherDuck databases, providing SQL analytics capabilities to AI Assistants and IDEs.
16
4
 
5
+ [![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/install-mcp?name=DuckDB&config=eyJjb21tYW5kIjoidXZ4IG1jcC1zZXJ2ZXItbW90aGVyZHVjayAtLWRiLXBhdGggbWQ6IiwiZW52Ijp7Im1vdGhlcmR1Y2tfdG9rZW4iOiIifX0%3D)
6
+
17
7
  ## Resources
18
8
  - [Close the Loop: Faster Data Pipelines with MCP, DuckDB & AI (Blogpost)](https://motherduck.com/blog/faster-data-pipelines-with-mcp-duckdb-ai/)
19
9
  - [Faster Data Pipelines development with MCP and DuckDB (YouTube)](https://www.youtube.com/watch?v=yG1mv8ZRxcU)
@@ -44,6 +34,37 @@ The server offers one tool:
44
34
 
45
35
  All interactions with both DuckDB and MotherDuck are done through writing SQL queries.
46
36
 
37
+ ## Command Line Parameters
38
+
39
+ The MCP server supports the following parameters:
40
+
41
+ | Parameter | Type | Default | Description |
42
+ |-----------|------|---------|-------------|
43
+ | `--transport` | Choice | `stdio` | Transport type. Options: `stdio`, `sse`, `stream` |
44
+ | `--port` | Integer | `8000` | Port to listen on for sse and stream transport mode |
45
+ | `--db-path` | String | `md:` | Path to local DuckDB database file or MotherDuck database |
46
+ | `--motherduck-token` | String | `None` | Access token to use for MotherDuck database connections (uses `motherduck_token` env var by default) |
47
+ | `--read-only` | Flag | `False` | Flag for connecting to DuckDB in read-only mode. Only supported for local DuckDB databases. Uses short-lived connections for concurrent access |
48
+ | `--home-dir` | String | `None` | Home directory for DuckDB (uses `HOME` env var by default) |
49
+ | `--saas-mode` | Flag | `False` | Flag for connecting to MotherDuck in SaaS mode |
50
+ | `--json-response` | Flag | `False` | Enable JSON responses for HTTP stream. Only supported for `stream` transport |
51
+
52
+ ### Quick Usage Examples
53
+
54
+ ```bash
55
+ # Connect to local DuckDB file in read-only mode with stream transport mode
56
+ uvx mcp-server-motherduck --transport stream --db-path /path/to/local.db --read-only
57
+
58
+ # Connect to MotherDuck with token with stream transport mode
59
+ uvx mcp-server-motherduck --transport stream --db-path md: --motherduck-token YOUR_TOKEN
60
+
61
+ # Connect to local DuckDB file in read-only mode with stream transport mode
62
+ uvx mcp-server-motherduck --transport stream --db-path /path/to/local.db --read-only
63
+
64
+ # Connect to MotherDuck in SaaS mode for enhanced security with stream transport mode
65
+ uvx mcp-server-motherduck --transport stream --db-path md: --motherduck-token YOUR_TOKEN --saas-mode
66
+ ```
67
+
47
68
  ## Getting Started
48
69
 
49
70
  ### General Prerequisites
@@ -93,11 +114,11 @@ See [Connect to local DuckDB](#connect-to-local-duckdb).
93
114
 
94
115
  ### Usage with VS Code
95
116
 
96
- [![Install with UV in VS Code](https://img.shields.io/badge/VS_Code-UV-0098FF?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=mcp-server-motherduck&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22mcp-server-motherduck%22%2C%22--db-path%22%2C%22md%3A%22%2C%22--motherduck-token%22%2C%22%24%7Binput%3Amotherduck_token%7D%22%5D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22motherduck_token%22%2C%22description%22%3A%22MotherDuck+Token%22%2C%22password%22%3Atrue%7D%5D) [![Install with UV in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-UV-24bfa5?style=flat-square&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=mcp-server-motherduck&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22mcp-server-motherduck%22%2C%22--db-path%22%2C%22md%3A%22%2C%22--motherduck-token%22%2C%22%24%7Binput%3Amotherduck_token%7D%22%5D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22motherduck_token%22%2C%22description%22%3A%22MotherDuck+Token%22%2C%22password%22%3Atrue%7D%5D&quality=insiders)
117
+ [![Install with UV in VS Code](https://img.shields.io/badge/VS_Code-Install_with_UV-0098FF?style=plastic)](https://insiders.vscode.dev/redirect/mcp/install?name=mcp-server-motherduck&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22mcp-server-motherduck%22%2C%22--db-path%22%2C%22md%3A%22%2C%22--motherduck-token%22%2C%22%24%7Binput%3Amotherduck_token%7D%22%5D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22motherduck_token%22%2C%22description%22%3A%22MotherDuck+Token%22%2C%22password%22%3Atrue%7D%5D) [![Install with UV in VS Code Insiders](https://img.shields.io/badge/VS_Code_Insiders-Install_with_UV-24bfa5?style=plastic&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=mcp-server-motherduck&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22mcp-server-motherduck%22%2C%22--db-path%22%2C%22md%3A%22%2C%22--motherduck-token%22%2C%22%24%7Binput%3Amotherduck_token%7D%22%5D%7D&inputs=%5B%7B%22type%22%3A%22promptString%22%2C%22id%22%3A%22motherduck_token%22%2C%22description%22%3A%22MotherDuck+Token%22%2C%22password%22%3Atrue%7D%5D&quality=insiders)
97
118
 
98
- 1. For the quickest installation, click one of the "Install with UV" buttons at the top of this README.
119
+ For the quickest installation, click one of the "Install with UV" buttons at the top.
99
120
 
100
- ### Manual Installation
121
+ #### Manual Installation
101
122
 
102
123
  Add the following JSON block to your User Settings (JSON) file in VS Code. You can do this by pressing `Ctrl + Shift + P` and typing `Preferences: Open User Settings (JSON)`.
103
124
 
@@ -288,47 +309,29 @@ Once configured, you can e.g. ask Claude to run queries like:
288
309
  - "Join data from my local DuckDB database with a table in MotherDuck"
289
310
  - "Analyze data stored in Amazon S3"
290
311
 
291
- ## Testing
292
-
293
- The server is designed to be run by tools like Claude Desktop and Cursor, but you can start it manually for testing purposes. When testing the server manually, you can specify which database to connect to using the `--db-path` parameter:
294
-
295
- 1. **Default MotherDuck database**:
296
-
297
- - To connect to the default MotherDuck database, you will need to pass the auth token using the `--motherduck-token` parameter.
298
-
299
- ```bash
300
- uvx mcp-server-motherduck --db-path md: --motherduck-token <your_motherduck_token>
301
- ```
302
-
303
- 2. **Specific MotherDuck database**:
304
-
305
- ```bash
306
- uvx mcp-server-motherduck --db-path md:your_database_name --motherduck-token <your_motherduck_token>
307
- ```
312
+ ## Running in SSE mode
308
313
 
309
- 3. **Local DuckDB database**:
314
+ The server can run in SSE mode in two ways:
310
315
 
311
- ```bash
312
- uvx mcp-server-motherduck --db-path /path/to/your/local.db
313
- ```
316
+ ### Direct SSE mode
314
317
 
315
- 4. **In-memory database**:
318
+ Run the server directly in SSE mode using the `--transport sse` flag:
316
319
 
317
- ```bash
318
- uvx mcp-server-motherduck --db-path :memory:
319
- ```
320
+ ```bash
321
+ uvx mcp-server-motherduck --transport sse --port 8000 --db-path md: --motherduck-token <your_motherduck_token>
322
+ ```
320
323
 
321
- If you don't specify a database path but have set the `motherduck_token` environment variable, the server will automatically connect to the default MotherDuck database (`md:`).
324
+ This will start the server listening on the specified port (default 8000) and you can point your clients directly to this endpoint.
322
325
 
323
- ## Running in SSE mode
326
+ ### Using supergateway
324
327
 
325
- The server could also be running SSE mode using `supergateway` by running the following command:
328
+ Alternatively, you can run SSE mode using `supergateway`:
326
329
 
327
330
  ```bash
328
331
  npx -y supergateway --stdio "uvx mcp-server-motherduck --db-path md: --motherduck-token <your_motherduck_token>"
329
332
  ```
330
333
 
331
- And you can point your clients such as Claude Desktop, Cursor to this endpoint.
334
+ Both methods allow you to point your clients such as Claude Desktop, Cursor to the SSE endpoint.
332
335
 
333
336
  ## Development configuration
334
337
 
@@ -1,13 +1,17 @@
1
1
  [project]
2
2
  name = "mcp-server-motherduck"
3
- version = "0.5.1"
3
+ version = "0.6.1"
4
4
  description = "A MCP server for MotherDuck and local DuckDB"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
7
7
  dependencies = [
8
- "mcp>=1.3.0",
9
- "duckdb==1.3.0",
8
+ "duckdb==1.3.1",
10
9
  "tabulate>=0.9.0",
10
+ "click>=8.1.8",
11
+ "starlette>=0.46.1",
12
+ "uvicorn>=0.34.0",
13
+ "anyio>=4.8.0",
14
+ "mcp>=1.9.4",
11
15
  ]
12
16
 
13
17
  [[project.authors]]
@@ -0,0 +1,193 @@
1
+ import anyio
2
+ import logging
3
+ import click
4
+ from .server import build_application
5
+ from .configs import SERVER_VERSION, SERVER_LOCALHOST, UVICORN_LOGGING_CONFIG
6
+
7
+ __version__ = SERVER_VERSION
8
+
9
+ logger = logging.getLogger("mcp_server_motherduck")
10
+ logging.basicConfig(
11
+ level=logging.INFO, format="[motherduck] %(levelname)s - %(message)s"
12
+ )
13
+
14
+
15
+ @click.command()
16
+ @click.option("--port", default=8000, help="Port to listen on for SSE")
17
+ @click.option(
18
+ "--transport",
19
+ type=click.Choice(["stdio", "sse", "stream"]),
20
+ default="stdio",
21
+ help="(Default: `stdio`) Transport type",
22
+ )
23
+ @click.option(
24
+ "--db-path",
25
+ default="md:",
26
+ help="(Default: `md:`) Path to local DuckDB database file or MotherDuck database",
27
+ )
28
+ @click.option(
29
+ "--motherduck-token",
30
+ default=None,
31
+ help="(Default: env var `motherduck_token`) Access token to use for MotherDuck database connections",
32
+ )
33
+ @click.option(
34
+ "--home-dir",
35
+ default=None,
36
+ help="(Default: env var `HOME`) Home directory for DuckDB",
37
+ )
38
+ @click.option(
39
+ "--saas-mode",
40
+ is_flag=True,
41
+ help="Flag for connecting to MotherDuck in SaaS mode",
42
+ )
43
+ @click.option(
44
+ "--read-only",
45
+ is_flag=True,
46
+ help="Flag for connecting to DuckDB in read-only mode. Only supported for local DuckDB databases. Also makes use of short lived connections so multiple MCP clients or other systems can remain active (though each operation must be done sequentially).",
47
+ )
48
+ @click.option(
49
+ "--json-response",
50
+ is_flag=True,
51
+ default=False,
52
+ help="(Default: `False`) Enable JSON responses instead of SSE streams. Only supported for `stream` transport.",
53
+ )
54
+ def main(
55
+ port,
56
+ transport,
57
+ db_path,
58
+ motherduck_token,
59
+ home_dir,
60
+ saas_mode,
61
+ read_only,
62
+ json_response,
63
+ ):
64
+ """Main entry point for the package."""
65
+
66
+ logger.info("🦆 MotherDuck MCP Server v" + SERVER_VERSION)
67
+ logger.info("Ready to execute SQL queries via DuckDB/MotherDuck")
68
+
69
+ app, init_opts = build_application(
70
+ db_path=db_path,
71
+ motherduck_token=motherduck_token,
72
+ home_dir=home_dir,
73
+ saas_mode=saas_mode,
74
+ read_only=read_only,
75
+ )
76
+
77
+ if transport == "sse":
78
+ from mcp.server.sse import SseServerTransport
79
+ from starlette.applications import Starlette
80
+ from starlette.responses import Response
81
+ from starlette.routing import Mount, Route
82
+
83
+ logger.info("MCP server initialized in \033[32msse\033[0m mode")
84
+
85
+ sse = SseServerTransport("/messages/")
86
+
87
+ async def handle_sse(request):
88
+ async with sse.connect_sse(
89
+ request.scope, request.receive, request._send
90
+ ) as (read_stream, write_stream):
91
+ await app.run(read_stream, write_stream, init_opts)
92
+ return Response()
93
+
94
+ logger.info(
95
+ f"🦆 Connect to MotherDuck MCP Server at \033[1m\033[36mhttp://{SERVER_LOCALHOST}:{port}/sse\033[0m"
96
+ )
97
+
98
+ starlette_app = Starlette(
99
+ debug=True,
100
+ routes=[
101
+ Route("/sse", endpoint=handle_sse, methods=["GET"]),
102
+ Mount("/messages/", app=sse.handle_post_message),
103
+ ],
104
+ )
105
+
106
+ import uvicorn
107
+
108
+ uvicorn.run(
109
+ starlette_app,
110
+ host=SERVER_LOCALHOST,
111
+ port=port,
112
+ log_config=UVICORN_LOGGING_CONFIG,
113
+ )
114
+
115
+ elif transport == "stream":
116
+ from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
117
+ from collections.abc import AsyncIterator
118
+ from starlette.applications import Starlette
119
+ from starlette.routing import Mount
120
+ from starlette.types import Receive, Scope, Send
121
+ import contextlib
122
+
123
+ logger.info("MCP server initialized in \033[32mhttp-streamable\033[0m mode")
124
+
125
+ # Create the session manager with true stateless mode
126
+ session_manager = StreamableHTTPSessionManager(
127
+ app=app,
128
+ event_store=None,
129
+ json_response=json_response,
130
+ stateless=True,
131
+ )
132
+
133
+ async def handle_streamable_http(
134
+ scope: Scope, receive: Receive, send: Send
135
+ ) -> None:
136
+ await session_manager.handle_request(scope, receive, send)
137
+
138
+ @contextlib.asynccontextmanager
139
+ async def lifespan(app: Starlette) -> AsyncIterator[None]:
140
+ """Context manager for session manager."""
141
+ async with session_manager.run():
142
+ logger.info("MCP server started with StreamableHTTP session manager")
143
+ try:
144
+ yield
145
+ finally:
146
+ logger.info(
147
+ "🦆 MotherDuck MCP Server in \033[32mhttp-streamable\033[0m mode shutting down"
148
+ )
149
+
150
+ logger.info(
151
+ f"🦆 Connect to MotherDuck MCP Server at \033[1m\033[36mhttp://{SERVER_LOCALHOST}:{port}/mcp\033[0m"
152
+ )
153
+
154
+ # Create an ASGI application using the transport
155
+ starlette_app = Starlette(
156
+ debug=True,
157
+ routes=[
158
+ Mount("/mcp", app=handle_streamable_http),
159
+ ],
160
+ lifespan=lifespan,
161
+ )
162
+
163
+ import uvicorn
164
+
165
+ uvicorn.run(
166
+ starlette_app,
167
+ host=SERVER_LOCALHOST,
168
+ port=port,
169
+ log_config=UVICORN_LOGGING_CONFIG,
170
+ )
171
+
172
+ else:
173
+ from mcp.server.stdio import stdio_server
174
+
175
+ logger.info("MCP server initialized in \033[32mstdio\033[0m mode")
176
+ logger.info("Waiting for client connection")
177
+
178
+ async def arun():
179
+ async with stdio_server() as (read_stream, write_stream):
180
+ await app.run(read_stream, write_stream, init_opts)
181
+
182
+ anyio.run(arun)
183
+ # This will only be reached when the server is shutting down
184
+ logger.info(
185
+ "🦆 MotherDuck MCP Server in \033[32mstdio\033[0m mode shutting down"
186
+ )
187
+
188
+
189
+ # Optionally expose other important items at package level
190
+ __all__ = ["main"]
191
+
192
+ if __name__ == "__main__":
193
+ main()
@@ -0,0 +1,32 @@
1
+ from typing import Any
2
+
3
+ SERVER_VERSION = "0.6.1"
4
+
5
+ SERVER_LOCALHOST = "127.0.0.1"
6
+
7
+ UVICORN_LOGGING_CONFIG: dict[str, Any] = {
8
+ "version": 1,
9
+ "disable_existing_loggers": False,
10
+ "formatters": {
11
+ "default": {
12
+ "()": "uvicorn.logging.DefaultFormatter",
13
+ "fmt": "[uvicorn] %(levelname)s - %(message)s",
14
+ "use_colors": None,
15
+ },
16
+ },
17
+ "handlers": {
18
+ "default": {
19
+ "formatter": "default",
20
+ "class": "logging.StreamHandler",
21
+ "stream": "ext://sys.stderr",
22
+ },
23
+ },
24
+ "loggers": {
25
+ "uvicorn": {
26
+ "handlers": ["default"],
27
+ "level": "INFO",
28
+ "propagate": False,
29
+ },
30
+ "uvicorn.error": {"level": "INFO"},
31
+ },
32
+ }