alibaba-cloud-ops-mcp-server 0.9.24__py3-none-any.whl → 0.9.26__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.
@@ -1,4 +1,7 @@
1
1
  import sys
2
+ import copy
3
+ import json
4
+ import ast
2
5
 
3
6
  from fastmcp import FastMCP
4
7
  import click
@@ -43,6 +46,97 @@ SUPPORTED_SERVICES_MAP = {
43
46
  }
44
47
 
45
48
 
49
+ def _register_tools_with_filter(mcp: FastMCP, visible_tools_set: set, visible_tools_original: dict, services: str, extra_config: str):
50
+ """
51
+ Register tools based on visible_tools whitelist (case-insensitive).
52
+
53
+ Args:
54
+ mcp: FastMCP instance
55
+ visible_tools_set: Set of allowed tool names (lowercase for case-insensitive matching)
56
+ visible_tools_original: Dict mapping lowercase names to original names
57
+ services: Services parameter for common_api_tools
58
+ extra_config: Extra config parameter
59
+ """
60
+ registered_tools = set()
61
+
62
+ # 1. Register common_api_tools if services is specified
63
+ if services:
64
+ service_keys = [s.strip().lower() for s in services.split(",")]
65
+ service_list = [(key, SUPPORTED_SERVICES_MAP.get(key, key)) for key in service_keys]
66
+ set_custom_service_list(service_list)
67
+ for tool in common_api_tools.tools:
68
+ if tool.__name__.lower() in visible_tools_set:
69
+ mcp.tool(tool)
70
+ registered_tools.add(tool.__name__.lower())
71
+
72
+ # 2. Register static tools from all modules
73
+ static_tool_modules = [
74
+ oos_tools,
75
+ application_management_tools,
76
+ cms_tools,
77
+ oss_tools,
78
+ local_tools
79
+ ]
80
+
81
+ for tool_module in static_tool_modules:
82
+ for tool in tool_module.tools:
83
+ if tool.__name__.lower() in visible_tools_set:
84
+ mcp.tool(tool)
85
+ registered_tools.add(tool.__name__.lower())
86
+
87
+ # 3. Handle dynamic API tools
88
+ # Parse tool names in visible_tools that follow SERVICE_API format
89
+ # Use original names to preserve API case (important for Alibaba Cloud APIs)
90
+ dynamic_tools_config = {}
91
+
92
+ for tool_name_lower in visible_tools_set:
93
+ if '_' in tool_name_lower and tool_name_lower not in registered_tools:
94
+ # Get original name to preserve API case
95
+ original_name = visible_tools_original.get(tool_name_lower, tool_name_lower)
96
+ parts = original_name.split('_', 1)
97
+ if len(parts) == 2:
98
+ service_code = parts[0].lower()
99
+ api_name = parts[1] # Preserve original case
100
+ if service_code not in dynamic_tools_config:
101
+ dynamic_tools_config[service_code] = []
102
+ if api_name not in dynamic_tools_config[service_code]:
103
+ dynamic_tools_config[service_code].append(api_name)
104
+
105
+ # 4. Merge with extra_config (only tools in visible_tools whitelist)
106
+ if extra_config:
107
+ try:
108
+ try:
109
+ extra = json.loads(extra_config)
110
+ except json.JSONDecodeError:
111
+ extra = ast.literal_eval(extra_config)
112
+
113
+ for service_code, apis in extra.items():
114
+ for api in apis:
115
+ tool_name_lower = f"{service_code.lower()}_{api.lower()}"
116
+ if tool_name_lower in visible_tools_set:
117
+ if service_code not in dynamic_tools_config:
118
+ dynamic_tools_config[service_code] = []
119
+ if api not in dynamic_tools_config[service_code]:
120
+ dynamic_tools_config[service_code].append(api)
121
+ logger.info(f'Merged extra config with visible tools filter: {dynamic_tools_config}')
122
+ except Exception as e:
123
+ logger.error(f'Failed to parse extra-config: {e}')
124
+
125
+ # 5. Create dynamic API tools
126
+ if dynamic_tools_config:
127
+ api_tools.create_api_tools(mcp, dynamic_tools_config)
128
+ for service_code, apis in dynamic_tools_config.items():
129
+ for api in apis:
130
+ registered_tools.add(f"{service_code.lower()}_{api.lower()}")
131
+
132
+ # 6. Log results
133
+ unregistered_tools = visible_tools_set - registered_tools
134
+ if unregistered_tools:
135
+ logger.warning(f"The following tools were not found and not registered: {unregistered_tools}")
136
+
137
+ logger.info(f"Visible tools mode: registered {len(registered_tools)} tools: {registered_tools}")
138
+
139
+
46
140
  @click.command()
