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

Deprecated: Sampling, Roots, and Logging

revision 2026-07-28 deprecate client feature สามตัวในคราวเดียว (SEP-2577): sampling, roots และ logging พวกมันยังไม่หายไป — feature ที่ถูก deprecate ยังทำงานได้อย่างน้อยสิบสองเดือนตาม feature lifecycle policy และถูกลิสต์ไว้ใน deprecated-features registry ให้ติดตามได้ แต่ implementation ใหม่ไม่ควรเอามาใช้ และของเดิมควรวางแผน migrate

บทนี้ครอบคลุมว่าแต่ละตัวเคยทำอะไร ตอนนี้หน้าตาเป็นอย่างไร และควรใช้อะไรแทน

sampling ให้ server ขอ completion จาก LLM ของ host — “ช่วยสรุป diff นี้ให้หน่อย” — โดยไม่ต้องพ่วง LLM SDK หรือ API key มาด้วย request คือ sampling/createMessage:

{
"method": "sampling/createMessage",
"params": {
"messages": [
{ "role": "user", "content": { "type": "text", "text": "Summarize this changelog in one line: …" } }
],
"systemPrompt": "You are terse.",
"maxTokens": 100,
"modelPreferences": {
"hints": [{ "name": "claude" }],
"intelligencePriority": 0.8,
"speedPriority": 0.5,
"costPriority": 0.2
}
}
}

modelPreferences เป็นแค่คำแนะนำ: hints เป็น substring match กับชื่อ model และ priority สามตัว (0–1) ให้ host เลือก model host ยังคงมีมนุษย์อยู่ใน loop — แสดง, แก้ หรือปฏิเสธทั้ง prompt และ completion ได้

ใน 2026-07-28 server ส่ง request ไม่ได้ ดังนั้นที่ เดียว ที่ sampling/createMessage จะปรากฏได้คือใน map InputRequiredResult.inputRequests ภายใต้ MRTR client รัน completion แล้ว return CreateMessageResult ใน inputResponses:

{
"capital": {
"role": "assistant",
"content": { "type": "text", "text": "The capital of France is Paris." },
"model": "claude-opus-5",
"stopReason": "endTurn"
}
}

ค่า includeContext แบบ "thisServer" และ "allServers" ถูก soft-deprecate ตั้งแต่ 2025-11-25 และตอนนี้ deprecate อย่างเป็นทางการ ให้ละ field นี้หรือส่ง "none"

สองเหตุผล หนึ่ง statelessness: completion แพง และการบังคับให้มันผ่าน MRTR retry แปลว่า host จ่ายค่า completion แล้วยังต้องส่ง request เดิมทั้งก้อนซ้ำอีก สอง model ของ host ไม่ใช่ model ของ server — คุณภาพ, ค่าใช้จ่าย และ safety policy เป็นของคนที่ถือ API key server ที่ต้องการ LLM ควรเรียกเองมากกว่า

import Anthropic from '@anthropic-ai/sdk';
const anthropic = new Anthropic(); // reads ANTHROPIC_API_KEY from the environment
async function summarize(text: string): Promise<string> {
const msg = await anthropic.messages.create({
model: 'claude-opus-5',
max_tokens: 256,
system: 'You are terse.',
messages: [{ role: 'user', content: `Summarize in one line:\n\n${text}` }],
});
const block = msg.content[0];
return block.type === 'text' ? block.text : '';
}
server.registerTool(
'summarize_changelog',
{ description: 'One-line changelog summary', inputSchema: z.object({ text: z.string() }) },
async ({ text }) => ({ content: [{ type: 'text', text: await summarize(text) }] })
);

บน stdio key มาจาก environment ที่ host ใช้ launch คุณ บน HTTP มาจาก secret store ของคุณเอง ไม่ว่าทางไหน ตอนนี้ server เป็นเจ้าของการเลือก model, retry และค่าใช้จ่าย

roots ให้ server ถาม client ว่าตำแหน่งไหนใน filesystem ที่อนุญาตให้ทำงาน — roots/list return URI เช่น file:///home/me/project — และ notifications/roots/list_changed บอก server เมื่อชุดนั้นเปลี่ยน

