Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/davidbuenov/dbv-mcp-server/llms.txt

Use this file to discover all available pages before exploring further.

Unreal Engine 5.8 registers toolsets under their fully-qualified Python module class paths. These names are verbose and inconvenient to type. The proxy (server.py and bridge.py) include a translate_toolset_name() function that resolves short or abbreviated names to the real registered names at runtime, using the local tools cache as the source of truth.

Why Qualified Names Are Long

When a Python toolset is loaded by the UE plugin, its class identity is <python_module_path>.<ClassName> — the same dotted path that Python itself uses to locate the class. For example, the Scene Tools class lives at:
editor_toolset.toolsets.scene.SceneTools
Clients must use this exact string when calling describe_toolset or call_tool with a toolset_name argument. The proxy’s translation layer makes it possible to use shorter names and have them resolved automatically.

Known Toolset Mappings

The table below shows the short reference names (as used in documentation, UI shortcuts, and AI prompts) mapped to the fully-qualified names registered in the engine.
Short Name / Common ReferenceFull Registered Name
EditorToolset.SceneToolseditor_toolset.toolsets.scene.SceneTools
EditorToolset.ActorToolseditor_toolset.toolsets.actor.ActorTools
EditorToolset.AssetToolseditor_toolset.toolsets.asset.AssetTools
EditorToolset.MaterialToolseditor_toolset.toolsets.material.MaterialTools
EditorToolset.BlueprintToolseditor_toolset.toolsets.blueprint.BlueprintTools
ToolsetRegistry.AgentSkillToolsetToolsetRegistry.AgentSkillToolset (exact — no translation needed)
The mappings above reflect the toolsets available when the EditorToolset, AutomationTestToolset, SlateInspectorToolset, and ToolsetRegistry plugins are all enabled. If a plugin is disabled, its toolsets will not appear in list_toolsets and cannot be translated or called.

Translation Algorithm

translate_toolset_name() reads .mcp_tools_cache.json and applies two resolution passes:
1. Exact match
   Is `toolset_name` already a known registered name?
   → Return it unchanged.

2. Case-insensitive suffix match
   Take the last segment after the final dot (e.g. "SceneTools" from "EditorToolset.SceneTools").
   Compare it (lowercase) against the last segment of every registered toolset name.
   → Return the first match found.

3. No match
   Return the original value unchanged. The Unreal server will return a "Toolset not found"
   error, which surfaces as a JSON-RPC error response.
The suffix match makes all of these equivalent for SceneTools:
SceneTools
EditorToolset.SceneTools
editor_toolset.toolsets.scene.SceneTools   ← already exact, returned as-is

Source Code

Here is the translate_toolset_name function as implemented in both server.py (async FastAPI proxy) and bridge.py (stdio bridge). Both implementations are identical in logic:
def translate_toolset_name(toolset_name: str) -> str:
    """
    Translates toolset names with incorrect prefixes or casing differences
    to the real class name registered in Unreal, using the local disk cache.
    e.g. "EditorToolset.SceneTools" -> "editor_toolset.toolsets.scene.SceneTools"
    """
    if not toolset_name:
        return toolset_name

    cache_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), ".mcp_tools_cache.json")
    if os.path.exists(cache_path):
        try:
            with open(cache_path, "r", encoding="utf-8") as f:
                cache_data = json.load(f)
                registered_toolsets = set()
                for tool in cache_data.get("tools", []):
                    name = tool.get("name", "")
                    if "." in name:
                        registered_toolsets.add(name[:name.rfind(".")])

                # Pass 1: exact match
                if toolset_name in registered_toolsets:
                    return toolset_name

                # Pass 2: case-insensitive suffix match
                requested_suffix = toolset_name.split(".")[-1].lower()
                for reg in registered_toolsets:
                    reg_suffix = reg.split(".")[-1].lower()
                    if requested_suffix == reg_suffix:
                        print(f"[server] Auto-translating toolset: {toolset_name} -> {reg}")
                        return reg
        except Exception as e:
            print(f"[server] Error in translate_toolset_name: {e}")

    return toolset_name

Dot-Notation Tool Calls

The proxy also supports calling toolset tools directly using a fully dotted name as the tools/call name parameter:
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "editor_toolset.toolsets.scene.SceneTools.SpawnActor",
    "arguments": { ... }
  }
}
The proxy splits on the last dot to separate the toolset name from the tool name:
editor_toolset.toolsets.scene.SceneTools.SpawnActor
└─────────────────────────────────────┘ └──────────┘
              toolset_name               tool_name
It then rewrites the request as a call_tool invocation:
{
  "name": "call_tool",
  "arguments": {
    "toolset_name": "editor_toolset.toolsets.scene.SceneTools",
    "tool_name": "SpawnActor",
    "arguments": { ... }
  }
}
translate_toolset_name() is applied to toolset_name before the call is forwarded, so short names like EditorToolset.SceneTools.SpawnActor also work:
EditorToolset.SceneTools.SpawnActor
└───────────────────────┘ └──────────┘
  translated to full name   tool_name

Caching Mechanism

The tools cache is stored at .mcp_tools_cache.json in the project root. It is used by both the translation function and the tools-list flattening logic.

Cache structure

{
  "toolsets_hash": "d41d8cd98f00b204e9800998ecf8427e",
  "tools": [
    {
      "name": "editor_toolset.toolsets.scene.SceneTools.SpawnActor",
      "description": "Spawns an actor in the current level.",
      "inputSchema": { ... }
    },
    ...
  ]
}
FieldDescription
toolsets_hashMD5 hash of the raw text returned by list_toolsets. Used to detect when the registry has changed.
toolsFlattened array of all tool definitions — native tools plus every tool from every toolset.

Cache validation flow

tools/list request received

    ├─ Hash current list_toolsets output

    ├─ Hash == in-memory hash?  ──YES──▶  Return cached list immediately (0 ms)
    │          │
    │          NO
    │          │
    ├─ Hash == .mcp_tools_cache.json hash?  ──YES──▶  Load from disk, update memory cache
    │          │
    │          NO
    │          │
    └─ Rebuild: call describe_toolset for each toolset concurrently (asyncio.gather)
                Save result to disk and memory
The cache is invalidated automatically whenever the list_toolsets output changes — for example when a new plugin is enabled or a custom toolset is registered at runtime.
If .mcp_tools_cache.json is missing or corrupted, translate_toolset_name() returns the original string unchanged and relies on Unreal to produce a “Toolset not found” error. Delete the cache file and call tools/list once to trigger a clean rebuild.

Build docs developers (and LLMs) love