oss-mcp-plus 1.0.3

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 ADDED
@@ -0,0 +1,229 @@
1
+ # OSS MCP Plus 🚀
2
+
3
+ > Fork 自 [1yhy/oss-mcp](https://github.com/1yhy/oss-mcp),新增批量重命名、目录列表、文件下载等实用工具。
4
+
5
+ 一个基于 Model Context Protocol (MCP) 的服务器,用于将文件上传到阿里云 OSS。此服务器使大型语言模型能够直接将文件上传到阿里云对象存储服务,并提供文件管理相关的实用工具。
6
+
7
+ ## 💡 使用场景
8
+
9
+ OSS MCP服务器能够与其他MCP工具无缝集成,为您提供强大的工作流程:
10
+
11
+ - **与[Playwright MCP](https://github.com/executeautomation/mcp-playwright)集成**:可以先使用Playwright MCP抓取网页截图或下载网页资源,然后直接上传到阿里云OSS存储。
12
+ - **与[Figma MCP](https://github.com/1yhy/Figma-Context-MCP)集成**:下载图片资源到本地后直接上传OSS、或者Figma网络文件直接上传OSS。
13
+ - **与[Filesystem MCP](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem)集成**:可以浏览和选择本地文件系统中的文件,然后一步上传到云存储。
14
+ - **数据备份流程**:将重要数据从本地或其他服务自动备份到OSS。
15
+ - **媒体处理流程**:结合其他处理工具,可以对图片、视频进行处理后直接上传并获取可访问的URL。
16
+ - **多OSS账号管理**:便捷地在多个OSS账号间切换上传目标。
17
+
18
+ ## ✨ 功能特点
19
+
20
+ - 📁 支持多个阿里云 OSS 配置
21
+ - 🗂️ 可指定上传目录
22
+ - 🔄 简单易用的接口
23
+ - 📥 支持从 URL 下载文件到本地
24
+ - 📂 列出目录文件,支持通配符过滤
25
+ - ✏️ 批量重命名文件,支持预览模式
26
+
27
+ ## 🔧 安装
28
+
29
+ 您可以通过npm或从源码安装:
30
+
31
+ ### 使用npm安装
32
+
33
+ ```bash
34
+ # 使用npm全局安装
35
+ npm install -g oss-mcp-plus
36
+
37
+ # 或使用pnpm全局安装
38
+ pnpm add -g oss-mcp-plus
39
+ ```
40
+
41
+ ### 使用示例
42
+
43
+ ```bash
44
+ # 直接启动 (stdio模式)
45
+ oss-mcp-plus --oss-config='{\"default\":{\"region\":\"oss-cn-shenzhen\",\"accessKeyId\":\"YOUR_KEY\",\"accessKeySecret\":\"YOUR_SECRET\",\"bucket\":\"YOUR_BUCKET\",\"endpoint\":\"oss-cn-shenzhen.aliyuncs.com\"}}'
46
+
47
+
48
+ # 使用Inspector调试
49
+ oss-mcp-plus --oss-config='{ "region": "oss-cn-shenzhen", "accessKeyId": "YOUR_KEY", "accessKeySecret": "YOUR_SECRET", "bucket": "BUCKET_NAME", "endpoint": "oss-cn-shenzhen.aliyuncs.com" }' --inspect
50
+ ```
51
+
52
+ ### 从源码安装
53
+
54
+ ```bash
55
+ # 克隆仓库
56
+ git clone https://github.com/lovelyJason/oss-mcp.git
57
+ cd oss-mcp
58
+
59
+ # 安装依赖
60
+ pnpm install
61
+
62
+ # 构建项目
63
+ pnpm build
64
+ ```
65
+
66
+ ## ⚙️ 配置
67
+
68
+ 您可以通过以下方式配置阿里云OSS参数:
69
+
70
+ ### 方式一:使用.env文件
71
+
72
+ 在项目根目录创建`.env`文件,参考`.env.example`模板。您可以配置多个阿里云OSS服务:
73
+
74
+ ```ini
75
+ # 默认OSS配置
76
+ OSS_CONFIG_DEFAULT={"region":"oss-cn-hangzhou","accessKeyId":"your-access-key-id","accessKeySecret":"your-access-key-secret","bucket":"your-bucket-name","endpoint":"oss-cn-hangzhou.aliyuncs.com"}
77
+
78
+ # 其他OSS配置
79
+ OSS_CONFIG_TEST={"region":"oss-cn-beijing","accessKeyId":"your-access-key-id-2","accessKeySecret":"your-access-key-secret-2","bucket":"your-bucket-name-2","endpoint":"oss-cn-beijing.aliyuncs.com"}
80
+ ```
81
+
82
+ ### 方式二:直接设置环境变量
83
+
84
+ 您也可以直接在系统中或启动命令中设置环境变量:
85
+
86
+ ```bash
87
+ # 设置环境变量并启动
88
+ pnpm dev --oss-config='{ "default": { "region": "oss-cn-shenzhen", "accessKeyId": "YOUR_KEY", "accessKeySecret": "YOUR_SECRET", "bucket": "BUCKET_NAME", "endpoint": "oss-cn-shenzhen.aliyuncs.com" }, "test": { "region": "oss-cn-beijing", "accessKeyId": "YOUR_KEY", "accessKeySecret": "YOUR_SECRET", "bucket": "BUCKET_NAME", "endpoint": "oss-cn-beijing.aliyuncs.com" } }'
89
+ ```
90
+
91
+ ## 🔍 参数说明
92
+
93
+ - `region`: 阿里云OSS区域
94
+ - `accessKeyId`: 阿里云访问密钥ID
95
+ - `accessKeySecret`: 阿里云访问密钥Secret
96
+ - `bucket`: OSS存储桶名称
97
+ - `endpoint`: OSS终端节点
98
+
99
+ ## 📋 使用方法
100
+
101
+ ### 命令行选项
102
+
103
+ ```
104
+ 选项:
105
+ -s, --stdio 使用stdio传输启动服务器
106
+ -h, --http 使用HTTP传输启动服务器
107
+ -p, --port HTTP服务器端口 (默认: 3000)
108
+ -i, --inspect 使用Inspector工具启动
109
+ -?, --help 显示帮助信息
110
+ ```
111
+
112
+
113
+ ### 从源码启动
114
+
115
+ ```bash
116
+ # 开发模式
117
+ pnpm dev
118
+
119
+ # 启动服务 (stdio模式)
120
+ pnpm start
121
+
122
+ # 启动HTTP服务
123
+ pnpm start:http
124
+
125
+ # 使用Inspector调试
126
+ pnpm inspect
127
+ ```
128
+
129
+ ## 🛠️ 与Claude/Cursor配置集成
130
+
131
+ ### Cursor配置方法
132
+
133
+ 1. 在Cursor中打开设置(Settings)
134
+ 2. 转到MCP服务器(MCP Servers)部分
135
+ 3. 添加新服务器配置:
136
+
137
+ ```json
138
+ {
139
+ "mcpServers": {
140
+ "oss-mcp-plus": {
141
+ "command": "npx",
142
+ "args": [
143
+ "oss-mcp-plus",
144
+ "--oss-config='{\"default\":{\"region\":\"oss-cn-shenzhen\",\"accessKeyId\":\"YOUR_KEY\",\"accessKeySecret\":\"YOUR_SECRET\",\"bucket\":\"YOUR_BUCKET\",\"endpoint\":\"oss-cn-shenzhen.aliyuncs.com\"}}'",
145
+ "--stdio"
146
+ ]
147
+ }
148
+ }
149
+ }
150
+ ```
151
+
152
+ ### 配置多个OSS账号
153
+
154
+ 使用环境变量方式可以轻松配置多个OSS账号:
155
+
156
+ ```json
157
+ {
158
+ "mcpServers": {
159
+ "oss-mcp-plus": {
160
+ "command": "npx",
161
+ "args": [
162
+ "oss-mcp-plus",
163
+ "--oss-config='{\"default\":{\"region\":\"oss-cn-shenzhen\",\"accessKeyId\":\"YOUR_KEY\",\"accessKeySecret\":\"YOUR_SECRET\",\"bucket\":\"YOUR_BUCKET\",\"endpoint\":\"oss-cn-shenzhen.aliyuncs.com\"}, \"test\":{\"region\":\"oss-cn-shenzhen\",\"accessKeyId\":\"YOUR_KEY\",\"accessKeySecret\":\"YOUR_SECRET\",\"bucket\":\"YOUR_BUCKET\",\"endpoint\":\"oss-cn-shenzhen.aliyuncs.com\"}}'",
164
+ "--stdio"
165
+ ]
166
+ }
167
+ }
168
+ }
169
+ ```
170
+
171
+ ## 🧰 可用工具
172
+
173
+ 服务器提供以下工具:
174
+
175
+ ### 1. 上传文件到OSS (`upload_to_oss`)
176
+
177
+ **参数**:
178
+ - `filePath`: 本地文件路径(必需)
179
+ - `targetDir`: 目标目录路径(可选)
180
+ - `fileName`: 文件名(可选,默认使用原文件名)
181
+ - `configName`: OSS配置名称(可选,默认使用'default')
182
+
183
+ ### 2. 列出可用的OSS配置 (`list_oss_configs`)
184
+
185
+ 无参数,返回所有可用的OSS配置名称。
186
+
187
+ ### 3. 批量重命名文件 (`batch_rename_files`)
188
+
189
+ 根据规则批量重命名指定目录下的文件,支持预览模式。
190
+
191
+ **参数**:
192
+ - `directory`: 要操作的目录路径(必需)
193
+ - `renameRules`: 重命名规则数组,每项包含 `oldName` 和 `newName`(必需)
194
+ - `dryRun`: 是否为预览模式(可选,默认 false)。为 true 时只返回将要执行的操作,不实际重命名
195
+
196
+ ### 4. 列出目录文件 (`list_directory_files`)
197
+
198
+ 列出指定目录下的所有文件,用于查看当前文件名以便进行重命名操作。
199
+
200
+ **参数**:
201
+ - `directory`: 要查看的目录路径(必需)
202
+ - `pattern`: 文件名过滤模式(可选),如 `*.png` 或 `icon_*`
203
+
204
+ ### 5. 下载文件 (`download_file`)
205
+
206
+ 从 URL 下载文件到本地目录,支持 HTTP/HTTPS 链接。
207
+
208
+ **参数**:
209
+ - `url`: 要下载的文件 URL(必需)
210
+ - `targetDir`: 保存文件的本地目录路径(必需)
211
+ - `fileName`: 保存的文件名(可选,默认从 URL 提取)
212
+
213
+ ## 📦 发布
214
+
215
+ ```bash
216
+ # 发布到npm
217
+ pnpm pub:release
218
+
219
+ # 本地打包测试
220
+ pnpm publish:local
221
+ ```
222
+
223
+ ## 📄 许可证
224
+
225
+ [MIT](LICENSE)
226
+
227
+ ## 🙏 致谢
228
+
229
+ 本项目基于 [1yhy/oss-mcp](https://github.com/1yhy/oss-mcp) 开发,感谢原作者的贡献!
package/dist/index.js ADDED
@@ -0,0 +1,765 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+
6
+ // src/server.ts
7
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
8
+ import { z as z3 } from "zod";
9
+
10
+ // src/services/oss.service.ts
11
+ import OSS from "ali-oss";
12
+ import fs from "fs";
13
+ import path from "path";
14
+
15
+ // src/config/oss.config.ts
16
+ import { config } from "dotenv";
17
+ import yargs from "yargs";
18
+ import { hideBin } from "yargs/helpers";
19
+ import { z } from "zod";
20
+ config();
21
+ var OssConfigSchema = z.object({
22
+ region: z.string(),
23
+ accessKeyId: z.string(),
24
+ accessKeySecret: z.string(),
25
+ bucket: z.string(),
26
+ endpoint: z.string()
27
+ });
28
+ function maskSecret(secret) {
29
+ if (secret.length <= 4) return "****";
30
+ return `${secret.substring(0, 4)}****${secret.slice(-4)}`;
31
+ }
32
+ function getServerConfig(isStdioMode = false) {
33
+ const argv = yargs(hideBin(process.argv)).options({
34
+ "oss-config": {
35
+ type: "string",
36
+ description: "OSS\u914D\u7F6EJSON\u5B57\u7B26\u4E32"
37
+ },
38
+ port: {
39
+ type: "number",
40
+ description: "\u670D\u52A1\u5668\u8FD0\u884C\u7AEF\u53E3",
41
+ default: 3e3
42
+ }
43
+ }).help().version("1.0.0").parseSync();
44
+ const config3 = {
45
+ port: 3e3,
46
+ ossConfig: {},
47
+ configSources: {
48
+ port: "default",
49
+ ossConfig: "default"
50
+ }
51
+ };
52
+ if (argv.port) {
53
+ config3.port = argv.port;
54
+ config3.configSources.port = "cli";
55
+ } else if (process.env.PORT) {
56
+ config3.port = parseInt(process.env.PORT, 10);
57
+ config3.configSources.port = "env";
58
+ }
59
+ if (argv["oss-config"]) {
60
+ const allOssConfigs = JSON.parse(argv["oss-config"]);
61
+ if (allOssConfigs.region && allOssConfigs.accessKeyId) {
62
+ config3.ossConfig.default = OssConfigSchema.parse(allOssConfigs);
63
+ } else {
64
+ Object.entries(allOssConfigs).forEach(([name, cfg]) => {
65
+ config3.ossConfig[name.toLowerCase()] = OssConfigSchema.parse(cfg);
66
+ });
67
+ }
68
+ config3.configSources.ossConfig = "cli";
69
+ } else if (process.env.OSS_CONFIG_DEFAULT) {
70
+ const ossConfig = JSON.parse(process.env.OSS_CONFIG_DEFAULT);
71
+ config3.ossConfig.default = OssConfigSchema.parse(ossConfig);
72
+ config3.configSources.ossConfig = "env";
73
+ }
74
+ Object.entries(process.env).forEach(([key, value]) => {
75
+ if (key.startsWith("OSS_CONFIG_") && key !== "OSS_CONFIG_DEFAULT" && value) {
76
+ try {
77
+ const configName = key.replace("OSS_CONFIG_", "").toLowerCase();
78
+ const ossConfig = JSON.parse(value);
79
+ config3.ossConfig[configName] = OssConfigSchema.parse(ossConfig);
80
+ } catch (error) {
81
+ console.error(`\u89E3\u6790\u73AF\u5883\u53D8\u91CF${key}\u5931\u8D25:`, error);
82
+ }
83
+ }
84
+ });
85
+ if (Object.keys(config3.ossConfig).length === 0) {
86
+ console.warn("\u672A\u627E\u5230\u6709\u6548\u7684OSS\u914D\u7F6E\u3002\u670D\u52A1\u5668\u5C06\u542F\u52A8\uFF0C\u4F46\u4E0A\u4F20\u529F\u80FD\u5C06\u4E0D\u53EF\u7528\u3002");
87
+ }
88
+ if (!isStdioMode) {
89
+ console.log("\n\u914D\u7F6E\u4FE1\u606F:");
90
+ console.log(`- \u7AEF\u53E3: ${config3.port} (\u6765\u6E90: ${config3.configSources.port})`);
91
+ if (Object.keys(config3.ossConfig).length > 0) {
92
+ console.log("- OSS\u914D\u7F6E:");
93
+ Object.entries(config3.ossConfig).forEach(([name, cfg]) => {
94
+ console.log(` - ${name}:`);
95
+ console.log(` Region: ${cfg.region}`);
96
+ console.log(` Endpoint: ${cfg.endpoint}`);
97
+ console.log(` Bucket: ${cfg.bucket}`);
98
+ console.log(` AccessKeyId: ${maskSecret(cfg.accessKeyId)}`);
99
+ console.log(` AccessKeySecret: ${maskSecret(cfg.accessKeySecret)}`);
100
+ });
101
+ } else {
102
+ console.log("- OSS\u914D\u7F6E: \u672A\u627E\u5230");
103
+ }
104
+ console.log();
105
+ }
106
+ return config3;
107
+ }
108
+ function getAllOssConfigs() {
109
+ const { ossConfig } = getServerConfig(true);
110
+ return ossConfig;
111
+ }
112
+ function getOssConfig(name = "default") {
113
+ const configs = getAllOssConfigs();
114
+ const normalizedName = name.toLowerCase();
115
+ return configs[normalizedName] || null;
116
+ }
117
+
118
+ // src/services/oss.service.ts
119
+ import { z as z2 } from "zod";
120
+ var UploadFileParamsSchema = z2.object({
121
+ filePath: z2.string(),
122
+ targetDir: z2.string().optional(),
123
+ fileName: z2.string().optional(),
124
+ configName: z2.string().optional()
125
+ });
126
+ var UploadResultSchema = z2.object({
127
+ success: z2.boolean(),
128
+ url: z2.string().optional(),
129
+ error: z2.string().optional(),
130
+ ossConfigName: z2.string().optional()
131
+ });
132
+ var OssService = class {
133
+ clients = /* @__PURE__ */ new Map();
134
+ /**
135
+ * 获取所有OSS配置
136
+ * @returns OSS配置列表
137
+ */
138
+ getConfigs() {
139
+ const configs = [];
140
+ const allConfigs = getAllOssConfigs();
141
+ for (const [id, config3] of Object.entries(allConfigs)) {
142
+ configs.push({
143
+ id,
144
+ name: `${id.charAt(0).toUpperCase()}${id.slice(1)} \u914D\u7F6E`,
145
+ ...config3
146
+ });
147
+ }
148
+ return configs;
149
+ }
150
+ /**
151
+ * 获取OSS客户端
152
+ * @param configName 配置名称
153
+ * @returns OSS客户端实例
154
+ */
155
+ getClient(configName = "default") {
156
+ if (this.clients.has(configName)) {
157
+ return this.clients.get(configName);
158
+ }
159
+ const config3 = getOssConfig(configName);
160
+ if (!config3) {
161
+ return null;
162
+ }
163
+ try {
164
+ const client = new OSS({
165
+ region: config3.region,
166
+ accessKeyId: config3.accessKeyId,
167
+ accessKeySecret: config3.accessKeySecret,
168
+ bucket: config3.bucket,
169
+ endpoint: config3.endpoint
170
+ });
171
+ this.clients.set(configName, client);
172
+ return client;
173
+ } catch (error) {
174
+ console.error(`Failed to create OSS client for ${configName}:`, error);
175
+ return null;
176
+ }
177
+ }
178
+ /**
179
+ * 上传文件到OSS
180
+ * @param params 上传参数
181
+ * @returns 上传结果
182
+ */
183
+ async uploadFile(params) {
184
+ const validParams = UploadFileParamsSchema.parse(params);
185
+ const { filePath, targetDir = "", fileName, configName = "default" } = validParams;
186
+ try {
187
+ if (!fs.existsSync(filePath)) {
188
+ return UploadResultSchema.parse({
189
+ success: false,
190
+ error: `File not found: ${filePath}`,
191
+ ossConfigName: configName
192
+ });
193
+ }
194
+ const client = this.getClient(configName);
195
+ if (!client) {
196
+ return UploadResultSchema.parse({
197
+ success: false,
198
+ error: `OSS config not found for: ${configName}`,
199
+ ossConfigName: configName
200
+ });
201
+ }
202
+ const actualFileName = fileName || path.basename(filePath);
203
+ let ossPath = actualFileName;
204
+ if (targetDir) {
205
+ const normalizedDir = targetDir.replace(/^\/+|\/+$/g, "");
206
+ ossPath = normalizedDir ? `${normalizedDir}/${actualFileName}` : actualFileName;
207
+ }
208
+ const result = await client.put(ossPath, filePath);
209
+ return UploadResultSchema.parse({
210
+ success: true,
211
+ url: result.url,
212
+ ossConfigName: configName
213
+ });
214
+ } catch (error) {
215
+ return UploadResultSchema.parse({
216
+ success: false,
217
+ error: `Upload failed: ${error.message}`,
218
+ ossConfigName: configName
219
+ });
220
+ }
221
+ }
222
+ };
223
+ var ossService = new OssService();
224
+
225
+ // src/server.ts
226
+ import express from "express";
227
+ import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
228
+ import fs2 from "fs";
229
+ import path2 from "path";
230
+ import https from "https";
231
+ import http from "http";
232
+ var Logger = {
233
+ log: (...args) => {
234
+ console.log(...args);
235
+ },
236
+ error: (...args) => {
237
+ console.error(...args);
238
+ }
239
+ };
240
+ var OssMcpServer = class {
241
+ server;
242
+ sseTransport = null;
243
+ constructor() {
244
+ this.server = new McpServer(
245
+ {
246
+ name: "@yhy2001/oss-mcp",
247
+ version: "1.0.0"
248
+ },
249
+ // 使用正确格式的capabilities配置
250
+ {
251
+ capabilities: {
252
+ tools: { listChanged: true },
253
+ resources: { listChanged: true },
254
+ prompts: { listChanged: true },
255
+ logging: {}
256
+ }
257
+ }
258
+ );
259
+ this.registerTools();
260
+ }
261
+ registerTools() {
262
+ const configs = ossService.getConfigs();
263
+ const configNames = configs.map((config3) => config3.id);
264
+ this.server.tool(
265
+ "upload_to_oss",
266
+ "\u5C06\u6587\u4EF6\u4E0A\u4F20\u5230\u963F\u91CC\u4E91OSS",
267
+ {
268
+ filePath: z3.string().describe("\u8981\u4E0A\u4F20\u7684\u672C\u5730\u6587\u4EF6\u8DEF\u5F84"),
269
+ targetDir: z3.string().optional().describe("OSS\u4E2D\u7684\u76EE\u6807\u76EE\u5F55\u8DEF\u5F84\uFF08\u53EF\u9009\uFF09"),
270
+ fileName: z3.string().optional().describe("\u4E0A\u4F20\u540E\u7684\u6587\u4EF6\u540D\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u539F\u6587\u4EF6\u540D\uFF09"),
271
+ configName: z3.string().optional().describe(`OSS\u914D\u7F6E\u540D\u79F0\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4E3A'default'\uFF09\u3002\u53EF\u7528\u914D\u7F6E: ${configNames.join(", ") || "\u65E0"}`)
272
+ },
273
+ async ({ filePath, targetDir, fileName, configName }) => {
274
+ try {
275
+ Logger.log(`\u51C6\u5907\u4E0A\u4F20: ${filePath} \u5230 ${targetDir || "\u6839\u76EE\u5F55"}`);
276
+ if (!filePath) {
277
+ throw new Error("\u6587\u4EF6\u8DEF\u5F84\u662F\u5FC5\u9700\u7684");
278
+ }
279
+ if (!fs2.existsSync(filePath)) {
280
+ throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${filePath}`);
281
+ }
282
+ const result = await ossService.uploadFile({
283
+ filePath,
284
+ targetDir,
285
+ fileName,
286
+ configName
287
+ });
288
+ if (result.success) {
289
+ Logger.log(`\u4E0A\u4F20\u6210\u529F: ${result.url}`);
290
+ return {
291
+ content: [{
292
+ type: "text",
293
+ text: `\u6587\u4EF6\u4E0A\u4F20\u6210\u529F!
294
+ \u6587\u4EF6\u540D: ${path2.basename(filePath)}
295
+ \u76EE\u6807\u4F4D\u7F6E: ${targetDir || "\u6839\u76EE\u5F55"}
296
+ URL: ${result.url}
297
+ \u914D\u7F6E\u540D\u79F0: ${result.ossConfigName}`
298
+ }]
299
+ };
300
+ } else {
301
+ Logger.error(`\u4E0A\u4F20\u5931\u8D25: ${result.error}`);
302
+ return {
303
+ isError: true,
304
+ content: [{
305
+ type: "text",
306
+ text: `\u4E0A\u4F20\u5931\u8D25: ${result.error}`
307
+ }]
308
+ };
309
+ }
310
+ } catch (error) {
311
+ Logger.error(`\u4E0A\u4F20\u8FC7\u7A0B\u4E2D\u51FA\u9519:`, error);
312
+ return {
313
+ isError: true,
314
+ content: [{
315
+ type: "text",
316
+ text: `\u4E0A\u4F20\u51FA\u9519: ${error}`
317
+ }]
318
+ };
319
+ }
320
+ }
321
+ );
322
+ this.server.tool(
323
+ "list_oss_configs",
324
+ "\u5217\u51FA\u53EF\u7528\u7684\u963F\u91CC\u4E91OSS\u914D\u7F6E",
325
+ {},
326
+ async () => {
327
+ try {
328
+ const configs2 = ossService.getConfigs();
329
+ const configNames2 = configs2.map((config3) => config3.id);
330
+ if (configNames2.length === 0) {
331
+ return {
332
+ content: [{
333
+ type: "text",
334
+ text: "\u672A\u627E\u5230OSS\u914D\u7F6E\u3002\u8BF7\u68C0\u67E5\u73AF\u5883\u53D8\u91CF\u8BBE\u7F6E\u3002"
335
+ }]
336
+ };
337
+ }
338
+ return {
339
+ content: [{
340
+ type: "text",
341
+ text: `\u53EF\u7528\u7684OSS\u914D\u7F6E:
342
+ ${configNames2.map((name) => `- ${name}`).join("\n")}`
343
+ }]
344
+ };
345
+ } catch (error) {
346
+ Logger.error(`\u83B7\u53D6OSS\u914D\u7F6E\u5217\u8868\u65F6\u51FA\u9519:`, error);
347
+ return {
348
+ isError: true,
349
+ content: [{
350
+ type: "text",
351
+ text: `\u83B7\u53D6\u914D\u7F6E\u5217\u8868\u5931\u8D25: ${error}`
352
+ }]
353
+ };
354
+ }
355
+ }
356
+ );
357
+ this.server.tool(
358
+ "batch_rename_files",
359
+ "\u6839\u636E\u81EA\u7136\u8BED\u8A00\u63CF\u8FF0\u6279\u91CF\u91CD\u547D\u540D\u6587\u4EF6\u3002\u652F\u6301\u6307\u5B9A\u76EE\u5F55\u4E0B\u7684\u6587\u4EF6\u6279\u91CF\u91CD\u547D\u540D\uFF0CAI\u4F1A\u7406\u89E3\u4F60\u7684\u91CD\u547D\u540D\u610F\u56FE\u5E76\u6267\u884C\u3002",
360
+ {
361
+ directory: z3.string().describe("\u8981\u64CD\u4F5C\u7684\u76EE\u5F55\u8DEF\u5F84"),
362
+ renameRules: z3.array(z3.object({
363
+ oldName: z3.string().describe("\u539F\u6587\u4EF6\u540D"),
364
+ newName: z3.string().describe("\u65B0\u6587\u4EF6\u540D")
365
+ })).describe("\u91CD\u547D\u540D\u89C4\u5219\u6570\u7EC4\uFF0C\u6BCF\u9879\u5305\u542B\u539F\u6587\u4EF6\u540D\u548C\u65B0\u6587\u4EF6\u540D"),
366
+ dryRun: z3.boolean().optional().describe("\u662F\u5426\u4E3A\u9884\u89C8\u6A21\u5F0F\uFF08\u9ED8\u8BA4false\uFF09\u3002\u4E3Atrue\u65F6\u53EA\u8FD4\u56DE\u5C06\u8981\u6267\u884C\u7684\u64CD\u4F5C\uFF0C\u4E0D\u5B9E\u9645\u91CD\u547D\u540D")
367
+ },
368
+ async ({ directory, renameRules, dryRun = false }) => {
369
+ try {
370
+ Logger.log(`\u6279\u91CF\u91CD\u547D\u540D: \u76EE\u5F55=${directory}, \u89C4\u5219\u6570=${renameRules.length}, \u9884\u89C8\u6A21\u5F0F=${dryRun}`);
371
+ if (!fs2.existsSync(directory)) {
372
+ throw new Error(`\u76EE\u5F55\u4E0D\u5B58\u5728: ${directory}`);
373
+ }
374
+ const stat = fs2.statSync(directory);
375
+ if (!stat.isDirectory()) {
376
+ throw new Error(`\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${directory}`);
377
+ }
378
+ const results = [];
379
+ for (const rule of renameRules) {
380
+ const oldPath = path2.join(directory, rule.oldName);
381
+ const newPath = path2.join(directory, rule.newName);
382
+ if (!fs2.existsSync(oldPath)) {
383
+ results.push({
384
+ oldName: rule.oldName,
385
+ newName: rule.newName,
386
+ success: false,
387
+ error: "\u6E90\u6587\u4EF6\u4E0D\u5B58\u5728"
388
+ });
389
+ continue;
390
+ }
391
+ if (fs2.existsSync(newPath) && oldPath !== newPath) {
392
+ results.push({
393
+ oldName: rule.oldName,
394
+ newName: rule.newName,
395
+ success: false,
396
+ error: "\u76EE\u6807\u6587\u4EF6\u540D\u5DF2\u5B58\u5728"
397
+ });
398
+ continue;
399
+ }
400
+ if (dryRun) {
401
+ results.push({
402
+ oldName: rule.oldName,
403
+ newName: rule.newName,
404
+ success: true
405
+ });
406
+ } else {
407
+ try {
408
+ fs2.renameSync(oldPath, newPath);
409
+ results.push({
410
+ oldName: rule.oldName,
411
+ newName: rule.newName,
412
+ success: true
413
+ });
414
+ } catch (err) {
415
+ results.push({
416
+ oldName: rule.oldName,
417
+ newName: rule.newName,
418
+ success: false,
419
+ error: String(err)
420
+ });
421
+ }
422
+ }
423
+ }
424
+ const successCount = results.filter((r) => r.success).length;
425
+ const failCount = results.filter((r) => !r.success).length;
426
+ let resultText = dryRun ? "\u3010\u9884\u89C8\u6A21\u5F0F\u3011\u4EE5\u4E0B\u662F\u5C06\u8981\u6267\u884C\u7684\u91CD\u547D\u540D\u64CD\u4F5C:\n\n" : "\u6279\u91CF\u91CD\u547D\u540D\u5B8C\u6210:\n\n";
427
+ resultText += `\u6210\u529F: ${successCount} \u4E2A, \u5931\u8D25: ${failCount} \u4E2A
428
+
429
+ `;
430
+ if (results.length > 0) {
431
+ resultText += "\u8BE6\u7EC6\u7ED3\u679C:\n";
432
+ for (const r of results) {
433
+ if (r.success) {
434
+ resultText += `\u2705 ${r.oldName} \u2192 ${r.newName}
435
+ `;
436
+ } else {
437
+ resultText += `\u274C ${r.oldName} \u2192 ${r.newName} (${r.error})
438
+ `;
439
+ }
440
+ }
441
+ }
442
+ return {
443
+ content: [{
444
+ type: "text",
445
+ text: resultText
446
+ }]
447
+ };
448
+ } catch (error) {
449
+ Logger.error(`\u6279\u91CF\u91CD\u547D\u540D\u51FA\u9519:`, error);
450
+ return {
451
+ isError: true,
452
+ content: [{
453
+ type: "text",
454
+ text: `\u6279\u91CF\u91CD\u547D\u540D\u5931\u8D25: ${error}`
455
+ }]
456
+ };
457
+ }
458
+ }
459
+ );
460
+ this.server.tool(
461
+ "list_directory_files",
462
+ "\u5217\u51FA\u6307\u5B9A\u76EE\u5F55\u4E0B\u7684\u6240\u6709\u6587\u4EF6\uFF0C\u7528\u4E8E\u67E5\u770B\u5F53\u524D\u6587\u4EF6\u540D\u4EE5\u4FBF\u8FDB\u884C\u91CD\u547D\u540D\u64CD\u4F5C",
463
+ {
464
+ directory: z3.string().describe("\u8981\u67E5\u770B\u7684\u76EE\u5F55\u8DEF\u5F84"),
465
+ pattern: z3.string().optional().describe("\u6587\u4EF6\u540D\u8FC7\u6EE4\u6A21\u5F0F\uFF08\u53EF\u9009\uFF09\uFF0C\u5982 '*.png' \u6216 'icon_*'")
466
+ },
467
+ async ({ directory, pattern }) => {
468
+ try {
469
+ Logger.log(`\u5217\u51FA\u76EE\u5F55\u6587\u4EF6: ${directory}, \u8FC7\u6EE4: ${pattern || "\u65E0"}`);
470
+ if (!fs2.existsSync(directory)) {
471
+ throw new Error(`\u76EE\u5F55\u4E0D\u5B58\u5728: ${directory}`);
472
+ }
473
+ const stat = fs2.statSync(directory);
474
+ if (!stat.isDirectory()) {
475
+ throw new Error(`\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${directory}`);
476
+ }
477
+ let files = fs2.readdirSync(directory);
478
+ files = files.filter((f) => !f.startsWith("."));
479
+ if (pattern) {
480
+ const regex = new RegExp(
481
+ "^" + pattern.replace(/\./g, "\\.").replace(/\*/g, ".*").replace(/\?/g, ".") + "$",
482
+ "i"
483
+ );
484
+ files = files.filter((f) => regex.test(f));
485
+ }
486
+ const fileInfos = files.map((f) => {
487
+ const filePath = path2.join(directory, f);
488
+ const fileStat = fs2.statSync(filePath);
489
+ return {
490
+ name: f,
491
+ isDirectory: fileStat.isDirectory(),
492
+ size: fileStat.size
493
+ };
494
+ });
495
+ fileInfos.sort((a, b) => {
496
+ if (a.isDirectory !== b.isDirectory) {
497
+ return a.isDirectory ? -1 : 1;
498
+ }
499
+ return a.name.localeCompare(b.name);
500
+ });
501
+ if (fileInfos.length === 0) {
502
+ return {
503
+ content: [{
504
+ type: "text",
505
+ text: `\u76EE\u5F55 ${directory} \u4E0B\u6CA1\u6709\u627E\u5230\u5339\u914D\u7684\u6587\u4EF6${pattern ? ` (\u8FC7\u6EE4: ${pattern})` : ""}`
506
+ }]
507
+ };
508
+ }
509
+ let resultText = `\u76EE\u5F55: ${directory}
510
+ `;
511
+ if (pattern) {
512
+ resultText += `\u8FC7\u6EE4: ${pattern}
513
+ `;
514
+ }
515
+ resultText += `\u5171 ${fileInfos.length} \u4E2A\u9879\u76EE:
516
+
517
+ `;
518
+ for (const f of fileInfos) {
519
+ if (f.isDirectory) {
520
+ resultText += `\u{1F4C1} ${f.name}/
521
+ `;
522
+ } else {
523
+ const sizeStr = f.size < 1024 ? `${f.size}B` : f.size < 1024 * 1024 ? `${(f.size / 1024).toFixed(1)}KB` : `${(f.size / 1024 / 1024).toFixed(1)}MB`;
524
+ resultText += `\u{1F4C4} ${f.name} (${sizeStr})
525
+ `;
526
+ }
527
+ }
528
+ return {
529
+ content: [{
530
+ type: "text",
531
+ text: resultText
532
+ }]
533
+ };
534
+ } catch (error) {
535
+ Logger.error(`\u5217\u51FA\u76EE\u5F55\u6587\u4EF6\u51FA\u9519:`, error);
536
+ return {
537
+ isError: true,
538
+ content: [{
539
+ type: "text",
540
+ text: `\u5217\u51FA\u76EE\u5F55\u5931\u8D25: ${error}`
541
+ }]
542
+ };
543
+ }
544
+ }
545
+ );
546
+ this.server.tool(
547
+ "download_file",
548
+ "\u4ECE URL \u4E0B\u8F7D\u6587\u4EF6\u5230\u672C\u5730\u76EE\u5F55\u3002\u652F\u6301 HTTP/HTTPS \u94FE\u63A5\uFF0C\u53EF\u81EA\u5B9A\u4E49\u4FDD\u5B58\u6587\u4EF6\u540D\u3002",
549
+ {
550
+ url: z3.string().describe("\u8981\u4E0B\u8F7D\u7684\u6587\u4EF6 URL"),
551
+ targetDir: z3.string().describe("\u4FDD\u5B58\u6587\u4EF6\u7684\u672C\u5730\u76EE\u5F55\u8DEF\u5F84"),
552
+ fileName: z3.string().optional().describe("\u4FDD\u5B58\u7684\u6587\u4EF6\u540D\uFF08\u53EF\u9009\uFF0C\u9ED8\u8BA4\u4ECE URL \u63D0\u53D6\uFF09")
553
+ },
554
+ async ({ url, targetDir, fileName }) => {
555
+ try {
556
+ Logger.log(`\u4E0B\u8F7D\u6587\u4EF6: ${url} \u5230 ${targetDir}`);
557
+ if (!fs2.existsSync(targetDir)) {
558
+ fs2.mkdirSync(targetDir, { recursive: true });
559
+ Logger.log(`\u521B\u5EFA\u76EE\u5F55: ${targetDir}`);
560
+ }
561
+ const stat = fs2.statSync(targetDir);
562
+ if (!stat.isDirectory()) {
563
+ throw new Error(`\u8DEF\u5F84\u4E0D\u662F\u76EE\u5F55: ${targetDir}`);
564
+ }
565
+ let finalFileName = fileName;
566
+ if (!finalFileName) {
567
+ const urlObj = new URL(url);
568
+ finalFileName = path2.basename(urlObj.pathname);
569
+ if (!finalFileName || finalFileName === "/") {
570
+ finalFileName = `download_${Date.now()}`;
571
+ }
572
+ }
573
+ const filePath = path2.join(targetDir, finalFileName);
574
+ if (fs2.existsSync(filePath)) {
575
+ throw new Error(`\u6587\u4EF6\u5DF2\u5B58\u5728: ${filePath}`);
576
+ }
577
+ await new Promise((resolve2, reject) => {
578
+ const urlObj = new URL(url);
579
+ const protocol = urlObj.protocol === "https:" ? https : http;
580
+ const request = protocol.get(url, (response) => {
581
+ if (response.statusCode === 301 || response.statusCode === 302) {
582
+ const redirectUrl = response.headers.location;
583
+ if (redirectUrl) {
584
+ Logger.log(`\u91CD\u5B9A\u5411\u5230: ${redirectUrl}`);
585
+ const redirectProtocol = redirectUrl.startsWith("https:") ? https : http;
586
+ redirectProtocol.get(redirectUrl, (redirectResponse) => {
587
+ if (redirectResponse.statusCode !== 200) {
588
+ reject(new Error(`\u4E0B\u8F7D\u5931\u8D25\uFF0CHTTP \u72B6\u6001\u7801: ${redirectResponse.statusCode}`));
589
+ return;
590
+ }
591
+ const fileStream2 = fs2.createWriteStream(filePath);
592
+ redirectResponse.pipe(fileStream2);
593
+ fileStream2.on("finish", () => {
594
+ fileStream2.close();
595
+ resolve2();
596
+ });
597
+ fileStream2.on("error", (err) => {
598
+ fs2.unlink(filePath, () => {
599
+ });
600
+ reject(err);
601
+ });
602
+ }).on("error", reject);
603
+ return;
604
+ }
605
+ }
606
+ if (response.statusCode !== 200) {
607
+ reject(new Error(`\u4E0B\u8F7D\u5931\u8D25\uFF0CHTTP \u72B6\u6001\u7801: ${response.statusCode}`));
608
+ return;
609
+ }
610
+ const fileStream = fs2.createWriteStream(filePath);
611
+ response.pipe(fileStream);
612
+ fileStream.on("finish", () => {
613
+ fileStream.close();
614
+ resolve2();
615
+ });
616
+ fileStream.on("error", (err) => {
617
+ fs2.unlink(filePath, () => {
618
+ });
619
+ reject(err);
620
+ });
621
+ });
622
+ request.on("error", (err) => {
623
+ fs2.unlink(filePath, () => {
624
+ });
625
+ reject(err);
626
+ });
627
+ request.setTimeout(6e4, () => {
628
+ request.destroy();
629
+ fs2.unlink(filePath, () => {
630
+ });
631
+ reject(new Error("\u4E0B\u8F7D\u8D85\u65F6\uFF0860\u79D2\uFF09"));
632
+ });
633
+ });
634
+ const downloadedStat = fs2.statSync(filePath);
635
+ const sizeStr = downloadedStat.size < 1024 ? `${downloadedStat.size}B` : downloadedStat.size < 1024 * 1024 ? `${(downloadedStat.size / 1024).toFixed(1)}KB` : `${(downloadedStat.size / 1024 / 1024).toFixed(1)}MB`;
636
+ return {
637
+ content: [{
638
+ type: "text",
639
+ text: `\u6587\u4EF6\u4E0B\u8F7D\u6210\u529F!
640
+ \u6E90URL: ${url}
641
+ \u4FDD\u5B58\u8DEF\u5F84: ${filePath}
642
+ \u6587\u4EF6\u5927\u5C0F: ${sizeStr}`
643
+ }]
644
+ };
645
+ } catch (error) {
646
+ Logger.error(`\u4E0B\u8F7D\u6587\u4EF6\u51FA\u9519:`, error);
647
+ return {
648
+ isError: true,
649
+ content: [{
650
+ type: "text",
651
+ text: `\u4E0B\u8F7D\u5931\u8D25: ${error}`
652
+ }]
653
+ };
654
+ }
655
+ }
656
+ );
657
+ }
658
+ async connect(transport) {
659
+ try {
660
+ await this.server.connect(transport);
661
+ Logger.log = (...args) => {
662
+ try {
663
+ this.server.server.sendLoggingMessage({
664
+ level: "info",
665
+ data: args
666
+ });
667
+ } catch (error) {
668
+ console.log(...args);
669
+ }
670
+ };
671
+ Logger.error = (...args) => {
672
+ try {
673
+ this.server.server.sendLoggingMessage({
674
+ level: "error",
675
+ data: args
676
+ });
677
+ } catch (error) {
678
+ console.error(...args);
679
+ }
680
+ };
681
+ Logger.log("OSS MCP\u670D\u52A1\u5668\u5DF2\u8FDE\u63A5\u5E76\u51C6\u5907\u5904\u7406\u8BF7\u6C42");
682
+ } catch (error) {
683
+ console.error("\u8FDE\u63A5\u5230\u4F20\u8F93\u65F6\u51FA\u9519:", error);
684
+ }
685
+ }
686
+ async startHttpServer(port) {
687
+ const app = express();
688
+ app.get("/sse", (req, res) => {
689
+ this.sseTransport = new SSEServerTransport(
690
+ "/messages",
691
+ res
692
+ );
693
+ try {
694
+ this.server.connect(this.sseTransport).catch((err) => {
695
+ console.error("\u8FDE\u63A5\u5230SSE\u4F20\u8F93\u65F6\u51FA\u9519:", err);
696
+ });
697
+ req.on("close", () => {
698
+ console.log("SSE\u5BA2\u6237\u7AEF\u65AD\u5F00\u8FDE\u63A5");
699
+ this.sseTransport = null;
700
+ });
701
+ } catch (error) {
702
+ console.error("\u5EFA\u7ACBSSE\u8FDE\u63A5\u65F6\u51FA\u9519:", error);
703
+ if (!res.writableEnded) {
704
+ res.status(500).end();
705
+ }
706
+ }
707
+ });
708
+ app.post("/messages", async (req, res) => {
709
+ if (!this.sseTransport) {
710
+ console.log("\u5C1D\u8BD5\u53D1\u9001\u6D88\u606F\uFF0C\u4F46SSE\u4F20\u8F93\u672A\u521D\u59CB\u5316");
711
+ res.status(400).json({
712
+ error: "SSE\u8FDE\u63A5\u672A\u5EFA\u7ACB",
713
+ message: "\u8BF7\u5148\u8FDE\u63A5\u5230/sse\u7AEF\u70B9"
714
+ });
715
+ return;
716
+ }
717
+ try {
718
+ await this.sseTransport.handlePostMessage(
719
+ req,
720
+ res
721
+ );
722
+ } catch (error) {
723
+ console.error("\u5904\u7406\u6D88\u606F\u65F6\u51FA\u9519:", error);
724
+ if (!res.writableEnded) {
725
+ res.status(500).json({
726
+ error: "\u5185\u90E8\u670D\u52A1\u5668\u9519\u8BEF",
727
+ message: String(error)
728
+ });
729
+ }
730
+ }
731
+ });
732
+ app.listen(port, () => {
733
+ Logger.log = console.log;
734
+ Logger.error = console.error;
735
+ Logger.log(`HTTP\u670D\u52A1\u5668\u76D1\u542C\u7AEF\u53E3: ${port}`);
736
+ Logger.log(`SSE\u7AEF\u70B9: http://localhost:${port}/sse`);
737
+ Logger.log(`\u6D88\u606F\u7AEF\u70B9: http://localhost:${port}/messages`);
738
+ });
739
+ }
740
+ };
741
+
742
+ // src/index.ts
743
+ import { resolve } from "path";
744
+ import { config as config2 } from "dotenv";
745
+ config2({ path: resolve(process.cwd(), ".env") });
746
+ async function startServer() {
747
+ const isStdioMode = process.env.NODE_ENV === "cli" || process.argv.includes("--stdio");
748
+ const serverConfig = getServerConfig(isStdioMode);
749
+ const server = new OssMcpServer();
750
+ if (isStdioMode) {
751
+ const transport = new StdioServerTransport();
752
+ await server.connect(transport);
753
+ } else {
754
+ console.log(`\u521D\u59CB\u5316OSS MCP\u670D\u52A1\u5668\uFF0CHTTP\u6A21\u5F0F\uFF0C\u7AEF\u53E3: ${serverConfig.port}...`);
755
+ await server.startHttpServer(serverConfig.port);
756
+ }
757
+ }
758
+ startServer().catch((error) => {
759
+ console.error("\u542F\u52A8\u670D\u52A1\u5668\u5931\u8D25:", error);
760
+ process.exit(1);
761
+ });
762
+ export {
763
+ startServer
764
+ };
765
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/services/oss.service.ts","../src/config/oss.config.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * 实现阿里云OSS文件上传功能。\n * - 上传文件到阿里云OSS\n * - 获取可用的OSS配置\n */\n\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { OssMcpServer } from \"./server.js\";\nimport { getServerConfig } from \"./config/oss.config.js\";\nimport { resolve } from \"path\";\nimport { config } from \"dotenv\";\n\n// 加载当前工作目录中的.env文件\nconfig({ path: resolve(process.cwd(), \".env\") });\n\nexport async function startServer(): Promise<void> {\n // 检查是否在stdio模式下运行\n const isStdioMode = process.env.NODE_ENV === \"cli\" || process.argv.includes(\"--stdio\");\n\n // 获取服务器配置\n const serverConfig = getServerConfig(isStdioMode);\n\n // 创建OSS MCP服务器\n const server = new OssMcpServer();\n\n if (isStdioMode) {\n // 在stdio模式下运行\n const transport = new StdioServerTransport();\n await server.connect(transport);\n } else {\n // 在HTTP模式下运行\n console.log(`初始化OSS MCP服务器,HTTP模式,端口: ${serverConfig.port}...`);\n await server.startHttpServer(serverConfig.port);\n }\n}\n\n// 启动服务器\nstartServer().catch((error) => {\n console.error(\"启动服务器失败:\", error);\n process.exit(1);\n});\n","import { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport { ossService } from \"./services/oss.service.js\";\nimport express, { Request, Response } from \"express\";\nimport { SSEServerTransport } from \"@modelcontextprotocol/sdk/server/sse.js\";\nimport { IncomingMessage, ServerResponse } from \"http\";\nimport { Transport } from \"@modelcontextprotocol/sdk/shared/transport.js\";\nimport fs from 'fs';\nimport path from 'path';\nimport https from 'https';\nimport http from 'http';\n\nexport const Logger = {\n log: (...args: any[]) => {\n console.log(...args);\n },\n error: (...args: any[]) => {\n console.error(...args);\n }\n};\n\nexport class OssMcpServer {\n private readonly server: McpServer;\n private sseTransport: SSEServerTransport | null = null;\n\n constructor() {\n this.server = new McpServer(\n {\n name: \"@yhy2001/oss-mcp\",\n version: \"1.0.0\",\n },\n // 使用正确格式的capabilities配置\n {\n capabilities: {\n tools: { listChanged: true },\n resources: { listChanged: true },\n prompts: { listChanged: true },\n logging: {}\n }\n }\n );\n\n this.registerTools();\n }\n\n private registerTools(): void {\n // 获取可用的OSS配置\n const configs = ossService.getConfigs();\n const configNames = configs.map(config => config.id);\n\n // 工具:上传文件到OSS\n this.server.tool(\n \"upload_to_oss\",\n \"将文件上传到阿里云OSS\",\n {\n filePath: z.string().describe(\"要上传的本地文件路径\"),\n targetDir: z.string().optional().describe(\"OSS中的目标目录路径(可选)\"),\n fileName: z.string().optional().describe(\"上传后的文件名(可选,默认使用原文件名)\"),\n configName: z.string().optional().describe(`OSS配置名称(可选,默认为'default')。可用配置: ${configNames.join(', ') || '无'}`)\n },\n async ({ filePath, targetDir, fileName, configName }) => {\n try {\n Logger.log(`准备上传: ${filePath} 到 ${targetDir || '根目录'}`);\n\n if (!filePath) {\n throw new Error(\"文件路径是必需的\");\n }\n\n // 检查文件是否存在\n if (!fs.existsSync(filePath)) {\n throw new Error(`文件不存在: ${filePath}`);\n }\n\n // 执行上传\n const result = await ossService.uploadFile({\n filePath,\n targetDir,\n fileName,\n configName\n });\n\n if (result.success) {\n Logger.log(`上传成功: ${result.url}`);\n return {\n content: [{\n type: \"text\",\n text: `文件上传成功!\\n文件名: ${path.basename(filePath)}\\n目标位置: ${targetDir || '根目录'}\\nURL: ${result.url}\\n配置名称: ${result.ossConfigName}`\n }]\n };\n } else {\n Logger.error(`上传失败: ${result.error}`);\n return {\n isError: true,\n content: [{\n type: \"text\",\n text: `上传失败: ${result.error}`\n }]\n };\n }\n } catch (error) {\n Logger.error(`上传过程中出错:`, error);\n return {\n isError: true,\n content: [{\n type: \"text\",\n text: `上传出错: ${error}`\n }]\n };\n }\n }\n );\n\n // 工具:列出可用的OSS配置\n this.server.tool(\n \"list_oss_configs\",\n \"列出可用的阿里云OSS配置\",\n {},\n async () => {\n try {\n const configs = ossService.getConfigs();\n const configNames = configs.map(config => config.id);\n\n if (configNames.length === 0) {\n return {\n content: [{\n type: \"text\",\n text: \"未找到OSS配置。请检查环境变量设置。\"\n }]\n };\n }\n\n return {\n content: [{\n type: \"text\",\n text: `可用的OSS配置:\\n${configNames.map(name => `- ${name}`).join('\\n')}`\n }]\n };\n } catch (error) {\n Logger.error(`获取OSS配置列表时出错:`, error);\n return {\n isError: true,\n content: [{\n type: \"text\",\n text: `获取配置列表失败: ${error}`\n }]\n };\n }\n }\n );\n\n // 工具:批量重命名文件\n this.server.tool(\n \"batch_rename_files\",\n \"根据自然语言描述批量重命名文件。支持指定目录下的文件批量重命名,AI会理解你的重命名意图并执行。\",\n {\n directory: z.string().describe(\"要操作的目录路径\"),\n renameRules: z.array(z.object({\n oldName: z.string().describe(\"原文件名\"),\n newName: z.string().describe(\"新文件名\")\n })).describe(\"重命名规则数组,每项包含原文件名和新文件名\"),\n dryRun: z.boolean().optional().describe(\"是否为预览模式(默认false)。为true时只返回将要执行的操作,不实际重命名\")\n },\n async ({ directory, renameRules, dryRun = false }) => {\n try {\n Logger.log(`批量重命名: 目录=${directory}, 规则数=${renameRules.length}, 预览模式=${dryRun}`);\n\n // 检查目录是否存在\n if (!fs.existsSync(directory)) {\n throw new Error(`目录不存在: ${directory}`);\n }\n\n const stat = fs.statSync(directory);\n if (!stat.isDirectory()) {\n throw new Error(`路径不是目录: ${directory}`);\n }\n\n const results: { oldName: string; newName: string; success: boolean; error?: string }[] = [];\n\n for (const rule of renameRules) {\n const oldPath = path.join(directory, rule.oldName);\n const newPath = path.join(directory, rule.newName);\n\n // 检查源文件是否存在\n if (!fs.existsSync(oldPath)) {\n results.push({\n oldName: rule.oldName,\n newName: rule.newName,\n success: false,\n error: '源文件不存在'\n });\n continue;\n }\n\n // 检查目标文件是否已存在\n if (fs.existsSync(newPath) && oldPath !== newPath) {\n results.push({\n oldName: rule.oldName,\n newName: rule.newName,\n success: false,\n error: '目标文件名已存在'\n });\n continue;\n }\n\n if (dryRun) {\n // 预览模式,不实际执行\n results.push({\n oldName: rule.oldName,\n newName: rule.newName,\n success: true\n });\n } else {\n // 实际执行重命名\n try {\n fs.renameSync(oldPath, newPath);\n results.push({\n oldName: rule.oldName,\n newName: rule.newName,\n success: true\n });\n } catch (err) {\n results.push({\n oldName: rule.oldName,\n newName: rule.newName,\n success: false,\n error: String(err)\n });\n }\n }\n }\n\n const successCount = results.filter(r => r.success).length;\n const failCount = results.filter(r => !r.success).length;\n\n let resultText = dryRun ? '【预览模式】以下是将要执行的重命名操作:\\n\\n' : '批量重命名完成:\\n\\n';\n resultText += `成功: ${successCount} 个, 失败: ${failCount} 个\\n\\n`;\n\n if (results.length > 0) {\n resultText += '详细结果:\\n';\n for (const r of results) {\n if (r.success) {\n resultText += `✅ ${r.oldName} → ${r.newName}\\n`;\n } else {\n resultText += `❌ ${r.oldName} → ${r.newName} (${r.error})\\n`;\n }\n }\n }\n\n return {\n content: [{\n type: \"text\",\n text: resultText\n }]\n };\n } catch (error) {\n Logger.error(`批量重命名出错:`, error);\n return {\n isError: true,\n content: [{\n type: \"text\",\n text: `批量重命名失败: ${error}`\n }]\n };\n }\n }\n );\n\n // 工具:列出目录文件\n this.server.tool(\n \"list_directory_files\",\n \"列出指定目录下的所有文件,用于查看当前文件名以便进行重命名操作\",\n {\n directory: z.string().describe(\"要查看的目录路径\"),\n pattern: z.string().optional().describe(\"文件名过滤模式(可选),如 '*.png' 或 'icon_*'\")\n },\n async ({ directory, pattern }) => {\n try {\n Logger.log(`列出目录文件: ${directory}, 过滤: ${pattern || '无'}`);\n\n // 检查目录是否存在\n if (!fs.existsSync(directory)) {\n throw new Error(`目录不存在: ${directory}`);\n }\n\n const stat = fs.statSync(directory);\n if (!stat.isDirectory()) {\n throw new Error(`路径不是目录: ${directory}`);\n }\n\n let files = fs.readdirSync(directory);\n\n // 过滤掉隐藏文件\n files = files.filter(f => !f.startsWith('.'));\n\n // 如果有 pattern,进行简单的通配符匹配\n if (pattern) {\n const regex = new RegExp(\n '^' + pattern\n .replace(/\\./g, '\\\\.')\n .replace(/\\*/g, '.*')\n .replace(/\\?/g, '.') + '$',\n 'i'\n );\n files = files.filter(f => regex.test(f));\n }\n\n // 获取文件信息\n const fileInfos = files.map(f => {\n const filePath = path.join(directory, f);\n const fileStat = fs.statSync(filePath);\n return {\n name: f,\n isDirectory: fileStat.isDirectory(),\n size: fileStat.size\n };\n });\n\n // 排序:目录在前,文件在后,按名称排序\n fileInfos.sort((a, b) => {\n if (a.isDirectory !== b.isDirectory) {\n return a.isDirectory ? -1 : 1;\n }\n return a.name.localeCompare(b.name);\n });\n\n if (fileInfos.length === 0) {\n return {\n content: [{\n type: \"text\",\n text: `目录 ${directory} 下没有找到匹配的文件${pattern ? ` (过滤: ${pattern})` : ''}`\n }]\n };\n }\n\n let resultText = `目录: ${directory}\\n`;\n if (pattern) {\n resultText += `过滤: ${pattern}\\n`;\n }\n resultText += `共 ${fileInfos.length} 个项目:\\n\\n`;\n\n for (const f of fileInfos) {\n if (f.isDirectory) {\n resultText += `📁 ${f.name}/\\n`;\n } else {\n const sizeStr = f.size < 1024\n ? `${f.size}B`\n : f.size < 1024 * 1024\n ? `${(f.size / 1024).toFixed(1)}KB`\n : `${(f.size / 1024 / 1024).toFixed(1)}MB`;\n resultText += `📄 ${f.name} (${sizeStr})\\n`;\n }\n }\n\n return {\n content: [{\n type: \"text\",\n text: resultText\n }]\n };\n } catch (error) {\n Logger.error(`列出目录文件出错:`, error);\n return {\n isError: true,\n content: [{\n type: \"text\",\n text: `列出目录失败: ${error}`\n }]\n };\n }\n }\n );\n\n // 工具:下载文件\n this.server.tool(\n \"download_file\",\n \"从 URL 下载文件到本地目录。支持 HTTP/HTTPS 链接,可自定义保存文件名。\",\n {\n url: z.string().describe(\"要下载的文件 URL\"),\n targetDir: z.string().describe(\"保存文件的本地目录路径\"),\n fileName: z.string().optional().describe(\"保存的文件名(可选,默认从 URL 提取)\")\n },\n async ({ url, targetDir, fileName }) => {\n try {\n Logger.log(`下载文件: ${url} 到 ${targetDir}`);\n\n // 检查目录是否存在,不存在则创建\n if (!fs.existsSync(targetDir)) {\n fs.mkdirSync(targetDir, { recursive: true });\n Logger.log(`创建目录: ${targetDir}`);\n }\n\n const stat = fs.statSync(targetDir);\n if (!stat.isDirectory()) {\n throw new Error(`路径不是目录: ${targetDir}`);\n }\n\n // 从 URL 提取文件名\n let finalFileName = fileName;\n if (!finalFileName) {\n const urlObj = new URL(url);\n finalFileName = path.basename(urlObj.pathname);\n // 如果 URL 没有文件名,生成一个\n if (!finalFileName || finalFileName === '/') {\n finalFileName = `download_${Date.now()}`;\n }\n }\n\n const filePath = path.join(targetDir, finalFileName);\n\n // 检查文件是否已存在\n if (fs.existsSync(filePath)) {\n throw new Error(`文件已存在: ${filePath}`);\n }\n\n // 下载文件\n await new Promise<void>((resolve, reject) => {\n const urlObj = new URL(url);\n const protocol = urlObj.protocol === 'https:' ? https : http;\n\n const request = protocol.get(url, (response) => {\n // 处理重定向\n if (response.statusCode === 301 || response.statusCode === 302) {\n const redirectUrl = response.headers.location;\n if (redirectUrl) {\n Logger.log(`重定向到: ${redirectUrl}`);\n const redirectProtocol = redirectUrl.startsWith('https:') ? https : http;\n redirectProtocol.get(redirectUrl, (redirectResponse) => {\n if (redirectResponse.statusCode !== 200) {\n reject(new Error(`下载失败,HTTP 状态码: ${redirectResponse.statusCode}`));\n return;\n }\n const fileStream = fs.createWriteStream(filePath);\n redirectResponse.pipe(fileStream);\n fileStream.on('finish', () => {\n fileStream.close();\n resolve();\n });\n fileStream.on('error', (err) => {\n fs.unlink(filePath, () => {});\n reject(err);\n });\n }).on('error', reject);\n return;\n }\n }\n\n if (response.statusCode !== 200) {\n reject(new Error(`下载失败,HTTP 状态码: ${response.statusCode}`));\n return;\n }\n\n const fileStream = fs.createWriteStream(filePath);\n response.pipe(fileStream);\n\n fileStream.on('finish', () => {\n fileStream.close();\n resolve();\n });\n\n fileStream.on('error', (err) => {\n fs.unlink(filePath, () => {});\n reject(err);\n });\n });\n\n request.on('error', (err) => {\n fs.unlink(filePath, () => {});\n reject(err);\n });\n\n request.setTimeout(60000, () => {\n request.destroy();\n fs.unlink(filePath, () => {});\n reject(new Error('下载超时(60秒)'));\n });\n });\n\n // 获取文件大小\n const downloadedStat = fs.statSync(filePath);\n const sizeStr = downloadedStat.size < 1024\n ? `${downloadedStat.size}B`\n : downloadedStat.size < 1024 * 1024\n ? `${(downloadedStat.size / 1024).toFixed(1)}KB`\n : `${(downloadedStat.size / 1024 / 1024).toFixed(1)}MB`;\n\n return {\n content: [{\n type: \"text\",\n text: `文件下载成功!\\n源URL: ${url}\\n保存路径: ${filePath}\\n文件大小: ${sizeStr}`\n }]\n };\n } catch (error) {\n Logger.error(`下载文件出错:`, error);\n return {\n isError: true,\n content: [{\n type: \"text\",\n text: `下载失败: ${error}`\n }]\n };\n }\n }\n );\n }\n\n async connect(transport: Transport): Promise<void> {\n try {\n await this.server.connect(transport);\n\n Logger.log = (...args: any[]) => {\n try {\n this.server.server.sendLoggingMessage({\n level: \"info\",\n data: args,\n });\n } catch (error) {\n console.log(...args);\n }\n };\n\n Logger.error = (...args: any[]) => {\n try {\n this.server.server.sendLoggingMessage({\n level: \"error\",\n data: args,\n });\n } catch (error) {\n console.error(...args);\n }\n };\n\n Logger.log(\"OSS MCP服务器已连接并准备处理请求\");\n } catch (error) {\n console.error(\"连接到传输时出错:\", error);\n }\n }\n\n async startHttpServer(port: number): Promise<void> {\n const app = express();\n\n // SSE连接端点 - 修复头部发送冲突\n app.get(\"/sse\", (req: Request, res: Response) => {\n // 初始化SSE传输,不再自己设置头部,而是让SDK处理\n this.sseTransport = new SSEServerTransport(\n \"/messages\",\n res as unknown as ServerResponse<IncomingMessage>\n );\n\n try {\n // 连接到传输层\n this.server.connect(this.sseTransport)\n .catch((err) => {\n console.error(\"连接到SSE传输时出错:\", err);\n });\n\n // 处理客户端断开连接\n req.on('close', () => {\n console.log('SSE客户端断开连接');\n this.sseTransport = null;\n });\n } catch (error) {\n console.error(\"建立SSE连接时出错:\", error);\n // 如果连接失败,关闭响应\n if (!res.writableEnded) {\n res.status(500).end();\n }\n }\n });\n\n // 消息端点\n app.post(\"/messages\", async (req: Request, res: Response) => {\n if (!this.sseTransport) {\n console.log(\"尝试发送消息,但SSE传输未初始化\");\n res.status(400).json({\n error: 'SSE连接未建立',\n message: '请先连接到/sse端点'\n });\n return;\n }\n\n try {\n await this.sseTransport.handlePostMessage(\n req as unknown as IncomingMessage,\n res as unknown as ServerResponse<IncomingMessage>\n );\n } catch (error) {\n console.error(\"处理消息时出错:\", error);\n if (!res.writableEnded) {\n res.status(500).json({\n error: \"内部服务器错误\",\n message: String(error)\n });\n }\n }\n });\n\n // 启动服务器\n app.listen(port, () => {\n Logger.log = console.log;\n Logger.error = console.error;\n\n Logger.log(`HTTP服务器监听端口: ${port}`);\n Logger.log(`SSE端点: http://localhost:${port}/sse`);\n Logger.log(`消息端点: http://localhost:${port}/messages`);\n });\n }\n}\n","import OSS from 'ali-oss';\nimport fs from 'fs';\nimport path from 'path';\nimport { OssConfig, getOssConfig, getAllOssConfigs } from '../config/oss.config.js';\nimport { z } from 'zod';\n\n// 上传文件参数验证Schema\nexport const UploadFileParamsSchema = z.object({\n filePath: z.string(),\n targetDir: z.string().optional(),\n fileName: z.string().optional(),\n configName: z.string().optional(),\n});\n\n// 导出上传文件参数类型\nexport type UploadFileParams = z.infer<typeof UploadFileParamsSchema>;\n\n// 上传结果验证Schema\nexport const UploadResultSchema = z.object({\n success: z.boolean(),\n url: z.string().optional(),\n error: z.string().optional(),\n ossConfigName: z.string().optional(),\n});\n\n// 导出上传结果类型\nexport type UploadResult = z.infer<typeof UploadResultSchema>;\n\n/**\n * OSS配置接口(包含ID和名称)\n */\nexport interface OssConfigWithMeta extends OssConfig {\n id: string;\n name: string;\n}\n\n/**\n * 阿里云OSS服务类\n */\nexport class OssService {\n private clients: Map<string, OSS> = new Map();\n\n /**\n * 获取所有OSS配置\n * @returns OSS配置列表\n */\n getConfigs(): OssConfigWithMeta[] {\n const configs: OssConfigWithMeta[] = [];\n const allConfigs = getAllOssConfigs();\n\n for (const [id, config] of Object.entries(allConfigs)) {\n configs.push({\n id,\n name: `${id.charAt(0).toUpperCase()}${id.slice(1)} 配置`,\n ...config\n });\n }\n\n return configs;\n }\n\n /**\n * 获取OSS客户端\n * @param configName 配置名称\n * @returns OSS客户端实例\n */\n private getClient(configName: string = 'default'): OSS | null {\n // 检查缓存中是否已有客户端\n if (this.clients.has(configName)) {\n return this.clients.get(configName) as OSS;\n }\n\n // 获取配置并创建客户端\n const config = getOssConfig(configName);\n if (!config) {\n return null;\n }\n\n try {\n const client = new OSS({\n region: config.region,\n accessKeyId: config.accessKeyId,\n accessKeySecret: config.accessKeySecret,\n bucket: config.bucket,\n endpoint: config.endpoint\n });\n\n // 缓存客户端实例\n this.clients.set(configName, client);\n return client;\n } catch (error) {\n console.error(`Failed to create OSS client for ${configName}:`, error);\n return null;\n }\n }\n\n /**\n * 上传文件到OSS\n * @param params 上传参数\n * @returns 上传结果\n */\n async uploadFile(params: UploadFileParams): Promise<UploadResult> {\n // 验证并解析参数\n const validParams = UploadFileParamsSchema.parse(params);\n const { filePath, targetDir = '', fileName, configName = 'default' } = validParams;\n\n try {\n // 检查文件是否存在\n if (!fs.existsSync(filePath)) {\n return UploadResultSchema.parse({\n success: false,\n error: `File not found: ${filePath}`,\n ossConfigName: configName\n });\n }\n\n // 获取OSS客户端\n const client = this.getClient(configName);\n if (!client) {\n return UploadResultSchema.parse({\n success: false,\n error: `OSS config not found for: ${configName}`,\n ossConfigName: configName\n });\n }\n\n // 确定文件名\n const actualFileName = fileName || path.basename(filePath);\n\n // 构建OSS路径,确保正斜杠格式\n let ossPath = actualFileName;\n if (targetDir) {\n // 规范化目标目录:移除头尾斜杠,然后加上结尾斜杠\n const normalizedDir = targetDir.replace(/^\\/+|\\/+$/g, '');\n ossPath = normalizedDir ? `${normalizedDir}/${actualFileName}` : actualFileName;\n }\n\n // 上传文件\n const result = await client.put(ossPath, filePath);\n\n return UploadResultSchema.parse({\n success: true,\n url: result.url,\n ossConfigName: configName\n });\n } catch (error) {\n return UploadResultSchema.parse({\n success: false,\n error: `Upload failed: ${(error as Error).message}`,\n ossConfigName: configName\n });\n }\n }\n}\n\n// 导出单例实例\nexport const ossService = new OssService();\n","import { config } from \"dotenv\";\nimport yargs from \"yargs\";\nimport { hideBin } from \"yargs/helpers\";\nimport { z } from \"zod\";\n\nconfig();\n\n// OSS配置验证Schema\nexport const OssConfigSchema = z.object({\n region: z.string(),\n accessKeyId: z.string(),\n accessKeySecret: z.string(),\n bucket: z.string(),\n endpoint: z.string(),\n});\n\n// 导出OSS配置类型\nexport type OssConfig = z.infer<typeof OssConfigSchema>;\n\n// 服务器配置接口\nexport interface ServerConfig {\n port: number;\n ossConfig: Record<string, OssConfig>;\n configSources: {\n port: \"cli\" | \"env\" | \"default\";\n ossConfig: \"cli\" | \"env\" | \"default\";\n };\n}\n\n// 掩码函数,用于打印敏感信息\nfunction maskSecret(secret: string): string {\n if (secret.length <= 4) return \"****\";\n return `${secret.substring(0, 4)}****${secret.slice(-4)}`;\n}\n\n// 获取服务器配置\nexport function getServerConfig(isStdioMode: boolean = false): ServerConfig {\n // 解析命令行参数\n const argv = yargs(hideBin(process.argv))\n .options({\n \"oss-config\": {\n type: \"string\",\n description: \"OSS配置JSON字符串\",\n },\n port: {\n type: \"number\",\n description: \"服务器运行端口\",\n default: 3000,\n },\n })\n .help()\n .version(\"1.0.0\")\n .parseSync();\n\n const config: ServerConfig = {\n port: 3000,\n ossConfig: {},\n configSources: {\n port: \"default\",\n ossConfig: \"default\",\n },\n };\n\n // 处理端口配置\n if (argv.port) {\n config.port = argv.port;\n config.configSources.port = \"cli\";\n } else if (process.env.PORT) {\n config.port = parseInt(process.env.PORT, 10);\n config.configSources.port = \"env\";\n }\n\n // 处理OSS配置 - 首先检查命令行参数\n if (argv[\"oss-config\"]) {\n const allOssConfigs = JSON.parse(argv[\"oss-config\"] as string);\n\n if (allOssConfigs.region && allOssConfigs.accessKeyId) {\n config.ossConfig.default = OssConfigSchema.parse(allOssConfigs);\n } else {\n Object.entries(allOssConfigs).forEach(([name, cfg]) => {\n config.ossConfig[name.toLowerCase()] = OssConfigSchema.parse(cfg);\n });\n }\n config.configSources.ossConfig = \"cli\";\n } else if (process.env.OSS_CONFIG_DEFAULT) {\n const ossConfig = JSON.parse(process.env.OSS_CONFIG_DEFAULT)\n config.ossConfig.default = OssConfigSchema.parse(ossConfig);\n config.configSources.ossConfig = \"env\";\n }\n\n // 检查其他命名的OSS配置\n Object.entries(process.env).forEach(([key, value]) => {\n if (key.startsWith(\"OSS_CONFIG_\") && key !== \"OSS_CONFIG_DEFAULT\" && value) {\n try {\n const configName = key.replace(\"OSS_CONFIG_\", \"\").toLowerCase();\n const ossConfig = JSON.parse(value);\n config.ossConfig[configName] = OssConfigSchema.parse(ossConfig);\n } catch (error) {\n console.error(`解析环境变量${key}失败:`, error);\n }\n }\n });\n\n // 验证配置\n if (Object.keys(config.ossConfig).length === 0) {\n console.warn(\"未找到有效的OSS配置。服务器将启动,但上传功能将不可用。\");\n }\n\n // 打印配置信息(非stdio模式下)\n if (!isStdioMode) {\n console.log(\"\\n配置信息:\");\n console.log(`- 端口: ${config.port} (来源: ${config.configSources.port})`);\n\n if (Object.keys(config.ossConfig).length > 0) {\n console.log(\"- OSS配置:\");\n Object.entries(config.ossConfig).forEach(([name, cfg]) => {\n console.log(` - ${name}:`);\n console.log(` Region: ${cfg.region}`);\n console.log(` Endpoint: ${cfg.endpoint}`);\n console.log(` Bucket: ${cfg.bucket}`);\n console.log(` AccessKeyId: ${maskSecret(cfg.accessKeyId)}`);\n console.log(` AccessKeySecret: ${maskSecret(cfg.accessKeySecret)}`);\n });\n } else {\n console.log(\"- OSS配置: 未找到\");\n }\n console.log(); // 空行,增加可读性\n }\n\n return config;\n}\n\n// 获取所有OSS配置\nexport function getAllOssConfigs(): Record<string, OssConfig> {\n const { ossConfig } = getServerConfig(true);\n return ossConfig;\n}\n\n// 获取特定名称的OSS配置\nexport function getOssConfig(name: string = 'default'): OssConfig | null {\n const configs = getAllOssConfigs();\n const normalizedName = name.toLowerCase();\n return configs[normalizedName] || null;\n}\n\n// 获取可用的OSS配置名称列表\nexport function getAvailableOssConfigNames(): string[] {\n return Object.keys(getAllOssConfigs());\n}\n"],"mappings":"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","names":["z","config","z","config","fs","path","config","z","configs","configNames","resolve","fileStream","config"]}
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "oss-mcp-plus",
3
+ "version": "1.0.3",
4
+ "description": "本地MCP服务器,用于将文件上传到阿里云OSS,支持多配置和目录指定",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "oss-mcp-plus": "dist/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "README.md"
13
+ ],
14
+ "scripts": {
15
+ "dev": "nodemon --watch src -e ts --exec \"npm run build && node dist/index.js --http\"",
16
+ "dev:watch": "cross-env NODE_ENV=development tsup --watch",
17
+ "build": "tsup",
18
+ "prepublishOnly": "npm run build",
19
+ "start": "npm run build && node dist/index.js",
20
+ "start:stdio": "cross-env NODE_ENV=cli node dist/index.js",
21
+ "start:http": "node dist/index.js --http",
22
+ "inspect": "pnpx @modelcontextprotocol/inspector",
23
+ "type-check": "tsc --noEmit",
24
+ "lint": "eslint . --ext .ts",
25
+ "format": "prettier --write \"src/**/*.ts\"",
26
+ "pub:release": "pnpm build && npm publish --access public",
27
+ "publish:local": "pnpm build && npm pack",
28
+ "serve:http": "node dist/index.js --http"
29
+ },
30
+ "engines": {
31
+ "node": ">=18.0.0"
32
+ },
33
+ "repository": {
34
+ "type": "git",
35
+ "url": "git+https://github.com/lovelyJason/oss-mcp.git"
36
+ },
37
+ "keywords": [
38
+ "oss",
39
+ "aliyun",
40
+ "upload",
41
+ "mcp",
42
+ "typescript",
43
+ "ai"
44
+ ],
45
+ "author": "",
46
+ "license": "MIT",
47
+ "dependencies": {
48
+ "@modelcontextprotocol/sdk": "^1.7.0",
49
+ "@types/yargs": "^17.0.33",
50
+ "ali-oss": "^6.19.0",
51
+ "cors": "^2.8.5",
52
+ "cross-env": "^7.0.3",
53
+ "dotenv": "^16.4.5",
54
+ "express": "^4.21.2",
55
+ "node-fetch": "^3.3.2",
56
+ "yargs": "^17.7.2",
57
+ "zod": "^3.24.2"
58
+ },
59
+ "devDependencies": {
60
+ "@types/ali-oss": "^6.16.11",
61
+ "@types/cors": "^2.8.17",
62
+ "@types/express": "^5.0.0",
63
+ "@types/node": "^20.14.1",
64
+ "@typescript-eslint/eslint-plugin": "^7.17.0",
65
+ "@typescript-eslint/parser": "^7.0.1",
66
+ "eslint": "^8.57.0",
67
+ "nodemon": "^3.1.9",
68
+ "prettier": "^3.2.5",
69
+ "tsup": "^8.0.2",
70
+ "typescript": "^5.4.2"
71
+ }
72
+ }