alibaba-cloud-ops-mcp-server 0.9.12__py3-none-any.whl → 0.9.14__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.
@@ -80,7 +80,13 @@ SUPPORTED_SERVICES_MAP = {
80
80
  default="domestic",
81
81
  help="Environment type: 'domestic' for domestic, 'international' for overseas (default: domestic)",
82
82
  )
83
- def main(transport: str, port: int, host: str, services: str, headers_credential_only: bool, env: str):
83
+ @click.option(
84
+ "--code-deploy",
85
+ is_flag=True,
86
+ default=False,
87
+ help="Enable code deploy mode, only load 6 specific tools: OOS_CodeDeploy, OOS_GetDeployStatus, OOS_GetLastDeploymentInfo, LOCAL_ListDirectory, LOCAL_RunShellScript, LOCAL_AnalyzeDeployStack",
88
+ )
89
+ def main(transport: str, port: int, host: str, services: str, headers_credential_only: bool, env: str, code_deploy: bool):
84
90
  _setup_logging()
85
91
  # Create an MCP server
86
92
  mcp = FastMCP(
@@ -152,23 +158,46 @@ def main(transport: str, port: int, host: str, services: str, headers_credential
152
158
  settings.headers_credential_only = headers_credential_only
153
159
  if env:
154
160
  settings.env = env
155
- if services:
156
- service_keys = [s.strip().lower() for s in services.split(",")]
157
- service_list = [(key, SUPPORTED_SERVICES_MAP.get(key, key)) for key in service_keys]
158
- set_custom_service_list(service_list)
159
- for tool in common_api_tools.tools:
161
+ if code_deploy:
162
+ # Code deploy mode: only load 6 specific tools
163
+ code_deploy_tools = {
164
+ 'OOS_CodeDeploy',
165
+ 'OOS_GetDeployStatus',
166
+ 'OOS_GetLastDeploymentInfo',
167
+ 'ECS_DescribeInstances',
168
+ 'LOCAL_ListDirectory',
169
+ 'LOCAL_RunShellScript',
170
+ 'LOCAL_AnalyzeDeployStack'
171
+ }
172
+
173
+ # Load from application_management_tools
174
+ for tool in application_management_tools.tools:
175
+ if tool.__name__ in code_deploy_tools:
176
+ mcp.tool(tool)
177
+
178
+ # Load from local_tools
179
+ for tool in local_tools.tools:
180
+ if tool.__name__ in code_deploy_tools:
181
+ mcp.tool(tool)
182
+ else:
183
+ # Normal mode: load all tools
184
+ if services:
185
+ service_keys = [s.strip().lower() for s in services.split(",")]
186
+ service_list = [(key, SUPPORTED_SERVICES_MAP.get(key, key)) for key in service_keys]
187
+ set_custom_service_list(service_list)
188
+ for tool in common_api_tools.tools:
189
+ mcp.tool(tool)
190
+ for tool in oos_tools.tools:
191
+ mcp.tool(tool)
192
+ for tool in application_management_tools.tools:
193
+ mcp.tool(tool)
194
+ for tool in cms_tools.tools:
195
+ mcp.tool(tool)
196
+ for tool in oss_tools.tools:
197
+ mcp.tool(tool)
198
+ api_tools.create_api_tools(mcp, config)
199
+ for tool in local_tools.tools:
160
200
  mcp.tool(tool)
161
- for tool in oos_tools.tools:
162
- mcp.tool(tool)
163
- for tool in application_management_tools.tools:
164
- mcp.tool(tool)
165
- for tool in cms_tools.tools:
166
- mcp.tool(tool)
167
- for tool in oss_tools.tools:
168
- mcp.tool(tool)
169
- api_tools.create_api_tools(mcp, config)
170
- for tool in local_tools.tools:
171
- mcp.tool(tool)
172
201
 
173
202
  # Initialize and run the server
174
203
  logger.debug(f'mcp server is running on {transport} mode.')
@@ -1,4 +1,7 @@
1
1
  import os
2
+ import time
3
+
4
+ from Tea.exceptions import UnretryableException
2
5
  from mcp.server.fastmcp import FastMCP, Context
3
6
  from pydantic import Field
4
7
  import logging
@@ -90,9 +93,9 @@ def create_client(service: str, region_id: str) -> OpenApiClient:
90
93
 
91
94
  # JSON array parameter of type String
92
95
  ECS_LIST_PARAMETERS = {
93
- 'HpcClusterIds', 'DedicatedHostClusterIds', 'DedicatedHostIds',
94
- 'InstanceIds', 'DeploymentSetIds', 'KeyPairNames', 'SecurityGroupIds',
95
- 'diskIds', 'repeatWeekdays', 'timePoints', 'DiskIds', 'SnapshotLinkIds',
96
+ 'HpcClusterIds', 'DedicatedHostClusterIds', 'DedicatedHostIds',
97
+ 'InstanceIds', 'DeploymentSetIds', 'KeyPairNames', 'SecurityGroupIds',
98
+ 'diskIds', 'repeatWeekdays', 'timePoints', 'DiskIds', 'SnapshotLinkIds',
96
99
  'EipAddresses', 'PublicIpAddresses', 'PrivateIpAddresses'
97
100
  }
98
101
 
@@ -109,7 +112,7 @@ def _tools_api_call(service: str, api: str, parameters: dict, ctx: Context):
109
112
  method = 'POST' if api_meta.get('methods', ['post'])[0] == 'post' else 'GET'
110
113
  path = api_meta.get('path', '/')
111
114
  style = ApiMetaClient.get_service_style(service)
112
-
115
+
113
116
  # Handling special parameter formats
114
117
  processed_parameters = parameters.copy()
115
118
  processed_parameters = {k: v for k, v in processed_parameters.items() if v is not None}
@@ -117,7 +120,7 @@ def _tools_api_call(service: str, api: str, parameters: dict, ctx: Context):
117
120
  for param_name, param_value in parameters.items():
118
121
  if param_name in ECS_LIST_PARAMETERS and isinstance(param_value, list):
119
122
  processed_parameters[param_name] = json.dumps(param_value)
120
-
123
+
121
124
  req = open_api_models.OpenApiRequest(
122
125
  query=OpenApiUtilClient.query(processed_parameters)
123
126
  )
@@ -135,9 +138,34 @@ def _tools_api_call(service: str, api: str, parameters: dict, ctx: Context):
135
138
  logger.info(f'Call API Request: Service: {service} API: {api} Method: {method} Parameters: {processed_parameters}')
136
139
  client = create_client(service, processed_parameters.get('RegionId', 'cn-hangzhou'))
137
140
  runtime = util_models.RuntimeOptions()
138
- resp = client.call_api(params, req, runtime)
139
- logger.info(f'Call API Response: {resp}')
140
- return resp
141
+
142
+ max_retries = 3
143
+ last_exception = None
144
+
145
+ for attempt in range(max_retries):
146
+ try:
147
+ resp = client.call_api(params, req, runtime)
148
+ logger.info(f'Call API Response: {resp}')
149
+ return resp
150
+ except UnretryableException as e:
151
+ last_exception = e
152
+ error_msg = str(e)
153
+ # 检查错误消息是否包含 [Errno 9] Bad file descriptor
154
+ has_bad_fd = '[Errno 9] Bad file descriptor' in error_msg
155
+
156
+ if has_bad_fd and attempt < max_retries - 1:
157
+ wait_time = (attempt + 1) * 1 # 递增等待时间:1秒、2秒
158
+ logger.warning(f'[_tools_api_call] UnretryableException with [Errno 9] Bad file descriptor (attempt {attempt + 1}/{max_retries}), retrying after {wait_time}s: {e}')
159
+ time.sleep(wait_time)
160
+ else:
161
+ # 如果不是可重试的错误,或者已经重试了3次,直接抛出异常
162
+ logger.error(f'Call API Error: {e}')
163
+ raise e
164
+
165
+ # 如果所有重试都失败了,抛出最后一次的异常
166
+ if last_exception:
167
+ logger.error(f'[_tools_api_call] All retries failed, raising last exception: {last_exception}')
168
+ raise last_exception
141
169
 
142
170
 
143
171
  def _create_parameter_schema(fields: dict):
@@ -5,7 +5,7 @@ from alibaba_cloud_ops_mcp_server.tools.api_tools import _tools_api_call
5
5
  from pathlib import Path
6
6
 
7
7
  from pydantic import Field
8
- from typing import Optional, Tuple
8
+ from typing import Optional, Tuple, List
9
9
  import json
10
10
  import time
11
11
  from alibabacloud_oos20190601.client import Client as oos20190601Client
@@ -78,7 +78,7 @@ def OOS_CodeDeploy(
78
78
 
79
79
  ):
80
80
  """
81
- 通过应用管理 API 部署应用到 ECS 实例。
81
+ 部署应用到阿里云ECS实例。
82
82
 
83
83
  完整部署流程(在调用此工具之前):
84
84
 
@@ -379,6 +379,30 @@ def OOS_GetDeployStatus(
379
379
  return response
380
380
 
381
381
 
382
+ @_append_tool
383
+ def ECS_DescribeInstances(
384
+ instance_ids: List[str] = Field(description='AlibabaCloud ECS instance ID List (required)'),
385
+ region_id: str = Field(description='AlibabaCloud region ID', default='cn-hangzhou'),
386
+ ):
387
+ """
388
+ 查询指定ECS实例的详细信息。此工具要求必须提供实例ID列表,避免随意查询所有实例。
389
+ 注意:此工具仅用于查询用户明确指定的实例信息,不允许用于扫描或枚举所有实例。
390
+ """
391
+ logger.info(f"[ECS_DescribeInstances] Input parameters: region_id={region_id}, instance_ids={instance_ids}")
392
+
393
+ if not instance_ids:
394
+ raise ValueError("instance_ids is required and cannot be empty")
395
+
396
+ describe_instances_request = ecs_20140526_models.DescribeInstancesRequest(
397
+ region_id=region_id,
398
+ instance_ids=json.dumps(instance_ids)
399
+ )
400
+
401
+ response = _describe_instances_with_retry(region_id, describe_instances_request)
402
+ logger.info(f"[ECS_DescribeInstances] Response: {json.dumps(str(response), ensure_ascii=False)}")
403
+ return response
404
+
405
+
382
406
  def _handle_new_application_group(client, name, application_group_name, deploy_region_id,
383
407
  region_id_oss, bucket_name, object_name, version_id,
384
408
  is_internal_oss, port, instance_ids, application_start,
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alibaba-cloud-ops-mcp-server
3
- Version: 0.9.12
3
+ Version: 0.9.14
4
4
  Summary: A MCP server for Alibaba Cloud
5
5
  Author-email: Zheng Dayu <dayu.zdy@alibaba-inc.com>, Zhao Shuaibo <zhaoshuaibo.zsb@alibaba-inc.com>
6
6
  License-File: LICENSE
7
7
  Requires-Python: >=3.10
8
8
  Requires-Dist: alibabacloud-cms20190101>=3.1.4
9
- Requires-Dist: alibabacloud-credentials-api==1.0.1
10
9
  Requires-Dist: alibabacloud-credentials>=1.0.3
11
10
  Requires-Dist: alibabacloud-ecs20140526>=6.1.0
12
11
  Requires-Dist: alibabacloud-oos20190601>=3.5.0
@@ -1,7 +1,7 @@
1
1
  alibaba_cloud_ops_mcp_server/__init__.py,sha256=BaluUNyRz8Qw-X7Y0ywDezwbkqiSvWlSYn2452XeGcA,213
2
2
  alibaba_cloud_ops_mcp_server/__main__.py,sha256=Q40p2HtWGvxj1JLvS7dn95NLzDhJNQ6JAgLLyCb4Y50,63
3
3
  alibaba_cloud_ops_mcp_server/config.py,sha256=PizctjXsQUWoMWBY1dFjNffVlZr9K6hNvqA4DpayR_o,513
4
- alibaba_cloud_ops_mcp_server/server.py,sha256=C3vb1VlVo2P_yJ1LjWiRMI8FAMkujUdD6j2NmB36kWs,8005
4
+ alibaba_cloud_ops_mcp_server/server.py,sha256=l-a53wmZPSilVq6TL9UHLw4LboYSSFJhNtEfDW2y-e4,9138
5
5
  alibaba_cloud_ops_mcp_server/settings.py,sha256=R1jvMtgErWn_1MZ2Gq3xzBZeMtkGpSHvVutInh0Ix4s,167
6
6
  alibaba_cloud_ops_mcp_server/alibabacloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  alibaba_cloud_ops_mcp_server/alibabacloud/api_meta_client.py,sha256=t2TSc0Gzcy_uEcaCgiHHuLoMiEGu3-NCtYmwYjyPWsY,7973
@@ -10,15 +10,15 @@ alibaba_cloud_ops_mcp_server/alibabacloud/utils.py,sha256=J3fywpnqMvIX19Fw87sKlK
10
10
  alibaba_cloud_ops_mcp_server/alibabacloud/static/PROMPT_UNDERSTANDING.md,sha256=QPubudP1bwDbWu0Js6MYb4cJd1B2zM_JGp53twYv5yc,3611
11
11
  alibaba_cloud_ops_mcp_server/alibabacloud/static/__init__.py,sha256=wJrYamaIb7e_kA4ILZpdP1f1TUUTXMGqEhA4IbSZ2Ts,230
12
12
  alibaba_cloud_ops_mcp_server/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
- alibaba_cloud_ops_mcp_server/tools/api_tools.py,sha256=nEtrjp-hFYJs47rFreXJoQ25OSdAUDODSv8GqBtP54Q,9687
14
- alibaba_cloud_ops_mcp_server/tools/application_management_tools.py,sha256=Y-YidjZ5wwNRE_FMb6_bD7WDav4XjsMa3fbAIusrPRc,34284
13
+ alibaba_cloud_ops_mcp_server/tools/api_tools.py,sha256=GFjummXzLDiPr8QQ_2LYmblhUXRxKw1E6Z1ZazmISSA,10910
14
+ alibaba_cloud_ops_mcp_server/tools/application_management_tools.py,sha256=Bivn1UXBzWcdJj3EWzO4EpXiGAdVn18dZJVxVe1RpvI,35363
15
15
  alibaba_cloud_ops_mcp_server/tools/cms_tools.py,sha256=BmPTiP8wu9DsEHBQsvR7JH9nFkcKMTBuNuafFqSfVxU,4308
16
16
  alibaba_cloud_ops_mcp_server/tools/common_api_tools.py,sha256=ccQAWqS1I9F-fdOdjLcXN-dIhNqSbZV8T5ODuGXlfXM,2711
17
17
  alibaba_cloud_ops_mcp_server/tools/local_tools.py,sha256=Sl7Vl2mVQMLyMIZQDLoE-xVF0vNz_haMEspyYPDe6Sg,13133
18
18
  alibaba_cloud_ops_mcp_server/tools/oos_tools.py,sha256=cPEl05Y0rlNvCeO2SF46Y7Ewky4LXZ8__sD0_JCi8ek,13569
19
19
  alibaba_cloud_ops_mcp_server/tools/oss_tools.py,sha256=6yKo1FqQN3n9I-eDUW8MrnIZTHthy-worKc8XIsn-Nw,7427
20
- alibaba_cloud_ops_mcp_server-0.9.12.dist-info/METADATA,sha256=fdcTjd-aehrJyuNJvHrc9Owb90cr7O7jlNCS3BNMqHU,8845
21
- alibaba_cloud_ops_mcp_server-0.9.12.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
22
- alibaba_cloud_ops_mcp_server-0.9.12.dist-info/entry_points.txt,sha256=ESGAWXKEp184forhs7VzTD4P1AUdZz6vCW6hRUKITGw,83
23
- alibaba_cloud_ops_mcp_server-0.9.12.dist-info/licenses/LICENSE,sha256=gQgVkp2ttRCjodiPpXZZR-d7JnrYIYNiHk1YDUYgpa4,11331
24
- alibaba_cloud_ops_mcp_server-0.9.12.dist-info/RECORD,,
20
+ alibaba_cloud_ops_mcp_server-0.9.14.dist-info/METADATA,sha256=EsGiCnz8252l848ovAPAsNXNjCTOJGbRLTg1cO0wjLI,8794
21
+ alibaba_cloud_ops_mcp_server-0.9.14.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
22
+ alibaba_cloud_ops_mcp_server-0.9.14.dist-info/entry_points.txt,sha256=ESGAWXKEp184forhs7VzTD4P1AUdZz6vCW6hRUKITGw,83
23
+ alibaba_cloud_ops_mcp_server-0.9.14.dist-info/licenses/LICENSE,sha256=gQgVkp2ttRCjodiPpXZZR-d7JnrYIYNiHk1YDUYgpa4,11331
24
+ alibaba_cloud_ops_mcp_server-0.9.14.dist-info/RECORD,,