From 9519cbe609cdc45a6d57af913788e727a3a267d4 Mon Sep 17 00:00:00 2001 From: Nic O'Connor Date: Sat, 12 Sep 2026 00:18:30 -0400 Subject: [PATCH] mcp-config: request /v1/model/info, so a versioned-route grant actually works MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A virtual key's allowed_routes is matched on the exact path: granting "/v1/model/info" does not also grant "/model/info". MCP_SYNC_GATEWAY has no /v1 suffix, so this asked for the UNVERSIONED path — meaning a key scoped to the versioned route still got a 403, still fell back to names-only, and still produced a config with no context limits, with nothing in the output to say so. Two correct-looking pieces of config that did not meet. Tries the versioned path first and falls back to the unversioned one, so it works whichever way a key happens to be scoped. With the route granted this now discovers limits live instead of leaning on the base-config floor. The floor stays: it is what keeps opencode correct if the key ever loses the route again, and live values override it field by field. Verified that the two agree — discovery returns exactly the 195584 / 261120 the floor declares — and the Claude models, which the floor does not cover, picked up 998976 and 198976 for the first time. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01FoDK4wwB1Twty5gwiriYLf --- mcp-config/sync.sh | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/mcp-config/sync.sh b/mcp-config/sync.sh index d405838..50100e3 100644 --- a/mcp-config/sync.sh +++ b/mcp-config/sync.sh @@ -212,10 +212,21 @@ _mcp_sync_refresh() { # context limit, and won't know a model can call tools). /model/info has # them. Best-effort: a key still scoped to llm_api_routes 403s here, and # we fall back to names-only, exactly as before. + # VERSIONED PATH FIRST. LiteLLM serves this metadata at both /model/info and + # /v1/model/info, but a virtual key's allowed_routes is matched on the exact + # path — granting "/v1/model/info" does NOT also grant "/model/info". Since + # MCP_SYNC_GATEWAY has no /v1 suffix, the unversioned path is what this used + # to request, so a key scoped to the versioned route still got a 403 and + # still silently fell back to names-only. Try both, versioned first, so it + # works whichever way the key is scoped. _info="" if [ -n "${LITELLM_KEY:-}" ]; then - _info="$(curl -fsS -m 8 -H "Authorization: Bearer $LITELLM_KEY" \ - "$MCP_SYNC_GATEWAY/model/info" 2>/dev/null)" || _info="" + for _mi_path in /v1/model/info /model/info; do + _info="$(curl -fsS -m 8 -H "Authorization: Bearer $LITELLM_KEY" \ + "$MCP_SYNC_GATEWAY$_mi_path" 2>/dev/null)" || _info="" + [ -n "$_info" ] && break + done + unset _mi_path fi # 3. Merge and deploy. python3 validates the base (don't clobber good config