FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

SEP-2145: Standardize `tools/call` failure reporting by KKonstantinov · Pull Request #2145 · modelcontextprotocol/modelcontextprotocol · GitHub

SEP-2145: Standardize tools/call failure reporting - #2145

Open
KKonstantinov wants to merge 9 commits into
modelcontextprotocol:mainfrom
KKonstantinov:sep/standardize-tools-call-failure-reporting
Open

SEP-2145: Standardize tools/call failure reporting#2145
KKonstantinov wants to merge 9 commits into
modelcontextprotocol:mainfrom
KKonstantinov:sep/standardize-tools-call-failure-reporting

Conversation

KKonstantinov commented Jan 23, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Summary

This SEP extends tools/call error handling so that additional failure modes — tool resolution failures and output validation failures — are reported as Tool Execution Errors (CallToolResult with isError: true) rather than JSON-RPC Protocol Errors.

Key Changes

  • Tool resolution failures (unknown tool, tool not callable/disabled) → Tool Execution Error
  • Output validation failures (missing or non-conforming structuredContent when outputSchema is declared) → Tool Execution Error
  • Protocol Errors reserved for malformed requests, unsupported methods, and unrecoverable server failures
  • Aligns specification with existing Python and TypeScript SDK behavior

Related

See the full SEP document in seps/2145-standardize-tools-call-failure-reporting.md for details.

