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
-
Missing OpenAI-compatible endpoints — Gateway only exposes MCP protocol (
/mcp), not OpenAI API endpoints (/v1/tools,/v1/models,/v1/chat/completions) -
Complex JSON schemas break OpenUI parsing — MCP tool schemas use features OpenAI API doesn't support:
typeas array:["string", "null"]instead of single typeanyOf/oneOfwith mixed content- Tuple validation with
itemsas array - Tool names getting truncated due to improper escaping
-
No schema normalization — While
gateway_proxy.pyhas_normalize_schema()for MCP protocol, the OpenAI adapter doesn't simplify schemas properly for OpenUI -
Missing
/v1/toolsendpoint — 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 formatconvert_mcp_tool_to_openai()— Properly maps MCP tool definitions to OpenAI function schema/v1/toolsendpoint — 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.pytogateway-proxy/ - Update
gateway_proxy.pywith import and routes (see Step 2 above) - Restart gateway container:
docker-compose restart gateway-proxy
Phase 2: Verify
- Test
/v1/modelsendpoint returns valid OpenAI model list - Test
/v1/toolsendpoint 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
- Check that
openai_routes_fixed.pyis in the correct directory - Verify import statement was added to
gateway_proxy.py - Check for import errors in gateway logs
- Ensure routes were added before the closing
]bracket
Tools loading but parameters wrong
- Check that
_simplify_schema()is being called - Verify property names aren't being corrupted
- Test individual tool schema with
jqto inspect conversion
OpenUI still showing errors
- Verify
/v1/toolsreturns valid JSON (usejqto validate) - Check browser console for actual error messages
- Ensure no truncation of tool names in the response
Additional Notes
- The
lambda r: tools(r, TOOL_DEFINITIONS)syntax is required becauseTOOL_DEFINITIONSis 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)