amazon-seller-mcp
Version:
Model Context Protocol (MCP) client for Amazon Selling Partner API
131 lines • 4.51 kB
JavaScript
/**
* Resource registration for the Amazon Seller MCP Server
*/
// Third-party dependencies
import { ResourceTemplate, } from '@modelcontextprotocol/sdk/server/mcp.js';
// Internal imports
import { handleResourceError } from './error-handler.js';
import { getLogger } from '../utils/logger.js';
/**
* Normalizes MCP parameters to string values
* Converts string arrays to their first element
*/
function normalizeParams(params) {
const normalized = {};
for (const [key, value] of Object.entries(params)) {
if (Array.isArray(value)) {
normalized[key] = value[0] || '';
}
else {
normalized[key] = value;
}
}
return normalized;
}
/**
* Resource registration manager
*/
export class ResourceRegistrationManager {
server;
registeredResources = new Set();
/**
* Creates a new resource registration manager
* @param server MCP server instance
*/
constructor(server) {
this.server = server;
}
/**
* Registers a resource with the MCP server
*
* @param name Resource name
* @param template Resource template
* @param options Resource registration options
* @param handler Resource handler function
* @returns True if the resource was registered, false if it was already registered
*/
registerResource(name, template, options, handler) {
// Check if the resource is already registered
if (this.registeredResources.has(name)) {
getLogger().warn(`Resource '${name}' is already registered`);
return false;
}
// Register the resource with the MCP server
this.server.registerResource(name, template, {
title: options.title,
description: options.description,
}, async (uri, params) => {
try {
// Normalize params to ensure string values for backward compatibility
const normalizedParams = normalizeParams(params);
return await handler(uri, normalizedParams);
}
catch (error) {
getLogger().error(`Error handling resource '${name}':`, {
error: error.message,
});
// Use the error handler to create a standardized error response
return handleResourceError(error);
}
});
// Add the resource to the set of registered resources
this.registeredResources.add(name);
getLogger().info(`Registered resource '${name}'`);
return true;
}
/**
* Creates a resource template
*
* @param uriTemplate URI template string
* @param listTemplate Optional list template string
* @param completions Optional completions configuration
* @returns Resource template
*/
createResourceTemplate(uriTemplate, listTemplate, completions) {
const templateOptions = {
list: undefined,
};
// Add list template if provided
if (listTemplate) {
// Create a simple list callback that returns the template
templateOptions.list = () => Promise.resolve({
resources: [
{
uri: listTemplate,
name: 'Resource List',
description: 'List of available resources',
},
],
});
}
// Add completions if provided
if (completions) {
templateOptions.complete = completions;
}
const template = new ResourceTemplate(uriTemplate, templateOptions);
// Expose completion methods directly on the template for easier testing
if (completions) {
const extendedTemplate = template;
for (const [key, completionFn] of Object.entries(completions)) {
extendedTemplate[key] = completionFn;
}
}
return template;
}
/**
* Gets the list of registered resource names
* @returns Array of registered resource names
*/
getRegisteredResources() {
return Array.from(this.registeredResources);
}
/**
* Checks if a resource is registered
* @param name Resource name
* @returns True if the resource is registered, false otherwise
*/
isResourceRegistered(name) {
return this.registeredResources.has(name);
}
}
//# sourceMappingURL=resources.js.map