ข้ามไปยังเนื้อหา

Prompts

prompt คือ message template ที่ใช้ซ้ำได้ซึ่ง server เสนอให้ และ user เป็นคนเลือกรัน UI ที่พบบ่อยคือ slash command: user พิมพ์ /code_review host ถาม argument แล้วเรียก prompts/get จากนั้นแทรก message ที่ได้กลับมาเข้าไปในบทสนทนา

“user-controlled” อธิบายว่าใครตัดสินใจว่าจะใช้ prompt เมื่อไร — ไม่ใช่ใครเป็นคนเขียน server เป็นผู้แต่งเนื้อหา คนเป็นผู้กด ความต่างนี้คือเหตุผลที่ prompt ปลอดภัยพอจะทำให้ทรงพลังได้: มันเก็บ checklist การรีวิวของทีม, playbook การ debug หรือชุดตัวอย่าง few-shot ได้ และจะรันก็ต่อเมื่อมีคนขอ

sequenceDiagram
  participant U as User
  participant C as Host
  participant S as Server
  C->>S: prompts/list
  S-->>C: prompts[] แสดงเป็น slash command
  U->>C: /code_review code=...
  C->>S: prompts/get name=code_review arguments
  S-->>C: messages[]
  C->>U: message ถูกแทรกเข้าบทสนทนา
จาก slash command สู่ message
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "complete",
"prompts": [
{
"name": "code_review",
"title": "Request Code Review",
"description": "Asks the LLM to analyze code quality and suggest improvements",
"arguments": [
{ "name": "code", "description": "The code to review", "required": true },
{ "name": "language", "description": "Programming language", "required": false }
]
}
],
"nextCursor": "next-page-cursor",
"ttlMs": 600000,
"cacheScope": "public"
}
}

prompt มี name, title และ description แบบเลือกใส่, icons แบบเลือกใส่ และรายการ arguments แบบเลือกใส่ ซึ่งแต่ละตัวมีชื่อ, description และ flag required argument บน wire เป็น string เสมอ — host เก็บมันจาก user เป็นข้อความ

{
"jsonrpc": "2.0",
"id": 2,
"method": "prompts/get",
"params": { "name": "code_review", "arguments": { "code": "def hello():\n print('world')" } }
}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"resultType": "complete",
"description": "Code review prompt",
"messages": [
{
"role": "user",
"content": { "type": "text", "text": "Please review this Python code:\ndef hello():\n print('world')" }
}
]
}
}

messages คือรายการ PromptMessage แบบมีลำดับ แต่ละตัวมี role เป็น user หรือ assistant และ content block หนึ่งก้อน เพราะคุณควบคุมทั้งลำดับ คุณจึงคืน บทสนทนา ได้ ไม่ใช่แค่คำสั่งเดียว — การวางกรอบแบบ system เป็น user message แรก, assistant message ที่แสดงรูปแบบที่คาดหวัง แล้วตามด้วย input จริงของ user

เช่นเดียวกับ method ลงมืออื่น ๆ prompts/get อาจ คืน InputRequiredResult เมื่อ server ต้อง elicit อะไรบางอย่างก่อนจะสร้าง message ได้

typeFieldใช้สำหรับ
texttextคำสั่ง, ตัวอย่าง few-shot
imagedata (base64), mimeTypescreenshot ให้วิจารณ์, design mock
audiodata (base64), mimeTypeเสียงให้ถอดความหรืออภิปราย
resource_linkuri, name, description, mimeTypeชี้ไปที่ resource ที่ host fetch ได้
resourceresource: { uri, mimeType, text หรือ blob }ฝังเอกสาร, schema หรือตัวอย่างโค้ดลงไปเลย

embedded resource คือฟีเจอร์ที่ทรงพลังที่สุดตรงนี้: prompt db_query_help ฝัง database schema สด ๆ ลงไปได้ เพื่อให้ model ไม่ต้องเดาชื่อ table content block ทุกตัวรองรับ annotations ตามปกติ (audience, priority, lastModified)

