{
  "schema_version": 3,
  "protocol_version": "2025-11-25",
  "transport_context_defaults": {
    "transport": "streamable_http",
    "token_active": true,
    "token_audience": "https://mcp.example.test/mcp",
    "resource": "https://mcp.example.test/mcp"
  },
  "authorization": {
    "protected_resource": "https://mcp.example.test/mcp",
    "initial_revision": "authz-v1",
    "revisions": {
      "authz-v1": {
        "principals": {
          "alice": {
            "tenant": "tenant-a",
            "scopes": [
              "resources:list",
              "resources:read",
              "resources:subscribe"
            ]
          },
          "reader": {
            "tenant": "tenant-a",
            "scopes": [
              "resources:list",
              "resources:read"
            ]
          },
          "mallory": {
            "tenant": "tenant-b",
            "scopes": [
              "resources:list",
              "resources:read",
              "resources:subscribe"
            ]
          }
        },
        "resources": [
          {
            "uri": "kb://tenant-a/handbook",
            "tenant": "tenant-a",
            "children": [
              "kb://tenant-a/handbook/chapter-1"
            ]
          },
          {
            "uri": "kb://tenant-a/handbook/chapter-1",
            "tenant": "tenant-a"
          },
          {
            "uri": "kb://tenant-a/handbookish",
            "tenant": "tenant-a"
          },
          {
            "uri": "kb://tenant-b/secret",
            "tenant": "tenant-b"
          }
        ],
        "resourceTemplates": [
          {
            "uriTemplate": "kb://tenant-a/docs/{doc_id}",
            "tenant": "tenant-a"
          },
          {
            "uriTemplate": "kb://tenant-b/docs/{doc_id}",
            "tenant": "tenant-b"
          }
        ]
      },
      "authz-v2": {
        "principals": {
          "alice": {
            "tenant": "tenant-a",
            "scopes": [
              "resources:list",
              "resources:read",
              "resources:subscribe"
            ],
            "enabled": false
          },
          "reader": {
            "tenant": "tenant-a",
            "scopes": [
              "resources:list",
              "resources:read"
            ]
          },
          "mallory": {
            "tenant": "tenant-b",
            "scopes": [
              "resources:list",
              "resources:read",
              "resources:subscribe"
            ]
          }
        },
        "resources": [
          {
            "uri": "kb://tenant-a/handbook",
            "tenant": "tenant-a",
            "children": [
              "kb://tenant-a/handbook/chapter-1"
            ]
          },
          {
            "uri": "kb://tenant-a/handbook/chapter-1",
            "tenant": "tenant-a"
          },
          {
            "uri": "kb://tenant-a/handbookish",
            "tenant": "tenant-a"
          },
          {
            "uri": "kb://tenant-b/secret",
            "tenant": "tenant-b"
          }
        ],
        "resourceTemplates": [
          {
            "uriTemplate": "kb://tenant-a/docs/{doc_id}",
            "tenant": "tenant-a"
          },
          {
            "uriTemplate": "kb://tenant-b/docs/{doc_id}",
            "tenant": "tenant-b"
          }
        ]
      }
    }
  },
  "client": {
    "info": {
      "name": "offline-course-client",
      "version": "1.0.0"
    },
    "capabilities": {
      "roots": {
        "listChanged": true
      },
      "sampling": {
        "tools": {}
      },
      "elicitation": {
        "form": {},
        "url": {}
      },
      "tasks": {
        "list": {},
        "cancel": {},
        "requests": {
          "sampling": {
            "createMessage": {}
          },
          "elicitation": {
            "create": {}
          }
        }
      }
    }
  },
  "server": {
    "info": {
      "name": "offline-course-server",
      "version": "1.0.0"
    },
    "capabilities": {
      "logging": {},
      "prompts": {
        "listChanged": true
      },
      "resources": {
        "subscribe": true,
        "listChanged": true
      },
      "tools": {
        "listChanged": true
      },
      "tasks": {
        "list": {},
        "cancel": {},
        "requests": {
          "tools": {
            "call": {}
          }
        }
      }
    }
  },
  "tool": {
    "name": "lookup_weather",
    "description": "Return deterministic sample weather without network access.",
    "inputSchema": {
      "type": "object",
      "properties": {
        "city": {
          "type": "string",
          "minLength": 1
        },
        "unit": {
          "type": "string",
          "enum": [
            "celsius",
            "fahrenheit"
          ]
        }
      },
      "required": [
        "city"
      ],
      "additionalProperties": false
    },
    "outputSchema": {
      "type": "object",
      "properties": {
        "temperature": {
          "type": "number"
        },
        "conditions": {
          "type": "string"
        },
        "unit": {
          "type": "string",
          "enum": [
            "celsius",
            "fahrenheit"
          ]
        }
      },
      "required": [
        "temperature",
        "conditions",
        "unit"
      ],
      "additionalProperties": false
    },
    "execution": {
      "taskSupport": "optional"
    }
  },
  "cases": [
    {
      "name": "valid_tool_call_and_structured_result",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 2,
            "method": "tools/call",
            "params": {
              "name": "lookup_weather",
              "arguments": {
                "city": "Shanghai",
                "unit": "celsius"
              }
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 2,
            "result": {
              "content": [
                {
                  "type": "text",
                  "text": "{\"temperature\": 23.5, \"conditions\": \"sample\", \"unit\": \"celsius\"}"
                }
              ],
              "structuredContent": {
                "temperature": 23.5,
                "conditions": "sample",
                "unit": "celsius"
              },
              "isError": false
            }
          }
        }
      ]
    },
    {
      "name": "missing_required_tool_argument",
      "expect": "fail",
      "error_contains": "missing required value",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 3,
            "method": "tools/call",
            "params": {
              "name": "lookup_weather",
              "arguments": {
                "unit": "celsius"
              }
            }
          }
        }
      ]
    },
    {
      "name": "unknown_tool_argument",
      "expect": "fail",
      "error_contains": "unknown values",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 4,
            "method": "tools/call",
            "params": {
              "name": "lookup_weather",
              "arguments": {
                "city": "Shanghai",
                "timezone": "Asia/Shanghai"
              }
            }
          }
        }
      ]
    },
    {
      "name": "invalid_tool_enum",
      "expect": "fail",
      "error_contains": "must be one of",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 5,
            "method": "tools/call",
            "params": {
              "name": "lookup_weather",
              "arguments": {
                "city": "Shanghai",
                "unit": "kelvin"
              }
            }
          }
        }
      ]
    },
    {
      "name": "wrong_tool_argument_type",
      "expect": "fail",
      "error_contains": "must be a string",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 6,
            "method": "tools/call",
            "params": {
              "name": "lookup_weather",
              "arguments": {
                "city": 42
              }
            }
          }
        }
      ]
    },
    {
      "name": "successful_tool_result_missing_structured_content",
      "expect": "fail",
      "error_contains": "structuredContent",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 7,
            "method": "tools/call",
            "params": {
              "name": "lookup_weather",
              "arguments": {
                "city": "Shanghai"
              }
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 7,
            "result": {
              "content": [
                {
                  "type": "text",
                  "text": "weather"
                }
              ]
            }
          }
        }
      ]
    },
    {
      "name": "tool_result_wrong_output_type",
      "expect": "fail",
      "error_contains": "must be a number",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 8,
            "method": "tools/call",
            "params": {
              "name": "lookup_weather",
              "arguments": {
                "city": "Shanghai"
              }
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 8,
            "result": {
              "content": [
                {
                  "type": "text",
                  "text": "weather"
                }
              ],
              "structuredContent": {
                "temperature": "warm",
                "conditions": "sample",
                "unit": "celsius"
              }
            }
          }
        }
      ]
    },
    {
      "name": "tool_execution_error_without_structured_content",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 9,
            "method": "tools/call",
            "params": {
              "name": "lookup_weather",
              "arguments": {
                "city": "Nowhere"
              }
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 9,
            "result": {
              "content": [
                {
                  "type": "text",
                  "text": "city is outside the sample data"
                }
              ],
              "isError": true
            }
          }
        }
      ]
    },
    {
      "name": "valid_roots_list",
      "expect": "pass",
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 10,
            "method": "roots/list"
          }
        },
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 10,
            "result": {
              "roots": [
                {
                  "uri": "file:///D:/course/project",
                  "name": "course-project"
                }
              ]
            }
          }
        }
      ]
    },
    {
      "name": "roots_without_client_capability",
      "expect": "fail",
      "error_contains": "client did not declare capability: roots",
      "client_capabilities": {
        "sampling": {},
        "elicitation": {
          "form": {}
        }
      },
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 11,
            "method": "roots/list"
          }
        }
      ]
    },
    {
      "name": "valid_sampling_with_tools",
      "expect": "pass",
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 12,
            "method": "sampling/createMessage",
            "params": {
              "messages": [
                {
                  "role": "user",
                  "content": {
                    "type": "text",
                    "text": "Summarize the sample."
                  }
                }
              ],
              "maxTokens": 64,
              "tools": [
                {
                  "name": "local_lookup",
                  "description": "Read deterministic local sample data.",
                  "inputSchema": {
                    "type": "object"
                  }
                }
              ]
            }
          }
        },
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 12,
            "result": {
              "role": "assistant",
              "content": {
                "type": "text",
                "text": "sample summary"
              },
              "model": "offline-placeholder",
              "stopReason": "endTurn"
            }
          }
        }
      ]
    },
    {
      "name": "sampling_tools_without_subcapability",
      "expect": "fail",
      "error_contains": "sampling.tools",
      "client_capabilities": {
        "roots": {},
        "sampling": {},
        "elicitation": {
          "form": {}
        }
      },
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 13,
            "method": "sampling/createMessage",
            "params": {
              "messages": [
                {
                  "role": "user",
                  "content": {
                    "type": "text",
                    "text": "Use a tool."
                  }
                }
              ],
              "maxTokens": 64,
              "tools": [
                {
                  "name": "local_lookup"
                }
              ]
            }
          }
        }
      ]
    },
    {
      "name": "sampling_context_without_subcapability",
      "expect": "fail",
      "error_contains": "sampling.context",
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 14,
            "method": "sampling/createMessage",
            "params": {
              "messages": [
                {
                  "role": "user",
                  "content": {
                    "type": "text",
                    "text": "Use all context."
                  }
                }
              ],
              "maxTokens": 64,
              "includeContext": "allServers"
            }
          }
        }
      ]
    },
    {
      "name": "valid_form_elicitation",
      "expect": "pass",
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 15,
            "method": "elicitation/create",
            "params": {
              "mode": "form",
              "message": "Choose the report language.",
              "requestedSchema": {
                "type": "object",
                "properties": {
                  "language": {
                    "type": "string",
                    "enum": [
                      "zh-CN",
                      "en"
                    ]
                  }
                },
                "required": [
                  "language"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 15,
            "result": {
              "action": "accept",
              "content": {
                "language": "zh-CN"
              }
            }
          }
        }
      ]
    },
    {
      "name": "form_elicitation_requests_secret",
      "expect": "fail",
      "error_contains": "must not request secrets",
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 16,
            "method": "elicitation/create",
            "params": {
              "message": "Enter a credential.",
              "requestedSchema": {
                "type": "object",
                "properties": {
                  "api_key": {
                    "type": "string"
                  }
                },
                "required": [
                  "api_key"
                ]
              }
            }
          }
        }
      ]
    },
    {
      "name": "valid_url_elicitation",
      "expect": "pass",
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 17,
            "method": "elicitation/create",
            "params": {
              "mode": "url",
              "message": "Complete the external authorization flow.",
              "url": "https://example.com/connect?id=course-demo",
              "elicitationId": "course-demo"
            }
          }
        },
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 17,
            "result": {
              "action": "accept"
            }
          }
        }
      ]
    },
    {
      "name": "url_elicitation_without_subcapability",
      "expect": "fail",
      "error_contains": "elicitation.url",
      "client_capabilities": {
        "roots": {},
        "sampling": {},
        "elicitation": {
          "form": {}
        }
      },
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 18,
            "method": "elicitation/create",
            "params": {
              "mode": "url",
              "message": "Open a secure page.",
              "url": "https://example.com/connect",
              "elicitationId": "missing-capability"
            }
          }
        }
      ]
    },
    {
      "name": "valid_tasks_list",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 19,
            "method": "tasks/list",
            "params": {}
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 19,
            "result": {
              "tasks": []
            }
          }
        }
      ]
    },
    {
      "name": "tasks_list_without_server_capability",
      "expect": "fail",
      "error_contains": "server did not declare capability: tasks.list",
      "server_capabilities": {
        "tools": {},
        "resources": {},
        "prompts": {}
      },
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 20,
            "method": "tasks/list",
            "params": {}
          }
        }
      ]
    },
    {
      "name": "valid_task_augmented_tool_call",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 21,
            "method": "tools/call",
            "params": {
              "name": "lookup_weather",
              "arguments": {
                "city": "Shanghai"
              },
              "task": {
                "ttl": 60000
              }
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 21,
            "result": {
              "task": {
                "taskId": "task-course-1",
                "status": "working",
                "createdAt": "2026-07-14T00:00:00Z",
                "lastUpdatedAt": "2026-07-14T00:00:00Z",
                "ttl": 60000,
                "pollInterval": 1000
              }
            }
          }
        }
      ]
    },
    {
      "name": "task_augmented_tool_call_without_capability",
      "expect": "fail",
      "error_contains": "tasks.requests.tools.call",
      "server_capabilities": {
        "tools": {},
        "resources": {},
        "prompts": {}
      },
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 22,
            "method": "tools/call",
            "params": {
              "name": "lookup_weather",
              "arguments": {
                "city": "Shanghai"
              },
              "task": {}
            }
          }
        }
      ]
    },
    {
      "name": "duplicate_outstanding_request_id",
      "expect": "fail",
      "error_contains": "duplicate outstanding request id",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 23,
            "method": "tools/list"
          }
        },
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:list"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 23,
            "method": "resources/list"
          }
        }
      ]
    },
    {
      "name": "response_id_mismatch",
      "expect": "fail",
      "error_contains": "no matching outstanding request",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 24,
            "method": "tools/list"
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 999,
            "result": {
              "tools": []
            }
          }
        }
      ]
    },
    {
      "name": "response_contains_result_and_error",
      "expect": "fail",
      "error_contains": "exactly one of result or error",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 25,
            "method": "tools/list"
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 25,
            "result": {
              "tools": []
            },
            "error": {
              "code": -32603,
              "message": "ambiguous"
            }
          }
        }
      ]
    },
    {
      "name": "request_before_initialize",
      "expect": "fail",
      "error_contains": "initialize request must be the first interaction",
      "setup": "none",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 26,
            "method": "tools/list"
          }
        }
      ]
    },
    {
      "name": "notification_carries_id",
      "expect": "fail",
      "error_contains": "notification method must not contain id",
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 27,
            "method": "notifications/tools/list_changed"
          }
        }
      ]
    },
    {
      "name": "tools_method_without_server_capability",
      "expect": "fail",
      "error_contains": "server did not declare capability: tools",
      "server_capabilities": {
        "resources": {},
        "prompts": {}
      },
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 28,
            "method": "tools/list"
          }
        }
      ]
    },
    {
      "name": "valid_protocol_error_response",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": 29,
            "method": "tools/list"
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 29,
            "error": {
              "code": -32603,
              "message": "sample protocol failure",
              "data": {
                "retryable": false
              }
            }
          }
        }
      ]
    },
    {
      "name": "boolean_request_id_rejected",
      "expect": "fail",
      "error_contains": "id must be a string or integer",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "id": true,
            "method": "tools/list"
          }
        }
      ]
    },
    {
      "name": "tool_request_in_wrong_direction",
      "expect": "fail",
      "error_contains": "wrong direction",
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 31,
            "method": "tools/list"
          }
        }
      ]
    },
    {
      "name": "valid_roots_list_changed_notification",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "message": {
            "jsonrpc": "2.0",
            "method": "notifications/roots/list_changed"
          }
        }
      ]
    },
    {
      "name": "tool_list_changed_without_subcapability",
      "expect": "fail",
      "error_contains": "tools.listChanged",
      "server_capabilities": {
        "tools": {},
        "resources": {},
        "prompts": {}
      },
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "method": "notifications/tools/list_changed"
          }
        }
      ]
    },
    {
      "name": "initialize_response_id_mismatch",
      "expect": "fail",
      "error_contains": "no matching outstanding request",
      "setup": "initialize_request_only",
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 99,
            "result": {
              "protocolVersion": "2025-11-25",
              "capabilities": {},
              "serverInfo": {
                "name": "bad-id-server",
                "version": "1.0.0"
              }
            }
          }
        }
      ]
    },
    {
      "name": "valid_resources_list_with_descriptor_and_cursor",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:list"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 40,
            "method": "resources/list",
            "params": {
              "cursor": "page-1"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 40,
            "result": {
              "resources": [
                {
                  "uri": "kb://tenant-a/handbook",
                  "name": "handbook",
                  "title": "Course handbook",
                  "description": "Offline course resource.",
                  "mimeType": "text/markdown",
                  "size": 42
                }
              ],
              "nextCursor": "page-2"
            }
          }
        }
      ]
    },
    {
      "name": "valid_resource_templates_list",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:list"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 41,
            "method": "resources/templates/list"
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 41,
            "result": {
              "resourceTemplates": [
                {
                  "uriTemplate": "kb://tenant-a/docs/{doc_id}",
                  "name": "tenant-doc",
                  "mimeType": "text/markdown"
                }
              ]
            }
          }
        }
      ]
    },
    {
      "name": "valid_resource_read_text_blob_and_child",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:read"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 42,
            "method": "resources/read",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 42,
            "result": {
              "contents": [
                {
                  "uri": "kb://tenant-a/handbook",
                  "mimeType": "text/markdown",
                  "text": "# Handbook"
                },
                {
                  "uri": "kb://tenant-a/handbook/chapter-1",
                  "mimeType": "application/octet-stream",
                  "blob": "aGVsbG8="
                }
              ]
            }
          }
        }
      ]
    },
    {
      "name": "valid_resources_list_changed_notification",
      "expect": "pass",
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "method": "notifications/resources/list_changed"
          }
        }
      ]
    },
    {
      "name": "valid_resource_subscription_update_reread_and_unsubscribe",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:read",
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 43,
            "method": "resources/subscribe",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 43,
            "result": {}
          }
        },
        {
          "direction": "server_to_client",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "method": "notifications/resources/updated",
            "params": {
              "uri": "kb://tenant-a/handbook/chapter-1"
            }
          }
        },
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:read"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 44,
            "method": "resources/read",
            "params": {
              "uri": "kb://tenant-a/handbook/chapter-1"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 44,
            "result": {
              "contents": [
                {
                  "uri": "kb://tenant-a/handbook/chapter-1",
                  "text": "Fresh chapter"
                }
              ]
            }
          }
        },
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 45,
            "method": "resources/unsubscribe",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 45,
            "result": {}
          }
        }
      ]
    },
    {
      "name": "failed_unsubscribe_preserves_active_subscription",
      "expect": "pass",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 46,
            "method": "resources/subscribe",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 46,
            "result": {}
          }
        },
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 47,
            "method": "resources/unsubscribe",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 47,
            "error": {
              "code": -32603,
              "message": "temporary failure"
            }
          }
        },
        {
          "direction": "server_to_client",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "method": "notifications/resources/updated",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        }
      ]
    },
    {
      "name": "failed_subscribe_does_not_authorize_updates",
      "expect": "fail",
      "error_contains": "no active subscription",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 48,
            "method": "resources/subscribe",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 48,
            "error": {
              "code": -32002,
              "message": "resource not available"
            }
          }
        },
        {
          "direction": "server_to_client",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "method": "notifications/resources/updated",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        }
      ]
    },
    {
      "name": "resource_descriptor_exceeds_profile_size_gate",
      "expect": "fail",
      "error_contains": "size limit",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:list"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 49,
            "method": "resources/list"
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 49,
            "result": {
              "resources": [
                {
                  "uri": "kb://tenant-a/handbook",
                  "name": "oversized",
                  "size": 65537
                }
              ]
            }
          }
        }
      ]
    },
    {
      "name": "resource_read_rejects_invalid_base64",
      "expect": "fail",
      "error_contains": "valid base64",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:read"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 50,
            "method": "resources/read",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 50,
            "result": {
              "contents": [
                {
                  "uri": "kb://tenant-a/handbook",
                  "blob": "not base64!"
                }
              ]
            }
          }
        }
      ]
    },
    {
      "name": "resource_subscribe_without_subcapability",
      "expect": "fail",
      "error_contains": "resources.subscribe",
      "server_capabilities": {
        "resources": {
          "listChanged": true
        }
      },
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 51,
            "method": "resources/subscribe",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        }
      ]
    },
    {
      "name": "resource_list_changed_without_subcapability",
      "expect": "fail",
      "error_contains": "resources.listChanged",
      "server_capabilities": {
        "resources": {
          "subscribe": true
        }
      },
      "steps": [
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "method": "notifications/resources/list_changed"
          }
        }
      ]
    },
    {
      "name": "resource_read_rejects_cross_tenant_uri",
      "expect": "fail",
      "error_contains": "resource tenant",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "mallory",
            "tenant": "tenant-b",
            "scopes": [
              "resources:read"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 52,
            "method": "resources/read",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        }
      ]
    },
    {
      "name": "resource_read_requires_scope",
      "expect": "fail",
      "error_contains": "resources:read",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "reader",
            "tenant": "tenant-a",
            "scopes": [
              "resources:list"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 53,
            "method": "resources/read",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        }
      ]
    },
    {
      "name": "resource_read_rejects_stale_authorization_revision",
      "expect": "fail",
      "error_contains": "authorization revision",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:read"
            ],
            "authorization_revision": "authz-v0"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 54,
            "method": "resources/read",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        }
      ]
    },
    {
      "name": "resource_read_rejects_principal_tenant_misbinding",
      "expect": "fail",
      "error_contains": "principal binding",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-b",
            "scopes": [
              "resources:read"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 55,
            "method": "resources/read",
            "params": {
              "uri": "kb://tenant-b/secret"
            }
          }
        }
      ]
    },
    {
      "name": "resource_update_rejects_uri_prefix_collision",
      "expect": "fail",
      "error_contains": "no active subscription",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 56,
            "method": "resources/subscribe",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 56,
            "result": {}
          }
        },
        {
          "direction": "server_to_client",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "method": "notifications/resources/updated",
            "params": {
              "uri": "kb://tenant-a/handbookish"
            }
          }
        }
      ]
    },
    {
      "name": "authorization_revision_change_invalidates_subscription_and_stale_reread",
      "expect": "fail",
      "error_contains": "authorization revision",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:subscribe"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 57,
            "method": "resources/subscribe",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        },
        {
          "direction": "server_to_client",
          "message": {
            "jsonrpc": "2.0",
            "id": 57,
            "result": {}
          }
        },
        {
          "control_event": {
            "type": "activate_authorization_revision",
            "revision": "authz-v2"
          }
        },
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:read"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 58,
            "method": "resources/read",
            "params": {
              "uri": "kb://tenant-a/handbook"
            }
          }
        }
      ]
    },
    {
      "name": "resource_list_rejects_wrong_token_audience",
      "expect": "fail",
      "error_contains": "token audience",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "token_audience": "https://other.example.test/mcp",
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:list"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 59,
            "method": "resources/list"
          }
        }
      ]
    },
    {
      "name": "resource_list_rejects_wrong_resource_indicator",
      "expect": "fail",
      "error_contains": "resource indicator",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "resource": "https://other.example.test/mcp",
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:list"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 60,
            "method": "resources/list"
          }
        }
      ]
    },
    {
      "name": "resource_list_rejects_inactive_token",
      "expect": "fail",
      "error_contains": "active access token",
      "steps": [
        {
          "direction": "client_to_server",
          "transport_context": {
            "token_active": false,
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:list"
            ],
            "authorization_revision": "authz-v1"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 61,
            "method": "resources/list"
          }
        }
      ]
    },
    {
      "name": "authorization_revision_rejects_revoked_principal",
      "expect": "fail",
      "error_contains": "principal is revoked",
      "steps": [
        {
          "control_event": {
            "type": "activate_authorization_revision",
            "revision": "authz-v2"
          }
        },
        {
          "direction": "client_to_server",
          "transport_context": {
            "subject": "alice",
            "tenant": "tenant-a",
            "scopes": [
              "resources:list"
            ],
            "authorization_revision": "authz-v2"
          },
          "message": {
            "jsonrpc": "2.0",
            "id": 62,
            "method": "resources/list"
          }
        }
      ]
    }
  ]
}
