sqlsaber 0.3.0__tar.gz → 0.4.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.

Potentially problematic release.


This version of sqlsaber might be problematic. Click here for more details.

Files changed (50) hide show
  1. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/CHANGELOG.md +9 -0
  2. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/PKG-INFO +40 -1
  3. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/README.md +38 -0
  4. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/pyproject.toml +4 -1
  5. sqlsaber-0.4.0/src/sqlsaber/agents/mcp.py +21 -0
  6. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/database/schema.py +2 -2
  7. sqlsaber-0.4.0/src/sqlsaber/mcp/__init__.py +5 -0
  8. sqlsaber-0.4.0/src/sqlsaber/mcp/mcp.py +138 -0
  9. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/uv.lock +171 -1
  10. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/.github/workflows/publish.yml +0 -0
  11. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/.gitignore +0 -0
  12. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/.python-version +0 -0
  13. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/CLAUDE.md +0 -0
  14. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/LICENSE +0 -0
  15. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/pytest.ini +0 -0
  16. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/__init__.py +0 -0
  17. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/__main__.py +0 -0
  18. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/agents/__init__.py +0 -0
  19. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/agents/anthropic.py +0 -0
  20. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/agents/base.py +0 -0
  21. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/agents/streaming.py +0 -0
  22. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/cli/__init__.py +0 -0
  23. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/cli/commands.py +0 -0
  24. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/cli/database.py +0 -0
  25. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/cli/display.py +0 -0
  26. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/cli/interactive.py +0 -0
  27. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/cli/memory.py +0 -0
  28. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/cli/models.py +0 -0
  29. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/cli/streaming.py +0 -0
  30. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/config/__init__.py +0 -0
  31. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/config/api_keys.py +0 -0
  32. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/config/database.py +0 -0
  33. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/config/settings.py +0 -0
  34. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/database/__init__.py +0 -0
  35. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/database/connection.py +0 -0
  36. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/memory/__init__.py +0 -0
  37. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/memory/manager.py +0 -0
  38. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/memory/storage.py +0 -0
  39. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/models/__init__.py +0 -0
  40. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/models/events.py +0 -0
  41. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/src/sqlsaber/models/types.py +0 -0
  42. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/tests/__init__.py +0 -0
  43. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/tests/conftest.py +0 -0
  44. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/tests/test_cli/__init__.py +0 -0
  45. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/tests/test_cli/test_commands.py +0 -0
  46. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/tests/test_config/__init__.py +0 -0
  47. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/tests/test_config/test_database.py +0 -0
  48. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/tests/test_config/test_settings.py +0 -0
  49. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/tests/test_database/__init__.py +0 -0
  50. {sqlsaber-0.3.0 → sqlsaber-0.4.0}/tests/test_database/test_connection.py +0 -0
@@ -4,6 +4,15 @@ All notable changes to SQLSaber will be documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [0.4.0] - 2025-06-25
8
+
9
+ ### Added
10
+
11
+ - MCP (Model Context Protocol) server support
12
+ - `saber-mcp` console script for running MCP server
13
+ - MCP tools: `get_databases()`, `list_tables()`, `introspect_schema()`, `execute_sql()`
14
+ - Instructions and documentation for configuring MCP clients (Claude Code, etc.)
15
+
7
16
  ## [0.3.0] - 2025-06-25
8
17
 
9
18
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlsaber
3
- Version: 0.3.0
3
+ Version: 0.4.0
4
4
  Summary: SQLSaber - Agentic SQL assistant like Claude Code
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.12
@@ -8,6 +8,7 @@ Requires-Dist: aiomysql>=0.2.0
8
8
  Requires-Dist: aiosqlite>=0.21.0
9
9
  Requires-Dist: anthropic>=0.54.0
10
10
  Requires-Dist: asyncpg>=0.30.0
11
+ Requires-Dist: fastmcp>=2.9.0
11
12
  Requires-Dist: httpx>=0.28.1
12
13
  Requires-Dist: keyring>=25.6.0
13
14
  Requires-Dist: pandas>=2.0.0
@@ -34,6 +35,7 @@ Ask your questions in natural language and it will gather the right context and
34
35
  - 💬 Interactive REPL mode
35
36
  - 🎨 Beautiful formatted output with syntax highlighting
36
37
  - 🗄️ Support for PostgreSQL, SQLite, and MySQL
38
+ - 🔌 MCP (Model Context Protocol) server support
37
39
 
38
40
  ## Installation
39
41
 
@@ -140,6 +142,43 @@ saber query "show me the distribution of customer ages"
140
142
  saber query "which products had the highest sales growth last quarter?"
