@@ -19,6 +19,8 @@ import (
1919	"github.com/containers/kubernetes-mcp-server/pkg/version" 
2020)
2121
22+ const  TokenScopesContextKey  =  "TokenScopesContextKey" 
23+ 
2224type  Configuration  struct  {
2325	Profile     Profile 
2426	ListOutput  output.Output 
@@ -45,20 +47,29 @@ func (c *Configuration) isToolApplicable(tool server.ServerTool) bool {
4547type  Server  struct  {
4648	configuration  * Configuration 
4749	server         * server.MCPServer 
50+ 	enabledTools   []string 
4851	k              * internalk8s.Manager 
4952}
5053
5154func  NewServer (configuration  Configuration ) (* Server , error ) {
55+ 	var  serverOptions  []server.ServerOption 
56+ 	serverOptions  =  append (serverOptions ,
57+ 		server .WithResourceCapabilities (true , true ),
58+ 		server .WithPromptCapabilities (true ),
59+ 		server .WithToolCapabilities (true ),
60+ 		server .WithLogging (),
61+ 		server .WithToolHandlerMiddleware (toolCallLoggingMiddleware ),
62+ 	)
63+ 	if  configuration .StaticConfig .RequireOAuth  {
64+ 		serverOptions  =  append (serverOptions , server .WithToolHandlerMiddleware (toolScopedAuthorizationMiddleware ))
65+ 	}
66+ 
5267	s  :=  & Server {
5368		configuration : & configuration ,
5469		server : server .NewMCPServer (
5570			version .BinaryName ,
5671			version .Version ,
57- 			server .WithResourceCapabilities (true , true ),
58- 			server .WithPromptCapabilities (true ),
59- 			server .WithToolCapabilities (true ),
60- 			server .WithLogging (),
61- 			server .WithToolHandlerMiddleware (toolCallLoggingMiddleware ),
72+ 			serverOptions ... ,
6273		),
6374	}
6475	if  err  :=  s .reloadKubernetesClient (); err  !=  nil  {
@@ -81,6 +92,7 @@ func (s *Server) reloadKubernetesClient() error {
8192			continue 
8293		}
8394		applicableTools  =  append (applicableTools , tool )
95+ 		s .enabledTools  =  append (s .enabledTools , tool .Tool .Name )
8496	}
8597	s .server .SetTools (applicableTools ... )
8698	return  nil 
@@ -125,6 +137,10 @@ func (s *Server) GetKubernetesAPIServerHost() string {
125137	return  s .k .GetAPIServerHost ()
126138}
127139
140+ func  (s  * Server ) GetEnabledTools () []string  {
141+ 	return  s .enabledTools 
142+ }
143+ 
128144func  (s  * Server ) Close () {
129145	if  s .k  !=  nil  {
130146		s .k .Close ()
@@ -181,3 +197,16 @@ func toolCallLoggingMiddleware(next server.ToolHandlerFunc) server.ToolHandlerFu
181197		return  next (ctx , ctr )
182198	}
183199}
200+ 
201+ func  toolScopedAuthorizationMiddleware (next  server.ToolHandlerFunc ) server.ToolHandlerFunc  {
202+ 	return  func (ctx  context.Context , ctr  mcp.CallToolRequest ) (* mcp.CallToolResult , error ) {
203+ 		scopes , ok  :=  ctx .Value (TokenScopesContextKey ).([]string )
204+ 		if  ! ok  {
205+ 			return  NewTextResult ("" , fmt .Errorf ("Authorization failed: Access denied: Tool '%s' requires scope 'mcp:%s' but no scope is available" , ctr .Params .Name , ctr .Params .Name )), nil 
206+ 		}
207+ 		if  ! slices .Contains (scopes , "mcp:" + ctr .Params .Name ) &&  ! slices .Contains (scopes , ctr .Params .Name ) {
208+ 			return  NewTextResult ("" , fmt .Errorf ("Authorization failed: Access denied: Tool '%s' requires scope 'mcp:%s' but only scopes %s are available" , ctr .Params .Name , ctr .Params .Name , scopes )), nil 
209+ 		}
210+ 		return  next (ctx , ctr )
211+ 	}
212+ }
0 commit comments