Skip to main content
Glama
Noveum

API-Market MCP Server

by Noveum

text-to-image

Generate high-quality images from text prompts using customizable parameters like dimensions, scheduler, and output count via API-Market MCP Server's POST request.

Instructions

Make a POST request to bridgeml/text!to!image/text_to_image

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
guidance_scaleNoThe guidance scale
heightYesThe height of the image
negative_promptNoThe negative promptworst quality, low quality
num_inference_stepsNoThe number of inference steps
num_outputsNoThe number of outputs
promptYesThe prompt for generating the imageFuturistic space battle, hyper realistic, 4k
schedulerNoThe scheduler to useK_EULER
widthYesThe width of the image

Implementation Reference

  • The MCP tool execution handler. For 'text-to-image', it derives the HTTP endpoint from the tool ID (e.g., POST-text-to-image), constructs the request using input arguments as params or body, calls the API, and returns the JSON response as text content.
    this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
      const { id, name, arguments: params } = request.params;
    
      console.error("Received request:", request.params);
      console.error("Using parameters from arguments:", params);
    
      // Find tool by ID or name
      let tool: Tool | undefined;
      let toolId: string | undefined;
    
      if (id) {
        toolId = id.trim();
        tool = this.tools.get(toolId);
      } else if (name) {
        // Search for tool by name
        for (const [tid, t] of this.tools.entries()) {
          if (t.name === name) {
            tool = t;
            toolId = tid;
            break;
          }
        }
      }
    
      if (!tool || !toolId) {
        console.error(
          `Available tools: ${Array.from(this.tools.entries())
            .map(([id, t]) => `${id} (${t.name})`)
            .join(", ")}`,
        );
        throw new Error(`Tool not found: ${id || name}`);
      }
    
      console.error(`Executing tool: ${toolId} (${tool.name})`);
    
      try {
        // Extract method and path from tool ID
        const [method, ...pathParts] = toolId.split("-");
        let path = "/" + pathParts.join("/")
          .replace(/-/g, "/")
          .replaceAll('!', "-");
    
    
        // Ensure base URL ends with slash for proper joining
        const baseUrl = this.config.apiBaseUrl.endsWith("/")
          ? this.config.apiBaseUrl
          : `${this.config.apiBaseUrl}/`;
    
    
        // Remove leading slash from path to avoid double slashes
        const cleanPath = path.startsWith("/") ? path.slice(1) : path;
    
        let url;
        try {
          // Validate that the path results in a valid URL
          // Construct the full URL
          url = new URL(cleanPath, baseUrl).toString();
        } catch (error) {
          throw new Error(`Invalid path generated from tool ID ${toolId}: ${error.message}`);
        }
        // Prepare request configuration
        this.config.headers = this.config.headers || {};
        const contentType = this.headers.get(toolId);
        if (contentType) {
          this.config.headers['Content-Type'] = contentType;
        }
        const config: any = {
          method: method.toLowerCase(),
          url: url,
          headers: this.config.headers,
        };
    
        // Handle different parameter types based on HTTP method
        if (method.toLowerCase() === "get") {
          // For GET requests, ensure parameters are properly structured
          if (params && typeof params === "object") {
            // Handle array parameters properly
            const queryParams: Record<string, string> = {};
            for (const [key, value] of Object.entries(params)) {
              if (Array.isArray(value)) {
                // Join array values with commas for query params
                queryParams[key] = value.join(",");
              } else if (value !== undefined && value !== null) {
                // Convert other values to strings
                queryParams[key] = String(value);
              }
            }
            config.params = queryParams;
          }
        } else {
          // For POST, PUT, PATCH - send as body
          config.data = params;
        }
    
        console.error("Final request config:", config);
    
        try {
    
          const response = await axios(config);
          return {
            content: [{
              type: "text",
              text: JSON.stringify(response.data, null, 2)
            }]
          };
        } catch (error) {
          if (axios.isAxiosError(error)) {
            console.error("Request failed:", {
              status: error.response?.status,
              statusText: error.response?.statusText,
              data: error.response?.data,
              headers: error.response?.headers,
            });
            throw new Error(
              `API request failed: ${error.message} - ${JSON.stringify(error.response?.data)}`,
            );
          }
          throw error;
        }
    
      } catch (error) {
        if (axios.isAxiosError(error)) {
          throw new Error(`API request failed: ${error.message}`);
        }
        throw error;
      }
    });
  • Dynamic registration of all MCP tools (including 'text-to-image') from OpenAPI specs listed in modified_files.txt. Tool names like 'text-to-image' come from operation summary after shortening by helper scripts.
    private async parseOpenAPISpec(): Promise<void> {
      const paths = await this.listOfFilePaths()
      for (const cur_path of paths) {
    
        if (!cur_path || cur_path.trim() === '') {
          console.error('Skipping empty path');
          continue;
        }
    
        try {
          const spec = await this.loadOpenAPISpec(path.resolve(__dirname, cur_path));
    
          // Convert each OpenAPI path to an MCP tool
          for (const [path, pathItem] of Object.entries(spec.paths)) {
            if (!pathItem) continue;
    
            for (const [method, operation] of Object.entries(pathItem)) {
              if (method === "parameters" || !operation) continue;
    
              const op = operation as OpenAPIV3.OperationObject;
              // Create a clean tool ID by removing the leading slash and replacing special chars
    
              const cleanPath = path.replace(/^\//, "");
              const toolId = `${method.toUpperCase()}-${cleanPath}`.replace(
                /[^a-zA-Z0-9-_]/g,
                "-",
              );
              const tool: Tool = {
                name:
                  (op.operationId || op.summary || `${method.toUpperCase()} ${path}`).replace(/\s+/g, "_"),
                description:
                  op.description ||
                  `Make a ${method.toUpperCase()} request to ${path}`,
                inputSchema: {
                  type: "object",
                  properties: {},
                  // Add any additional properties from OpenAPI spec
                },
              };
    
              // Add parameters from operation
              if (op.parameters) {
                for (const param of op.parameters) {
                  if ("name" in param && "in" in param) {
                    const paramSchema = param.schema as OpenAPIV3.SchemaObject;
                    tool.inputSchema.properties[param.name] = {
                      type: paramSchema.type || "string",
                      description: param.description || `${param.name} parameter`,
                    };
                    if (param.required) {
                      tool.inputSchema.required = tool.inputSchema.required || [];
                      tool.inputSchema.required.push(param.name);
                    }
                  }
                }
              }
    
              // Add request body if present (for POST, PUT, etc.)
              if (op.requestBody) {
                const requestBody = op.requestBody as OpenAPIV3.RequestBodyObject;
                const content = requestBody.content;
    
                // Usually we'd look for application/json content type
                if (content?.['application/json']) {
                  this.headers.set(toolId, 'application/json');
                  const jsonSchema = content['application/json'].schema as OpenAPIV3.SchemaObject;
    
                  // If it's a reference, we'd need to resolve it
                  // For simplicity, assuming it's an inline schema
                  if (jsonSchema.properties) {
                    // Add all properties from the request body schema
                    for (const [propName, propSchema] of Object.entries(jsonSchema.properties)) {
                      tool.inputSchema.properties[propName] = propSchema;
                    }
    
                    // Add required properties if defined
                    if (jsonSchema.required) {
                      tool.inputSchema.required = tool.inputSchema.required || [];
                      tool.inputSchema.required.push(...jsonSchema.required);
                    }
                  }
                }
                else if (content?.['application/x-www-form-urlencoded']) {
                  this.headers.set(toolId, 'application/x-www-form-urlencoded');
                  const urlencodedSchema = content['application/x-www-form-urlencoded'].schema as OpenAPIV3.SchemaObject;
    
                  if (urlencodedSchema.properties) {
                    for (const [propName, propSchema] of Object.entries(urlencodedSchema.properties)) {
                      tool.inputSchema.properties[propName] = propSchema;
                    }
    
                    if (urlencodedSchema.required) {
                      tool.inputSchema.required = tool.inputSchema.required || [];
                      tool.inputSchema.required.push(...urlencodedSchema.required);
                    }
                  }
                }
              }
    
              this.tools.set(toolId, tool);
            }
          }
        } catch (error) {
          console.error(`Error parsing OpenAPI spec from ${cur_path}:`, error);
        }
      }
    }
  • Dynamic input schema construction for tools from OpenAPI operation parameters and requestBody, defining the expected inputs for 'text-to-image' tool.
    const tool: Tool = {
      name:
        (op.operationId || op.summary || `${method.toUpperCase()} ${path}`).replace(/\s+/g, "_"),
      description:
        op.description ||
        `Make a ${method.toUpperCase()} request to ${path}`,
      inputSchema: {
        type: "object",
        properties: {},
        // Add any additional properties from OpenAPI spec
      },
    };
    
    // Add parameters from operation
    if (op.parameters) {
      for (const param of op.parameters) {
        if ("name" in param && "in" in param) {
          const paramSchema = param.schema as OpenAPIV3.SchemaObject;
          tool.inputSchema.properties[param.name] = {
            type: paramSchema.type || "string",
            description: param.description || `${param.name} parameter`,
          };
          if (param.required) {
            tool.inputSchema.required = tool.inputSchema.required || [];
            tool.inputSchema.required.push(param.name);
          }
        }
      }
    }
    
    // Add request body if present (for POST, PUT, etc.)
    if (op.requestBody) {
      const requestBody = op.requestBody as OpenAPIV3.RequestBodyObject;
      const content = requestBody.content;
    
      // Usually we'd look for application/json content type
      if (content?.['application/json']) {
        this.headers.set(toolId, 'application/json');
        const jsonSchema = content['application/json'].schema as OpenAPIV3.SchemaObject;
    
        // If it's a reference, we'd need to resolve it
        // For simplicity, assuming it's an inline schema
        if (jsonSchema.properties) {
          // Add all properties from the request body schema
          for (const [propName, propSchema] of Object.entries(jsonSchema.properties)) {
            tool.inputSchema.properties[propName] = propSchema;
          }
    
          // Add required properties if defined
          if (jsonSchema.required) {
            tool.inputSchema.required = tool.inputSchema.required || [];
            tool.inputSchema.required.push(...jsonSchema.required);
          }
        }
      }
      else if (content?.['application/x-www-form-urlencoded']) {
        this.headers.set(toolId, 'application/x-www-form-urlencoded');
        const urlencodedSchema = content['application/x-www-form-urlencoded'].schema as OpenAPIV3.SchemaObject;
    
        if (urlencodedSchema.properties) {
          for (const [propName, propSchema] of Object.entries(urlencodedSchema.properties)) {
            tool.inputSchema.properties[propName] = propSchema;
          }
    
          if (urlencodedSchema.required) {
            tool.inputSchema.required = tool.inputSchema.required || [];
            tool.inputSchema.required.push(...urlencodedSchema.required);
          }
        }
      }
    }
  • Preprocessing helper that shortens verbose OpenAPI operation summaries to concise names like 'text-to-image', ensuring MCP tool names are short and valid.
    summaries = ["A fast text-to-image model that makes high-quality images in 4 steps", "Finding the best route and get multiple stops driving directions", "Finding the best route between an origin and a destination", "Calculate distances and durations between a set of origins and destinations."]
    shortened_summaries = ["text-to-image", "best route for multiple stops", "best route bw start and stop", "distance and duration bw starts and stops"]
    if current_summary in summaries:
        index = summaries.index(current_summary)
        current_summary = shortened_summaries[index]
        print(current_summary)
        return current_summary
  • Example in LLM-based summary shortener referencing the same text-to-image model description used for tool naming.
    Bad example: 'iCanSee' for 'A fast text-to-image model that makes high-quality images in 4 steps'

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/Noveum/api-market-mcp-server'

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