alibaba-cloud-ops-mcp-server 0.9.2__py3-none-any.whl → 0.9.4__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,4 @@
1
+ from .server import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -39,6 +39,7 @@ When a user submits a request, analyze their needs and check if matching tools e
39
39
  - cbn: Cloud Enterprise Network (CBN)
40
40
  - dds: MongoDB Database Service (DDS)
41
41
  - r-kvstore: Cloud database Tair (compatible with Redis) (R-KVStore)
42
+ - bssopenapi: Billing and Cost Management (BssOpenAPI)
42
43
 
43
44
  2. **API Process**
44
45
  - Use `ListAPIs` for available APIs
@@ -3,6 +3,7 @@ import logging
3
3
  from alibabacloud_credentials.client import Client as CredClient
4
4
  from alibabacloud_tea_openapi.models import Config
5
5
  from fastmcp.server.dependencies import get_http_request
6
+ from alibaba_cloud_ops_mcp_server.settings import settings
6
7
 
7
8
  logger = logging.getLogger(__name__)
8
9
 
@@ -30,17 +31,21 @@ def get_credentials_from_header():
30
31
 
31
32
  def create_config():
32
33
  credentials = get_credentials_from_header()
34
+
33
35
  if credentials:
34
- access_key_id = credentials.get('AccessKeyId', None)
35
- access_key_secret = credentials.get('AccessKeySecret', None)
36
- token = credentials.get('SecurityToken', None)
36
+ access_key_id = credentials.get('AccessKeyId')
37
+ access_key_secret = credentials.get('AccessKeySecret')
38
+ token = credentials.get('SecurityToken')
37
39
  config = Config(
38
40
  access_key_id=access_key_id,
39
41
  access_key_secret=access_key_secret,
40
42
  security_token=token
41
43
  )
44
+ elif settings.headers_credential_only:
45
+ config = Config()
42
46
  else:
43
- credentialsClient = CredClient()
44
- config = Config(credential=credentialsClient)
47
+ credentials_client = CredClient()
48
+ config = Config(credential=credentials_client)
49
+
45
50
  config.user_agent = 'alibaba-cloud-ops-mcp-server'
46
51
  return config
@@ -5,6 +5,7 @@ import logging
5
5
  from alibaba_cloud_ops_mcp_server.tools.common_api_tools import set_custom_service_list
6
6
  from alibaba_cloud_ops_mcp_server.config import config
7
7
  from alibaba_cloud_ops_mcp_server.tools import cms_tools, oos_tools, oss_tools, api_tools, common_api_tools
8
+ from alibaba_cloud_ops_mcp_server.settings import settings
8
9
 
9
10
  logger = logging.getLogger(__name__)
10
11
 
@@ -18,7 +19,8 @@ SUPPORTED_SERVICES_MAP = {
18
19
  "ros": "Resource Orchestration Service (ROS)",
19
20
  "cbn": "Cloud Enterprise Network (CBN)",
20
21
  "dds": "MongoDB Database Service (DDS)",
21
- "r-kvstore": "Cloud database Tair (compatible with Redis) (R-KVStore)"
22
+ "r-kvstore": "Cloud database Tair (compatible with Redis) (R-KVStore)",
23
+ "bssopenapi": "Billing and Cost Management (BssOpenAPI)"
22
24
  }
23
25
 
24
26
 
@@ -47,14 +49,22 @@ SUPPORTED_SERVICES_MAP = {
47
49
  default=None,
48
50
  help="Comma-separated list of supported services, e.g., 'ecs,vpc,rds'",
49
51
  )
50
- def main(transport: str, port: int, host: str, services: str):
52
+ @click.option(
53
+ "--headers-credential-only",
54
+ type=bool,
55
+ default=False,
56
+ help="Whether to use credentials only from headers",
57
+ )
58
+ def main(transport: str, port: int, host: str, services: str, headers_credential_only: bool):
51
59
  # Create an MCP server
52
60
  mcp = FastMCP(
53
61
  name="alibaba-cloud-ops-mcp-server",
54
62
  port=port,
55
- host=host
63
+ host=host,
64
+ stateless_http=True
56
65
  )
57
-
66
+ if headers_credential_only:
67
+ settings.headers_credential_only = headers_credential_only
58
68
  if services:
59
69
  service_keys = [s.strip().lower() for s in services.split(",")]
60
70
  service_list = [(key, SUPPORTED_SERVICES_MAP.get(key, key)) for key in service_keys]
