Skip to content

Commit e938612

Browse files
author
YangSen-qn
committed
feat: support upload
1 parent 86fb92c commit e938612

File tree

6 files changed

+47
-28
lines changed

6 files changed

+47
-28
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,20 @@ Server 来访问七牛云存储、智能多媒体服务等。
77

88
关于访问七牛云存储详细情况请参考 [基于 MCP 使用大模型访问七牛云存储](https://developer.qiniu.com/kodo/12914/mcp-aimodel-kodo)
99

10+
能力集:
11+
- 存储
12+
- 获取 Bucket 列表
13+
- 获取 Bucket 中的文件列表
14+
- 上传本地文件,以及给出文件内容进行上传
15+
- 读取文件内容
16+
- 获取文件下载链接
17+
- 智能多媒体
18+
- 图片缩放
19+
- 图片切圆角
20+
- CDN
21+
- 根据链接刷新文件
22+
- 根据链接预取文件
23+
1024
## 环境要求
1125

1226
- Python 3.12 或更高版本

src/mcp_server/core/cdn/tools.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def __init__(self, cdn: CDNService):
2929

3030
@tools.tool_meta(
3131
types.Tool(
32-
name="CDNPrefetchUrls",
32+
name="cdn_prefetch_urls",
3333
description="Newly added resources are proactively retrieved by the CDN and stored on its cache nodes in advance. Users simply submit the resource URLs, and the CDN automatically triggers the prefetch process.",
3434
inputSchema={
3535
"type": "object",
@@ -76,7 +76,7 @@ def prefetch_urls(self, **kwargs) -> list[types.TextContent]:
7676

7777
@tools.tool_meta(
7878
types.Tool(
79-
name="CDNRefresh",
79+
name="cdn_refresh",
8080
description="This function marks resources cached on CDN nodes as expired. When users access these resources again, the CDN nodes will fetch the latest version from the origin server and store them anew.",
8181
inputSchema={
8282
"type": "object",

src/mcp_server/core/media_processing/tools.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def __init__(self, cli: MediaProcessingService):
1717

1818
@tools.tool_meta(
1919
types.Tool(
20-
name="ImageScaleByPercent",
20+
name="image_scale_by_percent",
2121
description="""Image scaling tool that resizes images based on a percentage and returns information about the scaled image.
2222
The information includes the object_url of the scaled image, which users can directly use for HTTP GET requests to retrieve the image content or open in a browser to view the file.
2323
The image must be stored in a Qiniu Cloud Bucket.
@@ -70,7 +70,7 @@ def image_scale_by_percent(
7070

7171
@tools.tool_meta(
7272
types.Tool(
73-
name="ImageScaleBySize",
73+
name="image_scale_by_size",
7474
description="""Image scaling tool that resizes images based on a specified width or height and returns information about the scaled image.
7575
The information includes the object_url of the scaled image, which users can directly use for HTTP GET requests to retrieve the image content or open in a browser to view the file.
7676
The image must be stored in a Qiniu Cloud Bucket.
@@ -134,7 +134,7 @@ def image_scale_by_size(
134134

135135
@tools.tool_meta(
136136
types.Tool(
137-
name="ImageRoundCorner",
137+
name="image_round_corner",
138138
description="""Image rounded corner tool that processes images based on width, height, and corner radius, returning information about the processed image.
139139
If only radius_x or radius_y is set, the other parameter will be assigned the same value, meaning horizontal and vertical parameters will be identical.
140140
The information includes the object_url of the processed image, which users can directly use for HTTP GET requests to retrieve the image content or open in a browser to view the file.
@@ -203,7 +203,7 @@ def image_round_corner(self, **kwargs) -> list[types.TextContent]:
203203

204204
@tools.tool_meta(
205205
types.Tool(
206-
name="ImageInfo",
206+
name="image_info",
207207
description="Retrieves basic image information, including image format, size, and color model.",
208208
inputSchema={
209209
"type": "object",
@@ -240,7 +240,7 @@ def image_info(self, **kwargs) -> list[types.TextContent]:
240240

241241
@tools.tool_meta(
242242
types.Tool(
243-
name="GetFopStatus",
243+
name="get_fop_status",
244244
description="Retrieves the execution status of a Fop operation.",
245245
inputSchema={
246246
"type": "object",

src/mcp_server/core/storage/storage.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,11 +172,11 @@ def upload_text_data(self, bucket: str, key: str, data: str, overwrite: bool = F
172172
token = self.auth.upload_token(bucket=bucket, key=key, policy=policy)
173173
ret, info = qiniu.put_data(up_token=token, key=key, data=bytes(data, encoding="utf-8"))
174174
if info.status_code != 200:
175-
raise Exception(f"Failed to upload object: {info.text}")
175+
raise Exception(f"Failed to upload object: {info}")
176176

177177
return self.get_object_url(bucket, key)
178178

179-
def upload_file(self, bucket: str, key: str, file_path: str, overwrite: bool = False) -> list[dict[str:Any]]:
179+
def upload_local_file(self, bucket: str, key: str, file_path: str, overwrite: bool = False) -> list[dict[str:Any]]:
180180
policy = {
181181
"insertOnly": 1,
182182
}
@@ -188,14 +188,14 @@ def upload_file(self, bucket: str, key: str, file_path: str, overwrite: bool = F
188188
token = self.auth.upload_token(bucket=bucket, key=key, policy=policy)
189189
ret, info = qiniu.put_file(up_token=token, key=key, file_path=file_path)
190190
if info.status_code != 200:
191-
raise Exception(f"Failed to upload object: {info.text}")
191+
raise Exception(f"Failed to upload object: {info}")
192192

193193
return self.get_object_url(bucket, key)
194194

195195
def fetch_object(self, bucket: str, key: str, url: str):
196196
ret, info = self.bucket_manager.fetch(url, bucket, key=key)
197197
if info.status_code != 200:
198-
raise Exception(f"Failed to fetch object: {info.text}")
198+
raise Exception(f"Failed to fetch object: {info}")
199199

200200
return self.get_object_url(bucket, key)
201201

src/mcp_server/core/storage/tools.py

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def __init__(self, storage: StorageService):
1818

1919
@tools.tool_meta(
2020
types.Tool(
21-
name="ListBuckets",
21+
name="list_buckets",
2222
description="Return the Bucket you configured based on the conditions.",
2323
inputSchema={
2424
"type": "object",
@@ -38,7 +38,7 @@ async def list_buckets(self, **kwargs) -> list[types.TextContent]:
3838

3939
@tools.tool_meta(
4040
types.Tool(
41-
name="ListObjects",
41+
name="list_objects",
4242
description="List objects in Qiniu Cloud, list a part each time, you can set start_after to continue listing, when the number of listed objects is less than max_keys, it means that all files are listed. start_after can be the key of the last file in the previous listing.",
4343
inputSchema={
4444
"type": "object",
@@ -70,7 +70,7 @@ async def list_objects(self, **kwargs) -> list[types.TextContent]:
7070

7171
@tools.tool_meta(
7272
types.Tool(
73-
name="GetObject",
73+
name="get_object",
7474
description="Get an object contents from Qiniu Cloud bucket. In the GetObject request, specify the full key name for the object.",
7575
inputSchema={
7676
"type": "object",
@@ -110,7 +110,7 @@ async def get_object(self, **kwargs) -> list[ImageContent] | list[TextContent]:
110110

111111
@tools.tool_meta(
112112
types.Tool(
113-
name="UploadTextData",
113+
name="upload_text_data",
114114
description="Upload text data to Qiniu bucket.",
115115
inputSchema={
116116
"type": "object",
@@ -121,7 +121,7 @@ async def get_object(self, **kwargs) -> list[ImageContent] | list[TextContent]:
121121
},
122122
"key": {
123123
"type": "string",
124-
"description": "Key of the object to upload. Length Constraints: Minimum length of 1.",
124+
"description": "The key under which a file is saved in Qiniu Cloud Storage serves as the unique identifier for the file within that space, typically using the filename.",
125125
},
126126
"data": {
127127
"type": "string",
@@ -142,7 +142,7 @@ def upload_text_data(self, **kwargs) -> list[types.TextContent]:
142142

143143
@tools.tool_meta(
144144
types.Tool(
145-
name="UploadFile",
145+
name="upload_local_file",
146146
description="Upload a local file to Qiniu bucket.",
147147
inputSchema={
148148
"type": "object",
@@ -153,7 +153,7 @@ def upload_text_data(self, **kwargs) -> list[types.TextContent]:
153153
},
154154
"key": {
155155
"type": "string",
156-
"description": "Key of the object to upload. Length Constraints: Minimum length of 1.",
156+
"description": "The key under which a file is saved in Qiniu Cloud Storage serves as the unique identifier for the file within that space, typically using the filename.",
157157
},
158158
"file_path": {
159159
"type": "string",
@@ -168,13 +168,13 @@ def upload_text_data(self, **kwargs) -> list[types.TextContent]:
168168
}
169169
)
170170
)
171-
def upload_file(self, **kwargs) -> list[types.TextContent]:
172-
urls = self.storage.upload_file(**kwargs)
171+
def upload_local_file(self, **kwargs) -> list[types.TextContent]:
172+
urls = self.storage.upload_local_file(**kwargs)
173173
return [types.TextContent(type="text", text=str(urls))]
174174

175175
@tools.tool_meta(
176176
types.Tool(
177-
name="FetchObject",
177+
name="fetch_object",
178178
description="Fetch a http object to Qiniu bucket.",
179179
inputSchema={
180180
"type": "object",
@@ -185,8 +185,14 @@ def upload_file(self, **kwargs) -> list[types.TextContent]:
185185
},
186186
"key": {
187187
"type": "string",
188-
}
189-
}
188+
"description": "The key under which a file is saved in Qiniu Cloud Storage serves as the unique identifier for the file within that space, typically using the filename.",
189+
},
190+
"url": {
191+
"type": "string",
192+
"description": "The URL of the object to fetch.",
193+
},
194+
},
195+
"required": ["bucket", "key", "url"],
190196
}
191197
)
192198
)
@@ -196,7 +202,7 @@ def fetch_object(self, **kwargs) -> list[types.TextContent]:
196202

197203
@tools.tool_meta(
198204
types.Tool(
199-
name="GetObjectURL",
205+
name="get_object_url",
200206
description="Get the file download URL, and note that the Bucket where the file is located must be bound to a domain name. If using Qiniu Cloud test domain, HTTPS access will not be available, and users need to make adjustments for this themselves.",
201207
inputSchema={
202208
"type": "object",
@@ -207,7 +213,7 @@ def fetch_object(self, **kwargs) -> list[types.TextContent]:
207213
},
208214
"key": {
209215
"type": "string",
210-
"description": "Key of the object to get. Length Constraints: Minimum length of 1.",
216+
"description": "Key of the object to get.",
211217
},
212218
"disable_ssl": {
213219
"type": "boolean",
@@ -235,8 +241,7 @@ def register_tools(storage: StorageService):
235241
tool_impl.list_objects,
236242
tool_impl.get_object,
237243
tool_impl.upload_text_data,
238-
tool_impl.upload_file,
239-
tool_impl.fetch_object,
244+
tool_impl.upload_local_file,
240245
tool_impl.get_object_url,
241246
]
242247
)

src/mcp_server/core/version/tools.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def __init__(self):
1111

1212
@tools.tool_meta(
1313
types.Tool(
14-
name="Version",
14+
name="version",
1515
description="qiniu mcp server version info.",
1616
inputSchema={
1717
"type": "object",

0 commit comments

Comments
 (0)