141
143
  ```
142
144
 
145
+ ## MCP Server Integration
146
+
147
+ SQLSaber includes an MCP (Model Context Protocol) server that allows AI agents like Claude Code to directly leverage tools available in SQLSaber.
148
+
149
+ ### Starting the MCP Server
150
+
151
+ Run the MCP server using uvx:
152
+
153
+ ```bash
154
+ uvx saber-mcp
155
+ ```
156
+
157
+ ### Configuring MCP Clients
158
+
159
+ #### Claude Code
160
+
161
+ Add SQLSaber as an MCP server in Claude Code:
162
+
163
+ ```bash
164
+ claude mcp add -- uvx saber-mcp
165
+ ```
166
+
167
+ #### Other MCP Clients
168
+
169
+ For other MCP clients, configure them to run the command: `uvx saber-mcp`
170
+
171
+ ### Available MCP Tools
172
+
173
+ Once connected, the MCP client will have access to these tools:
174
+
175
+ - `get_databases()` - Lists all configured databases
176
+ - `list_tables(database)` - Get all tables in a database with row counts
177
+ - `introspect_schema(database, table_pattern?)` - Get detailed schema information
178
+ - `execute_sql(database, query, limit?)` - Execute SQL queries (read-only)
179
+
180
+ The MCP server uses your existing SQLSaber database configurations, so make sure to set up your databases using `saber db add` first.
181
+
143
182
  ## How It Works
144
183
 
145
184
  SQLSaber uses an intelligent three-step process optimized for minimal token usage:
@@ -15,6 +15,7 @@ Ask your questions in natural language and it will gather the right context and
15
15
  - 💬 Interactive REPL mode
16
16
  - 🎨 Beautiful formatted output with syntax highlighting
17
17
  - 🗄️ Support for PostgreSQL, SQLite, and MySQL
18
+ - 🔌 MCP (Model Context Protocol) server support
18
19
 
19
20
  ## Installation
20
21
 
@@ -121,6 +122,43 @@ saber query "show me the distribution of customer ages"
121
122
  saber query "which products had the highest sales growth last quarter?"
122
123
  ```
123
124
 
125
+ ## MCP Server Integration
126
+
127
+ SQLSaber includes an MCP (Model Context Protocol) server that allows AI agents like Claude Code to directly leverage tools available in SQLSaber.
128
+
129
+ ### Starting the MCP Server
130
+
131
+ Run the MCP server using uvx:
132
+
133
+ ```bash
134
+ uvx saber-mcp
135
+ ```
136
+
137
+ ### Configuring MCP Clients
138
+
139
+ #### Claude Code
140
+
141
+ Add SQLSaber as an MCP server in Claude Code:
142
+
143
+ ```bash
144
+ claude mcp add -- uvx saber-mcp
145
+ ```
146
+
147
+ #### Other MCP Clients
148
+
149
+ For other MCP clients, configure them to run the command: `uvx saber-mcp`
150
+
151
+ ### Available MCP Tools
152
+
153
+ Once connected, the MCP client will have access to these tools:
154
+
155
+ - `get_databases()` - Lists all configured databases
156
+ - `list_tables(database)` - Get all tables in a database with row counts
157
+ - `introspect_schema(database, table_pattern?)` - Get detailed schema information
158
+ - `execute_sql(database, query, limit?)` - Execute SQL queries (read-only)
159
+
160
+ The MCP server uses your existing SQLSaber database configurations, so make sure to set up your databases using `saber db add` first.
161
+
124
162
  ## How It Works
125
163
 
126
164
  SQLSaber uses an intelligent three-step process optimized for minimal token usage:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sqlsaber"
3
- version = "0.3.0"
3
+ version = "0.4.0"
4
4
  description = "SQLSaber - Agentic SQL assistant like Claude Code"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -16,6 +16,7 @@ dependencies = [
16
16
  "aiomysql>=0.2.0",
17
17
  "aiosqlite>=0.21.0",
18
18
  "pandas>=2.0.0",
19
+ "fastmcp>=2.9.0",
19
20
  ]
20
21
 
21
22
  [tool.uv]
@@ -32,3 +33,5 @@ packages = ["src/sqlsaber"]
32
33
  sqlsaber = "sqlsaber.cli.commands:main"
33
34
  saber = "sqlsaber.cli.commands:main"
34
35
  sql = "sqlsaber.cli.commands:main"
36
+ sqlsaber-mcp = "sqlsaber.mcp.mcp:main"
37
+ saber-mcp = "sqlsaber.mcp.mcp:main"
@@ -0,0 +1,21 @@
1
+ """Generic SQL agent implementation for MCP tools."""
2
+
3
+ from typing import AsyncIterator
4
+ from sqlsaber.agents.base import BaseSQLAgent
5
+ from sqlsaber.database.connection import BaseDatabaseConnection
6
+ from sqlsaber.models.events import StreamEvent
7
+
8
+
9
+ class MCPSQLAgent(BaseSQLAgent):
10
+ """MCP SQL Agent for MCP tool operations without LLM-specific logic."""
11
+
12
+ def __init__(self, db_connection: BaseDatabaseConnection):
13
+ super().__init__(db_connection)
14
+
15
+ async def query_stream(
16
+ self, user_query: str, use_history: bool = True
17
+ ) -> AsyncIterator[StreamEvent]:
18
+ """Not implemented for generic agent as it's only used for tool operations."""
19
+ raise NotImplementedError(
20
+ "MCPSQLAgent does not support query streaming. Use specific agent implementations for conversation."
21
+ )
@@ -201,8 +201,8 @@ class PostgreSQLSchemaIntrospector(BaseSchemaIntrospector):
201
201
  t.table_type,
202
202
  COALESCE(ts.approximate_row_count, 0) as row_count
203
203
  FROM information_schema.tables t
204
- LEFT JOIN table_stats ts
205
- ON t.table_schema = ts.schemaname
204
+ LEFT JOIN table_stats ts
205
+ ON t.table_schema = ts.schemaname
206
206
  AND t.table_name = ts.tablename
207
207
  WHERE t.table_schema NOT IN ('pg_catalog', 'information_schema')
208
208
  ORDER BY t.table_schema, t.table_name;
