विषय पर बढ़ें

Header parameters

मशीनी अनुवाद

यह page अंग्रेज़ी documentation से अपने-आप अनुवादित किया गया है, और अंग्रेज़ी page ही प्रामाणिक version है। अगर कुछ गलत लगे, तो अनुवाद page बताता है कि इसकी सूचना कैसे दें।

ज़्यादातर servers को इसकी कभी ज़रूरत नहीं पड़ती।

server के आगे लगा gateway या load balancer सिर्फ़ उसी के आधार पर route कर सकता है जिसे वह body को parse किए बिना पढ़ सके। tool के किसी argument को x-mcp-header से mark करें, और 2026-07-28 protocol version वाले clients उसकी value HTTP header के रूप में भी भेजते हैं।

argument को mark करना

यह mark argument के JSON Schema में बस एक अतिरिक्त key है। MCPServer पर Field इसे वहाँ रख देता है:

server.py
from typing import Annotated

from pydantic import Field

from mcp.server import MCPServer

mcp = MCPServer("Bookshop")


@mcp.tool()
def check_stock(
    title: str,
    region: Annotated[str, Field(json_schema_extra={"x-mcp-header": "Region"})],
) -> str:
    """Count the copies of a book in one region's warehouses."""
    return f"{title}: 3 copies in {region}."
  • 2026-07-28 पर Streamable HTTP के ज़रिए client body के साथ Mcp-Param-Region भी भेजता है, और जिस call में दोनों मेल नहीं खाते उसे server reject कर देता है।
  • जिस client ने tool को list नहीं किया है, उसने mark कभी देखा ही नहीं: वह कोई header नहीं भेजता, और call reject हो जाता है। तब इस SDK का Client tools को list करता है और call एक बार दोबारा भेजता है, इसलिए पहले list करने से सिर्फ़ एक round trip बचता है।
  • बाकी हर connection इस annotation को अनदेखा करता है।

function में कोई बदलाव नहीं होता: region अब भी argument के रूप में ही आता है।

क्या mark किया जा सकता है

str, int और bool arguments। इनके अलावा कुछ भी हो, तो tool register होते समय InvalidSignature के साथ मना कर दिया जाता है।

इसमें str | None भी शामिल है, जिसका कोई एक type नहीं होता। optional argument के लिए उसका schema साफ़-साफ़ लिखना पड़ता है, Pydantic के WithJsonSchema से:

region: Annotated[str | None, WithJsonSchema({"type": "string", "x-mcp-header": "Region"})] = None

low-level Server पर

वहाँ input_schema आप खुद हाथ से लिखते हैं, इसलिए key सीधे उसी में जाती है:

server.py
from mcp.server import Server, ServerRequestContext
from mcp.types import (
    CallToolRequestParams,
    CallToolResult,
    ListToolsResult,
    PaginatedRequestParams,
    TextContent,
    Tool,
)

CHECK_STOCK = Tool(
    name="check_stock",
    description="Count the copies of a book in one region's warehouses.",
    input_schema={
        "type": "object",
        "properties": {
            "title": {"type": "string"},
            "region": {"type": "string", "x-mcp-header": "Region"},
        },
        "required": ["title", "region"],
    },
)


async def list_tools(ctx: ServerRequestContext, params: PaginatedRequestParams | None) -> ListToolsResult:
    return ListToolsResult(tools=[CHECK_STOCK])


async def call_tool(ctx: ServerRequestContext, params: CallToolRequestParams) -> CallToolResult:
    args = params.arguments or {}
    text = f"{args['title']}: 3 copies in {args['region']}."
    return CallToolResult(content=[TextContent(type="text", text=text)])


server = Server("Bookshop", on_list_tools=list_tools, on_call_tool=call_tool)
app = server.streamable_http_app()
  • यहाँ annotation की जाँच आपके लिए कोई नहीं करता: invalid annotation भी serve हो जाता है, और 2026-07-28 clients उस tool को अपनी listing से बाहर रखते हैं।

नाम से schemas

header की जाँच के लिए SDK को call dispatch करने से पहले tool का input schema चाहिए। get_tool_input_schema के बिना SDK यह schema हर उस call पर आपका on_list_tools handler चलाकर लेता है जिसमें arguments हों, चाहे कोई tool mark किया गया हो या नहीं।

server.py
from typing import Any

from mcp.server import Server, ServerRequestContext
from mcp.types import (
    CallToolRequestParams,
    CallToolResult,
    ListToolsResult,
    PaginatedRequestParams,
    TextContent,
    Tool,
)

CHECK_STOCK = Tool(
    name="check_stock",
    description="Count the copies of a book in one region's warehouses.",
    input_schema={
        "type": "object",
        "properties": {
            "title": {"type": "string"},
            "region": {"type": "string", "x-mcp-header": "Region"},
        },
        "required": ["title", "region"],
    },
)

TOOLS = {CHECK_STOCK.name: CHECK_STOCK}


async def list_tools(ctx: ServerRequestContext, params: PaginatedRequestParams | None) -> ListToolsResult:
    return ListToolsResult(tools=list(TOOLS.values()))


async def call_tool(ctx: ServerRequestContext, params: CallToolRequestParams) -> CallToolResult:
    args = params.arguments or {}
    text = f"{args['title']}: 3 copies in {args['region']}."
    return CallToolResult(content=[TextContent(type="text", text=text)])


def tool_input_schema(name: str) -> dict[str, Any] | None:
    tool = TOOLS.get(name)
    return tool.input_schema if tool else None


server = Server(
    "Bookshop",
    on_list_tools=list_tools,
    on_call_tool=call_tool,
    get_tool_input_schema=tool_input_schema,
)
app = server.streamable_http_app()
  • यह function pass करें, ताकि जवाब उसी से दिया जा सके जो आपके पास पहले से है।
  • जिस tool में जाँचने को कुछ नहीं है, उसके लिए None लौटाएँ।

सारांश

  • tool argument पर x-mcp-header होने से 2026-07-28 clients उसे Mcp-Param-* HTTP header के रूप में भी दोहराते हैं।
  • जिस call के header और body मेल नहीं खाते, उसे server reject कर देता है।
  • सिर्फ़ str, int और bool arguments mark किए जा सकते हैं। बाकी किसी भी चीज़ के लिए MCPServer InvalidSignature raise करता है।
  • low-level Server कुछ भी नहीं जाँचता, और जिस tool का annotation invalid हो उसे clients छोड़ देते हैं।
  • get_tool_input_schema की वजह से low-level Server को हर call पर on_list_tools नहीं चलाना पड़ता।

हाथ से लिखी जाने वाली Server API का बाकी हिस्सा low-level Server में है।