|
1 | | -import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; |
| 1 | +import { McpServer, RegisteredResource } from "@modelcontextprotocol/sdk/server/mcp.js"; |
2 | 2 | import { Resource, ResourceLink } from "@modelcontextprotocol/sdk/types.js"; |
3 | 3 |
|
| 4 | +/** |
| 5 | + * Tracks registered session resources by URI to allow updating/removing on re-registration. |
| 6 | + * This prevents "Resource already registered" errors when a tool creates a resource |
| 7 | + * with the same URI multiple times during a session. |
| 8 | + */ |
| 9 | +const registeredResources = new Map<string, RegisteredResource>(); |
| 10 | + |
4 | 11 | /** |
5 | 12 | * Generates a session-scoped resource URI string based on the provided resource name. |
6 | 13 | * |
@@ -47,17 +54,27 @@ export const registerSessionResource = ( |
47 | 54 | blob: payload, |
48 | 55 | }; |
49 | 56 |
|
| 57 | + // Check if a resource with this URI is already registered and remove it |
| 58 | + const existingResource = registeredResources.get(uri); |
| 59 | + if (existingResource) { |
| 60 | + existingResource.remove(); |
| 61 | + registeredResources.delete(uri); |
| 62 | + } |
| 63 | + |
50 | 64 | // Register file resource |
51 | | - server.registerResource( |
| 65 | + const registeredResource = server.registerResource( |
52 | 66 | name, |
53 | 67 | uri, |
54 | 68 | { mimeType, description, title, annotations, icons, _meta }, |
55 | | - async (uri) => { |
| 69 | + async () => { |
56 | 70 | return { |
57 | 71 | contents: [resourceContent], |
58 | 72 | }; |
59 | 73 | } |
60 | 74 | ); |
61 | 75 |
|
| 76 | + // Track the registered resource for potential future removal |
| 77 | + registeredResources.set(uri, registeredResource); |
| 78 | + |
62 | 79 | return { type: "resource_link", ...resource }; |
63 | 80 | }; |
0 commit comments