cos-mcp 1.0.6 → 1.0.8

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.
package/README.md CHANGED
@@ -60,6 +60,24 @@
60
60
  }
61
61
 
62
62
 
63
+ ```
64
+ 也可以简单配置
65
+ ```
66
+ {
67
+ "mcpServers": {
68
+ "cos-mcp": {
69
+ "command": "npx",
70
+ "args": [
71
+ "cos-mcp",
72
+ "--Region=yourRegion",
73
+ "--Bucket=yourBucket",
74
+ "--SecretId=yourSecretId",
75
+ "--SecretKey=yourSecretKey",
76
+ "--DatasetName=yourDatasetname",
77
+ ]
78
+ }
79
+ }
80
+ }
63
81
  ```
64
82
 
65
83
  ## 使用npm安装
@@ -69,6 +87,9 @@ npm install -g cos-mcp
69
87
 
70
88
  // 运行开启sse模式
71
89
  cos-mcp --cos-config='{"Region":"yourRegion","Bucket":"BucketName-APPID","SecretId":"yourSecretId","SecretKey":"yourSecretKey","DatasetName":"datasetName"}' --port=3001 --connectType=sse
90
+ // 也可以简单配置
91
+ cos-mcp --Region=yourRegion --Bucket=yourBucket --SecretId=yourSecretId --SecretKey=yourSecretKey --DatasetName=yourDatasetname --port=3001 --connectType=sse
92
+
72
93
 
73
94
  // 参数说明:
74
95
  // connectType 代表连接方式,可以是stdio (本地) 或 sse (远程)
@@ -97,7 +118,7 @@ cos-mcp --cos-config='{"Region":"yourRegion","Bucket":"BucketName-APPID","Secret
97
118
  ---
98
119
  ⚠️请注意!
99
120
 
100
- 1. 如果全局安装后直接使用cos-mcp不行,可能是全局变量有问题, 可以使用 npx的方式来启动
121
+ 1. 如果全局安装后直接使用cos-mcp不行,可能是全局变量有问题,可以使用拆分变量或使用 npx的方式来启动
101
122
 
102
123
  ```
103
124
  npm install -g cos-mcp
@@ -0,0 +1,23 @@
1
+ import { generateOutPutFileId, generateCode } from '../services/utils.js';
2
+ describe('utils.ts functions', () => {
3
+ describe('generateOutPutFileId function', () => {
4
+ it('should generate a valid output file ID', () => {
5
+ const objectKey = 'example.txt';
6
+ const result = generateOutPutFileId(objectKey);
7
+ expect(result).toContain('example');
8
+ expect(result).toMatch(/\d{8}_example/); // 日期格式验证
9
+ });
10
+ });
11
+ describe('generateCode function', () => {
12
+ it('should generate a code of specified length', () => {
13
+ const length = 8;
14
+ const code = generateCode(length);
15
+ expect(code).toHaveLength(length);
16
+ });
17
+ it('should generate a secure random code', () => {
18
+ const code = generateCode(6, true);
19
+ expect(code).toMatch(/^[A-Za-z0-9]+$/);
20
+ });
21
+ });
22
+ });
23
+ //# sourceMappingURL=utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../src/__tests__/utils.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAE1E,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;QAC7C,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,SAAS,GAAG,aAAa,CAAC;YAChC,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAC;YAC/C,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;YACpC,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,SAAS;QACpD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;YACpD,MAAM,MAAM,GAAG,CAAC,CAAC;YACjB,MAAM,IAAI,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,IAAI,GAAG,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YACnC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
package/dist/index.js CHANGED
@@ -1,53 +1,53 @@
1
1
  #!/usr/bin/env node
2
- import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
- import { createCosMcpServer, startWithSSE } from "./server.js";
4
- import { config } from "dotenv";
5
- import { resolve } from "path";
6
- import yargs from "yargs";
7
- import { hideBin } from "yargs/helpers";
8
- import { z } from "zod";
9
- import { maskSecret } from "./server.js";
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { createCosMcpServer, startWithSSE } from './server.js';
4
+ import { config } from 'dotenv';
5
+ import { resolve } from 'path';
6
+ import yargs from 'yargs';
7
+ import { hideBin } from 'yargs/helpers';
8
+ import { z } from 'zod';
9
+ import { maskSecret } from './server.js';
10
10
  // COS配置验证Schema
