MCP Server = Tool + Resource + Prompt : 감정 분석 예제 (250714)

WonTerry·2025년 7월 14일

MCP

목록 보기
9/23

아래는 OpenAI의 Model Context Protocol (MCP) 사양을 완전히 준수하는
@mcp.tool, ✅ @mcp.resource, ✅ @mcp.prompt를 모두 포함한
감정 분석용 완성된 MCP 서버 코드입니다.


✅ 목적

  • 감정 분석 기능 3종 (tool)
  • 샘플 문장 리소스 (resource)
  • 프롬프트 템플릿 (prompt)
  • GPT가 .well-known/mcp.json을 통해 context로 mount할 수 있는 완전한 MCP 서버

📁 디렉토리 구조

mcp_sentiment_server/
├── main.py                  ← MCP 서버 실행 스크립트
├── requirements.txt

📄 requirements.txt

fastapi
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

✅ GPT에서 사용 방법

  1. GPT에게 MCP 서버 등록:
다음 MCP 서버를 context로 연결해줘:
http://localhost:6277/.well-known/mcp.json
  1. 프롬프트 입력:
이 문장의 감정을 분석해줘: 오늘 정말 행복했어!
  1. GPT는 MCP의 tool 중 하나를 자동 선택하여 실행:
  • sentiment_basic"positive"
  • sentiment_score0.9
  • emotion_label"기쁨"

✅ 요약

구성 요소개수설명
Tool3개감정 분석 (범주/점수/라벨)
Resource1개샘플 문장 목록
Prompt1개문장 감정 분석 템플릿
.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는 사람이 아니라 도구 메타데이터만 보고 어떤 기능인지 판단해야 하므로, 명확한 명세가 필수입니다.


Prompt (ChatGPT)

 name, description, schema 등은 반드시 기입해야 하는 것인가?

✅ 각 항목별 필수 여부

1. @mcp.tool(...)

필드필수 여부이유
name필수GPT가 해당 기능을 호출하려면 고유 이름이 반드시 필요
description사실상 필수GPT가 어떤 기능인지 판단하는 데 필요
parameters (schema)필수JSON Schema 명세가 없으면 GPT가 매개변수를 어떻게 줄지 알 수 없음
함수 본문실제 실행될 Python 함수

📌 parametersOpenAI function calling과 같은 구조의 JSON Schema로 정의되어야 하며, "type": "object"이어야 합니다.


2. @mcp.resource(...)

필드필수 여부이유
nameLLM이 context 리소스를 참조하려면 고유 이름 필요
description리소스 의미를 이해하려면 설명 필요
schema리소스 데이터의 구조를 LLM이 알아야 context로 활용 가능
반환값 (함수)실제 리소스를 반환해야 LLM이 사용할 수 있음

3. @mcp.prompt(...)

필드필수 여부이유
name프롬프트 이름은 LLM이 선택할 때 필요
description어떤 시나리오에 쓰는 프롬프트인지 판단 근거
prompt실제 템플릿 문자열 필요 ({변수} 포함 가능)

⚠️ 만약 description 없이 등록하면 LLM이 prompt를 잘못 사용하거나 무시할 수 있습니다.


❗요약: MCP 사양에서의 필수 항목

요소필수 필드이유
@mcp.toolname, description, parameters (schema)GPT가 호출할 tool 탐색 및 호출 위해 필수
@mcp.resourcename, description, schemaGPT가 context에 mount할 수 있도록 하기 위해 필수
@mcp.promptname, description, promptGPT가 사용자 요청을 프리셋 형태로 활용할 수 있도록 하기 위해 필수

✅ 결론

네, name, description, schema는 MCP 사양상 거의 항상 필수입니다.
GPT나 LLM이 도구를 "자동으로 탐색하고 사용할 수 있도록 하기 위한 목적" 때문에,
이 메타정보들이 빠지면 도구로서 사용할 수 없습니다.


profile
Hello, I'm Terry! 👋 Enjoy every moment of your life! 🌱 My current interests are Signal processing, Machine learning, Python, Database, LLM & RAG, MCP & ADK, Multi-Agents, Physical AI, ROS2...

0개의 댓글