Skip to main content
Glama
connector-resources.ts10.2 kB
import {SimplifierClient} from "../client/simplifier-client.js"; import {McpServer, ResourceTemplate} from "@modelcontextprotocol/sdk/server/mcp.js"; import {wrapResourceResult} from "./resourcesresult.js"; import {trackingResourcePrefix} from "../client/matomo-tracking.js"; import { RFCWizardSearchOptions } from "../client/types.js"; export function registerConnectorResources(server: McpServer, simplifier: SimplifierClient): void { const noListCallback = { list: undefined } // Main discoverable connectors resource - shows up in resources/list const resourceNameConnectorsList = "connectors-list" server.resource(resourceNameConnectorsList, "simplifier://connectors", { title: "List All Connectors", mimeType: "application/json", description: `# Get the list of all Connectors This resource provides the entry point for discovering all available connectors in the Simplifier instance. Each connector can be accessed via simplifier://connector/{connectorName} for detailed information.` }, async (uri: URL) => { return wrapResourceResult(uri, async () => { const trackingKey = trackingResourcePrefix + resourceNameConnectorsList const response = await simplifier.listConnectors(trackingKey); const connectorResources = response.connectors.map(connector => ({ uri: `simplifier://connector/${connector.name}`, name: connector.name, description: connector.description, type: connector.connectorType.technicalName, active: connector.active, amountOfCalls: connector.amountOfCalls })); return { connectors: connectorResources, totalCount: response.connectors.length, resourcePatterns: [ "simplifier://connectors - List all connectors", "simplifier://connector/{connectorName} - Specific connector details", "simplifier://connector/{connectorName}/calls - List connector calls", "simplifier://connector/{connectorName}/call/{callName} - Specific call details", "simplifier://connector-wizard/{connectorName}/search/{term}/{page} - Search for available SAP RFC function calls", ] }; }); } ); // Resource template for specific connector details const resourceNameConnectorDetails = "connector-details" const connectorDetailsTemplate = new ResourceTemplate("simplifier://connector/{connectorName}", noListCallback); server.resource(resourceNameConnectorDetails, connectorDetailsTemplate, { title: "Connector Details", mimeType: "application/json", description: `# Get detailed information about a specific connector Returns connector configuration, endpoints, and metadata. Use simplifier://connector/{connectorName}/calls to see available calls for this connector.` }, async (uri: URL) => { return wrapResourceResult(uri, async () => { const pathParts = uri.pathname.split('/').filter(p => p); const connectorName = pathParts[0]; if (!connectorName) { throw new Error('Connector name is required'); } const trackingKey = trackingResourcePrefix + resourceNameConnectorDetails const connector = await simplifier.getConnector(connectorName, trackingKey, true); return { connector, relatedResources: [ { uri: `simplifier://connector/${connectorName}/calls`, description: "List all calls for this connector" } ] }; }); } ); // Resource template for connector calls list const resourceNameConnectorCallsList = "connector-calls-list" const connectorCallsListTemplate = new ResourceTemplate("simplifier://connector/{connectorName}/calls", noListCallback); server.resource(resourceNameConnectorCallsList, connectorCallsListTemplate, { title: "Connector Calls List", mimeType: "application/json", description: `# Get all calls available for a specific connector Returns a list of all callable operations for the connector. Each call can be accessed via simplifier://connector/{connectorName}/call/{callName} for detailed parameter information.` }, async (uri: URL) => { return wrapResourceResult(uri, async () => { const pathParts = uri.pathname.split('/').filter(p => p); const connectorName = pathParts[0]; if (!connectorName) { throw new Error('Connector name is required'); } const trackingKey = trackingResourcePrefix + resourceNameConnectorCallsList const response = await simplifier.listConnectorCalls(connectorName, trackingKey); const callResources = response.connectorCalls.map(call => ({ uri: `simplifier://connector/${connectorName}/call/${call.name}`, name: call.name, description: call.description, inputParameters: call.amountOfInputParameters, outputParameters: call.amountOfOutputParameters, executable: call.executable })); return { connectorName, calls: callResources, totalCount: response.connectorCalls.length }; }); } ); // Resource template for specific connector call details const resourceNameConnectorCallDetails = "connector-call-details" const connectorCallDetailsTemplate = new ResourceTemplate("simplifier://connector/{connectorName}/call/{callName}", noListCallback); server.resource(resourceNameConnectorCallDetails, connectorCallDetailsTemplate, { title: "Connector Call Details", mimeType: "application/json", description: `# Get detailed information about a specific connector call Returns complete parameter information including: - Input parameters with data types and whether they are optional - Output parameters with data types - Parameter aliases for use in Business Object functions - Constant values for certain parameters` }, async (uri: URL) => { return wrapResourceResult(uri, async () => { const pathParts = uri.pathname.split('/').filter(p => p); const connectorName = pathParts[0]; const callName = pathParts[2]; if (!connectorName || !callName) { throw new Error('Connector name and call name are required'); } const trackingKey = trackingResourcePrefix + resourceNameConnectorCallDetails const callDetails = await simplifier.getConnectorCall(connectorName, callName, trackingKey); return { call: callDetails, usage: { note: "Use this information when creating Business Object functions that call connectors", example: `Simplifier.Connector.${connectorName}.${callName}({ /* parameters */ })` } }; }); } ); // Resource template for specific connector call details const resourceNameConnectorWSDL = "connector-wsdl" const connectorWSDLTemplate = new ResourceTemplate("simplifier://connector/{connectorName}/wsdl", noListCallback); server.resource(resourceNameConnectorWSDL, connectorWSDLTemplate, { title: "SOAP Connector WSDL", mimeType: "application/xml", description: `# Get the currently used WSDL for a SOAP connector Returns the full XML source of the WSDL. Will fail on non-SOAP connectors` }, async (uri: URL, { connectorName }) => { return wrapResourceResult(uri, async () => { if (typeof connectorName === 'object') { throw new Error("only one connector name allowed") } const trackingKey = trackingResourcePrefix + resourceNameConnectorWSDL const instances = await simplifier.getInstanceSettings(trackingKey); const activeInstance = instances.find(inst => inst.active); if (!activeInstance) { throw new Error("The server currently does not define an active instance"); } return simplifier.getSoapConnectorWSDL(connectorName, activeInstance.name) }, "application/xml"); }, ); const resourceNameRFCConnectorWizardSearch = "connector-wizard-search-functions" const connectorRFCConnectorWizardSearch = new ResourceTemplate("simplifier://connector-wizard/{connectorName}/search/{term}/{page}", noListCallback); const connectorWizardSearchPageSize = 50; server.resource(resourceNameRFCConnectorWizardSearch, connectorRFCConnectorWizardSearch, { title: "Search available function calls (for RFC connectors)", mimeType: "application/json", description: `# Searches for function calls available to a connector Currently, this is only supported for RFC connectors. Returns a list of functions avaliable to the connector {connectorName}, that contain the given {term}. Any non-alphanumeric characters in the search term should be uri-encoded, e.g. %2F for /, %20 for space. At most ${connectorWizardSearchPageSize} items are returned at once, the third variable in the URI specifies the {page}, starting at 0.` }, async (uri: URL, { connectorName, term, page }) => { return wrapResourceResult(uri, async () => { if(typeof connectorName !== 'string' || typeof term !== 'string' || typeof page !== 'string') { throw new Error('URL variables may not be lists'); } const termDecoded = decodeURIComponent(term) const pageNo = parseInt(page) const trackingKey = trackingResourcePrefix + resourceNameRFCConnectorWizardSearch; const filter: RFCWizardSearchOptions = { searchOptions: { searchValue: termDecoded, }, retrievalOptions: { filter: `%${termDecoded}%`, filterMode: "Simple", }, } const matches = await simplifier.searchPossibleRFCConnectorCalls(connectorName, filter, trackingKey); return { matches: matches.slice(pageNo * connectorWizardSearchPageSize, (pageNo + 1) * connectorWizardSearchPageSize), searchTerm: term, page: pageNo, totalPages: Math.ceil(matches.length / connectorWizardSearchPageSize), }; }); }); }

Latest Blog Posts

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/SimplifierIO/simplifier-mcp'

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