alibaba-cloud-ops-mcp-server 0.9.9__py3-none-any.whl → 0.9.12__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.
@@ -0,0 +1,323 @@
1
+ import os
2
+ import subprocess
3
+ import json
4
+ import re
5
+ import logging
6
+ from pathlib import Path
7
+ from typing import Optional, Dict, List, Any
8
+ from pydantic import Field
9
+
10
+ logger = logging.getLogger(__name__)
11
+
12
+
13
+ class ToolsList:
14
+ """A tool list that can be used as both a list and a decorator"""
15
+ def __init__(self):
16
+ self._list = []
17
+
18
+ def append(self, func):
19
+ """Decorator: Add function to the list and return the function itself"""
20
+ self._list.append(func)
21
+ return func
22
+
23
+ def __iter__(self):
24
+ return iter(self._list)
25
+
26
+ def __len__(self):
27
+ return len(self._list)
28
+
29
+
30
+ tools = ToolsList()
31
+
32
+
33
+ def _validate_path(path: str) -> Path:
34
+ """Validate and normalize path to prevent path traversal attacks"""
35
+ try:
36
+ # Convert to absolute path
37
+ abs_path = Path(path).resolve()
38
+ # Ensure path exists and is a file or directory
39
+ if not abs_path.exists():
40
+ raise FileNotFoundError(f"Path does not exist: {path}")
41
+ return abs_path
42
+ except (OSError, ValueError) as e:
43
+ raise ValueError(f"Invalid path: {path}") from e
44
+
45
+
46
+ @tools.append
47
+ def LOCAL_ListDirectory(
48
+ path: str = Field(description="Directory path to list (absolute or relative path)"),
49
+ recursive: bool = Field(description="Whether to recursively list subdirectories", default=False)
50
+ ):
51
+ """列出指定目录中的文件和子目录。返回包含名称、类型和大小等信息的目录和文件列表。"""
52
+ logger.info(f"[ListDirectory] Input parameters: path={path}, recursive={recursive}")
53
+ try:
54
+ dir_path = _validate_path(path)
55
+
56
+ # Ensure it's a directory, not a file
57
+ if not dir_path.is_dir():
58
+ raise ValueError(f"Path is not a directory: {path}")
59
+
60
+ results = []
61
+
62
+ if recursive:
63
+ # Recursively list
64
+ for item in dir_path.rglob('*'):
65
+ try:
66
+ item_stat = item.stat()
67
+ results.append({
68
+ "name": item.name,
69
+ "path": str(item),
70
+ "type": "directory" if item.is_dir() else "file",
71
+ "size": item_stat.st_size if item.is_file() else None,
72
+ "modified": item_stat.st_mtime
73
+ })
74
+ except (OSError, PermissionError):
75
+ # Skip inaccessible files/directories
76
+ continue
77
+ else:
78
+ # List only current directory
79
+ for item in dir_path.iterdir():
80
+ try:
81
+ item_stat = item.stat()
82
+ results.append({
83
+ "name": item.name,
84
+ "path": str(item),
85
+ "type": "directory" if item.is_dir() else "file",
86
+ "size": item_stat.st_size if item.is_file() else None,
87
+ "modified": item_stat.st_mtime
88
+ })
89
+ except (OSError, PermissionError):
90
+ # Skip inaccessible files/directories
91
+ continue
92
+
93
+ # Sort by name
94
+ results.sort(key=lambda x: x["name"])
95
+
96
+ response = {
97
+ "path": str(dir_path),
98
+ "items": results,
99
+ "count": len(results)
100
+ }
101
+ logger.info(f"[ListDirectory] Response: {json.dumps(response, ensure_ascii=False, default=str)}")
102
+ return response
103
+ except Exception as e:
104
+ raise ValueError(f"Failed to list directory: {str(e)}")
105
+
106
+
107
+ @tools.append
108
+ def LOCAL_RunShellScript(
109
+ script: str = Field(description="Shell script content or command to execute"),
110
+ working_directory: Optional[str] = Field(description="Working directory for command execution", default=None),
111
+ timeout: int = Field(description="Command execution timeout in seconds", default=300),
112
+ shell: bool = Field(description="Whether to use shell execution (True uses /bin/sh, False executes command directly)", default=True)
113
+ ):
114
+ """执行 shell 脚本或命令。返回命令输出、错误信息和退出代码。注意:执行任意命令可能存在安全风险,请谨慎使用。"""
115
+ logger.info(f"[RunShellScript] Input parameters: script={script}, working_directory={working_directory}, timeout={timeout}, shell={shell}")
116
+ try:
117
+ # Set working directory
118
+ cwd = None
119
+ if working_directory:
120
+ cwd = _validate_path(working_directory)
121
+ if not cwd.is_dir():
122
+ raise ValueError(f"Working directory is not a directory: {working_directory}")
123
+ cwd = str(cwd)
124
+
125
+ # Execute command
126
+ if shell:
127
+ # Execute using shell
128
+ process = subprocess.run(
129
+ script,
130
+ shell=True,
131
+ capture_output=True,
132
+ text=True,
133
+ timeout=timeout,
134
+ cwd=cwd,
135
+ executable='/bin/sh' if os.name != 'nt' else None
136
+ )
137
+ else:
138
+ # Execute directly (need to split command into list)
139
+ import shlex
140
+ cmd_list = shlex.split(script)
141
+ process = subprocess.run(
142
+ cmd_list,
143
+ shell=False,
144
+ capture_output=True,
145
+ text=True,
146
+ timeout=timeout,
147
+ cwd=cwd
148
+ )
149
+
150
+ response = {
151
+ "command": script,
152
+ "exit_code": process.returncode,
153
+ "stdout": process.stdout,
154
+ "stderr": process.stderr,
155
+ "success": process.returncode == 0
156
+ }
157
+ logger.info(f"[RunShellScript] Response: {json.dumps(response, ensure_ascii=False, default=str)}")
158
+ return response
159
+ except subprocess.TimeoutExpired:
160
+ raise ValueError(f"Command execution timeout (exceeded {timeout} seconds)")
161
+ except FileNotFoundError:
162
+ raise ValueError(f"Command or script not found: {script}")
163
+ except Exception as e:
164
+ raise ValueError(f"Failed to execute command: {str(e)}")
165
+
166
+
167
+ @tools.append
168
+ def LOCAL_AnalyzeDeployStack(
169
+ directory: str = Field(description="Directory path to analyze (absolute or relative path)")
170
+ ):
171
+ """识别项目部署方式和技术栈。支持识别 npm、Python、Java、Go、Docker 等部署方式。"""
172
+ logger.info(f"[AnalyzeDeployStack] Input parameters: directory={directory}")
173
+ try:
174
+ dir_path = _validate_path(directory)
175
+
176
+ if not dir_path.is_dir():
177
+ raise ValueError(f"路径不是目录: {directory}")
178
+
179
+ detection_results = {
180
+ "directory": str(dir_path),
181
+ "deployment_methods": [],
182
+ "package_managers": [],
183
+ "frameworks": [],
184
+ "runtime_versions": {},
185
+ "config_files": {},
186
+ "detected": False
187
+ }
188
+
189
+ # List of files to check
190
+ files_to_check = {
191
+ # Node.js / npm
192
+ "package.json": ("npm", "nodejs"),
193
+ "package-lock.json": ("npm", "nodejs"),
194
+ "yarn.lock": ("yarn", "nodejs"),
195
+ "pnpm-lock.yaml": ("pnpm", "nodejs"),
196
+ ".nvmrc": ("nodejs", None),
197
+
198
+ # Python
199
+ "requirements.txt": ("pip", "python"),
200
+ "Pipfile": ("pipenv", "python"),
201
+ "pyproject.toml": ("poetry", "python"),
202
+ "setup.py": ("setuptools", "python"),
203
+ "environment.yml": ("conda", "python"),
204
+ ".python-version": ("python", None),
205
+
206
+ # Java
207
+ "pom.xml": ("maven", "java"),
208
+ "build.gradle": ("gradle", "java"),
209
+ "build.gradle.kts": ("gradle", "java"),
210
+
211
+ # Go
212
+ "go.mod": ("go", "go"),
213
+ "go.sum": ("go", "go"),
214
+ "Gopkg.toml": ("dep", "go"),
215
+
216
+ # Rust
217
+ "Cargo.toml": ("cargo", "rust"),
218
+ "Cargo.lock": ("cargo", "rust"),
219
+
220
+ # PHP
221
+ "composer.json": ("composer", "php"),
222
+
223
+ # Ruby
224
+ "Gemfile": ("bundler", "ruby"),
225
+
226
+ # Docker
227
+ "Dockerfile": ("docker", "docker"),
228
+ "docker-compose.yml": ("docker-compose", "docker"),
229
+ "docker-compose.yaml": ("docker-compose", "docker"),
230
+ ".dockerignore": ("docker", "docker"),
231
+
232
+ # 其他
233
+ "Makefile": ("make", None),
234
+ "CMakeLists.txt": ("cmake", "cpp"),
235
+ }
236
+
237
+ # Check if files exist
238
+ for filename, (package_manager, framework) in files_to_check.items():
239
+ file_path = dir_path / filename
240
+ if file_path.exists():
241
+ if package_manager:
242
+ if package_manager not in detection_results["package_managers"]:
243
+ detection_results["package_managers"].append(package_manager)
244
+ if framework:
245
+ if framework not in detection_results["frameworks"]:
246
+ detection_results["frameworks"].append(framework)
247
+ detection_results["config_files"][filename] = str(file_path)
248
+
249
+ # Read key files to get more information
250
+ # Read package.json
251
+ package_json = dir_path / "package.json"
252
+ if package_json.exists():
253
+ try:
254
+ with open(package_json, 'r', encoding='utf-8') as f:
255
+ pkg_data = json.load(f)
256
+ if "engines" in pkg_data and "node" in pkg_data["engines"]:
257
+ detection_results["runtime_versions"]["node"] = pkg_data["engines"]["node"]
258
+ except Exception:
259
+ pass
260
+
261
+ # Read requirements.txt or pyproject.toml to get Python version information
262
+ if (dir_path / "requirements.txt").exists() or (dir_path / "pyproject.toml").exists():
263
+ # Try to read from .python-version
264
+ py_version_file = dir_path / ".python-version"
265
+ if py_version_file.exists():
266
+ try:
267
+ version = py_version_file.read_text().strip()
268
+ detection_results["runtime_versions"]["python"] = version
269
+ except Exception:
270
+ pass
271
+
272
+ # Read go.mod to get Go version
273
+ go_mod = dir_path / "go.mod"
274
+ if go_mod.exists():
275
+ try:
276
+ content = go_mod.read_text()
277
+ match = re.search(r'go\s+(\d+\.\d+)', content)
278
+ if match:
279
+ detection_results["runtime_versions"]["go"] = match.group(1)
280
+ except Exception:
281
+ pass
282
+
283
+ # Read Dockerfile to detect base image
284
+ dockerfile = dir_path / "Dockerfile"
285
+ if dockerfile.exists():
286
+ try:
287
+ content = dockerfile.read_text()
288
+ # Detect common base images
289
+ if "FROM node" in content or "FROM node:" in content:
290
+ match = re.search(r'FROM node:?(\S+)', content)
291
+ if match:
292
+ detection_results["runtime_versions"]["node_docker"] = match.group(1)
293
+ elif "FROM python" in content or "FROM python:" in content:
294
+ match = re.search(r'FROM python:?(\S+)', content)
295
+ if match:
296
+ detection_results["runtime_versions"]["python_docker"] = match.group(1)
297
+ except Exception:
298
+ pass
299
+
300
+ # Determine main deployment method
301
+ if detection_results["package_managers"] or detection_results["frameworks"]:
302
+ detection_results["detected"] = True
303
+ # Infer deployment method based on detected package managers
304
+ if "npm" in detection_results["package_managers"] or "yarn" in detection_results["package_managers"] or "pnpm" in detection_results["package_managers"]:
305
+ detection_results["deployment_methods"].append("npm")
306
+ if "pip" in detection_results["package_managers"] or "pipenv" in detection_results["package_managers"] or "poetry" in detection_results["package_managers"]:
307
+ detection_results["deployment_methods"].append("python")
308
+ if "maven" in detection_results["package_managers"] or "gradle" in detection_results["package_managers"]:
309
+ detection_results["deployment_methods"].append("java")
310
+ if "go" in detection_results["package_managers"]:
311
+ detection_results["deployment_methods"].append("go")
312
+ if "docker" in detection_results["package_managers"]:
313
+ detection_results["deployment_methods"].append("docker")
314
+
315
+ # If nothing detected, return unknown
316
+ if not detection_results["detected"]:
317
+ detection_results["deployment_methods"].append("unknown")
318
+
319
+ logger.info(f"[IdentifyDeploymentMethod] Response: {json.dumps(detection_results, ensure_ascii=False, default=str)}")
320
+ return detection_results
321
+ except Exception as e:
322
+ raise ValueError(f"Failed to identify deployment method: {str(e)}")
323
+
@@ -150,7 +150,12 @@ def OOS_RunInstances(
150
150
  SystemDiskPerformanceLevel: str = Field(description='The performance level of the ESSD used as the system disk. Valid values: PL0, PL1, PL2, PL3', default='PL1'),
151
151
  PrivateIpAddress: str = Field(description='The private IP address of the instance. For VPC type ECS instances, the private IP address must be selected from the available IP range of the VSwitch', default=''),
152
152
  SystemDiskAutoSnapshotPolicyId: str = Field(description='The ID of the automatic snapshot policy to apply to the system disk', default=''),
153
- DataDiskParameters: str = Field(description='Data disk configuration in JSON format. Example: [{"Size":"100","DiskName":"data-disk-1","Description":"","Category":"cloud_essd","PerformanceLevel":"PL1","AutoSnapshotPolicyId":""}]', default='')
153
+ DataDiskParameters: str = Field(description='Data disk configuration in JSON format. Example: [{"Size":"100","DiskName":"data-disk-1","Description":"","Category":"cloud_essd","PerformanceLevel":"PL1","AutoSnapshotPolicyId":""}]', default=''),
154
+ Tags: list = Field(description='The tag of an ECS instance, for example: [{"Key":"oos","Value":"test"}]', default=[]),
155
+ ResourceGroupId: str = Field(description='Resource group ID', default=''),
156
+ Description: str = Field(description='The description of the ECS instances', default=''),
157
+ HostName: str = Field(description='The host name of the ECS instance', default=''),
158
+ ZoneId: str = Field(description='The ID of the zone where the ECS instances are deployed', default=''),
154
159
  ):
