Unity游戏API框架

Mimir MCP是一个开源的Unity框架,用于创建自定义模型上下文协议表面,描述游戏API而非编辑器UI,提供工具、模式、线程模型和网络支持,以实现游戏内的安全自动化控制。

  • by dhruv304c2
  • C#
  • 本地部署
  • 1 星标
  • 更新于
在 GitHub 查看 dhruv304c2/mimir-mcp

使用说明

Mimir MCP是一个开源的Unity框架,用于制作定制的模型上下文协议表面,描述您的 游戏玩法 API,而不是编辑器UI。它为您提供了定义代理如何感知和操纵您的实时世界的原语——工具、模式、线程模型、网络——这样您就可以在运行的构建中为安全的自动化提供足够的控制。将其放入场景中,连接反映您游戏动词的工具集,您的MCP感知代理可以通过玩家触摸的相同系统引导体验。

关于框架

  • 嵌入式MCP主机 –the MCPHost 组件旋转起来很轻 HttpListener 直接在场景内部(编辑器或播放器构建),并将请求路由到已注册的工具处理程序。
  • Unity首次执行 –传入的调用在接触对象之前会被编组回Unity主线程,因此您可以安全地修改场景数据,而无需编写额外的管道。
  • 可组合工具 –每个能力都很小 MCPToolBase 实施。您可以启用预构建的工具集、混合和匹配集,或者添加自己的工具,并添加几个属性和一个异步覆盖。

安装(Git包)

先决条件

在安装Mimir MCP之前,请确保在Unity项目中安装了以下软件包:

  1. Newtonsoft JSON for Unity -JSON序列化所需

    • 打开 窗口>包管理器>+>从git URL添加包。。。
    • 粘贴: com.unity.nuget.newtonsoft-json@3.2.1
    • 点击 添加
  2. UniTask -需要异步/等待支持

    • 请按照以下位置的安装说明进行操作:https://github.com/Cysharp/UniTask#install-通过git url
    • 此软件包需要OpenUPM注册表设置

安装步骤

  1. 打开你的目标Unity项目。
  2. 首选 窗口▸ 包管理器▸ + ▸ 从Git URL添加包…
  3. 粘贴 https://github.com/dhruv304c2/mimir-mcp.git?path=/Assets/MimirMCP 并确认。
  4. 在继续之前,请验证是否安装了两个必备包(Newtonsoft JSON和UniTask)。
  5. 进入播放模式一次,让Unity生成asmdef缓存。现在,您的项目中有了运行时,可以将宿主行为添加到任何场景中。

Unity入门

  1. 创建主机游戏对象 –添加 MCPHostBehaviour 前言/脚本(或一个小型的MonoBaviour,其中包含 MCPHost)到你的现场。
  2. 配置网络 –设置主机和端口字段(默认值为 localhost:3000).
  3. 注册工具集 –in Start,获取处理程序并选择所需的助手:
    void Start()
    {
        _mcpHandler = new MCPHandler(logger: new UnityLogger())
            .UseDefaultToolSet(); // or chain specific Use*ToolSet calls
    
        _mcpHost = new MCPHost(port: 3000);
        _mcpHost.SetLogger(new UnityLogger());
        _mcpHost.RegisterDefaultHandlers();
        _mcpHost.UseMCPHandler(_mcpHandler);
        _mcpHost.StartHTTPServer();
    }
    
  4. 运行场景 –当你点击播放时,你应该看到 Hosting server at localhost:3000 在控制台中。当行为被破坏时,主机会自动停止,但您可以调用 StopHTTPServer 如果需要,手动。
  5. 添加自定义工具(可选) –源自 MCPToolBase,用以下方式装饰田地/房产 [MCPToolParam],实施 ExecuteTool(IReadOnlyDictionary<string, object>),然后在调用之前注册该工具 StartHTTPServer.

内置工具集和工具

