> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# 도구

> Laravel Copilot SDK에서 커스텀 도구를 정의, 처리하고, 권한 설정, 호출 메타데이터, MCP 결과 변환을 다룹니다.

## 도구

Copilot CLI의 빌트인 도구는 기본적으로 활성화되어 있습니다. 여기서 지정할 수 있는 것은 커스텀 도구입니다.

## 기본 사용법

SessionConfig의 `tools`에 도구 정의를 지정합니다.

`Tool::define()`은 타 언어 버전의 `defineTool`과 같은 헬퍼입니다.
parameters에는 Laravel 자체가 Laravel MCP에서 사용하는 JsonSchema를 사용할 수 있습니다. JsonSchema를 사용하지 않고 직접 배열을 지정할 수도 있습니다.

```php theme={null}
use Illuminate\Support\Facades\Artisan;
use Illuminate\JsonSchema\JsonSchema;
use Revolution\Copilot\Contracts\CopilotSession;
use Revolution\Copilot\Facades\Copilot;
use Revolution\Copilot\Types\SessionConfig;
use Revolution\Copilot\Types\Tool;
use Revolution\Copilot\Types\ToolResultObject;

use function Laravel\Prompts\{info, note, spin, warning};

Artisan::command('copilot:tools', function () {
    $facts = [
        'PHP' => 'A popular general-purpose scripting language that is especially suited to web development.',
        'Laravel' => 'A web application framework with expressive, elegant syntax.',
    ];

    $parameters = JsonSchema::object(
        properties: [
            'topic' => JsonSchema::string()
                ->description('Topic to look up (e.g., "PHP", "Laravel")')
                ->required(),
        ],
    )->toArray();

    $config = new SessionConfig(
        tools: [
            Tool::define(
                name: 'lookup_fact',
                description: 'Returns a fun fact about a given topic.',
                parameters: $parameters,
                handler: function (array $params, array $invocation) use ($facts): array {
                    $topic = $params['topic'] ?? '';

                    $fact = $facts[$topic] ?? null;

                    if (! $fact) {
                        return new ToolResultObject(
                            textResultForLlm: "No fact stored for {$topic}.",
                            resultType: 'failure',
                            sessionLog: "lookup_fact: missing topic {$topic}",
                            toolTelemetry: [],
                        );
                    }

                    return new ToolResultObject(
                        textResultForLlm: $fact,
                        resultType: 'success',
                        sessionLog: "lookup_fact: served {$topic}",
                        toolTelemetry: [],
                    );
                },
                overridesBuiltInTool: false,
                skipPermission: false, // true로 하면 퍼미션 프롬프트 없이 실행
                defer: 'auto', // 도구를 항상 프리로드하는 것이 아니라, 지연 로드(도구 검색에 의한 지연 로드)할지 여부를 제어합니다. `"auto"`의 경우 도구는 지연 로드되며 도구 검색으로 표시됩니다. `"never"`의 경우 도구는 항상 프리로드됩니다. 옵션. 기본값은 `"auto"`입니다.
            ),
        ],
    );

    Copilot::start(function (CopilotSession $session) {
        info('Starting Copilot with tools: '.$session->id());

        $prompt = 'You can call the lookup_fact tool. Use lookup_fact to tell me something about Laravel.';

        warning($prompt);

        $response = spin(
            callback: fn () => $session->sendAndWait($prompt),
            message: 'Copilot thinking...',
        );

        note($response->content());
    }, config: $config);
});
```

## skipPermission

`skipPermission: true`를 지정하면 그 도구는 퍼미션 프롬프트 없이 실행할 수 있습니다.

```php theme={null}
Tool::define(
    name: 'read_only_lookup',
    description: 'Read-only data lookup.',
    parameters: $parameters,
    handler: fn ($params) => ['result' => 'data'],
    skipPermission: true,
),
```

## \$invocation

도구 핸들러의 두 번째 인자 `$invocation`에는 다음 필드가 전달됩니다.

```php theme={null}
[
    'sessionId'  => '...',
    'toolCallId' => '...',
    'toolName'   => 'lookup_fact',
    'arguments'  => [...], // 도구 인자($params와 같은 내용)
    // OpenTelemetry가 활성화된 경우에만 포함됨
    'traceparent' => '...', // W3C Trace Context traceparent
    'tracestate'  => '...', // W3C Trace Context tracestate
]
```

## 프로토콜 세부

Protocol v3(현재의 기본값)에서는 도구 호출이 JSON-RPC 요청이 아니라 세션 이벤트(`external_tool.requested`)로 브로드캐스트됩니다. SDK는 이 이벤트를 내부적으로 처리해 `session.tools.handlePendingToolCall` RPC로 응답합니다.

**`SessionConfig`의 사용법은 변하지 않습니다.** `tools`에 정의를 전달하는 것만으로 프로토콜 차이는 SDK가 흡수합니다.

## MCP CallToolResult의 변환

MCP 서버의 도구 결과(`CallToolResult`)를 Copilot SDK의 `ToolResultObject`로 변환하려면 `McpCallToolResult::convert()`를 사용합니다.
MCP 도구의 결과는 text, image, resource 등의 `content` 블록 배열이지만, Copilot SDK는 `ToolResultObject` 형식을 기대하므로 변환이 필요합니다.

```php theme={null}
use Revolution\Copilot\Support\McpCallToolResult;

// MCP CallToolResult 형식
$mcpResult = [
    'content' => [
        ['type' => 'text', 'text' => 'File contents here'],
        ['type' => 'image', 'data' => 'base64...', 'mimeType' => 'image/png'],
    ],
    'isError' => false,
];

// Copilot SDK ToolResultObject 형식으로 변환
$toolResult = McpCallToolResult::convert($mcpResult);
// $toolResult->textResultForLlm => 'File contents here'
// $toolResult->resultType => 'success'
// $toolResult->binaryResultsForLlm => [['data' => 'base64...', 'mimeType' => 'image/png', 'type' => 'image']]
```

<Info>
  최신 정보는 [GitHub 저장소](https://github.com/invokable/laravel-copilot-sdk)를 참고하세요.
</Info>


## Related topics

- [Laravel AI SDK](/ko/ai-sdk.md)
- [Laravel PAO — AI 에이전트용 출력 최적화 도구](/ko/blog/pao-introduction.md)
- [Laravel MCP](/ko/mcp.md)
- [시작하기 - GitHub Copilot SDK for Laravel](/ko/packages/laravel-copilot-sdk/getting-started.md)
- [Laravel에서 MCP 서버 만들기](/ko/advanced/mcp-server.md)
