├── .python-version ├── docs └── assets │ ├── images │ ├── query1.jpg │ ├── query2.jpg │ └── query3.jpg │ └── videos │ ├── notion-mcp.gif │ └── notion-mcp.mp4 ├── .env.example ├── pyproject.toml ├── .gitignore ├── Dockerfile ├── LICENSE ├── smithery.yaml ├── README.md ├── src └── server.py └── uv.lock /.python-version: -------------------------------------------------------------------------------- 1 | 3.11 2 | -------------------------------------------------------------------------------- /docs/assets/images/query1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badhansen/notion-mcp/HEAD/docs/assets/images/query1.jpg -------------------------------------------------------------------------------- /docs/assets/images/query2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badhansen/notion-mcp/HEAD/docs/assets/images/query2.jpg -------------------------------------------------------------------------------- /docs/assets/images/query3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badhansen/notion-mcp/HEAD/docs/assets/images/query3.jpg -------------------------------------------------------------------------------- /docs/assets/videos/notion-mcp.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badhansen/notion-mcp/HEAD/docs/assets/videos/notion-mcp.gif -------------------------------------------------------------------------------- /docs/assets/videos/notion-mcp.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Badhansen/notion-mcp/HEAD/docs/assets/videos/notion-mcp.mp4 -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | # Development settings 2 | NOTION_TOKEN= 3 | DATABSE_ID= 4 | PAGE_ID= 5 | NOTION_VERSION = "2022-06-28" 6 | NOTION_BASE_URL = "https://api.notion.com/v1" -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "notion-mcp" 3 | version = "1.0.0" 4 | description = "A simple Model Context Protocol (MCP) server that integrates with Notion's API to manage my personal todo list." 5 | readme = "README.md" 6 | requires-python = ">=3.11" 7 | dependencies = [ 8 | "httpx>=0.28.1", 9 | "mcp[cli]>=1.2.1", 10 | "python-dotenv>=1.0.1", 11 | ] 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Insta snapshots. 2 | *.pending-snap 3 | 4 | # Generated by Cargo 5 | # will have compiled files and executables 6 | debug/ 7 | target/ 8 | target-alpine/ 9 | 10 | # Bootstrapped Python versions 11 | /bin/ 12 | 13 | # These are backup files generated by rustfmt 14 | **/*.rs.bk 15 | 16 | # MSVC Windows builds of rustc generate these, which store debugging information 17 | *.pdb 18 | 19 | # Python tmp files 20 | __pycache__ 21 | 22 | # Maturin builds, and other native editable builds 23 | *.so 24 | *.pyd 25 | *.dll 26 | 27 | # Profiling 28 | flamegraph.svg 29 | perf.data 30 | perf.data.old 31 | profile.json 32 | 33 | # MkDocs 34 | /site 35 | 36 | # macOS 37 | **/.DS_Store 38 | 39 | # IDE 40 | .idea 41 | .vscode 42 | .env 43 | .venv 44 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile 2 | FROM python:3.11-alpine 3 | 4 | # Set environment variables for Python 5 | ENV PYTHONDONTWRITEBYTECODE=1 6 | ENV PYTHONUNBUFFERED=1 7 | 8 | # Set working directory 9 | WORKDIR /app 10 | 11 | # Install system dependencies 12 | RUN apk add --no-cache gcc musl-dev libffi-dev 13 | 14 | # Copy dependency files 15 | COPY pyproject.toml ./ 16 | COPY uv.lock ./ 17 | COPY .env.example ./ 18 | 19 | # Install pip dependencies 20 | RUN pip install --upgrade pip \ 21 | && pip install --no-cache-dir -e . 22 | 23 | # Copy rest of the project files 24 | COPY . . 25 | 26 | # If .env file doesn't exist, copy .env.example to .env 27 | RUN if [ ! -f .env ]; then cp .env.example .env; fi 28 | 29 | # Default command to run the MCP server 30 | CMD ["python", "src/server.py"] 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Badhan Sen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /smithery.yaml: -------------------------------------------------------------------------------- 1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml 2 | 3 | startCommand: 4 | type: stdio 5 | configSchema: 6 | # JSON Schema defining the configuration options for the MCP. 7 | type: object 8 | required: 9 | - notionToken 10 | - pageId 11 | properties: 12 | notionToken: 13 | type: string 14 | description: API token for the Notion integration 15 | pageId: 16 | type: string 17 | description: The Notion page ID for the todo list 18 | notionVersion: 19 | type: string 20 | default: 2022-06-28 21 | description: Notion API version to use 22 | notionBaseUrl: 23 | type: string 24 | default: https://api.notion.com/v1 25 | description: Base URL for the Notion API 26 | commandFunction: 27 | # A JS function that produces the CLI command based on the given config to start the MCP on stdio. 28 | |- 29 | (config) => ({ 30 | command: 'python', 31 | args: ['src/server.py'], 32 | env: { 33 | NOTION_TOKEN: config.notionToken, 34 | PAGE_ID: config.pageId, 35 | NOTION_VERSION: config.notionVersion || '2022-06-28', 36 | NOTION_BASE_URL: config.notionBaseUrl || 'https://api.notion.com/v1' 37 | } 38 | }) 39 | exampleConfig: 40 | notionToken: secret_exampleToken123 41 | pageId: example-page-id-456 42 | notionVersion: 2022-06-28 43 | notionBaseUrl: https://api.notion.com/v1 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # notion-mcp 2 | 3 | [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Badhansen/notion-mcp) 4 | 5 | [![Trust Score](https://archestra.ai/mcp-catalog/api/badge/quality/Badhansen/notion-mcp)](https://archestra.ai/mcp-catalog/badhansen__notion-mcp) 6 | [![smithery badge](https://smithery.ai/badge/@Badhansen/notion-mcp)](https://smithery.ai/server/@Badhansen/notion-mcp) 7 | 8 | A simple Model Context Protocol (MCP) server that integrates with Notion's API to manage my personal todo list. 9 | 10 | ## Demo 11 | 12 | ![Demo](docs/assets/videos/notion-mcp.gif) 13 | 14 | ## Visual Guide 15 | 16 | #### Notion MCP Query 1 17 | 18 | ![Notion MCP Query 1](docs/assets/images/query1.jpg) 19 | 20 | #### Notion MCP Query 2 21 | 22 | ![Notion MCP Query 1](docs/assets/images/query2.jpg) 23 | 24 | #### Notion MCP Query 3 25 | 26 | ![Notion MCP Query 1](docs/assets/images/query3.jpg) 27 | 28 | ## Prerequisites 29 | 30 | - Python 3.11 or higher 31 | - A Notion account with API access 32 | - A Notion integration token 33 | - A Notion page where you want to manage your todo list 34 | - Claude Desktop clint 35 | 36 | ## Setup 37 | 38 | ### Installing via Smithery 39 | 40 | To install Notion MCP for Claude Desktop automatically via [Smithery](https://smithery.ai/server/@Badhansen/notion-mcp): 41 | 42 | ```bash 43 | npx -y @smithery/cli install @Badhansen/notion-mcp --client claude 44 | ``` 45 | 46 | 1. Clone the repository: 47 | 48 | ```sh 49 | git clone https://github.com/Badhansen/notion-mcp.git 50 | cd notion-mcp 51 | ``` 52 | 53 | 2. Set up Python environment: 54 | 55 | ```sh 56 | uv venv 57 | source .venv/bin/activate 58 | uv pip install -e . 59 | ``` 60 | 61 | 3. Create a Notion integration: 62 | - Go to https://www.notion.so/my-integrations 63 | - Create new integration 64 | - Copy the API key 65 | 4. Share your database/page with the integration: 66 | - Open your notion workspace with a database/table present or a page. 67 | - Click "..." menu → "Add connections" 68 | - Select your integration (Search by name) 69 | 70 | ## Configuration 71 | 72 | 1. Create `.env` file: 73 | 74 | ```sh 75 | cp .env.example .env 76 | ``` 77 | 78 | 2. Configure Notion credentials in `.env`: 79 | 80 | ```markdown 81 | NOTION_TOKEN= 82 | PAGE_ID= 83 | NOTION_VERSION="2022-06-28" 84 | NOTION_BASE_URL="https://api.notion.com/v1" 85 | ``` 86 | 87 | 3. To use it with Claude Desktop as intended you need to adjust your `claude_desktop_config.json` file. 88 | Go to `Claude Desktop -> Settings -> Developer -> Edit Config`. Now add the `Notion` server configuration. 89 | 90 | ```json 91 | { 92 | "mcpServers": { 93 | "notion-mcp": { 94 | "command": "uv", 95 | "args": [ 96 | "--directory", 97 | "/Users/username/Projects/Python/notion-mcp/src" /* Path to your project */, 98 | "run", 99 | "server.py" 100 | ] 101 | } 102 | } 103 | } 104 | ``` 105 | 106 | ## Development 107 | 108 | Project structure: 109 | 110 | ```markdown 111 | notion-mcp/ 112 | ├── docs/ 113 | ├── src/ 114 | │ └── server.py 115 | ├── .env 116 | ├── .python-version 117 | ├── README.md 118 | ├── pyproject.toml 119 | └── uv.lock 120 | ``` 121 | 122 | ## Support Functions 123 | 124 | #### Show Tasks 125 | 126 | To show all tasks from your Notion workspace, use the `show_all_todos` function: 127 | 128 | ```json 129 | { 130 | "name": "show_all_todos", 131 | "arguments": {} 132 | } 133 | ``` 134 | 135 | #### Add Task 136 | 137 | To add a new task to your Notion workspace, use the `add_todo` function: 138 | 139 | ```json 140 | { 141 | "name": "add_todo", 142 | "arguments": { 143 | "task": "Your task description" 144 | } 145 | } 146 | ``` 147 | 148 | #### Update Task 149 | 150 | To update an existing task in your Notion workspace, use the `complete_todo` function: 151 | 152 | ```json 153 | { 154 | "name": "complete_todo", 155 | "arguments": { 156 | "task_id": "your-task-id" 157 | } 158 | } 159 | ``` 160 | 161 | ## Contributing 162 | 163 | 1. Fork the repository 164 | 2. Create feature branch 165 | 3. Submit pull request 166 | 167 | ## License 168 | 169 | MIT License. See LICENSE file for details. 170 | -------------------------------------------------------------------------------- /src/server.py: -------------------------------------------------------------------------------- 1 | from mcp.types import Tool, TextContent, EmbeddedResource 2 | from mcp.server import Server 3 | from typing import Any, Sequence 4 | from dotenv import load_dotenv 5 | from pathlib import Path 6 | import logging 7 | import httpx 8 | import os 9 | 10 | # Find and load .env file from project root 11 | project_root = Path(__file__).resolve().parent.parent 12 | env_path = project_root / '.env' 13 | 14 | if not env_path.exists(): 15 | raise FileNotFoundError(f"No .env file found at {env_path}") 16 | 17 | load_dotenv(env_path) 18 | 19 | # Setup logging configuration 20 | logging.basicConfig(level=logging.INFO) 21 | 22 | 23 | NOTION_TOKEN = os.getenv("NOTION_TOKEN") 24 | DATABSE_ID = os.getenv("DATABSE_ID") 25 | PAGE_ID = os.getenv("PAGE_ID") 26 | 27 | NOTION_VERSION = os.getenv("NOTION_VERSION") 28 | NOTION_BASE_URL = os.getenv("NOTION_BASE_URL") 29 | 30 | 31 | # Notion API headers 32 | headers = { 33 | "Authorization": f"Bearer {NOTION_TOKEN}", 34 | "Content-Type": "application/json", 35 | "Notion-Version": NOTION_VERSION 36 | } 37 | 38 | 39 | # Create a named server 40 | server = Server("notion-mcp") 41 | 42 | async def fetch_todos_on_page(page_id: str) -> list: 43 | """ 44 | Fetch all to-do items from a Notion page. 45 | :param page_id: The ID of the Notion page (UUID format). 46 | :return: A list of to-do items with text and their completion status. 47 | """ 48 | async with httpx.AsyncClient() as client: 49 | todos = [] 50 | has_more = True 51 | next_cursor = None 52 | 53 | while has_more: 54 | # Fetch child blocks from the page 55 | response = await client.get( 56 | f"{NOTION_BASE_URL}/blocks/{page_id}/children", 57 | headers=headers, 58 | params={"start_cursor": next_cursor} if next_cursor else None, 59 | ) 60 | response.raise_for_status() 61 | data = response.json() 62 | 63 | # Extract to-do items 64 | for block in data.get("results", []): 65 | if block["type"] == "to_do": 66 | todo_text = "".join( 67 | [text["plain_text"] for text in block["to_do"]["rich_text"]] 68 | ) 69 | is_checked = block["to_do"]["checked"] 70 | todos.append({"text": todo_text, "checked": is_checked, "task_id": block["id"]}) 71 | 72 | # Handle pagination 73 | has_more = data.get("has_more", False) 74 | next_cursor = data.get("next_cursor") 75 | 76 | return todos 77 | 78 | async def create_todo_on_page(task: str) -> dict: 79 | """ 80 | Add a to-do item to an existing Notion page (using the PAGE_ID from .env). 81 | Args: 82 | task (str): The text of the to-do item. 83 | Returns: 84 | dict: The response from the Notion API. 85 | Raises: 86 | ValueError: If PAGE_ID is not set in the .env file. 87 | httpx.HTTPStatusError: If the request to the Notion API fails. 88 | """ 89 | if not PAGE_ID: 90 | raise ValueError("PAGE_ID is not set in the .env file.") 91 | 92 | async with httpx.AsyncClient() as client: 93 | response = await client.patch( 94 | f"{NOTION_BASE_URL}/blocks/{PAGE_ID}/children", 95 | headers=headers, 96 | json={ 97 | "children": [ 98 | { 99 | "object": "block", 100 | "type": "to_do", 101 | "to_do": { 102 | "rich_text": [ 103 | {"type": "text", "text": {"content": task}} 104 | ], 105 | "checked": False 106 | } 107 | } 108 | ] 109 | } 110 | ) 111 | response.raise_for_status() 112 | return response.json() 113 | 114 | async def complete_todo_on_page(task_id: str) -> None: 115 | """ 116 | Mark a to-do item as complete in a Notion Page. 117 | Args: 118 | task_id (str): The task_id of the to-do item to be marked as complete. 119 | Raises: 120 | ValueError: If there is an error completing the to-do item. 121 | Returns: 122 | None 123 | """ 124 | todos = await fetch_todos_on_page(PAGE_ID) 125 | 126 | if not any(todo.get("task_id") == task_id for todo in todos): 127 | raise ValueError(f"No to-do item found with title: {task_id}") 128 | 129 | # The payload to update the block (to change the 'checked' status) 130 | payload = { 131 | "to_do": { 132 | "checked": True 133 | } 134 | } 135 | 136 | try: 137 | async with httpx.AsyncClient() as client: 138 | response = await client.patch( 139 | f"{NOTION_BASE_URL}/blocks/{task_id}", 140 | headers=headers, 141 | json=payload 142 | ) 143 | response.raise_for_status() 144 | return response.json() 145 | except httpx.HTTPError as e: 146 | logging.info("No to-do found in the page.") 147 | raise ValueError(f"Error completing todo: {str(e)}") 148 | 149 | async def handle_add_todo(arguments: dict) -> Sequence[TextContent | EmbeddedResource]: 150 | """ 151 | Handle adding a new to-do. 152 | Args: 153 | arguments (dict): A dictionary containing the task details. 154 | Returns: 155 | Sequence[TextContent | EmbeddedResource]: A sequence containing the result of the operation, either a success message or an error message. 156 | Raises: 157 | ValueError: If the arguments are not a dictionary or if the task is not provided. 158 | """ 159 | if not isinstance(arguments, dict): 160 | raise ValueError("Invalid arguments") 161 | 162 | task = arguments.get("task") 163 | 164 | if not task: 165 | raise ValueError("Task is required") 166 | 167 | try: 168 | result = await create_todo_on_page(task) 169 | return [ 170 | TextContent( 171 | type="text", 172 | text=f"Added todo: {task} in the Task Integration Page" 173 | ) 174 | ] 175 | except httpx.HTTPError as e: 176 | logging.error(f"Notion API error: {str(e)}") 177 | return [ 178 | TextContent( 179 | type="text", 180 | text=f"Error adding todo: {str(e)}\nPlease make sure your Notion integration is properly set up and has access to the database." 181 | ) 182 | ] 183 | 184 | async def handle_show_all_todos() -> Sequence[TextContent | EmbeddedResource]: 185 | """ 186 | Handle showing all to-do items. 187 | 188 | Fetches all to-do items from a specific page and returns them as a list of 189 | TextContent objects. If no to-do items are found, returns a message indicating 190 | that no items were found. 191 | 192 | Returns: 193 | Sequence[TextContent | EmbeddedResource]: A list containing a TextContent 194 | object with the to-do items or a message indicating no items were found. 195 | """ 196 | todos = await fetch_todos_on_page(PAGE_ID) 197 | if todos: 198 | todo_list = "\n".join([ 199 | f"- {todo['task_id']}: {todo['text']} (Completed: {'Yes' if todo['checked'] else 'No'})" 200 | for todo in todos 201 | ]) 202 | return [ 203 | TextContent( 204 | type="text", 205 | text=f"Here are the todo items in the Task Integration Page:\n{todo_list}" 206 | ) 207 | ] 208 | else: 209 | return [ 210 | TextContent( 211 | type="text", 212 | text="No todo items found in the Task Integration Page." 213 | ) 214 | ] 215 | 216 | async def handle_complete_todo(arguments: dict) -> Sequence[TextContent | EmbeddedResource]: 217 | """ 218 | Handle completing a to-do item. 219 | 220 | Args: 221 | arguments (dict): A dictionary containing the task ID. 222 | 223 | Returns: 224 | Sequence[TextContent | EmbeddedResource]: A sequence containing the result of the operation, either a success message or an error message. 225 | 226 | Raises: 227 | ValueError: If the arguments are not a dictionary or if the task ID is not provided. 228 | httpx.HTTPStatusError: If the request to the Notion API fails. 229 | """ 230 | if not isinstance(arguments, dict): 231 | raise ValueError("Invalid arguments") 232 | 233 | task_id = arguments.get("task_id") 234 | 235 | if not task_id: 236 | raise ValueError("Task_ID is required") 237 | 238 | try: 239 | await complete_todo_on_page(task_id) 240 | return [ 241 | TextContent( 242 | type="text", 243 | text=f"Marked todo as complete (Task_ID: {task_id})" 244 | ) 245 | ] 246 | except httpx.HTTPError as e: 247 | logging.error(f"Notion API error: {str(e)}") 248 | return [ 249 | TextContent( 250 | type="text", 251 | text=f"Error completing todo: {str(e)}\nPlease make sure your Notion integration is properly set up and has access to the database." 252 | ) 253 | ] 254 | 255 | @server.list_tools() 256 | async def list_tools() -> list[Tool]: 257 | """ 258 | List all available tools. 259 | 260 | Returns: 261 | list[Tool]: A list of available tools. 262 | """ 263 | return [ 264 | Tool( 265 | name="add_todo", 266 | description="Add a new todo item", 267 | inputSchema={ 268 | "type": "object", 269 | "properties": { 270 | "task": { 271 | "type": "string", 272 | "description": "The todo task description", 273 | }, 274 | 275 | }, 276 | "required": ["task"] 277 | } 278 | ), 279 | Tool( 280 | name="show_all_todos", 281 | description="Show all todo items from Notion.", 282 | inputSchema={ 283 | "type": "object", 284 | "properties": {}, 285 | "required": [] 286 | } 287 | ), 288 | Tool( 289 | name="complete_todo", 290 | description="Mark a todo item as completed.", 291 | inputSchema={ 292 | "type": "object", 293 | "properties": { 294 | "task_id": { 295 | "type": "string", 296 | "description": "The task_id of the todo task to mark as complete." 297 | } 298 | }, 299 | "required": ["task_id"] 300 | } 301 | ), 302 | ] 303 | 304 | @server.call_tool() 305 | async def call_tool(name: str, arguments: Any) -> Sequence[TextContent | EmbeddedResource]: 306 | """ 307 | Handle tool calls for todo management. 308 | 309 | Args: 310 | name (str): The name of the tool to call. 311 | arguments (Any): The arguments to pass to the tool. 312 | 313 | Returns: 314 | Sequence[TextContent | EmbeddedResource]: The result of the tool call, either a success message or an error message. 315 | """ 316 | 317 | if name == "add_todo": 318 | return await handle_add_todo(arguments) 319 | 320 | elif name == "show_all_todos" or name == "show_todos": 321 | return await handle_show_all_todos() 322 | 323 | elif name == "complete_todo": 324 | return await handle_complete_todo(arguments) 325 | 326 | raise ValueError(f"Unknown tool: {name}") 327 | 328 | async def main(): 329 | """Main entry point for the server""" 330 | from mcp.server.stdio import stdio_server 331 | 332 | if not NOTION_TOKEN or not PAGE_ID: 333 | raise ValueError("NOTION_TOKEN and PAGE_ID environment variables are required") 334 | 335 | async with stdio_server() as (read_stream, write_stream): 336 | await server.run( 337 | read_stream, 338 | write_stream, 339 | server.create_initialization_options() 340 | ) 341 | 342 | if __name__ == "__main__": 343 | import asyncio 344 | asyncio.run(main()) -------------------------------------------------------------------------------- /uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | requires-python = ">=3.11" 3 | 4 | [[package]] 5 | name = "annotated-types" 6 | version = "0.7.0" 7 | source = { registry = "https://pypi.org/simple" } 8 | sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 } 9 | wheels = [ 10 | { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 }, 11 | ] 12 | 13 | [[package]] 14 | name = "anyio" 15 | version = "4.8.0" 16 | source = { registry = "https://pypi.org/simple" } 17 | dependencies = [ 18 | { name = "idna" }, 19 | { name = "sniffio" }, 20 | { name = "typing-extensions", marker = "python_full_version < '3.13'" }, 21 | ] 22 | sdist = { url = "https://files.pythonhosted.org/packages/a3/73/199a98fc2dae33535d6b8e8e6ec01f8c1d76c9adb096c6b7d64823038cde/anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a", size = 181126 } 23 | wheels = [ 24 | { url = "https://files.pythonhosted.org/packages/46/eb/e7f063ad1fec6b3178a3cd82d1a3c4de82cccf283fc42746168188e1cdd5/anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a", size = 96041 }, 25 | ] 26 | 27 | [[package]] 28 | name = "certifi" 29 | version = "2025.1.31" 30 | source = { registry = "https://pypi.org/simple" } 31 | sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 } 32 | wheels = [ 33 | { url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 }, 34 | ] 35 | 36 | [[package]] 37 | name = "click" 38 | version = "8.1.8" 39 | source = { registry = "https://pypi.org/simple" } 40 | dependencies = [ 41 | { name = "colorama", marker = "sys_platform == 'win32'" }, 42 | ] 43 | sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } 44 | wheels = [ 45 | { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 }, 46 | ] 47 | 48 | [[package]] 49 | name = "colorama" 50 | version = "0.4.6" 51 | source = { registry = "https://pypi.org/simple" } 52 | sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 } 53 | wheels = [ 54 | { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 }, 55 | ] 56 | 57 | [[package]] 58 | name = "h11" 59 | version = "0.14.0" 60 | source = { registry = "https://pypi.org/simple" } 61 | sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 } 62 | wheels = [ 63 | { url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 }, 64 | ] 65 | 66 | [[package]] 67 | name = "httpcore" 68 | version = "1.0.7" 69 | source = { registry = "https://pypi.org/simple" } 70 | dependencies = [ 71 | { name = "certifi" }, 72 | { name = "h11" }, 73 | ] 74 | sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 } 75 | wheels = [ 76 | { url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 }, 77 | ] 78 | 79 | [[package]] 80 | name = "httpx" 81 | version = "0.28.1" 82 | source = { registry = "https://pypi.org/simple" } 83 | dependencies = [ 84 | { name = "anyio" }, 85 | { name = "certifi" }, 86 | { name = "httpcore" }, 87 | { name = "idna" }, 88 | ] 89 | sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 } 90 | wheels = [ 91 | { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 }, 92 | ] 93 | 94 | [[package]] 95 | name = "httpx-sse" 96 | version = "0.4.0" 97 | source = { registry = "https://pypi.org/simple" } 98 | sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624 } 99 | wheels = [ 100 | { url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819 }, 101 | ] 102 | 103 | [[package]] 104 | name = "idna" 105 | version = "3.10" 106 | source = { registry = "https://pypi.org/simple" } 107 | sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 } 108 | wheels = [ 109 | { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 }, 110 | ] 111 | 112 | [[package]] 113 | name = "markdown-it-py" 114 | version = "3.0.0" 115 | source = { registry = "https://pypi.org/simple" } 116 | dependencies = [ 117 | { name = "mdurl" }, 118 | ] 119 | sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 } 120 | wheels = [ 121 | { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 }, 122 | ] 123 | 124 | [[package]] 125 | name = "mcp" 126 | version = "1.2.1" 127 | source = { registry = "https://pypi.org/simple" } 128 | dependencies = [ 129 | { name = "anyio" }, 130 | { name = "httpx" }, 131 | { name = "httpx-sse" }, 132 | { name = "pydantic" }, 133 | { name = "pydantic-settings" }, 134 | { name = "sse-starlette" }, 135 | { name = "starlette" }, 136 | { name = "uvicorn" }, 137 | ] 138 | sdist = { url = "https://files.pythonhosted.org/packages/fc/30/51e4555826126e3954fa2ab1e934bf74163c5fe05e98f38ca4d0f8abbf63/mcp-1.2.1.tar.gz", hash = "sha256:c9d43dbfe943aa1530e2be8f54b73af3ebfb071243827b4483d421684806cb45", size = 103968 } 139 | wheels = [ 140 | { url = "https://files.pythonhosted.org/packages/4c/0d/6770742a84c8aa1d36c0d628896a380584c5759612e66af7446af07d8775/mcp-1.2.1-py3-none-any.whl", hash = "sha256:579bf9c9157850ebb1344f3ca6f7a3021b0123c44c9f089ef577a7062522f0fd", size = 66453 }, 141 | ] 142 | 143 | [package.optional-dependencies] 144 | cli = [ 145 | { name = "python-dotenv" }, 146 | { name = "typer" }, 147 | ] 148 | 149 | [[package]] 150 | name = "mdurl" 151 | version = "0.1.2" 152 | source = { registry = "https://pypi.org/simple" } 153 | sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 } 154 | wheels = [ 155 | { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 }, 156 | ] 157 | 158 | [[package]] 159 | name = "notion-mcp" 160 | version = "1.0.0" 161 | source = { virtual = "." } 162 | dependencies = [ 163 | { name = "httpx" }, 164 | { name = "mcp", extra = ["cli"] }, 165 | { name = "python-dotenv" }, 166 | ] 167 | 168 | [package.metadata] 169 | requires-dist = [ 170 | { name = "httpx", specifier = ">=0.28.1" }, 171 | { name = "mcp", extras = ["cli"], specifier = ">=1.2.1" }, 172 | { name = "python-dotenv", specifier = ">=1.0.1" }, 173 | ] 174 | 175 | [[package]] 176 | name = "pydantic" 177 | version = "2.10.6" 178 | source = { registry = "https://pypi.org/simple" } 179 | dependencies = [ 180 | { name = "annotated-types" }, 181 | { name = "pydantic-core" }, 182 | { name = "typing-extensions" }, 183 | ] 184 | sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681 } 185 | wheels = [ 186 | { url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696 }, 187 | ] 188 | 189 | [[package]] 190 | name = "pydantic-core" 191 | version = "2.27.2" 192 | source = { registry = "https://pypi.org/simple" } 193 | dependencies = [ 194 | { name = "typing-extensions" }, 195 | ] 196 | sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 } 197 | wheels = [ 198 | { url = "https://files.pythonhosted.org/packages/c2/89/f3450af9d09d44eea1f2c369f49e8f181d742f28220f88cc4dfaae91ea6e/pydantic_core-2.27.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc", size = 1893421 }, 199 | { url = "https://files.pythonhosted.org/packages/9e/e3/71fe85af2021f3f386da42d291412e5baf6ce7716bd7101ea49c810eda90/pydantic_core-2.27.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7", size = 1814998 }, 200 | { url = "https://files.pythonhosted.org/packages/a6/3c/724039e0d848fd69dbf5806894e26479577316c6f0f112bacaf67aa889ac/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15", size = 1826167 }, 201 | { url = "https://files.pythonhosted.org/packages/2b/5b/1b29e8c1fb5f3199a9a57c1452004ff39f494bbe9bdbe9a81e18172e40d3/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306", size = 1865071 }, 202 | { url = "https://files.pythonhosted.org/packages/89/6c/3985203863d76bb7d7266e36970d7e3b6385148c18a68cc8915fd8c84d57/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99", size = 2036244 }, 203 | { url = "https://files.pythonhosted.org/packages/0e/41/f15316858a246b5d723f7d7f599f79e37493b2e84bfc789e58d88c209f8a/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459", size = 2737470 }, 204 | { url = "https://files.pythonhosted.org/packages/a8/7c/b860618c25678bbd6d1d99dbdfdf0510ccb50790099b963ff78a124b754f/pydantic_core-2.27.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048", size = 1992291 }, 205 | { url = "https://files.pythonhosted.org/packages/bf/73/42c3742a391eccbeab39f15213ecda3104ae8682ba3c0c28069fbcb8c10d/pydantic_core-2.27.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d", size = 1994613 }, 206 | { url = "https://files.pythonhosted.org/packages/94/7a/941e89096d1175d56f59340f3a8ebaf20762fef222c298ea96d36a6328c5/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b", size = 2002355 }, 207 | { url = "https://files.pythonhosted.org/packages/6e/95/2359937a73d49e336a5a19848713555605d4d8d6940c3ec6c6c0ca4dcf25/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474", size = 2126661 }, 208 | { url = "https://files.pythonhosted.org/packages/2b/4c/ca02b7bdb6012a1adef21a50625b14f43ed4d11f1fc237f9d7490aa5078c/pydantic_core-2.27.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6", size = 2153261 }, 209 | { url = "https://files.pythonhosted.org/packages/72/9d/a241db83f973049a1092a079272ffe2e3e82e98561ef6214ab53fe53b1c7/pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", size = 1812361 }, 210 | { url = "https://files.pythonhosted.org/packages/e8/ef/013f07248041b74abd48a385e2110aa3a9bbfef0fbd97d4e6d07d2f5b89a/pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", size = 1982484 }, 211 | { url = "https://files.pythonhosted.org/packages/10/1c/16b3a3e3398fd29dca77cea0a1d998d6bde3902fa2706985191e2313cc76/pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", size = 1867102 }, 212 | { url = "https://files.pythonhosted.org/packages/d6/74/51c8a5482ca447871c93e142d9d4a92ead74de6c8dc5e66733e22c9bba89/pydantic_core-2.27.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0", size = 1893127 }, 213 | { url = "https://files.pythonhosted.org/packages/d3/f3/c97e80721735868313c58b89d2de85fa80fe8dfeeed84dc51598b92a135e/pydantic_core-2.27.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef", size = 1811340 }, 214 | { url = "https://files.pythonhosted.org/packages/9e/91/840ec1375e686dbae1bd80a9e46c26a1e0083e1186abc610efa3d9a36180/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7", size = 1822900 }, 215 | { url = "https://files.pythonhosted.org/packages/f6/31/4240bc96025035500c18adc149aa6ffdf1a0062a4b525c932065ceb4d868/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934", size = 1869177 }, 216 | { url = "https://files.pythonhosted.org/packages/fa/20/02fbaadb7808be578317015c462655c317a77a7c8f0ef274bc016a784c54/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6", size = 2038046 }, 217 | { url = "https://files.pythonhosted.org/packages/06/86/7f306b904e6c9eccf0668248b3f272090e49c275bc488a7b88b0823444a4/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c", size = 2685386 }, 218 | { url = "https://files.pythonhosted.org/packages/8d/f0/49129b27c43396581a635d8710dae54a791b17dfc50c70164866bbf865e3/pydantic_core-2.27.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2", size = 1997060 }, 219 | { url = "https://files.pythonhosted.org/packages/0d/0f/943b4af7cd416c477fd40b187036c4f89b416a33d3cc0ab7b82708a667aa/pydantic_core-2.27.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4", size = 2004870 }, 220 | { url = "https://files.pythonhosted.org/packages/35/40/aea70b5b1a63911c53a4c8117c0a828d6790483f858041f47bab0b779f44/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3", size = 1999822 }, 221 | { url = "https://files.pythonhosted.org/packages/f2/b3/807b94fd337d58effc5498fd1a7a4d9d59af4133e83e32ae39a96fddec9d/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4", size = 2130364 }, 222 | { url = "https://files.pythonhosted.org/packages/fc/df/791c827cd4ee6efd59248dca9369fb35e80a9484462c33c6649a8d02b565/pydantic_core-2.27.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57", size = 2158303 }, 223 | { url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064 }, 224 | { url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046 }, 225 | { url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092 }, 226 | { url = "https://files.pythonhosted.org/packages/41/b1/9bc383f48f8002f99104e3acff6cba1231b29ef76cfa45d1506a5cad1f84/pydantic_core-2.27.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b", size = 1892709 }, 227 | { url = "https://files.pythonhosted.org/packages/10/6c/e62b8657b834f3eb2961b49ec8e301eb99946245e70bf42c8817350cbefc/pydantic_core-2.27.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154", size = 1811273 }, 228 | { url = "https://files.pythonhosted.org/packages/ba/15/52cfe49c8c986e081b863b102d6b859d9defc63446b642ccbbb3742bf371/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9", size = 1823027 }, 229 | { url = "https://files.pythonhosted.org/packages/b1/1c/b6f402cfc18ec0024120602bdbcebc7bdd5b856528c013bd4d13865ca473/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9", size = 1868888 }, 230 | { url = "https://files.pythonhosted.org/packages/bd/7b/8cb75b66ac37bc2975a3b7de99f3c6f355fcc4d89820b61dffa8f1e81677/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1", size = 2037738 }, 231 | { url = "https://files.pythonhosted.org/packages/c8/f1/786d8fe78970a06f61df22cba58e365ce304bf9b9f46cc71c8c424e0c334/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a", size = 2685138 }, 232 | { url = "https://files.pythonhosted.org/packages/a6/74/d12b2cd841d8724dc8ffb13fc5cef86566a53ed358103150209ecd5d1999/pydantic_core-2.27.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e", size = 1997025 }, 233 | { url = "https://files.pythonhosted.org/packages/a0/6e/940bcd631bc4d9a06c9539b51f070b66e8f370ed0933f392db6ff350d873/pydantic_core-2.27.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4", size = 2004633 }, 234 | { url = "https://files.pythonhosted.org/packages/50/cc/a46b34f1708d82498c227d5d80ce615b2dd502ddcfd8376fc14a36655af1/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27", size = 1999404 }, 235 | { url = "https://files.pythonhosted.org/packages/ca/2d/c365cfa930ed23bc58c41463bae347d1005537dc8db79e998af8ba28d35e/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee", size = 2130130 }, 236 | { url = "https://files.pythonhosted.org/packages/f4/d7/eb64d015c350b7cdb371145b54d96c919d4db516817f31cd1c650cae3b21/pydantic_core-2.27.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1", size = 2157946 }, 237 | { url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 }, 238 | { url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 }, 239 | { url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 }, 240 | ] 241 | 242 | [[package]] 243 | name = "pydantic-settings" 244 | version = "2.7.1" 245 | source = { registry = "https://pypi.org/simple" } 246 | dependencies = [ 247 | { name = "pydantic" }, 248 | { name = "python-dotenv" }, 249 | ] 250 | sdist = { url = "https://files.pythonhosted.org/packages/73/7b/c58a586cd7d9ac66d2ee4ba60ca2d241fa837c02bca9bea80a9a8c3d22a9/pydantic_settings-2.7.1.tar.gz", hash = "sha256:10c9caad35e64bfb3c2fbf70a078c0e25cc92499782e5200747f942a065dec93", size = 79920 } 251 | wheels = [ 252 | { url = "https://files.pythonhosted.org/packages/b4/46/93416fdae86d40879714f72956ac14df9c7b76f7d41a4d68aa9f71a0028b/pydantic_settings-2.7.1-py3-none-any.whl", hash = "sha256:590be9e6e24d06db33a4262829edef682500ef008565a969c73d39d5f8bfb3fd", size = 29718 }, 253 | ] 254 | 255 | [[package]] 256 | name = "pygments" 257 | version = "2.19.1" 258 | source = { registry = "https://pypi.org/simple" } 259 | sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 } 260 | wheels = [ 261 | { url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 }, 262 | ] 263 | 264 | [[package]] 265 | name = "python-dotenv" 266 | version = "1.0.1" 267 | source = { registry = "https://pypi.org/simple" } 268 | sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 } 269 | wheels = [ 270 | { url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 }, 271 | ] 272 | 273 | [[package]] 274 | name = "rich" 275 | version = "13.9.4" 276 | source = { registry = "https://pypi.org/simple" } 277 | dependencies = [ 278 | { name = "markdown-it-py" }, 279 | { name = "pygments" }, 280 | ] 281 | sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 } 282 | wheels = [ 283 | { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, 284 | ] 285 | 286 | [[package]] 287 | name = "shellingham" 288 | version = "1.5.4" 289 | source = { registry = "https://pypi.org/simple" } 290 | sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 } 291 | wheels = [ 292 | { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 }, 293 | ] 294 | 295 | [[package]] 296 | name = "sniffio" 297 | version = "1.3.1" 298 | source = { registry = "https://pypi.org/simple" } 299 | sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 } 300 | wheels = [ 301 | { url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 }, 302 | ] 303 | 304 | [[package]] 305 | name = "sse-starlette" 306 | version = "2.2.1" 307 | source = { registry = "https://pypi.org/simple" } 308 | dependencies = [ 309 | { name = "anyio" }, 310 | { name = "starlette" }, 311 | ] 312 | sdist = { url = "https://files.pythonhosted.org/packages/71/a4/80d2a11af59fe75b48230846989e93979c892d3a20016b42bb44edb9e398/sse_starlette-2.2.1.tar.gz", hash = "sha256:54470d5f19274aeed6b2d473430b08b4b379ea851d953b11d7f1c4a2c118b419", size = 17376 } 313 | wheels = [ 314 | { url = "https://files.pythonhosted.org/packages/d9/e0/5b8bd393f27f4a62461c5cf2479c75a2cc2ffa330976f9f00f5f6e4f50eb/sse_starlette-2.2.1-py3-none-any.whl", hash = "sha256:6410a3d3ba0c89e7675d4c273a301d64649c03a5ef1ca101f10b47f895fd0e99", size = 10120 }, 315 | ] 316 | 317 | [[package]] 318 | name = "starlette" 319 | version = "0.45.3" 320 | source = { registry = "https://pypi.org/simple" } 321 | dependencies = [ 322 | { name = "anyio" }, 323 | ] 324 | sdist = { url = "https://files.pythonhosted.org/packages/ff/fb/2984a686808b89a6781526129a4b51266f678b2d2b97ab2d325e56116df8/starlette-0.45.3.tar.gz", hash = "sha256:2cbcba2a75806f8a41c722141486f37c28e30a0921c5f6fe4346cb0dcee1302f", size = 2574076 } 325 | wheels = [ 326 | { url = "https://files.pythonhosted.org/packages/d9/61/f2b52e107b1fc8944b33ef56bf6ac4ebbe16d91b94d2b87ce013bf63fb84/starlette-0.45.3-py3-none-any.whl", hash = "sha256:dfb6d332576f136ec740296c7e8bb8c8a7125044e7c6da30744718880cdd059d", size = 71507 }, 327 | ] 328 | 329 | [[package]] 330 | name = "typer" 331 | version = "0.15.1" 332 | source = { registry = "https://pypi.org/simple" } 333 | dependencies = [ 334 | { name = "click" }, 335 | { name = "rich" }, 336 | { name = "shellingham" }, 337 | { name = "typing-extensions" }, 338 | ] 339 | sdist = { url = "https://files.pythonhosted.org/packages/cb/ce/dca7b219718afd37a0068f4f2530a727c2b74a8b6e8e0c0080a4c0de4fcd/typer-0.15.1.tar.gz", hash = "sha256:a0588c0a7fa68a1978a069818657778f86abe6ff5ea6abf472f940a08bfe4f0a", size = 99789 } 340 | wheels = [ 341 | { url = "https://files.pythonhosted.org/packages/d0/cc/0a838ba5ca64dc832aa43f727bd586309846b0ffb2ce52422543e6075e8a/typer-0.15.1-py3-none-any.whl", hash = "sha256:7994fb7b8155b64d3402518560648446072864beefd44aa2dc36972a5972e847", size = 44908 }, 342 | ] 343 | 344 | [[package]] 345 | name = "typing-extensions" 346 | version = "4.12.2" 347 | source = { registry = "https://pypi.org/simple" } 348 | sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } 349 | wheels = [ 350 | { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, 351 | ] 352 | 353 | [[package]] 354 | name = "uvicorn" 355 | version = "0.34.0" 356 | source = { registry = "https://pypi.org/simple" } 357 | dependencies = [ 358 | { name = "click" }, 359 | { name = "h11" }, 360 | ] 361 | sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 } 362 | wheels = [ 363 | { url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 }, 364 | ] 365 | --------------------------------------------------------------------------------