@@ -141,7 +141,14 @@ type NotificationHandlerFunc func(ctx context.Context, notification mcp.JSONRPCN
141141// MCPServer implements a Model Control Protocol server that can handle various types of requests
142142// including resources, prompts, and tools.
143143type MCPServer struct {
144- mu sync.RWMutex // Add mutex for protecting shared resources
144+ // Separate mutexes for different resource types
145+ resourcesMu sync.RWMutex
146+ promptsMu sync.RWMutex
147+ toolsMu sync.RWMutex
148+ middlewareMu sync.RWMutex
149+ notificationHandlersMu sync.RWMutex
150+ capabilitiesMu sync.RWMutex
151+
145152 name string
146153 version string
147154 instructions string
@@ -301,7 +308,9 @@ func WithToolHandlerMiddleware(
301308 toolHandlerMiddleware ToolHandlerMiddleware ,
302309) ServerOption {
303310 return func (s * MCPServer ) {
311+ s .middlewareMu .Lock ()
304312 s .toolHandlerMiddlewares = append (s .toolHandlerMiddlewares , toolHandlerMiddleware )
313+ s .middlewareMu .Unlock ()
305314 }
306315}
307316
@@ -396,11 +405,14 @@ func (s *MCPServer) AddResource(
396405 resource mcp.Resource ,
397406 handler ResourceHandlerFunc ,
398407) {
408+ s .capabilitiesMu .Lock ()
399409 if s .capabilities .resources == nil {
400410 s .capabilities .resources = & resourceCapabilities {}
401411 }
402- s .mu .Lock ()
403- defer s .mu .Unlock ()
412+ s .capabilitiesMu .Unlock ()
413+
414+ s .resourcesMu .Lock ()
415+ defer s .resourcesMu .Unlock ()
404416 s .resources [resource .URI ] = resourceEntry {
405417 resource : resource ,
406418 handler : handler ,
@@ -412,11 +424,14 @@ func (s *MCPServer) AddResourceTemplate(
412424 template mcp.ResourceTemplate ,
413425 handler ResourceTemplateHandlerFunc ,
414426) {
427+ s .capabilitiesMu .Lock ()
415428 if s .capabilities .resources == nil {
416429 s .capabilities .resources = & resourceCapabilities {}
417430 }
418- s .mu .Lock ()
419- defer s .mu .Unlock ()
431+ s .capabilitiesMu .Unlock ()
432+
433+ s .resourcesMu .Lock ()
434+ defer s .resourcesMu .Unlock ()
420435 s .resourceTemplates [template .URITemplate .Raw ()] = resourceTemplateEntry {
421436 template : template ,
422437 handler : handler ,
@@ -425,11 +440,14 @@ func (s *MCPServer) AddResourceTemplate(
425440
426441// AddPrompt registers a new prompt handler with the given name
427442func (s * MCPServer ) AddPrompt (prompt mcp.Prompt , handler PromptHandlerFunc ) {
443+ s .capabilitiesMu .Lock ()
428444 if s .capabilities .prompts == nil {
429445 s .capabilities .prompts = & promptCapabilities {}
430446 }
431- s .mu .Lock ()
432- defer s .mu .Unlock ()
447+ s .capabilitiesMu .Unlock ()
448+
449+ s .promptsMu .Lock ()
450+ defer s .promptsMu .Unlock ()
433451 s .prompts [prompt .Name ] = prompt
434452 s .promptHandlers [prompt .Name ] = handler
435453}
@@ -441,34 +459,37 @@ func (s *MCPServer) AddTool(tool mcp.Tool, handler ToolHandlerFunc) {
441459
442460// AddTools registers multiple tools at once
443461func (s * MCPServer ) AddTools (tools ... ServerTool ) {
462+ s .capabilitiesMu .Lock ()
444463 if s .capabilities .tools == nil {
445464 s .capabilities .tools = & toolCapabilities {}
446465 }
447- s .mu .Lock ()
466+ s .capabilitiesMu .Unlock ()
467+
468+ s .toolsMu .Lock ()
448469 for _ , entry := range tools {
449470 s .tools [entry .Tool .Name ] = entry
450471 }
451- s .mu .Unlock ()
472+ s .toolsMu .Unlock ()
452473
453474 // Send notification to all initialized sessions
454475 s .sendNotificationToAllClients ("notifications/tools/list_changed" , nil )
455476}
456477
457478// SetTools replaces all existing tools with the provided list
458479func (s * MCPServer ) SetTools (tools ... ServerTool ) {
459- s .mu .Lock ()
480+ s .toolsMu .Lock ()
460481 s .tools = make (map [string ]ServerTool )
461- s .mu .Unlock ()
482+ s .toolsMu .Unlock ()
462483 s .AddTools (tools ... )
463484}
464485
465486// DeleteTools removes a tool from the server
466487func (s * MCPServer ) DeleteTools (names ... string ) {
467- s .mu .Lock ()
488+ s .toolsMu .Lock ()
468489 for _ , name := range names {
469490 delete (s .tools , name )
470491 }
471- s .mu .Unlock ()
492+ s .toolsMu .Unlock ()
472493
473494 // Send notification to all initialized sessions
474495 s .sendNotificationToAllClients ("notifications/tools/list_changed" , nil )
@@ -479,8 +500,8 @@ func (s *MCPServer) AddNotificationHandler(
479500 method string ,
480501 handler NotificationHandlerFunc ,
481502) {
482- s .mu .Lock ()
483- defer s .mu .Unlock ()
503+ s .notificationHandlersMu .Lock ()
504+ defer s .notificationHandlersMu .Unlock ()
484505 s .notificationHandlers [method ] = handler
485506}
486507
@@ -589,12 +610,12 @@ func (s *MCPServer) handleListResources(
589610 id interface {},
590611 request mcp.ListResourcesRequest ,
591612) (* mcp.ListResourcesResult , * requestError ) {
592- s .mu .RLock ()
613+ s .resourcesMu .RLock ()
593614 resources := make ([]mcp.Resource , 0 , len (s .resources ))
594615 for _ , entry := range s .resources {
595616 resources = append (resources , entry .resource )
596617 }
597- s .mu .RUnlock ()
618+ s .resourcesMu .RUnlock ()
598619
599620 // Sort the resources by name
600621 sort .Slice (resources , func (i , j int ) bool {
@@ -622,12 +643,12 @@ func (s *MCPServer) handleListResourceTemplates(
622643 id interface {},
623644 request mcp.ListResourceTemplatesRequest ,
624645) (* mcp.ListResourceTemplatesResult , * requestError ) {
625- s .mu .RLock ()
646+ s .resourcesMu .RLock ()
626647 templates := make ([]mcp.ResourceTemplate , 0 , len (s .resourceTemplates ))
627648 for _ , entry := range s .resourceTemplates {
628649 templates = append (templates , entry .template )
629650 }
630- s .mu .RUnlock ()
651+ s .resourcesMu .RUnlock ()
631652 sort .Slice (templates , func (i , j int ) bool {
632653 return templates [i ].Name < templates [j ].Name
633654 })
@@ -653,11 +674,11 @@ func (s *MCPServer) handleReadResource(
653674 id interface {},
654675 request mcp.ReadResourceRequest ,
655676) (* mcp.ReadResourceResult , * requestError ) {
656- s .mu .RLock ()
677+ s .resourcesMu .RLock ()
657678 // First try direct resource handlers
658679 if entry , ok := s .resources [request .Params .URI ]; ok {
659680 handler := entry .handler
660- s .mu .RUnlock ()
681+ s .resourcesMu .RUnlock ()
661682 contents , err := handler (ctx , request )
662683 if err != nil {
663684 return nil , & requestError {
@@ -686,7 +707,7 @@ func (s *MCPServer) handleReadResource(
686707 break
687708 }
688709 }
689- s .mu .RUnlock ()
710+ s .resourcesMu .RUnlock ()
690711
691712 if matched {
692713 contents , err := matchedHandler (ctx , request )
@@ -717,12 +738,12 @@ func (s *MCPServer) handleListPrompts(
717738 id interface {},
718739 request mcp.ListPromptsRequest ,
719740) (* mcp.ListPromptsResult , * requestError ) {
720- s .mu .RLock ()
741+ s .promptsMu .RLock ()
721742 prompts := make ([]mcp.Prompt , 0 , len (s .prompts ))
722743 for _ , prompt := range s .prompts {
723744 prompts = append (prompts , prompt )
724745 }
725- s .mu .RUnlock ()
746+ s .promptsMu .RUnlock ()
726747
727748 // sort prompts by name
728749 sort .Slice (prompts , func (i , j int ) bool {
@@ -750,9 +771,9 @@ func (s *MCPServer) handleGetPrompt(
750771 id interface {},
751772 request mcp.GetPromptRequest ,
752773) (* mcp.GetPromptResult , * requestError ) {
753- s .mu .RLock ()
774+ s .promptsMu .RLock ()
754775 handler , ok := s .promptHandlers [request .Params .Name ]
755- s .mu .RUnlock ()
776+ s .promptsMu .RUnlock ()
756777
757778 if ! ok {
758779 return nil , & requestError {
@@ -779,7 +800,7 @@ func (s *MCPServer) handleListTools(
779800 id interface {},
780801 request mcp.ListToolsRequest ,
781802) (* mcp.ListToolsResult , * requestError ) {
782- s .mu .RLock ()
803+ s .toolsMu .RLock ()
783804 tools := make ([]mcp.Tool , 0 , len (s .tools ))
784805
785806 // Get all tool names for consistent ordering
@@ -795,6 +816,8 @@ func (s *MCPServer) handleListTools(
795816 for _ , name := range toolNames {
796817 tools = append (tools , s .tools [name ].Tool )
797818 }
819+ s .toolsMu .RUnlock ()
820+
798821 toolsToReturn , nextCursor , err := listByPagination [mcp.Tool ](ctx , s , request .Params .Cursor , tools )
799822 if err != nil {
800823 return nil , & requestError {
@@ -817,9 +840,9 @@ func (s *MCPServer) handleToolCall(
817840 id interface {},
818841 request mcp.CallToolRequest ,
819842) (* mcp.CallToolResult , * requestError ) {
820- s .mu .RLock ()
843+ s .toolsMu .RLock ()
821844 tool , ok := s .tools [request .Params .Name ]
822- s .mu .RUnlock ()
845+ s .toolsMu .RUnlock ()
823846
824847 if ! ok {
825848 return nil , & requestError {
@@ -830,9 +853,16 @@ func (s *MCPServer) handleToolCall(
830853 }
831854
832855 finalHandler := tool .Handler
833- for i := len (s .toolHandlerMiddlewares ) - 1 ; i >= 0 ; i -- {
834- finalHandler = s.toolHandlerMiddlewares [i ](finalHandler )
856+
857+ s .middlewareMu .RLock ()
858+ mw := s .toolHandlerMiddlewares
859+ s .middlewareMu .RUnlock ()
860+
861+ // Apply middlewares in reverse order
862+ for i := len (mw ) - 1 ; i >= 0 ; i -- {
863+ finalHandler = mw [i ](finalHandler )
835864 }
865+
836866 result , err := finalHandler (ctx , request )
837867 if err != nil {
838868 return nil , & requestError {
@@ -849,9 +879,9 @@ func (s *MCPServer) handleNotification(
849879 ctx context.Context ,
850880 notification mcp.JSONRPCNotification ,
851881) mcp.JSONRPCMessage {
852- s .mu .RLock ()
882+ s .notificationHandlersMu .RLock ()
853883 handler , ok := s .notificationHandlers [notification .Method ]
854- s .mu .RUnlock ()
884+ s .notificationHandlersMu .RUnlock ()
855885
856886 if ok {
857887 handler (ctx , notification )
0 commit comments