alibaba-cloud-ops-mcp-server 0.7.9__py3-none-any.whl → 0.8.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
File without changes
@@ -75,6 +75,10 @@ class ApiMetaClient:
75
75
  # 获取POP平台API META参考文档:https://api.aliyun.com/openmeta/guide
76
76
  version = cls.get_service_version(service)
77
77
  service_standard, api_standard = cls.get_standard_service_and_api(service, api, version)
78
+ if service_standard is None:
79
+ raise Exception(f'InvalidServiceName: Please check the Service ({service}) you provide.')
80
+ if api_standard is None:
81
+ raise Exception(f'InvalidAPIName: Please check the Service ({service}) and the API ({api}) you provide.')
78
82
  data = cls.get_response_from_pop_api(cls.GET_API_INFO, service_standard, api_standard, version)
79
83
  return data, version
80
84
 
@@ -1,176 +1,13 @@
1
- # server.py
2
- import os
3
- from mcp.server.fastmcp import FastMCP, Context
4
- from pydantic import Field
1
+ from mcp.server.fastmcp import FastMCP
5
2
  import click
6
3
  import logging
7
4
 
8
- import inspect
9
- import types
10
- from dataclasses import make_dataclass, field
11
- from alibabacloud_tea_openapi import models as open_api_models
12
- from alibabacloud_tea_util import models as util_models
13
- from alibabacloud_tea_openapi.client import Client as OpenApiClient
14
- from alibabacloud_openapi_util.client import Client as OpenApiUtilClient
15
- from alibaba_cloud_ops_mcp_server.api_meta_client import ApiMetaClient
16
5
  from alibaba_cloud_ops_mcp_server.config import config
17
-
18
- from alibaba_cloud_ops_mcp_server import oos_tools
19
- from alibaba_cloud_ops_mcp_server import cms_tools
20
- from alibaba_cloud_ops_mcp_server import oss_tools
6
+ from alibaba_cloud_ops_mcp_server.tools import cms_tools, oos_tools, oss_tools, api_tools
21
7
 
22
8
  logger = logging.getLogger(__name__)
23
9
 
24
10
 
