Skip to main content
Glama
loginmethod-tools.ts9.72 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { z } from "zod"; import { trackingToolPrefix } from "../client/matomo-tracking.js"; import { SimplifierClient } from "../client/simplifier-client.js"; import { OAuthTargetAndSourceMapper } from "./loginmethod/OAuthTargetAndSourceMapper.js"; import { SAPSSOTargetAndSourceMapper } from "./loginmethod/SAPSSOMapper.js"; import { TargetAndSourceMapper } from "./loginmethod/TargetAndSourceMapper.js"; import { TokenTargetAndSourceMapper } from "./loginmethod/TokenTargetAndSourceMapper.js"; import { UserCredentialsTargetAndSourceMapper } from "./loginmethod/UserCredentialsTargetAndSourceMapper.js"; import { wrapToolResult } from "./toolresult.js"; /** * Register LoginMethod tools for Simplifier Low Code Platform integration */ /** * Validates OAuth2 client name for Default/Reference sources. * Fetches available OAuth2 clients and ensures the provided client name exists. * * @param simplifier - The Simplifier API client * @param params - Tool parameters containing oauth2ClientName * @param sourceType - The source type being used * @throws Error if validation fails or no clients are configured */ async function checkOAuthClient( simplifier: SimplifierClient, params: { oauth2ClientName?: string | undefined }, sourceType: string ): Promise<void> { // Fetch available OAuth2 clients const oauth2Clients = await simplifier.listOAuth2Clients("oauthclients-list"); const availableClientNames = oauth2Clients.authSettings.map(client => client.name); // Handle empty client list if (availableClientNames.length === 0) { throw new Error("No OAuth2 clients configured in Simplifier. Please configure at least one OAuth2 client before creating an OAuth2 login method."); } // Check if provided client name exists if (!params.oauth2ClientName) { throw new Error( `OAuth2 client name is required for ${sourceType} source. ` + `Available clients: ${availableClientNames.join(', ')}` ); } if (!availableClientNames.includes(params.oauth2ClientName)) { throw new Error( `Invalid OAuth2 client name "${params.oauth2ClientName}". ` + `Available clients: ${availableClientNames.join(', ')}` ); } } export function registerLoginMethodTools(server: McpServer, simplifier: SimplifierClient): void { const toolNameLoginMethodUpdate = "loginmethod-update" const toolDescriptionLoginMethodUpdate = `# Create or update a Login Method Create or update login methods for authenticating connectors with external systems. Check the documentation resource below for the type you want to create: **Supported Types:** - **UserCredentials (BasicAuth)**: Username/password authentication. Docs: simplifier://documentation/loginmethod-type/usercredentials - **OAuth2**: OAuth2 client-based authentication. Docs: simplifier://documentation/loginmethod-type/oauth2 - **Token**: Token-based authentication (API keys, SimplifierToken). Docs: simplifier://documentation/loginmethod-type/token - **SAPSSO**: SAP-Single Sign on via Logon Ticket. Docs: simplifier://documentation/loginmethod-type/sapsso Note that the type of a login method cannot be changed later. If you need to change the type, create a new login method instead. ` server.registerTool(toolNameLoginMethodUpdate, { description: toolDescriptionLoginMethodUpdate, inputSchema: { loginMethodType: z.enum(["UserCredentials", "OAuth2", "Token", "SingleSignOn"]) .describe(`Type of login method: UserCredentials for BasicAuth, OAuth2 for OAuth2-based auth, Token for token-based auth, SingleSignOn for SAP-SSO Logon Ticket`), name: z.string().describe("Name of the login method"), description: z.string().describe("Description of the login method"), // Source type (applies to UserCredentials, OAuth2, and Token) sourceType: z.enum(["Default", "Provided", "Reference", "SystemReference", "ProfileReference", "UserAttributeReference"]).optional() .describe(`Source type: * Default (system default - credentials for UserCredentials, OAuth2 client for OAuth2, empty for Token, user logon ticket for SAP-SSO) * SystemReference (Token - uses SimplifierToken) * Provided (UserCredentials - username/password, Token - token value) * Reference (OAuth2 - OAuth2 client reference) * ProfileReference (user profile key) * UserAttributeReference (user attribute)`), // UserCredentials Default/Provided source fields username: z.string().optional() .describe(`[UserCredentials Default/Provided] Username for basic authentication. Must not be empty string. If the information is not given (i.e. in case of Microsoft PAT authentication), use a non empty placeholder`), password: z.string().optional() .describe("[UserCredentials Default/Provided] Password for basic authentication"), changePassword: z.boolean().optional().default(false) .describe("[UserCredentials Default/Provided] Set to true when updating to change the password"), // Token Provided source fields token: z.string().optional().describe("[Token Provided] Token value for authentication"), changeToken: z.boolean().optional().default(false) .describe("[Token Provided] Set to true when updating to change the token"), // Token Provided source fields ticket: z.string().optional().describe("[SingleSignOn Provided] Ticket value for authentication"), changeTicket: z.boolean().optional().default(false) .describe("[SingleSignOn Provided] Set to true when updating to change the ticket"), // OAuth2 Default/Reference fields oauth2ClientName: z.string().optional() .describe("[OAuth2 Default/Reference] Name of the OAuth2 client (discover via simplifier://oauthclients). **Important**: The `oauth2ClientName` **MUST** match one of the existing OAuth2 clients configured in Simplifier. You should discover available clients using the `simplifier://oauthclients` resource before creating the login method."), // ProfileReference fields (UserCredentials and OAuth2) profileKey: z.string().optional().describe("[ProfileReference] Key name in the user's profile"), // UserAttributeReference fields (UserCredentials and OAuth2) userAttributeName: z.string().optional().describe("[UserAttributeReference] Name of the user attribute"), userAttributeCategory: z.string().optional().describe("[UserAttributeReference] Category of the user attribute"), // Target configuration (for OAuth2 and Token) targetType: z.enum(["Default", "CustomHeader", "QueryParameter"]).optional().default("Default") .describe("[OAuth2/Token] Target type: Default (standard auth header), CustomHeader (custom header name), QueryParameter (query param - OAuth2 only)"), customHeaderName: z.string().optional().describe("[OAuth2 CustomHeader] Name of the custom authentication header"), queryParameterKey: z.string().optional().describe("[OAuth2 QueryParameter] Key name for the query parameter") }, annotations: { title: "Create or update a Login Method", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true }, }, async (params) => { return wrapToolResult(`create or update Login Method ${params.name}`, async () => { // Check if login method exists let existing: any; try { const trackingKey = trackingToolPrefix + toolNameLoginMethodUpdate existing = await simplifier.getLoginMethodDetails(params.name, trackingKey); } catch { // Login method doesn't exist, will create } // Select appropriate mapper based on login method type let mapper: TargetAndSourceMapper; if (params.loginMethodType === "UserCredentials") { mapper = new UserCredentialsTargetAndSourceMapper(); } else if (params.loginMethodType === "OAuth2") { mapper = new OAuthTargetAndSourceMapper(); } else if (params.loginMethodType === "Token") { mapper = new TokenTargetAndSourceMapper(); } else if (params.loginMethodType === "SingleSignOn") { mapper = new SAPSSOTargetAndSourceMapper(); } else { throw new Error(`Unsupported loginMethodType: ${params.loginMethodType}`); } // Apply default source type if not provided const sourceType = params.sourceType || mapper.getDefaultSourceType(); // Map source and target using the mapper const { source, sourceConfiguration } = mapper.mapSource(sourceType, params, existing); const { target, targetConfiguration } = mapper.mapTarget(params.targetType || "Default", params); // Validate OAuth2 client name for Default/Reference sources if (params.loginMethodType === "OAuth2" && (sourceType === "Default" || sourceType === "Reference")) { await checkOAuthClient(simplifier, params, sourceType); } // Build the request object const request: any = { name: params.name, description: params.description, loginMethodType: params.loginMethodType, source, target, sourceConfiguration, ...(targetConfiguration && { targetConfiguration }) }; if (existing) { return simplifier.updateLoginMethod(params.name, request); } else { return simplifier.createLoginMethod(request); } }); }); }

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