11
11
  export const cosConfigSchema = z.object({
12
12
  Region: z.string(),
13
13
  SecretId: z.string(),
14
14
  SecretKey: z.string(),
15
15
  Bucket: z.string(),
16
- DatasetName: z.string().optional()
16
+ DatasetName: z.string().optional(),
17
17
  });
18
18
  // 加载当前工作目录中的.env文件
19
- config({ path: resolve(process.cwd(), ".env") });
19
+ config({ path: resolve(process.cwd(), '.env') });
20
20
  function getConfig() {
21
21
  const argv = yargs(hideBin(process.argv))
22
22
  .options({
23
- "cos-config": {
24
- type: "string",
25
- description: "COS配置的JSON",
23
+ 'cos-config': {
24
+ type: 'string',
25
+ description: 'COS配置的JSON',
26
26
  },
27
27
  port: {
28
- type: "number",
29
- description: "server运行端口",
28
+ type: 'number',
29
+ description: 'server运行端口',
30
30
  },
31
31
  connectType: {
32
- type: "string",
33
- description: "连接类型",
34
- choices: ["stdio", "sse"],
32
+ type: 'string',
33
+ description: '连接类型',
34
+ choices: ['stdio', 'sse'],
35
35
  },
36
36
  })
37
37
  .help()
38
- .version("0.0.1")
38
+ .version('0.0.1')
39
39
  .parseSync();
40
40
  // 首先从命令行中获取
41
41
  let config = {
42
+ connectType: 'stdio',
42
43
  port: 3001,
43
44
  cosConfig: {
44
- Region: "",
45
- SecretId: "",
46
- SecretKey: "",
47
- Bucket: "",
48
- DatasetName: ""
45
+ Region: '',
46
+ SecretId: '',
47
+ SecretKey: '',
48
+ Bucket: '',
49
+ DatasetName: '',
49
50
  },
50
- connectType: "stdio",
51
51
  };
52
52
  // 必要参数
53
53
  // SecretId SecretKey bucket region connectType
@@ -64,29 +64,42 @@ function getConfig() {
64
64
  else if (process.env.connectType) {
65
65
  config.connectType = process.env.connectType;
66
66
  }
67
- if (argv["cos-config"]) {
68
- config.cosConfig = JSON.parse(argv["cos-config"]);
67
+ // 从获取cos配置, 复杂获取
68
+ if (argv['cos-config']) {
69
+ config.cosConfig = JSON.parse(argv['cos-config']);
69
70
  }
70
71
  else if (process.env.cosConfig) {
71
72
  config.cosConfig = JSON.parse(process.env.cosConfig);
72
73
  }
74
+ // 从环境变量中获取cos配置, 简单获取
75
+ ['Region', 'SecretId', 'SecretKey', 'Bucket', 'DatasetName'].forEach((item) => {
76
+ if (argv[item]) {
77
+ config.cosConfig[item] = argv[item];
78
+ }
79
+ else if (process.env[item]) {
80
+ config.cosConfig[item] = process.env[item];
81
+ }
82
+ });
73
83
  // 验证配置
74
- if (!config.cosConfig.SecretId || !config.cosConfig.SecretKey || !config.cosConfig.Bucket || !config.cosConfig.Region) {
75
- console.error("COS配置不全。请使用cos-config参数指定COS配置");
84
+ if (!config.cosConfig.SecretId ||
85
+ !config.cosConfig.SecretKey ||
86
+ !config.cosConfig.Bucket ||
87
+ !config.cosConfig.Region) {
88
+ console.error('COS配置不全。请使用cos-config参数指定COS配置');
76
89
  }
77
- if (config.connectType !== "stdio") {
78
- console.log("\nCOS配置信息:");
90
+ if (config.connectType !== 'stdio') {
91
+ console.log('\nCOS配置信息:');
79
92
  console.log(`- 端口: ${config.port}`);
80
93
  console.log(`- 运行模式: ${config.connectType}`);
81
- console.log("- cos配置:");
94
+ console.log('- cos配置:');
82
95
  Object.keys(config.cosConfig).forEach((key) => {
83
96
  let value = config.cosConfig[key];
84
- if (key === "SecretId" || key === "SecretKey") {
97
+ if (key === 'SecretId' || key === 'SecretKey') {
85
98
  value = maskSecret(value);
86
99
  }
87
100
  console.log(` - ${key}: ${value}`);
88
101
  });
89
- console.log("\n");
102
+ console.log('\n');
90
103
  }
91
104
  return config;
92
105
  }
@@ -94,7 +107,7 @@ async function startCOServer() {
94
107
  const config = getConfig();
95
108
  // 创建COS MCP
96
109
  const server = createCosMcpServer(config);
97
- if (config.connectType === "stdio") {
110
+ if (config.connectType === 'stdio') {
98
111
  // 使用stdio:标准输入输出进行通信
99
112
  const transport = new StdioServerTransport();
100
113
  await server.connect(transport);
@@ -104,7 +117,7 @@ async function startCOServer() {
104
117
  startWithSSE(server, config.port || 3001);
105
118
  }
106
119
  startCOServer().catch((error) => {
107
- console.error("启动失败", error);
120
+ console.error('启动失败', error);
108
121
  process.exit(1);
109
122
  });
110
123
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/server.js CHANGED
@@ -1,17 +1,18 @@
1
- import express from "express";
2
- import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
3
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
- import { z } from "zod";
5
- import COS from "cos-nodejs-sdk-v5";
6
- import { CosService } from "./services/cos/cos.service.js";
7
- import { CIPicService } from "./services/ci/pic.service.js";
8
- import { CIMediaService } from "./services/ci/media.service.js";
9
- import { CIAIService } from "./services/ci/ai.service.js";
10
- import { CIMateInsightService } from "./services/ci/mateInsight.service.js";
11
- import { CIDocService } from "./services/ci/doc.service.js";
1
+ import express from 'express';
2
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
3
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
4
+ import COS from 'cos-nodejs-sdk-v5';
5
+ import { z } from 'zod';
6
+ import { CosService } from './services/cos/cos.service.js';
7
+ import { CIPicService } from './services/ci/pic.service.js';
8
+ import { CIMediaService } from './services/ci/media.service.js';
9
+ import { CIAIService } from './services/ci/ai.service.js';
10
+ import { CIMateInsightService } from './services/ci/mateInsight.service.js';
11
+ import { CIDocService } from './services/ci/doc.service.js';
12
12
  export function maskSecret(secret) {
13
+ secret = String(secret);
13
14
  if (secret.length <= 4)
14
- return "****";
15
+ return '****';
15
16
  return `${secret.substring(0, 4)}****${secret.slice(-4)}`;
16
17
  }
17
18
  export const Logger = {
@@ -22,10 +23,12 @@ export const Logger = {
22
23
  console.error(...args);
23
24
  },
24
25
  };
26
+ const USER_AGENT = 'modelcontextprotocol/servers/cos';
25
27
  export function createCosMcpServer(config) {
26
28
  const cos = new COS({
27
- SecretId: config.cosConfig?.SecretId || "",
28
- SecretKey: config.cosConfig?.SecretKey || "",
29
+ SecretId: config.cosConfig?.SecretId || '',
30
+ SecretKey: config.cosConfig?.SecretKey || '',
31
+ UserAgent: USER_AGENT,
29
32
  });
30
33
  const bucket = config.cosConfig.Bucket;
31
34
  const region = config.cosConfig.Region;
@@ -34,11 +37,11 @@ export function createCosMcpServer(config) {
34
37
  const CIPicInstance = new CIPicService(bucket, region, cos);
35
38
  const CIMediaInstance = new CIMediaService(bucket, region, cos);
36
39
  const CIAIInstance = new CIAIService(bucket, region, cos);
37
- const CIMateInsightInstance = new CIMateInsightService(bucket, region, datasetName || "", cos);
40
+ const CIMateInsightInstance = new CIMateInsightService(bucket, region, datasetName || '', cos);
38
41
  const CIDocInstance = new CIDocService(bucket, region, cos);
39
42
  const server = new McpServer({
40
- name: "COS MCP Server",
41
- version: "1.0.0",
43
+ name: 'COS MCP Server',
44
+ version: '1.0.0',
42
45
  }, {
43
46
  capabilities: {
44
47
  tools: { listChanged: true },
@@ -47,7 +50,7 @@ export function createCosMcpServer(config) {
47
50
  // logging: {},
48
51
  },
49
52
  });
50
- server.tool("getCosConfig", "获取COS配置, 腾讯云配置", {}, async () => {
53
+ server.tool('getCosConfig', '获取COS配置, 腾讯云配置', {}, async () => {
51
54
  if (config.cosConfig) {
52
55
  config.cosConfig.SecretId = maskSecret(config.cosConfig.SecretId);
53
56
  config.cosConfig.SecretKey = maskSecret(config.cosConfig.SecretKey);
@@ -55,17 +58,20 @@ export function createCosMcpServer(config) {
55
58
  return {
56
59
  content: [
57
60
  {
58
- type: "text",
61
+ type: 'text',
59
62
  text: JSON.stringify(config, null, 2),
60
63
  },
61
64
  ],
62
65
  };
63
66
  });
64
- server.tool("putObject", "上传文件到存储桶", {
65
- filePath: z.string().describe("文件路径 (包含文件名)"),
66
- fileName: z.string().optional().describe("文件名 (存在存储桶里的名称)"),
67
- targetDir: z.string().optional().describe("目标目录 (存在存储桶的哪个目录)"),
68
- }, async ({ fileName, filePath, targetDir }, extra) => {
67
+ server.tool('putObject', '上传文件到存储桶', {
68
+ filePath: z.string().describe('文件路径 (包含文件名)'),
69
+ fileName: z.string().optional().describe('文件名 (存在存储桶里的名称)'),
70
+ targetDir: z
71
+ .string()
72
+ .optional()
73
+ .describe('目标目录 (存在存储桶的哪个目录)'),
74
+ }, async ({ fileName, filePath, targetDir }) => {
69
75
  const res = await COSInstance.uploadFile({
70
76
  fileName,
71
77
  filePath,
@@ -74,142 +80,127 @@ export function createCosMcpServer(config) {
74
80
  return {
75
81
  content: [
76
82
  {
77
- type: "text",
83
+ type: 'text',
78
84
  text: JSON.stringify(res.data, null, 2),
79
85
  isError: res.isSuccess ? false : true,
80
86
  },
81
87
  ],
82
88
  };
83
89
  });
84
- server.tool("getObject", "下载存储桶内的文件", {
85
- objectKey: z.string().describe("文件的路径"),
86
- }, async ({ objectKey = "/" }) => {
90
+ server.tool('getObject', '下载存储桶内的文件', {
91
+ objectKey: z.string().describe('文件的路径'),
92
+ }, async ({ objectKey = '/' }) => {
87
93
  const res = await COSInstance.getObject(objectKey);
88
94
  return {
89
95
  content: [
90
96
  {
91
- type: "text",
97
+ type: 'text',
92
98
  text: JSON.stringify(res.data, null, 2),
93
99
  isError: res.isSuccess ? false : true,
94
100
  },
95
101
  ],
96
102
  };
97
103
  });
98
- server.tool("getBucket", "查询存储桶内的文件列表", {
99
- Prefix: z.string().optional().describe("文件列表的路径前缀,默认根路径"),
100
- }, async ({ Prefix = "" }) => {
104
+ server.tool('getBucket', '查询存储桶内的文件列表', {
105
+ Prefix: z.string().optional().describe('文件列表的路径前缀,默认根路径'),
106
+ }, async ({ Prefix = '' }) => {
101
107
  const res = await COSInstance.getBucket(Prefix);
102
108
  return {
103
109
  content: [
104
110
  {
105
- type: "text",
111
+ type: 'text',
106
112
  text: JSON.stringify(res.data, null, 2),
107
113
  isError: res.isSuccess ? false : true,
108
114
  },
109
115
  ],
110
116
  };
111
117
  });
112
- // server.tool(
113
- // "getObjectUrl",
114
- // "私有读, 获取带签名的 url",
115
- // {
116
- // ObjectKey: z.string().optional().describe("文件在存储桶里的路径"),
117
- // },
118
- // async ({ ObjectKey = "" }) => {
119
- // const res = await COSInstance.getObjectUrl(ObjectKey);
120
- // return {
121
- // content: [
122
- // {
123
- // type: "text",
124
- // text: JSON.stringify(res.data, null, 2),
125
- // isError: res.isSuccess ? false : true,
126
- // },
127
- // ],
128
- // };
129
- // }
130
- // );
131
118
  // --CI--
132
- server.tool("imageInfo", "图片处理-获取图片信息", {
133
- objectKey: z.string().describe("图片在存储桶里的路径"),
119
+ server.tool('imageInfo', '图片处理-获取图片信息', {
120
+ objectKey: z.string().describe('图片在存储桶里的路径'),
134
121
  }, async ({ objectKey }) => {
135
122
  const res = await CIPicInstance.imageInfo(objectKey);
136
123
  return {
137
124
  content: [
138
125
  {
139
- type: "text",
126
+ type: 'text',
140
127
  text: JSON.stringify(res.data, null, 2),
141
128
  isError: res.isSuccess ? false : true,
142
129
  },
143
130
  ],
144
131
  };
145
132
  });
146
- server.tool("assessQuality", "图片处理-图片质量评估", {
147
- objectKey: z.string().describe("图片在存储桶里的路径"),
133
+ server.tool('assessQuality', '图片处理-图片质量评估', {
134
+ objectKey: z.string().describe('图片在存储桶里的路径'),
148
135
  }, async ({ objectKey }) => {
149
136
  const res = await CIAIInstance.assessQuality(objectKey);
150
137
  return {
151
138
  content: [
152
139
  {
153
- type: "text",
140
+ type: 'text',
154
141
  text: JSON.stringify(res.data, null, 2),
155
142
  isError: res.isSuccess ? false : true,
156
143
  },
157
144
  ],
158
145
  };
159
146
  });
160
- server.tool("aiSuperResolution", "图片处理-超分辨率", {
161
- objectKey: z.string().describe("图片在存储桶里的路径"),
147
+ server.tool('aiSuperResolution', '图片处理-超分辨率', {
148
+ objectKey: z.string().describe('图片在存储桶里的路径'),
162
149
  }, async ({ objectKey }) => {
163
150
  const res = await CIAIInstance.aiSuperResolution(objectKey);
164
151
  return {
165
152
  content: [
166
153
  {
167
- type: "text",
154
+ type: 'text',
168
155
  text: JSON.stringify(res.data, null, 2),
169
156
  isError: res.isSuccess ? false : true,
170
157
  },
171
158
  ],
172
159
  };
173
160
  });
174
- server.tool("aiPicMatting", "图片处理-抠图", {
175
- objectKey: z.string().describe("图片在存储桶里的路径"),
176
- width: z.string().optional().describe("宽度"),
177
- height: z.string().optional().describe("高度"),
178
- }, async ({ objectKey, width = "5", height = "5" }) => {
161
+ server.tool('aiPicMatting', '图片处理-抠图', {
162
+ objectKey: z.string().describe('图片在存储桶里的路径'),
163
+ width: z.string().optional().describe('宽度'),
164
+ height: z.string().optional().describe('高度'),
165
+ }, async ({ objectKey, width = '5', height = '5' }) => {
179
166
  const res = await CIAIInstance.aiPicMatting(objectKey, width, height);
180
167
  return {
181
168
  content: [
182
169
  {
183
- type: "text",
170
+ type: 'text',
184
171
  text: JSON.stringify(res.data, null, 2),
185
172
  isError: res.isSuccess ? false : true,
186
173
  },
187
174
  ],
188
175
  };
189
176
  });
190
- server.tool("aiQrcode", "图片处理-二维码识别-识别存储桶内二维码图片内容", {
191
- objectKey: z.string().describe("COS对象键(完整路径)示例: images/qrcode.jpg"),
177
+ server.tool('aiQrcode', '图片处理-二维码识别-识别存储桶内二维码图片内容', {
178
+ objectKey: z
179
+ .string()
180
+ .describe('COS对象键(完整路径)示例: images/qrcode.jpg'),
192
181
  }, async ({ objectKey }) => {
193
182
  const res = await CIAIInstance.aiQrcode(objectKey);
194
183
  return {
195
184
  content: [
196
185
  {
197
- type: "text",
186
+ type: 'text',
198
187
  text: JSON.stringify(res.data, null, 2),
199
188
  isError: res.isSuccess ? false : true,
200
189
  },
201
190
  ],
202
191
  };
203
192
  });
204
- server.tool("waterMarkFont", "生成带文字水印的图片", {
205
- objectKey: z.string().describe("COS对象键(完整路径)示例: images/photo.jpg"),
206
- text: z.string().describe("水印文字内容(支持中文)").default("test"),
193
+ server.tool('waterMarkFont', '生成带文字水印的图片', {
194
+ objectKey: z
195
+ .string()
196
+ .describe('COS对象键(完整路径)示例: images/photo.jpg'),
197
+ text: z.string().describe('水印文字内容(支持中文)').default('test'),
207
198
  }, async ({ objectKey, text }) => {
208
199
  const res = await CIPicInstance.waterMarkFont({ objectKey, text });
209
200
  return {
210
201
  content: [
211
202
  {
212
- type: "text",
203
+ type: 'text',
213
204
  text: JSON.stringify(res.data, null, 2),
214
205
  isError: res.isSuccess ? false : true,
215
206
  },
@@ -217,28 +208,30 @@ export function createCosMcpServer(config) {
217
208
  };
218
209
  });
219
210
  // --MEDIA--
220
- server.tool("createMediaSmartCoverJob", "创建媒体智能封面任务", {
221
- objectKey: z.string().describe("对象在存储桶里的路径"),
211
+ server.tool('createMediaSmartCoverJob', '创建媒体智能封面任务', {
212
+ objectKey: z.string().describe('对象在存储桶里的路径'),
222
213
  }, async ({ objectKey }) => {
223
214
  const res = await CIMediaInstance.createMediaSmartCoverJob(objectKey);
224
215
  return {
225
216
  content: [
226
217
  {
227
- type: "text",
218
+ type: 'text',
228
219
  text: JSON.stringify(res.data, null, 2),
229
220
  isError: res.isSuccess ? false : true,
230
221
  },
231
222
  ],
232
223
  };
233
224
  });
234
- server.tool("describeMediaJob", "根据 jobid 查询指定的媒体智能封面任务结果", {
235
- jobId: z.string().describe("要查询的任务ID,可通过提交智能封面任务的响应中获取。"),
225
+ server.tool('describeMediaJob', '根据 jobid 查询指定的媒体智能封面任务结果', {
226
+ jobId: z
227
+ .string()
228
+ .describe('要查询的任务ID,可通过提交智能封面任务的响应中获取。'),
236
229
  }, async ({ jobId }) => {
237
230
  const res = await CIMediaInstance.describeMediaJob(jobId);
238
231
  return {
239
232
  content: [
240
233
  {
241
- type: "text",
234
+ type: 'text',
242
235
  text: JSON.stringify(res.data, null, 2),
243
236
  isError: res.isSuccess ? false : true,
244
237
  },
@@ -246,28 +239,28 @@ export function createCosMcpServer(config) {
246
239
  };
247
240
  });
248
241
  // --METAINSIGHT--
249
- server.tool("imageSearchPic", "根据输入的图片,从数据集中检索出与输入的图片内容相似的图片", {
250
- uri: z.string().describe("图片地址"),
242
+ server.tool('imageSearchPic', '根据输入的图片,从数据集中检索出与输入的图片内容相似的图片', {
243
+ uri: z.string().describe('图片地址'),
251
244
  }, async ({ uri }) => {
252
245
  const res = await CIMateInsightInstance.imageSearchPic({ uri });
253
246
  return {
254
247
  content: [
255
248
  {
256
- type: "text",
249
+ type: 'text',
257
250
  text: JSON.stringify(res.data, null, 2),
258
251
  isError: res.isSuccess ? false : true,
259
252
  },
260
253
  ],
261
254
  };
262
255
  });
263
- server.tool("imageSearchText", "根据输入的文本内容,从数据集中检索出与输入的文本内容相符的图片", {
264
- text: z.string().describe("检索的文本"),
256
+ server.tool('imageSearchText', '根据输入的文本内容,从数据集中检索出与输入的文本内容相符的图片', {
257
+ text: z.string().describe('检索的文本'),
265
258
  }, async ({ text }) => {
266
259
  const res = await CIMateInsightInstance.imageSearchText({ text });
267
260
  return {
268
261
  content: [
269
262
  {
270
- type: "text",
263
+ type: 'text',
271
264
  text: JSON.stringify(res.data, null, 2),
272
265
  isError: res.isSuccess ? false : true,
273
266
  },
@@ -275,28 +268,30 @@ export function createCosMcpServer(config) {
275
268
  };
276
269
  });
277
270
  // --DOCMENT--
278
- server.tool("createDocToPdfJob", "创建文档转 pdf 处理任务", {
279
- objectKey: z.string().describe("对象在存储桶里的路径"),
271
+ server.tool('createDocToPdfJob', '创建文档转 pdf 处理任务', {
272
+ objectKey: z.string().describe('对象在存储桶里的路径'),
280
273
  }, async ({ objectKey }) => {
281
274
  const res = await CIDocInstance.createDocToPdfJobs(objectKey);
282
275
  return {
283
276
  content: [
284
277
  {
285
- type: "text",
278
+ type: 'text',
286
279
  text: JSON.stringify(res.data, null, 2),
287
280
  isError: res.isSuccess ? false : true,
288
281
  },
289
282
  ],
290
283
  };
291
284
  });
292
- server.tool("describeDocProcessJob", "根据 jobid 查询指定的文档转码任务结果", {
293
- jobId: z.string().describe("要查询的任务ID,可通过提交文档任务的响应中获取。"),
285
+ server.tool('describeDocProcessJob', '根据 jobid 查询指定的文档转码任务结果', {
286
+ jobId: z
287
+ .string()
288
+ .describe('要查询的任务ID,可通过提交文档任务的响应中获取。'),
294
289
  }, async ({ jobId }) => {
295
290
  const res = await CIDocInstance.describeDocProcessJob(jobId);
296
291
  return {
297
292
  content: [
298
293
  {
299
- type: "text",
294
+ type: 'text',
300
295
  text: JSON.stringify(res.data, null, 2),
301
296
  isError: res.isSuccess ? false : true,
302
297
  },
@@ -310,22 +305,22 @@ export function startWithSSE(server, port = 3001) {
310
305
  // to support multiple simultaneous connections we have a lookup object from
311
306
  // sessionId to transport
312
307
  const transports = {};
313
- app.get("/sse", async (_, res) => {
314
- const transport = new SSEServerTransport("/messages", res);
308
+ app.get('/sse', async (_, res) => {
309
+ const transport = new SSEServerTransport('/messages', res);
315
310
  transports[transport.sessionId] = transport;
316
- res.on("close", () => {
311
+ res.on('close', () => {
317
312
  delete transports[transport.sessionId];
318
313
  });
319
314
  await server.connect(transport);
320
315
  });
321
- app.post("/messages", async (req, res) => {
316
+ app.post('/messages', async (req, res) => {
322
317
  const sessionId = req.query.sessionId;
323
318
  const transport = transports[sessionId];
324
319
  if (transport) {
325
320
  await transport.handlePostMessage(req, res);
326
321
  }
327
322
  else {
328
- res.status(400).send("No transport found for sessionId");
323
+ res.status(400).send('No transport found for sessionId');
329
324
  }
330
325
  });
331
326
  app.listen(port, () => {