Sume MCP returned a tool descriptor, not a result: it did not run
If a Sume MCP call returns a tool name, description and schema instead of a result, the tool did not run. Re-call with the namespaced name your client lists.

Sume's hosted MCP tells agents that some clients register tools namespaced by server, as <server>-<tool>, and that if a call returns a tool descriptor (name, description, input schema) instead of a result, the tool did not run. Re-call it using the namespaced name your client lists.
Where the namespace comes from
The namespacing is client-side. A client that connects several servers prefixes each tool with the server name so two servers cannot collide. Sume's server never sees that form. It also accepts dotted names from some clients, which it converts to underscore names. So a single create can be named generate_image, sume-generate_image or something else, depending on the client, and only the name in your client's own tool list is right.
Result or descriptor
The two shapes differ in ways a harness can test.
| Shape | Typical fields | Meaning |
|---|---|---|
| Result | response, agent.next_step, job or request id | the tool ran |
| Descriptor | name, description, input schema | the tool did not run |
| Error | isError true with a code | the tool ran and refused |
A guard
Before waiting on a job, make sure there is one. This runs as written.
def ran(result: dict) -> bool:
if 'inputSchema' in result or 'input_schema' in result:
return False # a descriptor, not a result
return bool(result.get('response') or result.get('job_id'))
print(ran({'name': 'sume-generate_image', 'inputSchema': {}}))
print(ran({'job_id': 'job_1'}))What to do next
Re-call with the namespaced name and the same arguments. For a paid create, keep the same idempotency_key: if the first call did not run there is nothing to deduplicate, and if it did, you get the same job and not a second one. If the name is wrong in a different way, the server answers tool_not_found with a did-you-mean suggestion; the Agents SDK post shows that shape.
Limits
This is guidance for client behavior, and the exact descriptor shape varies by client. Treat the check above as a starting point and adapt it to what your client returns.
Why this matters for money
A descriptor looks like a successful reply to a model: it is structured, it has a name, and it has a schema. If the agent treats it as a result, it may wait on a job id that was never created, or tell a user that a generation started. With a paid create the safe move is the cheapest: re-call with the right name and the same idempotency_key, and confirm a job id comes back.
Checklist before you ship
- Log the exact tool name your client registered, with its namespace.
- Re-call using the namespaced name the client lists, not the bare name.
- Never assume a paid create ran because the model produced a tool call.
- Confirm the job id exists before you start waiting.
Sources
Related posts
More in Agents
- Sume schedule cron field: expr, IANA timezone and next_run_at
A Sume schedule's cron object holds expr, timezone and next_run_at, or null for an API-only schedule. How to read when the next run is due over the API.
- Sume schedule cap null or 0: what a per-run override can do
A per-run generation_spend_cap_usd lowers a Sume schedule's cap but never raises it; null drops that ceiling, 0 is rejected, and wallet limits still apply.
- tts_create dry_run will not warn about a voice-language mismatch
A cost-only dry_run on Sume's tts_create stays a preview; the language double-check runs on submission. How to preflight voice, language and cost together.
- tts_source_get and verify_spine: check a voiceover vs its script
Sume's hosted MCP has two free read tools for voiceover work. One returns the accepted script for tts_create, the other compares chosen TTS jobs to it.
Written by Sume