mirror of
https://github.com/rohitg00/ai-engineering-from-scratch.git
synced 2026-10-02 01:54:39 +08:00
fix(cert-11): harden MCP integration contract
This commit is contained in:
@@ -53,7 +53,9 @@ class Capability:
|
||||
if name not in properties:
|
||||
continue
|
||||
expected = properties[name].get("type")
|
||||
if expected not in checks or not checks[expected](value):
|
||||
if expected not in checks:
|
||||
raise ValueError(f"unsupported schema type for {name}: {expected!r}")
|
||||
if not checks[expected](value):
|
||||
raise ValueError(f"{name} must be {expected}")
|
||||
return arguments
|
||||
|
||||
@@ -332,7 +334,6 @@ class MCPServer:
|
||||
},
|
||||
}
|
||||
capabilities = metadata[CLIENT_CAPABILITIES_KEY]
|
||||
required = {"roots": {}, "sampling": {}, "elicitation": {"form": {}}}
|
||||
missing: dict[str, Any] = {}
|
||||
if not isinstance(capabilities.get("roots"), dict):
|
||||
missing["roots"] = {}
|
||||
|
||||
+14
@@ -10,6 +10,7 @@ sys.path.insert(0, str(pathlib.Path(__file__).parents[1]))
|
||||
from main import (
|
||||
CLIENT_CAPABILITIES_KEY,
|
||||
CLIENT_INFO_KEY,
|
||||
Capability,
|
||||
CURRENT_PROTOCOL_VERSION,
|
||||
MCPClient,
|
||||
MCPServer,
|
||||
@@ -119,6 +120,19 @@ class MCPTests(unittest.TestCase):
|
||||
)
|
||||
self.assertEqual(response["error"]["code"], -32602)
|
||||
|
||||
def test_capability_rejects_missing_and_unsupported_schema_types_explicitly(self):
|
||||
for declared_type in (None, "number"):
|
||||
with self.subTest(declared_type=declared_type):
|
||||
schema = {"properties": {"topic": {}}}
|
||||
if declared_type is not None:
|
||||
schema["properties"]["topic"]["type"] = declared_type
|
||||
capability = Capability("review", "Review a topic.", schema, lambda args: args)
|
||||
with self.assertRaisesRegex(
|
||||
ValueError,
|
||||
rf"unsupported schema type for topic: {declared_type!r}",
|
||||
):
|
||||
capability.validate_arguments({"topic": "release"})
|
||||
|
||||
def test_resource_and_prompt_results_are_complete(self):
|
||||
listed = self.client.request("resources/list")
|
||||
read = self.client.request("resources/read", {"uri": listed["resources"][0]["uri"]})
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
- Explain the separate responsibilities of MCP host, client, and server
|
||||
- Build the MCP `2026-07-28` per-request metadata envelope
|
||||
- Implement mandatory `server/discover`, complete results, and cache hints
|
||||
- Use Multi Round-Trip Requests for roots, sampling, and elicitation compatibility
|
||||
- Explain why Roots, Sampling, and Logging are deprecated for new designs
|
||||
- Use Multi Round-Trip Requests for roots, sampling, and elicitation compatibility; explain why roots, sampling, and logging are deprecated for new designs
|
||||
- Deploy current Streamable HTTP without protocol sessions or sticky routing
|
||||
- Apply authorization, consent, integrity, and untrusted-output controls
|
||||
|
||||
|
||||
Reference in New Issue
Block a user