1+ """Test for base64 encoding issue in MCP server.
2+
3+ This test demonstrates the issue in server.py where the server uses
4+ urlsafe_b64encode but the BlobResourceContents validator expects standard
5+ base64 encoding.
6+
7+ The test should FAIL before fixing server.py to use b64encode instead of
8+ urlsafe_b64encode.
9+ After the fix, the test should PASS.
10+ """
11+
12+ import base64
13+ from typing import cast
14+
15+ import pytest
16+ from pydantic import AnyUrl
17+
18+ from mcp .server .lowlevel .helper_types import ReadResourceContents
19+ from mcp .server .lowlevel .server import Server
20+ from mcp .types import (
21+ BlobResourceContents ,
22+ ReadResourceRequest ,
23+ ReadResourceRequestParams ,
24+ ReadResourceResult ,
25+ ServerResult ,
26+ )
27+
28+
29+ @pytest .mark .anyio
30+ async def test_server_base64_encoding_issue ():
31+ """Tests that server response can be validated by BlobResourceContents.
32+
33+ This test will:
34+ 1. Set up a server that returns binary data
35+ 2. Extract the base64-encoded blob from the server's response
36+ 3. Verify the encoded data can be properly validated by BlobResourceContents
37+
38+ BEFORE FIX: The test will fail because server uses urlsafe_b64encode
39+ AFTER FIX: The test will pass because server uses standard b64encode
40+ """
41+ server = Server ("test" )
42+
43+ # Create binary data that will definitely result in + and / characters
44+ # when encoded with standard base64
45+ binary_data = bytes ([x for x in range (255 )] * 4 )
46+
47+ # Register a resource handler that returns our test data
48+ @server .read_resource ()
49+ async def read_resource (uri : AnyUrl ) -> list [ReadResourceContents ]:
50+ return [ReadResourceContents (content = binary_data ,
51+ mime_type = "application/octet-stream" )]
52+
53+ # Get the handler directly from the server
54+ handler = server .request_handlers [ReadResourceRequest ]
55+
56+ # Create a request
57+ request = ReadResourceRequest (
58+ method = "resources/read" ,
59+ params = ReadResourceRequestParams (uri = AnyUrl ("test://resource" )),
60+ )
61+
62+ # Call the handler to get the response
63+ result : ServerResult = await handler (request )
64+
65+ # Type cast and access the contents
66+ read_result : ReadResourceResult = cast (ReadResourceResult , result )
67+ blob_content = read_result .root .contents [0 ]
68+
69+
70+ # First verify our test data actually produces different encodings
71+ urlsafe_b64 = base64 .urlsafe_b64encode (binary_data ).decode ()
72+ standard_b64 = base64 .b64encode (binary_data ).decode ()
73+ assert urlsafe_b64 != standard_b64 , "Test data doesn't demonstrate"
74+ " encoding difference"
75+
76+ # Now validate the server's output with BlobResourceContents.model_validate
77+ # Before the fix: This should fail with "Invalid base64" because server
78+ # uses urlsafe_b64encode
79+ # After the fix: This should pass because server will use standard b64encode
80+ model_dict = blob_content .model_dump ()
81+
82+ # Direct validation - this will fail before fix, pass after fix
83+ blob_model = BlobResourceContents .model_validate (model_dict )
84+
85+ # Verify we can decode the data back correctly
86+ decoded = base64 .b64decode (blob_model .blob )
87+ assert decoded == binary_data
0 commit comments