콘텐츠로 이동

도구 확장과 커스텀 도구

Claude Code의 도구 시스템은 확장 가능하도록 설계되어 있습니다. 공통 인터페이스를 구현하면 내장 도구와 동일한 방식으로 동작하는 커스텀 도구를 만들 수 있습니다.

interface Tool<TInput = unknown, TOutput = unknown> {
// ── 필수: 식별 정보 ──────────────────────────────
name: string
// 모델이 읽는 설명 — 언제 이 도구를 사용할지 명확히 서술
description: string
// JSON Schema로 정의된 입력 파라미터
parameters: {
type: 'object'
properties: Record<string, JSONSchemaProperty>
required: string[]
}
// ── 필수: 핵심 실행 ──────────────────────────────
execute(input: TInput, context: ToolContext): Promise<TOutput>
// ── 선택: 권한 평가 ──────────────────────────────
// 미구현 시 기본값: 'ask'
checkPermissions?(input: TInput): Promise<'allow' | 'ask' | 'deny'>
// ── 선택: 활성화 조건 ────────────────────────────
// 미구현 시 기본값: true
isEnabled?(): boolean
// ── 선택: 결과 크기 제한 ─────────────────────────
// 초과 시 임시 파일에 저장하고 경로 반환
maxResultSizeChars?: number
}
// 데이터베이스 쿼리 도구 예시
class DatabaseQueryTool implements Tool {
name = 'DatabaseQuery'
description = `로컬 SQLite 데이터베이스에 SQL 쿼리를 실행합니다.
SELECT 쿼리만 허용됩니다. 데이터 변경(INSERT/UPDATE/DELETE)은 불가합니다.`
parameters = {
type: 'object' as const,
properties: {
query: {
type: 'string',
description: 'SELECT SQL 쿼리'
},
database: {
type: 'string',
description: '데이터베이스 파일 경로'
}
},
required: ['query', 'database']
}
maxResultSizeChars = 50_000
async checkPermissions(input: { query: string }) {
// SELECT만 허용
const isSelect = input.query.trim().toUpperCase().startsWith('SELECT')
return isSelect ? 'allow' : 'deny'
}
isEnabled(): boolean {
// sqlite3 바이너리가 있을 때만 활성화
return existsSync('/usr/bin/sqlite3')
}
async execute(input: { query: string; database: string }) {
const result = await runSQLite(input.database, input.query)
return { rows: result, count: result.length }
}
}

Jupyter 노트북(.ipynb)을 셀 수준 으로 편집합니다. 일반 Edit 도구는 JSON 구조를 직접 수정해야 하지만, NotebookEdit은 노트북 구조를 이해하고 셀 단위로 작업합니다.

// 새 셀 삽입
{
notebook_path: "/analysis/data.ipynb",
new_source: "import pandas as pd\ndf = pd.read_csv('data.csv')",
cell_type: "code",
insert_after: 2 // 3번째 셀 다음에 삽입
}
// 기존 셀 교체
{
notebook_path: "/analysis/data.ipynb",
new_source: "# 수정된 분석 코드\ndf.describe()",
cell_index: 5 // 6번째 셀을 교체
}
// 셀 삭제
{
notebook_path: "/analysis/data.ipynb",
cell_index: 3,
delete: true
}
작업파라미터설명
삽입insert_after + new_source지정 셀 다음에 삽입
교체cell_index + new_source지정 셀 내용 교체
삭제cell_index + delete: true지정 셀 제거

세션 내 영속적 태스크 목록 을 관리합니다. 복잡한 다단계 작업을 진행할 때 진행 상황을 추적하고, 사용자와 진행 상태를 공유하는 데 사용됩니다.

// 태스크 목록 생성 및 업데이트
{
todos: [
{
id: "1",
content: "src/auth.ts의 버그 재현",
status: "completed",
priority: "high"
},
{
id: "2",
content: "수정 사항 구현",
status: "in_progress",
priority: "high"
},
{
id: "3",
content: "테스트 작성",
status: "pending",
priority: "medium"
}
]
}

status 값:

의미표시
pending아직 시작 안 함
in_progress현재 진행 중
completed완료

TodoWrite는 대화형 UI에서 실시간으로 업데이트되어 사용자가 진행 상황을 즉시 파악할 수 있습니다.

MCP 서버에서 제공하는 도구는 고유한 네임스페이스 패턴을 따릅니다.

mcp__<서버명>__<도구명>
// settings.json MCP 서버 설정
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"]
}
}
}

위 설정으로 등록되는 도구 이름:

MCP 서버원래 도구명Claude Code 내 이름
filesystemread_filemcp__filesystem__read_file
filesystemwrite_filemcp__filesystem__write_file
githubcreate_issuemcp__github__create_issue
githublist_prsmcp__github__list_prs

서버명에 하이픈이 있으면 언더스코어로 변환됩니다. (my-servermcp__my_server__tool)

퀴즈를 불러오는 중...