@@ -0,0 +1,5 @@
1
+ """MCP (Model Context Protocol) server implementation for SQLSaber."""
2
+
3
+ from .mcp import mcp
4
+
5
+ __all__ = ["mcp"]
@@ -0,0 +1,138 @@
1
+ """FastMCP server implementation for SQLSaber."""
2
+
3
+ import json
4
+ from typing import Optional
5
+
6
+ from fastmcp import FastMCP
7
+
8
+ from sqlsaber.agents.mcp import MCPSQLAgent
9
+ from sqlsaber.config.database import DatabaseConfigManager
10
+ from sqlsaber.database.connection import DatabaseConnection
11
+
12
+ INSTRUCTIONS = """
13
+ This server provides helpful resources and tools that will help you address users queries on their database.
14
+
15
+ - Get all databases using `get_databases()`
16
+ - Call `list_tables()` to get a list of all tables in the database with row counts. Use this first to discover available tables.
17
+ - Call `introspect_schema()` to introspect database schema to understand table structures.
18
+ - Call `execute_sql()` to execute SQL queries against the database and retrieve results.
19
+
20
+ Guidelines:
21
+ - Use list_tables first, then introspect_schema for specific tables only
22
+ - Use table patterns like 'sample%' or '%experiment%' to filter related tables
23
+ - Use proper JOIN syntax and avoid cartesian products
24
+ - Include appropriate WHERE clauses to limit results
25
+ - Handle errors gracefully and suggest fixes
26
+ """
27
+
28
+ # Create the FastMCP server instance
29
+ mcp = FastMCP(name="SQL Assistant", instructions=INSTRUCTIONS)
30
+
31
+ # Initialize the database config manager
32
+ config_manager = DatabaseConfigManager()
33
+
34
+
35
+ async def _create_agent_for_database(database_name: str) -> Optional[MCPSQLAgent]:
36
+ """Create a MCPSQLAgent for the specified database."""
37
+ try:
38
+ # Look up configured database connection
39
+ db_config = config_manager.get_database(database_name)
40
+ if not db_config:
41
+ return None
42
+ connection_string = db_config.to_connection_string()
43
+
44
+ # Create database connection
45
+ db_conn = DatabaseConnection(connection_string)
46
+
47
+ # Create and return the agent
48
+ agent = MCPSQLAgent(db_conn)
49
+ return agent
50
+
51
+ except Exception:
52
+ return None
53
+
54
+
55
+ @mcp.tool
56
+ def get_databases() -> dict:
57
+ """List all configured databases with their types."""
58
+ databases = []
59
+ for db_config in config_manager.list_databases():
60
+ databases.append(
61
+ {
62
+ "name": db_config.name,
63
+ "type": db_config.type,
64
+ "database": db_config.database,
65
+ "host": db_config.host,
66
+ "port": db_config.port,
67
+ "is_default": db_config.name == config_manager.get_default_name(),
68
+ }
69
+ )
70
+
71
+ return {"databases": databases, "count": len(databases)}
72
+
73
+
74
+ @mcp.tool
75
+ async def list_tables(database: str) -> str:
76
+ """
77
+ Get a list of all tables in the database with row counts. Use this first to discover available tables.
78
+ """
79
+ try:
80
+ agent = await _create_agent_for_database(database)
81
+ if not agent:
82
+ return json.dumps(
83
+ {"error": f"Database '{database}' not found or could not connect"}
84
+ )
85
+
86
+ result = await agent.list_tables()
87
+ await agent.db.close()
88
+ return result
89
+
90
+ except Exception as e:
91
+ return json.dumps({"error": f"Error listing tables: {str(e)}"})
92
+
93
+
94
+ @mcp.tool
95
+ async def introspect_schema(database: str, table_pattern: Optional[str] = None) -> str:
96
+ """
97
+ Introspect database schema to understand table structures. Use optional pattern to filter tables (e.g., 'public.users', 'user%', '%order%').
98
+ """
99
+ try:
100
+ agent = await _create_agent_for_database(database)
101
+ if not agent:
102
+ return json.dumps(
103
+ {"error": f"Database '{database}' not found or could not connect"}
104
+ )
105
+
106
+ result = await agent.introspect_schema(table_pattern)
107
+ await agent.db.close()
108
+ return result
109
+
110
+ except Exception as e:
111
+ return json.dumps({"error": f"Error introspecting schema: {str(e)}"})
112
+
113
+
114
+ @mcp.tool
115
+ async def execute_sql(database: str, query: str, limit: Optional[int] = 100) -> str:
116
+ """Execute a SQL query against the specified database."""
117
+ try:
118
+ agent = await _create_agent_for_database(database)
119
+ if not agent:
120
+ return json.dumps(
121
+ {"error": f"Database '{database}' not found or could not connect"}
122
+ )
123
+
124
+ result = await agent.execute_sql(query, limit)
125
+ await agent.db.close()
126
+ return result
127
+
128
+ except Exception as e:
129
+ return json.dumps({"error": f"Error executing SQL: {str(e)}"})
130
+
131
+
132
+ def main():
133
+ """Entry point for the MCP server console script."""
134
+ mcp.run()
135
+
136
+
137
+ if __name__ == "__main__":
138
+ main()
@@ -91,6 +91,18 @@ wheels = [
91
91
  { url = "https://files.pythonhosted.org/packages/c8/a4/cec76b3389c4c5ff66301cd100fe88c318563ec8a520e0b2e792b5b84972/asyncpg-0.30.0-cp313-cp313-win_amd64.whl", hash = "sha256:f59b430b8e27557c3fb9869222559f7417ced18688375825f8f12302c34e915e", size = 621623 },
92
92
  ]
