Skip to content

Commit 722d954

Browse files
authored
enhc(server): allow adding multiple resource templates at once (#483)
* enhc(server): allow adding multiple resource templates at once Following the same pattern from tools, prompts and resources, this patch allows adding multiple resource templates at once. * Apply coderabbitai suggestion #483 (comment) * Increase test coverage Add a test case to cover the new function. #483 (comment)
1 parent cc3f765 commit 722d954

File tree

3 files changed

+74
-21
lines changed

3 files changed

+74
-21
lines changed

mcptest/mcptest.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ type Server struct {
2323
tools []server.ServerTool
2424
prompts []server.ServerPrompt
2525
resources []server.ServerResource
26-
resourceTemplates []ServerResourceTemplate
26+
resourceTemplates []server.ServerResourceTemplate
2727

2828
cancel func()
2929

@@ -107,22 +107,16 @@ func (s *Server) AddResources(resources ...server.ServerResource) {
107107
s.resources = append(s.resources, resources...)
108108
}
109109

110-
// ServerResourceTemplate combines a ResourceTemplate with its handler function.
111-
type ServerResourceTemplate struct {
112-
Template mcp.ResourceTemplate
113-
Handler server.ResourceTemplateHandlerFunc
114-
}
115-
116110
// AddResourceTemplate adds a resource template to an unstarted server.
117111
func (s *Server) AddResourceTemplate(template mcp.ResourceTemplate, handler server.ResourceTemplateHandlerFunc) {
118-
s.resourceTemplates = append(s.resourceTemplates, ServerResourceTemplate{
112+
s.resourceTemplates = append(s.resourceTemplates, server.ServerResourceTemplate{
119113
Template: template,
120114
Handler: handler,
121115
})
122116
}
123117

124118
// AddResourceTemplates adds multiple resource templates to an unstarted server.
125-
func (s *Server) AddResourceTemplates(templates ...ServerResourceTemplate) {
119+
func (s *Server) AddResourceTemplates(templates ...server.ServerResourceTemplate) {
126120
s.resourceTemplates = append(s.resourceTemplates, templates...)
127121
}
128122

@@ -142,10 +136,7 @@ func (s *Server) Start(ctx context.Context) error {
142136
mcpServer.AddTools(s.tools...)
143137
mcpServer.AddPrompts(s.prompts...)
144138
mcpServer.AddResources(s.resources...)
145-
146-
for _, template := range s.resourceTemplates {
147-
mcpServer.AddResourceTemplate(template.Template, template.Handler)
148-
}
139+
mcpServer.AddResourceTemplates(s.resourceTemplates...)
149140

150141
logger := log.New(&s.logBuffer, "", 0)
151142

server/server.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@ type ServerResource struct {
6464
Handler ResourceHandlerFunc
6565
}
6666

67+
// ServerResourceTemplate combines a ResourceTemplate with its handler function.
68+
type ServerResourceTemplate struct {
69+
Template mcp.ResourceTemplate
70+
Handler ResourceTemplateHandlerFunc
71+
}
72+
6773
// serverKey is the context key for storing the server instance
6874
type serverKey struct{}
6975

@@ -365,17 +371,16 @@ func (s *MCPServer) RemoveResource(uri string) {
365371
}
366372
}
367373

368-
// AddResourceTemplate registers a new resource template and its handler
369-
func (s *MCPServer) AddResourceTemplate(
370-
template mcp.ResourceTemplate,
371-
handler ResourceTemplateHandlerFunc,
372-
) {
374+
// AddResourceTemplates registers multiple resource templates at once
375+
func (s *MCPServer) AddResourceTemplates(resourceTemplates ...ServerResourceTemplate) {
373376
s.implicitlyRegisterResourceCapabilities()
374377

375378
s.resourcesMu.Lock()
376-
s.resourceTemplates[template.URITemplate.Raw()] = resourceTemplateEntry{
377-
template: template,
378-
handler: handler,
379+
for _, entry := range resourceTemplates {
380+
s.resourceTemplates[entry.Template.URITemplate.Raw()] = resourceTemplateEntry{
381+
template: entry.Template,
382+
handler: entry.Handler,
383+
}
379384
}
380385
s.resourcesMu.Unlock()
381386

@@ -386,6 +391,14 @@ func (s *MCPServer) AddResourceTemplate(
386391
}
387392
}
388393

394+
// AddResourceTemplate registers a new resource template and its handler
395+
func (s *MCPServer) AddResourceTemplate(
396+
template mcp.ResourceTemplate,
397+
handler ResourceTemplateHandlerFunc,
398+
) {
399+
s.AddResourceTemplates(ServerResourceTemplate{Template: template, Handler: handler})
400+
}
401+
389402
// AddPrompts registers multiple prompts at once
390403
func (s *MCPServer) AddPrompts(prompts ...ServerPrompt) {
391404
s.implicitlyRegisterPromptCapabilities()

server/server_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"errors"
88
"fmt"
99
"reflect"
10+
"slices"
1011
"sort"
1112
"testing"
1213
"time"
@@ -1456,6 +1457,54 @@ func TestMCPServer_ResourceTemplates(t *testing.T) {
14561457
assert.Equal(t, "text/plain", resultContent.MIMEType)
14571458
assert.Equal(t, "test content: something", resultContent.Text)
14581459
})
1460+
1461+
server.AddResourceTemplates(
1462+
ServerResourceTemplate{
1463+
Template: mcp.NewResourceTemplate(
1464+
"test://test-another-resource-1",
1465+
"Another Resource 1",
1466+
),
1467+
Handler: func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
1468+
return []mcp.ResourceContents{}, nil
1469+
},
1470+
},
1471+
ServerResourceTemplate{
1472+
Template: mcp.NewResourceTemplate(
1473+
"test://test-another-resource-2",
1474+
"Another Resource 2",
1475+
),
1476+
Handler: func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) {
1477+
return []mcp.ResourceContents{}, nil
1478+
},
1479+
},
1480+
)
1481+
1482+
t.Run("Check bulk add resource templates", func(t *testing.T) {
1483+
assert.Equal(t, 3, len(server.resourceTemplates))
1484+
})
1485+
1486+
t.Run("Get resource template again", func(t *testing.T) {
1487+
response := server.HandleMessage(
1488+
context.Background(),
1489+
[]byte(listMessage),
1490+
)
1491+
assert.NotNil(t, response)
1492+
1493+
resp, ok := response.(mcp.JSONRPCResponse)
1494+
assert.True(t, ok)
1495+
listResult, ok := resp.Result.(mcp.ListResourceTemplatesResult)
1496+
assert.True(t, ok)
1497+
assert.Len(t, listResult.ResourceTemplates, 3)
1498+
1499+
// resource templates are stored in a map, so the order is not guaranteed
1500+
for _, rt := range listResult.ResourceTemplates {
1501+
assert.True(t, slices.Contains([]string{
1502+
"My Resource",
1503+
"Another Resource 1",
1504+
"Another Resource 2",
1505+
}, rt.Name))
1506+
}
1507+
})
14591508
}
14601509

14611510
func createTestServer() *MCPServer {

0 commit comments

Comments
 (0)