---
name: tool-development
description: 새로운 MCP tool을 추가하고 등록하는 방법
---
# Tool 개발 가이드
## 개요
이 skill은 MCP OpenDART 프로젝트에 새로운 tool을 추가하는 방법을 설명합니다. FastMCP의 `@mcp.tool` 데코레이터를 사용하여 OpenDART API 기능을 MCP tool로 노출합니다.
## 사용 시나리오
- 새로운 OpenDART API 엔드포인트를 tool로 추가할 때
- 기존 tool의 기능을 확장하거나 수정할 때
- 새로운 비즈니스 로직을 tool로 구현할 때
## 구현 가이드
### 1. Tool 파일 선택
기존 tool 파일에 추가하거나 새 파일 생성:
- `src/mcp_opendart/tools/disclosure_tools.py` - 공시정보 관련
- `src/mcp_opendart/tools/financial_info_tools.py` - 재무정보 관련
- `src/mcp_opendart/tools/periodic_report_tools.py` - 정기보고서 관련
- `src/mcp_opendart/tools/ownership_disclosure_tools.py` - 지분공시 관련
- `src/mcp_opendart/tools/major_report_tools.py` - 주요사항보고서 관련
- `src/mcp_opendart/tools/securities_filing_tools.py` - 증권신고서 관련
### 2. 기본 Tool 구조
```python
from typing import Annotated
from mcp_opendart.server import mcp
from mcp.types import TextContent
from mcp_opendart.utils.ctx_helper import with_context, as_json_text
@mcp.tool(
name="tool_name",
description="도구 설명 (LLM이 이해할 수 있도록 명확하게)",
tags={"태그1", "태그2"}
)
def tool_function(
param1: Annotated[str, "파라미터 설명"],
param2: Annotated[Optional[int], "선택적 파라미터 설명"] = None,
) -> TextContent:
"""
Tool 함수 docstring (선택사항)
"""
result = with_context(
None, # ctx 파라미터는 제거됨, 내부에서 fallback 처리
"tool_name", # 로깅용 도구명
lambda context: context.ds001.get_something(param1, param2)
)
return as_json_text(result)
```
### 3. 중요 사항
#### ctx 파라미터 제거
- **이전**: `ctx: Optional[Any] = None` 파라미터 사용
- **현재**: ctx 파라미터 제거, `with_context(None, ...)` 사용
- **이유**: streamable-http에서 ctx 주입이 없어도 전역 컨텍스트로 fallback
#### Annotated 타입 힌팅
- 모든 파라미터에 `Annotated[Type, "description"]` 사용
- LLM이 tool의 목적과 파라미터를 이해하는 데 필수
- 예: `Annotated[str, "공시대상회사의 고유번호 (8자리)"]`
#### with_context() 사용
- 모든 API 호출은 `with_context()`로 래핑
- 자동으로 키 변환 및 금액 필드 숫자 변환 수행
- 전역 컨텍스트 fallback 자동 처리
### 4. 비동기 Tool
비동기 API 호출이 필요한 경우:
```python
@mcp.tool(
name="async_tool_name",
description="비동기 도구 설명",
tags={"태그"}
)
async def async_tool_function(
param: Annotated[str, "파라미터 설명"],
) -> TextContent:
from mcp_opendart.utils.ctx_helper import with_context_async
result = await with_context_async(
None,
"async_tool_name",
lambda context: context.ds001.async_get_something(param)
)
return as_json_text(result)
```
### 5. Tool Registry 등록 (선택)
도구 메타데이터를 레지스트리에 등록하려면:
```python
from mcp_opendart.registry.initialize_registry import initialize_registry
tool_registry = initialize_registry()
# tool_registry.register_tool() 호출 (필요시)
# 대부분의 경우 @mcp.tool 데코레이터만으로 충분
```
## 예제
### 예제 1: 간단한 조회 Tool
```python
@mcp.tool(
name="get_corporation_info",
description="대표자, 결산월, 상장상태 등 기업 기본 정보 조회",
tags={"기업기초정보", "지배구조", "공시일정"}
)
def get_corporation_info(
corp_code: Annotated[str, "공시대상회사의 고유번호 (8자리)"],
) -> TextContent:
"""
기업 개황정보 조회
"""
result = with_context(
None,
"get_corporation_info",
lambda context: context.ds001.get_corporation_info(corp_code)
)
return as_json_text(result)
```
### 예제 2: 복잡한 파라미터 Tool
```python
@mcp.tool(
name="get_disclosure_list",
description="기업의 전체 공시 이력을 날짜별로 조회",
tags={"공시", "목록", "접수내역"}
)
def get_disclosure_list(
corp_code: Annotated[str, "공시대상회사의 고유번호 (8자리)"],
bgn_de: Annotated[str, "조회 시작일 (YYYYMMDD)"],
end_de: Annotated[str, "조회 종료일 (YYYYMMDD)"],
page_no: Annotated[int, "페이지 번호 (기본값: 1)"] = 1,
pblntf_ty: Annotated[str, "공시유형 (A:정기공시, B:주요사항 등)"] = "",
) -> TextContent:
result = with_context(
None,
"get_disclosure_list",
lambda context: context.ds001.get_disclosure_list(
corp_code=corp_code,
bgn_de=bgn_de,
end_de=end_de,
page_no=page_no,
pblntf_ty=pblntf_ty
)
)
return as_json_text(result)
```
## 주의사항
1. **ctx 파라미터 절대 사용 금지**
- Tool 시그니처에 `ctx: Optional[Any] = None` 포함하지 않음
- `with_context(None, ...)` 사용
2. **파라미터 설명 명확히 작성**
- Annotated의 두 번째 인자에 상세 설명
- 예시 값 포함 (예: "YYYYMMDD", "8자리")
3. **태그 적절히 사용**
- 검색 및 분류를 위한 태그 지정
- 기존 태그와 일관성 유지
4. **에러 처리**
- API 호출 실패 시 적절한 에러 메시지 반환
- `as_json_text()`로 일관된 형식 유지
5. **모듈 Import 확인**
- 새 tool 파일 생성 시 `server.py`에서 모듈 import 확인
- `importlib.import_module()`로 자동 로드됨
## 관련 파일
- [src/mcp_opendart/tools/disclosure_tools.py](src/mcp_opendart/tools/disclosure_tools.py) - Tool 예제
- [src/mcp_opendart/server.py](src/mcp_opendart/server.py) - Tool 모듈 자동 로드
- [src/mcp_opendart/utils/ctx_helper.py](src/mcp_opendart/utils/ctx_helper.py) - with_context 함수
- [src/mcp_opendart/registry/tool_registry.py](src/mcp_opendart/registry/tool_registry.py) - Tool 레지스트리