155
160
  """批量创建ECS实例,适用于需要同时创建多台ECS实例的场景,例如应用部署和高可用性场景。"""
156
161
 
@@ -164,8 +169,7 @@ def OOS_RunInstances(
164
169
  'amount': Amount,
165
170
  'instanceName': InstanceName
166
171
  }
167
-
168
- # 添加系统盘相关参数
172
+
169
173
  if SystemDiskCategory:
170
174
  parameters['systemDiskCategory'] = SystemDiskCategory
171
175
  if SystemDiskSize:
@@ -180,17 +184,23 @@ def OOS_RunInstances(
180
184
  parameters['privateIpAddress'] = PrivateIpAddress
181
185
  if SystemDiskAutoSnapshotPolicyId:
182
186
  parameters['systemDiskAutoSnapshotPolicyId'] = SystemDiskAutoSnapshotPolicyId
183
-
184
- # 处理数据盘参数
187
+ if Tags:
188
+ parameters['tags'] = Tags
189
+ if ResourceGroupId:
190
+ parameters['resourceGroupId'] = ResourceGroupId
191
+ if Description:
192
+ parameters['description'] = Description
193
+ if HostName:
194
+ parameters['hostName'] = HostName
195
+ if ZoneId:
196
+ parameters['zoneId'] = ZoneId
197
+
185
198
  if DataDiskParameters:
186
199
  try:
187
- # 解析 JSON 字符串为列表
188
200
  data_disks = json.loads(DataDiskParameters) if isinstance(DataDiskParameters, str) else DataDiskParameters
189
201
  if isinstance(data_disks, list) and len(data_disks) > 0:
190
- # 将数据盘列表转换为 OOS 模板需要的格式
191
202
  parameters['dataDiskParameters'] = data_disks
192
203
  except (json.JSONDecodeError, TypeError) as e:
193
- # 如果解析失败,忽略数据盘参数
194
204
  pass
195
205
 
196
206
  return _start_execution_sync(region_id=RegionId, template_name='ACS-ECS-RunInstances', parameters=parameters)
@@ -1,19 +1,23 @@
1
- # oss_tools.py
2
1
  import os
2
+ import mimetypes
3
+ import logging
4
+ import json
3
5
  import alibabacloud_oss_v2 as oss
4
- from alibaba_cloud_ops_mcp_server.alibabacloud.utils import get_credentials_from_header
5
6
 
6
7
  from pydantic import Field
7
8
  from alibabacloud_oss_v2 import Credentials
8
9
  from alibabacloud_oss_v2.credentials import EnvironmentVariableCredentialsProvider
9
10
  from alibabacloud_credentials.client import Client as CredClient
10
11
 
11
-
12
12
  tools = []
13
13
 
14
14
 
15
+ logger = logging.getLogger(__name__)
16
+
17
+
15
18
  class CredentialsProvider(EnvironmentVariableCredentialsProvider):
16
19
  def __init__(self) -> None:
20
+ from alibaba_cloud_ops_mcp_server.alibabacloud.utils import get_credentials_from_header
17
21
  credentials = get_credentials_from_header()
18
22
  if credentials:
19
23
  access_key_id = credentials.get('AccessKeyId', None)
@@ -114,3 +118,64 @@ def OSS_DeleteBucket(
114
118
  client = create_client(region_id=RegionId)
115
119
  result = client.delete_bucket(oss.DeleteBucketRequest(bucket=BucketName))
116
120
  return result.__str__()
121
+
122
+
123
+
124
+ def OSS_PutObject(
125
+ BucketName: str = Field(description='AlibabaCloud OSS Bucket Name'),
126
+ ObjectKey: str = Field(description='AlibabaCloud OSS Object Key (file path/name in OSS)'),
127
+ FilePath: str = Field(description='Local file path to upload'),
128
+ RegionId: str = Field(description='AlibabaCloud region ID', default='cn-hangzhou'),
129
+ ContentType: str = Field(description='Content type of the object (e.g., text/plain, application/json). If not provided, will be inferred from file extension.', default=None)
130
+ ):
131
+ """上传本地文件到指定的OSS存储空间。"""
132
+ logger.info(f"[OSS_PutObject] Input parameters: BucketName={BucketName}, ObjectKey={ObjectKey}, "
133
+ f"FilePath={FilePath}, RegionId={RegionId}, ContentType={ContentType}")
134
+ if not BucketName:
135
+ raise ValueError("Bucket name is required")
136
+ if not ObjectKey:
137
+ raise ValueError("Object key is required")
138
+ if not FilePath:
139
+ raise ValueError("File path is required")
140
+
141
+ # Check if file exists
142
+ if not os.path.exists(FilePath):
143
+ raise FileNotFoundError(f"File not found: {FilePath}")
144
+
145
+ if not os.path.isfile(FilePath):
146
+ raise ValueError(f"Path is not a file: {FilePath}")
147
+
148
+ client = create_client(region_id=RegionId)
149
+
150
+ # Read file content in binary mode
151
+ with open(FilePath, 'rb') as f:
152
+ body = f.read()
153
+
154
+ # Infer content type from file extension if not provided
155
+ if not ContentType:
156
+ ContentType, _ = mimetypes.guess_type(FilePath)
157
+ if not ContentType:
158
+ ContentType = 'application/octet-stream' # Default to binary
159
+
160
+ # Prepare put object request
161
+ request = oss.PutObjectRequest(
162
+ bucket=BucketName,
163
+ key=ObjectKey,
164
+ body=body
165
+ )
166
+
167
+ # Set content type
168
+ request.content_type = ContentType
169
+
170
+ result = client.put_object(request)
171
+ version_id = result.version_id
172
+ response = {
173
+ 'status_code': result.status_code,
174
+ 'etag': result.etag if hasattr(result, 'etag') else None,
175
+ 'file_size': len(body),
176
+ 'content_type': ContentType,
177
+ 'version_id': version_id,
178
+ 'message': f'Successfully uploaded file {FilePath} as {ObjectKey} to bucket {BucketName}'
179
+ }
180
+ logger.info(f"[OSS_PutObject] Response: {json.dumps(response, ensure_ascii=False)}")
181
+ return response
@@ -1,14 +1,15 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alibaba-cloud-ops-mcp-server
3
- Version: 0.9.9
3
+ Version: 0.9.12
4
4
  Summary: A MCP server for Alibaba Cloud
5
- Author-email: Zheng Dayu <dayu.zdy@alibaba-inc.com>
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>=1.0.0
9
+ Requires-Dist: alibabacloud-credentials-api==1.0.1
10
+ Requires-Dist: alibabacloud-credentials>=1.0.3
10
11
  Requires-Dist: alibabacloud-ecs20140526>=6.1.0
11
- Requires-Dist: alibabacloud-oos20190601>=3.4.1
12
+ Requires-Dist: alibabacloud-oos20190601>=3.5.0
12
13
  Requires-Dist: alibabacloud-oss-v2>=1.1.0
13
14
  Requires-Dist: click>=8.1.8
14
15
  Requires-Dist: fastmcp==2.8.0
@@ -21,7 +22,19 @@ Description-Content-Type: text/markdown
21
22
 
22
23
  [中文版本](./README_zh.md)
23
24
 
24
- 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 operation resources on Alibaba Cloud, supporting ECS, Cloud Monitor, OOS and other widely used cloud products.
25
+ 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.
26
+
27
+ ## Features
28
+
29
+ - **ECS Management**: Create, start, stop, reboot, delete instances, run commands, view instances, regions, zones, images, security groups, and more
30
+ - **VPC Management**: View VPCs and VSwitches
31
+ - **RDS Management**: List, start, stop, and restart RDS instances
32
+ - **OSS Management**: List, create, delete buckets, and view objects
33
+ - **Cloud Monitor**: Get CPU usage, load average, memory usage, and disk usage metrics for ECS instances
34
+ - **Application Deployment**: Deploy applications to ECS instances with automatic application and application group management
35
+ - **Project Analysis**: Automatically identify project technology stack and deployment methods (npm, Python, Java, Go, Docker, etc.)
36
+ - **Local File Operations**: List directories, run shell scripts, and analyze project structures
37
+ - **Dynamic API Tools**: Support for Alibaba Cloud OpenAPI operations
25
38
 
26
39
  ## Prepare
27
40
 
@@ -60,8 +73,9 @@ To use `alibaba-cloud-ops-mcp-server` MCP Server with any other MCP Client, you
60
73
 
61
74
  ## MCP Maketplace Integration
62
75
 
63
- * [Cline](https://cline.bot/mcp-marketplace)
76
+ * [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>
64
77
  * [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)
78
+ * [Cline](https://cline.bot/mcp-marketplace)
65
79
  * [ModelScope](https://www.modelscope.cn/mcp/servers/@aliyun/alibaba-cloud-ops-mcp-server?lang=en_US)
66
80
  * [Lingma](https://lingma.aliyun.com/)
67
81
  * [Smithery AI](https://smithery.ai/server/@aliyun/alibaba-cloud-ops-mcp-server)
@@ -77,7 +91,7 @@ To use `alibaba-cloud-ops-mcp-server` MCP Server with any other MCP Client, you
77
91
 
78
92
  ## Tools
79
93
 
80
- | **Product** | **Tool** | **Function** | **Implematation** | **Status** |
94
+ | **Product** | **Tool** | **Function** | **Implementation** | **Status** |
81
95
  | --- | --- | --- | --- | --- |
82
96
  | ECS | RunCommand | Run Command | OOS | Done |
83
97
  | | StartInstances | Start Instances | OOS | Done |
@@ -112,6 +126,24 @@ To use `alibaba-cloud-ops-mcp-server` MCP Server with any other MCP Client, you
112
126
  | | GetDiskUsageData | Get Disk Utilization Metric Data | API | Done |
113
127
  | | GetDiskTotalData | Get Total Disk Partition Capacity Metric Data | API | Done |
114
128
  | | GetDiskUsedData | Get Disk Partition Usage Metric Data | API | Done |
129
+ | Application Management | OOS_CodeDeploy | Deploy applications to ECS instances with automatic artifact upload to OSS | OOS | Done |
130
+ | | OOS_GetDeployStatus | Query deployment status of application groups | API | Done |
131
+ | | OOS_GetLastDeploymentInfo | Retrieve information about the last deployment | API | Done |
132
+ | Local | LOCAL_ListDirectory | List files and subdirectories in a directory | Local | Done |
133
+ | | LOCAL_RunShellScript | Execute shell scripts or commands | Local | Done |
134
+ | | LOCAL_AnalyzeDeployStack | Identify project deployment methods and technology stack | Local | Done |
135
+
136
+ ## Deployment Workflow
137
+
138
+ The typical deployment workflow includes:
139
+
140
+ 1. **Project Analysis**: Use `LOCAL_AnalyzeDeployStack` to identify the project's technology stack and deployment method
141
+ 2. **Build Artifacts**: Build or package the application locally (e.g., create tar.gz or zip files)
142
+ 3. **Deploy Application**: Use `OOS_CodeDeploy` to deploy the application to ECS instances
143
+ - Automatically creates application and application group if they don't exist
144
+ - Uploads artifacts to OSS
145
+ - Deploys to specified ECS instances
146
+ 4. **Monitor Deployment**: Use `OOS_GetDeployStatus` to check deployment status
115
147
 
116
148
  ## Contact us
117
149
 
@@ -1,22 +1,24 @@
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=dv8S8E5Cj1eEe_CXKfSzhtAfhpGBGKvGcsliOlpzS9o,2900
4
+ alibaba_cloud_ops_mcp_server/server.py,sha256=C3vb1VlVo2P_yJ1LjWiRMI8FAMkujUdD6j2NmB36kWs,8005
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
8
8
  alibaba_cloud_ops_mcp_server/alibabacloud/exception.py,sha256=7PdhgqgXEGrTPL1cj98h9EH-RrM6-2TT89PDtcmlpmU,1230
9
- alibaba_cloud_ops_mcp_server/alibabacloud/utils.py,sha256=tZQAEqGKS6Rx6Te9zNYfPBJ75GnAA-wX7hs6uP_JN0M,1609
9
+ alibaba_cloud_ops_mcp_server/alibabacloud/utils.py,sha256=J3fywpnqMvIX19Fw87sKlKSxwWGjQcje8sRTMVAUZvg,8271
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=dqtbjonhuwpH6_gS_Yc3kYXaOzC0T-iJ2n9stzMbP1g,9568
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
14
15
  alibaba_cloud_ops_mcp_server/tools/cms_tools.py,sha256=BmPTiP8wu9DsEHBQsvR7JH9nFkcKMTBuNuafFqSfVxU,4308
15
16
  alibaba_cloud_ops_mcp_server/tools/common_api_tools.py,sha256=ccQAWqS1I9F-fdOdjLcXN-dIhNqSbZV8T5ODuGXlfXM,2711
16
- alibaba_cloud_ops_mcp_server/tools/oos_tools.py,sha256=IAr9x1lHuDmW-BNX2-f2wFto0LGc27pAdm_BZ3WyrE4,13013
17
- alibaba_cloud_ops_mcp_server/tools/oss_tools.py,sha256=MUAiYL4VlsYQPoR_JtHOLcF1i4VYK9KE6ff9BTqJr9E,5014
18
- alibaba_cloud_ops_mcp_server-0.9.9.dist-info/METADATA,sha256=G8ibBtTXZ7C4qY-h488ClZvZJpajhwJpbDBoGZ_MTqw,6001
19
- alibaba_cloud_ops_mcp_server-0.9.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
- alibaba_cloud_ops_mcp_server-0.9.9.dist-info/entry_points.txt,sha256=ESGAWXKEp184forhs7VzTD4P1AUdZz6vCW6hRUKITGw,83
21
- alibaba_cloud_ops_mcp_server-0.9.9.dist-info/licenses/LICENSE,sha256=gQgVkp2ttRCjodiPpXZZR-d7JnrYIYNiHk1YDUYgpa4,11331
22
- alibaba_cloud_ops_mcp_server-0.9.9.dist-info/RECORD,,
17
+ alibaba_cloud_ops_mcp_server/tools/local_tools.py,sha256=Sl7Vl2mVQMLyMIZQDLoE-xVF0vNz_haMEspyYPDe6Sg,13133
18
+ alibaba_cloud_ops_mcp_server/tools/oos_tools.py,sha256=cPEl05Y0rlNvCeO2SF46Y7Ewky4LXZ8__sD0_JCi8ek,13569
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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any