@@ -40,9 +40,37 @@ const newServer = async ({
4040 }
4141 }
4242
43+ // Parse x-stainless-mcp-client-permissions header to override permission options
44+ //
45+ // Note: Permissions are best-effort and intended to prevent clients from doing unexpected things;
46+ // they're not a hard security boundary, so we allow arbitrary, client-driven overrides.
47+ //
48+ // See the Stainless MCP documentation for more details.
49+ let effectiveMcpOptions = mcpOptions ;
50+ const clientPermissionsHeader = req . headers [ 'x-stainless-mcp-client-permissions' ] ;
51+ if ( typeof clientPermissionsHeader === 'string' ) {
52+ try {
53+ const parsed = JSON . parse ( clientPermissionsHeader ) ;
54+ if ( parsed && typeof parsed === 'object' && ! Array . isArray ( parsed ) ) {
55+ effectiveMcpOptions = {
56+ ...mcpOptions ,
57+ ...( typeof parsed . allow_http_gets === 'boolean' && { codeAllowHttpGets : parsed . allow_http_gets } ) ,
58+ ...( Array . isArray ( parsed . allowed_methods ) && { codeAllowedMethods : parsed . allowed_methods } ) ,
59+ ...( Array . isArray ( parsed . blocked_methods ) && { codeBlockedMethods : parsed . blocked_methods } ) ,
60+ } ;
61+ getLogger ( ) . info (
62+ { clientPermissions : parsed } ,
63+ 'Overriding code execution permissions from x-stainless-mcp-client-permissions header' ,
64+ ) ;
65+ }
66+ } catch ( error ) {
67+ getLogger ( ) . warn ( { error } , 'Failed to parse x-stainless-mcp-client-permissions header' ) ;
68+ }
69+ }
70+
4371 await initMcpServer ( {
4472 server : server ,
45- mcpOptions : mcpOptions ,
73+ mcpOptions : effectiveMcpOptions ,
4674 clientOptions : {
4775 ...clientOptions ,
4876 ...authOptions ,
0 commit comments