# 사용자 지정 도구 — Godot · AI Game Developer Wiki

C#로 나만의 Godot MCP 도구를 작성하고, 메인 스레드에서 Godot API를 호출하며, 실행 중인 Godot 게임에서 도구와 프롬프트, 리소스를 노출하세요.

이 페이지는 영어에서 기계 번역되었습니다. [영어 원문 읽기](https://ai-game.dev/docs/wiki/godot/custom-tools).

프로젝트 안에서 순수 C#으로 Godot MCP에 자신만의 MCP 도구를 추가할 수 있습니다. 사용자 지정 도구는 AI 에이전트가 호출할 수 있는 메서드이며, 설명을 통해 모델이 그 도구가 무엇을 하는지 알 수 있습니다. 이 페이지에서는 에디터 도구, 메인 스레드 규칙, 그리고 에이전트가 실행 중인 게임과 대화할 수 있게 해주는 옵트인 런타임을 다룹니다.

## 에디터 도구 작성하기

도구 패밀리는 `[AiToolType]`이 붙은 `partial class`입니다. 각 도구는 `[AiTool("tool-name")]`이 붙은 메서드이며, 메서드와 모든 매개변수에 `[Description]`을 붙여 모델이 언제 어떻게 호출해야 하는지 알 수 있게 합니다.

```csharp
using System.ComponentModel;
using com.IvanMurzak.McpPlugin;           // [AiToolType], [AiTool]
using com.IvanMurzak.ReflectorNet.Utils;  // MainThread

[AiToolType]
public partial class Tool_MyFeature
{
    [AiTool("my-custom-task", Title = "Do a custom task")]
    [Description("Explain to the LLM what this does and when to call it.")]
    public string CustomTask
    (
        [Description("Explain to the LLM what this parameter is.")]
        string inputData
    )
    {
        // Work that does not touch the Godot API can run here, on a background thread.

        return MainThread.Instance.Run(() =>
        {
            // Touch EditorInterface, Node or Resource here, on the main thread.
            return "[Success] Operation completed.";
        });
    }
}
```

C# 프로젝트를 빌드하세요(에디터의 Build 버튼, `godot-cli build`, 또는 에이전트에게 `script-build` 실행 요청). Godot이 어셈블리를 다시 로드하고 애드온이 재연결되면, 새 도구가 에이전트의 도구 목록과 독의 Tools 창에 나타납니다.

### 도구를 안정적으로 유지하는 규칙

- **Godot 객체는 메인 스레드에서만.** 도구 메서드는 메인 스레드 밖에서 호출됩니다. `Node`, `Resource`, `SceneTree`, `EditorInterface`에 대한 모든 호출은 `MainThread.Instance.Run(...)`을 거쳐야 합니다. 백그라운드 스레드에서 이들에 접근하면 에디터가 충돌할 수 있습니다.
- **포맷된 텍스트가 아니라 데이터를 반환하세요.** 속성이 있는 클래스를 반환하거나(모델을 위해 직렬화됩니다), 부수 효과만 있는 도구라면 `void`를 반환하세요. 에이전트가 파싱해야 하는 값에는 직접 만든 문자열을 쓰지 마세요.
- **선택적 매개변수를 표시하세요.** 기본값이 있는 널 허용 타입을 사용하세요. 예를 들어 `string? filter = null`처럼 쓰면 모델이 해당 매개변수를 선택 사항으로 취급합니다.
- **모든 것을 설명하세요.** 모델이 읽는 것은 바로 이 설명입니다. 도구가 무엇을 하는지, 언제 사용해야 하는지, 각 매개변수가 무엇을 의미하는지 적으세요.
- **에디터 전용 코드는 `#if TOOLS` 뒤에 두세요.** 에디터 API를 사용하는 코드는 내보낸 게임에 컴파일되어서는 안 됩니다.

### 힌트와 대상

`[AiTool]`은 `ReadOnlyHint = true`, `IdempotentHint = true` 같은 선택적 힌트를 받으며, 이는 클라이언트에게 해당 도구가 아무것도 변경하지 않거나 안전하게 반복 호출할 수 있음을 알려줍니다. `Target`은 도구가 등록되는 위치를 결정합니다: `ToolTarget.Editor`(에디터 전용), `ToolTarget.Runtime`(게임 전용), 또는 기본값인 양쪽 모두입니다.

### 에이전트가 도구를 작성하게 하기

시스템 도구 `godot-skill-create`는 프로젝트에 새 C# 도구 파일을 작성하며, 해당 도구는 다음 빌드 후에 호출 가능해집니다. 새 도구를 작성하기 전에 RQL이 이미 그 작업을 처리하는지 확인하세요. 대부분의 에디터 데이터 접근(노드, 리소스, 파일, 프로젝트 설정)은 `rql-query`나 `rql-mutate` 한 번이면 됩니다. [Tools](https://ai-game.dev/ko/docs/wiki/godot/tools#rql)를 참고하세요.

## 실행 중인 게임 속 도구

Godot MCP는 실행 중이거나 내보낸 게임 안에서도 동작할 수 있습니다(디버그 또는 릴리스). 이를 통해 에이전트는 실시간 게임 상태를 읽고 제어할 수 있습니다. 예를 들어 봇의 수가 LLM에서 나오는 체스 게임이 그렇습니다. 두 가지는 의도된 설계입니다:

- **스스로 연결하지 않습니다.** 연결 여부와 시점은 `Connect()` 호출로 여러분의 코드가 결정합니다.
- **기본적으로 아무것도 노출하지 않습니다.** 모든 도구, 프롬프트, 리소스는 직접 등록해야 합니다. 애드온의 에디터 도구는 게임 빌드에 컴파일되지 않습니다.

`SceneTree`가 존재한 뒤에 시작하세요. 예를 들어 오토로드의 `_Ready()`에서 시작할 수 있습니다:

```csharp
using System.Reflection;
using com.IvanMurzak.Godot.MCP.Connection;
using com.IvanMurzak.Godot.MCP.Runtime;
using McpServerConsts = com.IvanMurzak.McpPlugin.Common.Consts.MCP.Server;
using Godot;

public partial class GameMcp : Node
{
    private GodotMcpRuntimeHandle? _mcp;

    public override async void _Ready()
    {
        _mcp = GodotMcpRuntime.Initialize(builder =>
        {
            builder.WithConfig(config =>
            {
                config.ConnectionMode = GodotMcpConnectionMode.Custom;
                config.Host = "http://localhost:8080";
                config.AuthOption = McpServerConsts.AuthOption.token;
                config.Token = "your-secret-token";
            });
            builder.WithToolsFromAssembly(Assembly.GetExecutingAssembly());
        }).Build();

        await _mcp.Connect();
    }

    public override async void _ExitTree()
    {
        if (_mcp is not null)
            await _mcp.Disconnect();
    }
}
```

게임 전용 도구 클래스에는 `[AiToolType(Target = ToolTarget.Runtime)]`을 붙이세요(`com.IvanMurzak.McpPlugin.Common`에서 제공). 그러면 에디터가 해당 도구를 등록하지 않으며, 에디터가 연결되어 있는 동안에도 에이전트가 게임에 접근할 수 있습니다.

### 빌더 옵션

| 호출 | 동작 내용 |
| --- | --- |
| `WithConfig(...)` | 코드에서 `Host`, `Token`, `ConnectionMode`, `AuthOption`을 설정합니다. |
| `WithToolsFromAssembly(...)` / `WithTools(...)` | 어셈블리에서 `[AiToolType]` 클래스를 등록하거나 특정 타입을 등록합니다. |
| `WithPromptsFromAssembly(...)` / `WithPrompts(...)` | `[AiPromptType]` 프롬프트 클래스를 등록합니다. |
| `WithResourcesFromAssembly(...)` / `WithResources(...)` | `[AiResourceType]` 리소스 클래스를 등록합니다. |
| `WithRuntimeErrorCapture()` | 게임 내 오류를 캡처하고 `runtime-errors-get` / `runtime-errors-clear`를 등록합니다. 기본값은 꺼짐입니다. |
| `WithScriptExecute()` | 게임에 `script-execute`를 등록합니다. 기본값은 꺼짐이며 `.csproj` 옵트인이 필요합니다. |
| `ConnectWhenRunFromEditor()` | 에디터에서 Play로 게임을 시작한 경우에도 연결합니다. 기본값은 꺼짐입니다. |
| `WithoutMainThreadDispatcher()` | 자동 메인 스레드 디스패처를 건너뜁니다(직접 설치한 경우에만). |

Host와 토큰은 `GODOT_MCP_*` 환경 변수나 `.env` 파일에서도 가져올 수 있으며, 이 값이 코드보다 우선합니다. 게임은 에디터에 저장된 설정을 절대 읽지 않습니다.

### 프롬프트와 리소스

도구 외에도, 게임은 MCP 프롬프트(이름이 붙은 지시 템플릿, `[AiPrompt]` 메서드가 있는 `[AiPromptType]`)와 리소스(URI로 가져오는 읽기 전용 콘텐츠, `[AiResource]` 메서드가 있는 `[AiResourceType]`)를 노출할 수 있습니다. 각 종류는 선택 사항이며 도구와 동일한 방식으로 등록됩니다.

### 게임 내부에서 C# 실행하기

에이전트가 게임에서 C#을 실행하도록 하려면 게임의 `.csproj`에서 옵트인하고 `WithScriptExecute()`를 호출하세요:

```xml
<PropertyGroup>
  <GodotMcpCodeExecInGame>true</GodotMcpCodeExecInGame>
  <DefineConstants>$(DefineConstants);GODOT_MCP_CODE_EXEC_IN_GAME</DefineConstants>
</PropertyGroup>
```

이 기능은 데스크톱 CoreCLR 빌드에서만 동작하며, NativeAOT나 iOS에서는 동작하지 않습니다.

**경고**

게임 내 `script-execute`는 임의 코드 실행이며, 런타임 오류 캡처는 경로, 사용자 이름 또는 비밀 정보가 포함될 수 있는 전체 메시지와 스택 트레이스를 전달합니다. 둘 다 개발 빌드에서, 실제 토큰을 사용하는 루프백 호스트에서만 사용하고, 공개 릴리스에서는 절대 활성화한 채로 배포하지 마세요.

## 게임 빌드를 위한 보안 체크리스트

- `localhost` 또는 `127.0.0.1`에서 `AuthOption.token`과 실제 토큰을 사용하는 Custom 모드를 선호하세요.
- 필요한 도구만 등록하세요. 공격 표면은 정확히 여러분이 등록한 도구입니다.
- 그렇게 하도록 설계하고 보안을 갖추지 않은 한, 릴리스 빌드에서 공용 네트워크 인터페이스에 연결을 노출하지 마세요.

전체 도구 목록은 [Tools](https://ai-game.dev/ko/docs/wiki/godot/tools)를, 패키징된 도구 세트는 [Extensions](https://ai-game.dev/ko/docs/wiki/godot/extensions)를 참고하세요.

---

Source (HTML): https://ai-game.dev/ko/docs/wiki/godot/custom-tools

Machine-translated (ko) from the English page: https://ai-game.dev/docs/wiki/godot/custom-tools
