번역 자료 / / 2025. 5. 22. 14:42

MCP 프롬프트

원문: https://modelcontextprotocol.io/docs/concepts/prompts

재사용 가능한 프롬프트 템플릿과 워크플로우 생성하기

프롬프트는 서버가 사용자와 LLM에게 쉽게 제공할 수 있는 재사용 가능한 프롬프트 템플릿과 워크플로우를 정의할 수 있게 합니다. 이를 통해 일반적인 LLM 상호작용을 표준화하고 공유할 수 있는 강력한 방법을 제공합니다.

프롬프트는 사용자 제어(user-controlled)가 되도록 설계되었습니다. 이는 사용자가 명시적으로 선택하여 사용할 수 있도록 서버에서 클라이언트로 노출된다는 의미입니다.

개요

MCP의 프롬프트는 다음과 같은 기능을 가진 사전 정의된 템플릿입니다:

  • 동적 인자 허용
  • 리소스의 컨텍스트 포함
  • 여러 상호작용 연결
  • 특정 워크플로우 안내
  • UI 요소로 표시(슬래시 명령어와 같은)

프롬프트 구조

각 프롬프트는 다음과 같이 정의됩니다:

{
  name: string;              // 프롬프트의 고유 식별자
  description?: string;      // 사람이 읽을 수 있는 설명
  arguments?: [              // 선택적 인자 목록
    {
      name: string;          // 인자 식별자
      description?: string;  // 인자 설명
      required?: boolean;    // 인자가 필수인지 여부
    }
  ]
}

프롬프트 검색

클라이언트는 prompts/list 엔드포인트를 통해 사용 가능한 프롬프트를 검색할 수 있습니다:

// 요청
{
  method: "prompts/list"
}

// 응답
{
  prompts: [
    {
      name: "analyze-code",
      description: "코드의 잠재적 개선 사항 분석",
      arguments: [
        {
          name: "language",
          description: "프로그래밍 언어",
          required: true
        }
      ]
    }
  ]
}

프롬프트 사용

프롬프트를 사용하려면 클라이언트가 prompts/get 요청을 합니다:

// 요청
{
  method: "prompts/get",
  params: {
    name: "analyze-code",
    arguments: {
      language: "python"
    }
  }
}

// 응답
{
  description: "Python 코드의 잠재적 개선 사항 분석",
  messages: [
    {
      role: "user",
      content: {
        type: "text",
        text: "다음 Python 코드의 잠재적 개선 사항을 분석해 주세요:\n\n```python\ndef calculate_sum(numbers):\n    total = 0\n    for num in numbers:\n        total = total + num\n    return total\n\nresult = calculate_sum([1, 2, 3, 4, 5])\nprint(result)\n```"
      }
    }
  ]
}

동적 프롬프트

프롬프트는 동적일 수 있으며 다음을 포함할 수 있습니다:

내장 리소스 컨텍스트

{
  "name": "analyze-project",
  "description": "프로젝트 로그와 코드 분석",
  "arguments": [
    {
      "name": "timeframe",
      "description": "로그를 분석할 시간 범위",
      "required": true
    },
    {
      "name": "fileUri",
      "description": "검토할 코드 파일의 URI",
      "required": true
    }
  ]
}

prompts/get 요청을 처리할 때:

{
  "messages": [
    {
      "role": "user",
      "content": {
        "type": "text",
        "text": "이 시스템 로그와 코드 파일을 분석하여 문제를 찾아보세요:"
      }
    },
    {
      "role": "user",
      "content": {
        "type": "resource",
        "resource": {
          "uri": "logs://recent?timeframe=1h",
          "text": "[2024-03-14 15:32:11] ERROR: Connection timeout in network.py:127\n[2024-03-14 15:32:15] WARN: Retrying connection (attempt 2/3)\n[2024-03-14 15:32:20] ERROR: Max retries exceeded",
          "mimeType": "text/plain"
        }
      }
    },
    {
      "role": "user",
      "content": {
        "type": "resource",
        "resource": {
          "uri": "file:///path/to/code.py",
          "text": "def connect_to_service(timeout=30):\n    retries = 3\n    for attempt in range(retries):\n        try:\n            return establish_connection(timeout)\n        except TimeoutError:\n            if attempt == retries - 1:\n                raise\n            time.sleep(5)\n\ndef establish_connection(timeout):\n    # Connection implementation\n    pass",
          "mimeType": "text/x-python"
        }
      }
    }
  ]
}

다단계 워크플로우

const debugWorkflow = {
  name: "debug-error",
  async getMessages(error: string) {
    return [
      {
        role: "user",
        content: {
          type: "text",
          text: `내가 보고 있는 오류는 다음과 같습니다: ${error}`
        }
      },
      {
        role: "assistant",
        content: {
          type: "text",
          text: "이 오류를 분석하는 데 도움을 드리겠습니다. 지금까지 어떤 시도를 해보셨나요?"
        }
      },
      {
        role: "user",
        content: {
          type: "text",
          text: "서비스를 재시작해 보았지만 오류가 계속됩니다."
        }
      }
    ];
  }
};

구현 예시

다음은 MCP 서버에서 프롬프트를 구현하는 전체 예시입니다:

  • TypeScript
  • Python
import { Server } from "@modelcontextprotocol/sdk/server";
import {
  ListPromptsRequestSchema,
  GetPromptRequestSchema
} from "@modelcontextprotocol/sdk/types";

