成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

MCP 開發實戰:如何使用 MCP 真正加速 UE 項目開發

開發 架構
目前各種MCP的文章和實際例子以及開源工具層出不窮,本文試圖用最簡單的方式解釋下MCP解決什么問題和MCP怎么寫的問題。

作者 | hanzo

用說人話的方式講解MCP。

目前各種MCP的文章和實際例子以及開源工具層出不窮,本文試圖用最簡單的方式解釋下MCP解決什么問題和MCP怎么寫的問題。

為啥要用MCP

MCP是一項專為LLM工具化操作設計的輕量化標準協議,其核心目標是構建LLM與異構軟件系統間的通用指令交互框架。與傳統的單一功能調用機制不同,MCP通過三層架構創新解決工具擴展性問題:

(1) 協議定位

作為中間協議層,MCP抽象出獨立于具體LLM和業務系統的接口描述層,允許開發者在不同維度(功能權限、輸入格式、執行環境)對工具接口進行靈活管控,避免傳統方案中接口爆炸帶來的維護難題。

(2) 技術架構

  • 接口描述層:采用聲明式DSL定義工具元數據,包括功能語義、入參Schema、權限策略和執行上下文
  • 代理控制層:內置動態路由引擎和權限驗證模塊,支持熱插拔式工具注冊與版本管理
  • 協議適配層:提供跨平臺SDK,自動生成OpenAPI/Swagger等標準接口文檔

(3) 核心優勢

  • 雙向解耦:前端LLM無需感知具體工具實現,后端系統可獨立迭代
  • 權限縱深:細粒度控制工具可見性(開發者/用戶/模型層級)
  • 執行沙箱:支持Docker/WASM等多重運行時隔離方案
  • 生態兼容:自帶LangChain/LLamaIndex等主流框架的適配器

綜合上述的專業表述,說人話就是,只要你的LLM有Prompt遵循能力,那么不管你是qwen,llama,DeepSeek還是claude ,都可以連接同樣的MCP Server并且讓你的LLM能夠真正的調用工具,因此大大加速了LLM工具使用的開發速度。

為什么最近MCP爆發了?

最近大量MCP的爆發依賴于LLM本身兩個能力的大幅度提升:1.結構化輸出能力2.指令遵循能力。特別是claude3.7 sonnets之后的進展,使得工具的使用成功率大幅提升。對于LLM本身的能力進展來說,通過工具使用的方式積累真實世界的數據,并且進行后訓練,也會成為LLM的垂直能力和LLM工作準確率進一步提升的關鍵。

MCP Server開發實戰

有了基礎概念之后,我們就可以直接開始一個MCP Server的開發了,目前MCP官方提供四種語言的開發SDK,包括Python,typescript,java和kotlin。我們以IEG最常用的typescript為例構建工程。

在開始前我們先明確一些概念,通常,我們編寫的MCP是一個MCP Server,在Server中我們通常會定義一系列我們所需要的工具。使用各種LLM的客戶端只要能連接上Server,就可以使用我們的MCP的各種工具調用能力了。

在UE開發中,UE廢物一樣的文檔和天量的代碼經常讓人頭大,那么能不能讓LLM幫我來分析代碼呢?結合Emacs常用的tree-sitter語法分析庫和MCP,我們就可以用LLM來做這件事。

(本工程基于github:github.com/ayeletstu... 進行修改得來,由于原工程已經無法配置運行,我已經將修改后的代碼傳至 git.woa.com/IEG-RED-...)

首先,我們和普通配置NodeJs工程一樣,在Package.json中添加相應依賴:

"dependencies": {
    "@modelcontextprotocol/sdk": "0.6.0",
    "glob": "^8.1.0",
    "tree-sitter": "^0.20.1",
    "tree-sitter-cpp": "^0.20.0"
  },
  "devDependencies": {
    "@types/glob": "^8.1.0",
    "@types/jest": "^29.5.14",
    "@types/node": "^18.15.11",
    "jest": "^29.7.0",
    "ts-jest": "^29.2.5",
    "typescript": "^5.0.4"
  }

可以看到我們所需要的modelcontextprotocol sdk和tree-sitter等都可以直接從npm下載配置,我們按照常理執行npm install等步驟。接下來和通常的NodeJS程序一樣,我們編寫index.ts文件,先導入mcp相關的接口:

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ErrorCode,
  ListToolsRequestSchema,
  McpError,
} from '@modelcontextprotocol/sdk/types.js';

