apache/shenyu · error · IllegalArgumentException

OpenAPI document is missing the top-level 'servers' field…

Error message

OpenAPI document is missing the top-level 'servers' field, which is required for MCP import. Please add a servers section, e.g.: servers: [{ url: 'http://localhost:8080' }]

What it means

buildMetaDataRegisterDTO() throws IllegalArgumentException when the parsed OpenAPI document has no top-level 'servers' array (or it is empty). The servers field supplies the base URL used to build MCP tool metadata; without it the gateway cannot construct the upstream target. The message includes an example servers section to guide the user.

Solutions

  1. Add a top-level servers array to the OpenAPI document, e.g. servers: [{url: 'http://localhost:8080'}], with the real backend address.
  2. Regenerate/export the spec from the source tool with server information included.
  3. If migrating from Swagger 2.0, convert host/basePath into an OpenAPI 3.0 servers entry.

Example fix

// before (openapi.json)
{
  "openapi": "3.0.1",
  "info": { "title": "api", "version": "1.0" }
}
// after
{
  "openapi": "3.0.1",
  "info": { "title": "api", "version": "1.0" },
  "servers": [{ "url": "http://localhost:8080" }]
}
Defensive patterns

Strategy: validation

Validate before calling

JsonElement root = JsonParser.parseString(swaggerJson).getAsJsonObject();
if (!root.has("servers") || !root.getAsJsonArray("servers").iterator().hasNext()) {
    throw new IllegalArgumentException("openapi doc needs servers: [{url: ...}] before MCP import");
}

Type guard

boolean hasServers(OpenAPI api) {
    return api != null && api.getServers() != null && !api.getServers().isEmpty()
        && api.getServers().get(0).getUrl() != null && !api.getServers().get(0).getUrl().isBlank();
}

Try / catch

try {
    service.importMcpConfig(request);
} catch (IllegalArgumentException e) {
    return ResponseEntity.badRequest().body("Fix your OpenAPI doc: " + e.getMessage());
}

Prevention

When it happens

Trigger: Importing an MCP config whose swagger/OpenAPI JSON lacks `servers: [{url: ...}]` at the document root — the code checks openapi.getServers() for null/empty before reading servers.get(0).getUrl().

Common situations: OpenAPI documents generated for documentation only (no server info); swagger files copied from specs where servers were stripped; specs using relative server URLs or relying on host/basePath from Swagger 2.0 instead of OpenAPI 3.0 servers.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of apache/shenyu@567142e072 (2026-09-12). Data as JSON: /api/errors/aa89541f1f399fb6. Report an issue: GitHub.

Appendix: source

Thrown at shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SwaggerImportServiceImpl.java:215

                shenyuMcpRequestConfig.setBodyToJson("false");
                tool.setRequestConfig(shenyuMcpRequestConfig);
                tool.setToolName(operation.getOperationId());
                tool.setEnable(true);
                PathItem.HttpMethod httpMethod = opEntry.getKey();
                tool.setMethod(httpMethod.name().toLowerCase());

                toolMap.put(fullPath, tool);
            }
            maps.add(toolMap);
        }
        return result;
    }

    private MetaDataRegisterDTO buildMetaDataRegisterDTO(final OpenAPI openapi, final String selectorName,
                                                         final ShenyuMcpTool shenyuMcpTool, final String contentPath,
                                                         final String namespaceId) {
        if (Objects.isNull(openapi.getServers()) || openapi.getServers().isEmpty()) {
            throw new IllegalArgumentException("OpenAPI document is missing the top-level 'servers' field, which is required for MCP import. "
                + "Please add a servers section, e.g.: servers: [{ url: 'http://localhost:8080' }]");
        }
        String urlString = openapi.getServers().get(0).getUrl();
        URL url;
        try {
            url = new URL(urlString);
        } catch (MalformedURLException e) {
            LOG.error("url error");
            throw new RuntimeException(e);
        }
        String host = url.getHost();
        int port = url.getPort();
        Operation operation = shenyuMcpTool.getOperation();
        String parameterTypes = Objects.isNull(operation.getParameters())
                ? ""
                : operation.getParameters()
                        .stream()
                        .map(Parameter::getIn)

View on GitHub (pinned to 567142e072)