From 16841ad09842927bbff7cdb8d5b219c3addaf817 Mon Sep 17 00:00:00 2001 From: zgaetano Date: Tue, 31 Mar 2026 15:29:27 -0400 Subject: [PATCH] Add mcp-gateway/OPENUI_SCHEMA_FIX.md --- mcp-gateway/OPENUI_SCHEMA_FIX.md | 164 +++++++++++++++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 mcp-gateway/OPENUI_SCHEMA_FIX.md diff --git a/mcp-gateway/OPENUI_SCHEMA_FIX.md b/mcp-gateway/OPENUI_SCHEMA_FIX.md new file mode 100644 index 0000000..1b69e90 --- /dev/null +++ b/mcp-gateway/OPENUI_SCHEMA_FIX.md @@ -0,0 +1,164 @@ +# 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): + +```python +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): + +```python +# 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) +```json +{ + "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) +```json +{ + "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 + +```bash +# 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)