這里我們可以看到MCP的幾個關鍵概念:

  • Server:我們的MCP服務器,也就是處理一類任務的工具集合
  • stdioServertransport:MCP默認用的通訊格式。
  • RequestSchema:使用MCP時需要提供的參數,名字等等信息。

首先,我們需要定義一個Server class:

class UnrealAnalyzerServer {
  private server: Server;
  private analyzer: UnrealCodeAnalyzer;
 ......
  }

  public async start() {
    try {
      // Setup handlers first
      this.setupToolHandlers();
      
      // Connect to stdio transport
      const transport = new StdioServerTransport();
      await this.server.connect(transport);
      
      console.log('Unreal Analyzer Server started successfully');
    } catch (error) {
      console.error('Failed to initialize server:', error);
      process.exit(1);
    }
  }

這里定義了我們的server的一些最常用的初始化流程和工具定義過程,因為我們是希望用MCP來分析代碼,因此我們的CodeAnalyzer也屬于我們的Server Class Member。

要定義工具,我們首先需要結合ListToolsRequestSchema來綁定我們的tools,參考下面的代碼:

private setupToolHandlers() {
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        {
          ......
        {
          name: 'analyze_class',
          description: 'Get detailed information about a C++ class',
          inputSchema: {
            type: 'object',
            properties: {
              className: {
                type: 'string',
                description: 'Name of the class to analyze',
              },
            },
            required: ['className'],
          },
        },
  .....

我們定義工具的名字,和工具所需要的輸入,并將其綁定到server。這些信息會讓MCP識別到我們需要調用到什么工具,并且在調用工具時,需要提供什么樣的參數。

有了工具的名字和參數,MCP需要知道具體如何去執行我們想要的操作,比如分析C++類,搜索代碼等等,這里就要用到callToolRequestSchema結構體:

this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      // Only check for initialization for analysis tools
      const analysisTools = ['analyze_class', 'find_class_hierarchy', 'find_references', 'search_code', 'analyze_subsystem', 'query_api'];
      if (analysisTools.includes(request.params.name) && !this.analyzer.isInitialized() && 
          request.params.name !== 'set_unreal_path' && request.params.name !== 'set_custom_codebase') {
        throw new Error('No codebase initialized. Use set_unreal_path or set_custom_codebase first.');
      }

      switch (request.params.name) {
       .....
        case 'search_code':
          return this.handleSearchCode(request.params.arguments);
        case 'analyze_subsystem':
          return this.handleAnalyzeSubsystem(request.params.arguments);
        case 'query_api':
          return this.handleQueryApi(request.params.arguments);
        default:
          throw new Error(`Unknown tool: ${request.params.name}`);
      }
    });
  }

很明顯,callToolRequestSchema會將tools的名字和參數傳給工具真正的執行者。在我們的Server內部定義的工具函數中,會調用tree-sitter cpp庫 去進行真正的分析,然后將結果返回給我們的LLM進行總結。

來總結下, MCP的編寫本身是非常簡單的,我們需要實現的是定義工具的名字,參數(從LLM中自然語言的方式獲取),以及用代碼描述的真正執行工具的流程,并且將這些都綁定到我們的Server上,我們只需要關心我們在調用什么工具和我們需要什么數據就行了,至于給大模型的提示詞,多輪對話暫存,格式化輸出驗證等需要考慮到問題,MCP的SDK都能幫我們搞定。

接下來我們用tsc編譯我們的Nodejs程序,我們的Server就做好了。

使用MCP

讀到這里細心的讀者肯定會發現。我們的LLM在哪里?這就是MCP更重要的一個好處,它的Server是LLM無關的,只要客戶端使用的LLM看得懂提示詞,那么它就能使用同一個MCP Server。

接下來我們配置客戶端來使用我們的MCP Server,目前很多軟件,包括Claude desktop,dify等都支持了MCP,這里我們選擇VSCode 的Cline插件作為客戶端(因為他開源),安裝和配置Cline的過程在此不再贅述,打開Cline的Setting,點擊MCP Servers的按鈕,我們會在下方看到一個Configure MCP Server的按鈕,點擊我們就可以打開我們的MCP設置Json:

前文提到過,MCP支持多種語言開發,包括Python,Typescript等,因此可以看到我們的MCP配置中也支持多種入口,一個MCP Server的入口,可以是Python腳本,可以是bat批處理,也可以是nodejs程序的入口,對于我們的server來說,我們要配置的是一個nodejs的入口程序,如下面的代碼:

