아래는 OpenAI의 Model Context Protocol (MCP) 사양을 완전히 준수하는
✅ @mcp.tool, ✅ @mcp.resource, ✅ @mcp.prompt를 모두 포함한
감정 분석용 완성된 MCP 서버 코드입니다.
.well-known/mcp.json을 통해 context로 mount할 수 있는 완전한 MCP 서버mcp_sentiment_server/
├── main.py ← MCP 서버 실행 스크립트
├── requirements.txt
requirements.txtfastapi
uvicorn
openai
mcp
설치:
pip install fastapi uvicorn "openai[mcp]"
main.py – 완성된 MCP 서버from mcp.server.fastmcp import FastMCP
# MCP 서버 인스턴스 생성
mcp = FastMCP("sentiment-mcp")
# ----------------------------
# ✅ TOOL 1: 긍정/부정/중립
# ----------------------------
@mcp.tool(
name="sentiment_basic",
description="문장의 감정을 긍정, 부정, 중립으로 분류합니다.",
parameters={
"type": "object",
"properties": {
"text": {"type": "string", "description": "감정을 분석할 문장"}
},
"required": ["text"]
}
)
def sentiment_basic(text: str) -> str:
text = text.lower()
if any(word in text for word in ["좋아", "기뻐", "행복"]):
return "positive"
elif any(word in text for word in ["짜증", "화나", "싫어"]):
return "negative"
else:
return "neutral"
# ----------------------------
# ✅ TOOL 2: 감정 점수
# ----------------------------
@mcp.tool(
name="sentiment_score",
description="문장의 감정을 0~1 사이의 점수로 반환합니다.",
parameters={
"type": "object",
"properties": {
"text": {"type": "string", "description": "감정을 분석할 문장"}
},
"required": ["text"]
}
)
def sentiment_score(text: str) -> float:
score = 0.5
if "행복" in text or "좋아" in text:
score += 0.4
if "짜증" in text or "싫어" in text:
score -= 0.4
return round(min(max(score, 0.0), 1.0), 2)
# ----------------------------
# ✅ TOOL 3: 감정 라벨
# ----------------------------
@mcp.tool(
name="emotion_label",
description="문장의 감정을 '기쁨', '슬픔', '분노', '중립'으로 분류합니다.",
parameters={
"type": "object",
"properties": {
"text": {"type": "string", "description": "감정을 분석할 문장"}
},
"required": ["text"]
}
)
def emotion_label(text: str) -> str:
if "행복" in text or "기뻐" in text:
return "기쁨"
elif "짜증" in text or "화나" in text:
return "분노"
elif "슬퍼" in text or "눈물" in text:
return "슬픔"
else:
return "중립"
# ----------------------------
# ✅ RESOURCE: 샘플 문장 목록
# ----------------------------
sample_sentences = [
{"id": "s1", "text": "오늘 정말 행복해요."},
{"id": "s2", "text": "짜증나는 하루였어요."},
{"id": "s3", "text": "별다른 감정은 없어요."}
]
@mcp.resource(
name="sample_sentences",
description="감정 분석 예시 문장 목록입니다.",
schema={
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": "string"},
"text": {"type": "string"}
},
"required": ["id", "text"]
}
}
)
def get_sample_sentences():
return sample_sentences
# ----------------------------
# ✅ PROMPT: 감정 분석 템플릿
# ----------------------------
@mcp.prompt(
name="감정 분석 요청",
description="문장의 감정을 분석하기 위한 프롬프트 템플릿입니다.",
prompt="다음 문장의 감정을 분석해줘: {text}"
)
def prompt_template(text: str):
return f"다음 문장의 감정을 분석해줘: {text}"
# ----------------------------
# ✅ MCP 서버 실행
# ----------------------------
if __name__ == "__main__":
mcp.run()
python main.py
기본 MCP 포트는 6277 → MCP 진입점 URL:
http://localhost:6277/.well-known/mcp.json
다음 MCP 서버를 context로 연결해줘:
http://localhost:6277/.well-known/mcp.json
이 문장의 감정을 분석해줘: 오늘 정말 행복했어!
sentiment_basic → "positive"sentiment_score → 0.9emotion_label → "기쁨"| 구성 요소 | 개수 | 설명 |
|---|---|---|
| Tool | 3개 | 감정 분석 (범주/점수/라벨) |
| Resource | 1개 | 샘플 문장 목록 |
| Prompt | 1개 | 문장 감정 분석 템플릿 |
.well-known/mcp.json | 자동 생성됨 | GPT context 등록용 |
훌륭한 질문입니다.
OpenAI의 Model Context Protocol (MCP) 사양에 따르면,
@mcp.tool, @mcp.resource, @mcp.prompt에 정의하는 name, description, schema 등의 필드는 대부분 _필수_입니다.
왜냐하면 MCP는 내부 호출이 아니라, LLM이 외부 MCP 서버의 기능을 introspect(탐색)하고 이해할 수 있도록 하기 위한 프로토콜이기 때문입니다.
GPT는 사람이 아니라 도구 메타데이터만 보고 어떤 기능인지 판단해야 하므로, 명확한 명세가 필수입니다.
name, description, schema 등은 반드시 기입해야 하는 것인가?
@mcp.tool(...)| 필드 | 필수 여부 | 이유 |
|---|---|---|
name | ✅ 필수 | GPT가 해당 기능을 호출하려면 고유 이름이 반드시 필요 |
description | ✅ 사실상 필수 | GPT가 어떤 기능인지 판단하는 데 필요 |
parameters (schema) | ✅ 필수 | JSON Schema 명세가 없으면 GPT가 매개변수를 어떻게 줄지 알 수 없음 |
| 함수 본문 | ✅ | 실제 실행될 Python 함수 |
📌 parameters는 OpenAI function calling과 같은 구조의 JSON Schema로 정의되어야 하며, "type": "object"이어야 합니다.
@mcp.resource(...)| 필드 | 필수 여부 | 이유 |
|---|---|---|
name | ✅ | LLM이 context 리소스를 참조하려면 고유 이름 필요 |
description | ✅ | 리소스 의미를 이해하려면 설명 필요 |
schema | ✅ | 리소스 데이터의 구조를 LLM이 알아야 context로 활용 가능 |
| 반환값 (함수) | ✅ | 실제 리소스를 반환해야 LLM이 사용할 수 있음 |
@mcp.prompt(...)| 필드 | 필수 여부 | 이유 |
|---|---|---|
name | ✅ | 프롬프트 이름은 LLM이 선택할 때 필요 |
description | ✅ | 어떤 시나리오에 쓰는 프롬프트인지 판단 근거 |
prompt | ✅ | 실제 템플릿 문자열 필요 ({변수} 포함 가능) |
⚠️ 만약 description 없이 등록하면 LLM이 prompt를 잘못 사용하거나 무시할 수 있습니다.
| 요소 | 필수 필드 | 이유 |
|---|---|---|
@mcp.tool | name, description, parameters (schema) | GPT가 호출할 tool 탐색 및 호출 위해 필수 |
@mcp.resource | name, description, schema | GPT가 context에 mount할 수 있도록 하기 위해 필수 |
@mcp.prompt | name, description, prompt | GPT가 사용자 요청을 프리셋 형태로 활용할 수 있도록 하기 위해 필수 |
네, name, description, schema는 MCP 사양상 거의 항상 필수입니다.
GPT나 LLM이 도구를 "자동으로 탐색하고 사용할 수 있도록 하기 위한 목적" 때문에,
이 메타정보들이 빠지면 도구로서 사용할 수 없습니다.