Published Sep 17, 20264 min read
MCP Fusion 5.0.10: smaller descriptions, recovered thrown errors
Released September 17, 2026. Two P2 fixes in @mcpfusion/core aimed at the exact surfaces the model touches: grouped descriptions that echoed the tool summary once per action and under-reported required fields, and thrown classified responses that were flattened into a generic INTERNAL_ERROR.

By Renato Marinho
Founder · Vinkius
Published September 17, 2026, 5.0.10 is a maintenance release, and every code change in it sits inside @mcpfusion/core; the release notes confirm the other fifteen workspace packages still build clean, untouched (release notes · MCP Fusion on GitHub). Two P2 defects and one latent crash make up the release. All three matter, and all three can only be observed from where the language model stands.
Bug 152: the summary, said 1 + N times
Under toolExposition: 'grouped', a tool exposes a single name with a discriminating action field instead of N flat tools, and its description is layered. Layer 1 leads with the tool summary, the module/action listing and the dispatch instruction; Layer 2 carries one line per action: the Workflow: block in markdown, the desc: column in TOON. When a builder sets a .description() but its individual actions do not have one, the tool summary is inherited into each action (correct, flat exposition relies on that fallback), and it was then echoed back once per action in Layer 2. The model saw the summary 1 + N times with zero new information after the first. A redundant description does not merely bloat the prompt; it dilutes the exact signal the model is supposed to weigh. The fix treats a description equal to the tool summary as "not action-specific" and omits it from Layer 2; action-specific descriptions pass through untouched.
Bug 153: a hint the validator would reject
The "which fields must I pass" hint, the Requires: line, was computed from the per-action schema only. It never looked at the tool-level commonSchema and did not apply omitCommonFields. The consequence in practice: a required workspace_id declared via .commonSchema() appeared in inputSchema.required but not in the hint. The model omitted the field, validation rejected the call, the agent read the error, re-called with the missing field, and succeeded. One needless self-healing bounce, paid on every grouped call that shared a common field. The fix makes getActionRequiredFields() reflect the same merged schema that buildValidationSchema() enforces, including omitCommonFields, so the hint and the validator can no longer disagree.
The commonSchema parameter added to getActionRequiredFields / generateDescription / generateToonDescription is optional, which keeps the change wire-visible but non-breaking: no API, type or schema shape changed; flat exposition output is byte-for-byte unchanged, and grouped descriptions only shrink. The one operational consequence: mcpfusion.lock's integrityDigest changes for grouped servers that had inherited descriptions; regenerate the lockfile.
The catch that swallowed meaning
The framework's taught idiom is to classify failures, not just raise them: handlers and middleware may throw an already-classified response (throw toolError('NOT_FOUND', {...}), throw error('Unauthorized')) instead of returning one. The catch block in runChain() recognized a plain ToolResponse and nothing else, so a thrown response arrived stripped of its error code, its recovery guidance and its warning-versus-error severity, and left re-wrapped as a generic INTERNAL_ERROR.
Two shapes were worse than merely lost. A thrown HandoffResponse carries the tool-response brand but has no content array, so the isToolResponse()-only check forwarded it into code that indexes content, a crash on the federated-handoff path. A thrown ResponseBuilder was discarded instead of built, losing every composed content block. The catch now mirrors postProcessResult()'s ordering (isHandoffResponse → isResponseBuilder → isToolResponse), and only genuinely unexpected residue becomes INTERNAL_ERROR.
The part that matters most at the model boundary: that fallback no longer claims the failure is transient. A permanent failure (a bad id, a missing resource, expired auth) would otherwise send the agent into a retry loop with identical parameters. The new error reports the [tool/action] origin and tells the model to inspect the message rather than retry blindly, which is the difference between an agent that escalates and one that hammers the same call until it times out.
Pinned and shipped
DescriptionInheritance-bug152-153.test.ts(18 cases) andThrownResponseRecovery.test.ts(12 cases) pin both behaviors, per the release notes.- Full core suite: 5,243 passing, 0 failed;
tsc --noEmitclean; all 16 workspace packages build.
Installing is one line:
npm install @mcpfusion/core@5.0.10
Running grouped exposition? Regenerate your mcpfusion.lock so the integrityDigest matches the (now smaller) description, and nothing else in your handler code changes; the idiom of throwing a classified response now works the way the docs always said it would.
