Back to blog
    Cursor + MCP + 微调模型:在你的代码编辑器中使用领域 AI
    cursormcplocal-modelcode-editorfine-tuningsegment:vibecoder

    Cursor + MCP + 微调模型:在你的代码编辑器中使用领域 AI

    Cursor 支持 MCP 服务器。将你的微调领域模型连接到 Cursor,在编辑器内获得专业化的 AI 能力——基于你代码库训练的代码生成、符合你风格的文档、领域特定的自动补全。

    EErtas Team·

    Cursor 是大多数 vibecoder 每天使用的 AI 原生代码编辑器。它支持 MCP 服务器——这意味着你可以将微调模型连接到 Cursor,直接从编码环境中调用领域特定的 AI 能力,无需切换上下文。

    使用场景:基于你代码库风格训练的代码文档模型、基于你模式训练的领域特定代码生成器、用你产品的声音写作的内容模型,全部可作为 Cursor 工具使用。

    为什么领域模型在 Cursor 中胜过通用模型

    Cursor 内置的 AI(Claude Sonnet、GPT-4o)在通用编码任务上表现出色。但在以下方面表现不佳:

    你代码库的特定模式: 通用 AI 不了解你团队的命名规范、架构决策或你选择标准化的库。它会生成语法正确但不符合你代码库风格的代码。

    你的文档风格: 通用 AI 写出通用文档。而在你现有文档上训练的模型写出的文档听起来与你其余文档一致。

    领域特定逻辑: 如果你的应用处理复杂的业务逻辑(税务计算、医疗工作流程、法律文档处理),通用 AI 只能做出有根据的猜测。而在你领域逻辑上训练的模型能生成正确的业务逻辑。

    在你代码库和领域上训练的微调模型产生的输出,你团队的资深开发者会认为是合适的。

    为 Cursor 设置 MCP 服务器

    Cursor 从 ~/.cursor/mcp.json(或项目级 .cursor/mcp.json)读取 MCP 配置。

    第一步:构建以代码为中心的 MCP 服务器

    // cursor-domain-mcp/server.mjs
    import { Server } from '@modelcontextprotocol/sdk/server/index.js';
    import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
    import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
    
    const OLLAMA_URL = 'http://localhost:11434/api/chat';
    const MODEL = 'my-codebase-model';
    
    const server = new Server(
      { name: 'codebase-assistant', version: '1.0.0' },
      { capabilities: { tools: {} } }
    );
    
    server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        {
          name: 'generate_code',
          description: 'Generate code following the project\'s specific patterns, naming conventions, and library choices. Use for creating new functions, components, or modules that should match existing code style.',
          inputSchema: {
            type: 'object',
            properties: {
              description: { type: 'string', description: 'What code to generate' },
              file_context: { type: 'string', description: 'Relevant existing code from the codebase for context' },
              language: { type: 'string', description: 'Programming language or framework' }
            },
            required: ['description']
          }
        },
        {
          name: 'write_documentation',
          description: 'Write documentation in the project\'s established style — same format, same level of detail, same terminology. Use for JSDoc, README sections, or inline comments.',
          inputSchema: {
            type: 'object',
            properties: {
              code: { type: 'string', description: 'The code to document' },
              doc_type: { type: 'string', description: 'jsdoc, readme, comment, or api-reference' }
            },
            required: ['code']
          }
        },
        {
          name: 'domain_query',
          description: 'Answer domain-specific questions about the business logic, industry rules, or specialized requirements that the codebase implements.',
          inputSchema: {
            type: 'object',
            properties: {
              question: { type: 'string', description: 'The domain question to answer' }
            },
            required: ['question']
          }
        }
      ]
    }));
    
    server.setRequestHandler(CallToolRequestSchema, async (request) => {
      const { name, arguments: args } = request.params;
    
      let prompt;
      if (name === 'generate_code') {
        prompt = `Generate code for: ${args.description}
    ${args.file_context ? `\nExisting code context:\n${args.file_context}` : ''}
    ${args.language ? `\nLanguage/Framework: ${args.language}` : ''}`;
      } else if (name === 'write_documentation') {
        prompt = `Write ${args.doc_type || 'documentation'} for this code:\n\n${args.code}`;
      } else if (name === 'domain_query') {
        prompt = args.question;
      } else {
        throw new Error(`Unknown tool: ${name}`);
      }
    
      const response = await fetch(OLLAMA_URL, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          model: MODEL,
          messages: [{ role: 'user', content: prompt }],
          stream: false
        })
      });
    
      const data = await response.json();
      return { content: [{ type: 'text', text: data.message.content }] };
    });
    
    const transport = new StdioServerTransport();
    await server.connect(transport);

    第二步:添加到 Cursor MCP 配置

    创建或编辑 ~/.cursor/mcp.json

    {
      "mcpServers": {
        "codebase-assistant": {
          "command": "node",
          "args": ["/absolute/path/to/cursor-domain-mcp/server.mjs"]
        }
      }
    }

    重启 Cursor。工具将出现在 Cursor 聊天面板中。

    为 Cursor 集成训练合适的模型

    用于代码生成: 训练数据应该是你自己代码库中的(任务描述,正确实现)对。从你的 git 历史中提取:提交消息 + diff = (任务,实现)对。

    用于文档: 训练数据:已有文档的函数——(代码块,对应的文档字符串/README 部分)对。

    用于领域知识: 训练数据:内部 wiki、架构决策记录、领域术语表、Slack 或 Confluence 中的现有问答。转换为(问题,答案)格式。

    在 Cursor 聊天中使用模型

    在 Cursor 的聊天面板(Cmd+L / Ctrl+L)中,你可以调用你的工具:

    "使用 codebase-assistant 为 [描述] 生成一个新的 API 端点"

    或者让 Cursor 在识别到模式匹配你的工具描述时自动调用。你的工具描述越具体,Cursor 将请求路由到它而非内置模型的准确性就越高。

    独立开发者的实际工作流程:

    1. 打开 Cursor 聊天
    2. 粘贴你想要实现的签名/接口
    3. Cursor 调用 generate_code 工具 → 你的微调模型以你的风格生成实现
    4. Cursor 显示生成的代码并解释
    5. 应用到文件

    该模型不会取代 Cursor 的内置智能——它用你特定代码库的知识来增强它。


    Ship AI that runs on your users' devices.

    Ertas early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.

    延伸阅读

    Ship AI that runs on your users' devices.

    Early bird pricing starts at $14.50/mo — locked in for life. Plans for builders and agencies.

    Keep reading