different-ai/openwork · error
MCP tool catalog response was incomplete.
Error message
MCP tool catalog response was incomplete.
What it means
useMcpConnectionTools inspects an external MCP connection's tool catalog via a 30s requestJson call. Two separate checks throw this same message: (1) payload is not a record or payload.tools is not an array; (2) the parsed policy is null or any entry of payload.tools fails the isExternalMcpTool shape check. It means the server replied ok but the catalog body does not match the expected { tools: [...], policy: {...} } contract.
Source
Thrown at ee/apps/den-web/app/(den)/dashboard/_components/mcp-connections-data.tsx:310
};
}
export function useMcpConnectionTools(connectionId: string, enabled: boolean) {
const { orgId } = useOrgDashboard();
return useQuery({
enabled: enabled && Boolean(orgId),
queryKey: mcpConnectionQueryKeys.tools(orgId, connectionId),
queryFn: async (): Promise<ExternalMcpToolCatalog> => {
const { response, payload } = await requestJson(
`/v1/mcp-connections/${encodeURIComponent(connectionId)}/tools`,
{ headers: getOrgScopeHeaders(requireOrgId(orgId)) },
30000,
);
if (!response.ok) {
throw getRequestError(payload, response, `Failed to inspect MCP tools (${response.status}).`);
}
if (!isRecord(payload) || !Array.isArray(payload.tools)) {
throw new Error("MCP tool catalog response was incomplete.");
}
const policy = parseExternalMcpToolPolicy(payload.policy);
if (!policy || !payload.tools.every(isExternalMcpTool)) {
throw new Error("MCP tool catalog response was incomplete.");
}
return { tools: payload.tools, policy };
},
});
}
export function useUpdateMcpConnectionToolPolicy(connectionId: string) {
const queryClient = useQueryClient();
const { orgId } = useOrgDashboard();
return useMutation({
mutationFn: async (input: Pick<ExternalMcpToolPolicyView, "allDisabled" | "disabledTools">): Promise<ExternalMcpToolPolicyView> => {
const { response, payload } = await requestJson(
`/v1/mcp-connections/${encodeURIComponent(connectionId)}/tool-policy`,
{View on GitHub (pinned to 2b7df46e8a)
Solutions
- Log payload and compare each tool against the isExternalMcpTool required fields
- Upgrade den-api server to match the dashboard's expected catalog schema (or vice versa)
- Check parseExternalMcpToolPolicy against the actual payload.policy shape
- If a single malformed tool is the cause, fix or filter it server-side before returning the catalog
Example fix
// before
if (!policy || !payload.tools.every(isExternalMcpTool)) {
throw new Error("MCP tool catalog response was incomplete.");
}
// after
const badIndex = payload.tools.findIndex((t) => !isExternalMcpTool(t));
if (badIndex >= 0) {
console.warn("Skipping malformed MCP tool at index", badIndex, payload.tools[badIndex]);
}
const tools = payload.tools.filter(isExternalMcpTool);
if (!policy || tools.length === 0) {
throw new Error("MCP tool catalog response was incomplete.");
}
return { tools, policy }; Defensive patterns
Strategy: type-guard
Validate before calling
if (!isRecord(payload) || !Array.isArray(payload.tools)) {
// request a refetch or show a catalog-unavailable state
} Type guard
function isExternalMcpTool(v: unknown): v is ExternalMcpTool {
return isRecord(v) && typeof v.name === "string" && isRecord(v.inputSchema);
} Try / catch
try {
const { tools, policy } = await refetchCatalog();
} catch (err) {
if (err.message === "MCP tool catalog response was incomplete.") {
showCatalogUnavailable(err); // offer retry
}
} Prevention
- Validate one tool at a time and log the offending index instead of failing the whole catalog
- Add contract tests asserting {tools:[],policy:{}} shape on the inspect endpoint
- Keep dashboard and den-api schema versions in lockstep
When it happens
Trigger: POST inspect-tools returns 200 with {tools: '...'} or missing tools; a tool object missing required fields (name/inputSchema etc.) failing isExternalMcpTool; payload.policy absent or unparseable by parseExternalMcpToolPolicy.
Common situations: MCP server exposing tools with non-standard metadata; den-api version older than the dashboard expecting new tool fields; policy feature-flag disabled server-side so 'policy' is omitted from the response.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- invalid_mcp_token_payload
- MCP tool policy response was incomplete.
- MCP tool result was incomplete.
- Create MCP connection response was incomplete.
- invalid_session_payload
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/baddb06cc19d1a72.
Report an issue: GitHub.