93
93
 
94
+ [[package]]
95
+ name = "authlib"
96
+ version = "1.6.0"
97
+ source = { registry = "https://pypi.org/simple" }
98
+ dependencies = [
99
+ { name = "cryptography" },
100
+ ]
101
+ sdist = { url = "https://files.pythonhosted.org/packages/a2/9d/b1e08d36899c12c8b894a44a5583ee157789f26fc4b176f8e4b6217b56e1/authlib-1.6.0.tar.gz", hash = "sha256:4367d32031b7af175ad3a323d571dc7257b7099d55978087ceae4a0d88cd3210", size = 158371 }
102
+ wheels = [
103
+ { url = "https://files.pythonhosted.org/packages/84/29/587c189bbab1ccc8c86a03a5d0e13873df916380ef1be461ebe6acebf48d/authlib-1.6.0-py2.py3-none-any.whl", hash = "sha256:91685589498f79e8655e8a8947431ad6288831d643f11c55c2143ffcc738048d", size = 239981 },
104
+ ]
105
+
94
106
  [[package]]
95
107
  name = "certifi"
96
108
  version = "2025.6.15"
@@ -109,6 +121,8 @@ dependencies = [
109
121
  ]
110
122
  sdist = { url = "https://files.pythonhosted.org/packages/fc/97/c783634659c2920c3fc70419e3af40972dbaf758daa229a7d6ea6135c90d/cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", size = 516621 }