@@ -0,0 +1,8 @@
1
+ from pydantic_settings import BaseSettings
2
+
3
+
4
+ class Settings(BaseSettings):
5
+ headers_credential_only: bool = False
6
+
7
+
8
+ settings = Settings()
@@ -14,6 +14,7 @@ from alibabacloud_openapi_util.client import Client as OpenApiUtilClient
14
14
  from alibaba_cloud_ops_mcp_server.alibabacloud.api_meta_client import ApiMetaClient
15
15
  from alibaba_cloud_ops_mcp_server.alibabacloud.utils import create_config
16
16
 
17
+ logger = logging.getLogger(__name__)
17
18
 
18
19
  type_map = {
19
20
  'string': str,
@@ -29,37 +30,62 @@ REGION_ENDPOINT_SERVICE = ['ecs', 'oos', 'vpc', 'slb']
29
30
  DOUBLE_ENDPOINT_SERVICE = {
30
31
  'rds': ['cn-qingdao', 'cn-beijing', 'cn-hangzhou', 'cn-shanghai', 'cn-shenzhen', 'cn-heyuan', 'cn-guangzhou', 'cn-hongkong'],
31
32
  'ess': ['cn-qingdao', 'cn-beijing', 'cn-hangzhou', 'cn-shanghai', 'cn-nanjing', 'cn-shenzhen'],
32
- 'ros': ['cn-qingdao'],
33
33
  'dds': ['cn-qingdao', 'cn-beijing', 'cn-wulanchabu', 'cn-hangzhou', 'cn-shanghai', 'cn-shenzhen', 'cn-heyuan', 'cn-guangzhou'],
34
34
  'r-kvstore': ['cn-qingdao', 'cn-beijing', 'cn-wulanchabu', 'cn-hangzhou', 'cn-shanghai', 'cn-shenzhen', 'cn-heyuan']
35
35
  }
36
36
 
37
- CENTRAL_ENDPOINTS_SERVICE = ['cbn']
37
+ CENTRAL_SERVICE = ['cbn', 'ros', 'ram']
38
+
39
+ CENTRAL_SERVICE_ENDPOINTS = {
40
+ 'bssopenapi': {
41
+ 'DomesticEndpoint': 'business.aliyuncs.com',
42
+ 'InternationalEndpoint': 'business.ap-southeast-1.aliyuncs.com',
43
+ 'DomesticRegion': ['cn-qingdao', 'cn-beijing', 'cn-zhangjiakou', 'cn-huhehaote', 'cn-wulanchabu',
44
+ 'cn-hangzhou', 'cn-shanghai', 'cn-shenzhen', 'cn-chengdu', 'cn-hongkong']
45
+ }
46
+ }
38
47
 
39
48
 
40
49
  def _get_service_endpoint(service: str, region_id: str):
41
50
  region_id = region_id.lower()
42
- use_region_endpoint = service in REGION_ENDPOINT_SERVICE or (
43
- service in DOUBLE_ENDPOINT_SERVICE and region_id in DOUBLE_ENDPOINT_SERVICE[service]
44
- )
45
51
 
46
- if use_region_endpoint:
52
+ # Prioritizing central service endpoints
53
+ central = CENTRAL_SERVICE_ENDPOINTS.get(service)
54
+ if central:
55
+ if region_id in central.get('DomesticRegion', []):
56
+ return central['DomesticEndpoint']
57
+ else:
58
+ return central['InternationalEndpoint']
59
+
60
+ # Determine whether to use regional endpoints
61
+ if service in REGION_ENDPOINT_SERVICE:
47
62
  return f'{service}.{region_id}.aliyuncs.com'
48
- elif service in CENTRAL_ENDPOINTS_SERVICE or service in DOUBLE_ENDPOINT_SERVICE:
63
+
64
+ if service in DOUBLE_ENDPOINT_SERVICE:
65
+ not_in_central = region_id not in DOUBLE_ENDPOINT_SERVICE[service]
66
+ if not_in_central:
67
+ return f'{service}.{region_id}.aliyuncs.com'
68
+ else:
69
+ return f'{service}.aliyuncs.com'
70
+
71
+ if service in CENTRAL_SERVICE:
49
72
  return f'{service}.aliyuncs.com'
50
- else:
51
- return f'{service}.{region_id}.aliyuncs.com'
73
+
74
+ # Default
75
+ return f'{service}.{region_id}.aliyuncs.com'
52
76
 
53
77
 
54
78
  def create_client(service: str, region_id: str) -> OpenApiClient:
55
79
  config = create_config()
56
80
  if isinstance(service, str):
57
81
  service = service.lower()
58
- config.endpoint = _get_service_endpoint(service, region_id.lower())
82
+ endpoint = _get_service_endpoint(service, region_id.lower())
83
+ config.endpoint = endpoint
84
+ logger.info(f'Service Endpoint: {endpoint}')
59
85
  return OpenApiClient(config)
60
86
 
61
87
 
62
- # 类型为String的JSON数组参数
88
+ # JSON array parameter of type String
63
89
  ECS_LIST_PARAMETERS = {
64
90
  'HpcClusterIds', 'DedicatedHostClusterIds', 'DedicatedHostIds',
65
91
  'InstanceIds', 'DeploymentSetIds', 'KeyPairNames', 'SecurityGroupIds',
@@ -76,8 +102,9 @@ def _tools_api_call(service: str, api: str, parameters: dict, ctx: Context):
76
102
  path = api_meta.get('path', '/')
77
103
  style = ApiMetaClient.get_service_style(service)
78
104
 
79
- # 处理特殊参数格式
105
+ # Handling special parameter formats
80
106
  processed_parameters = parameters.copy()
107
+ processed_parameters = {k: v for k, v in processed_parameters.items() if v is not None}
81
108
  if service == 'ecs':
82
109
  for param_name, param_value in parameters.items():
83
110
  if param_name in ECS_LIST_PARAMETERS and isinstance(param_value, list):
@@ -97,8 +124,11 @@ def _tools_api_call(service: str, api: str, parameters: dict, ctx: Context):
97
124
  req_body_type='formData',
98
125
  body_type='json'
99
126
  )
127
+ logger.info(f'Call API Request: Service: {service} API: {api} Method: {method} Parameters: {processed_parameters}')
100
128
  client = create_client(service, processed_parameters.get('RegionId', 'cn-hangzhou'))
101
129
  runtime = util_models.RuntimeOptions()
130
+ resp = client.call_api(params, req, runtime)
131
+ logger.info(f'Call API Response: {resp}')
102
132
  return client.call_api(params, req, runtime)
103
133
 
104
134
 
@@ -1,3 +1,5 @@
1
+ import logging
2
+
1
3
  from pydantic import Field
2
4
  from typing import List
3
5
  import os
@@ -10,6 +12,7 @@ from alibaba_cloud_ops_mcp_server.alibabacloud.utils import create_config
10
12
 
11
13
  END_STATUSES = ['Success', 'Failed', 'Cancelled']
12
14
 
15
+ logger = logging.getLogger(__name__)
13
16
 
14
17
  tools = []
15
18
 
@@ -33,6 +36,7 @@ def _get_cms_metric_data(region_id: str, instance_ids: List[str], metric_name: s
33
36
  dimensions=json.dumps(dimesion),
34
37
  )
35
38
  describe_metric_last_resp = client.describe_metric_last(describe_metric_last_request)
39
+ logger.info(f'CMS Tools response: {describe_metric_last_resp.body}')
36
40
  return describe_metric_last_resp.body.datapoints
37
41
 
38
42
  @tools.append
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alibaba-cloud-ops-mcp-server
3
- Version: 0.9.2
3
+ Version: 0.9.4
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
@@ -1,20 +1,22 @@
1
1
  alibaba_cloud_ops_mcp_server/__init__.py,sha256=BaluUNyRz8Qw-X7Y0ywDezwbkqiSvWlSYn2452XeGcA,213
2
+ alibaba_cloud_ops_mcp_server/__main__.py,sha256=Q40p2HtWGvxj1JLvS7dn95NLzDhJNQ6JAgLLyCb4Y50,63
2
3
  alibaba_cloud_ops_mcp_server/config.py,sha256=PizctjXsQUWoMWBY1dFjNffVlZr9K6hNvqA4DpayR_o,513
3
- alibaba_cloud_ops_mcp_server/server.py,sha256=1TRZMsgicsnaK_YFktL8JPglIc7Z-EQgDmSd0Ww_wdI,2219
4
+ alibaba_cloud_ops_mcp_server/server.py,sha256=zmEL-4X35CklntDuWFk6Mc8QrHq-jvsaF1XLEyhKFSc,2639
5
+ alibaba_cloud_ops_mcp_server/settings.py,sha256=fqbTHaAw59nK7fJo6MyTCY_-M0K9YAD66WpybQalo9I,141
4
6
  alibaba_cloud_ops_mcp_server/alibabacloud/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
7
  alibaba_cloud_ops_mcp_server/alibabacloud/api_meta_client.py,sha256=t2TSc0Gzcy_uEcaCgiHHuLoMiEGu3-NCtYmwYjyPWsY,7973
6
8
  alibaba_cloud_ops_mcp_server/alibabacloud/exception.py,sha256=7PdhgqgXEGrTPL1cj98h9EH-RrM6-2TT89PDtcmlpmU,1230
7
- alibaba_cloud_ops_mcp_server/alibabacloud/utils.py,sha256=7PldufvFOb9GcXLHbUxKV6m9XqJpoNe4FVdQcg7Zeuk,1495
8
- alibaba_cloud_ops_mcp_server/alibabacloud/static/PROMPT_UNDERSTANDING.md,sha256=494HcCQQCc_iqDrRKhk7eWXB4I0dMtqCseT78KphDHg,3553
9
+ alibaba_cloud_ops_mcp_server/alibabacloud/utils.py,sha256=tZQAEqGKS6Rx6Te9zNYfPBJ75GnAA-wX7hs6uP_JN0M,1609
10
+ alibaba_cloud_ops_mcp_server/alibabacloud/static/PROMPT_UNDERSTANDING.md,sha256=QPubudP1bwDbWu0Js6MYb4cJd1B2zM_JGp53twYv5yc,3611
9
11
  alibaba_cloud_ops_mcp_server/alibabacloud/static/__init__.py,sha256=wJrYamaIb7e_kA4ILZpdP1f1TUUTXMGqEhA4IbSZ2Ts,230
10
12
  alibaba_cloud_ops_mcp_server/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- alibaba_cloud_ops_mcp_server/tools/api_tools.py,sha256=T5Zat31yjEBEmILKbb2uDUkgDHSqOIlPAjpi47hsCz8,8220
12
- alibaba_cloud_ops_mcp_server/tools/cms_tools.py,sha256=_M13s87WxxiHp3Phu5AmXKkHOj0KDvUlodJ6z5Ndi7E,4182
13
+ alibaba_cloud_ops_mcp_server/tools/api_tools.py,sha256=nkYLrrcZ1LVoc-4-sQoyHO4aO-G6Brz_xO5dz6NL9BI,9414
14
+ alibaba_cloud_ops_mcp_server/tools/cms_tools.py,sha256=BmPTiP8wu9DsEHBQsvR7JH9nFkcKMTBuNuafFqSfVxU,4308
13
15
  alibaba_cloud_ops_mcp_server/tools/common_api_tools.py,sha256=ccQAWqS1I9F-fdOdjLcXN-dIhNqSbZV8T5ODuGXlfXM,2711
14
16
  alibaba_cloud_ops_mcp_server/tools/oos_tools.py,sha256=8CLidg8Vrzpxv4lEOokPdScv31xlg_gX7glifiSqa8g,10063
15
17
  alibaba_cloud_ops_mcp_server/tools/oss_tools.py,sha256=MUAiYL4VlsYQPoR_JtHOLcF1i4VYK9KE6ff9BTqJr9E,5014
16
- alibaba_cloud_ops_mcp_server-0.9.2.dist-info/METADATA,sha256=j-SZxCA0-iHZGMWqaJ4z9-vXq3rYs1du4FQ9822zAFc,5965
17
- alibaba_cloud_ops_mcp_server-0.9.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
18
- alibaba_cloud_ops_mcp_server-0.9.2.dist-info/entry_points.txt,sha256=ESGAWXKEp184forhs7VzTD4P1AUdZz6vCW6hRUKITGw,83
19
- alibaba_cloud_ops_mcp_server-0.9.2.dist-info/licenses/LICENSE,sha256=gQgVkp2ttRCjodiPpXZZR-d7JnrYIYNiHk1YDUYgpa4,11331
20
- alibaba_cloud_ops_mcp_server-0.9.2.dist-info/RECORD,,
18
+ alibaba_cloud_ops_mcp_server-0.9.4.dist-info/METADATA,sha256=asXs9bS4X4omeQvusc63uF75qvNqs0DW4_V0YGNZKp4,5965
19
+ alibaba_cloud_ops_mcp_server-0.9.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
20
+ alibaba_cloud_ops_mcp_server-0.9.4.dist-info/entry_points.txt,sha256=ESGAWXKEp184forhs7VzTD4P1AUdZz6vCW6hRUKITGw,83
21
+ alibaba_cloud_ops_mcp_server-0.9.4.dist-info/licenses/LICENSE,sha256=gQgVkp2ttRCjodiPpXZZR-d7JnrYIYNiHk1YDUYgpa4,11331
22
+ alibaba_cloud_ops_mcp_server-0.9.4.dist-info/RECORD,,