mcp-server-motherduck 0.3.4__py3-none-any.whl → 0.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,12 +13,23 @@ def main():
13
13
  parser = argparse.ArgumentParser(description="MotherDuck MCP Server")
14
14
  parser.add_argument(
15
15
  "--db-path",
16
- help="Path to local DuckDB database file",
16
+ default="md:",
17
+ help="(Default: `md:`) Path to local DuckDB database file or MotherDuck database",
18
+ )
19
+ parser.add_argument(
20
+ "--motherduck-token",
21
+ default=None,
22
+ help="(Default: env var `motherduck_token`) Access token to use for MotherDuck database connections",
23
+ )
24
+ parser.add_argument(
25
+ "--home-dir",
26
+ default=None,
27
+ help="(Default: env var `HOME`) Home directory for DuckDB",
17
28
  )
18
29
  # This is experimental and will change in the future
19
30
  parser.add_argument(
20
31
  "--result-format",
21
- help="Format of the output",
32
+ help="(Default: `markdown`) Format of the query result",
22
33
  default="markdown",
23
34
  choices=["markdown", "duckbox", "text"],
24
35
  )
@@ -28,7 +39,14 @@ def main():
28
39
  logger.info("Ready to execute SQL queries via DuckDB/MotherDuck")
29
40
  logger.info("Waiting for client connection...\n")
30
41
 
31
- asyncio.run(server.main(db_path=args.db_path, result_format=args.result_format))
42
+ asyncio.run(
43
+ server.main(
44
+ db_path=args.db_path,
45
+ motherduck_token=args.motherduck_token,
46
+ result_format=args.result_format,
47
+ home_dir=args.home_dir,
48
+ )
49
+ )
32
50
 
33
51
 
34
52
  # Optionally expose other important items at package level
@@ -12,7 +12,7 @@ from mcp.server.models import InitializationOptions
12
12
  from .prompt import PROMPT_TEMPLATE
13
13
 
14
14
 
15
- SERVER_VERSION = "0.3.4"
15
+ SERVER_VERSION = "0.4.0"
16
16
 
17
17
  logger = logging.getLogger("mcp_server_motherduck")
18
18
 
@@ -21,18 +21,26 @@ class DatabaseClient:
21
21
  def __init__(
22
22
  self,
23
23
  db_path: str | None = None,
24
+ motherduck_token: str | None = None,
24
25
  result_format: Literal["markdown", "duckbox", "text"] = "markdown",
26
+ home_dir: str | None = None,
25
27
  ):
26
- self.db_path, self.db_type = self._resolve_db_path_type(db_path)
28
+ self.db_path, self.db_type = self._resolve_db_path_type(
29
+ db_path, motherduck_token
30
+ )
27
31
  logger.info(f"Database client initialized in `{self.db_type}` mode")
28
32
 
33
+ # Set the home directory for DuckDB
34
+ if home_dir:
35
+ os.environ["HOME"] = home_dir
36
+
29
37
  self.conn = self._initialize_connection()
30
38
  self.result_format = result_format
31
39
 
32
40
  def _initialize_connection(self) -> duckdb.DuckDBPyConnection:
33
41
  """Initialize connection to the MotherDuck or DuckDB database"""
34
42
 
35
- logger.info(f"🔌 Connecting to {self.db_type} database: {self.db_path}")
43
+ logger.info(f"🔌 Connecting to {self.db_type} database")
36
44
 
