CPN 한국어 자습서 · 외부 문서 한국어 미러
MCP 문서 · Develop
Build an MCP client · 원문: modelcontextprotocol.io/docs/develop/build-client
아래는 원문을 한국어로 옮긴 미러입니다. 코드·명령은 원문 그대로이며, 가장 최신 정보는 하단 원문 링크에서 확인하세요.
모든 MCP 서버와 통합할 수 있는 클라이언트를 직접 만들어 봅니다.
이 튜토리얼에서는 MCP 서버에 연결하는 LLM 기반 챗봇 클라이언트를 구축하는 방법을 배웁니다.
시작하기 전에 MCP 서버 구축 튜토리얼을 먼저 살펴보면 클라이언트와 서버가 어떻게 통신하는지 이해하는 데 도움이 됩니다.
이 튜토리얼의 완성된 코드는 여기서 확인할 수 있습니다.
시작하기 전에 시스템이 다음 요구사항을 충족하는지 확인하세요.
uv 설치uv로 새 Python 프로젝트를 만듭니다.
# macOS/Linux # 프로젝트 디렉터리 생성 uv init mcp-client cd mcp-client # 가상환경 생성 uv venv # 가상환경 활성화 source .venv/bin/activate # 필요한 패키지 설치 uv add mcp anthropic python-dotenv # 보일러플레이트 파일 제거 rm main.py # 메인 파일 생성 touch client.py
# Windows uv init mcp-client cd mcp-client uv venv .venv\Scripts\activate uv add mcp anthropic python-dotenv del main.py new-item client.py
Anthropic Console에서 Anthropic API 키를 발급받아야 합니다.
키를 저장할 .env 파일을 만듭니다.
echo "ANTHROPIC_API_KEY=your-api-key-goes-here" > .env
.gitignore에 .env를 추가합니다.
echo ".env" >> .gitignore
주의:
ANTHROPIC_API_KEY를 안전하게 보관하세요!
먼저 임포트를 설정하고 기본 클라이언트 클래스를 만듭니다.
import asyncio
from typing import Optional
from contextlib import AsyncExitStack
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from anthropic import Anthropic
from dotenv import load_dotenv
load_dotenv() # load environment variables from .env
class MCPClient:
def __init__(self):
# Initialize session and client objects
self.session: Optional[ClientSession] = None
self.exit_stack = AsyncExitStack()
self.anthropic = Anthropic()
# methods will go here
MCP 서버에 연결하는 메서드를 구현합니다.
async def connect_to_server(self, server_script_path: str):
"""Connect to an MCP server
Args:
server_script_path: Path to the server script (.py or .js)
"""
is_python = server_script_path.endswith('.py')
is_js = server_script_path.endswith('.js')
if not (is_python or is_js):
raise ValueError("Server script must be a .py or .js file")
command = "python" if is_python else "node"
server_params = StdioServerParameters(
command=command,
args=[server_script_path],
env=None
)
stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
self.stdio, self.write = stdio_transport
self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))
await self.session.initialize()
# List available tools
response = await self.session.list_tools()
tools = response.tools
print("\nConnected to server with tools:", [tool.name for tool in tools])
쿼리를 처리하고 도구 호출을 처리하는 핵심 기능을 추가합니다.
async def process_query(self, query: str) -> str:
"""Process a query using Claude and available tools"""
messages = [
{
"role": "user",
"content": query
}
]
response = await self.session.list_tools()
available_tools = [{
"name": tool.name,
"description": tool.description,
"input_schema": tool.inputSchema
} for tool in response.tools]
# Initial Claude API call
response = self.anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000,
messages=messages,
tools=available_tools
)
# Process response and handle tool calls
final_text = []
assistant_message_content = []
for content in response.content:
if content.type == 'text':
final_text.append(content.text)
assistant_message_content.append(content)
elif content.type == 'tool_use':
tool_name = content.name
tool_args = content.input
# Execute tool call
result = await self.session.call_tool(tool_name, tool_args)
final_text.append(f"[Calling tool {tool_name} with args {tool_args}]")
assistant_message_content.append(content)
messages.append({
"role": "assistant",
"content": assistant_message_content
})
messages.append({
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": content.id,
"content": result.content
}
]
})
# Get next response from Claude
response = self.anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1000,
messages=messages,
tools=available_tools
)
final_text.append(response.content[0].text)
return "\n".join(final_text)
채팅 루프와 정리 기능을 추가합니다.
async def chat_loop(self):
"""Run an interactive chat loop"""
print("\nMCP Client Started!")
print("Type your queries or 'quit' to exit.")
while True:
try:
query = input("\nQuery: ").strip()
if query.lower() == 'quit':
break
response = await self.process_query(query)
print("\n" + response)
except Exception as e:
print(f"\nError: {str(e)}")
async def cleanup(self):
"""Clean up resources"""
await self.exit_stack.aclose()
마지막으로 메인 실행 로직을 추가합니다.
async def main():
if len(sys.argv) < 2:
print("Usage: python client.py <path_to_server_script>")
sys.exit(1)
client = MCPClient()
try:
await client.connect_to_server(sys.argv[1])
await client.chat_loop()
finally:
await client.cleanup()
if __name__ == "__main__":
import sys
asyncio.run(main())
완성된 client.py 파일은 여기에서 확인할 수 있습니다.
MCPClient 클래스는 세션 관리 및 API 클라이언트로 초기화됩니다.AsyncExitStack을 사용합니다.MCP 서버와 함께 클라이언트를 실행합니다.
uv run client.py path/to/server.py # python server uv run client.py path/to/build/index.js # node server
참고: 서버 퀵스타트의 날씨 튜토리얼을 이어서 진행하는 경우 명령어는 다음과 비슷할 수 있습니다:
python client.py .../quickstart-resources/weather-server-python/weather.py
클라이언트는 다음을 수행합니다.
쿼리를 제출하면 다음이 진행됩니다.
오류 처리 * 도구 호출을 항상 try-catch 블록으로 감싸세요. * 의미 있는 오류 메시지를 제공하세요. * 연결 문제를 정상적으로 처리하세요.
리소스 관리
* 적절한 정리를 위해 AsyncExitStack을 사용하세요.
* 완료 후 연결을 닫으세요.
* 서버 연결 해제를 처리하세요.
보안
* API 키를 .env에 안전하게 저장하세요.
* 서버 응답을 검증하세요.
* 도구 권한에 주의하세요.
서버 경로 문제
/) 또는 이스케이프된 백슬래시(\\)를 사용하세요.# 상대 경로 uv run client.py ./server/weather.py # 절대 경로 uv run client.py /Users/username/projects/mcp-server/weather.py # Windows 경로 uv run client.py C:/projects/mcp-server/weather.py
응답 시간
일반적인 오류 메시지
FileNotFoundError: 서버 경로를 확인하세요.Connection refused: 서버가 실행 중이고 경로가 올바른지 확인하세요.Tool execution failed: 도구에 필요한 환경변수가 설정되어 있는지 확인하세요.이 튜토리얼의 완성된 코드는 여기서 확인할 수 있습니다.
npm 설치# macOS/Linux mkdir mcp-client-typescript cd mcp-client-typescript npm init -y npm install @anthropic-ai/sdk @modelcontextprotocol/sdk dotenv npm install -D @types/node typescript touch index.ts
package.json 업데이트:
{
"type": "module",
"scripts": {
"build": "tsc && chmod 755 build/index.js"
}
}
tsconfig.json 생성:
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["index.ts"],
"exclude": ["node_modules"]
}
# TypeScript 빌드 npm run build # 클라이언트 실행 node build/index.js path/to/server.py # python server node build/index.js path/to/build/index.js # node server
원문(영어): https://modelcontextprotocol.io/docs/develop/build-client · 본 문서는 학습용 한국어 번역이며 원본의 권리는 원저작자(Model Context Protocol)에게 있습니다.
원문(영어): https://modelcontextprotocol.io/docs/develop/build-client