"unreal-analyzer": {
      "command": "node",
      "args": [
        "C:/Users/admin/Documents/Cline/MCP/unreal-analyzer-mcp/build/index.js"
      ],
      "env": {},
      "disabled": false,
      "autoApprove": [],
      "timeout": 3600    }

我們將入口指向我們編譯好的JavaScript文件,保存好之后,Cline就會自動去執行這個index.js,如果有運行錯誤,那么Cline的設置窗口中會報錯,當出現下面的綠色按鈕時,則證明我們的MCP Server連接成功了:

接下來,我們就可以用自然語言的方式快速分析UE代碼了,我們在Cline的對話框中切換到Act Mode(只有Actmode可以調用MCP Server),然后按照我們日常和同事交流說話的口吻打字:先告訴他我們的UE代碼在哪里: 

直接說:我想分析下UMaterialExpressionPanner這個類,LLM會分析你的需求,自己去調用工具: 

同時,LLM也會根據自己的思考去繼續調用工具,比如我的這個問題,它會繼續調用工具,去搜索代碼: 

當他發現代碼非常多的時候,它會考慮到:OK,我可能需要過濾一下代碼,于是它會調用SearchWithContext的工具:

來個稍微復雜點的任務,讓它幫我找找lumen里AO相關的類:

通過這個很簡單的例子工程,我們可以總結出MCP的特點,MCP通過工程化的方法和統一的協議,給LLM裝上了使用工具的手,這樣我們的AI就可以真正的替我們干活。

真正的UnrealMCP實現

理解了MCP的工作邏輯和原理之后, 再開發垂直領域的MCP工具就會相對簡單。接下來我們來分析下真正的能干活的UnrealMCP(github.com/kvick-gam...)是怎么工作的。同時也展示下Python SDK下的MCP工作流。

UnrealMCP由兩部分組成,一部分是MCP Server的Python代碼,一部分是UE5的插件,其中UE5的插件主要負責對接我們操作UE需要的一些C++邏輯。這部分的安裝邏輯和通常的UE插件完全一樣。

而MCP本身的部分,我們希望能夠在Cline插件中調用,由于這個UnrealMCP只能在Claude中工作,而Claude在國內使用非常麻煩,因此在Cline中配置本MCP時,我們需要對倉庫上說明的配置文件稍微進行些修改。 在運行安裝python, 啟動venv等工作之后,我們在配置Cline MCP的json時,需要按照如下代碼配置:

"unreal": {
      "command": "cmd.exe",
      "args": [
        "/c", 
        "F:\\UnrealEngine\\Engine\\Plugins\\UnrealMCP\\MCP\\run_unreal_mcp.bat"
      ],
      "env": {
        "PYTHONPATH": "F:\\UnrealEngine\\Engine\\Plugins\\UnrealMCP\\MCP\\python_modules",
        "PATH": "${PATH};F:\\UnrealEngine\\Engine\\Plugins\\UnrealMCP\\MCP\\python_env\\Scripts"
      },
      "disabled": false,
      "autoApprove": [],
      "cwd": "F:\\UnrealEngine\\Engine\\Plugins\\UnrealMCP\\MCP"
    },

這樣就可以在Cline中使用UnrealMCP了。

使用上,UnrealMCP也是非常簡單的,打開UE,啟動UnrealMCP插件之后,我們告訴LLM我們的需求:在場景中創建一個迷宮關卡: 

MCP會將相關信息包裝成Python調用腳本,發給UnrealMCP Server:

我們就可以得到最終結果:

和之前的例子一樣,開發UnrealMCP還是遵循定義工具名字,參數,定義行為的這幾個步驟,在UnrealMCP中,它采用了:

  • Python MCP 服務
  • Python-C++ 橋接層
  • C++ Unreal Engine 插件

的三層架構來實現(因為UE的EditorPython并不是很完善,所以需要通過C++插件來實現命令的解析和工作)。以最簡單的CreateObject為例子: 首先,依然是注冊工具和參數,當然,使用Python SDK,這個過程會更加直接簡單,通過Python的注解語法來進行:

@mcp.tool()
def create_object(ctx: Context, type: str, location: list = None, label: str = None) -> str:
    params = {"type": type}
    if location:
        params["location"] = location
    if label:
        params["label"] = label
    response = send_command("create_object", params)

我們需要告訴UE我要創建的location和物體類型,接下來,用Python的socket通信封裝一下LLM產生的數據,傳給UE:

