mcp-servers/mcp-gateway/OPENUI_SCHEMA_FIX.md

5.5 KiB

OpenUI Tool Discovery Schema Fix

Problem Analysis

OpenUI fails to load any tools from the MCP Gateway with errors like:

"Email Digest string not found"
"DocType string not found"

Root Causes

  1. Missing OpenAI-compatible endpoints — Gateway only exposes MCP protocol (/mcp), not OpenAI API endpoints (/v1/tools, /v1/models, /v1/chat/completions)

  2. Complex JSON schemas break OpenUI parsing — MCP tool schemas use features OpenAI API doesn't support:

    • type as array: ["string", "null"] instead of single type
    • anyOf / oneOf with mixed content
    • Tuple validation with items as array
    • Tool names getting truncated due to improper escaping
  3. No schema normalization — While gateway_proxy.py has _normalize_schema() for MCP protocol, the OpenAI adapter doesn't simplify schemas properly for OpenUI

  4. Missing /v1/tools endpoint — OpenUI expects a dedicated tools discovery endpoint, not just embedded in /v1/chat/completions

Solution: Schema Conversion & New Endpoints

Step 1: Use Fixed OpenAI Routes Handler

Replace the basic openai_routes.py with openai_routes_fixed.py which includes:

  • _simplify_schema() — Recursively converts complex schemas to OpenAI-compatible format
  • convert_mcp_tool_to_openai() — Properly maps MCP tool definitions to OpenAI function schema
  • /v1/tools endpoint — Dedicated tools discovery (required by OpenUI)
  • Error handling — Gracefully handles malformed tool definitions

Step 2: Update gateway_proxy.py

Add the following import after existing imports (around line 27):

from .openai_routes_fixed import convert_mcp_tool_to_openai, list_models, tools, chat_completions

Add these routes to the routes list (before the closing bracket, around line 820):

# OpenAI-compatible API endpoints (for Open-UI and other OpenAI clients)
Route("/v1/models", list_models, methods=["GET"]),
Route("/v1/tools", lambda r: tools(r, TOOL_DEFINITIONS), methods=["GET"]),
Route("/v1/chat/completions", lambda r: chat_completions(r, TOOL_DEFINITIONS), methods=["POST"]),

Schema Conversion Examples

Before (MCP format - causes errors)

{
  "name": "erpnext_get_document",
  "description": "Retrieve a single document",
  "inputSchema": {
    "type": "object",
    "properties": {
      "doctype": {
        "type": ["string", "null"],
        "description": "DocType name"
      },
      "name": {
        "type": ["string", "null"],
        "description": "Document name"
      }
    },
    "required": ["doctype", "name"]
  }
}

After (OpenAI format - works in OpenUI)

{
  "type": "function",
  "function": {
    "name": "erpnext_get_document",
    "description": "Retrieve a single document",
    "parameters": {
      "type": "object",
      "properties": {
        "doctype": {
          "type": "string",
          "description": "DocType name"
        },
        "name": {
          "type": "string",
          "description": "Document name"
        }
      },
      "required": ["doctype", "name"]
    }
  }
}

Implementation Checklist

Phase 1: Apply Fixes

  • Deploy openai_routes_fixed.py to gateway-proxy/
  • Update gateway_proxy.py with import and routes (see Step 2 above)
  • Restart gateway container: docker-compose restart gateway-proxy

Phase 2: Verify

  • Test /v1/models endpoint returns valid OpenAI model list
  • Test /v1/tools endpoint returns tools with proper OpenAI schema
  • Verify no truncated tool names in response
  • Check gateway logs for errors: docker logs mcp-gateway

Phase 3: Test in OpenUI

  • Add gateway URL to OpenUI: http://mcp.wilddragon.net:8000
  • Verify tools appear in model selector
  • Try searching for tools by name
  • Call a tool to verify end-to-end functionality

Files Involved

File Purpose Status
gateway-proxy/openai_routes_fixed.py Fixed OpenAI schema conversion Created
gateway-proxy/gateway_proxy.py Main gateway with route definitions Needs updates
openai_adapter.py (Can be removed - superseded by openai_routes_fixed.py) Optional

Testing Commands

# Test tool discovery
curl http://localhost:8000/v1/tools

# Test models endpoint
curl http://localhost:8000/v1/models

# Check specific tool schema (example)
curl http://localhost:8000/v1/tools | jq '.data[] | select(.function.name == "erpnext_get_document")'

Troubleshooting

Tools still not loading

  1. Check that openai_routes_fixed.py is in the correct directory
  2. Verify import statement was added to gateway_proxy.py
  3. Check for import errors in gateway logs
  4. Ensure routes were added before the closing ] bracket

Tools loading but parameters wrong

  1. Check that _simplify_schema() is being called
  2. Verify property names aren't being corrupted
  3. Test individual tool schema with jq to inspect conversion

OpenUI still showing errors

  1. Verify /v1/tools returns valid JSON (use jq to validate)
  2. Check browser console for actual error messages
  3. Ensure no truncation of tool names in the response

Additional Notes

  • The lambda r: tools(r, TOOL_DEFINITIONS) syntax is required because TOOL_DEFINITIONS is a module-level variable that gets populated during initialization
  • Schema conversion happens at request time, so adding new backends will automatically make their tools available via OpenAI API
  • Error handling is intentionally lenient (malformed tools are skipped rather than failing the whole request)