@@ -33,6 +33,9 @@ module {
3333 auth : ?AuthTypes . AuthContext ;
3434 // The HTTP asset cache, if configured.
3535 http_asset_cache : ?CertifiedCache . CertifiedCache < Text , Blob > ;
36+ // The base path for all MCP requests, e.g., "/mcp".
37+ // The SDK will ignore any requests that do not start with this path.
38+ mcp_path : ?Text ;
3639 };
3740
3841 // Helper function to determine if a request is for a streaming response.
@@ -65,7 +68,7 @@ module {
6568 };
6669
6770 // The public entry point for query calls.
68- public func http_request(ctx : Context , req : SrvTypes . HttpRequest ) : SrvTypes . HttpResponse {
71+ public func http_request(ctx : Context , req : SrvTypes . HttpRequest ) : ? SrvTypes . HttpResponse {
6972 if (req. method == "GET" and Text . contains(req. url, #text "/.well-known/oauth-protected-resource" )) {
7073 switch (ctx. http_asset_cache) {
7174 case (?cache) {
@@ -94,7 +97,7 @@ module {
9497 switch (cache. get(clean_path)) {
9598 case (?bodyBlob) {
9699 // CACHE HIT: The library handles everything.
97- return {
100+ return ? {
98101 status_code = 200 ;
99102 headers = [
100103 ("Content-Type" , "application/json" ),
@@ -107,7 +110,7 @@ module {
107110 };
108111 case (null ) {
109112 // CACHE MISS: Instruct the client to upgrade.
110- return {
113+ return ? {
111114 status_code = 204 ;
112115 headers = [];
113116 body = Blob . fromArray([]);
@@ -121,6 +124,13 @@ module {
121124 };
122125 };
123126
127+ // --- 2. Check if the request is for the configured MCP path ---
128+ let mcpUrl = Option . get(ctx. mcp_path, "/mcp" );
129+ if (not Text . startsWith(req. url, #text mcpUrl)) {
130+ // This is not an MCP request. Signal the caller to handle it.
131+ return null ;
132+ };
133+
124134 if (req. method == "GET" and is_streaming_request(req)) {
125135 // Handle the streaming handshake for clients like the MCP Inspector.
126136 let token_blob = Blob . fromArray(Utils . nat64ToBytes(Nat64 . fromIntWrap(Time . now())));
@@ -132,7 +142,7 @@ module {
132142 token = token_blob;
133143 });
134144
135- return {
145+ return ? {
136146 status_code = 200 ;
137147 headers = [("Content-Type" , "text/event-stream" )];
138148 body = Blob . fromArray([]);
@@ -144,7 +154,7 @@ module {
144154 // For any other request, we don't handle it here. We immediately
145155 // instruct the client to upgrade to an update call. This ensures
146156 // all responses are certified via consensus.
147- return {
157+ return ? {
148158 status_code = 204 ; // 204 No Content is a standard way to signal an upgrade.
149159 headers = [];
150160 body = Blob . fromArray([]);
@@ -155,7 +165,7 @@ module {
155165 };
156166
157167 // The public entry point for update calls.
158- public func http_request_update(ctx : Context , req : SrvTypes . HttpRequest ) : async SrvTypes . HttpResponse {
168+ public func http_request_update(ctx : Context , req : SrvTypes . HttpRequest ) : async ? SrvTypes . HttpResponse {
159169 // All MCP logic is now routed through here, ensuring responses are certified.
160170
161171 // --- Intercept metadata requests to perform certification ---
@@ -169,7 +179,7 @@ module {
169179 cache. put(req. url, bodyBlob, null );
170180
171181 // 3. Return a simple, uncertified 200 OK.
172- return {
182+ return ? {
173183 status_code = 200 ;
174184 headers = [("Content-Type" , "application/json" )];
175185 body = bodyBlob;
@@ -181,6 +191,13 @@ module {
181191 };
182192 };
183193
194+ // --- 2. Check if the request is for the configured MCP path ---
195+ let mcpUrl = Option . get(ctx. mcp_path, "/mcp" );
196+ if (not Text . startsWith(req. url, #text mcpUrl)) {
197+ // This is not an MCP request. Signal the caller to handle it.
198+ return null ;
199+ };
200+
184201 // Check if authentication is configured on the server.
185202 switch (ctx. auth) {
186203 case (?authCtx) {
@@ -192,18 +209,18 @@ module {
192209 switch (authResult) {
193210 case (#err(httpResponse)) {
194211 // Auth failed, return the error response immediately.
195- return httpResponse;
212+ return ? httpResponse;
196213 };
197214 case (#ok(authInfo)) {
198215 // Auth succeeded, handle the request with the trusted auth info.
199- return await ctx. mcp_server. handle_request(req, ?authInfo);
216+ return ?( await ctx. mcp_server. handle_request(req, ?authInfo) );
200217 };
201218 };
202219 };
203220 case (_) {
204221 // --- AUTH IS OFF ---
205222 // No auth config, so proceed without authentication.
206- return await ctx. mcp_server. handle_request(req, null );
223+ return ?( await ctx. mcp_server. handle_request(req, null ) );
207224 };
208225 };
209226 };
0 commit comments