CLAUDE LABJP
SUNSET — The legacy Workbench and experimental prompt tool APIs retire tomorrow, August 17, one day outLATEST — Version 2.1.233, released August 15, is current: GitLab merge request URLs now work with --worktree and the claude agents view, where MRs appear as !NSECURITY — Windows paths written with the NT \??\ device prefix no longer bypass UNC validation, closing an NTLM credential-leak vectorTODO — Todo and task tracking tools are off by default on Opus 4.8, Sonnet 5, Fable 5, Mythos 5, and newer models; set CLAUDE_CODE_ENABLE_TODO_TOOLS=1 to bring them backFORK — Version 2.1.232, released August 14, makes subagent_type: 'fork' the default, so a forked subagent inherits the full conversation and prompt cacheMENTION — Typing @ in the prompt now mentions another Claude session by name, and SendMessage reaches that session directlySUNSET — The legacy Workbench and experimental prompt tool APIs retire tomorrow, August 17, one day outLATEST — Version 2.1.233, released August 15, is current: GitLab merge request URLs now work with --worktree and the claude agents view, where MRs appear as !NSECURITY — Windows paths written with the NT \??\ device prefix no longer bypass UNC validation, closing an NTLM credential-leak vectorTODO — Todo and task tracking tools are off by default on Opus 4.8, Sonnet 5, Fable 5, Mythos 5, and newer models; set CLAUDE_CODE_ENABLE_TODO_TOOLS=1 to bring them backFORK — Version 2.1.232, released August 14, makes subagent_type: 'fork' the default, so a forked subagent inherits the full conversation and prompt cacheMENTION — Typing @ in the prompt now mentions another Claude session by name, and SendMessage reaches that session directly
Articles/API & SDK
API & SDK/2026-07-08Advanced

Contract-Test Every Tool Before You Submit or Automate an MCP Connector

A connector that works once in a chat can still break silently in an unattended job through misread response shapes or double-fired writes. Here is a small harness that machine-checks tool descriptions, response contracts, idempotency, and latency, with measured numbers.

MCP50Claude API117Contract Testing2Unattended RunsTypeScript24

Premium Article

It was the night I wired a connector that had worked once in a chat straight into an unattended job. The next morning, the log showed the same article write running twice. The tool logic was correct, the permissions were fine, and it had never reproduced when I called it interactively.

The cause sat in front of the connector, not inside it. When the network stalled for a moment and the client retried, the write tool had no idempotency, so the same operation applied twice. Interactively I would have seen the result and caught it. An unattended job has nobody watching. With July's update, you can now submit a connector you built to the directory straight from Claude. Right before you hand it to someone else, or lean on it in your own nightly runs, I badly wanted to promote "it worked once" into "it is guaranteed as a contract."

This article builds that guarantee with a small contract-test harness, using the MCP SDK for TypeScript.

It Worked Once, Then Broke Silently at Night

Checking a connector by hand in a chat has a fatal blind spot: a human calls it once, sees only the successful response, and decides it works.

What breaks in unattended runs is almost always outside the success path. A tool returns an error as an isError: true structured response, and the caller misreads it as success. The response shape shifts slightly from last time, and the downstream parser quietly grabs nothing. A retry fires a write twice. None of these ever surface from a single interactive call.

I feel this acutely as an indie developer who hands nightly updates of several technical blogs to the model. The reliability of an unattended job is decided not by how the connector behaves at its best, but by whether it keeps its promises when things wobble. So what you should verify before submission or production is not whether features exist, but the very contract each tool claims to honor.

The Four Properties a Contract Test Checks

A contract test is a little different from both unit tests and end-to-end tests. It machine-checks the "promises" a connector publishes, from the outside, as a client would. Before shipping to unattended use, pin down at least these four.

PropertyWhat it checksWhat breaks if violated
Self-descriptionEvery tool has a description and a valid inputSchemaThe model misuses or ignores the tool
Response contractThe happy-path response shape matches the declarationDownstream parsing quietly grabs nothing
IdempotencyCalling a write twice yields one side effectRetries double-fire
LatencyPer-tool response time stays within budgetTimeouts drop the unattended job

Let us turn each into working code. Everything below uses the @modelcontextprotocol/sdk client to connect to the connector under test from the outside.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Validation code that enumerates every tool in an MCP connector and catches missing descriptions and inputSchema before you submit
An idempotency test that detects double-fired writes with a sentinel key, including p95 latency measurement
A procedure for setting unattended-job timeouts from measured per-tool p50/p95 latency rather than guessing
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

API & SDK2026-06-02
Beyond Tools in MCP: Designing with Resources, Prompts, and Sampling
Cramming everything into MCP tools hits a wall fast. Here is how resources, prompts, and sampling untangle a server, told through a real wallpaper-app asset manager I cut from 14 tools down to 5.
API & SDK2026-07-09
When the RAG Started Being Confidently Wrong — Field Notes on Measuring Retrieval Misses With Groundedness
In a Claude API RAG, the answers stay fluent while the facts drift. Often the cause is a silent recall decay on the retrieval side, missing the document that holds the answer. Field notes on measuring groundedness and retrieval hit rate and walking the system back, with working code and real numbers.
API & SDK2026-07-03
A 40% Lower Price Doesn't Mean a 40% Lower Bill — Measuring the Opus 4.8 to Sonnet 5 Migration by Cost per Completed Task
Sonnet 5's intro pricing looks ~40% cheaper than Opus 4.8, yet extra tool turns can flip the math. Working TypeScript for consumption vectors, a paired-run harness, and break-even turn counts.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →