query에 전달하며, Claude가 액세스할 수 있는 도구를 제어하는 방법을 다룹니다. 또한 오류 처리, 도구 주석, 이미지와 같은 비텍스트 콘텐츠 반환에 대해서도 다룹니다.
빠른 참조
| 원하는 작업 | 수행 방법 |
|---|---|
| 도구 정의 | 이름, 설명, 스키마 및 핸들러를 사용하여 @tool (Python) 또는 tool() (TypeScript)을 사용합니다. 사용자 정의 도구 만들기를 참조하세요. |
| Claude에 도구 등록 | create_sdk_mcp_server / createSdkMcpServer로 래핑하고 query()의 mcpServers에 전달합니다. 사용자 정의 도구 호출을 참조하세요. |
| 도구 사전 승인 | 허용된 도구에 추가합니다. 허용된 도구 구성을 참조하세요. |
| Claude의 컨텍스트에서 기본 제공 도구 제거 | 원하는 기본 제공 도구만 나열하는 tools 배열을 전달합니다. 허용된 도구 구성을 참조하세요. |
| Claude가 도구를 병렬로 호출하도록 허용 | 부작용이 없는 도구에 readOnlyHint: true를 설정합니다. 도구 주석 추가를 참조하세요. |
| 루프를 중지하지 않고 오류 처리 | 예외를 발생시키는 대신 isError: true를 반환합니다. 오류 처리를 참조하세요. |
| 이미지 또는 파일 반환 | 콘텐츠 배열에서 image 또는 resource 블록을 사용합니다. 이미지 및 리소스 반환을 참조하세요. |
| 머신 판독 가능한 JSON 결과 반환 | 결과에 structuredContent를 설정합니다. 구조화된 데이터 반환을 참조하세요. |
| 많은 도구로 확장 | 도구 검색을 사용하여 필요에 따라 도구를 로드합니다. |
사용자 정의 도구 만들기
도구는 TypeScript의tool() 헬퍼 또는 Python의 @tool 데코레이터에 인수로 전달되는 네 부분으로 정의됩니다:
- 이름: Claude가 도구를 호출하는 데 사용하는 고유 식별자입니다.
- 설명: 도구가 수행하는 작업입니다. Claude는 이를 읽고 도구를 호출할 시기를 결정합니다.
- 입력 스키마: Claude가 제공해야 하는 인수입니다. TypeScript에서는 항상 Zod 스키마이며, 핸들러의
args는 자동으로 입력됩니다. Python에서는{"latitude": float}와 같이 이름을 유형에 매핑하는 딕셔너리이며, SDK가 JSON Schema로 변환합니다. Python 데코레이터는 열거형, 범위, 선택적 필드 또는 중첩된 객체가 필요할 때 전체 JSON Schema 딕셔너리도 허용합니다. - 핸들러: Claude가 도구를 호출할 때 실행되는 비동기 함수입니다. 검증된 인수를 받고 다음을 포함하는 객체를 반환해야 합니다:
content(필수): 각각"text","image"또는"resource"의type을 가진 결과 블록의 배열입니다. 비텍스트 블록은 이미지 및 리소스 반환을 참조하세요.structuredContent(선택사항): 머신 판독 가능한 데이터로 결과를 보유하는 JSON 객체이며,content와 함께 반환됩니다. 구조화된 데이터 반환을 참조하세요.isError(선택사항): Claude가 반응할 수 있도록 도구 실패를 신호하려면true로 설정합니다. 오류 처리를 참조하세요.
createSdkMcpServer (TypeScript) 또는 create_sdk_mcp_server (Python)를 사용하여 서버로 래핑합니다. 서버는 별도의 프로세스가 아닌 애플리케이션 내에서 인프로세스로 실행됩니다.
날씨 도구 예제
이 예제는get_temperature 도구를 정의하고 MCP 서버로 래핑합니다. 도구만 설정합니다. query에 전달하고 실행하려면 아래의 사용자 정의 도구 호출을 참조하세요.
tool() TypeScript 참조 또는 @tool Python 참조를 참조하세요.
사용자 정의 도구 호출
mcpServers 옵션을 통해 생성한 MCP 서버를 query에 전달합니다. mcpServers의 키는 각 도구의 정규화된 이름에서 {server_name} 세그먼트가 됩니다: mcp__{server_name}__{tool_name}. 도구가 권한 프롬프트 없이 실행되도록 allowedTools에 해당 이름을 나열합니다.
이 스니펫은 위의 예제의 weatherServer를 재사용하여 Claude에 특정 위치의 날씨를 묻습니다.
더 많은 도구 추가
서버는tools 배열에 나열한 만큼 많은 도구를 보유합니다. 서버에 둘 이상의 도구가 있으면 allowedTools에서 각각을 개별적으로 나열하거나 와일드카드 mcp__weather__*를 사용하여 서버가 노출하는 모든 도구를 포함할 수 있습니다.
아래 예제는 날씨 도구 예제의 weatherServer에 두 번째 도구인 get_precipitation_chance를 추가하고 배열의 두 도구로 다시 빌드합니다.
도구 주석 추가
도구 주석은 도구의 동작을 설명하는 선택적 메타데이터입니다. TypeScript의tool() 헬퍼에 다섯 번째 인수로 전달하거나 Python의 @tool 데코레이터에 대해 annotations 키워드 인수를 통해 전달합니다. 모든 힌트 필드는 부울입니다.
| 필드 | 기본값 | 의미 |
|---|---|---|
readOnlyHint | false | 도구는 환경을 수정하지 않습니다. 도구를 다른 읽기 전용 도구와 병렬로 호출할 수 있는지 여부를 제어합니다. |
destructiveHint | true | 도구는 파괴적인 업데이트를 수행할 수 있습니다. 정보 제공용입니다. |
idempotentHint | false | 동일한 인수로 반복 호출해도 추가 효과가 없습니다. 정보 제공용입니다. |
openWorldHint | true | 도구는 프로세스 외부의 시스템에 도달합니다. 정보 제공용입니다. |
readOnlyHint: true로 표시된 도구도 핸들러가 수행하는 경우 디스크에 쓸 수 있습니다. 주석을 핸들러에 정확하게 유지합니다.
이 예제는 날씨 도구 예제의 get_temperature 도구에 readOnlyHint를 추가합니다.
ToolAnnotations를 참조하세요.
도구 액세스 제어
날씨 도구 예제는 서버를 등록하고allowedTools에 도구를 나열했습니다. 이 섹션에서는 도구 이름이 구성되는 방식과 여러 도구가 있거나 기본 제공 도구를 제한하려는 경우 액세스 범위를 지정하는 방법을 다룹니다.
도구 이름 형식
MCP 도구가 Claude에 노출될 때 이름은 특정 형식을 따릅니다:- 패턴:
mcp__{server_name}__{tool_name} - 예제:
weather서버의get_temperature라는 도구는mcp__weather__get_temperature가 됩니다
허용된 도구 구성
tools 옵션과 허용/거부 목록은 두 가지 계층에 영향을 미칩니다. 가용성은 도구가 Claude의 컨텍스트에 나타나는지 여부를 제어하고, 권한은 Claude가 호출을 시도한 후 호출이 승인되는지 여부를 제어합니다. tools와 단순 이름 disallowedTools 항목은 가용성을 변경합니다. allowedTools와 범위가 지정된 disallowedTools 규칙은 권한만 변경합니다.
| 옵션 | 계층 | 효과 |
|---|---|---|
tools: ["Read", "Grep"] | 가용성 | 나열된 기본 제공 도구만 Claude의 컨텍스트에 있습니다. 나열되지 않은 기본 제공 도구는 제거됩니다. MCP 도구는 영향을 받지 않습니다. |
tools: [] | 가용성 | 모든 기본 제공 도구가 제거됩니다. Claude는 MCP 도구만 사용할 수 있습니다. |
| 허용된 도구 | 권한 | 나열된 도구는 권한 프롬프트 없이 실행됩니다. 나열되지 않은 도구는 계속 사용 가능합니다. 호출은 권한 흐름을 거칩니다. |
| 거부된 도구 | 둘 다 | "Bash"와 같은 단순 도구 이름은 도구를 Claude의 컨텍스트에서 제거하며, tools에서 생략하는 것과 동일합니다. "Bash(rm *)" 같은 범위가 지정된 규칙은 도구를 컨텍스트에 남겨두고 일치하는 호출만 거부합니다. |
tools에서 생략하거나 disallowedTools(Python: disallowed_tools)에 단순 이름을 나열합니다. 둘 다 도구를 컨텍스트 밖으로 유지하므로 Claude는 시도하지 않습니다. 범위가 지정된 disallowedTools 규칙은 일치하는 호출을 차단하지만 도구를 표시하므로 Claude는 시도하는 데 턴을 낭비할 수 있습니다. 전체 평가 순서는 권한 구성을 참조하세요.
오류 처리
핸들러가 오류를 보고하는 방식에 따라 에이전트 루프가 계속되는지 중지되는지가 결정됩니다:| 발생하는 상황 | 결과 |
|---|---|
| 핸들러가 포착되지 않은 예외를 발생시킵니다 | 에이전트 루프가 중지됩니다. Claude는 오류를 보지 못하고 query 호출이 실패합니다. |
핸들러가 오류를 포착하고 isError: true (TS) / "is_error": True (Python)를 반환합니다 | 에이전트 루프가 계속됩니다. Claude는 오류를 데이터로 보고 재시도하거나, 다른 도구를 시도하거나, 실패를 설명할 수 있습니다. |
try/except (Python) 또는 try/catch (TypeScript)로 포착되어 오류 결과로도 반환됩니다. 두 경우 모두 핸들러는 정상적으로 반환되고 에이전트 루프가 계속됩니다.
이미지 및 리소스 반환
도구 결과의content 배열은 text, image 및 resource 블록을 허용합니다. 동일한 응답에서 이들을 혼합할 수 있습니다.
이미지
이미지 블록은 이미지 바이트를 base64로 인코딩하여 인라인으로 전달합니다. URL 필드가 없습니다. URL에 있는 이미지를 반환하려면 핸들러에서 가져오고, 응답 바이트를 읽고, 반환하기 전에 base64로 인코딩합니다. 결과는 시각적 입력으로 처리됩니다.| 필드 | 유형 | 참고 |
|---|---|---|
type | "image" | |
data | string | Base64로 인코딩된 바이트입니다. data:image/...;base64, 접두사 없이 원본 base64만 |
mimeType | string | 필수입니다. 예: image/png, image/jpeg, image/webp, image/gif |
리소스
리소스 블록은 URI로 식별되는 콘텐츠 조각을 포함합니다. URI는 Claude가 참조할 레이블입니다. 실제 콘텐츠는 블록의text 또는 blob 필드에 있습니다. 도구가 나중에 이름으로 주소를 지정하는 것이 합리적인 것을 생성할 때 사용합니다. 예를 들어 생성된 파일 또는 외부 시스템의 레코드입니다.
| 필드 | 유형 | 참고 |
|---|---|---|
type | "resource" | |
resource.uri | string | 콘텐츠의 식별자입니다. 모든 URI 스키마 |
resource.text | string | 텍스트인 경우 콘텐츠입니다. blob 대신 이것을 제공하되 둘 다는 아닙니다 |
resource.blob | string | 바이너리인 경우 base64로 인코딩된 콘텐츠입니다 |
resource.mimeType | string | 선택사항 |
file:///tmp/report.md는 Claude가 나중에 참조할 수 있는 레이블입니다. SDK는 해당 경로에서 읽지 않습니다.
CallToolResult 유형에서 나옵니다. 전체 정의는 MCP 사양을 참조하세요.
구조화된 데이터 반환
structuredContent는 content 배열과 별개인 결과의 선택적 JSON 객체입니다. 이를 사용하여 텍스트 문자열이나 이미지에서 구문 분석하는 대신 Claude가 정확한 필드로 읽을 수 있는 원본 값을 반환합니다.
structuredContent가 설정되면 Claude는 JSON과 content의 모든 이미지 또는 리소스 블록을 받습니다. content의 텍스트 블록은 구조화된 데이터를 복제한다고 가정하므로 전달되지 않습니다. 아래 예제는 차트를 이미지 블록으로 렌더링하고 동일한 핸들러에서 structuredContent의 뒤에 있는 데이터 포인트를 반환합니다.
TypeScript
Python
@tool 데코레이터는 핸들러의 반환 딕셔너리에서 content 및 is_error만 전달합니다. Python에서 structuredContent를 반환하려면 인프로세스 SDK 서버 대신 독립형 MCP 서버를 실행합니다.예제: 단위 변환기
이 도구는 길이, 온도 및 무게 단위 간에 값을 변환합니다. 사용자는 “100킬로미터를 마일로 변환” 또는 “72°F는 섭씨온도로 몇 도인가”라고 물을 수 있으며, Claude는 요청에서 올바른 단위 유형과 단위를 선택합니다. 두 가지 패턴을 보여줍니다:- 열거형 스키마:
unit_type은 고정된 값 집합으로 제한됩니다. TypeScript에서z.enum()을 사용합니다. Python에서 딕셔너리 스키마는 열거형을 지원하지 않으므로 전체 JSON Schema 딕셔너리가 필요합니다. - 지원되지 않는 입력 처리: 변환 쌍을 찾을 수 없으면 핸들러는
isError: true를 반환하므로 Claude는 실패를 정상 결과로 취급하는 대신 사용자에게 무엇이 잘못되었는지 알릴 수 있습니다.
query에 전달합니다. 이 예제는 루프에서 세 가지 다른 프롬프트를 보내 동일한 도구가 다양한 단위 유형을 처리하는 것을 보여줍니다. 각 응답에 대해 AssistantMessage 객체(Claude가 해당 턴 중에 수행한 도구 호출을 포함)를 검사하고 각 ToolUseBlock을 인쇄한 후 최종 ResultMessage 텍스트를 인쇄합니다. 이를 통해 Claude가 도구를 사용하는 시기와 자신의 지식에서 답변하는 시기를 볼 수 있습니다.
다음 단계
사용자 정의 도구는 비동기 함수를 표준 인터페이스로 래핑합니다. 동일한 서버에서 이 페이지의 패턴을 혼합할 수 있습니다: 단일 서버는 데이터베이스 도구, API 게이트웨이 도구 및 이미지 렌더러를 함께 보유할 수 있습니다. 여기서:- 서버가 수십 개의 도구로 증가하면 도구 검색을 참조하여 Claude가 필요할 때까지 로드를 연기합니다.
- 자신의 도구를 빌드하는 대신 외부 MCP 서버(파일 시스템, GitHub, Slack)에 연결하려면 MCP 서버 연결을 참조하세요.
- 어떤 도구가 자동으로 실행되는지 대 승인이 필요한지 제어하려면 권한 구성을 참조하세요.