Summary
Four tools returned by tools/list at https://stitch.googleapis.com/mcp carry an outputSchema with a $ref that MCP clients cannot dereference. One is a dangling reference; three are self-recursive. Clients that eagerly resolve $ref when registering tools reject the entire tool list, so the server connects successfully and then exposes zero tools.
Filing here as the public repo for Stitch's API surface — the defect is in the schemas the hosted MCP server emits, not in the SDK code itself.
Affected tools
Captured from a live tools/list (15 tools total):
1. upload_design_md — dangling reference
Its outputSchema is the ScreenInstance object inlined at the root, but it retains a self-reference with no $defs block present to resolve it:
outputSchema.$defs → absent
outputSchema./properties/variantScreenInstance/$ref → "#/$defs/ScreenInstance"
2. create_project, get_project, list_projects — recursive reference
Here ScreenInstance is defined under $defs, but it refers to itself:
outputSchema./$defs/ScreenInstance/properties/variantScreenInstance/$ref → "#/$defs/ScreenInstance"
list_projects additionally reaches it via /$defs/Project/properties/screenInstances/items.
The remaining 11 tools have schemas that resolve cleanly.
Impact
In Claude Code the server reports:
stitch: https://stitch.googleapis.com/mcp (HTTP) - ! Connected · tools fetch failed —
can't resolve reference #/$defs/ScreenInstance from id #
Authentication and tool calls work fine — the failure is purely schema registration — but because a single unloadable schema aborts the whole fetch, all 15 tools become unavailable and the integration is unusable as documented.
Corresponding client-side reports: anthropics/claude-code#76040 and anthropics/claude-code#81111 (both open, reproducing on current releases).
Reproduction
curl -s -X POST https://stitch.googleapis.com/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-H "X-Goog-Api-Key: $STITCH_API_KEY" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' \
| python3 -c '
import json,sys
def refs(n,a=[]):
if isinstance(n,dict):
if isinstance(n.get("$ref"),str): a.append(n["$ref"])
for v in n.values(): refs(v,a)
elif isinstance(n,list):
for v in n: refs(v,a)
return a
def resolve(root,ref):
cur=root
for p in ref[2:].split("/"):
if isinstance(cur,dict) and p in cur: cur=cur[p]
else: return None
return cur
for t in json.load(sys.stdin)["result"]["tools"]:
s=t.get("outputSchema")
if not s: continue
bad=[r for r in refs(s,[]) if resolve(s,r) is None]
rec=[r for r in refs(s,[]) if r.endswith("ScreenInstance")
and resolve(s,r) is not None and r in refs(resolve(s,r),[])]
if bad or rec: print(t["name"], "dangling:", set(bad), "recursive:", set(rec))
'
Suggested fix
- For
upload_design_md, emit the $defs block alongside the inlined root schema (or drop the variantScreenInstance property from that response schema if it is not actually returned).
- For the recursive
ScreenInstance, the cleanest option is to break the cycle in the generated schema — omit variantScreenInstance, or bound it to one level of nesting — since a self-referential $defs entry is legal JSON Schema but not universally consumable by MCP clients.
Clients arguably should tolerate a recursive $ref, and that is being tracked separately upstream. The dangling reference in upload_design_md is unambiguously a server-side bug either way.
Workaround
For anyone blocked today: put a stdio shim in front of the endpoint that forwards everything untouched and strips any outputSchema containing an unresolvable or cyclic $ref. outputSchema is optional and advisory in MCP, so all 15 tools stay callable and results are unaffected.
Summary
Four tools returned by
tools/listathttps://stitch.googleapis.com/mcpcarry anoutputSchemawith a$refthat MCP clients cannot dereference. One is a dangling reference; three are self-recursive. Clients that eagerly resolve$refwhen registering tools reject the entire tool list, so the server connects successfully and then exposes zero tools.Filing here as the public repo for Stitch's API surface — the defect is in the schemas the hosted MCP server emits, not in the SDK code itself.
Affected tools
Captured from a live
tools/list(15 tools total):1.
upload_design_md— dangling referenceIts
outputSchemais theScreenInstanceobject inlined at the root, but it retains a self-reference with no$defsblock present to resolve it:2.
create_project,get_project,list_projects— recursive referenceHere
ScreenInstanceis defined under$defs, but it refers to itself:list_projectsadditionally reaches it via/$defs/Project/properties/screenInstances/items.The remaining 11 tools have schemas that resolve cleanly.
Impact
In Claude Code the server reports:
Authentication and tool calls work fine — the failure is purely schema registration — but because a single unloadable schema aborts the whole fetch, all 15 tools become unavailable and the integration is unusable as documented.
Corresponding client-side reports: anthropics/claude-code#76040 and anthropics/claude-code#81111 (both open, reproducing on current releases).
Reproduction
Suggested fix
upload_design_md, emit the$defsblock alongside the inlined root schema (or drop thevariantScreenInstanceproperty from that response schema if it is not actually returned).ScreenInstance, the cleanest option is to break the cycle in the generated schema — omitvariantScreenInstance, or bound it to one level of nesting — since a self-referential$defsentry is legal JSON Schema but not universally consumable by MCP clients.Clients arguably should tolerate a recursive
$ref, and that is being tracked separately upstream. The dangling reference inupload_design_mdis unambiguously a server-side bug either way.Workaround
For anyone blocked today: put a stdio shim in front of the endpoint that forwards everything untouched and strips any
outputSchemacontaining an unresolvable or cyclic$ref.outputSchemais optional and advisory in MCP, so all 15 tools stay callable and results are unaffected.