const PROMPTS = {
  "git-commit": {
    name: "git-commit",
    description: "Git 커밋 메시지 생성",
    arguments: [
      {
        name: "changes",
        description: "Git diff 또는 변경 사항 설명",
        required: true
      }
    ]
  },
  "explain-code": {
    name: "explain-code",
    description: "코드 작동 방식 설명",
    arguments: [
      {
        name: "code",
        description: "설명할 코드",
        required: true
      },
      {
        name: "language",
        description: "프로그래밍 언어",
        required: false
      }
    ]
  }
};

const server = new Server({
  name: "example-prompts-server",
  version: "1.0.0"
}, {
  capabilities: {
    prompts: {}
  }
});

// 사용 가능한 프롬프트 나열
server.setRequestHandler(ListPromptsRequestSchema, async () => {
  return {
    prompts: Object.values(PROMPTS)
  };
});

// 특정 프롬프트 가져오기
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
  const prompt = PROMPTS[request.params.name];
  if (!prompt) {
    throw new Error(`프롬프트를 찾을 수 없습니다: ${request.params.name}`);
  }

  if (request.params.name === "git-commit") {
    return {
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `다음 변경 사항에 대한 간결하면서도 설명적인 커밋 메시지를 생성해 주세요:\n\n${request.params.arguments?.changes}`
          }
        }
      ]
    };
  }

  if (request.params.name === "explain-code") {
    const language = request.params.arguments?.language || "Unknown";
    return {
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `이 ${language} 코드가 어떻게 작동하는지 설명해 주세요:\n\n${request.params.arguments?.code}`
          }
        }
      ]
    };
  }

  throw new Error("프롬프트 구현을 찾을 수 없습니다");
});
from mcp.server import Server
import mcp.types as types

# 사용 가능한 프롬프트 정의
PROMPTS = {
    "git-commit": types.Prompt(
        name="git-commit",
        description="Git 커밋 메시지 생성",
        arguments=[
            types.PromptArgument(
                name="changes",
                description="Git diff 또는 변경 사항 설명",
                required=True
            )
        ],
    ),
    "explain-code": types.Prompt(
        name="explain-code",
        description="코드 작동 방식 설명",
        arguments=[
            types.PromptArgument(
                name="code",
                description="설명할 코드",
                required=True
            ),
            types.PromptArgument(
                name="language",
                description="프로그래밍 언어",
                required=False
            )
        ],
    )
}

# 서버 초기화
app = Server("example-prompts-server")

@app.list_prompts()
async def list_prompts() -> list[types.Prompt]:
    return list(PROMPTS.values())

@app.get_prompt()
async def get_prompt(
    name: str, arguments: dict[str, str] | None = None
) -> types.GetPromptResult:
    if name not in PROMPTS:
        raise ValueError(f"프롬프트를 찾을 수 없습니다: {name}")

    if name == "git-commit":
        changes = arguments.get("changes") if arguments else ""
        return types.GetPromptResult(
            messages=[
                types.PromptMessage(
                    role="user",
                    content=types.TextContent(
                        type="text",
                        text=f"다음 변경 사항에 대한 간결하면서도 설명적인 커밋 메시지를 "
                        f"생성해 주세요:\n\n{changes}"
                    )
                )
            ]
        )

    if name == "explain-code":
        code = arguments.get("code") if arguments else ""
        language = arguments.get("language", "Unknown") if arguments else "Unknown"
        return types.GetPromptResult(
            messages=[
                types.PromptMessage(
                    role="user",
                    content=types.TextContent(
                        type="text",
                        text=f"이 {language} 코드가 어떻게 작동하는지 설명해 주세요:\n\n{code}"
                    )
                )
            ]
        )

    raise ValueError("프롬프트 구현을 찾을 수 없습니다")

모범 사례

프롬프트를 구현할 때:

  1. 명확하고 설명적인 프롬프트 이름 사용
  2. 프롬프트와 인자에 대한 상세한 설명 제공
  3. 모든 필수 인자 검증
  4. 누락된 인자를 우아하게 처리
  5. 프롬프트 템플릿의 버전 관리 고려
  6. 적절한 경우 동적 콘텐츠 캐싱
  7. 오류 처리 구현
  8. 예상 인자 형식 문서화
  9. 프롬프트 조합 가능성 고려
  10. 다양한 입력으로 프롬프트 테스트

UI 통합

프롬프트는 클라이언트 UI에 다음과 같이 표시될 수 있습니다:

  • 슬래시 명령어
  • 빠른 작업
  • 컨텍스트 메뉴 항목
  • 명령 팔레트 항목
  • 안내형 워크플로우
  • 대화형 양식

업데이트 및 변경

서버는 프롬프트 변경에 대해 클라이언트에 알릴 수 있습니다:

  1. 서버 기능: prompts.listChanged
  2. 알림: notifications/prompts/list_changed
  3. 클라이언트가 프롬프트 목록을 다시 가져옴

보안 고려사항

프롬프트를 구현할 때:

  • 모든 인자 검증
  • 사용자 입력 정제
  • 속도 제한 고려
  • 접근 제어 구현
  • 프롬프트 사용 감사
  • 민감한 데이터 적절하게 처리
  • 생성된 콘텐츠 검증
  • 타임아웃 구현
  • 프롬프트 인젝션 위험 고려
  • 보안 요구사항 문서화
반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유