KKonstantinov marked this pull request as ready for review January 23, 2026 16:39
KKonstantinov requested a review from a team as a code owner January 23, 2026 16:39
KKonstantinov changed the title SEP - standardize tools/call failure reporting SEP-2145: Standardize tools/call failure reporting Jan 23, 2026
localden added proposal SEP proposal without a sponsor. SEP labels Jan 24, 2026
"content": [
{
"type": "text",
"text": "Input validation error: Invalid arguments for tool book_flight: Invalid departure date, must be in the future. Current date is 08/08/2025."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I would possibly avoid the tool name being in error messages because it makes parsing and comparison more difficult if they are logged, considering that the caller knows what method and name are being called, there's little value in returning it back.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I see, yes. This is just an example given, should we give explicit instruction on what the error message should/shouldn't contain, or do you think just cleaning up the example is enough?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I think it makes sense that SDKs all throw the same errors for same scenarios and the spec should provide the advice for what they should throw explicitly.

Conformance testing should also be an avenue for improving error consistency, which is being worked on proactively.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I agree, & locking it up via conformance tests makes sense.

codefromthecrypt left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

modelcontextprotocol/typescript-sdk#1428 ran into this and it may be scope creep, but I feel the following could improve the situation..

Add a error schema to tools/list

Schema change (schema/draft/schema.ts and docs):

  interface ListToolsResult {
    tools: Tool[];
    nextCursor?: string;
    errorSchema?: JSONSchema; // NEW: applies to ALL tool errors
  }

Then, something in the spec like

  • If isError: true and structuredContent is present:
    • If errorSchema exists, it MUST conform to errorSchema.
    • Clients SHOULD validate error results against errorSchema.

Why? it is very common to have a server-wide error format. e.g. OpenAI ErrorResult. Doing so would prevent one of three bad choices:

  • have no way to know the shape of an error (not validated)
  • force error to be the same shape as the success (weird)
  • complicated oneOf for every tool.

Fix the “error text disappears on validation failure”

  • If validation fails, clients MUST still surface content.
  • Clients MAY drop/ignore invalid structuredContent, but MUST NOT replace the tool’s error message with a schema error.

Why? this prevents replacing a good but pedantically incorrect error message with an unusable one. modelcontextprotocol/typescript-sdk#1428 is an example of this, but it can also happen in proxies, just like normal REST apis sometimes a proxy overrides the error response in CDN conditions.

It would be find to make it a detailed field. If we don't do something like that it requires JSON-RPC level debug which is not easy for people to do.

"content": [
{
"type": "text",
"text": "Output validation error: outputSchema defined but no structured output returned."

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

modelcontextprotocol/typescript-sdk#1428 ran into this, and I wonder if there is a way to return the actual content on output validation fail.

If we had the content sent back, mistakes are easier to identify and correct. Mistakes are sometimes in the raw server code, other times in proxies.

PederHP commented Feb 3, 2026
edited
Loading

Copy link
Copy Markdown
Member

Text mentions that models can handle stale tool lists by re-listing tools. Client hosts rarely provide a mechanism for models to do this. Only code mode style integrations allow for this out of the box. The example shown explicitly tells the model to re-run "tools/list" which the model usually cannot.

In 'basic' SDK driven integrations it is the client host that lists tools, and providing an easily handled error code at the JSON-RPC level allows the host to do this. This doesn't happen currently but JSON-RPC does allow for new error codes, and we could define one for this.

Alternatively an additional property in the payload could be introduced in addition to isError, so that the error handling accomodates both standard and code mode integrations.

Considering "unknown tool" purely a model concern prevents the host from handling this and may confuse models when they cannot re-list or otherwise adapt to the error (other than telling the user the tool failed).

Copy link
Copy Markdown
Contributor Author

Hi,

TL;DR on this SEP:

Python and Typescript SDK have this behavior for a long time, but the wording on the November SEP that got in did not describe these scenarios; Getting this SEP in will just clarify language, bit it would not lead to any tangible behavior or code change on the SDKs. Happy to be corrected on this, but checked it back in Oct/Nov, and believe it's still the situation.

Copy link
Copy Markdown
Contributor Author

PS.

modelcontextprotocol/typescript-sdk#1389 -> brought TS SDK back to spec.
modelcontextprotocol/python-sdk#1872 -> Pending on Python SDK to bring it back to spec.

This SEP would make the agent "aware" that a tool does not exist; while Protocol-level errors means the agent is unaware (this is the behavior Claude web has).

It's valuable context for the agent in some scenarios to know this, but it'll depend on whether this SEP gets reviewed/accepted.

pcarleton self-assigned this Mar 13, 2026
sep-automation-bot Bot added draft SEP proposal with a sponsor. and removed proposal SEP proposal without a sponsor. labels Mar 13, 2026

Copy link
Copy Markdown

State Transition: proposal → draft

This SEP has been transitioned from proposal to draft.

@pcarleton has been assigned as the sponsor for this SEP.


This is an automated message from the SEP lifecycle bot.

KKonstantinov requested a review from a team as a code owner March 19, 2026 08:34

Copy link
Copy Markdown

Maintainer Activity Check

Hi @pcarleton!

You're assigned to this SEP but there hasn't been any activity from you in 16 days.

Please provide an update on:

  • Current status of your review/work
  • Any blockers or concerns
  • Expected timeline for next steps

If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.


This is an automated message from the SEP lifecycle bot.

Copy link
Copy Markdown

Maintainer Activity Check

Hi @pcarleton!

You're assigned to this SEP but there hasn't been any activity from you in 14 days.

Please provide an update on:

  • Current status of your review/work
  • Any blockers or concerns
  • Expected timeline for next steps

If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.


This is an automated message from the SEP lifecycle bot.

mcp-virtual-tpm Bot added this to the 2026-06-30-RC milestone Apr 17, 2026
localden added in-review SEP proposal ready for review. and removed draft SEP proposal with a sponsor. labels Apr 22, 2026
localden moved this to In Review in SEP Review Pipeline Apr 22, 2026

Copy link
Copy Markdown

Maintainer Activity Check

Hi @pcarleton!

You're assigned to this SEP but there hasn't been any activity from you in 14 days.

Please provide an update on:

  • Current status of your review/work
  • Any blockers or concerns
  • Expected timeline for next steps

If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.


This is an automated message from the SEP lifecycle bot.

- Treat "Unknown tools" (tool name resolution) as a Tool Execution Error for `tools/call`.
- Add explicit categories for "tool not callable" and "output schema validation failures" as Tool Execution Errors.
- Keep Protocol Errors focused on malformed `CallToolRequest` and server-level failures.
- `schema/draft/schema.ts` documentation for `CallToolResult.isError` to remove/adjust language suggesting that "errors in finding the tool" should be protocol errors, aligning it with the above requirements.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

The PR diff doesn't include this schema.ts change. The current CallToolResult.isError JSDoc still says errors in finding the tool should be reported as an MCP error response, which directly contradicts the resolution-failure MUST above. Needs the schema hunk plus a regenerate.

- Keep Protocol Errors focused on malformed `CallToolRequest` and server-level failures.
- `schema/draft/schema.ts` documentation for `CallToolResult.isError` to remove/adjust language suggesting that "errors in finding the tool" should be protocol errors, aligning it with the above requirements.

#### Proposed draft wording for `docs/specification/draft/server/tools.mdx` (Error Handling)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

The proposed wording here includes "Clients SHOULD provide tool execution errors to language models…" but the actual tools.mdx diff in this PR doesn't add that sentence. Either the diff or this block should be brought in line.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

A few more drift items in the same block: the tools.mdx diff drops the "arguments do not match tool inputSchema" clause from the input-validation bullet, reorders output-validation before input-validation, and uses different example message formats than the templates and Examples section here. Probably easiest to regenerate the tools.mdx hunk from this block verbatim once it settles.


## Rationale

- **Aligns with existing SDK behavior**: As noted in the Nov 7 discussion, both the Python and TypeScript SDKs already return `CallToolResult` with `isError: true` for unknown tools, disabled tools, and various output schema failures. Making this behavior normative improves interoperability and reduces host-specific divergence.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

This is now backwards: typescript-sdk#1389 merged in March to bring the TS SDK back to the current spec (protocol error for unknown tool), and python-sdk#1872 proposes the same. So today the TypeScript SDK does the opposite of what this SEP mandates. Is that intended?


This SEP does not change JSON-RPC framing or introduce new required fields.

However, it is a **behavioral change** for servers that currently return Protocol Errors for tool resolution and output validation failures. Clients that rely on a JSON-RPC error response for these cases will need to handle `CallToolResult.isError: true` equivalently.

localden Apr 29, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I think this needs to be reconciled with the earlier TS change I mentioned. That PR brought the TS SDK into conformance with the current spec (protocol error for unknown tool); this SEP would make that change wrong. Which one reflects the intended direction?

- Exceptions thrown by the tool implementation.
- Timeouts or cancellations that occur during tool execution (if the server can still return a `CallToolResult`).

4. **SHOULD** report output validation failures as Tool Execution Errors when a tool declares an `outputSchema`, including:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

tools.mdx already has "Servers MUST provide structured results that conform to outputSchema / Clients SHOULD validate." Worth a cross-reference here so it's clear how this server-side SHOULD-report relates to that pair (defense-in-depth, or shifting the validator role?).

- Treat "Unknown tools" (tool name resolution) as a Tool Execution Error for `tools/call`.
- Add explicit categories for "tool not callable" and "output schema validation failures" as Tool Execution Errors.
- Keep Protocol Errors focused on malformed `CallToolRequest` and server-level failures.
- `schema/draft/schema.ts` documentation for `CallToolResult.isError` to remove/adjust language suggesting that "errors in finding the tool" should be protocol errors, aligning it with the above requirements.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

There's also InvalidParamsError in schema.ts whose JSDoc Tools bullet asserts the opposite, plus schema/draft/examples/InvalidParamsError/unknown-tool.json and invalid-tool-arguments.json which render into the Schema Reference. Without updating those, schema.mdx will contradict tools.mdx after this lands.

Suggested change
- `schema/draft/schema.ts` documentation for `CallToolResult.isError` to remove/adjust language suggesting that "errors in finding the tool" should be protocol errors, aligning it with the above requirements.
- `schema/draft/schema.ts` documentation for `CallToolResult.isError` to remove/adjust language suggesting that "errors in finding the tool" should be protocol errors, aligning it with the above requirements.
- `schema/draft/schema.ts` documentation for `InvalidParamsError` (Tools bullet) and the associated example files (`examples/InvalidParamsError/unknown-tool.json`, `invalid-tool-arguments.json`) so the generated Schema Reference matches.

KKonstantinov May 6, 2026
edited
Loading

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Hi @localden , missed notification about this one. I'll review the comments and address/resolve them tomorrow; PR also needs updating with latest, as it has some conflicts.

EDIT: Comments addressed

Copy link
Copy Markdown

Maintainer Activity Check

Hi @pcarleton!

You're assigned to this SEP but there hasn't been any activity from you in 14 days.

Please provide an update on:

  • Current status of your review/work
  • Any blockers or concerns
  • Expected timeline for next steps

If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.


This is an automated message from the SEP lifecycle bot.

localden removed this from the 2026-06-30-RC milestone May 19, 2026

Copy link
Copy Markdown

Maintainer Activity Check

Hi @pcarleton!

You're assigned to this SEP but there hasn't been any activity from you in 14 days.

Please provide an update on:

  • Current status of your review/work
  • Any blockers or concerns
  • Expected timeline for next steps

If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.


This is an automated message from the SEP lifecycle bot.

2 similar comments

Copy link
Copy Markdown

Maintainer Activity Check

Hi @pcarleton!

You're assigned to this SEP but there hasn't been any activity from you in 14 days.

Please provide an update on:

  • Current status of your review/work
  • Any blockers or concerns
  • Expected timeline for next steps

If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.


This is an automated message from the SEP lifecycle bot.

Copy link
Copy Markdown

Maintainer Activity Check

Hi @pcarleton!

You're assigned to this SEP but there hasn't been any activity from you in 14 days.

Please provide an update on:

  • Current status of your review/work
  • Any blockers or concerns
  • Expected timeline for next steps

If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.


This is an automated message from the SEP lifecycle bot.

Copy link
Copy Markdown

Maintainer Activity Check

Hi @pcarleton!

You're assigned to this SEP but there hasn't been any activity from you in 20 days.

Please provide an update on:

  • Current status of your review/work
  • Any blockers or concerns
  • Expected timeline for next steps

If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.


This is an automated message from the SEP lifecycle bot.

Copy link
Copy Markdown

Maintainer Activity Check

Hi @pcarleton!

You're assigned to this SEP but there hasn't been any activity from you in 14 days.

Please provide an update on:

  • Current status of your review/work
  • Any blockers or concerns
  • Expected timeline for next steps

If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.


This is an automated message from the SEP lifecycle bot.

Copy link
Copy Markdown

I ran a census against the live registry to see what this SEP would actually land on, and one number seems load-bearing for the output-validation clause specifically.

Method. Walked registry.modelcontextprotocol.io/v0/servers (60,892 entries, 609 pages) and took server.remotes[].url — 21,396 entries carry remotes, 10,559 unique endpoints, 10,500 probed. 5,722 of those completed an initialize handshake. I harvested tools/list from those 5,722; 5,014 returned a parseable tool list. Full response bodies are stored so the verdict is derived downstream rather than at probe time. One endpoint reported a tool list and would not parse; it stays in the denominator as a failure rather than being dropped.

Write tools. 2,355 of those servers expose at least one mutating tool (readOnlyHint: false, or a mutating verb where no annotation is declared — counted separately, 11,639 by annotation and 2,076 by verb inference). 13,715 write tools total.

The number:

count share of write tools
declare inputSchema 13,715 100%
declare outputSchema 1,535 11.19%
declare no output contract at all 12,180 88.81%

Every write tool in the registry says precisely what to send it. Fewer than one in nine says what comes back.

That matters here because "output validation failures (missing or non-conforming structuredContent when outputSchema is declared) → Tool Execution Error" is conditioned on a declared outputSchema. On the current write surface that clause is inert for roughly seven of every eight tools. Not an argument against it — the direction looks right to me — but if the SEP is partly motivated by making failures legible to clients, it is worth knowing that the population it reaches is about 11% of writes today, and that the other 89% will keep returning isError: false with an undeclared shape regardless of what this standardises.

A gap that remains after this SEP, which I think is orthogonal to it. Every failure mode enumerated here is one the server itself detects: unknown tool, disabled tool, malformed request, output that fails its own schema. There is no vocabulary for the case where the server did everything correctly, got an acknowledgement from a third party, validated cleanly, and the far side never committed. That call returns isError: false and is fully conformant. The success artifact and the silent-failure artifact are byte-identical by specification rather than by anyone's sloppiness — which means it cannot be found by reading your own logs, because your logs are you telling yourself what you already believe.

I went looking for anyone expressing that third state and want to publish the search honestly, including its noise. A regex for unverified/unconfirmed/indeterminate/pending-confirmation over declared output schemas returned 6 of 13,715, and on inspection I judge 5 of the 6 to be false positives — domain vocabulary rather than delivery semantics:

  • get_auto_insurance_quote, get_home_insurance_quote, get_bundle_insurance_quote — matched "uncertain", which is quote confidence
  • refresh_wallet_balance, check_swap — matched "unverified", which is token/contract status
  • start_free_diagnostic — matched "pending_confirmation"; this one may be real

So the honest count is 0–1 in 13,715, and I would rather show you the five I threw out than report a clean 6. My own crawler's false-positive rate on a different corpus measured 56% when I finally checked it, so I no longer trust a number of mine that arrives without its noise attached.

Happy to share the raw harvest or the classifier if either is useful to the SEP discussion, and happy to be told the third-state case belongs somewhere other than this thread.

Ahmad-Faraj commented Jul 31, 2026
edited
Loading

Copy link
Copy Markdown

Building on @siliroid's census above, which covers the remote surface. I measured the local one, and the two turn out to be close to disjoint: they probed hosted endpoints and read declared metadata, I installed and executed npm/PyPI stdio servers and tested behaviour against inputs.

The SEP argues that reclassifying tool resolution failures "aligns specification with existing Python and TypeScript SDK behavior." Here is how much alignment already exists.

Method. Every registry server that is locally installable, uses stdio, and declares no required credentials: 6,106 of a 17,432-server snapshot. Each launched in an isolated container and sent a tools/call for a tool name that does not exist, graded against the protocol version it negotiated.

Result. Of the 3,685 that completed a handshake, 88.4% (95% CI 87.3–89.4) answered with isError: true rather than a JSON-RPC protocol error.

SDK family servers answer with isError
official TypeScript SDK 2,347 90%
official Python SDK 645 88%
FastMCP (Python) 375 100%

The official reference servers behave the same way. The minority emitting protocol errors are mostly TypeScript-SDK servers, so the specified behaviour is reachable in the SDK but is not its default. Holding one server per publisher (3,913 publishers, largest ships 305) gives 85.2%, so this is not an artifact of templated bulk publishing.

Why it might matter. The alignment already covers roughly nine in ten servers, so adopting this ratifies existing behaviour and the migration cost falls on the ~11.6% minority rather than the majority. That is a different cost profile from "change the ecosystem to match the spec." I have no position on which mechanism is correct.

One thing that may bear on @siliroid's third-state gap. Sending a wrong-typed value for a required argument a server's own inputSchema declares, 129 servers executed the tool anyway and returned ordinary-looking output. A code-scanning tool asked to scan the integer 12345 replied CLEAN. isError: false, well-formed, no signal. Different cause from an unacknowledged third party, same artifact: a success response byte-identical to a real one. Suggests that shape is not only a distributed-systems problem.

Data, harness and raw transcripts: https://github.com/Ahmad-Faraj/mcp-conformance. Any server re-checkable with python driver/mcpprobe.py --cmd "<launch command>". Happy to re-run against a revised rule.

Disclosure: the measurement pipeline and write-up were built with substantial AI assistance; the data, method and this comment are mine and I am answerable for them.

Copy link
Copy Markdown

Maintainer Activity Check

Hi @pcarleton!

You're assigned to this SEP but there hasn't been any activity from you in 20 days.

Please provide an update on:

  • Current status of your review/work
  • Any blockers or concerns
  • Expected timeline for next steps

If you're no longer able to sponsor this SEP, please let us know so we can find another maintainer.


This is an automated message from the SEP lifecycle bot.

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in-review SEP proposal ready for review. SEP

Projects

Status: In Review

Development

Successfully merging this pull request may close these issues.

8 participants


Back | FazBrowse Home | New Git URL