The utility is here to convert existing OpenAPI in bulk to MCP Server

ChengTan & Wang Chen

|

Apr 10, 2025

|

Share on X

Convert existing OpenAPI into MCP Server in batches. This is the latest open-source capability from Higress, helping developers efficiently build MCP Server. [1]


Table of Contents

01. Relevant Concepts of OpenAPI

02. Common Practices for Converting Existing OpenAPI into MCP Server

03. Batch Conversion of OpenAPI to MCP Server

04. Tuning Configuration for MCP Server

05. Conclusion


01 Relevant Concepts of OpenAPI

OpenAPI is written in YAML or JSON and defines a language-agnostic HTTP API interface, providing a unified way to transmit information across all stages of the API life cycle. APIs allow developers to discover and use corresponding services without having to access the source code. For example, a social app wanting to obtain the geographical location information of both parties does not need to build its own Gaode Map or obtain its source code, but can instead receive geographical location information functionality through the Gaode Map API interface.

Classic internet applications such as Gaode Map and Alipay provide API services externally through an open platform. Public cloud services, such as Alibaba Cloud, offer API services to users through OpenAPI Explorer, allowing developers to manage cloud resources, data, and services through these APIs. Additionally, AI large models such as Tongyi, DeepSeek, and OpenAI offer access to large models via APIs. These APIs all comply with the OpenAPI specification; having standards enables efficient collaboration.


02 Common Practices for Converting Existing OpenAPI into MCP Server

MCP allows LLM to access external resources, data, and services in a standardized way. Converting existing OpenAPI into MCP Server is a useful reuse strategy and an economically efficient path that aims to enable external AI applications to invoke your services, thereby enhancing the value of existing services. For instance, Gaode Map provides the capability to convert existing OpenAPI services such as IP positioning and geocoding into MCP Server, allowing external applications to utilize Gaode Map capabilities, thus increasing service activity.

Although MCP has significantly reduced the complexity of accessing and invoking external resources, data, and services for large model applications, if you adopt reuse of existing infrastructure as a development strategy for MCP, you will face a new challenge: converting existing OpenAPI into MCP Server is a "repetitive manual task" that requires daily maintenance, including interface updates and server stability assurances. MCP provides SDK toolkits such as TypeScript and Java for developing MCP Server, exposing existing OpenAPI as regular HTTP services through MCP protocol. This process includes: [1]

  • Reading and parsing the existing OpenAPI documents, extracting key information such as API paths, request methods, request parameters, response formats, etc.

  • Transforming into new descriptions according to MCP protocol specifications, including tool functionality description and tool parameter description, returning the tool/list results to the client.

  • When the MCP client wants to call the MCP server, it parses the Json RPC request from tool/call, generates the backend HTTP call request using the mapped parameter configuration, Path, backend address, etc., and executes the call. After the call is completed, it wraps the backend call result to return the result for the standard tool/call interface.


03 Batch Conversion of OpenAPI to MCP Server

1.1 Installation

go install github.com/higress-group/openapi-to-mcpserver/cmd/openapi-to-mcp

1.2 Usage

openapi-to-mcp --input path/to/openapi.json --output path/to/mcp-config.yaml

Instructions

  • --input: The path to the OpenAPI specification file (in JSON or YAML format), required.

  • --output: The path for the output MCP configuration file (in YAML format), required.

  • --server-name: The name of the MCP server, default value is "openapi-server".

  • --tool-prefix: The prefix for tool names, default value is empty.

  • --format: Output format (yaml or json), default value is "yaml".

  • --validate: Whether to validate the OpenAPI specification, default value is false.

  • --template: The path to the template file used for fixing the output, default value is empty.

1.3 Example

openapi-to-mcp --input petstore.json --output petstore-mcp.yaml --server-name petstore

This example converts petstore.json into the petstore-mcp.yaml file and sets the MCP server name to petstore.

Here is the complete example.

a. Start with an OpenAPI specification (petstore.json):

