All MCP handlers converted to new format
This commit is contained in:
194
refactor.md
Normal file
194
refactor.md
Normal file
@@ -0,0 +1,194 @@
|
||||
|
||||
# Handler Refactor Instructions
|
||||
|
||||
Plugins/BlueprintMCP/Source/BlueprintMCP contains an MCP server that allows
|
||||
Claude Code to control Unreal functions. MCP servers accept different
|
||||
commands; each command has a "handler."
|
||||
|
||||
We are converting all handlers from an old style to a new style. In the old
|
||||
style, each handler is a method of FMCPServer. In the new style, each
|
||||
handler is a UCLASS derived from IMCPHandler. You will be assigned one
|
||||
source file to convert. **Only modify that one file.**
|
||||
|
||||
## Step 1: Study the Existing Code
|
||||
|
||||
Before editing, read these files carefully:
|
||||
|
||||
- `MCPHandler.h` — the IMCPHandler interface and marker structs
|
||||
- `MCPUtils.h` — utility functions available to handlers
|
||||
- `MCPAssetFinder.h` — asset lookup helpers (FindAsset, LoadAsset, etc.)
|
||||
- `MCPHandlers_Interfaces.h` — a clean example of new-style handlers
|
||||
- `MCPHandlers_Validation.h` — another example (shows Optional params, bool, int32)
|
||||
- `MCPHandlers_AnimMutation.h` — another example (shows FMCPJsonArray)
|
||||
|
||||
All of these are in `Plugins/BlueprintMCP/Source/BlueprintMCP/`.
|
||||
|
||||
## Step 2: Convert Your File
|
||||
|
||||
Each old-style handler function becomes a new-style UCLASS. The mechanical
|
||||
steps are:
|
||||
|
||||
### 2a. Change the file header
|
||||
|
||||
Replace the old includes with this pattern:
|
||||
|
||||
```cpp
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "MCPHandler.h"
|
||||
#include "MCPAssetFinder.h"
|
||||
#include "MCPUtils.h"
|
||||
// ... any other includes the handlers actually need ...
|
||||
#include "MCPHandlers_YourFile.generated.h"
|
||||
```
|
||||
|
||||
Remove `#include "MCPServer.h"` — new-style handlers don't need it.
|
||||
|
||||
Remove any includes that are no longer used after conversion. Keep only
|
||||
what the handler bodies actually reference.
|
||||
|
||||
### 2b. Wrap each handler in a UCLASS
|
||||
|
||||
Each old-style function like this:
|
||||
|
||||
```cpp
|
||||
void FMCPServer::HandleFoo(const FJsonObject* Json, FJsonObject* Result)
|
||||
{
|
||||
FString Name = Json->GetStringField(TEXT("name"));
|
||||
// ... body ...
|
||||
}
|
||||
```
|
||||
|
||||
Becomes:
|
||||
|
||||
```cpp
|
||||
UCLASS(meta=(ToolName="the_mcp_tool_name"))
|
||||
class UMCPHandler_Foo : public UObject, public IMCPHandler
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
public:
|
||||
UPROPERTY(meta=(Description="Human-readable description of this parameter"))
|
||||
FString Name;
|
||||
|
||||
virtual FString GetDescription() const override
|
||||
{
|
||||
return TEXT("Human-readable description of what this tool does.");
|
||||
}
|
||||
|
||||
virtual void Handle(const FJsonObject* Json, FJsonObject* Result) override
|
||||
{
|
||||
// ... body (minus the parameter extraction) ...
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### 2c. Convert parameters to UPROPERTY fields
|
||||
|
||||
- Each `Json->GetStringField(TEXT("foo"))` at the top of the handler becomes
|
||||
a `UPROPERTY` field on the class. The framework populates these
|
||||
automatically before calling `Handle()`.
|
||||
|
||||
- **Naming rule**: The UPROPERTY field name's first character gets
|
||||
lowercased to produce the JSON key. So `FString Blueprint;` maps to
|
||||
JSON key `"blueprint"`. `FString PackagePath;` maps to `"packagePath"`.
|
||||
Choose field names so that this automatic mapping produces the correct
|
||||
JSON key (i.e. the same key the old code was reading).
|
||||
|
||||
- **Required vs optional**: Fields are required by default. Add
|
||||
`meta=(Optional, Description="...")` for optional parameters. Optional
|
||||
fields should have default values (e.g. `bool Foo = false;`,
|
||||
`int32 Limit = 0;`, `FString Bar;` — empty string is the default).
|
||||
|
||||
- **Supported types**: `FString`, `bool`, `int32`, `float`, `FName`.
|
||||
For JSON arrays use `FMCPJsonArray` (has `.Array` field of type
|
||||
`TArray<TSharedPtr<FJsonValue>>`). For JSON objects use `FMCPJsonObject`
|
||||
(has `.Json` field of type `TSharedPtr<FJsonObject>`).
|
||||
|
||||
- **Remove manual extraction**: Delete the `Json->GetStringField()`,
|
||||
`Json->GetBoolField()`, etc. lines that read parameters. The UPROPERTY
|
||||
fields already contain the values. You can still use `Json->HasField()`
|
||||
to check whether an optional field was actually provided (for cases
|
||||
where you need to distinguish "not provided" from "provided as default
|
||||
value").
|
||||
|
||||
- **Remove manual validation of required fields**: The framework already
|
||||
returns an error if a required UPROPERTY field is missing from JSON.
|
||||
Delete checks like `if (Name.IsEmpty()) return MakeErrorJson(...)` for
|
||||
required FString fields. However, keep validation that checks field
|
||||
*content* (e.g. "must start with /Game").
|
||||
|
||||
### 2d. Avoid UPROPERTY / local variable name conflicts
|
||||
|
||||
If the old code has a local variable with the same name as your new
|
||||
UPROPERTY field (e.g. UPROPERTY `FString Blueprint;` and local
|
||||
`UBlueprint* Blueprint`), rename the local variable. Convention:
|
||||
append `Obj` — e.g. `UBlueprint* BlueprintObj`, `USkeleton* SkeletonObj`.
|
||||
|
||||
### 2e. Tool name
|
||||
|
||||
The `ToolName` in the UCLASS meta must exactly match the tool name string
|
||||
that was used in the old-style `H(TEXT("tool_name"), ...)` registration
|
||||
in MCPServer.cpp. If you're unsure, search MCPServer.cpp for the old
|
||||
handler function name to find the tool name.
|
||||
|
||||
### 2f. GetDescription()
|
||||
|
||||
Write a concise 1-2 sentence description of what the tool does. This is
|
||||
shown to the LLM that calls the tool.
|
||||
|
||||
### 2g. Separator between classes
|
||||
|
||||
Put this separator between each UCLASS:
|
||||
|
||||
```cpp
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
// ---------------------------------------------------------------------------
|
||||
```
|
||||
|
||||
## Step 3: Rename the File
|
||||
|
||||
After conversion, rename the file from `.cpp` to `.h`. The file is now a
|
||||
header — UHT will process the GENERATED_BODY() macros during build.
|
||||
|
||||
## What NOT to Do
|
||||
|
||||
- **Do NOT modify MCPServer.h or MCPServer.cpp.** We will clean up old
|
||||
registrations separately.
|
||||
- **Do NOT modify MCPHandlers.cpp** (the include aggregator). We will add
|
||||
the new include separately.
|
||||
- **Do NOT add `#include "MCPServer.h"`** — new-style handlers are
|
||||
self-registering via UHT reflection and don't need it.
|
||||
- **Do NOT change the handler logic.** Convert the structure, not the
|
||||
behavior. This is a mechanical refactor. If you see a bug that can be
|
||||
fixed within your file (e.g. a typo), fix it. But if you see a bug that
|
||||
would require editing other files to fix, leave the code as-is and insert
|
||||
a prominent comment block like this:
|
||||
```cpp
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
// BUG: <description of the bug and what needs to change>
|
||||
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
```
|
||||
Another agent will deal with it later.
|
||||
- **Do NOT rename JSON output fields.** The tool's output format must stay
|
||||
identical.
|
||||
- **Do NOT add or remove handlers.** Convert exactly what's there.
|
||||
|
||||
## Files to Convert
|
||||
|
||||
Each of these `.cpp` files contains old-style handlers to convert:
|
||||
|
||||
1. `MCPHandlers_Read.cpp`
|
||||
2. `MCPHandlers_Discovery.cpp`
|
||||
3. `MCPHandlers_Graphs.cpp`
|
||||
4. `MCPHandlers_Variables.cpp`
|
||||
5. `MCPHandlers_Params.cpp`
|
||||
6. `MCPHandlers_Dispatchers.cpp`
|
||||
7. `MCPHandlers_Components.cpp`
|
||||
8. `MCPHandlers_Snapshot.cpp`
|
||||
9. `MCPHandlers_MaterialRead.cpp`
|
||||
10. `MCPHandlers_MaterialMutation.cpp`
|
||||
11. `MCPHandlers_MaterialInstance.cpp`
|
||||
12. `MCPHandlers_StateMachine.cpp`
|
||||
Reference in New Issue
Block a user