Go를 활용한 Model Context Protocol(MCP) 서버 구현 가이드

Model Context Protocol(MCP)이란?
Model Context Protocol(MCP)은 대규모 언어 모델(LLM)과 외부 데이터 소스 및 도구 간의 원활한 통합을 가능하게 하는 오픈 프로토콜입니다. Anthropic에서 개발한 이 프로토콜은 AI 애플리케이션과 다양한 외부 시스템(콘텐츠 저장소, 비즈니스 도구, 개발 환경 등) 간의 표준화된 통신 방식을 제공합니다.
MCP는 AI 애플리케이션을 위한 USB-C 포트와 같다고 생각하면 이해하기 쉽습니다. USB-C가 다양한 주변기기와 액세서리에 연결할 수 있는 표준화된 방법을 제공하는 것처럼, MCP는 AI 모델을 다양한 데이터 소스와 도구에 연결하는 표준화된 방법을 제공합니다.
MCP의 주요 기능 | 장점 |
---|---|
표준화된 통신 프로토콜 | 다양한 시스템 간 쉬운 통합 |
데이터 소스 접근 | LLM에 필요한 컨텍스트 제공 용이 |
도구 기능 제공 | 코드 실행이나 부가 기능 구현 가능 |
오픈 소스 표준 | 커뮤니티 기반 발전 및 확장성 |
다양한 언어 SDK 지원 | 개발자 친화적 환경 |
Go로 MCP 서버 구현하기
이제 Go 언어를 사용하여 MCP 서버를 구현하는 방법에 대해 알아보겠습니다. 이 구현에는 mark3labs/mcp-go 라이브러리를 활용할 것입니다.
먼저, 기본적인 MCP 서버 구조를 설정해 보겠습니다:
package main
import (
"fmt"
"log"
"os"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
func main() {
// 서버 설정
config := &server.Config{
Transport: server.NewStdioTransport(),
Name: "my-mcp-server",
Version: "1.0.0",
}
// 서버 생성
s := server.NewServer(config)
// 리소스 및 도구 등록
registerResources(s)
registerTools(s)
// 서버 시작
if err := s.Start(); err != nil {
log.Fatalf("서버 시작 실패: %v", err)
}
}
// 리소스 등록 함수
func registerResources(s *server.Server) {
// 여기에 리소스 등록 코드 추가
}
// 도구 등록 함수
func registerTools(s *server.Server) {
// 여기에 도구 등록 코드 추가
}
리소스 및 도구 구현
MCP 서버의 핵심 기능은 리소스(Resources)와 도구(Tools)를 통해 구현됩니다. 리소스는 GET 엔드포인트와 유사하며 LLM의 컨텍스트에 정보를 로드하는 데 사용됩니다. 도구는 POST 엔드포인트와 유사하며 코드를 실행하거나 부수 효과를 생성하는 데 사용됩니다.
간단한 파일 시스템 리소스를 구현해 보겠습니다:
func registerResources(s *server.Server) {
// 파일 시스템 리소스 등록
s.RegisterResource("fs/read", mcp.ResourceParams{
RequiredParams: []string{"path"},
OptionalParams: []string{"encoding"},
Handler: func(params map[string]interface{}) (*mcp.ResourceResult, error) {
path, ok := params["path"].(string)
if !ok {
return nil, fmt.Errorf("path 파라미터가 문자열이 아닙니다")
}
// 기본 인코딩 설정
encoding := "utf-8"
if enc, ok := params["encoding"].(string); ok {
encoding = enc
}
// 파일 읽기
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("파일 읽기 실패: %v", err)
}
// 결과 반환
result := &mcp.ResourceResult{
Data: string(data),
MimeType: "text/plain",
}
return result, nil
},
})
}
이제 간단한 웹 검색 도구를 구현해 보겠습니다:
func registerTools(s *server.Server) {
// 웹 검색 도구 등록
s.RegisterTool("web/search", mcp.ToolParams{
RequiredParams: []string{"query"},
OptionalParams: []string{"limit"},
Handler: func(params map[string]interface{}) (*mcp.CallToolResult, error) {
query, ok := params["query"].(string)
if !ok {
return nil, fmt.Errorf("query 파라미터가 문자열이 아닙니다")
}
// 기본 검색 결과 수 설정
limit := 5
if lim, ok := params["limit"].(float64); ok {
limit = int(lim)
}
// 여기에 실제 검색 로직 구현
// 예제로 더미 데이터 반환
result := fmt.Sprintf("'%s'에 대한 상위 %d개 검색 결과입니다.", query, limit)
return &mcp.CallToolResult{
Result: result,
IsError: false,
}, nil
},
})
}
MCP 서버 배포 및 테스트
완성된 MCP 서버를 배포하고 테스트하는 방법에 대해 알아보겠습니다. MCP 서버는 다양한 전송 방식을 지원합니다. 위 예제에서는 표준 입출력(stdio)을 사용했지만, HTTP 전송 방식으로 변경하여 웹 서버로 배포할 수도 있습니다:
func main() {
// HTTP 전송 방식으로 서버 설정
config := &server.Config{
Transport: server.NewHTTPTransport(":8080"),
Name: "my-mcp-server",
Version: "1.0.0",
}
// 나머지 코드는 동일
// ...
}
Docker를 사용하여 서버를 컨테이너화하면 더 쉽게 배포하고 관리할 수 있습니다. 다음은 간단한 Dockerfile 예제입니다:
FROM golang:1.21 as builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o mcp-server .
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/mcp-server .
CMD ["./mcp-server"]
결론
이 블로그 포스트에서는 Go 언어를 사용하여 Model Context Protocol(MCP) 서버를 구현하는 방법에 대해 알아보았습니다. MCP는 LLM과 외부 데이터 소스 및 도구 간의 원활한 통합을 위한 표준화된 방법을 제공합니다. mark3labs/mcp-go 라이브러리를 사용하면 쉽게 MCP 서버를 구현할 수 있으며, 이를 통해 AI 애플리케이션에 다양한 기능을 제공할 수 있습니다.
MCP 서버를 구현함으로써 AI 모델이 더 정확하고 관련성 높은 응답을 생성할 수 있도록 도울 수 있습니다. 이는 AI 기반 애플리케이션의 품질과 기능을 크게 향상시킬 수 있는 중요한 요소입니다.