Skip to main content
Glama

NestJS MCP Server Module

by rekog-labs
MIT License
32,416
470
  • Apple
  • Linux
resource-templates.md7.33 kB
# Resource Templates Resource Templates are dynamic resources that can accept parameters in their URIs. Unlike static resources, they use URI patterns to match different paths and extract parameters. In mcp-nest, they're defined using the `@ResourceTemplate()` decorator. ## Basic Resource Template ```typescript import { Injectable, Scope } from '@nestjs/common'; import { ResourceTemplate } from '@rekog/mcp-nest'; @Injectable({ scope: Scope.REQUEST }) export class GreetingResource { @ResourceTemplate({ name: 'user-language', description: "Get a specific user's preferred language", mimeType: 'application/json', uriTemplate: 'mcp://users/{name}', }) getUserLanguage({ uri, name }) { const users = { alice: 'en', carlos: 'es', marie: 'fr', hans: 'de', yuki: 'ja', 'min-jun': 'ko', wei: 'zh', sofia: 'it', joão: 'pt', }; const language = users[name.toLowerCase()] || 'en'; return { contents: [ { uri: uri, mimeType: 'application/json', text: JSON.stringify({ name, language }, null, 2), }, ], }; } } ``` ## URI Template Patterns Resource templates use `path-to-regexp` style patterns: ### Single Parameter ```typescript uriTemplate: 'mcp://users/{userId}' // Matches: mcp://users/123 // Extracts: { userId: '123' } ``` ### Multiple Parameters ```typescript uriTemplate: 'mcp://users/{userId}/posts/{postId}' // Matches: mcp://users/123/posts/456 // Extracts: { userId: '123', postId: '456' } ``` ### Optional Parameters ```typescript uriTemplate: 'mcp://files/{path*}' // Matches: mcp://files/docs/readme.md // Extracts: { path: 'docs/readme.md' } ``` ## Method Signature Resource template methods receive: - `uri`: The actual URI that was requested - Individual parameters extracted from the URI pattern - Additional context if needed ## Real-World Examples ### File System Resource ```typescript @ResourceTemplate({ name: 'file-content', description: 'Read file contents from the system', mimeType: 'text/plain', uriTemplate: 'mcp://files/{path*}', }) getFileContent({ uri, path }) { // Validate path for security if (path.includes('..') || path.startsWith('/')) { return { contents: [{ uri, mimeType: 'text/plain', text: 'Error: Invalid file path', }], }; } // In real implementation, read actual file const content = `Content of file: ${path}`; return { contents: [{ uri, mimeType: 'text/plain', text: content, }], }; } ``` ### User Profile Resource ```typescript @ResourceTemplate({ name: 'user-profile', description: 'Get user profile information', mimeType: 'application/json', uriTemplate: 'mcp://profiles/{userId}', }) async getUserProfile({ uri, userId }) { // In real app, query database const profile = await this.userService.findById(userId); if (!profile) { return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify({ error: 'User not found' }), }], }; } return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(profile), }], }; } ``` ### API Data Resource ```typescript @ResourceTemplate({ name: 'api-endpoint', description: 'Proxy external API data', mimeType: 'application/json', uriTemplate: 'mcp://api/{service}/{endpoint}', }) async getApiData({ uri, service, endpoint }) { const allowedServices = ['github', 'weather', 'news']; if (!allowedServices.includes(service)) { return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify({ error: 'Service not allowed' }), }], }; } // Proxy to external API const data = await this.httpService.get(`https://api.${service}.com/${endpoint}`); return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(data), }], }; } ``` ## Error Handling Always handle invalid parameters gracefully: ```typescript @ResourceTemplate({ name: 'database-record', description: 'Get database records by ID', mimeType: 'application/json', uriTemplate: 'mcp://db/{table}/{id}', }) async getRecord({ uri, table, id }) { try { // Validate table name const allowedTables = ['users', 'posts', 'comments']; if (!allowedTables.includes(table)) { throw new Error('Table not allowed'); } // Validate ID format if (!/^\d+$/.test(id)) { throw new Error('Invalid ID format'); } const record = await this.dbService.findOne(table, id); return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify(record || { error: 'Record not found' }), }], }; } catch (error) { return { contents: [{ uri, mimeType: 'application/json', text: JSON.stringify({ error: error.message }), }], }; } } ``` ## Testing Your Resource Templates ### 1. Start the Server Run the playground server: ```bash npx ts-node-dev --respawn playground/servers/server-stateful.ts ``` ### 2. List Available Resource Templates ```bash npx @modelcontextprotocol/inspector@0.16.2 --cli http://localhost:3030/mcp --transport http --method resources/templates/list ``` Expected output: ```json { "resourceTemplates": [ { "name": "user-language", "description": "Get a specific user's preferred language", "mimeType": "application/json", "uriTemplate": "mcp://users/{name}" } ] } ``` ### 3. Access Resource Templates with Different Parameters **Test with a known user:** ```bash npx @modelcontextprotocol/inspector@0.16.2 --cli http://localhost:3030/mcp --transport http --method resources/read --uri "mcp://users/carlos" ``` Expected output: ```json { "contents": [ { "uri": "mcp://users/alice", "mimeType": "application/json", "text": "{\n \"name\": \"alice\",\n \"language\": \"en\"\n}" } ] } ``` **Test with another user:** ```bash npx @modelcontextprotocol/inspector@0.16.2 --cli http://localhost:3030/mcp --transport http --method resources/read --uri "mcp://users/carlos" ``` Expected output: ```json { "contents": [ { "uri": "mcp://users/carlos", "mimeType": "application/json", "text": "{\n \"name\": \"carlos\",\n \"language\": \"es\"\n}" } ] } ``` **Test with unknown user (fallback behavior):** ```bash npx @modelcontextprotocol/inspector@0.16.2 --cli http://localhost:3030/mcp --transport http --method resources/read --uri "mcp://users/unknown" ``` Expected output: ```json { "contents": [ { "uri": "mcp://users/unknown", "mimeType": "application/json", "text": "{\n \"name\": \"unknown\",\n \"language\": \"en\"\n}" } ] } ``` ### 4. Interactive Testing For interactive testing, use the MCP Inspector UI: ```bash npx @modelcontextprotocol/inspector@0.16.2 ``` Connect to `http://localhost:3030/mcp` and try accessing different URIs to test your templates. ## Example Location See the complete example at: `playground/resources/greeting.resource.ts` ## Related - For static resources, see [Resources](resources.md) - For executable functions, see [Tools](tools.md)

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/rekog-labs/MCP-Nest'

If you have feedback or need assistance with the MCP directory API, please join our Discord server