import { McpServer, completable } from '@modelcontextprotocol/server';
import * as z from 'zod/v4';
const server = new McpServer({ name: 'review', version: '1.0.0' });
server.registerPrompt(
'code_review',
{
title: 'Request Code Review',
description: 'Asks the LLM to analyze code quality and suggest improvements',
argsSchema: z.object({
code: z.string().describe('The code to review'),
language: completable(z.string().describe('Programming language'), (value) =>
['typescript', 'javascript', 'python', 'rust', 'go'].filter((l) => l.startsWith(value)),
),
}),
},
({ code, language }) => ({
messages: [
{
role: 'user' as const,
content: {
type: 'text' as const,
text: `Review this ${language} code. Check correctness first, then readability.\n\n${code}`,
},
},
],
}),
);

argsSchema เป็นตัวกำหนดรายการ arguments ใน prompts/list; การห่อ field ด้วย completable(...) ทำให้ server ตอบ completion/complete สำหรับ field นั้นได้

host เรียก completion/complete ขณะ user พิมพ์ค่า argument เพื่อให้ picker แนะนำค่าที่ถูกต้องได้:

{
"jsonrpc": "2.0",
"id": 3,
"method": "completion/complete",
"params": {
"ref": { "type": "ref/prompt", "name": "code_review" },
"argument": { "name": "language", "value": "py" }
}
}
{
"jsonrpc": "2.0",
"id": 3,
"result": { "resultType": "complete", "completion": { "values": ["python"], "hasMore": false } }
}

request เดียวกันที่ใช้ "type": "ref/resource" และ uri template จะ complete ตัวแปรของ resource template completion เป็น server capability ชื่อ completions; ประกาศมันถ้าคุณ implement

prompt โดดเด่นเมื่องาน ทำซ้ำ และมี รูปแบบที่ดีที่รู้กันอยู่แล้ว รูปแบบที่พบบ่อย:

  • Checklist “รีวิวความพร้อมก่อน release” ที่ไล่ผ่าน test, changelog, migration note — เป็นรายการลำดับเลขที่ model ต้องตอบทีละข้อตามลำดับ
  • ชุด few-shot ตัวอย่างที่ทำสำเร็จแล้วสองสามชุดของรูปแบบ output ที่ต้องการ เป็น message user/assistant สลับกัน แล้วตามด้วย input จริง
  • Prompt ที่มีหลักยึด ฝัง resource (schema, style guide, glossary) เพื่อให้ model ทำงานจากแหล่งข้อมูลจริงแทนความจำ
  • Playbook ที่รับ parameter incident_triage(service, severity) ที่ดึงส่วนของ runbook ที่ถูกต้องสำหรับ service นั้น

เมื่อไรที่ prompt คือตัวเลือกที่ ผิด?

สถานการณ์ใช้แทน
model ควรตัดสินใจเองว่าจะทำเมื่อไรtool
มันเป็นแค่ข้อมูลที่ไม่มีคำสั่งresource
มันต้อง ทำ อะไรบางอย่าง (เขียน, เรียก API)tool — prompt ผลิตได้แค่ message

prompt ไม่เคย execute อะไร ถ้า “prompt” ของคุณต้อง fetch ข้อมูลสด ให้มันฝัง resource หรือบอก model ว่าควรเรียก tool ไหนต่อ

  • ชื่อ prompt ไม่รู้จัก → -32602 (Invalid params)
  • ขาด argument ที่บังคับ → -32602
  • ความล้มเหลวภายใน → -32603

server ควร validate argument ก่อนสร้าง message และ — เพราะ argument คือข้อความที่ user ใส่มาซึ่งจะไปอยู่ใน context ของ model — ให้ถือว่ามันเป็น input ที่เชื่อถือไม่ได้ อย่าปล่อยให้ argument หลุดออกจากกรอบที่คุณตั้งใจไว้ (เช่น การเอาไปแทรกในตำแหน่งที่มันปลอมตัวเป็นเทิร์นของ assistant ได้)

ใน interaction model ของ prompt ใครเป็นคนตัดสินใจว่าจะใช้ prompt เมื่อไร?
method ไหนที่ให้ host แนะนำค่าที่ถูกต้องของ argument ขณะ user พิมพ์?
ทีมอยากได้คำสั่ง "/deploy" ที่สั่ง deploy จริง ๆ primitive ที่ถูกต้องคืออะไร?