工具集助手 包含的工具(工具名称) 典型用途
UseLogTool() log 将MCP触发的日志发送到Unity或自定义 ILogger 实施。
UseSceneHierarchyToolSet() scene_hierarchy_inspect 枚举根对象及其子对象以快速发现。
UseTransformToolSet() transform_change, transform_inspect, transform_position_update, transform_rotation_update, transform_scale_update 您可以通过层次路径处理任何游戏对象的读/写位置、旋转、缩放和过渡。
UseSerializedPropertyToolSet() inspector_component_list, inspector_property_inspect,加上设置器 string, bool, float, Vector2, Vector3,以及 Color 发现对象上有哪些组件,并更改序列化字段。
UseMaterialToolSet() mesh_material_inspect, mesh_material_set_color, mesh_material_set_float, mesh_material_set_boolean 检查渲染器的材质并远程更新着色器参数。
UseDefaultToolSet() 以上所有内容 无需考虑个人注册即可获得端到端沙盒的最快方法。

选择与要显示的控制曲面匹配的辅助对象。您可以呼叫多个助手或注册额外的定制工具,为您的团队或自动化代理构建精心策划的API表面。

数据库抽象

MimirMCP包括一个强大的数据库抽象系统,用于将Unity场景对象暴露给MCP工具。这允许AI代理查询场景中的MonoBehaviour集合并与之交互。

核心概念

数据库系统由几个关键接口和类组成:

  • IMCPDatabaseItem –可存储在数据库中的对象的接口。需要一个 ObjectId 财产和 ToJson() 方法。
  • MCPMonoBehaviourDatabaseItem –实现的基础MonoBehaviour类 IMCPDatabaseItem 自动JSON序列化。
  • IMCPDatabase<T> -类型安全数据库操作(添加、获取、删除项)的通用接口。
  • IMCPScannableDatabase<T> –扩展接口,支持通过以下方式配置读取策略 ReadFunction.
  • MCPMonoBehaviourDatabase<T> –灵活的实现,可以从任何来源填充:
    • Unity场景扫描 SetReadFromSceneHierarchy()
    • 通过以下方式自定义数据源 ReadFunction 委托
  • MCPHost.RegisterDatabase<T> 注册一个数据库,并自动创建一个MCP工具来读取它。

基本用法

  1. 创建数据库项类:

    using MimirMCP.Core.Database;
    using UnityEngine;
    
    public class Character : MCPMonoBehaviourDatabaseItem
    {
        [SerializeField]
        public string characterName;
    
        [SerializeField]
        [TextArea]
        public string description;
    }
    
  2. 在MCPHost中注册数据库:

    // Method 1: Using the convenience factory method (for MonoBehaviours)
    var characterDb = MCPMonoBehaviourDatabase<Character>.CreateFromScene();
    _mcpHost.RegisterDatabase("characters", characterDb);
    
    // Method 2: Manual configuration with custom options
    var characterDb = new MCPMonoBehaviourDatabase<Character>();
    characterDb.SetReadFromSceneHierarchy(
        sortMode: FindObjectsSortMode.InstanceID,
        includeInactive: true
    );
    characterDb.Read();
    _mcpHost.RegisterDatabase("characters", characterDb);
    
    // Method 3: Custom read function (for non-MonoBehaviour types or custom sources)
    var itemDb = new MCPMonoBehaviourDatabase<InventoryItem>();
    itemDb.ReadFunction = () => {
        // Custom logic to populate database from any source
        itemDb.AddItem(new InventoryItem { name = "Sword" });
        itemDb.AddItem(new InventoryItem { name = "Shield" });
    };
    itemDb.Read();
    _mcpHost.RegisterDatabase("inventory", itemDb);
    

    这将自动创建一个名为的工具 read_characters_database AI代理可以使用。

  3. 以编程方式检索项目:

    // Get the database
    var db = _mcpHost.GetDatabase<Character>();
    
    // Get a specific item by ID
    var character = db.GetItemById(objectId);
    
    // Get all items
    var allCharacters = db.All();
    