25
- type_map = {
26
- 'string': str,
27
- 'integer': int,
28
- 'boolean': bool,
29
- 'array': list,
30
- 'object': dict,
31
- 'number': float
32
- }
33
-
34
-
35
- def create_client(service: str, region_id: str) -> OpenApiClient:
36
- config = open_api_models.Config(
37
- access_key_id=os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'],
38
- access_key_secret=os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET'],
39
- user_agent='alibaba-cloud-ops-mcp-server',
40
- )
41
- if isinstance(service, str):
42
- service = service.lower()
43
- config.endpoint = f'{service}.{region_id}.aliyuncs.com'
44
- return OpenApiClient(config)
45
-
46
-
47
- def tools_api_call(service: str, api: str, parameters: dict, ctx: Context):
48
- service = service.lower()
49
- api_meta, _ = ApiMetaClient.get_api_meta(service, api)
50
- version = ApiMetaClient.get_service_version(service)
51
- method = 'POST' if api_meta.get('methods', [])[0] == 'post' else 'GET'
52
- path = api_meta.get('path', '/')
53
- style = ApiMetaClient.get_service_style(service)
54
- req = open_api_models.OpenApiRequest(
55
- query=OpenApiUtilClient.query(parameters)
56
- )
57
- params = open_api_models.Params(
58
- action=api,
59
- version=version,
60
- protocol='HTTPS',
61
- pathname=path,
62
- method=method,
63
- auth_type='AK',
64
- style=style,
65
- req_body_type='formData',
66
- body_type='json'
67
- )
68
- client = create_client(service, parameters.get('RegionId', 'cn-hangzhou'))
69
- runtime = util_models.RuntimeOptions()
70
- return client.call_api(params, req, runtime)
71
-
72
-
73
- def create_parameter_schema(fields: dict):
74
- return make_dataclass("ParameterSchema", [(name, type_, value) for name, (type_, value) in fields.items()])
75
-
76
-
77
- def create_function_schemas(service, api, api_meta):
78
- schemas = {}
79
- schemas[api] = {}
80
- parameters = api_meta['parameters']
81
- for parameter in parameters:
82
- name = parameter.get('name')
83
- # TODO 目前忽略了带'.'的参数
84
- if '.' in name:
85
- continue
86
- schema = parameter.get('schema', '')
87
- description = schema.get('description', '')
88
- example = schema.get('example', '')
89
- type_ = schema.get('type', '')
90
- description = f'{description} 请注意,提供参数要严格按照参数的类型和参数示例的提示,如果提到参数为String,且为一个 JSON 数组字符串,应在数组内使用单引号包裹对应的参数以避免转义问题,并在最外侧用双引号包裹以确保其是字符串,否则可能会导致参数解析错误。参数类型: {type_},参数示例:{example}'
91
- required = schema.get('required', False)
92
- python_type = type_map.get(type_, str)
93
- field_info = (
94
- python_type,
95
- field(
96
- default=None,
97
- metadata={'description': description, 'required': required}
98
- )
99
- )
100
- schemas[api][name] = field_info
101
- if 'RegionId' not in schemas[api]:
102
- schemas[api]['RegionId'] = (
103
- str,
104
- field(
105
- default=None,
106
- metadata={'description': '地域ID', 'required': False}
107
- )
108
- )
109
- return schemas
110
-
111
-
112
- def create_tool_function_with_signature(service: str, function_name: str, fields: dict, description: str):
113
- """
114
- Dynamically creates a lambda function with a custom signature based on the provided fields.
115
- """
116
- parameters = []
117
- annotations = {}
118
- defaults = {}
119
-
120
- for name, (type_, field_info) in fields.items():
121
- field_description = field_info.metadata.get('description', '')
122
- is_required = field_info.metadata.get('required', False)
123
- default_value = field_info.default if not is_required else ...
124
-
125
- field_default = Field(default=default_value, description=field_description)
126
- parameters.append(inspect.Parameter(
127
- name=name,
128
- kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
129
- default=field_default,
130
- annotation=type_
131
- ))
132
- annotations[name] = type_
133
- defaults[name] = field_default
134
-
135
- signature = inspect.Signature(parameters)
136
-
137
- def func_code(*args, **kwargs):
138
- bound_args = signature.bind(*args, **kwargs)
139
- bound_args.apply_defaults()
140
-
141
- return tools_api_call(
142
- service=service,
143
- api=function_name,
144
- parameters=bound_args.arguments,
145
- ctx=None
146
- )
147
-
148
- func = types.FunctionType(
149
- func_code.__code__,
150
- globals(),
151
- function_name,
152
- None,
153
- func_code.__closure__
154
- )
155
- func.__signature__ = signature
156
- func.__annotations__ = annotations
157
- func.__defaults__ = tuple(defaults.values())
158
- func.__doc__ = description
159
-
160
- return func
161
-
162
-
163
- def create_and_decorate_tool(mcp: FastMCP, service: str, api: str):
164
- """Create a tool function for a Lambda function."""
165
- api_meta, _ = ApiMetaClient.get_api_meta(service, api)
166
- fields = create_function_schemas(service, api, api_meta).get(api, {})
167
- description = api_meta.get('summary', '')
168
- dynamic_lambda = create_tool_function_with_signature(service, api, fields, description)
169
- decorated_function = mcp.tool(name=api)(dynamic_lambda)
170
-
171
- return decorated_function
172
-
173
-
174
11
  @click.command()
