Skip to content

Commit f1782e0

Browse files
committed
Add helpers and update README
1 parent d5d23eb commit f1782e0

File tree

8 files changed

+147
-318
lines changed

8 files changed

+147
-318
lines changed

README.md

Lines changed: 36 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -203,154 +203,76 @@ if err := server.ServeStdio(s); err != nil {
203203

204204
### Resources
205205

206-
<details>
207-
<summary>Show Resource Examples</summary>
206+
Resources are how you expose data to LLMs. They can be anything - files, API responses, database queries, system information, etc. Resources can be:
208207

209-
Resources are how you expose data to LLMs. They're similar to GET endpoints in a REST API - they provide data but shouldn't perform significant computation or have side effects. Some examples:
208+
- Static (fixed URI)
209+
- Dynamic (using URI templates)
210210

211-
- File contents
212-
- Database schemas
213-
- API responses
214-
- System information
211+
Here's a simple example of a static resource:
215212

216-
Resources can be static:
217213
```go
218-
// Static text resource
219-
s.AddResource("test://docs/readme", func() ([]interface{}, error) {
220-
return []interface{}{
221-
mcp.TextResourceContents{
222-
ResourceContents: mcp.ResourceContents{
223-
URI: "test://docs/readme",
224-
MIMEType: "text/markdown",
225-
},
226-
Text: "# Project Documentation\nThis is the main documentation...",
227-
},
228-
}, nil
229-
})
230-
231-
// Binary/blob resource (e.g., image)
232-
s.AddResource("test://images/logo", func() ([]interface{}, error) {
233-
imageData, err := os.ReadFile("logo.png")
234-
if err != nil {
235-
return nil, err
236-
}
237-
238-
return []interface{}{
239-
mcp.BlobResourceContents{
240-
ResourceContents: mcp.ResourceContents{
241-
URI: "test://images/logo",
242-
MIMEType: "image/png",
243-
},
244-
Blob: base64.StdEncoding.EncodeToString(imageData),
245-
},
246-
}, nil
247-
})
214+
// Static resource example - exposing a README file
215+
resource := mcp.NewResource(
216+
"docs://readme",
217+
"Project README",
218+
mcp.WithResourceDescription("The project's README file"),
219+
mcp.WithMIMEType("text/markdown"),
220+
mcp.WithAnnotations([]mcp.Role{mcp.RoleAssistant}, 0.8),
221+
)
248222

249-
// Dynamic resource that fetches data
250-
s.AddResource("test://api/weather", func() ([]interface{}, error) {
251-
weather, err := fetchWeatherData()
223+
// Add resource with its handler
224+
s.AddResource(resource, func(ctx context.Context) ([]interface{}, error) {
225+
content, err := os.ReadFile("README.md")
252226
if err != nil {
253227
return nil, err
254228
}
255229

256230
return []interface{}{
257231
mcp.TextResourceContents{
258232
ResourceContents: mcp.ResourceContents{
259-
URI: "test://api/weather",
260-
MIMEType: "application/json",
261-
},
262-
Text: weather,
263-
},
264-
}, nil
265-
})
266-
267-
// Resource with multiple contents
268-
s.AddResource("test://report", func() ([]interface{}, error) {
269-
return []interface{}{
270-
mcp.TextResourceContents{
271-
ResourceContents: mcp.ResourceContents{
272-
URI: "test://report/summary",
273-
MIMEType: "text/plain",
274-
},
275-
Text: "Monthly sales increased by 15%",
276-
},
277-
mcp.TextResourceContents{
278-
ResourceContents: mcp.ResourceContents{
279-
URI: "test://report/details",
280-
MIMEType: "application/json",
233+
URI: "docs://readme",
234+
MIMEType: "text/markdown",
281235
},
282-
Text: `{"sales": {"january": 100, "february": 115}}`,
236+
Text: string(content),
283237
},
284238
}, nil
285239
})
240+
```
286241

287-
// Resource template for dynamic paths
288-
s.AddResourceTemplate("test://users/{id}/profile", func() (mcp.ResourceTemplate, error) {
289-
return mcp.ResourceTemplate{
290-
Name: "User Profile",
291-
Description: "Returns user profile information",
292-
MIMEType: "application/json",
293-
}, nil
294-
})
242+
And here's an example of a dynamic resource using a template:
295243

296-
// Resource with metadata
297-
s.AddResource("test://docs/api", func() ([]interface{}, error) {
298-
return []interface{}{
299-
mcp.TextResourceContents{
300-
ResourceContents: mcp.ResourceContents{
301-
URI: "test://docs/api",
302-
MIMEType: "text/markdown",
303-
},
304-
Text: "## API Documentation\n...",
305-
// Add annotations for the LLM
306-
Annotated: mcp.Annotated{
307-
Annotations: &struct {
308-
Audience []mcp.Role `json:"audience,omitempty"`
309-
Priority float64 `json:"priority,omitempty"`
310-
}{
311-
Audience: []mcp.Role{mcp.RoleAssistant},
312-
Priority: 0.8,
313-
},
314-
},
315-
},
316-
}, nil
317-
})
244+
```go
245+
// Dynamic resource example - user profiles by ID
246+
template := mcp.NewResourceTemplate(
247+
"users://{id}/profile",
248+
"User Profile",
249+
mcp.WithTemplateDescription("Returns user profile information"),
250+
mcp.WithTemplateMIMEType("application/json"),
251+
mcp.WithTemplateAnnotations([]mcp.Role{mcp.RoleAssistant, mcp.RoleUser}, 0.5),
252+
)
318253

319-
// Database-backed resource
320-
s.AddResource("test://db/products", func() ([]interface{}, error) {
321-
products, err := db.QueryProducts()
322-
if err != nil {
323-
return nil, err
324-
}
254+
// Add template with its handler
255+
s.AddResourceTemplate(template, func(ctx context.Context, args map[string]interface{}) ([]interface{}, error) {
256+
userID := args["id"].(string)
325257

326-
productsJSON, err := json.Marshal(products)
258+
profile, err := getUserProfile(userID) // Your DB/API call here
327259
if err != nil {
328260
return nil, err
329261
}
330262

331263
return []interface{}{
332264
mcp.TextResourceContents{
333265
ResourceContents: mcp.ResourceContents{
334-
URI: "test://db/products",
266+
URI: fmt.Sprintf("users://%s/profile", userID),
335267
MIMEType: "application/json",
336268
},
337-
Text: string(productsJSON),
269+
Text: profile,
338270
},
339271
}, nil
340272
})
341273
```
342274

343-
</details>
344-
345-
Resources can be:
346-
- Static or dynamic
347-
- Text or binary
348-
- Single or multi-part
349-
- Template-based for dynamic paths
350-
- Annotated with metadata
351-
- Backed by various data sources
352-
353-
The URI scheme (e.g., `test://`) is arbitrary - you can use any scheme that makes sense for your application. The handler function is called whenever the resource is requested, allowing for dynamic content generation.
275+
The examples are simple but demonstrate the core concepts. Resources can be much more sophisticated - serving multiple contents, using annotations, integrating with databases or external APIs, etc.
354276

355277
### Tools
356278

examples/server/everything/stdio/main.go renamed to examples/everything/main.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,15 @@ func NewMCPServer() *MCPServer {
4747
allResources: generateResources(),
4848
}
4949

50-
s.server.AddResource(mcp.Resource{
51-
URI: "test://static/resource",
52-
Name: "Static Resource",
53-
}, s.handleReadResource)
50+
s.server.AddResource(mcp.NewResource("test://static/resource",
51+
"Static Resource",
52+
mcp.WithMIMEType("text/plain"),
53+
), s.handleReadResource)
5454
s.server.AddResourceTemplate(
55-
mcp.ResourceTemplate{
56-
URITemplate: "test://dynamoc/resource/{id}",
57-
Name: "Dynamic Resource",
58-
},
55+
mcp.NewResourceTemplate(
56+
"test://dynamic/resource/{id}",
57+
"Dynamic Resource",
58+
),
5959
s.handleResourceTemplate,
6060
)
6161
s.server.AddPrompt(mcp.NewPrompt(string(SIMPLE),

examples/server/calculator/calculator.go

Lines changed: 0 additions & 129 deletions
This file was deleted.

examples/server/calculator/sse/main.go

Lines changed: 0 additions & 29 deletions
This file was deleted.

0 commit comments

Comments
 (0)