cos-mcp 1.0.7 → 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,11 +23,11 @@ export const Logger = {
22
23
  console.error(...args);
23
24
  },
24
25
  };
25
- const USER_AGENT = `modelcontextprotocol/servers/cos`;
26
+ const USER_AGENT = 'modelcontextprotocol/servers/cos';
26
27
  export function createCosMcpServer(config) {
27
28
  const cos = new COS({
28
- SecretId: config.cosConfig?.SecretId || "",
29
- SecretKey: config.cosConfig?.SecretKey || "",
29
+ SecretId: config.cosConfig?.SecretId || '',
30
+ SecretKey: config.cosConfig?.SecretKey || '',
30
31
  UserAgent: USER_AGENT,
31
32
  });
32
33
  const bucket = config.cosConfig.Bucket;
@@ -36,11 +37,11 @@ export function createCosMcpServer(config) {
36
37
  const CIPicInstance = new CIPicService(bucket, region, cos);
37
38
  const CIMediaInstance = new CIMediaService(bucket, region, cos);
38
39
  const CIAIInstance = new CIAIService(bucket, region, cos);
39
- const CIMateInsightInstance = new CIMateInsightService(bucket, region, datasetName || "", cos);
40
+ const CIMateInsightInstance = new CIMateInsightService(bucket, region, datasetName || '', cos);
40
41
  const CIDocInstance = new CIDocService(bucket, region, cos);
41
42
  const server = new McpServer({
42
- name: "COS MCP Server",
43
- version: "1.0.0",
43
+ name: 'COS MCP Server',
44
+ version: '1.0.0',
44
45
  }, {
45
46
  capabilities: {
46
47
  tools: { listChanged: true },
@@ -49,7 +50,7 @@ export function createCosMcpServer(config) {
49
50
  // logging: {},
50
51
  },
51
52
  });
52
- server.tool("getCosConfig", "获取COS配置, 腾讯云配置", {}, async () => {
53
+ server.tool('getCosConfig', '获取COS配置, 腾讯云配置', {}, async () => {
53
54
  if (config.cosConfig) {
54
55
  config.cosConfig.SecretId = maskSecret(config.cosConfig.SecretId);
55
56
  config.cosConfig.SecretKey = maskSecret(config.cosConfig.SecretKey);
@@ -57,17 +58,20 @@ export function createCosMcpServer(config) {
57
58
  return {
58
59
  content: [
59
60
  {
60
- type: "text",
61
+ type: 'text',
61
62
  text: JSON.stringify(config, null, 2),
62
63
  },
63
64
  ],
64
65
  };
65
66
  });
66
- server.tool("putObject", "上传文件到存储桶", {
67
- filePath: z.string().describe("文件路径 (包含文件名)"),
68
- fileName: z.string().optional().describe("文件名 (存在存储桶里的名称)"),
69
- targetDir: z.string().optional().describe("目标目录 (存在存储桶的哪个目录)"),
70
- }, 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 }) => {
71
75
  const res = await COSInstance.uploadFile({
72
76
  fileName,
73
77
  filePath,
@@ -76,35 +80,35 @@ export function createCosMcpServer(config) {
76
80
  return {
77
81
  content: [
78
82
  {
79
- type: "text",
83
+ type: 'text',
80
84
  text: JSON.stringify(res.data, null, 2),
81
85
  isError: res.isSuccess ? false : true,
82
86
  },
83
87
  ],
84
88
  };
85
89
  });
86
- server.tool("getObject", "下载存储桶内的文件", {
87
- objectKey: z.string().describe("文件的路径"),
88
- }, async ({ objectKey = "/" }) => {
90
+ server.tool('getObject', '下载存储桶内的文件', {
91
+ objectKey: z.string().describe('文件的路径'),
92
+ }, async ({ objectKey = '/' }) => {
89
93
  const res = await COSInstance.getObject(objectKey);
90
94
  return {
91
95
  content: [
92
96
  {
93
- type: "text",
97
+ type: 'text',
94
98
  text: JSON.stringify(res.data, null, 2),
95
99
  isError: res.isSuccess ? false : true,
96
100
  },
97
101
  ],
98
102
  };
99
103
  });
100
- server.tool("getBucket", "查询存储桶内的文件列表", {
101
- Prefix: z.string().optional().describe("文件列表的路径前缀,默认根路径"),
102
- }, async ({ Prefix = "" }) => {
104
+ server.tool('getBucket', '查询存储桶内的文件列表', {
105
+ Prefix: z.string().optional().describe('文件列表的路径前缀,默认根路径'),
106
+ }, async ({ Prefix = '' }) => {
103
107
  const res = await COSInstance.getBucket(Prefix);
104
108
  return {
105
109
  content: [
106
110
  {
107
- type: "text",
111
+ type: 'text',
108
112
  text: JSON.stringify(res.data, null, 2),
109
113
  isError: res.isSuccess ? false : true,
110
114
  },
@@ -112,87 +116,91 @@ export function createCosMcpServer(config) {
112
116
  };
113
117
  });
114
118
  // --CI--
115
- server.tool("imageInfo", "图片处理-获取图片信息", {
116
- objectKey: z.string().describe("图片在存储桶里的路径"),
119
+ server.tool('imageInfo', '图片处理-获取图片信息', {
120
+ objectKey: z.string().describe('图片在存储桶里的路径'),
117
121
  }, async ({ objectKey }) => {
118
122
  const res = await CIPicInstance.imageInfo(objectKey);
119
123
  return {
120
124
  content: [
121
125
  {
122
- type: "text",
126
+ type: 'text',
123
127
  text: JSON.stringify(res.data, null, 2),
124
128
  isError: res.isSuccess ? false : true,
125
129
  },
126
130
  ],
127
131
  };
128
132
  });
129
- server.tool("assessQuality", "图片处理-图片质量评估", {
130
- objectKey: z.string().describe("图片在存储桶里的路径"),
133
+ server.tool('assessQuality', '图片处理-图片质量评估', {
134
+ objectKey: z.string().describe('图片在存储桶里的路径'),
131
135
  }, async ({ objectKey }) => {
132
136
  const res = await CIAIInstance.assessQuality(objectKey);
133
137
  return {
134
138
  content: [
135
139
  {
136
- type: "text",
140
+ type: 'text',
137
141
  text: JSON.stringify(res.data, null, 2),
138
142
  isError: res.isSuccess ? false : true,
139
143
  },
140
144
  ],
141
145
  };
142
146
  });
143
- server.tool("aiSuperResolution", "图片处理-超分辨率", {
144
- objectKey: z.string().describe("图片在存储桶里的路径"),
147
+ server.tool('aiSuperResolution', '图片处理-超分辨率', {
148
+ objectKey: z.string().describe('图片在存储桶里的路径'),
145
149
  }, async ({ objectKey }) => {
146
150
  const res = await CIAIInstance.aiSuperResolution(objectKey);
147
151
  return {
148
152
  content: [
149
153
  {
150
- type: "text",
154
+ type: 'text',
151
155
  text: JSON.stringify(res.data, null, 2),
152
156
  isError: res.isSuccess ? false : true,
153
157
  },
154
158
  ],
155
159
  };
156
160
  });
157
- server.tool("aiPicMatting", "图片处理-抠图", {
158
- objectKey: z.string().describe("图片在存储桶里的路径"),
159
- width: z.string().optional().describe("宽度"),
160
- height: z.string().optional().describe("高度"),
161
- }, 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' }) => {
162
166
  const res = await CIAIInstance.aiPicMatting(objectKey, width, height);
163
167
  return {
164
168
  content: [
165
169
  {
166
- type: "text",
170
+ type: 'text',
167
171
  text: JSON.stringify(res.data, null, 2),
168
172
  isError: res.isSuccess ? false : true,
169
173
  },
170
174
  ],
171
175
  };
172
176
  });
173
- server.tool("aiQrcode", "图片处理-二维码识别-识别存储桶内二维码图片内容", {
174
- objectKey: z.string().describe("COS对象键(完整路径)示例: images/qrcode.jpg"),
177
+ server.tool('aiQrcode', '图片处理-二维码识别-识别存储桶内二维码图片内容', {
178
+ objectKey: z
179
+ .string()
180
+ .describe('COS对象键(完整路径)示例: images/qrcode.jpg'),
175
181
  }, async ({ objectKey }) => {
176
182
  const res = await CIAIInstance.aiQrcode(objectKey);
177
183
  return {
178
184
  content: [
179
185
  {
180
- type: "text",
186
+ type: 'text',
181
187
  text: JSON.stringify(res.data, null, 2),
182
188
  isError: res.isSuccess ? false : true,
183
189
  },
184
190
  ],
185
191
  };
186
192
  });
187
- server.tool("waterMarkFont", "生成带文字水印的图片", {
188
- objectKey: z.string().describe("COS对象键(完整路径)示例: images/photo.jpg"),
189
- 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'),
190
198
  }, async ({ objectKey, text }) => {
191
199
  const res = await CIPicInstance.waterMarkFont({ objectKey, text });
192
200
  return {
193
201
  content: [
194
202
  {
195
- type: "text",
203
+ type: 'text',
196
204
  text: JSON.stringify(res.data, null, 2),
197
205
  isError: res.isSuccess ? false : true,
198
206
  },
@@ -200,28 +208,30 @@ export function createCosMcpServer(config) {
200
208
  };
201
209
  });
202
210
  // --MEDIA--
203
- server.tool("createMediaSmartCoverJob", "创建媒体智能封面任务", {
204
- objectKey: z.string().describe("对象在存储桶里的路径"),
211
+ server.tool('createMediaSmartCoverJob', '创建媒体智能封面任务', {
212
+ objectKey: z.string().describe('对象在存储桶里的路径'),
205
213
  }, async ({ objectKey }) => {
206
214
  const res = await CIMediaInstance.createMediaSmartCoverJob(objectKey);
207
215
  return {
208
216
  content: [
209
217
  {
210
- type: "text",
218
+ type: 'text',
211
219
  text: JSON.stringify(res.data, null, 2),
212
220
  isError: res.isSuccess ? false : true,
213
221
  },
214
222
  ],
215
223
  };
216
224
  });
217
- server.tool("describeMediaJob", "根据 jobid 查询指定的媒体智能封面任务结果", {
218
- jobId: z.string().describe("要查询的任务ID,可通过提交智能封面任务的响应中获取。"),
225
+ server.tool('describeMediaJob', '根据 jobid 查询指定的媒体智能封面任务结果', {
226
+ jobId: z
227
+ .string()
228
+ .describe('要查询的任务ID,可通过提交智能封面任务的响应中获取。'),
219
229
  }, async ({ jobId }) => {
220
230
  const res = await CIMediaInstance.describeMediaJob(jobId);
221
231
  return {
222
232
  content: [
223
233
  {
224
- type: "text",
234
+ type: 'text',
225
235
  text: JSON.stringify(res.data, null, 2),
226
236
  isError: res.isSuccess ? false : true,
227
237
  },
@@ -229,28 +239,28 @@ export function createCosMcpServer(config) {
229
239
  };
230
240
  });
231
241
  // --METAINSIGHT--
232
- server.tool("imageSearchPic", "根据输入的图片,从数据集中检索出与输入的图片内容相似的图片", {
233
- uri: z.string().describe("图片地址"),
242
+ server.tool('imageSearchPic', '根据输入的图片,从数据集中检索出与输入的图片内容相似的图片', {
243
+ uri: z.string().describe('图片地址'),
234
244
  }, async ({ uri }) => {
235
245
  const res = await CIMateInsightInstance.imageSearchPic({ uri });
236
246
  return {
237
247
  content: [
238
248
  {
239
- type: "text",
249
+ type: 'text',
240
250
  text: JSON.stringify(res.data, null, 2),
241
251
  isError: res.isSuccess ? false : true,
242
252
  },
243
253
  ],
244
254
  };
245
255
  });
246
- server.tool("imageSearchText", "根据输入的文本内容,从数据集中检索出与输入的文本内容相符的图片", {
247
- text: z.string().describe("检索的文本"),
256
+ server.tool('imageSearchText', '根据输入的文本内容,从数据集中检索出与输入的文本内容相符的图片', {
257
+ text: z.string().describe('检索的文本'),
248
258
  }, async ({ text }) => {
249
259
  const res = await CIMateInsightInstance.imageSearchText({ text });
250
260
  return {
251
261
  content: [
252
262
  {
253
- type: "text",
263
+ type: 'text',
254
264
  text: JSON.stringify(res.data, null, 2),
255
265
  isError: res.isSuccess ? false : true,
256
266
  },
@@ -258,28 +268,30 @@ export function createCosMcpServer(config) {
258
268
  };
259
269
  });
260
270
  // --DOCMENT--
261
- server.tool("createDocToPdfJob", "创建文档转 pdf 处理任务", {
262
- objectKey: z.string().describe("对象在存储桶里的路径"),
271
+ server.tool('createDocToPdfJob', '创建文档转 pdf 处理任务', {
272
+ objectKey: z.string().describe('对象在存储桶里的路径'),
263
273
  }, async ({ objectKey }) => {
264
274
  const res = await CIDocInstance.createDocToPdfJobs(objectKey);
265
275
  return {
266
276
  content: [
267
277
  {
268
- type: "text",
278
+ type: 'text',
269
279
  text: JSON.stringify(res.data, null, 2),
270
280
  isError: res.isSuccess ? false : true,
271
281
  },
272
282
  ],
273
283
  };
274
284
  });
275
- server.tool("describeDocProcessJob", "根据 jobid 查询指定的文档转码任务结果", {
276
- jobId: z.string().describe("要查询的任务ID,可通过提交文档任务的响应中获取。"),
285
+ server.tool('describeDocProcessJob', '根据 jobid 查询指定的文档转码任务结果', {
286
+ jobId: z
287
+ .string()
288
+ .describe('要查询的任务ID,可通过提交文档任务的响应中获取。'),
277
289
  }, async ({ jobId }) => {
278
290
  const res = await CIDocInstance.describeDocProcessJob(jobId);
279
291
  return {
280
292
  content: [
281
293
  {
282
- type: "text",
294
+ type: 'text',
283
295
  text: JSON.stringify(res.data, null, 2),
284
296
  isError: res.isSuccess ? false : true,
285
297
  },
@@ -293,22 +305,22 @@ export function startWithSSE(server, port = 3001) {
293
305
  // to support multiple simultaneous connections we have a lookup object from
294
306
  // sessionId to transport
295
307
  const transports = {};
296
- app.get("/sse", async (_, res) => {
297
- const transport = new SSEServerTransport("/messages", res);
308
+ app.get('/sse', async (_, res) => {
309
+ const transport = new SSEServerTransport('/messages', res);
298
310
  transports[transport.sessionId] = transport;
299
- res.on("close", () => {
311
+ res.on('close', () => {
300
312
  delete transports[transport.sessionId];
301
313
  });
302
314
  await server.connect(transport);
303
315
  });
304
- app.post("/messages", async (req, res) => {
316
+ app.post('/messages', async (req, res) => {
305
317
  const sessionId = req.query.sessionId;
306
318
  const transport = transports[sessionId];
307
319
  if (transport) {
308
320
  await transport.handlePostMessage(req, res);
309
321
  }
310
322
  else {
311
- res.status(400).send("No transport found for sessionId");
323
+ res.status(400).send('No transport found for sessionId');
312
324
  }
313
325
  });
314
326
  app.listen(port, () => {