47
141
  @click.option(
48
142
  "--transport",
@@ -86,7 +180,19 @@ SUPPORTED_SERVICES_MAP = {
86
180
  default=False,
87
181
  help="Enable code deploy mode, only load 6 specific tools: OOS_CodeDeploy, OOS_GetDeployStatus, OOS_GetLastDeploymentInfo, LOCAL_ListDirectory, LOCAL_RunShellScript, LOCAL_AnalyzeDeployStack",
88
182
  )
89
- def main(transport: str, port: int, host: str, services: str, headers_credential_only: bool, env: str, code_deploy: bool):
183
+ @click.option(
184
+ "--extra-config",
185
+ type=str,
186
+ default=None,
187
+ help="Add extra services and APIs to config, e.g., \"{'sls': ['GetProject', 'ListProject'], 'ecs': ['StartInstance']}\"",
188
+ )
189
+ @click.option(
190
+ "--visible-tools",
191
+ type=str,
192
+ default=None,
193
+ help="Comma-separated list of tool names to make visible (whitelist mode). Only these tools will be registered when specified, e.g., 'OOS_RunCommand,ECS_DescribeInstances,LOCAL_ListDirectory'",
194
+ )
195
+ def main(transport: str, port: int, host: str, services: str, headers_credential_only: bool, env: str, code_deploy: bool, extra_config: str, visible_tools: str):
90
196
  _setup_logging()
91
197
  # Create an MCP server
92
198
  mcp = FastMCP(
@@ -158,6 +264,12 @@ def main(transport: str, port: int, host: str, services: str, headers_credential
158
264
  settings.headers_credential_only = headers_credential_only
159
265
  if env:
160
266
  settings.env = env
267
+
268
+ # Handle mutual exclusivity between code_deploy and visible_tools
269
+ if code_deploy and visible_tools:
270
+ logger.warning("--code-deploy and --visible-tools are mutually exclusive. Using --code-deploy mode.")
271
+ visible_tools = None
272
+
161
273
  if code_deploy:
162
274
  # Code deploy mode: only load 6 specific tools
163
275
  code_deploy_tools = {
@@ -179,7 +291,21 @@ def main(transport: str, port: int, host: str, services: str, headers_credential
179
291
  for tool in local_tools.tools:
180
292
  if tool.__name__ in code_deploy_tools:
181
293
  mcp.tool(tool)
182
- else:
294
+ elif visible_tools:
295
+ # Visible tools mode: only load tools in whitelist (case-insensitive)
296
+ # Build both lowercase set and original name mapping
297
+ visible_tools_list = [tool.strip() for tool in visible_tools.split(",") if tool.strip()]
298
+ visible_tools_set = set(t.lower() for t in visible_tools_list)
299
+ visible_tools_original = {t.lower(): t for t in visible_tools_list}
300
+ if visible_tools_set:
301
+ logger.info(f"Visible tools mode enabled (case-insensitive). Allowed tools: {visible_tools_set}")
302
+ _register_tools_with_filter(mcp, visible_tools_set, visible_tools_original, services, extra_config)
303
+ else:
304
+ logger.warning("--visible-tools is empty, falling back to normal mode.")
305
+ # Fall through to normal mode by setting a flag
306
+ visible_tools = None
307
+
308
+ if not code_deploy and not visible_tools:
183
309
  # Normal mode: load all tools
184
310
  if services:
185
311
  service_keys = [s.strip().lower() for s in services.split(",")]
@@ -197,7 +323,29 @@ def main(transport: str, port: int, host: str, services: str, headers_credential
197
323
  mcp.tool(tool)
198
324
  for tool in oss_tools.tools:
199
325
  mcp.tool(tool)
200
- api_tools.create_api_tools(mcp, config)
326
+ # Merge extra_config into the existing config
327
+ merged_config = copy.deepcopy(config)
328
+ if extra_config:
329
+ try:
330
+ # Try JSON first, then fallback to ast.literal_eval for single quotes
331
+ try:
332
+ extra = json.loads(extra_config)
333
+ except json.JSONDecodeError:
334
+ extra = ast.literal_eval(extra_config)
335
+ for service_code, apis in extra.items():
336
+ if service_code in merged_config:
337
+ # Add new APIs to existing service (avoid duplicates)
338
+ existing_apis = set(merged_config[service_code])
339
+ for api in apis:
340
+ if api not in existing_apis:
341
+ merged_config[service_code].append(api)
342
+ else:
343
+ # Add new service with its APIs
344
+ merged_config[service_code] = apis
345
+ logger.info(f'Merged extra config: {extra}')
346
+ except Exception as e:
347
+ logger.error(f'Failed to parse extra-config: {e}')
348
+ api_tools.create_api_tools(mcp, merged_config)
201
349
  for tool in local_tools.tools:
202
350
  mcp.tool(tool)
203
351
 
@@ -672,8 +672,27 @@ def _list_application_group_deployment(client, name, application_group_name, sta
672
672
  )
673
673
  response = client.get_application_group(get_application_group_request)
674
674
  status = response.body.application_group.status
675
- if status in status_list:
676
- return response.body
675
+ execution_id = response.body.application_group.execution_id
676
+ list_executions_response = None
677
+
678
+ if execution_id:
679
+ try:
680
+ list_executions_request = oos_20190601_models.ListExecutionsRequest(
681
+ execution_id=execution_id
682
+ )
683
+ list_executions_response = client.list_executions(list_executions_request)
684
+ except Exception as e:
685
+ logger.info(f"[_list_application_group_deployment] Error listing executions for application group {application_group_name}: {e}")
686
+ pass
687
+
688
+ resp = {
689
+ 'info': response.body,
690
+ 'status': status,
691
+ 'execution_id': execution_id,
692
+ 'deploy_execution_info': list_executions_response.body if list_executions_response else None
693
+ }
694
+
695
+ return resp
677
696
 
678
697
 
679
698
  def _check_application_exists(client: oos20190601Client, name: str) -> bool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alibaba-cloud-ops-mcp-server
3
- Version: 0.9.24
3
+ Version: 0.9.26
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
@@ -9,7 +9,10 @@ Requires-Dist: alibabacloud-cms20190101>=3.1.4
9
9
  Requires-Dist: alibabacloud-credentials>=1.0.3
10
10
  Requires-Dist: alibabacloud-ecs20140526>=6.1.0
11
11
  Requires-Dist: alibabacloud-oos20190601>=3.5.0
12
+ Requires-Dist: alibabacloud-openapi-util>=0.2.0
12
13
  Requires-Dist: alibabacloud-oss-v2>=1.2.0
14
+ Requires-Dist: alibabacloud-tea-openapi>=0.3.0
15
+ Requires-Dist: alibabacloud-tea-util>=0.3.0
13
16
  Requires-Dist: click>=8.1.8
14
17
  Requires-Dist: fastmcp==2.8.0
15
18
  Requires-Dist: pydantic==2.11.3
@@ -23,6 +26,17 @@ Description-Content-Type: text/markdown
23
26
 
24
27
  Alibaba Cloud Ops MCP Server is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) server that provides seamless integration with Alibaba Cloud APIs, enabling AI assistants to operate resources on Alibaba Cloud, supporting ECS, Cloud Monitor, OOS, OSS, VPC, RDS and other widely used cloud products. It also enables AI assistants to analyze, build, and deploy applications to Alibaba Cloud ECS instances.
25
28
 
29
+ ## MCP Maketplace Integration
30
+
31
+ * [Qoder](https://qoder.com) <a href="qoder://aicoding.aicoding-deeplink/mcp/add?name=alibaba-cloud-ops-mcp-server&config=JTdCJTIyY29tbWFuZCUyMiUzQSUyMnV2eCUyMiUyQyUyMmFyZ3MlMjIlM0ElNUIlMjJhbGliYWJhLWNsb3VkLW9wcy1tY3Atc2VydmVyJTQwbGF0ZXN0JTIyJTVEJTJDJTIyZW52JTIyJTNBJTdCJTIyQUxJQkFCQV9DTE9VRF9BQ0NFU1NfS0VZX0lEJTIyJTNBJTIyWW91ciUyMEFjY2VzcyUyMEtleSUyMElkJTIyJTJDJTIyQUxJQkFCQV9DTE9VRF9BQ0NFU1NfS0VZX1NFQ1JFVCUyMiUzQSUyMllvdXIlMjBBY2Nlc3MlMjBLZXklMjBTRUNSRVQlMjIlN0QlN0Q%3D"><img src="./image/qoder.svg" alt="Install MCP Server" height="20"></a>
32
+ * [Cursor](https://docs.cursor.com/tools) [![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=alibaba-cloud-ops-mcp-server&config=eyJ0aW1lb3V0Ijo2MDAsImNvbW1hbmQiOiJ1dnggYWxpYmFiYS1jbG91ZC1vcHMtbWNwLXNlcnZlckBsYXRlc3QiLCJlbnYiOnsiQUxJQkFCQV9DTE9VRF9BQ0NFU1NfS0VZX0lEIjoiWW91ciBBY2Nlc3MgS2V5IElkIiwiQUxJQkFCQV9DTE9VRF9BQ0NFU1NfS0VZX1NFQ1JFVCI6IllvdXIgQWNjZXNzIEtleSBTZWNyZXQifX0%3D)
33
+ * [Cline](https://cline.bot/mcp-marketplace)
34
+ * [ModelScope](https://www.modelscope.cn/mcp/servers/@aliyun/alibaba-cloud-ops-mcp-server?lang=en_US)
35
+ * [Lingma](https://lingma.aliyun.com/)
36
+ * [Smithery AI](https://smithery.ai/server/@aliyun/alibaba-cloud-ops-mcp-server)
37
+ * [FC-Function AI](https://cap.console.aliyun.com/template-detail?template=237)
38
+ * [Alibaba Cloud Model Studio](https://bailian.console.aliyun.com/?tab=mcp#/mcp-market/detail/alibaba-cloud-ops)
39
+
26
40
  ## Features
27
41
 
28
42
  - **ECS Management**: Create, start, stop, reboot, delete instances, run commands, view instances, regions, zones, images, security groups, and more
@@ -70,17 +84,6 @@ To use `alibaba-cloud-ops-mcp-server` MCP Server with any other MCP Client, you
70
84
 
71
85
  [For detailed parameter description, see MCP startup parameter document](./README_mcp_args.md)
72
86
 
73
- ## MCP Maketplace Integration
74
-
75
- * [Qoder](https://qoder.com) <a href="qoder://aicoding.aicoding-deeplink/mcp/add?name=alibaba-cloud-ops-mcp-server&config=JTdCJTIyY29tbWFuZCUyMiUzQSUyMnV2eCUyMiUyQyUyMmFyZ3MlMjIlM0ElNUIlMjJhbGliYWJhLWNsb3VkLW9wcy1tY3Atc2VydmVyJTQwbGF0ZXN0JTIyJTVEJTJDJTIyZW52JTIyJTNBJTdCJTIyQUxJQkFCQV9DTE9VRF9BQ0NFU1NfS0VZX0lEJTIyJTNBJTIyWW91ciUyMEFjY2VzcyUyMEtleSUyMElkJTIyJTJDJTIyQUxJQkFCQV9DTE9VRF9BQ0NFU1NfS0VZX1NFQ1JFVCUyMiUzQSUyMllvdXIlMjBBY2Nlc3MlMjBLZXklMjBTRUNSRVQlMjIlN0QlN0Q%3D"><img src="./image/qoder.svg" alt="Install MCP Server" height="20"></a>
76
- * [Cursor](https://docs.cursor.com/tools) [![Install MCP Server](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=alibaba-cloud-ops-mcp-server&config=eyJ0aW1lb3V0Ijo2MDAsImNvbW1hbmQiOiJ1dnggYWxpYmFiYS1jbG91ZC1vcHMtbWNwLXNlcnZlckBsYXRlc3QiLCJlbnYiOnsiQUxJQkFCQV9DTE9VRF9BQ0NFU1NfS0VZX0lEIjoiWW91ciBBY2Nlc3MgS2V5IElkIiwiQUxJQkFCQV9DTE9VRF9BQ0NFU1NfS0VZX1NFQ1JFVCI6IllvdXIgQWNjZXNzIEtleSBTZWNyZXQifX0%3D)
77
- * [Cline](https://cline.bot/mcp-marketplace)
78
- * [ModelScope](https://www.modelscope.cn/mcp/servers/@aliyun/alibaba-cloud-ops-mcp-server?lang=en_US)
79
- * [Lingma](https://lingma.aliyun.com/)
80
- * [Smithery AI](https://smithery.ai/server/@aliyun/alibaba-cloud-ops-mcp-server)
81
- * [FC-Function AI](https://cap.console.aliyun.com/template-detail?template=237)
82
- * [Alibaba Cloud Model Studio](https://bailian.console.aliyun.com/?tab=mcp#/mcp-market/detail/alibaba-cloud-ops)
83
-
84
87
  ## Know More
85
88
 
86
89
  * [Alibaba Cloud Ops MCP Server is ready to use out of the box!!](https://developer.aliyun.com/article/1661348)
@@ -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=nXZVhNnvPk5_VqGfTEmlFjv6lG3VYAxnTfzeF7zisog,9255
4
+ alibaba_cloud_ops_mcp_server/server.py,sha256=mt3LtII8CObvUwsC62ZlJjT0LpsGxz_fM2ZFg6GSuOk,16159
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
@@ -11,14 +11,14 @@ alibaba_cloud_ops_mcp_server/alibabacloud/static/PROMPT_UNDERSTANDING.md,sha256=
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
13
  alibaba_cloud_ops_mcp_server/tools/api_tools.py,sha256=n7FLDAlnTSIk38iQqT1ABwAskIyswO_tBGTm34SPMpg,10632
14
- alibaba_cloud_ops_mcp_server/tools/application_management_tools.py,sha256=WX8lJMEEFSgMWx4hDL_J5rdAw_BWBFEQKr2dg7e4iS4,35582
14
+ alibaba_cloud_ops_mcp_server/tools/application_management_tools.py,sha256=fzuNzAfqsQpfOXrwNhIDBXQM_bcN6MTs4Rw7_4MD8Io,36305
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.24.dist-info/METADATA,sha256=dBKDUk4-cVEON2AhxisR7zPmDOq8ne_mV5S1FNdcY1A,8794
21
- alibaba_cloud_ops_mcp_server-0.9.24.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
22
- alibaba_cloud_ops_mcp_server-0.9.24.dist-info/entry_points.txt,sha256=ESGAWXKEp184forhs7VzTD4P1AUdZz6vCW6hRUKITGw,83
23
- alibaba_cloud_ops_mcp_server-0.9.24.dist-info/licenses/LICENSE,sha256=gQgVkp2ttRCjodiPpXZZR-d7JnrYIYNiHk1YDUYgpa4,11331
24
- alibaba_cloud_ops_mcp_server-0.9.24.dist-info/RECORD,,
20
+ alibaba_cloud_ops_mcp_server-0.9.26.dist-info/METADATA,sha256=xiUpt3I8ugJBmzKxElO1_jRGPZso86fTYXL6TbqfnHg,8933
21
+ alibaba_cloud_ops_mcp_server-0.9.26.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
22
+ alibaba_cloud_ops_mcp_server-0.9.26.dist-info/entry_points.txt,sha256=ESGAWXKEp184forhs7VzTD4P1AUdZz6vCW6hRUKITGw,83
23
+ alibaba_cloud_ops_mcp_server-0.9.26.dist-info/licenses/LICENSE,sha256=gQgVkp2ttRCjodiPpXZZR-d7JnrYIYNiHk1YDUYgpa4,11331
24
+ alibaba_cloud_ops_mcp_server-0.9.26.dist-info/RECORD,,