핵심 요약
MCP(Model Context Protocol)는 LLM 클라이언트(Claude Desktop, Cursor, Claude Code, Cline 등)가 표준 방식으로 외부 시스템에 접근하는 프로토콜. 한 번 만들면 모든 MCP 클라이언트에서 재사용된다.
1. 만들 가치가 있는 사내 도구
- JIRA·Linear 티켓 조회/생성
- 사내 위키·Notion 검색
- Datadog·Grafana 메트릭 쿼리
- k8s 클러스터 상태 조회 (읽기 전용)
- 사내 RAG 데이터베이스
- 온콜 페이저듀티 통합
2. 최소 MCP 서버 — TypeScript
npm init -y
npm i @modelcontextprotocol/sdk zod
// server.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import { z } from 'zod'
const server = new McpServer({
name: 'company-toolkit',
version: '1.0.0',
})
server.registerTool(
'get_user',
{
title: '사용자 조회',
description: '사번이나 이메일로 사내 사용자 정보 조회',
inputSchema: {
identifier: z.string().describe('사번 또는 이메일'),
},
},
async ({ identifier }) => {
const user = await fetchFromInternalLDAP(identifier)
return {
content: [{ type: 'text', text: JSON.stringify(user) }],
}
}
)
const transport = new StdioServerTransport()
await server.connect(transport)
3. Claude Desktop / Code에서 사용
// ~/.claude/claude_desktop_config.json (Desktop)
// 또는 ~/.claude/config.json (Code)
{
"mcpServers": {
"company": {
"command": "node",
"args": ["/Users/me/mcp-servers/company/dist/server.js"],
"env": { "INTERNAL_API_TOKEN": "..." }
}
}
}
4. 리소스 노출 — 데이터 읽기
server.registerResource(
'wiki',
new ResourceTemplate('wiki://{path}', {
list: async () => {
const pages = await wiki.listPages()
return { resources: pages.map(p => ({ uri: `wiki://${p.path}`, name: p.title })) }
}
}),
{
title: '사내 위키',
description: '사내 Confluence 문서를 LLM 컨텍스트에 포함',
},
async (uri, { path }) => {
const content = await wiki.getMarkdown(path as string)
return { contents: [{ uri: uri.href, mimeType: 'text/markdown', text: content }] }
}
)
5. 인증 패턴
| 시나리오 | 인증 방식 |
|---|---|
| 로컬 개인 사용 | 환경변수에 사용자 토큰 |
| 팀 공용 / 원격 호스팅 | OAuth 2.1 (MCP 표준) |
| 회사 보안 강력 | SAML SSO 프록시 |
// OAuth 2.1 Discovery (회사 IDP)
{
"authorization_endpoint": "https://idp.company.com/oauth/authorize",
"token_endpoint": "https://idp.company.com/oauth/token",
"scopes_supported": ["read", "write"]
}
6. 원격 MCP 서버 (HTTP)
로컬 stdio가 가장 단순하지만, 팀 공유는 원격 HTTP가 편하다.
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
import express from 'express'
const app = express()
const transport = new StreamableHTTPServerTransport()
await server.connect(transport)
app.use('/mcp', transport.expressMiddleware())
app.listen(3001)
클라이언트 설정:
{
"mcpServers": {
"company": {
"type": "http",
"url": "https://mcp.company.internal/mcp",
"headers": { "Authorization": "Bearer ${COMPANY_TOKEN}" }
}
}
}
7. 안전성 가드
- 도구 분류: 읽기/쓰기/위험 — 위험한 도구는
annotations: { destructive: true }명시 - 화이트리스트: 호출 가능한 시스템·경로를 명시적으로 정의
- 레이트 리밋: LLM이 도구를 폭주 호출하는 사고 방지 (분당 60회 등)
- 감사 로깅: 모든 도구 호출 로그 저장 — 7일 보관
- Prompt Injection 방어: 도구 결과에 포함된 사용자 콘텐츠는 별도 sandbox 영역으로 마킹
8. 배포 옵션
| 옵션 | 장점 | 단점 |
|---|---|---|
| 로컬 stdio | 설정 간단·빠름 | 공유 어려움 |
| HTTP + 사내망 | 팀 공유 쉬움 | 인프라 필요 |
| Docker 이미지 | 일관성 | 네트워크 설정 복잡 |
| k8s + Ingress | 스케일·관찰성 | 오버킬일 수 있음 |
9. 한국 사례
토스·카카오·우아한형제들이 사내 MCP 카탈로그를 운영 중. JIRA·Confluence·Datadog·자체 사내 시스템(결제·정산)을 Claude/Cursor에서 직접 호출. 평균 시니어 개발자 도입 후 디버깅 시간 30% 감소 보고.
참고
- modelcontextprotocol.io 공식 문서
- GitHub modelcontextprotocol/servers — 80+ 공식 예제

댓글 0