alibaba-cloud-ops-mcp-server 0.9.13__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.
- alibaba_cloud_ops_mcp_server/server.py +46 -17
- alibaba_cloud_ops_mcp_server/tools/api_tools.py +36 -8
- alibaba_cloud_ops_mcp_server/tools/application_management_tools.py +26 -2
- {alibaba_cloud_ops_mcp_server-0.9.13.dist-info → alibaba_cloud_ops_mcp_server-0.9.14.dist-info}/METADATA +1 -1
- {alibaba_cloud_ops_mcp_server-0.9.13.dist-info → alibaba_cloud_ops_mcp_server-0.9.14.dist-info}/RECORD +8 -8
- {alibaba_cloud_ops_mcp_server-0.9.13.dist-info → alibaba_cloud_ops_mcp_server-0.9.14.dist-info}/WHEEL +0 -0
- {alibaba_cloud_ops_mcp_server-0.9.13.dist-info → alibaba_cloud_ops_mcp_server-0.9.14.dist-info}/entry_points.txt +0 -0
- {alibaba_cloud_ops_mcp_server-0.9.13.dist-info → alibaba_cloud_ops_mcp_server-0.9.14.dist-info}/licenses/LICENSE +0 -0
|
@@ -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
|
-
|
|
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
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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
|
-
|
|
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,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=
|
|
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=
|
|
14
|
-
alibaba_cloud_ops_mcp_server/tools/application_management_tools.py,sha256=
|
|
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.
|
|
21
|
-
alibaba_cloud_ops_mcp_server-0.9.
|
|
22
|
-
alibaba_cloud_ops_mcp_server-0.9.
|
|
23
|
-
alibaba_cloud_ops_mcp_server-0.9.
|
|
24
|
-
alibaba_cloud_ops_mcp_server-0.9.
|
|
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,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|