Skip to main content
Glama

Tencent Cloud COS MCP Server

Official
by Tencent
cos.service.ts6.27 kB
import COS from 'cos-nodejs-sdk-v5'; import fs from 'fs'; import path from 'path'; import { z } from 'zod'; import axios from 'axios'; import { PassThrough } from 'stream'; import { generateOutPutFileId } from '../utils.js'; import { TEXT_TYPES } from '../constant.js'; export const UploadFileParamsSchema = z.object({ filePath: z.string().optional(), targetDir: z.string().optional(), fileName: z.string().optional(), sourceUrl: z.string().optional() }); export type UploadFileParams = z.infer<typeof UploadFileParamsSchema>; export class CosService { bucket: string; region: string; cos: COS; constructor(bucket: string, region: string, cos: COS) { this.bucket = bucket; this.region = region; this.cos = cos; } // /** // * 上传文件到COS // * @param params 上传参数 // * @returns 上传结果 // */ async uploadFile(params: UploadFileParams) { // 验证并解析参数 const validParams = UploadFileParamsSchema.parse(params); const { filePath, targetDir = '', fileName } = validParams; try { // 检查文件是否存在 if (!filePath || !fs.existsSync(filePath)) { return { isSuccess: false, message: '此路径上文件不存在', data: '此路径上文件不存在: ' + filePath, }; } // 确定文件名 const actualFileName = fileName || path.basename(filePath); // 构建COS路径,确保正斜杠格式 let cosPath = actualFileName; if (targetDir) { // 规范化目标目录:移除头尾斜杠,然后加上结尾斜杠 const normalizedDir = targetDir.replace(/^\/+|\/+$/g, ''); cosPath = normalizedDir ? `${normalizedDir}/${actualFileName}` : actualFileName; } // 上传文件 const cosParams: COS.UploadFileParams = { Bucket: this.bucket, Region: this.region, Key: cosPath, FilePath: filePath, }; const result = await this.cos.uploadFile(cosParams); return { isSuccess: true, message: '上传成功', data: result, }; } catch (error) { return { isSuccess: false, message: '上传失败', data: error, }; } } // /** // * 上传文件到COS // * @param params 上传参数 // * @returns 上传结果 // */ async uploadFileSourceUrl(params: UploadFileParams) { // 验证并解析参数 const validParams = UploadFileParamsSchema.parse(params); const { targetDir = '', fileName, sourceUrl } = validParams; try { const response = await axios({ method: 'get', url: sourceUrl, responseType: 'stream' }); const actualFileName = fileName ? fileName : generateOutPutFileId(''); let cosPath = actualFileName; if (targetDir) { // 规范化目标目录:移除头尾斜杠,然后加上结尾斜杠 const normalizedDir = targetDir.replace(/^\/+|\/+$/g, ''); cosPath = normalizedDir ? `${normalizedDir}/${actualFileName}` : actualFileName; } const req = response.data; const passThrough = new PassThrough(); const result = await this.cos.putObject({ Bucket: this.bucket, Region:this.region, Key: cosPath, Body: req.pipe(passThrough), }); return { isSuccess: true, message: '上传成功', data: result, }; } catch (error) { return { isSuccess: false, message: '上传失败', data: error, }; } } async getObject(objectKey = '/') { try { // 下载文件 const cosParams: COS.GetObjectParams = { Bucket: this.bucket, Region: this.region, Key: objectKey, }; const result = await this.cos.getObject(cosParams); // 统一处理 buffer const buffer = Buffer.isBuffer(result.Body) ? result.Body : Buffer.from(result.Body ?? ''); // 获取 Content-Type,统一小写 let contentType = result.headers && (result.headers['content-type'] || result.headers['Content-Type']); contentType = typeof contentType === 'string' ? contentType.toLowerCase() : ''; let mcpData; if (contentType.startsWith('image/')) { mcpData = { type: 'image', data: buffer.toString('base64'), mimeType: contentType }; } else if (contentType.startsWith('audio/')) { mcpData = { type: 'audio', data: buffer.toString('base64'), mimeType: contentType }; } else if (contentType.startsWith('text/') || TEXT_TYPES.includes(contentType)) { mcpData = { type: 'text', text: buffer.toString('utf-8') }; } else { mcpData = { type: 'text', text: buffer.toString('base64') }; } return { isSuccess: true, message: '下载文件成功', data: mcpData, }; } catch (error) { return { isSuccess: false, message: '下载文件失败', data: error instanceof Error ? error.message : error, }; } } // 获取文件列表 async getBucket(Prefix = '') { try { const result = await this.cos.getBucket({ Bucket: this.bucket, Region: this.region, Prefix, Delimiter: '', }); return { isSuccess: true, message: '获取列表成功', data: result, }; } catch (error) { return { isSuccess: false, message: '获取列表失败', data: error, }; } } //获取带签名的objecturl async getObjectUrl(ObjectKey: string) { try { const result = await new Promise((resolve, reject) => { this.cos.getObjectUrl( { Bucket: this.bucket, Region: this.region, Key: ObjectKey, }, (error, data) => (error ? reject(error) : resolve(data)), ); }); return { isSuccess: true, message: '获取带签名 ObjectUrl 成功', data: result, }; } catch (error) { return { isSuccess: false, message: '获取带签名 ObjectUrl 失败', data: error, }; } } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Tencent/cos-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server