{"record":{"id":"892b7c978ca4c28e","repo":"rohitg00/ai-engineering-from-scratch","slug":"meta-client-capabilities-key-is-required","errorCode":null,"errorMessage":"_meta.{CLIENT_CAPABILITIES_KEY} is required","messagePattern":"_meta\\.(.+?) is required","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py","lineNumber":213,"sourceCode":"            raise ValueError(\"notifications/cancelled reason must be a string\")\n        metadata = params.get(\"_meta\")\n        if metadata is not None and not isinstance(metadata, dict):\n            raise ValueError(\"notifications/cancelled _meta must be an object\")\n        if set(params) - {\"requestId\", \"reason\", \"_meta\"}:\n            raise ValueError(\"notifications/cancelled contains unexpected fields\")\n\n    def _validate_request_metadata(self, params: Any) -> dict[str, Any]:\n        if not isinstance(params, dict):\n            raise ValueError(\"params must be an object\")\n        metadata = params.get(\"_meta\")\n        if not isinstance(metadata, dict):\n            raise ValueError(\"_meta must be an object\")\n        version = metadata.get(PROTOCOL_VERSION_KEY)\n        capabilities = metadata.get(CLIENT_CAPABILITIES_KEY)\n        if not isinstance(version, str):\n            raise ValueError(f\"_meta.{PROTOCOL_VERSION_KEY} is required\")\n        if not isinstance(capabilities, dict):\n            raise ValueError(f\"_meta.{CLIENT_CAPABILITIES_KEY} is required\")\n        client_info = metadata.get(CLIENT_INFO_KEY)\n        if client_info is not None and (\n            not isinstance(client_info, dict)\n            or not isinstance(client_info.get(\"name\"), str)\n            or not isinstance(client_info.get(\"version\"), str)\n        ):\n            raise ValueError(f\"_meta.{CLIENT_INFO_KEY} must include name and version\")\n        if version != CURRENT_PROTOCOL_VERSION:\n            raise ProtocolError(\n                -32022,\n                \"Unsupported protocol version\",\n                {\"supported\": [CURRENT_PROTOCOL_VERSION], \"requested\": version},\n            )\n        return metadata\n\n    def _dispatch(\n        self, method: str, params: dict[str, Any], metadata: dict[str, Any]\n    ) -> tuple[dict[str, Any], list[dict[str, Any]]]:","sourceCodeStart":195,"sourceCodeEnd":231,"githubUrl":"https://github.com/rohitg00/ai-engineering-from-scratch/blob/39ea8a1c6d0b61f071226eff7ede4d4105fed820/certifications/claude/lessons/11-mcp-server-design-and-integration/code/main.py#L195-L231","documentation":"The server requires `_meta[\"io.modelcontextprotocol/clientCapabilities\"]` to be a dict. It may be empty, but it must exist and be an object — a stateless server re-negotiates capabilities on every request because it cannot rely on an initialize handshake. Missing key, null, arrays, or strings all trigger this error.","triggerScenarios":"_meta containing only protocolVersion; clientCapabilities set to [], \"tools\", null, or true; capabilities nested one level too deep (e.g. under clientInfo).","commonSituations":"Minimal hand-rolled clients that send only the version; clients modeled on the stateful initialize flow where capabilities were sent once and omitted afterward; merging bugs that drop the capabilities key during payload assembly.","solutions":["Add \"io.modelcontextprotocol/clientCapabilities\": {} (empty dict is valid) next to protocolVersion in _meta","If you do advertise capabilities, keep it an object: {\"roots\": {\"listChanged\": true}}","Validate the assembled _meta with a helper before calling exchange"],"exampleFix":"# before\n\"_meta\": {\n  \"io.modelcontextprotocol/protocolVersion\": \"2026-07-28\",\n}\n# after\n\"_meta\": {\n  \"io.modelcontextprotocol/protocolVersion\": \"2026-07-28\",\n  \"io.modelcontextprotocol/clientCapabilities\": {},\n}","handlingStrategy":"validation","validationCode":"CAPS_KEY = \"io.modelcontextprotocol/clientCapabilities\"\n\ndef with_capabilities(meta: dict) -> dict:\n    if not isinstance(meta.get(CAPS_KEY), dict):\n        meta[CAPS_KEY] = {}\n    return meta","typeGuard":"def has_client_capabilities(meta: dict) -> bool:\n    return isinstance(meta.get(\"io.modelcontextprotocol/clientCapabilities\"), dict)","tryCatchPattern":null,"preventionTips":["Default clientCapabilities to {} in the shared request builder","Treat _meta assembly as all-or-nothing: version, capabilities, and optional clientInfo in one function","Test the minimal valid _meta against every method your client calls"],"tags":["mcp","capabilities","metadata","validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"39ea8a1c6d0b61f071226eff7ede4d4105fed820","analyzedAt":"2026-08-26T03:13:46.626Z","schemaVersion":2},"datasetVersion":"2026-08-26T07:17:17.940Z"}