mcp-server-motherduck 0.1.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.
@@ -0,0 +1,9 @@
1
+ from . import server
2
+ import asyncio
3
+
4
+ def main():
5
+ """Main entry point for the package."""
6
+ asyncio.run(server.main())
7
+
8
+ # Optionally expose other important items at package level
9
+ __all__ = ['main', 'server']
@@ -0,0 +1,110 @@
1
+ import asyncio
2
+
3
+ from mcp.server.models import InitializationOptions
4
+ import mcp.types as types
5
+ from mcp.server import NotificationOptions, Server
6
+ from pydantic import AnyUrl
7
+ import mcp.server.stdio
8
+ import duckdb
9
+
10
+ # Store notes as a simple key-value dict to demonstrate state management
11
+ notes: dict[str, str] = {}
12
+
13
+ server = Server("mcp-server-motherduck")
14
+
15
+ conn = duckdb.connect('md:')
16
+
17
+ @server.list_resources()
18
+ async def handle_list_resources() -> list[types.Resource]:
19
+ """
20
+ List available note resources.
21
+ Each note is exposed as a resource with a custom note:// URI scheme.
22
+ """
23
+ return []
24
+
25
+ @server.read_resource()
26
+ async def handle_read_resource(uri: AnyUrl) -> str:
27
+ """
28
+ Read a specific note's content by its URI.
29
+ The note name is extracted from the URI host component.
30
+ """
31
+ raise ValueError(f"Unsupported URI scheme: {uri.scheme}")
32
+
33
+ @server.list_prompts()
34
+ async def handle_list_prompts() -> list[types.Prompt]:
35
+ """
36
+ List available prompts.
37
+ Each prompt can have optional arguments to customize its behavior.
38
+ """
39
+ return []
40
+
41
+ @server.get_prompt()
42
+ async def handle_get_prompt(
43
+ name: str, arguments: dict[str, str] | None
44
+ ) -> types.GetPromptResult:
45
+ """
46
+ Generate a prompt by combining arguments with server state.
47
+ The prompt includes all current notes and can be customized via arguments.
48
+ """
49
+ return types.GetPromptResult(
50
+ description="None",
51
+ messages=[
52
+ types.PromptMessage(
53
+ role="user",
54
+ content=types.TextContent(
55
+ type="text",
56
+ text="none",
57
+ ),
58
+ )
59
+ ],
60
+ )
61
+
62
+ @server.list_tools()
63
+ async def handle_list_tools() -> list[types.Tool]:
64
+ """
65
+ List available tools.
66
+ Each tool specifies its arguments using JSON Schema validation.
67
+ """
68
+ return [
69
+ types.Tool(
70
+ name="read-query-motherduck",
71
+ description="Execute a SELECT query on the MotherDuck (DuckDB) database",
72
+ inputSchema={
73
+ "type": "object",
74
+ "properties": {
75
+ "query": {"type": "string", "description": "SELECT SQL query to execute"},
76
+ },
77
+ "required": ["query"],
78
+ },
79
+ )
80
+ ]
81
+
82
+ @server.call_tool()
83
+ async def handle_call_tool(
84
+ name: str, arguments: dict | None
85
+ ) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
86
+ """
87
+ Handle tool execution requests.
88
+ Tools can modify server state and notify clients of changes.
89
+ """
90
+ if name == "read-query-motherduck":
91
+ if not arguments["query"].strip().upper().startswith("SELECT"):
92
+ raise ValueError("Only SELECT queries are allowed for read-query")
93
+ results = conn.execute(arguments["query"]).fetchall()
94
+ return [types.TextContent(type="text", text=str(results))]
95
+
96
+ async def main():
97
+ # Run the server using stdin/stdout streams
98
+ async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
99
+ await server.run(
100
+ read_stream,
101
+ write_stream,
102
+ InitializationOptions(
103
+ server_name="motherduck",
104
+ server_version="0.1.0",
105
+ capabilities=server.get_capabilities(
106
+ notification_options=NotificationOptions(),
107
+ experimental_capabilities={},
108
+ ),
109
+ ),
110
+ )
@@ -0,0 +1,112 @@
1
+ Metadata-Version: 2.3
2
+ Name: mcp-server-motherduck
3
+ Version: 0.1.0
4
+ Summary: A MCP server for MotherDuck
5
+ Author-email: tdoehmen <till@motherduck.com>
6
+ Requires-Python: >=3.10
7
+ Requires-Dist: duckdb>=1.1.3
8
+ Requires-Dist: mcp>=1.0.0
9
+ Description-Content-Type: text/markdown
10
+
11
+ # mcp-server-motherduck MCP server
12
+
13
+ A MCP server for MotherDuck
14
+
15
+ ## Components
16
+
17
+ ### Resources
18
+
19
+ ### Prompts
20
+
21
+ ### Tools
22
+
23
+ The server implements one tool:
24
+ - read-query-motherduck: Executes a single SQL SELECT statement on MotherDuck and retrieves the result
25
+ - Takes "query" as required string arguments
26
+
27
+ ## Configuration
28
+
29
+ Set [MotherDuck token](https://motherduck.com/docs/key-tasks/authenticating-and-connecting-to-motherduck/authenticating-to-motherduck/#storing-the-access-token-as-an-environment-variable) as environment variable:
30
+ `export motherduck_token='<token>'`
31
+
32
+ ## Quickstart
33
+
34
+ ### Install
35
+
36
+ #### Claude Desktop
37
+
38
+ On MacOS: `~/Library/Application\ Support/Claude/claude_desktop_config.json`
39
+ On Windows: `%APPDATA%/Claude/claude_desktop_config.json`
40
+
41
+ <details>
42
+ <summary>Development/Unpublished Servers Configuration</summary>
43
+ ```
44
+ "mcpServers": {
45
+ "mcp-server-motherduck": {
46
+ "command": "uv",
47
+ "args": [
48
+ "--directory",
49
+ "/Users/<username>/mcp-server/mcp-server-motherduck",
50
+ "run",
51
+ "mcp-server-motherduck"
52
+ ]
53
+ }
54
+ }
55
+ ```
56
+ </details>
57
+
58
+ <details>
59
+ <summary>Published Servers Configuration</summary>
60
+ ```
61
+ "mcpServers": {
62
+ "mcp-server-motherduck": {
63
+ "command": "uvx",
64
+ "args": [
65
+ "mcp-server-motherduck"
66
+ ]
67
+ }
68
+ }
69
+ ```
70
+ </details>
71
+
72
+ ## Development
73
+
74
+ ### Building and Publishing
75
+
76
+ To prepare the package for distribution:
77
+
78
+ 1. Sync dependencies and update lockfile:
79
+ ```bash
80
+ uv sync
81
+ ```
82
+
83
+ 2. Build package distributions:
84
+ ```bash
85
+ uv build
86
+ ```
87
+
88
+ This will create source and wheel distributions in the `dist/` directory.
89
+
90
+ 3. Publish to PyPI:
91
+ ```bash
92
+ uv publish
93
+ ```
94
+
95
+ Note: You'll need to set PyPI credentials via environment variables or command flags:
96
+ - Token: `--token` or `UV_PUBLISH_TOKEN`
97
+ - Or username/password: `--username`/`UV_PUBLISH_USERNAME` and `--password`/`UV_PUBLISH_PASSWORD`
98
+
99
+ ### Debugging
100
+
101
+ Since MCP servers run over stdio, debugging can be challenging. For the best debugging
102
+ experience, we strongly recommend using the [MCP Inspector](https://github.com/modelcontextprotocol/inspector).
103
+
104
+
105
+ You can launch the MCP Inspector via [`npm`](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm) with this command:
106
+
107
+ ```bash
108
+ npx @modelcontextprotocol/inspector uv --directory /Users/doehmen/Documents/Research/docs/ai-playground/mcp-server/mcp-server-motherduck run mcp-server-motherduck
109
+ ```
110
+
111
+
112
+ Upon launching, the Inspector will display a URL that you can access in your browser to begin debugging.
@@ -0,0 +1,6 @@
1
+ mcp_server_motherduck/__init__.py,sha256=KNZ1bD9ZGfyZwlv91Ueeega_1lsRDLs2fYQDgNbBdtc,212
2
+ mcp_server_motherduck/server.py,sha256=iMKB8Y_RpPUKgjNMu1INJ2cTe0YOJIKWBIlkjoU1oXc,3445
3
+ mcp_server_motherduck-0.1.0.dist-info/METADATA,sha256=fNVbRCZNdhbSfZdabcpSS-YFkZRyyGdq1lDyuqgo_ho,2767
4
+ mcp_server_motherduck-0.1.0.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
5
+ mcp_server_motherduck-0.1.0.dist-info/entry_points.txt,sha256=dRTgcvWJn40bz0PVuKPylK6w92cFN32lwunZOgo5j4s,69
6
+ mcp_server_motherduck-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.26.3
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ mcp-server-motherduck = mcp_server_motherduck:main