MCP工具使用

注册数据库时,会自动创建相应的MCP工具。对于上述示例:

  • 工具名称: read_characters_database
  • 参数:
    • object_id (可选)–通过ID检索特定项目
  • 退货:项目的JSON表示

获取所有字符的示例工具调用:

{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "tools/call",
  "params": {
    "tool_name": "read_characters_database",
    "arguments": {}
  }
}

获取特定字符的示例工具调用:

{
  "jsonrpc": "2.0",
  "id": "2",
  "method": "tools/call",
  "params": {
    "tool_name": "read_characters_database",
    "arguments": {
      "object_id": "12345-6789-abcd-efgh"
    }
  }
}

高级功能

自定义读取功能: 数据库系统通过以下方式支持灵活的读取策略 ReadFunction 财产:

// Read from a JSON file
database.ReadFunction = () => {
    var json = File.ReadAllText("data/characters.json");
    var items = JsonConvert.DeserializeObject<List<Character>>(json);
    foreach (var item in items) {
        database.AddItem(item);
    }
};

// Read from a web service
database.ReadFunction = async () => {
    var response = await httpClient.GetStringAsync("https://api.example.com/characters");
    // Parse and add items...
};

// Combine multiple sources
database.ReadFunction = () => {
    // First read from scene
    database.SetReadFromSceneHierarchy();
    database.Read();

    // Then add items from other sources
    database.AddItem(specialCharacter);
};

多个数据库:

// Register multiple database types
_mcpHost.RegisterDatabase("characters", MCPMonoBehaviourDatabase<Character>.CreateFromScene());
_mcpHost.RegisterDatabase("locations", MCPMonoBehaviourDatabase<Location>.CreateFromScene());
_mcpHost.RegisterDatabase("items", new MCPMonoBehaviourDatabase<InventoryItem> {
    ReadFunction = LoadInventoryFromSaveGame
});

线程安全:使用读写器锁,所有数据库操作都是线程安全的,允许从MCP工具调用进行安全的并发访问。

最佳实践

  1. 适当配置读取策略 –使用 SetReadFromSceneHierarchy() 对于场景对象,或设置自定义 ReadFunction 对于其他数据源。
  2. 使用有意义的名称 –数据库名称成为MCP工具名称的一部分(例如,“字符”→ “read_characters_database”)。
  3. 保持物品轻便 –The ToJson() 方法被频繁调用,因此避免了昂贵的序列化。
  4. 每个数据库一种类型 –每种类型在MCPHost中只能有一个注册的数据库。

调用托管MCP API

主机运行后,您可以通过HTTP与之交互。所有路径都以您配置的主机/端口为根。

  • GET / –简单的健康调查。示例响应:
    { "message": "Service is healthy" }
    
  • GET /mcp –确认MCP端点存在的发现ping:
    { "message": "Mimir-MCP endpoint ready at /mcp (POST for MCP RPC)." }
    
  • POST /mcp –JSON-RPC风格的MCP端点。主体遵循MCP规范,并支持以下所示的标准方法:
    • initialize –协商协议版本。
    • ping -活着。
    • tools/list –列举每个注册的工具和从您的 MCPToolParam 属性。
    • tools/call –使用参数按名称调用工具。

示例 tools/list 请求/响应:

curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{
        "jsonrpc": "2.0",
        "id": "list-1",
        "method": "tools/list",
        "params": {}
      }'

响应(截断):

{
  "jsonrpc": "2.0",
  "id": "list-1",
  "result": {
    "tools": [
      {
        "name": "log",
        "description": "A tool to log messages to the Unity console via MCP.",
        "inputSchema": {
          "properties": {
            "message": { "type": "string" },
            "level": { "type": "string" }
          },
          "required": ["message"]
        }
      }
    ]
  }
}

示例 tools/call 要运行日志工具,请执行以下操作:

curl -X POST http://localhost:3000/mcp \
  -H "Content-Type: application/json" \
  -d '{
        "jsonrpc": "2.0",
        "id": "call-1",
        "method": "tools/call",
        "params": {
          "tool_name": "log",
          "arguments": {
            "message": "Hello from MCP!",
            "level": "warning"
          }
        }
      }'

典型成功载荷:

{
  "jsonrpc": "2.0",
  "id": "call-1",
  "result": {
    "content": [
      { "type": "text", "text": "Logged message as Warning level." }
    ]
  }
}

交换 tool_name 和 arguments 针对任何其他内置或自定义工具。

错误处理

Mimir MCP会自动捕获从您的 ExecuteTool 并将其作为符合MCP的错误响应返回。您无需担心错误代码或响应格式,只需抛出标准的C#异常即可。

运作原理

当 ExecuteTool throws,框架捕获异常并返回 JSON-RPC协议错误 MCP客户端(包括Google ADK)识别并向代理表明:

{
  "jsonrpc": "2.0",
  "id": "call-1",
  "error": {
    "code": -32602,
    "message": "Transform 'NonExistent/Path' was not found."
  }
}

代理框架在传输层看到错误并向LLM报告失败,LLM然后可以进行调整(使用不同的参数重试、调用不同的工具等)。

抛出哪个例外

使用语义上与失败匹配的标准C#异常。该框架将每种异常类型映射到JSON-RPC错误代码:

场景 异常 JSON-RPC错误代码 示例
参数缺失或无效 ArgumentException -32602 throw new ArgumentException("path parameter is required.");
找不到对象/资源 KeyNotFoundException -32602 throw new KeyNotFoundException($"Transform '{path}' was not found.");
请求中的数据格式错误 JsonException -32700 throw new JsonException("Expected a JSON object.");
功能未实现 NotImplementedException -32601 throw new NotImplementedException("Undo is not supported.");
状态或先决条件无效 InvalidOperationException -32603 throw new InvalidOperationException("Active scene is invalid.");
操作超时 TimeoutException -32603 throw new TimeoutException("Physics raycast timed out.");
任何其他故障 Exception (或子类) -32603 throw new Exception("Something unexpected happened.");

示例

[MCPTool(toolName: "my_tool", description: "Does something cool.")]
public class MyTool : MCPToolBase
{
    [MCPToolParam("target", "Path to the target object.", MCPToolParam.ParamType.String, true)]
    public string Target;

    protected override UniTask<ContentBase[]> ExecuteTool(
        IReadOnlyDictionary<string, object> rawParameters)
    {
        if (string.IsNullOrWhiteSpace(Target))
            throw new ArgumentException("target is required.");

        var scene = SceneManager.GetActiveScene();
        if (!scene.IsValid())
            throw new InvalidOperationException("No active scene.");

        var go = GameObject.Find(Target);
        if (go == null)
            throw new KeyNotFoundException($"GameObject '{Target}' not found.");

        // Do work...
        return UniTask.FromResult(new ContentBase[] { new ContentText("Done.") });
    }
}

错误响应层

层 触发它的原因 响应形状
参数绑定 缺少必需的参数,类型转换失败 JSON-RPC error 带代码 -32602
工具执行 任何例外情况 ExecuteTool JSON-RPC error 从异常类型映射代码
运输/路线 JSON正文格式错误,MCP方法未知 JSON-RPC error 带代码 -32700 或 -32603

所有错误都是协议级JSON-RPC错误。这确保了MCP客户端(包括Google ADK)可靠地向代理报告故障,无论它们是否支持 isError 内容标志。

灵感

Mimir的名字来源于陪伴奎托斯的无形圣人 战神:一个犀利、非侵入性的向导,他的建议在不抓住控制者的情况下赋予英雄权力。该框架旨在实现同样的平衡。它为你的代理人提供了在游戏中提供建议甚至采取行动所需的知识和切入点,而你则负责你暴露的叙事表面。

许可证

Mimir MCP在MIT许可证下可用。看 LICENSE 了解详情。