Skip to main content
Glama
TykTechnologies

OpenAPI to MCP Server

getPetById

Retrieve pet details by providing a unique pet ID using the MCP server generated from OpenAPI specifications for API integration with AI assistants.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
petIdYesEnhanced pet ID description from overlay

Implementation Reference

  • src/server.ts:48-165 (registration)
    Registers all dynamically mapped MCP tools from OpenAPI spec, including "getPetById". Creates Zod input schema from JSON Schema and registers server.tool with generic handler.
    // Register each tool with the server
    for (const tool of mappedTools) {
        const { mcpToolDefinition, apiCallDetails } = tool;
        console.error(`Registering MCP tool: ${mcpToolDefinition.name}`);  
        
        try {
            // Convert JSON Schema properties to zod schema
            const params: any = {};
            
            if (mcpToolDefinition.inputSchema && mcpToolDefinition.inputSchema.properties) {
                // Loop through all properties and create appropriate Zod schemas based on data type
                for (const [propName, propSchema] of Object.entries(mcpToolDefinition.inputSchema.properties)) {
                    if (typeof propSchema !== 'object') continue;
                    
                    const description = propSchema.description as string || `Parameter: ${propName}`;
                    const required = mcpToolDefinition.inputSchema.required?.includes(propName) || false;
                    
                    // Map JSON Schema types to Zod schema types
                    let zodSchema;
                    const schemaType = Array.isArray(propSchema.type) 
                        ? propSchema.type[0] // If type is an array (for nullable union types), use first type
                        : propSchema.type;
                        
                    // Handle different types with proper Zod schemas
                    switch (schemaType) {
                        case 'integer':
                            zodSchema = z.number().int().describe(description);
                            break;
                        case 'number':
                            zodSchema = z.number().describe(description);
                            break;
                        case 'boolean':
                            zodSchema = z.boolean().describe(description);
                            break;
                        case 'object':
                            // For objects, create a more permissive schema
                            zodSchema = z.object({}).passthrough().describe(description);
                            break;
                        case 'array':
                            // For arrays, allow any array content
                            zodSchema = z.array(z.any()).describe(description);
                            break;
                        case 'string':
                        default:
                            zodSchema = z.string().describe(description);
                            break;
                    }
                    
                    // Make it optional if not required
                    params[propName] = required ? zodSchema : zodSchema.optional();
                    
                    // Add this for debugging
                    console.error(`Registered parameter ${propName} with type: ${schemaType}, required: ${required}`);
                }
            }
            
            // Register the tool using proper MCP SDK format
            server.tool(
                mcpToolDefinition.name,
                params, // This schema will be visible in the MCP Inspector
                async (toolParams: any) => {
                    const requestId = 'req-' + Math.random().toString(36).substring(2, 9);
                    console.error(`MCP Tool '${mcpToolDefinition.name}' invoked. Request ID: ${requestId}`);
                    console.error(`Parameters received:`, toolParams);
                    
                    try {
                        // Execute the API call with the provided parameters
                        const result = await executeApiCall(apiCallDetails, toolParams);
                        
                        if (result.success) {
                            console.error(`[Request ID: ${requestId}] Tool '${mcpToolDefinition.name}' executed successfully.`);
                            
                            // Return success response
                            return {
                                content: [
                                    {
                                        type: "text", 
                                        text: JSON.stringify(result.data)
                                    }
                                ]
                            };
                        } else {
                            console.error(`[Request ID: ${requestId}] Tool '${mcpToolDefinition.name}' execution failed: ${result.error}`);
                            
                            // Map API errors to MCP errors
                            let errorCode = ErrorCode.InternalError;
                            let errorMessage = result.error || `API Error ${result.statusCode}`;
                            
                            if (result.statusCode === 400) {
                                errorCode = ErrorCode.InvalidParams;
                                errorMessage = `Invalid parameters: ${result.error}`;
                            } else if (result.statusCode === 404) {
                                errorCode = ErrorCode.InvalidParams;
                                errorMessage = `Resource not found: ${result.error}`;
                            }
                            
                            throw new McpError(errorCode, errorMessage, result.data);
                        }
                    } catch (invocationError: any) {
                        console.error(`[Request ID: ${requestId}] Error invoking tool:`, invocationError);
                        
                        if (invocationError instanceof McpError) {
                            throw invocationError; // Re-throw known MCP errors
                        }
                        
                        throw new McpError(
                            ErrorCode.InternalError, 
                            `Internal server error: ${invocationError.message}`
                        );
                    }
                }
            );
            
            console.error(`Registered Tool: ${mcpToolDefinition.name}`);
        } catch (registerError) {
            console.error(`Failed to register tool ${mcpToolDefinition.name}:`, registerError);
        }
    }
  • Handler executed for 'getPetById' tool invocation. Logs parameters, calls executeApiCall on the target API, returns JSON response or maps errors to MCP errors.
    async (toolParams: any) => {
        const requestId = 'req-' + Math.random().toString(36).substring(2, 9);
        console.error(`MCP Tool '${mcpToolDefinition.name}' invoked. Request ID: ${requestId}`);
        console.error(`Parameters received:`, toolParams);
        
        try {
            // Execute the API call with the provided parameters
            const result = await executeApiCall(apiCallDetails, toolParams);
            
            if (result.success) {
                console.error(`[Request ID: ${requestId}] Tool '${mcpToolDefinition.name}' executed successfully.`);
                
                // Return success response
                return {
                    content: [
                        {
                            type: "text", 
                            text: JSON.stringify(result.data)
                        }
                    ]
                };
            } else {
                console.error(`[Request ID: ${requestId}] Tool '${mcpToolDefinition.name}' execution failed: ${result.error}`);
                
                // Map API errors to MCP errors
                let errorCode = ErrorCode.InternalError;
                let errorMessage = result.error || `API Error ${result.statusCode}`;
                
                if (result.statusCode === 400) {
                    errorCode = ErrorCode.InvalidParams;
                    errorMessage = `Invalid parameters: ${result.error}`;
                } else if (result.statusCode === 404) {
                    errorCode = ErrorCode.InvalidParams;
                    errorMessage = `Resource not found: ${result.error}`;
                }
                
                throw new McpError(errorCode, errorMessage, result.data);
            }
        } catch (invocationError: any) {
            console.error(`[Request ID: ${requestId}] Error invoking tool:`, invocationError);
            
            if (invocationError instanceof McpError) {
                throw invocationError; // Re-throw known MCP errors
            }
            
            throw new McpError(
                ErrorCode.InternalError, 
                `Internal server error: ${invocationError.message}`
            );
        }
  • Helper function that executes the underlying HTTP API call for any tool, including 'getPetById'. Maps MCP parameters to path/query/header/body, applies auth/security, uses axios to call the target API.
    export async function executeApiCall(
        details: ApiCallDetails,
        mcpInput: Record<string, any> // The raw input object from MCP
    ): Promise<ApiClientResponse> {
        const { method, pathTemplate, serverUrl, parameters, requestBody, securityRequirements, securitySchemes } = details;
    
        // Input validation
        if (!method) {
            return { success: false, statusCode: 400, error: 'API call details missing HTTP method' };
        }
        
        if (!pathTemplate) {
            return { success: false, statusCode: 400, error: 'API call details missing path template' };
        }
        
        if (!serverUrl) {
            return { success: false, statusCode: 400, error: 'API call details missing server URL' };
        }
        
        // Ensure mcpInput is a valid object
        if (!mcpInput || typeof mcpInput !== 'object' || Array.isArray(mcpInput)) {
            console.error(`Invalid input type: ${typeof mcpInput}. Expected an object.`);
            return { success: false, statusCode: 400, error: 'Invalid input: expected an object' };
        }
    
        // Normalize the input object to handle different formats
        // Some MCP clients might send parameters differently
        const normalizedInput = { ...mcpInput };
    
        let url = `${serverUrl}${pathTemplate}`;
        const queryParams: Record<string, any> = {};
        const headers: Record<string, any> = {};
        let body: any = undefined;
    
        console.error(`Executing API call for tool: ${details.method} ${details.pathTemplate}`);
        console.error(`MCP Input received:`, normalizedInput);
    
    
        // Map MCP input back to HTTP request components
        for (const paramDef of parameters) {
            const paramName = paramDef.name;
            const paramValue = normalizedInput[paramName];
    
            if (paramValue !== undefined) { // Only map if present in MCP input
                // Validate parameter value according to schema if possible
                if (paramDef.schema) {
                    const validationError = validateParameterValue(paramValue, paramDef);
                    if (validationError) {
                        return { success: false, statusCode: 400, error: `Parameter '${paramName}': ${validationError}` };
                    }
                }
                
                switch (paramDef.in) {
                    case 'path':
                        url = url.replace(`{${paramName}}`, encodeURIComponent(String(paramValue)));
                        break;
                    case 'query':
                        queryParams[paramName] = paramValue;
                        break;
                    case 'header':
                        headers[paramName] = String(paramValue);
                        break;
                    case 'cookie':
                        // Cookie handling is more complex, often managed by agents or specific header logic
                        console.error(`Cookie parameter '${paramName}' handling not implemented.`);
                        break;
                }
            } else if (paramDef.required) {
                 console.error(`Error: Required parameter '${paramName}' missing in MCP input.`);
                 return { success: false, statusCode: 400, error: `Missing required parameter: ${paramName}` };
            }
        }
    
         // Map request body if defined and present in input
         if (requestBody && normalizedInput.requestBody !== undefined) {
             // Validate request body against schema if available
             const bodyValidationError = validateRequestBody(normalizedInput.requestBody, requestBody);
             if (bodyValidationError) {
                 return { success: false, statusCode: 400, error: `Request body validation failed: ${bodyValidationError}` };
             }
             
             // Assuming the nested 'requestBody' property in mcpInput holds the body
             body = normalizedInput.requestBody;
             // Assume application/json for now, get content type from requestBody definition if needed
             headers['Content-Type'] = 'application/json';
         } else if (requestBody?.required) {
              console.error(`Error: Required requestBody missing in MCP input.`);
              return { success: false, statusCode: 400, error: `Missing required request body` };
         }
    
    
        const requestConfig: AxiosRequestConfig = {
            method: method as any, // Cast needed for Axios types
            url: url,
            params: queryParams,
            headers: headers,
            data: body,
            // Validate status to handle non-2xx as resolved promises
            validateStatus: (status: number) => status >= 200 && status < 500, // Handle 4xx as well
        };
    
        // Apply custom headers from configuration
        if (config.customHeaders && Object.keys(config.customHeaders).length > 0) {
            requestConfig.headers = { ...requestConfig.headers, ...config.customHeaders };
        }
    
        // Add X-MCP header unless disabled
        if (!config.disableXMcp) {
            requestConfig.headers = { ...requestConfig.headers, 'X-MCP': '1' };
        }
        
        // Apply security before making the call
        try {
            await applySecurity(requestConfig, securityRequirements, securitySchemes);
        } catch (secErr: any) {
            console.error("Security application failed:", secErr);
            return { success: false, statusCode: 401, error: `Security setup failed: ${secErr.message}` };
        }
    
        console.error(`Making HTTP request:`, {
            method: requestConfig.method,
            url: requestConfig.url,
            params: requestConfig.params,
            headers: requestConfig.headers,
            data: requestConfig.data ? '[Request Body Present]' : undefined // Avoid logging sensitive data
        });
    
        try {
            const response = await axios(requestConfig);
    
            console.error(`API response received: Status ${response.status}`);
    
            if (response.status >= 200 && response.status < 300) {
                return {
                    success: true,
                    statusCode: response.status,
                    data: response.data,
                };
            } else {
                // Handle 4xx client errors reported by the API
                console.error(`API returned client error ${response.status}:`, response.data);
                return {
                    success: false,
                    statusCode: response.status,
                    error: `API Error ${response.status}: ${JSON.stringify(response.data)}`,
                    data: response.data // Optionally include error data
                };
            }
        } catch (error) {
            const axiosError = error as AxiosError;
            console.error(`API call failed: ${axiosError.message}`, axiosError.response?.data || axiosError.code);
    
            if (axiosError.response) {
                // Errors during the request setup or >= 500 if validateStatus wasn't broad enough
                return {
                    success: false,
                    statusCode: axiosError.response.status || 500,
                    error: `API Error ${axiosError.response.status}: ${JSON.stringify(axiosError.response.data) || axiosError.message}`,
                    data: axiosError.response.data
                };
            } else {
                // Network error, DNS error, etc.
                return {
                    success: false,
                    statusCode: 503, // Service Unavailable or similar
                    error: `Network or request setup error: ${axiosError.message}`,
                };
            }
        }
    }
  • Maps OpenAPI operations to MCP tools. Creates tool named 'getPetById' from matching operationId, generates inputSchema from parameters and outputSchema from 2xx response.
    export function mapOpenApiToMcpTools(openapi: ProcessedOpenAPI): MappedTool[] {
        const mappedTools: MappedTool[] = [];
        const globalSecurity = openapi.security || null; // Global security requirements
        const securitySchemes = openapi.components?.securitySchemes || undefined; // Security scheme definitions
    
        if (!openapi.paths) {
            console.error("OpenAPI spec has no paths defined.");
            return [];
        }
    
        // Determine the base server URL
        // Priority: Configured URL > First Server URL > Error/Default
        let baseServerUrl = config.targetApiBaseUrl;
        if (!baseServerUrl) {
            // Extract URL template from servers, defaulting to '/' if not found
            baseServerUrl = openapi.servers?.[0]?.url ?? '/';
        }
        // Ensure it's not undefined before using replace
        baseServerUrl = (baseServerUrl || '/').replace(/\/$/, '');
    
        for (const path in openapi.paths) {
            const pathItem = openapi.paths[path] as OpenAPIV3.PathItemObject; // Assuming dereferenced
    
            for (const method in pathItem) {
                // Check if the method is a valid HTTP method
                if (!['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'].includes(method.toLowerCase())) {
                    continue;
                }
    
                const operation = pathItem[method as keyof OpenAPIV3.PathItemObject] as OpenAPIV3.OperationObject;
                if (!operation || typeof operation !== 'object') continue;
    
    
                const operationId = operation.operationId;
    
                // --- Filtering ---
                if (!shouldIncludeOperation(operationId, path, method)) {
                    // If operationId is available, log it for better debugging
                    if (operationId) {
                        console.error(`Skipping operation ${operationId} (${method.toUpperCase()} ${path}) due to filter rules.`);
                    } else {
                        console.error(`Skipping operation ${method.toUpperCase()} ${path} due to filter rules.`);
                    }
                    continue;
                }
    
                // Skip operations without operationId as we need it for the tool name
                if (!operationId) {
                    console.error(`Skipping operation ${method.toUpperCase()} ${path} due to missing operationId.`);
                    continue;
                }
    
                // --- Mapping ---
                let toolName = operationId;
                
                // Debug logging to identify what summary/description fields are available
                console.error(`Tool: ${toolName} - Operation description: ${operation.description || 'N/A'}`);
                console.error(`Tool: ${toolName} - Operation summary: ${operation.summary || 'N/A'}`);
                console.error(`Tool: ${toolName} - Path summary: ${pathItem.summary || 'N/A'}`);
                
                // Check for custom MCP extensions at the operation level first, then path level
                const operationMcpExtension = (operation as any)['x-mcp'];
                const pathMcpExtension = (pathItem as any)['x-mcp'];
                
                // Priority: Operation-level extension > Path-level extension > Default
                if (operationMcpExtension && typeof operationMcpExtension === 'object') {
                    if (operationMcpExtension.name && typeof operationMcpExtension.name === 'string') {
                        console.error(`Tool: ${toolName} - Using custom name from operation-level x-mcp extension: ${operationMcpExtension.name}`);
                        toolName = operationMcpExtension.name;
                    }
                } else if (pathMcpExtension && typeof pathMcpExtension === 'object') {
                    if (pathMcpExtension.name && typeof pathMcpExtension.name === 'string') {
                        console.error(`Tool: ${toolName} - Using custom name from path-level x-mcp extension: ${pathMcpExtension.name}`);
                        toolName = pathMcpExtension.name;
                    }
                }
    
                let toolDescription = operation.description || operation.summary || pathItem.summary || 'No description available.';
                
                // Check for custom description in MCP extension - operation level first, then path level
                if (operationMcpExtension && typeof operationMcpExtension === 'object') {
                    if (operationMcpExtension.description && typeof operationMcpExtension.description === 'string') {
                        console.error(`Tool: ${toolName} - Using custom description from operation-level x-mcp extension: ${operationMcpExtension.description}`);
                        toolDescription = operationMcpExtension.description;
                    }
                } else if (pathMcpExtension && typeof pathMcpExtension === 'object') {
                    if (pathMcpExtension.description && typeof pathMcpExtension.description === 'string') {
                        console.error(`Tool: ${toolName} - Using custom description from path-level x-mcp extension: ${pathMcpExtension.description}`);
                        toolDescription = pathMcpExtension.description;
                    }
                }
                
                console.error(`Tool: ${toolName} - Final description used: ${toolDescription}`);
    
                // --- Input Schema ---
                const inputJsonSchema: JSONSchema7 = {
                    type: 'object',
                    properties: {},
                    required: [],
                };
    
                const allParameters: OpenAPIV3.ParameterObject[] = [
                    ...(pathItem.parameters || []), // Parameters defined at path level
                    ...(operation.parameters || []), // Parameters defined at operation level
                ].filter(isParameterObject); // Ensure they are actual parameter objects
    
                // Group parameters by their location (path, query, header, cookie)
                const parametersByLocation: Record<string, OpenAPIV3.ParameterObject[]> = {};
                for (const param of allParameters) {
                    const location = param.in || 'query'; // Default to query if not specified
                    if (!parametersByLocation[location]) {
                        parametersByLocation[location] = [];
                    }
                    parametersByLocation[location].push(param);
                }
                
                // Create separate property for each parameter location group for better organization
                for (const [location, params] of Object.entries(parametersByLocation)) {
                    // If there are parameters in this location, create a property for them
                    if (params.length > 0 && inputJsonSchema.properties) {
                        // Process each parameter within its location group
                        for (const param of params) {
                            if (param.name && param.schema && inputJsonSchema.properties) {
                                // Debug log to identify potential type issues
                                console.error(`Processing parameter ${param.name} with schema type: ${(param.schema as any).type} format: ${(param.schema as any).format}`);
                                
                                // Convert OpenAPI schema to JSON Schema
                                const paramSchema = openApiSchemaToJsonSchema(param.schema as OpenAPIV3.SchemaObject);
                                
                                if (paramSchema) {
                                    // Debug log for converted schema
                                    console.error(`Converted schema for ${param.name}: type=${paramSchema.type}, format=${(paramSchema as any).format}`);
                                    
                                    // Add parameter to properties
                                    inputJsonSchema.properties[param.name] = paramSchema;
                                    
                                    // Add description if available
                                    if (param.description) {
                                        (inputJsonSchema.properties[param.name] as JSONSchema7).description = param.description;
                                    }
                                    
                                    // Add parameter location metadata as an annotation
                                    (inputJsonSchema.properties[param.name] as any)['x-parameter-location'] = location;
                                    
                                    // Add deprecated flag if needed
                                    if (param.deprecated) {
                                        (inputJsonSchema.properties[param.name] as any).deprecated = true;
                                    }
                                    
                                    // Add example if available
                                    if (param.example !== undefined) {
                                        (inputJsonSchema.properties[param.name] as any).example = param.example;
                                    }
                                    
                                    // Handle required parameters
                                    if (param.required && inputJsonSchema.required) {
                                        inputJsonSchema.required.push(param.name);
                                    }
                                    
                                    // Add any extensions (x-... properties)
                                    Object.keys(param).forEach(key => {
                                        if (key.startsWith('x-')) {
                                            (inputJsonSchema.properties![param.name] as any)[key] = param[key as keyof OpenAPIV3.ParameterObject];
                                        }
                                    });
                                }
                            }
                        }
                    }
                }
    
                // Handle Request Body
                if (isRequestBodyObject(operation.requestBody)) {
                    // Look for application/json content first, fall back to any available content type
                    const jsonContent = operation.requestBody.content?.['application/json']?.schema;
                    const anyContent = Object.values(operation.requestBody.content || {})[0]?.schema;
                    const requestBodySchema = jsonContent || anyContent;
    
                    if (isSchemaObject(requestBodySchema)) {
                        // Convert request body schema and add it to input schema
                        const convertedSchema = openApiSchemaToJsonSchema(requestBodySchema);
                        
                        if (convertedSchema && inputJsonSchema.properties) {
                            // Add as 'requestBody' property
                            inputJsonSchema.properties['requestBody'] = convertedSchema;
                            
                            // Mark as required if specified
                            if (operation.requestBody.required && inputJsonSchema.required) {
                                inputJsonSchema.required.push('requestBody');
                            }
                            
                            // Add description if available
                            if (operation.requestBody.description && inputJsonSchema.properties['requestBody']) {
                                inputJsonSchema.properties['requestBody'].description = operation.requestBody.description;
                            }
                            
                            // Add content type annotation
                            const contentTypes = Object.keys(operation.requestBody.content || {});
                            if (contentTypes.length > 0) {
                                (inputJsonSchema.properties['requestBody'] as any)['x-content-types'] = contentTypes;
                            }
                        }
                    }
                }
    
                // Remove empty required array if nothing is required
                if (inputJsonSchema.required?.length === 0) {
                    delete inputJsonSchema.required;
                }
    
                // --- Output Schema (Primary Success Response, e.g., 200) ---
                let outputJsonSchema: JSONSchema7 | undefined = undefined;
                const successResponseCode = Object.keys(operation.responses || {}).find(code => code.startsWith('2')); // Find first 2xx response
                if (successResponseCode) {
                    const response = operation.responses?.[successResponseCode];
                    if (isResponseObject(response)) {
                        const jsonContent = response.content?.['application/json']?.schema;
                        if (isSchemaObject(jsonContent)) {
                            const tempSchema = openApiSchemaToJsonSchema(jsonContent);
                            outputJsonSchema = tempSchema as JSONSchema7; // Cast to JSONSchema7 since we know it's a schema
                            if(outputJsonSchema && response.description){
                                outputJsonSchema.description = response.description; // Add response description
                            }
                        }
                    }
                }
    
                // --- Assemble MCP Tool Definition ---
                const mcpDefinition: McpToolDefinition = {
                    name: toolName,
                    description: toolDescription,
                    inputSchema: inputJsonSchema,
                    outputSchema: outputJsonSchema, // Properly include the outputSchema
                    annotations: {
                        // Add any relevant annotations, e.g., from spec extensions
                        'x-openapi-path': path,
                        'x-openapi-method': method.toUpperCase(),
                    }
                };
    
                // --- Assemble API Call Details ---
                const apiDetails: ApiCallDetails = {
                    method: method.toUpperCase(),
                    pathTemplate: path,
                    serverUrl: baseServerUrl, // Use the determined base URL
                    parameters: allParameters, // Store original params for mapping back
                    requestBody: isRequestBodyObject(operation.requestBody) ? operation.requestBody : undefined, // Store original body info
                    securityRequirements: operation.security !== undefined ? operation.security : globalSecurity, // Operation security overrides global
                    securitySchemes, // Include security schemes from OpenAPI components
                };
    
                mappedTools.push({ mcpToolDefinition: mcpDefinition, apiCallDetails: apiDetails });
                console.error(`Mapped tool: ${toolName} (${method.toUpperCase()} ${path})`);
            }
        }
    
        console.error(`Total tools mapped: ${mappedTools.length}`);
        return mappedTools;
    }
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Tool has no description.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness1/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Tool has no description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness1/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Tool has no description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Tool has no description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose1/5

Does the description clearly state what the tool does and how it differs from similar tools?

Tool has no description.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines1/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Tool has no description.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

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/TykTechnologies/api-to-mcp'

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