You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* release: v0.20.0 (align SDK adapter session-limit enforcement)
Brings `create_sdk_mcp_server` in line with `create_langchain_tools`:
every wrapped tool now pre-checks `ContractSession.check_limits()` by
default. Pre-0.20.0, only `run_query` self-checked limits — lookup
tools (`describe_table`, `list_metrics`, etc.) bypassed entirely.
The two adapters now behave identically.
Practical effect: `max_duration_seconds` measures wall-clock from the
first tool call (any tool), not just from the first `run_query`. For
most users this is invisible — lookups complete in milliseconds. The
narrow population that sees a behavior change: agents with tight
`max_duration_seconds` AND lookup-heavy prompts that browse extensively
before querying. The new behavior matches the YAML's documented intent
('the agent has N seconds total') and closes the runaway-loop gap where
an agent stuck on lookups previously bypassed the duration cap.
Public API unchanged. New optional `apply_middleware: bool = True`
kwarg on `create_sdk_mcp_server` mirrors the LangChain adapter; pass
`False` to opt out and restore pre-0.20.0 semantics.
SQL validation is intentionally NOT auto-applied, same reasoning as
the LangChain adapter: doing so would block `inspect_query`'s purpose
of reporting violations as JSON. `run_query` self-validation at
`factory.py:632-702` already covers the cost path.
6 new tests on the `_wrap_with_session_check` helper and the new
kwarg surface. Full suite: 591 passed, 8 skipped, 0 regressions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* review: address 2 sub-threshold items from automated review
- Issue A (score 75): Wrapper-emitted BLOCKED envelopes now include
the canonical `Remaining: {budget}` suffix matching run_query's
self-emitted blocks (factory.py:627-628). Affected both SDK and
LangChain adapters' wrappers (_wrap_with_session_check,
_to_structured_tool, ContractMiddleware._check). Agents whose
retry-planning logic depended on the suffix now see consistent
output regardless of whether the limit fired in run_query or in
the wrapper layer.
- Issue D (score 72): Clarified the apply_middleware=False docstring
in sdk.py. The earlier 'matching create_langchain_tools' phrasing
understated a transport-inherent divergence — with apply_middleware=False
the LangChain adapter still raises ToolException via its always-active
prefix sniff, while the SDK adapter passes BLOCKED envelopes through
as plain MCP text content (the SDK MCP transport has no status='error'
field). The docstring now spells out that timing is aligned but error
transport differs by design.
3 tests extended to assert the Remaining: suffix appears on session-
limit-exceeded paths in both adapters. Full suite: 591 passed,
8 skipped, 0 regressions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+21Lines changed: 21 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,6 +2,27 @@
2
2
3
3
All notable changes to this project will be documented in this file.
4
4
5
+
## [0.20.0] - 2026-05-10
6
+
7
+
### Changed
8
+
9
+
-**`create_sdk_mcp_server` now auto-applies session-limit enforcement to all 9 tools by default**, matching the v0.19.0 behavior of `create_langchain_tools`. Pre-v0.20.0, only `run_query` self-checked `ContractSession` limits — lookup tools (`describe_table`, `list_metrics`, etc.) bypassed. The two adapters now behave identically: a single contract YAML enforces the same way under SDK and LangChain.
10
+
-**Practical effect**: `max_duration_seconds` now measures wall-clock from the *first tool call* (any tool), not just from the first `run_query`. For most contracts this is invisible — lookups complete in milliseconds. The narrow population that sees a behavior change: agents with tight `max_duration_seconds` AND lookup-heavy prompts that browse extensively before querying. The new behavior matches the YAML's documented intent ("the agent has N seconds total"), and closes the runaway-loop gap where an agent stuck on lookup tools previously bypassed the duration cap.
11
+
-**Escape hatch**: pass `apply_middleware=False` to `create_sdk_mcp_server` to restore pre-0.20.0 behavior.
12
+
13
+
### Added
14
+
15
+
- New `_wrap_with_session_check(inner, session)` helper in `tools/sdk.py` — exported as a private symbol so tests can verify the enforcement wrapper directly without going through the SDK's `@tool` decorator. Mirrors the in-tool enforcement pattern in `tools/langchain.py:_to_structured_tool`.
16
+
17
+
### Fixed
18
+
19
+
- Wrapper-emitted BLOCKED envelopes now include the canonical `Remaining: {budget}` suffix that `run_query`'s self-emitted blocks have always carried (per `factory.py:627-628`). Pre-0.20.0 the LangChain wrapper (introduced in v0.19.0) and the new SDK wrapper both omitted this suffix, so agents whose retry-planning logic depended on the suffix would lose context once they hit the wrapper layer instead of `run_query`'s own block. Applies to both `_wrap_with_session_check` (SDK) and `_to_structured_tool` / `ContractMiddleware._check` (LangChain).
20
+
21
+
### Compatibility
22
+
23
+
- Public API unchanged — `create_sdk_mcp_server` gains one optional kwarg with a sensible default. Pre-built `ToolDef` lists, custom sessions, and all other call shapes continue to work.
24
+
- 6 new tests in `tests/test_tools/test_sdk.py` cover the wrapper behavior and the new kwarg.
0 commit comments