roots/list เหลืออยู่แค่ในฐานะ MRTR input request ส่วน notifications/roots/list_changed ถูกถอดทิ้งทั้งหมด (ใน 2026-07-28 ไม่มี notification จาก client ไป server สำหรับเรื่องนี้) ListRootsResult ยังหน้าตาแบบนี้เมื่อกลับมาใน inputResponses:

{
"roots": [{ "uri": "file:///home/me/project", "name": "project" }]
}

ตัวแทนที่แนะนำเรียบง่ายจนน่าอาย: ส่ง directory เป็น tool argument, resource URI หรือ server configuration

  • tool ที่ค้นหาไฟล์รับ parameter path แล้ว validate กับ allowlist ที่ config ตอน launch
  • server ที่ทำงานกับ project เดียวเสมอรับ directory นั้นเป็น CLI argument หรือ environment variable ตอน host spawn — ซึ่งก็คือวิธีที่ npx @modelcontextprotocol/server-filesystem ~/Desktop ทำมาตลอด
  • ไฟล์ที่ model ควร อ่าน เหมาะจะเปิดเป็น resource มากกว่าให้ค้นพบผ่าน roots

path ที่ระบุชัดยัง secure ง่ายกว่าด้วย: คุณ sanitize parameter ได้ แต่ audit สิทธิ์โดยนัยที่ client เคยให้ใน request ก่อนหน้าได้ยาก

logging ให้ server มี channel ไปยัง log ของ client: client ตั้ง threshold ด้วย logging/setLevel แล้ว server push entry notifications/message ที่มี level (debug ถึง emergency), ชื่อ logger (optional) และ data อะไรก็ได้

logging/setLevel ถูกถอดออก threshold ตอนนี้เป็น ต่อ request อยู่ใน _meta:

{
"_meta": {
"io.modelcontextprotocol/logLevel": "info",
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
}
}

server ต้องไม่ ส่ง notifications/message ให้ request ที่ไม่ได้ใส่ field นี้ และที่ส่งออกไปจะวิ่งบน response stream ของ request นั้น ไม่ใช่บน subscription

  • บน stdio log ลง stderr transport สงวน stdout ไว้ให้ protocol message แต่ stderr มีไว้สำหรับ log โดยเฉพาะ host อาจ capture, forward หรือเมินก็ได้ ห้ามเขียน log ลง stdout เด็ดขาด
  • บน HTTP ใช้ logging stack ปกติของคุณ และเพื่อ correlate ข้าม service ใช้ OpenTelemetry key traceparent, tracestate และ baggage ใน _meta ถูกสงวนไว้สำหรับ W3C trace-context propagation ดังนั้น client ส่ง trace id มาให้ได้ และ span ของคุณจะเรียงต่อกับของเขา:
{
"params": {
"name": "get_weather",
"arguments": { "location": "Bangkok" },
"_meta": {
"traceparent": "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01",
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {}
}
}
}
// stdio server: logs go to stderr, never stdout
console.error(JSON.stringify({ level: 'info', msg: 'import started', files: urls.length }));
flowchart LR
  A["Active"] --> D["Deprecated (12+ เดือน, อยู่ใน registry)"]
  D --> R["Removed ใน revision ถัดไป"]
Feature lifecycle: Active, Deprecated, Removed

feature ที่ถูก deprecate จะระบุทาง migrate และคงอยู่อย่างน้อยสิบสองเดือน (เก้าสิบวันภายใต้ข้อยกเว้นแบบเร่งด่วน) ก่อนจะเข้าข่ายถูกถอด sampling, roots และ logging เข้าสู่สถานะ Deprecated พร้อม 2026-07-28 revision เดียวกันนี้ยังจัด HTTP+SSE transport แบบเก่าและ dynamic client registration เป็น Deprecated ด้วย เช็คหน้า registry เพื่อดูสถานะปัจจุบันก่อนจะสร้างอะไรบนสิ่งที่ถูกทำเครื่องหมาย Deprecated

ใน exchange แบบ 2026-07-28 sampling/createMessage ยังปรากฏได้ที่ไหน?
อะไรมาแทน logging/setLevel?
ทาง migrate ที่แนะนำจาก roots คืออะไร?
stdio server ควรเขียน log ไปที่ไหน?