175
12
  @click.option(
176
13
  "--transport",
@@ -187,9 +24,7 @@ def main(transport: str):
187
24
  mcp.add_tool(tool)
188
25
  for tool in oss_tools.tools:
189
26
  mcp.add_tool(tool)
190
- for service_code, apis in config.items():
191
- for api_name in apis:
192
- create_and_decorate_tool(mcp, service_code, api_name)
27
+ api_tools.create_api_tools(mcp, config)
193
28
 
194
29
  # Initialize and run the server
195
30
  logger.debug(f'mcp server is running on {transport} mode.')
File without changes
@@ -0,0 +1,168 @@
1
+ import os
2
+ from mcp.server.fastmcp import FastMCP, Context
3
+ from pydantic import Field
4
+ import logging
5
+
6
+ import inspect
7
+ import types
8
+ from dataclasses import make_dataclass, field
9
+ from alibabacloud_tea_openapi import models as open_api_models
10
+ from alibabacloud_tea_util import models as util_models
11
+ from alibabacloud_tea_openapi.client import Client as OpenApiClient
12
+ from alibabacloud_openapi_util.client import Client as OpenApiUtilClient
13
+ from alibaba_cloud_ops_mcp_server.alibabacloud.api_meta_client import ApiMetaClient
14
+
15
+
16
+ type_map = {
17
+ 'string': str,
18
+ 'integer': int,
19
+ 'boolean': bool,
20
+ 'array': list,
21
+ 'object': dict,
22
+ 'number': float
23
+ }
24
+
25
+
26
+ def create_client(service: str, region_id: str) -> OpenApiClient:
27
+ config = open_api_models.Config(
28
+ access_key_id=os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
29
+ access_key_secret=os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
30
+ security_token=os.getenv('ALIBABA_CLOUD_SECURITY_TOKEN'),
31
+ user_agent='alibaba-cloud-ops-mcp-server',
32
+ )
33
+ if isinstance(service, str):
34
+ service = service.lower()
35
+ config.endpoint = f'{service}.{region_id}.aliyuncs.com'
36
+ return OpenApiClient(config)
37
+
38
+
39
+ def _tools_api_call(service: str, api: str, parameters: dict, ctx: Context):
40
+ service = service.lower()
41
+ api_meta, _ = ApiMetaClient.get_api_meta(service, api)
42
+ version = ApiMetaClient.get_service_version(service)
43
+ method = 'POST' if api_meta.get('methods', [])[0] == 'post' else 'GET'
44
+ path = api_meta.get('path', '/')
45
+ style = ApiMetaClient.get_service_style(service)
46
+ req = open_api_models.OpenApiRequest(
47
+ query=OpenApiUtilClient.query(parameters)
48
+ )
49
+ params = open_api_models.Params(
50
+ action=api,
51
+ version=version,
52
+ protocol='HTTPS',
53
+ pathname=path,
54
+ method=method,
55
+ auth_type='AK',
56
+ style=style,
57
+ req_body_type='formData',
58
+ body_type='json'
59
+ )
60
+ client = create_client(service, parameters.get('RegionId', 'cn-hangzhou'))
61
+ runtime = util_models.RuntimeOptions()
62
+ return client.call_api(params, req, runtime)
63
+
64
+
65
+ def _create_parameter_schema(fields: dict):
66
+ return make_dataclass("ParameterSchema", [(name, type_, value) for name, (type_, value) in fields.items()])
67
+
68
+
69
+ def _create_function_schemas(service, api, api_meta):
70
+ schemas = {}
71
+ schemas[api] = {}
72
+ parameters = api_meta.get('parameters', [])
73
+ for parameter in parameters:
74
+ name = parameter.get('name')
75
+ # TODO 目前忽略了带'.'的参数
76
+ if '.' in name:
77
+ continue
78
+ schema = parameter.get('schema', '')
79
+ description = schema.get('description', '')
80
+ example = schema.get('example', '')
81
+ type_ = schema.get('type', '')
82
+ description = f'{description} 请注意,提供参数要严格按照参数的类型和参数示例的提示,如果提到参数为String,且为一个 JSON 数组字符串,应在数组内使用单引号包裹对应的参数以避免转义问题,并在最外侧用双引号包裹以确保其是字符串,否则可能会导致参数解析错误。参数类型: {type_},参数示例:{example}'
83
+ required = schema.get('required', False)
84
+ python_type = type_map.get(type_, str)
85
+ field_info = (
86
+ python_type,
87
+ field(
88
+ default=None,
89
+ metadata={'description': description, 'required': required}
90
+ )
91
+ )
92
+ schemas[api][name] = field_info
93
+ if 'RegionId' not in schemas[api]:
94
+ schemas[api]['RegionId'] = (
95
+ str,
96
+ field(
97
+ default=None,
98
+ metadata={'description': '地域ID', 'required': False}
99
+ )
100
+ )
101
+ return schemas
102
+
103
+
104
+ def _create_tool_function_with_signature(service: str, function_name: str, fields: dict, description: str):
105
+ """
106
+ Dynamically creates a lambda function with a custom signature based on the provided fields.
107
+ """
108
+ parameters = []
109
+ annotations = {}
110
+ defaults = {}
111
+
112
+ for name, (type_, field_info) in fields.items():
113
+ field_description = field_info.metadata.get('description', '')
114
+ is_required = field_info.metadata.get('required', False)
115
+ default_value = field_info.default if not is_required else ...
116
+
117
+ field_default = Field(default=default_value, description=field_description)
118
+ parameters.append(inspect.Parameter(
119
+ name=name,
120
+ kind=inspect.Parameter.POSITIONAL_OR_KEYWORD,
121
+ default=field_default,
122
+ annotation=type_
123
+ ))
124
+ annotations[name] = type_
125
+ defaults[name] = field_default
126
+
127
+ signature = inspect.Signature(parameters)
128
+
129
+ def func_code(*args, **kwargs):
130
+ bound_args = signature.bind(*args, **kwargs)
131
+ bound_args.apply_defaults()
132
+
133
+ return _tools_api_call(
134
+ service=service,
135
+ api=function_name,
136
+ parameters=bound_args.arguments,
137
+ ctx=None
138
+ )
139
+
140
+ func = types.FunctionType(
141
+ func_code.__code__,
142
+ globals(),
143
+ function_name,
144
+ None,
145
+ func_code.__closure__
146
+ )
147
+ func.__signature__ = signature
148
+ func.__annotations__ = annotations
149
+ func.__defaults__ = tuple(defaults.values())
150
+ func.__doc__ = description
151
+
152
+ return func
153
+
154
+
155
+ def _create_and_decorate_tool(mcp: FastMCP, service: str, api: str):
156
+ """Create a tool function for an AlibabaCloud openapi."""
157
+ api_meta, _ = ApiMetaClient.get_api_meta(service, api)
158
+ fields = _create_function_schemas(service, api, api_meta).get(api, {})
159
+ description = api_meta.get('summary', '')
160
+ dynamic_lambda = _create_tool_function_with_signature(service, api, fields, description)
161
+ decorated_function = mcp.tool(name=api)(dynamic_lambda)
162
+
163
+ return decorated_function
164
+
165
+ def create_api_tools(mcp: FastMCP, config:dict):
166
+ for service_code, apis in config.items():
167
+ for api_name in apis:
168
+ _create_and_decorate_tool(mcp, service_code, api_name)
@@ -15,10 +15,12 @@ END_STATUSES = ['Success', 'Failed', 'Cancelled']
15
15
 
16
16
  tools = []
17
17
 
18
+
18
19
  def create_client(region_id: str) -> cms20190101Client:
19
20
  config = open_api_models.Config(
20
- access_key_id=os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'],
21
- access_key_secret=os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET'],
21
+ access_key_id=os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
22
+ access_key_secret=os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
23
+ security_token=os.getenv('ALIBABA_CLOUD_SECURITY_TOKEN'),
22
24
  user_agent='alibaba-cloud-ops-mcp-server',
23
25
  )
24
26
  config.endpoint = f'metrics.{region_id}.aliyuncs.com'
@@ -7,8 +7,6 @@ import time
7
7
  from alibabacloud_oos20190601.client import Client as oos20190601Client
8
8
  from alibabacloud_tea_openapi import models as open_api_models
9
9
  from alibabacloud_oos20190601 import models as oos_20190601_models
10
- from alibabacloud_tea_util import models as util_models
11
- from alibabacloud_tea_util.client import Client as UtilClient
12
10
 
13
11
 
14
12
  END_STATUSES = ['Success', 'Failed', 'Cancelled']
@@ -18,8 +16,9 @@ tools = []
18
16
 
19
17
  def create_client(region_id: str) -> oos20190601Client:
20
18
  config = open_api_models.Config(
21
- access_key_id=os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID'],
22
- access_key_secret=os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET'],
19
+ access_key_id=os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID'),
20
+ access_key_secret=os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET'),
21
+ security_token=os.getenv('ALIBABA_CLOUD_SECURITY_TOKEN'),
23
22
  user_agent='alibaba-cloud-ops-mcp-server',
24
23
  )
25
24
  config.endpoint = f'oos.{region_id}.aliyuncs.com'
@@ -13,8 +13,8 @@ tools = []
13
13
  class CredentialsProvider(EnvironmentVariableCredentialsProvider):
14
14
  def __init__(self) -> None:
15
15
  super().__init__()
16
- access_key_id = os.environ['ALIBABA_CLOUD_ACCESS_KEY_ID']
17
- access_key_secret = os.environ['ALIBABA_CLOUD_ACCESS_KEY_SECRET']
16
+ access_key_id = os.getenv('ALIBABA_CLOUD_ACCESS_KEY_ID')
17
+ access_key_secret = os.getenv('ALIBABA_CLOUD_ACCESS_KEY_SECRET')
18
18
  session_token = os.getenv('ALIBABA_CLOUD_SESSION_TOKEN', None)
19
19
 
20
20
  self._credentials = Credentials(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alibaba-cloud-ops-mcp-server
3
- Version: 0.7.9
3
+ Version: 0.8.1
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
@@ -14,7 +14,9 @@ Requires-Dist: mcp[cli]>=1.6.0
14
14
  Description-Content-Type: text/markdown
15
15
 
16
16
  # alibaba-cloud-ops-mcp-server
17
+
17
18
  [中文版本](./README_zh.md)
19
+
18
20
  ## Prepare
19
21
 
20
22
  Install [uv](https://github.com/astral-sh/uv)
@@ -90,8 +92,8 @@ To use `alibaba-cloud-ops-mcp-server` MCP Server with any other MCP Client, you
90
92
 
91
93
  If you have any questions, please join the [Alibaba Cloud Ops MCP discussion group](https://qr.dingtalk.com/action/joingroup?code=v1,k1,iFxYG4jjLVh1jfmNAkkclji7CN5DSIdT+jvFsLyI60I=&_dt_no_comment=1&origin=11) (DingTalk group: 113455011677) for discussion.
92
94
 
93
- <img src="https://github.com/aliyun/alibaba-cloud-ops-mcp-server/blob/master/image/Alibaba-Cloud-Ops-MCP-User-Group-en.png?raw=true" width="500">
95
+ <img src="https://oos-public-cn-hangzhou.oss-cn-hangzhou.aliyuncs.com/alibaba-cloud-ops-mcp-server/Alibaba-Cloud-Ops-MCP-User-Group-en.png" width="500">
94
96
 
95
97
  ## Know More
96
98
 
97
- - [Alibaba Cloud MCP Server is ready to use out of the box!!](https://developer.aliyun.com/article/1661348)
99
+ - [Alibaba Cloud MCP Server is ready to use out of the box!!](https://developer.aliyun.com/article/1661348)
@@ -0,0 +1,15 @@
1
+ alibaba_cloud_ops_mcp_server/__init__.py,sha256=BaluUNyRz8Qw-X7Y0ywDezwbkqiSvWlSYn2452XeGcA,213
2
+ alibaba_cloud_ops_mcp_server/config.py,sha256=Nq6AT8bqSVa6zu9xjInaSjFcxA-GC7MLlCsV1q53yO0,514
3
+ alibaba_cloud_ops_mcp_server/server.py,sha256=nwn04rpm68GI3UJ_hQ0E3pny86dJ47Lw1LncQiBIfW8,896
4
+ alibaba_cloud_ops_mcp_server/alibabacloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ alibaba_cloud_ops_mcp_server/alibabacloud/api_meta_client.py,sha256=inOmW1no1YsR6_ezOZfgJtzGKo5nRTDufkf2qUTuNOs,7605
6
+ alibaba_cloud_ops_mcp_server/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ alibaba_cloud_ops_mcp_server/tools/api_tools.py,sha256=HMB7-PdBU8qiyok-gtymt83Cs4eGVSNNCubC0nN9NqE,6000
8
+ alibaba_cloud_ops_mcp_server/tools/cms_tools.py,sha256=ZrOgVqd97EGcGy47Uy5Nwsf1Nqu9rLIfxN9SDZ2Wyzs,4529
9
+ alibaba_cloud_ops_mcp_server/tools/oos_tools.py,sha256=8cIhpy61Ca7sT9aMR6rCtY4V1u6oFuLsY51gtVvkkyk,10051
10
+ alibaba_cloud_ops_mcp_server/tools/oss_tools.py,sha256=Fb15QUCnllEh8J9TppUEAoA2fB46FhSihUP3_dSfVRM,4449
11
+ alibaba_cloud_ops_mcp_server-0.8.1.dist-info/METADATA,sha256=4eS0pIQhD_KP5g_js_DoP1-jcf48tFQRDUfsSwQQAnc,4033
12
+ alibaba_cloud_ops_mcp_server-0.8.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
13
+ alibaba_cloud_ops_mcp_server-0.8.1.dist-info/entry_points.txt,sha256=ESGAWXKEp184forhs7VzTD4P1AUdZz6vCW6hRUKITGw,83
14
+ alibaba_cloud_ops_mcp_server-0.8.1.dist-info/licenses/LICENSE,sha256=gQgVkp2ttRCjodiPpXZZR-d7JnrYIYNiHk1YDUYgpa4,11331
15
+ alibaba_cloud_ops_mcp_server-0.8.1.dist-info/RECORD,,
@@ -1,12 +0,0 @@
1
- alibaba_cloud_ops_mcp_server/__init__.py,sha256=BaluUNyRz8Qw-X7Y0ywDezwbkqiSvWlSYn2452XeGcA,213
2
- alibaba_cloud_ops_mcp_server/api_meta_client.py,sha256=pxJztmkmcqqI3djECziAIMc3ZxsS8crqSc6AbneOX2I,7315
3
- alibaba_cloud_ops_mcp_server/cms_tools.py,sha256=5IhPtkHSwqLsy7D3lGznovQ94e-XBy6HBE7qLDMoYaQ,4464
4
- alibaba_cloud_ops_mcp_server/config.py,sha256=Nq6AT8bqSVa6zu9xjInaSjFcxA-GC7MLlCsV1q53yO0,514
5
- alibaba_cloud_ops_mcp_server/oos_tools.py,sha256=NDu18_R3SqB-Fv1SpnljV0b2Py6G9HXcoqvbV0MWL7Y,10105
6
- alibaba_cloud_ops_mcp_server/oss_tools.py,sha256=6d_vacAJllwkr74bsWgle8yMzqb_Xr1CPAIr_htFP-I,4451
7
- alibaba_cloud_ops_mcp_server/server.py,sha256=9qk122yEAZgzJ9iBTBns90McguU4pQFIgjOPD1CzH8c,6723
8
- alibaba_cloud_ops_mcp_server-0.7.9.dist-info/METADATA,sha256=KM1S455aPWzv05MyXGMJPzfnmgJqbVXF1L61Kzp6l4A,4023
9
- alibaba_cloud_ops_mcp_server-0.7.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
- alibaba_cloud_ops_mcp_server-0.7.9.dist-info/entry_points.txt,sha256=ESGAWXKEp184forhs7VzTD4P1AUdZz6vCW6hRUKITGw,83
11
- alibaba_cloud_ops_mcp_server-0.7.9.dist-info/licenses/LICENSE,sha256=gQgVkp2ttRCjodiPpXZZR-d7JnrYIYNiHk1YDUYgpa4,11331
12
- alibaba_cloud_ops_mcp_server-0.7.9.dist-info/RECORD,,