alibaba-cloud-ops-mcp-server 0.9.1__tar.gz → 0.9.3__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.
Files changed (41) hide show
  1. alibaba_cloud_ops_mcp_server-0.9.3/Dockerfile +23 -0
  2. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/PKG-INFO +2 -2
  3. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/pyproject.toml +2 -2
  4. alibaba_cloud_ops_mcp_server-0.9.3/src/alibaba_cloud_ops_mcp_server/__main__.py +4 -0
  5. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/alibabacloud/utils.py +10 -5
  6. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/server.py +12 -3
  7. alibaba_cloud_ops_mcp_server-0.9.3/src/alibaba_cloud_ops_mcp_server/settings.py +8 -0
  8. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/tools/api_tools.py +7 -3
  9. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/tools/cms_tools.py +4 -0
  10. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/tests/test_server.py +11 -7
  11. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/tests/tools/test_api_tools.py +1 -2
  12. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/uv.lock +5 -5
  13. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/.github/workflows/python-ci.yml +0 -0
  14. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/.gitignore +0 -0
  15. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/LICENSE +0 -0
  16. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/README.md +0 -0
  17. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/README_mcp_args.md +0 -0
  18. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/README_zh.md +0 -0
  19. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/examples/openapi_mcp_quickstart/server.py +0 -0
  20. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/image/Alibaba-Cloud-Ops-MCP-User-Group-en.png +0 -0
  21. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/image/Alibaba-Cloud-Ops-MCP-User-Group-zh.png +0 -0
  22. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/image/alibaba-cloud.png +0 -0
  23. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/__init__.py +0 -0
  24. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/__init__.py +0 -0
  25. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/alibabacloud/__init__.py +0 -0
  26. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/alibabacloud/api_meta_client.py +0 -0
  27. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/alibabacloud/exception.py +0 -0
  28. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/alibabacloud/static/PROMPT_UNDERSTANDING.md +0 -0
  29. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/alibabacloud/static/__init__.py +0 -0
  30. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/config.py +0 -0
  31. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/tools/__init__.py +0 -0
  32. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/tools/common_api_tools.py +0 -0
  33. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/tools/oos_tools.py +0 -0
  34. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/src/alibaba_cloud_ops_mcp_server/tools/oss_tools.py +0 -0
  35. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/tests/alibabacloud/test_api_meta_client.py +0 -0
  36. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/tests/alibabacloud/test_exception.py +0 -0
  37. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/tests/alibabacloud/test_utils.py +0 -0
  38. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/tests/test_init.py +0 -0
  39. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/tests/tools/test_cms_tools.py +0 -0
  40. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/tests/tools/test_oos_tools.py +0 -0
  41. {alibaba_cloud_ops_mcp_server-0.9.1 → alibaba_cloud_ops_mcp_server-0.9.3}/tests/tools/test_oss_tools.py +0 -0
@@ -0,0 +1,23 @@
1
+ # Use official Python 3.10 image as base image
2
+ FROM python:3.10-slim
3
+
4
+ # Set working directory
5
+ WORKDIR /app
6
+
7
+ # Update package manager and install system dependencies
8
+ RUN apt-get update && apt-get install -y \
9
+ curl \
10
+ gcc \
11
+ && rm -rf /var/lib/apt/lists/*
12
+
13
+ RUN useradd --create-home --shell /bin/bash app && chown -R app:app /app
14
+ USER app
15
+
16
+ COPY . /app
17
+ RUN pip install --no-cache-dir .
18
+
19
+ # Expose port
20
+ EXPOSE 8000
21
+
22
+ # Set default startup command
23
+ ENTRYPOINT ["python", "-m", "alibaba_cloud_ops_mcp_server"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alibaba-cloud-ops-mcp-server
3
- Version: 0.9.1
3
+ Version: 0.9.3
4
4
  Summary: A MCP server for Alibaba Cloud
5
5
  Author-email: Zheng Dayu <dayu.zdy@alibaba-inc.com>
6
6
  License-File: LICENSE
@@ -11,7 +11,7 @@ Requires-Dist: alibabacloud-ecs20140526>=6.1.0
11
11
  Requires-Dist: alibabacloud-oos20190601>=3.4.1
12
12
  Requires-Dist: alibabacloud-oss-v2>=1.1.0
13
13
  Requires-Dist: click>=8.1.8
14
- Requires-Dist: fastmcp>=2.8.0
14
+ Requires-Dist: fastmcp==2.8.0
15
15
  Description-Content-Type: text/markdown
16
16
 
17
17
  # Alibaba Cloud Ops MCP Server
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "alibaba-cloud-ops-mcp-server"
3
- version = "0.9.1"
3
+ version = "0.9.3"
4
4
  description = "A MCP server for Alibaba Cloud"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -14,7 +14,7 @@ dependencies = [
14
14
  "alibabacloud_oss_v2>=1.1.0",
15
15
  "alibabacloud-credentials>=1.0.0",
16
16
  "click>=8.1.8",
17
- "fastmcp>=2.8.0"
17
+ "fastmcp==2.8.0"
18
18
  ]
19
19
 
20
20
  [build-system]
@@ -0,0 +1,4 @@
1
+ from .server import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -3,6 +3,7 @@ import logging
3
3
  from alibabacloud_credentials.client import Client as CredClient
4
4
  from alibabacloud_tea_openapi.models import Config
5
5
  from fastmcp.server.dependencies import get_http_request
6
+ from alibaba_cloud_ops_mcp_server.settings import settings
6
7
 
7
8
  logger = logging.getLogger(__name__)
8
9
 
@@ -30,17 +31,21 @@ def get_credentials_from_header():
30
31
 
31
32
  def create_config():
32
33
  credentials = get_credentials_from_header()
34
+
33
35
  if credentials:
34
- access_key_id = credentials.get('AccessKeyId', None)
35
- access_key_secret = credentials.get('AccessKeySecret', None)
36
- token = credentials.get('SecurityToken', None)
36
+ access_key_id = credentials.get('AccessKeyId')
37
+ access_key_secret = credentials.get('AccessKeySecret')
38
+ token = credentials.get('SecurityToken')
37
39
  config = Config(
38
40
  access_key_id=access_key_id,
39
41
  access_key_secret=access_key_secret,
40
42
  security_token=token
41
43
  )
44
+ elif settings.headers_credential_only:
45
+ config = Config()
42
46
  else:
43
- credentialsClient = CredClient()
44
- config = Config(credential=credentialsClient)
47
+ credentials_client = CredClient()
48
+ config = Config(credential=credentials_client)
49
+
45
50
  config.user_agent = 'alibaba-cloud-ops-mcp-server'
46
51
  return config
@@ -5,6 +5,7 @@ import logging
5
5
  from alibaba_cloud_ops_mcp_server.tools.common_api_tools import set_custom_service_list
6
6
  from alibaba_cloud_ops_mcp_server.config import config
7
7
  from alibaba_cloud_ops_mcp_server.tools import cms_tools, oos_tools, oss_tools, api_tools, common_api_tools
8
+ from alibaba_cloud_ops_mcp_server.settings import settings
8
9
 
9
10
  logger = logging.getLogger(__name__)
10
11
 
@@ -47,14 +48,22 @@ SUPPORTED_SERVICES_MAP = {
47
48
  default=None,
48
49
  help="Comma-separated list of supported services, e.g., 'ecs,vpc,rds'",
49
50
  )
50
- def main(transport: str, port: int, host: str, services: str):
51
+ @click.option(
52
+ "--headers-credential-only",
53
+ type=bool,
54
+ default=False,
55
+ help="Whether to use credentials only from headers",
56
+ )
57
+ def main(transport: str, port: int, host: str, services: str, headers_credential_only: bool):
51
58
  # Create an MCP server
52
59
  mcp = FastMCP(
53
60
  name="alibaba-cloud-ops-mcp-server",
54
61
  port=port,
55
- host=host
62
+ host=host,
63
+ stateless_http=True
56
64
  )
57
-
65
+ if headers_credential_only:
66
+ settings.headers_credential_only = headers_credential_only
58
67
  if services:
59
68
  service_keys = [s.strip().lower() for s in services.split(",")]
60
69
  service_list = [(key, SUPPORTED_SERVICES_MAP.get(key, key)) for key in service_keys]
@@ -0,0 +1,8 @@
1
+ from pydantic_settings import BaseSettings
2
+
3
+
4
+ class Settings(BaseSettings):
5
+ headers_credential_only: bool = False
6
+
7
+
8
+ settings = Settings()
@@ -14,6 +14,7 @@ from alibabacloud_openapi_util.client import Client as OpenApiUtilClient
14
14
  from alibaba_cloud_ops_mcp_server.alibabacloud.api_meta_client import ApiMetaClient
15
15
  from alibaba_cloud_ops_mcp_server.alibabacloud.utils import create_config
16
16
 
17
+ logger = logging.getLogger(__name__)
17
18
 
18
19
  type_map = {
19
20
  'string': str,
@@ -29,18 +30,17 @@ REGION_ENDPOINT_SERVICE = ['ecs', 'oos', 'vpc', 'slb']
29
30
  DOUBLE_ENDPOINT_SERVICE = {
30
31
  'rds': ['cn-qingdao', 'cn-beijing', 'cn-hangzhou', 'cn-shanghai', 'cn-shenzhen', 'cn-heyuan', 'cn-guangzhou', 'cn-hongkong'],
31
32
  'ess': ['cn-qingdao', 'cn-beijing', 'cn-hangzhou', 'cn-shanghai', 'cn-nanjing', 'cn-shenzhen'],
32
- 'ros': ['cn-qingdao'],
33
33
  'dds': ['cn-qingdao', 'cn-beijing', 'cn-wulanchabu', 'cn-hangzhou', 'cn-shanghai', 'cn-shenzhen', 'cn-heyuan', 'cn-guangzhou'],
34
34
  'r-kvstore': ['cn-qingdao', 'cn-beijing', 'cn-wulanchabu', 'cn-hangzhou', 'cn-shanghai', 'cn-shenzhen', 'cn-heyuan']
35
35
  }
36
36
 
37
- CENTRAL_ENDPOINTS_SERVICE = ['cbn']
37
+ CENTRAL_ENDPOINTS_SERVICE = ['cbn', 'ros']
38
38
 
39
39
 
40
40
  def _get_service_endpoint(service: str, region_id: str):
41
41
  region_id = region_id.lower()
42
42
  use_region_endpoint = service in REGION_ENDPOINT_SERVICE or (
43
- service in DOUBLE_ENDPOINT_SERVICE and region_id in DOUBLE_ENDPOINT_SERVICE[service]
43
+ service in DOUBLE_ENDPOINT_SERVICE and region_id not in DOUBLE_ENDPOINT_SERVICE[service]
44
44
  )
45
45
 
46
46
  if use_region_endpoint:
@@ -78,6 +78,7 @@ def _tools_api_call(service: str, api: str, parameters: dict, ctx: Context):
78
78
 
79
79
  # 处理特殊参数格式
80
80
  processed_parameters = parameters.copy()
81
+ processed_parameters = {k: v for k, v in processed_parameters.items() if v is not None}
81
82
  if service == 'ecs':
82
83
  for param_name, param_value in parameters.items():
83
84
  if param_name in ECS_LIST_PARAMETERS and isinstance(param_value, list):
@@ -97,8 +98,11 @@ def _tools_api_call(service: str, api: str, parameters: dict, ctx: Context):
97
98
  req_body_type='formData',
98
99
  body_type='json'
99
100
  )
101
+ logger.info(f'Call API Request: Service: {service} API: {api} Method: {method} Parameters: {processed_parameters}')
100
102
  client = create_client(service, processed_parameters.get('RegionId', 'cn-hangzhou'))
101
103
  runtime = util_models.RuntimeOptions()
104
+ resp = client.call_api(params, req, runtime)
105
+ logger.info(f'Call API Response: {resp}')
102
106
  return client.call_api(params, req, runtime)
103
107
 
104
108
 
@@ -1,3 +1,5 @@
1
+ import logging
2
+
1
3
  from pydantic import Field
2
4
  from typing import List
3
5
  import os
@@ -10,6 +12,7 @@ from alibaba_cloud_ops_mcp_server.alibabacloud.utils import create_config
10
12
 
11
13
  END_STATUSES = ['Success', 'Failed', 'Cancelled']
12
14
 
15
+ logger = logging.getLogger(__name__)
13
16
 
14
17
  tools = []
15
18
 
@@ -33,6 +36,7 @@ def _get_cms_metric_data(region_id: str, instance_ids: List[str], metric_name: s
33
36
  dimensions=json.dumps(dimesion),
34
37
  )
35
38
  describe_metric_last_resp = client.describe_metric_last(describe_metric_last_request)
39
+ logger.info(f'CMS Tools response: {describe_metric_last_resp.body}')
36
40
  return describe_metric_last_resp.body.datapoints
37
41
 
38
42
  @tools.append
@@ -11,10 +11,11 @@ def test_main_run(mock_create_api_tools, mock_FastMCP):
11
11
  mcp = MagicMock()
12
12
  mock_FastMCP.return_value = mcp
13
13
  # 调用main函数
14
- server.main.callback(transport='stdio', port=12345, host='127.0.0.1', services='ecs')
14
+ server.main.callback(transport='stdio', port=12345, host='127.0.0.1', services='ecs',
15
+ headers_credential_only=None)
15
16
  mock_FastMCP.assert_called_once_with(
16
17
  name='alibaba-cloud-ops-mcp-server',
17
- port=12345, host='127.0.0.1')
18
+ port=12345, host='127.0.0.1', stateless_http=True)
18
19
  assert mcp.tool.call_count == 7 # common_api_tools 4 + oss/oos/cms 各1
19
20
  mock_create_api_tools.assert_called_once()
20
21
  mcp.run.assert_called_once_with(transport='stdio')
@@ -31,10 +32,11 @@ def test_main_run_without_services(mock_create_api_tools, mock_FastMCP):
31
32
  mcp = MagicMock()
32
33
  mock_FastMCP.return_value = mcp
33
34
  # 调用main函数,不指定services
34
- server.main.callback(transport='stdio', port=8000, host='127.0.0.1', services=None)
35
+ server.main.callback(transport='stdio', port=8000, host='127.0.0.1', services=None,
36
+ headers_credential_only=None)
35
37
  mock_FastMCP.assert_called_once_with(
36
38
  name='alibaba-cloud-ops-mcp-server',
37
- port=8000, host='127.0.0.1')
39
+ port=8000, host='127.0.0.1', stateless_http=True)
38
40
  # 不指定services时,应该只有oss/oos/cms的工具被添加,没有common_api_tools
39
41
  assert mcp.tool.call_count == 3 # oss/oos/cms 各1
40
42
  mock_create_api_tools.assert_called_once()
@@ -75,10 +77,11 @@ def test_main_run_multiple_services(mock_create_api_tools, mock_FastMCP):
75
77
  mcp = MagicMock()
76
78
  mock_FastMCP.return_value = mcp
77
79
  # 调用main函数,指定多个services
78
- server.main.callback(transport='sse', port=9000, host='0.0.0.0', services='ecs,vpc,rds')
80
+ server.main.callback(transport='sse', port=9000, host='0.0.0.0', services='ecs,vpc,rds',
81
+ headers_credential_only=None)
79
82
  mock_FastMCP.assert_called_once_with(
80
83
  name='alibaba-cloud-ops-mcp-server',
81
- port=9000, host='0.0.0.0')
84
+ port=9000, host='0.0.0.0', stateless_http=True)
82
85
  # common_api_tools 2 + oss/oos/cms 各1 = 5
83
86
  assert mcp.tool.call_count == 5
84
87
  mock_create_api_tools.assert_called_once()
@@ -97,6 +100,7 @@ def test_main_run_with_logging(mock_logger, mock_create_api_tools, mock_FastMCP)
97
100
  mcp = MagicMock()
98
101
  mock_FastMCP.return_value = mcp
99
102
  # 调用main函数
100
- server.main.callback(transport='streamable-http', port=8080, host='localhost', services=None)
103
+ server.main.callback(transport='streamable-http', port=8080, host='localhost', services=None,
104
+ headers_credential_only=None)
101
105
  # 验证日志被调用
102
106
  mock_logger.debug.assert_called_once_with('mcp server is running on streamable-http mode.')
@@ -232,7 +232,6 @@ def test_tools_api_call_ecs_list_parameters_non_list():
232
232
  # 验证传入query方法的参数
233
233
  query_args = mock_OpenApiUtilClient.query.call_args[0][0]
234
234
  assert query_args['InstanceIds'] == 'i-123'
235
- assert query_args['SecurityGroupIds'] is None
236
235
 
237
236
  def test_create_tool_function_with_signature_bind_and_apply_defaults():
238
237
  """测试func_code函数中的signature.bind和apply_defaults调用"""
@@ -382,7 +381,7 @@ def test_get_service_endpoint_all_branches():
382
381
  # REGION_ENDPOINT_SERVICE 分支
383
382
  assert _get_service_endpoint('ecs', 'cn-hangzhou') == 'ecs.cn-hangzhou.aliyuncs.com'
384
383
  # DOUBLE_ENDPOINT_SERVICE 且 region 匹配
385
- assert _get_service_endpoint('rds', 'cn-hangzhou') == 'rds.cn-hangzhou.aliyuncs.com'
384
+ assert _get_service_endpoint('rds', 'cn-hangzhou') == 'rds.aliyuncs.com'
386
385
  # CENTRAL_ENDPOINTS_SERVICE 分支
387
386
  assert _get_service_endpoint('cbn', 'cn-hangzhou') == 'cbn.aliyuncs.com'
388
387
  # 其它分支
@@ -116,7 +116,7 @@ wheels = [
116
116
 
117
117
  [[package]]
118
118
  name = "alibaba-cloud-ops-mcp-server"
119
- version = "0.9.0"
119
+ version = "0.9.3"
120
120
  source = { editable = "." }
121
121
  dependencies = [
122
122
  { name = "alibabacloud-cms20190101" },
@@ -142,7 +142,7 @@ requires-dist = [
142
142
  { name = "alibabacloud-oos20190601", specifier = ">=3.4.1" },
143
143
  { name = "alibabacloud-oss-v2", specifier = ">=1.1.0" },
144
144
  { name = "click", specifier = ">=8.1.8" },
145
- { name = "fastmcp", specifier = ">=2.8.0" },
145
+ { name = "fastmcp", specifier = "==2.8.0" },
146
146
  ]
147
147
 
148
148
  [package.metadata.requires-dev]
@@ -666,7 +666,7 @@ wheels = [
666
666
 
667
667
  [[package]]
668
668
  name = "fastmcp"
669
- version = "2.8.1"
669
+ version = "2.8.0"
670
670
  source = { registry = "https://pypi.org/simple" }
671
671
  dependencies = [
672
672
  { name = "authlib" },
@@ -678,9 +678,9 @@ dependencies = [
678
678
  { name = "rich" },
679
679
  { name = "typer" },
680
680
  ]
681
- sdist = { url = "https://files.pythonhosted.org/packages/04/76/d9b352dd632dbac9eea3255df7bba6d83b2def769b388ec332368d7b4638/fastmcp-2.8.1.tar.gz", hash = "sha256:c89d8ce8bf53a166eda444cfdcb2c638170e62445487229fbaf340aed31beeaf", size = 2559427 }
681
+ sdist = { url = "https://files.pythonhosted.org/packages/8d/a3/d5b2c47b25d13cca8108e077bf4a72b255b113fb525f4c22ce9ca5af9b08/fastmcp-2.8.0.tar.gz", hash = "sha256:8a6427ece23d0a324d4be2043598c8b89a91b2b5688873d8ae1e7aeaa7960513", size = 2554559 }
682
682
  wheels = [
683
- { url = "https://files.pythonhosted.org/packages/0a/f9/ecb902857d634e81287f205954ef1c69637f27b487b109bf3b4b62d3dbe7/fastmcp-2.8.1-py3-none-any.whl", hash = "sha256:3b56a7bbab6bbac64d2a251a98b3dec5bb822ab1e4e9f20bb259add028b10d44", size = 138191 },
683
+ { url = "https://files.pythonhosted.org/packages/2c/05/b9b0ee091578ff37da8ef0bee8fff80bed95daff61834982a6064e3e327f/fastmcp-2.8.0-py3-none-any.whl", hash = "sha256:772468e98dacd55ab3381f49dd2583341c41b0e5ef0d9c7620fd43833d949c0c", size = 137492 },
684
684
  ]
685
685
 
686
686
  [[package]]