def send_command(command_type, params=None, timeout=DEFAULT_TIMEOUT):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.connect(("localhost", DEFAULT_PORT))
        command = {"type": command_type, "params": params or {}}
        s.sendall(json.dumps(command).encode('utf-8'))
        response_data = receive_response(s)
        return json.loads(response_data.decode('utf-8'))

最后UE在C++插件中進行接受消息,去調用NewActor函數:

TSharedPtr<FJsonObject> FMCPCreateObjectHandler::Execute(const TSharedPtr<FJsonObject> &Params, FSocket *ClientSocket)
{
    // 從參數中提取數據
    FString Type;
    Params->TryGetStringField(FStringView(TEXT("type")), Type);
    
    // 執行 Unreal Engine 操作
    AStaticMeshActor *NewActor = World->SpawnActor<AStaticMeshActor>(...);
    
    // 返回響應
    TSharedPtr<FJsonObject> ResultObj = MakeShared<FJsonObject>();
    ResultObj->SetStringField("name", NewActor->GetName());
    return CreateSuccessResponse(ResultObj);
}

雖然整體流程復雜了些,但是可以看到,它依然遵循了MCP的設計范式,既通過Tools來擴展能力,告訴LLM,你可以去干什么事,然后用各種方法,將LLM分析自然語言后得出的指令轉為工具調用,去做真正的工作。

MCP的局限性

MCP雖然非常簡潔明了,大大方便了LLM Tool use的開發成本,但是從本質上來說,MCP只是解決了工具使用的可能性這一個主題,要想讓AI真正干活,可以說MCP只是干活的那只手,我們同樣需要大腦(規劃Agent),記憶力(數據庫,記事本)來共同輔助完成自動化的工作。

此外,對于真正的專業軟件來說,每一個接口/功能對應MCP可能也是一個工程量不小的工作,MCP結合真正靠譜的Agent編程框架才有可能完成真正復雜的任務。

總結

本文通過兩個案例,展示了MCP的整體開發邏輯和能力。通過MCP,大模型可以真正干活。但同時,MCP不應該被過度神話,它只是解決了工具調用這一系列的問題。要想讓大模型徹底重塑日常的游戲開發工作流,還需要在流程,記憶力,以及模型本身的后訓練上持續工作。

責任編輯:趙寧寧 來源: 騰訊技術工程
相關推薦

2025-06-19 03:30:00

智能體DifyMCP

2025-05-13 00:05:00

CursorMCP工具

2025-03-13 03:00:00

DockerAgentic工具

2025-04-01 08:38:25

模型上下文協議MCPLLM

2025-05-09 06:30:52

2025-05-08 00:00:00

2025-05-06 11:56:21

2025-04-22 09:17:41

2013-07-04 13:19:24

Java開發速度

2025-06-09 01:00:00

2025-05-28 01:20:00

MCPRAGAgent

2025-06-23 08:35:00

2025-05-14 03:20:00

AgenticAIMCP

2025-04-01 08:45:56

2025-04-17 08:42:38

2016-04-09 17:29:33

銳捷網絡云營銷

2025-05-27 00:15:07

2025-04-11 09:43:57

2025-06-10 09:28:31

智能體開發工具
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产一区 | 精品日韩一区二区三区 | 日日夜夜免费精品 | 欧美中文字幕一区二区三区 | av电影手机版 | 欧美日韩视频一区二区 | 成人免费观看视频 | 91精品国产一区二区三区 | 91一区二区三区 | 热99精品视频 | 国产一区中文字幕 | 欧美久久精品一级c片 | 亚洲嫩草| 国产1区2区在线观看 | 国产精品久久久久久久久大全 | 精品av天堂毛片久久久借种 | 亚洲第一色站 | 亚洲日本乱码在线观看 | 激情网站在线 | 久久亚洲国产 | 成人av在线播放 | 一级片片 | 一区二区在线不卡 | 中文字幕一区二区三区乱码在线 | 久久精品小视频 | 岛国av在线免费观看 | 一级做a爰片久久毛片免费看 | 日日夜夜91 | 在线中文视频 | 亚洲国产二区 | 国产精品欧美日韩 | 成人精品一区二区 | 狠狠影院 | 欧美一区二区三区电影 | 美女国产精品 | 免费视频中文字幕 | 国产99精品| 国产精品久久久久久久久久三级 | 国产精品国产三级国产aⅴ浪潮 | 一区二区三区在线免费观看视频 | 国产99久久久国产精品 |