111
123
  wheels = [
124
+ { url = "https://files.pythonhosted.org/packages/5a/84/e94227139ee5fb4d600a7a4927f322e1d4aea6fdc50bd3fca8493caba23f/cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", size = 183178 },
125
+ { url = "https://files.pythonhosted.org/packages/da/ee/fb72c2b48656111c4ef27f0f91da355e130a923473bf5ee75c5643d00cca/cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", size = 178840 },
112
126
  { url = "https://files.pythonhosted.org/packages/cc/b6/db007700f67d151abadf508cbfd6a1884f57eab90b1bb985c4c8c02b0f28/cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", size = 454803 },
113
127
  { url = "https://files.pythonhosted.org/packages/1a/df/f8d151540d8c200eb1c6fba8cd0dfd40904f1b0682ea705c36e6c2e97ab3/cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", size = 478850 },
114
128
  { url = "https://files.pythonhosted.org/packages/28/c0/b31116332a547fd2677ae5b78a2ef662dfc8023d67f41b2a83f7c2aa78b1/cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", size = 485729 },
@@ -116,6 +130,10 @@ wheels = [
116
130
  { url = "https://files.pythonhosted.org/packages/b2/d5/da47df7004cb17e4955df6a43d14b3b4ae77737dff8bf7f8f333196717bf/cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", size = 479424 },
117
131
  { url = "https://files.pythonhosted.org/packages/0b/ac/2a28bcf513e93a219c8a4e8e125534f4f6db03e3179ba1c45e949b76212c/cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", size = 484568 },
118
132
  { url = "https://files.pythonhosted.org/packages/d4/38/ca8a4f639065f14ae0f1d9751e70447a261f1a30fa7547a828ae08142465/cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", size = 488736 },
133
+ { url = "https://files.pythonhosted.org/packages/86/c5/28b2d6f799ec0bdecf44dced2ec5ed43e0eb63097b0f58c293583b406582/cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", size = 172448 },
134
+ { url = "https://files.pythonhosted.org/packages/50/b9/db34c4755a7bd1cb2d1603ac3863f22bcecbd1ba29e5ee841a4bc510b294/cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", size = 181976 },
135
+ { url = "https://files.pythonhosted.org/packages/8d/f8/dd6c246b148639254dad4d6803eb6a54e8c85c6e11ec9df2cffa87571dbe/cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", size = 182989 },
136
+ { url = "https://files.pythonhosted.org/packages/8b/f1/672d303ddf17c24fc83afd712316fda78dc6fce1cd53011b839483e1ecc8/cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", size = 178802 },
119
137
  { url = "https://files.pythonhosted.org/packages/0e/2d/eab2e858a91fdff70533cab61dcff4a1f55ec60425832ddfdc9cd36bc8af/cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", size = 454792 },
120
138
  { url = "https://files.pythonhosted.org/packages/75/b2/fbaec7c4455c604e29388d55599b99ebcc250a60050610fadde58932b7ee/cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", size = 478893 },
121
139
  { url = "https://files.pythonhosted.org/packages/4f/b7/6e4a2162178bf1935c336d4da8a9352cccab4d3a5d7914065490f08c0690/cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", size = 485810 },
@@ -123,6 +141,8 @@ wheels = [
123
141
  { url = "https://files.pythonhosted.org/packages/26/9f/1aab65a6c0db35f43c4d1b4f580e8df53914310afc10ae0397d29d697af4/cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", size = 479447 },
124
142
  { url = "https://files.pythonhosted.org/packages/5f/e4/fb8b3dd8dc0e98edf1135ff067ae070bb32ef9d509d6cb0f538cd6f7483f/cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", size = 484358 },
125
143
  { url = "https://files.pythonhosted.org/packages/f1/47/d7145bf2dc04684935d57d67dff9d6d795b2ba2796806bb109864be3a151/cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", size = 488469 },
144
+ { url = "https://files.pythonhosted.org/packages/bf/ee/f94057fa6426481d663b88637a9a10e859e492c73d0384514a17d78ee205/cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", size = 172475 },
145
+ { url = "https://files.pythonhosted.org/packages/7c/fc/6a8cb64e5f0324877d503c854da15d76c1e50eb722e320b15345c4d0c6de/cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", size = 182009 },
126
146
  ]
127
147
 
128
148
  [[package]]
@@ -155,6 +175,7 @@ dependencies = [
155
175
  ]
156
176
  sdist = { url = "https://files.pythonhosted.org/packages/fe/c8/a2a376a8711c1e11708b9c9972e0c3223f5fc682552c82d8db844393d6ce/cryptography-45.0.4.tar.gz", hash = "sha256:7405ade85c83c37682c8fe65554759800a4a8c54b2d96e0f8ad114d31b808d57", size = 744890 }
157
177
  wheels = [
178
+ { url = "https://files.pythonhosted.org/packages/cc/1c/92637793de053832523b410dbe016d3f5c11b41d0cf6eef8787aabb51d41/cryptography-45.0.4-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:425a9a6ac2823ee6e46a76a21a4e8342d8fa5c01e08b823c1f19a8b74f096069", size = 7055712 },
158
179
  { url = "https://files.pythonhosted.org/packages/ba/14/93b69f2af9ba832ad6618a03f8a034a5851dc9a3314336a3d71c252467e1/cryptography-45.0.4-cp311-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:680806cf63baa0039b920f4976f5f31b10e772de42f16310a6839d9f21a26b0d", size = 4205335 },
159
180
  { url = "https://files.pythonhosted.org/packages/67/30/fae1000228634bf0b647fca80403db5ca9e3933b91dd060570689f0bd0f7/cryptography-45.0.4-cp311-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4ca0f52170e821bc8da6fc0cc565b7bb8ff8d90d36b5e9fdd68e8a86bdf72036", size = 4431487 },
160
181
  { url = "https://files.pythonhosted.org/packages/6d/5a/7dffcf8cdf0cb3c2430de7404b327e3db64735747d641fc492539978caeb/cryptography-45.0.4-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:f3fe7a5ae34d5a414957cc7f457e2b92076e72938423ac64d215722f6cf49a9e", size = 4208922 },
@@ -164,6 +185,9 @@ wheels = [
164
185
  { url = "https://files.pythonhosted.org/packages/db/b7/a84bdcd19d9c02ec5807f2ec2d1456fd8451592c5ee353816c09250e3561/cryptography-45.0.4-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:2882338b2a6e0bd337052e8b9007ced85c637da19ef9ecaf437744495c8c2999", size = 4463623 },
165
186
  { url = "https://files.pythonhosted.org/packages/d8/84/69707d502d4d905021cac3fb59a316344e9f078b1da7fb43ecde5e10840a/cryptography-45.0.4-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:23b9c3ea30c3ed4db59e7b9619272e94891f8a3a5591d0b656a7582631ccf750", size = 4332447 },
166
187
  { url = "https://files.pythonhosted.org/packages/f3/ee/d4f2ab688e057e90ded24384e34838086a9b09963389a5ba6854b5876598/cryptography-45.0.4-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b0a97c927497e3bc36b33987abb99bf17a9a175a19af38a892dc4bbb844d7ee2", size = 4572830 },
188
+ { url = "https://files.pythonhosted.org/packages/70/d4/994773a261d7ff98034f72c0e8251fe2755eac45e2265db4c866c1c6829c/cryptography-45.0.4-cp311-abi3-win32.whl", hash = "sha256:e00a6c10a5c53979d6242f123c0a97cff9f3abed7f064fc412c36dc521b5f257", size = 2932769 },
189
+ { url = "https://files.pythonhosted.org/packages/5a/42/c80bd0b67e9b769b364963b5252b17778a397cefdd36fa9aa4a5f34c599a/cryptography-45.0.4-cp311-abi3-win_amd64.whl", hash = "sha256:817ee05c6c9f7a69a16200f0c90ab26d23a87701e2a284bd15156783e46dbcc8", size = 3410441 },
190
+ { url = "https://files.pythonhosted.org/packages/ce/0b/2488c89f3a30bc821c9d96eeacfcab6ff3accc08a9601ba03339c0fd05e5/cryptography-45.0.4-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:964bcc28d867e0f5491a564b7debb3ffdd8717928d315d12e0d7defa9e43b723", size = 7031836 },
167
191
  { url = "https://files.pythonhosted.org/packages/fe/51/8c584ed426093aac257462ae62d26ad61ef1cbf5b58d8b67e6e13c39960e/cryptography-45.0.4-cp37-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6a5bf57554e80f75a7db3d4b1dacaa2764611ae166ab42ea9a72bcdb5d577637", size = 4195746 },
168
192
  { url = "https://files.pythonhosted.org/packages/5c/7d/4b0ca4d7af95a704eef2f8f80a8199ed236aaf185d55385ae1d1610c03c2/cryptography-45.0.4-cp37-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:46cf7088bf91bdc9b26f9c55636492c1cce3e7aaf8041bbf0243f5e5325cfb2d", size = 4424456 },
169
193
  { url = "https://files.pythonhosted.org/packages/1d/45/5fabacbc6e76ff056f84d9f60eeac18819badf0cefc1b6612ee03d4ab678/cryptography-45.0.4-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7bedbe4cc930fa4b100fc845ea1ea5788fcd7ae9562e669989c11618ae8d76ee", size = 4198495 },
@@ -173,6 +197,8 @@ wheels = [
173
197
  { url = "https://files.pythonhosted.org/packages/3a/c0/85fa358ddb063ec588aed4a6ea1df57dc3e3bc1712d87c8fa162d02a65fc/cryptography-45.0.4-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:06509dc70dd71fa56eaa138336244e2fbaf2ac164fc9b5e66828fccfd2b680d6", size = 4451442 },
174
198
  { url = "https://files.pythonhosted.org/packages/33/67/362d6ec1492596e73da24e669a7fbbaeb1c428d6bf49a29f7a12acffd5dc/cryptography-45.0.4-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5f31e6b0a5a253f6aa49be67279be4a7e5a4ef259a9f33c69f7d1b1191939872", size = 4325038 },
175
199
  { url = "https://files.pythonhosted.org/packages/53/75/82a14bf047a96a1b13ebb47fb9811c4f73096cfa2e2b17c86879687f9027/cryptography-45.0.4-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:944e9ccf67a9594137f942d5b52c8d238b1b4e46c7a0c2891b7ae6e01e7c80a4", size = 4560964 },
200
+ { url = "https://files.pythonhosted.org/packages/cd/37/1a3cba4c5a468ebf9b95523a5ef5651244693dc712001e276682c278fc00/cryptography-45.0.4-cp37-abi3-win32.whl", hash = "sha256:c22fe01e53dc65edd1945a2e6f0015e887f84ced233acecb64b4daadb32f5c97", size = 2924557 },
201
+ { url = "https://files.pythonhosted.org/packages/2a/4b/3256759723b7e66380397d958ca07c59cfc3fb5c794fb5516758afd05d41/cryptography-45.0.4-cp37-abi3-win_amd64.whl", hash = "sha256:627ba1bc94f6adf0b0a2e35d87020285ead22d9f648c7e75bb64f367375f3b22", size = 3395508 },
176
202
  ]
177
203
 
178
204
  [[package]]
@@ -184,6 +210,37 @@ wheels = [
184
210
  { url = "https://files.pythonhosted.org/packages/12/b3/231ffd4ab1fc9d679809f356cebee130ac7daa00d6d6f3206dd4fd137e9e/distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2", size = 20277 },
185
211
  ]
186
212
 
213
+ [[package]]
214
+ name = "exceptiongroup"
215
+ version = "1.3.0"
216
+ source = { registry = "https://pypi.org/simple" }
217
+ dependencies = [
218
+ { name = "typing-extensions", marker = "python_full_version < '3.13'" },
219
+ ]
220
+ sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749 }
221
+ wheels = [
222
+ { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674 },
223
+ ]
224
+
225
+ [[package]]
226
+ name = "fastmcp"
227
+ version = "2.9.0"
228
+ source = { registry = "https://pypi.org/simple" }
229
+ dependencies = [
230
+ { name = "authlib" },
231
+ { name = "exceptiongroup" },
232
+ { name = "httpx" },
233
+ { name = "mcp" },
234
+ { name = "openapi-pydantic" },
235
+ { name = "python-dotenv" },
236
+ { name = "rich" },
237
+ { name = "typer" },
238
+ ]
239
+ sdist = { url = "https://files.pythonhosted.org/packages/2d/43/31af92e392c8e28269599fe3228419fe4bbb829b04a61fac17ab8dd2a7a9/fastmcp-2.9.0.tar.gz", hash = "sha256:3f1dc97c409193729b4aa8ad240ad396fe767a982c55c3a3e788f422b1278dd6", size = 2650412 }
240
+ wheels = [
241
+ { url = "https://files.pythonhosted.org/packages/dc/43/1095c0cbcf9f3b25d048faaf361b81b4dec403c3f75990dc93eeb6f3c3af/fastmcp-2.9.0-py3-none-any.whl", hash = "sha256:e5b00e5fcea2d216d96f7cfb8b67836bd58fc3cd57147e0d89043d905a84334f", size = 159401 },
242
+ ]
243
+
187
244
  [[package]]
188
245
  name = "h11"
189
246
  version = "0.16.0"
@@ -221,6 +278,15 @@ wheels = [
221
278
  { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
222
279
  ]
223
280
 
281
+ [[package]]
282
+ name = "httpx-sse"
283
+ version = "0.4.1"
284
+ source = { registry = "https://pypi.org/simple" }
285
+ sdist = { url = "https://files.pythonhosted.org/packages/6e/fa/66bd985dd0b7c109a3bcb89272ee0bfb7e2b4d06309ad7b38ff866734b2a/httpx_sse-0.4.1.tar.gz", hash = "sha256:8f44d34414bc7b21bf3602713005c5df4917884f76072479b21f68befa4ea26e", size = 12998 }
286
+ wheels = [
287
+ { url = "https://files.pythonhosted.org/packages/25/0a/6269e3473b09aed2dab8aa1a600c70f31f00ae1349bee30658f7e358a159/httpx_sse-0.4.1-py3-none-any.whl", hash = "sha256:cba42174344c3a5b06f255ce65b350880f962d99ead85e776f23c6618a377a37", size = 8054 },
288
+ ]
289
+
224
290
  [[package]]
225
291
  name = "idna"
226
292
  version = "3.10"
@@ -358,6 +424,26 @@ wheels = [
358
424
  { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
359
425
  ]
360
426
 
427
+ [[package]]
428
+ name = "mcp"
429
+ version = "1.9.4"
430
+ source = { registry = "https://pypi.org/simple" }
431
+ dependencies = [
432
+ { name = "anyio" },
433
+ { name = "httpx" },
434
+ { name = "httpx-sse" },
435
+ { name = "pydantic" },
436
+ { name = "pydantic-settings" },
437
+ { name = "python-multipart" },
438
+ { name = "sse-starlette" },
439
+ { name = "starlette" },
440
+ { name = "uvicorn", marker = "sys_platform != 'emscripten'" },
441
+ ]
442
+ sdist = { url = "https://files.pythonhosted.org/packages/06/f2/dc2450e566eeccf92d89a00c3e813234ad58e2ba1e31d11467a09ac4f3b9/mcp-1.9.4.tar.gz", hash = "sha256:cfb0bcd1a9535b42edaef89947b9e18a8feb49362e1cc059d6e7fc636f2cb09f", size = 333294 }
443
+ wheels = [
444
+ { url = "https://files.pythonhosted.org/packages/97/fc/80e655c955137393c443842ffcc4feccab5b12fa7cb8de9ced90f90e6998/mcp-1.9.4-py3-none-any.whl", hash = "sha256:7fcf36b62936adb8e63f89346bccca1268eeca9bf6dfb562ee10b1dfbda9dac0", size = 130232 },
445
+ ]
446
+
361
447
  [[package]]
362
448
  name = "mdurl"
363
449
  version = "0.1.2"
@@ -417,6 +503,18 @@ wheels = [
417
503
  { url = "https://files.pythonhosted.org/packages/d4/ca/af82bf0fad4c3e573c6930ed743b5308492ff19917c7caaf2f9b6f9e2e98/numpy-2.3.1-cp313-cp313t-win_arm64.whl", hash = "sha256:eccb9a159db9aed60800187bc47a6d3451553f0e1b08b068d8b277ddfbb9b244", size = 10260376 },
418
504
  ]
419
505
 
506
+ [[package]]
507
+ name = "openapi-pydantic"
508
+ version = "0.5.1"
509
+ source = { registry = "https://pypi.org/simple" }
510
+ dependencies = [
511
+ { name = "pydantic" },
512
+ ]
513
+ sdist = { url = "https://files.pythonhosted.org/packages/02/2e/58d83848dd1a79cb92ed8e63f6ba901ca282c5f09d04af9423ec26c56fd7/openapi_pydantic-0.5.1.tar.gz", hash = "sha256:ff6835af6bde7a459fb93eb93bb92b8749b754fc6e51b2f1590a19dc3005ee0d", size = 60892 }
514
+ wheels = [
515
+ { url = "https://files.pythonhosted.org/packages/12/cf/03675d8bd8ecbf4445504d8071adab19f5f993676795708e36402ab38263/openapi_pydantic-0.5.1-py3-none-any.whl", hash = "sha256:a3a09ef4586f5bd760a8df7f43028b60cafb6d9f61de2acba9574766255ab146", size = 96381 },
516
+ ]
517
+
420
518
  [[package]]
421
519
  name = "packaging"
422
520
  version = "25.0"
@@ -556,6 +654,20 @@ wheels = [
556
654
  { url = "https://files.pythonhosted.org/packages/6f/9a/e73262f6c6656262b5fdd723ad90f518f579b7bc8622e43a942eec53c938/pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", size = 1935777 },
557
655
  ]
558
656
 
657
+ [[package]]
658
+ name = "pydantic-settings"
659
+ version = "2.10.1"
660
+ source = { registry = "https://pypi.org/simple" }
661
+ dependencies = [
662
+ { name = "pydantic" },
663
+ { name = "python-dotenv" },
664
+ { name = "typing-inspection" },
665
+ ]
666
+ sdist = { url = "https://files.pythonhosted.org/packages/68/85/1ea668bbab3c50071ca613c6ab30047fb36ab0da1b92fa8f17bbc38fd36c/pydantic_settings-2.10.1.tar.gz", hash = "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", size = 172583 }
667
+ wheels = [
668
+ { url = "https://files.pythonhosted.org/packages/58/f0/427018098906416f580e3cf1366d3b1abfb408a0652e9f31600c24a1903c/pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796", size = 45235 },
669
+ ]
670
+
559
671
  [[package]]
560
672
  name = "pygments"
561
673
  version = "2.19.1"
@@ -614,6 +726,24 @@ wheels = [
614
726
  { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 },
615
727
  ]
616
728
 
729
+ [[package]]
730
+ name = "python-dotenv"
731
+ version = "1.1.1"
732
+ source = { registry = "https://pypi.org/simple" }
733
+ sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978 }
734
+ wheels = [
735
+ { url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556 },
736
+ ]
737
+
738
+ [[package]]
739
+ name = "python-multipart"
740
+ version = "0.0.20"
741
+ source = { registry = "https://pypi.org/simple" }
742
+ sdist = { url = "https://files.pythonhosted.org/packages/f3/87/f44d7c9f274c7ee665a29b885ec97089ec5dc034c7f3fafa03da9e39a09e/python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13", size = 37158 }
743
+ wheels = [
744
+ { url = "https://files.pythonhosted.org/packages/45/58/38b5afbc1a800eeea951b9285d3912613f2603bdf897a4ab0f4bd7f405fc/python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104", size = 24546 },
745
+ ]
746
+
617
747
  [[package]]
618
748
  name = "pytz"
619
749
  version = "2025.2"
@@ -724,13 +854,14 @@ wheels = [
724
854
 
725
855
  [[package]]
726
856
  name = "sqlsaber"
727
- version = "0.3.0"
857
+ version = "0.4.0"
728
858
  source = { editable = "." }
729
859
  dependencies = [
730
860
  { name = "aiomysql" },
731
861
  { name = "aiosqlite" },
732
862
  { name = "anthropic" },
733
863
  { name = "asyncpg" },
864
+ { name = "fastmcp" },
734
865
  { name = "httpx" },
735
866
  { name = "keyring" },
736
867
  { name = "pandas" },
@@ -753,6 +884,7 @@ requires-dist = [
753
884
  { name = "aiosqlite", specifier = ">=0.21.0" },
754
885
  { name = "anthropic", specifier = ">=0.54.0" },
755
886
  { name = "asyncpg", specifier = ">=0.30.0" },
887
+ { name = "fastmcp", specifier = ">=2.9.0" },
756
888
  { name = "httpx", specifier = ">=0.28.1" },
757
889
  { name = "keyring", specifier = ">=25.6.0" },
758
890
  { name = "pandas", specifier = ">=2.0.0" },
@@ -769,6 +901,31 @@ dev = [
769
901
  { name = "ruff", specifier = ">=0.12.0" },
770
902
  ]
771
903
 
904
+ [[package]]
905
+ name = "sse-starlette"
906
+ version = "2.3.6"
907
+ source = { registry = "https://pypi.org/simple" }
908
+ dependencies = [
909
+ { name = "anyio" },
910
+ ]
911
+ sdist = { url = "https://files.pythonhosted.org/packages/8c/f4/989bc70cb8091eda43a9034ef969b25145291f3601703b82766e5172dfed/sse_starlette-2.3.6.tar.gz", hash = "sha256:0382336f7d4ec30160cf9ca0518962905e1b69b72d6c1c995131e0a703b436e3", size = 18284 }
912
+ wheels = [
913
+ { url = "https://files.pythonhosted.org/packages/81/05/78850ac6e79af5b9508f8841b0f26aa9fd329a1ba00bf65453c2d312bcc8/sse_starlette-2.3.6-py3-none-any.whl", hash = "sha256:d49a8285b182f6e2228e2609c350398b2ca2c36216c2675d875f81e93548f760", size = 10606 },
914
+ ]
915
+
916
+ [[package]]
917
+ name = "starlette"
918
+ version = "0.47.1"
919
+ source = { registry = "https://pypi.org/simple" }
920
+ dependencies = [
921
+ { name = "anyio" },
922
+ { name = "typing-extensions", marker = "python_full_version < '3.13'" },
923
+ ]
924
+ sdist = { url = "https://files.pythonhosted.org/packages/0a/69/662169fdb92fb96ec3eaee218cf540a629d629c86d7993d9651226a6789b/starlette-0.47.1.tar.gz", hash = "sha256:aef012dd2b6be325ffa16698f9dc533614fb1cebd593a906b90dc1025529a79b", size = 2583072 }
925
+ wheels = [
926
+ { url = "https://files.pythonhosted.org/packages/82/95/38ef0cd7fa11eaba6a99b3c4f5ac948d8bc6ff199aabd327a29cc000840c/starlette-0.47.1-py3-none-any.whl", hash = "sha256:5e11c9f5c7c3f24959edbf2dffdc01bba860228acf657129467d8a7468591527", size = 72747 },
927
+ ]
928
+
772
929
  [[package]]
773
930
  name = "typer"
774
931
  version = "0.16.0"
@@ -814,6 +971,19 @@ wheels = [
814
971
  { url = "https://files.pythonhosted.org/packages/5c/23/c7abc0ca0a1526a0774eca151daeb8de62ec457e77262b66b359c3c7679e/tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", size = 347839 },
815
972
  ]
816
973
 
974
+ [[package]]
975
+ name = "uvicorn"
976
+ version = "0.34.3"
977
+ source = { registry = "https://pypi.org/simple" }
978
+ dependencies = [
979
+ { name = "click" },
980
+ { name = "h11" },
981
+ ]
982
+ sdist = { url = "https://files.pythonhosted.org/packages/de/ad/713be230bcda622eaa35c28f0d328c3675c371238470abdea52417f17a8e/uvicorn-0.34.3.tar.gz", hash = "sha256:35919a9a979d7a59334b6b10e05d77c1d0d574c50e0fc98b8b1a0f165708b55a", size = 76631 }
983
+ wheels = [
984
+ { url = "https://files.pythonhosted.org/packages/6d/0d/8adfeaa62945f90d19ddc461c55f4a50c258af7662d34b6a3d5d1f8646f6/uvicorn-0.34.3-py3-none-any.whl", hash = "sha256:16246631db62bdfbf069b0645177d6e8a77ba950cfedbfd093acef9444e4d885", size = 62431 },
985
+ ]
986
+
817
987
  [[package]]
818
988
  name = "wcwidth"
819
989
  version = "0.2.13"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes