Initial Checks
Description
Summary
On current main (v2, tested at 3a6f299), FileResource treats MIME types as text only when the value starts with text/ using a case-sensitive comparison. As a result, mixed-case or uppercase text MIME types such as Text/Markdown or TEXT/plain are incorrectly classified as binary.
This is inconsistent with RFC 9110 §8.3.1, which states that media types are case-insensitive. In other words, application/json, Application/JSON, and APPLICATION/JSON are equivalent, and the same principle applies to text/* media types.
Root cause
The current logic checks whether the MIME type starts with text/ directly, without normalizing the value first. Because the comparison is case-sensitive, uppercase or mixed-case text media types do not match and are misclassified as binary.
Why it matters
This can cause text resources to be read and returned as bytes instead of text when the caller provides a non-lowercase text/* MIME type. That can break downstream consumers that expect text content to be handled as text.
Proposed fix
Normalize the MIME type to lowercase before checking whether it begins with text/, so text media types are detected case-insensitively.
This fix is already covered by this PR:
Example
from mcp.server.mcpserver.resources.types import FileResource
resource = FileResource(
uri="file:///tmp/example.md",
name="example",
path="/tmp/example.md",
mime_type="Text/Markdown",
)
assert resource.is_binary is False
Example Code
class DummyRequest:
def __init__(self, headers):
self.headers = headers
def _check_content_type(request):
content_type = request.headers.get("content-type", "")
media_types = [
part.strip().lower()
for part in content_type.split(";", 1)[0].split(",")
]
return "application/json" in media_types
def test(ct):
req = DummyRequest({"content-type": ct})
result = _check_content_type(req)
print(f'"{ct}" -> {result}')
if __name__ == '__main__':
cases = [
'application/json',
'Application/JSON',
'application/json; charset=utf-8',
'APPLICATION/JSON; CHARSET=UTF-8',
'text/plain',
]
for c in cases:
test(c)
Result:
"application/json" -> True
"Application/JSON" -> True
"application/json; charset=utf-8" -> True
"APPLICATION/JSON; CHARSET=UTF-8" -> True
"text/plain" -> False
Python & MCP Python SDK
Python 3.12.13
MCP Python SDK 1.28.1
Initial Checks
Description
Summary
On current
main(v2, tested at 3a6f299),FileResourcetreats MIME types as text only when the value starts withtext/using a case-sensitive comparison. As a result, mixed-case or uppercase text MIME types such asText/MarkdownorTEXT/plainare incorrectly classified as binary.This is inconsistent with RFC 9110 §8.3.1, which states that media types are case-insensitive. In other words,
application/json,Application/JSON, andAPPLICATION/JSONare equivalent, and the same principle applies totext/*media types.Root cause
The current logic checks whether the MIME type starts with
text/directly, without normalizing the value first. Because the comparison is case-sensitive, uppercase or mixed-case text media types do not match and are misclassified as binary.Why it matters
This can cause text resources to be read and returned as bytes instead of text when the caller provides a non-lowercase
text/*MIME type. That can break downstream consumers that expect text content to be handled as text.Proposed fix
Normalize the MIME type to lowercase before checking whether it begins with
text/, so text media types are detected case-insensitively.This fix is already covered by this PR:
Example
Example Code
Result:
Python & MCP Python SDK