{
  "openapi": "3.0.0",
  "info": {
    "version": "1.0.0",
    "title": "Swagger Petstore",
    "description": "A sample API that uses a petstore as an example to demonstrate features in the OpenAPI 3.0 specification"
  },
  "servers": [
    {
      "url": "http://petstore.swagger.io/v1"
    }
  ],
  "paths": {
    "/pets": {
      "get": {
        "summary": "List all pets",
        "operationId": "listPets",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "How many items to return at one time (max 100)",
            "required": false,
            "schema": {
              "type": "integer",
              "format": "int32"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A paged array of pets",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "pets": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "id": {
                            "type": "integer",
                            "description": "Unique identifier for the pet"
                          },
                          "name": {
                            "type": "string",
                            "description": "Name of the pet"
                          },
                          "tag": {
                            "type": "string",
                            "description": "Tag of the pet"
                          }
                        }
                      }
                    },
                    "nextPage": {
                      "type": "string",
                      "description": "URL to get the next page of pets"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "post": {
        "summary": "Create a pet",
        "operationId": "createPets",
        "requestBody": {
          "description": "Pet to add to the store",
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": ["name"],
                "properties": {
                  "name": {
                    "type": "string",
                    "description": "Name of the pet"
                  },
                  "tag": {
                    "type": "string",
                    "description": "Tag of the pet"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Null response"
          }
        }
      }
    },
    "/pets/{petId}": {
      "get": {
        "summary": "Info for a specific pet",
        "operationId": "showPetById",
        "parameters": [
          {
            "name": "petId",
            "in": "path",
            "required": true,
            "description": "The id of the pet to retrieve",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Expected response to a valid request",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "integer",
                      "description": "Unique identifier for the pet"
                    },
                    "name": {
                      "type": "string",
                      "description": "Name of the pet"
                    },
                    "tag": {
                      "type": "string",
                      "description": "Tag of the pet"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

b. Convert it into Higress REST-to-MCP configuration:

openapi-to-mcp --input petstore.json --output petstore-mcp.yaml --server-name petstore

c. Generate petstore-mcp.yaml file:

server:
  name: petstore
tools:
  - name: showPetById
    description: Info for a specific pet
    args:
      - name: petId
        description: The id of the pet to retrieve
        type: string
        required: true
        position: path
    requestTemplate:
      url: /pets/{petId}
      method: GET
    responseTemplate:
      prependBody: |
        # API Response Information

        Below is the response from an API call. To help you understand the data, I've provided:

        1. A detailed description of all fields in the response structure
        2. The complete API response

        ## Response Structure

        > Content-Type: application/json

        - **id**: Unique identifier for the pet (Type: integer)
        - **name**: Name of the pet (Type: string)
        - **tag**: Tag of the pet (Type: string)

        ## Original Response

  - name: createPets
    description: Create a pet
    args:
      - name: name
        description: Name of the pet
        type: string
        required: true
        position: body
      - name: tag
        description: Tag of the pet
        type: string
        position: body
    requestTemplate:
      url: /pets
      method: POST
      headers:
        - key: Content-Type
          value: application/json
    responseTemplate: {}

  - name: listPets
    description: List all pets
    args:
      - name: limit
        description: How many items to return at one time (max 100)
        type: integer
        position: query
    requestTemplate:
      url: /pets
      method: GET
    responseTemplate:
      prependBody: |
        # API Response Information

        Below is the response from an API call. To help you understand the data, I've provided:

        1. A detailed description of all fields in the response structure
        2. The complete API response

        ## Response Structure

        > Content-Type: application/json

        - **pets**:  (Type: array)
          - **pets[].id**: Unique identifier for the pet (Type: integer)
          - **pets[].name**: Name of the pet (Type: string)
          - **pets[].tag**: Tag of the pet (Type: string)
        - **nextPage**: URL to get the next page of pets (Type: string)

        ## Original Response

Note that the tool will automatically set the position field based on the location of each parameter in the OpenAPI specification:

  • The petId parameter is set to position: path, as it is defined as in: path in the OpenAPI specification.

  • The limit parameter is set to position: query, as it is defined as in: query in the OpenAPI specification.

  • The request body properties (name and tag) are set to position: body.

The MCP server will automatically handle these parameters in the correct position when initiating API requests. For more information on how to use this configuration with Higress REST-to-MCP, please refer to the Higress REST-to-MCP documentation. [2]

1.4 Functionality

  • Convert OpenAPI paths to MCP tools.

  • Support OpenAPI specifications in JSON and YAML formats.

  • Generate MCP configuration containing server and tool definitions.

  • Preserve parameter descriptions and types.

  • Automatically set parameter positions based on OpenAPI parameter positions (path, query, header, cookie, request body).

  • Handle path, query, header, cookie, and request body parameters.

  • Generate response templates with field descriptions and improved formats for better understanding by large language models (LLMs).

  • Optional validation of the OpenAPI specification (disabled by default).

1.4 Configure MCP Server Plugin

Next, we will import the generated file into the Higress console, add the MCP Server plugin, and configure it for use together with Higress.

Example of plugin configuration:

server:
  name: "random-user-server"
tools:
- description: "Get random user information"
  name: "get-user"
  requestTemplate:
    method: "GET"
    url: "https://randomuser.me/api/"
  responseTemplate:
    body: |-
      # User Information
      {{- with (index .results 0) }}
      - **Name**: {{.name.first}} {{.name.last}}
      - **Email**: {{.email}}
      - **Location**: {{.location.city}}, {{.location.country}}
      - **Phone**: {{.phone}}
      {{- end }}

Note: For the MCP streamable HTTP protocol dated 2025-03-26, this plugin can be used directly without global ConfigMap configuration.

1.5 Calling MCP Server

Configure the SSE connection for MCP Server in the AI Agent, taking Cursor as an example:

  • Database-type MCP Server: Use path + sse_path_suffix configured in ConfigMap

  • REST API-type MCP Server: Use routing path + sse_path_suffix configured in the console

"mcpServers": {
  "postgres": {
    "url": "http://your-higress-address/postgres/sse"
  },
  "rest-api": {
    "url": "http://your-higress-address/user/sse"
  }

Configuration completed in Cursor:

Through the MCP Server, you can quickly add various data source support for AI agents, improving development efficiency. Any REST API can be transformed into MCP Server with simple configuration without writing additional code.

04 Tuning Configuration for MCP Server

In the previous chapters, we have learned how the OpenAPI to MCP tool helps us quickly convert existing APIs into tools that can be invoked by AI assistants. This automated conversion greatly improves development efficiency, allowing us to accomplish what would originally take hours or even days in just a few minutes.

However, although the automatically generated configuration is functionally complete, it is often not precise enough. Particularly when APIs return complex data structures, if the configuration is not manually tuned, it may lead to large language models (LLMs) not accurately understanding the data, thus affecting user experience.

4.1 Why Tune MCP Configurations?

Automatically generated MCP configurations usually include all fields returned by APIs and present them in a flat manner. This may be sufficient for simple APIs, but for complex APIs that return a large amount of nested data, it brings several issues:

  1. Information Overload: LLM's context window is limited, and excessive irrelevant information dilutes important content.

  2. Lack of Structure: Complex nested relationships are easily lost in flat descriptions.

  3. Lack of Semantics: Technical codes and specialized terms remain unconverted, making it difficult for LLM to understand correctly.

  4. Hallucination Risk: Faced with unfamiliar data structures, LLM might make incorrect inferences.

By manually tuning MCP configurations, we can significantly enhance LLM's understanding of the data returned by APIs, reducing misinterpretations and hallucinations, thereby providing users with more accurate and valuable responses.

4.2 Tuning Case Study: E-commerce Product Search API

Let’s illustrate the importance of MCP configuration tuning through a specific case. Suppose we have a product search API from an e-commerce platform, which returns complex product information laden with technical details.

4.2.1 Automatically Generated Basic Configuration

The configuration automatically generated using the OpenAPI to MCP tool might look like this:

server:
  name: ecommerce-api
tools:
  - name: searchProducts
    description: "Search for products in the e-commerce platform"
    args:
      - name: query
        description: "Search query string"
        type: string
        required: true
      - name: category
        description: "Product category"
        type: string
        required: false
      - name: limit
        description: "Maximum number of results to return"
        type: integer
        default: 10
    requestTemplate:
      url: "https://api.example.com/products/search"
      method: GET
      argsToUrlParam: true
    responseTemplate:
      prependBody: |
        # Search Results
        
        Below is the API response with these fields:
        
        - **success**: Boolean indicating if the request was successful
        - **total**: Total number of matching products
        - **page**: Current page number
        - **pageSize**: Number of items per page
        - **products**: Array of product objects with the following fields:
          - **id**: Product unique identifier
          - **name**: Product name
          - **description**: Product description 
          - **price**: Product price
          - **compareAtPrice**: Original price before discount
          - **currency**: Currency code (e.g., USD, EUR)
          - **availability**: Product availability status
          - **metadata**: Technical metadata
          - **attributes**: Product attributes
          - **variants**: Product variations
          - **images**: Product images
          - **categories**: Categories the product belongs to
          - **tags**: Product tags
          - **brand**: Product brand information
          - **shipping**: Shipping information
          - **ratings**: Product ratings and reviews
        
        Original response:

When LLM receives API responses under this configuration, it will face the following challenges:

  1. Data Structure Confusion: Unable to clearly understand the internal structure of nested objects (e.g., metadata, attributes).

  2. Ambiguous Field Meaning: Uncertain about the possible values and meanings of the "availability" field.

  3. Unclear Information Priority: Difficult to determine which information is most important to users.

  4. Context Window Occupation: Large amounts of raw JSON occupy LLM's context window, crowding out other important information.

These problems might lead LLM to misinterpret various aspects:

  • Confusing product main body with variant information: “This watch comes in black, silver, and rose gold at prices of 899 yuan, 899 yuan, and 949 yuan respectively.” (Mistaking variant information as main information)

  • Incorrectly linking technical details: “The warranty period for this TechFit Pro smart watch is TF-SW-P10.” (Confusing SKU with the warranty period)

  • Generating hallucinations based on incomplete information: “This watch is available in all electronic shops.” (Incorrect inference based on shipping.locations)

4.2.2 Manually Tuned Configuration

Higress supports fine-tuning request and response templates by combining go template and gjson expressions (for detailed capabilities, please refer to the documentation: https://higress.cn/en/ai/mcp-server), through careful tuning, we can optimize the configuration as follows:

server:
  name: ecommerce-api
tools:
  - name: searchProducts
    description: "搜索电商平台上的产品,返回匹配搜索条件的产品列表,包含产品基本信息、价格、库存状态、评分等"
    args:
      - name: query
        description: "搜索关键词,可以是产品名称、品牌、型号或描述中的关键词"
        type: string
        required: true
      - name: category
        description: "产品类别,例如'electronics'、'clothing'、'home'等"
        type: string
        required: false
      - name: limit
        description: "返回结果数量,范围1-50"
        type: integer
        minimum: 1
        maximum: 50
        default: 10
    requestTemplate:
      url: "https://api.example.com/products/search"
      method: GET
      argsToUrlParam: true
    responseTemplate:
      body: |
        # 产品搜索结果

        找到 {{.total}} 个匹配"{{.query}}"的产品,以下是最相关的 {{len .products}} 个结果:

        {{range $index, $product := .products}}
        ## {{add $index 1}}. {{$product.name}}

        **价格**: {{if $product.onSale}}~~{{$product.compareAtPrice}} {{$product.currency}}~~ **{{$product.price}} {{$product.currency}}** (节省 {{percentage $product.compareAtPrice $product.price}}%){{else}}{{$product.price}} {{$product.currency}}{{end}}

        **品牌**: {{$product.brand.name}}

        **库存状态**: {{if eq $product.availability "in_stock"}}有货{{else if eq $product.availability "low_stock"}}库存不多{{else}}缺货{{end}}

        {{if gt (len $product.ratings.reviews) 0}}**评分**: {{$product.ratings.averageRating}}/5 ({{$product.ratings.reviewCount}}条评价){{end}}

        {{$product.description | truncate 200 "..."}}

        {{if gt (len $product.highlights) 0}}**产品特点**:
        {{range $highlight := $product.highlights}}
        - {{$highlight}}
        {{end}}{{end}}

        {{end}}

        {{if gt .total (len .products)}}
        还有更多结果未显示,可以通过调整搜索条件获取更精准的匹配。
        {{end}}

Here is a real response example for a smart watch product showcasing how the tuned template handles raw data:

# 产品搜索结果

找到 128 个匹配"智能手表"的产品,以下是最相关的 10 个结果:

## 1. TechFit Pro 智能手表

**价格**: ~~1299 CNY~~ **899 CNY** (节省 30.8%)

**品牌**: TechFit

**库存状态**: 有货

**评分**: 4.7/5 (342条评价)

TechFit Pro智能手表配备高清彩色触摸屏,支持心率监测、血氧检测、多种运动模式追踪和睡眠分析。防水设计,续航可达7天。

**产品特点**:
- 高清AMOLED触摸屏
- 7天超长续航
- 心率和血氧监测
- 30种运动模式
- 5ATM防水

## 2. FitBit Versa 3

**价格**: 1499 CNY

**品牌**: FitBit

**库存状态**: 有货

**评分**: 4.5/5 (287条评价)

FitBit Versa 3智能手表集成GPS定位,支持24/7心率监测,内置语音助手,可接听电话,电池续航可达6天。

**产品特点**:
- 内置GPS
- 语音助手功能
- 来电接听
- 20+运动模式
- 防水50米

## 3. Apple Watch Series 7

**价格**: 2999 CNY

**品牌**: Apple

**库存状态**: 库存不多

**评分**: 4.9/5 (1243条评价)

Apple Watch Series 7拥有更大的显示屏,更快的充电速度,IP6X防尘认证,游泳级防水,全天候血氧监测和心电图功能。

**产品特点**:
- 视网膜级OLED显示屏
- 快速充电
- 心电图和血氧监测
- 跌倒检测和紧急SOS
- 支持Apple Pay

还有更多结果未显示,可以通过调整搜索条件获取更精准的匹配。

With this structured response format, LLM can clearly identify each product's key information without being overwhelmed by excessive technical details and raw JSON structures.

4.3 How Tuning Improves LLM Understanding

Tuned configurations can significantly enhance LLM's data understanding:

4.3.1 Understanding Issues Before Tuning

  1. Structural Confusion: Unable to distinguish main products from variants, potentially mislabeling variant attributes as main features.

  2. Incorrect Focus: May overemphasize details (like SKU, barcode) rather than product features that interest users.

  3. Misinterpreting Field Meaning: Cannot accurately grasp specialized terminology and encoded values.

  4. Generating Hallucinations: Influenced by irrelevant content in, for example, product details, leading to hallucinations.

4.3.2 Improved Understanding After Tuning

  1. Clear Structure: Accurately understands each product's basic information, price, brand, stock status, and rating.

  2. Highlighted Key Information: Can identify key information such as price discounts and product descriptions and features.

  3. Clear Semantics: Correctly interprets the meaning of stock status without ambiguity.

  4. Complete Context: Grasp the full picture of search results (“Found 128 matching items, showing 10”).

4.4 Summary of Tuning Strategies

Based on the above case, we can extract the following MCP configuration tuning strategies:

  1. Identify and extract core fields: Analyze the information users truly need, removing technical details and internal data.

  2. Transform specialized terminology: Convert technical codes and specialized terms into descriptions that are easier for LLMs to comprehend.

  3. Add contextual information: Help LLM understand the integrity and scope of the data.

  4. Structure key information: Use hierarchies to make the importance and relationships of the information clear.

05 Conclusion

The OpenAPI to MCP tool provides us with the ability to quickly convert APIs into AI tools, while manual tuning is a crucial step in enhancing AI understanding and user experience. Through carefully designed response templates, we can guide LLM to more accurately understand the data returned by APIs, reducing misinterpretation and hallucinations, thereby offering users more valuable services.

In practical applications, it is recommended to first use the OpenAPI to MCP tool to generate the basic configuration and then tune it based on the complexity of the API and user needs. For simple APIs, the automatically generated configuration may already be sufficient; however, for complex APIs, particularly those that return large amounts of nested data, manual tuning will significantly enhance the experience.

It should be emphasized that high-quality MCP configuration tuning often relies on data feedback and iterative optimization. A single configuration is unlikely to meet all user scenarios at once, thus requiring a gray testing approach based on multiple configuration versions to create a feedback loop for evaluation and continuous improvement. Higress will combine with the powerful capabilities of the Nacos configuration center to provide more refined configuration management features for MCP server maintainers, including version control, gray publishing, configuration rollback, and effect analysis, making configuration tuning a continuous optimization process driven by data rather than a one-off task.

Through a complete chain of "automatic conversion + manual tuning + data feedback," we can enjoy the efficiency gains brought by automation while ensuring that AI assistants deliver a high-quality user experience, concurrently optimizing configurations based on actual usage data, so that the capabilities of AI assistants continually evolve with use.

Preview: Higress will launch the first MCP Marketplace based on API gateway in the country, including 50 meticulously tuned MCP services.

[1] https://github.com/higress-group/openapi-to-mcpserver

[2] https://mp.weixin.qq.com/s/bgDd82lj0jBUWifLMNByjw

[3] https://higress.cn/en/ai/mcp-quick-start/#configuring-rest-api-mcp-server

[4] https://mp.weixin.qq.com/s/WYlqHm2YZSiRv4USUNUBgg

Contact

Follow and engage with us through the following channels to stay updated on the latest developments from higress.ai.

Contact

Follow and engage with us through the following channels to stay updated on the latest developments from higress.ai.

Contact

Follow and engage with us through the following channels to stay updated on the latest developments from higress.ai.

Contact

Follow and engage with us through the following channels to stay updated on the latest developments from higress.ai.