duckduckgo-mcp-server 0.1.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.
- duckduckgo_mcp_server-0.1.0/.gitignore +171 -0
- duckduckgo_mcp_server-0.1.0/.python-version +1 -0
- duckduckgo_mcp_server-0.1.0/LICENSE +21 -0
- duckduckgo_mcp_server-0.1.0/PKG-INFO +144 -0
- duckduckgo_mcp_server-0.1.0/README.md +122 -0
- duckduckgo_mcp_server-0.1.0/pyproject.toml +29 -0
- duckduckgo_mcp_server-0.1.0/src/duckduckgo_mcp_server/__init__.py +1 -0
- duckduckgo_mcp_server-0.1.0/src/duckduckgo_mcp_server/server.py +249 -0
- duckduckgo_mcp_server-0.1.0/uv.lock +421 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py,cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
#Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
#uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
#poetry.lock
|
|
109
|
+
|
|
110
|
+
# pdm
|
|
111
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
112
|
+
#pdm.lock
|
|
113
|
+
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
|
114
|
+
# in version control.
|
|
115
|
+
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
|
|
116
|
+
.pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
121
|
+
__pypackages__/
|
|
122
|
+
|
|
123
|
+
# Celery stuff
|
|
124
|
+
celerybeat-schedule
|
|
125
|
+
celerybeat.pid
|
|
126
|
+
|
|
127
|
+
# SageMath parsed files
|
|
128
|
+
*.sage.py
|
|
129
|
+
|
|
130
|
+
# Environments
|
|
131
|
+
.env
|
|
132
|
+
.venv
|
|
133
|
+
env/
|
|
134
|
+
venv/
|
|
135
|
+
ENV/
|
|
136
|
+
env.bak/
|
|
137
|
+
venv.bak/
|
|
138
|
+
|
|
139
|
+
# Spyder project settings
|
|
140
|
+
.spyderproject
|
|
141
|
+
.spyproject
|
|
142
|
+
|
|
143
|
+
# Rope project settings
|
|
144
|
+
.ropeproject
|
|
145
|
+
|
|
146
|
+
# mkdocs documentation
|
|
147
|
+
/site
|
|
148
|
+
|
|
149
|
+
# mypy
|
|
150
|
+
.mypy_cache/
|
|
151
|
+
.dmypy.json
|
|
152
|
+
dmypy.json
|
|
153
|
+
|
|
154
|
+
# Pyre type checker
|
|
155
|
+
.pyre/
|
|
156
|
+
|
|
157
|
+
# pytype static type analyzer
|
|
158
|
+
.pytype/
|
|
159
|
+
|
|
160
|
+
# Cython debug symbols
|
|
161
|
+
cython_debug/
|
|
162
|
+
|
|
163
|
+
# PyCharm
|
|
164
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
165
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
166
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
167
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
168
|
+
#.idea/
|
|
169
|
+
|
|
170
|
+
# PyPI configuration file
|
|
171
|
+
.pypirc
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13.2
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Nick Clyde
|
|
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.
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: duckduckgo-mcp-server
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP Server for searching via DuckDuckGo
|
|
5
|
+
Project-URL: Homepage, https://github.com/nickclyde/duckduckgo-mcp-server
|
|
6
|
+
Project-URL: Issues, https://github.com/nickclyde/duckduckgo-mcp-server/issues
|
|
7
|
+
Author-email: Nick Clyde <nick@clyde.tech>
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Requires-Python: >=3.10
|
|
18
|
+
Requires-Dist: beautifulsoup4>=4.13.3
|
|
19
|
+
Requires-Dist: httpx>=0.28.1
|
|
20
|
+
Requires-Dist: mcp[cli]>=1.3.0
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# DuckDuckGo Search MCP Server
|
|
24
|
+
|
|
25
|
+
A Model Context Protocol (MCP) server that provides web search capabilities through DuckDuckGo, with additional features for content fetching and parsing.
|
|
26
|
+
|
|
27
|
+
## Features
|
|
28
|
+
|
|
29
|
+
- **Web Search**: Search DuckDuckGo with advanced rate limiting and result formatting
|
|
30
|
+
- **Content Fetching**: Retrieve and parse webpage content with intelligent text extraction
|
|
31
|
+
- **Rate Limiting**: Built-in protection against rate limits for both search and content fetching
|
|
32
|
+
- **Error Handling**: Comprehensive error handling and logging
|
|
33
|
+
- **LLM-Friendly Output**: Results formatted specifically for large language model consumption
|
|
34
|
+
|
|
35
|
+
## Installation
|
|
36
|
+
|
|
37
|
+
This server requires Python 3.10 or higher. Install dependencies using `uv` (recommended) or `pip`:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Using uv (recommended)
|
|
41
|
+
uv add "mcp[cli]" httpx beautifulsoup4
|
|
42
|
+
|
|
43
|
+
# Using pip
|
|
44
|
+
pip install "mcp[cli]" httpx beautifulsoup4
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
### Running with Claude Desktop
|
|
50
|
+
|
|
51
|
+
1. Download [Claude Desktop](https://claude.ai/download)
|
|
52
|
+
2. Create or edit `claude_desktop_config.json`:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"ddg-search": {
|
|
58
|
+
"command": "python",
|
|
59
|
+
"args": ["path/to/ddg_search_server.py"]
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
3. Restart Claude Desktop
|
|
66
|
+
|
|
67
|
+
### Direct Usage
|
|
68
|
+
|
|
69
|
+
Run the server directly:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python ddg_search_server.py
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Or use the MCP CLI for development:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
mcp dev ddg_search_server.py
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Available Tools
|
|
82
|
+
|
|
83
|
+
### 1. Search Tool
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
async def search(query: str, max_results: int = 10) -> str
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Performs a web search on DuckDuckGo and returns formatted results.
|
|
90
|
+
|
|
91
|
+
**Parameters:**
|
|
92
|
+
- `query`: Search query string
|
|
93
|
+
- `max_results`: Maximum number of results to return (default: 10)
|
|
94
|
+
|
|
95
|
+
**Returns:**
|
|
96
|
+
Formatted string containing search results with titles, URLs, and snippets.
|
|
97
|
+
|
|
98
|
+
### 2. Content Fetching Tool
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
async def fetch_content(url: str) -> str
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Fetches and parses content from a webpage.
|
|
105
|
+
|
|
106
|
+
**Parameters:**
|
|
107
|
+
- `url`: The webpage URL to fetch content from
|
|
108
|
+
|
|
109
|
+
**Returns:**
|
|
110
|
+
Cleaned and formatted text content from the webpage.
|
|
111
|
+
|
|
112
|
+
## Features in Detail
|
|
113
|
+
|
|
114
|
+
### Rate Limiting
|
|
115
|
+
|
|
116
|
+
- Search: Limited to 30 requests per minute
|
|
117
|
+
- Content Fetching: Limited to 20 requests per minute
|
|
118
|
+
- Automatic queue management and wait times
|
|
119
|
+
|
|
120
|
+
### Result Processing
|
|
121
|
+
|
|
122
|
+
- Removes ads and irrelevant content
|
|
123
|
+
- Cleans up DuckDuckGo redirect URLs
|
|
124
|
+
- Formats results for optimal LLM consumption
|
|
125
|
+
- Truncates long content appropriately
|
|
126
|
+
|
|
127
|
+
### Error Handling
|
|
128
|
+
|
|
129
|
+
- Comprehensive error catching and reporting
|
|
130
|
+
- Detailed logging through MCP context
|
|
131
|
+
- Graceful degradation on rate limits or timeouts
|
|
132
|
+
|
|
133
|
+
## Contributing
|
|
134
|
+
|
|
135
|
+
Issues and pull requests are welcome! Some areas for potential improvement:
|
|
136
|
+
|
|
137
|
+
- Additional search parameters (region, language, etc.)
|
|
138
|
+
- Enhanced content parsing options
|
|
139
|
+
- Caching layer for frequently accessed content
|
|
140
|
+
- Additional rate limiting strategies
|
|
141
|
+
|
|
142
|
+
## License
|
|
143
|
+
|
|
144
|
+
This project is licensed under the MIT License.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# DuckDuckGo Search MCP Server
|
|
2
|
+
|
|
3
|
+
A Model Context Protocol (MCP) server that provides web search capabilities through DuckDuckGo, with additional features for content fetching and parsing.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Web Search**: Search DuckDuckGo with advanced rate limiting and result formatting
|
|
8
|
+
- **Content Fetching**: Retrieve and parse webpage content with intelligent text extraction
|
|
9
|
+
- **Rate Limiting**: Built-in protection against rate limits for both search and content fetching
|
|
10
|
+
- **Error Handling**: Comprehensive error handling and logging
|
|
11
|
+
- **LLM-Friendly Output**: Results formatted specifically for large language model consumption
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
This server requires Python 3.10 or higher. Install dependencies using `uv` (recommended) or `pip`:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Using uv (recommended)
|
|
19
|
+
uv add "mcp[cli]" httpx beautifulsoup4
|
|
20
|
+
|
|
21
|
+
# Using pip
|
|
22
|
+
pip install "mcp[cli]" httpx beautifulsoup4
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### Running with Claude Desktop
|
|
28
|
+
|
|
29
|
+
1. Download [Claude Desktop](https://claude.ai/download)
|
|
30
|
+
2. Create or edit `claude_desktop_config.json`:
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"mcpServers": {
|
|
35
|
+
"ddg-search": {
|
|
36
|
+
"command": "python",
|
|
37
|
+
"args": ["path/to/ddg_search_server.py"]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
3. Restart Claude Desktop
|
|
44
|
+
|
|
45
|
+
### Direct Usage
|
|
46
|
+
|
|
47
|
+
Run the server directly:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python ddg_search_server.py
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Or use the MCP CLI for development:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
mcp dev ddg_search_server.py
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Available Tools
|
|
60
|
+
|
|
61
|
+
### 1. Search Tool
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
async def search(query: str, max_results: int = 10) -> str
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Performs a web search on DuckDuckGo and returns formatted results.
|
|
68
|
+
|
|
69
|
+
**Parameters:**
|
|
70
|
+
- `query`: Search query string
|
|
71
|
+
- `max_results`: Maximum number of results to return (default: 10)
|
|
72
|
+
|
|
73
|
+
**Returns:**
|
|
74
|
+
Formatted string containing search results with titles, URLs, and snippets.
|
|
75
|
+
|
|
76
|
+
### 2. Content Fetching Tool
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
async def fetch_content(url: str) -> str
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Fetches and parses content from a webpage.
|
|
83
|
+
|
|
84
|
+
**Parameters:**
|
|
85
|
+
- `url`: The webpage URL to fetch content from
|
|
86
|
+
|
|
87
|
+
**Returns:**
|
|
88
|
+
Cleaned and formatted text content from the webpage.
|
|
89
|
+
|
|
90
|
+
## Features in Detail
|
|
91
|
+
|
|
92
|
+
### Rate Limiting
|
|
93
|
+
|
|
94
|
+
- Search: Limited to 30 requests per minute
|
|
95
|
+
- Content Fetching: Limited to 20 requests per minute
|
|
96
|
+
- Automatic queue management and wait times
|
|
97
|
+
|
|
98
|
+
### Result Processing
|
|
99
|
+
|
|
100
|
+
- Removes ads and irrelevant content
|
|
101
|
+
- Cleans up DuckDuckGo redirect URLs
|
|
102
|
+
- Formats results for optimal LLM consumption
|
|
103
|
+
- Truncates long content appropriately
|
|
104
|
+
|
|
105
|
+
### Error Handling
|
|
106
|
+
|
|
107
|
+
- Comprehensive error catching and reporting
|
|
108
|
+
- Detailed logging through MCP context
|
|
109
|
+
- Graceful degradation on rate limits or timeouts
|
|
110
|
+
|
|
111
|
+
## Contributing
|
|
112
|
+
|
|
113
|
+
Issues and pull requests are welcome! Some areas for potential improvement:
|
|
114
|
+
|
|
115
|
+
- Additional search parameters (region, language, etc.)
|
|
116
|
+
- Enhanced content parsing options
|
|
117
|
+
- Caching layer for frequently accessed content
|
|
118
|
+
- Additional rate limiting strategies
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
This project is licensed under the MIT License.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "duckduckgo-mcp-server"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "MCP Server for searching via DuckDuckGo"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{ name = "Nick Clyde", email = "nick@clyde.tech" }]
|
|
7
|
+
requires-python = ">=3.10"
|
|
8
|
+
dependencies = ["beautifulsoup4>=4.13.3", "httpx>=0.28.1", "mcp[cli]>=1.3.0"]
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Development Status :: 3 - Alpha",
|
|
11
|
+
"Intended Audience :: Developers",
|
|
12
|
+
"License :: OSI Approved :: MIT License",
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Programming Language :: Python :: 3.10",
|
|
15
|
+
"Programming Language :: Python :: 3.11",
|
|
16
|
+
"Programming Language :: Python :: 3.12",
|
|
17
|
+
"Programming Language :: Python :: 3.13",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://github.com/nickclyde/duckduckgo-mcp-server"
|
|
22
|
+
Issues = "https://github.com/nickclyde/duckduckgo-mcp-server/issues"
|
|
23
|
+
|
|
24
|
+
[project.scripts]
|
|
25
|
+
duckduckgo-mcp = "duckduckgo_mcp_server.server:main"
|
|
26
|
+
|
|
27
|
+
[build-system]
|
|
28
|
+
requires = ["hatchling"]
|
|
29
|
+
build-backend = "hatchling.build"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
from mcp.server.fastmcp import FastMCP, Context
|
|
2
|
+
import httpx
|
|
3
|
+
from bs4 import BeautifulSoup
|
|
4
|
+
from typing import List, Dict, Optional, Any
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
import urllib.parse
|
|
7
|
+
import sys
|
|
8
|
+
import traceback
|
|
9
|
+
import asyncio
|
|
10
|
+
from datetime import datetime, timedelta
|
|
11
|
+
import time
|
|
12
|
+
import re
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class SearchResult:
|
|
17
|
+
title: str
|
|
18
|
+
link: str
|
|
19
|
+
snippet: str
|
|
20
|
+
position: int
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class RateLimiter:
|
|
24
|
+
def __init__(self, requests_per_minute: int = 30):
|
|
25
|
+
self.requests_per_minute = requests_per_minute
|
|
26
|
+
self.requests = []
|
|
27
|
+
|
|
28
|
+
async def acquire(self):
|
|
29
|
+
now = datetime.now()
|
|
30
|
+
# Remove requests older than 1 minute
|
|
31
|
+
self.requests = [
|
|
32
|
+
req for req in self.requests if now - req < timedelta(minutes=1)
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
if len(self.requests) >= self.requests_per_minute:
|
|
36
|
+
# Wait until we can make another request
|
|
37
|
+
wait_time = 60 - (now - self.requests[0]).total_seconds()
|
|
38
|
+
if wait_time > 0:
|
|
39
|
+
await asyncio.sleep(wait_time)
|
|
40
|
+
|
|
41
|
+
self.requests.append(now)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class DuckDuckGoSearcher:
|
|
45
|
+
BASE_URL = "https://html.duckduckgo.com/html"
|
|
46
|
+
HEADERS = {
|
|
47
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
def __init__(self):
|
|
51
|
+
self.rate_limiter = RateLimiter()
|
|
52
|
+
|
|
53
|
+
def format_results_for_llm(self, results: List[SearchResult]) -> str:
|
|
54
|
+
"""Format results in a natural language style that's easier for LLMs to process"""
|
|
55
|
+
if not results:
|
|
56
|
+
return "No results were found for your search query. This could be due to DuckDuckGo's bot detection or the query returned no matches. Please try rephrasing your search or try again in a few minutes."
|
|
57
|
+
|
|
58
|
+
output = []
|
|
59
|
+
output.append(f"Found {len(results)} search results:\n")
|
|
60
|
+
|
|
61
|
+
for result in results:
|
|
62
|
+
output.append(f"{result.position}. {result.title}")
|
|
63
|
+
output.append(f" URL: {result.link}")
|
|
64
|
+
output.append(f" Summary: {result.snippet}")
|
|
65
|
+
output.append("") # Empty line between results
|
|
66
|
+
|
|
67
|
+
return "\n".join(output)
|
|
68
|
+
|
|
69
|
+
async def search(
|
|
70
|
+
self, query: str, ctx: Context, max_results: int = 10
|
|
71
|
+
) -> List[SearchResult]:
|
|
72
|
+
try:
|
|
73
|
+
# Apply rate limiting
|
|
74
|
+
await self.rate_limiter.acquire()
|
|
75
|
+
|
|
76
|
+
# Create form data for POST request
|
|
77
|
+
data = {
|
|
78
|
+
"q": query,
|
|
79
|
+
"b": "",
|
|
80
|
+
"kl": "",
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
await ctx.info(f"Searching DuckDuckGo for: {query}")
|
|
84
|
+
|
|
85
|
+
async with httpx.AsyncClient() as client:
|
|
86
|
+
response = await client.post(
|
|
87
|
+
self.BASE_URL, data=data, headers=self.HEADERS, timeout=30.0
|
|
88
|
+
)
|
|
89
|
+
response.raise_for_status()
|
|
90
|
+
|
|
91
|
+
# Parse HTML response
|
|
92
|
+
soup = BeautifulSoup(response.text, "html.parser")
|
|
93
|
+
if not soup:
|
|
94
|
+
await ctx.error("Failed to parse HTML response")
|
|
95
|
+
return []
|
|
96
|
+
|
|
97
|
+
results = []
|
|
98
|
+
for result in soup.select(".result"):
|
|
99
|
+
title_elem = result.select_one(".result__title")
|
|
100
|
+
if not title_elem:
|
|
101
|
+
continue
|
|
102
|
+
|
|
103
|
+
link_elem = title_elem.find("a")
|
|
104
|
+
if not link_elem:
|
|
105
|
+
continue
|
|
106
|
+
|
|
107
|
+
title = link_elem.get_text(strip=True)
|
|
108
|
+
link = link_elem.get("href", "")
|
|
109
|
+
|
|
110
|
+
# Skip ad results
|
|
111
|
+
if "y.js" in link:
|
|
112
|
+
continue
|
|
113
|
+
|
|
114
|
+
# Clean up DuckDuckGo redirect URLs
|
|
115
|
+
if link.startswith("//duckduckgo.com/l/?uddg="):
|
|
116
|
+
link = urllib.parse.unquote(link.split("uddg=")[1].split("&")[0])
|
|
117
|
+
|
|
118
|
+
snippet_elem = result.select_one(".result__snippet")
|
|
119
|
+
snippet = snippet_elem.get_text(strip=True) if snippet_elem else ""
|
|
120
|
+
|
|
121
|
+
results.append(
|
|
122
|
+
SearchResult(
|
|
123
|
+
title=title,
|
|
124
|
+
link=link,
|
|
125
|
+
snippet=snippet,
|
|
126
|
+
position=len(results) + 1,
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
if len(results) >= max_results:
|
|
131
|
+
break
|
|
132
|
+
|
|
133
|
+
await ctx.info(f"Successfully found {len(results)} results")
|
|
134
|
+
return results
|
|
135
|
+
|
|
136
|
+
except httpx.TimeoutError:
|
|
137
|
+
await ctx.error("Search request timed out")
|
|
138
|
+
return []
|
|
139
|
+
except httpx.HTTPError as e:
|
|
140
|
+
await ctx.error(f"HTTP error occurred: {str(e)}")
|
|
141
|
+
return []
|
|
142
|
+
except Exception as e:
|
|
143
|
+
await ctx.error(f"Unexpected error during search: {str(e)}")
|
|
144
|
+
traceback.print_exc(file=sys.stderr)
|
|
145
|
+
return []
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class WebContentFetcher:
|
|
149
|
+
def __init__(self):
|
|
150
|
+
self.rate_limiter = RateLimiter(requests_per_minute=20)
|
|
151
|
+
|
|
152
|
+
async def fetch_and_parse(self, url: str, ctx: Context) -> str:
|
|
153
|
+
"""Fetch and parse content from a webpage"""
|
|
154
|
+
try:
|
|
155
|
+
await self.rate_limiter.acquire()
|
|
156
|
+
|
|
157
|
+
await ctx.info(f"Fetching content from: {url}")
|
|
158
|
+
|
|
159
|
+
async with httpx.AsyncClient() as client:
|
|
160
|
+
response = await client.get(
|
|
161
|
+
url,
|
|
162
|
+
headers={
|
|
163
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
|
|
164
|
+
},
|
|
165
|
+
follow_redirects=True,
|
|
166
|
+
timeout=30.0,
|
|
167
|
+
)
|
|
168
|
+
response.raise_for_status()
|
|
169
|
+
|
|
170
|
+
# Parse the HTML
|
|
171
|
+
soup = BeautifulSoup(response.text, "html.parser")
|
|
172
|
+
|
|
173
|
+
# Remove script and style elements
|
|
174
|
+
for element in soup(["script", "style", "nav", "header", "footer"]):
|
|
175
|
+
element.decompose()
|
|
176
|
+
|
|
177
|
+
# Get the text content
|
|
178
|
+
text = soup.get_text()
|
|
179
|
+
|
|
180
|
+
# Clean up the text
|
|
181
|
+
lines = (line.strip() for line in text.splitlines())
|
|
182
|
+
chunks = (phrase.strip() for line in lines for phrase in line.split(" "))
|
|
183
|
+
text = " ".join(chunk for chunk in chunks if chunk)
|
|
184
|
+
|
|
185
|
+
# Remove extra whitespace
|
|
186
|
+
text = re.sub(r"\s+", " ", text).strip()
|
|
187
|
+
|
|
188
|
+
# Truncate if too long
|
|
189
|
+
if len(text) > 8000:
|
|
190
|
+
text = text[:8000] + "... [content truncated]"
|
|
191
|
+
|
|
192
|
+
await ctx.info(
|
|
193
|
+
f"Successfully fetched and parsed content ({len(text)} characters)"
|
|
194
|
+
)
|
|
195
|
+
return text
|
|
196
|
+
|
|
197
|
+
except httpx.TimeoutError:
|
|
198
|
+
await ctx.error(f"Request timed out for URL: {url}")
|
|
199
|
+
return "Error: The request timed out while trying to fetch the webpage."
|
|
200
|
+
except httpx.HTTPError as e:
|
|
201
|
+
await ctx.error(f"HTTP error occurred while fetching {url}: {str(e)}")
|
|
202
|
+
return f"Error: Could not access the webpage ({str(e)})"
|
|
203
|
+
except Exception as e:
|
|
204
|
+
await ctx.error(f"Error fetching content from {url}: {str(e)}")
|
|
205
|
+
return f"Error: An unexpected error occurred while fetching the webpage ({str(e)})"
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# Initialize FastMCP server
|
|
209
|
+
mcp = FastMCP("ddg-search")
|
|
210
|
+
searcher = DuckDuckGoSearcher()
|
|
211
|
+
fetcher = WebContentFetcher()
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
@mcp.tool()
|
|
215
|
+
async def search(query: str, ctx: Context, max_results: int = 10) -> str:
|
|
216
|
+
"""
|
|
217
|
+
Search DuckDuckGo and return formatted results.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
query: The search query string
|
|
221
|
+
max_results: Maximum number of results to return (default: 10)
|
|
222
|
+
ctx: MCP context for logging
|
|
223
|
+
"""
|
|
224
|
+
try:
|
|
225
|
+
results = await searcher.search(query, ctx, max_results)
|
|
226
|
+
return searcher.format_results_for_llm(results)
|
|
227
|
+
except Exception as e:
|
|
228
|
+
traceback.print_exc(file=sys.stderr)
|
|
229
|
+
return f"An error occurred while searching: {str(e)}"
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@mcp.tool()
|
|
233
|
+
async def fetch_content(url: str, ctx: Context) -> str:
|
|
234
|
+
"""
|
|
235
|
+
Fetch and parse content from a webpage URL.
|
|
236
|
+
|
|
237
|
+
Args:
|
|
238
|
+
url: The webpage URL to fetch content from
|
|
239
|
+
ctx: MCP context for logging
|
|
240
|
+
"""
|
|
241
|
+
return await fetcher.fetch_and_parse(url, ctx)
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def main():
|
|
245
|
+
mcp.run()
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
if __name__ == "__main__":
|
|
249
|
+
main()
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 1
|
|
3
|
+
requires-python = ">=3.10"
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "annotated-types"
|
|
7
|
+
version = "0.7.0"
|
|
8
|
+
source = { registry = "https://pypi.org/simple" }
|
|
9
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081 }
|
|
10
|
+
wheels = [
|
|
11
|
+
{ url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643 },
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "anyio"
|
|
16
|
+
version = "4.8.0"
|
|
17
|
+
source = { registry = "https://pypi.org/simple" }
|
|
18
|
+
dependencies = [
|
|
19
|
+
{ name = "exceptiongroup", marker = "python_full_version < '3.11'" },
|
|
20
|
+
{ name = "idna" },
|
|
21
|
+
{ name = "sniffio" },
|
|
22
|
+
{ name = "typing-extensions", marker = "python_full_version < '3.13'" },
|
|
23
|
+
]
|
|
24
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a3/73/199a98fc2dae33535d6b8e8e6ec01f8c1d76c9adb096c6b7d64823038cde/anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a", size = 181126 }
|
|
25
|
+
wheels = [
|
|
26
|
+
{ url = "https://files.pythonhosted.org/packages/46/eb/e7f063ad1fec6b3178a3cd82d1a3c4de82cccf283fc42746168188e1cdd5/anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a", size = 96041 },
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[[package]]
|
|
30
|
+
name = "beautifulsoup4"
|
|
31
|
+
version = "4.13.3"
|
|
32
|
+
source = { registry = "https://pypi.org/simple" }
|
|
33
|
+
dependencies = [
|
|
34
|
+
{ name = "soupsieve" },
|
|
35
|
+
{ name = "typing-extensions" },
|
|
36
|
+
]
|
|
37
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f0/3c/adaf39ce1fb4afdd21b611e3d530b183bb7759c9b673d60db0e347fd4439/beautifulsoup4-4.13.3.tar.gz", hash = "sha256:1bd32405dacc920b42b83ba01644747ed77456a65760e285fbc47633ceddaf8b", size = 619516 }
|
|
38
|
+
wheels = [
|
|
39
|
+
{ url = "https://files.pythonhosted.org/packages/f9/49/6abb616eb3cbab6a7cca303dc02fdf3836de2e0b834bf966a7f5271a34d8/beautifulsoup4-4.13.3-py3-none-any.whl", hash = "sha256:99045d7d3f08f91f0d656bc9b7efbae189426cd913d830294a15eefa0ea4df16", size = 186015 },
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[[package]]
|
|
43
|
+
name = "certifi"
|
|
44
|
+
version = "2025.1.31"
|
|
45
|
+
source = { registry = "https://pypi.org/simple" }
|
|
46
|
+
sdist = { url = "https://files.pythonhosted.org/packages/1c/ab/c9f1e32b7b1bf505bf26f0ef697775960db7932abeb7b516de930ba2705f/certifi-2025.1.31.tar.gz", hash = "sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651", size = 167577 }
|
|
47
|
+
wheels = [
|
|
48
|
+
{ url = "https://files.pythonhosted.org/packages/38/fc/bce832fd4fd99766c04d1ee0eead6b0ec6486fb100ae5e74c1d91292b982/certifi-2025.1.31-py3-none-any.whl", hash = "sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe", size = 166393 },
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
[[package]]
|
|
52
|
+
name = "click"
|
|
53
|
+
version = "8.1.8"
|
|
54
|
+
source = { registry = "https://pypi.org/simple" }
|
|
55
|
+
dependencies = [
|
|
56
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
57
|
+
]
|
|
58
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 }
|
|
59
|
+
wheels = [
|
|
60
|
+
{ url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188 },
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
[[package]]
|
|
64
|
+
name = "colorama"
|
|
65
|
+
version = "0.4.6"
|
|
66
|
+
source = { registry = "https://pypi.org/simple" }
|
|
67
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697 }
|
|
68
|
+
wheels = [
|
|
69
|
+
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335 },
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
[[package]]
|
|
73
|
+
name = "duckduckgo-mcp-server"
|
|
74
|
+
version = "0.1.0"
|
|
75
|
+
source = { editable = "." }
|
|
76
|
+
dependencies = [
|
|
77
|
+
{ name = "beautifulsoup4" },
|
|
78
|
+
{ name = "httpx" },
|
|
79
|
+
{ name = "mcp", extra = ["cli"] },
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
[package.metadata]
|
|
83
|
+
requires-dist = [
|
|
84
|
+
{ name = "beautifulsoup4", specifier = ">=4.13.3" },
|
|
85
|
+
{ name = "httpx", specifier = ">=0.28.1" },
|
|
86
|
+
{ name = "mcp", extras = ["cli"], specifier = ">=1.3.0" },
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
[[package]]
|
|
90
|
+
name = "exceptiongroup"
|
|
91
|
+
version = "1.2.2"
|
|
92
|
+
source = { registry = "https://pypi.org/simple" }
|
|
93
|
+
sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 }
|
|
94
|
+
wheels = [
|
|
95
|
+
{ url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 },
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
[[package]]
|
|
99
|
+
name = "h11"
|
|
100
|
+
version = "0.14.0"
|
|
101
|
+
source = { registry = "https://pypi.org/simple" }
|
|
102
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f5/38/3af3d3633a34a3316095b39c8e8fb4853a28a536e55d347bd8d8e9a14b03/h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d", size = 100418 }
|
|
103
|
+
wheels = [
|
|
104
|
+
{ url = "https://files.pythonhosted.org/packages/95/04/ff642e65ad6b90db43e668d70ffb6736436c7ce41fcc549f4e9472234127/h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761", size = 58259 },
|
|
105
|
+
]
|
|
106
|
+
|
|
107
|
+
[[package]]
|
|
108
|
+
name = "httpcore"
|
|
109
|
+
version = "1.0.7"
|
|
110
|
+
source = { registry = "https://pypi.org/simple" }
|
|
111
|
+
dependencies = [
|
|
112
|
+
{ name = "certifi" },
|
|
113
|
+
{ name = "h11" },
|
|
114
|
+
]
|
|
115
|
+
sdist = { url = "https://files.pythonhosted.org/packages/6a/41/d7d0a89eb493922c37d343b607bc1b5da7f5be7e383740b4753ad8943e90/httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c", size = 85196 }
|
|
116
|
+
wheels = [
|
|
117
|
+
{ url = "https://files.pythonhosted.org/packages/87/f5/72347bc88306acb359581ac4d52f23c0ef445b57157adedb9aee0cd689d2/httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd", size = 78551 },
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
[[package]]
|
|
121
|
+
name = "httpx"
|
|
122
|
+
version = "0.28.1"
|
|
123
|
+
source = { registry = "https://pypi.org/simple" }
|
|
124
|
+
dependencies = [
|
|
125
|
+
{ name = "anyio" },
|
|
126
|
+
{ name = "certifi" },
|
|
127
|
+
{ name = "httpcore" },
|
|
128
|
+
{ name = "idna" },
|
|
129
|
+
]
|
|
130
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406 }
|
|
131
|
+
wheels = [
|
|
132
|
+
{ url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517 },
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
[[package]]
|
|
136
|
+
name = "httpx-sse"
|
|
137
|
+
version = "0.4.0"
|
|
138
|
+
source = { registry = "https://pypi.org/simple" }
|
|
139
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4c/60/8f4281fa9bbf3c8034fd54c0e7412e66edbab6bc74c4996bd616f8d0406e/httpx-sse-0.4.0.tar.gz", hash = "sha256:1e81a3a3070ce322add1d3529ed42eb5f70817f45ed6ec915ab753f961139721", size = 12624 }
|
|
140
|
+
wheels = [
|
|
141
|
+
{ url = "https://files.pythonhosted.org/packages/e1/9b/a181f281f65d776426002f330c31849b86b31fc9d848db62e16f03ff739f/httpx_sse-0.4.0-py3-none-any.whl", hash = "sha256:f329af6eae57eaa2bdfd962b42524764af68075ea87370a2de920af5341e318f", size = 7819 },
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
[[package]]
|
|
145
|
+
name = "idna"
|
|
146
|
+
version = "3.10"
|
|
147
|
+
source = { registry = "https://pypi.org/simple" }
|
|
148
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490 }
|
|
149
|
+
wheels = [
|
|
150
|
+
{ url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442 },
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
[[package]]
|
|
154
|
+
name = "markdown-it-py"
|
|
155
|
+
version = "3.0.0"
|
|
156
|
+
source = { registry = "https://pypi.org/simple" }
|
|
157
|
+
dependencies = [
|
|
158
|
+
{ name = "mdurl" },
|
|
159
|
+
]
|
|
160
|
+
sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596 }
|
|
161
|
+
wheels = [
|
|
162
|
+
{ url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528 },
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
[[package]]
|
|
166
|
+
name = "mcp"
|
|
167
|
+
version = "1.3.0"
|
|
168
|
+
source = { registry = "https://pypi.org/simple" }
|
|
169
|
+
dependencies = [
|
|
170
|
+
{ name = "anyio" },
|
|
171
|
+
{ name = "httpx" },
|
|
172
|
+
{ name = "httpx-sse" },
|
|
173
|
+
{ name = "pydantic" },
|
|
174
|
+
{ name = "pydantic-settings" },
|
|
175
|
+
{ name = "sse-starlette" },
|
|
176
|
+
{ name = "starlette" },
|
|
177
|
+
{ name = "uvicorn" },
|
|
178
|
+
]
|
|
179
|
+
sdist = { url = "https://files.pythonhosted.org/packages/6b/b6/81e5f2490290351fc97bf46c24ff935128cb7d34d68e3987b522f26f7ada/mcp-1.3.0.tar.gz", hash = "sha256:f409ae4482ce9d53e7ac03f3f7808bcab735bdfc0fba937453782efb43882d45", size = 150235 }
|
|
180
|
+
wheels = [
|
|
181
|
+
{ url = "https://files.pythonhosted.org/packages/d0/d2/a9e87b506b2094f5aa9becc1af5178842701b27217fa43877353da2577e3/mcp-1.3.0-py3-none-any.whl", hash = "sha256:2829d67ce339a249f803f22eba5e90385eafcac45c94b00cab6cef7e8f217211", size = 70672 },
|
|
182
|
+
]
|
|
183
|
+
|
|
184
|
+
[package.optional-dependencies]
|
|
185
|
+
cli = [
|
|
186
|
+
{ name = "python-dotenv" },
|
|
187
|
+
{ name = "typer" },
|
|
188
|
+
]
|
|
189
|
+
|
|
190
|
+
[[package]]
|
|
191
|
+
name = "mdurl"
|
|
192
|
+
version = "0.1.2"
|
|
193
|
+
source = { registry = "https://pypi.org/simple" }
|
|
194
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729 }
|
|
195
|
+
wheels = [
|
|
196
|
+
{ url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979 },
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
[[package]]
|
|
200
|
+
name = "pydantic"
|
|
201
|
+
version = "2.10.6"
|
|
202
|
+
source = { registry = "https://pypi.org/simple" }
|
|
203
|
+
dependencies = [
|
|
204
|
+
{ name = "annotated-types" },
|
|
205
|
+
{ name = "pydantic-core" },
|
|
206
|
+
{ name = "typing-extensions" },
|
|
207
|
+
]
|
|
208
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b7/ae/d5220c5c52b158b1de7ca89fc5edb72f304a70a4c540c84c8844bf4008de/pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236", size = 761681 }
|
|
209
|
+
wheels = [
|
|
210
|
+
{ url = "https://files.pythonhosted.org/packages/f4/3c/8cc1cc84deffa6e25d2d0c688ebb80635dfdbf1dbea3e30c541c8cf4d860/pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584", size = 431696 },
|
|
211
|
+
]
|
|
212
|
+
|
|
213
|
+
[[package]]
|
|
214
|
+
name = "pydantic-core"
|
|
215
|
+
version = "2.27.2"
|
|
216
|
+
source = { registry = "https://pypi.org/simple" }
|
|
217
|
+
dependencies = [
|
|
218
|
+
{ name = "typing-extensions" },
|
|
219
|
+
]
|
|
220
|
+
sdist = { url = "https://files.pythonhosted.org/packages/fc/01/f3e5ac5e7c25833db5eb555f7b7ab24cd6f8c322d3a3ad2d67a952dc0abc/pydantic_core-2.27.2.tar.gz", hash = "sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39", size = 413443 }
|
|
221
|
+
wheels = [
|
|
222
|
+
{ url = "https://files.pythonhosted.org/packages/3a/bc/fed5f74b5d802cf9a03e83f60f18864e90e3aed7223adaca5ffb7a8d8d64/pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa", size = 1895938 },
|
|
223
|
+
{ url = "https://files.pythonhosted.org/packages/71/2a/185aff24ce844e39abb8dd680f4e959f0006944f4a8a0ea372d9f9ae2e53/pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c", size = 1815684 },
|
|
224
|
+
{ url = "https://files.pythonhosted.org/packages/c3/43/fafabd3d94d159d4f1ed62e383e264f146a17dd4d48453319fd782e7979e/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a", size = 1829169 },
|
|
225
|
+
{ url = "https://files.pythonhosted.org/packages/a2/d1/f2dfe1a2a637ce6800b799aa086d079998959f6f1215eb4497966efd2274/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5", size = 1867227 },
|
|
226
|
+
{ url = "https://files.pythonhosted.org/packages/7d/39/e06fcbcc1c785daa3160ccf6c1c38fea31f5754b756e34b65f74e99780b5/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c", size = 2037695 },
|
|
227
|
+
{ url = "https://files.pythonhosted.org/packages/7a/67/61291ee98e07f0650eb756d44998214231f50751ba7e13f4f325d95249ab/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7", size = 2741662 },
|
|
228
|
+
{ url = "https://files.pythonhosted.org/packages/32/90/3b15e31b88ca39e9e626630b4c4a1f5a0dfd09076366f4219429e6786076/pydantic_core-2.27.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a", size = 1993370 },
|
|
229
|
+
{ url = "https://files.pythonhosted.org/packages/ff/83/c06d333ee3a67e2e13e07794995c1535565132940715931c1c43bfc85b11/pydantic_core-2.27.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236", size = 1996813 },
|
|
230
|
+
{ url = "https://files.pythonhosted.org/packages/7c/f7/89be1c8deb6e22618a74f0ca0d933fdcb8baa254753b26b25ad3acff8f74/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962", size = 2005287 },
|
|
231
|
+
{ url = "https://files.pythonhosted.org/packages/b7/7d/8eb3e23206c00ef7feee17b83a4ffa0a623eb1a9d382e56e4aa46fd15ff2/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9", size = 2128414 },
|
|
232
|
+
{ url = "https://files.pythonhosted.org/packages/4e/99/fe80f3ff8dd71a3ea15763878d464476e6cb0a2db95ff1c5c554133b6b83/pydantic_core-2.27.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af", size = 2155301 },
|
|
233
|
+
{ url = "https://files.pythonhosted.org/packages/2b/a3/e50460b9a5789ca1451b70d4f52546fa9e2b420ba3bfa6100105c0559238/pydantic_core-2.27.2-cp310-cp310-win32.whl", hash = "sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4", size = 1816685 },
|
|
234
|
+
{ url = "https://files.pythonhosted.org/packages/57/4c/a8838731cb0f2c2a39d3535376466de6049034d7b239c0202a64aaa05533/pydantic_core-2.27.2-cp310-cp310-win_amd64.whl", hash = "sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31", size = 1982876 },
|
|
235
|
+
{ 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 },
|
|
236
|
+
{ 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 },
|
|
237
|
+
{ 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 },
|
|
238
|
+
{ 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 },
|
|
239
|
+
{ 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 },
|
|
240
|
+
{ 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 },
|
|
241
|
+
{ 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 },
|
|
242
|
+
{ 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 },
|
|
243
|
+
{ 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 },
|
|
244
|
+
{ 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 },
|
|
245
|
+
{ 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 },
|
|
246
|
+
{ url = "https://files.pythonhosted.org/packages/72/9d/a241db83f973049a1092a079272ffe2e3e82e98561ef6214ab53fe53b1c7/pydantic_core-2.27.2-cp311-cp311-win32.whl", hash = "sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c", size = 1812361 },
|
|
247
|
+
{ url = "https://files.pythonhosted.org/packages/e8/ef/013f07248041b74abd48a385e2110aa3a9bbfef0fbd97d4e6d07d2f5b89a/pydantic_core-2.27.2-cp311-cp311-win_amd64.whl", hash = "sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc", size = 1982484 },
|
|
248
|
+
{ url = "https://files.pythonhosted.org/packages/10/1c/16b3a3e3398fd29dca77cea0a1d998d6bde3902fa2706985191e2313cc76/pydantic_core-2.27.2-cp311-cp311-win_arm64.whl", hash = "sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4", size = 1867102 },
|
|
249
|
+
{ 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 },
|
|
250
|
+
{ 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 },
|
|
251
|
+
{ 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 },
|
|
252
|
+
{ 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 },
|
|
253
|
+
{ 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 },
|
|
254
|
+
{ 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 },
|
|
255
|
+
{ 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 },
|
|
256
|
+
{ 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 },
|
|
257
|
+
{ 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 },
|
|
258
|
+
{ 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 },
|
|
259
|
+
{ 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 },
|
|
260
|
+
{ url = "https://files.pythonhosted.org/packages/9b/67/4e197c300976af185b7cef4c02203e175fb127e414125916bf1128b639a9/pydantic_core-2.27.2-cp312-cp312-win32.whl", hash = "sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc", size = 1834064 },
|
|
261
|
+
{ url = "https://files.pythonhosted.org/packages/1f/ea/cd7209a889163b8dcca139fe32b9687dd05249161a3edda62860430457a5/pydantic_core-2.27.2-cp312-cp312-win_amd64.whl", hash = "sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9", size = 1989046 },
|
|
262
|
+
{ url = "https://files.pythonhosted.org/packages/bc/49/c54baab2f4658c26ac633d798dab66b4c3a9bbf47cff5284e9c182f4137a/pydantic_core-2.27.2-cp312-cp312-win_arm64.whl", hash = "sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b", size = 1885092 },
|
|
263
|
+
{ 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 },
|
|
264
|
+
{ 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 },
|
|
265
|
+
{ 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 },
|
|
266
|
+
{ 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 },
|
|
267
|
+
{ 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 },
|
|
268
|
+
{ 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 },
|
|
269
|
+
{ 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 },
|
|
270
|
+
{ 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 },
|
|
271
|
+
{ 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 },
|
|
272
|
+
{ 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 },
|
|
273
|
+
{ 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 },
|
|
274
|
+
{ url = "https://files.pythonhosted.org/packages/a4/99/bddde3ddde76c03b65dfd5a66ab436c4e58ffc42927d4ff1198ffbf96f5f/pydantic_core-2.27.2-cp313-cp313-win32.whl", hash = "sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130", size = 1834387 },
|
|
275
|
+
{ url = "https://files.pythonhosted.org/packages/71/47/82b5e846e01b26ac6f1893d3c5f9f3a2eb6ba79be26eef0b759b4fe72946/pydantic_core-2.27.2-cp313-cp313-win_amd64.whl", hash = "sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee", size = 1990453 },
|
|
276
|
+
{ url = "https://files.pythonhosted.org/packages/51/b2/b2b50d5ecf21acf870190ae5d093602d95f66c9c31f9d5de6062eb329ad1/pydantic_core-2.27.2-cp313-cp313-win_arm64.whl", hash = "sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b", size = 1885186 },
|
|
277
|
+
{ url = "https://files.pythonhosted.org/packages/46/72/af70981a341500419e67d5cb45abe552a7c74b66326ac8877588488da1ac/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e", size = 1891159 },
|
|
278
|
+
{ url = "https://files.pythonhosted.org/packages/ad/3d/c5913cccdef93e0a6a95c2d057d2c2cba347815c845cda79ddd3c0f5e17d/pydantic_core-2.27.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8", size = 1768331 },
|
|
279
|
+
{ url = "https://files.pythonhosted.org/packages/f6/f0/a3ae8fbee269e4934f14e2e0e00928f9346c5943174f2811193113e58252/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3", size = 1822467 },
|
|
280
|
+
{ url = "https://files.pythonhosted.org/packages/d7/7a/7bbf241a04e9f9ea24cd5874354a83526d639b02674648af3f350554276c/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f", size = 1979797 },
|
|
281
|
+
{ url = "https://files.pythonhosted.org/packages/4f/5f/4784c6107731f89e0005a92ecb8a2efeafdb55eb992b8e9d0a2be5199335/pydantic_core-2.27.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133", size = 1987839 },
|
|
282
|
+
{ url = "https://files.pythonhosted.org/packages/6d/a7/61246562b651dff00de86a5f01b6e4befb518df314c54dec187a78d81c84/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc", size = 1998861 },
|
|
283
|
+
{ url = "https://files.pythonhosted.org/packages/86/aa/837821ecf0c022bbb74ca132e117c358321e72e7f9702d1b6a03758545e2/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50", size = 2116582 },
|
|
284
|
+
{ url = "https://files.pythonhosted.org/packages/81/b0/5e74656e95623cbaa0a6278d16cf15e10a51f6002e3ec126541e95c29ea3/pydantic_core-2.27.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9", size = 2151985 },
|
|
285
|
+
{ url = "https://files.pythonhosted.org/packages/63/37/3e32eeb2a451fddaa3898e2163746b0cffbbdbb4740d38372db0490d67f3/pydantic_core-2.27.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151", size = 2004715 },
|
|
286
|
+
]
|
|
287
|
+
|
|
288
|
+
[[package]]
|
|
289
|
+
name = "pydantic-settings"
|
|
290
|
+
version = "2.8.0"
|
|
291
|
+
source = { registry = "https://pypi.org/simple" }
|
|
292
|
+
dependencies = [
|
|
293
|
+
{ name = "pydantic" },
|
|
294
|
+
{ name = "python-dotenv" },
|
|
295
|
+
]
|
|
296
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ca/a2/ad2511ede77bb424f3939e5148a56d968cdc6b1462620d24b2a1f4ab65b4/pydantic_settings-2.8.0.tar.gz", hash = "sha256:88e2ca28f6e68ea102c99c3c401d6c9078e68a5df600e97b43891c34e089500a", size = 83347 }
|
|
297
|
+
wheels = [
|
|
298
|
+
{ url = "https://files.pythonhosted.org/packages/c1/a9/3b9642025174bbe67e900785fb99c9bfe91ea584b0b7126ff99945c24a0e/pydantic_settings-2.8.0-py3-none-any.whl", hash = "sha256:c782c7dc3fb40e97b238e713c25d26f64314aece2e91abcff592fcac15f71820", size = 30746 },
|
|
299
|
+
]
|
|
300
|
+
|
|
301
|
+
[[package]]
|
|
302
|
+
name = "pygments"
|
|
303
|
+
version = "2.19.1"
|
|
304
|
+
source = { registry = "https://pypi.org/simple" }
|
|
305
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581 }
|
|
306
|
+
wheels = [
|
|
307
|
+
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293 },
|
|
308
|
+
]
|
|
309
|
+
|
|
310
|
+
[[package]]
|
|
311
|
+
name = "python-dotenv"
|
|
312
|
+
version = "1.0.1"
|
|
313
|
+
source = { registry = "https://pypi.org/simple" }
|
|
314
|
+
sdist = { url = "https://files.pythonhosted.org/packages/bc/57/e84d88dfe0aec03b7a2d4327012c1627ab5f03652216c63d49846d7a6c58/python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca", size = 39115 }
|
|
315
|
+
wheels = [
|
|
316
|
+
{ url = "https://files.pythonhosted.org/packages/6a/3e/b68c118422ec867fa7ab88444e1274aa40681c606d59ac27de5a5588f082/python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a", size = 19863 },
|
|
317
|
+
]
|
|
318
|
+
|
|
319
|
+
[[package]]
|
|
320
|
+
name = "rich"
|
|
321
|
+
version = "13.9.4"
|
|
322
|
+
source = { registry = "https://pypi.org/simple" }
|
|
323
|
+
dependencies = [
|
|
324
|
+
{ name = "markdown-it-py" },
|
|
325
|
+
{ name = "pygments" },
|
|
326
|
+
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
|
327
|
+
]
|
|
328
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ab/3a/0316b28d0761c6734d6bc14e770d85506c986c85ffb239e688eeaab2c2bc/rich-13.9.4.tar.gz", hash = "sha256:439594978a49a09530cff7ebc4b5c7103ef57baf48d5ea3184f21d9a2befa098", size = 223149 }
|
|
329
|
+
wheels = [
|
|
330
|
+
{ url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 },
|
|
331
|
+
]
|
|
332
|
+
|
|
333
|
+
[[package]]
|
|
334
|
+
name = "shellingham"
|
|
335
|
+
version = "1.5.4"
|
|
336
|
+
source = { registry = "https://pypi.org/simple" }
|
|
337
|
+
sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310 }
|
|
338
|
+
wheels = [
|
|
339
|
+
{ url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755 },
|
|
340
|
+
]
|
|
341
|
+
|
|
342
|
+
[[package]]
|
|
343
|
+
name = "sniffio"
|
|
344
|
+
version = "1.3.1"
|
|
345
|
+
source = { registry = "https://pypi.org/simple" }
|
|
346
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a2/87/a6771e1546d97e7e041b6ae58d80074f81b7d5121207425c964ddf5cfdbd/sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc", size = 20372 }
|
|
347
|
+
wheels = [
|
|
348
|
+
{ url = "https://files.pythonhosted.org/packages/e9/44/75a9c9421471a6c4805dbf2356f7c181a29c1879239abab1ea2cc8f38b40/sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", size = 10235 },
|
|
349
|
+
]
|
|
350
|
+
|
|
351
|
+
[[package]]
|
|
352
|
+
name = "soupsieve"
|
|
353
|
+
version = "2.6"
|
|
354
|
+
source = { registry = "https://pypi.org/simple" }
|
|
355
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d7/ce/fbaeed4f9fb8b2daa961f90591662df6a86c1abf25c548329a86920aedfb/soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb", size = 101569 }
|
|
356
|
+
wheels = [
|
|
357
|
+
{ url = "https://files.pythonhosted.org/packages/d1/c2/fe97d779f3ef3b15f05c94a2f1e3d21732574ed441687474db9d342a7315/soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9", size = 36186 },
|
|
358
|
+
]
|
|
359
|
+
|
|
360
|
+
[[package]]
|
|
361
|
+
name = "sse-starlette"
|
|
362
|
+
version = "2.2.1"
|
|
363
|
+
source = { registry = "https://pypi.org/simple" }
|
|
364
|
+
dependencies = [
|
|
365
|
+
{ name = "anyio" },
|
|
366
|
+
{ name = "starlette" },
|
|
367
|
+
]
|
|
368
|
+
sdist = { url = "https://files.pythonhosted.org/packages/71/a4/80d2a11af59fe75b48230846989e93979c892d3a20016b42bb44edb9e398/sse_starlette-2.2.1.tar.gz", hash = "sha256:54470d5f19274aeed6b2d473430b08b4b379ea851d953b11d7f1c4a2c118b419", size = 17376 }
|
|
369
|
+
wheels = [
|
|
370
|
+
{ url = "https://files.pythonhosted.org/packages/d9/e0/5b8bd393f27f4a62461c5cf2479c75a2cc2ffa330976f9f00f5f6e4f50eb/sse_starlette-2.2.1-py3-none-any.whl", hash = "sha256:6410a3d3ba0c89e7675d4c273a301d64649c03a5ef1ca101f10b47f895fd0e99", size = 10120 },
|
|
371
|
+
]
|
|
372
|
+
|
|
373
|
+
[[package]]
|
|
374
|
+
name = "starlette"
|
|
375
|
+
version = "0.45.3"
|
|
376
|
+
source = { registry = "https://pypi.org/simple" }
|
|
377
|
+
dependencies = [
|
|
378
|
+
{ name = "anyio" },
|
|
379
|
+
]
|
|
380
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ff/fb/2984a686808b89a6781526129a4b51266f678b2d2b97ab2d325e56116df8/starlette-0.45.3.tar.gz", hash = "sha256:2cbcba2a75806f8a41c722141486f37c28e30a0921c5f6fe4346cb0dcee1302f", size = 2574076 }
|
|
381
|
+
wheels = [
|
|
382
|
+
{ url = "https://files.pythonhosted.org/packages/d9/61/f2b52e107b1fc8944b33ef56bf6ac4ebbe16d91b94d2b87ce013bf63fb84/starlette-0.45.3-py3-none-any.whl", hash = "sha256:dfb6d332576f136ec740296c7e8bb8c8a7125044e7c6da30744718880cdd059d", size = 71507 },
|
|
383
|
+
]
|
|
384
|
+
|
|
385
|
+
[[package]]
|
|
386
|
+
name = "typer"
|
|
387
|
+
version = "0.15.1"
|
|
388
|
+
source = { registry = "https://pypi.org/simple" }
|
|
389
|
+
dependencies = [
|
|
390
|
+
{ name = "click" },
|
|
391
|
+
{ name = "rich" },
|
|
392
|
+
{ name = "shellingham" },
|
|
393
|
+
{ name = "typing-extensions" },
|
|
394
|
+
]
|
|
395
|
+
sdist = { url = "https://files.pythonhosted.org/packages/cb/ce/dca7b219718afd37a0068f4f2530a727c2b74a8b6e8e0c0080a4c0de4fcd/typer-0.15.1.tar.gz", hash = "sha256:a0588c0a7fa68a1978a069818657778f86abe6ff5ea6abf472f940a08bfe4f0a", size = 99789 }
|
|
396
|
+
wheels = [
|
|
397
|
+
{ url = "https://files.pythonhosted.org/packages/d0/cc/0a838ba5ca64dc832aa43f727bd586309846b0ffb2ce52422543e6075e8a/typer-0.15.1-py3-none-any.whl", hash = "sha256:7994fb7b8155b64d3402518560648446072864beefd44aa2dc36972a5972e847", size = 44908 },
|
|
398
|
+
]
|
|
399
|
+
|
|
400
|
+
[[package]]
|
|
401
|
+
name = "typing-extensions"
|
|
402
|
+
version = "4.12.2"
|
|
403
|
+
source = { registry = "https://pypi.org/simple" }
|
|
404
|
+
sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 }
|
|
405
|
+
wheels = [
|
|
406
|
+
{ url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 },
|
|
407
|
+
]
|
|
408
|
+
|
|
409
|
+
[[package]]
|
|
410
|
+
name = "uvicorn"
|
|
411
|
+
version = "0.34.0"
|
|
412
|
+
source = { registry = "https://pypi.org/simple" }
|
|
413
|
+
dependencies = [
|
|
414
|
+
{ name = "click" },
|
|
415
|
+
{ name = "h11" },
|
|
416
|
+
{ name = "typing-extensions", marker = "python_full_version < '3.11'" },
|
|
417
|
+
]
|
|
418
|
+
sdist = { url = "https://files.pythonhosted.org/packages/4b/4d/938bd85e5bf2edeec766267a5015ad969730bb91e31b44021dfe8b22df6c/uvicorn-0.34.0.tar.gz", hash = "sha256:404051050cd7e905de2c9a7e61790943440b3416f49cb409f965d9dcd0fa73e9", size = 76568 }
|
|
419
|
+
wheels = [
|
|
420
|
+
{ url = "https://files.pythonhosted.org/packages/61/14/33a3a1352cfa71812a3a21e8c9bfb83f60b0011f5e36f2b1399d51928209/uvicorn-0.34.0-py3-none-any.whl", hash = "sha256:023dc038422502fa28a09c7a30bf2b6991512da7dcdb8fd35fe57cfc154126f4", size = 62315 },
|
|
421
|
+
]
|