37
45
  conn = duckdb.connect(
38
46
  self.db_path,
@@ -44,32 +52,36 @@ class DatabaseClient:
44
52
  return conn
45
53
 
46
54
  def _resolve_db_path_type(
47
- self, db_path: str | None = None
55
+ self, db_path: str, motherduck_token: str | None = None
48
56
  ) -> tuple[str, Literal["duckdb", "motherduck"]]:
49
57
  """Resolve and validate the database path"""
50
- # Use MotherDuck if token is available and no path specified
51
- if db_path is None and os.getenv("motherduck_token"):
52
- logger.info("Using MotherDuck token to connect to database `md:`")
53
- return "md:", "motherduck"
54
-
55
58
  # Handle MotherDuck paths
56
- if db_path and (db_path == "md:" or db_path.startswith("md:")):
57
- if not os.getenv("motherduck_token"):
59
+ if db_path.startswith("md:"):
60
+ if motherduck_token:
61
+ logger.info("Using MotherDuck token to connect to database `md:`")
62
+ return f"{db_path}?motherduck_token={motherduck_token}", "motherduck"
63
+ elif os.getenv("motherduck_token"):
64
+ logger.info(
65
+ "Using MotherDuck token from env to connect to database `md:`"
66
+ )
67
+ return (
68
+ f"{db_path}?motherduck_token={os.getenv('motherduck_token')}",
69
+ "motherduck",
70
+ )
71
+ else:
58
72
  raise ValueError(
59
- "Please set the `motherduck_token` environment variable when using `md:` as db_path."
73
+ "Please set the `motherduck_token` as an environment variable or pass it as an argument with `--motherduck-token` when using `md:` as db_path."
60
74
  )
61
- return db_path, "motherduck"
62
75
 
63
- # Handle local database paths
64
- if db_path:
65
- if not os.path.exists(db_path):
66
- raise FileNotFoundError(
67
- f"The database path `{db_path}` does not exist."
68
- )
76
+ if db_path == ":memory:":
69
77
  return db_path, "duckdb"
70
78
 
71
- # Default to in-memory database
72
- return ":memory:", "duckdb"
79
+ # Handle local database paths as the last check
80
+ if not os.path.exists(db_path):
81
+ raise FileNotFoundError(
82
+ f"The local database path `{db_path}` does not exist."
83
+ )
84
+ return db_path, "duckdb"
73
85
 
74
86
  def query(self, query: str) -> str:
75
87
  try:
@@ -94,21 +106,21 @@ class DatabaseClient:
94
106
  except Exception as e:
95
107
  raise ValueError(f"❌ Error executing query: {e}")
96
108
 
97
- def mcp_config(self) -> dict[str, str]:
98
- """Used for debugging purposes to show the current MCP config"""
99
- return {
100
- "current_working_directory": os.getcwd(),
101
- "database_type": self.db_type,
102
- "database_path": self.db_path,
103
- }
104
-
105
109
 
106
110
  async def main(
107
- db_path: str, result_format: Literal["markdown", "duckbox", "text"] = "markdown"
111
+ db_path: str,
112
+ motherduck_token: str | None = None,
113
+ result_format: Literal["markdown", "duckbox", "text"] = "markdown",
114
+ home_dir: str | None = None,
108
115
  ):
109
- logger.info(f"Starting MotherDuck MCP Server with DB path: {db_path}")
116
+ logger.info("Starting MotherDuck MCP Server")
110
117
  server = Server("mcp-server-motherduck")
111
- db_client = DatabaseClient(db_path=db_path, result_format=result_format)
118
+ db_client = DatabaseClient(
119
+ db_path=db_path,
120
+ result_format=result_format,
121
+ motherduck_token=motherduck_token,
122
+ home_dir=home_dir,
123
+ )
112
124
 
113
125
  logger.info("Registering handlers")
114
126
 
@@ -235,4 +247,3 @@ async def main(
235
247
 
236
248
  # This will only be reached when the server is shutting down
237
249
  logger.info("\n🦆 MotherDuck MCP Server shutting down...")
238
- logger.info(f"Database connection to {db_client.db_path} closed.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-server-motherduck
3
- Version: 0.3.4
3
+ Version: 0.4.0
4
4
  Summary: A MCP server for MotherDuck and local DuckDB
5
5
  Author-email: tdoehmen <till@motherduck.com>
6
6
  License-File: LICENSE
@@ -8,7 +8,6 @@ Requires-Python: >=3.10
8
8
  Requires-Dist: duckdb>=1.2.1
9
9
  Requires-Dist: mcp>=1.3.0
10
10
  Requires-Dist: pandas>=2.0.0
11
- Requires-Dist: pydantic-settings>=2.8.1
12
11
  Requires-Dist: tabulate>=0.9.0
13
12
  Description-Content-Type: text/markdown
14
13
 
@@ -72,12 +71,12 @@ If you plan to use MotherDuck MCP with Claude Desktop, you will also need Claude
72
71
  "mcp-server-motherduck": {
73
72
  "command": "uvx",
74
73
  "args": [
75
- "mcp-server-motherduck"
74
+ "mcp-server-motherduck",
75
+ "--db-path",
76
+ "md:",
77
+ "--motherduck-token",
78
+ "<YOUR_MOTHERDUCK_TOKEN_HERE>",
76
79
  ],
77
- "env": {
78
- "motherduck_token": "YOUR_MOTHERDUCK_TOKEN_HERE",
79
- "HOME": "YOUR_HOME_FOLDER_PATH"
80
- }
81
80
  }
82
81
  }
83
82
  ```
@@ -99,27 +98,20 @@ Once configured, you can ask Claude to run queries like:
99
98
 
100
99
  ## Testing
101
100
 
102
- The server is designed to be run by tools like Claude Desktop, 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:
101
+ 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:
103
102
 
104
103
  1. **Default MotherDuck database**:
105
104
 
106
- - To connect to the default MotherDuck database, you will need to export the `motherduck_token` environment variable.
105
+ - To connect to the default MotherDuck database, you will need to pass the auth token using the `--motherduck-token` parameter.
107
106
 
108
107
  ```bash
109
- export motherduck_token=<your_motherduck_token>
110
- uvx mcp-server-motherduck --db-path md:
111
- ```
112
-
113
- - Alternatively, you can pass the token directly:
114
-
115
- ```bash
116
- motherduck_token=<your_motherduck_token> uvx mcp-server-motherduck --db-path md:
108
+ uvx mcp-server-motherduck --db-path md: --motherduck-token <your_motherduck_token>
117
109
  ```
118
110
 
119
111
  2. **Specific MotherDuck database**:
120
112
 
121
113
  ```bash
122
- uvx mcp-server-motherduck --db-path md:your_database_name
114
+ uvx mcp-server-motherduck --db-path md:your_database_name --motherduck-token <your_motherduck_token>
123
115
  ```
124
116
 
125
117
  3. **Local DuckDB database**:
@@ -128,10 +120,10 @@ The server is designed to be run by tools like Claude Desktop, but you can start
128
120
  uvx mcp-server-motherduck --db-path /path/to/your/local.db
129
121
  ```
130
122
 
131
- 4. **In-memory database** (default if no path and no token):
123
+ 4. **In-memory database**:
132
124
 
133
125
  ```bash
134
- uvx mcp-server-motherduck
126
+ uvx mcp-server-motherduck --db-path :memory:
135
127
  ```
136
128
 
137
129
  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:`).
@@ -141,23 +133,17 @@ If you don't specify a database path but have set the `motherduck_token` environ
141
133
  The server could also be run ing SSE mode using `supergateway` by running the following command:
142
134
 
143
135
  ```bash
144
- motherduck_token=<your_motherduck_token> HOME=<your_home_folder_path> npx -y supergateway --stdio "uvx mcp-server-motherduck"
136
+ npx -y supergateway --stdio "uvx mcp-server-motherduck --db-path md: --motherduck-token <your_motherduck_token>"
145
137
  ```
146
138
 
147
139
  And you can point your clients such as Claude Desktop, Cursor to this endpoint.
148
140
 
149
- ### Environment Variables
150
-
151
- The server uses the following environment variables:
152
-
153
- - `motherduck_token`: Your MotherDuck authentication token
154
- - `HOME`: Directory used by DuckDB for file operations
155
-
156
141
  ## Troubleshooting
157
142
 
158
143
  - If you encounter connection issues, verify your MotherDuck token is correct
159
- - For local file access problems, ensure the `HOME` environment variable is set correctly
144
+ - For local file access problems, ensure the `--home-dir` parameter is set correctly
160
145
  - Check that the `uvx` command is available in your PATH
146
+ - In version previous for v0.4.0 we used environment variables, now we use parameters
161
147
 
162
148
  ## License
163
149
 
@@ -0,0 +1,8 @@
1
+ mcp_server_motherduck/__init__.py,sha256=_HXXeC7-S1nr4oaNEQKt_TKJrdrS_1iWRt557_pX6kI,1642
2
+ mcp_server_motherduck/prompt.py,sha256=P7BrmhVXwDkPeSHQ3f25WMP6lpBpN2BxDzYPOQ3fxX8,56699
3
+ mcp_server_motherduck/server.py,sha256=cS1bLPEnrf3RSHklcAoktGUTxctvhH5DMp2SZ3eA1AM,9085
4
+ mcp_server_motherduck-0.4.0.dist-info/METADATA,sha256=766vAQwLLRwi6fNVoZKI6JpJKhGfEf1oKZWUPfjAwy0,5325
5
+ mcp_server_motherduck-0.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
6
+ mcp_server_motherduck-0.4.0.dist-info/entry_points.txt,sha256=dRTgcvWJn40bz0PVuKPylK6w92cFN32lwunZOgo5j4s,69
7
+ mcp_server_motherduck-0.4.0.dist-info/licenses/LICENSE,sha256=Tj68w9jCiceFKTvZ3jET-008NjhozcQMXpm-fyL9WUI,1067
8
+ mcp_server_motherduck-0.4.0.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- mcp_server_motherduck/__init__.py,sha256=fvkO3-wgyUVAdIzy-As4pl3_LYHFMgO9STVTHAyTyKA,1078
2
- mcp_server_motherduck/prompt.py,sha256=P7BrmhVXwDkPeSHQ3f25WMP6lpBpN2BxDzYPOQ3fxX8,56699
3
- mcp_server_motherduck/server.py,sha256=N7ySKj43BtMRGE_9HGhWr8_3wGSsjxKD9xIJJv7W4Eg,8841
4
- mcp_server_motherduck-0.3.4.dist-info/METADATA,sha256=jhdryCCXMVJdKKi0o7E6v9NiJBakx_d9HRECRn21mks,5623
5
- mcp_server_motherduck-0.3.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
6
- mcp_server_motherduck-0.3.4.dist-info/entry_points.txt,sha256=dRTgcvWJn40bz0PVuKPylK6w92cFN32lwunZOgo5j4s,69
7
- mcp_server_motherduck-0.3.4.dist-info/licenses/LICENSE,sha256=Tj68w9jCiceFKTvZ3jET-008NjhozcQMXpm-fyL9WUI,1067
8
- mcp_server_motherduck-0.3.4.dist-info/RECORD,,