不会写Mcp server,那就让Trae写吧

前言

在上一篇文章中,Trae帮助我们深入理解了MCP(Model Context Protocol)是什么,以及MCP标准输入输出的格式。MCP是一种轻量级的通信协议,通过标准输入输出(stdin/stdout)进行数据交换,使用JSON格式来传递消息。

这种协议非常适合构建微服务,因为它简单、高效,且易于实现。

在本文中,我们将进一步深入,使用官方SDK来创建一个支持文件夹增删改查功能的MCP服务。我们将通过一个具体的实例,展示如何从零开始构建这样一个服务,并确保它能够与MCP协议无缝对接。

首先先让Trae使用官方的sdk帮我创建一个可以crud文件夹的mcp服务,使用nodejs来编写这个Mcp服务

可以看到所谓的官方的sdk是这个@modelcontextprotocol/sdk,如果对这个不了解的话,可以自己去npm上面看,这里可以简单的理解为,有了这个官方的sdk,我们的mcp就可以做很多事情

2.1 初始化项目

首先,我们需要创建一个新的Node.js项目并初始化。

Trae在你的工作目录中运行以下命令:

bash 复制代码
mkdir folder-mcp--server
cd folder-mcp--server
npm init -y

这将创建一个名为folder-mcp--server的文件夹,并在其中初始化一个新的Node.js项目。

2.2 安装官方SDK

接下来,我们需要安装@modelcontextprotocol/sdk

bash 复制代码
npm install @modelcontextprotocol/sdk

安装完成后,你可以在项目的node_modules文件夹中找到@modelcontextprotocol/sdk

2.3 编写服务代码

Trae在项目src目录中创建一个名为index.js的文件,并添加以下代码:

javascript 复制代码
#!/usr/bin/env node
  
import { Server } from '@modelcontextprotocol/sdk/server/index.js';

import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

import {

  CallToolRequestSchema,

  ListToolsRequestSchema,

} from '@modelcontextprotocol/sdk/types.js';

import { promises as fs, constants as fsConstants } from 'fs';

import path from 'path';

import { fileURLToPath } from 'url';

  

创建一个mcp服务

css 复制代码
const server = new Server(
  {
    name: 'folder-mcp-server',
    version: '1.0.0',
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

辅助函数:检查路径是否存在

typescript 复制代码
async function pathExists(targetPath: string): Promise<boolean> {
  try {
    await fs.access(targetPath);
    return true;
  } catch {
    return false;
  }
}

辅助函数:计算文件夹大小

typescript 复制代码
async function getFolderSize(folderPath: string): Promise<number> {
  let totalSize = 0;
  try {
    const stats = await fs.stat(folderPath);
    if (!stats.isDirectory()) {
      return stats.size;
    }
  
    const items = await fs.readdir(folderPath, { withFileTypes: true });
    for (const item of items) {
      const itemPath = path.join(folderPath, item.name);
      if (item.isDirectory()) {
        totalSize += await getFolderSize(itemPath);
      } else {
        const itemStats = await fs.stat(itemPath);
        totalSize += itemStats.size;
      }
    }
  } catch (error) {
    console.error(`Error calculating folder size: ${error}`);
  }
  return totalSize;
}

辅助函数:格式化文件大小

ini 复制代码
function formatBytes(bytes: number, decimals = 2): string {
  if (bytes === 0) return '0 Bytes';
  const k = 1024;
  const dm = decimals < 0 ? 0 : decimals;
  const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
  const i = Math.floor(Math.log(bytes) / Math.log(k));
  return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}

辅助函数:递归复制文件夹

csharp 复制代码
async function copyFolder(source: string, destination: string): Promise<void> {
  await fs.mkdir(destination, { recursive: true });
  const items = await fs.readdir(source, { withFileTypes: true });
  for (const item of items) {
    const sourcePath = path.join(source, item.name);
    const destinationPath = path.join(destination, item.name);
    if (item.isDirectory()) {
      await copyFolder(sourcePath, destinationPath);
    } else {
      await fs.copyFile(sourcePath, destinationPath);
    }
  }
}  

注册工具

php 复制代码
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: 'create_folder',
        description: '创建新文件夹',
        inputSchema: {
          type: 'object',
          properties: {
            path: {
              type: 'string',
              description: '要创建的文件夹路径',
            },
            recursive: {
              type: 'boolean',
              description: '是否递归创建父目录',
              default: true,
            },
          },
          required: ['path'],
        },
      },
      {
        name: 'delete_folder',
        description: '删除文件夹',
        inputSchema: {
          type: 'object',
          properties: {
            path: {
              type: 'string',
              description: '要删除的文件夹路径',
            },
            force: {
              type: 'boolean',
              description: '是否强制删除非空文件夹',
              default: false,
            },
          },
          required: ['path'],
        },
      },
      {
        name: 'rename_folder',
        description: '重命名或移动文件夹',
        inputSchema: {
          type: 'object',
          properties: {
            oldPath: {
              type: 'string',
              description: '原文件夹路径',
            },
            newPath: {
              type: 'string',
              description: '新文件夹路径',
            },
          },
          required: ['oldPath', 'newPath'],
        },
      },
      {
        name: 'list_folder',
        description: '列出文件夹内容',
        inputSchema: {
          type: 'object',
          properties: {
            path: {
              type: 'string',
              description: '要列出的文件夹路径',
            },
            recursive: {
              type: 'boolean',
              description: '是否递归列出子文件夹内容',
              default: false,
            },
          },
          required: ['path'],
        },
      },
  }

});

启动服务器的方法

javascript 复制代码
async function main() {

  const transport = new StdioServerTransport();

  await server.connect(transport);

  console.error('文件夹管理MCP服务器已启动');

}

  


main().catch((error) => {

  console.error('服务器启动失败:', error);

  process.exit(1);

});

然后让Trae帮我们创建一个可以测试的js脚本

执行node simple-test.js ,可以看到控制台,输出打印和文件夹创建test-demo文件夹

执行一下删除文件夹,把刚刚新建的也删除了

相关推荐
搬砖的前端2 天前
AI编辑器开源主模型搭配本地模型辅助对标GPT5.2/GPT5.4/Claude4.6(前端开发专属)
人工智能·开源·claude·mcp·trae·qwen3.6·ops4.6
FEF前端团队3 天前
Skill 入门指南:从零开始打造你的智能编程助手
aigc·ai编程·trae
豆包MarsCode3 天前
从创意到落地,SOLO 如何让短剧制作更高效
trae
豆包MarsCode3 天前
SOLO 必装的 14个 Skills,看这一篇就够了
trae
0zien03 天前
【AI编程 - 第一弹】2048小游戏
ai编程·claude·creator·trae·vibe
不会敲代码14 天前
从零开始读懂 MCP:大模型如何通过标准化协议“调用”你的工具?
javascript·cursor·trae
搬砖的前端4 天前
本地模型+TRAE CN 打造最优模型组合实测:开源主模型+本地辅模型,对标GPT5.2/5.3/Gemini-3-Flash
前端·ai·mac·ai编程·qwen·trae·qwen3.6
低调小一4 天前
Harness Engineering:从 Prompt/Context 到“可交付 Agent”的四层系统
trae·harness
Bigger6 天前
告别 AI 塑料感:我是如何用 frontend-design skill 重塑项目官网的
前端·ai编程·trae
Aaron_Chou3138 天前
如何在Trae中配置Claude,gpt-5.4,deepseek等大模型的中转API
人工智能·gpt·claude·deepseek·cline·trae