From 9c9b2f67322c735d865bdc0d141e68b699a84303 Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Mon, 3 Aug 2026 12:49:51 -0400 Subject: [PATCH 01/13] =?UTF-8?q?feat!:=20AgentCat=20v2=20=E2=80=94=20expl?= =?UTF-8?q?icit=20handles=20for=20sessionless=20MCP,=20and=20MCP=20Python?= =?UTF-8?q?=20SDK=20v2=20support?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MCP 2026-07-28 (SEP-2567) removed protocol-level sessions: no `initialize` handshake, no `Mcp-Session-Id` header, and list endpoints are now connection-independent. Every request is self-contained. For analytics that is a tectonic shift — sessions were the built-in thread tying related tool calls together, and without them a stateless deployment sees each call in isolation. The MCP core team's guidance for cross-call state is to mint an explicit handle from a tool and have the model pass it back as an argument. AgentCat v2 rebuilds correlation on exactly that pattern: `track()` mints a `session_id`, delivers it to the agent, and the agent threads it back on every later call. Session correlation via explicit handles - `session_id` is injected into every tracked tool's input schema. Agents echo it back, grouping related calls into one session across stateless HTTP, load balancers, and per-request server instances. - Issued IDs are delivered via `_mcp_instructions` and mirrored into `structuredContent` for tools declaring an output schema. - Injected parameters are stripped before the customer's handler runs, and mint-back instructions never appear in published events. - AgentCat honors only handles it issued. A `session_id` that is not a `ses_` KSUID from this server is rejected rather than adopted — the call publishes without a session and the agent is told to re-send the ID it was given. `Event.session_id` is exempt from both redaction hooks, so a value AgentCat did not mint could not be redacted after the fact. - A tool whose own schema declares `session_id` keeps it. Their value reaches their handler untouched and is never read as a handle; those calls publish without a session and log an error naming the tool. `resolve_session_id` is the documented remedy — it reads no arguments at all. Agent attribution (beta, opt-in) - `agent_id` — enable with `enable_agent_tracking=True`. Each agent self-generates a `model|harness|nonce` ID, so parallel agents on one session stay individually attributable. Off by default; no server-side minting. MCP Python SDK v2 and community FastMCP 4 support - `track()` supports four server flavors through one call, dispatched by per-object detection: official SDK 1.x (low-level `Server` and `mcp.server.fastmcp.FastMCP`), official SDK 2.x (low-level `Server` and `mcp.server.mcpserver.MCPServer`), and community FastMCP 3.x and 4.x. - Full 2026-07-28 protocol support: envelope-first client identity, the protocol-version ladder, fully-qualified reserved metadata keys, and MRTR tagging for multi-round tool responses. - Per-request serving is first-class: call `track()` inside your server factory. Queues, exporters and diagnostics initialize once and are shared across instances. - Architecture is a shared pure engine plus thin per-era adapters, replacing the v1 monkey-patch overrides. Reliability - Full exception detail on tool errors is recovered on every era through a per-call inner tap, isolated by `ContextVar` so parallel calls can never read each other's exception. - `redact_sensitive_information` now actually runs on the publish path. - Real-HTTP e2e suites across four deployment topologies, cross-flavor behavior-parity suites, and a 25-way concurrency proof per flavor. Breaking changes - Session machinery, identity caches and identify events are removed. Correlation flows through explicit `session_id` handles. See MIGRATION.md. - `AgentCatOptions.stateless` is gone; agent tracking is opt-in. - `identify`, `event_tags`, `event_properties` and `resolve_session_id` receive the tool call's request PARAMS, not the enclosing request. - `publish_custom_event` takes verbatim session IDs; `CustomEventData.session_id` replaces session references. - Community FastMCP 2.x is no longer supported. --- .github/scripts/discover_versions.py | 146 ++ .github/workflows/mcp-compatibility.yml | 273 ++-- .../mcp-prerelease-compatibility.yml | 140 +- CONTRIBUTING.md | 146 +- MIGRATION.md | 186 ++- README.md | 140 +- ...26-08-01-python-sdk-v2-explicit-handles.md | 1364 +++++++++++++++++ ...26-08-01-mcp-2026-07-28-python-v2-audit.md | 445 ++++++ ...1-python-sdk-v2-explicit-handles-design.md | 466 ++++++ pyproject.toml | 23 +- src/agentcat/__init__.py | 527 +++++-- src/agentcat/modules/__init__.py | 13 - src/agentcat/modules/adapters/__init__.py | 11 + src/agentcat/modules/adapters/_common.py | 123 ++ src/agentcat/modules/adapters/_inner_tap.py | 390 +++++ src/agentcat/modules/adapters/community.py | 813 ++++++++++ src/agentcat/modules/adapters/lowlevel_v1.py | 521 +++++++ src/agentcat/modules/adapters/lowlevel_v2.py | 599 ++++++++ src/agentcat/modules/callpath.py | 316 ++++ src/agentcat/modules/client_identity.py | 103 ++ src/agentcat/modules/compatibility.py | 262 ---- src/agentcat/modules/constants.py | 46 +- src/agentcat/modules/context_parameters.py | 56 - src/agentcat/modules/detection.py | 191 +++ src/agentcat/modules/event_queue.py | 45 +- src/agentcat/modules/exceptions.py | 44 +- src/agentcat/modules/exporters/otlp.py | 2 +- src/agentcat/modules/exporters/sentry.py | 2 +- src/agentcat/modules/handles.py | 318 ++++ src/agentcat/modules/identify.py | 49 +- src/agentcat/modules/injection.py | 381 +++++ src/agentcat/modules/internal.py | 165 +- .../overrides/community/monkey_patch.py | 201 --- .../overrides/community/tool_manager.py | 177 --- .../overrides/community_v3/__init__.py | 11 - .../overrides/community_v3/integration.py | 94 -- .../overrides/community_v3/middleware.py | 499 ------ src/agentcat/modules/overrides/mcp_server.py | 329 ---- .../overrides/official/monkey_patch.py | 583 ------- src/agentcat/modules/redaction.py | 55 +- src/agentcat/modules/request_extra.py | 15 + src/agentcat/modules/session.py | 200 --- src/agentcat/modules/tools.py | 51 +- src/agentcat/modules/version_detection.py | 48 - src/agentcat/types.py | 187 ++- src/agentcat/utils.py | 14 + tests/community/__init__.py | 2 +- .../test_community_dynamic_tracking.py | 412 ----- .../community/test_community_event_capture.py | 375 ----- tests/community/test_community_fastmcp.py | 191 --- .../test_community_report_missing.py | 404 ----- .../community/test_community_tool_context.py | 583 ------- .../test_community_tracking_timing.py | 382 ----- .../test_community_v3_event_serialization.py | 137 +- tests/community/test_community_v3_handles.py | 1156 ++++++++++++++ .../test_community_v3_inject_context.py | 137 +- tests/community/test_community_v3_openapi.py | 180 +-- .../test_community_v3_runtime_state_tools.py | 85 +- tests/conftest.py | 52 + tests/e2e/community_v2/conftest.py | 100 -- tests/e2e/community_v2/test_identify_http.py | 58 - .../community_v2/test_request_extra_http.py | 40 - tests/e2e/community_v3/conftest.py | 27 +- .../community_v3/test_event_capture_http.py | 67 +- tests/e2e/community_v3/test_identify_http.py | 76 +- .../community_v3/test_request_extra_http.py | 49 +- tests/e2e/community_v3/test_stateless_http.py | 89 +- tests/e2e/community_v4/__init__.py | 1 + tests/e2e/community_v4/conftest.py | 97 ++ tests/e2e/community_v4/test_session_http.py | 155 ++ tests/e2e/community_v4/test_stateless_http.py | 92 ++ tests/e2e/official/conftest.py | 7 + tests/e2e/official/test_event_capture_http.py | 21 +- tests/e2e/official/test_identify_http.py | 34 +- tests/e2e/official/test_redaction_http.py | 34 +- tests/e2e/official/test_request_extra_http.py | 20 +- tests/e2e/official/test_session_http.py | 94 +- tests/e2e/official/test_stateless_http.py | 109 +- .../__init__.py | 0 tests/e2e/official_modern/conftest.py | 70 + .../official_modern/test_mcpserver_http.py | 101 ++ .../e2e/official_modern/test_session_http.py | 162 ++ .../official_modern/test_stateless_http.py | 82 + tests/test_api_base_url.py | 78 +- tests/test_callpath.py | 694 +++++++++ tests/test_client_identity.py | 111 ++ tests/test_community_v4_handles.py | 843 ++++++++++ tests/test_concurrency_handles.py | 190 +++ tests/test_constants_copy.py | 198 +++ tests/test_context_parameters.py | 389 ----- tests/test_customer_owned_parameters.py | 160 ++ tests/test_detection.py | 336 ++++ tests/test_diagnostics_export.py | 7 +- tests/test_diagnostics_test_env.py | 9 +- tests/test_dynamic_tracking.py | 431 ++---- tests/test_event_capture_completeness.py | 73 +- tests/test_event_queue.py | 208 ++- tests/test_event_tags_properties.py | 29 +- tests/test_exceptions.py | 62 +- tests/test_exporter_sdk_version.py | 27 + tests/test_handles.py | 451 ++++++ tests/test_identify_shape.py | 131 ++ tests/test_injection.py | 527 +++++++ tests/test_inner_tap.py | 1303 ++++++++++++++++ tests/test_lowlevel_v1_handles.py | 677 ++++++++ tests/test_lowlevel_v2_handles.py | 1312 ++++++++++++++++ tests/test_mcp_version_compatibility.py | 37 - tests/test_multiple_servers.py | 15 +- tests/test_options_v2.py | 14 + tests/test_publish_custom_event.py | 447 ++++++ tests/test_rebuild_on_demand.py | 253 +++ tests/test_redaction.py | 104 +- tests/test_removed_events.py | 90 ++ tests/test_report_missing.py | 40 +- tests/test_request_extra.py | 110 +- tests/test_response_shape.py | 77 + tests/test_session.py | 426 ----- tests/test_session_id_validation.py | 443 ++++++ tests/test_stateless.py | 200 --- tests/test_tool_context.py | 971 +++++------- tests/test_truncation.py | 6 + tests/test_truncation_json_safe.py | 6 +- tests/test_utils/__init__.py | 31 + tests/test_utils/client.py | 19 +- tests/test_utils/community_openapi_server.py | 21 +- tests/test_utils/delivery.py | 73 + tests/test_utils/flavors.py | 695 +++++++++ tests/test_utils/modern_server.py | 144 ++ tests/test_utils/todo_server.py | 30 +- 129 files changed, 20612 insertions(+), 8337 deletions(-) create mode 100644 .github/scripts/discover_versions.py create mode 100644 docs/superpowers/plans/2026-08-01-python-sdk-v2-explicit-handles.md create mode 100644 docs/superpowers/specs/2026-08-01-mcp-2026-07-28-python-v2-audit.md create mode 100644 docs/superpowers/specs/2026-08-01-python-sdk-v2-explicit-handles-design.md create mode 100644 src/agentcat/modules/adapters/__init__.py create mode 100644 src/agentcat/modules/adapters/_common.py create mode 100644 src/agentcat/modules/adapters/_inner_tap.py create mode 100644 src/agentcat/modules/adapters/community.py create mode 100644 src/agentcat/modules/adapters/lowlevel_v1.py create mode 100644 src/agentcat/modules/adapters/lowlevel_v2.py create mode 100644 src/agentcat/modules/callpath.py create mode 100644 src/agentcat/modules/client_identity.py delete mode 100644 src/agentcat/modules/compatibility.py delete mode 100644 src/agentcat/modules/context_parameters.py create mode 100644 src/agentcat/modules/detection.py create mode 100644 src/agentcat/modules/handles.py create mode 100644 src/agentcat/modules/injection.py delete mode 100644 src/agentcat/modules/overrides/community/monkey_patch.py delete mode 100644 src/agentcat/modules/overrides/community/tool_manager.py delete mode 100644 src/agentcat/modules/overrides/community_v3/__init__.py delete mode 100644 src/agentcat/modules/overrides/community_v3/integration.py delete mode 100644 src/agentcat/modules/overrides/community_v3/middleware.py delete mode 100644 src/agentcat/modules/overrides/mcp_server.py delete mode 100644 src/agentcat/modules/overrides/official/monkey_patch.py delete mode 100644 src/agentcat/modules/session.py delete mode 100644 src/agentcat/modules/version_detection.py delete mode 100644 tests/community/test_community_dynamic_tracking.py delete mode 100644 tests/community/test_community_event_capture.py delete mode 100644 tests/community/test_community_fastmcp.py delete mode 100644 tests/community/test_community_report_missing.py delete mode 100644 tests/community/test_community_tool_context.py delete mode 100644 tests/community/test_community_tracking_timing.py create mode 100644 tests/community/test_community_v3_handles.py delete mode 100644 tests/e2e/community_v2/conftest.py delete mode 100644 tests/e2e/community_v2/test_identify_http.py delete mode 100644 tests/e2e/community_v2/test_request_extra_http.py create mode 100644 tests/e2e/community_v4/__init__.py create mode 100644 tests/e2e/community_v4/conftest.py create mode 100644 tests/e2e/community_v4/test_session_http.py create mode 100644 tests/e2e/community_v4/test_stateless_http.py rename tests/e2e/{community_v2 => official_modern}/__init__.py (100%) create mode 100644 tests/e2e/official_modern/conftest.py create mode 100644 tests/e2e/official_modern/test_mcpserver_http.py create mode 100644 tests/e2e/official_modern/test_session_http.py create mode 100644 tests/e2e/official_modern/test_stateless_http.py create mode 100644 tests/test_callpath.py create mode 100644 tests/test_client_identity.py create mode 100644 tests/test_community_v4_handles.py create mode 100644 tests/test_concurrency_handles.py create mode 100644 tests/test_constants_copy.py delete mode 100644 tests/test_context_parameters.py create mode 100644 tests/test_customer_owned_parameters.py create mode 100644 tests/test_detection.py create mode 100644 tests/test_handles.py create mode 100644 tests/test_identify_shape.py create mode 100644 tests/test_injection.py create mode 100644 tests/test_inner_tap.py create mode 100644 tests/test_lowlevel_v1_handles.py create mode 100644 tests/test_lowlevel_v2_handles.py delete mode 100644 tests/test_mcp_version_compatibility.py create mode 100644 tests/test_options_v2.py create mode 100644 tests/test_publish_custom_event.py create mode 100644 tests/test_rebuild_on_demand.py create mode 100644 tests/test_removed_events.py create mode 100644 tests/test_response_shape.py delete mode 100644 tests/test_session.py create mode 100644 tests/test_session_id_validation.py delete mode 100644 tests/test_stateless.py create mode 100644 tests/test_utils/delivery.py create mode 100644 tests/test_utils/flavors.py create mode 100644 tests/test_utils/modern_server.py diff --git a/.github/scripts/discover_versions.py b/.github/scripts/discover_versions.py new file mode 100644 index 0000000..be9e176 --- /dev/null +++ b/.github/scripts/discover_versions.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python3 +"""Pick the upstream versions a compatibility matrix should test. + +Replaces the `pip index versions | grep | sort -V` pipelines the two +compatibility workflows used to carry. Three reasons it is Python: + +- `sort -V` is not PEP 440. Measured: it sorts `4.0.0b1` AFTER `4.0.0`, where + PEP 440 puts a prerelease BEFORE the release it leads to. So "latest" off + `sort -V | tail -1` could name a superseded prerelease as the newest version. +- `pip index versions` is an experimental command that prints a deprecation + banner to stderr and has no stable output contract. +- A range like `>=1.2,<3` is one specifier here instead of hand-rolled + major/minor arithmetic that has to be re-derived every time a bound moves. + +Usage: + discover_versions.py # stable releases + discover_versions.py --pre # prereleases only + +Specifier gotcha, and why the prerelease callers pass `a0`: PEP 440 orders +`4.0.0b1 < 4.0.0`, so `>=4.0` EXCLUDES every 4.0.0 prerelease and a `--pre` +run against it silently finds nothing. `>=4.0.0a0` is the lowest bound that +admits the whole 4.0.0 prerelease series. + +Stable mode emits the newest patch of every minor in range — one matrix leg per +minor, which is the granularity upstream breaks things at. + +Prerelease mode emits at most one version: the newest prerelease in range that +no stable release has superseded. A prerelease older than the latest stable is +not an early warning about anything, it is history, so `mcp 2.0.0rc1` drops out +the day `mcp 2.0.0` ships and that job goes back to skipping itself. This is +what keeps the prerelease workflow pointed at the NEXT generation without a +hardcoded version number to bump. + +Writes GitHub Actions step outputs (`versions=[...]`, `has-versions=...`) to +stdout, for appending to $GITHUB_OUTPUT. +""" + +from __future__ import annotations + +import argparse +import json +import sys +import urllib.error +import urllib.request + +from packaging.specifiers import SpecifierSet +from packaging.version import InvalidVersion, Version + +PYPI_JSON = "https://pypi.org/pypi/{package}/json" +TIMEOUT_SECONDS = 30 + + +def fetch_releases(package: str) -> dict[str, list[dict[str, object]]]: + """Every release of `package` from PyPI's JSON API, mapped to its files.""" + url = PYPI_JSON.format(package=package) + try: + with urllib.request.urlopen(url, timeout=TIMEOUT_SECONDS) as response: + payload = json.load(response) + except (urllib.error.URLError, json.JSONDecodeError, TimeoutError) as exc: + print(f"::error::Could not read {url}: {exc}", file=sys.stderr) + raise SystemExit(1) from exc + releases = payload.get("releases") + if not isinstance(releases, dict): + print(f"::error::{url} returned no releases map", file=sys.stderr) + raise SystemExit(1) + return releases + + +def installable(files: object) -> bool: + """True when a release still has at least one file nobody has yanked. + + PyPI keeps an entry for deleted and fully-yanked releases, and pinning one + fails the install rather than reporting an incompatibility — so a matrix + leg for it would be noise that looks exactly like a real failure. + """ + if not isinstance(files, list) or not files: + return False + return any(not entry.get("yanked", False) for entry in files) + + +def parse_versions(releases: dict[str, list[dict[str, object]]]) -> list[Version]: + parsed = [] + for raw, files in releases.items(): + if not installable(files): + continue + try: + parsed.append(Version(raw)) + except InvalidVersion: + continue + return parsed + + +def latest_per_minor(versions: list[Version]) -> list[Version]: + newest: dict[tuple[int, int], Version] = {} + for version in versions: + key = (version.major, version.minor) + if key not in newest or version > newest[key]: + newest[key] = version + return [newest[key] for key in sorted(newest)] + + +def select(package: str, specifier: str, prerelease: bool) -> list[Version]: + all_versions = parse_versions(fetch_releases(package)) + # `prereleases=True` on both sides: the default would silently drop every + # prerelease from an in-range check, which is exactly what we filter on. + in_range = [v for v in all_versions if SpecifierSet(specifier).contains(v, True)] + + if not prerelease: + return latest_per_minor([v for v in in_range if not v.is_prerelease]) + + candidates = [v for v in in_range if v.is_prerelease] + stable = [v for v in all_versions if not v.is_prerelease] + if stable: + newest_stable = max(stable) + candidates = [v for v in candidates if v > newest_stable] + return [max(candidates)] if candidates else [] + + +def main() -> int: + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("package") + parser.add_argument("specifier", help="PEP 440 range, e.g. '>=1.2,<3'") + parser.add_argument( + "--pre", + action="store_true", + dest="prerelease", + help="emit the newest un-superseded prerelease instead of stables", + ) + args = parser.parse_args() + + selected = select(args.package, args.specifier, args.prerelease) + rendered = json.dumps([str(v) for v in selected], separators=(",", ":")) + + channel = "prerelease" if args.prerelease else "stable" + print( + f"Selected {len(selected)} {args.package} {channel} version(s) " + f"for {args.specifier}: {rendered}", + file=sys.stderr, + ) + print(f"versions={rendered}") + print(f"has-versions={'true' if selected else 'false'}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/.github/workflows/mcp-compatibility.yml b/.github/workflows/mcp-compatibility.yml index f6ae2df..20c4c0f 100644 --- a/.github/workflows/mcp-compatibility.yml +++ b/.github/workflows/mcp-compatibility.yml @@ -10,6 +10,17 @@ on: - cron: '0 0 * * *' workflow_dispatch: +# The two generations agentcat 2.x supports, as PEP 440 ranges. `mcp` spans +# both majors from one dependency (1.x lowlevel/FastMCP and 2.x +# lowlevel/MCPServer are four adapters behind one `track()`); `fastmcp` starts +# at 3.0 because agentcat>=2 dropped community FastMCP 2.x outright — a 2.x +# server is classified, refused and returned untracked on purpose, so there is +# nothing for a compatibility leg to assert. That is also why the old `2.9.*` +# carve-out is gone rather than moved: the whole 2.x line is out of range now. +env: + MCP_RANGE: ">=1.2,<3" + FASTMCP_RANGE: ">=3.0,<5" + jobs: discover-mcp-versions: runs-on: ubuntu-latest @@ -17,35 +28,18 @@ jobs: mcp-versions: ${{ steps.get-mcp-versions.outputs.versions }} steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Get available MCP versions id: get-mcp-versions run: | - # Get all available versions from PyPI - versions=$(pip index versions mcp 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | sort -V) - - # Filter to versions >= 1.2.0 and get only latest patch version for each minor - declare -A latest_minor - for version in $versions; do - major=$(echo $version | cut -d. -f1) - minor=$(echo $version | cut -d. -f2) - patch=$(echo $version | cut -d. -f3) - - # Include if version >= 1.2.0 - if [ "$major" -gt 1 ] || ([ "$major" -eq 1 ] && [ "$minor" -ge 2 ]); then - minor_key="$major.$minor" - latest_minor[$minor_key]="$version" - fi - done - - # Create JSON array from latest versions - filtered_versions=() - for version in "${latest_minor[@]}"; do - filtered_versions+=(\"$version\") - done - - json_array="[$(IFS=,; echo "${filtered_versions[*]}")]" - echo "Found MCP versions: $json_array" - echo "versions=$json_array" >> $GITHUB_OUTPUT + python -m pip install --quiet --disable-pip-version-check packaging + python .github/scripts/discover_versions.py mcp "$MCP_RANGE" >> "$GITHUB_OUTPUT" discover-fastmcp-versions: runs-on: ubuntu-latest @@ -53,41 +47,84 @@ jobs: fastmcp-versions: ${{ steps.get-fastmcp-versions.outputs.versions }} steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Get available FastMCP versions id: get-fastmcp-versions run: | - # Get all available versions from PyPI - versions=$(pip index versions fastmcp 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+' | sort -V) - - # Filter to versions >= 2.7.0, exclude 2.9.*, and get only latest patch version for each minor - declare -A latest_minor - for version in $versions; do - major=$(echo $version | cut -d. -f1) - minor=$(echo $version | cut -d. -f2) - patch=$(echo $version | cut -d. -f3) - - # Skip 2.9.* versions (known compatibility issues) - if [ "$major" -eq 2 ] && [ "$minor" -eq 9 ]; then - echo "Skipping FastMCP $version (2.9.* versions have known issues)" - continue - fi - - # Include if version >= 2.7.0 - if [ "$major" -gt 2 ] || ([ "$major" -eq 2 ] && [ "$minor" -ge 7 ]); then - minor_key="$major.$minor" - latest_minor[$minor_key]="$version" - fi - done - - # Create JSON array from latest versions - filtered_versions=() - for version in "${latest_minor[@]}"; do - filtered_versions+=("\"$version\"") - done - - json_array="[$(IFS=,; echo "${filtered_versions[*]}")]" - echo "Found FastMCP versions: $json_array" - echo "versions=$json_array" >> $GITHUB_OUTPUT + python -m pip install --quiet --disable-pip-version-check packaging + python .github/scripts/discover_versions.py fastmcp "$FASTMCP_RANGE" >> "$GITHUB_OUTPUT" + + # The shipped dual-generation configuration, exactly as a customer gets it: + # no version pinning, just the two mutually exclusive dependency groups from + # pyproject. The discovery matrices below sweep what upstream has PUBLISHED; + # this job is the one that proves what we RESOLVE TO still works, and it is + # the only place the modern generation's full suite runs on a schedule. + # + # Both legs run the whole suite. `tests/conftest.py` gates collection on the + # installed `mcp` major, so each leg selects its own subset — there is no + # per-leg test path to keep in sync here. + test-dependency-groups: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + include: + - generation: legacy + group: mcp-legacy + excluded: mcp-modern + - generation: modern + group: mcp-modern + excluded: mcp-legacy + + steps: + - uses: actions/checkout@v4 + + - name: Install uv + uses: astral-sh/setup-uv@v4 + with: + version: "latest" + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + + - name: Install the ${{ matrix.generation }} generation + run: | + uv sync --extra community \ + --no-group ${{ matrix.excluded }} --group ${{ matrix.group }} + + - name: Show installed versions + run: | + uv pip show mcp | grep "Version:" || echo "MCP not found" + uv pip show fastmcp | grep "Version:" || echo "FastMCP not found" + + - name: Run the full suite (${{ matrix.generation }}) + run: | + set -o pipefail + uv run --no-sync pytest -q 2>&1 | tee pytest.log + + - name: Collect failure details + if: failure() + env: + PACKAGE_UNDER_TEST: dependency-group + PACKAGE_VERSION: ${{ matrix.group }} + run: | + python .github/scripts/collect_failure.py pytest.log + + - name: Upload failure artifact + if: failure() + uses: actions/upload-artifact@v4 + with: + name: compat-failure-group-${{ matrix.group }} + path: failure.json + retention-days: 7 test-fastmcp-compatibility: runs-on: ubuntu-latest @@ -110,27 +147,50 @@ jobs: with: python-version: '3.12' - - name: Update pyproject.toml with FastMCP ${{ matrix.fastmcp-version }} + - name: Pin the community extra to FastMCP ${{ matrix.fastmcp-version }} run: | - # Update the community extras section with the specific FastMCP version - sed -i -E 's/"fastmcp[>=]+[^"]+"/\"fastmcp==${{ matrix.fastmcp-version }}\"/' pyproject.toml - - # Also update the MCP dependency to be flexible so FastMCP can choose its version - # Remove the strict MCP version constraint and use >=1.2.0 - sed -i -E 's/"mcp[>=]+[^"]+"/\"mcp>=1.2.0\"/' pyproject.toml - - # Show the updated dependencies for verification - echo "Updated dependencies:" - grep -A 5 "^dependencies = \[" pyproject.toml + # Both edits are ADDRESS-SCOPED to one table. Since Task 1 there are + # three `fastmcp` pins and three `mcp` pins in this file — the community + # extra plus the `mcp-legacy` / `mcp-modern` dependency groups — and an + # unscoped `s/"fastmcp[>=]+[^"]+"/.../` rewrites all of them. That + # breaks resolution outright: the group pins are what make the two + # generations coherent, and `fastmcp-slim` (4.x's runtime package, and + # not matched by that pattern) would be left demanding 4.x while + # `fastmcp` was pinned to 3.x. + # + # This job installs no dependency group at all (see the install step), + # so the groups are left exactly as committed and only the two tables + # that actually drive this resolution are touched. + sed -i -E '/^community = \[/,/^\]/ s/"fastmcp[^"]*"/"fastmcp==${{ matrix.fastmcp-version }}"/' pyproject.toml + + # Widen the base `mcp` floor so FastMCP picks whichever generation it + # needs. The `<3` ceiling stays: outside it we have no adapter. + sed -i -E '/^dependencies = \[/,/^\]/ s/"mcp[<>=!~][^"]*"/"mcp>=1.2.0,<3"/' pyproject.toml + + echo "Updated [project] dependencies:" + sed -n '/^dependencies = \[/,/^\]/p' pyproject.toml echo "" - echo "Updated community extras:" - grep -A 2 "^\[project.optional-dependencies\]" pyproject.toml | grep -A 2 "community" + echo "Updated community extra:" + sed -n '/^community = \[/,/^\]/p' pyproject.toml + echo "" + echo "Dependency groups (must be UNCHANGED):" + sed -n '/^\[dependency-groups\]/,/^\[/p' pyproject.toml - name: Install dependencies with FastMCP ${{ matrix.fastmcp-version }} run: | - # Install with both dev and community extras - # Let FastMCP determine which MCP version it needs - uv sync --extra dev --extra community + # `uv pip install`, NOT `uv sync`. `uv sync` locks before it installs, + # and locking is universal: it has to satisfy every declared dependency + # group even for groups it will not install, so `--no-default-groups` + # does not save it. Measured — pinning `fastmcp==3.4.5` and syncing + # fails with "agentcat:mcp-modern depends on fastmcp>=4.0.0b1,<5 and + # agentcat[community] depends on fastmcp==3.4.5 ... unsatisfiable". + # + # A pip-style install reads only `[project]` and its extras. PEP 735 + # groups are opt-in there, so the pin above is the only thing choosing + # a FastMCP and FastMCP is the only thing choosing an mcp — which is + # exactly this job's premise. + uv venv --python 3.12 + uv pip install -e ".[dev,community]" - name: Show installed versions run: | @@ -142,7 +202,9 @@ jobs: run: | echo "Running community FastMCP tests with version ${{ matrix.fastmcp-version }}" set -o pipefail - uv run pytest -v 2>&1 | tee pytest.log + # `--no-sync`: plain `uv run` would re-sync the env from the lockfile + # and undo the pinned install above. + uv run --no-sync pytest -v 2>&1 | tee pytest.log - name: Collect failure details if: failure() @@ -183,24 +245,21 @@ jobs: - name: Install dependencies with MCP ${{ matrix.mcp-version }} (no FastMCP) run: | - # Create virtual environment - uv venv + uv venv --python 3.12 - # Install base dependencies first - uv pip install pydantic>=2.0.0 requests>=2.31.0 agentcat-api==1.0.0 + # The project's own declared deps, rather than a hand-copied list that + # silently goes stale every time `[project] dependencies` moves. The + # `community` extra is deliberately omitted: this job's whole point is + # that agentcat works on official mcp alone. + uv pip install -e ".[dev]" - # Install the specific MCP version + # Then force the exact generation under test, overriding whatever the + # `>=1.2.0,<3` floor resolved to a moment ago. uv pip install "mcp==${{ matrix.mcp-version }}" - # Install dev dependencies for testing - uv pip install pytest>=7.0.0 pytest-asyncio>=0.21.0 mypy>=1.0.0 ruff>=0.1.0 freezegun>=1.2.0 - - # Explicitly uninstall fastmcp if it somehow got installed + # Belt and braces: nothing above should pull fastmcp in. uv pip uninstall fastmcp -y 2>/dev/null || true - # Install the package itself in editable mode - uv pip install -e . - - name: Show installed MCP version run: | echo "Installed MCP version:" @@ -218,9 +277,12 @@ jobs: - name: Run tests without community FastMCP run: | echo "Running tests with MCP ${{ matrix.mcp-version }} (no community FastMCP)" - # Run all tests except community tests + # `conftest.py` gates collection on the installed mcp major, so the + # right subset is selected for whichever generation this leg pinned. + # `--no-sync` so `uv run` cannot re-resolve from the lockfile and undo + # both the pin and the fastmcp-free premise this job just verified. set -o pipefail - uv run pytest -v 2>&1 | tee pytest.log + uv run --no-sync pytest -v 2>&1 | tee pytest.log - name: Collect failure details if: failure() @@ -240,7 +302,7 @@ jobs: send-failure-notification: runs-on: ubuntu-latest - needs: [discover-mcp-versions, discover-fastmcp-versions, test-fastmcp-compatibility, test-without-fastmcp] + needs: [discover-mcp-versions, discover-fastmcp-versions, test-dependency-groups, test-fastmcp-compatibility, test-without-fastmcp] if: failure() steps: @@ -482,7 +544,7 @@ jobs: report-compatibility: runs-on: ubuntu-latest - needs: [discover-mcp-versions, discover-fastmcp-versions, test-fastmcp-compatibility, test-without-fastmcp, send-failure-notification] + needs: [discover-mcp-versions, discover-fastmcp-versions, test-dependency-groups, test-fastmcp-compatibility, test-without-fastmcp, send-failure-notification] if: always() steps: @@ -498,30 +560,41 @@ jobs: echo "" echo "Generated on: $(date)" echo "" + echo "📋 SHIPPED DEPENDENCY GROUPS (the configuration customers get)" + echo "─────────────────────────────────────────" + echo "Legs: mcp-legacy (mcp 1.x + fastmcp 3.x), mcp-modern (mcp 2.x + fastmcp 4.x)" + echo "Tests run: the full suite on each leg; tests/conftest.py gates" + echo " collection on the installed mcp major, so each leg" + echo " automatically selects its own era's subset." + echo "" echo "📋 OFFICIAL MCP COMPATIBILITY (without community FastMCP)" echo "─────────────────────────────────────────" + echo "Range swept: ${MCP_RANGE}" echo "MCP versions tested: ${{ needs.discover-mcp-versions.outputs.mcp-versions }}" - echo "Tests run: All tests except community FastMCP tests" + echo "Tests run: the full suite, minus whatever conftest gates out" echo "Python version: 3.12" echo "" echo "📋 COMMUNITY FASTMCP COMPATIBILITY TESTING" echo "─────────────────────────────────────────" + echo "Range swept: ${FASTMCP_RANGE} (2.x is unsupported by agentcat>=2)" echo "FastMCP versions tested: ${{ needs.discover-fastmcp-versions.outputs.fastmcp-versions }}" echo "MCP version: Determined by each FastMCP version's requirements" - echo "Tests run: Community FastMCP tests only" echo "Python version: 3.12" echo "" - echo "🧪 TEST COVERAGE" + echo "🧪 SERVER SHAPES COVERED" echo "─────────────────────────────────────────" - echo "✓ Official FastMCP (mcp.server.fastmcp) compatibility" - echo "✓ Community FastMCP (fastmcp package) compatibility - optional dependency" - echo "✓ Low-level Server compatibility" - echo "✓ All implementations tested with is_compatible_server function" - echo "✓ Package works without community FastMCP (using only official MCP)" + echo "✓ Official mcp 1.x — low-level Server and mcp.server.fastmcp.FastMCP" + echo "✓ Official mcp 2.x — low-level server and MCPServer" + echo "✓ Community FastMCP 3.x and 4.x (the agentcat[community] extra)" + echo "✓ Community FastMCP 2.x — refused and returned untracked, by design" + echo "✓ Package works without community FastMCP (official MCP alone)" echo "" echo "📦 INSTALLATION OPTIONS" echo "─────────────────────────────────────────" - echo "• pip install agentcat - Official MCP only (includes mcp.server.fastmcp)" + echo "• pip install agentcat - Official MCP only. Resolves the" + echo " newest mcp in >=1.2.0,<3, i.e. 2.x," + echo " which has NO mcp.server.fastmcp;" + echo " pin 'mcp<2' if you need that module." echo "• pip install agentcat[community] - Adds community FastMCP support" echo "" echo "📊 RESULTS" diff --git a/.github/workflows/mcp-prerelease-compatibility.yml b/.github/workflows/mcp-prerelease-compatibility.yml index 3919561..d55bb60 100644 --- a/.github/workflows/mcp-prerelease-compatibility.yml +++ b/.github/workflows/mcp-prerelease-compatibility.yml @@ -11,58 +11,65 @@ on: required: false type: string +# The prerelease CHANNELS this workflow watches — the generation after each +# package's current stable line, which is where a breaking change lands first. +# +# The `a0` floors are load-bearing, not decoration. PEP 440 orders +# `4.0.0b1 < 4.0.0`, so a bound of `>=4.0` excludes every 4.0.0 prerelease and +# this workflow would find nothing while reporting success. `>=4.0.0a0` is the +# lowest bound that admits the whole prerelease series. +# +# Discovery emits nothing once a stable release supersedes the channel (see +# `discover_versions.py --pre`), and the jobs below are already gated on +# `has-prereleases`, so a generation that ships simply stops being tested here +# instead of pinning CI to a version that no longer matters. Move these floors +# forward when the NEXT generation opens. +env: + MCP_PRERELEASE_RANGE: ">=2.0.0a0,<3" + FASTMCP_PRERELEASE_RANGE: ">=4.0.0a0,<5" + jobs: discover-mcp-prereleases: runs-on: ubuntu-latest outputs: mcp-prereleases: ${{ steps.get-mcp-prereleases.outputs.versions }} - has-prereleases: ${{ steps.get-mcp-prereleases.outputs.has-prereleases }} + has-prereleases: ${{ steps.get-mcp-prereleases.outputs.has-versions }} steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Get available MCP prerelease versions id: get-mcp-prereleases run: | - # Get all available versions from PyPI including prereleases - all_versions=$(pip index versions mcp --pre 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+[ab][0-9]\+\|[0-9]\+\.[0-9]\+\.[0-9]\+rc[0-9]\+' | sort -V || echo "") - - if [ -z "$all_versions" ]; then - echo "No MCP prereleases found" - echo "versions=[]" >> $GITHUB_OUTPUT - echo "has-prereleases=false" >> $GITHUB_OUTPUT - else - # Get only the latest prerelease - latest=$(echo "$all_versions" | tail -n 1) - json_array="[\"$latest\"]" - echo "Found MCP prerelease: $json_array" - echo "versions=$json_array" >> $GITHUB_OUTPUT - echo "has-prereleases=true" >> $GITHUB_OUTPUT - fi + python -m pip install --quiet --disable-pip-version-check packaging + python .github/scripts/discover_versions.py --pre \ + mcp "$MCP_PRERELEASE_RANGE" >> "$GITHUB_OUTPUT" discover-fastmcp-prereleases: runs-on: ubuntu-latest outputs: fastmcp-prereleases: ${{ steps.get-fastmcp-prereleases.outputs.versions }} - has-prereleases: ${{ steps.get-fastmcp-prereleases.outputs.has-prereleases }} + has-prereleases: ${{ steps.get-fastmcp-prereleases.outputs.has-versions }} steps: + - uses: actions/checkout@v4 + + - name: Set up Python 3.12 + uses: actions/setup-python@v5 + with: + python-version: '3.12' + - name: Get available FastMCP prerelease versions id: get-fastmcp-prereleases run: | - # Get all available versions from PyPI including prereleases - all_versions=$(pip index versions fastmcp --pre 2>/dev/null | grep -o '[0-9]\+\.[0-9]\+\.[0-9]\+[ab][0-9]\+\|[0-9]\+\.[0-9]\+\.[0-9]\+rc[0-9]\+' | sort -V || echo "") - - if [ -z "$all_versions" ]; then - echo "No FastMCP prereleases found" - echo "versions=[]" >> $GITHUB_OUTPUT - echo "has-prereleases=false" >> $GITHUB_OUTPUT - else - # Get only the latest prerelease - latest=$(echo "$all_versions" | tail -n 1) - json_array="[\"$latest\"]" - echo "Found FastMCP prerelease: $json_array" - echo "versions=$json_array" >> $GITHUB_OUTPUT - echo "has-prereleases=true" >> $GITHUB_OUTPUT - fi + python -m pip install --quiet --disable-pip-version-check packaging + python .github/scripts/discover_versions.py --pre \ + fastmcp "$FASTMCP_PRERELEASE_RANGE" >> "$GITHUB_OUTPUT" test-fastmcp-prerelease: runs-on: ubuntu-latest @@ -86,31 +93,41 @@ jobs: with: python-version: '3.12' - - name: Update pyproject.toml with prerelease FastMCP ${{ matrix.fastmcp-version }} + - name: Pin the community extra to FastMCP ${{ matrix.fastmcp-version }} run: | - # Update the community extras section with the specific FastMCP prerelease version - sed -i -E 's/"fastmcp[>=]+[^"]+"/\"fastmcp==${{ matrix.fastmcp-version }}\"/' pyproject.toml - - # Keep MCP flexible so FastMCP can choose its version - sed -i -E 's/"mcp[>=]+[^"]+"/\"mcp>=1.2.0\"/' pyproject.toml - - # Show the updated dependencies for verification - echo "Updated dependencies:" - grep -A 5 "^dependencies = \[" pyproject.toml + # Address-scoped to one table each. Since Task 1 there are three + # `fastmcp` pins and three `mcp` pins in this file — the community + # extra plus the `mcp-legacy` / `mcp-modern` dependency groups — and an + # unscoped substitution rewrites all of them, leaving `fastmcp-slim` + # (4.x's runtime package, which the old pattern did not match) pinned + # to a generation the rewritten `fastmcp` no longer agrees with. + sed -i -E '/^community = \[/,/^\]/ s/"fastmcp[^"]*"/"fastmcp==${{ matrix.fastmcp-version }}"/' pyproject.toml + + # Widen the base `mcp` floor so the prerelease FastMCP picks whichever + # generation it needs; the `<3` ceiling stays. + sed -i -E '/^dependencies = \[/,/^\]/ s/"mcp[<>=!~][^"]*"/"mcp>=1.2.0,<3"/' pyproject.toml + + echo "Updated [project] dependencies:" + sed -n '/^dependencies = \[/,/^\]/p' pyproject.toml echo "" - echo "Updated community extras:" - grep -A 2 "^\[project.optional-dependencies\]" pyproject.toml | grep -A 2 "community" + echo "Updated community extra:" + sed -n '/^community = \[/,/^\]/p' pyproject.toml - name: Install dependencies with prerelease FastMCP ${{ matrix.fastmcp-version }} run: | - # Install with both dev and community extras, allow prereleases. - # FastMCP will determine which MCP version it needs. - # Use --prerelease=allow (not if-necessary-or-explicit): FastMCP 3.4+ + # `uv pip install`, NOT `uv sync`: syncing locks first, and locking is + # universal — it must satisfy every declared dependency group, so the + # committed `mcp-modern` pin collides with whatever this leg pinned and + # resolution fails before a single test runs. A pip-style install reads + # only `[project]` and its extras (PEP 735 groups are opt-in there). + # + # `--prerelease=allow`, not if-necessary-or-explicit: FastMCP 3.4+ # splits into fastmcp + a transitive fastmcp-slim package. Pinning a # prerelease fastmcp pulls a matching prerelease fastmcp-slim that is # not named in our pyproject, so if-necessary-or-explicit refuses it # and resolution fails. "allow" is correct for a prerelease-testing job. - uv sync --extra dev --extra community --prerelease allow + uv venv --python 3.12 + uv pip install -e ".[dev,community]" --prerelease allow - name: Show installed versions run: | @@ -125,7 +142,9 @@ jobs: run: | echo "Running community FastMCP tests with prerelease version ${{ matrix.fastmcp-version }}" set -o pipefail - uv run pytest -v 2>&1 | tee pytest.log + # `--no-sync`: plain `uv run` re-resolves from the lockfile and would + # undo the pinned prerelease install above. + uv run --no-sync pytest -v 2>&1 | tee pytest.log - name: Collect failure details if: failure() @@ -167,24 +186,19 @@ jobs: - name: Install dependencies with prerelease MCP ${{ matrix.mcp-version }} (no FastMCP) run: | - # Create virtual environment - uv venv + uv venv --python 3.12 - # Install base dependencies first - uv pip install pydantic>=2.0.0 requests>=2.31.0 agentcat-api==1.0.0 + # The project's own declared deps rather than a hand-copied list that + # goes stale whenever `[project] dependencies` moves. No `community` + # extra: this job proves agentcat works on official mcp alone. + uv pip install -e ".[dev]" - # Install the specific MCP prerelease version + # Then force the exact prerelease under test. uv pip install "mcp==${{ matrix.mcp-version }}" --prerelease=allow - # Install dev dependencies for testing - uv pip install pytest>=7.0.0 pytest-asyncio>=0.21.0 mypy>=1.0.0 ruff>=0.1.0 freezegun>=1.2.0 - - # Explicitly uninstall fastmcp if it somehow got installed + # Belt and braces: nothing above should pull fastmcp in. uv pip uninstall fastmcp -y 2>/dev/null || true - # Install the package itself in editable mode - uv pip install -e . - - name: Verify FastMCP is not installed run: | if uv pip show fastmcp 2>/dev/null; then @@ -207,7 +221,9 @@ jobs: echo "Running tests with prerelease MCP version ${{ matrix.mcp-version }} (no FastMCP)" # Run all tests except community tests set -o pipefail - uv run pytest -v 2>&1 | tee pytest.log + # `--no-sync`: plain `uv run` re-resolves from the lockfile and would + # undo the pinned prerelease install above. + uv run --no-sync pytest -v 2>&1 | tee pytest.log - name: Collect failure details if: failure() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0ad3f50..028d789 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,9 +10,9 @@ Thank you for your interest in contributing to AgentCat! We're excited to have y git clone https://github.com/YOUR-USERNAME/agentcat-python-sdk.git cd agentcat-python-sdk ``` -3. **Install dependencies** using uv: +3. **Install dependencies** using uv (see [Dev environments](#dev-environments) for the legacy variant): ```bash - uv sync + uv sync --extra community ``` 4. **Create a branch** for your feature or fix: ```bash @@ -21,21 +21,63 @@ Thank you for your interest in contributing to AgentCat! We're excited to have y git checkout -b fix/your-bug-fix ``` +## Dev Environments + +AgentCat v2 supports two generations of the MCP ecosystem: the official `mcp` package 1.x and 2.x, and community `fastmcp` 3.x and 4.x. The two `mcp` majors cannot be installed side by side, so development uses two mutually exclusive uv dependency groups, declared as conflicting in `pyproject.toml`: + +- `mcp-modern` — `mcp` 2.x + `fastmcp` 4.x (the default group) +- `mcp-legacy` — `mcp` 1.x + `fastmcp` 3.x + +**Modern environment (default):** + +```bash +uv sync --extra community +``` + +**Legacy environment** (turn off the default modern group, turn on legacy): + +```bash +uv sync --extra community --no-group mcp-modern --group mcp-legacy +``` + +Note that a bare `uv run` re-syncs to the default (modern) environment, which would silently undo a legacy sync. Once you have synced the generation you want, run against it with `--no-sync`: + +```bash +uv run --no-sync pytest +``` + +**Both generations are expected to pass.** `tests/conftest.py` reads the installed `mcp` major at collection time and skips the modules that target the other generation, so the same `pytest` invocation selects the right subset in either environment — there is nothing to pass by hand. At the time of writing that is 576 passed / 26 skipped on modern and 732 passed / 10 skipped on legacy. CI runs both legs in the `test-dependency-groups` job of `mcp-compatibility.yml`, so a change that only works in the generation you developed in will be caught there. + ## Development Process ### Making Changes 1. **Write your code** following our Python standards 2. **Add tests** for new features (required for feature additions) -3. **Run the test suite** to ensure everything passes: +3. **Run the test suite** to ensure everything passes, in the generation you + synced: ```bash - uv run pytest + uv run --no-sync pytest ``` + `--no-sync`: a bare `uv run` re-syncs to the default (modern) groups and + silently undoes a legacy sync. Both generations are expected to pass — see + [Dev Environments](#dev-environments). 4. **Check your code** meets our standards: ```bash - uv run ruff check . # Run linting checks - uv run ruff format . # Format code + uvx ruff check . # lint the whole repo + git diff --name-only main -- '*.py' | xargs -r uvx ruff format --check ``` + `uvx`, not `uv run` — see [Code Quality](#code-quality) for why. And + `--check`, scoped to the files you touched: 46 files in this repo are + unformatted, so a bare `uvx ruff format .` rewrites all of them and buries + your change in an unrelated 46-file diff. Reformatting debt you did not + create is welcome as [its own PR](#the-linttype-debt-and-the-ratchet). + + **`xargs -r`, not `$(…)`.** With no path arguments `ruff format` defaults to + `.` — so on a branch that has touched no Python (a docs change, or before + you have made any), the substitution expands to nothing and the command + becomes exactly the whole-repo rewrite this step exists to avoid. `-r` skips + the run instead. ### Commit Conventions @@ -97,29 +139,98 @@ Looking for a place to start? Check out issues labeled [`good first issue`](http ## Testing - New features **should include tests** to ensure reliability -- Run tests locally with `uv run pytest` +- Run tests locally with `uv run --no-sync pytest`, in the generation you synced - We use [pytest](https://docs.pytest.org/) for our test suite - Test files should be placed in the `tests/` directory with `test_*.py` naming convention ## Code Quality -Before submitting your PR, ensure your code passes all checks: - ```bash -# Run tests -uv run pytest +# Run tests — this IS gated in CI. `--no-sync` keeps the generation you synced. +uv run --no-sync pytest # Check code style and linting -uv run ruff check . +uvx ruff check . + +# Check formatting (the whole repo; 46 files already fail — see the ratchet) +uvx ruff format --check . -# Format code -uv run ruff format . +# Format only what you changed. `xargs -r`, never `$(…)`: with no path +# arguments ruff formats `.`, so an empty expansion silently rewrites all 46. +git diff --name-only main -- '*.py' | xargs -r uvx ruff format -# Type checking (if applicable) -uv run mypy src/agentcat --ignore-missing-imports +# Type checking +uvx mypy src/agentcat ``` -Our CI will run these same checks on your PR. +**`uvx`, not `uv run`, for the last three.** `ruff` and `mypy` are declared only +in the `dev` *extra*, and no default sync installs an extra — +`[tool.uv] default-groups` selects the `dev` dependency *group*, which holds +`freezegun`, `pytest-asyncio` and `pytest-cov`. So `uv run ruff check .` fails +with `ruff: command not found` in a normally-synced checkout. `uvx` fetches the +tool on demand and needs no environment change, which also keeps these commands +safe to run in either dependency generation. + +One consequence worth knowing: `uvx mypy` runs *without* the project's +dependencies, so a handful of its findings are import-resolution noise rather +than real type errors. `uvx --with pydantic mypy src/agentcat` removes the +largest chunk of it. The table below reports the plain `uvx mypy` number, so +the commands above reproduce it exactly. + +Note that a bare `uv run pytest` syncs the environment to the **default** +groups first, which is the modern generation (`mcp` 2.x + `fastmcp` 4.x). To +run the legacy generation's suite, sync it explicitly — see +[Dev Environments](#dev-environments) — and then use `uv run --no-sync`. + +**Only the tests are gated.** Neither workflow in `.github/workflows/` mentions +ruff or mypy at all, so a lint or type finding will not fail your PR today. +That is what makes the rule below a convention rather than a check. + +### The lint/type debt, and the ratchet + +Neither tool has ever been clean on this repo, and turning either into a +blocking gate would fail every PR on pre-existing findings. Measured on +`feat/explicit-handles-v2` (`uvx ruff check .`, `uvx mypy src/agentcat`, which +reads the `strict = true` in `pyproject.toml`): + +| Check | `main` | this branch | +| --- | --- | --- | +| `ruff check .` | 515 | 259 | +| `ruff format --check .` | 57 files | 46 files | +| `mypy src/agentcat` | 80 in 23 files | 53 in 15 files | + +Reproduce them with the three `uvx` commands under [Code Quality](#code-quality), +`ruff format --check .` included — that row counts files the formatter *would* +rewrite, which is why it is the `--check` form and not the rewriting one. + +The standing rule is a **ratchet, not a gate: a change may not add findings.** +Compare rule-by-rule against `main` rather than eyeballing the totals — a patch +that fixes ten `E501`s and introduces one `B904` has gone backwards even though +the count fell. Cleaning up debt you did not create is welcome as its own PR, +where it can be reviewed as such. + +Most of what remains is mechanical: `UP006`/`UP045` (pre-PEP-585/604 typing +spellings), `E501`, `I001` import ordering, and untyped test helpers. + +Measure both sides the same way. Roughly 3 of the 53 mypy findings are the +import-resolution noise described above, so a `uvx mypy` number and a +`uvx --with pydantic mypy` number are not comparable to each other — mixing +them invents an improvement, or hides a regression, that is purely an artifact +of the invocation. + +## Release dependencies outside this repo + +Some changes here are only half-shipped until another repo moves. Check these +before cutting a release: + +- **`agentcat-go-api/api/openapi.yaml` is missing the `agentcat:custom` + `event_type` enum entry.** `publish_custom_event` emits that type, and the + backend has accepted it since TS 2.0, but the generated `agentcat-api` client + still validates against the older enum. This SDK works around it by + overriding the validator (`Event.event_type_validate_enum` in + `src/agentcat/types.py`) — **any other consumer of that spec stays broken + until the enum entry lands.** Adding it upstream lets the override be + deleted. ## Dependencies @@ -141,7 +252,6 @@ agentcat-python-sdk/ │ ├── types.py # Type definitions │ └── utils.py # Utility functions ├── tests/ # Test files -├── examples/ # Example usage ├── docs/ # Documentation └── dist/ # Built distributions (generated) ``` diff --git a/MIGRATION.md b/MIGRATION.md index 3f85276..bae06b1 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -1,3 +1,187 @@ +# Migrating `agentcat` 1.x to 2.0 — Explicit handles replace MCP session correlation + +MCP protocol 2026-07-28 (SEP-2567) removed protocol-level sessions, so AgentCat now correlates work with two explicit, server-minted handles that agents echo back as tool parameters: + +- `session_id` — one goal, start to finish. Subagents share their parent's session_id. It is stored in the existing `session_id` event field with the same `ses_` prefix, so dashboards, queries, saved filters, and exporters are unaffected. **No backend migration.** +- `agent_id` — one per agent; subagents get their own. Rides on events as the `agentcat_agent_id` tag. Off by default — opt in with `enable_agent_tracking=True`. + +### This changes your tools' public interface + +Upgrading takes no configuration, but it does change what your MCP server publishes to its callers. These are your schemas and your responses — review them before you roll out. + +**Every tracked tool's input schema gains** `session_id` — type `string`, optional. Agents echo it back on later calls, and AgentCat strips it before your handler runs. + +```diff + { + "name": "search_orders", + "inputSchema": { + "type": "object", + "properties": { + "query": { "type": "string" }, ++ "session_id": { "type": "string", "description": "REQUIRED on every call after your first…" } + } + } + } +``` + +`additionalProperties: false` **is removed** from tracked input schemas. If you declared it deliberately to reject unknown parameters, that constraint no longer appears in the schema AgentCat publishes. + +**With** `enable_agent_tracking=True`**,** `agent_id` **is added to the schema's** `required` **array.** This is the one addition a strict client will enforce — a schema-validating MCP client refuses to send a call that omits it. Server-side enforcement is soft: a call without `agent_id` still succeeds, and the event is simply published without agent identity. This is why agent tracking is off by default. + +**Tools with a plain-object** `outputSchema` **gain an optional** `_mcp_instructions` **property**, so validating clients accept the handle mirrored into `structuredContent`. Schemas built from `oneOf` / `allOf` / `anyOf` have no single properties bag to extend and are skipped — mint-back stays content-only there. + +**Responses that mint a handle gain a trailing** `[MCP INSTRUCTIONS]:` **text block.** It is wire-only: recorded event responses and error messages contain only your tool's own output. The same block appears when an agent sends a `session_id` this server never issued, correcting it without handing out a replacement. + +**Tools that already declare** `session_id`**,** `agent_id`**, or** `context` **keep their own parameter.** No injection happens for that name on that tool, and the value reaches your handler untouched. `agent_id` and `context` log a warning; `session_id` logs an **error**, once per tool, because it costs you correlation on that tool. + +AgentCat also stops treating that name as its own there, which is what you want and worth stating plainly: a tool whose `session_id` is *yours* — a ticket ID, a job ID, a row key — never becomes the analytics handle, and is never confirmed back to the agent. Those calls publish **without a session** rather than with a minted one: a fresh handle per call on a tool that can never carry it manufactures a phantom session per call, which looks like data and is not. The practical consequence: **calls to a tool with its own `session_id` are not correlated with each other.** If you want them correlated, either rename your parameter or supply the handle yourself with `resolve_session_id`, which injects nothing anywhere and reads no arguments at all — your parameter stays entirely yours. + +**AgentCat honors only handles it issued.** A supplied `session_id` that is not a `ses_` KSUID from this server is rejected rather than adopted: the call publishes without a session, tagged `agentcat_session_id_source=invalid`, and the agent is told to re-send the ID it was given (or to omit the parameter and be issued one). `Event.session_id` is exempt from `redact_sensitive_information` and from `redact_event`, so a value AgentCat did not mint could not be redacted after the fact — which is exactly why it is never written there. + +One caveat on all of the above: it depends on a `tools/list` having run. A call arriving at an instance that never served a listing rebuilds the registry from your list source; only if *that* fails does it fall back to treating all three names as AgentCat's. + +### Most integrations need no code changes + +`track(server, project_id, options)` keeps its signature, and `AgentCatOptions` is additive apart from one removal (`stateless`, below). Every 1.x option keeps its name: `identify`, `redact_sensitive_information`, `exporters`, `enable_report_missing`, `enable_tracing`, `enable_tool_call_context`, `custom_context_description`, `event_tags`, `event_properties`, `debug_mode`, `api_base_url`, and `disable_diagnostics`. + +Three of them changed *behavior*, and all three are covered below: `identify` and the other request hooks receive a different object ([the hook argument](#the-hook-argument-changed)), `identify` / `event_tags` / `event_properties` now run at different points in the call ([behavior changes](#behavior-changes-worth-knowing)), and `redact_sensitive_information` now actually runs. + +If your integration is a bare `track(server, "proj_...")` with no callbacks, upgrading is a version bump. Handles are injected and stripped inside the SDK, so your tool handlers never see the extra parameters, and handles keep landing in the `session_id` field with the `ses_` prefix — your existing dashboards, queries, and exporter pipelines keep working untouched. If you pass callbacks, read the two sections above first: both changes are one-line edits, but both are silent if you skip them. + +```bash +pip install --pre --upgrade "agentcat>=2" +# or, for Jlowin's/Prefect's FastMCP support: +pip install --pre --upgrade "agentcat[community]>=2" +``` + +`--pre` while 2.x is a prerelease; drop it once a stable 2.0.0 ships. (Plain `pip install agentcat` skips prereleases entirely and resolves the 1.x line.) + +### Update your code only if… + +**You pass** `AgentCatOptions(stateless=...)`**.** The option is gone, along with its auto-detection. Every handle, actor, and client identity is now resolved per request from the request itself, so a stateless server and a stateful one take exactly the same code path — there is nothing left to configure. Passing it raises `TypeError` from the dataclass constructor; delete the argument. + +```diff +- agentcat.track(server, "proj_abc", AgentCatOptions(stateless=True)) ++ agentcat.track(server, "proj_abc") +``` + +If you set it because you run stateless HTTP, also read the note on header-derived `client_name` under [Behavior changes worth knowing](#behavior-changes-worth-knowing) — that is the one place where stateless deployments see a visible difference. + +**You run community FastMCP 2.x.** `agentcat>=2` supports FastMCP 3.x and 4.x. On a 2.x server, `track()` logs a warning to `~/agentcat.log` and returns your server **untracked** — it does not raise, and your server keeps serving. Either upgrade FastMCP or pin `agentcat<2`, which stays published and keeps working. + +```bash +pip install "agentcat<2" # staying on FastMCP 2.x +``` + +**You built dashboards on** `mcp:initialize`**,** `mcp:tools/list`**, or** `agentcat:identify` **events.** None of the three is published anymore. `tools/list` is still intercepted — that is how schema injection happens — it just emits no event. The actor your `identify` hook returns now rides on **every** tool-call event (`identify_actor_given_id`, `identify_actor_name`, `identify_data`), so requery against the tool-call events themselves. + +**You import** `EventType`**.** It has two members: `MCP_TOOLS_CALL` (`"mcp:tools/call"`) and `AGENTCAT_CUSTOM` (`"agentcat:custom"`). Everything else was removed. + +**You import** `AgentCatData`**,** `SessionInfo` **or** `ToolRegistration`**.** `SessionInfo` and `ToolRegistration` are gone. `AgentCatData` keeps `project_id` and `options`; its session and patching bookkeeping — `session_id`, `session_info`, `last_activity`, `is_stateless`, `tool_registry`, `wrapped_tools`, `monkey_patched`, `tracker_initialized` — is gone, replaced by per-request resolution. Most integrations never reference these types. + +**You import from** `agentcat.modules.session`**,** `agentcat.modules.compatibility`**,** `agentcat.modules.version_detection`**,** `agentcat.modules.context_parameters`**, or anything under** `agentcat.modules.overrides`**.** All of them were deleted, the whole `overrides` package included — monkey-patching is gone, replaced by the adapters in `agentcat.modules.adapters`. The top-level names those modules exported went with them: `override_lowlevel_mcp_server`, `get_session_info`, `new_session_id`, `COMPATIBILITY_ERROR_MESSAGE`, `is_compatible_server`, `is_community_fastmcp_v2`, `is_community_fastmcp_v3`, `is_official_fastmcp_server`, `add_context_parameter_to_schema` and `add_context_parameter_to_tools`. Server classification lives in `agentcat.modules.detection` (`detect_server(server).flavor`), and there is no session module because there are no sessions. + +**Your** `identify`**,** `event_tags`**,** `event_properties` **or** `resolve_session_id` **hook reads** `request.params`**.** Drop the hop — it is `request.arguments` and `request.name` now. This one fails silently; see [The hook argument changed](#the-hook-argument-changed). + +**You set** `redact_sensitive_information`**.** The hook never actually ran in 1.x. It does now — check that yours is narrow enough before you upgrade. See [Behavior changes worth knowing](#behavior-changes-worth-knowing). + +**You depend on** `track()` **raising.** It no longer does — see below. + +**You snapshot tool schemas in tests.** The schema additions above will fail exact-match assertions. Parameter order is: your params, `session_id`, `agent_id`, `context`. + +### The hook argument changed + +**Your** `identify`**,** `event_tags`**,** `event_properties` **and** `resolve_session_id` **callbacks now receive the tool call's request PARAMS, not the enclosing request.** 1.x built a synthetic request object with a `.params` attribute; 2.0 hands over the params model itself, which is the one shape all four adapters can produce — the official 2.x SDK gives its handler `(ctx, params)` with no request object anywhere, and community FastMCP's message is params too. + +```diff + def identify_user(request, extra): +- token = request.params.arguments["token"] ++ token = request.arguments["token"] + return UserIdentity(user_id=token, user_name=None, user_data=None) +``` + +**This fails silently if you miss it.** A hook that raises is caught, logged to `~/agentcat.log`, and treated as "no identity" — so an un-migrated `identify` does not break your server, it just publishes every event anonymously. Grep your hooks for `.params` before you roll out, or run once with `AgentCatOptions(debug_mode=True)` and check the log. + +`extra` is unchanged in spirit — it is the request context your framework exposes — but it is your adapter's own object, so keep reading it defensively (`getattr(getattr(extra, "request", None), "headers", {}) or {}`) as the examples here do. + +### Behavior changes worth knowing + +- **`track()` never raises.** A missing `project_id` with no exporters, an unsupported server generation, or an object AgentCat cannot recognize is logged to `~/agentcat.log` and returns your server untracked. 1.x raised `ValueError`/`TypeError` from `track()`; if you wrapped the call in `try`/`except` to keep a bad config from taking your server down, that guard is now redundant. If you *relied* on the exception to fail your startup loudly, check `~/agentcat.log` (or run with `AgentCatOptions(debug_mode=True)`) instead. +- **`identify` now runs on every tool call**, and its result is stamped directly on that call's event. There is no identity cache and no `agentcat:identify` event. If your hook does a database or API lookup, it is now on the hot path for every call — add your own caching if that matters for your latency budget. +- **`event_tags` and `event_properties` now resolve _after_ your tool handler returns.** They receive the same `(request, extra)` pair as before, but they see a later snapshot: 1.x resolved them before invoking the tool, 2.0 resolves them while building the event that reports the finished call. If your callback reads request-scoped context that your framework tears down when the handler exits (a scoped DB session, a context-local that a middleware closes, a request object your ASGI stack recycles), it may now observe a closed or mutated context. Failures degrade to "no tags/properties on that event" — the callback's exception is logged and swallowed, never raised into your tool. If your hooks read anything request-scoped, capture what you need eagerly rather than lazily. +- **`client_name` / `client_version` are no longer derived from HTTP headers.** 1.x fell back to parsing the `user-agent` header and reading `x-mcp-client-name` / `x-mcp-client-version`. 2.0 resolves client identity from three per-request sources only: the reserved `io.modelcontextprotocol/clientInfo` metadata key (2026-era clients), the same key passed through `_meta`, and the `clientInfo` your client sent at `initialize`. **If your callers are identified only by headers — the common case for pre-2026 clients on stateless HTTP, where each request gets a fresh session that never handshakes — `client_name` will start arriving empty on your events.** Nothing else about those events changes, and tool calls are unaffected. Two ways forward: have your clients send `clientInfo` at `initialize` (any stateful HTTP or stdio transport), or attach the header yourself with `event_tags`, which puts it on every event and is filterable in the dashboard: + + ```python + from agentcat import AgentCatOptions + + def client_tag(request, extra): + headers = getattr(getattr(extra, "request", None), "headers", {}) or {} + name = headers.get("x-mcp-client-name") or headers.get("user-agent") + return {"client": name} if name else None + + agentcat.track(server, "proj_abc", AgentCatOptions(event_tags=client_tag)) + ``` + +- **`redact_sensitive_information` now actually runs.** In 1.x the hook was configured, documented, and never invoked on a published event: the redactor walked `str`/`list`/`dict` and was handed the event *model*, so it returned it untouched. 2.0 fixes that, which means a hook you set in 1.x starts taking effect the moment you upgrade. It runs on every string in the event — `parameters`, `response`, `user_intent`, `client_name`, `server_name` and the rest — except the fields AgentCat needs to attribute the event: `session_id`, `id`, `project_id`, `event_type`, `resource_name`, `actor_id`, the three `identify_*` fields, and your own `tags` and `properties`. **If your hook is an aggressive catch-all** (`lambda s: "[REDACTED]"`), it will now blank fields your dashboards read, such as `client_name`. Narrow it to the patterns you actually care about before upgrading. A hook that raises drops the event rather than publishing it unredacted, and an async hook is supported. +- **MCP `extra.sessionId` is ignored entirely**, and inactivity-based session rollover is gone. The transport's `mcp-session-id` still rides along untouched under `parameters.extra.sessionId` on each event if you need it. + +### Bringing your own session IDs + +If you already track your own session or correlation IDs, plug yours in and AgentCat will not prompt the agent about `session_id` at all — no parameter is injected and no instructions are added to your tool descriptions: + +```python +import agentcat +from agentcat import AgentCatOptions + +def session_from_header(request, extra): + headers = getattr(getattr(extra, "request", None), "headers", {}) or {} + return headers.get("x-correlation-id") + +agentcat.track(server, "proj_abc", AgentCatOptions(resolve_session_id=session_from_header)) +``` + +The returned string is combined with your project ID into a deterministic `ses_` handle, so the same correlation ID always maps to the same session. The hook may be sync or async and receives the same `(request, extra)` pair as `identify`. Returning `None` or raising mints a fresh handle silently — a configured hook should answer every request. + +### Publishing your own events + +`publish_custom_event` records work that is not a tool call — a background job, a webhook, a checkout step — against a session: + +```python +import agentcat + +agentcat.publish_custom_event(server, "proj_abc", { + "session_id": current_session_id, + "resource_name": "checkout", + "message": "order confirmed", +}) +``` + +The session ID is used **verbatim** — never validated, derived or reformatted, because this is your deliberate server-side call and not an agent's guess — and events published without one land without a session. The first argument may also be a session-ID string instead of a tracked server. Events are typed `agentcat:custom`, are fire-and-forget, and never raise. + +**A server tracked with `enable_tracing=False` publishes no custom events.** Turning tracing off silences this entry point exactly as it silences tool-call events, so a server you deliberately muted does not start emitting a new event type. The session-ID-string form has no options to consult and always publishes. + +### Known limitations in 2.0.0b1 + +- **Multi-round tool calls that mint their own handle land on separate sessions.** If a tool call spans several round trips and the *first* round is what mints the handle, each round is attributed to its own session instead of one shared session. The other two modes correlate correctly and are protocol-enforced: supplying `session_id` yourself, or deriving it with a `resolve_session_id` hook. If your server relies on multi-round tool calls, prefer one of those two. +- **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and the upstream returns an error result, no Python exception is raised locally, so the event records the message without a stack trace. Errors raised by your own tool code are unaffected. + +### Supported versions + +| Runtime | Supported | Notes | +| --- | --- | --- | +| Official MCP SDK (`mcp`) 1.x | ✅ | Low-level `Server` and `mcp.server.fastmcp.FastMCP` | +| Official MCP SDK (`mcp`) 2.x | ✅ | Low-level server and `MCPServer` | +| Community FastMCP (`fastmcp`) 3.x | ✅ | Requires the `agentcat[community]` extra | +| Community FastMCP (`fastmcp`) 4.x | ✅ | Requires the `agentcat[community]` extra | +| Community FastMCP (`fastmcp`) 2.x | ❌ | Logged and returned untracked — pin `agentcat<2` | +| Python | 3.10+ | Unchanged | + +One `track()` call handles every supported shape; AgentCat classifies the server it is handed and installs the matching adapter. A shape it does not recognize is logged with a diagnostic fingerprint and returned untracked. + +> **Installing into a fresh environment resolves `mcp` 2.x**, which removed `mcp.server.fastmcp`. AgentCat's dependency is `mcp>=1.2.0,<3` and both generations are supported, so an existing project that pins `mcp<2` is unaffected — but a `pip install agentcat` into an empty environment will give you the 2.x line, where the 1.x `from mcp.server.fastmcp import FastMCP` import does not exist. Pin `mcp<2` if you need it. + +--- + # Migrating from `mcpcat` to `agentcat` MCPcat is now **AgentCat** — same team, same product, new name. The PyPI package has been renamed from `mcpcat` to [`agentcat`](https://pypi.org/project/agentcat/), starting fresh at `v1.0.0`. @@ -25,7 +209,7 @@ If you never touch your integration, nothing stops working. Migrate on your own | Debug logging | `MCPCAT_DEBUG_MODE` | `AGENTCAT_DEBUG_MODE` (no fallback) | | Local log file | `~/mcpcat.log` | `~/agentcat.log` | -There are no other API changes — `track()`, its options, the `identify` and redaction hooks, and the telemetry exporters all work exactly as before. +There are no other API changes in the rename itself — `track()`, its options, the `identify` and redaction hooks, and the telemetry exporters all work exactly as before. (Going from 1.x to 2.0 is a separate step, covered at the top of this document.) > **Note:** `agentcat` does not install a `mcpcat` compatibility module — a shim would collide with the real `mcpcat` distribution when both are installed. The import rename is required. diff --git a/README.md b/README.md index cab7954..0e5d84d 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,10 @@

> [!IMPORTANT] -> **MCPcat is now AgentCat** 🐱 — same team, same product, new name. This package was previously published as [`mcpcat`](https://pypi.org/project/mcpcat/), which keeps working forever, but new features land here. Upgrading takes a few minutes — see the [migration guide](./MIGRATION.md). +> **AgentCat 2.0 is here.** MCP 2026-07-28 removed protocol-level sessions, so AgentCat now correlates work with an explicit `session_id` handle that agents echo back as a tool parameter. Handles land in the same `session_id` event field with the same `ses_` prefix, so your dashboards and exporters are unaffected — but tracked tools gain a `session_id` parameter, `AgentCatOptions.stateless` is gone, and FastMCP 2.x is no longer supported. Read the [1.x → 2.0 migration guide](https://github.com/agentcathq/agentcat-python-sdk/blob/main/MIGRATION.md) before upgrading a production server. + +> [!IMPORTANT] +> **MCPcat is now AgentCat** 🐱 — same team, same product, new name. This package was previously published as [`mcpcat`](https://pypi.org/project/mcpcat/), which keeps working forever, but new features land here. Upgrading takes a few minutes — see the [migration guide](https://github.com/agentcathq/agentcat-python-sdk/blob/main/MIGRATION.md). > [!NOTE] > Looking for the TypeScript SDK? Check it out here [agentcat-typescript](https://github.com/agentcathq/agentcat-typescript-sdk). @@ -35,12 +38,25 @@ This SDK also provides a free and simple way to forward telemetry like logs, tra ```bash # Basic installation (includes official MCP SDK) -pip install agentcat +pip install --pre agentcat # With Jlowin's/Prefect's FastMCP support -pip install "agentcat[community]" +pip install --pre "agentcat[community]" ``` +`--pre` is required while 2.x is a prerelease: without it pip skips +`2.0.0b1` and resolves the 1.x line instead, which has none of the features +documented below. Drop the flag once a stable 2.0.0 ships. + +One `track()` call covers every supported server shape: + +| Runtime | Supported | +| --- | --- | +| Official MCP SDK (`mcp`) 1.x — low-level `Server` and `mcp.server.fastmcp.FastMCP` | ✅ | +| Official MCP SDK (`mcp`) 2.x — low-level server and `MCPServer` | ✅ | +| Community FastMCP (`fastmcp`) 3.x and 4.x | ✅ (`agentcat[community]`) | +| Community FastMCP (`fastmcp`) 2.x | ❌ pin `agentcat<2` | + To learn more about us, check us out [here](https://agentcat.com) ## Why use AgentCat? 🤔 @@ -63,22 +79,72 @@ Once you have your project ID, integrate AgentCat into your MCP server: ```python import agentcat -from mcp.server import FastMCP +from mcp.server.mcpserver import MCPServer # official MCP SDK 2.x + +server = MCPServer("echo-mcp") + +agentcat.track(server, "proj_0000000") +``` + +On the official SDK's 1.x line the server class is `mcp.server.fastmcp.FastMCP` instead; everything after it is identical. + +```python +import agentcat +from mcp.server.fastmcp import FastMCP # official MCP SDK 1.x -server = FastMCP(name="echo-mcp", version="1.0.0") +server = FastMCP("echo-mcp") agentcat.track(server, "proj_0000000") ``` +> [!NOTE] +> A fresh `pip install` resolves `mcp` **2.x**, where `mcp.server.fastmcp` no longer exists — the 1.x snippet above only runs on a checkout that already pins `mcp<2`. AgentCat supports both generations from one install; which import you use is decided by the `mcp` you have, not by AgentCat. + +`track()` classifies whatever object you hand it and installs the matching adapter, so the same call covers a low-level `Server`, either official facade, and community FastMCP. It **never raises** — a shape AgentCat does not support is logged to `~/agentcat.log` and your server comes back untracked rather than failing to start. + +### Session handles: how work is correlated + +MCP 2026-07-28 removed protocol-level sessions, so AgentCat correlates a series of calls with an explicit **session handle** instead. Tracked tools gain an optional `session_id` string parameter; AgentCat mints one on the first call, tells the agent to echo it back, and strips it out again before your handler runs. Your tool signatures and your handler code are untouched. + +AgentCat honors only handles it issued. A `session_id` that is not a `ses_` KSUID this server minted is rejected rather than adopted — the call publishes without a session and the agent is told to re-send the ID it was given, or to omit the parameter and be issued one. That keeps a hallucinated value, or an auth token a client auto-populated into a parameter of the same name, out of the event field your redaction hook cannot reach. + +**If one of your own tools already declares a** `session_id` **parameter,** AgentCat leaves it alone: your value reaches your handler untouched and is never read as a handle. Calls to that tool publish **without a session**, so they cannot be correlated, and an `ERROR` naming the tool goes to `~/agentcat.log`. If you already manage sessions, pass `resolve_session_id` — AgentCat then derives its own handle from your identifier and stops injecting `session_id` entirely. + +Handles land in the existing `session_id` event field with the same `ses_` prefix, so dashboards, saved filters, and exporters carry over unchanged. See the [migration guide](https://github.com/agentcathq/agentcat-python-sdk/blob/main/MIGRATION.md) for exactly what this adds to your published schemas. + +### Track inside your server factory + +`track()` mutates the server instance it is given, so it has to run on the *same* instance that serves traffic. If you build servers in a factory — the usual shape for tests, for multi-tenant hosting, or for a per-worker server — call `track()` inside the factory, on the instance you are about to return: + +```python +import agentcat +from mcp.server.mcpserver import MCPServer + +def create_server() -> MCPServer: + server = MCPServer("echo-mcp") + + @server.tool() + def echo(text: str) -> str: + return text + + agentcat.track(server, "proj_0000000") + return server +``` + +Tools registered *after* `track()` are picked up automatically — there is no need to re-track, and calling `track()` twice on one server is safe (the most recent options win). + ### Identifying users -You can identify your user sessions with a simple callback AgentCat exposes, called `identify`. +You can identify the actor behind a call with a simple callback AgentCat exposes, called `identify`. It runs on **every** tool call and its result is stamped on that call's event, so keep it cheap — add your own caching if it does a database or API lookup. ```python from agentcat import AgentCatOptions, UserIdentity def identify_user(request, extra): - user = myapi.get_user(request.params.arguments.token) + # `request` is the tool call's PARAMS on every server flavor: `.name` and + # `.arguments`, one hop, not two. `arguments` is a plain dict — index it, + # don't reach for an attribute. + user = myapi.get_user(request.arguments["token"]) return UserIdentity( user_id=user.id, user_name=user.name, @@ -90,6 +156,52 @@ def identify_user(request, extra): agentcat.track(server, "proj_0000000", AgentCatOptions(identify=identify_user)) ``` +### Bringing your own session IDs + +If you already have a correlation ID — a trace ID, a job ID, a header your gateway sets — hand it to AgentCat with `resolve_session_id` and no `session_id` parameter is injected into your tools at all: + +```python +import agentcat +from agentcat import AgentCatOptions + +def session_from_header(request, extra): + headers = getattr(getattr(extra, "request", None), "headers", {}) or {} + return headers.get("x-correlation-id") + +agentcat.track(server, "proj_0000000", AgentCatOptions(resolve_session_id=session_from_header)) +``` + +The string you return is combined with your project ID into a deterministic `ses_` handle, so the same correlation ID always maps to the same session. The hook may be sync or async, receives the same `(request, extra)` pair as `identify`, and returning `None` (or raising) quietly mints a fresh handle instead. + +### Tracking individual agents + +Set `enable_agent_tracking=True` to also distinguish *which* agent is working — subagents get their own identity while sharing their parent's session. This adds an `agent_id` parameter to your tools and, unlike `session_id`, marks it **required**, which schema-validating clients will enforce. That is why it is off by default. + +```python +import agentcat +from agentcat import AgentCatOptions + +agentcat.track(server, "proj_0000000", AgentCatOptions(enable_agent_tracking=True)) +``` + +Agent identity rides on events as the `agentcat_agent_id` tag. A call that omits `agent_id` still succeeds — the event is simply published without it. + +### Publishing your own events + +Not everything worth seeing on the timeline is a tool call. `publish_custom_event` records background jobs, webhooks, or checkout steps against a session: + +```python +import agentcat + +agentcat.publish_custom_event(server, "proj_0000000", { + "session_id": "ses_2cOHEO0LYGADMzRvWTXXVbbgxgm", + "resource_name": "checkout", + "message": "order confirmed", +}) +``` + +The first argument may be a tracked server or a bare session-ID string. `session_id` is used **verbatim** — never validated, derived or reformatted, since it is your deliberate server-side call rather than an agent's guess — and an event published without one lands untethered to any session. Events are typed `agentcat:custom`, are fire-and-forget, and never raise. A server tracked with `enable_tracing=False` publishes nothing here either. + ### Redacting sensitive data AgentCat redacts all data sent to its servers and encrypts at rest, but for additional security, it offers a hook to do your own redaction on all text data returned back to our servers. @@ -97,13 +209,14 @@ AgentCat redacts all data sent to its servers and encrypts at rest, but for addi ```python from agentcat import AgentCatOptions -# Sync version -def redact_sync(text): +def redact(text): return custom_redact(text) -agentcat.track(server, "proj_0000000", AgentCatOptions(redact_sensitive_information=redact_sync)) +agentcat.track(server, "proj_0000000", AgentCatOptions(redact_sensitive_information=redact)) ``` +The hook may be sync or async. It runs on every string in the event except the fields AgentCat needs to attribute it — the session handle, the event, project and resource IDs, the actor your `identify` hook returned, and your own tags and properties. If it raises, the event is dropped rather than published unredacted. + ### Forwarding data to existing observability platforms AgentCat seamlessly integrates with your existing observability stack, providing automatic logging and tracing without the tedious setup typically required. Export telemetry data to multiple platforms simultaneously: @@ -143,6 +256,13 @@ agentcat.track( Learn more about our free and open source [telemetry integrations](https://docs.agentcat.com/telemetry/integrations). +### Known limitations + +Two behaviors are worth knowing before you read your first dashboard. Both are deliberate for `2.0.0b1`. + +- **Multi-round tool calls that mint their own handle land on separate sessions.** When a tool call runs several round trips and the *first* round is what mints the handle, each round is attributed to its own session rather than one shared session. Supplying a `session_id` yourself, or deriving one with `resolve_session_id`, correlates the rounds correctly — those two modes are protocol-enforced. Only the mint-on-first-round case is affected. +- **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and that upstream returns an error result, there is no local Python exception to read, so the event records the error message without a stack trace. Errors raised by your own tool code are unaffected and carry full detail. + ### Internal diagnostics To help us catch and fix broken installs, the SDK sends AgentCat a small, anonymized diff --git a/docs/superpowers/plans/2026-08-01-python-sdk-v2-explicit-handles.md b/docs/superpowers/plans/2026-08-01-python-sdk-v2-explicit-handles.md new file mode 100644 index 0000000..5a6f231 --- /dev/null +++ b/docs/superpowers/plans/2026-08-01-python-sdk-v2-explicit-handles.md @@ -0,0 +1,1364 @@ +# AgentCat Python SDK v2 — Explicit Handles Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +> **Superseded in part (2026-08-03).** Everything below calls the handle +> `task_id`. It is now **`session_id`** throughout — the old name collided with +> the MCP Task extension (`tasks/*`), and AgentCat's handle is not an MCP task. +> The rename is mechanical (`TASK_ID_PARAM` → `SESSION_ID_PARAM`, +> `agentcat_task_id_source` → `agentcat_session_id_source`, `resolve_task_id` → +> `resolve_session_id`, `derive_task_id` → `derive_session_id`, and so on), and +> the four frozen derivation vectors are unchanged. One behavior change came +> with it: AgentCat now honors only handles it issued — see +> `agentcat-typescript-sdk/docs/superpowers/specs/2026-08-02-session-id-validation-design.md` +> and `tests/test_session_id_validation.py`. Read this document for the +> architecture; read the code for the names. + +**Goal:** Upgrade `agentcat` to `2.0.0b1`: replace session machinery with stateless per-call `task_id`/`agent_id` handles (MCP 2026-07-28), supporting official MCP SDK 1.x + 2.x and community FastMCP 3.x + 4.x through one `track()` call. + +**Architecture:** Shared pure engine (`handles.py`, `injection.py`, `callpath.py`, `client_identity.py`, `detection.py`) + three thin adapters (`lowlevel_v1`, `lowlevel_v2`, `community`) replacing `modules/overrides/`. Spec: `docs/superpowers/specs/2026-08-01-python-sdk-v2-explicit-handles-design.md`. Behavior contract: `2026-07-28-cross-sdk-changelog.md` (Appendices A/B byte-authoritative). North star: `/Users/naseemalnaji/Projects/mcpcat/agentcat-typescript-sdk` @ `feat/explicit-handles-v2`. + +**Tech Stack:** Python ≥3.10, pydantic 2, `mcp` 1.x/2.x, `fastmcp` 3.x/4.x, uv (conflict groups), pytest + pytest-asyncio, ruff, mypy --strict, hatch. + +## Global Constraints + +- Agent-facing copy MUST be byte-identical to TS `src/modules/constants.ts` (em dashes, quotes, spacing included). Never reword. +- Golden derivation vectors are frozen: `("customer-abc","proj_1")→ses_2cOHEO0LYGADMzRvWTXXVbbgxgm`, `("customer-abc",None)→ses_2cZY3tvyI25O2AmL2CGVo2B1IIj`, `(" x ","p")→ses_2c3yR5mYKQdLaXsJNgZH6erbfQK`, `("x","p")→ses_2bw285VY9apdgUgTPXKFnT6P4G0`. +- `task_id` is stored in `Event.session_id` with the existing `ses_` prefix. No backend/wire changes. +- v2 publishes ONLY `mcp:tools/call` (+ `agentcat:custom`). No `mcp:initialize`, `mcp:tools/list`, `agentcat:identify` events anywhere. +- `track()` never raises. Failures log via `write_to_log` + return the server untracked. +- Never mutate customer objects: deep-copy schemas, clone requests before stripping, copy results before decorating. The published event carries the RAW request and the UNDECORATED response. +- No module-scope imports of version-specific `mcp`/`fastmcp` symbols in engine/detection modules (must import cleanly under both majors). Adapters may import inside functions. +- Private attributes of the SDKs are fair game (CI change detection covers drift). +- Deps: `mcp>=1.2.0,<3`, `pydantic>=2.0.0,<3`, community extra `fastmcp>=3.0.0,<5`, `requires-python>=3.10`. FastMCP 2.x is unsupported (log + return untracked). +- Style: ruff (88 cols), mypy `--strict` on `src/agentcat`, snake_case, `TypedDict` for shared shapes, Conventional Commits. +- Run tests with `uv run pytest -q` (default env = mcp-modern once Task 1 lands; use `uv sync --group mcp-legacy` env for legacy-only suites). Every task ends green in the env(s) it touches. + +--- + +### Task 1: Packaging & dual-generation dev environments + +**Files:** +- Modify: `pyproject.toml` +- Modify: `CONTRIBUTING.md` (dev-env section) + +**Interfaces:** +- Produces: uv dependency-groups `mcp-legacy` (mcp 1.x) and `mcp-modern` (mcp 2.x + fastmcp 4), mutually exclusive; version `2.0.0b1`. + +- [ ] **Step 1: Edit `pyproject.toml`** + +```toml +[project] +version = "2.0.0b1" +dependencies = [ + "mcp>=1.2.0,<3", + "agentcat-api==1.0.0", + "pydantic>=2.0.0,<3", + "requests>=2.31.0", +] + +[project.optional-dependencies] +community = [ + "fastmcp>=3.0.0,<5", +] +# dev extra unchanged + +[dependency-groups] +dev = [ + "freezegun>=1.5.2", + "pytest-asyncio>=1.0.0", + "pytest-cov>=6.1.1", +] +mcp-legacy = ["mcp>=1.2.0,<2", "fastmcp>=3.0.0,<4"] +mcp-modern = ["mcp>=2.0.0,<3", "fastmcp>=4.0.0b1,<5"] + +[tool.uv] +conflicts = [[{ group = "mcp-legacy" }, { group = "mcp-modern" }]] +default-groups = ["dev", "mcp-modern"] +prerelease = "if-necessary-or-explicit" +``` + +- [ ] **Step 2: Verify both environments resolve** + +Run: `uv sync --extra community && uv pip show mcp fastmcp | grep -E "Name|Version"` +Expected: mcp 2.0.x, fastmcp 4.0.0b1. +Run: `uv sync --extra community --no-group mcp-modern --group mcp-legacy && uv pip show mcp fastmcp | grep -E "Name|Version"` +Expected: mcp 1.x (≥1.24), fastmcp 3.x. + +- [ ] **Step 3: Verify current suite still passes in the LEGACY env** + +Run (still in legacy env): `uv run pytest -q -m "not e2e"` +Expected: PASS (code untouched; legacy env matches today's supported range). The modern env is NOT expected to work until Task 8+ — do not run pytest there yet. + +- [ ] **Step 4: Document in CONTRIBUTING.md** + +Add a "Dev environments" section: default sync = modern (`uv sync --extra community`); legacy = `uv sync --extra community --no-group mcp-modern --group mcp-legacy`; explain the conflict groups and that each suite auto-skips by installed major (Task 8 conftest). + +- [ ] **Step 5: Commit** + +```bash +git add pyproject.toml CONTRIBUTING.md +git commit -m "chore: v2.0.0b1 packaging, dual mcp-generation dev envs" +``` + +--- + +### Task 2: Canonical copy constants + byte-parity tests + +**Files:** +- Modify: `src/agentcat/modules/constants.py` +- Test: `tests/test_constants_copy.py` + +**Interfaces:** +- Produces (all in `agentcat.modules.constants`): `TASK_ID_PARAM = "task_id"`, `AGENT_ID_PARAM = "agent_id"`, `CONTEXT_PARAM = "context"`, `GET_MORE_TOOLS_NAME = "get_more_tools"`, `AGENT_ID_PREFIX = "agt"`, `MCP_INSTRUCTIONS_KEY = "_mcp_instructions"`, `META_CLIENT_INFO_KEY`, `META_PROTOCOL_VERSION_KEY`, `AGENTCAT_TAG_TASK_SOURCE`, `AGENTCAT_TAG_AGENT_ID`, `AGENTCAT_TAG_AGENT_SOURCE`, `AGENTCAT_TAG_PROTOCOL_VERSION`, `AGENTCAT_TAG_MRTR`, `AGENTCAT_CUSTOM_EVENT_TYPE = "agentcat:custom"`, `TASK_ID_PARAM_DESCRIPTION`, `AGENT_ID_PARAM_DESCRIPTION`, `AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE`, `MINT_BACK_HEADER_TASK`, `MINT_BACK_CLOSER`, `MCP_INSTRUCTIONS_FIELD_DESCRIPTION`, `MCP_INSTRUCTIONS_TASK_ID_DESCRIPTION`, `MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION`, `mint_back_task_line(task_id: str) -> str`, `mint_back_confirmed(names: list[str]) -> str`. + +- [ ] **Step 1: Write the failing test** — `tests/test_constants_copy.py` asserts every string equals the TS bytes. Copy each expected literal EXACTLY from `agentcat-typescript-sdk/src/modules/constants.ts:20-62` (open the file; do not retype from this plan). Skeleton with the short ones inline: + +```python +"""Byte-parity guard for agent-facing copy (TS constants.ts is the SoT).""" +from agentcat.modules import constants as c + + +def test_param_names_and_keys(): + assert c.TASK_ID_PARAM == "task_id" + assert c.AGENT_ID_PARAM == "agent_id" + assert c.MCP_INSTRUCTIONS_KEY == "_mcp_instructions" + assert c.META_CLIENT_INFO_KEY == "io.modelcontextprotocol/clientInfo" + assert c.META_PROTOCOL_VERSION_KEY == "io.modelcontextprotocol/protocolVersion" + assert c.AGENTCAT_TAG_TASK_SOURCE == "agentcat_task_id_source" + assert c.AGENTCAT_TAG_AGENT_ID == "agentcat_agent_id" + assert c.AGENTCAT_TAG_AGENT_SOURCE == "agentcat_agent_id_source" + assert c.AGENTCAT_TAG_PROTOCOL_VERSION == "agentcat_protocol_version" + assert c.AGENTCAT_TAG_MRTR == "agentcat_mrtr" + assert c.AGENT_ID_PREFIX == "agt" + + +def test_mint_back_assembly(): + assert c.MINT_BACK_HEADER_TASK == "[MCP INSTRUCTIONS]: task_id issued." + assert ( + c.MINT_BACK_CLOSER + == "Without task_id, this server does not function as intended." + ) + assert ( + c.mint_back_task_line("ses_X") + == " task_id=ses_X — required on every subsequent tool call" + ) + assert c.mint_back_confirmed(["task_id"]) == ( + "[MCP INSTRUCTIONS]: task_id confirmed. " + "Keep sending this exact value on every call." + ) + assert c.mint_back_confirmed(["task_id", "agent_id"]) == ( + "[MCP INSTRUCTIONS]: task_id and agent_id confirmed. " + "Keep sending these exact values on every call." + ) + + +def test_param_descriptions_match_ts(): + # Paste full literals from TS constants.ts lines 20-27; spot anchors: + assert c.TASK_ID_PARAM_DESCRIPTION.startswith("REQUIRED on every call after your first.") + assert c.TASK_ID_PARAM_DESCRIPTION.endswith("Without task_id, this server does not function as intended.") + assert "task_id and agent_id" not in c.TASK_ID_PARAM_DESCRIPTION + assert "working this task" in c.AGENT_ID_PARAM_DESCRIPTION + assert "working this task" not in c.AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE + assert c.AGENT_ID_PARAM_DESCRIPTION.replace(" working this task", "") == c.AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE + # ...plus full == comparisons against the pasted literals. +``` + +- [ ] **Step 2: Run to verify it fails** — `uv run pytest tests/test_constants_copy.py -q` → FAIL (AttributeError). + +- [ ] **Step 3: Implement** — append to `constants.py` (copy long strings from TS source, not from here): + +```python +# ── Explicit handles: injected parameter names & wire keys ─────────────────── +TASK_ID_PARAM = "task_id" +AGENT_ID_PARAM = "agent_id" +CONTEXT_PARAM = "context" +GET_MORE_TOOLS_NAME = "get_more_tools" +AGENT_ID_PREFIX = "agt" # reserved; server-side agent minting was removed +MCP_INSTRUCTIONS_KEY = "_mcp_instructions" +META_CLIENT_INFO_KEY = "io.modelcontextprotocol/clientInfo" +META_PROTOCOL_VERSION_KEY = "io.modelcontextprotocol/protocolVersion" +AGENTCAT_TAG_TASK_SOURCE = "agentcat_task_id_source" +AGENTCAT_TAG_AGENT_ID = "agentcat_agent_id" +AGENTCAT_TAG_AGENT_SOURCE = "agentcat_agent_id_source" +AGENTCAT_TAG_PROTOCOL_VERSION = "agentcat_protocol_version" +AGENTCAT_TAG_MRTR = "agentcat_mrtr" +AGENTCAT_CUSTOM_EVENT_TYPE = "agentcat:custom" + +# ── Explicit handles: agent-facing copy (byte-identical to TS constants.ts) ── +TASK_ID_PARAM_DESCRIPTION = "REQUIRED on every call after your first. ..." # full TS string +AGENT_ID_PARAM_DESCRIPTION = "REQUIRED on every call, including your first. ..." # full TS string +AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE = "..." # full TS string (no "working this task") +MINT_BACK_HEADER_TASK = "[MCP INSTRUCTIONS]: task_id issued." +MINT_BACK_CLOSER = "Without task_id, this server does not function as intended." +MCP_INSTRUCTIONS_FIELD_DESCRIPTION = "Your handles for this task, confirmed by this MCP server on every response, and the instructions for echoing them on later calls. Read and follow." +MCP_INSTRUCTIONS_TASK_ID_DESCRIPTION = "Echo this exact value as the task_id argument on every subsequent tool call." +MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION = "Your agent_id as this server received it. Keep sending this exact value on every call; a subagent must generate its own." + + +def mint_back_task_line(task_id: str) -> str: + return f" task_id={task_id} — required on every subsequent tool call" + + +def mint_back_confirmed(names: list[str]) -> str: + tail = "these exact values" if len(names) > 1 else "this exact value" + return ( + f"[MCP INSTRUCTIONS]: {' and '.join(names)} confirmed. " + f"Keep sending {tail} on every call." + ) +``` + +- [ ] **Step 4: Run** — `uv run pytest tests/test_constants_copy.py -q` → PASS. Also `uv run ruff check src tests` → clean. + +- [ ] **Step 5: Commit** — `git commit -m "feat(handles): canonical agent-facing copy constants (TS byte-parity)"` + +--- + +### Task 3: Options & type additions (additive only) + +**Files:** +- Modify: `src/agentcat/types.py` +- Test: `tests/test_options_v2.py` + +**Interfaces:** +- Produces: `ResolveTaskIdFunction = Callable[[Any, Any], str | None | Awaitable[str | None]]`; `AgentCatOptions.enable_agent_tracking: bool = False`; `AgentCatOptions.resolve_task_id: ResolveTaskIdFunction | None = None`; `class CustomEventData(TypedDict, total=False)` with keys `task_id, resource_name, parameters, response, message, duration, is_error, error, tags, properties`; `AgentCatData` gains `injected_params_registry: dict[str, set[str]] | None = None`, `output_injection_registry: set[str] | None = None`, `original_list_source: Any = None`, `server_name: str | None = None`, `server_version: str | None = None`. Do NOT remove `stateless`/session fields yet (Task 11). +- Docstrings for the two options adapted from TS `src/types.ts:6-26` (types.ts wording, not the stale index.ts `@param`). + +- [ ] **Step 1: Failing test** + +```python +from agentcat.types import AgentCatOptions, CustomEventData + + +def test_v2_option_defaults(): + o = AgentCatOptions() + assert o.enable_agent_tracking is False + assert o.resolve_task_id is None + + +def test_custom_event_data_keys(): + d: CustomEventData = {"task_id": "ses_x", "is_error": False, "tags": {"a": "b"}} + assert d["task_id"] == "ses_x" +``` + +- [ ] **Step 2: Run → FAIL.** `uv run pytest tests/test_options_v2.py -q` +- [ ] **Step 3: Implement in `types.py`** (fields + TypedDict + registry fields on `AgentCatData`). +- [ ] **Step 4: Run → PASS; `uv run mypy src/agentcat --strict` clean for the touched file.** +- [ ] **Step 5: Commit** — `git commit -m "feat(types): v2 options (agent tracking, resolve_task_id) and CustomEventData"` + +--- + +### Task 4: Handle primitives (`modules/handles.py`) + +**Files:** +- Create: `src/agentcat/modules/handles.py` +- Test: `tests/test_handles.py` + +**Interfaces:** +- Produces: + - `@dataclass HandleResolution(task_id: str, task_source: Literal["supplied","minted","hook"], agent_id: str | None = None, agent_source: Literal["supplied"] | None = None, hook_mode: bool = False)` + - `new_task_id() -> str` + - `derive_task_id(id: str, project_id: str | None = None) -> str` + - `extract_handle(arguments: Any, name: str) -> str | None` + - `async resolve_handles(arguments: Any, options: AgentCatOptions, project_id: str | None, request: Any, extra: Any) -> HandleResolution` + - `build_mint_back_text(res: HandleResolution) -> str | None` (non-None only when `task_source=="minted"` and not `hook_mode`) + - `build_structured_mint_back(res: HandleResolution) -> dict[str, Any] | None` + - `mirror_into_structured_content(sc: Any, mint: dict[str, Any]) -> Any | None` (returns the NEW dict, or `None` = leave result untouched) + - `build_handle_tags(res: HandleResolution, protocol_version: str | None = None, mrtr: str | None = None) -> dict[str, str]` + +- [ ] **Step 1: Failing tests** (port of TS `handles.test.ts`): + +```python +import asyncio +import pytest +from agentcat.modules.handles import ( + HandleResolution, build_handle_tags, build_mint_back_text, + build_structured_mint_back, derive_task_id, extract_handle, + mirror_into_structured_content, new_task_id, resolve_handles, +) +from agentcat.types import AgentCatOptions + + +def test_mint_shape(): + a, b = new_task_id(), new_task_id() + assert a.startswith("ses_") and len(a) == 4 + 27 and a != b + + +def test_golden_vectors(): + assert derive_task_id("customer-abc", "proj_1") == "ses_2cOHEO0LYGADMzRvWTXXVbbgxgm" + assert derive_task_id("customer-abc") == "ses_2cZY3tvyI25O2AmL2CGVo2B1IIj" + assert derive_task_id(" x ", "p") == "ses_2c3yR5mYKQdLaXsJNgZH6erbfQK" # no trim + assert derive_task_id("x", "p") == "ses_2bw285VY9apdgUgTPXKFnT6P4G0" + + +def test_extract_handle_trust_model(): + assert extract_handle({"task_id": " ses_x "}, "task_id") == "ses_x" + assert extract_handle({"task_id": "my-own-correlation-id"}, "task_id") == "my-own-correlation-id" + for bad in ({"task_id": ""}, {"task_id": " "}, {"task_id": 42}, None, "str"): + assert extract_handle(bad, "task_id") is None + + +async def test_prompted_supplied_vs_minted(): + o = AgentCatOptions() + r1 = await resolve_handles({"task_id": "ses_supplied"}, o, "proj", None, None) + assert (r1.task_id, r1.task_source, r1.hook_mode) == ("ses_supplied", "supplied", False) + r2 = await resolve_handles({}, o, "proj", None, None) + assert r2.task_source == "minted" and r2.task_id.startswith("ses_") + + +async def test_hook_mode_derives_and_falls_back(): + o = AgentCatOptions(resolve_task_id=lambda req, extra: " customer-abc ") + r = await resolve_handles({"task_id": "ignored"}, o, "proj_1", None, None) + assert r.task_id == derive_task_id("customer-abc", "proj_1") # trimmed by caller + assert r.task_source == "hook" and r.hook_mode is True + + async def async_hook(req, extra): + return "customer-abc" + r = await resolve_handles({}, AgentCatOptions(resolve_task_id=async_hook), "proj_1", None, None) + assert r.task_source == "hook" + + def boom(req, extra): + raise RuntimeError("hook broke") + r = await resolve_handles({}, AgentCatOptions(resolve_task_id=boom), "proj_1", None, None) + assert r.task_source == "minted" and r.hook_mode is True + r = await resolve_handles({}, AgentCatOptions(resolve_task_id=lambda q, e: None), None, None, None) + assert r.task_source == "minted" and r.hook_mode is True + + +async def test_agent_extraction_gated_on_option(): + on = AgentCatOptions(enable_agent_tracking=True) + r = await resolve_handles({"agent_id": " a|b|c "}, on, None, None, None) + assert (r.agent_id, r.agent_source) == ("a|b|c", "supplied") + r = await resolve_handles({"agent_id": "a|b|c"}, AgentCatOptions(), None, None, None) + assert r.agent_id is None + + +def test_mint_back_text_rules(): + minted = HandleResolution(task_id="ses_T", task_source="minted") + assert build_mint_back_text(minted) == ( + "[MCP INSTRUCTIONS]: task_id issued.\n" + " task_id=ses_T — required on every subsequent tool call\n" + "Without task_id, this server does not function as intended." + ) + assert build_mint_back_text(HandleResolution("ses_T", "supplied")) is None + assert build_mint_back_text(HandleResolution("ses_T", "minted", hook_mode=True)) is None + + +def test_structured_mint_back_omission_rules(): + both = HandleResolution("ses_T", "supplied", agent_id="A", agent_source="supplied") + m = build_structured_mint_back(both) + assert m == { + "task_id": "ses_T", "agent_id": "A", + "instructions": "[MCP INSTRUCTIONS]: task_id and agent_id confirmed. Keep sending these exact values on every call.", + } + hook_agent = HandleResolution("ses_T", "hook", agent_id="A", agent_source="supplied", hook_mode=True) + m = build_structured_mint_back(hook_agent) + assert "task_id" not in m and m["agent_id"] == "A" and "agent_id confirmed" in m["instructions"] + assert build_structured_mint_back(HandleResolution("ses_T", "hook", hook_mode=True)) is None + minted = HandleResolution("ses_T", "minted") + assert build_structured_mint_back(minted)["instructions"].startswith("[MCP INSTRUCTIONS]: task_id issued.") + + +def test_mirror_rules(): + mint = {"task_id": "ses_T", "instructions": "i"} + assert mirror_into_structured_content(None, mint) is None + assert mirror_into_structured_content([1], mint) is None + assert mirror_into_structured_content({"_mcp_instructions": "customer"}, mint) is None + out = mirror_into_structured_content({"a": 1}, mint) + assert out == {"a": 1, "_mcp_instructions": mint} + + +def test_tag_clamp(): + res = HandleResolution("ses_T", "supplied", agent_id="a\r\nb" + "x" * 300, agent_source="supplied") + tags = build_handle_tags(res, protocol_version="2026-07-28", mrtr="continuation") + assert tags["agentcat_task_id_source"] == "supplied" + assert tags["agentcat_agent_id"].startswith("a b") and len(tags["agentcat_agent_id"]) == 200 + assert tags["agentcat_agent_id_source"] == "supplied" + assert tags["agentcat_protocol_version"] == "2026-07-28" + assert tags["agentcat_mrtr"] == "continuation" + assert build_handle_tags(HandleResolution("s", "minted")) == {"agentcat_task_id_source": "minted"} +``` + +- [ ] **Step 2: Run → FAIL** (`ModuleNotFoundError`). +- [ ] **Step 3: Implement `handles.py`:** + +```python +"""Explicit-handle primitives: minting, derivation, extraction, mint-back. + +Cross-SDK contract: 2026-07-28-cross-sdk-changelog.md §3-§4; TS reference +src/modules/handles.ts. Derivation golden vectors are frozen — changing them +splits customer tasks across an upgrade. +""" +import hashlib +import inspect +from dataclasses import dataclass +from typing import Any, Literal, Optional + +from agentcat.modules.constants import ( + AGENT_ID_PARAM, AGENTCAT_TAG_AGENT_ID, AGENTCAT_TAG_AGENT_SOURCE, + AGENTCAT_TAG_MRTR, AGENTCAT_TAG_PROTOCOL_VERSION, AGENTCAT_TAG_TASK_SOURCE, + MCP_INSTRUCTIONS_KEY, MINT_BACK_CLOSER, MINT_BACK_HEADER_TASK, + SESSION_ID_PREFIX, TASK_ID_PARAM, mint_back_confirmed, mint_back_task_line, +) +from agentcat.modules.logging import write_to_log +from agentcat.thirdparty.ksuid import Ksuid +from agentcat.utils import generate_prefixed_ksuid + +_KSUID_EPOCH_MS = 1_400_000_000_000 +_DERIVE_EPOCH_MS = 1_704_067_200_000 # 2024-01-01T00:00:00Z +_YEAR_MS = 365 * 24 * 60 * 60 * 1000 + + +@dataclass +class HandleResolution: + task_id: str + task_source: Literal["supplied", "minted", "hook"] + agent_id: Optional[str] = None + agent_source: Optional[Literal["supplied"]] = None + hook_mode: bool = False + + +def new_task_id() -> str: + return generate_prefixed_ksuid(SESSION_ID_PREFIX) + + +def derive_task_id(id: str, project_id: str | None = None) -> str: + # NOTE: does not trim — callers trim (resolve_handles trims hook output). + payload_input = f"{id}:{project_id}" if project_id else id + digest = hashlib.sha256(payload_input.encode("utf-8")).digest() + ts_ms = _DERIVE_EPOCH_MS + (int.from_bytes(digest[0:4], "big") % _YEAR_MS) + ts_field = (ts_ms - _KSUID_EPOCH_MS) // 1000 + raw = ts_field.to_bytes(4, "big") + digest[4:20] + return f"{SESSION_ID_PREFIX}_{Ksuid.from_bytes(raw)}" + + +def extract_handle(arguments: Any, name: str) -> str | None: + if not isinstance(arguments, dict): + return None + value = arguments.get(name) + if isinstance(value, str) and value.strip(): + return value.strip() + return None + + +async def resolve_handles(arguments, options, project_id, request, extra) -> HandleResolution: + hook = options.resolve_task_id + agent_id = ( + extract_handle(arguments, AGENT_ID_PARAM) + if options.enable_agent_tracking else None + ) + agent_source: Literal["supplied"] | None = "supplied" if agent_id else None + + if callable(hook): + try: + value = hook(request, extra) + if inspect.isawaitable(value): + value = await value + except Exception as e: # hook errors mint silently + write_to_log(f"Warning: resolve_task_id hook raised: {e}") + value = None + if isinstance(value, str) and value.strip(): + return HandleResolution( + derive_task_id(value.strip(), project_id), "hook", + agent_id, agent_source, hook_mode=True, + ) + return HandleResolution(new_task_id(), "minted", agent_id, agent_source, hook_mode=True) + + supplied = extract_handle(arguments, TASK_ID_PARAM) + if supplied: + return HandleResolution(supplied, "supplied", agent_id, agent_source) + return HandleResolution(new_task_id(), "minted", agent_id, agent_source) + + +def build_mint_back_text(res: HandleResolution) -> str | None: + if res.task_source != "minted" or res.hook_mode: + return None + return "\n".join( + [MINT_BACK_HEADER_TASK, mint_back_task_line(res.task_id), MINT_BACK_CLOSER] + ) + + +def build_structured_mint_back(res: HandleResolution) -> dict[str, Any] | None: + names: list[str] = [] + if not res.hook_mode: + names.append(TASK_ID_PARAM) + if res.agent_id: + names.append(AGENT_ID_PARAM) + if not names: + return None + mint: dict[str, Any] = {} + if not res.hook_mode: + mint[TASK_ID_PARAM] = res.task_id + if res.agent_id: + mint[AGENT_ID_PARAM] = res.agent_id + mint["instructions"] = build_mint_back_text(res) or mint_back_confirmed(names) + return mint + + +def mirror_into_structured_content(sc: Any, mint: dict[str, Any]) -> Any | None: + if not isinstance(sc, dict) or MCP_INSTRUCTIONS_KEY in sc: + return None + return {**sc, MCP_INSTRUCTIONS_KEY: mint} + + +def build_handle_tags(res, protocol_version=None, mrtr=None) -> dict[str, str]: + tags = {AGENTCAT_TAG_TASK_SOURCE: res.task_source} + if res.agent_id and res.agent_source: + clamped = res.agent_id.replace("\r", " ").replace("\n", " ")[:200] + tags[AGENTCAT_TAG_AGENT_ID] = clamped + tags[AGENTCAT_TAG_AGENT_SOURCE] = res.agent_source + if protocol_version: + tags[AGENTCAT_TAG_PROTOCOL_VERSION] = protocol_version + if mrtr: + tags[AGENTCAT_TAG_MRTR] = mrtr + return tags +``` + +If the golden-vector test fails: diff against TS `src/modules/handles.ts:33-47` and `src/thirdparty/ksuid/index.js:44-50` (`Math.floor((ms-14e11)/1e3)` uint32-BE + `hash[4:20]`). Do NOT adjust the vectors. + +- [ ] **Step 4: Run → PASS**; `uv run mypy src/agentcat/modules/handles.py --strict` clean. +- [ ] **Step 5: Commit** — `git commit -m "feat(handles): mint/derive/extract/mint-back primitives with TS golden parity"` + +--- + +### Task 5: Pure injection pipeline (`modules/injection.py`) + +**Files:** +- Create: `src/agentcat/modules/injection.py` +- Test: `tests/test_injection.py` + +**Interfaces:** +- Produces: + - `@dataclass ToolSpec(name: str, input_schema: dict[str, Any], output_schema: dict[str, Any] | None = None)` — schemas are the adapter's DEEP COPIES; the pipeline mutates them in place. + - `@dataclass InjectionResult(injected_params: dict[str, set[str]], output_injected: set[str])` + - `build_injected_schemas(tools: list[ToolSpec], options: AgentCatOptions) -> InjectionResult` + - `strip_injected_arguments(tool_name: str, arguments: dict[str, Any], registry: dict[str, set[str]] | None) -> dict[str, Any]` — always returns a new dict; `registry=None` → heuristic (strip `task_id`/`agent_id`/`context`, except `get_more_tools` keeps `context`). + - `mcp_instructions_schema_property() -> dict[str, Any]` — the `_mcp_instructions` outputSchema fragment. +- Consumes: Task 2 constants, Task 3 options. + +- [ ] **Step 1: Failing tests** (key cases; write all of these): + +```python +import copy +from agentcat.modules.injection import ( + InjectionResult, ToolSpec, build_injected_schemas, + mcp_instructions_schema_property, strip_injected_arguments, +) +from agentcat.modules import constants as c +from agentcat.types import AgentCatOptions + + +def spec(name="t", props=None, extra=None, out=None): + schema = {"type": "object", "properties": dict(props or {"q": {"type": "string"}})} + schema.update(extra or {}) + return ToolSpec(name=name, input_schema=schema, output_schema=out) + + +def test_param_order_and_descriptions(): + s = spec() + r = build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + keys = list(s.input_schema["properties"]) + assert keys == ["q", "task_id", "agent_id", "context"] + assert s.input_schema["properties"]["task_id"]["description"] == c.TASK_ID_PARAM_DESCRIPTION + assert s.input_schema["properties"]["agent_id"]["description"] == c.AGENT_ID_PARAM_DESCRIPTION + assert "task_id" not in s.input_schema.get("required", []) + assert "agent_id" in s.input_schema["required"] + assert r.injected_params["t"] == {"task_id", "agent_id", "context"} + + +def test_hook_mode_omits_task_id_and_switches_agent_copy(): + s = spec() + build_injected_schemas([s], AgentCatOptions( + enable_agent_tracking=True, resolve_task_id=lambda q, e: "x")) + props = s.input_schema["properties"] + assert "task_id" not in props + assert props["agent_id"]["description"] == c.AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE + + +def test_tracing_disabled_skips_handles_but_not_context(): + s = spec() + r = build_injected_schemas([s], AgentCatOptions(enable_tracing=False)) + assert set(s.input_schema["properties"]) == {"q", "context"} + assert r.injected_params["t"] == {"context"} + + +def test_additional_properties_false_removed(): + s = spec(extra={"additionalProperties": False}) + build_injected_schemas([s], AgentCatOptions()) + assert "additionalProperties" not in s.input_schema + + +def test_composed_schema_skipped_with_empty_registry_entry(): + s = ToolSpec(name="t", input_schema={"oneOf": [{"type": "object"}]}) + r = build_injected_schemas([s], AgentCatOptions()) + assert s.input_schema == {"oneOf": [{"type": "object"}]} + assert r.injected_params["t"] == set() + + +def test_collision_skips_that_param_only(): + s = spec(props={"task_id": {"type": "string", "description": "customer"}}) + r = build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + assert s.input_schema["properties"]["task_id"]["description"] == "customer" + assert r.injected_params["t"] == {"agent_id", "context"} + + +def test_get_more_tools_gets_handles_but_not_context(): + s = spec(name=c.GET_MORE_TOOLS_NAME, props={"context": {"type": "string"}}) + r = build_injected_schemas([s], AgentCatOptions()) + assert r.injected_params[c.GET_MORE_TOOLS_NAME] == {"task_id"} + + +def test_output_schema_extension_and_registry(): + s = spec(out={"type": "object", "properties": {"answer": {"type": "string"}}}) + r = build_injected_schemas([s], AgentCatOptions()) + prop = s.output_schema["properties"][c.MCP_INSTRUCTIONS_KEY] + assert prop["description"] == c.MCP_INSTRUCTIONS_FIELD_DESCRIPTION + assert prop["properties"]["task_id"]["description"] == c.MCP_INSTRUCTIONS_TASK_ID_DESCRIPTION + assert c.MCP_INSTRUCTIONS_KEY not in s.output_schema.get("required", []) + assert r.output_injected == {"t"} + s2 = spec(out={"oneOf": []}) + r2 = build_injected_schemas([s2], AgentCatOptions()) + assert r2.output_injected == set() + + +def test_determinism(): + def make(): + return [spec(), spec(name="u", extra={"additionalProperties": False})] + a, b = make(), make() + ra = build_injected_schemas(a, AgentCatOptions(enable_agent_tracking=True)) + rb = build_injected_schemas(b, AgentCatOptions(enable_agent_tracking=True)) + assert ra == rb and [t.input_schema for t in a] == [t.input_schema for t in b] + + +def test_strip_registry_driven_and_heuristic(): + args = {"q": 1, "task_id": "s", "agent_id": "a", "context": "c"} + reg = {"t": {"task_id", "context"}} + out = strip_injected_arguments("t", args, reg) + assert out == {"q": 1, "agent_id": "a"} and args["task_id"] == "s" # clone + # Registry present but tool not in it: it was never advertised through the + # pipeline, so nothing was injected for it — strip nothing. + assert strip_injected_arguments("unknown", args, reg) == args + assert strip_injected_arguments("t", args, None) == {"q": 1} + gmt = {"context": "real", "task_id": "s"} + assert strip_injected_arguments(c.GET_MORE_TOOLS_NAME, gmt, None) == {"context": "real"} +``` + +- [ ] **Step 2: Run → FAIL.** +- [ ] **Step 3: Implement.** Core injector: + +```python +_COMPOSED_KEYS = ("oneOf", "allOf", "anyOf") + + +def _inject_param(schema: dict, name: str, description: str, required: bool, registry_entry: set[str]) -> None: + props = schema.setdefault("properties", {}) + if name in props: + write_to_log(f"Warning: tool already defines '{name}'; skipping injection") + return + props[name] = {"type": "string", "description": description} + if required: + schema.setdefault("required", []) + if name not in schema["required"]: + schema["required"].append(name) + registry_entry.add(name) + + +def build_injected_schemas(tools, options): + hook_mode = callable(options.resolve_task_id) + result = InjectionResult(injected_params={}, output_injected=set()) + for tool in tools: + entry: set[str] = set() + result.injected_params[tool.name] = entry + schema = tool.input_schema + if any(k in schema for k in _COMPOSED_KEYS): + write_to_log(f"Warning: composed input schema on '{tool.name}'; skipping injection") + continue + if schema.get("additionalProperties") is False: + del schema["additionalProperties"] + if options.enable_tracing and not hook_mode: + _inject_param(schema, TASK_ID_PARAM, TASK_ID_PARAM_DESCRIPTION, False, entry) + if options.enable_tracing and options.enable_agent_tracking: + desc = AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE if hook_mode else AGENT_ID_PARAM_DESCRIPTION + _inject_param(schema, AGENT_ID_PARAM, desc, True, entry) + if options.enable_tool_call_context and tool.name != GET_MORE_TOOLS_NAME: + _inject_param(schema, CONTEXT_PARAM, options.custom_context_description, False, entry) + out = tool.output_schema + if isinstance(out, dict): + if any(k in out for k in _COMPOSED_KEYS): + write_to_log(f"Warning: composed output schema on '{tool.name}'; content-only mint-back") + elif isinstance(out.get("properties"), dict): + if MCP_INSTRUCTIONS_KEY not in out["properties"]: + out["properties"][MCP_INSTRUCTIONS_KEY] = mcp_instructions_schema_property() + result.output_injected.add(tool.name) + return result +``` + +`mcp_instructions_schema_property()` returns `{"type": "object", "description": MCP_INSTRUCTIONS_FIELD_DESCRIPTION, "properties": {"task_id": {"type": "string", "description": MCP_INSTRUCTIONS_TASK_ID_DESCRIPTION}, "agent_id": {"type": "string", "description": MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION}, "instructions": {"type": "string"}}}`. `strip_injected_arguments` per the test contract (registry present + tool listed → strip exactly the entry; registry present + tool unknown → strip nothing; registry `None` → heuristic with the `get_more_tools` context exception). + +- [ ] **Step 4: Run → PASS; ruff + mypy clean.** +- [ ] **Step 5: Commit** — `git commit -m "feat(injection): pure schema-injection pipeline with registries"` + +--- + +### Task 6: Detection & client identity + +**Files:** +- Create: `src/agentcat/modules/detection.py`, `src/agentcat/modules/client_identity.py` +- Test: `tests/test_detection.py`, `tests/test_client_identity.py` + +**Interfaces:** +- Produces (`detection.py`): + - `class ServerFlavor(str, Enum)`: `LOWLEVEL_V1, LOWLEVEL_V2, OFFICIAL_FASTMCP_V1, MCPSERVER_V2, COMMUNITY_V3, COMMUNITY_V4, COMMUNITY_V2_UNSUPPORTED, UNKNOWN` + - `@dataclass Detection(flavor: ServerFlavor, lowlevel: Any | None, fingerprint: dict[str, bool])` — `lowlevel` = the object adapters wrap (`_mcp_server` / `_lowlevel_server` / the server itself; `None` for community + unknown). + - `detect_server(server: Any) -> Detection` +- Produces (`client_identity.py`): + - `@dataclass ClientIdentity(name: str | None = None, version: str | None = None)` + - `client_identity_from_meta(meta: Any) -> ClientIdentity | None` — reads `META_CLIENT_INFO_KEY`, per-field `isinstance(str)` narrowing. + - `resolve_client_identity(meta_sources: list[Any], legacy: Callable[[], Any | None]) -> ClientIdentity` — first meta hit wins, then legacy object (accepts objects with `.name`/`.version` attrs or dicts), else empty. + - `resolve_protocol_version(meta_sources: list[Any], fallback: str | None = None) -> str | None` +- Probes (fingerprint keys, spec §8.1): `is_fastmcp_class`, `has_local_provider`, `has_add_middleware`, `has_middleware`, `has_tool_manager`, `has_mcp_server_attr`, `has_lowlevel_server_attr`, `has_extensions`, `has_request_state_security`, `has_request_handlers`, `has_private_request_handlers`, `has_add_request_handler`, `has_request_context`. + +- [ ] **Step 1: Failing tests.** Build minimal doubles — module/class names matter: + +```python +from agentcat.modules.detection import Detection, ServerFlavor, detect_server + + +def make(name, module, **attrs): + cls = type(name, (), {}) + cls.__module__ = module + obj = cls() + for k, v in attrs.items(): + setattr(obj, k, v) + return obj + + +def test_community_v4_vs_v3(): + base = dict(_local_provider=object(), add_middleware=lambda m: None, middleware=[]) + v3 = make("FastMCP", "fastmcp.server.server", **base) + v4 = make("FastMCP", "fastmcp.server.server", **base, _extensions={}, add_extension=lambda e: None) + assert detect_server(v3).flavor is ServerFlavor.COMMUNITY_V3 + assert detect_server(v4).flavor is ServerFlavor.COMMUNITY_V4 + + +def test_community_v2_unsupported(): + v2 = make("FastMCP", "fastmcp.server", _mcp_server=object(), _tool_manager=object()) + assert detect_server(v2).flavor is ServerFlavor.COMMUNITY_V2_UNSUPPORTED + + +def test_official_flavors(): + ll1 = make("Server", "mcp.server.lowlevel.server", request_handlers={}, request_context=None) + ll2 = make("Server", "mcp.server.lowlevel.server", _request_handlers={}, add_request_handler=lambda *a: None) + fm1 = make("FastMCP", "mcp.server.fastmcp.server", _mcp_server=ll1, _tool_manager=object()) + ms2 = make("MCPServer", "mcp.server.mcpserver.server", _lowlevel_server=ll2, _tool_manager=object()) + assert detect_server(ll1).flavor is ServerFlavor.LOWLEVEL_V1 + d = detect_server(ll2); assert d.flavor is ServerFlavor.LOWLEVEL_V2 and d.lowlevel is ll2 + d = detect_server(fm1); assert d.flavor is ServerFlavor.OFFICIAL_FASTMCP_V1 and d.lowlevel is ll1 + d = detect_server(ms2); assert d.flavor is ServerFlavor.MCPSERVER_V2 and d.lowlevel is ll2 + + +def test_unknown_shape_has_fingerprint(): + d = detect_server(object()) + assert d.flavor is ServerFlavor.UNKNOWN and isinstance(d.fingerprint, dict) +``` + +`tests/test_client_identity.py`: + +```python +from agentcat.modules.client_identity import ( + ClientIdentity, client_identity_from_meta, resolve_client_identity, resolve_protocol_version, +) + +KEY = "io.modelcontextprotocol/clientInfo" +PV = "io.modelcontextprotocol/protocolVersion" + + +def test_meta_narrowing(): + assert client_identity_from_meta({KEY: {"name": "cursor", "version": "2.1"}}) == ClientIdentity("cursor", "2.1") + assert client_identity_from_meta({KEY: {"name": "cursor", "version": 7}}) == ClientIdentity("cursor", None) + assert client_identity_from_meta({KEY: "junk"}) is None + assert client_identity_from_meta(None) is None + + +def test_ladder_order_and_legacy(): + envelope = {KEY: {"name": "envelope", "version": "1"}} + passthrough = {KEY: {"name": "meta", "version": "2"}} + class Legacy: # duck-typed clientInfo object + name, version = "legacy", "3" + assert resolve_client_identity([envelope, passthrough], lambda: Legacy()).name == "envelope" + assert resolve_client_identity([None, passthrough], lambda: Legacy()).name == "meta" + assert resolve_client_identity([None, None], lambda: Legacy()).name == "legacy" + assert resolve_client_identity([None], lambda: (_ for _ in ()).throw(RuntimeError())) == ClientIdentity() + + +def test_protocol_version(): + assert resolve_protocol_version([{PV: "2026-07-28"}]) == "2026-07-28" + assert resolve_protocol_version([None], fallback="2026-07-28") == "2026-07-28" + assert resolve_protocol_version([{PV: 9}]) is None +``` + +- [ ] **Step 2: Run → FAIL.** +- [ ] **Step 3: Implement.** Detection order: community v2 check BEFORE official-fastmcp-v1 (both have `_mcp_server`+`_tool_manager`; discriminate on module prefix `fastmcp` vs `mcp.server.fastmcp`). `meta` access supports both Mapping (`meta.get(KEY)`) and pydantic `Meta` objects (try `.model_extra.get(KEY)` then `getattr`). Legacy accepts objects (`.name`/`.version`) or dicts. Everything wrapped so no probe can raise. +- [ ] **Step 4: Run → PASS.** Extra check: `uv run python -c "import agentcat.modules.detection, agentcat.modules.client_identity"` in BOTH envs (legacy + modern) — must import cleanly (no version-specific imports). +- [ ] **Step 5: Commit** — `git commit -m "feat(detection): per-object flavor classifier and per-request client identity ladder"` + +--- + +### Task 7: Call-path orchestration (`modules/callpath.py`) + +**Files:** +- Create: `src/agentcat/modules/callpath.py` +- Test: `tests/test_callpath.py` + +**Interfaces:** +- Produces: + - `@dataclass ResolvedCall(resolution: HandleResolution, actor: UserIdentity | None, client: ClientIdentity, protocol_version: str | None, intent: str | None)` + - `async resolve_call(data: AgentCatData, tool_name: str, raw_arguments: dict, request: Any, extra: Any, meta_sources: list[Any], legacy_client: Callable[[], Any | None], protocol_fallback: str | None = None) -> ResolvedCall` — runs `resolve_handles`, the customer `identify` hook (never raises), the client ladder; captures `intent = raw_arguments.get("context")` when a str. + - `async get_stripped_arguments(data: AgentCatData, options, tool_name: str, raw_arguments: dict, rebuild: Callable[[], Awaitable[list[ToolSpec]]] | None) -> dict` — registry from `data.injected_params_registry`; on `None` awaits `rebuild()` → `build_injected_schemas` → stores registries on `data`; on failure logs + heuristic strip (and sets `data.output_injection_registry = None` so the mirror gate is bypassed). + - `detect_mrtr(result_type: str | None, has_input_responses: bool) -> str | None` → `"input_required" | "continuation" | None`. + - `decorate_content(content: list[Any] | None, res: HandleResolution, make_text_block: Callable[[str], Any]) -> list[Any] | None` — returns a NEW list with the trailing block appended, or `None` when no decoration applies (not minted / hook mode / content not a list). + - `structured_mirror(sc: Any, res: HandleResolution, tool_name: str, output_registry: set[str] | None) -> Any | None` — gate: mirror when `output_registry is None` (rebuild failed) or `tool_name in output_registry`; delegates to `mirror_into_structured_content`. + - `async publish_tool_call_event(server_key: Any, data: AgentCatData, rc: ResolvedCall, tool_name: str, raw_arguments: dict, response: Any, is_error: bool, error_msg: str | None, duration_ms: int | None, mrtr: str | None, extra_params: dict | None) -> None` — builds `UnredactedEvent(event_type="mcp:tools/call", session_id=rc.resolution.task_id, resource_name=tool_name, user_intent=rc.intent, parameters={"arguments": raw_arguments, **(extra_params or {})}, response=response, is_error=is_error, error=..., client_name=rc.client.name, client_version=rc.client.version, identify_actor_given_id=..., ...)`, resolves customer tags/properties via `attach_event_metadata`, then merges `build_handle_tags(rc.resolution, rc.protocol_version, mrtr)` OVER them (SDK wins; exempt from the 50-tag cap — merge after `validate_tags`), and `event_queue.publish_event(server_key, event)`. +- Consumes: Tasks 4–6 symbols exactly as defined there. + +- [ ] **Step 1: Failing tests** — pure-python fakes, no MCP imports. Cover: identify hook error → `actor is None`; `intent` captured; strip with registry / rebuild-success (fake rebuild returns `ToolSpec`s and registries land on `data`) / rebuild-raise → heuristic + `output_injection_registry is None`; `detect_mrtr` matrix; `decorate_content` minted vs supplied vs hook vs non-list content (append also happens on `is_error` results — `decorate_content` never looks at error state); `structured_mirror` gate matrix (in registry / not in registry / registry None); `publish_tool_call_event` → capture `event_queue.publish_event` with monkeypatch and assert `session_id`, raw args, SDK tag merge collision (customer tag `agentcat_task_id_source:"fake"` is overridden), 50-cap exemption (50 customer tags + SDK tags all present). Anchor style: + +```python +from agentcat.modules.callpath import decorate_content, detect_mrtr, get_stripped_arguments +from agentcat.modules.handles import HandleResolution +from agentcat.modules.injection import ToolSpec +from agentcat.types import AgentCatData, AgentCatOptions + + +def test_detect_mrtr_matrix(): + assert detect_mrtr("input_required", False) == "input_required" + assert detect_mrtr("input_required", True) == "input_required" # intermediate wins + assert detect_mrtr(None, True) == "continuation" + assert detect_mrtr("complete", False) is None + + +def test_decorate_content_only_when_minted_prompted(): + minted = HandleResolution("ses_T", "minted") + out = decorate_content([{"type": "text", "text": "x"}], minted, lambda t: {"type": "text", "text": t}) + assert out is not None and "[MCP INSTRUCTIONS]: task_id issued." in out[-1]["text"] + assert decorate_content([{"t": 1}], HandleResolution("ses_T", "supplied"), dict) is None + assert decorate_content([{"t": 1}], HandleResolution("ses_T", "minted", hook_mode=True), dict) is None + assert decorate_content("not-a-list", minted, dict) is None + + +async def test_rebuild_failure_falls_back_to_heuristic(caplog): + data = AgentCatData(project_id="p", options=AgentCatOptions()) + async def broken_rebuild(): + raise RuntimeError("list source gone") + out = await get_stripped_arguments(data, data.options, "t", + {"q": 1, "task_id": "s", "context": "c"}, broken_rebuild) + assert out == {"q": 1} + assert data.output_injection_registry is None # mirror gate bypassed +``` +- [ ] **Step 2: Run → FAIL.** +- [ ] **Step 3: Implement** exactly per the Interfaces block. Reuse `identify` logic from `modules/identify.py` but WITHOUT publishing an event (new helper `resolve_identity(data, request, extra) -> UserIdentity | None` added to `identify.py`; old `identify_session` stays until Task 11). +- [ ] **Step 4: Run → PASS; ruff + mypy clean.** +- [ ] **Step 5: Commit** — `git commit -m "feat(callpath): shared per-call orchestration (resolve/strip/decorate/publish)"` + +### Task 8: Lowlevel-v1 adapter + `track()` cutover (official SDK 1.x flavors) + +**Files:** +- Create: `src/agentcat/modules/adapters/__init__.py`, `src/agentcat/modules/adapters/lowlevel_v1.py` +- Modify: `src/agentcat/__init__.py` (full `track()` rewrite), `src/agentcat/modules/request_extra.py` (expose `extra_from_request_context(request_context) -> dict`), `src/agentcat/modules/identify.py` (add `resolve_identity`), `tests/conftest.py` (env gating) +- Delete: `src/agentcat/modules/overrides/official/` (whole dir) +- Test: `tests/test_lowlevel_v1_handles.py` (new); rewrite `tests/test_tool_context.py`, `tests/test_report_missing.py`, `tests/test_event_capture_completeness.py`, `tests/test_mcp_version_compatibility.py`, `tests/test_dynamic_tracking.py`, `tests/test_multiple_servers.py`, `tests/e2e/official/*` + +**Interfaces:** +- Produces: `install_lowlevel_v1(server: Any, data: AgentCatData) -> None` (wraps type-keyed `request_handlers`); `track()` v2: detection-dispatched, never raises; `agentcat` imports cleanly under BOTH mcp majors (all mcp/fastmcp imports lazy). +- Consumes: `detect_server` (Task 6), `resolve_call`/`get_stripped_arguments`/`decorate_content`/`structured_mirror`/`publish_tool_call_event`/`detect_mrtr` (Task 7), `ToolSpec`/`build_injected_schemas` (Task 5). + +- [ ] **Step 1: conftest env gating.** In `tests/conftest.py`: + +```python +from importlib.metadata import version + +MCP_MAJOR = int(version("mcp").split(".")[0]) +_LEGACY_ONLY = [ + "e2e/official", "e2e/community_v2", "e2e/community_v3", "community", + "test_tool_context.py", "test_report_missing.py", "test_dynamic_tracking.py", + "test_multiple_servers.py", "test_event_capture_completeness.py", + "test_mcp_version_compatibility.py", "test_session.py", "test_stateless.py", + "test_request_extra.py", "test_lowlevel_v1_handles.py", +] +_MODERN_ONLY = ["e2e/official_modern", "e2e/community_v4", "test_lowlevel_v2_handles.py"] +collect_ignore_glob = [ + f"{p}*" for p in (_MODERN_ONLY if MCP_MAJOR < 2 else _LEGACY_ONLY) +] +``` + +- [ ] **Step 2: Failing integration test** `tests/test_lowlevel_v1_handles.py` (legacy env), using `tests/test_utils/todo_server.py` + `client.py`: + +```python +import json +import pytest +from agentcat import AgentCatOptions, track +from tests.test_utils.client import create_test_client +from tests.test_utils.todo_server import create_todo_server + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + events = [] + from agentcat.modules import event_queue + monkeypatch.setattr(event_queue.event_queue, "add_event", events.append) + return events + + +async def test_prompted_mode_end_to_end(capture): + server = create_todo_server() + track(server, "proj_test", AgentCatOptions()) + async with create_test_client(server) as client: + listed = await client.list_tools() + add = next(t for t in listed.tools if t.name == "add_todo") + assert list(add.inputSchema["properties"])[-2:] == ["task_id", "context"] + assert "task_id" not in add.inputSchema.get("required", []) + assert any(t.name == "get_more_tools" for t in listed.tools) + + r1 = await client.call_tool("add_todo", {"text": "hi", "context": "Adding a todo item for the user's task list to track work"}) + text = "".join(c.text for c in r1.content if hasattr(c, "text")) + assert "[MCP INSTRUCTIONS]: task_id issued." in text + minted = text.split("task_id=")[1].split(" ")[0] + assert minted.startswith("ses_") + + r2 = await client.call_tool("add_todo", {"text": "again", "task_id": minted}) + text2 = "".join(c.text for c in r2.content if hasattr(c, "text")) + assert "[MCP INSTRUCTIONS]: task_id issued." not in text2 + + call_events = [e for e in capture if e.event_type == "mcp:tools/call"] + assert {e.event_type for e in capture} <= {"mcp:tools/call"} # no initialize/list/identify + assert call_events[0].session_id == minted == call_events[1].session_id + assert call_events[0].parameters["arguments"]["context"] # raw request keeps injected params + assert "[MCP INSTRUCTIONS]" not in json.dumps(call_events[0].response) # undecorated + + +async def test_handler_sees_stripped_args_and_customer_result_untouched(capture): + server = create_todo_server() + seen = {} + # register a probe tool BEFORE track (todo_server helper or direct decorator) + track(server, "proj_test") + # call with task_id/context; assert the tool body received neither (todo_server + # tools raise on unexpected kwargs, so a successful call is the assertion). +``` + +Also: `test_track_never_raises()` — `track(object(), None)` returns the object, no exception; `test_agent_tracking_injection()` — with `enable_agent_tracking=True`, `agent_id` in required + tags `agentcat_agent_id` on events when supplied; `test_hook_mode()` — `resolve_task_id=lambda q, e: "cust-1"` → no `task_id` param in schemas, event session = `derive_task_id("cust-1", "proj_test")`, no `[MCP INSTRUCTIONS]` text ever. + +- [ ] **Step 3: Run → FAIL.** + +- [ ] **Step 4: Implement `adapters/lowlevel_v1.py`:** + +```python +"""Adapter for official MCP SDK 1.x lowlevel Server (also serves +mcp.server.fastmcp.FastMCP via its _mcp_server). All mcp imports are lazy so +the package imports under either SDK major.""" + + +def install_lowlevel_v1(server, data): + from mcp.types import (CallToolRequest, CallToolResult, ListToolsRequest, + ListToolsResult, ServerResult, TextContent, Tool) + from agentcat.modules.callpath import (decorate_content, detect_mrtr, + get_stripped_arguments, publish_tool_call_event, resolve_call, structured_mirror) + from agentcat.modules.injection import ToolSpec, build_injected_schemas + from agentcat.modules.tools import GET_MORE_TOOLS_SCHEMA, handle_report_missing + + handlers = server.request_handlers + orig_list = handlers.get(ListToolsRequest) + orig_call = handlers.get(CallToolRequest) + + def make_gmt() -> Tool: + # Reuse the existing description string and GET_MORE_TOOLS_SCHEMA from + # modules/tools.py exactly as-is (the bytes already match the TS SDK). + return Tool( + name="get_more_tools", + description=GET_MORE_TOOLS_DESCRIPTION, + inputSchema=copy.deepcopy(GET_MORE_TOOLS_SCHEMA), + annotations={"readOnlyHint": True}, + ) + + async def list_specs() -> tuple[list[Tool], list[ToolSpec]]: + tools: list[Tool] = [] + if orig_list is not None: + result = await orig_list(ListToolsRequest(method="tools/list")) + tools = [t.model_copy(deep=True) for t in result.root.tools] + if data.options.enable_report_missing and all(t.name != "get_more_tools" for t in tools): + tools.append(make_gmt()) + specs = [ToolSpec(t.name, t.inputSchema, getattr(t, "outputSchema", None)) for t in tools] + return tools, specs + + async def rebuild() -> list[ToolSpec]: + _, specs = await list_specs() + return specs + + async def wrapped_list(req): + tools, specs = await list_specs() + result = build_injected_schemas(specs, data.options) + data.injected_params_registry = result.injected_params + data.output_injection_registry = result.output_injected + for tool, s in zip(tools, specs): + tool.inputSchema = s.input_schema + if s.output_schema is not None: + tool.outputSchema = s.output_schema + return ServerResult(ListToolsResult(tools=tools)) + + async def wrapped_call(req): + name = req.params.name + raw_args = dict(req.params.arguments or {}) + ctx = _safe_request_context(server) + rc = await resolve_call( + data, name, raw_args, req, ctx, + meta_sources=[_meta_extras(req)], + legacy_client=lambda: _legacy_client_info(ctx), + ) + stripped = await get_stripped_arguments(data, data.options, name, raw_args, rebuild) + start = _now_ms() + if name == "get_more_tools" and data.options.enable_report_missing: + inner = CallToolResult(content=await handle_report_missing(stripped.get("context", ""))) + else: + new_params = req.params.model_copy(update={"arguments": stripped}) + inner = (await orig_call(req.model_copy(update={"params": new_params}))).root + mrtr = detect_mrtr(getattr(inner, "resultType", None), False) + is_err = bool(getattr(inner, "isError", False)) + await publish_tool_call_event( + server, data, rc, name, raw_args, + response=inner.model_dump(mode="json"), is_error=is_err, + error_msg=_first_text(inner) if is_err else None, + duration_ms=_now_ms() - start, mrtr=mrtr, + extra_params=extra_from_request_context(ctx), + ) + if mrtr == "input_required": + return ServerResult(inner) + update: dict = {} + new_content = decorate_content( + list(inner.content) if isinstance(inner.content, list) else None, + rc.resolution, lambda t: TextContent(type="text", text=t)) + if new_content is not None: + update["content"] = new_content + mirrored = structured_mirror(getattr(inner, "structuredContent", None), + rc.resolution, name, data.output_injection_registry) + if mirrored is not None: + update["structuredContent"] = mirrored + return ServerResult(inner.model_copy(update=update) if update else inner) + + handlers[ListToolsRequest] = wrapped_list + handlers[CallToolRequest] = wrapped_call +``` + +(`_meta_extras(req)` = `req.params.meta.model_extra` when present; `_legacy_client_info(ctx)` = `ctx.session.client_params.clientInfo` guarded; `decorate_content` internally applies only when `build_mint_back_text` is non-None — keep the single source of truth in callpath, drop the local `text` variable if redundant.) + +- [ ] **Step 5: Rewrite `track()` in `__init__.py`:** keep diagnostics/exporters/api-url blocks; replace compatibility checks + `_apply_server_tracking` with: + +```python +detection = detect_server(server) +if detection.flavor in (ServerFlavor.LOWLEVEL_V1, ServerFlavor.OFFICIAL_FASTMCP_V1): + lowlevel = detection.lowlevel + data = AgentCatData( + project_id=project_id, options=options, + server_name=getattr(lowlevel, "name", None), + server_version=getattr(lowlevel, "version", None), + ) + set_server_tracking_data(lowlevel, data) + from agentcat.modules.adapters.lowlevel_v1 import install_lowlevel_v1 + install_lowlevel_v1(lowlevel, data) +elif detection.flavor is ServerFlavor.COMMUNITY_V3: + data = AgentCatData(project_id=project_id, options=options, + server_name=getattr(server, "name", None), server_version=None) + set_server_tracking_data(server, data) + from agentcat.modules.overrides.community_v3.integration import apply_community_v3_integration + apply_community_v3_integration(server, data) # legacy path; replaced by Task 9 +elif detection.flavor is ServerFlavor.COMMUNITY_V2_UNSUPPORTED: + write_to_log("FastMCP 2.x is not supported by agentcat>=2 — pin agentcat<2 or upgrade FastMCP") +elif detection.flavor in (ServerFlavor.LOWLEVEL_V2, ServerFlavor.MCPSERVER_V2, ServerFlavor.COMMUNITY_V4): + write_to_log(f"{detection.flavor} support arrives in Tasks 12/13; server not tracked yet") +else: + # Unrecognized shape: log fingerprint AND emit a diagnostics beacon + # (fleet-level drift detection, changelog §6.7). + write_to_log(f"Unrecognized server shape; not tracked | fingerprint={detection.fingerprint}") +``` + +The whole body sits in one `try/except Exception` that logs and returns `server` — including the former `ValueError`/`TypeError` paths (breaking change: never raises). + +- [ ] **Step 6: Make imports lazy.** `rg -n "^from mcp|^import mcp|^from fastmcp|^import fastmcp" src/agentcat` — move every hit inside functions or `TYPE_CHECKING`. Then verify in the MODERN env: `uv run python -c "import agentcat; print(agentcat.__version__)"` → prints `2.0.0b1`. + +- [ ] **Step 7: Update the legacy-env test files listed above.** Delete assertions about `mcp:initialize` / `mcp:tools/list` / `agentcat:identify` events and session rollover; identify tests now assert actor fields ON the tools/call event; e2e/official `test_session_http.py` → `test_task_http.py` asserting mint-back + echo across HTTP calls. Run: `uv run pytest -q` (legacy env) → PASS. + +- [ ] **Step 8: Commit** — `git commit -m "feat(adapters)!: lowlevel-v1 engine cutover; official FastMCP unified; track() never raises"` + +--- + +### Task 9: Community adapter (FastMCP 3.x era) + retire overrides/ + +**Files:** +- Create: `src/agentcat/modules/adapters/community.py` +- Modify: `src/agentcat/__init__.py` (route COMMUNITY_V3/V4 → new adapter), `src/agentcat/modules/tools.py` (readOnlyHint on the FastMCP registration) +- Delete: `src/agentcat/modules/overrides/` (entire tree: `mcp_server.py`, `community/`, `community_v3/`, `__init__.py`) +- Test: `tests/community/test_community_v3_handles.py` (new); rewrite `tests/community/test_community_v3_inject_context.py`, `test_community_v3_event_serialization.py`, `test_community_v3_openapi.py`, `test_community_v3_runtime_state_tools.py`, `tests/e2e/community_v3/*`; delete `tests/e2e/community_v2/`, `tests/community/test_community_fastmcp.py`, `test_community_event_capture.py`, `test_community_tool_context.py`, `test_community_report_missing.py`, `test_community_dynamic_tracking.py`, `test_community_tracking_timing.py` (fastmcp-2-era suites; port any still-relevant scenario onto the v3 harness first) + +**Interfaces:** +- Produces: `install_community(server: Any, data: AgentCatData, era: int) -> None` — constructs `AgentCatMiddleware(data, server, era)` and `server.middleware.insert(0, mw)`; registers `get_more_tools` via `server.add_tool(Tool.from_function(...))` with `annotations={"readOnlyHint": True}`. +- Consumes: Tasks 4–7 exactly as defined. + +- [ ] **Step 1: Failing tests** (legacy env = fastmcp 3.x). Mirror Task 8's integration shape using the community harness (`tests/test_utils/community_todo_server.py` + `community_client.py`): schema injection order on `tools/list`; mint-back on first call; echo on second; raw-vs-stripped; hook mode; agent tracking; **only tools/call events**; OpenAPI tool coverage (port from the old inject-context test: injected `context` on OpenAPI-generated tools without breaking pickling). + +- [ ] **Step 2: Run → FAIL.** + +- [ ] **Step 3: Implement `AgentCatMiddleware`** (single class, era flag): + +```python +class AgentCatMiddleware(Middleware): # fastmcp import inside install_community + def __init__(self, data, server, era: int): + self._data, self._server, self._era = data, server, era + self._handshake_client: dict | None = None + + async def on_initialize(self, context, call_next): + params = getattr(context.message, "params", None) or context.message + info = getattr(params, "client_info", None) or getattr(params, "clientInfo", None) + if info is not None: + self._handshake_client = {"name": getattr(info, "name", None), + "version": getattr(info, "version", None)} + return await call_next(context) # NO event + + async def on_list_tools(self, context, call_next): + tools = list(await call_next(context)) + copies = [t.model_copy(deep=True) for t in tools] + specs = [ToolSpec(t.name, t.parameters, getattr(t, "output_schema", None)) for t in copies] + result = build_injected_schemas(specs, self._data.options) + self._data.injected_params_registry = result.injected_params + self._data.output_injection_registry = result.output_injected + return [t.model_copy(update={"parameters": s.input_schema, + **({"output_schema": s.output_schema} if s.output_schema is not None else {})}) + for t, s in zip(copies, specs)] + + async def on_call_tool(self, context, call_next): + msg = context.message + name, raw_args = msg.name, dict(msg.arguments or {}) + meta = self._request_meta(context) # fastmcp_context.request_context.meta, guarded + rc = await resolve_call(self._data, name, raw_args, msg, context.fastmcp_context, + meta_sources=[meta], + legacy_client=lambda: self._handshake_client) + async def rebuild(): + listed = await self._server.list_tools(run_middleware=False) + return [ToolSpec(t.name, copy.deepcopy(t.parameters), + copy.deepcopy(getattr(t, "output_schema", None))) for t in listed] + stripped = await get_stripped_arguments(self._data, self._data.options, name, raw_args, rebuild) + new_msg = msg.model_copy(update={"arguments": stripped}) # preserves input_responses/request_state/_meta + start = _now_ms() + result = await call_next(context.copy(message=new_msg)) + continuation = getattr(msg, "input_responses", None) is not None + intermediate = type(result).__name__ == "InputRequiredToolResult" or \ + getattr(result, "result_type", None) == "input_required" + mrtr = "input_required" if intermediate else ("continuation" if continuation else None) + await publish_tool_call_event(self._server, self._data, rc, name, raw_args, + response=_tool_result_payload(result), is_error=bool(getattr(result, "is_error", False)), + error_msg=None, duration_ms=_now_ms() - start, mrtr=mrtr, + extra_params=_extra_from_fastmcp(context.fastmcp_context)) + if intermediate: + return result + update = {} + new_content = decorate_content(list(result.content) if isinstance(getattr(result, "content", None), list) else None, + rc.resolution, _make_text_content) + if new_content is not None: + update["content"] = new_content + mirrored = structured_mirror(getattr(result, "structured_content", None), + rc.resolution, name, self._data.output_injection_registry) + if mirrored is not None: + update["structured_content"] = mirrored + return result.model_copy(update=update) if update else result +``` + +`get_more_tools` keeps flowing through the provider (`server.add_tool`), so its calls traverse this middleware and publish like any tool. + +- [ ] **Step 4: Route in `track()`** (`COMMUNITY_V3` → `install_community(server, data, era=3)`; leave `COMMUNITY_V4` on the placeholder branch until Task 13), delete `modules/overrides/`, fix stragglers (`rg -n "overrides" src tests`). +- [ ] **Step 5: Run legacy env full suite → PASS.** Commit — `git commit -m "feat(adapters)!: community FastMCP middleware on the shared engine; drop FastMCP 2.x"` + +--- + +### Task 10: Session/identify teardown + event pipeline restamp + migration docs + +**Files:** +- Delete: `src/agentcat/modules/session.py`, `src/agentcat/modules/compatibility.py`, `src/agentcat/modules/version_detection.py`, `tests/test_session.py`, `tests/test_stateless.py` +- Modify: `src/agentcat/types.py` (remove `AgentCatOptions.stateless`, `SessionInfo` deletion, `AgentCatData` slim per spec §3.3, `EventType` → `MCP_TOOLS_CALL` + `AGENTCAT_CUSTOM` only), `src/agentcat/__init__.py` (drop `_detect_stateless`, session imports), `src/agentcat/modules/event_queue.py` (`publish_event` stamps `sdk_language="python"`, `agentcat_version=__version__`, `server_name`/`server_version` from `AgentCatData`; no `get_session_info` merge; no `set_last_activity`), `src/agentcat/modules/identify.py` (delete `identify_session`; keep `resolve_identity`), `src/agentcat/modules/tools.py` (drop version_detection gates), `MIGRATION.md`, `README.md` +- Test: `tests/test_event_queue.py` (update stamping assertions), `tests/test_request_extra.py` (transport `mcp-session-id` still lands in `parameters.extra.sessionId`; AgentCat `session_id` unaffected) + +- [ ] **Step 1: Update tests first** (stamping + request-extra semantics), run → FAIL. +- [ ] **Step 2: Implement removals/restamp.** `rg -n "session_info|get_session_info|last_activity|INACTIVITY|is_stateless|identify_session|SessionInfo" src tests` must return zero hits in `src/` afterward. +- [ ] **Step 3: MIGRATION.md — add section "agentcat 1.x → 2.0":** sessions→tasks table (`Event.sessionId` now carries the task handle, same `ses_` prefix); removed events (`mcp:initialize`, `mcp:tools/list`, `agentcat:identify` — actor fields now ride every tools/call event); removed `AgentCatOptions.stateless`; `identify` runs per call (keep hooks cheap); `track()` no longer raises; FastMCP 2.x unsupported (pin `agentcat<2`); new: `task_id`/`agent_id` injection, `enable_agent_tracking`, `resolve_task_id`, `publish_custom_event`; supported matrix (mcp 1.x/2.x, FastMCP 3.x/4.x). +- [ ] **Step 4: Run both envs' importable checks + legacy full suite → PASS.** +- [ ] **Step 5: Commit** — `git commit -m "feat!: remove session machinery and identify/initialize/list events"` + +--- + +### Task 11: `publish_custom_event` + +**Files:** +- Modify: `src/agentcat/__init__.py`, `src/agentcat/types.py` (only if `CustomEventData` needs export wiring) +- Test: `tests/test_publish_custom_event.py` + +**Interfaces:** +- Produces: `publish_custom_event(server_or_task_id: Any, project_id: str, event_data: CustomEventData | None = None) -> None`, exported in `__all__`. + +- [ ] **Step 1: Failing tests:** string form uses the string verbatim as `session_id` (never derived); `event_data["task_id"]` takes precedence over the string; tracked-server form without `task_id` → `session_id` empty/None; event_type == `"agentcat:custom"`; `resource_name`/`tags`/`properties`/`is_error` pass through; bad input never raises. +- [ ] **Step 2: Run → FAIL. Step 3: Implement** (build `UnredactedEvent(event_type=AGENTCAT_CUSTOM_EVENT_TYPE, session_id=..., ...)`; tracked-server form resolves `AgentCatData` via `get_server_tracking_data` for project fallback; wrap in try/except + log). **Step 4: Run → PASS. Step 5: Commit** — `git commit -m "feat(events): publish_custom_event with verbatim task attribution"` + +--- + +### Task 12: Lowlevel-v2 adapter (official SDK 2.x + MCPServer) + +**Files:** +- Create: `src/agentcat/modules/adapters/lowlevel_v2.py` +- Modify: `src/agentcat/__init__.py` (route `LOWLEVEL_V2` / `MCPSERVER_V2`), `src/agentcat/modules/request_extra.py` (add `extra_from_server_context(ctx) -> dict`: headers from `ctx.request` when HTTP; keep `sessionId` only when transport provides one) +- Test: `tests/test_lowlevel_v2_handles.py`, `tests/e2e/official_modern/{conftest.py,test_task_http.py,test_mcpserver_http.py}` (modern env only) + +**Interfaces:** +- Produces: `install_lowlevel_v2(server: Any, data: AgentCatData) -> None` — swaps `_request_handlers["tools/list"|"tools/call"]` entries and re-arms `add_request_handler`. +- Consumes: Tasks 4–7 symbols; era specifics: snake_case fields, `ctx.meta`, `ctx.protocol_version`, MRTR types. + +- [ ] **Step 1: Failing tests (modern env).** Unit: real `mcp.server.lowlevel.Server` with a `tools/call` + `tools/list` handler registered via v2 API; assert injection order, mint-back, echo, strip, raw event, `agentcat_protocol_version` tag, MRTR: a handler returning `InputRequiredResult` → event tagged `input_required`, result NOT decorated; a continuation call (`params.input_responses={...}`) → tagged `continuation`; re-registration after `track()` still wrapped; `MCPServer` end-to-end via `_lowlevel_server`. E2E: streamable HTTP modern path (mirror `tests/e2e/official/conftest.py` boot pattern with the v2 app API). +- [ ] **Step 2: Run (modern env) → FAIL.** +- [ ] **Step 3: Implement:** + +```python +def install_lowlevel_v2(server, data): + # No mcp imports needed: HandlerEntry is cloned via type(entry)(...). + from agentcat.modules.callpath import ... + from agentcat.modules.injection import ToolSpec, build_injected_schemas + + def swap(method: str, wrap): + entry = server.get_request_handler(method) + if entry is None: + return None + original = entry.handler + server._request_handlers[method] = type(entry)(entry.params_type, wrap(original)) + return original + + def wrap_list(original): + async def wrapped(ctx, params): + result = await original(ctx, params) + tools = [t.model_copy(deep=True) for t in result.tools] + if data.options.enable_report_missing and all(t.name != "get_more_tools" for t in tools): + tools.append(_make_gmt_v2()) # mcp.types.Tool imported lazily here + specs = [ToolSpec(t.name, t.input_schema, t.output_schema) for t in tools] + r = build_injected_schemas(specs, data.options) + data.injected_params_registry = r.injected_params + data.output_injection_registry = r.output_injected + for t, s in zip(tools, specs): + t.input_schema = s.input_schema + if s.output_schema is not None: + t.output_schema = s.output_schema + return result.model_copy(update={"tools": tools}) + return wrapped + + def wrap_call(original): + async def wrapped(ctx, params): + name, raw_args = params.name, dict(params.arguments or {}) + rc = await resolve_call( + data, name, raw_args, params, ctx, + meta_sources=[ctx.meta], + legacy_client=lambda: _v2_legacy_client(ctx), # ctx.session.client_params.client_info + protocol_fallback=getattr(ctx, "protocol_version", None), + ) + async def rebuild(): + entry = ... # captured original list handler; call with (ctx, None) + listed = await original_list(ctx, None) + return [ToolSpec(t.name, t.input_schema.copy() if isinstance(t.input_schema, dict) else {}, ...)] + stripped = await get_stripped_arguments(data, data.options, name, raw_args, rebuild) + call_params = params.model_copy(update={"arguments": stripped}) # keeps input_responses/request_state/_meta + start = _now_ms() + if name == "get_more_tools" and data.options.enable_report_missing: + result = _gmt_result_v2(stripped) + else: + result = await original(ctx, call_params) + mrtr = detect_mrtr(getattr(result, "result_type", None), + getattr(params, "input_responses", None) is not None) + is_err = bool(getattr(result, "is_error", False)) + await publish_tool_call_event(server, data, rc, name, raw_args, + response=result.model_dump(mode="json"), is_error=is_err, + error_msg=None, duration_ms=_now_ms() - start, mrtr=mrtr, + extra_params=extra_from_server_context(ctx)) + if mrtr == "input_required": + return result + update = {} + new_content = decorate_content(list(result.content) if isinstance(result.content, list) else None, + rc.resolution, _make_text_content_v2) + if new_content is not None: + update["content"] = new_content + mirrored = structured_mirror(result.structured_content if isinstance(result.structured_content, dict) else None, + rc.resolution, name, data.output_injection_registry) + if mirrored is not None: + update["structured_content"] = mirrored + return result.model_copy(update=update) if update else result + return wrapped + + original_list = swap("tools/list", wrap_list) + swap("tools/call", wrap_call) + + original_add = server.add_request_handler + def rearming_add(method, params_type, handler): + original_add(method, params_type, handler) + if method in ("tools/list", "tools/call"): + swap(method, wrap_list if method == "tools/list" else wrap_call) + server.add_request_handler = rearming_add # instance attribute shadows the method +``` + +- [ ] **Step 4: Route in `track()`** (replace the placeholder branch); run modern-env suite → PASS; run legacy env → still PASS. +- [ ] **Step 5: Commit** — `git commit -m "feat(adapters): official MCP SDK v2 support (lowlevel + MCPServer)"` + +--- + +### Task 13: Community FastMCP 4 era + +**Files:** +- Modify: `src/agentcat/__init__.py` (route `COMMUNITY_V4` → `install_community(server, data, era=4)`), `src/agentcat/modules/adapters/community.py` (only if a v4-specific fix surfaces — the era paths were built in Task 9) +- Test: `tests/e2e/community_v4/{conftest.py,test_task_http.py}`, `tests/test_community_v4_handles.py` (modern env) + +- [ ] **Step 1: Failing tests (modern env, fastmcp 4.0.0b1):** injection/mint-back/echo end-to-end over `http_app`; **strip preserves MRTR fields** (build a `CallToolRequestParams` with `input_responses={"r1": ...}` + `request_state="s"`, assert the params object reaching the tool retains both after stripping); `InputRequiredToolResult` passes undecorated with `agentcat_mrtr=input_required`; ordering vs `ResponseCachingMiddleware` (register caching, call list twice, injected schema present both times); OpenAPI-generated tools still injectable. +- [ ] **Step 2: Run → FAIL** (routing placeholder). **Step 3:** enable routing; fix any v4 snake/camel drift the tests surface. **Step 4: Run modern env → PASS; legacy env → PASS.** +- [ ] **Step 5: Commit** — `git commit -m "feat(adapters): community FastMCP 4 era support"` + +--- + +### Task 14: Cross-flavor regressions (concurrency, removed events, rebuild) + +**Files:** +- Test: `tests/test_concurrency_handles.py`, `tests/test_removed_events.py`, `tests/test_rebuild_on_demand.py` + +- [ ] **Step 1: Concurrency** — per flavor available in the active env: `asyncio.gather` 25 simultaneous calls, each supplying a distinct `task_id`; assert each captured event's `session_id` matches its own call's handle (no cross-attribution) and each response's mint-back/mirror names only its own handle. +- [ ] **Step 2: Removed events** — full lifecycle (initialize where applicable, tools/list, tools/call ×2) per flavor; assert captured event types `== {"mcp:tools/call"}`. +- [ ] **Step 3: Rebuild-on-demand** — fresh tracked server, call `tools/call` FIRST (no prior list): registry gets rebuilt, customer handler receives stripped args, mirror gating uses the rebuilt output registry. Also the failure path: monkeypatch the list source to raise → heuristic strip still protects `get_more_tools.context`, mirror applies anyway. +- [ ] **Step 4: Run in BOTH envs → PASS. Commit** — `git commit -m "test: concurrency, removed-event, and rebuild regressions across flavors"` + +--- + +### Task 15: CI matrices, docs polish, final validation + +**Files:** +- Modify: `.github/workflows/mcp-compatibility.yml`, `.github/workflows/mcp-prerelease-compatibility.yml`, `README.md`, `MIGRATION.md` (final read-through) + +- [ ] **Step 1: `mcp-compatibility.yml`:** mcp discovery filter accepts `>=1.2,<3` (drop the implicit `<2`); fastmcp discovery accepts `>=3.0,<5`, remove the `2.9.*` carve-out; the fastmcp job's `sed` pins now target the community extra + groups from Task 1; add matrix legs that run `uv sync --group mcp-legacy` and default (modern) with the full suite (conftest gating selects the right subsets). +- [ ] **Step 2: `mcp-prerelease-compatibility.yml`:** discovery uses `pip index versions --pre` for `mcp` 2.x and `fastmcp` 4.x prerelease channels. +- [ ] **Step 3: README:** update quickstart for v2 (task handles paragraph, `enable_agent_tracking`, `resolve_task_id`, `publish_custom_event`, supported matrix, `track()`-inside-factory pattern note). +- [ ] **Step 4: Final validation (both envs):** + +```bash +uv run ruff check . && uv run ruff format --check . +uv run mypy src/agentcat --strict +uv run pytest -q # modern env +uv sync --extra community --no-group mcp-modern --group mcp-legacy && uv run pytest -q # legacy env +uv run hatch build && ls dist/ +``` + +Expected: all green; wheel + sdist for `agentcat-2.0.0b1`. + +- [ ] **Step 5: Commit** — `git commit -m "ci: dual-generation compatibility matrices for mcp 2.x and fastmcp 4"` + +--- + +## Execution notes + +- Tasks 1–11 are fully testable in the legacy env (plus import smoke in modern); Tasks 12–14 need the modern env; Task 15 exercises both. +- If any golden vector or byte-parity test fails, the reference implementation wins: diff against the TS SDK before touching the expected values (they are frozen cross-SDK contracts). +- The changelog's §8 rollout order maps to Tasks 4→7 (primitives/resolution), 5 (injection), 8–9 (wiring + removals), 5/7 (structured mint-back), 3/4 (agent_id), 12–14 (2026-era topology). + diff --git a/docs/superpowers/specs/2026-08-01-mcp-2026-07-28-python-v2-audit.md b/docs/superpowers/specs/2026-08-01-mcp-2026-07-28-python-v2-audit.md new file mode 100644 index 0000000..97f6e17 --- /dev/null +++ b/docs/superpowers/specs/2026-08-01-mcp-2026-07-28-python-v2-audit.md @@ -0,0 +1,445 @@ +# AgentCat Python SDK v2 Audit — MCP 2026-07-28 Compatibility + +> **Superseded in part (2026-08-03).** Everything below calls the handle +> `task_id`. It is now **`session_id`** throughout — the old name collided with +> the MCP Task extension (`tasks/*`), and AgentCat's handle is not an MCP task. +> The rename is mechanical (`TASK_ID_PARAM` → `SESSION_ID_PARAM`, +> `agentcat_task_id_source` → `agentcat_session_id_source`, `resolve_task_id` → +> `resolve_session_id`, `derive_task_id` → `derive_session_id`, and so on), and +> the four frozen derivation vectors are unchanged. One behavior change came +> with it: AgentCat now honors only handles it issued — see +> `agentcat-typescript-sdk/docs/superpowers/specs/2026-08-02-session-id-validation-design.md` +> and `tests/test_session_id_validation.py`. Read this document for the +> architecture; read the code for the names. + +**Date:** 2026-08-01 +**Inputs:** `2026-07-28-cross-sdk-changelog.md` (behavioral spec, Appendices A/B are +byte-authoritative), AgentCat TypeScript SDK `2.0.0-beta.4` +(`feat/explicit-handles-v2`, north star), local reference checkouts: +`reference-sdks/mcp-python-sdk` @ v2.0.0, `reference-sdks/mcp-python-sdk-v1` @ +v1.29.0, `reference-sdks/fastmcp` @ v4.0.0b1, `reference-sdks/fastmcp-v3` @ v3.4.5. +**Scope:** what must change in `agentcat` (Python, currently 1.0.2) to ship v2.0.0: +explicit `task_id`/`agent_id` handles, stateless per-request resolution, and +dual-generation support for the official MCP SDK (1.x **and** 2.x) plus community +FastMCP 3.x **and** 4.0. + +Line references are to the repos above as of this date. + +--- + +## 1. Landscape summary + +### 1.1 Protocol 2026-07-28 (what we must absorb) + +Per the cross-SDK changelog: no initialize handshake, no `Mcp-Session-Id`, +per-request self-describing metadata under `io.modelcontextprotocol/*` keys, +MRTR (a tool call may return `resultType: "input_required"` and complete on a +continuation round carrying `inputResponses`). AgentCat replaces all session +machinery with explicit stateless handles: `task_id` (echoed tool parameter, +`ses_` KSUID stored in `Event.sessionId` — zero backend changes) and opt-in +self-chosen `agent_id` (event tags). Canonical agent-facing copy and tag names +are fixed in changelog Appendix A/B and TS `src/modules/constants.ts` — reuse +byte-identical. + +### 1.2 Official MCP Python SDK v2.0.0 — server-side changes that hit us + +The low-level server was **rebuilt, not renamed** (`docs/whats-new.md:48`). + +| Seam we use today (v1.29) | v2.0.0 replacement | +| --- | --- | +| `Server.request_handlers: dict[type, handler]` (public, `lowlevel/server.py:156`) | `Server._request_handlers: dict[str, HandlerEntry]` keyed by method string, `HandlerEntry(params_type, handler)` is **frozen** (`lowlevel/server.py:92,427`); public `add_request_handler(method, params_type, handler)` / `get_request_handler(method)` (`:472,514`) | +| Handler signature `async (req: CallToolRequest) -> ServerResult` | `async (ctx: ServerRequestContext, params: CallToolRequestParams) -> CallToolResult \| InputRequiredResult` | +| `server.request_context` contextvar (`lowlevel/server.py:109,239`) | **Removed** — context is the first handler argument (`docs/migration.md:1625`) | +| `mcp.server.fastmcp.FastMCP` with `_mcp_server` + `_tool_manager` | **Module gone.** New `mcp.server.mcpserver.MCPServer` with `_lowlevel_server` + `_tool_manager` (survives) (`mcpserver/server.py:190,199`; `docs/migration.md:873`) | +| Client identity from initialize: `request_context.session.client_params.clientInfo` | Ladder: `ctx.meta["io.modelcontextprotocol/clientInfo"]` (constants `CLIENT_INFO_META_KEY`, `mcp_types/_types.py:53-63`), `ctx.protocol_version`, synthesized `ctx.session.client_params.client_info` (snake_case, may be `None`) | +| camelCase model fields (`inputSchema`, `isError`, `structuredContent`), `extra="allow"` | **snake_case** (`input_schema`, `is_error`, `structured_content: Any`); unknown extras **silently dropped** — custom data must ride `_meta` (`docs/migration.md:328-358`) | +| Tool results: bare content lists wrapped by SDK | Handlers must return full `ListToolsResult`/`CallToolResult`; bare lists are TypeErrors (`docs/whats-new.md:102`) | + +MRTR types: `InputRequiredResult` (`result_type == "input_required"`, +`mcp_types/_types.py:2074`), continuation params +`CallToolRequestParams.input_responses` / `.request_state` (`:871,1449`). + +Other v2 facts that shape the design: + +- `initialize` **cannot** be overridden via `add_request_handler` (raises, + `lowlevel/server.py:490`); it is legacy-path-only anyway. +- Provisional `Server.middleware` list exists (`docs/migration.md:1577`) but is + marked provisional/TODO — not a stable seam. +- No per-request `Server` factory in this SDK: `StreamableHTTPSessionManager` + holds one `Server`; the 2026 path builds a per-request `Connection` + (`streamable_http_manager.py:79`, `runner.py:781`). Rebuild-on-demand still + matters for replicas behind an LB and late `track()`. +- `stateless_http` still exists but only affects 2025-era clients + (`docs/whats-new.md:159`). +- `requires-python >= 3.10` — no floor bump needed. `mcp-types` requires + `pydantic>=2.12.0`. + +### 1.3 Community FastMCP 4.0.0b1 — changes vs 3.4.5 + +v4 = **v3 middleware surface + mcp SDK v2 engine + sessionless protocol** +(changelog `docs/changelog.mdx` v4.0.0b1; `docs/getting-started/whats-new.mdx`). + +Stable across v3→v4 (our integration surface survives): + +- `fastmcp.server.server.FastMCP`, `_local_provider`, `add_middleware`, + `middleware`, `server.add_tool(...)` (v4 `server.py:344,478,591,1800`). +- Middleware hooks and `MiddlewareContext` fields unchanged: `on_call_tool`, + `on_list_tools`, `message`, `fastmcp_context`, `method`, `.copy()` + (v4 `middleware/middleware.py:93-279`). +- Internal `Tool.parameters` (input schema) / `Tool.output_schema`; + `tool.model_copy(update=...)` is the sanctioned rewrite pattern (their own + `DereferenceRefsMiddleware` does it, `dereference.py:44`). +- Wraps official lowlevel Server as `self._mcp_server` in **both** (v4 + `server.py:429`, v3 `:412`). + +Breaking/behavioral for us: + +- **Detection:** our v3 probe set (`_local_provider` + `add_middleware` + + `middleware`, no `_tool_manager`) matches v4 too → v4 misclassified as v3. + v4 discriminators: `add_extension` / `_extensions` (`server.py:484,594`), + `_request_state_security` (`:402`), `fastmcp.__version__` major. +- v4 imports `mcp_types` (snake_case). camelCase reads (`params.clientInfo`, + `structuredContent`) only work through a deprecation bridge scheduled for + removal. +- `Middleware.on_initialize` **never fires** on modern (2026) connections + (`docs/getting-started/upgrading/from-fastmcp-3.mdx:430`) — initialize-based + capture is dead there. +- Arg-strip must preserve MRTR fields: our v3 strip rebuilds + `CallToolRequestParams(name=..., arguments=...)` and would **drop** + `input_responses` / `request_state` / `_meta` on v4 + (ours: `overrides/community_v3/middleware.py:228-232`; theirs: + `server.py:1407-1420`). +- Results may be `InputRequiredToolResult` — don't treat as payload + (`tools/base.py:187-222`). +- `ResponseCachingMiddleware` caches list/call results — AgentCat middleware + must sit **outermost** so injected schemas/mint-backs aren't cached-around. +- `fastmcp.tools.tool` import path removed (our TYPE_CHECKING import breaks). +- Deps: `mcp>=2.0.0,<3`, `mcp-types>=2.0.0,<3`, `pydantic>=2.12.0`, + `requires-python >= 3.10`. +- FastMCP 2.x remains on mcp 1.x with the old `_tool_manager` architecture — + unchanged from what we support today. + +### 1.4 TypeScript SDK v2 (north star) + +Public surface (`src/types.ts:1-44`, `src/index.ts:213-217,363-367`): + +- `track(server, projectId, options)` — never throws; failure logs + returns + untracked server. +- Options added: `enableAgentTracking` (default false), `resolveTaskId` + (hook mode). Removed/changed: identify runs per call (no cache); no session + options. +- `publishCustomEvent(serverOrSessionId, projectId, eventData)` with + `CustomEventData.taskId` (verbatim, never derived; takes precedence). +- `AgentCatIDPrefixes` now includes `Agent = "agt"` (reserved). + +Mechanics (all specified in changelog §3–§6; implemented in TS +`src/modules/handles.ts`, `src/engine/*`): + +- Mint `ses_` KSUID per call when no `task_id` supplied; supplied values + trusted verbatim (trim-only check). `task_source ∈ supplied|minted|hook`. +- Deterministic hook derivation (changelog §3.6): SHA-256 of + `customer_id[:project_id]`, timestamp = 2024-01-01 epoch + `uint32_be(hash[0:4]) % 31536000000` + ms, payload = `hash[4:20]`, standard KSUID base62 → `ses_` + 27 chars. + **Golden vectors** (TS `src/tests/handles.test.ts:53-68`): + - `("customer-abc", "proj_1")` → `ses_2cOHEO0LYGADMzRvWTXXVbbgxgm` + - `("customer-abc", None)` → `ses_2cZY3tvyI25O2AmL2CGVo2B1IIj` + - `(" x ", "p")` → `ses_2c3yR5mYKQdLaXsJNgZH6erbfQK` + - `("x", "p")` → `ses_2bw285VY9apdgUgTPXKFnT6P4G0` +- Injection pipeline (pure): order customer params → `task_id` → `agent_id` → + `context`; deep copy; drop `additionalProperties: false`; skip composed + schemas; collision-skip + warn; registries (injected-params + output-injection) + drive stripping and mirroring; rebuild-on-demand from the original list + handler when a call lands with no registry; heuristic strip fallback + (`task_id`/`agent_id`/`context`, except `get_more_tools` keeps `context`). +- Mint-back: text block only on mint (never hook mode), also on `isError` + results; `_mcp_instructions` mirror on every response into plain-object + `structuredContent` gated by output registry; customer key wins; event + records the **undecorated** result. +- `agent_id`: required-in-schema, soft server-side; tags + `agentcat_agent_id` (CR/LF→space, ≤200 chars) + `agentcat_agent_id_source`. +- Client identity ladder per request: envelope → `_meta` → legacy initialize + capture. Protocol version → `agentcat_protocol_version` tag. +- MRTR tags `agentcat_mrtr = input_required|continuation`; intermediate rounds + are never decorated. +- Copy constants to reuse byte-identical (TS `src/modules/constants.ts:20-62`): + `TASK_ID_PARAM_DESCRIPTION`, `AGENT_ID_PARAM_DESCRIPTION`, + `AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE`, `MINT_BACK_HEADER_TASK`, + `MINT_BACK_CLOSER`, `mintBackTaskLine`, `mintBackConfirmed`, + `MCP_INSTRUCTIONS_FIELD_DESCRIPTION`, `MCP_INSTRUCTIONS_TASK_ID_DESCRIPTION`, + `MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION`, `MCP_INSTRUCTIONS_KEY`, + `META_CLIENT_INFO_KEY`, `META_PROTOCOL_VERSION_KEY`, and the five + `agentcat_*` tag names. + +--- + +## 2. Current Python SDK — inventory + +### 2.1 Reusable as-is or with small changes + +- Event queue + processing order (redact → sanitize → truncate → send): + `modules/event_queue.py:106-154,289-326`. +- Exporters (`modules/exporters/*`), diagnostics (`modules/diagnostics.py`), + logging, truncation/sanitization/redaction, exceptions capture. +- Per-server storage via `weakref.WeakKeyDictionary` + (`modules/internal.py:14-16`) — already matches changelog §6.3 guidance. +- Vendored KSUID (`thirdparty/ksuid/ksuid.py`) — has `from_bytes` + + base62 `__str__` (zfill 27); deterministic derivation is implementable as + `bytes(uint32_be((ts_ms - 1400000000000)//1000)) + hash[4:20]` → base62. +- `get_more_tools` handler + schema (`modules/tools.py:13-44`) — description + already byte-identical to TS; needs `readOnlyHint` annotation + handle + injection (not exempt) + context preserved on strip. +- Tag/property callback resolution (`modules/internal.py:123-192`) and tag + validation — needs an SDK-owned-tags merge that bypasses customer validation + and the 50-tag cap. +- Event tags/properties, `identify` (already cache-less per call: + `modules/identify.py:9-42`) — but the separate `agentcat:identify` event goes + away; result gets stamped on the tool-call event instead. + +### 2.2 To be removed (changelog §3.1) + +- `modules/session.py` session machinery: `new_session_id` rollover, + `INACTIVITY_TIMEOUT_IN_MINUTES` (30), `get_server_session_id` + (`session.py:183-200`), `last_activity` bookkeeping, stateless client-info + header fallbacks used for session identity. +- `AgentCatOptions.stateless` + `_detect_stateless` (`__init__.py:35-54`) — + meaningless once sessions are gone. +- `AgentCatData.session_id/session_info/last_activity/is_stateless` and the + identity fields on `SessionInfo` (client name/version become per-request). +- Event emissions for `mcp:initialize`, `mcp:tools/list`, and + `agentcat:identify` (interception of initialize/tools-list remains where it + exists, for capture/injection — they just publish nothing). +- Transport-session reads for correlation (`request_extra.py:158-181` reads + `mcp-session-id` into `parameters.extra.sessionId` — see Open decision 5). + +### 2.3 Not present today (net-new) + +- Handle primitives module: mint, extract, deterministic derive (+ golden + vectors), mint-back text builder, `_mcp_instructions` mirror builder, agent + tag clamp. +- Injected-params + output-injection registries; pure injection pipeline + (today's context injection is inline per flavor and never touches + `additionalProperties` or composed schemas: `context_parameters.py:26-56`). +- Output-schema extension (`_mcp_instructions` optional property) — nothing + touches `outputSchema` today. +- Per-request client identity ladder + protocol version tag; envelope/`_meta` + reads (`rg io.modelcontextprotocol src/` → zero hits today). +- MRTR detection/tagging. +- `agent_id` support end-to-end. +- Official SDK v2 adapter (method-string handlers, ctx-as-argument) and + `MCPServer` support; FastMCP v4 discriminator + snake_case/MRTR-safe + middleware. +- `publish_custom_event` (Python has no custom-event API at all today; TS does + — see Open decision 2). + +--- + +## 3. Gap analysis — required changes by area + +### 3.1 Handle primitives (new `modules/handles.py`) + +- `new_task_id()` → `ses_` KSUID (reuse `generate_prefixed_ksuid`). +- `derive_task_id(id, project_id)` — changelog §3.6 algorithm; pin the four TS + golden vectors in tests (cross-language contract). Caller trims; derive does + not. +- `extract_handle(args, name)` — trimmed non-empty `str` else absent; verbatim + trust. +- `resolve_handles(...)` — prompted vs hook mode; `task_source` + supplied/minted/hook; hook errors/None → silent random mint (log, never + agent-facing); agent extraction only when `enable_agent_tracking`. +- Mint-back builders: text block (exact 3-line format), confirmed copy + (`task_id and agent_id` + pluralization), `_mcp_instructions` object + (omission rules: no `task_id` key in hook mode; no `agent_id` key unless + supplied; nothing if neither). +- Tag builder: `agentcat_task_id_source` always; `agentcat_agent_id` + (CR/LF→space, ≤200), `agentcat_agent_id_source`, `agentcat_protocol_version`, + `agentcat_mrtr` conditionally. SDK tags merge **after** customer tags, + exempt from the 50-tag cap and customer validation. + +### 3.2 Options & public API (`types.py`, `__init__.py`) + +- Add `enable_agent_tracking: bool = False` and + `resolve_task_id: Callable[[Any, Any], str | None | Awaitable[str | None]] | None = None` + (docstrings adapted from TS JSDoc; prefer the types.ts wording — the + index.ts `@param` line for agent tracking is stale on "minted by server"). +- Remove `stateless`. Keep everything else (`identify`, redaction, exporters, + tags/properties, `custom_context_description`, ...). +- `AgentCatData` slims to `project_id`, `options`, plus per-server engine + state: injected-params registry (`dict[str, set[str]]`), output-injection + registry (`set[str]`), original-list-handler ref for rebuild. +- `track()` **never throws** (changelog §6.3): today `ValueError`/`TypeError` + propagate (`__init__.py:198-202`) — v2 logs + returns the server untracked. + Module-level state stays first-wins. +- Version bump to `2.0.0` (see Open decision 6 re: beta), `EventType` prunes to + tool-call (+ custom); constants file gains the Appendix A/B strings. + +### 3.3 Shared injection pipeline (new `modules/injection.py`) + +Pure function: `(options, listed_tools) -> (advertised_tools, injected_params_registry, output_registry)`. + +- Param order customer → `task_id` → `agent_id` → `context`; deep-copy schemas + (per-SDK-flavor copy strategy: `model_copy(deep=True)` for pydantic tools, + `copy.deepcopy` for dict schemas); remove `additionalProperties: false`; + skip composed schemas with warning; collision-skip per param with warning + (customer's own `task_id` must reach their handler — never stripped). +- `task_id` optional; `agent_id` **added to `required`**; hook mode injects no + `task_id` and uses `AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE`. +- `get_more_tools` included (handles injected; its `context` is bespoke). +- Output side: for every tool with plain-object `output_schema`, add optional + `_mcp_instructions` property (sub-descriptions from Appendix A); record in + output registry; composed → warn, content-only mint-back. +- Determinism is a hard requirement (rebuild-on-demand equality). + +### 3.4 Call path (per flavor, shared helpers) + +resolve handles → identify → client-info ladder → strip (cloned) → dispatch → +MRTR probe → mint-back/mirror (wire only) → publish event (raw request, +undecorated response, `Event.sessionId = task_id`, actor + client fields, SDK +tags). Error results also get mint-back. Fallback heuristic strip when no +registry and rebuild failed. + +### 3.5 Per-flavor adapters + +| Flavor | Detection (per-object) | Seam | Notes | +| --- | --- | --- | --- | +| lowlevel v1 | has `request_handlers` (type-keyed dict) + `request_context` in `dir()` | wrap `request_handlers[CallToolRequest/ListToolsRequest]` (as today, `overrides/mcp_server.py:34-241`) | camelCase models; strip via copied `params.arguments` (stop in-place `pop`, `mcp_server.py:207-209`) | +| lowlevel v2 | has `_request_handlers` (str-keyed) + `add_request_handler`; no `request_context` | replace `_request_handlers["tools/call"|"tools/list"]` with new frozen `HandlerEntry(params_type, wrapped)` | ctx arg carries `meta`/`protocol_version`/`session`; snake_case; must return full result models; MRTR union | +| official FastMCP v1 (`mcp.server.fastmcp`) | module `mcp.server.fastmcp` + `_mcp_server` + `_tool_manager` | keep ToolManager patching or re-route through the lowlevel adapter on `_mcp_server` | initialize/tools-list events no longer published — the "minimal override" shrinks | +| MCPServer v2 (`mcp.server.mcpserver`) | `_lowlevel_server` + `_tool_manager`, class `MCPServer` | wrap `_lowlevel_server._request_handlers` (same engine as lowlevel v2) | MCPServer converts tool exceptions to `is_error=True` (`mcpserver/server.py:421`) | +| community FastMCP v3 | current probe set AND NOT v4 discriminators | middleware (as today) with fixes | keep `context.copy(message=...)` strip | +| community FastMCP v4 | v3 probes AND (`add_extension`/`_extensions` or `_request_state_security`) | same middleware, era-aware: snake_case, preserve `input_responses`/`request_state`/`_meta` on strip, handle `InputRequiredToolResult`, register outermost | `on_initialize` dead on modern era — client info via ladder only | +| community FastMCP v2 | `_mcp_server` + `_tool_manager`, module `fastmcp` | **proposed drop** (Open decision 1) | if kept: monkey-patch path needs the full v2 handle treatment | + +Version-specific knowledge stays in thin adapters; probe results logged as a +shape fingerprint with a diagnostics beacon on unrecognized shapes (changelog +§6.7). + +### 3.6 Per-request client identity / actor identity + +- Ladder (changelog §5.1): envelope → `_meta` → legacy initialize capture. + Python mapping: lowlevel v2 `ctx.meta[CLIENT_INFO_META_KEY]` (TypedDict); + lowlevel v1 `request.params.meta` extras (`RequestParams.Meta` is + `extra="allow"`); legacy = v1 `request_context.session.client_params.clientInfo` + / v2 `ctx.session.client_params.client_info`; FastMCP v3/v4 + `fastmcp_context.request_context.meta` + initialize capture only on + handshake era. Narrow: accept `name`/`version` only if individually `str`. +- Protocol version: same ladder; v2 also `ctx.protocol_version`. Tag + `agentcat_protocol_version`. +- Identify: stamp result onto the tool-call event + (`identify_actor_given_id/name`, `identify_data`); delete the + `agentcat:identify` event type; SessionInfo-as-cache disappears — + server name/version + SDK metadata stamped at publish from server object + + package metadata. + +### 3.7 Event pipeline changes + +- `Event.session_id` carries the task ID (`ses_` prefix preserved; wire field + unchanged — zero backend migration). +- Publish only `mcp:tools/call` (+ `agentcat:custom` if custom events land). +- Raw request recorded unstripped; response recorded undecorated. +- SDK tags merged post-customer-tags, exempt from cap/validation. +- `duration`/timestamps, redaction/sanitization/truncation unchanged. + +### 3.8 Packaging, CI, docs + +- `pyproject.toml`: version `2.0.0`; `mcp>=1.2.0,<3`; **relax + `pydantic<2.12`** (pin origin: commit `e594b24`, pre-dates mcp 2/fastmcp 4 + which both require `>=2.12`) → propose `pydantic>=2.0.0,<3`; community extra + → `fastmcp>=3.0.0,<5` (pending Open decision 1); mypy/ruff unchanged; + Python floor stays 3.10 (matches mcp v2 and fastmcp v4). +- Dev/test env: uv **conflict groups** `mcp-legacy` (mcp 1.x) / `mcp-modern` + (mcp 2.x) so the suite can sync either major — the gitignored local + `uv.lock` already models exactly this (`agentcat 2.0.0b1`, conflicting + extras, mcp 1.29.0/2.0.0). +- CI: `mcp-compatibility.yml` discovery keeps testing every mcp minor ≥1.2 + and now <3 with per-major test selection; fastmcp discovery range updates + (drop `!=2.9.*` if 2.x support is dropped); `mcp-prerelease-compatibility.yml` + gains the 4.0.0bX / 2.x prerelease channels. The e2e suites split + official/legacy vs official/modern, community_v3, community_v4. +- Docs: MIGRATION.md gains a "1.x → 2.0" section mirroring TS MIGRATION.md; + README examples; module docstrings for new options (AGENTS.md requirement). + +--- + +## 4. Test plan requirements (mirroring TS suites) + +- **Golden vectors:** the four derivation vectors above, byte-equal. +- **Handles unit:** mint prefix/uniqueness, extraction trust model, tag clamp + (CR/LF, 200), mint-back text exact bytes, confirmed-copy pluralization, + `_mcp_instructions` omission rules (hook mode / no agent). +- **Injection:** param order, additionalProperties removal, composed skip, + collision skip + passthrough of customer's own `task_id`, output-schema + extension, registry contents, determinism (pipeline twice ≡). +- **Call path:** supplied/minted/hook sources; strip-clone (customer handler + sees clean args; raw event keeps handles); error-result mint-back; mirror + gating incl. no-registry-mirror-anyway rule; customer `_mcp_instructions` + wins; MRTR intermediate undecorated + tags; continuation tag. +- **Per-flavor e2e (HTTP):** official v1 (existing harness), official v2 + (new harness on mcp 2 lock), MCPServer v2, community v3 (existing), + community v4 (new; must run against 4.0.0b1). Concurrency regression: + parallel calls with distinct handles never cross-attribute (no shared + mutable per-request state). +- **Removed-events regression:** no initialize/tools-list/identify events + published on any flavor. +- **Dual-generation detection:** shape fingerprints for all seven object + shapes; unrecognized-shape beacon. + +--- + +## 5. Risks & gotchas + +1. **pydantic resolver wall:** `agentcat[community]` with fastmcp 4 forces + pydantic ≥2.12 at install time; our `<2.12` pin makes v2 uninstallable + alongside it. Relaxing risks customers on old pydantic — the original pin + (#16) reason should be re-verified against `agentcat-api==1.0.0` models. +2. **Frozen `HandlerEntry`:** wrapping must replace the entry, not mutate it; + re-registration after `track()` (customer calls `add_request_handler` + later) needs a re-arm story (TS solves via `registrationPatch`). +3. **v2 outbound validation:** `_serialize` validates results per protocol + version — malformed injected schemas / mirrors raise server-side. Injection + must produce schema-valid output on both eras (snake_case vs camelCase + serialization). +4. **Extras dropped in v2 models:** never attach unknown attributes to v2 + pydantic objects; `structured_content` is `Any` (safe), `Tool` extras are + not (use real fields only). +5. **FastMCP 4 strip bug class:** rebuilding params without MRTR fields + severs continuations — must `model_copy(update={"arguments": ...})`. +6. **Middleware ordering (v4):** response caching / dereference middlewares + can cache or rewrite around us; AgentCat must be outermost and re-inject on + whatever list result it sees. +7. **In-place mutation on the v1 path today** (`arguments.pop("context")`, + shared dict) violates the copy rule and can corrupt concurrent retries — + v2 rewrite fixes it, but the v1 adapter must be audited for every mutation. +8. **`get_more_tools` context:** heuristic fallback strip must except it, or + its real parameter is destroyed (changelog §6.2). +9. **Float precision in derivation:** compute the KSUID timestamp in integer + milliseconds (`(ts_ms - 1400000000000) // 1000`), never through + `datetime.timestamp()` floats, or golden vectors will drift on boundaries. +10. **camelCase bridge removal (fastmcp 4.x):** code must be snake_case-first + with camelCase fallback for v3, not the reverse. +11. **Diagnostics/event-queue globals:** first-wins init already holds, but + `track()`-in-factory patterns mean repeated `track()` calls must stay + idempotent per server object (weak-keyed state covers this). + +--- + +## 6. Open decisions (need user input) + +1. **Community FastMCP 2.x support:** drop in agentcat v2 (recommended — the + local uv.lock experiment already excludes it; fastmcp 2.x predates the + provider architecture and carries the heaviest monkey-patch surface) or + keep 7-flavor support. +2. **`publish_custom_event`:** add to Python v2 for TS parity (changelog §3.7 + semantics: verbatim task ID, `CustomEventData.task_id` precedence, + `agentcat:custom` type) or defer to 2.1. +3. **Official-SDK v2 seam:** wrap `_request_handlers` entries directly + (recommended: deterministic, mirrors TS engine, private-API-friendly per + our CI change detection) vs build on the provisional `Server.middleware`. +4. **Official FastMCP v1 path consolidation:** keep today's ToolManager + monkey-patching, or re-route official-FastMCP-v1 through the lowlevel-v1 + engine on `_mcp_server` (one engine, fewer patch surfaces — recommended). +5. **`parameters.extra.sessionId` telemetry:** changelog says transport + session IDs are ignored for correlation; keep capturing `mcp-session-id` + into the raw-request `extra` (telemetry-only, recommended) or remove + entirely. +6. **Release train:** ship `2.0.0b1` prerelease first (matches TS + `2.0.0-beta.4` posture + fastmcp 4.0.0b1 timing) or straight to `2.0.0`. diff --git a/docs/superpowers/specs/2026-08-01-python-sdk-v2-explicit-handles-design.md b/docs/superpowers/specs/2026-08-01-python-sdk-v2-explicit-handles-design.md new file mode 100644 index 0000000..41a2d54 --- /dev/null +++ b/docs/superpowers/specs/2026-08-01-python-sdk-v2-explicit-handles-design.md @@ -0,0 +1,466 @@ +# AgentCat Python SDK v2 — Explicit Handles Design + +**Date:** 2026-08-01 +**Status:** Approved (design review 2026-08-01) +**Inputs:** `2026-07-28-cross-sdk-changelog.md` (behavioral spec; Appendices A/B +byte-authoritative), audit +`docs/superpowers/specs/2026-08-01-mcp-2026-07-28-python-v2-audit.md`, +AgentCat TypeScript SDK `2.0.0-beta.4` (`feat/explicit-handles-v2`, north star). + +> **Superseded in part (2026-08-03).** Everything below calls the handle +> `task_id`. It is now **`session_id`** throughout — the old name collided with +> the MCP Task extension (`tasks/*`), and AgentCat's handle is not an MCP task. +> The rename is mechanical (`TASK_ID_PARAM` → `SESSION_ID_PARAM`, +> `agentcat_task_id_source` → `agentcat_session_id_source`, `resolve_task_id` → +> `resolve_session_id`, `derive_task_id` → `derive_session_id`, and so on), and +> the four frozen derivation vectors are unchanged. One behavior change came +> with it: AgentCat now honors only handles it issued — see +> `agentcat-typescript-sdk/docs/superpowers/specs/2026-08-02-session-id-validation-design.md` +> and `tests/test_session_id_validation.py`. Read this document for the +> architecture; read the code for the names. +**Target:** `agentcat` `2.0.0b1` (prerelease train; stable `2.0.0` follows). + +## 0. Locked decisions + +1. Community FastMCP **2.x support dropped**; community support is FastMCP 3.x + and 4.x. FastMCP-2-shaped servers get a clear log ("not supported by + agentcat>=2; pin agentcat<2") and are returned untracked. +2. **`publish_custom_event` ships in v2** with TS-parity semantics. +3. Official MCP SDK v2 integration replaces entries in the private + `Server._request_handlers` dict (frozen `HandlerEntry` swap). +4. Official FastMCP v1 (`mcp.server.fastmcp`) is **unified** through the + lowlevel-v1 adapter via `server._mcp_server`; the ToolManager monkey-patch + layer is deleted. +5. Transport `mcp-session-id` is still captured into the raw request's + `parameters.extra.sessionId` (telemetry only; never correlation). +6. Architecture: **shared engine + thin adapters** (Approach A). + +## 1. Goal + +Replace session machinery with the 2026-07-28 explicit-handles model: a +stateless per-call `task_id` handle (echoed as an injected tool parameter, +stored in `Event.sessionId` with the `ses_` prefix — zero backend changes) and +an opt-in agent-chosen `agent_id` (event tags). Support servers built on the +official MCP Python SDK **1.x and 2.x** and community FastMCP **3.x and 4.x** +through one `track()` call, with per-object feature detection. Agent-facing +copy is byte-identical to the TS SDK (§9). + +## 2. Module layout + +``` +src/agentcat/ + __init__.py track(), publish_custom_event(), exports + types.py AgentCatOptions, AgentCatData, CustomEventData, EventType (pruned) + modules/ + constants.py + Appendix A/B strings, tag names, meta keys, "agt" prefix + handles.py NEW mint / derive / extract / resolve / mint-back / tags + injection.py NEW pure schema-injection pipeline + registries + callpath.py NEW shared tools/call orchestration + client_identity.py NEW per-request client info + protocol version ladder + detection.py NEW six-shape classifier + fingerprint + beacon + (replaces compatibility.py + version_detection.py) + adapters/ NEW (replaces overrides/) + lowlevel_v1.py official SDK 1.x Server; also official FastMCP v1 via _mcp_server + lowlevel_v2.py official SDK 2.x Server; also MCPServer via _lowlevel_server + community.py FastMCP 3.x/4.x middleware (era flag) + identify.py per-call resolver; stamps event fields; no identify event + tools.py get_more_tools (+ readOnlyHint annotation) + request_extra.py kept; per-flavor context accessors injected + session.py DELETED + event_queue.py, exporters/, diagnostics.py, redaction.py, truncation.py, + sanitization.py, validation.py, logging.py, internal.py (kept; targeted edits) +``` + +Per-server state stays in `internal.py`'s `WeakKeyDictionary`, keyed on the +lowlevel server object for official flavors (v1 `_mcp_server` / +v2 `_lowlevel_server` / the `Server` itself) and on the FastMCP instance for +community flavors. Module-level state (event queue, telemetry manager, +diagnostics) initializes once, first-wins; repeated `track()` on the same +server is idempotent. + +## 3. Public API + +### 3.1 `track(server, project_id=None, options=None) -> server` + +Same signature. **Never raises** (changelog §6.3): all failures — including +missing `project_id`+exporters and incompatible servers — log a warning, emit +a diagnostics beacon, and return the server untracked. (v1 raised +`ValueError`/`TypeError`; breaking change documented in MIGRATION.md.) + +### 3.2 `AgentCatOptions` changes + +Added: + +- `enable_agent_tracking: bool = False` — injects a required `agent_id` + parameter into every tool. Agents self-generate `model|harness|nonce`; + echoed in `_mcp_instructions`, stamped as event tags. Omission never rejects + a call server-side; enforcement is client-side schema validation. +- `resolve_task_id: Callable[[Any, Any], str | None | Awaitable[str | None]] | None = None` + — hook mode. When set: no `task_id` parameter injected, no task instructions + prompted; the returned string is trimmed and deterministically derived with + the project ID into a `ses_` KSUID (`task_source="hook"`). `None` return or + a raised exception mints silently (`task_source="minted"`, hook error + logged). Same `(request, extra)` call shape as `identify`; sync or async. + +Removed: `stateless` (and `_detect_stateless`). Unchanged: everything else. +`identify` docs updated: runs on **every** tool call, result stamped on that +event; hooks must be cheap. + +### 3.3 `AgentCatData` (internal) slims to + +`project_id: str | None`, `options: AgentCatOptions`, plus engine state: +`injected_params_registry: dict[str, set[str]] | None`, +`output_injection_registry: set[str] | None`, +`original_list_source: Callable | None` (rebuild seam), +`server_info: (name, version)` captured at track time. +Deleted fields: `session_id`, `session_info`, `last_activity`, `is_stateless`, +`tool_registry`, `wrapped_tools`, `monkey_patched`. + +### 3.4 `publish_custom_event(server_or_task_id, project_id, event_data=None) -> None` + +TS parity (`publishCustomEvent`, TS `src/index.ts:363`): + +- `CustomEventData` (TypedDict, `total=False`): `task_id`, `resource_name`, + `parameters`, `response`, `message`, `duration`, `is_error`, `error`, + `tags`, `properties`. +- Tracked-server form: `event_data["task_id"]` used **verbatim** as + `Event.sessionId`; absent → event publishes **without** a task (empty + session). +- String form: first argument is a task-id string used **verbatim** (never + derived); `event_data["task_id"]` takes precedence. +- Event type `agentcat:custom`. Fire-and-forget; never raises. + +### 3.5 Exports + +Add `publish_custom_event`, `CustomEventData` to `__all__`. Constants gain +`AGENT_ID_PREFIX = "agt"` (reserved — server-side agent minting was removed +from the design; never mint with it). + +## 4. Handle primitives (`modules/handles.py`) + +- `new_task_id() -> str` — `ses_` + random KSUID (existing + `generate_prefixed_ksuid`). +- `derive_task_id(id: str, project_id: str | None) -> str` — changelog §3.6, + integer-only arithmetic: + + ```python + input = f"{id}:{project_id}" if project_id else id + h = sha256(input.encode()).digest() + ts_ms = 1704067200000 + (int.from_bytes(h[0:4], "big") % 31536000000) + ts_field = (ts_ms - 1400000000000) // 1000 # uint32 + raw = ts_field.to_bytes(4, "big") + h[4:20] # 20-byte KSUID + return "ses_" + str(Ksuid.from_bytes(raw)) # base62, zfill 27 + ``` + + Does **not** trim (callers trim). Pinned to the four TS golden vectors + (§10 tests). +- `extract_handle(arguments, name) -> str | None` — `str` whose `.strip()` is + non-empty → trimmed value; anything else → `None`. Supplied values trusted + verbatim (no shape validation). +- `resolve_handles(arguments, options, project_id, request, extra) -> HandleResolution` + — dataclass: `task_id: str`, `task_source: Literal["supplied","minted","hook"]`, + `agent_id: str | None`, `hook_mode: bool`. Prompted mode per changelog §3.3; + hook mode per §3.5. `agent_id` extracted only when + `enable_agent_tracking` (source always `"supplied"`). +- Mint-back builders (§9 copy): + - `build_mint_back_text(task_id)` — exactly + `MINT_BACK_HEADER_TASK + "\n" + mint_back_task_line(task_id) + "\n" + MINT_BACK_CLOSER`. + - `build_confirmed_text(names)` — `mint_back_confirmed` template with + `" and "` join and singular/plural tail. + - `build_mcp_instructions(resolution, minted_this_call) -> dict | None` — + keys: `task_id` (omit in hook mode), `agent_id` (omit unless supplied), + `instructions` (mint-back text if minted this call, else confirmed copy). + Returns `None` when neither handle key would be present. +- `build_sdk_tags(resolution, protocol_version, mrtr) -> dict[str, str]` — + `agentcat_task_id_source` always; `agentcat_agent_id` (CR/LF→`" "`, then + `[:200]`) + `agentcat_agent_id_source="supplied"` when supplied; + `agentcat_protocol_version` when present; `agentcat_mrtr` when applicable. + +## 5. Injection pipeline (`modules/injection.py`) + +Pure, deterministic function used by both list-time injection and +rebuild-on-demand: + +``` +build_injected_list(tools, options) -> (advertised_tools, + injected_params: dict[str, set[str]], + output_injected: set[str]) +``` + +Rules (changelog §6.1): + +1. `get_more_tools` is appended by the adapter **before** the pipeline runs + (when `enable_report_missing`), so it flows through injection like any + tool. +2. Injection order per tool: customer params → `task_id` → `agent_id` → + `context`. Handle injection runs before the context injector. +3. `task_id`: optional string param, description §9.1. Never added to + `required` (omission is the minting signal). Skipped entirely in hook mode + and when `enable_tracing=False`. +4. `agent_id` (only when `enable_agent_tracking`): string param, **appended to + `required`**; description §9.2 (default) or §9.3 (hook mode). +5. `context` (when `enable_tool_call_context`): existing behavior, description + `custom_context_description`; skipped for `get_more_tools` (bespoke param). +6. Deep-copy before modifying — dict schemas via `copy.deepcopy`, pydantic + tool objects via `model_copy(deep=True)`/rebuilt dicts. Never mutate the + customer's registered tool. +7. If the input schema has `additionalProperties: false`, delete it. +8. Composed input schemas (`oneOf`/`allOf`/`anyOf` at top level): skip all + injection for that tool, log warning, record empty registry entry. +9. Name collision (tool already defines `task_id`/`agent_id`/`context`): skip + that parameter only, log warning; the customer's own parameter must reach + their handler (the registry simply omits it, so stripping spares it). +10. Every advertised tool gets a registry entry (possibly empty set). +11. Output side: tools whose `output_schema` is a plain object with a + `properties` bag get an optional `_mcp_instructions` object property + (field + sub-property descriptions §9.5); recorded in `output_injected`. + Composed/missing output schemas: skipped (content-only mint-back), warn + on composed. + +The pipeline operates on a normalized internal representation +(`name`, `description`, `input_schema: dict`, `output_schema: dict | None`, +`annotations`) produced/consumed by per-adapter codecs, so era differences +(camelCase `inputSchema` v1 / snake_case `input_schema` v2 / FastMCP +`parameters`) live in the adapters, not the pipeline. + +## 6. Call path (`modules/callpath.py`) + +Shared orchestration invoked by every adapter for `tools/call`: + +1. **Resolve** handles (§4) from raw arguments. +2. **Identify**: run `options.identify(request, extra)`; never throws; result + stamps `identify_actor_given_id` / `identify_actor_name` / `identify_data` + on this event only. No cache, no identify event. +3. **Client identity + protocol version** via `client_identity.py` ladder + (§7); stamped on the event; protocol version → tag. +4. **Strip** on a cloned request: remove exactly the registry's params for + this tool. Registry missing → **rebuild-on-demand**: invoke the adapter's + `original_list_source`, run the pipeline, store registries; if that fails, + heuristic strip (`task_id`, `agent_id`, `context` — but `get_more_tools` + keeps `context`) and skip the structured mirror gate (mirror anyway, per + changelog §3.4b exception). +5. **Dispatch** the customer handler with stripped arguments. + `get_more_tools` short-circuits to its internal handler (still injected, + still publishes). +6. **MRTR probe**: intermediate = result `result_type`/`resultType` == + `"input_required"` (or `isinstance` of the era's type); continuation = + request params carry `input_responses`/`inputResponses`. Tag accordingly. +7. **Decorate the wire result only** (never the event copy), skipping + intermediate rounds entirely: + - Text block appended to a **copied** `content` array only when + `task_source == "minted"` and not hook mode — including `is_error` + results. Only requirement: result has a list `content`. + - `_mcp_instructions` mirrored into `structured_content` / + `structuredContent` on **every** completing response — but only when the + result already carries a **plain-dict** structured content (absent or + non-dict → no mirror; TS `mirrorStructuredMintBack`, `handles.ts:152-163`), + gated by the output registry (see rebuild exception above); mirror onto a + shallow copy; a customer-supplied `_mcp_instructions` key wins. +8. **Publish** one `mcp:tools/call` event: raw unstripped arguments, + undecorated response, `session_id = task_id`, `user_intent` = captured + `context`, actor + client fields, duration, error capture, customer + tags/properties resolved first, then SDK tags merged (SDK wins on + collision, exempt from the 50-tag customer cap and customer validation). + +`tools/list` path: adapter intercepts, appends `get_more_tools`, runs the +pipeline, caches registries + advertised list, returns it. **No event.** +Initialize interception (where the era has one) captures legacy client info +only; **no event**. + +## 7. Per-request client identity (`modules/client_identity.py`) + +Resolution ladder (first hit wins; changelog §5.1), each rung narrowed to +per-field `isinstance(x, str)`: + +1. **Envelope / lifted meta**: lowlevel v2 `ctx.meta[META_CLIENT_INFO_KEY]`; + FastMCP `fastmcp_context.request_context.meta[...]`. +2. **`_meta` passthrough** (pre-2026 servers): v1 + `request.params.meta` extras (`model_extra`) under the fully-qualified key. +3. **Legacy initialize capture**: v1 + `request_context.session.client_params.clientInfo`; v2 + `ctx.session.client_params.client_info` (may be `None`); community + handshake-era initialize capture (weak-keyed, per server — a convenience + cache of static handshake data, not per-request state). + +Protocol version: same ladder for `META_PROTOCOL_VERSION_KEY`; lowlevel v2 +also has `ctx.protocol_version`. Stamped as `agentcat_protocol_version` tag +when present. + +Server name/version + SDK language + agentcat version are stamped at publish +time from track-time capture and package metadata (no SessionInfo cache +object). + +## 8. Detection & adapters + +### 8.1 Classifier (`modules/detection.py`) + +Probe the object in hand; never import version-specific symbols for the +decision. Returns `(flavor, fingerprint)`: + +| Flavor | Probes | +| --- | --- | +| `community-v4` | class contains `FastMCP`, module starts `fastmcp`, has `_local_provider` + `add_middleware` + `middleware`, AND (`add_extension` or `_extensions` or `_request_state_security`) | +| `community-v3` | same minus the v4 discriminators, and no `_tool_manager` | +| `community-v2` (**unsupported**) | module starts `fastmcp`, has `_mcp_server` + `_tool_manager` → log + return untracked | +| `official-fastmcp-v1` | module starts `mcp.server.fastmcp`, has `_mcp_server` + `_tool_manager` → adapt lowlevel-v1 on `_mcp_server` | +| `mcpserver-v2` | has `_lowlevel_server` + `_tool_manager` (class `MCPServer`) → adapt lowlevel-v2 on `_lowlevel_server` | +| `lowlevel-v1` | has `request_handlers` dict (type-keyed) + `request_context` in `dir()` | +| `lowlevel-v2` | has `_request_handlers` + `add_request_handler`, no `request_context` | + +Unrecognized shape: log the full probe fingerprint, emit a diagnostics beacon +(fleet drift detection), return untracked. + +### 8.2 `adapters/lowlevel_v1.py` + +Wraps `request_handlers[ListToolsRequest]` and `[CallToolRequest]` (and +`[InitializeRequest]` for legacy client-info capture only). Argument stripping +clones `request.params.arguments` — the in-place `pop` from v1 is gone. +Decoration builds a new `CallToolResult` (camelCase era). Serves both the bare +`Server` and official FastMCP v1 (tracked via `_mcp_server`; `get_more_tools` +appended list-side, call short-circuited — no ToolManager registration, +no `_get_cached_tool_definition` patch; the injected params never reach +FastMCP's validation layer because stripping happens above it). + +### 8.3 `adapters/lowlevel_v2.py` + +For `"tools/list"` / `"tools/call"`: read `entry = server.get_request_handler(m)`, +store `entry.handler` as the original, write back +`HandlerEntry(entry.params_type, wrapped)` into `_request_handlers[m]` +(frozen dataclass — replace, never mutate). Wrapped handlers receive +`(ctx, params)`; must return complete result models (era codec produces +`ListToolsResult`/`CallToolResult`; `structured_content` is `Any`, safe for +the mirror; never attach unknown attributes to v2 models). MRTR union +respected: `InputRequiredResult` passes through undecorated (tag only). +Re-arm: after `track()`, `add_request_handler` is patched on the instance so +a customer re-registering `tools/*` gets re-wrapped (TS `registrationPatch` +equivalent). Serves both bare v2 `Server` and `MCPServer` via +`_lowlevel_server`. + +### 8.4 `adapters/community.py` + +One `AgentCatMiddleware(Middleware)` with an era flag (v3/v4), inserted at +**index 0 = outermost** (verified: the chain builds via +`for mw in reversed(self.middleware)`, v4 `server.py:555`, so element 0 is +called first — matching today's v3 integration) so response +caching/dereference middlewares cannot cache around injection; caching below +us keys on **stripped** arguments, which is the desired semantics. `on_list_tools`: run pipeline over the FastMCP `Tool` +objects (`parameters`/`output_schema` attrs, `model_copy(update=...)`). +`on_call_tool`: strip via +`context.copy(message=message.model_copy(update={"arguments": stripped}))` — +preserving `input_responses`, `request_state`, `_meta` and every other field. +Result handling tolerates `ToolResult` and `InputRequiredToolResult` (v4). +snake_case-first field access with camelCase fallback for v3. `on_initialize` +captures legacy client info when it fires (handshake era only). Rebuild seam +(identical in both eras, verified): `await server.list_tools(run_middleware=False)` +(v3 `server.py:651`, v4 `server.py:827`); on failure, heuristic strip. `get_more_tools` registered via +`server.add_tool(Tool.from_function(...))` as today, plus `readOnlyHint`. + +## 9. Byte-authoritative agent-facing copy + +Source of truth: TS `src/modules/constants.ts` (verified on +`feat/explicit-handles-v2`) and changelog Appendix A. Python constants must +be byte-identical (same em-dashes, quotes, spacing). Inventory: + +### 9.1 `TASK_ID_PARAM_DESCRIPTION` + +> REQUIRED on every call after your first. This MCP server associates all of your tool calls for a given task using task_id; a call that arrives without it cannot be associated with your earlier work and is treated as the start of an unrelated task, disconnected from the original goal. Omit it on your first call only — the server will issue one in the _mcp_instructions field of the result (or a trailing [MCP INSTRUCTIONS] text block) — then echo that exact value on every later call. Never invent a value, and do not issue parallel tool calls until the server has issued your task_id. One task_id covers the whole goal from start to finish: when you spawn subagents you MUST give them this same task_id, or their work is severed from yours. Without task_id, this server does not function as intended. + +### 9.2 `AGENT_ID_PARAM_DESCRIPTION` + +> REQUIRED on every call, including your first. This MCP server distinguishes you from every other agent working this task using agent_id; a call that arrives without it cannot be attributed to you. Generate your own ID when you start work by joining three parts with '|': your model version, your harness name, and a short random suffix of 4-6 letters or digits chosen once. Example: opus-4.80-1m|claude-code|k3n9x. Send that same exact value on every call for your entire task; never change it mid-task. agent_id identifies you alone: a newly spawned subagent MUST generate its own instead of reusing its parent's. Without agent_id, this server does not function as intended. + +### 9.3 `AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE` + +Identical to 9.2 except the first body sentence reads "…distinguishes you +from every other agent using agent_id;" (no "working this task"). + +### 9.4 Mint-back text + +``` +MINT_BACK_HEADER_TASK = "[MCP INSTRUCTIONS]: task_id issued." +MINT_BACK_CLOSER = "Without task_id, this server does not function as intended." +mint_back_task_line(task_id) = f" task_id={task_id} — required on every subsequent tool call" +mint_back_confirmed(names) = f"[MCP INSTRUCTIONS]: {' and '.join(names)} confirmed. Keep sending " + + ("these exact values" if len(names) > 1 else "this exact value") + + " on every call." +``` + +### 9.5 `_mcp_instructions` schema descriptions + +- Field: "Your handles for this task, confirmed by this MCP server on every response, and the instructions for echoing them on later calls. Read and follow." +- `task_id`: "Echo this exact value as the task_id argument on every subsequent tool call." +- `agent_id`: "Your agent_id as this server received it. Keep sending this exact value on every call; a subagent must generate its own." + +### 9.6 Wire keys, tags, prefixes + +`MCP_INSTRUCTIONS_KEY = "_mcp_instructions"`, +`META_CLIENT_INFO_KEY = "io.modelcontextprotocol/clientInfo"`, +`META_PROTOCOL_VERSION_KEY = "io.modelcontextprotocol/protocolVersion"`, +tags `agentcat_task_id_source` / `agentcat_agent_id` / +`agentcat_agent_id_source` / `agentcat_protocol_version` / `agentcat_mrtr`, +`AGENTCAT_CUSTOM_EVENT_TYPE = "agentcat:custom"`, prefixes `ses` / `evt` / +`agt` (reserved). Existing `DEFAULT_CONTEXT_DESCRIPTION` and the +`get_more_tools` description/context copy are already byte-identical to TS — +assert, don't retype. + +## 10. Testing + +- **Golden vectors** (cross-language contract, frozen): + `derive_task_id("customer-abc", "proj_1") == "ses_2cOHEO0LYGADMzRvWTXXVbbgxgm"`, + `derive_task_id("customer-abc") == "ses_2cZY3tvyI25O2AmL2CGVo2B1IIj"`, + `derive_task_id(" x ", "p") == "ses_2c3yR5mYKQdLaXsJNgZH6erbfQK"`, + `derive_task_id("x", "p") == "ses_2bw285VY9apdgUgTPXKFnT6P4G0"`. +- **Constants parity test**: assert every §9 string equals the expected bytes + (guards accidental rewording; mirrors TS `constants.test.ts`). +- **Handles unit**: mint prefix; extraction trust model incl. non-string/empty; + agent tag clamp; mint-back exact bytes; confirmed pluralization; + `_mcp_instructions` omission rules. +- **Injection unit**: order, deep-copy isolation, `additionalProperties` + removal, composed skip, collision skip + customer param passthrough, output + extension, registry contents, determinism (run twice, equal). +- **Call-path unit**: supplied/minted/hook; hook error/None → silent mint; + strip-clone (handler sees clean args, event records raw); error-result + mint-back; mirror gating incl. rebuild-failure mirror-anyway; customer + `_mcp_instructions` wins; MRTR intermediate undecorated + tagged; + continuation tagged; identify per call; ladder rungs; removed events never + published. +- **Per-flavor suites** under uv conflict groups `mcp-legacy` / `mcp-modern`: + existing official-v1 + community-v3 harnesses updated; new official-v2 + (lowlevel + MCPServer, streamable HTTP modern path) and community-v4 + (4.0.0b1) harnesses; concurrency regression (parallel calls, distinct + handles, no cross-attribution) on every flavor; late-`track()` / + rebuild-on-demand coverage (call before any list). +- **CI**: `mcp-compatibility.yml` matrix extends to mcp 2.x minors and + fastmcp 3.x/4.x (drop 2.x discovery + the `!=2.9.*` carve-out); + `mcp-prerelease-compatibility.yml` tracks 2.x/4.x prerelease channels. + +## 11. Packaging & migration + +- `pyproject.toml`: version `2.0.0b1`; `mcp>=1.2.0,<3`; + `pydantic>=2.0.0,<3` (re-verify `agentcat-api==1.0.0` under pydantic 2.12 + before merging); community extra `fastmcp>=3.0.0,<5`; keep + `requires-python>=3.10`; add `[tool.uv] conflicts` groups `mcp-legacy` + (`mcp>=1.2.0,<2`) / `mcp-modern` (`mcp>=2.0.0,<3`) for dev/test. +- MIGRATION.md: new "agentcat 1.x → 2.0" section (sessions → tasks; removed + events; removed `stateless`; identify per-call; `track()` never raises; + FastMCP 2.x dropped; new options; `publish_custom_event`), mirroring TS + MIGRATION.md structure. +- README + module docstrings for the new options and factory-pattern + (`track()` inside the request factory) guidance. + +## 12. Error-handling posture + +`track()` never raises. Hook (`resolve_task_id`) errors mint silently + log. +`identify` errors drop actor fields for that event. Injection failure on one +tool skips that tool's injection (registry entry empty) + logs. Decoration +failure returns the customer's original result. Detection failure returns the +server untracked + beacon. Event publishing keeps existing queue semantics +(redact-fail drops event; sanitize/truncate-fail continue). Nothing AgentCat +does may alter customer tool behavior beyond the specified wire decoration. + +## 13. Non-goals (changelog §7) + +No use of the `io.modelcontextprotocol/tasks` extension; no `Mcp-Method` / +`Mcp-Name` routing headers; no server-side session or handle storage; no +server-side `agent_id` minting; no hard rejection of calls missing +`agent_id`; no FastMCP 2.x compatibility layer. diff --git a/pyproject.toml b/pyproject.toml index 48d8aad..95fe21c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "agentcat" -version = "1.0.2" +version = "2.0.0b1" description = "Analytics tool for MCP (Model Context Protocol) servers and AI agents - tracks tool usage patterns and provides insights" authors = [ { name = "AgentCat, Inc.", email = "support@agentcat.com" }, @@ -18,9 +18,9 @@ classifiers = [ "Programming Language :: Python :: 3.12", ] dependencies = [ - "mcp>=1.2.0", + "mcp>=1.2.0,<3", "agentcat-api==1.0.0", - "pydantic>=2.0.0,<2.12", + "pydantic>=2.0.0,<3", "requests>=2.31.0", ] @@ -31,7 +31,7 @@ dependencies = [ [project.optional-dependencies] community = [ - "fastmcp>=2.7.0,!=2.9.*", + "fastmcp>=3.0.0,<5", ] dev = [ "pytest>=7.0.0", @@ -117,6 +117,11 @@ exclude = [ "dist", ] +# The agent-facing copy in constants.py must stay byte-identical to the TS SDK +# (tests/test_constants_copy.py), so its long literals cannot be wrapped. +[tool.ruff.per-file-ignores] +"src/agentcat/modules/constants.py" = ["E501"] + [tool.ruff.isort] known-first-party = ["agentcat"] @@ -126,3 +131,13 @@ dev = [ "pytest-asyncio>=1.0.0", "pytest-cov>=6.1.1", ] +mcp-legacy = ["mcp>=1.2.0,<2", "fastmcp>=3.0.0,<4"] +# fastmcp-slim is fastmcp 4's own runtime package; it is listed explicitly so +# its prerelease is permitted under prerelease = "if-necessary-or-explicit" +# (uv only honors prerelease markers on direct dependencies). +mcp-modern = ["mcp>=2.0.0,<3", "fastmcp>=4.0.0b1,<5", "fastmcp-slim>=4.0.0b1,<5"] + +[tool.uv] +conflicts = [[{ group = "mcp-legacy" }, { group = "mcp-modern" }]] +default-groups = ["dev", "mcp-modern"] +prerelease = "if-necessary-or-explicit" diff --git a/src/agentcat/__init__.py b/src/agentcat/__init__.py index 933c5f3..52c2a27 100644 --- a/src/agentcat/__init__.py +++ b/src/agentcat/__init__.py @@ -1,57 +1,52 @@ """AgentCat - Analytics Tool for MCP Servers.""" import os -import warnings +from collections.abc import Mapping from datetime import datetime, timezone from importlib.metadata import version from typing import Any __version__ = version("agentcat") -from agentcat.modules.overrides.mcp_server import override_lowlevel_mcp_server -from agentcat.modules.session import get_session_info, new_session_id - -from .modules.compatibility import ( - COMPATIBILITY_ERROR_MESSAGE, - is_community_fastmcp_v2, - is_community_fastmcp_v3, - is_compatible_server, - is_official_fastmcp_server, -) +from .modules.constants import AGENTCAT_CUSTOM_EVENT_TYPE +from .modules.detection import Detection, ServerFlavor, detect_server from .modules.diagnostics import init_diagnostics -from .modules.internal import set_server_tracking_data +from .modules.internal import get_server_tracking_data, set_server_tracking_data from .modules.logging import set_debug_mode, write_to_log +from .modules.validation import validate_tags from .types import ( + AgentCatData, + AgentCatOptions, + CustomEventData, EventPropertiesFunction, EventTagsFunction, IdentifyFunction, - AgentCatData, - AgentCatOptions, RedactionFunction, + ResolveSessionIdFunction, + UnredactedEvent, UserIdentity, ) - -def _detect_stateless(server) -> bool: - """Auto-detect stateless mode from FastMCP server settings. - - Best-effort: community FastMCP v3 deprecated per-instance .settings - in favor of global fastmcp.settings, but the global isn't per-server. - The deprecated shim is the only per-instance API available. - AgentCatOptions(stateless=True) is the recommended explicit path. - """ - try: - with warnings.catch_warnings(): - warnings.simplefilter("ignore", DeprecationWarning) - result = server.settings.stateless_http - if result: - write_to_log( - "Auto-detected stateless HTTP mode from your FastMCP server's .settings. " - "If this is incorrect, please pass stateless=False to AgentCatOptions and file a bug report." - ) - return result - except (AttributeError, RuntimeError): - return False +# Flavors an adapter already exists for. Everything else is logged and returned +# untracked — track() never raises, so an unsupported server degrades to a +# no-op rather than breaking the customer's process at import/startup time. +_LOWLEVEL_V1_FLAVORS = (ServerFlavor.LOWLEVEL_V1, ServerFlavor.OFFICIAL_FASTMCP_V1) +_LOWLEVEL_V2_FLAVORS = (ServerFlavor.LOWLEVEL_V2, ServerFlavor.MCPSERVER_V2) +# Both community generations share one middleware; the era selects its field +# bridge and names the generation an installed middleware was built for. This +# map is also the single answer to "is this a community flavor", so a later +# generation is one entry here rather than a branch in two places. +# +# The values are `adapters.community.ERA_V3` / `ERA_V4`, spelled out rather +# than imported: importing that module at module scope would pull the event +# queue — and its worker thread, executor and signal handlers — into every +# `import agentcat`. Every adapter import in this file is deferred for the same +# reason. Only the V4 pairing is pinned by a test that runs +# (`tests/test_community_v4_handles.py`); the V3 one is not, because the suite +# that could assert it is collected under the OTHER mcp major, where `ERA_V3` +# is unreachable from a modern-env test. The era is a log/diagnostic label, so +# a wrong pairing would misreport rather than misbehave. +_COMMUNITY_ERAS = {ServerFlavor.COMMUNITY_V3: 3, ServerFlavor.COMMUNITY_V4: 4} def track( @@ -66,11 +61,13 @@ def track( options: Configuration options including telemetry exporters Returns: - The server instance with tracking enabled + The server instance, tracked when its shape is one AgentCat supports. - Raises: - ValueError: If neither project_id nor exporters are provided - TypeError: If server is not a compatible MCP server instance + Never raises. A misconfiguration (no project_id and no exporters), an + unsupported server generation, or an unrecognized object is logged to + ~/agentcat.log and mirrored to SDK diagnostics; the server comes back + untracked so an analytics problem can never take a customer's MCP server + down. This is a 2.0 breaking change — 1.x raised ValueError/TypeError. Example: Attach custom metadata to every auto-captured event using @@ -84,175 +81,366 @@ def track( ... event_properties=lambda req, ctx: {"feature_flags": ["dark_mode"]}, ... )) """ - if options is None: - options = AgentCatOptions() + try: + if options is None: + options = AgentCatOptions() - set_debug_mode(options.debug_mode) + set_debug_mode(options.debug_mode) - # Initialize internal diagnostics before anything can fail, so even an - # invalid setup still emits a failure beacon. Never throws into the host. - init_diagnostics(project_id, disabled=options.disable_diagnostics) + # Initialize internal diagnostics before anything can fail, so even an + # invalid setup still emits a failure beacon. Never throws into the host. + init_diagnostics(project_id, disabled=options.disable_diagnostics) - # Wrap the whole setup so any failure emits a diagnostic. Config-contract - # errors (ValueError/TypeError) still propagate; tracking-application errors - # are logged but never break the host (server is still returned). - try: - if not project_id and not options.exporters: - raise ValueError( - "Either project_id or exporters must be provided. " - "Use project_id for AgentCat, exporters for telemetry-only mode, or both." - ) + _apply_tracking(server, project_id, options) + except Exception as e: + write_to_log(f"Error initializing AgentCat: {e}") - if not is_compatible_server(server): - raise TypeError(COMPATIBILITY_ERROR_MESSAGE) - - is_community_v3 = is_community_fastmcp_v3(server) - is_community_v2 = is_community_fastmcp_v2(server) - is_official_fastmcp = is_official_fastmcp_server(server) - is_fastmcp_v2 = is_official_fastmcp or is_community_v2 - - # Determine where to store tracking data: - # - v2 FastMCP servers use server._mcp_server - # - v3 and low-level servers use the server itself - if is_fastmcp_v2: - lowlevel_server = server._mcp_server - else: - lowlevel_server = server - - # Metadata-only setup-started beacon (INFO — no fail/error/Warning). - server_kind = ( - "fastmcp-v2" - if is_fastmcp_v2 - else "fastmcp-v3" - if is_community_v3 - else "lowlevel" + return server + + +def _apply_tracking( + server: Any, project_id: str | None, options: AgentCatOptions +) -> None: + """Detect the server's shape and install the matching adapter.""" + if not project_id and not options.exporters: + write_to_log( + "Warning: Failed to track server - neither project_id nor exporters " + "were provided. Use project_id for AgentCat, exporters for " + "telemetry-only mode, or both. Server returned untracked." ) + return + + detection = detect_server(server) + is_lowlevel_v1 = detection.flavor in _LOWLEVEL_V1_FLAVORS + is_lowlevel_v2 = detection.flavor in _LOWLEVEL_V2_FLAVORS + + community_era = _COMMUNITY_ERAS.get(detection.flavor) + + if is_lowlevel_v1 or is_lowlevel_v2: + # The adapter wraps the lowlevel object, which for official FastMCP is + # its `_mcp_server` and for MCPServer its `_lowlevel_server` — that is + # also where the tracking data is keyed. + target = detection.lowlevel + elif community_era is not None: + # Community flavors are adapted via middleware on the server itself. + target = server + else: + _log_unsupported(detection) + return + + write_to_log( + f"AgentCat setup started | project {project_id or '(telemetry-only)'} | " + f"server {detection.flavor.value}" + ) + + if options.exporters: + from agentcat.modules.event_queue import set_telemetry_manager + from agentcat.modules.telemetry import TelemetryManager + + set_telemetry_manager(TelemetryManager(options.exporters)) + write_to_log(f"Telemetry initialized with {len(options.exporters)} exporter(s)") + + # Server identity is captured once, here: it is static for the life of the + # server and there is no session cache left to re-read it from at publish + # time. + data = AgentCatData( + project_id=project_id, + options=options, + server_name=getattr(target, "name", None), + server_version=getattr(target, "version", None), + ) + set_server_tracking_data(target, data) + + # Resolve API base URL: option > new env var > legacy env var > default + api_base_url = ( + options.api_base_url + or os.environ.get("AGENTCAT_API_URL") + or os.environ.get("MCPCAT_API_URL") + ) + if api_base_url: + from agentcat.modules.event_queue import event_queue + + event_queue.configure(api_base_url) + + # The high-level object that owns the lowlevel one, when the two differ. + # Only the inner tap needs it: on an official FastMCP or an MCPServer the + # customer's tool sits below a tool manager the lowlevel object cannot + # reach, and that is where a raised exception has to be recorded before the + # SDK flattens it into an isError result. + facade = server if server is not target else None + + if is_lowlevel_v1: + from agentcat.modules.adapters.lowlevel_v1 import install_lowlevel_v1 + + install_lowlevel_v1(target, data, facade) + elif is_lowlevel_v2: + from agentcat.modules.adapters.lowlevel_v2 import install_lowlevel_v2 + + install_lowlevel_v2(target, data, facade) + elif community_era is not None: + from agentcat.modules.adapters.community import install_community + + install_community(server, data, era=community_era) + + # Metadata-only setup-complete beacon (INFO). A start-without-complete + # signals a failed setup. + write_to_log( + f"AgentCat setup complete | project {project_id or '(telemetry-only)'} | " + f"tracing={options.enable_tracing} " + f"context={options.enable_tool_call_context} " + f"report_missing={options.enable_report_missing} " + f"agent_tracking={options.enable_agent_tracking} " + f"hook_mode={options.resolve_session_id is not None} " + f"exporters={len(options.exporters) if options.exporters else 0}" + ) + + +def _log_unsupported(detection: Detection) -> None: + """Explain why a server was not tracked, loudly enough to reach diagnostics. + + write_to_log tees every entry to the SDK diagnostics sink, so the + unrecognized-shape line below IS the fleet-drift beacon: the full probe + fingerprint travels with it, which is how a new upstream server shape gets + noticed across the installed base (cross-SDK changelog 6.7). + + Every flavor the classifier can name now has an adapter, so the only two + outcomes left are the one shape that is deliberately refused (FastMCP 2.x) + and the fingerprint beacon. A generation newer than this build classifies + as UNKNOWN rather than as itself, so it reaches the beacon — which carries + more than a "not supported yet" line could. + """ + if detection.flavor is ServerFlavor.COMMUNITY_V2_UNSUPPORTED: write_to_log( - f"AgentCat setup started | project {project_id or '(telemetry-only)'} | " - f"server {server_kind}" + "Warning: Failed to track server - FastMCP 2.x is not supported by " + "agentcat>=2. Pin agentcat<2 or upgrade to FastMCP 3.x or 4.x. " + "Server returned untracked." + ) + else: + write_to_log( + "Warning: Failed to track server - Unrecognized MCP server shape; " + f"server returned untracked | fingerprint={detection.fingerprint}" ) - if options.exporters: - from agentcat.modules.event_queue import set_telemetry_manager - from agentcat.modules.telemetry import TelemetryManager - telemetry_manager = TelemetryManager(options.exporters) - set_telemetry_manager(telemetry_manager) - write_to_log( - f"Telemetry initialized with {len(options.exporters)} exporter(s)" - ) +def publish_custom_event( + server_or_session_id: Any, + project_id: str, + event_data: CustomEventData | None = None, +) -> None: + """Publish one `agentcat:custom` event for work that is not a tool call. - session_id = new_session_id() - session_info = get_session_info(lowlevel_server) - data = AgentCatData( - session_id=session_id, - project_id=project_id, - last_activity=datetime.now(timezone.utc), - session_info=session_info, - options=options, - is_stateless=options.stateless if options.stateless is not None else _detect_stateless(server), - ) - set_server_tracking_data(lowlevel_server, data) + A background job, a webhook, a checkout step — anything the customer wants + on the same timeline as the tool calls AgentCat captures automatically. - # Resolve API base URL: option > new env var > legacy env var > default - api_base_url = ( - options.api_base_url - or os.environ.get("AGENTCAT_API_URL") - or os.environ.get("MCPCAT_API_URL") - ) - if api_base_url: - from agentcat.modules.event_queue import event_queue - event_queue.configure(api_base_url) + Args: + server_or_session_id: a tracked MCP server, or a session ID string. A server + tracked with `enable_tracing=False` publishes nothing, the same + silence its tool calls keep; a session ID string carries no options to + consult, so that form always publishes. + project_id: the AgentCat project. Used as-is in the session-ID-string + form; in the tracked-server form the project captured at `track()` + time wins, so a telemetry-only server still publishes. + event_data: optional `CustomEventData`. `session_id` attributes the event + to a session **verbatim** — never validated, trimmed, prefixed or + derived, since it is a deliberate server-side call rather than an + agent's guess, so a + caller's own correlation ID arrives exactly as given. It takes + precedence over a session ID string. Without one the event publishes + without a session: handles are per-request in v2, so a tracked server + has no ambient session to fall back on. + + Fire-and-forget: never raises, and never lets one unusable field cost the + whole event. Two different rules get it there. A `parameters`, `response` + or `properties` value that is not a dict is WRAPPED — `response="shipped"` + is recorded as `{"value": "shipped"}` — because the wire field holds an + object and the payload is the caller's to keep (a non-dict `error` becomes + `{"message": ...}`, the shape its consumers read). A mistyped + `resource_name`, `message`, `duration`, `is_error` or `tags` is DROPPED, + because those wire fields are strictly typed and a near miss carries no + payload worth preserving. Both cases log; the event publishes either way. + + TS parity — `publishCustomEvent`, design §3.4. + + Example: + >>> import agentcat + >>> agentcat.publish_custom_event(server, "proj_abc123", { + ... "session_id": "ses_2cOHEO0LYGADMzRvWTXXVbbgxgm", + ... "resource_name": "checkout", + ... "message": "order confirmed", + ... }) + """ + try: + _publish_custom_event(server_or_session_id, project_id, event_data) + except Exception as e: + write_to_log(f"Warning: failed to publish custom event - {e}") - if not data.tracker_initialized: - data.tracker_initialized = True - write_to_log( - f"Dynamic tracking initialized for server {id(lowlevel_server)}" - ) - _apply_server_tracking( - server, lowlevel_server, data, - is_community_v3, is_official_fastmcp, is_community_v2 +def _publish_custom_event( + server_or_session_id: Any, project_id: str, event_data: CustomEventData | None +) -> None: + """The body of `publish_custom_event`, minus the never-raises wrapper.""" + # Imported here, not at module scope: importing the event queue constructs + # the global queue (worker thread, executor, signal handlers), which must + # not happen merely because someone imported `agentcat`. + from agentcat.modules import event_queue as queue_module + from agentcat.utils import get_agentcat_version + + data: Mapping[str, Any] = event_data if isinstance(event_data, dict) else {} + if event_data is not None and not isinstance(event_data, dict): + write_to_log( + "publish_custom_event: event_data is not a dict " + f"(got {type(event_data).__name__}); publishing without it" ) - if project_id: + session_id = _verbatim_session_id(data.get("session_id")) + project = _wire_scalar("project_id", project_id, str) + server: Any = None + if isinstance(server_or_session_id, str): + session_id = session_id or server_or_session_id + if not project: write_to_log( - f"AgentCat initialized with dynamic tracking for session " - f"{session_id} on project {project_id}" + "publish_custom_event: project_id is required when the first " + "argument is a session ID string; event dropped" ) - else: + return + else: + server = server_or_session_id + tracking = _tracking_data(server) + if tracking is None: write_to_log( - f"AgentCat initialized in telemetry-only mode for session {session_id}" + "publish_custom_event: first argument is neither a tracked " + f"server nor a session ID string (got {type(server).__name__}); " + "event dropped. Call agentcat.track() first, or pass a session ID." ) + return + if not tracking.options.enable_tracing: + # Every other event type is gated on this inside the adapters, and + # TS gates it inside publishEvent itself; Python's publish_event + # has no gate, so this entry point carries its own. A customer who + # turned tracing off does not start emitting a new event type. + write_to_log( + "publish_custom_event: tracing is disabled for this server " + "(enable_tracing=False); event dropped" + ) + return - # Metadata-only setup-complete beacon (INFO). A start-without-complete - # (or the ERROR diagnostics below) signals a failed setup. + tags = data.get("tags") + if tags is not None and not isinstance(tags, dict): write_to_log( - f"AgentCat setup complete | project {project_id or '(telemetry-only)'} | " - f"tracing={options.enable_tracing} " - f"context={options.enable_tool_call_context} " - f"report_missing={options.enable_report_missing} " - f"exporters={len(options.exporters) if options.exporters else 0}" + "publish_custom_event: dropping 'tags' - expected dict, " + f"got {type(tags).__name__}" ) + tags = None + + error = data.get("error") + if error is not None and not isinstance(error, dict): + # `error` has a known shape (`ErrorData`) and consumers read its + # message, so a bare value becomes one rather than a nested payload. + error = {"message": str(error)} + + event = UnredactedEvent( + session_id=session_id or None, + project_id=project or None, + event_type=AGENTCAT_CUSTOM_EVENT_TYPE, + timestamp=datetime.now(timezone.utc), + resource_name=_wire_scalar("resource_name", data.get("resource_name"), str), + user_intent=_wire_scalar("message", data.get("message"), str), + duration=_wire_scalar("duration", data.get("duration"), int), + is_error=_wire_scalar("is_error", data.get("is_error"), bool), + parameters=_wire_payload("parameters", data.get("parameters")), + response=_wire_payload("response", data.get("response")), + properties=_wire_payload("properties", data.get("properties")), + error=error, + tags=validate_tags(tags) if isinstance(tags, dict) else None, + sdk_language=queue_module.SDK_LANGUAGE, + agentcat_version=get_agentcat_version(), + ) + + if server is not None: + # The tracked path stamps the project, the server identity captured at + # track() time and the customer's redaction hook — the same publish + # every tool-call event goes through. + queue_module.publish_event(server, event) + else: + queue_module.event_queue.add(event) - except (ValueError, TypeError) as e: - # Config-contract failures: emit a failure diagnostic, then propagate so - # callers still see the error (preserves existing public behavior). - write_to_log(f"Warning: Failed to track server - {e}") - raise - except Exception as e: - write_to_log(f"Error initializing AgentCat: {e}") + where = ( + f"for session {event.session_id}" if event.session_id else "without a session" + ) + write_to_log(f"Published custom event {where} | {AGENTCAT_CUSTOM_EVENT_TYPE}") - return server +def _tracking_data(server: Any) -> AgentCatData | None: + """This server's tracking data, or None if it is not a server at all. -def _apply_server_tracking( - server: Any, - lowlevel_server: Any, - data: AgentCatData, - is_community_v3: bool, - is_official_fastmcp: bool, - is_community_v2: bool, -) -> None: - """Apply the appropriate tracking method based on server type.""" - if is_community_v3: - from agentcat.modules.overrides.community_v3.integration import ( - apply_community_v3_integration, - ) + The lookup is keyed by weak reference, so an int, a string or a dict raises + rather than missing — all three mean the same thing here. + """ + try: + return get_server_tracking_data(server) + except Exception: + return None - apply_community_v3_integration(server, data) - write_to_log( - f"Applied Community FastMCP v3 middleware for server {id(server)}" - ) - elif is_official_fastmcp: - from agentcat.modules.overrides.mcp_server import ( - override_lowlevel_mcp_server_minimal, - ) - from agentcat.modules.overrides.official.monkey_patch import ( - apply_official_fastmcp_patches, - ) +def _verbatim_session_id(value: Any) -> str | None: + """`event_data["session_id"]` if it can be sent as-is, else nothing. - apply_official_fastmcp_patches(server, data) - override_lowlevel_mcp_server_minimal(lowlevel_server, data) + Verbatim cuts both ways: a non-string is not stringified into a session ID the + caller never chose, it is dropped and the event lands untethered. + """ + if value is None or isinstance(value, str): + return value + write_to_log( + f"publish_custom_event: ignoring non-string session_id ({type(value).__name__})" + ) + return None - elif is_community_v2: - from agentcat.modules.overrides.community.monkey_patch import ( - patch_community_fastmcp, - ) - patch_community_fastmcp(server) - write_to_log(f"Applied Community FastMCP v2 patches for server {id(server)}") +def _wire_scalar(field: str, value: Any, kind: type) -> Any: + """A value the strict wire field can hold, or None. - else: - override_lowlevel_mcp_server(lowlevel_server, data) + `PublishEventRequest` types these `StrictStr`/`StrictInt`/`StrictBool`, so a + near miss (`1` for a bool, `12.5` for an int) fails construction and takes + the entire event with it. One unusable field is not worth an event. + """ + if value is None or ( + isinstance(value, kind) and (kind is bool or not isinstance(value, bool)) + ): + return value + write_to_log( + f"publish_custom_event: dropping '{field}' - expected {kind.__name__}, " + f"got {type(value).__name__}" + ) + return None + + +def _wire_payload(field: str, value: Any) -> dict[str, Any] | None: + """A dict for the dict-shaped wire fields, wrapping whatever is not one. + + `parameters`/`response`/`properties` are `Optional[Dict[str, Any]]` while + `CustomEventData` types them `Any`, so a string or a list is a plausible + input rather than a bug. The adapters discard a non-dict `response` + (`adapters/_common.response_payload`) because there it is a serialization + anomaly with no author; here it is exactly what the caller asked to record, + so it is kept. + """ + if value is None or isinstance(value, dict): + return value + write_to_log( + f"publish_custom_event: wrapping non-dict '{field}' " + f"({type(value).__name__}) as {{'value': ...}}" + ) + return {"value": value} __all__ = [ # Main API "track", + "publish_custom_event", # Configuration "AgentCatOptions", + # Type for publish_custom_event payloads + "CustomEventData", # Types for identify functionality "UserIdentity", "IdentifyFunction", @@ -261,4 +449,5 @@ def _apply_server_tracking( # Types for event metadata callbacks "EventTagsFunction", "EventPropertiesFunction", + "ResolveSessionIdFunction", ] diff --git a/src/agentcat/modules/__init__.py b/src/agentcat/modules/__init__.py index 4a0d2a2..ae27987 100644 --- a/src/agentcat/modules/__init__.py +++ b/src/agentcat/modules/__init__.py @@ -1,28 +1,15 @@ """AgentCat modules.""" -from .compatibility import is_compatible_server, is_official_fastmcp_server -from .context_parameters import ( - add_context_parameter_to_schema, - add_context_parameter_to_tools, -) from .internal import get_server_tracking_data, set_server_tracking_data from .logging import write_to_log from .tools import handle_report_missing __all__ = [ - # Compatibility - "is_compatible_server", - "is_official_fastmcp_server", - # Context parameters - "add_context_parameter_to_schema", - "add_context_parameter_to_tools", # Internal "get_server_tracking_data", "set_server_tracking_data", # Logging "write_to_log", - # Redaction - # Session # Tools "handle_report_missing", ] diff --git a/src/agentcat/modules/adapters/__init__.py b/src/agentcat/modules/adapters/__init__.py new file mode 100644 index 0000000..a8d9bb6 --- /dev/null +++ b/src/agentcat/modules/adapters/__init__.py @@ -0,0 +1,11 @@ +"""Era-specific wiring between a customer's MCP server and the v2 engine. + +One adapter per server generation. Each knows only the mechanics of its era — +which field holds the dispatched handler, how results are wrapped, whether the +model fields are camelCase or snake_case — and delegates every orchestration +decision (resolve / strip / decorate / publish) to +`agentcat.modules.callpath`. + +Adapters import `mcp` / `fastmcp` symbols inside their install function, never +at module scope, so `import agentcat` succeeds under either SDK major. +""" diff --git a/src/agentcat/modules/adapters/_common.py b/src/agentcat/modules/adapters/_common.py new file mode 100644 index 0000000..4bc5384 --- /dev/null +++ b/src/agentcat/modules/adapters/_common.py @@ -0,0 +1,123 @@ +"""Helpers every adapter needs, in one place so they cannot drift apart. + +A few small things, extracted because four adapters (lowlevel v1/v2, community +v3/v4) each want them and two of them encode rules that must never differ +between eras: a non-dict ``response`` silently drops the whole event, and +per-server install state must not outlive the server. + +Nothing version-specific from ``mcp``/``fastmcp`` is imported here, so this +module loads under either SDK major. +""" + +from __future__ import annotations + +import time +from typing import Any + +from agentcat.modules.internal import get_server_tracking_data +from agentcat.modules.logging import write_to_log +from agentcat.types import AgentCatData + +# Where an adapter's per-server install state is kept: on the server, in one +# private attribute. See `install_state`. +STATE_ATTR = "_agentcat_install_state" + + +def now_ms() -> int: + """A monotonic millisecond stamp for measuring one call's duration.""" + return int(time.monotonic() * 1000) + + +def install_state(server: Any) -> dict[str, Any] | None: + """This server's install state, created on first use. None if unstorable. + + Every value an adapter puts in here closes over the server — the handler + wrappers do, and so does a customer handler bound to a + ``FastMCP``/``MCPServer`` facade that owns the lowlevel object — so a + module-level ``WeakKeyDictionary`` would be kept alive by its own values + and the weak key would never die. + + That is not a bounded cost on the topology this generation documents: 2026 + factories build a fresh server per request and ``track()`` runs inside the + factory, with the explicit requirement that "per-server state lives in maps + that don't outlive the server object" (cross-SDK changelog §6.8). A + module-level map means one immortal server — plus its handler table, its + deep-copied tool schemas, its ``AgentCatData`` and its injection registries + — PER REQUEST, which is a linear leak. + + Held on the server, the state's lifetime is exactly the server's. The + reference cycle it forms with the wrappers is the same one the server's own + handler table already holds, and the cyclic collector takes both. + + What the state is FOR is idempotence: a repeated ``track()`` finds its + predecessor's wrapper in the handler table and takes the customer's handler + from the recorded original instead of wrapping the wrapper. A stacked pass + would inject session_id on the inside, find it already present on the outside, + never record it as strippable, and hand the customer's tool a parameter it + never declared. + """ + existing = getattr(server, STATE_ATTR, None) + if isinstance(existing, dict): + return existing + state: dict[str, Any] = {} + try: + setattr(server, STATE_ATTR, state) + except Exception as e: + # Nothing that reaches an adapter can refuse an attribute — re-arming + # sets one too — but a server that did would leave no way to recognize + # our own wrapper on a second track(), and a stacked wrapper is worse + # than no tracking. + write_to_log( + "Warning: could not store AgentCat state on this server, so a " + f"repeated track() could not stay idempotent; not tracking it - {e}" + ) + return None + return state + + +def current_tracking_data(server: Any, fallback: AgentCatData) -> AgentCatData: + """The tracking data as of this request, so a re-``track()`` takes effect. + + Adapters must never capture the data at install time: a second + ``track(server, ...)`` stores a fresh ``AgentCatData``, and a handler still + reading the first one would serve stale options forever. ``fallback`` is + the install-time data, used only if the lookup finds nothing. + """ + try: + live = get_server_tracking_data(server) + except Exception: + live = None + return live if live is not None else fallback + + +def response_payload(result: Any) -> dict[str, Any] | None: + """A JSON-safe dict for the event's ``response`` field, or None. + + ``PublishEventRequest.response`` is ``Optional[Dict[str, Any]]``: handing + it anything else fails pydantic construction and silently drops the whole + event, so a non-dict dump is discarded here instead. + + **The dump is era-native, deliberately.** No ``by_alias``, so the keys are + whatever the result model this generation produced calls them: official + mcp 1.x publishes ``isError`` / ``structuredContent``, while mcp 2.x and + both community eras publish ``is_error`` / ``structured_content``. The + divergence is RULED IN, not an oversight: + + - it is not a regression — v1 community already published FastMCP's + snake_case dump, so normalizing would CHANGE data the backend has been + receiving rather than fix it; + - ``to_mcp_result()`` is not a drop-in normalizer: it returns a bare list + or a tuple for a non-error result, and this field must be a dict; + - the wire result the agent receives is untouched either way. This is the + analytics payload, not the tool's answer. + + ``tests/test_response_shape.py`` pins the actual spelling per flavor. + Adding ``by_alias`` here is a breaking change to published data; change + this ruling first if you mean to make it. + """ + try: + dumped = result.model_dump(mode="json") + except Exception as e: + write_to_log(f"Warning: could not serialize tool result for the event - {e}") + return None + return dumped if isinstance(dumped, dict) else None diff --git a/src/agentcat/modules/adapters/_inner_tap.py b/src/agentcat/modules/adapters/_inner_tap.py new file mode 100644 index 0000000..b6ee951 --- /dev/null +++ b/src/agentcat/modules/adapters/_inner_tap.py @@ -0,0 +1,390 @@ +"""The inner tap: full Python exception detail on tool-error events. + +v2 intercepts at the protocol boundary, and by the time an adapter sees a +failed ``tools/call`` most SDK generations have already caught the exception +and flattened it into an ``isError`` result. `mcp/server/lowlevel/server.py` +does it in the handler its ``@call_tool()`` decorator builds; `MCPServer` +does it in ``_handle_call_tool``. Either way the exception object dies inside +that ``except`` — nothing on the returned result retains its type, traceback +or ``__cause__``. Without a tap the only honest payload left is the three-key +fallback ``capture_call_tool_result_error`` produces. + +This module is the tap. It is the Python answer to the TypeScript engine's +``src/engine/innerTap.ts``: something *below* the conversion records the live +exception, and the adapter's publish path picks it up for that same call. + +**The contract** — the same on every era, however the tap is placed: + +- `inner_tap()` opens a capture slot for exactly one tool call. Enter it + before the customer's handler runs; the slot closes on every exit path, + including the error path, because a context manager cannot skip ``__exit__``. +- `capture()` / `capture_in_flight()` record into whatever slot is open for + the *calling* call, and are no-ops when none is. +- `InnerTap.error()` is the adapter's read: the tapped exception when there + was one, the flattened result when there was not (a proxied upstream error + and a tool that simply returned ``is_error`` have no local exception to + find, and never will). + +**Which exception, when a tool composes another tool.** A tool that calls a +tool re-enters a tapped seam, so one slot can see more than one failure — and +the event must describe the one the AGENT was told about, never a sub-call's +that the caller handled. Two rules settle it, and both are needed: + +- **The last write wins.** A sub-call's failure is recorded, then the caller's + own failure is recorded after it and replaces it. (The caller re-raising the + same object, or a wrapper around it, is the same rule.) An earlier design + kept the FIRST write and published a swallowed sub-call's exception against + the caller's message. +- **A capture that never escaped is discarded.** A seam that returns *normally* + drops any capture recorded inside its own dynamic extent: the exception was + handled in there, so it did not produce this result. That is what covers the + caller who suppresses a sub-call and then answers with an ``is_error`` result + of its own rather than raising. A capture the seam re-raised is untouched, + which is what keeps the community case — a middleware BELOW us converting a + real tool failure into an ``is_error`` result — working. + + "Inside its own extent" is answered per SEAM, never per nesting level. Each + entry into a seam takes a fresh marker and pushes it onto a per-task chain, + and a capture remembers the chain it was recorded under; a normal return + discards only a capture whose chain names that entry. A depth counter cannot + answer the same question, because the counter has to live on the cell — and + the cell is shared with every task that inherits it, so a sub-call the tool + left running inflated the count and then erased a genuine capture on its own + normal return. The chain is a ``ContextVar``, so a child task's pushes are + invisible to its parent and to its siblings, which is exactly the isolation + the question needs. + +**Why a cell and not a "last error" variable.** The slot is an object created +inside the adapter's own frame; the `ContextVar` only carries a *reference* to +it downward, and the adapter reads its own local cell rather than the +variable. Two properties follow, and both matter: + +1. *Cross-attribution is structurally impossible.* Two tool calls can only + interleave if they are separate asyncio tasks, and a task runs in its own + copy of the context — so `set()` in one call is invisible to the other, and + each tap writes to the cell its own call installed. There is no shared slot + to race for. +2. *A capture from a child task or worker thread still lands.* Contexts are + copied downward, so a `ContextVar.set()` inside a child would be invisible + to the parent that must read it — which is exactly what the retired + ``store_captured_error`` did. Writing to the cell OBJECT is visible to + whoever holds it, and `anyio.to_thread` (how both FastMCP generations run a + sync tool body) copies the context into the worker thread. + + The same direction has a bounded cost worth naming: a background task the + customer's tool spawns and does not await inherits a context that still + references this call's cell, so a failure in it can be recorded after the + slot closed — retaining that exception and its traceback for as long as the + child lives. Nothing reads the cell after `__exit__`, so it cannot reach an + event; it is a lifetime footnote, not a correctness one. + +**Never alters what the customer's server does.** The wrapping form catches, +records and re-raises the same exception object with a bare ``raise``; the +probing form only reads `sys.exc_info()` and returns the original's own +result. A tap that fails is logged and degrades to the no-tap payload; it +never raises into the customer's server. + +Nothing version-specific from ``mcp``/``fastmcp`` is imported here, so this +module loads under either SDK major. WHERE the tap is placed is era-specific +and belongs to each adapter; WHAT it records does not, and belongs here. +""" + +from __future__ import annotations + +import contextvars +import inspect +import sys +from collections.abc import Awaitable, Callable +from types import TracebackType +from typing import Any + +from agentcat.modules.exceptions import capture_exception +from agentcat.modules.logging import write_to_log +from agentcat.types import ErrorData + + +class _Cell: + """One tool call's exception slot. + + ``baseline`` is whatever exception was already being handled when the slot + opened. `capture_in_flight` reads `sys.exc_info`, which answers for the + whole stack rather than one frame, so a conversion site reached with no + exception of its own would otherwise record an older frame's — the SDK + calls ``_make_error_result`` for a bad return type too, outside any + ``except``. Remembering the baseline is how that reads as "nothing to + record" instead of as someone else's failure. + + ``exc_seams`` is the chain of seam entries that were open, in this task, + when the stored exception was recorded. It is what answers "did this + failure actually escape?" — see the module docstring. Nothing here counts: + the cell is shared with every task that inherits it, so a count would be + everyone's and an identity is only its own. + """ + + __slots__ = ("exc", "exc_seams", "baseline") + + def __init__(self, baseline: BaseException | None) -> None: + self.exc: BaseException | None = None + self.exc_seams: tuple[object, ...] = () + self.baseline = baseline + + def record(self, exc: BaseException) -> None: + """Store ``exc`` as this call's failure so far. Last write wins.""" + self.exc = exc + self.exc_seams = _open_seams.get() + + def discard_unescaped(self, seam: object) -> None: + """Drop a capture that ``seam`` handled inside itself. + + Called when that seam entry returns NORMALLY: a capture whose chain + names it was raised within it and did not come back out, so it did not + produce the result the agent is about to be handed. A capture from a + sibling — sequential or concurrent — does not name it, and survives to + be settled by whichever seam actually encloses them both. + """ + if self.exc is not None and seam in self.exc_seams: + self.exc = None + self.exc_seams = () + + +# Holds a reference to the innermost open cell. Never the exception itself: +# see the module docstring for why that distinction is the whole design. +_open_cell: contextvars.ContextVar[_Cell | None] = contextvars.ContextVar( + "agentcat_inner_tap", default=None +) + +# The seam entries currently open in THIS task, outermost first. A ContextVar +# rather than a field on the cell, because the question it answers is about one +# task's call stack and the cell is shared with every task that inherits it. +_open_seams: contextvars.ContextVar[tuple[object, ...]] = contextvars.ContextVar( + "agentcat_inner_tap_seams", default=() +) + + +class InnerTap: + """The capture slot for one ``tools/call``. Use via `inner_tap`.""" + + __slots__ = ("_cell", "_token") + + def __init__(self) -> None: + self._cell = _Cell(_in_flight()) + self._token: contextvars.Token[_Cell | None] | None = None + + def __enter__(self) -> InnerTap: + self._token = _open_cell.set(self._cell) + return self + + def __exit__( + self, + exc_type: type[BaseException] | None, + exc: BaseException | None, + tb: TracebackType | None, + ) -> None: + # Every exit path, the raise included: a token reset restores exactly + # the cell that was open before, so a nested call (a tool that calls + # its own server) hands the slot back to its caller rather than + # clearing it. + if self._token is not None: + _open_cell.reset(self._token) + self._token = None + + @property + def captured(self) -> BaseException | None: + """The exception a tap recorded for this call, if one did.""" + return self._cell.exc + + def error(self, flattened: Any) -> ErrorData: + """The event's ``error`` payload for a call that failed. + + The tapped exception when there is one — real type, formatted stack, + stack frames and the ``__cause__`` chain the SDK wrapped it in. + Otherwise ``flattened``, whatever the adapter could make of the result: + an upstream error a proxy passed through, or a tool that returned + ``is_error`` without anything having been raised at all, both of which + have no local exception and never will. + """ + # `is not None`, not truthiness: an exception class that defines + # `__len__` or `__bool__` can be falsy, and losing its traceback to + # that would be a very quiet bug. + exc = self._cell.exc + return capture_exception(exc if exc is not None else flattened) + + +def inner_tap() -> InnerTap: + """Open a capture slot around one tool call. + + >>> with inner_tap() as tap: # doctest: +SKIP + ... result = await run_the_customers_handler() + ... error = tap.error(result) if is_error(result) else None + """ + return InnerTap() + + +def capture(exc: BaseException) -> None: + """Record ``exc`` as the failure behind the call currently in flight. + + Last write wins: a tool that composes another tool sees the sub-call's + failure first and its own second, and the event has to describe the one the + agent was told about. A capture that turns out never to have escaped is + discarded separately, by `tapped`. + """ + try: + cell = _open_cell.get() + if cell is not None: + cell.record(exc) + except Exception as e: # pragma: no cover - defensive + write_to_log(f"Warning: inner tap could not record an exception - {e}") + + +def capture_in_flight(surfaced_message: str) -> None: + """Record the exception being handled right now, if the SDK is surfacing it. + + For a conversion site that keeps only ``str(e)``: called from inside the + SDK's own ``except`` block, `sys.exc_info` still holds the live exception + with its traceback. Costs the customer nothing — no wrapper frame, no + re-raise — so it is preferred wherever a conversion site can be observed + directly. + + ``surfaced_message`` is the text the site is about to put on the wire, and + the capture is taken **only when it is exactly ``str(exc)``**. One site on + lowlevel v1 hands over the exception's own message + (``_make_error_result(str(e))``); the schema-validation sites hand over a + sentence the SDK composed instead (``f"Input validation error: …"``). + Recording those would replace the one-line message the agent saw with a + multi-line ``jsonschema`` dump that embeds the schema and the offending + argument value — a payload change, on a common error class, that no one + asked for. Equality is the exact test that separates the two. + """ + try: + exc = _in_flight() + cell = _open_cell.get() + if exc is None or cell is None or exc is cell.baseline: + return + if str(exc) == surfaced_message: + cell.record(exc) + except Exception as e: # pragma: no cover - defensive + write_to_log(f"Warning: inner tap could not record an exception - {e}") + + +def _in_flight() -> BaseException | None: + try: + return sys.exc_info()[1] + except Exception: # pragma: no cover - defensive + return None + + +def tapped(fn: Callable[..., Awaitable[Any]]) -> Callable[..., Awaitable[Any]]: + """``fn`` with a catch-record-re-raise around it, and nothing else changed. + + The re-raise is bare, so the SDK above receives the same exception object + it would have received untracked and the wire result is byte-identical. The + one observable difference is the tap's own frame in the traceback, which is + what a middleware seam costs on every era that has one. + + The seam also carries the bookkeeping a composing tool needs: each entry + takes a marker of its own and pushes it onto this task's chain of open + seams, and on a NORMAL return it drops any capture recorded under that + marker — that failure was handled in here and is not what the agent is + being told. A capture it re-raises is left alone, which is the whole point + of the tap, and so is a capture from a seam that merely ran beside it. + """ + + async def tap(*args: Any, **kwargs: Any) -> Any: + cell = _open_cell.get() + seam = object() + token = _open_seams.set((*_open_seams.get(), seam)) + try: + result = await fn(*args, **kwargs) + except Exception as exc: + capture(exc) + raise + else: + if cell is not None: + cell.discard_unescaped(seam) + return result + finally: + _open_seams.reset(token) + + return tap + + +def probing(fn: Callable[..., Any]) -> Callable[..., Any]: + """``fn`` with a `capture_in_flight` read in front of it, and nothing else. + + For a *conversion* site rather than an invocation one: something the SDK + calls from inside its own ``except`` to build the error result. The + customer's exception never passes through here, so there is nothing to + catch and re-raise — and nothing of ours ends up in their traceback. + + The message the site was handed is what gates the read (see + `capture_in_flight`). It is read defensively — first positional argument, + then the keyword lowlevel v1 names it by — because a call shape this does + not recognize must cost a capture, never the customer's error path. + """ + + def probe(*args: Any, **kwargs: Any) -> Any: + message = args[0] if args else kwargs.get("error_message") + if isinstance(message, str): + capture_in_flight(message) + return fn(*args, **kwargs) + + return probe + + +def tap_method( + owner: Any, + name: str, + state: dict[str, Any], + key: str, + wrap: Callable[[Any], Any] = tapped, + accepts: Callable[[Any], bool] = inspect.iscoroutinefunction, +) -> bool: + """Put a tap over ``owner.name``, in place. Never raises. + + ``state`` is the adapter's per-server install state and ``key`` the slot to + record under, so a repeated ``track()`` re-wraps the customer's original + rather than stacking a second tap on top of the first. ``wrap`` selects the + form — `tapped` around an invocation, `probing` in front of a conversion. + + ``accepts`` is the precondition of that form, checked against the callable + about to be wrapped. `tapped` awaits what it wraps, so a target that is not + a coroutine function would turn every tool call into + ``TypeError: … can't be used in 'await' expression`` — a break the customer + sees on every call, and one the install-time ``try`` cannot catch because it + happens later. Every seam this ships with is ``async def`` on both majors; + a customer subclass that overrode one synchronously is refused the tap + instead, and keeps the previous no-tap payload. + """ + original_key = f"orig_tap_{key}" + installed_key = f"tap_{key}" + try: + current = getattr(owner, name, None) + if not callable(current): + return False + # Ours from an earlier pass? Then the original is the one we recorded. + original = ( + state.get(original_key) if current is state.get(installed_key) else current + ) + if original is None: + return False + if not accepts(original): + write_to_log( + f"Warning: '{name}' on this server is not the shape the inner " + "tap wraps, so it is left alone; tool errors keep the surfaced " + "message but lose the stack" + ) + return False + wrapper = wrap(original) + # Installed first, recorded second: a `setattr` a server refuses would + # otherwise leave the state claiming a tap that is not there, and the + # next `track()` would unwrap an original nothing ever wrapped. + setattr(owner, name, wrapper) + state[original_key] = original + state[installed_key] = wrapper + return True + except Exception as e: + write_to_log( + f"Warning: could not install the inner tap on '{name}'; tool errors " + f"on this server keep the surfaced message but lose the stack - {e}" + ) + return False diff --git a/src/agentcat/modules/adapters/community.py b/src/agentcat/modules/adapters/community.py new file mode 100644 index 0000000..e02868c --- /dev/null +++ b/src/agentcat/modules/adapters/community.py @@ -0,0 +1,813 @@ +"""Adapter for community FastMCP (the 3.x and 4.x eras). + +Community FastMCP has a first-class middleware seam, so unlike the official +SDKs there is nothing to monkey-patch: one object inserted at index 0 of +``server.middleware`` sees every ``tools/list`` and ``tools/call`` before any +other layer does. + +Era-specific knowledge only: FastMCP's snake_case ``Tool.parameters`` / +``output_schema``, its ``MiddlewareContext``/``ToolResult`` shapes, and the +provider registration used for ``get_more_tools``. Every decision about what to +resolve, strip, decorate or publish belongs to +:mod:`agentcat.modules.callpath` and is not re-derived here — the v1 middleware +this replaces reimplemented all of it inline. + +Three invariants the middleware exists to protect: + +- **Nothing customer-owned is mutated.** Tool schemas are copied before the + injection pipeline rewrites them in place, and the request message is cloned + via ``model_copy`` rather than rebuilt — a rebuilt ``CallToolRequestParams`` + silently drops ``_meta`` (and, from the 2026 era, ``input_responses`` / + ``request_state``), which severs multi-round-trip continuations. +- **Index 0 is outermost.** FastMCP builds its chain with + ``for mw in reversed(self.middleware)``, so element 0 runs first. A caching or + dereferencing middleware below us therefore keys on the STRIPPED arguments and + never caches our injected schemas. +- **The event records the call as the agent made it.** Raw (unstripped) + arguments and the customer's undecorated result; the mint-back is wire-only. + +``AgentCatMiddleware`` deliberately does not subclass ``fastmcp``'s +``Middleware``: that would require a module-scope ``fastmcp`` import, and +``import agentcat`` has to succeed with no MCP SDK installed at all. FastMCP +calls middleware objects, so the dispatch its base class performs is +reproduced in ``__call__``. +""" + +from __future__ import annotations + +import copy +import weakref +from typing import Any + +from agentcat.modules.adapters._common import ( + current_tracking_data, + install_state, + now_ms, + response_payload, +) +from agentcat.modules.adapters._inner_tap import inner_tap, tap_method +from agentcat.modules.callpath import ( + ResolvedCall, + decorate_content, + detect_mrtr, + get_stripped_arguments, + publish_tool_call_event, + resolve_call, + structured_mirror, +) +from agentcat.modules.constants import GET_MORE_TOOLS_NAME +from agentcat.modules.exceptions import capture_exception +from agentcat.modules.injection import ToolSpec, build_injected_schemas +from agentcat.modules.logging import write_to_log +from agentcat.modules.request_extra import extra_from_request_context +from agentcat.modules.tools import GET_MORE_TOOLS_DESCRIPTION +from agentcat.types import AgentCatData, ErrorData + +# Eras this adapter serves. Verified against FastMCP 4.0.0b1: it renamed +# nothing this middleware touches — ``Tool.output_schema`` and +# ``ToolResult.structured_content`` are the live field names on both sides, and +# every read that COULD have drifted goes through ``_field``, snake-first with a +# camelCase fallback — so no code path branches on the era. (The MRTR +# continuation probes in ``on_call_tool`` are bare ``getattr``s: the 2026-era +# ``input_responses`` / ``request_state`` fields postdate the camelCase bridge +# entirely, so there is no older spelling for either to fall back to, and on +# era 3 the message model has neither.) The one v4-only difference this +# adapter had to answer, the era's second dispatch pass, turned out to be a +# property of the message rather than of the generation, and is handled as one +# (``_is_typed_message``). The era is recorded anyway: it names which generation +# an installed middleware was built for in the log, and it is the seam a later +# divergence would use. +ERA_V3 = 3 +ERA_V4 = 4 + + +def _field(obj: Any, snake: str, camel: str) -> Any: + """snake_case first, camelCase fallback (v3 keeps a bridge; v4 does not).""" + value = getattr(obj, snake, None) + return getattr(obj, camel, None) if value is None else value + + +def _is_typed_message(message: Any) -> bool: + """Whether ``context.message`` is the request model the hooks expect. + + FastMCP 4 dispatches the middleware chain a SECOND time for a component + request that failed *before* the interior chain ran — malformed params, a + routing failure — so that ``on_message``/``on_request`` observe every + inbound message (``server/low_level.py::_dispatch_component``). That pass + carries the same ``method``, but its message is the RAW params **mapping**: + reconstructing a typed model is exactly what fails on a malformed message, + so FastMCP deliberately does not try (``_raw_message``). + + It is observation only — the pass's ``call_next`` re-raises the original + failure rather than dispatching — so there is nothing here for AgentCat to + do: no tool ran, and no event describes a request that never became one. + What matters is that we get out of the way intact. ``on_call_tool`` clones + the message with ``model_copy``, which a ``dict`` does not have, and the + ``AttributeError`` that raised REPLACED the customer server's own ``-32602`` + on the wire — an analytics library changing what a client is told. + + FastMCP 3 has no such pass, so this only ever fires on 4.x; it is written + as a property of the message rather than an era branch because it is the + honest precondition of both typed hooks either way. + """ + return hasattr(message, "model_copy") + + +def _request_context(context: Any) -> Any: + """The MCP ``RequestContext`` behind a middleware call, or None.""" + try: + fastmcp_context = context.fastmcp_context + return fastmcp_context.request_context if fastmcp_context else None + except Exception: + return None + + +def _connection_key(source: Any) -> Any: + """The per-connection object a handshake capture is filed under, or None. + + FastMCP builds one ``ServerSession`` per connection — and, under stateless + HTTP, a fresh one per REQUEST — so it is the only thing in reach that tells + one caller from another. ``initialize`` runs before the MCP + ``RequestContext`` exists (``fastmcp_context.request_context`` is None + there), so the session is read off the FastMCP context when capturing and + off the request context when looking up; on a stateful connection those are + the same object, and under stateless HTTP they deliberately are not. + """ + try: + return getattr(source, "session", None) + except Exception: + return None + + +def _flattened(result: Any) -> Any: + """A ``ToolResult`` in the shape the error extractor recognizes. + + ``capture_exception`` reads the wire ``CallToolResult`` (camelCase + ``isError`` + ``content``), not FastMCP's snake_case ``ToolResult``, so the + result is converted first — otherwise the recorded message would be a + pydantic repr of the model. + """ + try: + return result.to_mcp_result() + except Exception: + return result + + +class AgentCatMiddleware: + """One middleware for both community eras; ``era`` selects the field bridge. + + Stateless apart from the initialize-time client capture: the tracking data + is re-read per request so a repeated ``track()`` takes effect, and a + ``ResolvedCall`` is never held across rounds (it carries that round's + request/extra for the customer's tag and property callbacks). + """ + + def __init__(self, data: AgentCatData, server: Any, era: int) -> None: + self._data = data + self._server = server + self._era = era + # Handshake clientInfo, the last rung of the client identity ladder, + # filed PER CONNECTION. One middleware object serves every connection, + # so a single "last seen" slot would let a later client's initialize + # rename an earlier client's call — which is exactly what happens under + # stateless HTTP, where the session carries no client_params and the + # ladder reaches this rung on every call. Weakly keyed, so a finished + # connection's entry goes away with its session. + self._handshake_clients: weakref.WeakKeyDictionary[Any, dict[str, Any]] = ( + weakref.WeakKeyDictionary() + ) + # The get_more_tools Tool object install_community registered, if any, + # and — once conceded — where it moves to. The conceded record is kept + # rather than dropped so a listing that was already in flight when we + # conceded still filters out the tool we just un-registered. See + # _concede_get_more_tools. + self._registered_get_more_tools: Any = None + self._conceded_get_more_tools: Any = None + + # ── dispatch ──────────────────────────────────────────────────────────── + + async def __call__(self, context: Any, call_next: Any) -> Any: + method = getattr(context, "method", None) + # Deliberately silent: on v4 this is the expected outer pass, which + # fires on every malformed request, and a log line there would be noise + # a customer cannot act on. The residual cost is that a layer inserted + # ABOVE us after track() which hands down a mapping would take tracking + # dead with no diagnostic — an inversion of the index-0 install that + # nothing in FastMCP does today. + if not _is_typed_message(getattr(context, "message", None)): + return await call_next(context) + if method == "initialize": + return await self.on_initialize(context, call_next) + if method == "tools/list": + return await self.on_list_tools(context, call_next) + if method == "tools/call": + return await self.on_call_tool(context, call_next) + return await call_next(context) + + # ── helpers ───────────────────────────────────────────────────────────── + + def _current_data(self) -> AgentCatData: + """The tracking data as of this request, so a re-track takes effect.""" + return current_tracking_data(self._server, self._data) + + def _meta_sources(self, message: Any, request_context: Any) -> list[Any]: + """Where per-request client identity may ride, best rung first.""" + return [ + getattr(message, "meta", None), + getattr(request_context, "meta", None), + ] + + def _legacy_client_info(self, request_context: Any) -> Any: + """Initialize-time ``clientInfo`` for THIS connection, or None. + + Two forms of the same rung (design §7, rung 3): what the SDK kept on + the session, then what this middleware saw on the same session's + ``initialize``. Both are per connection, so neither can name a client + that did not make this call. A stateless-HTTP request gets a brand new + session that never handshook, so it misses both and identity floors at + empty — the honest answer, and the one ``stateless=True`` produced in + 1.x. Under the 2026-era protocol there is no ``initialize`` at all, so + this rung is simply never populated. + """ + try: + info = request_context.session.client_params.clientInfo + except Exception: + info = None + if info is not None: + return info + return self._remembered_handshake_client(_connection_key(request_context)) + + def _remember_handshake_client(self, key: Any, client: dict[str, Any]) -> None: + """File one connection's handshake identity. Never raises.""" + if key is None: + return + try: + self._handshake_clients[key] = client + except TypeError as e: + # A session object that cannot be weakly referenced cannot be told + # apart from any other, so it gets no entry rather than a shared one. + write_to_log(f"Warning: could not file the handshake clientInfo - {e}") + + def _remembered_handshake_client(self, key: Any) -> dict[str, Any] | None: + if key is None: + return None + try: + return self._handshake_clients.get(key) + except TypeError: + return None + + def _specs(self, tools: list[Any]) -> list[ToolSpec]: + """Copies of the listed schemas, ready for the in-place injection pass. + + Only the schema dicts are copied. Deep-copying the ``Tool`` itself + raises on every tool holding live runtime state — an OpenAPI tool's + ``httpx.AsyncClient`` carries a ``threading.RLock`` — which silently + dropped injection for whole servers in v1. + """ + return [ + ToolSpec( + tool.name, + copy.deepcopy(getattr(tool, "parameters", None) or {}), + copy.deepcopy(_field(tool, "output_schema", "outputSchema")), + ) + for tool in tools + ] + + # ── hooks ─────────────────────────────────────────────────────────────── + + async def on_initialize(self, context: Any, call_next: Any) -> Any: + """Capture this connection's client identity. Publishes nothing (v2). + + The MCP ``RequestContext`` does not exist yet at this point, so the + connection is identified by the FastMCP context's session — the same + object the tool call will present. + """ + try: + message = context.message + params = getattr(message, "params", None) or message + info = _field(params, "client_info", "clientInfo") + if info is not None: + self._remember_handshake_client( + _connection_key(getattr(context, "fastmcp_context", None)), + { + "name": getattr(info, "name", None), + "version": getattr(info, "version", None), + }, + ) + except Exception as e: + write_to_log(f"Warning: could not read initialize clientInfo - {e}") + return await call_next(context) + + async def on_list_tools(self, context: Any, call_next: Any) -> Any: + """Serve the customer's listing with AgentCat's parameters injected. + + Publishes nothing: v2 intercepts ``tools/list`` for schema injection + only. On any failure the customer's own list is served unmodified. + """ + # The list handed back here has passed through every layer below us, so + # it may hold COPIES of our own tool — hence authoritative=False. + tools = await self._concede_get_more_tools( + list(await call_next(context)), authoritative=False + ) + tracking = self._current_data() + try: + specs = self._specs(tools) + injected = build_injected_schemas( + specs, tracking.options, tracking.reported_conflicts + ) + tracking.injected_params_registry = injected.injected_params + tracking.output_injection_registry = injected.output_injected + # Union, never replace: membership only grows, and a concurrent + # listing on another instance may already have recorded a tool this + # one did not see. + tracking.declared_session_params |= injected.declared_session_params + return [ + tool.model_copy(update=self._schema_update(spec)) + for tool, spec in zip(tools, specs, strict=True) + ] + except Exception as e: + write_to_log( + "Warning: tools/list injection failed, serving the customer's " + f"unmodified list - {e}" + ) + return tools + + def _is_ours(self, tool: Any, ours: Any) -> bool: + """Whether a listed tool is the ``get_more_tools`` AgentCat registered. + + Object identity is the exact answer but not a sufficient one: layers + below us hand back ``model_copy`` results — a customer middleware that + re-stamps tools, FastMCP's own visibility transforms, v4's + dereferencing middleware — and **a copy of our own tool must never read + as a customer's**. So identity first, then two copy-tolerant fallbacks: + the underlying function object, which a ``model_copy`` carries over, + and our canonical description, which is the copy an agent would see. + + This is the single definition of "ours" for both halves of the + concession: whatever it calls ours is what the decision ignores AND + what the advertised list drops, so the two can never disagree. + """ + if ours is None: + return False + if tool is ours: + return True + if getattr(tool, "name", None) != GET_MORE_TOOLS_NAME: + return False + our_fn = getattr(ours, "fn", None) + if our_fn is not None and getattr(tool, "fn", None) is our_fn: + return True + return bool(getattr(tool, "description", None) == GET_MORE_TOOLS_DESCRIPTION) + + def _foreign_get_more_tools(self, tools: list[Any], ours: Any) -> bool: + """Whether anyone but us supplies ``get_more_tools`` in this listing.""" + return any( + getattr(tool, "name", None) == GET_MORE_TOOLS_NAME + and not self._is_ours(tool, ours) + for tool in tools + ) + + async def _concede_get_more_tools( + self, tools: list[Any], authoritative: bool + ) -> list[Any]: + """Give the name back the moment another provider turns out to own it. + + ``install_community`` can only read the LOCAL provider synchronously, + so a ``get_more_tools`` supplied by a mounted sub-server, a proxy, an + OpenAPI provider or ``add_provider`` is invisible to it. The local + provider is added first and wins aggregation, so ours would answer for + theirs — the one thing the ownership gate exists to prevent (spec §12). + An all-provider listing is the first view that can settle it, so both + views we get — the client-facing one and the rebuild-on-demand one — + run this. + + ``authoritative`` says whether ``tools`` already IS the raw + all-provider view. When it is not, a positive finding is re-checked + against that raw view before anything is un-registered: if a layer + below us rewrote our own tool past recognition, the honest answer is + "nobody else supplies this" and the safe move is to leave the + registration alone. Un-registering on a false positive would advertise + a ``get_more_tools`` that no longer resolves, and the next call to it + would fail. + """ + ours = self._registered_get_more_tools + if ours is None: + # Already conceded — keep filtering, so a listing that was already + # in flight when we conceded cannot advertise the tool we removed. + conceded = self._conceded_get_more_tools + if conceded is None: + return tools + return [tool for tool in tools if not self._is_ours(tool, conceded)] + + if not self._foreign_get_more_tools(tools, ours): + return tools + if not authoritative and not await self._provider_view_has_a_foreign_one(ours): + return tools + + self._registered_get_more_tools = None + self._conceded_get_more_tools = ours + removed = _unregister_get_more_tools(self._server, ours) + write_to_log( + "A provider on this server supplies its own get_more_tools; " + + ( + "un-registered AgentCat's so the customer's tool answers." + if removed + else "AgentCat's was already gone from the local registry." + ) + ) + return [tool for tool in tools if not self._is_ours(tool, ours)] + + async def _provider_view_has_a_foreign_one(self, ours: Any) -> bool: + """Re-ask the question of the raw provider listing, middleware bypassed. + + Only reached when a processed listing already looked foreign, so the + extra listing is paid on the rare path, never on every ``tools/list``. + """ + try: + listed = list(await self._server.list_tools(run_middleware=False)) + except Exception as e: + write_to_log( + "Warning: could not re-read the provider listing to confirm a " + f"get_more_tools owner; leaving AgentCat's registered - {e}" + ) + return False + return self._foreign_get_more_tools(listed, ours) + + def _schema_update(self, spec: ToolSpec) -> dict[str, Any]: + update: dict[str, Any] = {"parameters": spec.input_schema} + if spec.output_schema is not None: + update["output_schema"] = spec.output_schema + return update + + async def on_call_tool(self, context: Any, call_next: Any) -> Any: + tracking = self._current_data() + options = tracking.options + message = context.message + name = getattr(message, "name", None) or "Unknown Tool" + raw_arguments = dict(getattr(message, "arguments", None) or {}) + + async def rebuild() -> list[ToolSpec]: + """The list source for registry rebuild-on-demand (changelog 6.3). + + ``run_middleware=False`` is the seam in both community eras: it + returns the provider's own tools without re-entering this hook. + That is the raw all-provider view, so it settles the get_more_tools + ownership question too — and this is the path a tools/call takes on + an instance that never served a listing, which is precisely the + case install_community registers eagerly for. + """ + listed = list(await self._server.list_tools(run_middleware=False)) + return self._specs( + await self._concede_get_more_tools(listed, authoritative=True) + ) + + stripped = await get_stripped_arguments( + tracking, options, name, raw_arguments, rebuild + ) + stripped_context = context.copy( + message=message.model_copy(update={"arguments": stripped}) + ) + + # Tracing off: still strip what we injected, so the customer's tool runs + # exactly as it would untracked — then get out of the way. No handle + # resolution, no mint-back (there is no session_id parameter to echo), and + # no event. + if not options.enable_tracing: + return await call_next(stripped_context) + + request_context = _request_context(context) + try: + # Resolved fresh every round: the ResolvedCall carries this round's + # message/extra for the customer's tag and property callbacks. + resolved = await resolve_call( + tracking, + name, + raw_arguments, + message, + request_context, + meta_sources=self._meta_sources(message, request_context), + legacy_client=lambda: self._legacy_client_info(request_context), + ) + except Exception as e: + # Belt and braces at the customer boundary: the resolvers are all + # documented not to raise, but a tool call must never fail because + # analytics did. Degrade to an untraced call. + write_to_log( + f"Warning: AgentCat resolution failed for tool '{name}', running " + f"it untraced - {e}" + ) + return await call_next(stripped_context) + + started = now_ms() + extra_params = extra_from_request_context( + request_context, getattr(context, "fastmcp_context", None) + ) + + # The tap's slot is open for exactly the rest of the chain and the + # publish that reads it, and closes on every exit path including the + # raise below. + with inner_tap() as tap: + try: + result = await call_next(stripped_context) + except Exception as e: + # FastMCP surfaces a failing tool as a raised error, so unlike + # the official adapters this path holds the live exception, + # with its type and traceback intact. + await self._publish( + tracking, + resolved, + name, + raw_arguments, + response=None, + is_error=True, + error=capture_exception(e), + started=started, + mrtr=None, + extra_params=extra_params, + ) + raise + + mrtr = detect_mrtr( + self._result_type(result), + getattr(message, "input_responses", None) is not None, + getattr(message, "request_state", None) is not None, + ) + is_error = bool(getattr(result, "is_error", False)) + await self._publish( + tracking, + resolved, + name, + raw_arguments, + response=response_payload(result), + is_error=is_error, + # An `is_error` result that never raised THROUGH us: a layer + # below answered with one. The tap holds the exception when a + # local one produced it, and there simply is none when a proxy + # passed an upstream error through — then the surfaced message + # is the whole truth. + error=tap.error(_flattened(result)) if is_error else None, + started=started, + mrtr=mrtr, + extra_params=extra_params, + ) + + # An intermediate multi-round-trip round is never decorated: only the + # completing round carries the mint-back (changelog 6.4). + if mrtr == "input_required": + return result + return self._decorated(result, resolved, name, tracking) + + def _result_type(self, result: Any) -> str | None: + """The 2026-era ``resultType`` discriminator, however it is spelled.""" + declared = _field(result, "result_type", "resultType") + if isinstance(declared, str): + return declared + return ( + "input_required" + if type(result).__name__ == "InputRequiredToolResult" + else None + ) + + async def _publish( + self, + tracking: AgentCatData, + resolved: ResolvedCall, + name: str, + raw_arguments: dict[str, Any], + response: dict[str, Any] | None, + is_error: bool, + error: ErrorData | None, + started: int, + mrtr: str | None, + extra_params: dict[str, Any], + ) -> None: + await publish_tool_call_event( + self._server, + tracking, + resolved, + name, + raw_arguments, + response=response, + is_error=is_error, + error=error, + duration_ms=now_ms() - started, + mrtr=mrtr, + extra_params=extra_params, + ) + + def _decorated( + self, + result: Any, + resolved: ResolvedCall, + name: str, + tracking: AgentCatData, + ) -> Any: + """The wire result with the mint-back appended, or the original.""" + update: dict[str, Any] = {} + content = getattr(result, "content", None) + decorated = decorate_content( + list(content) if isinstance(content, list) else None, + resolved.resolution, + _text_block, + ) + if decorated is not None: + update["content"] = decorated + mirrored = structured_mirror( + _field(result, "structured_content", "structuredContent"), + resolved.resolution, + name, + tracking.output_injection_registry, + ) + if mirrored is not None: + update["structured_content"] = mirrored + # A copy, never an in-place edit: the event above still references the + # customer's own result object. + return result.model_copy(update=update) if update else result + + +def _text_block(text: str) -> Any: + from mcp.types import TextContent + + return TextContent(type="text", text=text) + + +def _customer_owns_get_more_tools(server: Any) -> bool: + """Whether a tool named ``get_more_tools`` is already registered. + + Read off the local provider's component store, the only synchronous view of + the registry (``list_tools`` is async and ``install_community`` is not). + Registering over an existing tool would replace the customer's handler with + our canned reply, and nothing AgentCat does may alter tool behavior + (spec §12), so an unreadable registry is treated as owned. + """ + try: + components = server._local_provider._components.values() + except Exception as e: + write_to_log( + "Warning: could not read the tool registry to check for a " + f"get_more_tools collision; skipping registration - {e}" + ) + return True + return any(getattr(c, "name", None) == GET_MORE_TOOLS_NAME for c in components) + + +def _unregister_get_more_tools(server: Any, ours: Any) -> bool: + """Remove the tool we registered — and only ever that exact object. + + Returns whether anything was actually removed, so the caller's log never + claims an un-registration that did not happen. + + Removing by name would be wrong: a customer who registers their own + ``get_more_tools`` after ``track()`` replaces ours in the local store under + the same key, and deleting by name would then delete theirs. The identity + check makes the removal a no-op in exactly that case. + """ + try: + provider = server._local_provider + if provider._components.get(ours.key) is not ours: + return False + provider.remove_tool(GET_MORE_TOOLS_NAME) + return True + except Exception as e: + write_to_log(f"Warning: could not un-register get_more_tools - {e}") + return False + + +def _register_get_more_tools(server: Any) -> Any: + """Register ``get_more_tools`` on the server's own provider; returns it. + + Provider registration rather than a listing-time append, so the tool + survives the compositions community FastMCP is built around: a mounted or + proxied parent enumerates through the provider and never runs this + server's middleware. The returned object is what + ``AgentCatMiddleware._concede_get_more_tools`` compares listings against. + """ + # `fastmcp.tools` is the public home of Tool in both eras; + # `fastmcp.tools.tool` is a sys.modules shim that no type checker resolves. + from fastmcp.tools import Tool + + from agentcat.modules.tools import ( + GET_MORE_TOOLS_DESCRIPTION, + GET_MORE_TOOLS_SCHEMA, + handle_report_missing, + ) + + async def get_more_tools(context: str) -> str: + result = await handle_report_missing({"context": context}) + block = result.content[0] if result.content else None + return getattr(block, "text", "No additional tools available.") + + # Spec defaults assume the worst; declare the honest hint so + # annotation-aware clients skip the confirmation prompt. Passed as a plain + # mapping, not the v3 `ToolAnnotations` model — pydantic coerces it into + # whichever annotations type the running FastMCP declares. + annotations: Any = {"readOnlyHint": True} + tool = Tool.from_function( + get_more_tools, + name=GET_MORE_TOOLS_NAME, + description=GET_MORE_TOOLS_DESCRIPTION, + annotations=annotations, + ) + # The generated schema loses the agent-facing parameter copy (pydantic + # writes no description for a bare `context: str`), so the canonical + # schema — byte-guarded against the TypeScript SDK — is substituted. + schema = copy.deepcopy(GET_MORE_TOOLS_SCHEMA) + registered = server.add_tool(tool.model_copy(update={"parameters": schema})) + write_to_log("Registered get_more_tools on the community provider") + return registered + + +def install_community(server: Any, data: AgentCatData, era: int) -> None: + """Insert the AgentCat middleware at index 0 of a community FastMCP server. + + ``era`` is 3 or 4. Idempotent: a repeated ``track()`` replaces the existing + middleware rather than stacking a second one — a stacked pass would inject + session_id on the inside, find it already present on the outside, and never + record it as strippable, handing the customer's tool a parameter it never + declared. + + ``get_more_tools`` is registered here so it exists for a ``tools/call`` that + arrives on an instance which never served a listing. That is only half the + ownership check — this function can read the local provider synchronously + but not the mounted/proxied/OpenAPI ones — so every all-provider view we + later get (a client listing, or the rebuild-on-demand one) re-checks and + concedes the name if anyone else turns out to supply it. + + Two residual asymmetries of provider registration, both requiring a + customer tool literally named ``get_more_tools``: + + - Turning ``enable_report_missing`` OFF on a *later* ``track()`` leaves the + already-registered tool in place; disable it before the first ``track()``. + - If the customer registers theirs on the LOCAL provider after ``track()``, + the server's own ``on_duplicate`` policy decides: the default (``warn``) + lets theirs replace ours, which is the right outcome, but ``ignore`` + would discard theirs and ``error`` would raise on their registration. + ``_on_duplicate`` is readable synchronously, so the ``error`` sub-case — + the only one where AgentCat makes the customer's own code raise — could + be guarded at no cost to ``warn``/``replace`` servers if it ever bites. + Registering before ``track()`` avoids all of it today, and that is what + the local gate below already handles. + """ + chain = server.middleware + existing = [mw for mw in chain if isinstance(mw, AgentCatMiddleware)] + for mw in existing: + chain.remove(mw) + # Index 0 is outermost: FastMCP builds the chain over `reversed(middleware)`. + middleware = AgentCatMiddleware(data, server, era) + chain.insert(0, middleware) + + # Carry a previous install's registration forward. The local gate below + # cannot tell OUR get_more_tools from a customer's, so on a re-track it + # reports "already owned" and registration is skipped — and without this the + # fresh middleware would hold no marker, could never concede the name, and a + # re-tracked server would go back to hijacking a provider-supplied tool. + for previous in existing: + if previous._registered_get_more_tools is not None: + middleware._registered_get_more_tools = previous._registered_get_more_tools + break + if previous._conceded_get_more_tools is not None: + middleware._conceded_get_more_tools = previous._conceded_get_more_tools + break + + register = data.options.enable_report_missing and not _customer_owns_get_more_tools( + server + ) + if register: + try: + middleware._registered_get_more_tools = _register_get_more_tools(server) + except Exception as e: + write_to_log(f"Warning: could not register get_more_tools - {e}") + + tapped = _arm_inner_tap(server) + write_to_log( + f"Installed community adapter (era {era}) on server {id(server)} " + f"at middleware index 0 (replaced={len(existing)}, " + f"inner-tap={tapped or 'none'})" + ) + + +def _arm_inner_tap(server: Any) -> list[str]: + """Arm the inner tap on ``FastMCP.call_tool``. Never raises. + + The one thing on a community server that a middleware seam cannot do. The + middleware chain sees a raised tool error and already records it in full — + but a layer BELOW us that answers with an ``is_error`` result instead of + raising (``providers/proxy.py`` does it deliberately for an upstream error, + and any error-handling middleware a customer writes does it too) leaves + nothing for the chain to catch. The tap has to sit under all of them. + + ``call_tool`` is where "all of them" ends: the middleware chain's innermost + ``call_next`` is ``self.call_tool(..., run_middleware=False)``, dispatched + through the instance on every call, below every middleware and below the + extension interceptors. Position in ``server.middleware`` therefore cannot + matter — including for a middleware the customer adds after ``track()``, + which a tail middleware of ours would have ended up above. + + The wrapper is a pass-through that records and re-raises, so the same + exception reaches the same layer it would have untracked. It is also + entered a second time per call, from the top with ``run_middleware=True``, + where nothing has raised yet and the outer entry is a no-op. + """ + state = install_state(server) + if state is None: + return [] # already logged + return ["call_tool"] if tap_method(server, "call_tool", state, "call_tool") else [] diff --git a/src/agentcat/modules/adapters/lowlevel_v1.py b/src/agentcat/modules/adapters/lowlevel_v1.py new file mode 100644 index 0000000..6c7cc35 --- /dev/null +++ b/src/agentcat/modules/adapters/lowlevel_v1.py @@ -0,0 +1,521 @@ +"""Adapter for the official MCP SDK 1.x lowlevel ``Server``. + +It also serves ``mcp.server.fastmcp.FastMCP`` through its ``_mcp_server``, so +both official flavors run one interception path instead of the v1 split +between handler overrides and tool-manager monkey patches. + +Era-specific knowledge only: the type-keyed ``request_handlers`` dict, the +``ServerResult`` root wrapper, and camelCase model fields +(``inputSchema``/``structuredContent``/``isError``). Every decision about what +to resolve, strip, decorate or publish belongs to +:mod:`agentcat.modules.callpath` and is not re-derived here. + +Two invariants the wrappers exist to protect: + +- **Nothing customer-owned is mutated.** Listed tools are deep-copied before + the injection pipeline rewrites their schemas in place, and the request is + cloned before its arguments are stripped — v1 popped ``context`` off the + caller's shared dict, which corrupted concurrent retries. +- **The event records the call as the agent made it.** Raw (unstripped) + arguments and the customer's undecorated result; the mint-back is wire-only. + +All ``mcp`` imports are function-local so ``import agentcat`` succeeds under +either SDK major. +""" + +from __future__ import annotations + +import copy +from typing import Any + +from agentcat.modules.adapters._common import ( + current_tracking_data, + install_state, + now_ms, + response_payload, +) +from agentcat.modules.adapters._inner_tap import ( + inner_tap, + probing, + tap_method, +) +from agentcat.modules.logging import write_to_log +from agentcat.modules.request_extra import extra_from_request_context +from agentcat.types import AgentCatData + +# The two handlers this adapter wraps, keyed by the name of the ``Server`` +# decorator that registers each one. Patching those decorators is how a +# handler the customer registers AFTER ``track()`` still ends up wrapped: on +# this generation registration writes straight into ``request_handlers``, so +# the decorator is the only seam there is. +_LIST = "list_tools" +_CALL = "call_tool" + + +def _safe_request_context(server: Any) -> Any: + """The in-flight request context, or None outside a request. + + On a lowlevel v1 ``Server`` this is a property that raises when no request + is active, so it is never read without a guard. + """ + try: + return server.request_context + except Exception: + return None + + +def _meta_extras(request: Any) -> Any: + """The request's ``_meta`` object, where per-request client identity rides.""" + try: + return getattr(getattr(request, "params", None), "meta", None) + except Exception: + return None + + +def _legacy_client_info(ctx: Any) -> Any: + """Initialize-time ``clientInfo``, captured by the SDK's own ServerSession. + + The last rung of the client identity ladder, supplied lazily so the + earlier meta rungs never pay for it. + """ + try: + return ctx.session.client_params.clientInfo + except Exception: + return None + + +def _arm_inner_tap(server: Any, facade: Any, state: dict[str, Any]) -> list[str]: + """Arm the inner tap wherever this generation lets an exception be seen. + + This era has one interception point but two server shapes behind it, and + they need different seams: + + - **The lowlevel error-result factory**, for every shape. The handler + ``Server.call_tool()`` builds catches everything and keeps only + ``str(e)`` — but it builds the result by calling + ``self._make_error_result(...)`` from *inside* that ``except``, where + ``sys.exc_info()`` still holds the live exception. Reading it there costs + the customer nothing: no wrapper frame in their traceback, no re-raise, + and the factory's own result is returned untouched. On a bare lowlevel + server it is also the only seam there is, and the exception it finds is + the customer handler's own. + + The SDK calls that factory from three places, and only one of them + surfaces the exception's own message; `probing` records only when the + message it is handed IS ``str(exc)``, which is exactly that one. The + schema-validation sites keep the one-line wire text they always had + rather than a multi-line ``jsonschema`` dump of the schema and the + offending value. + - **Official FastMCP's tool manager**, for the FastMCP shape. There the + customer's tool is two layers below the handler and its exception arrives + already wrapped in a ``ToolError``, whose traceback stops at the wrapper; + the tool manager is the innermost seam outside the tool itself. + ``FastMCP.call_tool`` cannot be used instead — the SDK binds it into the + handler's closure at registration, so replacing the attribute afterwards + would be ignored — while ``self._tool_manager.call_tool`` is looked up + per call. + + Both are armed when both exist, and the order does not matter here: the + tap is last-write-wins, and the second write is the same exception object + as the first. The tool manager's seam records what it caught and re-raises + it; the factory then reads `sys.exc_info()` from the ``except`` that same + exception is propagating through, and `capture_in_flight` only records when + the surfaced message IS ``str(exc)`` — so what it re-records is the object + already there. + """ + armed: list[str] = [] + # `probing` does not await what it wraps, so the precondition is only that + # the factory is callable at all — not that it is a coroutine function. + if tap_method( + server, + "_make_error_result", + state, + "error_result", + wrap=probing, + accepts=callable, + ): + armed.append("_make_error_result") + manager = getattr(facade, "_tool_manager", None) + if manager is not None and tap_method(manager, "call_tool", state, "tool_manager"): + armed.append("_tool_manager.call_tool") + return armed + + +def install_lowlevel_v1(server: Any, data: AgentCatData, facade: Any = None) -> None: + """Wrap ``tools/list`` and ``tools/call`` on a lowlevel v1 server. + + ``server`` is the lowlevel object the detector handed back (a bare + ``Server``, or a FastMCP's ``_mcp_server``); ``facade`` is the high-level + object that owns it when there is one, which only the inner tap needs; + ``data`` is the tracking data already stored for it. Idempotent: calling + ``track()`` again re-wraps the same originals with fresh closures rather + than stacking a second pass. + + ``track()`` may legitimately run before a single ``@server.call_tool()`` + exists, and a customer may register one afterwards, so the registration + decorators are patched too — otherwise this adapter would install nothing + at all on a fresh ``Server()`` and be silently overwritten by the + customer's own registration. + + ``initialize`` is deliberately left alone. v2 publishes no initialize + event, and the only thing the old override took from it — the handshake + ``clientInfo`` — the SDK already keeps on the session, where the client + identity ladder reads it per request. + """ + from mcp.types import ( + CallToolRequest, + ListToolsRequest, + ListToolsResult, + ServerResult, + TextContent, + Tool, + ToolAnnotations, + ) + + from agentcat.modules.callpath import ( + decorate_content, + detect_mrtr, + get_stripped_arguments, + publish_tool_call_event, + resolve_call, + structured_mirror, + ) + from agentcat.modules.constants import GET_MORE_TOOLS_NAME + from agentcat.modules.exceptions import capture_exception + from agentcat.modules.injection import ToolSpec, build_injected_schemas + from agentcat.modules.tools import ( + GET_MORE_TOOLS_DESCRIPTION, + GET_MORE_TOOLS_SCHEMA, + handle_report_missing, + ) + + handlers = server.request_handlers + request_types = {_LIST: ListToolsRequest, _CALL: CallToolRequest} + state = install_state(server) + if state is None: + return # already logged + + # Whether WE are the one advertising get_more_tools. Stated positively on + # purpose: it is set at the append site by every pass over the listing + # (client-facing or rebuild-on-demand), so until a listing has actually + # advertised our tool this stays False — and a server with no tools/list + # handler at all, or one whose listing raised, cannot hijack a customer's + # own get_more_tools by default. + agentcat_advertises_get_more_tools = False + + def current_data() -> AgentCatData: + """The tracking data as of this request, so a re-track takes effect.""" + return current_tracking_data(server, data) + + def original(key: str) -> Any: + """The customer's handler for ``key`` as of right now. + + Read from the shared state on every call rather than captured, so a + handler the customer re-registers after ``track()`` is the one that + runs — the wrapper on top of it does not need replacing for that. + """ + return state.get(f"orig_{key}") + + def make_get_more_tools() -> Tool: + return Tool( + name=GET_MORE_TOOLS_NAME, + description=GET_MORE_TOOLS_DESCRIPTION, + inputSchema=copy.deepcopy(GET_MORE_TOOLS_SCHEMA), + # Spec defaults assume the worst; declare the honest hint so + # annotation-aware clients skip the confirmation prompt. + annotations=ToolAnnotations(readOnlyHint=True), + ) + + def advertised_tools(original: Any, options: Any) -> list[Any]: + """Deep copies of the listed tools, plus get_more_tools when enabled. + + Copies because the injection pipeline rewrites schemas in place and + FastMCP hands out the very dict its tool manager holds. + """ + nonlocal agentcat_advertises_get_more_tools + tools: list[Any] = [] + listed = getattr(getattr(original, "root", None), "tools", None) + if isinstance(listed, list): + tools = [tool.model_copy(deep=True) for tool in listed] + customer_owns_get_more_tools = any( + getattr(tool, "name", None) == GET_MORE_TOOLS_NAME for tool in tools + ) + agentcat_advertises_get_more_tools = ( + options.enable_report_missing and not customer_owns_get_more_tools + ) + # Appended before injection so it receives handle parameters too; the + # context pass skips it by name, so early placement cannot double-inject. + if agentcat_advertises_get_more_tools: + tools.append(make_get_more_tools()) + return tools + + def specs_for(tools: list[Any]) -> list[ToolSpec]: + return [ + ToolSpec(tool.name, tool.inputSchema, getattr(tool, "outputSchema", None)) + for tool in tools + ] + + async def rebuild() -> list[ToolSpec]: + """The list source for registry rebuild-on-demand (changelog 6.3).""" + list_handler = original(_LIST) + if list_handler is None: + return [] + listed = await list_handler(ListToolsRequest(method="tools/list")) + return specs_for(advertised_tools(listed, current_data().options)) + + async def wrapped_list(request: Any) -> Any: + listed = await original(_LIST)(request) + tracking = current_data() + try: + tools = advertised_tools(listed, tracking.options) + specs = specs_for(tools) + injected = build_injected_schemas( + specs, tracking.options, tracking.reported_conflicts + ) + tracking.injected_params_registry = injected.injected_params + tracking.output_injection_registry = injected.output_injected + # Union, never replace: membership only grows, and a concurrent + # listing on another instance may already have recorded a tool this + # one did not see. + tracking.declared_session_params |= injected.declared_session_params + for tool, spec in zip(tools, specs, strict=True): + tool.inputSchema = spec.input_schema + if spec.output_schema is not None: + tool.outputSchema = spec.output_schema + # Rebuild the result rather than mutate the original: nextCursor and + # any other fields the customer's handler set are carried over. + return ServerResult( + ListToolsResult( + tools=tools, + nextCursor=getattr(listed.root, "nextCursor", None), + ) + ) + except Exception as e: + write_to_log( + "Warning: tools/list injection failed, serving the customer's " + f"unmodified list - {e}" + ) + return listed + + async def run_original(request: Any, arguments: dict[str, Any]) -> Any: + """Dispatch to the customer's handler on a clone carrying only their args.""" + params = request.params.model_copy(update={"arguments": arguments}) + return await original(_CALL)(request.model_copy(update={"params": params})) + + async def wrapped_call(request: Any) -> Any: + tracking = current_data() + options = tracking.options + name = getattr(request.params, "name", None) or "Unknown Tool" + raw_arguments = dict(getattr(request.params, "arguments", None) or {}) + + # Runs first: on an instance that never served a listing this rebuilds + # the registries, which is also what settles whether the customer ships + # a get_more_tools of their own. + stripped = await get_stripped_arguments( + tracking, options, name, raw_arguments, rebuild + ) + + # Answer get_more_tools ourselves only when WE are the one advertising + # it. A customer who happens to name a tool `get_more_tools` keeps it: + # silently swapping their handler for our canned reply would alter tool + # behavior, which nothing AgentCat does may do (spec §12). + serve_report_missing = ( + name == GET_MORE_TOOLS_NAME and agentcat_advertises_get_more_tools + ) + + # Tracing off: still strip what we injected, so the customer's tool runs + # exactly as it would untracked — then get out of the way. No handle + # resolution, no mint-back (there is no session_id parameter to echo), and + # no event. get_more_tools still answers (changelog 6.6). + if not options.enable_tracing: + if serve_report_missing: + return ServerResult(await handle_report_missing(stripped)) + return await run_original(request, stripped) + + context = _safe_request_context(server) + try: + # Resolved fresh every round: the ResolvedCall carries this round's + # request/extra for the customer's tag and property callbacks. + # + # `request.params`, not `request`: the customer-facing hooks + # (`identify`, `event_tags`, `event_properties`, `resolve_session_id`) + # take ONE shape on every flavor, and the params model is the only + # one all four adapters can produce — mcp 2.x hands its handler + # `(ctx, params)` with no request object anywhere, and community + # FastMCP's `context.message` is params too. So `request.name` and + # `request.arguments` here, exactly as everywhere else. + resolved = await resolve_call( + tracking, + name, + raw_arguments, + request.params, + context, + meta_sources=[_meta_extras(request)], + legacy_client=lambda: _legacy_client_info(context), + ) + except Exception as e: + # Belt and braces at the customer boundary: the resolvers are all + # documented not to raise, but a tool call must never fail because + # analytics did. Degrade to an untraced call. + write_to_log( + f"Warning: AgentCat resolution failed for tool '{name}', running " + f"it untraced - {e}" + ) + if serve_report_missing: + return ServerResult(await handle_report_missing(stripped)) + return await run_original(request, stripped) + + started = now_ms() + + # The tap's slot is open for exactly the customer's handler and the + # publish that reads it, and closes on every exit path including the + # raise below. + with inner_tap() as tap: + try: + if serve_report_missing: + inner = await handle_report_missing(stripped) + else: + inner = (await run_original(request, stripped)).root + except Exception as e: + await publish_tool_call_event( + server, + tracking, + resolved, + name, + raw_arguments, + response=None, + is_error=True, + # The live exception, so this path keeps its type and + # traceback. Better than anything the tap could hold, and + # it is the same object when the tap holds one at all. + error=capture_exception(e), + duration_ms=now_ms() - started, + mrtr=None, + extra_params=extra_from_request_context(context), + ) + raise + + mrtr = detect_mrtr(getattr(inner, "resultType", None), False) + is_error = bool(getattr(inner, "isError", False)) + await publish_tool_call_event( + server, + tracking, + resolved, + name, + raw_arguments, + response=response_payload(inner), + is_error=is_error, + # The SDK caught the exception and kept only its message, so + # `tap.error` reaches past the flattened result for the object + # the tap recorded — and falls back to that result's message + # when nothing local raised at all. + error=tap.error(inner) if is_error else None, + duration_ms=now_ms() - started, + mrtr=mrtr, + extra_params=extra_from_request_context(context), + ) + + # An intermediate multi-round-trip round is never decorated: only the + # completing round carries the mint-back (changelog 6.4). + if mrtr == "input_required": + return ServerResult(inner) + + update: dict[str, Any] = {} + content = getattr(inner, "content", None) + decorated = decorate_content( + list(content) if isinstance(content, list) else None, + resolved.resolution, + lambda text: TextContent(type="text", text=text), + ) + if decorated is not None: + update["content"] = decorated + mirrored = structured_mirror( + getattr(inner, "structuredContent", None), + resolved.resolution, + name, + tracking.output_injection_registry, + ) + if mirrored is not None: + update["structuredContent"] = mirrored + # A copy, never an in-place edit: the event above still references the + # customer's own result object. + return ServerResult(inner.model_copy(update=update) if update else inner) + + def swap(key: str) -> bool: + """Put our wrapper on top of whatever is registered for ``key``. + + Returns whether anything was wrapped. Never raises: a handler table we + cannot rewrite leaves the customer's handler exactly where it was, + which costs analytics for that method and nothing else. + """ + try: + current = handlers.get(request_types[key]) + # Ours from an earlier pass? Then the customer's handler is the one + # we recorded, not the wrapper sitting in the table. + customer = original(key) if current is state.get(key) else current + if customer is None: + return False + wrapper = wrapped_list if key == _LIST else wrapped_call + state[f"orig_{key}"] = customer + state[key] = wrapper + handlers[request_types[key]] = wrapper + return True + except Exception as e: + write_to_log( + f"Warning: could not wrap '{key}' on this server; it stays " + f"untracked - {e}" + ) + return False + + def rearm(key: str) -> bool: + """Patch the registration decorator so later registrations land wrapped. + + Registration on this generation writes straight into + ``request_handlers``, so there is no single ``add_request_handler`` to + patch the way lowlevel v2 has — the decorator that performs the write + is the seam. The patch is an instance attribute shadowing the class + method, and it unstacks itself on a re-``track()`` the same way the + handlers do. + """ + decorator_key = f"{key}_decorator" + current = getattr(server, key, None) + if not callable(current): + return False + register = ( + state.get(f"orig_{decorator_key}") + if current is state.get(decorator_key) + else current + ) + if register is None: + return False + + def rearming(*args: Any, **kwargs: Any) -> Any: + decorator = register(*args, **kwargs) + + def apply(func: Any) -> Any: + registered = decorator(func) + swap(key) + return registered + + return apply + + state[f"orig_{decorator_key}"] = register + state[decorator_key] = rearming + try: + setattr(server, key, rearming) + except Exception as e: + write_to_log( + f"Warning: could not re-arm '{key}' registration; a handler " + f"registered after track() will not be tracked - {e}" + ) + return False + return True + + wrapped = [key for key in (_LIST, _CALL) if swap(key)] + rearmed = [key for key in (_LIST, _CALL) if rearm(key)] + tapped_seams = _arm_inner_tap(server, facade, state) + write_to_log( + f"Installed lowlevel-v1 adapter on server {id(server)} " + f"(wrapped={wrapped or 'none yet'}, re-armed={rearmed or 'no'}, " + f"inner-tap={tapped_seams or 'none'})" + ) diff --git a/src/agentcat/modules/adapters/lowlevel_v2.py b/src/agentcat/modules/adapters/lowlevel_v2.py new file mode 100644 index 0000000..c96abd9 --- /dev/null +++ b/src/agentcat/modules/adapters/lowlevel_v2.py @@ -0,0 +1,599 @@ +"""Adapter for the official MCP SDK 2.x lowlevel ``Server``. + +It also serves ``mcp.server.mcpserver.MCPServer`` through its +``_lowlevel_server``, so both modern official flavors run one interception +path — the same arrangement ``lowlevel_v1`` has with official FastMCP. + +Era-specific knowledge only: the method-keyed ``_request_handlers`` table, the +frozen ``HandlerEntry`` registration record, ``(ctx, params)`` handlers that +return complete result models, snake_case model fields +(``input_schema``/``structured_content``/``is_error``), and the 2026 +multi-round-trip result vocabulary. Every decision about what to resolve, +strip, decorate or publish belongs to :mod:`agentcat.modules.callpath` and is +not re-derived here. + +Four invariants the wrappers exist to protect: + +- **Nothing customer-owned is mutated.** Listed tools are deep-copied before + the injection pipeline rewrites their schemas in place, and the request + params are cloned via ``model_copy`` rather than rebuilt — a rebuilt + ``CallToolRequestParams`` drops ``input_responses`` / ``request_state`` / + ``_meta``, which severs multi-round-trip continuations. +- **The event records the call as the agent made it.** Raw (unstripped) + arguments and the customer's undecorated result; the mint-back is wire-only. +- **An intermediate MRTR round is never decorated.** This is the first era + where a tool can ask the client for more input, so ``input_required`` is real + behavior here: the round publishes, tagged, but goes back undecorated. +- **The registration seam stays armed.** ``track()`` can run before a single + ``tools/*`` handler exists, and a customer may replace one afterwards; + either way the wrapper ends up on top exactly once. + +All ``mcp`` imports are function-local so ``import agentcat`` succeeds under +either SDK major. +""" + +from __future__ import annotations + +import copy +import dataclasses +from typing import Any + +from agentcat.modules.adapters._common import ( + current_tracking_data, + install_state, + now_ms, + response_payload, +) +from agentcat.modules.adapters._inner_tap import inner_tap, tap_method +from agentcat.modules.callpath import ( + ResolvedCall, + decorate_content, + detect_mrtr, + get_stripped_arguments, + publish_tool_call_event, + resolve_call, + structured_mirror, +) +from agentcat.modules.constants import GET_MORE_TOOLS_NAME +from agentcat.modules.detection import HANDLER_REGISTRATION_NAMES +from agentcat.modules.exceptions import capture_exception +from agentcat.modules.injection import ToolSpec, build_injected_schemas +from agentcat.modules.logging import write_to_log +from agentcat.modules.request_extra import extra_from_request_context +from agentcat.modules.tools import ( + GET_MORE_TOOLS_DESCRIPTION, + GET_MORE_TOOLS_SCHEMA, + handle_report_missing, +) +from agentcat.types import AgentCatData + +LIST_METHOD = "tools/list" +CALL_METHOD = "tools/call" + + +def _entry(server: Any, method: str) -> Any: + """The registration record for ``method``, or None.""" + try: + return server._request_handlers.get(method) + except Exception: + return None + + +def _handler_of(entry: Any) -> Any: + """The callable inside a registration record. + + 2.0 wraps it in a ``HandlerEntry``; the pre-2.0 development line stored the + callable directly, and the classifier still accepts that shape. + """ + return getattr(entry, "handler", entry) + + +def _registration(entry: Any, handler: Any) -> Any: + """``entry`` with ``handler`` swapped in, for writing back to the table. + + ``HandlerEntry`` is a frozen dataclass, so the record is rebuilt rather + than mutated — via ``dataclasses.replace``, which carries every field + forward by name and so cannot silently drop one upstream adds later (a + validator, a title, an annotation). Positional reconstruction is the + fallback for a record that is not a dataclass at all, and a record that is + just the callable has no params type to carry. + """ + params_type = getattr(entry, "params_type", None) + if params_type is None: + return handler + if dataclasses.is_dataclass(entry) and not isinstance(entry, type): + return dataclasses.replace(entry, handler=handler) + return type(entry)(params_type, handler) + + +def _legacy_client_info(ctx: Any) -> Any: + """Handshake-time ``client_info``, captured by the SDK's own connection. + + The last rung of the client identity ladder, supplied lazily so the + earlier meta rungs never pay for it. On a 2026-era wire there is no + handshake and the envelope rung above answers first; on a legacy-era + connection this is the only rung there is. + """ + try: + return ctx.session.client_params.client_info + except Exception: + return None + + +def _text_block(text: str) -> Any: + from mcp.types import TextContent + + return TextContent(type="text", text=text) + + +def _make_get_more_tools() -> Any: + from mcp.types import Tool, ToolAnnotations + + # Built from a keyword mapping rather than literal kwargs. `input_schema` + # and `read_only_hint` are the 2.x field names, and a type-check pass run + # against the 1.x models — which is exactly what happens in the legacy + # dependency set, where this whole module is dead code — sees only their + # camelCase predecessors. Same era bridge `adapters/community.py` uses for + # its annotations mapping. + annotations: dict[str, Any] = {"read_only_hint": True} + fields: dict[str, Any] = { + "name": GET_MORE_TOOLS_NAME, + "description": GET_MORE_TOOLS_DESCRIPTION, + "input_schema": copy.deepcopy(GET_MORE_TOOLS_SCHEMA), + # Spec defaults assume the worst; declare the honest hint so + # annotation-aware clients skip the confirmation prompt. + "annotations": ToolAnnotations(**annotations), + } + return Tool(**fields) + + +def _mcpserver_behind(server: Any, state: dict[str, Any]) -> Any: + """The ``MCPServer`` that owns ``server``, found from its own handler. + + ``track()`` supplies the facade when it was handed one, but a customer who + tracks ``mcpserver._lowlevel_server`` directly hands it only the lowlevel + object. The registered ``tools/call`` handler is a bound method of the + MCPServer either way, and the ownership check — that the object's own + ``_lowlevel_server`` IS this server — is what keeps a customer handler + bound to some unrelated object with a ``call_tool`` attribute out. + """ + owner = getattr(state.get(f"orig_{CALL_METHOD}"), "__self__", None) + if owner is None or getattr(owner, "_lowlevel_server", None) is not server: + return None + return owner + + +def _arm_inner_tap(server: Any, facade: Any, state: dict[str, Any]) -> list[str]: + """Arm the inner tap on ``MCPServer.call_tool``, if there is an MCPServer. + + ``MCPServer._handle_call_tool`` — the ``tools/call`` handler this adapter + wraps — catches everything its ``call_tool`` raises and keeps only + ``str(e)``, so the exception dies one frame below the wrapper. There is no + method call inside that ``except`` to read ``sys.exc_info()`` from the way + lowlevel v1 has, so the seam is ``call_tool`` itself: looked up on the + instance per call, and the innermost thing outside the customer's tool. + + A **bare** lowlevel v2 server needs nothing. This generation lets a + handler's exception through to the runner, so the adapter's own ``except`` + already holds it live — which is why there is no owner to find there and + this is a no-op. + """ + owner = facade if facade is not None else _mcpserver_behind(server, state) + if owner is None or not callable(getattr(owner, "call_tool", None)): + return [] + return ["call_tool"] if tap_method(owner, "call_tool", state, "call_tool") else [] + + +def install_lowlevel_v2(server: Any, data: AgentCatData, facade: Any = None) -> None: + """Wrap ``tools/list`` and ``tools/call`` on a lowlevel v2 server. + + ``server`` is the lowlevel object the detector handed back (a bare + ``Server``, or an ``MCPServer``'s ``_lowlevel_server``); ``facade`` is the + ``MCPServer`` that owns it when there is one, which only the inner tap + needs; ``data`` is the tracking data already stored for it. + + ``initialize`` is deliberately left alone — it cannot be overridden on this + generation, and there is nothing there v2 wants: the only thing the old 1.x + override took from it, the handshake ``clientInfo``, the SDK already keeps + on the connection where the client identity ladder reads it per request. + """ + state = install_state(server) + if state is None: + return # already logged + + # Whether WE are the one advertising get_more_tools. Stated positively on + # purpose: it is set at the append site by every pass over the listing + # (client-facing or rebuild-on-demand), so until a listing has actually + # advertised our tool this stays False — and a server with no tools/list + # handler at all, or one whose listing raised, cannot hijack a customer's + # own get_more_tools by default. + agentcat_advertises_get_more_tools = False + + def current_data() -> AgentCatData: + """The tracking data as of this request, so a re-track takes effect.""" + return current_tracking_data(server, data) + + def original(method: str) -> Any: + """The customer's handler for ``method`` as of right now. + + Read from the shared state on every call rather than captured, so a + handler the customer re-registers after ``track()`` is the one that + runs — the wrapper on top of it does not need replacing for that. + """ + return state.get(f"orig_{method}") + + def advertised_tools(result: Any, options: Any) -> list[Any] | None: + """Deep copies of the listed tools, plus get_more_tools when enabled. + + None when the handler returned something with no tool list to inject + into (a raw dict, an error shape), which the caller serves untouched. + Copies because the injection pipeline rewrites schemas in place. + """ + nonlocal agentcat_advertises_get_more_tools + listed = getattr(result, "tools", None) + if not isinstance(listed, list): + return None + tools = [tool.model_copy(deep=True) for tool in listed] + customer_owns_get_more_tools = any( + getattr(tool, "name", None) == GET_MORE_TOOLS_NAME for tool in tools + ) + agentcat_advertises_get_more_tools = ( + options.enable_report_missing and not customer_owns_get_more_tools + ) + # Appended before injection so it receives handle parameters too; the + # context pass skips it by name, so early placement cannot double-inject. + if agentcat_advertises_get_more_tools: + tools.append(_make_get_more_tools()) + return tools + + def specs_for(tools: list[Any]) -> list[ToolSpec]: + return [ + ToolSpec(tool.name, tool.input_schema, getattr(tool, "output_schema", None)) + for tool in tools + ] + + def empty_list_params() -> Any: + """A default-constructed params model for a listing we ask for. + + The registered params type is all-optional (``PaginatedRequestParams``), + which is what the runner would hand a handler for a request that + carried none — so a customer handler reading ``params.cursor`` sees the + same thing it always does. + """ + params_type = getattr(_entry(server, LIST_METHOD), "params_type", None) + try: + return params_type() if params_type is not None else None + except Exception: + return None + + async def wrapped_list(ctx: Any, params: Any) -> Any: + result = await original(LIST_METHOD)(ctx, params) + tracking = current_data() + try: + tools = advertised_tools(result, tracking.options) + if tools is None: + return result + specs = specs_for(tools) + injected = build_injected_schemas( + specs, tracking.options, tracking.reported_conflicts + ) + tracking.injected_params_registry = injected.injected_params + tracking.output_injection_registry = injected.output_injected + # Union, never replace: membership only grows, and a concurrent + # listing on another instance may already have recorded a tool this + # one did not see. + tracking.declared_session_params |= injected.declared_session_params + for tool, spec in zip(tools, specs, strict=True): + tool.input_schema = spec.input_schema + if spec.output_schema is not None: + tool.output_schema = spec.output_schema + # A copy rather than a mutation: next_cursor, cache hints and any + # other field the customer's handler set are carried over, and the + # result object they still hold is left alone. + return result.model_copy(update={"tools": tools}) + except Exception as e: + write_to_log( + "Warning: tools/list injection failed, serving the customer's " + f"unmodified list - {e}" + ) + return result + + async def wrapped_call(ctx: Any, params: Any) -> Any: + tracking = current_data() + options = tracking.options + name = getattr(params, "name", None) or "Unknown Tool" + raw_arguments = dict(getattr(params, "arguments", None) or {}) + + async def rebuild() -> list[ToolSpec]: + """The list source for registry rebuild-on-demand (changelog 6.3). + + Driven off this request's own context, so a customer handler that + reads the session or the lifespan state gets the real thing. + """ + list_handler = original(LIST_METHOD) + if list_handler is None: + return [] + listed = await list_handler(ctx, empty_list_params()) + tools = advertised_tools(listed, current_data().options) + return specs_for(tools) if tools is not None else [] + + # Runs first: on an instance that never served a listing this rebuilds + # the registries, which is also what settles whether the customer ships + # a get_more_tools of their own. + stripped = await get_stripped_arguments( + tracking, options, name, raw_arguments, rebuild + ) + + async def run_customer() -> Any: + """Dispatch to the customer's handler on a clone carrying only + their arguments. ``model_copy`` keeps ``input_responses`` / + ``request_state`` / ``_meta``, which a rebuilt params model loses.""" + return await original(CALL_METHOD)( + ctx, params.model_copy(update={"arguments": stripped}) + ) + + # Answer get_more_tools ourselves only when WE are the one advertising + # it. A customer who happens to name a tool `get_more_tools` keeps it: + # silently swapping their handler for our canned reply would alter tool + # behavior, which nothing AgentCat does may do (spec §12). + serve_report_missing = ( + name == GET_MORE_TOOLS_NAME and agentcat_advertises_get_more_tools + ) + + # Tracing off: still strip what we injected, so the customer's tool runs + # exactly as it would untracked — then get out of the way. No handle + # resolution, no mint-back (there is no session_id parameter to echo), and + # no event. get_more_tools still answers (changelog 6.6). + if not options.enable_tracing: + if serve_report_missing: + return await handle_report_missing(stripped) + return await run_customer() + + try: + # Resolved fresh every round: the ResolvedCall carries this round's + # params/context for the customer's tag and property callbacks, so + # it must never be cached across MRTR rounds. + resolved = await resolve_call( + tracking, + name, + raw_arguments, + params, + ctx, + meta_sources=[getattr(ctx, "meta", None)], + legacy_client=lambda: _legacy_client_info(ctx), + protocol_fallback=getattr(ctx, "protocol_version", None), + ) + except Exception as e: + # Belt and braces at the customer boundary: the resolvers are all + # documented not to raise, but a tool call must never fail because + # analytics did. Degrade to an untraced call. + write_to_log( + f"Warning: AgentCat resolution failed for tool '{name}', running " + f"it untraced - {e}" + ) + if serve_report_missing: + return await handle_report_missing(stripped) + return await run_customer() + + started = now_ms() + + # The tap's slot is open for exactly the customer's handler and the + # publish that reads it, and closes on every exit path including the + # raise below. + with inner_tap() as tap: + try: + if serve_report_missing: + result = await handle_report_missing(stripped) + else: + result = await run_customer() + except Exception as e: + # Unlike 1.x, this generation lets a bare handler's exception + # through to the runner, so this path holds the live exception + # with its type and traceback intact. + await _publish( + tracking, + resolved, + name, + raw_arguments, + ctx, + response=None, + is_error=True, + error=capture_exception(e), + started=started, + mrtr=None, + ) + raise + + mrtr = detect_mrtr( + getattr(result, "result_type", None), + getattr(params, "input_responses", None) is not None, + getattr(params, "request_state", None) is not None, + ) + is_error = bool(getattr(result, "is_error", False)) + await _publish( + tracking, + resolved, + name, + raw_arguments, + ctx, + response=response_payload(result), + is_error=is_error, + # An `MCPServer` handler flattens the exception before this + # wrapper sees it, so `tap.error` reaches past the result for + # the object the inner tap recorded — and falls back to that + # result's message when nothing local raised at all. + error=tap.error(result) if is_error else None, + started=started, + mrtr=mrtr, + ) + + # An intermediate multi-round-trip round is never decorated: only the + # completing round carries the mint-back (changelog 6.4). It has no + # content to append to and no structured payload to mirror into, and + # even if it did the handle belongs on the round that finishes. + if mrtr == "input_required": + return result + return _decorated(result, resolved, name, tracking) + + async def _publish( + tracking: AgentCatData, + resolved: ResolvedCall, + name: str, + raw_arguments: dict[str, Any], + ctx: Any, + response: dict[str, Any] | None, + is_error: bool, + error: Any, + started: int, + mrtr: str | None, + ) -> None: + await publish_tool_call_event( + server, + tracking, + resolved, + name, + raw_arguments, + response=response, + is_error=is_error, + error=error, + duration_ms=now_ms() - started, + mrtr=mrtr, + extra_params=extra_from_request_context(ctx), + ) + + def _decorated( + result: Any, resolved: ResolvedCall, name: str, tracking: AgentCatData + ) -> Any: + """The wire result with the mint-back appended, or the original.""" + if not hasattr(result, "model_copy"): + # A handler that returned a raw dict is serialized as-is by the + # runner; there is no model to copy and nothing safe to edit. The + # call is still tracked, but the agent never sees the mint-back and + # so mints a fresh task on every call — say so, or that shows up as + # an unexplained pile of one-call tasks. + write_to_log( + f"Warning: tool '{name}' returned a raw mapping rather than a " + "result model, so the session_id mint-back cannot be attached; " + "every call to it will start a new task" + ) + return result + update: dict[str, Any] = {} + content = getattr(result, "content", None) + decorated = decorate_content( + list(content) if isinstance(content, list) else None, + resolved.resolution, + _text_block, + ) + if decorated is not None: + update["content"] = decorated + mirrored = structured_mirror( + getattr(result, "structured_content", None), + resolved.resolution, + name, + tracking.output_injection_registry, + ) + if mirrored is not None: + update["structured_content"] = mirrored + # A copy, never an in-place edit: the event above still references the + # customer's own result object. + return result.model_copy(update=update) if update else result + + def swap(method: str) -> bool: + """Put our wrapper on top of whatever is registered for ``method``. + + Returns whether anything was wrapped. Never raises: a table shape we + cannot rewrite leaves the customer's handler exactly where it was, + which costs analytics for that method and nothing else. + """ + entry = _entry(server, method) + if entry is None: + return False + try: + current = _handler_of(entry) + # Ours from an earlier pass? Then the customer's handler is the one + # we recorded, not the wrapper sitting in the table. + customer = original(method) if current is state.get(method) else current + if customer is None: + return False + wrapper = wrapped_list if method == LIST_METHOD else wrapped_call + state[f"orig_{method}"] = customer + state[method] = wrapper + server._request_handlers[method] = _registration(entry, wrapper) + return True + except Exception as e: + write_to_log( + f"Warning: could not wrap '{method}' on this server; it stays " + f"untracked - {e}" + ) + return False + + def rearm_seam(name: str, already_patched: list[Any]) -> bool: + """Patch one registration seam so later registrations land wrapped. + + Without this, ``track()`` on a server whose ``tools/*`` handlers are + registered afterwards installs nothing at all, and a customer who + replaces a handler later silently drops out of tracking. The patch is + an instance attribute shadowing the class method, and it unstacks + itself on a re-``track()`` the same way the handlers do. + + ``already_patched`` collects the underlying functions patched so far. + A build whose public name is a bare alias for the private one resolves + to the same function twice; patching it twice would register twice. + """ + current = getattr(server, name, None) + if not callable(current): + return False + add = ( + state.get(f"orig_seam_{name}") + if current is state.get(f"seam_{name}") + else current + ) + if add is None: + return False + underlying = getattr(add, "__func__", add) + if any(patched is underlying for patched in already_patched): + return False + + def rearming_add(*args: Any, **kwargs: Any) -> Any: + result = add(*args, **kwargs) + method = args[0] if args else kwargs.get("method") + if method in (LIST_METHOD, CALL_METHOD): + swap(method) + return result + + state[f"orig_seam_{name}"] = add + state[f"seam_{name}"] = rearming_add + try: + setattr(server, name, rearming_add) + except Exception as e: + write_to_log( + f"Warning: could not re-arm '{name}'; a tools handler " + f"registered after track() through it will not be tracked - {e}" + ) + return False + already_patched.append(underlying) + return True + + def rearm() -> list[str]: + """Patch EVERY registration seam this build exposes. + + Not just the first one found: the classifier accepts both spellings + because the method has been public and private at different points on + the 2.x line, and the natural refactor shape — a public wrapper + delegating to a private one — exposes both at once. Patching only the + public name there would silently drop re-arm for anyone who registers + through the private one. + """ + patched: list[Any] = [] + return [ + name for name in HANDLER_REGISTRATION_NAMES if rearm_seam(name, patched) + ] + + wrapped = [method for method in (LIST_METHOD, CALL_METHOD) if swap(method)] + seams = rearm() + tapped_seams = _arm_inner_tap(server, facade, state) + write_to_log( + f"Installed lowlevel-v2 adapter on server {id(server)} " + f"(wrapped={wrapped or 'none yet'}, re-armed={seams or 'no'}, " + f"inner-tap={tapped_seams or 'none'})" + ) diff --git a/src/agentcat/modules/callpath.py b/src/agentcat/modules/callpath.py new file mode 100644 index 0000000..a3e492b --- /dev/null +++ b/src/agentcat/modules/callpath.py @@ -0,0 +1,316 @@ +"""Shared per-call orchestration for `tools/call`. + +Every adapter — lowlevel v1, lowlevel v2, community FastMCP — wraps the +customer's handler with the same steps: resolve (handles, actor, client), +strip the parameters we injected, run, publish exactly one event, decorate the +wire result. This module is that shared middle. The primitives it composes +live in handles.py / injection.py / client_identity.py and are never +re-derived here. + +Engine code: nothing version-specific from `mcp`/`fastmcp` is imported, so it +loads identically under mcp 1.x and 2.x. Nothing here may raise into the +customer's server, and nothing here mutates a customer object — the published +event carries the RAW arguments and the UNDECORATED result (mint-back is +wire-only), `get_stripped_arguments` returns a new dict and `decorate_content` +a new list. + +Cross-SDK contract: 2026-07-28-cross-sdk-changelog.md §3.4, §6.2-§6.5; TS +reference src/engine/callWrap.ts. +""" + +from collections.abc import Awaitable, Callable +from dataclasses import dataclass +from datetime import datetime, timedelta, timezone +from typing import Any + +from agentcat.modules import event_queue +from agentcat.modules.client_identity import ( + ClientIdentity, + resolve_client_identity, + resolve_protocol_version, +) +from agentcat.modules.constants import CONTEXT_PARAM +from agentcat.modules.handles import ( + HandleResolution, + build_handle_tags, + build_mint_back_text, + build_structured_mint_back, + mirror_into_structured_content, + resolve_handles, +) +from agentcat.modules.identify import resolve_identity +from agentcat.modules.injection import ( + ToolSpec, + build_injected_schemas, + injected_parameter_names, + strip_injected_arguments, +) +from agentcat.modules.internal import attach_event_metadata +from agentcat.modules.logging import write_to_log +from agentcat.types import ( + AgentCatData, + AgentCatOptions, + ErrorData, + EventType, + UnredactedEvent, + UserIdentity, +) + +# A failed call whose adapter could make nothing of the failure. Same shape as +# every other error payload so consumers never have to branch on presence. +_UNKNOWN_ERROR: ErrorData = { + "message": "Unknown error", + "type": None, + "platform": "python", +} + + +@dataclass +class ResolvedCall: + """Everything resolved about one tool call before its handler runs.""" + + resolution: HandleResolution + actor: UserIdentity | None + client: ClientIdentity + protocol_version: str | None + intent: str | None + # The originating request/extra, carried so the customer's event_tags and + # event_properties callbacks receive the same pair `identify` got — the + # documented contract of `internal.attach_event_metadata`, which + # publish_tool_call_event runs long after the adapter's frame is gone. + # Consequently a ResolvedCall is single-round state: an adapter must + # resolve afresh on each MRTR round, never cache one across rounds, or + # round N's callbacks would be handed round 1's request. + request: Any = None + extra: Any = None + + +async def resolve_call( + data: AgentCatData, + tool_name: str, + raw_arguments: dict[str, Any], + request: Any, + extra: Any, + meta_sources: list[Any], + legacy_client: Callable[[], Any | None], + protocol_fallback: str | None = None, +) -> ResolvedCall: + """Resolve handles, actor, client and intent. Publishes nothing. + + None of the four resolvers raises: a `resolve_session_id` hook that blows up + mints silently, a broken `identify` yields an anonymous call, and the + client ladder floors at an empty identity. `tool_name` is taken so every + adapter calls this with one shape; intent capture is unconditional. + + MUST run after `get_stripped_arguments` — every adapter does — because the + registry it reads is what that call populates (and rebuilds on demand). It + is the same registry, so the handles read here are exactly the parameters + stripped there: a `session_id` the customer's own schema declared is neither + taken from their handler nor consumed as ours. + + A tool absent from `declared_session_params` is ours — including one this + instance never listed. That is the common case on stateless HTTP and it + degrades safely: a customer's foreign value in that window is classified + `invalid` rather than `foreign`, and both publish sessionless. + """ + resolution = await resolve_handles( + raw_arguments, + data.options, + data.project_id, + request, + extra, + injected_parameter_names(tool_name, data.injected_params_registry), + tool_name not in data.declared_session_params, + ) + actor = resolve_identity(data, request, extra) + client = resolve_client_identity(meta_sources, legacy_client) + protocol_version = resolve_protocol_version(meta_sources, protocol_fallback) + # Read from the RAW arguments (pre-strip): the event records what the agent + # sent, and a non-string `context` is not an explanation. + context_value = raw_arguments.get(CONTEXT_PARAM) + return ResolvedCall( + resolution=resolution, + actor=actor, + client=client, + protocol_version=protocol_version, + intent=context_value if isinstance(context_value, str) else None, + request=request, + extra=extra, + ) + + +async def get_stripped_arguments( + data: AgentCatData, + options: AgentCatOptions, + tool_name: str, + raw_arguments: dict[str, Any], + rebuild: Callable[[], Awaitable[list[ToolSpec]]] | None, +) -> dict[str, Any]: + """A NEW argument dict with only the params AgentCat injected removed. + + Registry-first (§6.2). A call that lands on an instance which never served + `tools/list` rebuilds the registries on demand from the adapter's list + source (§6.3); the injection pipeline is deterministic, so a rebuilt + registry matches what any listing instance advertised. Only a failed + rebuild falls back to the heuristic strip — and it clears the + output-injection registry, so the structured mirror stops gating on + knowledge we no longer have (§3.4b). + """ + registry = data.injected_params_registry + if registry is None and rebuild is not None: + try: + result = build_injected_schemas( + await rebuild(), options, data.reported_conflicts + ) + except Exception as e: + write_to_log( + "Warning: injection registry rebuild-on-demand failed for tool " + f"'{tool_name}', falling back to heuristic strip - {e}" + ) + # Only the mirror gate is cleared. `injected_params_registry` is + # left alone: it is already None on this path, and assigning would + # destroy a good registry a concurrent call had just stored while + # this one was awaiting — after which every later call would + # heuristic-strip and eat customer `context` parameters. + data.output_injection_registry = None + else: + registry = result.injected_params + data.injected_params_registry = result.injected_params + data.output_injection_registry = result.output_injected + data.declared_session_params |= result.declared_session_params + write_to_log( + "Rebuilt injection registries on demand " + "(tools/call before tools/list on this instance)" + ) + return strip_injected_arguments(tool_name, raw_arguments, registry) + + +def detect_mrtr( + result_type: str | None, + has_input_responses: bool, + has_request_state: bool = False, +) -> str | None: + """Classify one round of a multi round-trip tool call (§6.4). + + `input_required` wins: an intermediate round that is itself a continuation + is still intermediate, and only a completing round carries the mint-back. + + A continuation is EITHER shape the SEP-2322 driver can send. It answers an + intermediate round that carried `input_requests` with the collected + `inputResponses`, but an intermediate round that carried only + `requestState` — a tool asking to be resumed rather than asking the client + a question — is retried after a backoff with **no** responses at all + (`mcp/client/_input_required.py::run_input_required_driver`). Keying the + tag on `inputResponses` alone left that second shape untagged, which is the + shape FastMCP 4's own `InputRequiredResult(request_state=...)` produces. + `requestState` rides only on a round that is answering an earlier one — a + first round never carries it — so it is a sound continuation witness on its + own. + """ + if result_type == "input_required": + return "input_required" + if has_input_responses or has_request_state: + return "continuation" + return None + + +def decorate_content( + content: list[Any] | None, + res: HandleResolution, + make_text_block: Callable[[str], Any], +) -> list[Any] | None: + """The trailing mint-back block, or None to leave the result untouched. + + Error state is deliberately not an input: the retry after a failure has to + carry the same session, so `isError` results decorate on identical terms + (§3.4a). Whether there is anything to say at all stays the single ruling of + `build_mint_back_text` — a session minted on this call, or a supplied one + this server never issued; never in hook mode, and never for a parameter + AgentCat did not inject. + """ + text = build_mint_back_text(res) + if text is None or not isinstance(content, list): + return None + return [*content, make_text_block(text)] + + +def structured_mirror( + sc: Any, + res: HandleResolution, + tool_name: str, + output_registry: set[str] | None, +) -> Any | None: + """Handle state mirrored into `structuredContent`, or None (§3.4b). + + Gated on the output-injection registry: mirroring a key the tool's own + `outputSchema` never declared fails the customer's entire result on a + schema-validating client. No registry at all means the rebuild failed — + mirror anyway, since no schema we know about can be in play. + """ + if output_registry is not None and tool_name not in output_registry: + return None + mint = build_structured_mint_back(res) + if mint is None: + return None + return mirror_into_structured_content(sc, mint) + + +async def publish_tool_call_event( + server_key: Any, + data: AgentCatData, + rc: ResolvedCall, + tool_name: str, + raw_arguments: dict[str, Any], + response: Any, + is_error: bool, + error: ErrorData | None, + duration_ms: int | None, + mrtr: str | None, + extra_params: dict[str, Any] | None, +) -> None: + """Publish the one event a v2 tool call produces. Never raises. + + The event records the call as the agent made it: RAW arguments (handles and + `context` included) and the customer's undecorated result. SDK tags merge + over the customer's, so they win on collision and ride outside the 50-tag + customer cap `validate_tags` enforces (§6.5). + + `error` is whatever `modules.exceptions.capture_exception` made of the + failure — the adapter decides, because only it knows whether it holds a + live exception or the `isError` result the SDK already flattened it into. + A failure always records an error object, never a bare `is_error` flag. + """ + try: + now = datetime.now(timezone.utc) + event = UnredactedEvent( + # "" is sessionless (invalid/foreign); the wire carries null. + session_id=rc.resolution.session_id or None, + # Events timestamp when the call STARTED; the adapter measured how + # long ago that was. + timestamp=now - timedelta(milliseconds=duration_ms) if duration_ms else now, + event_type=EventType.MCP_TOOLS_CALL.value, + resource_name=tool_name, + user_intent=rc.intent, + parameters={"arguments": raw_arguments, **(extra_params or {})}, + response=response, + is_error=is_error, + error=(error or _UNKNOWN_ERROR) if is_error else None, + duration=duration_ms, + client_name=rc.client.name, + client_version=rc.client.version, + identify_actor_given_id=rc.actor.user_id if rc.actor else None, + identify_actor_name=rc.actor.user_name if rc.actor else None, + identify_data=rc.actor.user_data if rc.actor else None, + ) + await attach_event_metadata(event, data, rc.request, rc.extra) + # SDK tags last so they win, and after validate_tags so they are exempt + # from the customer cap. + event.tags = { + **(event.tags or {}), + **build_handle_tags(rc.resolution, rc.protocol_version, mrtr), + } + event_queue.publish_event(server_key, event) + except Exception as e: + write_to_log( + f"Warning: failed to publish tools/call event for '{tool_name}' - {e}" + ) diff --git a/src/agentcat/modules/client_identity.py b/src/agentcat/modules/client_identity.py new file mode 100644 index 0000000..5282549 --- /dev/null +++ b/src/agentcat/modules/client_identity.py @@ -0,0 +1,103 @@ +"""Per-request client identity + protocol version ladder (spec §7). + +Cross-SDK contract: 2026-07-28-cross-sdk-changelog.md §5.1; TS reference +src/modules/session.ts (``narrowClientInfo`` / ``getClientInfoForRequest``). +Client name/version arrives per request under the fully-qualified +``META_CLIENT_INFO_KEY`` meta key (envelope or ``_meta`` passthrough); the +pre-2026 initialize-time capture is the last rung, supplied lazily by the +adapter as a callable. First hit wins and every rung is narrowed per field +to ``isinstance(x, str)`` — a non-string leaking into an event tag is a +wire-format break. + +A rung that is present but unusable (junk under the key, no string field) +is a miss, not a stop: it must not shadow a good value further down the +ladder. Nothing here raises — a torn-down request context or a hostile +meta object resolves to a miss. +""" + +from collections.abc import Callable, Mapping +from dataclasses import dataclass +from typing import Any + +from agentcat.modules.constants import ( + META_CLIENT_INFO_KEY, + META_PROTOCOL_VERSION_KEY, +) + + +@dataclass +class ClientIdentity: + name: str | None = None + version: str | None = None + + +def _meta_value(meta: Any, key: str) -> Any: + """Raw value under a fully-qualified meta key; ``None`` on any miss. + + Accepts plain mappings (v2 envelopes / lifted meta) and pydantic + ``RequestParams.Meta``-style objects whose extras live in + ``.model_extra`` (``None`` when the model forbids extras). + """ + if meta is None: + return None + try: + if isinstance(meta, Mapping): + return meta.get(key) + extra = getattr(meta, "model_extra", None) + if isinstance(extra, Mapping) and key in extra: + return extra[key] + return getattr(meta, key, None) + except Exception: + return None + + +def _narrow(raw: Any) -> ClientIdentity | None: + """Per-field narrowing of a clientInfo-shaped mapping or object; a value + with no usable string field is a miss (``None``), mirroring the TS + narrower.""" + if raw is None: + return None + try: + if isinstance(raw, Mapping): + name = raw.get("name") + version = raw.get("version") + else: + name = getattr(raw, "name", None) + version = getattr(raw, "version", None) + except Exception: + return None + narrowed_name = name if isinstance(name, str) else None + narrowed_version = version if isinstance(version, str) else None + if narrowed_name is None and narrowed_version is None: + return None + return ClientIdentity(name=narrowed_name, version=narrowed_version) + + +def client_identity_from_meta(meta: Any) -> ClientIdentity | None: + return _narrow(_meta_value(meta, META_CLIENT_INFO_KEY)) + + +def resolve_client_identity( + meta_sources: list[Any], legacy: Callable[[], Any | None] +) -> ClientIdentity: + for meta in meta_sources: + identity = client_identity_from_meta(meta) + if identity is not None: + return identity + try: + legacy_info = legacy() + except Exception: + legacy_info = None + identity = _narrow(legacy_info) + return identity if identity is not None else ClientIdentity() + + +def resolve_protocol_version( + meta_sources: list[Any], fallback: str | None = None +) -> str | None: + for meta in meta_sources: + value = _meta_value(meta, META_PROTOCOL_VERSION_KEY) + # Non-empty like TS getProtocolVersion (`value.length > 0`). + if isinstance(value, str) and value: + return value + return fallback diff --git a/src/agentcat/modules/compatibility.py b/src/agentcat/modules/compatibility.py deleted file mode 100644 index fe43d3f..0000000 --- a/src/agentcat/modules/compatibility.py +++ /dev/null @@ -1,262 +0,0 @@ -"""Compatibility checks for MCP servers.""" - -from typing import Any, Protocol, runtime_checkable - -from mcp import ServerResult - -# Supported version ranges for MCP and FastMCP -SUPPORTED_MCP_VERSIONS = ">=1.2.0" -SUPPORTED_OFFICIAL_FASTMCP_VERSIONS = ">=1.2.0" -SUPPORTED_COMMUNITY_FASTMCP_VERSIONS = ">=2.7.0" -SUPPORTED_COMMUNITY_FASTMCP_V3_VERSIONS = ">=3.0.0" - -# Version compatibility message for errors -COMPATIBILITY_ERROR_MESSAGE = ( - f"Server must be a supported version of a FastMCP instance " - f"(official: {SUPPORTED_OFFICIAL_FASTMCP_VERSIONS}, " - f"community: {SUPPORTED_COMMUNITY_FASTMCP_VERSIONS}) " - f"or MCP Low-level Server instance ({SUPPORTED_MCP_VERSIONS})" -) - -@runtime_checkable -class MCPServerProtocol(Protocol): - """Protocol for MCP server compatibility.""" - - def list_tools(self) -> Any: - """List available tools.""" - ... - - def call_tool(self, name: str, arguments: dict) -> Any: - """Call a tool by name.""" - ... - -def is_community_fastmcp_v3(server: Any) -> bool: - """Check if the server is a Community FastMCP v3 instance. - - Community FastMCP v3 uses the Provider architecture with _local_provider - instead of the ToolManager architecture with _tool_manager. - It also has the middleware system with add_middleware method. - """ - # Check by class name and module - class_name = server.__class__.__name__ - module_name = server.__class__.__module__ - - # Community FastMCP v3 has: - # - Class name containing 'FastMCP' - # - Module starts with 'fastmcp' - # - Has _local_provider (Provider architecture) - # - Has add_middleware method (middleware system) - # - Does NOT have _tool_manager (v2 attribute) - return ( - "FastMCP" in class_name and - module_name.startswith("fastmcp") and - hasattr(server, "_local_provider") and - hasattr(server, "add_middleware") and - hasattr(server, "middleware") and - not hasattr(server, "_tool_manager") - ) - - -def is_community_fastmcp_v2(server: Any) -> bool: - """Check if the server is a Community FastMCP v2 instance. - - Community FastMCP v2 uses the ToolManager architecture with _tool_manager. - """ - # Check by class name and module - class_name = server.__class__.__name__ - module_name = server.__class__.__module__ - - # Community FastMCP v2 has: - # - Class name containing 'FastMCP' - # - Module starts with 'fastmcp' - # - Has _mcp_server - # - Has _tool_manager (ToolManager architecture) - return ( - "FastMCP" in class_name and - module_name.startswith("fastmcp") and - hasattr(server, "_mcp_server") and - hasattr(server, "_tool_manager") - ) - - -def is_community_fastmcp_server(server: Any) -> bool: - """Check if the server is a community FastMCP instance (any version). - - Community FastMCP comes from the 'fastmcp' package. - Supports FastMCP subclasses like FastMCPOpenAPI, FastMCPProxy, etc. - This function returns True for both v2 and v3. - """ - return is_community_fastmcp_v2(server) or is_community_fastmcp_v3(server) - -def is_official_fastmcp_server(server: Any) -> bool: - """Check if the server is an official FastMCP instance. - - Official FastMCP comes from the 'mcp.server.fastmcp' module. - Supports FastMCP subclasses like FastMCPOpenAPI, FastMCPProxy, etc. - """ - # Check by class name and module - class_name = server.__class__.__name__ - module_name = server.__class__.__module__ - - # Official FastMCP has class name containing 'FastMCP' and module - # 'mcp.server.fastmcp'. Supports FastMCPOpenAPI, FastMCPProxy, etc. - return ( - "FastMCP" in class_name and - module_name.startswith("mcp.server.fastmcp") and - hasattr(server, "_mcp_server") and - hasattr(server, "_tool_manager") - ) - - -def has_required_fastmcp_attributes(server: Any) -> bool: - """Check if a FastMCP server has all required attributes for monkey patching. - - This validates that the server has all the attributes that monkey_patch.py expects. - """ - # Check for _tool_manager and its required methods - if not hasattr(server, "_tool_manager"): - return False - - tool_manager = server._tool_manager - required_tool_manager_methods = ["add_tool", "call_tool", "list_tools"] - for method in required_tool_manager_methods: - if not hasattr(tool_manager, method) or not callable( - getattr(tool_manager, method) - ): - return False - - # Check for _tools dict on tool_manager (used for tracking existing tools) - if not hasattr(tool_manager, "_tools") or not isinstance(tool_manager._tools, dict): - return False - - # Check for add_tool method on the server itself (used for adding get_more_tools) - if not hasattr(server, "add_tool") or not callable(server.add_tool): - return False - - # Check for _mcp_server (used for event tracking and session management) - if not hasattr(server, "_mcp_server"): - return False - - # Check if _mcp_server has _get_cached_tool_definition method - # (for community FastMCP patching) - if not hasattr(server._mcp_server, "_get_cached_tool_definition"): - return False - - return True - - -def has_necessary_attributes(server: Any) -> bool: - """Check if the server has necessary attributes for compatibility.""" - required_methods = ["list_tools", "call_tool"] - - # Check for core methods that both FastMCP and Server implementations have - for method in required_methods: - if not hasattr(server, method): - return False - - # For FastMCP servers, verify all required attributes for monkey patching - if is_official_fastmcp_server(server): - # Use the comprehensive FastMCP validation - if not has_required_fastmcp_attributes(server): - return False - - # Additional checks for request handling - # Use dir() to avoid triggering property getters that might raise exceptions - if "request_context" not in dir(server._mcp_server): - return False - # Check for get_context method which is FastMCP specific - if not hasattr(server, "get_context"): - return False - # Check for request_handlers dictionary on internal server - if not hasattr(server._mcp_server, "request_handlers"): - return False - if not isinstance(server._mcp_server.request_handlers, dict): - return False - else: - # Regular Server implementation - check for request_context directly - # Use dir() to avoid triggering property getters that might raise exceptions - if "request_context" not in dir(server): - return False - # Check for request_handlers dictionary - if not hasattr(server, "request_handlers"): - return False - if not isinstance(server.request_handlers, dict): - return False - - return True - - -def is_compatible_server(server: Any) -> bool: - """Check if the server is compatible with AgentCat.""" - # If it's FastMCP v3 (community), it's compatible - if is_community_fastmcp_v3(server): - return True - - # If it's either official or community FastMCP v2, it's compatible - if is_official_fastmcp_server(server) or is_community_fastmcp_v2(server): - return True - - # Otherwise, check for necessary attributes - return has_necessary_attributes(server) - - -def get_mcp_compatible_error_message(error: Any) -> str: - """Get error message in a compatible format.""" - return str(error) - - -def is_mcp_error_response(response: ServerResult) -> tuple[bool, str]: - """Check if the response is an MCP error.""" - # ServerResult is a RootModel, so we need to access its root attribute - if not hasattr(response, "root"): - return False, "" - - result = response.root - - # Check if it's a CallToolResult with an error - if not (hasattr(result, "isError") and result.isError): - return False, "" - - # Extract error message from content - if not (hasattr(result, "content") and result.content): - return True, "Unknown error" - - # content is a list of TextContent/ImageContent/EmbeddedResource - for content_item in result.content: - # Check if it has a text attribute (TextContent) - if hasattr(content_item, "text"): - return True, str(content_item.text) - # Check if it has type and content attributes - if ( - hasattr(content_item, "type") - and hasattr(content_item, "content") - and content_item.type == "text" - ): - return True, str(content_item.content) - - # If no text content found, stringify the first item - if result.content: - return True, str(result.content[0]) - - return True, "Unknown error" - -__all__ = [ - # Version constants - "SUPPORTED_MCP_VERSIONS", - "SUPPORTED_OFFICIAL_FASTMCP_VERSIONS", - "SUPPORTED_COMMUNITY_FASTMCP_VERSIONS", - "SUPPORTED_COMMUNITY_FASTMCP_V3_VERSIONS", - "COMPATIBILITY_ERROR_MESSAGE", - # Functions - "is_compatible_server", - "is_official_fastmcp_server", - "is_community_fastmcp_server", - "is_community_fastmcp_v2", - "is_community_fastmcp_v3", - "has_required_fastmcp_attributes", - "has_necessary_attributes", - "get_mcp_compatible_error_message", - "is_mcp_error_response", - # Protocols - "MCPServerProtocol", -] diff --git a/src/agentcat/modules/constants.py b/src/agentcat/modules/constants.py index 8146fb4..1e5462a 100644 --- a/src/agentcat/modules/constants.py +++ b/src/agentcat/modules/constants.py @@ -1,4 +1,3 @@ -INACTIVITY_TIMEOUT_IN_MINUTES = 30 LOG_PATH = "agentcat.log" # Default log file path SESSION_ID_PREFIX = "ses" EVENT_ID_PREFIX = "evt" @@ -20,3 +19,48 @@ # DIAGNOSTICS_TOKEN env var. Must match the collector's bearer token (same # literal as the TypeScript SDK). DEFAULT_DIAGNOSTICS_TOKEN = "dgk_sdk_diag_3f9a2c7e1b8d4065af2e9c1d7b6a4f80" + +# ── Explicit handles: injected parameter names & wire keys ─────────────────── +SESSION_ID_PARAM = "session_id" +AGENT_ID_PARAM = "agent_id" +CONTEXT_PARAM = "context" +GET_MORE_TOOLS_NAME = "get_more_tools" +AGENT_ID_PREFIX = "agt" # reserved; server-side agent minting was removed +MCP_INSTRUCTIONS_KEY = "_mcp_instructions" +META_CLIENT_INFO_KEY = "io.modelcontextprotocol/clientInfo" +META_PROTOCOL_VERSION_KEY = "io.modelcontextprotocol/protocolVersion" +AGENTCAT_TAG_SESSION_SOURCE = "agentcat_session_id_source" +AGENTCAT_TAG_AGENT_ID = "agentcat_agent_id" +AGENTCAT_TAG_AGENT_SOURCE = "agentcat_agent_id_source" +AGENTCAT_TAG_PROTOCOL_VERSION = "agentcat_protocol_version" +AGENTCAT_TAG_MRTR = "agentcat_mrtr" +AGENTCAT_CUSTOM_EVENT_TYPE = "agentcat:custom" + +# ── Explicit handles: agent-facing copy (byte-identical to TS constants.ts) ── +# Source of truth: agentcat-typescript-sdk/src/modules/constants.ts (and the +# copy spec it cites). Do not reword here without changing the TS SDK first; +# tests/test_constants_copy.py enforces byte parity. +SESSION_ID_PARAM_DESCRIPTION = "REQUIRED on every call after your first. This MCP server associates all of your tool calls for a given task using session_id; a call that arrives without it cannot be associated with your earlier work and is treated as the start of an unrelated task, disconnected from the original goal. Omit it on your first call only — the server will issue one in the _mcp_instructions field of the result (or a trailing [MCP INSTRUCTIONS] text block) — then echo that exact value on every later call. Never invent a value, and do not issue parallel tool calls until the server has issued your session_id. One session_id covers the whole goal from start to finish: when you spawn subagents you MUST give them this same session_id, or their work is severed from yours. Without session_id, this server does not function as intended." +AGENT_ID_PARAM_DESCRIPTION = "REQUIRED on every call, including your first. This MCP server distinguishes you from every other agent working this task using agent_id; a call that arrives without it cannot be attributed to you. Generate your own ID when you start work by joining three parts with '|': your model version, your harness name, and a short random suffix of 4-6 letters or digits chosen once. Example: opus-4.80-1m|claude-code|k3n9x. Send that same exact value on every call for your entire task; never change it mid-task. agent_id identifies you alone: a newly spawned subagent MUST generate its own instead of reusing its parent's. Without agent_id, this server does not function as intended." +AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE = "REQUIRED on every call, including your first. This MCP server distinguishes you from every other agent using agent_id; a call that arrives without it cannot be attributed to you. Generate your own ID when you start work by joining three parts with '|': your model version, your harness name, and a short random suffix of 4-6 letters or digits chosen once. Example: opus-4.80-1m|claude-code|k3n9x. Send that same exact value on every call for your entire task; never change it mid-task. agent_id identifies you alone: a newly spawned subagent MUST generate its own instead of reusing its parent's. Without agent_id, this server does not function as intended." +MINT_BACK_HEADER_SESSION = "[MCP INSTRUCTIONS]: session_id issued." +MINT_BACK_HEADER_INVALID = "[MCP INSTRUCTIONS]: session_id not recognized." +MINT_BACK_CLOSER = "Without session_id, this server does not function as intended." +MINT_BACK_INVALID_LINE = " The session_id you sent was not issued by this server. Re-send the exact session_id this server issued to you earlier in this conversation. Never invent a value. If this server has not issued you a session_id yet, omit the parameter and one will be issued." +MCP_INSTRUCTIONS_FIELD_DESCRIPTION = "Your handles for this task, confirmed by this MCP server on every response, and the instructions for echoing them on later calls. Read and follow." +MCP_INSTRUCTIONS_SESSION_ID_DESCRIPTION = ( + "Echo this exact value as the session_id argument on every subsequent tool call." +) +MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION = "Your agent_id as this server received it. Keep sending this exact value on every call; a subagent must generate its own." + + +def mint_back_session_line(session_id: str) -> str: + return f" session_id={session_id} — required on every subsequent tool call" + + +def mint_back_confirmed(names: list[str]) -> str: + tail = "these exact values" if len(names) > 1 else "this exact value" + return ( + f"[MCP INSTRUCTIONS]: {' and '.join(names)} confirmed. " + f"Keep sending {tail} on every call." + ) diff --git a/src/agentcat/modules/context_parameters.py b/src/agentcat/modules/context_parameters.py deleted file mode 100644 index 5aa6f2c..0000000 --- a/src/agentcat/modules/context_parameters.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Context parameter injection for MCP tools.""" - -from typing import Any - - -def add_context_parameter_to_tools( - tools: list[dict[str, Any]], custom_context_description: str -) -> list[dict[str, Any]]: - """Add context parameter to tool schemas.""" - modified_tools = [] - - for tool in tools: - # Create a copy to avoid modifying original - modified_tool = tool.copy() - - if "inputSchema" in modified_tool: - modified_tool["inputSchema"] = add_context_parameter_to_schema( - modified_tool["inputSchema"], custom_context_description - ) - - modified_tools.append(modified_tool) - - return modified_tools - - -def add_context_parameter_to_schema( - schema: dict[str, Any], custom_context_description: str -) -> dict[str, Any]: - """Add context parameter to a JSON schema.""" - # Create a copy to avoid modifying original - modified_schema = schema.copy() - - # Ensure properties exists - if "properties" not in modified_schema: - modified_schema["properties"] = {} - else: - # Deep copy properties - modified_schema["properties"] = modified_schema["properties"].copy() - - # Add context parameter - modified_schema["properties"]["context"] = { - "type": "string", - "description": custom_context_description, - } - - # Add to required fields - if "required" not in modified_schema: - modified_schema["required"] = [] - else: - # Copy required list - modified_schema["required"] = list(modified_schema["required"]) - - if "context" not in modified_schema["required"]: - modified_schema["required"].append("context") - - return modified_schema diff --git a/src/agentcat/modules/detection.py b/src/agentcat/modules/detection.py new file mode 100644 index 0000000..c124296 --- /dev/null +++ b/src/agentcat/modules/detection.py @@ -0,0 +1,191 @@ +"""Per-object server flavor classification (spec §8.1). + +Decides which adapter wraps a customer's server using only signals readable +off the object in hand: class name, defining module prefix, and attribute +presence. It never imports version-specific MCP symbols and never raises +into the customer's process. + +Two probe strengths, deliberately different: + +- ``_probe`` (presence): the name resolves, or its getter raises something + other than ``AttributeError`` — the attribute exists even when a lazy or + proxy getter is unhappy. ``hasattr`` would re-raise those, so it is never + used here. +- ``_get`` (retrieval): the value must actually come back. Used where the + classifier hands the value onward (handler tables, the wrapped lowlevel + object) — a table we cannot read is a shape we cannot adapt. + +Every ``Detection`` carries all 13 fingerprint probes (spec §8.1); for +``UNKNOWN`` shapes the fingerprint is the payload of the fleet-drift +diagnostics beacon. +""" + +from dataclasses import dataclass +from enum import Enum +from typing import Any + + +class ServerFlavor(str, Enum): + """Diagnostics-beacon wire strings; keep stable across releases.""" + + LOWLEVEL_V1 = "lowlevel-v1" + LOWLEVEL_V2 = "lowlevel-v2" + OFFICIAL_FASTMCP_V1 = "official-fastmcp-v1" + MCPSERVER_V2 = "mcpserver-v2" + COMMUNITY_V3 = "community-v3" + COMMUNITY_V4 = "community-v4" + COMMUNITY_V2_UNSUPPORTED = "community-v2-unsupported" + UNKNOWN = "unknown" + + +@dataclass +class Detection: + """``lowlevel`` is the object the adapters wrap (``_mcp_server``, + ``_lowlevel_server``, or the bare server itself); ``None`` for community + flavors (adapted via middleware) and ``UNKNOWN`` (returned untracked).""" + + flavor: ServerFlavor + lowlevel: Any | None + fingerprint: dict[str, bool] + + +_MISSING = object() + +# What the lowlevel-v2 handler-registration seam is called, best-known name +# first. It has been spelled both ways on the 2.x line — public +# ``add_request_handler`` in 2.0, private ``_add_request_handler`` on the +# development line before it — and a build that ships only the other spelling +# must not fall through to UNKNOWN and be returned untracked with no error. +# `adapters.lowlevel_v2` re-arms whichever one it finds, so this tuple is the +# single definition of that seam. +HANDLER_REGISTRATION_NAMES = ("add_request_handler", "_add_request_handler") + + +def _probe(server: Any, name: str) -> bool: + try: + getattr(server, name) + except AttributeError: + return False + except Exception: + return True + return True + + +def _get(server: Any, name: str) -> Any: + try: + return getattr(server, name) + except Exception: + return _MISSING + + +def _dir_names(server: Any) -> list[str]: + try: + return dir(server) + except Exception: + return [] + + +def _class_info(server: Any) -> tuple[str, str]: + try: + cls = type(server) + name = getattr(cls, "__name__", "") + module = getattr(cls, "__module__", "") + except Exception: + return "", "" + return ( + name if isinstance(name, str) else "", + module if isinstance(module, str) else "", + ) + + +def _fingerprint(server: Any, class_name: str) -> dict[str, bool]: + return { + "is_fastmcp_class": "FastMCP" in class_name, + "has_local_provider": _probe(server, "_local_provider"), + "has_add_middleware": _probe(server, "add_middleware"), + "has_middleware": _probe(server, "middleware"), + "has_tool_manager": _probe(server, "_tool_manager"), + "has_mcp_server_attr": _probe(server, "_mcp_server"), + "has_lowlevel_server_attr": _probe(server, "_lowlevel_server"), + "has_extensions": ( + _probe(server, "_extensions") or _probe(server, "add_extension") + ), + "has_request_state_security": _probe(server, "_request_state_security"), + "has_request_handlers": _probe(server, "request_handlers"), + "has_private_request_handlers": _probe(server, "_request_handlers"), + "has_add_request_handler": any( + _probe(server, name) for name in HANDLER_REGISTRATION_NAMES + ), + "has_request_context": _probe(server, "request_context"), + } + + +def _classify( + server: Any, class_name: str, module: str +) -> tuple[ServerFlavor, Any | None]: + is_fastmcp_class = "FastMCP" in class_name + + if module.startswith("fastmcp") and is_fastmcp_class: + # fastmcp 2.x kept the official `_tool_manager` architecture; it is + # unsupported and must win before the v3/v4 probe set looks, because + # only the module prefix separates it from official FastMCP v1. + if _probe(server, "_mcp_server") and _probe(server, "_tool_manager"): + return ServerFlavor.COMMUNITY_V2_UNSUPPORTED, None + if ( + _probe(server, "_local_provider") + and _probe(server, "add_middleware") + and _probe(server, "middleware") + and not _probe(server, "_tool_manager") + ): + if ( + _probe(server, "add_extension") + or _probe(server, "_extensions") + or _probe(server, "_request_state_security") + ): + return ServerFlavor.COMMUNITY_V4, None + return ServerFlavor.COMMUNITY_V3, None + + if module.startswith("mcp.server.fastmcp") and is_fastmcp_class: + mcp_server = _get(server, "_mcp_server") + if ( + mcp_server is not _MISSING + and mcp_server is not None + and _probe(server, "_tool_manager") + ): + return ServerFlavor.OFFICIAL_FASTMCP_V1, mcp_server + + lowlevel_server = _get(server, "_lowlevel_server") + if ( + lowlevel_server is not _MISSING + and lowlevel_server is not None + and _probe(server, "_tool_manager") + ): + return ServerFlavor.MCPSERVER_V2, lowlevel_server + + names = _dir_names(server) + # `request_context` via dir() only: on a real lowlevel v1 Server it is a + # property that raises outside a request, so it must never be evaluated. + if ( + isinstance(_get(server, "request_handlers"), dict) + and "request_context" in names + ): + return ServerFlavor.LOWLEVEL_V1, server + + if ( + isinstance(_get(server, "_request_handlers"), dict) + and any(_probe(server, name) for name in HANDLER_REGISTRATION_NAMES) + and "request_context" not in names + ): + return ServerFlavor.LOWLEVEL_V2, server + + return ServerFlavor.UNKNOWN, None + + +def detect_server(server: Any) -> Detection: + class_name, module = _class_info(server) + flavor, lowlevel = _classify(server, class_name, module) + return Detection( + flavor=flavor, + lowlevel=lowlevel, + fingerprint=_fingerprint(server, class_name), + ) diff --git a/src/agentcat/modules/event_queue.py b/src/agentcat/modules/event_queue.py index 473ab2e..a10366f 100644 --- a/src/agentcat/modules/event_queue.py +++ b/src/agentcat/modules/event_queue.py @@ -4,6 +4,7 @@ import queue import signal import os +import sys import threading import time from datetime import datetime, timezone @@ -17,14 +18,16 @@ from agentcat.modules.constants import AGENTCAT_API_URL, EVENT_ID_PREFIX from ..types import Event, UnredactedEvent -from ..utils import generate_prefixed_ksuid -from .compatibility import get_mcp_compatible_error_message +from ..utils import generate_prefixed_ksuid, get_agentcat_version from .internal import get_server_tracking_data from .logging import write_to_log from .redaction import redact_event from .sanitization import sanitize_event from .truncation import truncate_event -from .session import get_session_info, set_last_activity + +# Stamped on every event. Same value 1.x reported, resolved once at import +# instead of rebuilt per event inside a per-server session cache. +SDK_LANGUAGE = f"Python {sys.version_info.major}.{sys.version_info.minor}" class EventQueue: @@ -170,7 +173,7 @@ def _send_event(self, event: Event, retries: int = 0) -> None: ) return write_to_log( - f"Failed to send event {event.id}, retrying... [Error: {get_mcp_compatible_error_message(error)}]" + f"Failed to send event {event.id}, retrying... [Error: {error}]" ) if retries < self.max_retries: # Exponential backoff: 1s, 2s, 4s @@ -287,7 +290,16 @@ def set_event_queue(new_queue: EventQueue) -> None: def publish_event(server: Any, event: UnredactedEvent) -> None: - """Publish an event to the queue.""" + """Publish an event to the queue. + + Everything about the CALL is already on the event: the call path resolved + the actor, the client identity (design §7) and the handle tags per request + and stamped them there. This adds only what is per-SERVER or per-INSTALL — + project, server identity captured at track time, SDK language, SDK version + — and never merges anything over a field the event already carries. v1 + merged a per-server metadata cache on top of the event, which silently + overwrote the ladder's client name/version on any server that kept one. + """ if not event.duration: if event.timestamp: event.duration = int( @@ -304,23 +316,18 @@ def publish_event(server: Any, event: UnredactedEvent) -> None: ) return - session_info = get_session_info(server, data) - - # Create full event with all required fields - # Merge event data with session info - event_data = event.model_dump(exclude_none=True) - session_data = session_info.model_dump(exclude_none=True) - - # Merge data, ensuring project_id from data takes precedence - merged_data = {**event_data, **session_data} - merged_data["project_id"] = ( - data.project_id - ) # Override with tracking data's project_id + stamped = { + **event.model_dump(exclude_none=True), + "project_id": data.project_id, + "sdk_language": SDK_LANGUAGE, + "agentcat_version": get_agentcat_version(), + "server_name": data.server_name, + "server_version": data.server_version, + } full_event = UnredactedEvent( - **merged_data, + **stamped, redaction_fn=data.options.redact_sensitive_information, ) - set_last_activity(server) event_queue.add(full_event) diff --git a/src/agentcat/modules/exceptions.py b/src/agentcat/modules/exceptions.py index c540d38..6c6fc5f 100644 --- a/src/agentcat/modules/exceptions.py +++ b/src/agentcat/modules/exceptions.py @@ -1,6 +1,5 @@ """Exception tracking module for AgentCat.""" -import contextvars import linecache import os import re @@ -12,10 +11,6 @@ from agentcat.types import ChainedErrorData, ErrorData, StackFrame from agentcat.modules.constants import MAX_EXCEPTION_CHAIN_DEPTH, MAX_STACK_FRAMES -_captured_error: contextvars.ContextVar[BaseException | None] = contextvars.ContextVar( - "_captured_error", default=None -) - def capture_exception(exc: BaseException | Any) -> ErrorData: """ @@ -325,6 +320,19 @@ def is_call_tool_result(value: Any) -> bool: MCP SDK converts errors to CallToolResult format: { content: [{ type: "text", text: "error message" }], isError: true } + Both spellings of the error flag count: the official SDK renamed it + `isError` -> `is_error` in 2.x, and community FastMCP has always used the + snake_case one. Missing the rename would not fail loudly — it would record + a pydantic repr of the whole result as the error message. + + Snake case is probed FIRST, and the order is load-bearing rather than + cosmetic: FastMCP answers a camelCase attribute through a compatibility + shim that emits a `FastMCPDeprecationWarning`, so asking for `isError` + first warns on every error result any FastMCP server produces. Asking for + `is_error` first short-circuits before the shim is ever reached, and an + mcp 1.x `CallToolResult` — which has only the camelCase name — still falls + through to it. + Args: value: Value to check @@ -333,8 +341,7 @@ def is_call_tool_result(value: Any) -> bool: """ return ( value is not None - and hasattr(value, "isError") - and hasattr(value, "content") + and (hasattr(value, "is_error") or hasattr(value, "isError")) and isinstance(getattr(value, "content", None), list) ) @@ -406,19 +413,10 @@ def stringify_non_exception(value: Any) -> str: return str(value) -def store_captured_error(exc: BaseException) -> None: - """Stores exception in context variable before MCP SDK processing.""" - _captured_error.set(exc) - - -def get_captured_error() -> BaseException | None: - """Retrieves and clears stored exception from context variable.""" - exc = _captured_error.get() - if exc is not None: - _captured_error.set(None) - return exc - - -def clear_captured_error() -> None: - """Clears any stored exception from context variable.""" - _captured_error.set(None) +# The inner-tap trio that used to live here — `store_captured_error` / +# `get_captured_error` / `clear_captured_error` — was retired by Task 13.5 in +# favour of `modules.adapters._inner_tap`. It stored the exception IN a +# ContextVar, which cannot see a capture made below a task or thread boundary +# (a context is copied downward, so the child's `set` never reaches the parent) +# and has no per-call slot to close. The replacement stores a per-call cell in +# the ContextVar and writes to the cell instead; see that module's docstring. diff --git a/src/agentcat/modules/exporters/otlp.py b/src/agentcat/modules/exporters/otlp.py index 4381f3f..1975a3b 100644 --- a/src/agentcat/modules/exporters/otlp.py +++ b/src/agentcat/modules/exporters/otlp.py @@ -9,7 +9,7 @@ from ...types import Event, OTLPExporterConfig from ...modules.constants import AGENTCAT_SOURCE from ...modules.logging import write_to_log -from ...modules.session import get_agentcat_version +from ...utils import get_agentcat_version from . import Exporter from .trace_context import trace_context diff --git a/src/agentcat/modules/exporters/sentry.py b/src/agentcat/modules/exporters/sentry.py index b8b3f5b..a1df1b4 100644 --- a/src/agentcat/modules/exporters/sentry.py +++ b/src/agentcat/modules/exporters/sentry.py @@ -9,7 +9,7 @@ from ...types import Event, SentryExporterConfig from ...modules.constants import AGENTCAT_SOURCE from ...modules.logging import write_to_log -from ...modules.session import get_agentcat_version +from ...utils import get_agentcat_version from . import Exporter from .trace_context import trace_context diff --git a/src/agentcat/modules/handles.py b/src/agentcat/modules/handles.py new file mode 100644 index 0000000..84c0d01 --- /dev/null +++ b/src/agentcat/modules/handles.py @@ -0,0 +1,318 @@ +"""Explicit-handle primitives: minting, derivation, extraction, mint-back. + +Cross-SDK contract: 2026-07-28-cross-sdk-changelog.md §3-§4; TS reference +src/modules/handles.ts. Derivation golden vectors are frozen — changing them +splits customer sessions across an upgrade. +""" + +import hashlib +import inspect +import re +from dataclasses import dataclass +from typing import Any, Literal + +from agentcat.modules.constants import ( + AGENT_ID_PARAM, + AGENTCAT_TAG_AGENT_ID, + AGENTCAT_TAG_AGENT_SOURCE, + AGENTCAT_TAG_MRTR, + AGENTCAT_TAG_PROTOCOL_VERSION, + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, + MINT_BACK_CLOSER, + MINT_BACK_HEADER_INVALID, + MINT_BACK_HEADER_SESSION, + MINT_BACK_INVALID_LINE, + SESSION_ID_PARAM, + SESSION_ID_PREFIX, + mint_back_confirmed, + mint_back_session_line, +) +from agentcat.modules.logging import write_to_log +from agentcat.thirdparty.ksuid import Ksuid +from agentcat.types import AgentCatOptions +from agentcat.utils import generate_prefixed_ksuid + +_KSUID_EPOCH_MS = 1_400_000_000_000 +_DERIVE_EPOCH_MS = 1_704_067_200_000 # 2024-01-01T00:00:00Z +_YEAR_MS = 365 * 24 * 60 * 60 * 1000 + +# 27 is the KSUID string length; `ses_` is the prefix both issuing paths use. +_SESSION_ID_RE = re.compile(rf"{SESSION_ID_PREFIX}_[0-9A-Za-z]{{27}}") + +SessionSource = Literal["supplied", "minted", "hook", "invalid", "foreign"] + + +@dataclass +class HandleResolution: + # Empty string means sessionless — the event publishes with no session at + # all, which is what `invalid` and `foreign` both resolve to. The wire + # boundary turns it into null; nothing downstream sees "". + session_id: str + session_source: SessionSource + agent_id: str | None = None + agent_source: Literal["supplied"] | None = None + hook_mode: bool = False + # Whether AgentCat put its own `session_id` parameter on THIS tool. False + # in three cases: hook mode (none is injected anywhere), a tool whose + # customer schema already declared the name, and a composed + # (oneOf/allOf/anyOf) schema the injection pass skipped wholesale. Gates + # the mint-back, because a mint-back is an instruction to send + # `session_id=ses_…` on the next call — and if the tool has no such + # parameter, that instruction names a slot the agent cannot fill, or worse, + # one that belongs to the customer's domain. Telling an agent to overwrite + # it would change what the customer's tool does, which nothing AgentCat + # does may do. + # + # Deliberately NOT the same question as "may we READ the argument" — see + # `session_param_is_ours` on `resolve_handles`. They differ on the composed + # schema, which is ours to read but has no parameter to prompt for. + prompts_session_id: bool = True + + +def is_valid_session_id(value: str) -> bool: + """True only for a session ID this SDK issued. + + Both issuing paths — `new_session_id` and `derive_session_id` — satisfy + this by construction, so a value that fails was invented by the agent or + belongs to someone else. + + `fullmatch`, not `match` against a trailing `$`: Python's `$` also matches + immediately BEFORE a final newline, so the literal transcription of the TS + regex would accept `"ses_" + "a" * 27 + "\\n"` that TypeScript rejects. + """ + return _SESSION_ID_RE.fullmatch(value) is not None + + +def new_session_id() -> str: + return generate_prefixed_ksuid(SESSION_ID_PREFIX) + + +def derive_session_id(id: str, project_id: str | None = None) -> str: + # NOTE: does not trim — callers trim (resolve_handles trims hook output). + payload_input = f"{id}:{project_id}" if project_id else id + digest = hashlib.sha256(payload_input.encode("utf-8")).digest() + ts_ms = _DERIVE_EPOCH_MS + (int.from_bytes(digest[0:4], "big") % _YEAR_MS) + ts_field = (ts_ms - _KSUID_EPOCH_MS) // 1000 + raw = ts_field.to_bytes(4, "big") + digest[4:20] + return f"{SESSION_ID_PREFIX}_{Ksuid.from_bytes(raw)}" + + +def extract_handle(arguments: Any, name: str) -> str | None: + if not isinstance(arguments, dict): + return None + value = arguments.get(name) + if isinstance(value, str) and value.strip(): + return value.strip() + return None + + +async def resolve_handles( + arguments: Any, + options: AgentCatOptions, + project_id: str | None, + request: Any, + extra: Any, + injected: frozenset[str] | None = None, + session_param_is_ours: bool = True, +) -> HandleResolution: + """Resolve this call's session and agent handles. Never raises. + + Two independent questions, deliberately not the same gate: + + `session_param_is_ours` — may we READ `arguments["session_id"]`? False only + when the customer's own schema declared that name, which `callpath` reads + off `AgentCatData.declared_session_params`. Reading a parameter they own + would sever the agent's real session AND route a customer-domain + identifier into `Event.session_id`, a field the customer's redaction hook + is not allowed to touch. + + `injected` — which parameter names did AgentCat actually put on THIS tool + (`injection.injected_parameter_names`)? None means "assume ours", the same + fallback the strip takes when no registry exists. It drives `agent_id` + reads and `prompts_session_id`, the mint-back gate. + + They diverge on exactly one shape: a composed (oneOf/allOf/anyOf) schema, + where AgentCat injected nothing but the customer declared nothing either. + That tool is ours to read — an echoed valid ID still correlates — but has + no parameter to prompt for, so it gets no mint-back. + """ + hook = options.resolve_session_id + prompts_session_id = injected is None or SESSION_ID_PARAM in injected + ours_agent_id = injected is None or AGENT_ID_PARAM in injected + agent_id = ( + extract_handle(arguments, AGENT_ID_PARAM) + if options.enable_agent_tracking and ours_agent_id + else None + ) + agent_source: Literal["supplied"] | None = "supplied" if agent_id else None + + if callable(hook): + try: + value = hook(request, extra) + if inspect.isawaitable(value): + value = await value + except Exception as e: # hook errors mint silently + write_to_log(f"Warning: resolve_session_id hook raised: {e}") + value = None + if isinstance(value, str) and value.strip(): + return HandleResolution( + derive_session_id(value.strip(), project_id), + "hook", + agent_id, + agent_source, + hook_mode=True, + prompts_session_id=False, + ) + return HandleResolution( + new_session_id(), + "minted", + agent_id, + agent_source, + hook_mode=True, + prompts_session_id=False, + ) + + if not session_param_is_ours: + # The tool declares its own `session_id`. Nothing in the arguments is + # ours to read, and minting one per call would manufacture a phantom + # session per call — noise shaped like data. Sessionless is the honest + # signal, and it resolves the moment the customer adopts + # `resolve_session_id`: hook mode reads no arguments at all, so their + # parameter stays entirely theirs. + return HandleResolution( + "", "foreign", agent_id, agent_source, prompts_session_id=False + ) + + supplied = extract_handle(arguments, SESSION_ID_PARAM) + if supplied: + if is_valid_session_id(supplied): + return HandleResolution( + supplied, + "supplied", + agent_id, + agent_source, + prompts_session_id=prompts_session_id, + ) + # Not an ID this server issued. Publish sessionless rather than adopt + # it: `Event.session_id` is exempt from both redaction hooks, so an + # agent's hallucination — or an auth token a client auto-populated + # into a parameter that happens to be named `session_id` — would reach + # every downstream exporter unredactable. + return HandleResolution( + "", "invalid", agent_id, agent_source, prompts_session_id=prompts_session_id + ) + return HandleResolution( + new_session_id(), + "minted", + agent_id, + agent_source, + prompts_session_id=prompts_session_id, + ) + + +def _echoes_session_id(res: HandleResolution) -> bool: + """Whether the agent has an AgentCat `session_id` value to echo back. + + Three ways to have none: hook mode and the no-parameter cases collapsed + into `prompts_session_id`, plus `invalid` — where the parameter is ours + but there is no value to confirm. That branch corrects the agent rather + than issuing a replacement, so naming a `session_id` would be a lie. + """ + return ( + res.prompts_session_id and not res.hook_mode and res.session_source != "invalid" + ) + + +def build_mint_back_text(res: HandleResolution) -> str | None: + if res.hook_mode or not res.prompts_session_id: + return None + if res.session_source == "minted": + return "\n".join( + [ + MINT_BACK_HEADER_SESSION, + mint_back_session_line(res.session_id), + MINT_BACK_CLOSER, + ] + ) + if res.session_source == "invalid": + # No replacement is handed out. An agent that sent something was + # usually already issued a good ID, and giving it a second one splits a + # session that was never split. The closing sentence of + # MINT_BACK_INVALID_LINE is the way out for the agent that was never + # issued one: omit the parameter and take the `minted` branch. + return "\n".join( + [MINT_BACK_HEADER_INVALID, MINT_BACK_INVALID_LINE, MINT_BACK_CLOSER] + ) + return None + + +def build_structured_mint_back(res: HandleResolution) -> dict[str, Any] | None: + """The persistent handle state mirrored into `structuredContent`. + + Unlike `build_mint_back_text` (mint announcements only), this is present + on EVERY response, so an agent can re-read its own handles mid-session. + Handles the agent cannot echo are never named. + + Suppression is per-HANDLE, not per-response: a `session_id` collision skips + only `session_id`. `agent_id` is a separate injection and still landed in + that tool's schema, so it is still ours to confirm. Dropping the whole + mirror would withhold a handle AgentCat issued purely because a + neighbouring one belongs to the customer. + """ + echoes = _echoes_session_id(res) + names: list[str] = [] + if echoes: + names.append(SESSION_ID_PARAM) + if res.agent_id: + names.append(AGENT_ID_PARAM) + text = build_mint_back_text(res) + # `not names` alone would drop the `invalid` correction whenever no + # agent_id is in play — the one branch that has something to say and + # nothing to echo. + if not names and not text: + return None + mint: dict[str, Any] = {} + if echoes: + mint[SESSION_ID_PARAM] = res.session_id + if res.agent_id: + mint[AGENT_ID_PARAM] = res.agent_id + mint["instructions"] = text or mint_back_confirmed(names) + return mint + + +def mirror_into_structured_content( + sc: Any, mint: dict[str, Any] +) -> dict[str, Any] | None: + if not isinstance(sc, dict) or MCP_INSTRUCTIONS_KEY in sc: + return None + return {**sc, MCP_INSTRUCTIONS_KEY: mint} + + +def _clamp_tag_value(value: str) -> str: + """The value rule `validate_tags` enforces, applied to an SDK tag. + + SDK tags are merged AFTER `validate_tags` — deliberately, so they win on + collision and ride outside the customer's 50-tag cap (§6.5) — which also + means nothing else checks them. Both values here come from the CLIENT: + `agent_id` is whatever the agent typed into a string parameter, and the + protocol version is read off untrusted request meta. Neither may put an + unbounded, newline-bearing string on the wire. + """ + return value.replace("\r", " ").replace("\n", " ")[:200] + + +def build_handle_tags( + res: HandleResolution, + protocol_version: str | None = None, + mrtr: str | None = None, +) -> dict[str, str]: + tags: dict[str, str] = {AGENTCAT_TAG_SESSION_SOURCE: res.session_source} + if res.agent_id and res.agent_source: + tags[AGENTCAT_TAG_AGENT_ID] = _clamp_tag_value(res.agent_id) + tags[AGENTCAT_TAG_AGENT_SOURCE] = res.agent_source + if protocol_version: + tags[AGENTCAT_TAG_PROTOCOL_VERSION] = _clamp_tag_value(protocol_version) + if mrtr: + tags[AGENTCAT_TAG_MRTR] = mrtr + return tags diff --git a/src/agentcat/modules/identify.py b/src/agentcat/modules/identify.py index 9f002fa..0bcfff3 100644 --- a/src/agentcat/modules/identify.py +++ b/src/agentcat/modules/identify.py @@ -1,42 +1,33 @@ -from datetime import datetime, timezone +from typing import Any -from agentcat.modules import event_queue -from agentcat.modules.internal import get_server_tracking_data from agentcat.modules.logging import write_to_log -from agentcat.types import EventType, UnredactedEvent, UserIdentity +from agentcat.types import AgentCatData, UserIdentity -def identify_session(server, request: any, context: any) -> UserIdentity | None: - """Run the configured identify hook and publish an `agentcat:identify` event. +def resolve_identity( + data: AgentCatData | None, request: Any, extra: Any +) -> UserIdentity | None: + """Run the configured identify hook and return its UserIdentity. - Returns the resulting UserIdentity, or None if no hook is configured, the - hook raises, or it returns a non-UserIdentity value. + v1 published a standalone `agentcat:identify` event and cached the result + for the connection's lifetime. v2 publishes one event per tool call and + stamps the actor onto it, so identity resolution is pure and runs on every + call. Never raises — a customer hook that blows up yields an anonymous + call, not a failed one. """ - data = get_server_tracking_data(server) - if not data or not data.options or not data.options.identify: return None try: - identify_result = data.options.identify(request, context) - if not identify_result or not isinstance(identify_result, UserIdentity): - write_to_log( - "User identification function did not return a valid UserIdentity " - f"instance. Received type: {type(identify_result).__name__}" - ) - return None - - event = UnredactedEvent( - session_id=data.session_id, - timestamp=datetime.now(timezone.utc), - event_type=EventType.AGENTCAT_IDENTIFY.value, - identify_actor_given_id=identify_result.user_id, - identify_actor_name=identify_result.user_name, - identify_data=identify_result.user_data or {}, - ) - event_queue.publish_event(server, event) - - return identify_result + result = data.options.identify(request, extra) except Exception as e: write_to_log(f"Error occurred during user identification: {e}") return None + + if not result or not isinstance(result, UserIdentity): + write_to_log( + "User identification function did not return a valid UserIdentity " + f"instance. Received type: {type(result).__name__}" + ) + return None + return result diff --git a/src/agentcat/modules/injection.py b/src/agentcat/modules/injection.py new file mode 100644 index 0000000..fb0842b --- /dev/null +++ b/src/agentcat/modules/injection.py @@ -0,0 +1,381 @@ +"""Pure schema-injection pipeline: handles, context, and strip registries. + +The pipeline is pure and deterministic: (adapter's deep-copied tool schemas, +options) -> schemas mutated in place + registries recording exactly what was +injected, so rebuild-on-demand can reproduce the registries on a fresh +instance that never served tools/list. Mirrors the TS SDK's +handle-injection.ts and context-parameters.ts as composed by +listWrap.buildInjectedList. + +Two passes over the tools, in order: + +1. Handle pass — session_id/agent_id input params plus the _mcp_instructions + outputSchema extension. Runs only when at least one handle is injectable + (prompted-mode tracing -> session_id, agent tracking -> agent_id); when + neither is, the pass is skipped wholesale and schemas keep their original + shape (no normalization, additionalProperties untouched). +2. Context pass — the optional context param, independent of the handle + flags. get_more_tools is exempt (its bespoke context is a real + parameter); it is NOT exempt from handles, since its calls publish + events. + +Resulting property order: customer params, session_id, agent_id, context. +session_id is never required — omission is the minting signal. agent_id and +context are both appended to required; that is client-side compliance +only, since callWrap tolerates either being absent, and it is the only +enforcement an injected parameter has. +""" + +from collections.abc import Iterable +from dataclasses import dataclass, field +from typing import Any + +from agentcat.modules.constants import ( + AGENT_ID_PARAM, + AGENT_ID_PARAM_DESCRIPTION, + AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE, + CONTEXT_PARAM, + GET_MORE_TOOLS_NAME, + MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION, + MCP_INSTRUCTIONS_FIELD_DESCRIPTION, + MCP_INSTRUCTIONS_KEY, + MCP_INSTRUCTIONS_SESSION_ID_DESCRIPTION, + SESSION_ID_PARAM, + SESSION_ID_PARAM_DESCRIPTION, +) +from agentcat.modules.logging import write_to_log +from agentcat.types import AgentCatOptions + +_COMPOSED_KEYS = ("oneOf", "allOf", "anyOf") +_ALL_INJECTABLE = (SESSION_ID_PARAM, AGENT_ID_PARAM, CONTEXT_PARAM) + + +@dataclass +class ToolSpec: + """One listed tool as the adapter hands it to the pipeline. + + The schemas are the adapter's deep copies of the customer's originals; + the pipeline mutates them in place. + """ + + name: str + input_schema: dict[str, Any] + output_schema: dict[str, Any] | None = None + + +@dataclass +class InjectionResult: + """What the pipeline injected, keyed for later stripping. + + injected_params has an entry for EVERY tool seen (possibly empty), so + the strip fallback applies only to tools never seen in any listing. + output_injected lists tools whose outputSchema gained _mcp_instructions. + declared_session_params lists tools whose OWN schema declared + `session_id`; see `build_injected_schemas` for why that is a separate + signal rather than "absent from injected_params". + """ + + injected_params: dict[str, set[str]] + output_injected: set[str] + declared_session_params: set[str] = field(default_factory=set) + + +def mcp_instructions_schema_property( + include_session_id: bool, include_agent_id: bool +) -> dict[str, Any]: + """Build a fresh _mcp_instructions outputSchema fragment. + + Sub-properties mirror the modes — no session_id in hook mode, no agent_id + when tracking is off — so the copy never references a parameter the + agent cannot see. `instructions` is unconditional. + """ + sub_properties: dict[str, Any] = {} + if include_session_id: + sub_properties[SESSION_ID_PARAM] = { + "type": "string", + "description": MCP_INSTRUCTIONS_SESSION_ID_DESCRIPTION, + } + if include_agent_id: + sub_properties[AGENT_ID_PARAM] = { + "type": "string", + "description": MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION, + } + sub_properties["instructions"] = {"type": "string"} + return { + "type": "object", + "description": MCP_INSTRUCTIONS_FIELD_DESCRIPTION, + "properties": sub_properties, + } + + +def _inject_param( + tool_name: str, + schema: dict[str, Any], + name: str, + description: str, + required: bool, + entry: set[str], +) -> None: + """Add one string param, honoring collisions and the required array.""" + properties = schema.setdefault("properties", {}) + if name in properties: + write_to_log( + f"WARN: Tool \"{tool_name}\" already has '{name}' parameter. " + f"Skipping {name} injection." + ) + return + properties[name] = {"type": "string", "description": description} + if required: + existing = schema.get("required") + if isinstance(existing, list): + if name not in existing: + existing.append(name) + else: + schema["required"] = [name] + entry.add(name) + + +def _report_session_conflict(tool_name: str, reported: set[str] | None) -> None: + """Tell the customer their `session_id` collides, once per tool. + + ERROR, not WARN: unlike the other two collisions, this one costs them + correlation on that tool entirely. The pipeline reruns on every + `tools/list`, so an undeduped log would repeat for the life of the + process. Copy is byte-parallel with the TS SDK's handle-injection.ts. + """ + if reported is not None: + if tool_name in reported: + return + reported.add(tool_name) + write_to_log( + f'ERROR: Tool "{tool_name}" already declares a ' + f"'{SESSION_ID_PARAM}' parameter. AgentCat will not inject its own, " + "and calls to this tool are published without a session, so they " + "cannot be correlated. Your parameter is untouched and still reaches " + "your handler. If you already manage sessions, pass a " + "resolve_session_id hook to track() — AgentCat will derive its " + f"session from your identifier and stop injecting {SESSION_ID_PARAM} " + "entirely." + ) + + +def _add_handle_parameters( + tool: ToolSpec, + inject_session_id: bool, + inject_agent_id: bool, + result: InjectionResult, + reported_conflicts: set[str] | None = None, +) -> None: + """Inject session_id/agent_id and extend the outputSchema for one tool.""" + schema = tool.input_schema + entry = result.injected_params[tool.name] + declares_session_id = SESSION_ID_PARAM in (schema.get("properties") or {}) + if any(key in schema for key in _COMPOSED_KEYS): + # Injection is skipped, but ownership still has to be recorded: a + # schema that composes AND declares session_id at its root is the + # customer's parameter, not ours to read at call time. (Only the root + # bag is visible here — a session_id nested inside a branch is + # unreachable, the same limitation the injection itself has.) + if inject_session_id and declares_session_id: + result.declared_session_params.add(tool.name) + _report_session_conflict(tool.name, reported_conflicts) + write_to_log( + f'WARN: Tool "{tool.name}" has complex schema (oneOf/allOf/anyOf). ' + "Skipping handle injection." + ) + return + if not schema: + # In-place normalization: the adapter's dict object must survive. + schema["type"] = "object" + schema["properties"] = {} + schema["required"] = [] + schema.setdefault("properties", {}) + if schema.get("additionalProperties") is False: + del schema["additionalProperties"] + + if inject_session_id: + if declares_session_id: + # The customer owns this name on this tool. Record it so call-time + # resolution never reads their value as an AgentCat handle. + result.declared_session_params.add(tool.name) + _report_session_conflict(tool.name, reported_conflicts) + else: + _inject_param( + tool.name, + schema, + SESSION_ID_PARAM, + SESSION_ID_PARAM_DESCRIPTION, + False, + entry, + ) + if inject_agent_id: + # Hook mode has no session_id param anywhere; never reference one the + # agent cannot see. + description = ( + AGENT_ID_PARAM_DESCRIPTION + if inject_session_id + else AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE + ) + _inject_param(tool.name, schema, AGENT_ID_PARAM, description, True, entry) + + _extend_output_schema(tool, inject_session_id, inject_agent_id, result) + + +def _extend_output_schema( + tool: ToolSpec, + inject_session_id: bool, + inject_agent_id: bool, + result: InjectionResult, +) -> None: + """Declare the optional _mcp_instructions property on a plain-object + outputSchema so schema-validating clients accept the mirrored field. + + Never added to required. Composed schemas have no single properties bag + to extend and are skipped (mint-back stays content-only), same policy as + the input side. + """ + schema = tool.output_schema + if not isinstance(schema, dict): + return + if any(key in schema for key in _COMPOSED_KEYS): + write_to_log( + f'WARN: Tool "{tool.name}" has complex outputSchema ' + f"(oneOf/allOf/anyOf). Skipping {MCP_INSTRUCTIONS_KEY} injection; " + "mint-back stays content-only for this tool." + ) + return + properties = schema.setdefault("properties", {}) + if MCP_INSTRUCTIONS_KEY in properties: + write_to_log( + f'WARN: Tool "{tool.name}" already declares ' + f"'{MCP_INSTRUCTIONS_KEY}' in outputSchema. Skipping injection." + ) + return + properties[MCP_INSTRUCTIONS_KEY] = mcp_instructions_schema_property( + inject_session_id, inject_agent_id + ) + result.output_injected.add(tool.name) + + +def _add_context_parameter(tool: ToolSpec, description: str, entry: set[str]) -> None: + """Inject the context param for one tool, appended to `required`. + + Required is the existing behavior — both v1 paths appended it + (`overrides/official/monkey_patch.py` and the retired + `modules/context_parameters.py`, on `bb1e9bc`) and the TS SDK still does + (`context-parameters.ts`) — and it is the only enforcement + there is. Nothing server-side rejects a call that omits `context`; a + schema-validating client refusing to send one is the whole mechanism, the + same argument the migration guide makes for `agent_id`. Optional `context` + means agents quietly stop supplying it and `user_intent` coverage decays + with nothing to show for it. + + `session_id` is the deliberate exception (never required): omitting it is how + an agent signals "mint me one". + """ + schema = tool.input_schema + properties = schema.get("properties") + if isinstance(properties, dict) and CONTEXT_PARAM in properties: + write_to_log( + f"WARN: Tool \"{tool.name}\" already has '{CONTEXT_PARAM}' " + "parameter. Skipping context injection." + ) + return + if any(key in schema for key in _COMPOSED_KEYS): + write_to_log( + f'WARN: Tool "{tool.name}" has complex schema (oneOf/allOf/anyOf). ' + "Skipping context injection." + ) + return + # TS-faithful (context-parameters.ts): the context injector drops + # additionalProperties: false itself, so a schema the (skipped) handle + # pass never normalized still admits the injected param. + if schema.get("additionalProperties") is False: + del schema["additionalProperties"] + _inject_param(tool.name, schema, CONTEXT_PARAM, description, True, entry) + + +def build_injected_schemas( + tools: list[ToolSpec], + options: AgentCatOptions, + reported_conflicts: set[str] | None = None, +) -> InjectionResult: + """Run both injection passes over the listed tools, in place. + + Deterministic and config-derived: identical (tools, options) inputs yield + identical schemas and registries. `reported_conflicts` is the only + exception — a per-server set that suppresses repeat `session_id` collision + reports across successive listings, and the only thing here that carries + state between calls. + + `declared_session_params` is a POSITIVE signal — "the customer's schema + declared this name" — not the negation of `injected_params`. The two are + not complements: a composed schema gets an entry in `injected_params` + that stays empty, because the whole pass is skipped for it. Reading + ownership off that emptiness would classify every composed-schema tool as + the customer's and publish it sessionless, when in fact nobody declared + the name and the tool is ours to correlate exactly as before. + """ + inject_session_id = options.enable_tracing and options.resolve_session_id is None + inject_agent_id = options.enable_tracing and options.enable_agent_tracking + injected_params: dict[str, set[str]] = {tool.name: set() for tool in tools} + result = InjectionResult(injected_params=injected_params, output_injected=set()) + + # Handle pass first: property order is customer -> session_id -> agent_id + # -> context. The output-schema extension lives inside this pass, so it + # is gated with it (handle-injection.ts:59). + if inject_session_id or inject_agent_id: + for tool in tools: + _add_handle_parameters( + tool, inject_session_id, inject_agent_id, result, reported_conflicts + ) + if options.enable_tool_call_context: + for tool in tools: + if tool.name == GET_MORE_TOOLS_NAME: + continue + _add_context_parameter( + tool, + options.custom_context_description, + injected_params[tool.name], + ) + return result + + +def injected_parameter_names( + tool_name: str, registry: dict[str, set[str]] | None +) -> frozenset[str]: + """The parameter names AgentCat injected into `tool_name`. + + With a registry, a listed tool reports exactly its recorded entry and an + unlisted tool reports nothing (it was never advertised through the + pipeline). Without one (tools/call before any tools/list, and the rebuild + failed) fall back to all three names — except get_more_tools' bespoke + context, which is a real parameter. + + Single source of truth for both consumers, deliberately: what + `strip_injected_arguments` removes before the customer's handler runs is + exactly what the call path may read as an AgentCat handle. Split the two + and a customer's OWN `session_id` parameter — which the injection pass + correctly skipped, and the strip correctly spares — gets consumed as the + analytics handle anyway, collapsing every call to that tool into one task + and putting a customer-domain identifier into `session_id`, a field the + customer's redaction hook is not allowed to touch. + """ + if registry is not None: + return frozenset(registry.get(tool_name, ())) + if tool_name == GET_MORE_TOOLS_NAME: + return frozenset((SESSION_ID_PARAM, AGENT_ID_PARAM)) + return frozenset(_ALL_INJECTABLE) + + +def strip_injected_arguments( + tool_name: str, + arguments: dict[str, Any], + registry: dict[str, set[str]] | None, +) -> dict[str, Any]: + """Return a new dict with ONLY the params AgentCat injected removed.""" + names: Iterable[str] = injected_parameter_names(tool_name, registry) + cleaned = dict(arguments) + for name in names: + cleaned.pop(name, None) + return cleaned diff --git a/src/agentcat/modules/internal.py b/src/agentcat/modules/internal.py index 9884ecf..8f6242c 100644 --- a/src/agentcat/modules/internal.py +++ b/src/agentcat/modules/internal.py @@ -2,11 +2,14 @@ import inspect import weakref -from datetime import datetime, timezone -from typing import Any, Dict, List, Optional +from typing import Any, Dict, Optional -from ..types import EventType, AgentCatData, ToolRegistration, UnredactedEvent -from .compatibility import is_official_fastmcp_server +from ..types import AgentCatData, UnredactedEvent + +# The classifier's own presence probe, shared rather than copied — see +# `_get_server_key`. detection.py imports nothing from this module, so this +# does not close a cycle. +from .detection import _probe as _attribute_present from .logging import write_to_log from .validation import validate_tags @@ -15,15 +18,58 @@ weakref.WeakKeyDictionary() ) -# Global storage for original unpatched methods (keyed by tool_manager or handler id) -# This is global because tool managers might be shared between servers -_original_methods: Dict[str, Any] = {} - def _get_server_key(server: Any) -> Any: - """Get the canonical key for a server (handles FastMCP vs low-level).""" - if is_official_fastmcp_server(server): - return server._mcp_server + """The object a server's tracking data is stored under. + + ``track()`` installs the adapter on the LOWLEVEL server for both official + facades — an ``mcp.server.fastmcp.FastMCP``'s ``_mcp_server`` and an + ``MCPServer``'s ``_lowlevel_server`` — and stores the data there, so a + lookup holding the facade has to make the same hop. Without it, + ``publish_custom_event(mcpserver, ...)`` looked up an object nothing was + ever filed under and dropped the event as "not a tracked server". + + Applies detection.py's ``OFFICIAL_FASTMCP_V1`` and ``MCPSERVER_V2`` rules + inline rather than calling ``detect_server``: this runs on every request, + and a 13-probe sweep to answer one question is not worth paying for. Both + rules are reproduced in full — class name, module prefix, a non-None inner + server, and a ``_tool_manager``. The ``_tool_manager`` half is also what + keeps a community FastMCP — which is tracked on ITSELF — out of both + branches. + + The two probe strengths are the classifier's, not lookalikes, because the + difference decides where data lands. ``_tool_manager`` is a PRESENCE test + and reuses ``detection._probe`` itself: an attribute that exists but whose + lazy or proxy getter raises, or that holds ``None``, still means "this is a + facade". Reading it with ``getattr(..., None) is not None`` instead looked + like a harmless tightening and was not — it made this function classify a + facade the classifier calls ``MCPSERVER_V2`` as an ordinary server, so + ``track()`` filed the data under ``_lowlevel_server`` while every later + lookup keyed on the facade. That silent lost lookup is the exact bug this + function exists to prevent, so the predicate is shared rather than + re-spelled. + + The inner server is a RETRIEVAL test, matching detection's ``_get``, and + ``is not None`` rather than truthiness: a facade whose ``_mcp_server`` + defines ``__bool__`` or ``__len__`` falsily is still the object ``track()`` + filed the data under. + """ + try: + cls = type(server) + module = getattr(cls, "__module__", "") + is_official_fastmcp = "FastMCP" in getattr( + cls, "__name__", "" + ) and module.startswith("mcp.server.fastmcp") + has_tool_manager = _attribute_present(server, "_tool_manager") + if is_official_fastmcp and has_tool_manager: + mcp_server = getattr(server, "_mcp_server", None) + if mcp_server is not None: + return mcp_server + lowlevel = getattr(server, "_lowlevel_server", None) + if lowlevel is not None and has_tool_manager: + return lowlevel + except Exception: + pass return server @@ -50,76 +96,9 @@ def reset_server_tracking_data(server: Any) -> None: def reset_all_tracking_data() -> None: """Reset all server tracking data (mainly for testing).""" _server_data_map.clear() - _original_methods.clear() write_to_log("Reset all server tracking data") - -# Dynamic tracking helper methods -def register_tool(server: Any, name: str) -> None: - """Register a tool in the server's tracking system.""" - data = get_server_tracking_data(server) - if data and name not in data.tool_registry: - data.tool_registry[name] = ToolRegistration( - name=name, registered_at=datetime.now(timezone.utc) - ) - write_to_log(f"Registered tool '{name}'") - - -def mark_tool_tracked(server: Any, name: str) -> None: - """Mark a tool as being tracked by AgentCat for this server.""" - data = get_server_tracking_data(server) - if data and name in data.tool_registry: - data.tool_registry[name].tracked = True - data.tool_registry[name].wrapped = True - data.wrapped_tools.add(name) - - -def is_tool_tracked(server: Any, name: str) -> bool: - """Check if a tool is already being tracked for this server.""" - data = get_server_tracking_data(server) - return data and name in data.wrapped_tools - - -def get_untracked_tools(server: Any) -> List[str]: - """Get list of tools that aren't tracked yet for this server.""" - data = get_server_tracking_data(server) - if not data: - return [] - return [name for name, reg in data.tool_registry.items() if not reg.tracked] - - -def discover_new_tools(server: Any, tools: List[Any]) -> List[str]: - """Discover tools that weren't previously known for this server.""" - data = get_server_tracking_data(server) - if not data: - return [] - - new_tools = [] - for tool in tools: - if tool.name not in data.tool_registry: - register_tool(server, tool.name) - new_tools.append(tool.name) - return new_tools - - -# Original methods storage (global, not per-server) -def store_original_method(key: str, method: Any) -> None: - """Store an original unpatched method.""" - if key not in _original_methods: - _original_methods[key] = method - - -def get_original_method(key: str) -> Optional[Any]: - """Get an original unpatched method.""" - return _original_methods.get(key) - - -def get_original_methods() -> Dict[str, Any]: - """Get the global original methods storage.""" - return _original_methods - - async def resolve_event_tags( data: AgentCatData, request: Any, extra: Any ) -> Optional[Dict[str, str]]: @@ -190,33 +169,3 @@ async def attach_event_metadata( properties = await resolve_event_properties(data, request, extra) if properties: event.properties = properties - - -def get_tool_timeline(server: Any) -> List[Dict[str, Any]]: - """Get a timeline of tool registrations for debugging. - - Args: - server: MCP server instance - - Returns: - List of tool registration events sorted by time - """ - data = get_server_tracking_data(server) - if not data: - return [] - timeline = [] - - for name, reg in data.tool_registry.items(): - timeline.append( - { - "name": name, - "registered_at": reg.registered_at.isoformat(), - "tracked": reg.tracked, - "wrapped": reg.wrapped, - } - ) - - # Sort by registration time - timeline.sort(key=lambda x: x["registered_at"]) - - return timeline diff --git a/src/agentcat/modules/overrides/community/monkey_patch.py b/src/agentcat/modules/overrides/community/monkey_patch.py deleted file mode 100644 index c7f8106..0000000 --- a/src/agentcat/modules/overrides/community/monkey_patch.py +++ /dev/null @@ -1,201 +0,0 @@ -"""Monkey-patching implementation for community FastMCP servers. - -This module patches community FastMCP servers to intercept tool operations -and add AgentCat tracking capabilities. -""" - -from datetime import datetime, timezone -from typing import Any - -from mcp.types import CallToolRequest -from mcp import ServerResult - -from agentcat.modules import event_queue -from agentcat.modules.compatibility import is_mcp_error_response -from agentcat.modules.exceptions import capture_exception -from agentcat.modules.identify import identify_session -from agentcat.modules.internal import attach_event_metadata, get_server_tracking_data -from agentcat.modules.logging import write_to_log -from agentcat.modules.request_extra import params_with_extra -from agentcat.modules.session import ( - get_client_info_from_request_context, - get_server_session_id, -) -from agentcat.types import EventType, UnredactedEvent - -from ..mcp_server import override_lowlevel_mcp_server_minimal, safe_request_context - - -def patch_community_fastmcp(server: Any) -> None: - """Main entry point for patching community FastMCP servers. - - This function: - 1. Patches the tool manager to add context parameters to tools - 2. Overrides the call_tool handler for tracking and context removal - 3. Sets up minimal overrides for other MCP events - """ - try: - # First, patch the tool manager for context injection and tool tracking - from .tool_manager import patch_community_fastmcp_tool_manager - patch_community_fastmcp_tool_manager(server) - - # Get the low-level MCP server - lowlevel_server = server._mcp_server - data = get_server_tracking_data(lowlevel_server) - - if not data: - write_to_log("No tracking data found for community FastMCP server") - return - - # Patch _get_cached_tool_definition to remove context from validation - original_get_cached_tool = lowlevel_server._get_cached_tool_definition - - async def patched_get_cached_tool_definition(tool_name: str): - """Get tool definition with context removed for validation.""" - # Get the original tool definition - tool = await original_get_cached_tool(tool_name) - - if tool and data.options.enable_tool_call_context and tool_name != "get_more_tools": - # Create a copy of the tool to avoid modifying the cache - import copy - tool_copy = copy.deepcopy(tool) - - # Remove context from the schema for validation - if hasattr(tool_copy, "inputSchema") and tool_copy.inputSchema: - if "properties" in tool_copy.inputSchema: - if "context" in tool_copy.inputSchema["properties"]: - # Remove context from properties - del tool_copy.inputSchema["properties"]["context"] - - # Remove context from required if present - if "required" in tool_copy.inputSchema and isinstance(tool_copy.inputSchema["required"], list): - if "context" in tool_copy.inputSchema["required"]: - tool_copy.inputSchema["required"].remove("context") - - write_to_log(f"Removed context from validation schema for tool {tool_name}") - return tool_copy - - return tool - - # Apply the patched method - lowlevel_server._get_cached_tool_definition = patched_get_cached_tool_definition - write_to_log("Patched _get_cached_tool_definition for community FastMCP") - - # Override the call_tool handler to handle context removal and tracking - original_call_tool_handler = lowlevel_server.request_handlers.get(CallToolRequest) - - if not original_call_tool_handler: - write_to_log("No original call_tool handler found") - return - - async def wrapped_call_tool_handler(request: CallToolRequest) -> ServerResult: - """Intercept call_tool requests to handle context and tracking.""" - tool_name = request.params.name - arguments = dict(request.params.arguments) if request.params.arguments else {} - - # Get request context for session tracking - request_context = safe_request_context(lowlevel_server) - session_id = get_server_session_id(lowlevel_server) - - # Handle session identification - try: - client_name, client_version = get_client_info_from_request_context(lowlevel_server, request_context) - identity = identify_session(lowlevel_server, request, request_context) - except Exception as e: - client_name, client_version = None, None - identity = None - write_to_log(f"Non-critical error in session handling: {e}") - - # Extract user intent from context parameter - user_intent = None - if tool_name == "get_more_tools": - # get_more_tools has its own context parameter that serves as user intent - user_intent = arguments.get("context", None) - elif data.options.enable_tool_call_context: - # For other tools, extract user intent when context injection is enabled - user_intent = arguments.get("context", None) - - # Create tracking event - event = UnredactedEvent( - session_id=session_id, - timestamp=datetime.now(timezone.utc), - parameters=params_with_extra( - {"name": tool_name, "arguments": arguments}, - request_context, - ), - event_type=EventType.MCP_TOOLS_CALL.value, - resource_name=tool_name, - user_intent=user_intent, - identify_actor_given_id=identity.user_id if identity else None, - identify_actor_name=identity.user_name if identity else None, - identify_data=identity.user_data if identity else None, - client_name=client_name, - client_version=client_version, - ) - await attach_event_metadata(event, data, request, request_context) - - try: - # Handle get_more_tools specially - don't intercept for community FastMCP - # Let it go through the normal tool handler which will return a string - if tool_name == "get_more_tools": - # Just track the event but let the tool execute normally - # The tool function itself returns a string which is what community FastMCP expects - pass # Fall through to call original handler - elif data.options.enable_tool_call_context: - # Remove context from arguments before calling other tools - # Create a new request with modified arguments - modified_args = arguments.copy() - modified_args.pop("context", None) - - # Modify the request in place since we can't create a new one easily - request.params.arguments = modified_args - - # Call original handler with potentially modified request - result = await original_call_tool_handler(request) - - # Check for errors - is_error, error_message = is_mcp_error_response(result) - event.is_error = is_error - # Use full exception capture if there's an error - if is_error: - event.error = capture_exception(result) - else: - event.error = None - event.response = result.model_dump() if result else None - - return result - - except Exception as e: - write_to_log(f"Error in wrapped_call_tool_handler: {e}") - event.is_error = True - # Use full exception capture with stack trace - try: - event.error = capture_exception(e) - except Exception as capture_err: - # Fallback to simple error if capture fails - write_to_log(f"Error capturing exception: {capture_err}") - event.error = { - "message": str(e), - "type": type(e).__name__, - "platform": "python", - } - raise - finally: - # Always publish event if tracing is enabled - if data.options.enable_tracing: - try: - event_queue.publish_event(lowlevel_server, event) - except Exception as e: - write_to_log(f"Error publishing event: {e}") - - # Apply the wrapped handler - lowlevel_server.request_handlers[CallToolRequest] = wrapped_call_tool_handler - write_to_log(f"Successfully patched call_tool handler for community FastMCP server {id(server)}") - - # Use minimal override for other events (initialize, list_tools) - # This handles event tracking for non-tool operations - override_lowlevel_mcp_server_minimal(lowlevel_server, data) - write_to_log(f"Applied minimal overrides for community FastMCP server {id(server)}") - - except Exception as e: - write_to_log(f"Error patching community FastMCP server: {e}") diff --git a/src/agentcat/modules/overrides/community/tool_manager.py b/src/agentcat/modules/overrides/community/tool_manager.py deleted file mode 100644 index ef8fc95..0000000 --- a/src/agentcat/modules/overrides/community/tool_manager.py +++ /dev/null @@ -1,177 +0,0 @@ -from typing import Any - -from agentcat.modules.compatibility import is_community_fastmcp_server -from agentcat.modules.internal import ( - get_server_tracking_data, - get_original_method, - store_original_method, - is_tool_tracked, - register_tool, - mark_tool_tracked, -) -from agentcat.modules.logging import write_to_log -from agentcat.modules.tools import handle_report_missing - -from fastmcp import FastMCP - - -def _ensure_context_parameter(tool: Any, description: str) -> None: - """Add or overwrite the 'context' parameter in a tool's schema. - - Ensures the tool has a valid parameters dict with a 'context' property - marked as required. - """ - if not hasattr(tool, "parameters") or not tool.parameters: - tool.parameters = {"type": "object", "properties": {}, "required": []} - - if "properties" not in tool.parameters: - tool.parameters["properties"] = {} - - tool.parameters["properties"]["context"] = { - "type": "string", - "description": description, - } - - if "required" not in tool.parameters: - tool.parameters["required"] = [] - - if isinstance(tool.parameters["required"], list): - if "context" not in tool.parameters["required"]: - tool.parameters["required"].append("context") - else: - tool.parameters["required"] = ["context"] - - -def patch_community_fastmcp_tool_manager(server: Any) -> None: - """Patch the community FastMCP tool manager to add AgentCat tracking. - - This function modifies the tool manager to: - 1. Add context parameter to existing tools - 2. Automatically add context to new tools via add_tool patching - 3. Add get_more_tools if enabled - """ - # Check that the server is a community FastMCP server - if not is_community_fastmcp_server(server): - write_to_log("WARNING: Incompatible community FastMCP server detected. Tracking not properly enabled.") - return - - # Get tracking data from the low-level server - data = get_server_tracking_data(server._mcp_server) - if not data: - write_to_log("WARNING: Unknown error when tracking community FastMCP. Tracking data for server not initialized.") - return - - write_to_log(f"Patching community FastMCP tool manager for server {id(server)}") - - # Add get_more_tools if enabled - if data.options.enable_report_missing: - try: - async def get_more_tools(context: str) -> str: - """Check for additional tools whenever your task might benefit from specialized capabilities.""" - result = await handle_report_missing({"context": context}) - if result.content: - return result.content[0].text - return "No additional tools available" - - server.tool( - get_more_tools, - name="get_more_tools", - description="Check for additional tools whenever your task might benefit from specialized capabilities - even if existing tools could work as a fallback.", - ) - - # Force the correct schema - Pydantic's TypeAdapter can mangle - # the type on async closures into anyOf: [string, null] - from agentcat.modules.tools import GET_MORE_TOOLS_SCHEMA - if hasattr(server._tool_manager, "_tools") and "get_more_tools" in server._tool_manager._tools: - server._tool_manager._tools["get_more_tools"].parameters = GET_MORE_TOOLS_SCHEMA - - write_to_log("Added get_more_tools tool to community FastMCP server") - except Exception as e: - write_to_log(f"Error adding get_more_tools: {e}") - - # Track existing tools and optionally add context parameter - if hasattr(server._tool_manager, "_tools"): - for tool_name, tool in server._tool_manager._tools.items(): - # Track the tool - if not is_tool_tracked(server._mcp_server, tool_name): - register_tool(server._mcp_server, tool_name) - mark_tool_tracked(server._mcp_server, tool_name) - write_to_log(f"Found existing community FastMCP tool: {tool_name}") - - # Patch existing tools if context injection is enabled - if data.options.enable_tool_call_context: - patch_existing_tools(server) - patch_add_tool_fn(server) - - -def patch_existing_tools(server: FastMCP) -> None: - """Modify existing tools to include the context parameter.""" - try: - data = get_server_tracking_data(server._mcp_server) - tool_manager = server._tool_manager - if not hasattr(tool_manager, "_tools"): - write_to_log("No _tools dictionary found on tool manager") - return - - for tool_name, tool in tool_manager._tools.items(): - if tool_name == "get_more_tools": - continue - - _ensure_context_parameter(tool, data.options.custom_context_description) - write_to_log(f"Added/updated context parameter for existing tool: {tool_name}") - - except Exception as e: - write_to_log(f"Error patching existing tools: {e}") - - -def patch_add_tool_fn(server: FastMCP) -> None: - """Patch the add_tool method to automatically add context parameter to new tools.""" - try: - tool_manager = server._tool_manager - tool_manager_id = id(tool_manager) - method_key = f"community_{tool_manager_id}_add_tool" - - # Store original method if not already stored - if get_original_method(method_key) is None: - store_original_method(method_key, tool_manager.add_tool) - write_to_log(f"Stored original add_tool for community tool_manager {tool_manager_id}") - - original_add_tool = get_original_method(method_key) - if not original_add_tool: - write_to_log("Failed to get original add_tool method") - return - - def patched_add_tool(tool: Any) -> Any: - """Patched add_tool that adds context parameter to new tools.""" - try: - # Call original method first - result = original_add_tool(tool) - - # Track the tool - tool_name = tool.key if hasattr(tool, "key") else (tool.name if hasattr(tool, "name") else "unknown") - if not is_tool_tracked(server._mcp_server, tool_name): - register_tool(server._mcp_server, tool_name) - mark_tool_tracked(server._mcp_server, tool_name) - write_to_log(f"Tracked new community FastMCP tool: {tool_name}") - - # Add context parameter if it's not get_more_tools - if tool_name != "get_more_tools": - data = get_server_tracking_data(server._mcp_server) - if data and data.options.enable_tool_call_context: - _ensure_context_parameter(tool, data.options.custom_context_description) - write_to_log(f"Added/updated context parameter for new tool: {tool_name}") - - return result - except Exception as e: - write_to_log(f"Error in patched add_tool: {e}") - # Fall back to original if something goes wrong - if callable(original_add_tool): - return original_add_tool(tool) - return tool - - # Apply the patch - tool_manager.add_tool = patched_add_tool - write_to_log(f"Successfully patched add_tool for community tool_manager {tool_manager_id}") - - except Exception as e: - write_to_log(f"Error patching add_tool: {e}") diff --git a/src/agentcat/modules/overrides/community_v3/__init__.py b/src/agentcat/modules/overrides/community_v3/__init__.py deleted file mode 100644 index 17f329c..0000000 --- a/src/agentcat/modules/overrides/community_v3/__init__.py +++ /dev/null @@ -1,11 +0,0 @@ -"""Community FastMCP v3 integration using the middleware system.""" - -from agentcat.modules.overrides.community_v3.integration import ( - apply_community_v3_integration, -) -from agentcat.modules.overrides.community_v3.middleware import AgentCatMiddleware - -__all__ = [ - "AgentCatMiddleware", - "apply_community_v3_integration", -] diff --git a/src/agentcat/modules/overrides/community_v3/integration.py b/src/agentcat/modules/overrides/community_v3/integration.py deleted file mode 100644 index eccf6d3..0000000 --- a/src/agentcat/modules/overrides/community_v3/integration.py +++ /dev/null @@ -1,94 +0,0 @@ -"""Integration module for Community FastMCP v3. - -This module provides the function to apply AgentCat tracking to -FastMCP v3 servers using the middleware system. -""" - -from typing import Annotated, Any - -from pydantic import Field - -from agentcat.modules.logging import write_to_log -from agentcat.modules.overrides.community_v3.middleware import AgentCatMiddleware -from agentcat.types import AgentCatData - - -def apply_community_v3_integration(server: Any, agentcat_data: AgentCatData) -> None: - """Apply AgentCat tracking to a Community FastMCP v3 server. - - This function: - 1. Creates an AgentCatMiddleware instance - 2. Inserts it at the beginning of the middleware chain (position 0) - 3. Registers get_more_tools tool if enabled - - Args: - server: A Community FastMCP v3 server instance. - agentcat_data: AgentCat tracking configuration. - """ - try: - # Create middleware instance - middleware = AgentCatMiddleware(agentcat_data, server) - - # Insert at beginning of middleware chain (position 0) - # This ensures AgentCat sees all requests first - server.middleware.insert(0, middleware) - write_to_log( - f"Inserted AgentCatMiddleware at position 0 for server {id(server)}" - ) - - # Register get_more_tools if enabled - if agentcat_data.options.enable_report_missing: - _register_get_more_tools_v3(server, agentcat_data) - - write_to_log( - f"Successfully applied Community FastMCP v3 integration " - f"for server {id(server)}" - ) - - except Exception as e: - write_to_log(f"Error applying Community FastMCP v3 integration: {e}") - raise - - -def _register_get_more_tools_v3(server: Any, agentcat_data: AgentCatData) -> None: - """Register the get_more_tools tool for FastMCP v3. - - Args: - server: A Community FastMCP v3 server instance. - agentcat_data: AgentCat tracking configuration. - """ - from fastmcp.tools.tool import Tool - - from agentcat.modules.tools import handle_report_missing - - # Define the get_more_tools function - async def get_more_tools( - context: Annotated[ - str, - Field( - description="A description of your goal and what kind of tool would help accomplish it." - ), - ], - ) -> str: - """Check for additional tools when your task might benefit from them.""" - result = await handle_report_missing({"context": context}) - - if result.content and hasattr(result.content[0], "text"): - return result.content[0].text - return "No additional tools available." - - try: - tool = Tool.from_function( - get_more_tools, - name="get_more_tools", - description=( - "Check for additional tools whenever your task might benefit from " - "specialized capabilities - even if existing tools could work as a " - "fallback." - ), - ) - server.add_tool(tool) - write_to_log("Registered get_more_tools using server.add_tool()") - - except Exception as e: - write_to_log(f"Error registering get_more_tools: {e}") diff --git a/src/agentcat/modules/overrides/community_v3/middleware.py b/src/agentcat/modules/overrides/community_v3/middleware.py deleted file mode 100644 index 62e22cf..0000000 --- a/src/agentcat/modules/overrides/community_v3/middleware.py +++ /dev/null @@ -1,499 +0,0 @@ -"""AgentCat Middleware for Community FastMCP v3. - -This module provides a middleware implementation that integrates AgentCat -tracking capabilities with the FastMCP v3 middleware system. -""" - -from __future__ import annotations - -import copy -from collections.abc import Sequence -from datetime import datetime, timezone -from importlib.metadata import version -from typing import TYPE_CHECKING, Any - -import mcp.types as mt - -from agentcat.modules import event_queue -from agentcat.modules.exceptions import ( - capture_exception, - clear_captured_error, - get_captured_error, - store_captured_error, -) -from agentcat.modules.identify import identify_session -from agentcat.modules.internal import attach_event_metadata, mark_tool_tracked, register_tool -from agentcat.modules.logging import write_to_log -from agentcat.modules.request_extra import params_with_extra -from agentcat.modules.session import ( - get_client_info_from_request_context, - get_server_session_id, -) -from agentcat.types import EventType, AgentCatData, UnredactedEvent - -if TYPE_CHECKING: - from fastmcp.server.middleware import CallNext, MiddlewareContext - from fastmcp.tools.tool import Tool, ToolResult - - -def _fastmcp_version() -> str: - """Best-effort resolved fastmcp version for diagnostics; never throws.""" - try: - return version("fastmcp") - except Exception: - return "unknown" - - -class AgentCatMiddleware: - """Middleware for AgentCat tracking in FastMCP v3. - - This middleware intercepts tool calls, list_tools, and initialize events - to provide analytics tracking for AgentCat. - - Attributes: - agentcat_data: The AgentCat tracking data configuration. - server: The FastMCP server instance. - """ - - def __init__(self, agentcat_data: AgentCatData, server: Any) -> None: - """Initialize the AgentCat middleware. - - Args: - agentcat_data: AgentCat tracking configuration. - server: The FastMCP v3 server instance. - """ - self.agentcat_data = agentcat_data - self.server = server - - async def __call__( - self, - context: MiddlewareContext[Any], - call_next: CallNext[Any, Any], - ) -> Any: - """Main entry point that orchestrates the pipeline.""" - from functools import partial - - handler = call_next - - # Dispatch based on method - method = context.method - if method == "initialize": - handler = partial(self.on_initialize, call_next=handler) - elif method == "tools/call": - handler = partial(self.on_call_tool, call_next=handler) - elif method == "tools/list": - handler = partial(self.on_list_tools, call_next=handler) - - return await handler(context) - - async def on_initialize( - self, - context: MiddlewareContext[mt.InitializeRequest], - call_next: CallNext[mt.InitializeRequest, mt.InitializeResult | None], - ) -> mt.InitializeResult | None: - """Track initialize events and capture client info. - - Args: - context: The middleware context containing the initialize request. - call_next: Function to call the next handler in the chain. - - Returns: - The initialize result from the next handler. - """ - session_id = self._get_session_id() - params = context.message.params - - # Extract client info from initialize params (MCP protocol provides clientInfo here) - client_name, client_version = None, None - if params and hasattr(params, "clientInfo") and params.clientInfo: - client_info = params.clientInfo - if hasattr(client_info, "name") and client_info.name: - client_name = client_info.name - if hasattr(client_info, "version") and client_info.version: - client_version = client_info.version - - # Handle session identification - # Note: Use self.server (FastMCP) not self.server._mcp_server because - # tracking data is stored with the FastMCP server as the key for v3 - request_context = self._get_request_context(context) - try: - if not client_name: - client_name, client_version = get_client_info_from_request_context(self.server, request_context) - else: - get_client_info_from_request_context(self.server, request_context) - identity = identify_session(self.server, context.message, request_context) - except Exception as e: - identity = None - write_to_log(f"Non-critical error in session handling: {e}") - - event = UnredactedEvent( - session_id=session_id, - timestamp=datetime.now(timezone.utc), - parameters=params_with_extra( - params.model_dump() if params else None, - request_context, - context.fastmcp_context, - ), - event_type=EventType.MCP_INITIALIZE.value, - identify_actor_given_id=identity.user_id if identity else None, - identify_actor_name=identity.user_name if identity else None, - identify_data=identity.user_data if identity else None, - client_name=client_name, - client_version=client_version, - ) - await attach_event_metadata(event, self.agentcat_data, context.message, request_context) - - try: - result = await call_next(context) - event.response = result.model_dump() if result else None - return result - except Exception as e: - event.is_error = True - event.error = capture_exception(e) - raise - finally: - self._publish_event(event, "initialize") - - async def on_call_tool( - self, - context: MiddlewareContext[mt.CallToolRequestParams], - call_next: CallNext[mt.CallToolRequestParams, ToolResult], - ) -> ToolResult: - """Track tool call events and handle context parameter extraction. - - Args: - context: The middleware context containing the tool call request. - call_next: Function to call the next handler in the chain. - - Returns: - The tool result from the next handler. - """ - message = context.message - tool_name = message.name - arguments = dict(message.arguments or {}) - session_id = self._get_session_id() - - # Handle session identification - # Note: Use self.server (FastMCP) not self.server._mcp_server because - # tracking data is stored with the FastMCP server as the key for v3 - request_context = self._get_request_context(context) - try: - client_name, client_version = get_client_info_from_request_context(self.server, request_context) - identity = identify_session(self.server, context.message, request_context) - except Exception as e: - client_name, client_version = None, None - identity = None - write_to_log(f"Non-critical error in session handling: {e}") - - register_tool(self.server, tool_name) - mark_tool_tracked(self.server, tool_name) - - # Extract user intent and determine if we should remove context from arguments - user_intent = None - should_remove_context = ( - self.agentcat_data.options.enable_tool_call_context - and tool_name != "get_more_tools" - ) - - if tool_name == "get_more_tools": - user_intent = arguments.get("context") - elif should_remove_context: - user_intent = arguments.pop("context", None) - - event = UnredactedEvent( - session_id=session_id, - timestamp=datetime.now(timezone.utc), - parameters=params_with_extra( - {"name": tool_name, "arguments": arguments}, - request_context, - context.fastmcp_context, - ), - event_type=EventType.MCP_TOOLS_CALL.value, - resource_name=tool_name, - user_intent=user_intent, - identify_actor_given_id=identity.user_id if identity else None, - identify_actor_name=identity.user_name if identity else None, - identify_data=identity.user_data if identity else None, - client_name=client_name, - client_version=client_version, - ) - await attach_event_metadata(event, self.agentcat_data, context.message, request_context) - - # Create modified context without context parameter if needed - call_context = context - if should_remove_context and "context" in (message.arguments or {}): - modified_args = { - k: v for k, v in (message.arguments or {}).items() if k != "context" - } - modified_message = mt.CallToolRequestParams( - name=tool_name, - arguments=modified_args or None, - ) - call_context = context.copy(message=modified_message) - - clear_captured_error() - - try: - result = await call_next(call_context) - - if hasattr(result, "is_error") and result.is_error: - event.is_error = True - captured = get_captured_error() - event.error = capture_exception(captured if captured else result) - else: - event.is_error = False - - event.response = self._serialize_result(result) - return result - - except Exception as e: - write_to_log(f"Error in on_call_tool: {e}") - event.is_error = True - store_captured_error(e) - event.error = capture_exception(e) - raise - - finally: - self._publish_event(event, "tool call") - - async def on_list_tools( - self, - context: MiddlewareContext[mt.ListToolsRequest], - call_next: CallNext[mt.ListToolsRequest, Sequence[Tool]], - ) -> Sequence[Tool]: - """Inject context parameter and track list_tools events. - - Args: - context: The middleware context containing the list tools request. - call_next: Function to call the next handler in the chain. - - Returns: - The list of tools, potentially modified with context parameter. - """ - session_id = self._get_session_id() - - # Handle session identification - # Note: Use self.server (FastMCP) not self.server._mcp_server because - # tracking data is stored with the FastMCP server as the key for v3 - request_context = self._get_request_context(context) - try: - client_name, client_version = get_client_info_from_request_context(self.server, request_context) - identity = identify_session(self.server, context.message, request_context) - except Exception as e: - client_name, client_version = None, None - identity = None - write_to_log(f"Non-critical error in session handling: {e}") - - params = getattr(context.message, "params", None) - - event = UnredactedEvent( - session_id=session_id, - timestamp=datetime.now(timezone.utc), - parameters=params_with_extra( - params.model_dump() if params else None, - request_context, - context.fastmcp_context, - ), - event_type=EventType.MCP_TOOLS_LIST.value, - identify_actor_given_id=identity.user_id if identity else None, - identify_actor_name=identity.user_name if identity else None, - identify_data=identity.user_data if identity else None, - client_name=client_name, - client_version=client_version, - ) - await attach_event_metadata(event, self.agentcat_data, context.message, request_context) - - try: - tools = list(await call_next(context)) - - for tool in tools: - register_tool(self.server, tool.name) - mark_tool_tracked(self.server, tool.name) - - if self.agentcat_data.options.enable_tool_call_context: - tools = self._inject_context_into_tools(tools) - - event.response = {"tools": [self._tool_to_dict(t) for t in tools]} - return tools - - except Exception as e: - event.is_error = True - event.error = capture_exception(e) - raise - - finally: - self._publish_event(event, "list_tools") - - def _get_session_id(self) -> str: - """Get the session ID for tracking. - - Returns: - The session ID string. - """ - try: - return get_server_session_id(self.server) - except Exception as e: - write_to_log(f"Error getting session ID: {e}") - return self.agentcat_data.session_id - - def _get_request_context(self, context: MiddlewareContext[Any]) -> Any: - """Get the MCP request context from middleware context. - - Args: - context: The middleware context. - - Returns: - The MCP request context, or None if not available. - """ - if context.fastmcp_context: - return context.fastmcp_context.request_context - return None - - def _publish_event(self, event: UnredactedEvent, event_name: str) -> None: - """Publish an event if tracing is enabled. - - Args: - event: The event to publish. - event_name: Human-readable name for error logging. - """ - if not self.agentcat_data.options.enable_tracing: - return - - try: - event_queue.publish_event(self.server, event) - except Exception as e: - write_to_log(f"Error publishing {event_name} event: {e}") - - def _serialize_result(self, result: Any) -> dict[str, Any]: - """Serialize a tool result to a dictionary. - - Args: - result: The result to serialize. - - Returns: - Dictionary representation of the result. - """ - if hasattr(result, "model_dump"): - return result.model_dump() - if isinstance(result, dict): - return result - return {"content": str(result)} - - def _inject_context_into_tools(self, tools: list[Tool]) -> list[Tool]: - """Inject context parameter into tool schemas. - - Args: - tools: List of tools to modify. - - Returns: - List of tools with context parameter injected. - """ - context_description = self.agentcat_data.options.custom_context_description - modified_tools = [] - - for tool in tools: - if tool.name == "get_more_tools": - modified_tools.append(tool) - continue - - # Only the parameters schema (a plain dict) is mutated below, so copy - # just that — never the whole Tool. Deep-copying the Tool drags in - # non-picklable fields it may hold (e.g. an httpx.AsyncClient with a - # threading.RLock on OpenAPI-generated tools), which raised - # "cannot pickle '_thread.RLock' object" and silently dropped context - # injection on every tools/list. - try: - tool_copy = tool.model_copy( - update={"parameters": copy.deepcopy(getattr(tool, "parameters", None))} - ) - except Exception as e: - write_to_log( - f"Error copying tool {tool.name} (fastmcp {_fastmcp_version()}): {e}" - ) - modified_tools.append(tool) - continue - - params = self._ensure_parameters_schema(tool_copy) - self._add_context_property(params, context_description) - self._add_to_required(params, "context") - - modified_tools.append(tool_copy) - - return modified_tools - - def _ensure_parameters_schema(self, tool: Tool) -> dict[str, Any]: - """Ensure tool has a valid parameters schema and return it. - - Args: - tool: The tool to check/modify. - - Returns: - The parameters dict (created if necessary). - """ - if not hasattr(tool, "parameters") or tool.parameters is None: - tool.parameters = {"type": "object", "properties": {}, "required": []} - - params = tool.parameters - if "properties" not in params: - params["properties"] = {} - - return params - - def _add_context_property( - self, params: dict[str, Any], description: str - ) -> None: - """Add or update the context property in a parameters schema. - - Args: - params: The parameters dict to modify. - description: The description for the context property. - """ - properties = params["properties"] - - if "context" not in properties: - properties["context"] = {"type": "string", "description": description} - elif not properties["context"].get("description"): - properties["context"]["description"] = description - - def _add_to_required(self, params: dict[str, Any], field: str) -> None: - """Add a field to the required array if not already present. - - Args: - params: The parameters dict to modify. - field: The field name to add to required. - """ - if "required" not in params: - params["required"] = [] - - required = params["required"] - if isinstance(required, list) and field not in required: - required.append(field) - - def _tool_to_dict(self, tool: Tool) -> dict[str, Any]: - """Convert a tool to a dictionary for event response. - - Args: - tool: The tool to convert. - - Returns: - Dictionary representation of the tool. - """ - try: - # Prefer the canonical MCP shape. A FastMCP Tool.model_dump() includes - # SDK-internal fields that are not JSON-serializable — a callable ``fn`` - # (FunctionTool) and a ``tags`` set — which would break event - # serialization; to_mcp_tool() yields the clean wire representation - # (name/description/inputSchema/...). - if hasattr(tool, "to_mcp_tool"): - mcp_tool = tool.to_mcp_tool() - if hasattr(mcp_tool, "model_dump"): - return mcp_tool.model_dump(mode="json") - if hasattr(tool, "model_dump"): - return tool.model_dump(mode="json") - return { - "name": getattr(tool, "name", "unknown"), - "description": getattr(tool, "description", ""), - } - except Exception as e: - write_to_log(f"Error converting tool to dict: {e}") - return {"name": getattr(tool, "name", "unknown")} diff --git a/src/agentcat/modules/overrides/mcp_server.py b/src/agentcat/modules/overrides/mcp_server.py deleted file mode 100644 index 12e632c..0000000 --- a/src/agentcat/modules/overrides/mcp_server.py +++ /dev/null @@ -1,329 +0,0 @@ -from datetime import datetime, timezone -from typing import Any, Optional - -from mcp import ListToolsResult, ServerResult, Tool -from mcp.server import Server -from mcp.types import CallToolRequest, ListToolsRequest, InitializeRequest -from mcp.shared.context import RequestContext - -from agentcat.modules import event_queue -from agentcat.modules.compatibility import is_mcp_error_response -from agentcat.modules.identify import identify_session -from agentcat.modules.internal import attach_event_metadata -from agentcat.modules.logging import write_to_log -from agentcat.modules.request_extra import params_with_extra -from agentcat.modules.tools import handle_report_missing - -from ...types import EventType, AgentCatData, UnredactedEvent -from ..session import get_client_info_from_request_context, get_server_session_id - - -def safe_request_context(server: Server) -> Optional[RequestContext]: - """Safely extract request context, handling missing attributes.""" - try: - request_context = server.request_context - except Exception: - request_context = None - - return request_context - - -"""Tool management and interception for AgentCat.""" - - -def override_lowlevel_mcp_server(server: Server, data: AgentCatData) -> None: - """Set up tool list and call handlers for FastMCP.""" - # Store original request handlers - we only need to intercept at the low-level - # TODO: original_call_tool_handler = server.request_handlers.get(InitializeRequest) - original_initialize_handler = server.request_handlers.get(InitializeRequest) - original_call_tool_handler = server.request_handlers.get(CallToolRequest) - original_list_tools_handler = server.request_handlers.get(ListToolsRequest) - - async def wrapped_initialize_handler(request: InitializeRequest) -> ServerResult: - """Intercept initialize requests to add AgentCat data to the request context.""" - session_id = get_server_session_id(server) - request_context = safe_request_context(server) - identity = identify_session(server, request, request_context) - - # Extract clientInfo from InitializeRequest params (MCP protocol provides it here) - client_name, client_version = None, None - if request.params and hasattr(request.params, 'clientInfo') and request.params.clientInfo: - client_name = request.params.clientInfo.name - client_version = getattr(request.params.clientInfo, 'version', None) - if not client_name: - client_name, client_version = get_client_info_from_request_context(server, request_context) - - event = UnredactedEvent( - session_id=session_id, - timestamp=datetime.now(timezone.utc), - parameters=params_with_extra( - request.params.model_dump() if request.params else None, - request_context, - ), - event_type=EventType.MCP_INITIALIZE.value, - identify_actor_given_id=identity.user_id if identity else None, - identify_actor_name=identity.user_name if identity else None, - identify_data=identity.user_data if identity else None, - client_name=client_name, - client_version=client_version, - ) - await attach_event_metadata(event, data, request, request_context) - - # Call the original handler - result = await original_initialize_handler(request) - - # Record the event - event.response = result.model_dump() if result else None - event_queue.publish_event(server, event) - return result - - async def wrapped_list_tools_handler(request: ListToolsRequest) -> ServerResult: - """Intercept list_tools requests to add AgentCat tools and modify existing ones.""" - session_id = get_server_session_id(server) - request_context = safe_request_context(server) - client_name, client_version = get_client_info_from_request_context(server, request_context) - identity = identify_session(server, request, request_context) - - event = UnredactedEvent( - session_id=session_id, - timestamp=datetime.now(timezone.utc), - parameters=params_with_extra( - request.params.model_dump() if request and request.params else None, - request_context, - ), - event_type=EventType.MCP_TOOLS_LIST.value, - identify_actor_given_id=identity.user_id if identity else None, - identify_actor_name=identity.user_name if identity else None, - identify_data=identity.user_data if identity else None, - client_name=client_name, - client_version=client_version, - ) - await attach_event_metadata(event, data, request, request_context) - - # Call the original handler to get the tools - original_result = await original_list_tools_handler(request) - if ( - not original_result - or not hasattr(original_result, "root") - or not hasattr(original_result.root, "tools") - ): - return original_result - tools_list = original_result.root.tools - - # Add report_missing tool if enabled - if data.options.enable_report_missing: - get_more_tools = Tool( - name="get_more_tools", - description="Check for additional tools whenever your task might benefit from specialized capabilities - even if existing tools could work as a fallback.", - inputSchema={ - "type": "object", - "properties": { - "context": { - "type": "string", - "description": "A description of your goal and what kind of tool would help accomplish it.", - } - }, - "required": ["context"], - }, - ) - tools_list.append(get_more_tools) - - # Add context parameters to existing tools if enabled - if data.options.enable_tool_call_context: - for tool in tools_list: - if tool.name != "get_more_tools": # Don't modify our own tool - if not tool.inputSchema: - tool.inputSchema = { - "type": "object", - "properties": {}, - "required": [], - } - - # Add context property if it doesn't exist - if "context" not in tool.inputSchema.get("properties", {}): - if "properties" not in tool.inputSchema: - tool.inputSchema["properties"] = {} - - tool.inputSchema["properties"]["context"] = { - "type": "string", - "description": data.options.custom_context_description, - } - - # Add context to required array if it exists - if isinstance(tool.inputSchema.get("required"), list): - if "context" not in tool.inputSchema["required"]: - tool.inputSchema["required"].append("context") - else: - tool.inputSchema["required"] = ["context"] - - result = ServerResult(ListToolsResult(tools=tools_list)) - event.response = result.model_dump() if result else None - event_queue.publish_event(server, event) - return result - - async def wrapped_call_tool_handler(request: CallToolRequest) -> ServerResult: - """Intercept call_tool requests to add AgentCat tracking and handle special tools.""" - tool_name = request.params.name - arguments = request.params.arguments or {} - session_id = get_server_session_id(server) - request_context = safe_request_context(server) - client_name, client_version = get_client_info_from_request_context(server, request_context) - identity = identify_session(server, request, request_context) - - write_to_log( - f"Intercepted call to tool '{tool_name}' with arguments: {arguments} and request context: {request_context}" - ) - event = UnredactedEvent( - session_id=session_id, - timestamp=datetime.now(timezone.utc), - parameters=params_with_extra( - request.params.model_dump() if request.params else None, - request_context, - ), - event_type=EventType.MCP_TOOLS_CALL.value, - resource_name=tool_name, - identify_actor_given_id=identity.user_id if identity else None, - identify_actor_name=identity.user_name if identity else None, - identify_data=identity.user_data if identity else None, - client_name=client_name, - client_version=client_version, - ) - await attach_event_metadata(event, data, request, request_context) - - # Extract user intent from context (but don't pop yet - we need it for the event) - if data.options.enable_tool_call_context and tool_name != "get_more_tools": - event.user_intent = arguments.get("context", None) - elif tool_name == "get_more_tools": - # For get_more_tools, context is the actual parameter - event.user_intent = arguments.get("context", None) - - # Handle report_missing tool directly - if tool_name == "get_more_tools": - result = await handle_report_missing(arguments) - event.response = result.model_dump() if result else None - event_queue.publish_event(server, event) - return result - - # Now pop context from arguments before calling the original handler - if data.options.enable_tool_call_context: - arguments.pop("context", None) - # Log warning if context is missing and tool is not report_missing - if event.user_intent is None and tool_name != "get_more_tools": - write_to_log( - f"Tool '{tool_name}' called without context. agentcat.track() might have been called BEFORE tool initialization." - ) - - # If tracing is enabled, wrap the call with timing and logging - if data.options.enable_tracing: - try: - # Call the original handler - result = await original_call_tool_handler(request) - is_error, error_message = is_mcp_error_response(result) - event.is_error = is_error - event.error = {"message": error_message} if is_error else None - # Record the trace using existing infrastructure - event.response = result.model_dump() if result else None - event_queue.publish_event(server, event) - return result - - except Exception as e: - # Record the error trace - event.is_error = True - event.error = {"message": str(e)} - event_queue.publish_event(server, event) - raise - else: - # No tracing, just call the original handler - return await original_call_tool_handler(request) - - server.request_handlers[CallToolRequest] = wrapped_call_tool_handler - server.request_handlers[ListToolsRequest] = wrapped_list_tools_handler - server.request_handlers[InitializeRequest] = wrapped_initialize_handler - - -def override_lowlevel_mcp_server_minimal(server: Server, data: AgentCatData) -> None: - """Set up minimal handlers for FastMCP servers (non-tool events only). - - This is used for FastMCP servers where tool tracking is handled by monkey-patching. - We only need to track initialize and other non-tool events. - """ - # Store original request handlers - original_initialize_handler = server.request_handlers.get(InitializeRequest) - original_list_tools_handler = server.request_handlers.get(ListToolsRequest) - - async def wrapped_initialize_handler(request: InitializeRequest) -> ServerResult: - """Intercept initialize requests to add AgentCat data to the request context.""" - session_id = get_server_session_id(server) - request_context = safe_request_context(server) - try: - identity = identify_session(server, request, request_context) - except Exception as e: - identity = None - write_to_log(f"Ran into an error in session identification, no identity could be determined: {e}") - - client_name, client_version = None, None - if request.params and hasattr(request.params, 'clientInfo') and request.params.clientInfo: - client_name = request.params.clientInfo.name - client_version = getattr(request.params.clientInfo, 'version', None) - if not client_name: - client_name, client_version = get_client_info_from_request_context(server, request_context) - - event = UnredactedEvent( - session_id=session_id, - timestamp=datetime.now(timezone.utc), - parameters=params_with_extra( - request.params.model_dump() if request.params else None, - request_context, - ), - event_type=EventType.MCP_INITIALIZE.value, - identify_actor_given_id=identity.user_id if identity else None, - identify_actor_name=identity.user_name if identity else None, - identify_data=identity.user_data if identity else None, - client_name=client_name, - client_version=client_version, - ) - await attach_event_metadata(event, data, request, request_context) - - # Call the original handler - result = await original_initialize_handler(request) - - # Record the event - event.response = result.model_dump() if result else None - event_queue.publish_event(server, event) - return result - - async def wrapped_list_tools_handler(request: ListToolsRequest) -> ServerResult: - """Intercept list_tools requests to track the event (tool modifications handled by monkey-patch).""" - session_id = get_server_session_id(server) - request_context = safe_request_context(server) - client_name, client_version = get_client_info_from_request_context(server, request_context) - identity = identify_session(server, request, request_context) - - event = UnredactedEvent( - session_id=session_id, - timestamp=datetime.now(timezone.utc), - parameters=params_with_extra( - request.params.model_dump() if request and request.params else None, - request_context, - ), - event_type=EventType.MCP_TOOLS_LIST.value, - identify_actor_given_id=identity.user_id if identity else None, - identify_actor_name=identity.user_name if identity else None, - identify_data=identity.user_data if identity else None, - client_name=client_name, - client_version=client_version, - ) - await attach_event_metadata(event, data, request, request_context) - - # Call the original handler - tool modifications are handled by monkey-patch - result = await original_list_tools_handler(request) - - # Record the event - event.response = result.model_dump() if result else None - event_queue.publish_event(server, event) - return result - - # Only override initialize and list_tools for event tracking - # Tool call tracking is handled by monkey-patching for FastMCP - server.request_handlers[InitializeRequest] = wrapped_initialize_handler - server.request_handlers[ListToolsRequest] = wrapped_list_tools_handler diff --git a/src/agentcat/modules/overrides/official/monkey_patch.py b/src/agentcat/modules/overrides/official/monkey_patch.py deleted file mode 100644 index 28f3d6b..0000000 --- a/src/agentcat/modules/overrides/official/monkey_patch.py +++ /dev/null @@ -1,583 +0,0 @@ -"""Monkey-patching implementation for dynamic tool tracking. - -This module patches MCP server methods to intercept tool registration and execution, -enabling AgentCat to track tools regardless of when they are registered. -""" - -import inspect -from collections.abc import Callable -from datetime import datetime, timezone -from typing import Annotated, Any, List - -from pydantic import Field - -from agentcat.modules import event_queue -from agentcat.modules.compatibility import is_official_fastmcp_server, is_mcp_error_response -from agentcat.modules.exceptions import ( - capture_exception, - clear_captured_error, - get_captured_error, - store_captured_error, -) -from agentcat.modules.internal import ( - attach_event_metadata, - get_original_method, - get_server_tracking_data, - is_tool_tracked, - mark_tool_tracked, - register_tool, - store_original_method, -) -from agentcat.modules.logging import write_to_log -from agentcat.modules.request_extra import params_with_extra -from agentcat.modules.session import ( - get_client_info_from_request_context, - get_server_session_id, -) -from agentcat.types import EventType, AgentCatData, UnredactedEvent - -from ..mcp_server import safe_request_context - - -def get_current_agentcat_data(server: Any, fallback: AgentCatData) -> AgentCatData: - """Get the current AgentCat data for a server.""" - data = get_server_tracking_data(server) - return data if data else fallback - - -def patch_fastmcp_tool_manager(server: Any, agentcat_data: AgentCatData) -> bool: - """Monkey-patch FastMCP's ToolManager to intercept tool operations. - - Args: - server: FastMCP server instance - agentcat_data: AgentCat tracking data - - Returns: - True if patching was successful, False otherwise - """ - try: - # Check if this is a FastMCP server (which now includes _tool_manager check) - if not is_official_fastmcp_server(server): - return False - - tool_manager = server._tool_manager - data = get_server_tracking_data(server) - if not data: - return False - - # Add the get_more_tools tool if enabled - if agentcat_data.options.enable_report_missing: - # Create the get_more_tools function that returns CallToolResult - async def get_more_tools( - context: Annotated[ - str, - Field( - description="A description of your goal and what kind of tool would help accomplish it." - ), - ], - ) -> List[Any]: - """Check for additional tools whenever your task might benefit from specialized capabilities.""" - from agentcat.modules.tools import handle_report_missing - - result = await handle_report_missing({"context": context}) - # Return just the content list for FastMCP - return result.content - - # Register it with the server - # Use inspect to determine which parameters are supported - try: - if hasattr(server, 'add_tool'): - sig = inspect.signature(server.add_tool) - kwargs = { - "name": "get_more_tools", - "description": "Check for additional tools whenever your task might benefit from specialized capabilities - even if existing tools could work as a fallback.", - } - # Only add icons if the parameter exists - if "icons" in sig.parameters: - kwargs["icons"] = None - server.add_tool(get_more_tools, **kwargs) - else: - # Fallback for older versions - server.add_tool( - get_more_tools, - name="get_more_tools", - description="Check for additional tools whenever your task might benefit from specialized capabilities - even if existing tools could work as a fallback.", - ) - except Exception as e: - write_to_log(f"Error registering get_more_tools: {e}") - write_to_log("Added get_more_tools tool to FastMCP server") - - # First, capture any tools that were already registered - if hasattr(tool_manager, "_tools"): - for tool_name, _tool in tool_manager._tools.items(): - if not is_tool_tracked(server, tool_name): - register_tool(server, tool_name) - mark_tool_tracked(server, tool_name) - write_to_log(f"Found existing FastMCP tool: {tool_name}") - - # Store original methods - use tool_manager ID to avoid conflicts - # We need to store the original unpatched methods once per tool_manager - tool_manager_id = id(tool_manager) - method_key_prefix = f"fastmcp_{tool_manager_id}_" - - write_to_log( - f"Patching FastMCP server {id(server)}, tool_manager {tool_manager_id}" - ) - - # Only store original methods if this tool_manager hasn't been seen before - if get_original_method(f"{method_key_prefix}add_tool") is None: - store_original_method(f"{method_key_prefix}add_tool", tool_manager.add_tool) - store_original_method( - f"{method_key_prefix}call_tool", tool_manager.call_tool - ) - store_original_method( - f"{method_key_prefix}list_tools", tool_manager.list_tools - ) - write_to_log(f"Stored original methods for tool_manager {tool_manager_id}") - - # Get original methods for this tool_manager - original_add_tool = get_original_method(f"{method_key_prefix}add_tool") - original_call_tool = get_original_method(f"{method_key_prefix}call_tool") - original_list_tools = get_original_method(f"{method_key_prefix}list_tools") - - # Safety check - if original methods don't exist, bail out - if not original_add_tool or not original_call_tool or not original_list_tools: - write_to_log( - f"Original methods not found for tool_manager {tool_manager_id}, skipping patches" - ) - return False - - # Patch add_tool to track new registrations - def patched_add_tool( - fn: Callable[..., Any], - **kwargs - ) -> Any: - """Patched add_tool that tracks tool registration.""" - try: - # Call original method first to get the actual tool object - # Use callable check to avoid mypy error - if not callable(original_add_tool): - write_to_log("Warning: original_add_tool is not callable") - return fn - - # Get the signature of the original method to filter kwargs - try: - sig = inspect.signature(original_add_tool) - # Filter kwargs to only include parameters that exist in the original signature - filtered_kwargs = { - k: v for k, v in kwargs.items() - if k in sig.parameters - } - except Exception as e: - write_to_log(f"Could not inspect signature, passing all kwargs: {e}") - filtered_kwargs = kwargs - - result = original_add_tool(fn, **filtered_kwargs) - - # Track the tool registration (wrapped in try-catch to never fail) - try: - tool_name = ( - result.name - if hasattr(result, "name") - else (kwargs.get("name") or fn.__name__) - ) - register_tool(server, tool_name) - - # Get current data for this server - current_data = get_current_agentcat_data(server, agentcat_data) - - # If AgentCat is already initialized, we need to wrap this tool - if data.tracker_initialized and current_data.options.enable_tracing: - write_to_log( - f"Late-registered FastMCP tool detected: {tool_name}" - ) - except Exception as e: - write_to_log(f"Error tracking tool registration: {e}") - # Continue with original result - - return result - except Exception as e: - write_to_log(f"Critical error in patched_add_tool, falling back: {e}") - # If anything fails, try to call original method directly - if callable(original_add_tool): - try: - # Try with filtered kwargs first - sig = inspect.signature(original_add_tool) - filtered_kwargs = { - k: v for k, v in kwargs.items() - if k in sig.parameters - } - return original_add_tool(fn, **filtered_kwargs) - except: - # Last attempt with no kwargs - try: - return original_add_tool(fn) - except: - pass - return fn # Last resort fallback - - # Patch call_tool to ensure tracking and add context - async def patched_call_tool( - name: str, - arguments: dict[str, Any], - context: Any | None = None, - **kwargs # Accept any additional parameters for version compatibility - ) -> Any: - """Patched call_tool that adds AgentCat tracking.""" - # Initialize variables for tracking - event = None - current_data = None - - try: - # Try to get tracking data, but don't fail if we can't - try: - session_id = get_server_session_id(server._mcp_server) - current_data = get_current_agentcat_data(server, agentcat_data) - except Exception as e: - write_to_log(f"Error getting tracking data: {e}") - session_id = "unknown" - current_data = agentcat_data - - # Handle session identification (non-critical) - request_context = None - mock_request = None - try: - request_context = safe_request_context(server._mcp_server) - client_name, client_version = (None, None) - if request_context is not None: - client_name, client_version = get_client_info_from_request_context( - server._mcp_server, request_context - ) - - # Call identify_session for custom identification - from agentcat.modules.identify import identify_session - - # Create a mock request for identify_session - mock_request = type( - "MockCallToolRequest", - (), - { - "params": type( - "Params", (), {"name": name, "arguments": arguments} - )() - }, - )() - - identity = identify_session(server._mcp_server, mock_request, request_context) - except Exception as e: - client_name, client_version = None, None - identity = None - write_to_log(f"Non-critical error in session handling: {e}") - - # Extract user intent (non-critical) - user_intent = None - try: - should_capture_intent = ( - name == "get_more_tools" - or (current_data and current_data.options.enable_tool_call_context) - ) - if should_capture_intent: - user_intent = arguments.get("context", None) - except Exception as e: - write_to_log(f"Error extracting user intent: {e}") - - # Track the tool (non-critical) - try: - if not is_tool_tracked(server, name): - register_tool(server, name) - mark_tool_tracked(server, name) - write_to_log(f"Dynamically tracking FastMCP tool: {name}") - except Exception as e: - write_to_log(f"Error tracking tool: {e}") - - # Create tracking event (non-critical) - try: - event = UnredactedEvent( - session_id=session_id, - timestamp=datetime.now(timezone.utc), - parameters=params_with_extra( - {"name": name, "arguments": arguments}, - request_context, - ), - event_type=EventType.MCP_TOOLS_CALL.value, - resource_name=name, - user_intent=user_intent, - identify_actor_given_id=identity.user_id if identity else None, - identify_actor_name=identity.user_name if identity else None, - identify_data=identity.user_data if identity else None, - client_name=client_name, - client_version=client_version, - ) - await attach_event_metadata(event, current_data, mock_request, request_context) - except Exception as e: - write_to_log(f"Error creating event: {e}") - event = None - - # Prepare arguments (remove context if needed) - args_for_tool = arguments.copy() - try: - if ( - current_data - and current_data.options.enable_tool_call_context - and name != "get_more_tools" - ): - args_for_tool.pop("context", None) - except Exception as e: - write_to_log(f"Error preparing arguments: {e}") - args_for_tool = arguments # Use original if modification fails - - # Clear any previous captured error before execution - clear_captured_error() - - # Call original method - THIS IS CRITICAL, must not fail - if not callable(original_call_tool): - write_to_log("Critical: original_call_tool is not callable") - raise ValueError("Original call_tool method is not callable") - - # Wrap execution to preserve exceptions before MCP SDK processes them - try: - result = await original_call_tool( - name, args_for_tool, context=context, **kwargs - ) - except Exception as tool_exc: - # Preserve original exception before MCP SDK converts it - store_captured_error(tool_exc) - raise # Re-raise so MCP SDK can handle it normally - - # Try to capture response in event (non-critical) - if event: - try: - # Check if result indicates an error (CallToolResult with isError=True) - is_error_result = False - if hasattr(result, "model_dump"): - is_error_result, error_message = is_mcp_error_response(result) - - if is_error_result: - # MCP SDK converted an exception to CallToolResult - event.is_error = True - - # Try to use preserved exception first (has full traceback) - captured = get_captured_error() - if captured: - event.error = capture_exception(captured) - else: - # Fallback: extract from CallToolResult - event.error = capture_exception(result) - - # Capture response data - if isinstance(result, tuple): - event.response = result[1] if len(result) > 1 else None - elif hasattr(result, "model_dump"): - event.response = result.model_dump() - elif isinstance(result, dict): - event.response = result - elif isinstance(result, list): - event.response = { - "content": [ - item.model_dump() - if hasattr(item, "model_dump") - else item - for item in result - ] - } - else: - event.response = {"value": result} - except Exception as e: - write_to_log(f"Error capturing response: {e}") - - return result - - except Exception as e: - # Log the error - write_to_log(f"Error in patched_call_tool: {e}") - - # Try to mark event as error if it exists - if event: - try: - event.is_error = True - # Use full exception capture with stack trace - event.error = capture_exception(e) - except Exception as capture_err: - # Fallback to simple error if capture fails - write_to_log(f"Error capturing exception: {capture_err}") - try: - event.error = { - "message": str(e), - "type": type(e).__name__, - "platform": "python", - } - except: - pass - - # Re-raise to preserve original error behavior - raise - - finally: - # Try to publish event (non-critical) - if event and current_data: - try: - if current_data.options.enable_tracing: - event_queue.publish_event(server._mcp_server, event) - except Exception as e: - write_to_log(f"Error publishing event: {e}") - # Don't re-raise, let the tool result be returned - - # Patch list_tools to add AgentCat tools and context - def patched_list_tools() -> List[Any]: - """Patched list_tools that adds AgentCat modifications.""" - try: - # Get current data for this server - current_data = get_current_agentcat_data(server, agentcat_data) - - # Get original tools with safety check - if not callable(original_list_tools): - write_to_log("Warning: original_list_tools is not callable") - return [] - tools = original_list_tools() - - # Track all tools (non-critical) - try: - for tool in tools: - if hasattr(tool, "name") and not is_tool_tracked( - server, tool.name - ): - register_tool(server, tool.name) - mark_tool_tracked(server, tool.name) - except Exception as e: - write_to_log(f"Error tracking tools in list_tools: {e}") - - # Add report_missing tool if enabled (non-critical) - try: - if current_data.options.enable_report_missing: - # Check if already added - if not any( - hasattr(t, "name") and t.name == "get_more_tools" - for t in tools - ): - from mcp.server.fastmcp.tools.base import ( - Tool as FastMCPTool, - ) - - # Create a function for get_more_tools - async def get_more_tools_fn(context: str) -> Any: - """Check for additional tools whenever your task might benefit from specialized capabilities.""" - from agentcat.modules.tools import handle_report_missing - - return await handle_report_missing({"context": context}) - - # Create the tool from the function - get_more_tools = FastMCPTool.from_function( - get_more_tools_fn, - name="get_more_tools", - description="Check for additional tools whenever your task might benefit from specialized capabilities - even if existing tools could work as a fallback.", - ) - tools.append(get_more_tools) - except Exception as e: - write_to_log(f"Error adding get_more_tools: {e}") - - # Add context parameter to tools if enabled (non-critical) - try: - if current_data.options.enable_tool_call_context: - for tool in tools: - if hasattr(tool, "name") and tool.name != "get_more_tools": - if not hasattr(tool, "parameters"): - tool.parameters = { - "type": "object", - "properties": {}, - "required": [], - } - elif not tool.parameters: - tool.parameters = { - "type": "object", - "properties": {}, - "required": [], - } - - # Add context property if not present - if "context" not in tool.parameters.get( - "properties", {} - ): - if "properties" not in tool.parameters: - tool.parameters["properties"] = {} - - tool.parameters["properties"]["context"] = { - "type": "string", - "description": current_data.options.custom_context_description, - } - - # Add to required array - if isinstance( - tool.parameters.get("required"), list - ): - if "context" not in tool.parameters["required"]: - tool.parameters["required"].append( - "context" - ) - else: - tool.parameters["required"] = ["context"] - except Exception as e: - write_to_log(f"Error adding context to tools: {e}") - - return list(tools) # Ensure we return a list - except Exception as e: - write_to_log( - f"Critical error in patched_list_tools, falling back to original: {e}" - ) - # If anything fails, try to call original method - if callable(original_list_tools): - try: - result = original_list_tools() - return result if isinstance(result, list) else [] - except: - pass - return [] # Last resort - - # Apply patches directly (they capture the correct context via closure) - write_to_log(f"Applying patches to tool_manager {id(tool_manager)}") - write_to_log(f"Before patch - call_tool: {tool_manager.call_tool}") - - tool_manager.add_tool = patched_add_tool - tool_manager.call_tool = patched_call_tool - tool_manager.list_tools = patched_list_tools - - write_to_log(f"After patch - call_tool: {tool_manager.call_tool}") - - write_to_log( - f"Successfully monkey-patched FastMCP ToolManager for server {id(server)}" - ) - return True - - except Exception as e: - write_to_log(f"Failed to patch FastMCP ToolManager: {e}") - return False - - -def apply_official_fastmcp_patches(server: Any, agentcat_data: AgentCatData) -> bool: - """Apply monkey patches for FastMCP servers only. - - Args: - server: FastMCP server instance - agentcat_data: AgentCat tracking data - - Returns: - True if patching was successful - """ - # The AgentCat data is already stored by the caller - # Just verify we can get it - data = get_server_tracking_data(server) - if not data: - write_to_log(f"Warning: AgentCat data not found for server {id(server)}") - return False - - # Only patch FastMCP servers - if is_official_fastmcp_server(server): - if patch_fastmcp_tool_manager(server, agentcat_data): - write_to_log( - f"Monkey patches applied successfully to FastMCP server {id(server)}" - ) - return True - - write_to_log( - f"Server {id(server)} is not a FastMCP server, skipping monkey patches" - ) - return False diff --git a/src/agentcat/modules/redaction.py b/src/agentcat/modules/redaction.py index 58b0dca..215a73a 100644 --- a/src/agentcat/modules/redaction.py +++ b/src/agentcat/modules/redaction.py @@ -1,5 +1,7 @@ """PII redaction for AgentCat logs.""" +import asyncio +import inspect from typing import Any, TYPE_CHECKING, Callable, Set if TYPE_CHECKING: @@ -87,12 +89,51 @@ def redact_strings_in_object( return obj +async def _resolved(awaitable: Any) -> Any: + return await awaitable + + +def _sync_redactor(redact_fn: Callable[[str], Any]) -> Callable[[str], Any]: + """A synchronous view of the customer's hook. + + `RedactionFunction` permits an async hook, and the publish path is a + worker THREAD with no event loop of its own — so an awaitable result has + to be driven to completion here. Left alone it would be assigned straight + into the payload and every "redacted" string would reach the wire as + ``, which is worse than not redacting because it + looks like it worked. One loop per string is not cheap; correctness on a + security control wins, and this runs off the request's hot path. A hook + that cannot be driven raises, and the queue drops the event rather than + publishing it unredacted. + """ + + def redact(value: str) -> Any: + result = redact_fn(value) + if inspect.isawaitable(result): + return asyncio.run(_resolved(result)) + return result + + return redact + + def redact_event(event: "UnredactedEvent", redact_fn: Callable[[str], str]) -> "Event": """ Applies the customer's redaction function to all string fields in an Event object. This is the main entry point for redacting sensitive information from events before they are sent to the analytics service. + `redact_strings_in_object` walks `str` / `list` / `dict` and returns + anything else untouched — so handing it the pydantic event itself, which is + what the publish path holds, returned the event unchanged and made the + documented `redact_sensitive_information` hook a no-op on every real event. + The model is dumped to a plain dict, redacted, and copied back over the + original: `model_copy` rather than a rebuild, so a customer's redaction can + never fail model validation, and fields the walk drops (it skips `None`) + keep the values they already had. + + `redaction_fn` itself is excluded — it is machinery, not event data, and + the customer's hook must not be handed its own function object. + Args: event: The event to redact redact_fn: The customer's redaction function @@ -100,4 +141,16 @@ def redact_event(event: "UnredactedEvent", redact_fn: Callable[[str], str]) -> " Returns: A new event object with all strings redacted """ - return redact_strings_in_object(event, redact_fn, "", False) + redact = _sync_redactor(redact_fn) + # Duck-typed on `model_dump` rather than `isinstance(event, BaseModel)`: + # this module stays free of a pydantic import, and a plain mapping — what + # the unit tests and any caller holding a dict pass — has no such method. + dump = getattr(event, "model_dump", None) + if not callable(dump): + plain: Event = redact_strings_in_object(event, redact, "", False) + return plain + dumped = dump(exclude={"redaction_fn"}, warnings=False) + redacted: Event = event.model_copy( + update=redact_strings_in_object(dumped, redact, "", False) + ) + return redacted diff --git a/src/agentcat/modules/request_extra.py b/src/agentcat/modules/request_extra.py index e35387e..71a2ee8 100644 --- a/src/agentcat/modules/request_extra.py +++ b/src/agentcat/modules/request_extra.py @@ -183,6 +183,21 @@ def extract_request_extra( return extra +def extra_from_request_context( + request_context: Any, + fastmcp_context: Any | None = None, +) -> dict[str, Any]: + """`{"extra": {...}}` ready to merge into an event's `parameters`, or `{}`. + + The v2 adapters build `parameters` as `{"arguments": raw, **extra_params}` + rather than dumping the whole request, so this is the shape they need. The + key is omitted entirely when there is nothing to report (stdio), matching + `params_with_extra` and the TypeScript SDK. + """ + extra = extract_request_extra(request_context, fastmcp_context) + return {"extra": extra} if extra else {} + + def params_with_extra( params_dump: dict | None, request_context: Any, diff --git a/src/agentcat/modules/session.py b/src/agentcat/modules/session.py deleted file mode 100644 index f6d2603..0000000 --- a/src/agentcat/modules/session.py +++ /dev/null @@ -1,200 +0,0 @@ -"""Session management for AgentCat.""" - -import re -import sys -from datetime import datetime, timedelta, timezone - -from mcp.shared.context import RequestContext -from mcp.server import Server - -from agentcat.modules.constants import INACTIVITY_TIMEOUT_IN_MINUTES, SESSION_ID_PREFIX -from agentcat.modules.internal import get_server_tracking_data, set_server_tracking_data -from agentcat.modules.logging import write_to_log - -from ..types import AgentCatData, SessionInfo -from ..utils import generate_prefixed_ksuid - - -def new_session_id() -> str: - """Generate a new session ID.""" - return generate_prefixed_ksuid(SESSION_ID_PREFIX) - - -def get_agentcat_version() -> str | None: - """Get the current AgentCat SDK version.""" - try: - import importlib.metadata - - return importlib.metadata.version("agentcat") - except Exception: - return None - - -def get_headers_from_request_context( - request_context: RequestContext, -) -> dict[str, str] | None: - """Safely extract HTTP headers from a request context. - - Args: - request_context: The request context that may contain a Starlette Request object - - Returns: - A dictionary of headers if available, None otherwise - """ - if request_context is None: - return None - - try: - # Check if the context has a request object with headers - if hasattr(request_context, "request") and request_context.request: - request = request_context.request - if hasattr(request, "headers"): - return dict(request.headers) - except Exception: - pass - - return None - - -def get_client_info_from_request_context( - server: Server, request_context: RequestContext | None -) -> tuple[str | None, str | None]: - """Extract client information from request context or HTTP headers. - - Returns (client_name, client_version). In stateless mode, extracts per-request - without caching. In stateful mode, caches on shared session_info. - - This function is designed to be resilient and never fail - any error is logged - but won't affect the server operation. - """ - # Handle None request_context (e.g., in stateless HTTP mode outside handlers) - if request_context is None: - write_to_log("Request context is None, skipping client info extraction") - return (None, None) - - try: - data = get_server_tracking_data(server) - if not data: - return (None, None) - - client_name: str | None = None - client_version: str | None = None - - # In stateful mode, return cached values if already set - if not data.is_stateless and data.session_info.client_name and data.session_info.client_version: - return (data.session_info.client_name, data.session_info.client_version) - - try: - # Try to get from MCP session (stateful mode) - if hasattr(request_context, "session") and request_context.session: - client_info = request_context.session.client_params.clientInfo - if client_info: - client_name = client_info.name - client_version = client_info.version - if not data.is_stateless: - data.session_info.client_name = client_name - data.session_info.client_version = client_version - set_server_tracking_data(server, data) - return (client_name, client_version) - except (AttributeError, TypeError): - # This is expected in stateless mode, just continue - pass - except Exception as e: - write_to_log(f"Error extracting client info from session: {e}") - - # Fallback: Try to extract from HTTP headers (stateless mode) - try: - headers = get_headers_from_request_context(request_context) - if headers: - # Parse User-Agent header (format: "ClientName/Version ...") - user_agent = headers.get("user-agent", "") - if user_agent: - match = re.match(r"^([^/]+)/([^\s]+)", user_agent) - if match: - client_name = match.group(1) - client_version = match.group(2) - else: - # No neat match, use the whole string as client_name - client_name = user_agent - - # Custom MCP headers override User-Agent if present - if headers.get("x-mcp-client-name"): - client_name = headers.get("x-mcp-client-name") - if headers.get("x-mcp-client-version"): - client_version = headers.get("x-mcp-client-version") - - if not data.is_stateless and (client_name or client_version): - data.session_info.client_name = client_name - data.session_info.client_version = client_version - set_server_tracking_data(server, data) - - if client_name or client_version: - write_to_log( - f"Extracted client info from headers: {client_name} v{client_version}" - ) - except Exception as e: - write_to_log(f"Error extracting client info from headers: {e}") - # Continue without client info - - return (client_name, client_version) - except Exception as e: - # Catch-all for any unexpected errors - log but never fail - write_to_log(f"Unexpected error in get_client_info_from_request_context: {e}") - return (None, None) - - -def get_session_info(server: Server, data: AgentCatData | None = None) -> SessionInfo: - """Get session information for the current MCP session.""" - session_info = SessionInfo( - ip_address=None, # grab from django - sdk_language=f"Python {sys.version_info.major}.{sys.version_info.minor}", - agentcat_version=get_agentcat_version(), - server_name=server.name if hasattr(server, "name") else None, - server_version=server.version if hasattr(server, "version") else None, - client_name=data.session_info.client_name - if data and data.session_info and not data.is_stateless - else None, - client_version=data.session_info.client_version - if data and data.session_info and not data.is_stateless - else None, - identify_actor_given_id=None, - identify_actor_name=None, - identify_data=None, - ) - - if not data: - return session_info - - data.session_info = session_info - set_server_tracking_data(server, data) # Store updated data - return data.session_info - - -def set_last_activity(server: Server) -> None: - data = get_server_tracking_data(server) - - if not data: - raise Exception("AgentCat data not initialized for this server") - - data.last_activity = datetime.now(timezone.utc) - set_server_tracking_data(server, data) - - -def get_server_session_id(server: Server) -> str | None: - data = get_server_tracking_data(server) - - if not data: - raise Exception("AgentCat data not initialized for this server") - - if data.is_stateless: - return None - - now = datetime.now(timezone.utc) - timeout = timedelta(minutes=INACTIVITY_TIMEOUT_IN_MINUTES) - # If last activity timed out - if now - data.last_activity > timeout: - data.session_id = new_session_id() - set_server_tracking_data(server, data) - set_last_activity(server) - - return data.session_id diff --git a/src/agentcat/modules/tools.py b/src/agentcat/modules/tools.py index 71b005f..38ddafd 100644 --- a/src/agentcat/modules/tools.py +++ b/src/agentcat/modules/tools.py @@ -1,11 +1,24 @@ -"""Tool management and interception for AgentCat.""" +"""The get_more_tools descriptor and handler. -from typing import Any, TYPE_CHECKING -from mcp.types import CallToolResult, TextContent -from agentcat.modules.version_detection import has_fastmcp_support +Agent-facing copy here is byte-identical to the TypeScript SDK's +`src/modules/tools.ts` and guarded by tests/test_constants_copy.py. + +`mcp` is imported inside the handler, never at module scope, so this module +loads under either SDK major. +""" + +from typing import TYPE_CHECKING, Any from .logging import write_to_log +if TYPE_CHECKING: + from mcp.types import CallToolResult + +GET_MORE_TOOLS_DESCRIPTION = ( + "Check for additional tools whenever your task might benefit from " + "specialized capabilities - even if existing tools could work as a fallback." +) + # Correct schema for the get_more_tools tool parameter. # Defined explicitly because Pydantic's TypeAdapter generates a broken schema # (anyOf: [string, null], default: "") for Annotated[str, Field(description=...)] @@ -15,30 +28,28 @@ "properties": { "context": { "type": "string", - "description": "A description of your goal and what kind of tool would help accomplish it.", + "description": "A description of your goal and what kind of tool would help accomplish it.", # noqa: E501 } }, "required": ["context"], } -if TYPE_CHECKING or has_fastmcp_support(): - try: - from mcp.server import FastMCP - except ImportError: - FastMCP = None +REPORT_MISSING_RESPONSE_TEXT = ( + "Unfortunately, we have shown you the full tool list. We have noted your " + "feedback and will work to improve the tool list in the future." +) + +async def handle_report_missing(arguments: dict[str, Any]) -> "CallToolResult": + """Answer a get_more_tools call. Never sees the tool list; always the same.""" + from mcp.types import CallToolResult, TextContent -async def handle_report_missing(arguments: dict[str, Any]) -> CallToolResult: - """Handle the report_missing tool.""" - # Metadata-only diagnostics: log the context length, never the context text. + # Metadata-only diagnostics: the context length, never the context text. + context = arguments.get("context") if isinstance(arguments, dict) else None write_to_log( - f"Missing tool reported (context length: {len(arguments.get('context', ''))})" + f"Missing tool reported (context length: " + f"{len(context) if isinstance(context, str) else 0})" ) return CallToolResult( - content=[ - TextContent( - type="text", - text="Unfortunately, we have shown you the full tool list. We have noted your feedback and will work to improve the tool list in the future.", - ) - ] + content=[TextContent(type="text", text=REPORT_MISSING_RESPONSE_TEXT)] ) diff --git a/src/agentcat/modules/version_detection.py b/src/agentcat/modules/version_detection.py deleted file mode 100644 index 8c9c835..0000000 --- a/src/agentcat/modules/version_detection.py +++ /dev/null @@ -1,48 +0,0 @@ -"""MCP version detection utilities.""" - -import importlib.metadata -from typing import Tuple, Optional - - -def get_mcp_version() -> Optional[str]: - """Get the installed MCP version.""" - try: - return importlib.metadata.version("mcp") - except importlib.metadata.PackageNotFoundError: - return None - - -def parse_version(version_str: str) -> Tuple[int, int, int]: - """Parse version string to tuple of integers.""" - parts = version_str.split(".") - major = int(parts[0]) if len(parts) > 0 else 0 - minor = int(parts[1]) if len(parts) > 1 else 0 - patch = int(parts[2]) if len(parts) > 2 else 0 - return (major, minor, patch) - - -def has_fastmcp_support() -> bool: - """Check if the current MCP version supports FastMCP.""" - version = get_mcp_version() - if not version: - return False - - major, minor, _ = parse_version(version) - - # FastMCP was introduced after version 1.1 - if major < 1: - return False - if major == 1 and minor <= 1: - return False - - return True - - -def can_import_fastmcp() -> bool: - """Check if FastMCP can be imported.""" - try: - from mcp.server import FastMCP - - return True - except ImportError: - return False diff --git a/src/agentcat/types.py b/src/agentcat/types.py index 41f15a9..0eebc3c 100644 --- a/src/agentcat/types.py +++ b/src/agentcat/types.py @@ -2,16 +2,32 @@ from collections.abc import Awaitable, Callable from dataclasses import dataclass, field -from datetime import datetime from enum import Enum -from typing import Any, Dict, Optional, Set, TypedDict, Literal, Union, NotRequired -from agentcat_api import PublishEventRequest -from pydantic import BaseModel - -from agentcat.modules.constants import DEFAULT_CONTEXT_DESCRIPTION +from typing import Any, Literal, NotRequired, Optional, TypedDict, Union -# Type alias for identify function -IdentifyFunction = Callable[[dict[str, Any], Any], Optional["UserIdentity"]] +from agentcat_api import PublishEventRequest +from pydantic import field_validator + +from agentcat.modules.constants import ( + AGENTCAT_CUSTOM_EVENT_TYPE, + DEFAULT_CONTEXT_DESCRIPTION, +) + +# Type alias for identify function. +# +# The first argument is the tool call's REQUEST PARAMS — the object carrying +# `.name` and `.arguments` — never the enclosing JSON-RPC request. That is the +# one shape every adapter can produce: mcp 2.x hands its handler `(ctx, params)` +# with no request object in scope, and community FastMCP's `context.message` is +# params as well, so the official 1.x adapter unwraps `request.params` to match. +# Typed `Any` rather than a protocol because the concrete class differs per +# generation (`mcp.types.CallToolRequestParams` on the official SDKs, +# `fastmcp`'s own model on community). The second argument is the adapter's +# request context, whatever it holds on that flavor. +# +# `event_tags`, `event_properties` and `resolve_session_id` all receive this same +# pair — see EventTagsFunction / EventPropertiesFunction / ResolveSessionIdFunction. +IdentifyFunction = Callable[[Any, Any], Optional["UserIdentity"]] # Type alias for redaction function RedactionFunction = Callable[[str], str | Awaitable[str]] # Type alias for event_tags callback — returns str:str map attached to every auto-captured event. @@ -26,6 +42,10 @@ [Any, Any], Optional[dict[str, Any]] | Awaitable[Optional[dict[str, Any]]], ] +# Type alias for the resolve_session_id hook — returns the caller-managed +# session ID, or None. Accepts sync or async callables (mirrors +# RedactionFunction). +ResolveSessionIdFunction = Callable[[Any, Any], str | None | Awaitable[str | None]] @dataclass @@ -37,27 +57,37 @@ class UserIdentity: user_data: dict[str, str] | None -class SessionInfo(BaseModel): - """Session information for tracking.""" - - ip_address: Optional[str] = None - sdk_language: Optional[str] = None - agentcat_version: Optional[str] = None - server_name: Optional[str] = None - server_version: Optional[str] = None - client_name: Optional[str] = None - client_version: Optional[str] = None - identify_actor_given_id: Optional[str] = None # Actor ID for agentcat:identify events - identify_actor_name: Optional[str] = None # Actor name for agentcat:identify events - identify_data: Optional[dict[str, Any]] = None - - class Event(PublishEventRequest): # The generated client marks project_id as required on the wire, but the SDK # constructs events before the project ID is known: event_queue merges it in # at publish time, and telemetry-only mode sends events without one. project_id: Optional[str] = None + @field_validator("event_type") + @classmethod + def event_type_validate_enum(cls, value: str | None) -> str | None: + """Validate against what THIS SDK publishes, not the generated enum. + + `agentcat_api` 1.0.0 enforces the OpenAPI spec's `event_type` list, + which predates `agentcat:custom` — the backend has accepted that type + since TS 2.0, but the generated model rejects it. Left alone, every + custom event would fail construction inside the publish path's + try/except and vanish without a trace. `EventType` below is the source + of truth for the (two) types v2 emits; it is resolved at call time, so + forward-declaring it here is fine. + + The NAME is load-bearing: pydantic keys collected validators by + attribute name, so this supersedes the generated one only because it + matches `agentcat_api`'s exactly. Renaming it to something more + idiomatic silently reinstates the stale enum — and silently re-breaks + custom events. `tests/test_publish_custom_event.py` has the tripwire. + """ + if value is None or value in {member.value for member in EventType}: + return value + raise ValueError( + "must be one of " + str(sorted(member.value for member in EventType)) + ) + # Error tracking types @@ -97,38 +127,22 @@ class ErrorData(TypedDict, total=False): class EventType(str, Enum): - """MCP event types.""" - - MCP_PING = "mcp:ping" - MCP_INITIALIZE = "mcp:initialize" - MCP_COMPLETION_COMPLETE = "mcp:completion/complete" - MCP_LOGGING_SET_LEVEL = "mcp:logging/setLevel" - MCP_PROMPTS_GET = "mcp:prompts/get" - MCP_PROMPTS_LIST = "mcp:prompts/list" - MCP_RESOURCES_LIST = "mcp:resources/list" - MCP_RESOURCES_TEMPLATES_LIST = "mcp:resources/templates/list" - MCP_RESOURCES_READ = "mcp:resources/read" - MCP_RESOURCES_SUBSCRIBE = "mcp:resources/subscribe" - MCP_RESOURCES_UNSUBSCRIBE = "mcp:resources/unsubscribe" + """The event types AgentCat 2.0 publishes. + + Two, and only two. `mcp:initialize`, `mcp:tools/list` and + `agentcat:identify` are gone (changelog §3.1): tools/list is still + intercepted for schema injection but emits nothing, and the actor the + `identify` hook returns rides on the tool-call event instead. + """ + MCP_TOOLS_CALL = "mcp:tools/call" - MCP_TOOLS_LIST = "mcp:tools/list" - AGENTCAT_IDENTIFY = "agentcat:identify" + AGENTCAT_CUSTOM = AGENTCAT_CUSTOM_EVENT_TYPE class UnredactedEvent(Event): redaction_fn: RedactionFunction | None = None -@dataclass -class ToolRegistration: - """Metadata about a registered tool.""" - - name: str - registered_at: datetime - tracked: bool = False - wrapped: bool = False - - # Telemetry Exporter Configuration Types @@ -179,7 +193,6 @@ class AgentCatOptions: exporters: dict[str, ExporterConfig] | None = None debug_mode: bool = False api_base_url: str | None = None - stateless: bool | None = None # Disables AgentCat's internal SDK diagnostics — anonymous, metadata-only # setup/error reporting used to detect failed installs. On by default; also # disable-able via the DISABLE_DIAGNOSTICS env var. Automatically disabled in @@ -187,8 +200,8 @@ class AgentCatOptions: # never send anything; set DISABLE_DIAGNOSTICS=false to re-enable there. Never # sends event payloads or user data; the local ~/agentcat.log is unaffected. disable_diagnostics: bool = False - # Callback invoked on every auto-captured event (initialize, tools/list, - # tools/call) to attach string key-value tags. Tags are intended for + # Callback invoked on every auto-captured event (one per tool call) to + # attach string key-value tags. Tags are intended for # structured metadata you'll filter or group by in the AgentCat dashboard # (e.g. trace IDs, environments, regions). Validated client-side: keys # must be <=32 chars matching [a-zA-Z0-9$_.:\- ], values must be strings @@ -204,21 +217,73 @@ class AgentCatOptions: # (stricter than the TypeScript SDK). May be sync or async. If the callback # raises or returns None, properties are omitted. event_properties: EventPropertiesFunction | None = None + # Default False. Set True to inject a required agent_id parameter into every + # tool. Agents self-generate the value (model|harness|nonce, e.g. + # "opus-4.80-1m|claude-code|k3n9x"); it is echoed back in _mcp_instructions + # and stamped on events as tags. Omission never rejects a call server-side — + # the event is simply published without agent identity. The intended + # enforcement is client-side: a strict schema-validating MCP client will + # refuse to send a call that omits a required agent_id in the first place. + enable_agent_tracking: bool = False + # Hook mode: you manage session state. When configured, AgentCat injects no + # session_id parameter and prompts no session instructions; the returned value is + # combined with the project ID into a deterministic ses_ KSUID. None returns + # and raises mint silently — a configured hook should answer every request. + # May be sync or async. Receives the same (request, extra) arguments as + # `identify`. + resolve_session_id: ResolveSessionIdFunction | None = None @dataclass class AgentCatData: - """Internal data structure for tracking.""" + """Per-server tracking state (spec §3.3). + + Nothing here is per-request. v1 kept a session ID, an idle clock, a cached + metadata object and a registry of tools on this object; 2.0 resolves all of + that per call, so what survives is the project, the customer's options, and + the engine state that is genuinely per-server. + """ project_id: str | None - session_id: str - session_info: SessionInfo - last_activity: datetime options: AgentCatOptions - # Dynamic tracking fields (initialized on demand) - tool_registry: Dict[str, ToolRegistration] = field(default_factory=dict) - wrapped_tools: Set[str] = field(default_factory=set) - tracker_initialized: bool = False - monkey_patched: bool = False - is_stateless: bool = False + # v2 engine state + # Per-tool set of parameter names AgentCat injected into the schema + # (context/session_id/agent_id), so they can be stripped before the tool runs. + injected_params_registry: dict[str, set[str]] | None = None + # Tools whose results receive an _mcp_instructions injection. + output_injection_registry: set[str] | None = None + # Tools whose OWN input schema declares `session_id` — the customer's + # parameter, never ours to read at call time. Membership only ever grows; + # a tool that once declared the name stays foreign until the process + # restarts, which is the conservative direction, since the alternative is + # adopting a value that is not ours into an unredactable field. + declared_session_params: set[str] = field(default_factory=set) + # Tools whose `session_id` collision has already been reported, so the + # per-listing pipeline logs it once rather than for the life of the + # process. + reported_conflicts: set[str] = field(default_factory=set) + # The server's original tools/list source, kept so wrapped lists can be + # rebuilt from the unmodified definitions. + original_list_source: Any = None + # Server identity captured at track time; stamped onto every event at + # publish time, since there is no session cache to read it from. + server_name: str | None = None + server_version: str | None = None + + +# Custom event types for the publish_custom_event function +class CustomEventData(TypedDict, total=False): + """Optional fields describing a custom event.""" + + # Session ID to attribute this event to. + session_id: str + resource_name: str + parameters: Any + response: Any + message: str + duration: int # milliseconds + is_error: bool + error: Any + tags: dict[str, str] + properties: dict[str, Any] diff --git a/src/agentcat/utils.py b/src/agentcat/utils.py index 134a54e..00196fd 100644 --- a/src/agentcat/utils.py +++ b/src/agentcat/utils.py @@ -6,6 +6,20 @@ from .thirdparty.ksuid import Ksuid, KsuidMs +def get_agentcat_version() -> str | None: + """The installed AgentCat SDK version, or None if it cannot be read. + + Lives here rather than in the package root so the event pipeline and the + telemetry exporters can stamp it without importing `agentcat` itself. + """ + try: + import importlib.metadata + + return importlib.metadata.version("agentcat") + except Exception: + return None + + def generate_ksuid( use_milliseconds: bool = False, dt: Optional[datetime] = None ) -> str: diff --git a/tests/community/__init__.py b/tests/community/__init__.py index e3e9355..13a33e8 100644 --- a/tests/community/__init__.py +++ b/tests/community/__init__.py @@ -1 +1 @@ -"""Community FastMCP test suite.""" \ No newline at end of file +"""Community FastMCP test suite.""" diff --git a/tests/community/test_community_dynamic_tracking.py b/tests/community/test_community_dynamic_tracking.py deleted file mode 100644 index 56ab5dd..0000000 --- a/tests/community/test_community_dynamic_tracking.py +++ /dev/null @@ -1,412 +0,0 @@ -"""Tests for dynamic tracking with community FastMCP.""" - - -import pytest - -from agentcat import track -from agentcat.modules.internal import ( - get_server_tracking_data, - get_tool_timeline, - reset_all_tracking_data, -) -from agentcat.types import AgentCatOptions - -from ..test_utils.community_client import create_community_test_client -from ..test_utils.community_todo_server import ( - HAS_COMMUNITY_FASTMCP, - create_community_todo_server, - get_lowlevel_server, - get_server_tools, -) - -# Skip all tests if community FastMCP is not available -pytestmark = pytest.mark.skipif( - not HAS_COMMUNITY_FASTMCP, - reason="Community FastMCP not available. Install with: pip install fastmcp" -) - - -class TestCommunityDynamicTracking: - """Test suite for dynamic tool tracking with community FastMCP.""" - - @pytest.fixture(autouse=True) - def setup(self): - """Reset the tracker before each test.""" - reset_all_tracking_data() - yield - reset_all_tracking_data() - - @pytest.mark.asyncio - async def test_dynamic_tracking_early_registration(self): - """Test that tools registered before track() are tracked and work correctly.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - # Register tools before tracking - @server.tool - def early_tool(x: int) -> str: - return str(x) - - # Enable tracking - track(server, "test-project") - - # Test the tool actually works - async with create_community_test_client(server) as client: - result = await client.call_tool("early_tool", {"x": 42}) - assert "42" in str(result), f"Expected '42' in result, got {result}" - - # Test with different value - result2 = await client.call_tool("early_tool", {"x": 999}) - assert "999" in str(result2), f"Expected '999' in result, got {result2}" - - # Verify tool is tracked - data = get_server_tracking_data(get_lowlevel_server(server)) - assert data and "early_tool" in data.tool_registry - assert data.tool_registry["early_tool"].tracked - - @pytest.mark.asyncio - async def test_dynamic_tracking_late_registration(self): - """Test that late-registered tools are tracked with dynamic mode.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - # Enable tracking first - track(server, "test-project") - - # Register tool after tracking - @server.tool - def late_tool(x: int) -> str: - return str(x) - - # Test the tool actually works - async with create_community_test_client(server) as client: - result = await client.call_tool("late_tool", {"x": 123}) - assert "123" in str(result), f"Expected '123' in result, got {result}" - - # Test with another value - result2 = await client.call_tool("late_tool", {"x": -456}) - assert "-456" in str(result2), f"Expected '-456' in result, got {result2}" - - # Verify tool is tracked - data = get_server_tracking_data(get_lowlevel_server(server)) - assert data and "late_tool" in data.tool_registry - assert data.tool_registry["late_tool"].tracked - - @pytest.mark.asyncio - async def test_late_registration_always_tracked(self): - """Test that late registrations are always tracked and function correctly.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - # Enable tracking - track(server, "test-project") - - # Register tool after tracking - @server.tool - def late_tool_always_tracked(x: int) -> str: - return str(x) - - # Test the tool works correctly - async with create_community_test_client(server) as client: - result = await client.call_tool("late_tool_always_tracked", {"x": 777}) - assert "777" in str(result), f"Expected '777' in result, got {result}" - - # Test with zero - result2 = await client.call_tool("late_tool_always_tracked", {"x": 0}) - assert "0" in str(result2), f"Expected '0' in result, got {result2}" - - # Check that it's tracked - data = get_server_tracking_data(get_lowlevel_server(server)) - assert data and "late_tool_always_tracked" in data.tool_registry - assert data.tool_registry["late_tool_always_tracked"].tracked - - @pytest.mark.asyncio - async def test_dynamic_tool_execution_tracking(self): - """Test that dynamically added tools are tracked during execution.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - # Enable tracking - track(server, "test-project") - - # Add tool after tracking - @server.tool - async def dynamic_tool(x: int) -> str: - return f"Result: {x}" - - # Call the tool through client and verify results - async with create_community_test_client(server) as client: - result = await client.call_tool("dynamic_tool", {"x": 42}) - assert "Result: 42" in str(result) - - # Test with different value - result2 = await client.call_tool("dynamic_tool", {"x": 100}) - assert "Result: 100" in str(result2) - - # Test with negative value - result3 = await client.call_tool("dynamic_tool", {"x": -5}) - assert "Result: -5" in str(result3) - - # Verify tracking - data = get_server_tracking_data(get_lowlevel_server(server)) - assert data and "dynamic_tool" in data.tool_registry - assert data.tool_registry["dynamic_tool"].tracked - - @pytest.mark.asyncio - async def test_tool_timeline(self): - """Test tool registration timeline tracking and that both tools work.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - # Register first tool - @server.tool - def tool1(x: int) -> str: - return str(x) - - # Enable tracking - options = AgentCatOptions() - track(server, "test-project", options) - - # Register second tool - @server.tool - def tool2(x: int) -> str: - return str(x * 2) # Different logic to distinguish - - # Test both tools work correctly - async with create_community_test_client(server) as client: - result1 = await client.call_tool("tool1", {"x": 5}) - assert "5" in str(result1), f"tool1: Expected '5' in result, got {result1}" - - result2 = await client.call_tool("tool2", {"x": 5}) - assert "10" in str(result2) - - # Test with different values - result3 = await client.call_tool("tool1", {"x": 100}) - assert "100" in str(result3) - - result4 = await client.call_tool("tool2", {"x": 100}) - assert "200" in str(result4) - - # Get timeline - timeline = get_tool_timeline(get_lowlevel_server(server)) - - # Should have both tools in timeline - tool_names = [t["name"] for t in timeline] - assert "tool1" in tool_names - assert "tool2" in tool_names - - # Timeline should be sorted by registration time - for i in range(1, len(timeline)): - assert timeline[i]["registered_at"] >= timeline[i - 1]["registered_at"] - - @pytest.mark.asyncio - async def test_context_injection_with_dynamic_tracking(self): - """Test that context injection works with dynamic tracking.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - # Enable tracking with context - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test-project", options) - - # Add tool after tracking - @server.tool - def context_tool(x: int) -> str: - return str(x * 3) # Multiply by 3 to verify logic - - # Test the tool works with context parameter - async with create_community_test_client(server) as client: - result = await client.call_tool( - "context_tool", - {"x": 7, "context": "Testing context injection"} - ) - assert "21" in str(result), f"Expected '21' in result, got {result}" - - # Test without context (should still work as context is stripped) - result2 = await client.call_tool("context_tool", {"x": 10}) - assert "30" in str(result2), f"Expected '30' in result, got {result2}" - - # Test with empty context - result3 = await client.call_tool( - "context_tool", - {"x": 4, "context": ""} - ) - assert "12" in str(result3), f"Expected '12' in result, got {result3}" - - # List tools should show context parameter - tools = await get_server_tools(server) - - # Find our tool - context_tool_def = tools.get("context_tool") - assert context_tool_def is not None - - # Should have context in parameters - if hasattr(context_tool_def, "parameters"): - schema = context_tool_def.parameters - if schema and "properties" in schema: - assert "context" in schema["properties"] - - @pytest.mark.asyncio - async def test_report_missing_tool_with_dynamic_tracking(self): - """Test that get_more_tools is added with dynamic tracking.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - # Enable tracking with report_missing - options = AgentCatOptions(enable_report_missing=True) - track(server, "test-project", options) - - # Test calling get_more_tools - async with create_community_test_client(server) as client: - result = await client.call_tool( - "get_more_tools", - {"context": "Need a tool to translate text"} - ) - # Should return the standard "Unfortunately" message - assert "Unfortunately" in str(result) - - # Test with empty context - result2 = await client.call_tool("get_more_tools", {"context": ""}) - assert "Unfortunately" in str(result2) - - # Test with missing context parameter - should raise ToolError - # since context is a required parameter - with pytest.raises(Exception, match="(?i)required"): - await client.call_tool("get_more_tools", {}) - - # List tools - tools = await get_server_tools(server) - - # Should include get_more_tools - tool_names = list(tools.keys()) - assert "get_more_tools" in tool_names - - @pytest.mark.asyncio - async def test_multiple_servers_isolation(self): - """Test that multiple servers can be tracked independently.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server1 = FastMCP("server1") - server2 = FastMCP("server2") - - # Track both servers - options = AgentCatOptions() - track(server1, "project1", options) - track(server2, "project2", options) - - # Add tools to each server - @server1.tool - def server1_tool(x: int) -> str: - return f"Server1: {x}" - - @server2.tool - def server2_tool(x: int) -> str: - return f"Server2: {x}" - - # Test server1 tool works correctly - async with create_community_test_client(server1) as client: - result1 = await client.call_tool("server1_tool", {"x": 10}) - assert "Server1: 10" in str(result1) - - result1b = await client.call_tool("server1_tool", {"x": 25}) - assert "Server1: 25" in str(result1b) - - # Test server2 tool works correctly - async with create_community_test_client(server2) as client: - result2 = await client.call_tool("server2_tool", {"x": 20}) - assert "Server2: 20" in str(result2) - - result2b = await client.call_tool("server2_tool", {"x": 50}) - assert "Server2: 50" in str(result2b) - - # Verify both tools are tracked separately - data1 = get_server_tracking_data(get_lowlevel_server(server1)) - data2 = get_server_tracking_data(get_lowlevel_server(server2)) - assert data1 and "server1_tool" in data1.tool_registry - assert data2 and "server2_tool" in data2.tool_registry - - @pytest.mark.asyncio - async def test_existing_todo_server_tools(self): - """Test dynamic tracking with the pre-configured todo server.""" - server = create_community_todo_server() - - # Enable tracking - options = AgentCatOptions() - track(server, "test-project", options) - - # Test existing tools work correctly - async with create_community_test_client(server) as client: - # Test add_todo - add_result = await client.call_tool("add_todo", {"text": "Test todo item"}) - assert "Added todo" in str(add_result) - - # Test list_todos - list_result = await client.call_tool("list_todos", {}) - assert "Test todo item" in str(list_result) - - # Test complete_todo - complete_result = await client.call_tool("complete_todo", {"id": 1}) - assert "Completed todo" in str(complete_result) - - # Verify existing tools are tracked - data = get_server_tracking_data(get_lowlevel_server(server)) - assert data - assert "add_todo" in data.tool_registry - assert "list_todos" in data.tool_registry - assert "complete_todo" in data.tool_registry - - # Add a new tool dynamically - @server.tool - def delete_todo(id: int) -> str: - return f"Deleted todo {id}" - - # In v3, tools are registered when list_tools or call_tool is invoked - # So we need to list tools or call the tool to trigger registration - - # Test new tool execution through client - async with create_community_test_client(server) as client: - result = await client.call_tool("delete_todo", {"id": 1}) - assert "Deleted todo 1" in str(result) - - # Test with different ID - result2 = await client.call_tool("delete_todo", {"id": 999}) - assert "Deleted todo 999" in str(result2) - - # After calling the tool, it should be registered - data = get_server_tracking_data(get_lowlevel_server(server)) - assert "delete_todo" in data.tool_registry - - -if __name__ == "__main__": - pytest.main([__file__, "-v"]) diff --git a/tests/community/test_community_event_capture.py b/tests/community/test_community_event_capture.py deleted file mode 100644 index 84ab85f..0000000 --- a/tests/community/test_community_event_capture.py +++ /dev/null @@ -1,375 +0,0 @@ -"""Test event capture completeness with community FastMCP.""" - -import time -from datetime import datetime -from unittest.mock import MagicMock - -import pytest - -from agentcat import AgentCatOptions, track -from agentcat.modules.event_queue import EventQueue, set_event_queue -from agentcat.modules.internal import ( - get_server_tracking_data, - set_server_tracking_data, -) -from agentcat.types import UserIdentity - -from ..test_utils.community_client import create_community_test_client -from ..test_utils.community_todo_server import ( - HAS_COMMUNITY_FASTMCP, - create_community_todo_server, - get_lowlevel_server, -) - -# Skip all tests if community FastMCP is not available -pytestmark = pytest.mark.skipif( - not HAS_COMMUNITY_FASTMCP, - reason="Community FastMCP not available. Install with: pip install fastmcp" -) - - -class TestCommunityEventCapture: - """Test that all required fields are captured in events with community FastMCP.""" - - @pytest.fixture(autouse=True) - def setup_and_teardown(self): - """Set up and tear down for each test.""" - # Store original event queue - from agentcat.modules.event_queue import event_queue as original_queue - - yield - # Restore original event queue after test - set_event_queue(original_queue) - - @pytest.mark.asyncio - async def test_event_contains_all_basic_fields(self): - """Test that events contain all basic required fields.""" - # Create a mock API client - mock_api_client = MagicMock() - captured_events = [] - - def capture_event(publish_event_request): - captured_events.append(publish_event_request) - - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - - # Create event queue with mock - test_queue = EventQueue(api_client=mock_api_client) - set_event_queue(test_queue) - - # Create and track server - server = create_community_todo_server() - options = AgentCatOptions(enable_tracing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Make a tool call to generate an event - await client.call_tool("add_todo", {"text": "Test todo"}) - - # Wait for event processing - time.sleep(1.0) - - # Find the tool call event - tool_events = [e for e in captured_events if e.event_type == "mcp:tools/call"] - assert len(tool_events) > 0, "No tool call event captured" - - event = tool_events[0] - - # Verify all basic fields are present - assert event.project_id == "test_project" - assert event.event_type == "mcp:tools/call" - assert event.resource_name == "add_todo" - assert event.timestamp is not None - assert isinstance(event.timestamp, datetime) - assert event.duration is not None - assert isinstance(event.duration, int) - assert event.parameters is not None - assert event.parameters.get("arguments") == {"text": "Test todo"} - - # Verify event has its own ID - assert event.id is not None - assert event.id.startswith("evt_") - assert len(event.id) > 10 # Should be a proper KSUID - - @pytest.mark.asyncio - async def test_event_contains_server_info(self): - """Test that events capture server name and version.""" - mock_api_client = MagicMock() - captured_events = [] - - def capture_event(publish_event_request): - captured_events.append(publish_event_request) - - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - - test_queue = EventQueue(api_client=mock_api_client) - set_event_queue(test_queue) - - server = create_community_todo_server() - options = AgentCatOptions(enable_tracing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - await client.call_tool("add_todo", {"text": "Test"}) - time.sleep(1.0) - - tool_events = [e for e in captured_events if e.event_type == "mcp:tools/call"] - assert len(tool_events) > 0 - - event = tool_events[0] - - # Server info should be captured - assert event.server_name == "todo-server" - - @pytest.mark.asyncio - async def test_event_contains_user_intent_from_context(self): - """Test that events capture user intent when tool context is enabled.""" - mock_api_client = MagicMock() - captured_events = [] - - def capture_event(publish_event_request): - captured_events.append(publish_event_request) - - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - - test_queue = EventQueue(api_client=mock_api_client) - set_event_queue(test_queue) - - server = create_community_todo_server() - options = AgentCatOptions(enable_tracing=True, enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Call tool with context parameter - await client.call_tool( - "add_todo", - { - "text": "Buy groceries", - "context": "User wants to add a reminder to buy groceries", - }, - ) - time.sleep(1.0) - - tool_events = [e for e in captured_events if e.event_type == "mcp:tools/call"] - assert len(tool_events) > 0 - - event = tool_events[0] - - # User intent should be captured from context - assert event.user_intent == ( - "User wants to add a reminder to buy groceries" - ) - - @pytest.mark.asyncio - async def test_event_contains_actor_info_after_identify(self): - """Test that events contain actor information after identify is called.""" - mock_api_client = MagicMock() - captured_events = [] - - def capture_event(publish_event_request): - captured_events.append(publish_event_request) - - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - - test_queue = EventQueue(api_client=mock_api_client) - set_event_queue(test_queue) - - def identify_fn(request, context): - return UserIdentity( - user_id="user123", - user_name="John Doe", - user_data={"email": "john@example.com", "role": "admin"}, - ) - - server = create_community_todo_server() - options = AgentCatOptions(enable_tracing=True, identify=identify_fn) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - await client.call_tool("add_todo", {"text": "Test 1"}) - time.sleep(0.5) - await client.call_tool("add_todo", {"text": "Test 2"}) - time.sleep(1.0) - - tool_events = [e for e in captured_events if e.event_type == "mcp:tools/call"] - assert len(tool_events) >= 2 - - for event in tool_events[:2]: - assert event.identify_actor_given_id == "user123" - assert event.identify_actor_name == "John Doe" - assert event.identify_data == { - "email": "john@example.com", - "role": "admin", - } - - @pytest.mark.asyncio - async def test_multiple_event_types_capture_all_fields(self): - """Test that different event types all capture required fields.""" - mock_api_client = MagicMock() - captured_events = [] - - def capture_event(publish_event_request): - captured_events.append(publish_event_request) - - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - - test_queue = EventQueue(api_client=mock_api_client) - set_event_queue(test_queue) - - server = create_community_todo_server() - options = AgentCatOptions(enable_tracing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Generate various event types - await client.list_tools() # mcp:tools/list - await client.call_tool("add_todo", {"text": "Test"}) # mcp:tools/call - await client.call_tool("list_todos", {}) # Another tool call - time.sleep(1.0) - - # Check all captured events - assert len(captured_events) >= 3 - - # Verify each event has all required fields - for event in captured_events: - # Basic fields - assert event.project_id == "test_project" - assert event.event_type is not None - assert event.timestamp is not None - assert event.id is not None - assert event.id.startswith("evt_") - - # Session info fields - assert event.server_name == "todo-server" - - @pytest.mark.asyncio - async def test_event_ids_are_unique(self): - """Test that each event gets a unique ID.""" - mock_api_client = MagicMock() - captured_events = [] - - def capture_event(publish_event_request): - captured_events.append(publish_event_request) - - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - - test_queue = EventQueue(api_client=mock_api_client) - set_event_queue(test_queue) - - server = create_community_todo_server() - options = AgentCatOptions(enable_tracing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Generate multiple events - for i in range(5): - await client.call_tool("add_todo", {"text": f"Todo {i}"}) - time.sleep(1.0) - - # Focus on tool call events - tool_call_events = [ - e for e in captured_events - if e.event_type == "mcp:tools/call" - ] - - assert len(tool_call_events) >= 5, ( - f"Expected at least 5 tool call events, got {len(tool_call_events)}" - ) - - # Extract tool call event IDs - tool_call_ids = [e.id for e in tool_call_events] - - # All tool call IDs should be unique - assert len(tool_call_ids) == len(set(tool_call_ids)), ( - f"Tool call event IDs are not unique: {tool_call_ids}" - ) - - # All IDs should have proper format - for event_id in tool_call_ids: - assert event_id.startswith("evt_") - assert len(event_id) > 10 - - @pytest.mark.asyncio - async def test_event_duration_is_calculated(self): - """Test that event duration is properly calculated.""" - mock_api_client = MagicMock() - captured_events = [] - - def capture_event(publish_event_request): - captured_events.append(publish_event_request) - - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - - test_queue = EventQueue(api_client=mock_api_client) - set_event_queue(test_queue) - - server = create_community_todo_server() - options = AgentCatOptions(enable_tracing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Add a small delay in the tool to ensure measurable duration - await client.call_tool("add_todo", {"text": "Test with duration"}) - time.sleep(1.0) - - tool_events = [e for e in captured_events if e.event_type == "mcp:tools/call"] - assert len(tool_events) > 0 - - event = tool_events[0] - - # Duration should be present and reasonable - assert event.duration is not None - assert isinstance(event.duration, int) - assert event.duration >= 0 # Should be non-negative - assert event.duration < 10000 # Should be less than 10 seconds - - @pytest.mark.asyncio - async def test_server_error_capture_in_event(self): - """Test that errors are captured in the event's is_error and error fields.""" - mock_api_client = MagicMock() - captured_events = [] - - def capture_event(publish_event_request): - captured_events.append(publish_event_request) - - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - - test_queue = EventQueue(api_client=mock_api_client) - set_event_queue(test_queue) - - server = create_community_todo_server() - options = AgentCatOptions(enable_tracing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Try to complete a non-existent todo to trigger an error - try: - await client.call_tool("complete_todo", {"id": 999}) - except Exception: - # The client might raise an exception, but we're interested in the event - pass - - time.sleep(1.0) - - # Find the tool call event for complete_todo - tool_events = [ - e - for e in captured_events - if e.event_type == "mcp:tools/call" and e.resource_name == "complete_todo" - ] - assert len(tool_events) > 0, "No complete_todo tool call event captured" - - event = tool_events[0] - - # Verify error fields are populated - assert event.is_error is True, "Event should be marked as error" - assert event.error is not None, "Event should have error details" - assert isinstance(event.error, dict), "Error should be a dictionary" - assert "message" in event.error, "Error should have a message" - assert "Todo with ID 999 not found" in event.error["message"], ( - "Error message should contain the ValueError message" - ) - - -if __name__ == "__main__": - pytest.main([__file__, "-v"]) diff --git a/tests/community/test_community_fastmcp.py b/tests/community/test_community_fastmcp.py deleted file mode 100644 index 836e3ca..0000000 --- a/tests/community/test_community_fastmcp.py +++ /dev/null @@ -1,191 +0,0 @@ -"""Basic tests for Community FastMCP integration with AgentCat.""" - -import pytest - -from agentcat import AgentCatOptions, track - -from ..test_utils.community_client import create_community_test_client -from ..test_utils.community_todo_server import ( - HAS_COMMUNITY_FASTMCP, - create_community_todo_server, -) - -# Skip all tests if community FastMCP is not available -pytestmark = pytest.mark.skipif( - not HAS_COMMUNITY_FASTMCP, - reason="Community FastMCP not available. Install with: pip install fastmcp" -) - - -class TestCommunityFastMCPBasics: - """Test basic Community FastMCP functionality.""" - - @pytest.mark.asyncio - async def test_create_server(self): - """Test creating a community FastMCP server.""" - server = create_community_todo_server() - assert server.name == "todo-server" - # v2 has _mcp_server, v3 has _local_provider - assert hasattr(server, "_mcp_server") or hasattr(server, "_local_provider") - - @pytest.mark.asyncio - async def test_tool_registration(self): - """Test that tools are registered correctly.""" - server = create_community_todo_server() - - # v2: get_tools() returns dict, v3: list_tools() returns list - if hasattr(server, "list_tools"): - # v3 API - tools = await server.list_tools() - tool_names = [t.name for t in tools] - elif hasattr(server, "get_tools"): - # v2 API - tools = await server.get_tools() - tool_names = list(tools.keys()) - else: - raise AssertionError("Server has no tool listing method") - - assert "add_todo" in tool_names - assert "list_todos" in tool_names - assert "complete_todo" in tool_names - - @pytest.mark.asyncio - async def test_is_community_fastmcp_server(self): - """Test is_community_fastmcp_server identifies community FastMCP.""" - from agentcat.modules.compatibility import ( - is_community_fastmcp_server, - is_compatible_server, - is_official_fastmcp_server, - ) - - server = create_community_todo_server() - - # Should be identified as community FastMCP - assert is_community_fastmcp_server(server) is True, ( - "Server should be identified as community FastMCP" - ) - - # Should NOT be identified as official FastMCP - assert is_official_fastmcp_server(server) is False, ( - "Server should NOT be identified as official FastMCP" - ) - - # Should be compatible with AgentCat - assert is_compatible_server(server) is True, ( - "Server should be compatible with AgentCat" - ) - - - @pytest.mark.asyncio - async def test_tool_execution(self): - """Test executing tools through community client.""" - server = create_community_todo_server() - - async with create_community_test_client(server) as client: - # Add a todo - result = await client.call_tool("add_todo", {"text": "Test todo"}) - assert "Added todo" in str(result) - assert "Test todo" in str(result) - - # List todos - result = await client.call_tool("list_todos", {}) - assert "Test todo" in str(result) - assert "○" in str(result) # Not completed - - # Complete the todo - result = await client.call_tool("complete_todo", {"id": 1}) - assert "Completed todo" in str(result) - - # List todos again to verify completion - result = await client.call_tool("list_todos", {}) - assert "Test todo" in str(result) - assert "✓" in str(result) # Completed - - -class TestCommunityFastMCPWithAgentCat: - """Test Community FastMCP integration with AgentCat tracking.""" - - @pytest.mark.asyncio - async def test_agentcat_tracking_basic(self): - """Test that AgentCat can track a community FastMCP server.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=False) - - # This will likely fail initially due to incompatibilities - # but demonstrates the intended usage - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Test that tracking doesn't break basic functionality - result = await client.call_tool("add_todo", {"text": "AgentCat test"}) - assert "Added todo" in str(result) - - @pytest.mark.asyncio - async def test_agentcat_tracking_with_context(self): - """Test AgentCat context injection with community FastMCP.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - - # Track the server with context enabled - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # List tools to check if context was added - tools = await client.list_tools() - - # Check if context parameter was injected - # This is expected to fail, demonstrating incompatibility - for tool in tools: - if tool.name in ["add_todo", "list_todos", "complete_todo"]: - # Community FastMCP might handle schemas differently - schema = ( - getattr(tool, "inputSchema", None) - or getattr(tool, "input_schema", None) - ) - assert schema is not None, ( - f"Tool {tool.name} has no input schema" - ) - assert "properties" in schema, ( - f"Tool {tool.name} schema has no properties" - ) - - # This assertion will fail, showing that AgentCat's context injection - # doesn't work with community FastMCP - assert "context" in schema["properties"], ( - f"Tool {tool.name} is missing 'context' parameter. " - f"Properties found: {list(schema['properties'].keys())}" - ) - - @pytest.mark.asyncio - async def test_multiple_operations(self): - """Test multiple todo operations in sequence.""" - server = create_community_todo_server() - - async with create_community_test_client(server) as client: - # Add multiple todos - await client.call_tool("add_todo", {"text": "First todo"}) - await client.call_tool("add_todo", {"text": "Second todo"}) - await client.call_tool("add_todo", {"text": "Third todo"}) - - # List all todos - result = await client.call_tool("list_todos", {}) - result_str = str(result) - - assert "First todo" in result_str - assert "Second todo" in result_str - assert "Third todo" in result_str - - # Complete middle todo - await client.call_tool("complete_todo", {"id": 2}) - - # Verify only the middle one is completed - result = await client.call_tool("list_todos", {}) - lines = str(result).split("\n") - - # These assertions assume the result format - # They might need adjustment based on actual output - for line in lines: - if "Second todo" in line: - assert "✓" in line - elif "First todo" in line or "Third todo" in line: - assert "○" in line diff --git a/tests/community/test_community_report_missing.py b/tests/community/test_community_report_missing.py deleted file mode 100644 index 9db041c..0000000 --- a/tests/community/test_community_report_missing.py +++ /dev/null @@ -1,404 +0,0 @@ -"""Test report_missing functionality with community FastMCP.""" - -import pytest -from unittest.mock import MagicMock -import time - -from agentcat import AgentCatOptions, track - -from ..test_utils.community_client import create_community_test_client -from ..test_utils.community_todo_server import ( - HAS_COMMUNITY_FASTMCP, - create_community_todo_server, -) - -# Skip all tests if community FastMCP is not available -pytestmark = pytest.mark.skipif( - not HAS_COMMUNITY_FASTMCP, - reason="Community FastMCP not available. Install with: pip install fastmcp" -) - - -class TestCommunityReportMissing: - """Test report_missing functionality with community FastMCP.""" - - @pytest.mark.asyncio - async def test_report_missing_tool_injection(self): - """Test that report_missing tool is properly injected when enabled.""" - server = create_community_todo_server() - - # Track the server with report_missing enabled - options = AgentCatOptions(enable_report_missing=True) - track(server, "test_project", options) - - # Use client to list all tools and verify report_missing is injected - async with create_community_test_client(server) as client: - # List all tools on the server - tools_result = await client.list_tools() - - # Get tool names - tool_names = [tool.name for tool in tools_result] - - # Verify original tools are present - assert "add_todo" in tool_names - assert "list_todos" in tool_names - assert "complete_todo" in tool_names - - # Verify report_missing tool was injected - assert "get_more_tools" in tool_names - - @pytest.mark.asyncio - async def test_report_missing_tool_schema(self): - """Test that get_more_tools has context as a required string, not anyOf.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_report_missing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - get_more_tools = next(t for t in tools_result if t.name == "get_more_tools") - schema = get_more_tools.inputSchema - - # context must be a simple {"type": "string"}, not anyOf/oneOf - context_prop = schema["properties"]["context"] - assert context_prop["type"] == "string", ( - f"Expected context type 'string', got: {context_prop}" - ) - assert "anyOf" not in context_prop, ( - f"context should not use anyOf: {context_prop}" - ) - assert "default" not in context_prop, ( - f"context should not have a default: {context_prop}" - ) - - # context must be required - assert "context" in schema.get("required", []), ( - f"context should be required, got required={schema.get('required')}" - ) - - @pytest.mark.asyncio - async def test_report_missing_disabled_by_default(self): - """Verify tool is NOT injected when enable_report_missing=False.""" - server = create_community_todo_server() - - # Track with report_missing disabled - options = AgentCatOptions(enable_report_missing=False) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - tool_names = [tool.name for tool in tools_result] - - # Verify report_missing is NOT present - assert "get_more_tools" not in tool_names - # But original tools should still be there - assert "add_todo" in tool_names - - @pytest.mark.asyncio - async def test_report_missing_tool_call_success(self): - """Call report_missing tool and verify it executes successfully.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_report_missing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - result = await client.call_tool( - "get_more_tools", - {"context": "Need a tool to translate text between languages"}, - ) - - # Verify successful response - result_str = str(result) - assert "Unfortunately" in result_str - - @pytest.mark.asyncio - async def test_report_missing_with_valid_params(self): - """Test with various valid parameters.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_report_missing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Test with different valid parameters - test_cases = [ - {"context": "database_query"}, - {"context": "send_email"}, - {"context": "generate_chart"}, - ] - - for params in test_cases: - result = await client.call_tool("get_more_tools", params) - result_str = str(result) - assert "Unfortunately" in result_str - - @pytest.mark.asyncio - async def test_report_missing_with_missing_params(self): - """Test error handling when required parameters are missing.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_report_missing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Test with missing context - should raise a validation error - # since context is a required parameter - with pytest.raises(Exception, match="(?i)required"): - await client.call_tool("get_more_tools", {}) - - # Test with valid context - result = await client.call_tool("get_more_tools", {"context": "test_tool"}) - result_str = str(result) - assert "Unfortunately" in result_str - - @pytest.mark.asyncio - async def test_report_missing_with_other_tools(self): - """Verify report_missing doesn't interfere with existing server tools.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_report_missing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # First use a regular tool - add_result = await client.call_tool("add_todo", {"text": "Test todo item"}) - assert "Added todo" in str(add_result) - - # Then use report_missing - report_result = await client.call_tool( - "get_more_tools", {"context": "Delete a todo item"} - ) - assert "Unfortunately" in str(report_result) - - # Verify the original tool still works - list_result = await client.call_tool("list_todos", {}) - assert "Test todo item" in str(list_result) - - @pytest.mark.asyncio - async def test_multiple_report_missing_calls(self): - """Test calling report_missing multiple times in succession.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_report_missing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Call report_missing multiple times - tools_to_report = [ - ("tool1", "Description 1"), - ("tool2", "Description 2"), - ("tool3", "Description 3"), - ] - - for tool_name, description in tools_to_report: - result = await client.call_tool( - "get_more_tools", - {"context": f"{tool_name}: {description}"}, - ) - # Each call should work identically - result_str = str(result) - assert "Unfortunately" in result_str - - @pytest.mark.asyncio - async def test_report_missing_with_context_enabled(self): - """Test interaction when both report_missing and tool_context are enabled.""" - server = create_community_todo_server() - options = AgentCatOptions( - enable_report_missing=True, enable_tool_call_context=True - ) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # Find the report_missing tool - report_missing_tool = None - other_tool = None - for tool in tools_result: - if tool.name == "get_more_tools": - report_missing_tool = tool - elif tool.name == "add_todo": - other_tool = tool - - assert report_missing_tool is not None - assert other_tool is not None - - # Verify get_more_tools has its own context parameter - assert "context" in report_missing_tool.inputSchema.get("properties", {}) - - # Other tools should also have context - assert "context" in other_tool.inputSchema.get("properties", {}) - - @pytest.mark.asyncio - async def test_report_missing_with_null_values(self): - """Test with null/None values for parameters.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_report_missing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Test with None context - should raise a validation error - # since context is required as a string - with pytest.raises(Exception, match="(?i)string"): - await client.call_tool("get_more_tools", {"context": None}) - - @pytest.mark.asyncio - async def test_report_missing_publishes_event(self): - """Verify that calling report_missing tool publishes an event to the queue.""" - from agentcat.modules.event_queue import EventQueue, set_event_queue - - # Create a mock API client - mock_api_client = MagicMock() - mock_api_client.publish_event = MagicMock(return_value=None) - - # Create a new EventQueue with our mock - test_queue = EventQueue(api_client=mock_api_client) - - # Replace the global event queue - set_event_queue(test_queue) - - try: - server = create_community_todo_server() - options = AgentCatOptions(enable_report_missing=True, enable_tracing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Call the report_missing tool - await client.call_tool( - "get_more_tools", - {"context": "Need to resize images to different dimensions"}, - ) - - # Give the event queue worker thread time to process - time.sleep(1.0) - - # Verify that publish_event was called - assert mock_api_client.publish_event.called - assert ( - mock_api_client.publish_event.call_count >= 1 - ) # At least one call - - # Find the tool call event - tool_call_event = None - for call in mock_api_client.publish_event.call_args_list: - event = call[1]["publish_event_request"] - if ( - event.event_type == "mcp:tools/call" - and event.resource_name == "get_more_tools" - ): - tool_call_event = event - break - - assert tool_call_event is not None, ( - "No get_more_tools tool call event found" - ) - - # Verify event properties - assert tool_call_event.project_id == "test_project" - - # Verify the arguments contain our input - assert ( - tool_call_event.parameters["arguments"]["context"] - == "Need to resize images to different dimensions" - ) - - # Verify user_intent was captured from the context parameter - assert tool_call_event.user_intent == "Need to resize images to different dimensions" - - finally: - # Clean up: restore original event queue - from agentcat.modules.event_queue import EventQueue, set_event_queue - - set_event_queue(EventQueue()) - - @pytest.mark.asyncio - async def test_multiple_tool_calls_publish_multiple_events(self): - """Verify that multiple tool calls result in multiple events being published.""" - from agentcat.modules.event_queue import EventQueue, set_event_queue - - # Create a mock API client - mock_api_client = MagicMock() - mock_api_client.publish_event = MagicMock(return_value=None) - - # Create a new EventQueue with our mock - test_queue = EventQueue(api_client=mock_api_client) - - # Replace the global event queue - set_event_queue(test_queue) - - try: - server = create_community_todo_server() - options = AgentCatOptions(enable_report_missing=True, enable_tracing=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Call report_missing tool - await client.call_tool( - "get_more_tools", - {"context": "Need a tool to translate text between languages"}, - ) - - # Call a regular tool - await client.call_tool("add_todo", {"text": "Test todo item"}) - - # Call get_more_tools again - await client.call_tool( - "get_more_tools", - {"context": "Need a tool to translate text between languages"}, - ) - - # Allow time for processing - time.sleep(1.0) - - # Should have at least 3 tool call events (plus initialize and list_tools events) - assert mock_api_client.publish_event.call_count >= 3 - - # Get all published events - events = [ - call[1]["publish_event_request"] - for call in mock_api_client.publish_event.call_args_list - ] - - # Filter to just tool call events - tool_events = [e for e in events if e.event_type == "mcp:tools/call"] - - # Should have exactly 3 tool calls - assert len(tool_events) == 3 - - # Verify event types and tool names (order not guaranteed due to concurrent processing) - tool_names = [e.resource_name for e in tool_events] - assert tool_names.count("get_more_tools") == 2 - assert tool_names.count("add_todo") == 1 - - # Find events by resource name for detailed verification - get_more_tools_events = [ - e for e in tool_events if e.resource_name == "get_more_tools" - ] - add_todo_events = [ - e for e in tool_events if e.resource_name == "add_todo" - ] - - # Verify get_more_tools events - for event in get_more_tools_events: - assert ( - event.parameters["arguments"]["context"] - == "Need a tool to translate text between languages" - ) - assert ( - event.user_intent - == "Need a tool to translate text between languages" - ) - - # Verify add_todo event - assert len(add_todo_events) == 1 - assert ( - add_todo_events[0].parameters["arguments"]["text"] - == "Test todo item" - ) - - finally: - # Clean up: restore original event queue - from agentcat.modules.event_queue import EventQueue, set_event_queue - - set_event_queue(EventQueue()) - - -if __name__ == "__main__": - pytest.main([__file__, "-v"]) \ No newline at end of file diff --git a/tests/community/test_community_tool_context.py b/tests/community/test_community_tool_context.py deleted file mode 100644 index 74ee026..0000000 --- a/tests/community/test_community_tool_context.py +++ /dev/null @@ -1,583 +0,0 @@ -"""Test tool context functionality with community FastMCP.""" - -import pytest - -from agentcat import AgentCatOptions, track -from agentcat.modules.constants import DEFAULT_CONTEXT_DESCRIPTION - -from ..test_utils.community_client import create_community_test_client -from ..test_utils.community_todo_server import ( - HAS_COMMUNITY_FASTMCP, - create_community_todo_server, -) - -# Skip all tests if community FastMCP is not available -pytestmark = pytest.mark.skipif( - not HAS_COMMUNITY_FASTMCP, - reason="Community FastMCP not available. Install with: pip install fastmcp" -) - - -class TestCommunityToolContext: - """Test tool context functionality with community FastMCP.""" - - @pytest.mark.asyncio - async def test_context_parameter_injection_enabled(self): - """Test that context parameter is added when enable_tool_call_context=True.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # Check each tool (except get_more_tools if present) - for tool in tools_result: - if tool.name == "get_more_tools": - continue - - # Verify context parameter exists - assert "context" in tool.inputSchema["properties"] - - # Verify context is required - assert "context" in tool.inputSchema["required"] - - # Verify context schema properties - context_schema = tool.inputSchema["properties"]["context"] - assert context_schema["type"] == "string" - assert ( - context_schema["description"] - == DEFAULT_CONTEXT_DESCRIPTION - ) - - @pytest.mark.asyncio - async def test_context_parameter_not_injected_when_disabled(self): - """Test that context parameter is NOT added when enable_tool_call_context=False.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=False) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - for tool in tools_result: - if tool.name == "get_more_tools": - continue - - # Verify context parameter does NOT exist - assert "context" not in tool.inputSchema.get("properties", {}) - - # Verify context is NOT in required - assert "context" not in tool.inputSchema.get("required", []) - - @pytest.mark.asyncio - async def test_schema_with_existing_properties(self): - """Test with tools that have existing inputSchema and properties.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # Find add_todo which has existing schema - add_todo_tool = next(t for t in tools_result if t.name == "add_todo") - - # Verify original properties still exist - assert "text" in add_todo_tool.inputSchema["properties"] - - # Verify context was added - assert "context" in add_todo_tool.inputSchema["properties"] - assert "context" in add_todo_tool.inputSchema["required"] - - @pytest.mark.asyncio - async def test_schema_with_no_input_schema(self): - """Test with tools that have no inputSchema.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - # Create a custom server with a tool that has no parameters - server = FastMCP("test-server") - - @server.tool - def simple_tool(): - """A tool with no parameters.""" - return "success" - - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - simple_tool_def = next( - t for t in tools_result if t.name == "simple_tool" - ) - - # Verify inputSchema was created - assert simple_tool_def.inputSchema is not None - assert "properties" in simple_tool_def.inputSchema - assert "context" in simple_tool_def.inputSchema["properties"] - assert "required" in simple_tool_def.inputSchema - assert "context" in simple_tool_def.inputSchema["required"] - - @pytest.mark.asyncio - async def test_schema_with_empty_properties(self): - """Test with tools that have empty properties object.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - # Create a tool with function that has no parameters - @server.tool - def empty_tool(): - """Tool with empty schema.""" - return "success" - - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - empty_tool = next(t for t in tools_result if t.name == "empty_tool") - - # Verify context was added to empty properties - assert "context" in empty_tool.inputSchema["properties"] - assert len(empty_tool.inputSchema["properties"]) >= 1 - - @pytest.mark.asyncio - async def test_schema_with_existing_required_fields(self): - """Test with tools that already have required fields.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # add_todo has 'text' as required - add_todo_tool = next(t for t in tools_result if t.name == "add_todo") - - # Verify both original and context are required - assert "text" in add_todo_tool.inputSchema["required"] - assert "context" in add_todo_tool.inputSchema["required"] - assert len(add_todo_tool.inputSchema["required"]) >= 2 - - @pytest.mark.asyncio - async def test_tool_call_with_valid_context(self): - """Test calling a tool with valid context parameter.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Call tool with context - result = await client.call_tool( - "add_todo", - { - "text": "Test todo item", - "context": "Adding a test todo to verify context handling", - }, - ) - - # Should succeed - assert "Added todo" in str(result) - - @pytest.mark.asyncio - async def test_tool_call_without_context_still_works(self): - """Test that tool calls without context still work (context is stripped).""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # The implementation strips context before passing to handler - result = await client.call_tool( - "add_todo", - {"text": "Test todo item"}, # Missing context - ) - - # The call should succeed because context is stripped before passing to handler - assert "Added todo" in str(result) - - @pytest.mark.asyncio - async def test_tool_call_with_empty_context(self): - """Test calling a tool with empty string context.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Call with empty context - should still work - result = await client.call_tool( - "add_todo", - { - "text": "Test todo", - "context": "", # Empty but present - }, - ) - - assert "Added todo" in str(result) - - @pytest.mark.asyncio - async def test_get_more_tools_exclusion_with_context(self): - """Test that get_more_tools doesn't get context when both features are enabled.""" - server = create_community_todo_server() - options = AgentCatOptions( - enable_report_missing=True, enable_tool_call_context=True - ) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # Find get_more_tools tool - get_more_tools_tool = next( - t for t in tools_result if t.name == "get_more_tools" - ) - - # Verify it has context parameter (it's special and keeps its own context param) - assert "context" in get_more_tools_tool.inputSchema.get("properties", {}) - - # Verify other tools DO have context - other_tools = [t for t in tools_result if t.name != "get_more_tools"] - for tool in other_tools: - assert "context" in tool.inputSchema["properties"] - - @pytest.mark.asyncio - async def test_tool_with_existing_context_parameter(self): - """Test that existing context parameter is overwritten with AgentCat's version.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - @server.tool - def tool_with_context(context: str, data: str): - """Tool that already has a context parameter.""" - return f"Original context: {context}, data: {data}" - - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - tool = next(t for t in tools_result if t.name == "tool_with_context") - - # Verify context exists - assert "context" in tool.inputSchema["properties"] - - # Check if it has AgentCat's description - context_schema = tool.inputSchema["properties"]["context"] - assert ( - context_schema.get("description") - == DEFAULT_CONTEXT_DESCRIPTION - ) - - # Should still be in required - assert "context" in tool.inputSchema["required"] - - @pytest.mark.asyncio - async def test_original_functionality_preserved(self): - """Verify that original tool functionality remains intact with context.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Add multiple todos - await client.call_tool( - "add_todo", {"text": "First todo", "context": "Adding first item"} - ) - await client.call_tool( - "add_todo", {"text": "Second todo", "context": "Adding second item"} - ) - - # List todos - list_result = await client.call_tool( - "list_todos", {"context": "Listing all todos to verify they were added"} - ) - - # Verify both todos are present - result_str = str(list_result) - assert "First todo" in result_str - assert "Second todo" in result_str - - # Complete a todo - complete_result = await client.call_tool( - "complete_todo", {"id": 1, "context": "Completing the first todo"} - ) - - assert "Completed todo" in str(complete_result) - - @pytest.mark.asyncio - async def test_context_not_passed_to_original_handler(self): - """Verify that context parameter is stripped before passing to original handler.""" - server = create_community_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Call with context - result = await client.call_tool( - "add_todo", - {"text": "test data", "context": "This context should be stripped"}, - ) - - # The call should succeed, proving context was stripped - # (otherwise it would fail since add_todo doesn't accept context param) - assert "Added todo" in str(result) - - @pytest.mark.asyncio - async def test_dynamically_added_tool_gets_context(self): - """Test that tools added after tracking get context parameter.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - # Track with context enabled - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - # Add tool AFTER tracking - @server.tool - def late_tool(value: str): - """Tool added after tracking.""" - return f"Processed: {value}" - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - late_tool_def = next(t for t in tools_result if t.name == "late_tool") - - # Should have context parameter - assert "context" in late_tool_def.inputSchema["properties"] - assert "context" in late_tool_def.inputSchema["required"] - - # Test calling it - result = await client.call_tool( - "late_tool", - {"value": "test", "context": "Testing late-added tool"} - ) - assert "Processed: test" in str(result) - - @pytest.mark.asyncio - async def test_custom_context_description(self): - """Test that custom context description is correctly applied in community FastMCP.""" - server = create_community_todo_server() - custom_description = "Explain why you need to use this tool" - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=custom_description - ) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # Check each tool (except get_more_tools) - for tool in tools_result: - if tool.name == "get_more_tools": - continue - - # Verify context parameter has custom description - context_schema = tool.inputSchema["properties"]["context"] - assert context_schema["description"] == custom_description - - @pytest.mark.asyncio - async def test_custom_context_description_empty_string(self): - """Test edge case with empty string custom description in community FastMCP.""" - server = create_community_todo_server() - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description="" - ) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # Find a tool to test - add_todo_tool = next(t for t in tools_result if t.name == "add_todo") - - # Verify context exists with empty description - context_schema = add_todo_tool.inputSchema["properties"]["context"] - assert context_schema["description"] == "" - assert context_schema["type"] == "string" - - @pytest.mark.asyncio - async def test_custom_context_description_special_characters(self): - """Test custom description with special characters and Unicode in community FastMCP.""" - server = create_community_todo_server() - special_description = "Why use this? 🚀 Include: 'quotes', \"double\", newlines\n, tabs\t." - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=special_description - ) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # Verify special characters are preserved - add_todo_tool = next(t for t in tools_result if t.name == "add_todo") - context_schema = add_todo_tool.inputSchema["properties"]["context"] - assert context_schema["description"] == special_description - - @pytest.mark.asyncio - async def test_custom_context_description_very_long(self): - """Test with a very long description string in community FastMCP.""" - server = create_community_todo_server() - # Create a very long description - long_description = "This is a very detailed description for the context. " * 50 - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=long_description - ) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # Verify long description is preserved - add_todo_tool = next(t for t in tools_result if t.name == "add_todo") - context_schema = add_todo_tool.inputSchema["properties"]["context"] - assert context_schema["description"] == long_description - assert len(context_schema["description"]) > 1000 - - @pytest.mark.asyncio - async def test_default_context_description(self): - """Verify the default description is used when not specified in community FastMCP.""" - server = create_community_todo_server() - # Don't specify custom_context_description, should use default - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # Check for default description - add_todo_tool = next(t for t in tools_result if t.name == "add_todo") - context_schema = add_todo_tool.inputSchema["properties"]["context"] - assert context_schema["description"] == DEFAULT_CONTEXT_DESCRIPTION - - @pytest.mark.asyncio - async def test_custom_context_description_with_multiple_tools(self): - """Test that custom description is applied to all tools consistently in community FastMCP.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - @server.tool - def tool1(param: str): - """First tool.""" - return f"Tool 1: {param}" - - @server.tool - def tool2(value: int): - """Second tool.""" - return f"Tool 2: {value}" - - @server.tool - def tool3(): - """Third tool with no params.""" - return "Tool 3" - - custom_desc = "Custom community context for all tools" - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=custom_desc - ) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # All tools should have the same custom context description - for tool in tools_result: - if tool.name in ["tool1", "tool2", "tool3"]: - assert "context" in tool.inputSchema["properties"] - assert tool.inputSchema["properties"]["context"]["description"] == custom_desc - - @pytest.mark.asyncio - async def test_custom_context_with_tool_call(self): - """Test tool calls work correctly with custom context description in community FastMCP.""" - server = create_community_todo_server() - custom_desc = "Provide reasoning for this action in the community server" - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=custom_desc - ) - track(server, "test_project", options) - - async with create_community_test_client(server) as client: - # Verify the custom description is set - tools_result = await client.list_tools() - add_todo_tool = next(t for t in tools_result if t.name == "add_todo") - assert add_todo_tool.inputSchema["properties"]["context"]["description"] == custom_desc - - # Call the tool with context - result = await client.call_tool( - "add_todo", - { - "text": "Test with custom description in community", - "context": "Adding todo to test custom context description in community FastMCP" - } - ) - - # Should succeed - assert "Added todo" in str(result) - - @pytest.mark.asyncio - async def test_custom_context_with_dynamically_added_tool(self): - """Test that dynamically added tools get custom context description in community FastMCP.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("test-server") - - # Track with custom context description - custom_desc = "Dynamic tool custom context" - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=custom_desc - ) - track(server, "test_project", options) - - # Add tool AFTER tracking - @server.tool - def dynamic_tool(data: str): - """Tool added after tracking with custom context.""" - return f"Dynamic result: {data}" - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - dynamic_tool_def = next(t for t in tools_result if t.name == "dynamic_tool") - - # Should have context parameter with custom description - assert "context" in dynamic_tool_def.inputSchema["properties"] - assert dynamic_tool_def.inputSchema["properties"]["context"]["description"] == custom_desc - - # Test calling it - result = await client.call_tool( - "dynamic_tool", - {"data": "test", "context": "Using dynamic tool with custom context"} - ) - assert "Dynamic result: test" in str(result) - - -if __name__ == "__main__": - pytest.main([__file__, "-v"]) \ No newline at end of file diff --git a/tests/community/test_community_tracking_timing.py b/tests/community/test_community_tracking_timing.py deleted file mode 100644 index 190a9d1..0000000 --- a/tests/community/test_community_tracking_timing.py +++ /dev/null @@ -1,382 +0,0 @@ -"""Test .track() timing flexibility with community FastMCP.""" - -import pytest - -from agentcat import AgentCatOptions, track -from agentcat.modules.internal import ( - get_server_tracking_data, - reset_all_tracking_data, -) - -from ..test_utils.community_client import create_community_test_client -from ..test_utils.community_todo_server import ( - HAS_COMMUNITY_FASTMCP, - get_lowlevel_server, -) - -# Skip all tests if community FastMCP is not available -pytestmark = pytest.mark.skipif( - not HAS_COMMUNITY_FASTMCP, - reason="Community FastMCP not available. Install with: pip install fastmcp" -) - - -class TestCommunityTrackingTiming: - """Test that .track() works when called at different stages of server setup.""" - - @pytest.fixture(autouse=True) - def setup(self): - """Reset the tracker before each test.""" - reset_all_tracking_data() - yield - reset_all_tracking_data() - - @pytest.mark.asyncio - async def test_track_empty_server_then_add_tools(self): - """Test tracking a server with NO tools, then adding tools later.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - # Create empty server - server = FastMCP("empty-server") - - # Track the empty server first (disable report_missing to truly have no tools) - options = AgentCatOptions(enable_report_missing=False) - track(server, "test-project", options) - - # Verify tracking is initialized even with no tools - data = get_server_tracking_data(get_lowlevel_server(server)) - assert data is not None - assert data.tracker_initialized - assert len(data.tool_registry) == 0 # No tools yet - - # Now add tools AFTER tracking - @server.tool - def first_tool(x: int) -> str: - return f"First: {x}" - - @server.tool - def second_tool(x: int) -> str: - return f"Second: {x * 2}" - - # Test that both tools work correctly - async with create_community_test_client(server) as client: - result1 = await client.call_tool("first_tool", {"x": 10}) - assert "First: 10" in str(result1), f"Expected 'First: 10', got {result1}" - - result2 = await client.call_tool("second_tool", {"x": 10}) - assert "Second: 20" in str(result2), f"Expected 'Second: 20', got {result2}" - - # Verify tools are tracked - data = get_server_tracking_data(get_lowlevel_server(server)) - assert "first_tool" in data.tool_registry - assert "second_tool" in data.tool_registry - assert data.tool_registry["first_tool"].tracked - assert data.tool_registry["second_tool"].tracked - - @pytest.mark.asyncio - async def test_track_server_with_some_tools_then_add_more(self): - """Test tracking a server with existing tools, then adding more tools.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("partial-server") - - # Add initial tools - @server.tool - def existing_tool1(x: int) -> str: - return f"Existing1: {x}" - - @server.tool - def existing_tool2(x: int) -> str: - return f"Existing2: {x + 1}" - - # Track server with some tools (disable report_missing for cleaner counts) - options = AgentCatOptions(enable_report_missing=False) - track(server, "test-project", options) - - # Test initial tools work (registered when list_tools or call_tool invoked) - async with create_community_test_client(server) as client: - # First list tools to trigger registration - await client.list_tools() - - # Verify initial tools are now tracked - data = get_server_tracking_data(get_lowlevel_server(server)) - assert len(data.tool_registry) == 2 - assert "existing_tool1" in data.tool_registry - assert "existing_tool2" in data.tool_registry - result = await client.call_tool("existing_tool1", {"x": 5}) - assert "Existing1: 5" in str(result) - - result = await client.call_tool("existing_tool2", {"x": 5}) - assert "Existing2: 6" in str(result) - - # Add more tools after tracking - @server.tool - def new_tool1(x: int) -> str: - return f"New1: {x * 3}" - - @server.tool - def new_tool2(x: int) -> str: - return f"New2: {x - 1}" - - # Test all tools work (both old and new) - async with create_community_test_client(server) as client: - # Test existing tools still work - result = await client.call_tool("existing_tool1", {"x": 7}) - assert "Existing1: 7" in str(result) - - result = await client.call_tool("existing_tool2", {"x": 7}) - assert "Existing2: 8" in str(result) - - # Test new tools work - result = await client.call_tool("new_tool1", {"x": 7}) - assert "New1: 21" in str(result), f"Expected 'New1: 21', got {result}" - - result = await client.call_tool("new_tool2", {"x": 7}) - assert "New2: 6" in str(result), f"Expected 'New2: 6', got {result}" - - # Verify all tools are tracked - data = get_server_tracking_data(get_lowlevel_server(server)) - assert len(data.tool_registry) == 4 - for tool_name in ["existing_tool1", "existing_tool2", "new_tool1", "new_tool2"]: - assert tool_name in data.tool_registry - assert data.tool_registry[tool_name].tracked - - @pytest.mark.asyncio - async def test_track_server_with_all_tools_already_added(self): - """Test tracking a server after ALL its tools have been added.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("complete-server") - - # Add ALL tools before tracking - @server.tool - def tool_a(x: int) -> str: - return f"A: {x}" - - @server.tool - def tool_b(x: int) -> str: - return f"B: {x * 2}" - - @server.tool - def tool_c(x: int) -> str: - return f"C: {x + 10}" - - @server.tool - async def async_tool_d(x: int) -> str: - return f"D: {x - 5}" - - # Track server AFTER all tools added (disable report_missing for cleaner counts) - options = AgentCatOptions(enable_report_missing=False) - track(server, "test-project", options) - - # Test all tools work correctly - async with create_community_test_client(server) as client: - result = await client.call_tool("tool_a", {"x": 15}) - assert "A: 15" in str(result), f"Expected 'A: 15', got {result}" - - result = await client.call_tool("tool_b", {"x": 15}) - assert "B: 30" in str(result), f"Expected 'B: 30', got {result}" - - result = await client.call_tool("tool_c", {"x": 15}) - assert "C: 25" in str(result), f"Expected 'C: 25', got {result}" - - result = await client.call_tool("async_tool_d", {"x": 15}) - assert "D: 10" in str(result), f"Expected 'D: 10', got {result}" - - # Verify all tools are tracked - data = get_server_tracking_data(get_lowlevel_server(server)) - assert len(data.tool_registry) == 4 - for tool_name in ["tool_a", "tool_b", "tool_c", "async_tool_d"]: - assert tool_name in data.tool_registry - assert data.tool_registry[tool_name].tracked - - @pytest.mark.asyncio - async def test_track_with_options_on_empty_server(self): - """Test tracking an empty server with various options enabled.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("empty-with-options") - - # Track with options on empty server - options = AgentCatOptions( - enable_tool_call_context=True, - enable_report_missing=True, - enable_tracing=True - ) - track(server, "test-project", options) - - # Verify tracking is initialized - data = get_server_tracking_data(get_lowlevel_server(server)) - assert data is not None - assert data.tracker_initialized - - # get_more_tools should be added due to enable_report_missing - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - tool_names = [tool.name for tool in tools_result] - assert "get_more_tools" in tool_names - - # Test that get_more_tools works - result = await client.call_tool( - "get_more_tools", - {"context": "Need a tool for testing"} - ) - assert "Unfortunately" in str(result) - - # Now add a tool and verify context injection works - @server.tool - def late_added_tool(value: str) -> str: - return f"Value: {value}" - - async with create_community_test_client(server) as client: - tools_result = await client.list_tools() - - # Find late_added_tool - late_tool = next( - (t for t in tools_result if t.name == "late_added_tool"), - None - ) - assert late_tool is not None - - # Verify context was injected (due to enable_tool_call_context) - assert "context" in late_tool.inputSchema["properties"] - assert "context" in late_tool.inputSchema["required"] - - # Test the tool works with context - result = await client.call_tool( - "late_added_tool", - {"value": "test", "context": "Testing late added tool"} - ) - assert "Value: test" in str(result) - - @pytest.mark.asyncio - async def test_multiple_track_calls_on_same_server(self): - """Test that calling track() multiple times on the same server is safe.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("multi-track-server") - - # First track call - track(server, "project1") - - @server.tool - def tool1(x: int) -> str: - return f"Tool1: {x}" - - # Second track call with different project - track(server, "project2") - - @server.tool - def tool2(x: int) -> str: - return f"Tool2: {x * 2}" - - # Third track call with options - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "project3", options) - - @server.tool - def tool3(x: int) -> str: - return f"Tool3: {x + 5}" - - # Test all tools work - async with create_community_test_client(server) as client: - result = await client.call_tool("tool1", {"x": 10}) - assert "Tool1: 10" in str(result) - - result = await client.call_tool("tool2", {"x": 10}) - assert "Tool2: 20" in str(result) - - result = await client.call_tool( - "tool3", {"x": 10, "context": "Testing tool3"} - ) - assert "Tool3: 15" in str(result) - - # Verify all tools are tracked - data = get_server_tracking_data(get_lowlevel_server(server)) - assert "tool1" in data.tool_registry - assert "tool2" in data.tool_registry - assert "tool3" in data.tool_registry - - @pytest.mark.asyncio - async def test_track_interleaved_with_tool_additions(self): - """Test complex scenario: add tool, track, add tool, track again, add more.""" - if not HAS_COMMUNITY_FASTMCP: - pytest.skip("Community FastMCP not available") - - from fastmcp import FastMCP - - server = FastMCP("interleaved-server") - - # Add first tool - @server.tool - def step1_tool(x: int) -> str: - return f"Step1: {x}" - - # First track - track(server, "test-project") - - # Add second tool - @server.tool - def step2_tool(x: int) -> str: - return f"Step2: {x * 2}" - - # Track again with options - options = AgentCatOptions(enable_report_missing=True) - track(server, "test-project", options) - - # Add third and fourth tools - @server.tool - def step3_tool(x: int) -> str: - return f"Step3: {x + 1}" - - @server.tool - async def step4_tool(x: int) -> str: - return f"Step4: {x - 1}" - - # Test all tools work and verify functionality - async with create_community_test_client(server) as client: - # Test each tool - result = await client.call_tool("step1_tool", {"x": 100}) - assert "Step1: 100" in str(result) - - result = await client.call_tool("step2_tool", {"x": 100}) - assert "Step2: 200" in str(result) - - result = await client.call_tool("step3_tool", {"x": 100}) - assert "Step3: 101" in str(result) - - result = await client.call_tool("step4_tool", {"x": 100}) - assert "Step4: 99" in str(result) - - # Also verify get_more_tools was added - result = await client.call_tool( - "get_more_tools", - {"context": "Testing report missing"} - ) - assert "Unfortunately" in str(result) - - # Verify all tools are tracked - data = get_server_tracking_data(get_lowlevel_server(server)) - for tool_name in ["step1_tool", "step2_tool", "step3_tool", "step4_tool"]: - assert tool_name in data.tool_registry - assert data.tool_registry[tool_name].tracked - assert "get_more_tools" in data.tool_registry - - -if __name__ == "__main__": - pytest.main([__file__, "-v"]) diff --git a/tests/community/test_community_v3_event_serialization.py b/tests/community/test_community_v3_event_serialization.py index dade60a..7ef0e02 100644 --- a/tests/community/test_community_v3_event_serialization.py +++ b/tests/community/test_community_v3_event_serialization.py @@ -1,20 +1,23 @@ -"""End-to-end: tools/list events must be JSON-serializable (agentcat 1.0.1 data loss). - -On 1.0.1 every ``tools/list`` event carried the FastMCP tool's ``fn`` callable and -``tags`` set (via ``_tool_to_dict`` -> ``tool.model_dump()``), so truncation logged -``Unable to serialize unknown type: `` and the event was then -dropped by the API client (``'set' object has no attribute '__dict__'``). These -tests drive a real ``tools/list`` and assert the captured event survives. +"""End-to-end: published events must be JSON-serializable (agentcat 1.0.1 data loss). + +On 1.0.1 every ``tools/list`` event carried the FastMCP tool's ``fn`` callable +and ``tags`` set, so truncation logged ``Unable to serialize unknown type: +`` and the event was then dropped by the API client (``'set' +object has no attribute '__dict__'``). + +v2 publishes no ``tools/list`` event at all, so the surviving risk moved to the +one event type that remains: a ``tools/call`` response is a FastMCP +``ToolResult``, and ``PublishEventRequest.response`` is +``Optional[Dict[str, Any]]`` — a non-dict there fails pydantic construction and +silently drops the whole event. These tests drive real calls and assert the +captured events survive the send path. """ import json -import time -from unittest.mock import MagicMock import pytest from agentcat import AgentCatOptions, track -from agentcat.modules.event_queue import EventQueue, set_event_queue from ..test_utils.community_client import ( HAS_COMMUNITY_CLIENT, @@ -32,62 +35,104 @@ @pytest.fixture -def captured_events(): - from agentcat.modules.event_queue import event_queue as original_queue - +def captured_events(monkeypatch): events: list = [] - mock_api_client = MagicMock() - mock_api_client.publish_event = MagicMock( - side_effect=lambda publish_event_request: events.append(publish_event_request) - ) - set_event_queue(EventQueue(api_client=mock_api_client)) - try: - yield events - finally: - set_event_queue(original_queue) + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +def _call_events(events): + return [e for e in events if e.event_type == "mcp:tools/call"] + +async def test_only_tools_call_events_are_published(captured_events): + """A handshake plus a listing publishes nothing; v2 has one event type.""" + server = create_community_todo_server() + track(server, "test_project", AgentCatOptions(enable_tracing=True)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + assert captured_events == [], [e.event_type for e in captured_events] + # The listing still went through AgentCat: the handles are on the + # schemas. + add = next(t for t in listed if t.name == "add_todo") + assert "session_id" in add.inputSchema["properties"] + + await client.call_tool("add_todo", {"text": "serialize me"}) -def _list_event(events): - matches = [e for e in events if e.event_type == "mcp:tools/list"] - return matches[-1] if matches else None + assert {e.event_type for e in captured_events} == {"mcp:tools/call"} -@pytest.mark.asyncio -async def test_tools_list_event_is_json_serializable(captured_events): - """The captured tools/list event.response must be fully JSON-safe.""" +async def test_tools_call_event_response_is_json_serializable(captured_events): + """The captured tools/call event.response must be a fully JSON-safe dict.""" server = create_community_todo_server() # FunctionTools carry the fn callable track(server, "test_project", AgentCatOptions(enable_tracing=True)) async with create_community_test_client(server) as client: - await client.list_tools() - time.sleep(1.0) + await client.call_tool("add_todo", {"text": "hi"}) - event = _list_event(captured_events) - assert event is not None, "no tools/list event captured" - # The exact thing the generated API client does before sending — must not raise. + event = _call_events(captured_events)[-1] + # A non-dict response never reaches the wire — it fails PublishEventRequest + # construction and the event is dropped whole. + assert isinstance(event.response, dict) + # The exact thing the generated API client does before sending. json.dumps(event.response) - - # And the payload is the clean MCP shape (from to_mcp_tool), not a raw - # tool.model_dump() with an embedded callable ``fn``. - tool = event.response["tools"][0] - assert "fn" not in tool - assert "inputSchema" in tool + assert "fn" not in event.response + assert "Added todo" in json.dumps(event.response) -@pytest.mark.asyncio -async def test_tools_list_event_survives_api_client_serialization(captured_events): +async def test_event_survives_api_client_serialization(captured_events): """Reproduce the send path: the generated client's sanitizer must not raise.""" server = create_community_todo_server() track(server, "test_project", AgentCatOptions(enable_tracing=True)) async with create_community_test_client(server) as client: - await client.list_tools() - time.sleep(1.0) + await client.call_tool("add_todo", {"text": "sanitize me"}) - event = _list_event(captured_events) - assert event is not None + event = _call_events(captured_events)[-1] from agentcat_api.api_client import ApiClient - # 'set' object has no attribute '__dict__' was the 1.0.1 drop; must be gone now. + # 'set' object has no attribute '__dict__' was the 1.0.1 drop; must be gone. ApiClient.sanitize_for_serialization(ApiClient(), event.response) + ApiClient.sanitize_for_serialization(ApiClient(), event.parameters) + + +async def test_an_unserializable_result_drops_only_the_response(captured_events): + """A result we cannot dump must not take the whole event down with it — + nor the customer's tool call.""" + from fastmcp.server.middleware import Middleware + from fastmcp.tools import ToolResult + from mcp.types import TextContent + + class Unserializable(ToolResult): + def model_dump(self, *args, **kwargs): + raise TypeError("cannot serialize") + + class Unserializing(Middleware): + async def on_call_tool(self, context, call_next): + return Unserializable(content=[TextContent(type="text", text="opaque")]) + + from fastmcp import FastMCP + + server = FastMCP("opaque-server") + + @server.tool(output_schema=None) + def opaque() -> str: + """Answered by the middleware below AgentCat.""" + return "unused" + + server.add_middleware(Unserializing()) + track(server, "test_project", AgentCatOptions(enable_tracing=True)) + + async with create_community_test_client(server) as client: + result = await client.call_tool("opaque", {}) + + assert result.is_error is False + assert "opaque" in "".join(c.text for c in result.content if hasattr(c, "text")) + events = _call_events(captured_events) + assert len(events) == 1 + assert events[0].response is None + assert events[0].session_id.startswith("ses_") diff --git a/tests/community/test_community_v3_handles.py b/tests/community/test_community_v3_handles.py new file mode 100644 index 0000000..3b93d00 --- /dev/null +++ b/tests/community/test_community_v3_handles.py @@ -0,0 +1,1156 @@ +"""End-to-end handle behavior on the community FastMCP adapter. + +The community sibling of `tests/test_lowlevel_v1_handles.py`: every assertion +here rides a real `fastmcp.Client` against a real server, so the whole wire +path is covered — schema injection on `tools/list`, the stripped arguments the +customer's tool actually receives, the mint-back the agent sees, and the single +`mcp:tools/call` event AgentCat publishes. +""" + +import json + +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import ( + AGENTCAT_TAG_AGENT_ID, + AGENTCAT_TAG_AGENT_SOURCE, + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, + META_CLIENT_INFO_KEY, +) +from agentcat.modules.handles import derive_session_id + +from ..test_utils import sid +from ..test_utils.community_client import ( + HAS_COMMUNITY_CLIENT, + create_community_test_client, +) +from ..test_utils.community_todo_server import ( + HAS_COMMUNITY_FASTMCP, + create_community_todo_server, +) + +pytestmark = pytest.mark.skipif( + not (HAS_COMMUNITY_FASTMCP and HAS_COMMUNITY_CLIENT), + reason="Community FastMCP not available", +) + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +def _call_events(capture) -> list: + return [e for e in capture if e.event_type == "mcp:tools/call"] + + +def _named(tools, name): + return next(t for t in tools if t.name == name) + + +def _new_server(name: str = "probe-server"): + from fastmcp import FastMCP + + return FastMCP(name) + + +async def test_prompted_mode_end_to_end(capture): + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions()) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + add = _named(listed, "add_todo") + assert list(add.inputSchema["properties"])[-2:] == ["session_id", "context"] + assert "session_id" not in add.inputSchema.get("required", []) + # session_id is the one injected param that is never required — omitting + # it is the minting signal. `context` is required, which is the only + # thing that makes agents supply intent at all. + assert "context" in add.inputSchema["required"] + assert any(t.name == "get_more_tools" for t in listed) + + r1 = await client.call_tool( + "add_todo", + { + "text": "hi", + "context": "Adding a todo item for the user's task list to track work", + }, + ) + text = _text(r1) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + assert minted.startswith("ses_") + + r2 = await client.call_tool("add_todo", {"text": "again", "session_id": minted}) + assert MINT_BACK_HEADER not in _text(r2) + + call_events = _call_events(capture) + # v2 publishes tools/call and nothing else: no initialize, no tools/list, + # no agentcat:identify. + assert {e.event_type for e in capture} == {"mcp:tools/call"} + assert len(call_events) == 2 + assert call_events[0].session_id == minted == call_events[1].session_id + # The event records the call as the agent made it: raw, unstripped. + assert call_events[0].parameters["arguments"]["context"] + assert call_events[1].parameters["arguments"]["session_id"] == minted + # ...and the customer's result, undecorated. + assert call_events[0].response is not None + assert "Added todo" in json.dumps(call_events[0].response) + assert "[MCP INSTRUCTIONS]" not in json.dumps(call_events[0].response) + assert call_events[0].tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + assert call_events[1].tags[AGENTCAT_TAG_SESSION_SOURCE] == "supplied" + assert call_events[0].user_intent.startswith("Adding a todo item") + + +async def test_structured_mint_back_mirrors_into_structured_content(capture): + """A tool with an output schema gets `_mcp_instructions` mirrored in, and + its schema declares the field so schema-validating clients still accept + it.""" + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions()) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + assert MCP_INSTRUCTIONS_KEY in _named(listed, "add_todo").outputSchema[ + "properties" + ] + + result = await client.call_tool("add_todo", {"text": "structured"}) + mint = result.structured_content[MCP_INSTRUCTIONS_KEY] + assert mint["session_id"].startswith("ses_") + assert mint["session_id"] == _call_events(capture)[0].session_id + # The customer's own structured payload survives untouched. + assert result.structured_content["result"].startswith("Added todo") + + +async def test_handler_sees_stripped_args_and_customer_result_untouched(capture): + """The injected params never reach the tool body, and what the tool returned + is exactly what the agent gets back (minus AgentCat's trailing block).""" + seen: dict = {} + server = _new_server() + + @server.tool + def probe(text: str) -> str: + """A tool that would fail validation if handed an unexpected argument.""" + seen["text"] = text + return f"probe:{text}" + + track(server, "proj_test") + + async with create_community_test_client(server) as client: + await client.list_tools() + result = await client.call_tool( + "probe", + {"text": "payload", "session_id": sid("supplied"), "context": "why"}, + ) + + assert result.is_error is False, _text(result) + assert seen == {"text": "payload"} + assert result.content[0].text == "probe:payload" + # session_id was supplied, so nothing is minted back and nothing is appended. + assert len(result.content) == 1 + assert _call_events(capture)[0].session_id == sid("supplied") + + +async def test_get_more_tools_keeps_its_own_context_and_publishes(capture): + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + gmt = _named(listed, "get_more_tools") + # Its bespoke `context` is a real parameter: still required, still + # described by the tool's own copy — and handles ride alongside. + assert gmt.inputSchema["required"] == ["context"] + assert gmt.inputSchema["properties"]["context"]["description"].startswith( + "A description of your goal" + ) + assert "session_id" in gmt.inputSchema["properties"] + assert gmt.annotations.readOnlyHint is True + + result = await client.call_tool( + "get_more_tools", {"context": "I need a tool to send emails"} + ) + assert "Unfortunately" in _text(result) + + event = _call_events(capture)[0] + assert event.resource_name == "get_more_tools" + assert event.user_intent == "I need a tool to send emails" + assert event.parameters["arguments"]["context"] == "I need a tool to send emails" + + +async def test_get_more_tools_absent_when_disabled(capture): + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions(enable_report_missing=False)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + + assert not any(t.name == "get_more_tools" for t in listed) + + +async def test_customer_get_more_tools_is_never_replaced(capture): + """A customer tool that happens to be named `get_more_tools` keeps running. + + Registering ours over theirs would silently swap their handler for our + canned reply, and nothing AgentCat does may alter tool behavior (spec §12). + """ + server = _new_server("collision-server") + + @server.tool + def get_more_tools(context: str) -> str: + """The customer's own tool, which happens to share our name.""" + return f"customer answered: {context}" + + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + # Exactly one, and it is theirs — ours is not registered alongside it. + assert [t.name for t in listed] == ["get_more_tools"] + assert listed[0].description.startswith("The customer's own tool") + + result = await client.call_tool("get_more_tools", {"context": "mine"}) + + assert result.is_error is False, _text(result) + assert "customer answered: mine" in _text(result) + assert "Unfortunately" not in _text(result) + # Still tracked like any other tool call. + assert _call_events(capture)[0].resource_name == "get_more_tools" + + +async def test_a_mounted_customer_get_more_tools_is_never_usurped(capture): + """A customer tool can arrive from a provider the install-time gate cannot + see — a mounted sub-server, a proxy, an OpenAPI provider — and the local + provider wins aggregation, so ours would answer for theirs. The first + listing is the full provider view, and it concedes the name. + """ + parent = _new_server("parent") + sub = _new_server("sub") + + @sub.tool + def get_more_tools(context: str) -> str: + """The customer's own tool, supplied by a mounted sub-server.""" + return f"customer answered: {context}" + + parent.mount(sub) + track(parent, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(parent) as client: + listed = await client.list_tools() + # Exactly one, and it is theirs. + assert [t.name for t in listed] == ["get_more_tools"] + assert listed[0].description.startswith("The customer's own tool") + + result = await client.call_tool("get_more_tools", {"context": "mine"}) + + assert "customer answered: mine" in _text(result) + assert "Unfortunately" not in _text(result) + # And ours is gone from the registry, so the call path routes to theirs too. + names = [t.name for t in await parent.list_tools(run_middleware=False)] + assert names.count("get_more_tools") == 1 + assert _call_events(capture)[0].resource_name == "get_more_tools" + + +async def test_a_mounted_get_more_tools_survives_a_re_track(capture): + """The local gate cannot tell OUR get_more_tools from a customer's, so a + re-track skips registration — and the fresh middleware must inherit the + marker or it could never concede the name again.""" + parent = _new_server("parent") + sub = _new_server("sub") + + @sub.tool + def get_more_tools(context: str) -> str: + """The customer's own tool, supplied by a mounted sub-server.""" + return f"customer answered: {context}" + + parent.mount(sub) + # No listing in between: a listing would self-heal it and hide the bug. + track(parent, "proj_test", AgentCatOptions(enable_report_missing=True)) + track(parent, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(parent) as client: + listed = await client.list_tools() + assert [t.description for t in listed] == [ + "The customer's own tool, supplied by a mounted sub-server." + ] + result = await client.call_tool("get_more_tools", {"context": "mine"}) + + assert "customer answered: mine" in _text(result) + assert "Unfortunately" not in _text(result) + + +async def test_a_call_before_any_listing_concedes_get_more_tools(capture): + """rebuild-on-demand reads the same all-provider view, so the case the + eager registration exists for is also the case it must not hijack. + + Driven through `server.call_tool`, which runs the middleware chain without + a tools/list: a real FastMCP client fetches output schemas on its way to a + call, so it can never reproduce a genuinely un-listed instance. + """ + parent = _new_server("parent") + sub = _new_server("sub") + + @sub.tool + def get_more_tools(context: str) -> str: + """The customer's own tool, supplied by a mounted sub-server.""" + return f"customer answered: {context}" + + parent.mount(sub) + track(parent, "proj_test", AgentCatOptions(enable_report_missing=True)) + + result = await parent.call_tool("get_more_tools", {"context": "mine"}) + + assert "customer answered: mine" in _text(result) + assert "Unfortunately" not in _text(result) + assert _call_events(capture)[0].resource_name == "get_more_tools" + + +async def test_a_middleware_that_copies_tools_keeps_get_more_tools_working(capture): + """A layer below us handing back `model_copy` results must not make our own + tool read as a customer's. + + Detecting ours by object identity alone did: the copy looked foreign, ours + was un-registered, and because the copy was not the object being filtered + it stayed in the listing — advertising a `get_more_tools` whose very next + call raised `Unknown tool`. + """ + from fastmcp.server.middleware import Middleware + + class Copier(Middleware): + async def on_list_tools(self, context, call_next): + return [t.model_copy(update={}) for t in await call_next(context)] + + server = _new_server("copy-server") + + @server.tool + def add_todo(text: str) -> str: + """Add a todo.""" + return f"added {text}" + + server.add_middleware(Copier()) + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(server) as client: + first = sorted(t.name for t in await client.list_tools()) + assert first == ["add_todo", "get_more_tools"] + + # The listing advertised it, so it has to answer. + result = await client.call_tool("get_more_tools", {"context": "why"}) + assert "Unfortunately" in _text(result) + + # ...and it is still advertised on the next listing. + assert sorted(t.name for t in await client.list_tools()) == first + + names = [t.name for t in await server.list_tools(run_middleware=False)] + assert "get_more_tools" in names, "our tool was un-registered on a false positive" + + +async def test_a_middleware_that_rebuilds_tools_does_not_lose_get_more_tools(capture): + """The authoritative re-check, and the only shape that needs it. + + `_is_ours` recognizes a copy of our tool three ways: object identity, the + underlying `fn` a `model_copy` carries over, and our canonical description. + A layer that REBUILDS each tool with `Tool.from_function` and a description + of its own defeats all three — and that is not exotic: it is what any + middleware that re-stamps or re-documents a listing does. + + Ours then reads as a foreign `get_more_tools` in the processed listing. + Conceding on that would un-register the real tool while the rebuilt copy + stays advertised, so the very next call to it raises `Unknown tool`. The + re-check asks the RAW provider listing — where our own object is present + and recognizable — and answers "nobody else supplies this". + """ + from fastmcp.server.middleware import Middleware + from fastmcp.tools import Tool + + class Rebuilder(Middleware): + """Hands back tools it built itself, not copies of the originals.""" + + async def on_list_tools(self, context, call_next): + async def rebuilt_body(context: str = "") -> str: + return "rebuilt" + + return [ + Tool.from_function( + rebuilt_body, + name=tool.name, + description=f"rebuilt: {tool.description}", + ).model_copy(update={"parameters": tool.parameters}) + for tool in await call_next(context) + ] + + server = _new_server("rebuilding-server") + + @server.tool + def add_todo(text: str) -> str: + """Add a todo.""" + return f"added {text}" + + server.add_middleware(Rebuilder()) + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + assert sorted(t.name for t in listed) == ["add_todo", "get_more_tools"] + # Nothing in that listing is recognizable as ours any more. + assert all(t.description.startswith("rebuilt: ") for t in listed) + + # The listing advertised it, so it has to answer — and the answer is + # ours, from the provider, because ours is still registered. + result = await client.call_tool("get_more_tools", {"context": "why"}) + assert "Unfortunately" in _text(result) + + names = [t.name for t in await server.list_tools(run_middleware=False)] + assert "get_more_tools" in names, "ours was un-registered on a false positive" + + +async def test_a_copying_middleware_still_concedes_to_a_real_owner(capture): + """The copy tolerance must not blind the concession: with a genuine + customer tool present, ours goes even though both arrive as copies.""" + from fastmcp.server.middleware import Middleware + + class Copier(Middleware): + async def on_list_tools(self, context, call_next): + return [t.model_copy(update={}) for t in await call_next(context)] + + parent = _new_server("parent") + sub = _new_server("sub") + + @sub.tool + def get_more_tools(context: str) -> str: + """The customer's own tool, supplied by a mounted sub-server.""" + return f"customer answered: {context}" + + parent.mount(sub) + parent.add_middleware(Copier()) + track(parent, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(parent) as client: + listed = await client.list_tools() + # Exactly one — ours was dropped from the list even as a copy. + assert [t.description for t in listed] == [ + "The customer's own tool, supplied by a mounted sub-server." + ] + result = await client.call_tool("get_more_tools", {"context": "mine"}) + + assert "customer answered: mine" in _text(result) + + +async def test_conceding_get_more_tools_never_deletes_the_customers_tool(capture): + """The un-registration is by object identity, so a customer who registers + their own on the LOCAL provider after track() keeps it.""" + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + # Replaces ours in the local store under the same key (on_duplicate=warn). + @server.tool + def get_more_tools(context: str) -> str: + """The customer's own tool, registered after track().""" + return f"customer answered: {context}" + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + assert [t.name for t in listed].count("get_more_tools") == 1 + result = await client.call_tool("get_more_tools", {"context": "mine"}) + + assert "customer answered: mine" in _text(result) + names = [t.name for t in await server.list_tools(run_middleware=False)] + assert names.count("get_more_tools") == 1 + + +async def test_an_unreadable_tool_registry_skips_registration(capture, monkeypatch): + """Registration is gated positively: only a registry we could actually read + and found clean lets us add our tool over the customer's server.""" + from agentcat.modules.adapters import community + + logged: list[str] = [] + monkeypatch.setattr(community, "write_to_log", logged.append) + + server = create_community_todo_server() + monkeypatch.setattr(server, "_local_provider", None, raising=False) + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + + assert any(t.name == "add_todo" for t in listed), "the server is still serving" + assert not any(t.name == "get_more_tools" for t in listed) + assert any("could not read the tool registry" in line for line in logged), logged + + +async def test_agent_tracking_injection(capture): + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions(enable_agent_tracking=True)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + add = _named(listed, "add_todo") + assert list(add.inputSchema["properties"])[-3:] == [ + "session_id", + "agent_id", + "context", + ] + assert "agent_id" in add.inputSchema["required"] + assert "session_id" not in add.inputSchema["required"] + + result = await client.call_tool( + "add_todo", {"text": "with agent", "agent_id": "opus|claude-code|k3n9x"} + ) + assert result.is_error is False, _text(result) + + event = _call_events(capture)[0] + assert event.tags[AGENTCAT_TAG_AGENT_ID] == "opus|claude-code|k3n9x" + assert event.tags[AGENTCAT_TAG_AGENT_SOURCE] == "supplied" + + +async def test_hook_mode(capture): + server = create_community_todo_server() + track( + server, + "proj_test", + AgentCatOptions(resolve_session_id=lambda request, extra: "cust-1"), + ) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + assert listed + for tool in listed: + assert "session_id" not in tool.inputSchema.get("properties", {}) + + r1 = await client.call_tool("add_todo", {"text": "hook one"}) + r2 = await client.call_tool("add_todo", {"text": "hook two"}) + assert "[MCP INSTRUCTIONS]" not in _text(r1) + assert "[MCP INSTRUCTIONS]" not in _text(r2) + assert MCP_INSTRUCTIONS_KEY not in (r1.structured_content or {}) + + call_events = _call_events(capture) + expected = derive_session_id("cust-1", "proj_test") + assert [e.session_id for e in call_events] == [expected, expected] + assert call_events[0].tags[AGENTCAT_TAG_SESSION_SOURCE] == "hook" + + +async def test_hook_receives_the_live_request_every_round(capture): + """A ResolvedCall is single-round state: the hook must see each round's own + message, never a cached first-round one.""" + seen: list = [] + + def hook(request, extra): + seen.append(getattr(request, "arguments", None)) + return "cust-1" + + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions(resolve_session_id=hook)) + + async with create_community_test_client(server) as client: + await client.call_tool("add_todo", {"text": "first"}) + await client.call_tool("add_todo", {"text": "second"}) + + assert [args.get("text") for args in seen] == ["first", "second"] + + +async def test_tracing_disabled_strips_but_publishes_nothing(capture): + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions(enable_tracing=False)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + add = _named(listed, "add_todo") + # No handles when tracing is off, but the context parameter is + # independent — so it must still be stripped before the tool runs. + assert "session_id" not in add.inputSchema["properties"] + assert "context" in add.inputSchema["properties"] + + result = await client.call_tool( + "add_todo", {"text": "quiet", "context": "no tracing"} + ) + assert result.is_error is False, _text(result) + assert "[MCP INSTRUCTIONS]" not in _text(result) + + assert capture == [] + + +async def test_resolution_failure_degrades_to_an_untraced_call(capture, monkeypatch): + """A tool call must never fail because analytics did — and the injected + parameters are still stripped on the way down.""" + from agentcat.modules.adapters import community + + async def boom(*args, **kwargs): + raise RuntimeError("resolver exploded") + + monkeypatch.setattr(community, "resolve_call", boom) + + server = create_community_todo_server() + track(server, "proj_test") + + async with create_community_test_client(server) as client: + await client.list_tools() + result = await client.call_tool( + "add_todo", {"text": "degraded", "context": "why", "session_id": sid("x")} + ) + + assert result.is_error is False, _text(result) + assert "Added todo" in _text(result) + assert capture == [] + + +async def test_customer_tool_schema_is_never_mutated(capture): + """Injection works on copies: the server's own tool definitions and a + second, untracked server built the same way stay identical.""" + server = create_community_todo_server() + reference = create_community_todo_server() + track(server, "proj_test") + + async with create_community_test_client(server) as client: + await client.list_tools() + await client.list_tools() + + tracked = { + t.name: t.parameters for t in await server.list_tools(run_middleware=False) + } + untracked = { + t.name: t.parameters for t in await reference.list_tools(run_middleware=False) + } + assert {k: v for k, v in tracked.items() if k != "get_more_tools"} == untracked + + +async def test_tool_error_publishes_the_event_and_reraises(capture): + """FastMCP surfaces a failing tool as a raised ToolError, so unlike the + official adapters this path holds the live exception: the community error + payload keeps its type, its traceback and the cause chain, and the error + itself reaches the client untouched.""" + from fastmcp.exceptions import ToolError + + server = create_community_todo_server() + track(server, "proj_test") + + async with create_community_test_client(server) as client: + await client.list_tools() + with pytest.raises(ToolError): + await client.call_tool("complete_todo", {"id": 999}) + + event = _call_events(capture)[0] + assert event.is_error is True + assert event.session_id.startswith("ses_") + assert "Todo with ID 999 not found" in event.error["message"] + assert event.error["type"] == "ToolError" + assert event.error["platform"] == "python" + assert event.error["frames"], "the live exception's traceback was lost" + assert "ValueError" in [c["type"] for c in event.error["chained_errors"]] + assert event.duration is not None and event.duration >= 0 + + +async def test_a_tool_returning_is_error_records_the_surfaced_message(capture): + """A tool that returns is_error instead of raising never had an exception + to tap, so the payload is the SDK-wide no-tap shape built from the wire + result — not a pydantic repr of FastMCP's ToolResult.""" + from fastmcp.server.middleware import Middleware + from fastmcp.tools import ToolResult + from mcp.types import TextContent + + class Failing(Middleware): + async def on_call_tool(self, context, call_next): + return ToolResult( + content=[TextContent(type="text", text="the tool said no")], + is_error=True, + ) + + server = _new_server("is-error-server") + + @server.tool(output_schema=None) + def flaky() -> str: + """Answered by the middleware below AgentCat.""" + return "unused" + + server.add_middleware(Failing()) + track(server, "proj_test") + + async with create_community_test_client(server) as client: + result = await client.call_tool("flaky", {}, raise_on_error=False) + + assert result.is_error is True + event = _call_events(capture)[0] + assert event.is_error is True + assert event.error["message"] == "the tool said no" + assert event.error["type"] is None + assert event.error["platform"] == "python" + # An error result still carries the handle: the retry has to be the same + # task. + assert MINT_BACK_HEADER in _text(result) + + +async def test_retracking_updates_options_without_double_wrapping(capture): + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions(enable_report_missing=False)) + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + assert [t.name for t in listed].count("get_more_tools") == 1 + add = _named(listed, "add_todo") + assert list(add.inputSchema["properties"]) == ["text", "session_id", "context"] + + # A second, stacked middleware would inject session_id in the inner pass + # and then skip it in the outer one — leaving it out of the strip + # registry and handing the customer's tool a parameter it never + # declared. + result = await client.call_tool( + "add_todo", {"text": "retracked", "session_id": sid("retrack")} + ) + assert result.is_error is False, _text(result) + + assert len(_call_events(capture)) == 1 + assert _call_events(capture)[0].session_id == sid("retrack") + + +async def test_agentcat_middleware_is_outermost(capture): + """Element 0 of `server.middleware` runs first, so a caching or + dereferencing middleware below us keys on STRIPPED arguments and never + caches our injection.""" + from fastmcp.server.middleware import Middleware + + below: dict = {} + + class Probe(Middleware): + async def on_call_tool(self, context, call_next): + below["arguments"] = dict(context.message.arguments or {}) + return await call_next(context) + + async def on_list_tools(self, context, call_next): + tools = list(await call_next(context)) + below["schemas"] = {t.name: dict(t.parameters or {}) for t in tools} + return tools + + server = create_community_todo_server() + server.add_middleware(Probe()) + track(server, "proj_test") + + async with create_community_test_client(server) as client: + await client.list_tools() + await client.call_tool( + "add_todo", {"text": "layered", "context": "why", "session_id": sid("z")} + ) + + assert below["arguments"] == {"text": "layered"} + assert "session_id" not in below["schemas"]["add_todo"]["properties"] + + +async def test_options_are_read_per_request_not_captured_at_install(capture): + """The middleware re-reads the server's tracking data every request, so + swapping it in place takes effect on the next call.""" + from dataclasses import replace + + from agentcat.modules.internal import ( + get_server_tracking_data, + set_server_tracking_data, + ) + + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions(enable_agent_tracking=False)) + + installed = get_server_tracking_data(server) + set_server_tracking_data( + server, + replace( + installed, + options=AgentCatOptions(enable_agent_tracking=True), + injected_params_registry=None, + output_injection_registry=None, + ), + ) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + assert "agent_id" in _named(listed, "add_todo").inputSchema["properties"] + result = await client.call_tool( + "add_todo", {"text": "swapped", "agent_id": "opus|cc|abc12"} + ) + + assert result.is_error is False, _text(result) + assert _call_events(capture)[0].tags[AGENTCAT_TAG_AGENT_ID] == "opus|cc|abc12" + + +# ── the handshake rung (design §7, rung 3) ────────────────────────────────── +# +# One middleware object serves every connection, so the rung that remembers +# what `initialize` said has to be filed per connection or it will rename other +# people's calls. The doubles below reproduce the shapes real FastMCP v3 hands +# the middleware, verified against a live server on both transports: +# +# stateful initialize: fastmcp_context.request_context is None, .session=S +# tools/call: request_context.session is the SAME S +# stateless every request gets a NEW session, and it carries no +# client_params — so the ladder always reaches this rung +# +# `client_params = None` on the double is the stateless shape on purpose: with +# it set, rung 3a answers first and this rung is never exercised at all. + + +class _FakeSession: + """A weak-referenceable ServerSession stand-in with no handshake recorded.""" + + client_params = None + session_id = None + + +class _FakeRequestContext: + def __init__(self, session: object) -> None: + self.session = session + self.request = None + self.request_id = None + self.meta = None + + +class _FakeConnection: + """One connection's FastMCP `Context`, before and during a request.""" + + def __init__(self) -> None: + self.session = _FakeSession() + self.request_context = None + self.session_id = None + + def in_request(self) -> "_FakeConnection": + self.request_context = _FakeRequestContext(self.session) + return self + + +async def _ok_result(_ctx): + from fastmcp.tools import ToolResult + from mcp.types import TextContent + + return ToolResult(content=[TextContent(type="text", text="ok")]) + + +async def _handshake(middleware, connection, name: str, version: str) -> None: + from fastmcp.server.middleware import MiddlewareContext + from mcp.types import Implementation, InitializeRequest, InitializeRequestParams + + initialize = InitializeRequest( + method="initialize", + params=InitializeRequestParams( + protocolVersion="2025-06-18", + capabilities={}, + clientInfo=Implementation(name=name, version=version), + ), + ) + await middleware( + MiddlewareContext( + message=initialize, method="initialize", fastmcp_context=connection + ), + _ok_result, + ) + + +async def _tool_call(middleware, connection, meta: dict | None = None) -> None: + from fastmcp.server.middleware import MiddlewareContext + from mcp.types import CallToolRequestParams + + params = CallToolRequestParams(name="add_todo", arguments={"text": "x"}) + if meta is not None: + params = params.model_copy(update={"meta": meta}) + await middleware( + MiddlewareContext( + message=params, method="tools/call", fastmcp_context=connection.in_request() + ), + _ok_result, + ) + + +async def test_handshake_client_info_is_the_last_rung_of_the_ladder(capture): + """initialize publishes nothing, but what it captures still names the + client when no per-request source does (design §7, rung 3). + + It is the LAST rung on purpose: a per-request source always wins. + """ + server = create_community_todo_server() + track(server, "proj_test") + middleware = server.middleware[0] + + connection = _FakeConnection() + await _handshake(middleware, connection, "Cursor", "2.6.22") + + await _tool_call(middleware, connection) + assert _call_events(capture)[-1].client_name == "Cursor" + assert _call_events(capture)[-1].client_version == "2.6.22" + + await _tool_call( + middleware, + connection, + meta={META_CLIENT_INFO_KEY: {"name": "Claude", "version": "1.0.0"}}, + ) + assert _call_events(capture)[-1].client_name == "Claude" + assert _call_events(capture)[-1].client_version == "1.0.0" + + +async def test_a_later_handshake_never_renames_an_earlier_connections_call(capture): + """Two clients, one middleware: B's initialize must not rename A's call. + + A single "last seen" slot published Cursor's tool call as Claude on every + stateless-HTTP server — the session there carries no client_params, so the + ladder reaches this rung on every call, and whichever client connected most + recently owned it. The 1.x `stateless` option was the only guard against + that, and it is gone, so the rung is filed per connection instead. + """ + server = create_community_todo_server() + track(server, "proj_test") + middleware = server.middleware[0] + + first, second = _FakeConnection(), _FakeConnection() + await _handshake(middleware, first, "Cursor", "2.6.22") + await _handshake(middleware, second, "Claude", "1.0.0") + + await _tool_call(middleware, first) + assert _call_events(capture)[-1].client_name == "Cursor" + assert _call_events(capture)[-1].client_version == "2.6.22" + + await _tool_call(middleware, second) + assert _call_events(capture)[-1].client_name == "Claude" + assert _call_events(capture)[-1].client_version == "1.0.0" + + +async def test_a_connection_that_never_handshook_gets_no_client_name(capture): + """The stateless-HTTP shape: a fresh session per request, none of which + handshook. The honest answer is "unknown", never the last name we saw.""" + server = create_community_todo_server() + track(server, "proj_test") + middleware = server.middleware[0] + + await _handshake(middleware, _FakeConnection(), "Cursor", "2.6.22") + + await _tool_call(middleware, _FakeConnection()) + assert _call_events(capture)[-1].client_name is None + assert _call_events(capture)[-1].client_version is None + + +async def test_strip_preserves_the_rest_of_the_request_message(capture): + """The stripped message is a copy of the customer's, not a rebuilt + `CallToolRequestParams`: rebuilding drops `_meta` (and, in the 2026 era, + `input_responses`/`request_state`), which severs MRTR continuations.""" + from fastmcp.server.middleware import MiddlewareContext + from fastmcp.tools import ToolResult + from mcp.types import CallToolRequestParams, TextContent + + server = create_community_todo_server() + track(server, "proj_test") + middleware = server.middleware[0] + + seen: dict = {} + + async def call_next(ctx): + seen["message"] = ctx.message + return ToolResult(content=[TextContent(type="text", text="ok")]) + + message = CallToolRequestParams( + name="add_todo", + arguments={"text": "hi", "context": "why"}, + _meta={"trace": "abc"}, + ) + await middleware( + MiddlewareContext(message=message, method="tools/call"), call_next + ) + + assert seen["message"].arguments == {"text": "hi"} + assert getattr(seen["message"].meta, "trace", None) == "abc" + assert seen["message"].meta is message.meta + # The customer's own message object is untouched. + assert message.arguments == {"text": "hi", "context": "why"} + + +@pytest.mark.parametrize("flavor", ["by_type_name", "by_result_type"]) +async def test_intermediate_mrtr_round_is_tagged_but_never_decorated(capture, flavor): + """A round that asks the client for more input is not the completing round, + so it carries no mint-back — text or structured.""" + from fastmcp.server.middleware import Middleware + from fastmcp.tools import ToolResult + from mcp.types import TextContent + + class InputRequiredToolResult(ToolResult): + pass + + class LaterEraToolResult(ToolResult): + result_type: str = "input_required" + + cls = InputRequiredToolResult if flavor == "by_type_name" else LaterEraToolResult + + class Intermediate(Middleware): + async def on_call_tool(self, context, call_next): + return cls(content=[TextContent(type="text", text="need more")]) + + server = _new_server("mrtr-server") + + @server.tool(output_schema=None) + def ask(text: str) -> str: + """Needs another round.""" + return text + + server.add_middleware(Intermediate()) + track(server, "proj_test") + + async with create_community_test_client(server) as client: + result = await client.call_tool("ask", {"text": "round one"}) + + assert [block.text for block in result.content] == ["need more"] + assert result.structured_content is None + event = _call_events(capture)[0] + assert event.tags["agentcat_mrtr"] == "input_required" + assert event.session_id.startswith("ses_") + + +async def test_tools_added_after_track_are_injected_and_tracked(capture): + """track() may run before a single tool exists: the middleware reads the + provider's listing per request, so late registrations are covered.""" + server = _new_server("late-server") + track(server, "proj_test") + + @server.tool + def late(value: str) -> str: + """Registered after track().""" + return f"late:{value}" + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + assert "session_id" in _named(listed, "late").inputSchema["properties"] + + result = await client.call_tool( + "late", {"value": "v", "session_id": sid("late")} + ) + + assert "late:v" in _text(result) + assert _call_events(capture)[0].resource_name == "late" + assert _call_events(capture)[0].session_id == sid("late") + + +async def test_a_call_before_any_listing_rebuilds_the_strip_registry(capture): + """tools/call may land on an instance that never served tools/list; the + rebuild reads the server's own listing so the strip still matches.""" + seen: dict = {} + server = _new_server("rebuild-server") + + @server.tool + def probe(text: str) -> str: + """Would fail validation if handed an argument it never declared.""" + seen["text"] = text + return "ok" + + track(server, "proj_test") + + async with create_community_test_client(server) as client: + # No list_tools first. + result = await client.call_tool( + "probe", {"text": "t", "session_id": sid("rb"), "context": "why"} + ) + + assert result.is_error is False, _text(result) + assert seen == {"text": "t"} + assert _call_events(capture)[0].session_id == sid("rb") + + +async def test_tool_with_its_own_context_parameter_is_left_alone(capture): + """A customer parameter named `context` is theirs: it is neither + re-described nor stripped.""" + seen: dict = {} + server = _new_server("context-server") + + @server.tool + def search(query: str, context: str) -> str: + """A tool whose own API already has a context argument.""" + seen.update(query=query, context=context) + return "found" + + track(server, "proj_test") + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + schema = _named(listed, "search").inputSchema + assert "description" not in schema["properties"]["context"] + assert schema["required"] == ["query", "context"] + + await client.call_tool("search", {"query": "q", "context": "theirs"}) + + assert seen == {"query": "q", "context": "theirs"} + # It is still read as the intent — the event records what the agent sent. + assert _call_events(capture)[0].user_intent == "theirs" + + +async def test_two_tracked_servers_stay_isolated(capture): + """Registries and project IDs are per-server; one server's listing never + settles another's strip.""" + first = _new_server("first") + second = _new_server("second") + + @first.tool + def alpha(a: str) -> str: + """First server's tool.""" + return "alpha" + + @second.tool + def beta(b: str) -> str: + """Second server's tool.""" + return "beta" + + track(first, "proj_one", AgentCatOptions(enable_report_missing=False)) + track(second, "proj_two", AgentCatOptions(enable_agent_tracking=True)) + + async with create_community_test_client(first) as client: + listed = await client.list_tools() + assert "agent_id" not in _named(listed, "alpha").inputSchema["properties"] + await client.call_tool("alpha", {"a": "1", "session_id": sid("one")}) + + async with create_community_test_client(second) as client: + listed = await client.list_tools() + assert "agent_id" in _named(listed, "beta").inputSchema["properties"] + await client.call_tool("beta", {"b": "2", "session_id": sid("two")}) + + events = _call_events(capture) + assert [e.resource_name for e in events] == ["alpha", "beta"] + assert [e.session_id for e in events] == [sid("one"), sid("two")] + assert [e.project_id for e in events] == ["proj_one", "proj_two"] + + +async def test_event_carries_server_and_sdk_metadata(capture): + server = create_community_todo_server() + track(server, "proj_test") + + async with create_community_test_client(server) as client: + await client.call_tool("add_todo", {"text": "meta"}) + + event = _call_events(capture)[0] + assert event.server_name == "todo-server" + assert event.sdk_language.startswith("Python ") + assert event.duration is not None and event.duration >= 0 + + +def test_a_tracked_server_is_collectable_once_the_customer_drops_it(): + """Nothing AgentCat holds may outlive the server (changelog §6.8). + + The community adapter keeps no module-level per-server map — the middleware + lives in the server's own `middleware` list, and its per-connection + handshake cache is weakly keyed on sessions by values that do not reference + them — so this is a guard against that changing, and the community half of + the same audit the official adapters carry. + """ + import gc + import weakref + + alive = [] + for _ in range(3): + server = create_community_todo_server() + track(server, "proj_test") + alive.append(weakref.ref(server)) + del server + + gc.collect() + assert [ref() for ref in alive] == [None, None, None] diff --git a/tests/community/test_community_v3_inject_context.py b/tests/community/test_community_v3_inject_context.py index 4f5ffd7..bdeb7cd 100644 --- a/tests/community/test_community_v3_inject_context.py +++ b/tests/community/test_community_v3_inject_context.py @@ -1,29 +1,30 @@ -"""Regression tests for context injection in the FastMCP v3 middleware. - -Root cause reproduced here: OpenAPI-generated FastMCP v3 tools hold a reference -to an ``httpx.AsyncClient``, which contains a ``threading.RLock``. The old -implementation did ``copy.deepcopy(tool)`` to inject the ``context`` parameter, -which raised ``TypeError: cannot pickle '_thread.RLock' object`` for every such -tool on every ``tools/list`` — silently dropping context injection and flooding -diagnostics with errors (observed for proj_3E07PMEFqZoF9sc6QeWvoaNbpet). +"""Regression guard: the community adapter never deep-copies a customer Tool. + +Root cause reproduced here: OpenAPI-generated FastMCP tools hold a reference to +an ``httpx.AsyncClient``, which contains a ``threading.RLock``. A middleware +that did ``copy.deepcopy(tool)`` to inject parameters raised ``TypeError: cannot +pickle '_thread.RLock' object`` for every such tool on every ``tools/list`` — +silently dropping injection and flooding diagnostics with errors (observed for +proj_3E07PMEFqZoF9sc6QeWvoaNbpet). + +The v2 adapter copies only the schema dicts and rebuilds each tool with +``model_copy(update=...)``, so the invariant is: injection succeeds on a tool +the interpreter refuses to deep-copy, and the customer's original is untouched. """ -import asyncio -from datetime import datetime, timezone - import copy + import pytest -from agentcat.modules.overrides.community_v3 import middleware as v3_middleware -from agentcat.modules.overrides.community_v3.middleware import AgentCatMiddleware -from agentcat.types import AgentCatData, AgentCatOptions, SessionInfo +from agentcat.modules.constants import CONTEXT_PARAM, SESSION_ID_PARAM +from agentcat.types import AgentCatData, AgentCatOptions -# The community_v3 middleware and FastMCP.from_openapi are FastMCP v3+ only. Skip -# this module entirely when FastMCP is absent (test-without-fastmcp job) or on the -# v2 compatibility matrix, without importing fastmcp at module top level. +# FastMCP.from_openapi is FastMCP v3+ only. Skip this module entirely when +# FastMCP is absent (test-without-fastmcp job), without importing it at module +# top level. try: - import httpx import fastmcp + import httpx from fastmcp import FastMCP HAS_FASTMCP_V3 = int(fastmcp.__version__.split(".")[0]) >= 3 @@ -32,22 +33,19 @@ pytestmark = pytest.mark.skipif( not HAS_FASTMCP_V3, - reason="Requires FastMCP v3+ (community_v3 OpenAPI middleware path)", + reason="Requires FastMCP v3+ (community OpenAPI provider)", ) def _make_data() -> AgentCatData: return AgentCatData( project_id="test_project", - session_id="test_session", - session_info=SessionInfo(client_name="TestClient", client_version="1.0.0"), - last_activity=datetime.now(timezone.utc), options=AgentCatOptions(custom_context_description="Why are you doing this?"), ) -def _openapi_tool(): - """An OpenAPI-generated tool holding an httpx client (non-deepcopyable).""" +def _openapi_server(): + """A FastMCP server whose only tool holds a live httpx client.""" spec = { "openapi": "3.0.0", "info": {"title": "acme", "version": "1"}, @@ -62,64 +60,79 @@ def _openapi_tool(): }, } client = httpx.AsyncClient(base_url="https://example.com") - server = FastMCP.from_openapi(openapi_spec=spec, client=client, name="acme") - tools = server.list_tools() - if asyncio.iscoroutine(tools): - tools = asyncio.run(tools) - return server, tools[0] + return FastMCP.from_openapi(openapi_spec=spec, client=client, name="acme") + + +async def _openapi_tool(): + """An OpenAPI-generated tool holding an httpx client (non-deepcopyable).""" + server = _openapi_server() + return server, (await server.list_tools())[0] + + +async def _inject(server, tools): + """Run the adapter's tools/list hook over a fixed tool list.""" + from agentcat.modules.adapters.community import ERA_V3, AgentCatMiddleware + middleware = AgentCatMiddleware(_make_data(), server, ERA_V3) -def test_openapi_tool_is_not_deepcopyable(): + async def call_next(_context): + return tools + + return await middleware.on_list_tools(_Context(), call_next) + + +class _Context: + """The two attributes the tools/list hook reads off a MiddlewareContext.""" + + method = "tools/list" + message = None + fastmcp_context = None + + +async def test_openapi_tool_is_not_deepcopyable(): """Guard: confirms the repro condition (deepcopy raises on the RLock).""" - _server, tool = _openapi_tool() + _server, tool = await _openapi_tool() with pytest.raises(TypeError, match="cannot pickle '_thread.RLock' object"): copy.deepcopy(tool) -def test_context_injected_into_openapi_tool(): - """Context injection must succeed even for non-deepcopyable tools.""" - server, tool = _openapi_tool() - middleware = AgentCatMiddleware(_make_data(), server) +async def test_parameters_injected_into_an_openapi_tool(): + """Injection must succeed even for non-deepcopyable tools.""" + server, tool = await _openapi_tool() - result = middleware._inject_context_into_tools([tool]) + result = await _inject(server, [tool]) assert len(result) == 1 params = result[0].parameters - assert "context" in params["properties"], "context was not injected" - assert "context" in params["required"] + assert SESSION_ID_PARAM in params["properties"], "session_id was not injected" + assert CONTEXT_PARAM in params["properties"], "context was not injected" assert ( - params["properties"]["context"]["description"] == "Why are you doing this?" + params["properties"][CONTEXT_PARAM]["description"] == "Why are you doing this?" ) + # Required, as in 1.x: a schema-validating client refusing to send a call + # without it is the only enforcement an injected parameter has. + assert CONTEXT_PARAM in params["required"] -def test_original_tool_not_mutated(): +async def test_original_tool_not_mutated(): """Injection must not mutate the server's original tool object.""" - server, tool = _openapi_tool() - middleware = AgentCatMiddleware(_make_data(), server) - - middleware._inject_context_into_tools([tool]) - - assert "context" not in (tool.parameters or {}).get("properties", {}) - + server, tool = await _openapi_tool() + before = copy.deepcopy(tool.parameters or {}) -def test_copy_failure_logs_fastmcp_version(monkeypatch): - """If a tool still can't be copied, the log names the fastmcp version.""" - from importlib.metadata import version + result = await _inject(server, [tool]) - server, tool = _openapi_tool() - middleware = AgentCatMiddleware(_make_data(), server) + assert result[0] is not tool + assert (tool.parameters or {}) == before - def _boom(*args, **kwargs): - raise RuntimeError("copy blew up") - monkeypatch.setattr(v3_middleware.copy, "deepcopy", _boom) +async def test_a_failed_injection_serves_the_customers_list(monkeypatch): + """If the pipeline blows up, the client still gets the customer's tools.""" + from agentcat.modules.adapters import community - logged: list[str] = [] - monkeypatch.setattr(v3_middleware, "write_to_log", lambda msg: logged.append(msg)) + def boom(*args, **kwargs): + raise RuntimeError("injection exploded") - result = middleware._inject_context_into_tools([tool]) + monkeypatch.setattr(community, "build_injected_schemas", boom) - assert result == [tool] # falls back to the untouched original - assert len(logged) == 1 - assert f"fastmcp {version('fastmcp')}" in logged[0] - assert "list_severities" in logged[0] + server, tool = await _openapi_tool() + assert await _inject(server, [tool]) == [tool] diff --git a/tests/community/test_community_v3_openapi.py b/tests/community/test_community_v3_openapi.py index 1caa96e..ac1ae57 100644 --- a/tests/community/test_community_v3_openapi.py +++ b/tests/community/test_community_v3_openapi.py @@ -1,22 +1,21 @@ -"""End-to-end tests for AgentCat against OpenAPI-generated FastMCP v3 servers. +"""End-to-end tests for AgentCat against OpenAPI-generated FastMCP servers. These drive the real middleware dispatch (``tools/list`` and ``tools/call``) through a FastMCP ``Client`` against tools that hold a live ``httpx.AsyncClient`` (mock transport, no network). This is the coverage that was missing when the -``copy.deepcopy(tool)`` regression (PR #38) shipped: the whole suite only ever -exercised plain function tools, which deep-copy cleanly. +``copy.deepcopy(tool)`` regression (PR #38) shipped: the rest of the suite only +ever exercises plain function tools, which deep-copy cleanly. """ import copy -import time -from unittest.mock import patch import pytest from agentcat import AgentCatOptions, track -from agentcat.modules.event_queue import EventQueue, set_event_queue -from agentcat.modules.overrides.community_v3 import middleware as v3_middleware +from agentcat.modules.adapters import community +from agentcat.modules.constants import SESSION_ID_PARAM +from ..test_utils import sid from ..test_utils.community_client import create_community_test_client from ..test_utils.community_openapi_server import ( HAS_FASTMCP_V3, @@ -26,34 +25,24 @@ pytestmark = pytest.mark.skipif( not HAS_FASTMCP_V3, - reason="Requires FastMCP v3+ (OpenAPI middleware path)", + reason="Requires FastMCP v3+ (OpenAPI provider)", ) CONTEXT_DESC = "Why are you making this tool call?" -@pytest.fixture -def captured_events(): - """Swap in a mock-backed event queue and collect published events.""" - from agentcat.modules.event_queue import event_queue as original_queue - from unittest.mock import MagicMock - +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" events: list = [] - mock_api_client = MagicMock() - - def capture_event(publish_event_request): - events.append(publish_event_request) + from agentcat.modules import event_queue - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - set_event_queue(EventQueue(api_client=mock_api_client)) - try: - yield events - finally: - set_event_queue(original_queue) + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events def _options(**overrides) -> AgentCatOptions: - base = dict(enable_tracing=True, custom_context_description=CONTEXT_DESC) + base = {"enable_tracing": True, "custom_context_description": CONTEXT_DESC} base.update(overrides) return AgentCatOptions(**base) @@ -63,9 +52,8 @@ def _tool_call_events(events, name=None): return [e for e in out if name is None or e.resource_name == name] -@pytest.mark.asyncio -async def test_list_tools_injects_context(captured_events): - """Every OpenAPI tool exposes the injected context param to the client.""" +async def test_list_tools_injects_handles_and_context(capture): + """Every OpenAPI tool exposes the injected parameters to the client.""" server = create_community_openapi_server() track(server, "test_project", _options()) @@ -77,31 +65,31 @@ async def test_list_tools_injects_context(captured_events): assert name in by_name, f"{name} missing from list_tools" schema = by_name[name].inputSchema props = schema.get("properties", {}) + assert SESSION_ID_PARAM in props, f"session_id not injected into {name}" assert "context" in props, f"context not injected into {name}" assert props["context"]["description"] == CONTEXT_DESC - assert "context" in schema.get("required", []), f"context not required on {name}" + # session_id is never required — omitting it is the minting signal — + # but context is, as it was in 1.x. + assert SESSION_ID_PARAM not in schema.get("required", []) + assert "context" in schema["required"] + +async def test_no_copy_error_logged(capture, monkeypatch): + """A tools/list against OpenAPI tools must not log any injection failure.""" + logged: list[str] = [] + monkeypatch.setattr(community, "write_to_log", logged.append) -@pytest.mark.asyncio -async def test_no_copy_error_logged(captured_events): - """A tools/list against OpenAPI tools must not log any copy failure.""" server = create_community_openapi_server() track(server, "test_project", _options()) - with patch.object(v3_middleware, "write_to_log") as mock_log: - async with create_community_test_client(server) as client: - await client.list_tools() + async with create_community_test_client(server) as client: + await client.list_tools() - copy_errors = [ - c.args[0] - for c in mock_log.call_args_list - if c.args and "Error copying tool" in str(c.args[0]) - ] - assert copy_errors == [], f"unexpected copy failures logged: {copy_errors}" + failures = [line for line in logged if "injection failed" in line] + assert failures == [], f"unexpected injection failures logged: {failures}" -@pytest.mark.asyncio -async def test_original_tools_not_mutated(captured_events): +async def test_original_tools_not_mutated(capture): """Injection must not mutate the server's cached tools across repeated lists.""" server = create_community_openapi_server() track(server, "test_project", _options()) @@ -111,14 +99,14 @@ async def raw_severity_props(): raw = {t.name: t for t in await server.list_tools(run_middleware=False)} return (raw["get_severity"].parameters or {}).get("properties", {}) - # The server's own cached tool never gains a context param. + # The server's own cached tool never gains an injected param. assert "context" not in await raw_severity_props() async with create_community_test_client(server) as client: first = {t.name: t.inputSchema for t in await client.list_tools()} second = {t.name: t.inputSchema for t in await client.list_tools()} - # Client sees context injected... + # Client sees the injection... assert "context" in first["get_severity"]["properties"] # ...repeated calls are stable... assert first == second @@ -126,103 +114,95 @@ async def raw_severity_props(): assert "context" not in await raw_severity_props() -@pytest.mark.asyncio -async def test_call_tool_strips_context_and_captures_intent(captured_events): - """context is captured as intent and stripped before the downstream HTTP call.""" +async def test_call_tool_strips_injected_params_and_captures_intent(capture): + """Injected params are captured on the event and stripped before the + downstream HTTP call.""" requests: list = [] server = create_community_openapi_server(record_requests=requests) track(server, "test_project", _options()) async with create_community_test_client(server) as client: await client.call_tool( - "get_severity", {"id": "42", "context": "investigating an outage"} + "get_severity", + { + "id": "42", + "context": "investigating an outage", + SESSION_ID_PARAM: sid("openapi"), + }, ) - time.sleep(1.0) # let the event-queue worker drain - calls = _tool_call_events(captured_events, "get_severity") + calls = _tool_call_events(capture, "get_severity") assert calls, "no tools/call event captured" event = calls[-1] assert event.user_intent == "investigating an outage" - assert (event.parameters.get("arguments") or {}) == {"id": "42"} - # The intent string must never reach the customer's backend. + assert event.session_id == sid("openapi") + # The event records the RAW arguments the agent sent. + assert event.parameters["arguments"]["context"] == "investigating an outage" + # Neither the intent nor the handle may reach the customer's backend. assert requests, "downstream request was not recorded" assert not any(b"investigating an outage" in (r.content or b"") for r in requests) assert not any("investigating an outage" in str(r.url) for r in requests) + assert not any(sid("openapi") in str(r.url) for r in requests) -@pytest.mark.asyncio -async def test_call_tool_error_captured(captured_events): - """A failing OpenAPI HTTP call surfaces to the client and is captured as an error.""" +async def test_call_tool_error_captured(capture): + """A failing OpenAPI HTTP call surfaces to the client and is captured.""" + from fastmcp.exceptions import ToolError + server = create_community_openapi_server() track(server, "test_project", _options()) async with create_community_test_client(server) as client: - with pytest.raises(Exception): + with pytest.raises(ToolError): await client.call_tool("boom", {}) - time.sleep(1.0) - boom = _tool_call_events(captured_events, "boom") + boom = _tool_call_events(capture, "boom") assert boom, "no tools/call event captured for boom" assert boom[-1].is_error is True assert boom[-1].error is not None + assert boom[-1].error["platform"] == "python" -@pytest.mark.asyncio -async def test_tools_list_event_serializes_openapi_tool(captured_events): - """The tools/list event response serializes OpenAPITool subclasses cleanly.""" - server = create_community_openapi_server() - track(server, "test_project", _options()) - - async with create_community_test_client(server) as client: - await client.list_tools() - time.sleep(1.0) - - list_events = [e for e in captured_events if e.event_type == "mcp:tools/list"] - assert list_events, "no tools/list event captured" - response = list_events[-1].response - assert response and isinstance(response.get("tools"), list) - names = {t.get("name") for t in response["tools"]} - assert set(OPENAPI_TOOL_NAMES).issubset(names) - - -@pytest.mark.asyncio -async def test_get_more_tools_alongside_openapi(captured_events): - """get_more_tools coexists with OpenAPI tools and is excluded from context injection.""" +async def test_get_more_tools_alongside_openapi(capture): + """get_more_tools coexists with OpenAPI tools and keeps its own context.""" server = create_community_openapi_server() track(server, "test_project", _options(enable_report_missing=True)) async with create_community_test_client(server) as client: by_name = {t.name: t for t in await client.list_tools()} assert "get_more_tools" in by_name - # get_more_tools carries its own context arg by design; other tools get one injected. + # get_more_tools carries its own context arg by design; other tools get + # one injected. assert "context" in by_name["get_severity"].inputSchema.get("properties", {}) - result = await client.call_tool("get_more_tools", {"context": "need more tools"}) - assert result is not None + assert by_name["get_more_tools"].inputSchema["required"] == ["context"] + result = await client.call_tool( + "get_more_tools", {"context": "need more tools"} + ) + assert "Unfortunately" in "".join( + c.text for c in result.content if hasattr(c, "text") + ) + + assert _tool_call_events(capture, "get_more_tools") + +async def test_tools_call_event_response_is_json_safe(capture): + """The captured event's response must survive the generated API client.""" + import json + + from agentcat_api.api_client import ApiClient -@pytest.mark.asyncio -async def test_many_tools_single_pass_no_errors(captured_events): - """The full multi-tool spec lists in one pass with context on all and no errors.""" server = create_community_openapi_server() track(server, "test_project", _options()) - with patch.object(v3_middleware, "write_to_log") as mock_log: - async with create_community_test_client(server) as client: - tools = await client.list_tools() + async with create_community_test_client(server) as client: + await client.call_tool("get_severity", {"id": "7"}) - injected = [ - t for t in tools - if t.name != "get_more_tools" - and "context" in t.inputSchema.get("properties", {}) - ] - assert len(injected) >= len(OPENAPI_TOOL_NAMES) - assert not any( - c.args and "Error copying tool" in str(c.args[0]) - for c in mock_log.call_args_list - ) + event = _tool_call_events(capture, "get_severity")[-1] + assert isinstance(event.response, dict) + json.dumps(event.response) + ApiClient.sanitize_for_serialization(ApiClient(), event.response) -@pytest.mark.asyncio async def test_openapi_tool_not_deepcopyable(): """Precondition guard: OpenAPI tools hold non-deepcopyable runtime state.""" server = create_community_openapi_server() diff --git a/tests/community/test_community_v3_runtime_state_tools.py b/tests/community/test_community_v3_runtime_state_tools.py index 7aeb79a..e0e05fc 100644 --- a/tests/community/test_community_v3_runtime_state_tools.py +++ b/tests/community/test_community_v3_runtime_state_tools.py @@ -1,24 +1,25 @@ -"""Regression guard across every FastMCP v3 tool type that holds runtime state. +"""Regression guard across every FastMCP tool type that holds runtime state. The ``copy.deepcopy(tool)`` regression (PR #38) was reported for OpenAPI tools, but the same failure mode applies to any tool that references live runtime state: -- ``OpenAPITool`` -> holds an ``httpx.AsyncClient`` (threading.RLock) -- ``ProxyTool`` -> holds a client factory +- ``OpenAPITool`` -> holds an ``httpx.AsyncClient`` (threading.RLock) +- ``ProxyTool`` -> holds a client factory - ``FastMCPProviderTool`` -> holds a live sub-server reference -This suite asserts the two subclass-agnostic invariants that matter for all of -them: after ``track()``, a client ``tools/list`` sees the injected ``context`` -param on every tool, and no "Error copying tool" is ever logged. +This suite asserts the subclass-agnostic invariants that matter for all of them: +after ``track()``, a client ``tools/list`` sees AgentCat's parameters on every +tool, nothing is logged as a failure, and a call round-trips with the injected +parameters stripped back off. """ -from unittest.mock import patch - import pytest from agentcat import AgentCatOptions, track -from agentcat.modules.overrides.community_v3 import middleware as v3_middleware +from agentcat.modules.adapters import community +from agentcat.modules.constants import CONTEXT_PARAM, SESSION_ID_PARAM +from ..test_utils import sid from ..test_utils.community_client import create_community_test_client from ..test_utils.community_openapi_server import ( HAS_FASTMCP_V3, @@ -33,6 +34,15 @@ ) +@pytest.fixture(autouse=True) +def capture(monkeypatch): + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + def _build(factory): """Build a server from a factory, skipping if this fastmcp version can't.""" try: @@ -50,8 +60,10 @@ def _build(factory): ], ids=["openapi", "proxy", "mounted"], ) -@pytest.mark.asyncio -async def test_context_injected_without_copy_errors(factory): +async def test_parameters_injected_without_failures(factory, monkeypatch, capture): + logged: list[str] = [] + monkeypatch.setattr(community, "write_to_log", logged.append) + server = _build(factory) track( server, @@ -59,21 +71,44 @@ async def test_context_injected_without_copy_errors(factory): AgentCatOptions(enable_tracing=True, custom_context_description="Why?"), ) - with patch.object(v3_middleware, "write_to_log") as mock_log: - async with create_community_test_client(server) as client: - tools = await client.list_tools() + async with create_community_test_client(server) as client: + tools = await client.list_tools() assert tools, "server exposed no tools" for tool in tools: - if tool.name == "get_more_tools": - continue props = tool.inputSchema.get("properties", {}) - assert "context" in props, f"context not injected into {tool.name}" - assert "context" in tool.inputSchema.get("required", []) - - copy_errors = [ - c.args[0] - for c in mock_log.call_args_list - if c.args and "Error copying tool" in str(c.args[0]) - ] - assert copy_errors == [], f"copy failures logged: {copy_errors}" + assert SESSION_ID_PARAM in props, f"session_id not injected into {tool.name}" + if tool.name != "get_more_tools": + assert CONTEXT_PARAM in props, f"context not injected into {tool.name}" + + failures = [line for line in logged if "injection failed" in line] + assert failures == [], f"injection failures logged: {failures}" + + +@pytest.mark.parametrize( + "factory,tool_name,arguments", + [ + (create_community_proxy_server, "ping", {"text": "hi"}), + (create_community_mounted_server, "sub_sub_action", {"value": "hi"}), + ], + ids=["proxy", "mounted"], +) +async def test_call_round_trips_through_a_runtime_state_tool( + factory, tool_name, arguments, capture +): + """The injected params are stripped before a proxied/mounted tool runs.""" + server = _build(factory) + track(server, "test_project", AgentCatOptions(enable_report_missing=False)) + + async with create_community_test_client(server) as client: + listed = {t.name for t in await client.list_tools()} + if tool_name not in listed: # pragma: no cover - naming differs by version + pytest.skip(f"{tool_name} not exposed by this FastMCP: {sorted(listed)}") + result = await client.call_tool( + tool_name, {**arguments, SESSION_ID_PARAM: sid("runtime"), "context": "why"} + ) + + assert result.is_error is False + assert "hi" in "".join(c.text for c in result.content if hasattr(c, "text")) + events = [e for e in capture if e.event_type == "mcp:tools/call"] + assert [e.session_id for e in events] == [sid("runtime")] diff --git a/tests/conftest.py b/tests/conftest.py index 4f40e0a..0916782 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,7 +1,59 @@ import os +from importlib.metadata import version # Belt-and-suspenders: force diagnostics off before any test imports/runs, so no # test ordering or future change to the auto-disable detection can ever ship OTLP # diagnostics to the live collector from our own suite. Diagnostics-specific tests # opt back in explicitly with DISABLE_DIAGNOSTICS=false plus mocked HTTP. os.environ["DISABLE_DIAGNOSTICS"] = "true" + + +# ── Per-era collection gating ──────────────────────────────────────────────── +# The suite runs under two mutually exclusive dependency sets (see pyproject's +# `mcp-legacy` / `mcp-modern` groups). Era-specific test modules import symbols +# that exist on only one side, so each era's collection skips the other's. +MCP_MAJOR = int(version("mcp").split(".")[0]) + +_LEGACY_ONLY = ( + "e2e/official", + "e2e/community_v3", + "community", + "test_tool_context.py", + "test_report_missing.py", + "test_dynamic_tracking.py", + "test_multiple_servers.py", + "test_event_capture_completeness.py", + "test_request_extra.py", + "test_lowlevel_v1_handles.py", + # Every test in this module drives a tracked mcp 1.x server end to end, so + # there is no era-agnostic remainder to rescue: the whole file is gated. + # `test_event_tags_properties.py` and `test_exceptions.py` used to be gated + # here too, taking their era-agnostic unit tests with them; those two now + # import under both majors and mark only their integration class + # (`test_utils.LEGACY_ONLY`). The privacy guard this module encodes has no + # 2.x equivalent yet. + "test_diagnostics_no_payload.py", +) +_MODERN_ONLY = ( + "e2e/official_modern", + "e2e/community_v4", + "test_lowlevel_v2_handles.py", + # FastMCP 4 only: the era ships a second dispatch pass, a default + # dereferencing middleware and real multi-round-trip results, none of which + # exist on the 3.x line this suite's community/ directory covers. + "test_community_v4_handles.py", +) + + +def _ignore_globs(paths: tuple[str, ...]) -> list[str]: + """Ignore each path itself plus everything beneath it. + + Patterns are fnmatched against absolute paths, so a bare trailing `*` on a + directory name would also swallow siblings that merely share the prefix + (`e2e/official` vs `e2e/official_modern`). Anchoring the recursive form on + `/` keeps each entry to exactly its own subtree. + """ + return [pattern for path in paths for pattern in (path, f"{path}/*")] + + +collect_ignore_glob = _ignore_globs(_MODERN_ONLY if MCP_MAJOR < 2 else _LEGACY_ONLY) diff --git a/tests/e2e/community_v2/conftest.py b/tests/e2e/community_v2/conftest.py deleted file mode 100644 index 582730e..0000000 --- a/tests/e2e/community_v2/conftest.py +++ /dev/null @@ -1,100 +0,0 @@ -"""Community FastMCP v2 Streamable-HTTP harness. - -v2 is the legacy FastMCP architecture (ToolManager-based). Skips gracefully -when v2 is not installed — the typical dev venv has v3 installed, and v2 -would conflict with v3 (same package name, different majors). - -The harness uses v2's `streamable_http_app()` (or fallbacks) on a uvicorn -thread, mirroring the official-SDK pattern. -""" - -from __future__ import annotations - -import threading -from typing import Any, Callable, Tuple - -import pytest - -import agentcat -from agentcat import AgentCatOptions -from agentcat.modules.compatibility import ( - is_community_fastmcp_v2, - is_community_fastmcp_v3, -) - -from tests.e2e._helpers import find_free_port, wait_for_port - -try: - from fastmcp import FastMCP as CommunityFastMCP - - HAS_FASTMCP = True -except ImportError: - CommunityFastMCP = None # type: ignore - HAS_FASTMCP = False - - -def _create_v2_todo_server() -> Any: - if CommunityFastMCP is None: - raise RuntimeError("fastmcp not installed") - mcp = CommunityFastMCP("v2-todo") - - @mcp.tool() - def add_todo(text: str, context: str = "") -> str: - return f'Added: "{text}"' - - return mcp - - -def _default_options_factory() -> AgentCatOptions: - return AgentCatOptions(enable_tracing=True) - - -@pytest.fixture(scope="module") -def v2_http_server(request) -> Tuple[str, Any]: - if not HAS_FASTMCP: - pytest.skip("fastmcp not installed") - - server = _create_v2_todo_server() - if is_community_fastmcp_v3(server): - pytest.skip( - "installed fastmcp is v3, not v2 — v2 e2e tests require fastmcp<3" - ) - if not is_community_fastmcp_v2(server): - pytest.skip("server is not detected as community FastMCP v2") - - options_factory: Callable[[], AgentCatOptions] = getattr( - request.module, "AGENTCAT_OPTIONS_FACTORY", _default_options_factory - ) - options = options_factory() - agentcat.track(server, "test_project", options) - - import uvicorn - - # v2 may expose either streamable_http_app() or http_app(transport=...). - # Try the conventional names; fall back if needed. - if hasattr(server, "streamable_http_app"): - app = server.streamable_http_app() - elif hasattr(server, "http_app"): - app = server.http_app(transport="streamable-http") - else: - pytest.skip( - "v2 server has no recognized streamable_http_app/http_app method" - ) - - port = find_free_port() - config = uvicorn.Config(app, host="127.0.0.1", port=port, log_level="error") - uv_server = uvicorn.Server(config) - thread = threading.Thread(target=uv_server.run, daemon=True) - thread.start() - try: - wait_for_port(port, timeout=5.0) - except TimeoutError: - uv_server.should_exit = True - thread.join(timeout=2.0) - raise - - url = f"http://127.0.0.1:{port}/mcp" - yield url, server - - uv_server.should_exit = True - thread.join(timeout=5.0) diff --git a/tests/e2e/community_v2/test_identify_http.py b/tests/e2e/community_v2/test_identify_http.py deleted file mode 100644 index 93ed1f9..0000000 --- a/tests/e2e/community_v2/test_identify_http.py +++ /dev/null @@ -1,58 +0,0 @@ -"""Community FastMCP v2 identify-per-event smoke. - -Skips when v2 is not installed. -""" - -from __future__ import annotations - -import time -from typing import Any, Optional - -import pytest - -from agentcat.modules.internal import get_server_tracking_data -from agentcat.types import UserIdentity - - -pytestmark = pytest.mark.e2e - - -def _set_identify(server, fn) -> None: - # v2 stores tracking data against server._mcp_server (the lowlevel Server), - # not the FastMCP wrapper. - target = getattr(server, "_mcp_server", server) - data = get_server_tracking_data(target) - assert data is not None - data.options.identify = fn - - -@pytest.mark.asyncio -async def test_v2_identify_hook_receives_real_extra( - v2_http_server, capture_queue -): - from fastmcp import Client - from fastmcp.client.transports import StreamableHttpTransport - - url, server = v2_http_server - seen: list = [] - - def identify(_req: Any, extra: Any) -> Optional[UserIdentity]: - seen.append(extra) - return UserIdentity(user_id="v2-user", user_name=None, user_data=None) - - _set_identify(server, identify) - try: - async with Client( - StreamableHttpTransport(url, headers={"X-Identify-V2": "yes"}) - ) as client: - await client.call_tool( - "add_todo", {"text": "id-v2", "context": "id"} - ) - - time.sleep(0.5) - call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] - assert call_events - assert call_events[0].identify_actor_given_id == "v2-user" - assert seen, "v2 identify hook never invoked" - finally: - _set_identify(server, None) diff --git a/tests/e2e/community_v2/test_request_extra_http.py b/tests/e2e/community_v2/test_request_extra_http.py deleted file mode 100644 index 4bef067..0000000 --- a/tests/e2e/community_v2/test_request_extra_http.py +++ /dev/null @@ -1,40 +0,0 @@ -"""Community FastMCP v2 headers smoke. - -Skips when v2 is not installed (the standard dev venv has v3). -""" - -from __future__ import annotations - -import time - -import pytest - - -pytestmark = pytest.mark.e2e - - -@pytest.mark.asyncio -async def test_v2_custom_header_lands_in_extra(v2_http_server, capture_queue): - from fastmcp import Client - from fastmcp.client.transports import StreamableHttpTransport - - url, _ = v2_http_server - async with Client( - StreamableHttpTransport(url, headers={"X-V2-Header": "v2-value"}) - ) as client: - await client.call_tool( - "add_todo", {"text": "v2-h", "context": "v2-h"} - ) - - time.sleep(0.5) - call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] - assert call_events - headers = ( - (call_events[0].parameters or {}) - .get("extra", {}) - .get("requestInfo", {}) - .get("headers", {}) - ) - assert headers.get("x-v2-header") == "v2-value", ( - f"expected x-v2-header in extra.requestInfo.headers, got {headers}" - ) diff --git a/tests/e2e/community_v3/conftest.py b/tests/e2e/community_v3/conftest.py index 1f42ce8..9fae1af 100644 --- a/tests/e2e/community_v3/conftest.py +++ b/tests/e2e/community_v3/conftest.py @@ -4,25 +4,31 @@ mounted on a random uvicorn port. Tests connect with `fastmcp.Client(StreamableHttpTransport(url, headers=...))`. +A test module declares `STATELESS_HTTP = True` at module scope to be served by +a stateless app instead. That is a different code path, not a configuration +detail: a stateless server builds a fresh `ServerSession` per REQUEST, so every +call reaches the last rung of the client-identity ladder — the rung whose +per-connection filing this exists to hold. + Module-scoped: one boot per test file. """ from __future__ import annotations import threading -from typing import Any, Callable, Tuple +from collections.abc import Callable +from typing import Any import pytest import agentcat from agentcat import AgentCatOptions - from tests.e2e._helpers import find_free_port, wait_for_port try: from fastmcp import FastMCP - from agentcat.modules.compatibility import is_community_fastmcp_v3 + from agentcat.modules.detection import ServerFlavor, detect_server HAS_FASTMCP_V3 = True except ImportError: FastMCP = None # type: ignore @@ -34,12 +40,14 @@ def _create_v3_todo_server() -> Any: raise RuntimeError("fastmcp v3 is not installed; cannot run v3 e2e tests") mcp = FastMCP("v3-todo-server") + # No `context` parameter of their own: the one the tests send is AgentCat's + # injected parameter, so the wire path covers injection and stripping. @mcp.tool - def add_todo(text: str, context: str = "") -> str: + def add_todo(text: str) -> str: return f'Added todo: "{text}"' @mcp.tool - def list_todos(context: str = "") -> str: + def list_todos() -> str: return "no todos" return mcp @@ -50,12 +58,12 @@ def _default_options_factory() -> AgentCatOptions: @pytest.fixture(scope="module") -def v3_http_server(request) -> Tuple[str, Any]: +def v3_http_server(request) -> tuple[str, Any]: if not HAS_FASTMCP_V3: pytest.skip("fastmcp v3 not installed") server = _create_v3_todo_server() - if not is_community_fastmcp_v3(server): + if detect_server(server).flavor is not ServerFlavor.COMMUNITY_V3: pytest.skip("installed fastmcp is not v3") options_factory: Callable[[], AgentCatOptions] = getattr( @@ -66,7 +74,10 @@ def v3_http_server(request) -> Tuple[str, Any]: import uvicorn - app = server.http_app(transport="streamable-http") + app = server.http_app( + transport="streamable-http", + stateless_http=getattr(request.module, "STATELESS_HTTP", False), + ) port = find_free_port() config = uvicorn.Config(app, host="127.0.0.1", port=port, log_level="error") uv_server = uvicorn.Server(config) diff --git a/tests/e2e/community_v3/test_event_capture_http.py b/tests/e2e/community_v3/test_event_capture_http.py index 7c3fb6b..0321a13 100644 --- a/tests/e2e/community_v3/test_event_capture_http.py +++ b/tests/e2e/community_v3/test_event_capture_http.py @@ -1,7 +1,8 @@ -"""FastMCP v3 event-capture tests over real Streamable HTTP. +"""Community FastMCP event-capture tests over real Streamable HTTP. -Initialize-event capture is intentionally omitted (handled by ServerSession -internally; see tests/e2e/official/test_event_capture_http.py docstring). +v2 publishes exactly one event type — mcp:tools/call. initialize only feeds the +client-identity ladder, and tools/list is intercepted for schema injection only, +so neither produces an event. """ from __future__ import annotations @@ -10,10 +11,26 @@ import pytest - pytestmark = pytest.mark.e2e +@pytest.mark.asyncio +async def test_handshake_and_list_publish_nothing(v3_http_server, capture_queue): + """A real handshake plus list_tools produces no events at all.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v3_http_server + async with Client(StreamableHttpTransport(url)) as client: + listed = await client.list_tools() + + time.sleep(0.5) + # The listing still went through AgentCat: the handles are on the schemas. + add = next(t for t in listed if t.name == "add_todo") + assert "session_id" in add.inputSchema["properties"] + assert capture_queue == [], [e.event_type for e in capture_queue] + + @pytest.mark.asyncio async def test_call_tool_via_v3(v3_http_server, capture_queue): from fastmcp import Client @@ -21,27 +38,36 @@ async def test_call_tool_via_v3(v3_http_server, capture_queue): url, _ = v3_http_server async with Client(StreamableHttpTransport(url)) as client: - await client.call_tool( - "add_todo", {"text": "v3-call", "context": "x"} - ) + await client.call_tool("add_todo", {"text": "v3-call", "context": "x"}) time.sleep(0.5) call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] assert call_events assert call_events[0].resource_name == "add_todo" + assert call_events[0].user_intent == "x" + # Raw arguments on the event; the tool received the stripped copy. + assert call_events[0].parameters["arguments"]["context"] == "x" @pytest.mark.asyncio -async def test_list_tools_via_v3(v3_http_server, capture_queue): +async def test_task_handle_is_minted_then_echoed(v3_http_server, capture_queue): + """The mint-back travels over the wire, and the echoed handle keys the + second event to the same task.""" from fastmcp import Client from fastmcp.client.transports import StreamableHttpTransport url, _ = v3_http_server async with Client(StreamableHttpTransport(url)) as client: - await client.list_tools() + first = await client.call_tool("add_todo", {"text": "one"}) + text = "".join(c.text for c in first.content if hasattr(c, "text")) + assert "[MCP INSTRUCTIONS]: session_id issued." in text + minted = text.split("session_id=")[1].split(" ")[0] + + await client.call_tool("add_todo", {"text": "two", "session_id": minted}) time.sleep(0.5) - assert any(e.event_type == "mcp:tools/list" for e in capture_queue) + call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] + assert [e.session_id for e in call_events] == [minted, minted] @pytest.mark.asyncio @@ -51,12 +77,27 @@ async def test_v3_event_duration_is_non_negative(v3_http_server, capture_queue): url, _ = v3_http_server async with Client(StreamableHttpTransport(url)) as client: - await client.call_tool( - "add_todo", {"text": "duration", "context": "x"} - ) + await client.call_tool("add_todo", {"text": "duration", "context": "x"}) time.sleep(0.5) call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] assert call_events assert call_events[0].duration is not None assert call_events[0].duration >= 0 + + +@pytest.mark.asyncio +async def test_client_identity_reaches_the_event(v3_http_server, capture_queue): + """The handshake clientInfo is the last rung of the identity ladder, and it + reaches the tools/call event over a real connection.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v3_http_server + async with Client(StreamableHttpTransport(url)) as client: + await client.call_tool("add_todo", {"text": "who", "context": "x"}) + + time.sleep(0.5) + call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] + assert call_events + assert call_events[-1].client_name, "no client name resolved for the call" diff --git a/tests/e2e/community_v3/test_identify_http.py b/tests/e2e/community_v3/test_identify_http.py index 3c794fb..dfd7a61 100644 --- a/tests/e2e/community_v3/test_identify_http.py +++ b/tests/e2e/community_v3/test_identify_http.py @@ -1,16 +1,22 @@ -"""Identify-per-event behavior under FastMCP v3 middleware over real HTTP.""" +"""Identify-per-event behavior under the community adapter over real HTTP. + +v2 has no standalone agentcat:identify event: the hook runs per tool call and +its result is stamped onto that call's event. + +Tests mutate the running server's AgentCatData.options.identify to vary the hook +per scenario, and reset it in finally so later tests start clean. +""" from __future__ import annotations import time -from typing import Any, Optional +from typing import Any import pytest from agentcat.modules.internal import get_server_tracking_data from agentcat.types import UserIdentity - pytestmark = pytest.mark.e2e @@ -20,8 +26,12 @@ def _set_identify(server, fn) -> None: data.options.identify = fn +def _last_call(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"][-1] + + @pytest.mark.asyncio -async def test_identify_hook_runs_under_v3_middleware( +async def test_identify_hook_runs_under_the_community_adapter( v3_http_server, capture_queue ): from fastmcp import Client @@ -30,53 +40,71 @@ async def test_identify_hook_runs_under_v3_middleware( url, server = v3_http_server seen: list = [] - def identify(_req: Any, extra: Any) -> Optional[UserIdentity]: + def identify(_req: Any, extra: Any) -> UserIdentity | None: seen.append(extra) return UserIdentity(user_id="v3-user", user_name=None, user_data=None) _set_identify(server, identify) try: async with Client(StreamableHttpTransport(url)) as client: - await client.call_tool( - "add_todo", {"text": "id-v3", "context": "id"} - ) + await client.call_tool("add_todo", {"text": "id-v3", "context": "id"}) time.sleep(0.5) - call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] - assert call_events - assert call_events[0].identify_actor_given_id == "v3-user" - assert seen, "identify hook never invoked under v3" + assert _last_call(capture_queue).identify_actor_given_id == "v3-user" + assert seen, "identify hook never invoked under the community adapter" finally: _set_identify(server, None) @pytest.mark.asyncio -async def test_agentcat_identify_self_event_via_v3_middleware( +async def test_actor_rides_the_tool_call_event_not_a_self_event( v3_http_server, capture_queue ): + """v2 stamps the actor onto every tools/call event; the standalone + agentcat:identify event is gone.""" from fastmcp import Client from fastmcp.client.transports import StreamableHttpTransport url, server = v3_http_server - def identify(_req: Any, _extra: Any) -> Optional[UserIdentity]: + def identify(_req: Any, _extra: Any) -> UserIdentity | None: return UserIdentity(user_id="v3-bob", user_name=None, user_data=None) _set_identify(server, identify) try: async with Client(StreamableHttpTransport(url)) as client: - await client.call_tool( - "add_todo", {"text": "self-v3", "context": "x"} + await client.call_tool("add_todo", {"text": "self-v3", "context": "x"}) + + time.sleep(0.5) + assert {e.event_type for e in capture_queue} == {"mcp:tools/call"} + assert _last_call(capture_queue).identify_actor_given_id == "v3-bob" + finally: + _set_identify(server, None) + + +@pytest.mark.asyncio +async def test_identify_exception_does_not_break_the_tool_call( + v3_http_server, capture_queue +): + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, server = v3_http_server + + def identify(_req: Any, _extra: Any) -> UserIdentity | None: + raise RuntimeError("identify exploded") + + _set_identify(server, identify) + try: + async with Client(StreamableHttpTransport(url)) as client: + result = await client.call_tool( + "add_todo", {"text": "boom", "context": "x"} ) + assert result.is_error is False time.sleep(0.5) - identify_events = [ - e for e in capture_queue if e.event_type == "agentcat:identify" - ] - assert identify_events, ( - f"expected agentcat:identify under v3, got " - f"{[e.event_type for e in capture_queue]}" - ) - assert identify_events[0].identify_actor_given_id == "v3-bob" + call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] + assert call_events, "tool/call event must still publish despite hook crash" + assert call_events[-1].identify_actor_given_id is None finally: _set_identify(server, None) diff --git a/tests/e2e/community_v3/test_request_extra_http.py b/tests/e2e/community_v3/test_request_extra_http.py index a371ace..b78d0e1 100644 --- a/tests/e2e/community_v3/test_request_extra_http.py +++ b/tests/e2e/community_v3/test_request_extra_http.py @@ -1,4 +1,4 @@ -"""parameters.extra.requestInfo.headers parity for FastMCP v3 over real HTTP.""" +"""parameters.extra.requestInfo.headers parity for community FastMCP over HTTP.""" from __future__ import annotations @@ -26,9 +26,7 @@ async def test_custom_header_lands_in_extra(v3_http_server, capture_queue): async with Client( StreamableHttpTransport(url, headers={"X-V3-Header": "v3-value"}) ) as client: - await client.call_tool( - "add_todo", {"text": "v3-h", "context": "v3-h"} - ) + await client.call_tool("add_todo", {"text": "v3-h", "context": "v3-h"}) time.sleep(0.5) headers = _extra(_last_call(capture_queue)).get("requestInfo", {}).get( @@ -40,49 +38,38 @@ async def test_custom_header_lands_in_extra(v3_http_server, capture_queue): @pytest.mark.asyncio -async def test_list_tools_event_carries_headers_via_v3( - v3_http_server, capture_queue -): - """tools/list events under v3 transport carry parameters.extra. This - exercises the v3 middleware pipeline including the FastMCP - `_current_http_request` ContextVar fallback path.""" +async def test_extra_sits_beside_the_raw_arguments(v3_http_server, capture_queue): + """v2 builds parameters as {"arguments": raw, "extra": {...}} rather than + dumping the whole request.""" from fastmcp import Client from fastmcp.client.transports import StreamableHttpTransport url, _ = v3_http_server async with Client( - StreamableHttpTransport(url, headers={"X-V3-List": "list-v"}) + StreamableHttpTransport(url, headers={"X-V3-Shape": "shape"}) ) as client: - await client.list_tools() + await client.call_tool("add_todo", {"text": "shape", "context": "why"}) time.sleep(0.5) - list_events = [e for e in capture_queue if e.event_type == "mcp:tools/list"] - assert list_events - headers = ( - (list_events[0].parameters or {}) - .get("extra", {}) - .get("requestInfo", {}) - .get("headers", {}) - ) - assert headers.get("x-v3-list") == "list-v", ( - f"expected x-v3-list on tools/list event, got headers={headers}" - ) + event = _last_call(capture_queue) + assert set(event.parameters) == {"arguments", "extra"} + assert event.parameters["arguments"] == {"text": "shape", "context": "why"} + assert _extra(event)["requestInfo"]["headers"]["x-v3-shape"] == "shape" @pytest.mark.asyncio -async def test_meta_dict_present_when_supported(v3_http_server, capture_queue): - """Sanity: extra.meta is either absent or a dict — never a malformed value.""" +async def test_session_id_and_meta_shapes(v3_http_server, capture_queue): + """Sanity: extra.sessionId is a string when present, extra.meta a dict.""" from fastmcp import Client from fastmcp.client.transports import StreamableHttpTransport url, _ = v3_http_server async with Client(StreamableHttpTransport(url)) as client: - await client.call_tool( - "add_todo", {"text": "v3-meta", "context": "meta"} - ) + await client.call_tool("add_todo", {"text": "v3-meta", "context": "meta"}) time.sleep(0.5) extra = _extra(_last_call(capture_queue)) - meta = extra.get("meta") - if meta is not None: - assert isinstance(meta, dict) + if extra.get("sessionId") is not None: + assert isinstance(extra["sessionId"], str) + if extra.get("meta") is not None: + assert isinstance(extra["meta"], dict) diff --git a/tests/e2e/community_v3/test_stateless_http.py b/tests/e2e/community_v3/test_stateless_http.py index 935c005..ec5a146 100644 --- a/tests/e2e/community_v3/test_stateless_http.py +++ b/tests/e2e/community_v3/test_stateless_http.py @@ -1,4 +1,17 @@ -"""FastMCP v3 stateless mode over real HTTP.""" +"""Per-request resolution over a STATELESS Streamable-HTTP server (community). + +The `stateless` option is gone in 2.0 — resolution is per request either way — +so these guard what the option used to protect: a task handle that survives +without any server-side session, and client identity that never leaks from one +connection to another even though one middleware instance serves them all. + +The transport is the point. `stateless_http=True` builds a fresh +`ServerSession` per REQUEST, so the middleware's per-connection filing of the +handshake `clientInfo` has nothing to match and the ladder falls all the way +through on EVERY call. That is exactly where a single "last seen" slot — what +this rung used to be — renames one client's call after another's handshake, and +it is why the fix needed a transport test rather than only a unit one. +""" from __future__ import annotations @@ -7,57 +20,71 @@ import pytest -from agentcat import AgentCatOptions - - -def AGENTCAT_OPTIONS_FACTORY() -> AgentCatOptions: - return AgentCatOptions(enable_tracing=True, stateless=True) - - pytestmark = pytest.mark.e2e +# Read by this tree's conftest: the app really is served statelessly, so the +# transport builds a fresh session per REQUEST and nothing survives a call. +STATELESS_HTTP = True + @pytest.mark.asyncio -async def test_v3_stateless_session_id_null(v3_http_server, capture_queue): +async def test_every_call_carries_a_task_handle(v3_http_server, capture_queue): + """Handles are resolved per request from the arguments, so nothing is held + server-side: session_id carries the task, minted or echoed.""" from fastmcp import Client from fastmcp.client.transports import StreamableHttpTransport url, _ = v3_http_server async with Client(StreamableHttpTransport(url)) as client: - await client.call_tool( - "add_todo", {"text": "s", "context": "stateless-v3"} - ) + first = await client.call_tool("add_todo", {"text": "s", "context": "x"}) + text = "".join(c.text for c in first.content if hasattr(c, "text")) + minted = text.split("session_id=")[1].split(" ")[0] + + await client.call_tool("add_todo", {"text": "s2", "session_id": minted}) time.sleep(0.5) call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] - assert call_events - assert call_events[0].session_id is None + assert len(call_events) == 2 + assert [e.session_id for e in call_events] == [minted, minted] @pytest.mark.asyncio -async def test_v3_stateless_no_session_info_pollution( +async def test_two_clients_different_clientinfo_dont_bleed( v3_http_server, capture_queue ): - """After stateless requests, data.session_info.client_name stays None.""" + """One middleware object serves every connection, and its handshake capture + is the LAST rung of the identity ladder — the one a stateless server always + reaches, because the session that handshook is gone by the time the call + arrives. It is filed per connection, so it can only ever answer for the + connection that made it. + + Each event is matched to the call that produced it by the argument that + call sent, so this asserts ATTRIBUTION: a shared slot puts one name on both + events, and a set-membership check can be satisfied by the wrong pairing. + """ from fastmcp import Client from fastmcp.client.transports import StreamableHttpTransport + from mcp.types import Implementation - url, server = v3_http_server + url, _ = v3_http_server - async def call_once(text: str) -> None: - async with Client(StreamableHttpTransport(url)) as client: - await client.call_tool( - "add_todo", {"text": text, "context": "no-bleed"} - ) + async def call_as(name: str, version: str, text: str) -> None: + async with Client( + StreamableHttpTransport(url), + client_info=Implementation(name=name, version=version), + ) as client: + await client.call_tool("add_todo", {"text": text, "context": "no-bleed"}) - await asyncio.gather(call_once("a"), call_once("b")) + await asyncio.gather( + call_as("Cursor", "2.6.22", "from-cursor"), + call_as("Claude", "1.0.0", "from-claude"), + ) time.sleep(0.7) - from agentcat.modules.internal import get_server_tracking_data - - data = get_server_tracking_data(server) - assert data is not None - assert data.session_info.client_name is None, ( - f"v3 stateless mode polluted session_info.client_name = " - f"{data.session_info.client_name}" - ) + call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] + assert len(call_events) == 2 + attributed = {e.parameters["arguments"]["text"]: e.client_name for e in call_events} + # No name at all is the honest answer for a connection that is already + # gone; SOMEONE ELSE's name never is. + assert attributed["from-cursor"] in (None, "Cursor"), attributed + assert attributed["from-claude"] in (None, "Claude"), attributed diff --git a/tests/e2e/community_v4/__init__.py b/tests/e2e/community_v4/__init__.py new file mode 100644 index 0000000..c44dfba --- /dev/null +++ b/tests/e2e/community_v4/__init__.py @@ -0,0 +1 @@ +"""Streamable-HTTP e2e suite for community FastMCP 4.""" diff --git a/tests/e2e/community_v4/conftest.py b/tests/e2e/community_v4/conftest.py new file mode 100644 index 0000000..d391612 --- /dev/null +++ b/tests/e2e/community_v4/conftest.py @@ -0,0 +1,97 @@ +"""FastMCP v4 Streamable-HTTP harness. + +The 4.x sibling of `tests/e2e/community_v3/conftest.py`: a community FastMCP 4 +server on `mcp.http_app()`, mounted on a random uvicorn port, with tests +connecting through `fastmcp.Client(StreamableHttpTransport(url))`. + +A test module declares `STATELESS_HTTP = True` at module scope to be served by +a stateless app instead. That is a different code path, not a configuration +detail: a stateless server builds a fresh `ServerSession` per REQUEST, so every +call reaches the last rung of the client-identity ladder — the rung whose +per-connection filing this exists to hold. + +Module-scoped: one boot per test file. +""" + +from __future__ import annotations + +import threading +from collections.abc import Callable +from typing import Any + +import pytest + +import agentcat +from agentcat import AgentCatOptions +from tests.e2e._helpers import find_free_port, wait_for_port + +try: + from fastmcp import FastMCP + + from agentcat.modules.detection import ServerFlavor, detect_server + + HAS_FASTMCP_V4 = True +except ImportError: # pragma: no cover - import guard + FastMCP = None # type: ignore + HAS_FASTMCP_V4 = False + + +def _create_v4_todo_server() -> Any: + if FastMCP is None: # pragma: no cover - import guard + raise RuntimeError("fastmcp v4 is not installed; cannot run v4 e2e tests") + mcp = FastMCP("v4-todo-server") + + # No `context` parameter of their own: the one the tests send is AgentCat's + # injected parameter, so the wire path covers injection and stripping. + @mcp.tool + def add_todo(text: str) -> str: + return f'Added todo: "{text}"' + + @mcp.tool + def list_todos() -> str: + return "no todos" + + return mcp + + +def _default_options_factory() -> AgentCatOptions: + return AgentCatOptions(enable_tracing=True) + + +@pytest.fixture(scope="module") +def v4_http_server(request) -> tuple[str, Any]: + if not HAS_FASTMCP_V4: # pragma: no cover - import guard + pytest.skip("fastmcp v4 not installed") + + server = _create_v4_todo_server() + if detect_server(server).flavor is not ServerFlavor.COMMUNITY_V4: + pytest.skip("installed fastmcp is not v4") + + options_factory: Callable[[], AgentCatOptions] = getattr( + request.module, "AGENTCAT_OPTIONS_FACTORY", _default_options_factory + ) + agentcat.track(server, "test_project", options_factory()) + + import uvicorn + + app = server.http_app( + transport="streamable-http", + stateless_http=getattr(request.module, "STATELESS_HTTP", False), + ) + port = find_free_port() + config = uvicorn.Config(app, host="127.0.0.1", port=port, log_level="error") + uv_server = uvicorn.Server(config) + thread = threading.Thread(target=uv_server.run, daemon=True) + thread.start() + try: + wait_for_port(port, timeout=10.0) + except TimeoutError: # pragma: no cover - boot failure + uv_server.should_exit = True + thread.join(timeout=2.0) + raise + + url = f"http://127.0.0.1:{port}/mcp/" + yield url, server + + uv_server.should_exit = True + thread.join(timeout=5.0) diff --git a/tests/e2e/community_v4/test_session_http.py b/tests/e2e/community_v4/test_session_http.py new file mode 100644 index 0000000..5ab27ac --- /dev/null +++ b/tests/e2e/community_v4/test_session_http.py @@ -0,0 +1,155 @@ +"""Community FastMCP 4 over real Streamable HTTP. + +The in-process tests cover the adapter's logic; this file covers what only a +socket can — the SDK's outbound validation of the injected schema, the wire +mint-back, and the protocol error a malformed request must keep. v2 publishes +exactly one event type: `mcp:tools/call`. `initialize` only feeds the +client-identity ladder and `tools/list` is intercepted for schema injection, so +neither produces an event. +""" + +from __future__ import annotations + +import json +import time + +import httpx2 +import pytest +from fastmcp import Client +from fastmcp.client.transports import StreamableHttpTransport + +from agentcat.modules.constants import ( + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, + SESSION_ID_PARAM, +) + +pytestmark = pytest.mark.e2e + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +async def test_handshake_and_list_publish_nothing(v4_http_server, capture_queue): + """A real handshake plus list_tools produces no events at all — and the + injected schema survives the SDK's outbound validation.""" + url, _ = v4_http_server + async with Client(StreamableHttpTransport(url)) as client: + listed = await client.list_tools() + + time.sleep(0.5) + add = next(t for t in listed if t.name == "add_todo") + assert list(add.input_schema["properties"])[-2:] == [SESSION_ID_PARAM, "context"] + assert MCP_INSTRUCTIONS_KEY in add.output_schema["properties"] + assert capture_queue == [], [e.event_type for e in capture_queue] + + +async def test_task_handle_is_minted_then_echoed(v4_http_server, capture_queue): + """The mint-back travels over the wire — text and structured — and the + echoed handle keys the next event to the same task.""" + url, _ = v4_http_server + async with Client(StreamableHttpTransport(url)) as client: + first = await client.call_tool( + "add_todo", {"text": "one", "context": "first call of the task"} + ) + text = _text(first) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + assert minted.startswith("ses_") + assert first.structured_content[MCP_INSTRUCTIONS_KEY]["session_id"] == minted + + second = await client.call_tool( + "add_todo", {"text": "two", SESSION_ID_PARAM: minted} + ) + assert MINT_BACK_HEADER not in _text(second) + + time.sleep(0.5) + events = _call_events(capture_queue) + assert [e.session_id for e in events] == [minted, minted] + sources = [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] + assert sources == ["minted", "supplied"] + # The event records the call as the agent made it: raw arguments in, the + # customer's undecorated result out. + assert events[0].parameters["arguments"]["context"] == "first call of the task" + assert events[0].user_intent == "first call of the task" + assert MINT_BACK_HEADER not in json.dumps(events[0].response) + assert events[0].duration is not None and events[0].duration >= 0 + + +async def test_client_identity_reaches_the_event(v4_http_server, capture_queue): + """The handshake clientInfo is the last rung of the identity ladder, and it + reaches the tools/call event over a real connection.""" + url, _ = v4_http_server + async with Client(StreamableHttpTransport(url)) as client: + await client.call_tool("add_todo", {"text": "who", "context": "x"}) + + time.sleep(0.5) + assert _call_events(capture_queue)[-1].client_name + + +async def test_a_malformed_tools_call_keeps_its_own_protocol_error( + v4_http_server, capture_queue +): + """FastMCP 4 runs the middleware chain a SECOND time for a component + request that failed before the interior chain did, and hands the hooks the + RAW params mapping rather than a typed model. + + A `tools/call` with no `name` is exactly that request. AgentCat must let it + past untouched: an `AttributeError` raised in the hook would REPLACE the + customer server's own `-32602` on the wire, and no real client can be made + to send this, so only a hand-built request reaches it. + """ + url, _ = v4_http_server + headers = { + "Content-Type": "application/json", + "Accept": "application/json, text/event-stream", + "MCP-Protocol-Version": "2025-06-18", + } + async with httpx2.AsyncClient(follow_redirects=True) as http: + handshake = await http.post( + url, + headers=headers, + json={ + "jsonrpc": "2.0", + "id": 1, + "method": "initialize", + "params": { + "protocolVersion": "2025-06-18", + "capabilities": {}, + "clientInfo": {"name": "malformed-probe", "version": "1"}, + }, + }, + ) + session_id = handshake.headers.get("mcp-session-id") + if session_id: + headers["Mcp-Session-Id"] = session_id + await http.post( + url, + headers=headers, + json={"jsonrpc": "2.0", "method": "notifications/initialized"}, + ) + response = await http.post( + url, + headers=headers, + json={ + "jsonrpc": "2.0", + "id": 2, + "method": "tools/call", + "params": {"arguments": {"text": "no name at all"}}, + }, + ) + + body = response.text + payload = json.loads(body.split("data: ", 1)[1]) + assert payload["error"]["code"] == -32602, body + assert "model_copy" not in payload["error"]["message"], body + + time.sleep(0.5) + assert _call_events(capture_queue) == [] diff --git a/tests/e2e/community_v4/test_stateless_http.py b/tests/e2e/community_v4/test_stateless_http.py new file mode 100644 index 0000000..ccd836d --- /dev/null +++ b/tests/e2e/community_v4/test_stateless_http.py @@ -0,0 +1,92 @@ +"""A genuinely stateless HTTP server — the transport the identity bug lived on. + +Every other e2e module in this tree boots a stateful app, where one +`ServerSession` serves a whole connection. `stateless_http=True` builds a fresh +one per REQUEST, and that is not a configuration detail for AgentCat: the +session is what tells one caller from another, so under stateless HTTP the +per-connection filing of the handshake `clientInfo` has nothing to hold and +every call falls through to whatever rung answers next. + +One middleware object serves every connection. A single "last seen" slot for +the handshake identity therefore let a later client's `initialize` rename an +earlier client's call — and stateless HTTP is exactly where that fires on every +call rather than never. The fix is unit-tested; this is the transport that +would have caught it. +""" + +from __future__ import annotations + +import asyncio +import time + +import pytest + +pytestmark = pytest.mark.e2e + +# Read by `tests/e2e/community_v4/conftest.py`. +STATELESS_HTTP = True + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +async def test_a_task_handle_survives_with_no_server_side_session( + v4_http_server, capture_queue +): + """Handles are resolved per request from the arguments, so a server that + keeps nothing between requests keeps the task anyway.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v4_http_server + async with Client(StreamableHttpTransport(url)) as client: + first = await client.call_tool( + "add_todo", {"text": "s", "context": "stateless first call"} + ) + minted = _text(first).split("session_id=")[1].split(" ")[0] + await client.call_tool("add_todo", {"text": "s2", "session_id": minted}) + + time.sleep(0.5) + events = _call_events(capture_queue) + assert len(events) == 2 + assert [e.session_id for e in events] == [minted, minted] + + +async def test_concurrent_clients_never_wear_each_others_name( + v4_http_server, capture_queue +): + """Two clients at once, each named, on a server that remembers nothing. + + Each event is matched to the call that produced it by the argument that + call sent, so this asserts ATTRIBUTION rather than "both names appear + somewhere" — the shared-slot bug produced one name on both events, and a + set membership check can be satisfied by the wrong pairing. + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + from mcp.types import Implementation + + url, _ = v4_http_server + + async def call_as(name: str, version: str, text: str) -> None: + async with Client( + StreamableHttpTransport(url), + client_info=Implementation(name=name, version=version), + ) as client: + await client.call_tool("add_todo", {"text": text, "context": "no-bleed"}) + + await asyncio.gather( + call_as("Cursor", "2.6.22", "from-cursor"), + call_as("Claude", "1.0.0", "from-claude"), + ) + time.sleep(0.7) + + events = _call_events(capture_queue) + assert len(events) == 2 + attributed = {e.parameters["arguments"]["text"]: e.client_name for e in events} + assert attributed == {"from-cursor": "Cursor", "from-claude": "Claude"} diff --git a/tests/e2e/official/conftest.py b/tests/e2e/official/conftest.py index 0850cb8..bccbd62 100644 --- a/tests/e2e/official/conftest.py +++ b/tests/e2e/official/conftest.py @@ -5,6 +5,10 @@ FastMCP todo server for the module, calls `agentcat.track(...)` with those options, mounts the server's Streamable-HTTP app, and yields the URL. +`STATELESS_HTTP = True` at module scope serves it from a stateless app +instead — a different code path, where the transport builds a fresh session +per REQUEST and nothing survives between calls. + Module-scoped: one boot per test file, not per test. """ @@ -43,6 +47,9 @@ def official_http_server(request) -> Tuple[str, Any]: ) options = options_factory() server = create_todo_server() + # Before the app is built: v1 FastMCP reads this off its settings when it + # constructs the session manager. + server.settings.stateless_http = getattr(request.module, "STATELESS_HTTP", False) agentcat.track(server, "test_project", options) app = server.streamable_http_app() diff --git a/tests/e2e/official/test_event_capture_http.py b/tests/e2e/official/test_event_capture_http.py index eb5abab..fb45b1f 100644 --- a/tests/e2e/official/test_event_capture_http.py +++ b/tests/e2e/official/test_event_capture_http.py @@ -1,9 +1,8 @@ """Event-capture and round-trip tests over real Streamable HTTP. -NOTE: mcp:initialize events are not captured under any transport because -ServerSession handles initialize internally before user request handlers -fire (see the skipped in-memory test_initialization_event_capture). All -assertions in this file use post-initialize events instead. +v2 publishes exactly one event type — mcp:tools/call. initialize is handled by +ServerSession before any user handler fires, and tools/list is intercepted for +schema injection only, so neither produces an event. """ from __future__ import annotations @@ -20,19 +19,19 @@ @pytest.mark.asyncio -async def test_tools_list_event_captured(official_http_server, capture_queue): - """Real handshake + list_tools produces a mcp:tools/list event.""" +async def test_handshake_and_list_publish_nothing(official_http_server, capture_queue): + """A real handshake plus list_tools produces no events at all.""" url, _server = official_http_server async with streamablehttp_client(url) as (read, write, _): async with ClientSession(read, write) as client: await client.initialize() - await client.list_tools() + listed = await client.list_tools() time.sleep(0.5) - list_events = [e for e in capture_queue if e.event_type == "mcp:tools/list"] - assert list_events, ( - f"expected mcp:tools/list, got {[e.event_type for e in capture_queue]}" - ) + # The listing still went through AgentCat: the handles are on the schemas. + add = next(t for t in listed.tools if t.name == "add_todo") + assert "session_id" in add.inputSchema["properties"] + assert capture_queue == [], [e.event_type for e in capture_queue] @pytest.mark.asyncio diff --git a/tests/e2e/official/test_identify_http.py b/tests/e2e/official/test_identify_http.py index f005663..fd6ee51 100644 --- a/tests/e2e/official/test_identify_http.py +++ b/tests/e2e/official/test_identify_http.py @@ -1,9 +1,11 @@ """Identify-per-event behavior over real Streamable HTTP. +v2 has no standalone agentcat:identify event: the hook runs per tool call and +its result is stamped onto that call's event. + Tests mutate the running server's AgentCatData.options.identify to vary the hook -per scenario. The default options-factory is tracing-only with no identify; -identify-swapping on the live server matches the pattern used by -tests/test_stateless.py. +per scenario. The default options-factory is tracing-only with no identify, so +the hook is swapped on the live server instead of re-tracking it. Each test resets the hook in finally so subsequent tests start clean. """ @@ -65,9 +67,11 @@ def identify(request: Any, extra: Any) -> Optional[UserIdentity]: @pytest.mark.asyncio -async def test_agentcat_identify_self_event_published_per_request( +async def test_actor_rides_the_tool_call_event_not_a_self_event( official_http_server, capture_queue ): + """v2 stamps the actor onto every tools/call event; the standalone + agentcat:identify event is gone.""" url, server = official_http_server def identify(_req: Any, _extra: Any) -> Optional[UserIdentity]: @@ -83,14 +87,8 @@ def identify(_req: Any, _extra: Any) -> Optional[UserIdentity]: ) time.sleep(0.5) - identify_events = [ - e for e in capture_queue if e.event_type == "agentcat:identify" - ] - assert identify_events, ( - f"expected agentcat:identify event, got " - f"{[e.event_type for e in capture_queue]}" - ) - assert identify_events[0].identify_actor_given_id == "bob" + assert {e.event_type for e in capture_queue} == {"mcp:tools/call"} + assert _last_call(capture_queue).identify_actor_given_id == "bob" finally: _set_identify(server, None) @@ -134,7 +132,7 @@ def identify(_req: Any, _extra: Any) -> Optional[UserIdentity]: @pytest.mark.asyncio -async def test_identify_returning_none_yields_no_self_event( +async def test_identify_returning_none_yields_an_anonymous_event( official_http_server, capture_queue ): url, server = official_http_server @@ -152,13 +150,9 @@ def identify(_req: Any, _extra: Any) -> Optional[UserIdentity]: ) time.sleep(0.5) - identify_events = [ - e for e in capture_queue if e.event_type == "agentcat:identify" - ] - assert not identify_events, ( - f"identify returned None; should NOT publish self-event, got " - f"{len(identify_events)}" - ) + event = _last_call(capture_queue) + assert event.identify_actor_given_id is None + assert event.identify_actor_name is None finally: _set_identify(server, None) diff --git a/tests/e2e/official/test_redaction_http.py b/tests/e2e/official/test_redaction_http.py index 30cb60f..a538d5d 100644 --- a/tests/e2e/official/test_redaction_http.py +++ b/tests/e2e/official/test_redaction_http.py @@ -1,15 +1,13 @@ """Redaction over real-wire payloads. -KNOWN BUG (xfail-tracked): `agentcat.modules.redaction.redact_event` only -recurses into `dict` and `list` types, not Pydantic `UnredactedEvent` objects. -The event_queue worker invokes `redact_event(event, ...)` where `event` is an -`UnredactedEvent`; the call returns the input unchanged, so customer-supplied -redact functions never actually run on the live event-publish path. - -Tests below are marked xfail so they: -1. Codify the intended behavior. -2. Serve as a regression target — when the bug is fixed, they should be - un-xfailed (the strict=False xfail still passes if the test starts working). +These were xfail-tracked for the whole of the v2 branch: +`agentcat.modules.redaction.redact_event` walked `str` / `list` / `dict` and +returned anything else untouched, and the publish path hands it a pydantic +`UnredactedEvent` — so the documented `redact_sensitive_information` hook was +a no-op on every real event while the README advertised it as a security +control. `redact_event` now dumps the model, redacts, and copies back, so the +markers are gone and these tests are the live guard: a regression here fails +the suite instead of quietly passing as an xpass. """ from __future__ import annotations @@ -32,11 +30,6 @@ def _set_redact(server, fn) -> None: data.options.redact_sensitive_information = fn -@pytest.mark.xfail( - reason="redact_event does not recurse into Pydantic UnredactedEvent; " - "redaction never fires on real events. Track as separate fix.", - strict=False, -) @pytest.mark.asyncio async def test_redact_function_runs_on_real_event_payload( official_http_server, capture_queue @@ -67,11 +60,6 @@ def redact(s: str) -> str: _set_redact(server, None) -@pytest.mark.xfail( - reason="redact_event does not recurse into Pydantic UnredactedEvent; " - "redaction never fires on real events. Track as separate fix.", - strict=False, -) @pytest.mark.asyncio async def test_redaction_can_scrub_authorization_header_in_extra( official_http_server, capture_queue @@ -111,12 +99,6 @@ def redact(s: str) -> str: _set_redact(server, None) -@pytest.mark.xfail( - reason="redact_event does not invoke the user's redact fn on Pydantic " - "events, so redact-fn-raise never fires; the 'drop event on raise' path " - "is unreachable until the redact_event recursion bug is fixed.", - strict=False, -) @pytest.mark.asyncio async def test_redaction_failure_drops_event(official_http_server, capture_queue): url, server = official_http_server diff --git a/tests/e2e/official/test_request_extra_http.py b/tests/e2e/official/test_request_extra_http.py index 1245843..91a5779 100644 --- a/tests/e2e/official/test_request_extra_http.py +++ b/tests/e2e/official/test_request_extra_http.py @@ -131,10 +131,11 @@ async def test_meta_dict_present_when_supported(official_http_server, capture_qu @pytest.mark.asyncio -async def test_list_tools_event_carries_extra(official_http_server, capture_queue): - """tools/list events also receive parameters.extra under HTTP transport - (initialize events don't reach our handlers; tools/list is the next-best - early-handshake event to verify extra propagation on).""" +async def test_extra_survives_a_listing_in_the_same_session( + official_http_server, capture_queue +): + """tools/list publishes no event in v2, so `extra` rides the tools/call + that follows it — with the headers of THAT request, not the listing's.""" url, _ = official_http_server async with streamablehttp_client( url, headers={"X-List-Header": "list-value"} @@ -142,14 +143,11 @@ async def test_list_tools_event_carries_extra(official_http_server, capture_queu async with ClientSession(read, write) as client: await client.initialize() await client.list_tools() + await client.call_tool("add_todo", {"text": "l", "context": "listing"}) time.sleep(0.5) - list_events = [e for e in capture_queue if e.event_type == "mcp:tools/list"] - assert list_events - headers = ( - (list_events[0].parameters or {}) - .get("extra", {}) - .get("requestInfo", {}) - .get("headers", {}) + assert {e.event_type for e in capture_queue} == {"mcp:tools/call"} + headers = _extra(_last_call_event(capture_queue)).get("requestInfo", {}).get( + "headers", {} ) assert headers.get("x-list-header") == "list-value" diff --git a/tests/e2e/official/test_session_http.py b/tests/e2e/official/test_session_http.py index 3e46252..9f7f773 100644 --- a/tests/e2e/official/test_session_http.py +++ b/tests/e2e/official/test_session_http.py @@ -1,15 +1,10 @@ -"""Client-info propagation tests over real Streamable HTTP. - -NOTE: User-Agent / X-MCP-Client-Name header parsing is *not* tested e2e -because real MCP clients always populate session.client_params.clientInfo -during initialize, and that path wins over header parsing in the SDK -(see src/agentcat/modules/session.py::get_client_info_from_request_context). -The header-fallback path is covered by unit tests in tests/test_stateless.py -that mock ctx.session = None to force the fallback. e2e here verifies the -real-world path: clientInfo from the SDK propagates to events. - -Uses stateless mode so each test gets independent client_info extraction -rather than fixture-level caching. +"""Task-handle and client-info propagation over real Streamable HTTP. + +Two things ride every tools/call event and both are resolved per request: +the task handle (minted on the first call, echoed back by the agent on later +ones) and the client identity. The identity ladder reads the per-request +`_meta` keys first and falls back to the handshake clientInfo the SDK's own +ServerSession captured — no header parsing, no caching of our own. """ from __future__ import annotations @@ -21,13 +16,6 @@ from mcp.client.streamable_http import streamablehttp_client from mcp.types import Implementation -from agentcat import AgentCatOptions - - -def AGENTCAT_OPTIONS_FACTORY() -> AgentCatOptions: - return AgentCatOptions(enable_tracing=True, stateless=True) - - pytestmark = pytest.mark.e2e @@ -137,3 +125,71 @@ async def test_clientinfo_in_extra_headers_when_set( ) assert headers.get("x-mcp-client-name") == "HeaderClient" assert headers.get("x-mcp-client-version") == "8.8.8" + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +@pytest.mark.asyncio +async def test_minted_session_id_is_echoed_across_http_calls( + official_http_server, capture_queue +): + """First call mints and hands the handle back; the agent echoes it on the + next call and both events land on the same task.""" + url, _ = official_http_server + async with streamablehttp_client(url) as (read, write, _): + async with ClientSession(read, write) as client: + await client.initialize() + first = await client.call_tool( + "add_todo", {"text": "one", "context": "first call of the task"} + ) + text = _text(first) + assert "[MCP INSTRUCTIONS]: session_id issued." in text + minted = text.split("session_id=")[1].split(" ")[0] + assert minted.startswith("ses_") + + second = await client.call_tool( + "add_todo", {"text": "two", "session_id": minted} + ) + # Already supplied: nothing is minted back a second time. + assert "[MCP INSTRUCTIONS]: session_id issued." not in _text(second) + + time.sleep(0.5) + events = _call_events(capture_queue) + assert len(events) == 2 + assert [e.session_id for e in events] == [minted, minted] + assert [e.tags["agentcat_session_id_source"] for e in events] == [ + "minted", + "supplied", + ] + + +@pytest.mark.asyncio +async def test_separate_connections_get_separate_tasks( + official_http_server, capture_queue +): + """Nothing is stored server-side, so two agents that never echo a handle + get two different tasks.""" + url, _ = official_http_server + + async def call_once(text: str) -> str: + async with streamablehttp_client(url) as (read, write, _): + async with ClientSession(read, write) as client: + await client.initialize() + result = await client.call_tool( + "add_todo", {"text": text, "context": "independent task"} + ) + return _text(result).split("session_id=")[1].split(" ")[0] + + first = await call_once("a") + second = await call_once("b") + assert first != second + + time.sleep(0.5) + minted = {e.session_id for e in _call_events(capture_queue)} + assert {first, second} <= minted diff --git a/tests/e2e/official/test_stateless_http.py b/tests/e2e/official/test_stateless_http.py index d79f0cc..8818730 100644 --- a/tests/e2e/official/test_stateless_http.py +++ b/tests/e2e/official/test_stateless_http.py @@ -1,4 +1,16 @@ -"""Stateless mode behavior over real Streamable HTTP.""" +"""Per-request resolution over a real STATELESS Streamable-HTTP server. + +The `stateless` option is gone in 2.0 — resolution is per request either way — +so these guard what the option used to protect: a task handle that survives +without any server-side session, and client identity that never leaks from one +connection to another. + +The transport is the point, and it is where the sibling e2e modules cannot +reach: `stateless_http=True` builds a fresh session per REQUEST, so nothing a +server might have kept between calls exists, and every identity lookup falls +through to whatever rung can still answer. A shared "last seen" slot anywhere +in that ladder fires here on every call rather than never. +""" from __future__ import annotations @@ -10,43 +22,47 @@ from mcp.client.streamable_http import streamablehttp_client from mcp.types import Implementation -from agentcat import AgentCatOptions - - -def AGENTCAT_OPTIONS_FACTORY() -> AgentCatOptions: - return AgentCatOptions(enable_tracing=True, stateless=True) - - pytestmark = pytest.mark.e2e +# Read by this tree's conftest: the app really is served statelessly, so the +# transport builds a fresh session per REQUEST and nothing survives a call. +STATELESS_HTTP = True + @pytest.mark.asyncio -async def test_stateless_mode_returns_null_session_id( - official_http_server, capture_queue -): - """In stateless mode, captured events have session_id=None.""" +async def test_every_call_carries_a_task_handle(official_http_server, capture_queue): + """Handles are resolved per request from the arguments, so nothing is held + server-side: session_id carries the task, minted or echoed.""" url, _ = official_http_server async with streamablehttp_client(url) as (read, write, _): async with ClientSession(read, write) as client: await client.initialize() - await client.call_tool( + result = await client.call_tool( "add_todo", {"text": "s", "context": "stateless"} ) + text = "".join(c.text for c in result.content if hasattr(c, "text")) + minted = text.split("session_id=")[1].split(" ")[0] + + await client.call_tool("add_todo", {"text": "s2", "session_id": minted}) time.sleep(0.5) call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] - assert call_events - # In stateless mode, the SDK-level event session_id field is None. - assert call_events[0].session_id is None + assert len(call_events) == 2 + assert [e.session_id for e in call_events] == [minted, minted] @pytest.mark.asyncio -async def test_stateless_two_clients_different_clientinfo_dont_bleed( +async def test_two_clients_different_clientinfo_dont_bleed( official_http_server, capture_queue ): - """Concurrent stateless requests with different clientInfo must produce - events whose client_name reflects the *requesting* connection, not a - cached value from a different connection.""" + """Concurrent requests with different clientInfo must produce events whose + client_name reflects the *requesting* connection, not a cached value from a + different one. There is no identity cache left to bleed from. + + Each event is matched to the call that produced it by the argument that + call sent, so this asserts ATTRIBUTION: a shared slot puts one name on both + events, and a set-membership check can be satisfied by the wrong pairing. + """ url, _ = official_http_server async def call_with_client(name: str, version: str, text: str) -> None: @@ -62,52 +78,15 @@ async def call_with_client(name: str, version: str, text: str) -> None: ) await asyncio.gather( - call_with_client("Cursor", "2.6.22", "a"), - call_with_client("Claude", "1.0.0", "b"), + call_with_client("Cursor", "2.6.22", "from-cursor"), + call_with_client("Claude", "1.0.0", "from-claude"), ) time.sleep(0.7) call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] - client_names = {ev.client_name for ev in call_events} - assert "Cursor" in client_names and "Claude" in client_names, ( - f"stateless mode bled client_info across requests: {client_names}" - ) - - -@pytest.mark.asyncio -async def test_stateless_no_session_info_pollution( - official_http_server, capture_queue -): - """After multiple stateless requests, the server's data.session_info - fields should remain unset, proving we're not caching.""" - url, server = official_http_server - - async with streamablehttp_client(url) as (read, write, _): - async with ClientSession( - read, - write, - client_info=Implementation(name="First", version="1.0"), - ) as client: - await client.initialize() - await client.call_tool("add_todo", {"text": "1", "context": "x"}) - - async with streamablehttp_client(url) as (read, write, _): - async with ClientSession( - read, - write, - client_info=Implementation(name="Second", version="2.0"), - ) as client: - await client.initialize() - await client.call_tool("add_todo", {"text": "2", "context": "x"}) - - time.sleep(0.5) - - from agentcat.modules.internal import get_server_tracking_data - - data = get_server_tracking_data(server) - assert data is not None - # In stateless mode, we never cache client_info onto data.session_info. - assert data.session_info.client_name is None, ( - f"stateless mode polluted session_info.client_name = " - f"{data.session_info.client_name}" - ) + assert len(call_events) == 2 + attributed = {e.parameters["arguments"]["text"]: e.client_name for e in call_events} + # No name at all is the honest answer for a connection that is already + # gone; SOMEONE ELSE's name never is. + assert attributed["from-cursor"] in (None, "Cursor"), attributed + assert attributed["from-claude"] in (None, "Claude"), attributed diff --git a/tests/e2e/community_v2/__init__.py b/tests/e2e/official_modern/__init__.py similarity index 100% rename from tests/e2e/community_v2/__init__.py rename to tests/e2e/official_modern/__init__.py diff --git a/tests/e2e/official_modern/conftest.py b/tests/e2e/official_modern/conftest.py new file mode 100644 index 0000000..dc7784e --- /dev/null +++ b/tests/e2e/official_modern/conftest.py @@ -0,0 +1,70 @@ +"""Uvicorn-in-thread harness for the modern official MCP SDK (mcp 2.x). + +The legacy sibling (`tests/e2e/official/conftest.py`) boots a FastMCP v1 todo +server; this one boots either 2.x flavor over the same real Streamable-HTTP +transport, so the assertions cover the wire path a customer actually deploys — +headers, session ids, the per-request `_meta` envelope — none of which the +in-process client exercises. + +A test module declares `AGENTCAT_OPTIONS_FACTORY` (callable returning +`AgentCatOptions`) and `SERVER_FACTORY` (callable returning the server to +track) at module scope, and `STATELESS_HTTP = True` to be served by a stateless +app — a different code path, where the transport builds a fresh session per +REQUEST and nothing survives between calls. Module-scoped: one boot per test +file, not per test. +""" + +from __future__ import annotations + +import threading +from collections.abc import Callable +from typing import Any + +import pytest +import uvicorn + +import agentcat +from agentcat import AgentCatOptions +from tests.e2e._helpers import find_free_port, wait_for_port +from tests.test_utils.modern_server import create_lowlevel_todo_server + + +def _default_options_factory() -> AgentCatOptions: + return AgentCatOptions(enable_tracing=True) + + +@pytest.fixture(scope="module") +def modern_http_server(request) -> tuple[str, Any]: + """Boot a Streamable-HTTP MCP server for the test module. + + Yields: + (url, server) — the Streamable-HTTP URL and the tracked server. + """ + options_factory: Callable[[], AgentCatOptions] = getattr( + request.module, "AGENTCAT_OPTIONS_FACTORY", _default_options_factory + ) + server_factory: Callable[[], Any] = getattr( + request.module, "SERVER_FACTORY", create_lowlevel_todo_server + ) + server = server_factory() + agentcat.track(server, "test_project", options_factory()) + + app = server.streamable_http_app( + stateless_http=getattr(request.module, "STATELESS_HTTP", False) + ) + port = find_free_port() + config = uvicorn.Config(app, host="127.0.0.1", port=port, log_level="error") + uv_server = uvicorn.Server(config) + thread = threading.Thread(target=uv_server.run, daemon=True) + thread.start() + try: + wait_for_port(port, timeout=5.0) + except TimeoutError: + uv_server.should_exit = True + thread.join(timeout=2.0) + raise + + yield f"http://127.0.0.1:{port}/mcp", server + + uv_server.should_exit = True + thread.join(timeout=5.0) diff --git a/tests/e2e/official_modern/test_mcpserver_http.py b/tests/e2e/official_modern/test_mcpserver_http.py new file mode 100644 index 0000000..c4278d9 --- /dev/null +++ b/tests/e2e/official_modern/test_mcpserver_http.py @@ -0,0 +1,101 @@ +"""`MCPServer` over real Streamable HTTP. + +`MCPServer` is tracked through its `_lowlevel_server`, so this is the same +adapter the bare-`Server` file exercises — what is new here is the whole +higher-level stack on top of it: the tool manager's generated schemas, its +argument delivery, and its structured-output conversion. + +That manager does NOT reject a parameter AgentCat failed to strip — measured on +mcp 2.0, it drops an undeclared argument silently — so the strip is asserted +against what the manager was handed (`tests.test_utils.delivery`), not against +the call merely succeeding. +""" + +from __future__ import annotations + +import time + +import pytest +from mcp.client import Client + +from agentcat.modules.constants import ( + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, +) +from tests.test_utils.delivery import delivered_arguments_for +from tests.test_utils.modern_server import create_mcpserver_todo_server + +from ...test_utils import sid + +pytestmark = pytest.mark.e2e + +SERVER_FACTORY = create_mcpserver_todo_server + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +@pytest.mark.asyncio +async def test_mcpserver_injects_strips_and_publishes( + modern_http_server, capture_queue +): + url, server = modern_http_server + async with Client(url) as client: + listed = await client.list_tools() + add = next(t for t in listed.tools if t.name == "add_todo") + assert list(add.input_schema["properties"])[-2:] == ["session_id", "context"] + assert MCP_INSTRUCTIONS_KEY in add.output_schema["properties"] + + result = await client.call_tool( + "add_todo", {"text": "over http", "context": "why"} + ) + assert result.is_error is False, _text(result) + text = _text(result) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + assert result.structured_content[MCP_INSTRUCTIONS_KEY]["session_id"] == minted + assert result.structured_content["result"].startswith("Added todo") + + # The tool layer never saw `context` — the only observation on this shape + # that a broken strip would fail. The server runs in-process (uvicorn in a + # thread), so its recorder is readable straight off the fixture's object. + assert delivered_arguments_for(server, "add_todo") == [{"text": "over http"}] + + time.sleep(0.5) + events = _call_events(capture_queue) + assert [e.resource_name for e in events] == ["add_todo"] + assert events[0].session_id == minted + assert events[0].tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + # The event carries the RAW arguments and the UNDECORATED response. + assert events[0].parameters["arguments"] == {"text": "over http", "context": "why"} + assert MCP_INSTRUCTIONS_KEY not in (events[0].response or {}).get( + "structuredContent", {} + ) + assert MCP_INSTRUCTIONS_KEY not in (events[0].response or {}).get( + "structured_content", {} + ) + + +@pytest.mark.asyncio +async def test_mcpserver_echoed_handle_is_not_minted_again( + modern_http_server, capture_queue +): + url, _ = modern_http_server + async with Client(url) as client: + result = await client.call_tool( + "list_todos", {"session_id": sid("supplied_over_http")} + ) + assert result.is_error is False, _text(result) + assert MINT_BACK_HEADER not in _text(result) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert event.session_id == sid("supplied_over_http") + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "supplied" diff --git a/tests/e2e/official_modern/test_session_http.py b/tests/e2e/official_modern/test_session_http.py new file mode 100644 index 0000000..c09621f --- /dev/null +++ b/tests/e2e/official_modern/test_session_http.py @@ -0,0 +1,162 @@ +"""Task handles, client identity and per-request extra over real Streamable HTTP. + +The in-process tests cover the adapter's logic; this file covers what only a +socket can: the HTTP request object the transport hands the handler +(`ctx.request`), the headers riding on it, and the transport's own session id. +""" + +from __future__ import annotations + +import time + +import httpx2 +import pytest +from mcp.client import Client +from mcp.client.streamable_http import streamable_http_client +from mcp.types import Implementation + +from agentcat.modules.constants import ( + AGENTCAT_TAG_PROTOCOL_VERSION, + AGENTCAT_TAG_SESSION_SOURCE, +) + +pytestmark = pytest.mark.e2e + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +@pytest.mark.asyncio +async def test_minted_session_id_is_echoed_across_http_calls( + modern_http_server, capture_queue +): + """First call mints and hands the handle back; the agent echoes it on the + next call and both events land on the same task.""" + url, _ = modern_http_server + async with Client(url) as client: + first = await client.call_tool( + "add_todo", {"text": "one", "context": "first call of the task"} + ) + text = _text(first) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + assert minted.startswith("ses_") + + second = await client.call_tool( + "add_todo", {"text": "two", "session_id": minted} + ) + # Already supplied: nothing is minted back a second time. + assert MINT_BACK_HEADER not in _text(second) + + time.sleep(0.5) + events = _call_events(capture_queue) + assert len(events) == 2 + assert [e.session_id for e in events] == [minted, minted] + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == [ + "minted", + "supplied", + ] + assert all(e.tags[AGENTCAT_TAG_PROTOCOL_VERSION] for e in events) + + +@pytest.mark.asyncio +async def test_separate_connections_get_separate_tasks( + modern_http_server, capture_queue +): + """Nothing is stored server-side, so two agents that never echo a handle + get two different tasks.""" + url, _ = modern_http_server + + async def call_once(text: str) -> str: + async with Client(url) as client: + result = await client.call_tool( + "add_todo", {"text": text, "context": "independent task"} + ) + return _text(result).split("session_id=")[1].split(" ")[0] + + first = await call_once("a") + second = await call_once("b") + assert first != second + + time.sleep(0.5) + minted = {e.session_id for e in _call_events(capture_queue)} + assert {first, second} <= minted + + +@pytest.mark.asyncio +async def test_custom_clientinfo_propagates_to_event( + modern_http_server, capture_queue +): + """`client_info` reaches the event as client_name / client_version, whether + it rides the handshake or the per-request `_meta` envelope.""" + url, _ = modern_http_server + async with Client( + url, client_info=Implementation(name="MyAgent", version="1.2.3") + ) as client: + await client.call_tool("add_todo", {"text": "agent", "context": "id"}) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert (event.client_name, event.client_version) == ("MyAgent", "1.2.3") + + +@pytest.mark.asyncio +async def test_request_headers_ride_the_event(modern_http_server, capture_queue): + """`parameters.extra.requestInfo.headers` is only reachable from the HTTP + request the transport attaches to the context — the in-process client has + none, so this is the only place it can be asserted.""" + url, _ = modern_http_server + http_client = httpx2.AsyncClient( + headers={"X-MCP-Client-Name": "HeaderClient", "X-Tenant": "acme"} + ) + async with Client(streamable_http_client(url, http_client=http_client)) as client: + await client.call_tool("add_todo", {"text": "hdr", "context": "hdr"}) + + time.sleep(0.5) + extra = (_call_events(capture_queue)[-1].parameters or {}).get("extra", {}) + headers = extra.get("requestInfo", {}).get("headers", {}) + assert headers.get("x-mcp-client-name") == "HeaderClient" + assert headers.get("x-tenant") == "acme" + + +@pytest.mark.asyncio +async def test_session_id_is_reported_only_when_the_transport_issues_one( + modern_http_server, capture_queue +): + """The 2026-07-28 wire dropped the handshake, so a connection on it has no + session at all and the event must not invent one. The handshake era still + issues `Mcp-Session-Id`, and there it is reported verbatim.""" + url, _ = modern_http_server + + async with Client(url) as client: + await client.call_tool("add_todo", {"text": "modern", "context": "x"}) + time.sleep(0.5) + modern = (_call_events(capture_queue)[-1].parameters or {}).get("extra", {}) + assert "sessionId" not in modern + + async with Client(url, mode="legacy") as client: + await client.call_tool("add_todo", {"text": "legacy", "context": "x"}) + time.sleep(0.5) + legacy = (_call_events(capture_queue)[-1].parameters or {}).get("extra", {}) + assert isinstance(legacy.get("sessionId"), str) and legacy["sessionId"] + + +@pytest.mark.asyncio +async def test_injected_schema_survives_the_wire(modern_http_server, capture_queue): + """The SDK validates every outbound spec result against the negotiated + protocol surface, so a malformed injected schema fails server-side rather + than reaching the agent. Listing over HTTP proves ours is valid.""" + url, _ = modern_http_server + async with Client(url) as client: + listed = await client.list_tools() + + add = next(t for t in listed.tools if t.name == "add_todo") + assert list(add.input_schema["properties"])[-2:] == ["session_id", "context"] + assert "_mcp_instructions" in add.output_schema["properties"] diff --git a/tests/e2e/official_modern/test_stateless_http.py b/tests/e2e/official_modern/test_stateless_http.py new file mode 100644 index 0000000..0d4afde --- /dev/null +++ b/tests/e2e/official_modern/test_stateless_http.py @@ -0,0 +1,82 @@ +"""A genuinely stateless HTTP server, on the modern official SDK. + +Every other e2e module in this tree boots a stateful app, where one session +serves a whole connection. `stateless_http=True` builds a fresh one per +REQUEST, so nothing the server might have kept between calls is there — which +is the whole premise v2 is built on: handles are resolved per request from the +call's own arguments, and client identity is resolved per request from the +call's own envelope. +""" + +from __future__ import annotations + +import asyncio +import time + +import pytest +from mcp.client import Client +from mcp.types import Implementation + +pytestmark = pytest.mark.e2e + +# Read by `tests/e2e/official_modern/conftest.py`. +STATELESS_HTTP = True + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +async def test_a_task_handle_survives_with_no_server_side_session( + modern_http_server, capture_queue +): + """Nothing is held server-side, and the task is carried anyway.""" + url, _ = modern_http_server + async with Client(url) as client: + first = await client.call_tool( + "add_todo", {"text": "s", "context": "stateless first call"} + ) + minted = _text(first).split("session_id=")[1].split(" ")[0] + await client.call_tool("add_todo", {"text": "s2", "session_id": minted}) + + time.sleep(0.5) + events = _call_events(capture_queue) + assert len(events) == 2 + assert [e.session_id for e in events] == [minted, minted] + + +async def test_concurrent_clients_never_wear_each_others_name( + modern_http_server, capture_queue +): + """Two named clients at once, on a server that remembers nothing. + + Each event is matched to the call that produced it by the argument that + call sent, so this asserts ATTRIBUTION rather than "both names appear + somewhere" — a shared identity slot produces one name on both events, and + a set membership check can be satisfied by the wrong pairing. + """ + url, _ = modern_http_server + + async def call_as(name: str, version: str, text: str) -> None: + async with Client( + url, client_info=Implementation(name=name, version=version) + ) as client: + await client.call_tool("add_todo", {"text": text, "context": "no-bleed"}) + + await asyncio.gather( + call_as("Cursor", "2.6.22", "from-cursor"), + call_as("Claude", "1.0.0", "from-claude"), + ) + time.sleep(0.7) + + events = _call_events(capture_queue) + assert len(events) == 2 + attributed = {e.parameters["arguments"]["text"]: e.client_name for e in events} + # No name at all is the honest answer for a connection that is gone; + # SOMEONE ELSE's name never is. + assert attributed["from-cursor"] in (None, "Cursor"), attributed + assert attributed["from-claude"] in (None, "Claude"), attributed diff --git a/tests/test_api_base_url.py b/tests/test_api_base_url.py index 3135b08..4f57a09 100644 --- a/tests/test_api_base_url.py +++ b/tests/test_api_base_url.py @@ -3,8 +3,12 @@ import os from unittest.mock import MagicMock, patch +import pytest + from agentcat.types import AgentCatOptions +from .conftest import MCP_MAJOR + class TestAgentCatOptionsApiBaseUrl: """Test api_base_url field on AgentCatOptions.""" @@ -60,67 +64,35 @@ def test_default_url_used_when_not_configured( mock_configuration.assert_called_with(host=AGENTCAT_API_URL) +@pytest.mark.skipif( + MCP_MAJOR >= 2, + reason="needs a server flavor track() can adapt; mcp 2.x lands in Task 12", +) class TestTrackApiBaseUrl: """Test that track() wires api_base_url resolution correctly.""" - # Common patches needed to isolate track() from real MCP server logic - TRACK_PATCHES = [ - "agentcat.is_community_fastmcp_v3", - "agentcat.is_community_fastmcp_v2", - "agentcat.is_official_fastmcp_server", - "agentcat.is_compatible_server", - "agentcat._apply_server_tracking", - "agentcat.get_session_info", - "agentcat.set_server_tracking_data", - ] - def _call_track_with_patches(self, options, env_vars=None): - """Helper to call track() with all internals mocked, returning a mock event_queue.""" + """Run the real track() against a real server, with only the queue mocked. + + A bare lowlevel `Server` has no tools/list or tools/call handler yet, so + the adapter installs nothing — but detection, data storage and the + api-base-url resolution all run exactly as they do in production. + """ + from mcp.server.lowlevel import Server + from agentcat import track mock_eq = MagicMock() - patches = {} - for p in self.TRACK_PATCHES: - patches[p] = patch(p) - - eq_patch = patch("agentcat.modules.event_queue.event_queue", mock_eq) - - started = [] - try: - for name, p in patches.items(): - m = p.start() - started.append(p) - if name == "agentcat.is_compatible_server": - m.return_value = True - elif name in ( - "agentcat.is_community_fastmcp_v3", - "agentcat.is_community_fastmcp_v2", - "agentcat.is_official_fastmcp_server", - ): - m.return_value = False - elif name == "agentcat.get_session_info": - from agentcat.types import SessionInfo - m.return_value = SessionInfo() - - eq_patch.start() - started.append(eq_patch) - - server = MagicMock() - if env_vars is not None: - with patch.dict(os.environ, env_vars, clear=True): - track(server, project_id="proj-123", options=options) - else: + with patch("agentcat.modules.event_queue.event_queue", mock_eq): + server = Server("api-base-url-test") + if env_vars is None: # Clear API URL env vars to avoid interference - env = os.environ.copy() - env.pop("AGENTCAT_API_URL", None) - env.pop("MCPCAT_API_URL", None) - with patch.dict(os.environ, env, clear=True): - track(server, project_id="proj-123", options=options) - - return mock_eq - finally: - for p in started: - p.stop() + env_vars = os.environ.copy() + env_vars.pop("AGENTCAT_API_URL", None) + env_vars.pop("MCPCAT_API_URL", None) + with patch.dict(os.environ, env_vars, clear=True): + track(server, project_id="proj-123", options=options) + return mock_eq def test_option_overrides_default(self): """api_base_url option should trigger configure() on event_queue.""" diff --git a/tests/test_callpath.py b/tests/test_callpath.py new file mode 100644 index 0000000..1179d55 --- /dev/null +++ b/tests/test_callpath.py @@ -0,0 +1,694 @@ +"""Shared per-call orchestration: resolve / strip / decorate / publish. + +`callpath` is the one code path every adapter (lowlevel v1, lowlevel v2, +community FastMCP) runs for `tools/call`, so it is exercised here with pure +Python fakes and no MCP imports at all — the module must import and behave +identically under mcp 1.x and mcp 2.x. + +Behavior contract: 2026-07-28-cross-sdk-changelog.md §3.4, §6.2-§6.5; TS +reference src/engine/callWrap.ts. +""" + +import asyncio +from datetime import datetime, timedelta, timezone +from typing import Any + +from agentcat.modules import event_queue +from agentcat.modules.callpath import ( + ResolvedCall, + decorate_content, + detect_mrtr, + get_stripped_arguments, + publish_tool_call_event, + resolve_call, + structured_mirror, +) +from agentcat.modules.client_identity import ClientIdentity +from agentcat.modules.handles import HandleResolution +from agentcat.modules.injection import ToolSpec +from agentcat.types import ( + AgentCatData, + AgentCatOptions, + UnredactedEvent, + UserIdentity, +) + +from .test_utils import sid + +CLIENT_KEY = "io.modelcontextprotocol/clientInfo" +PV_KEY = "io.modelcontextprotocol/protocolVersion" + + +def make_data(options: AgentCatOptions | None = None, **kwargs: Any) -> AgentCatData: + """Tracking data in its v2 shape: a project, options, and engine state.""" + return AgentCatData( + project_id="proj_1", + options=options if options is not None else AgentCatOptions(), + **kwargs, + ) + + +def text_block(text: str) -> dict[str, str]: + return {"type": "text", "text": text} + + +# ── detect_mrtr ────────────────────────────────────────────────────────────── + + +def test_detect_mrtr_matrix(): + assert detect_mrtr("input_required", False) == "input_required" + assert detect_mrtr("input_required", True) == "input_required" # intermediate wins + assert detect_mrtr(None, True) == "continuation" + assert detect_mrtr("complete", False) is None + + +# An ordinary completing round carries neither signal; a continuation that +# completes is tagged `continuation`, not dropped (§6.4). +def test_detect_mrtr_plain_and_completing_continuation(): + assert detect_mrtr(None, False) is None + assert detect_mrtr("complete", True) == "continuation" + assert detect_mrtr("", False) is None + + +def test_detect_mrtr_tags_the_request_state_only_continuation(): + """A resumed round carries `requestState` and no responses at all. + + The SEP-2322 driver answers an intermediate round that asked no questions + by retrying after a backoff with `inputResponses=None` and the echoed + `requestState` — the shape FastMCP 4's own + `InputRequiredResult(request_state=...)` produces. Keying the tag on + `inputResponses` alone left it untagged. + """ + assert detect_mrtr(None, False, True) == "continuation" + assert detect_mrtr("complete", False, True) == "continuation" + # Intermediate still wins over either witness. + assert detect_mrtr("input_required", False, True) == "input_required" + # And the default keeps every existing two-argument call site honest. + assert detect_mrtr(None, True) == "continuation" + assert detect_mrtr(None, False) is None + + +# ── decorate_content ───────────────────────────────────────────────────────── + + +def test_decorate_content_only_when_minted_prompted(): + minted = HandleResolution(sid("T"), "minted") + out = decorate_content([{"type": "text", "text": "x"}], minted, text_block) + assert out is not None + assert "[MCP INSTRUCTIONS]: session_id issued." in out[-1]["text"] + assert decorate_content([{"t": 1}], HandleResolution(sid("T"), "supplied"), dict) is None # noqa: E501 + assert decorate_content([{"t": 1}], HandleResolution(sid("T"), "minted", hook_mode=True), dict) is None # noqa: E501 + assert decorate_content("not-a-list", minted, dict) is None + + +# §3.4a: the appended text carries the id the agent must echo, built by the one +# source of truth (handles.build_mint_back_text) rather than re-derived here. +def test_decorate_content_appends_the_minted_id(): + out = decorate_content([], HandleResolution(sid("ABC"), "minted"), text_block) + assert out is not None and len(out) == 1 + assert "session_id=ses_ABC" in out[0]["text"] + assert out[0]["text"].endswith( + "Without session_id, this server does not function as intended." + ) + + +# §3.4a: "Append it to error results too" — decorate_content never inspects +# error state, so an isError result decorates on exactly the same terms. +def test_decorate_content_ignores_error_state(): + error_content = [{"type": "text", "text": "boom: tool failed"}] + out = decorate_content(error_content, HandleResolution(sid("T"), "minted"), text_block) # noqa: E501 + assert out is not None and len(out) == 2 + assert "[MCP INSTRUCTIONS]" in out[-1]["text"] + + +# Never mutate the customer's result: the returned list is new and the +# original is untouched. +def test_decorate_content_returns_a_new_list(): + original = [{"type": "text", "text": "x"}] + out = decorate_content(original, HandleResolution(sid("T"), "minted"), text_block) + assert out is not original + assert original == [{"type": "text", "text": "x"}] + + +def test_decorate_content_none_content(): + assert decorate_content(None, HandleResolution(sid("T"), "minted"), dict) is None + + +# ── structured_mirror ──────────────────────────────────────────────────────── + + +def test_structured_mirror_gate_matrix(): + res = HandleResolution(sid("T"), "minted") + # In the output-injection registry: the tool's outputSchema declares the key. + mirrored = structured_mirror({"ok": True}, res, "search", {"search"}) + assert mirrored is not None + assert mirrored["ok"] is True + assert mirrored["_mcp_instructions"]["session_id"] == sid("T") + # Registry exists but this tool is not in it: mirroring would fail the + # customer's own schema validation. + assert structured_mirror({"ok": True}, res, "other", {"search"}) is None + # No registry at all (rebuild failed) — mirror anyway (§3.4b). + assert structured_mirror({"ok": True}, res, "other", None) is not None + # Empty registry is a real registry, not a missing one. + assert structured_mirror({"ok": True}, res, "search", set()) is None + + +def test_structured_mirror_delegates_shape_rules(): + res = HandleResolution(sid("T"), "minted") + # Non-dict structuredContent (or none at all) is never mirrored into. + assert structured_mirror(None, res, "search", None) is None + assert structured_mirror(["a"], res, "search", None) is None + assert structured_mirror("str", res, "search", None) is None + # Customer data under the key wins. + assert structured_mirror({"_mcp_instructions": "mine"}, res, "search", None) is None + + +def test_structured_mirror_hook_mode_without_agent_has_nothing_to_mirror(): + hook = HandleResolution(sid("T"), "hook", hook_mode=True) + assert structured_mirror({"ok": True}, hook, "search", None) is None + + with_agent = HandleResolution( + sid("T"), "hook", "agt|x|1", "supplied", hook_mode=True + ) + mirrored = structured_mirror({"ok": True}, with_agent, "search", None) + assert mirrored is not None + assert "session_id" not in mirrored["_mcp_instructions"] + assert mirrored["_mcp_instructions"]["agent_id"] == "agt|x|1" + + +# ── get_stripped_arguments ─────────────────────────────────────────────────── + + +async def test_strip_uses_the_existing_registry(): + data = make_data() + data.injected_params_registry = { + "search": {"session_id", "context"}, + "other": set(), + } + raw = {"q": 1, "session_id": sid("T"), "agent_id": "a", "context": "why"} + + assert await get_stripped_arguments(data, data.options, "search", raw, None) == { + "q": 1, + "agent_id": "a", + } + # Listed with an empty entry: nothing was injected, so nothing is stripped. + assert await get_stripped_arguments(data, data.options, "other", raw, None) == raw + # Unlisted tool: never advertised through the pipeline, strip nothing. + assert await get_stripped_arguments(data, data.options, "ghost", raw, None) == raw + # Never mutate the caller's dict. + assert raw == {"q": 1, "session_id": sid("T"), "agent_id": "a", "context": "why"} + + +async def test_strip_rebuilds_registries_on_demand(): + data = make_data(AgentCatOptions(enable_agent_tracking=True)) + specs = [ + ToolSpec("search", {"type": "object", "properties": {"q": {"type": "string"}}}), + ToolSpec("other", {"type": "object", "properties": {}}, {"type": "object"}), + ] + calls: list[int] = [] + + async def rebuild() -> list[ToolSpec]: + calls.append(1) + return specs + + out = await get_stripped_arguments( + data, + data.options, + "search", + {"q": "x", "session_id": sid("T"), "context": "why"}, + rebuild, + ) + assert out == {"q": "x"} + assert calls == [1] + # Registries landed on data for every later call on this instance. + assert data.injected_params_registry == { + "search": {"session_id", "agent_id", "context"}, + "other": {"session_id", "agent_id", "context"}, + } + assert data.output_injection_registry == {"other"} + + # Second call reuses the stored registry instead of rebuilding. + await get_stripped_arguments(data, data.options, "search", {"q": "x"}, rebuild) + assert calls == [1] + + +# Mode gating (§5): with tracing off nothing is injected, so the rebuilt +# registry strips nothing — the registry, not a heuristic, is the truth. +async def test_strip_registry_reflects_injection_mode_gating(): + data = make_data( + AgentCatOptions(enable_tracing=False, enable_tool_call_context=False) + ) + + async def rebuild() -> list[ToolSpec]: + return [ToolSpec("search", {"type": "object", "properties": {}})] + + raw = {"q": 1, "session_id": sid("T"), "context": "why"} + stripped = await get_stripped_arguments(data, data.options, "search", raw, rebuild) + assert stripped == raw + assert data.injected_params_registry == {"search": set()} + + +async def test_rebuild_failure_falls_back_to_heuristic(monkeypatch): + logged: list[str] = [] + monkeypatch.setattr("agentcat.modules.callpath.write_to_log", logged.append) + data = make_data() + # A stale output registry from some earlier state must not survive the + # failure: it would gate the mirror on knowledge we no longer have. + data.output_injection_registry = {"some_other_tool"} + + async def broken_rebuild() -> list[ToolSpec]: + raise RuntimeError("list source gone") + + out = await get_stripped_arguments( + data, + data.options, + "t", + {"q": 1, "session_id": "s", "context": "c"}, + broken_rebuild, + ) + assert out == {"q": 1} + assert data.output_injection_registry is None # mirror gate bypassed + assert any("list source gone" in entry for entry in logged) + + +# Two calls can race the rebuild on a server that never served tools/list. +# A loser's failure must not wipe the registries a winner already stored: every +# later call would then heuristic-strip, eating the `context` parameter of any +# customer tool that owns one. +async def test_a_failed_rebuild_does_not_wipe_a_concurrent_success(): + data = make_data() + winner_stored = asyncio.Event() + + async def slow_failing_rebuild() -> list[ToolSpec]: + await winner_stored.wait() + raise RuntimeError("list source gone") + + async def good_rebuild() -> list[ToolSpec]: + return [ToolSpec("search", {"type": "object", "properties": {}})] + + # The loser reads the empty registry first, then parks inside its rebuild. + loser = asyncio.create_task( + get_stripped_arguments( + data, data.options, "search", {"q": 1}, slow_failing_rebuild + ) + ) + await asyncio.sleep(0) + await get_stripped_arguments(data, data.options, "search", {"q": 1}, good_rebuild) + assert data.injected_params_registry == {"search": {"session_id", "context"}} + + winner_stored.set() + assert await loser == {"q": 1} + # Still the winner's registry, not None. + assert data.injected_params_registry == {"search": {"session_id", "context"}} + + +# No rebuild hook at all (adapter has no list source): straight to the +# heuristic, and get_more_tools keeps its own `context` parameter (§6.6). +async def test_strip_without_rebuild_uses_the_heuristic(): + data = make_data() + raw = {"q": 1, "session_id": "s", "agent_id": "a", "context": "c"} + assert await get_stripped_arguments(data, data.options, "t", raw, None) == {"q": 1} + assert await get_stripped_arguments( + data, data.options, "get_more_tools", raw, None + ) == {"q": 1, "context": "c"} + + +# ── resolve_call ───────────────────────────────────────────────────────────── + + +async def test_resolve_call_resolves_handles_client_and_protocol(): + data = make_data() + rc = await resolve_call( + data, + "search", + {"session_id": f" {sid('supplied')} ", "context": "why the call"}, + request={"params": {}}, + extra=None, + meta_sources=[ + {CLIENT_KEY: {"name": "cursor", "version": "2.1"}, PV_KEY: "2026-07-28"} + ], + legacy_client=lambda: None, + ) + assert rc.resolution.session_id == sid("supplied") + assert rc.resolution.session_source == "supplied" + assert rc.client == ClientIdentity("cursor", "2.1") + assert rc.protocol_version == "2026-07-28" + assert rc.intent == "why the call" + assert rc.actor is None + + +async def test_resolve_call_protocol_fallback_and_legacy_client(): + data = make_data() + rc = await resolve_call( + data, + "search", + {}, + request=None, + extra=None, + meta_sources=[None], + legacy_client=lambda: {"name": "legacy", "version": "0.9"}, + protocol_fallback="2025-06-18", + ) + assert rc.client == ClientIdentity("legacy", "0.9") + assert rc.protocol_version == "2025-06-18" + assert rc.resolution.session_source == "minted" + assert rc.resolution.session_id.startswith("ses_") + + +async def test_resolve_call_intent_only_when_a_string(): + data = make_data() + + async def intent_for(arguments): + rc = await resolve_call( + data, + "search", + arguments, + None, + None, + meta_sources=[], + legacy_client=lambda: None, + ) + return rc.intent + + assert await intent_for({"context": "third-person explanation"}) == "third-person explanation" # noqa: E501 + assert await intent_for({}) is None + assert await intent_for({"context": {"nested": True}}) is None + assert await intent_for({"context": 42}) is None + assert await intent_for({"context": None}) is None + + +# The intent is read from the RAW arguments, before any stripping — the event +# records what the agent actually sent. +async def test_resolve_call_reads_intent_before_stripping(): + data = make_data() + raw = {"context": "why", "session_id": sid("T")} + rc = await resolve_call( + data, "search", raw, None, None, meta_sources=[], legacy_client=lambda: None + ) + stripped = await get_stripped_arguments(data, data.options, "search", raw, None) + assert rc.intent == "why" + assert "context" not in stripped + + +async def test_resolve_call_identify_hook_error_yields_no_actor(): + def boom(request, extra): + raise RuntimeError("customer identify blew up") + + data = make_data(AgentCatOptions(identify=boom)) + rc = await resolve_call( + data, "search", {}, None, None, meta_sources=[], legacy_client=lambda: None + ) + assert rc.actor is None + assert rc.resolution.session_id.startswith("ses_") # the call still resolves + + +async def test_resolve_call_captures_the_actor(): + identity = UserIdentity(user_id="u1", user_name="Ada", user_data={"plan": "pro"}) + seen: list[tuple[Any, Any]] = [] + + def identify(request, extra): + seen.append((request, extra)) + return identity + + data = make_data(AgentCatOptions(identify=identify)) + rc = await resolve_call( + data, "search", {}, request="REQ", extra="EXTRA", meta_sources=[], legacy_client=lambda: None # noqa: E501 + ) + assert rc.actor is identity + assert seen == [("REQ", "EXTRA")] + + +# A hook returning something that is not a UserIdentity is not an actor. +async def test_resolve_call_rejects_a_non_identity_return(): + data = make_data(AgentCatOptions(identify=lambda request, extra: {"user_id": "u1"})) + rc = await resolve_call( + data, "search", {}, None, None, meta_sources=[], legacy_client=lambda: None + ) + assert rc.actor is None + + +# v2 publishes exactly one event per tool call, from publish_tool_call_event. +# Resolution — including the identify hook — publishes nothing. +async def test_resolve_call_publishes_nothing(monkeypatch): + published: list[Any] = [] + monkeypatch.setattr(event_queue, "publish_event", lambda server, event: published.append(event)) # noqa: E501 + identity = UserIdentity(user_id="u1", user_name=None, user_data=None) + data = make_data(AgentCatOptions(identify=lambda request, extra: identity)) + + rc = await resolve_call( + data, "search", {}, None, None, meta_sources=[], legacy_client=lambda: None + ) + assert rc.actor is identity + assert published == [] + + +# ── publish_tool_call_event ────────────────────────────────────────────────── + + +def capture_published(monkeypatch) -> list[UnredactedEvent]: + published: list[UnredactedEvent] = [] + monkeypatch.setattr( + event_queue, "publish_event", lambda server, event: published.append(event) + ) + return published + + +def resolved(**kwargs: Any) -> ResolvedCall: + defaults: dict[str, Any] = { + "resolution": HandleResolution(sid("T"), "minted"), + "actor": None, + "client": ClientIdentity("cursor", "2.1"), + "protocol_version": "2026-07-28", + "intent": "why the call", + } + defaults.update(kwargs) + return ResolvedCall(**defaults) + + +async def test_publish_tool_call_event_builds_the_event(monkeypatch): + published = capture_published(monkeypatch) + data = make_data() + actor = UserIdentity(user_id="u1", user_name="Ada", user_data={"plan": "pro"}) + raw = {"q": "x", "session_id": sid("T"), "context": "why the call"} + server = object() + + await publish_tool_call_event( + server, + data, + resolved(actor=actor), + "search", + raw, + response={"content": [{"type": "text", "text": "ok"}]}, + is_error=False, + error=None, + duration_ms=42, + mrtr=None, + extra_params={"extra": {"requestId": 7}}, + ) + + assert len(published) == 1 + event = published[0] + assert event.event_type == "mcp:tools/call" + assert event.session_id == sid("T") # the handle, not any transport session + assert event.resource_name == "search" + assert event.user_intent == "why the call" + # Raw, unstripped arguments plus the adapter's per-request extras. + assert event.parameters == {"arguments": raw, "extra": {"requestId": 7}} + assert event.response == {"content": [{"type": "text", "text": "ok"}]} + assert event.is_error is False + assert event.error is None + assert event.duration == 42 + assert event.client_name == "cursor" + assert event.client_version == "2.1" + assert event.identify_actor_given_id == "u1" + assert event.identify_actor_name == "Ada" + assert event.identify_data == {"plan": "pro"} + assert event.tags == { + "agentcat_session_id_source": "minted", + "agentcat_protocol_version": "2026-07-28", + } + + +async def test_publish_tool_call_event_records_errors_and_mrtr(monkeypatch): + published = capture_published(monkeypatch) + data = make_data() + res = HandleResolution(sid("T"), "supplied", "agt|x|1", "supplied") + + await publish_tool_call_event( + object(), + data, + resolved(resolution=res), + "search", + {"q": "x"}, + response={"isError": True}, + is_error=True, + error={"message": "tool exploded", "type": "ValueError", "platform": "python"}, + duration_ms=7, + mrtr="continuation", + extra_params=None, + ) + + event = published[0] + assert event.is_error is True + # Whatever the adapter captured is carried through verbatim. + assert event.error == { + "message": "tool exploded", + "type": "ValueError", + "platform": "python", + } + assert event.parameters == {"arguments": {"q": "x"}} + assert event.tags == { + "agentcat_session_id_source": "supplied", + "agentcat_agent_id": "agt|x|1", + "agentcat_agent_id_source": "supplied", + "agentcat_protocol_version": "2026-07-28", + "agentcat_mrtr": "continuation", + } + + # An adapter that could make nothing of the failure still records an error + # object of the same shape, not a bare flag. + await publish_tool_call_event( + object(), data, resolved(), "search", {}, None, True, None, 1, None, None + ) + assert published[1].error == { + "message": "Unknown error", + "type": None, + "platform": "python", + } + + +# §6.5: SDK tags merge over customer tags — SDK wins on collision. +async def test_publish_tool_call_event_sdk_tags_win_on_collision(monkeypatch): + published = capture_published(monkeypatch) + data = make_data( + AgentCatOptions( + event_tags=lambda request, extra: { + "agentcat_session_id_source": "fake", + "env": "prod", + }, + event_properties=lambda request, extra: {"region": "us-east-1"}, + ) + ) + + await publish_tool_call_event( + object(), data, resolved(), "search", {}, None, False, None, 1, None, None + ) + + event = published[0] + assert event.tags["agentcat_session_id_source"] == "minted" # SDK wins + assert event.tags["env"] == "prod" # customer tag survives + assert event.properties == {"region": "us-east-1"} + + +# §6.5: SDK tags are exempt from the customer 50-tag cap. +async def test_publish_tool_call_event_sdk_tags_exempt_from_the_cap(monkeypatch): + published = capture_published(monkeypatch) + customer_tags = {f"tag_{i:02d}": str(i) for i in range(50)} + data = make_data( + AgentCatOptions(event_tags=lambda request, extra: dict(customer_tags)) + ) + + await publish_tool_call_event( + object(), + data, + resolved( + resolution=HandleResolution(sid("T"), "minted", "agt|x|1", "supplied") + ), + "search", + {}, + None, + False, + None, + 1, + "input_required", + None, + ) + + event = published[0] + sdk_tags = { + "agentcat_session_id_source": "minted", + "agentcat_agent_id": "agt|x|1", + "agentcat_agent_id_source": "supplied", + "agentcat_protocol_version": "2026-07-28", + "agentcat_mrtr": "input_required", + } + assert all(event.tags[key] == value for key, value in customer_tags.items()) + assert all(event.tags[key] == value for key, value in sdk_tags.items()) + assert len(event.tags) == 55 + + +# The customer callbacks receive the same (request, extra) they always have. +async def test_publish_tool_call_event_hands_callbacks_request_and_extra(monkeypatch): + capture_published(monkeypatch) + seen: list[tuple[Any, Any]] = [] + + def event_tags(request, extra): + seen.append((request, extra)) + return {"env": "prod"} + + data = make_data(AgentCatOptions(event_tags=event_tags)) + rc = await resolve_call( + data, + "search", + {}, + request="REQ", + extra="EXTRA", + meta_sources=[], + legacy_client=lambda: None, + ) + await publish_tool_call_event( + object(), data, rc, "search", {}, None, False, None, 1, None, None + ) + assert seen == [("REQ", "EXTRA")] + + +# Nothing AgentCat does may raise into the customer's server. +async def test_publish_tool_call_event_never_raises(monkeypatch): + logged: list[str] = [] + monkeypatch.setattr("agentcat.modules.callpath.write_to_log", logged.append) + + def boom(server, event): + raise RuntimeError("queue is gone") + + monkeypatch.setattr(event_queue, "publish_event", boom) + data = make_data() + + await publish_tool_call_event( + object(), data, resolved(), "search", {}, None, False, None, 1, None, None + ) + assert any("queue is gone" in entry for entry in logged) + + +# An unserializable response would fail event construction; the call still +# survives it. +async def test_publish_tool_call_event_survives_a_bad_event_payload(monkeypatch): + published = capture_published(monkeypatch) + data = make_data() + + await publish_tool_call_event( + object(), data, resolved(), "search", {}, ["not", "a", "dict"], False, None, 1, None, None # noqa: E501 + ) + assert published == [] + + +# The event timestamps when the call STARTED (TS callWrap.ts uses `startTime`), +# recovered from the duration the adapter measured. +async def test_publish_tool_call_event_timestamps_the_call_start(monkeypatch): + published = capture_published(monkeypatch) + data = make_data() + before = datetime.now(timezone.utc) + + await publish_tool_call_event( + object(), data, resolved(), "search", {}, None, False, None, 5000, None, None + ) + await publish_tool_call_event( + object(), data, resolved(), "search", {}, None, False, None, None, None, None + ) + after = datetime.now(timezone.utc) + + timed, untimed = published + assert timed.timestamp is not None and untimed.timestamp is not None + # 5s of tool work: the call began ~5s before this publish. + assert before - timedelta(seconds=6) <= timed.timestamp <= before - timedelta(seconds=4) # noqa: E501 + # No measurement to subtract: publish time is the best available. + assert before <= untimed.timestamp <= after diff --git a/tests/test_client_identity.py b/tests/test_client_identity.py new file mode 100644 index 0000000..873835c --- /dev/null +++ b/tests/test_client_identity.py @@ -0,0 +1,111 @@ +"""Per-request client identity + protocol version ladder (spec §7). + +Client name/version now arrives per request under a fully-qualified `_meta` +key, with the pre-2026 initialize-time capture as the last rung. The ladder is +first-hit-wins and every field is narrowed to `isinstance(x, str)`, because a +non-string leaking into an event tag is a wire-format break. The two key +literals below are the cross-SDK wire contract — fix the implementation, never +the literal. +""" + +from agentcat.modules.client_identity import ( + ClientIdentity, + client_identity_from_meta, + resolve_client_identity, + resolve_protocol_version, +) + +KEY = "io.modelcontextprotocol/clientInfo" +PV = "io.modelcontextprotocol/protocolVersion" + + +class FakeMeta: + """mcp 1.x `RequestParams.Meta`: extras live in `.model_extra`, not on the + object, and `.model_extra` is `None` unless the model allows extras.""" + + def __init__(self, model_extra): + self.model_extra = model_extra + + +def test_meta_narrowing(): + assert client_identity_from_meta({KEY: {"name": "cursor", "version": "2.1"}}) == ClientIdentity("cursor", "2.1") # noqa: E501 + assert client_identity_from_meta({KEY: {"name": "cursor", "version": 7}}) == ClientIdentity("cursor", None) # noqa: E501 + assert client_identity_from_meta({KEY: "junk"}) is None + assert client_identity_from_meta(None) is None + + +# spec §7 rung 2 — pre-2026 servers hand us the pydantic Meta model, not a +# dict, and the fully-qualified key is an extra field rather than an attribute. +def test_meta_reads_pydantic_style_model_extra(): + meta = FakeMeta({KEY: {"name": "cursor", "version": "2.1"}}) + assert client_identity_from_meta(meta) == ClientIdentity("cursor", "2.1") + assert client_identity_from_meta(FakeMeta(None)) is None + assert client_identity_from_meta(FakeMeta({})) is None + + +# A meta object with no usable key must not be mistaken for a hit; the ladder +# relies on `None` to fall through to the next rung. +def test_meta_without_the_key_is_a_miss(): + assert client_identity_from_meta({}) is None + assert client_identity_from_meta({"other": {"name": "cursor"}}) is None + + +def test_ladder_order_and_legacy(): + envelope = {KEY: {"name": "envelope", "version": "1"}} + passthrough = {KEY: {"name": "meta", "version": "2"}} + + class Legacy: # duck-typed clientInfo object + name, version = "legacy", "3" + + assert resolve_client_identity([envelope, passthrough], lambda: Legacy()).name == "envelope" # noqa: E501 + assert resolve_client_identity([None, passthrough], lambda: Legacy()).name == "meta" + assert resolve_client_identity([None, None], lambda: Legacy()).name == "legacy" + assert resolve_client_identity([None], lambda: (_ for _ in ()).throw(RuntimeError())) == ClientIdentity() # noqa: E501 + + +# A rung that is present but unusable is a miss, not a stop: junk under the key +# must not shadow a good value further down the ladder. +def test_unusable_meta_rung_falls_through(): + passthrough = {KEY: {"name": "meta", "version": "2"}} + assert resolve_client_identity([{KEY: "junk"}, passthrough], lambda: None).name == "meta" # noqa: E501 + assert resolve_client_identity([{}, FakeMeta({KEY: {"name": "extra"}})], lambda: None).name == "extra" # noqa: E501 + + +# spec §7 rung 3 — the legacy accessor is whatever the era hands back: +# a clientInfo model, a plain dict, `None` (v2 sessions may have none), or an +# exception from touching a torn-down request context. All four resolve, never +# raise, and the empty identity is the floor. +def test_legacy_rung_shapes(): + assert resolve_client_identity([], lambda: {"name": "dict", "version": "4"}) == ClientIdentity("dict", "4") # noqa: E501 + assert resolve_client_identity([None], lambda: None) == ClientIdentity() + assert resolve_client_identity([], lambda: None) == ClientIdentity() + + def boom(): + raise RuntimeError("request context is gone") + + assert resolve_client_identity([None, None], boom) == ClientIdentity() + + +# Narrowing applies to every rung, not just the meta ones. +def test_legacy_rung_is_narrowed_per_field(): + class Weird: + name, version = "legacy", 3 + + identity = resolve_client_identity([], lambda: Weird()) + assert identity == ClientIdentity("legacy", None) + + +def test_protocol_version(): + assert resolve_protocol_version([{PV: "2026-07-28"}]) == "2026-07-28" + assert resolve_protocol_version([None], fallback="2026-07-28") == "2026-07-28" + assert resolve_protocol_version([{PV: 9}]) is None + + +# Same ladder shape as the identity resolver: first hit wins, misses fall +# through, pydantic Meta is read the same way, and the fallback is the floor. +def test_protocol_version_ladder(): + assert resolve_protocol_version([{PV: "first"}, {PV: "second"}]) == "first" + assert resolve_protocol_version([{}, {PV: "second"}]) == "second" + assert resolve_protocol_version([FakeMeta({PV: "2026-07-28"})]) == "2026-07-28" + assert resolve_protocol_version([FakeMeta(None)], fallback="fb") == "fb" + assert resolve_protocol_version([]) is None diff --git a/tests/test_community_v4_handles.py b/tests/test_community_v4_handles.py new file mode 100644 index 0000000..5d2e165 --- /dev/null +++ b/tests/test_community_v4_handles.py @@ -0,0 +1,843 @@ +"""Handle behavior on the community FastMCP adapter, FastMCP 4 era. + +The 4.x sibling of `tests/community/test_community_v3_handles.py`. Task 9 built +one middleware for both eras and Task 13 turned era 4 on, so this file does not +re-prove the shared behavior the v3 file already covers — it covers what only +FastMCP 4 can reach: + +- the era's own dispatch, which runs the middleware chain a SECOND time for a + component request that failed before the interior chain ran, handing the + hooks a raw params **mapping** instead of a typed model; +- `DereferenceRefsMiddleware`, which FastMCP 4 installs on every server by + default and which the `get_more_tools` concession must survive; +- `ResponseCachingMiddleware`, which proves index 0 is load-bearing rather than + incidental; +- real multi-round-trip tool calls — `InputRequiredToolResult` and the + `input_responses` / `request_state` continuation envelope are first-class on + this era, not a simulation; +- the four TS-parity behaviors, which the 3.x suite proves but cannot prove + HERE: `tests/community/` is collected only under mcp 1.x, so nothing in it + has ever run against fastmcp 4. + +Most of it rides a real `fastmcp.Client` against a real server. The three +tests that call the middleware directly do so because no client can reach what +they assert: FastMCP's own dispatch is what hands the hooks a raw mapping, and +a client that receives an `InputRequiredToolResult` answers it and moves on +rather than handing the round back for inspection. +""" + +import copy + +import mcp.types as mt +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import ( + AGENTCAT_TAG_AGENT_ID, + AGENTCAT_TAG_MRTR, + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, + SESSION_ID_PARAM, +) +from agentcat.modules.detection import ServerFlavor, detect_server + +from .test_utils import sid +from .test_utils.community_client import ( + HAS_COMMUNITY_CLIENT, + create_community_test_client, +) +from .test_utils.community_openapi_server import ( + OPENAPI_TOOL_NAMES, + create_community_openapi_server, +) +from .test_utils.community_todo_server import ( + HAS_COMMUNITY_FASTMCP, + create_community_todo_server, +) + +pytestmark = pytest.mark.skipif( + not (HAS_COMMUNITY_FASTMCP and HAS_COMMUNITY_CLIENT), + reason="Community FastMCP not available", +) + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +def _call_events(capture) -> list: + return [e for e in capture if e.event_type == "mcp:tools/call"] + + +def _named(tools, name): + return next(t for t in tools if t.name == name) + + +def _new_server(name: str = "probe-server"): + from fastmcp import FastMCP + + return FastMCP(name) + + +def _agentcat_middleware(server): + from agentcat.modules.adapters.community import AgentCatMiddleware + + return [mw for mw in server.middleware if isinstance(mw, AgentCatMiddleware)] + + +# ── the era is recognized and routed ──────────────────────────────────────── + + +def test_track_installs_the_community_middleware_at_index_zero(): + """`track()` routes COMMUNITY_V4 to the community adapter with era 4. + + The flavor assert is the precondition every other test here rests on — + `tests/test_detection.py` proves the classifier, this proves what `track()` + does with its answer. + + Index 0 is outermost — FastMCP builds its chain over `reversed(middleware)` + — and on this era the list is never empty to begin with: + `DereferenceRefsMiddleware` is installed by default, so "insert at 0" and + "append" are visibly different placements from the very first track(). + """ + from agentcat.modules.adapters.community import ERA_V4 + + server = create_community_todo_server() + assert detect_server(server).flavor is ServerFlavor.COMMUNITY_V4 + assert server.middleware, "FastMCP 4 ships a default middleware chain" + + track(server, "proj_test") + + installed = _agentcat_middleware(server) + assert len(installed) == 1 + assert server.middleware[0] is installed[0] + assert installed[0]._era == ERA_V4 + + +# ── the four TS-parity behaviors, executed on this era ────────────────────── +# +# The middleware does not branch on the era, so these four are the same code +# the 3.x suite proves. They are re-run here anyway because `tests/community/` +# is collected ONLY under mcp 1.x (`tests/conftest.py::_LEGACY_ONLY`), so +# nothing in that directory has ever executed against fastmcp 4 — "shared code" +# is an argument about risk, not a substitute for running it. + + +async def test_retracking_updates_options_without_stacking_a_middleware(capture): + """A repeated `track()` replaces the middleware; it never adds a second. + + A stacked pass would inject session_id on the inside, find it already present + on the outside, never record it as strippable, and hand the customer's tool + a parameter it never declared. The second track() also carries different + options, so this pins the replacement AND that the new options are the ones + serving requests. + """ + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions(enable_report_missing=False)) + track( + server, + "proj_test", + AgentCatOptions(enable_report_missing=True, enable_agent_tracking=True), + ) + + installed = _agentcat_middleware(server) + assert len(installed) == 1, "a second track() stacked another middleware" + assert server.middleware[0] is installed[0], "the replacement left index 0" + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + # Both option changes are live: the tool the first track() suppressed is + # now advertised, and agent tracking is now injecting. + assert [t.name for t in listed].count("get_more_tools") == 1 + add = _named(listed, "add_todo") + assert list(add.input_schema["properties"]) == [ + "text", + SESSION_ID_PARAM, + "agent_id", + "context", + ] + + result = await client.call_tool( + "add_todo", + { + "text": "retracked", + SESSION_ID_PARAM: sid("retrack"), + "agent_id": "o|cc|k3n9x", + }, + ) + assert result.is_error is False, _text(result) + + events = _call_events(capture) + assert len(events) == 1, "a stacked middleware published the call twice" + assert events[0].session_id == sid("retrack") + assert events[0].tags[AGENTCAT_TAG_AGENT_ID] == "o|cc|k3n9x" + + +async def test_options_are_read_per_request_not_captured_at_install(capture): + """The middleware re-reads the server's tracking data every request. + + Distinct from the re-track above, which installs a fresh middleware object: + here the data is swapped in place and the SAME middleware has to pick it up, + which is the only thing that proves the lookup is per request rather than + captured in `__init__`. + """ + from dataclasses import replace + + from agentcat.modules.internal import ( + get_server_tracking_data, + set_server_tracking_data, + ) + + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions(enable_agent_tracking=False)) + middleware = server.middleware[0] + + set_server_tracking_data( + server, + replace( + get_server_tracking_data(server), + options=AgentCatOptions(enable_agent_tracking=True), + injected_params_registry=None, + output_injection_registry=None, + ), + ) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + assert "agent_id" in _named(listed, "add_todo").input_schema["properties"] + result = await client.call_tool( + "add_todo", {"text": "swapped", "agent_id": "o|cc|abc12"} + ) + + assert server.middleware[0] is middleware, "the middleware was reinstalled" + assert result.is_error is False, _text(result) + assert _call_events(capture)[0].tags[AGENTCAT_TAG_AGENT_ID] == "o|cc|abc12" + + +async def test_tracing_disabled_strips_but_publishes_nothing(capture): + """Tracing off is not injection off. + + No handles are injected and nothing is published, but `context` is an + independent option — so it is still advertised, and it must still be + stripped before the customer's tool runs or the call fails validation. + """ + seen: dict = {} + server = _new_server("quiet-server") + + @server.tool + def probe(text: str) -> str: + """Would fail validation if handed an argument it never declared.""" + seen["text"] = text + return f"probe:{text}" + + track(server, "proj_test", AgentCatOptions(enable_tracing=False)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + schema = _named(listed, "probe").input_schema + assert SESSION_ID_PARAM not in schema["properties"] + assert "context" in schema["properties"] + + result = await client.call_tool( + "probe", {"text": "quiet", "context": "no tracing"} + ) + + assert result.is_error is False, _text(result) + assert seen == {"text": "quiet"} + assert MINT_BACK_HEADER not in _text(result) + assert capture == [] + + +async def test_resolution_failure_degrades_to_an_untraced_call(capture, monkeypatch): + """A tool call must never fail because analytics did. + + The injected parameters are stripped on the way DOWN, before resolution is + attempted, so the degrade path still hands the customer's tool a clean + argument set rather than failing its validation. + """ + from agentcat.modules.adapters import community + + seen: dict = {} + + async def boom(*args, **kwargs): + raise RuntimeError("resolver exploded") + + monkeypatch.setattr(community, "resolve_call", boom) + + server = _new_server("degrade-server") + + @server.tool + def probe(text: str) -> str: + """Would fail validation if handed an argument it never declared.""" + seen["text"] = text + return f"probe:{text}" + + track(server, "proj_test") + + async with create_community_test_client(server) as client: + await client.list_tools() + result = await client.call_tool( + "probe", + {"text": "degraded", "context": "why", SESSION_ID_PARAM: sid("x")}, + ) + + assert result.is_error is False, _text(result) + assert "probe:degraded" in _text(result) + assert seen == {"text": "degraded"} + assert capture == [] + + +# ── injection, mint-back and echo ─────────────────────────────────────────── + + +async def test_prompted_mode_end_to_end(capture): + server = create_community_todo_server() + track(server, "proj_test", AgentCatOptions()) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + add = _named(listed, "add_todo") + tail = list(add.input_schema["properties"])[-2:] + assert tail == [SESSION_ID_PARAM, "context"] + assert SESSION_ID_PARAM not in add.input_schema.get("required", []) + assert MCP_INSTRUCTIONS_KEY in add.output_schema["properties"] + assert any(t.name == "get_more_tools" for t in listed) + + r1 = await client.call_tool( + "add_todo", {"text": "hi", "context": "tracking the user's work"} + ) + text = _text(r1) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + assert minted.startswith("ses_") + assert r1.structured_content[MCP_INSTRUCTIONS_KEY]["session_id"] == minted + + r2 = await client.call_tool( + "add_todo", {"text": "again", SESSION_ID_PARAM: minted} + ) + assert MINT_BACK_HEADER not in _text(r2) + + # v2 publishes tools/call and nothing else. + assert {e.event_type for e in capture} == {"mcp:tools/call"} + events = _call_events(capture) + assert [e.session_id for e in events] == [minted, minted] + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == [ + "minted", + "supplied", + ] + # The event records the call as the agent made it: raw arguments, and the + # customer's own undecorated result. + assert events[0].parameters["arguments"]["context"] + assert MINT_BACK_HEADER not in str(events[0].response) + + +async def test_handler_sees_stripped_args(capture): + """The injected parameters never reach the customer's tool body.""" + seen: dict = {} + server = _new_server() + + @server.tool + def probe(text: str) -> str: + """A tool that would fail validation if handed an extra argument.""" + seen["text"] = text + return f"probe:{text}" + + track(server, "proj_test") + + async with create_community_test_client(server) as client: + result = await client.call_tool( + "probe", + {"text": "payload", SESSION_ID_PARAM: sid("supplied"), "context": "why"}, + ) + + assert result.is_error is False, _text(result) + assert seen == {"text": "payload"} + assert _call_events(capture)[0].session_id == sid("supplied") + + +# ── multi round-trip tool calls (SEP-2322) ───────────────────────────────── + + +async def test_strip_preserves_the_mrtr_continuation_envelope(capture): + """The stripped message is a COPY of the customer's, not a rebuilt + `CallToolRequestParams`. + + Rebuilding from `(name, arguments)` — what the v1 middleware did — drops + `_meta` and, on this era, `input_responses` / `request_state`. A tool that + asked for input would then be handed a continuation with no responses and + no state, and the round-trip would restart forever. + """ + from fastmcp.server.middleware import MiddlewareContext + from fastmcp.tools import ToolResult + from mcp.types import CallToolRequestParams, ElicitResult, TextContent + + server = create_community_todo_server() + track(server, "proj_test") + middleware = server.middleware[0] + + seen: dict = {} + + async def call_next(ctx): + seen["message"] = ctx.message + return ToolResult(content=[TextContent(type="text", text="ok")]) + + responses = {"r1": ElicitResult(action="accept", content={"answer": "yes"})} + message = CallToolRequestParams( + name="add_todo", + arguments={"text": "hi", "context": "why"}, + _meta={"trace": "abc"}, + input_responses=responses, + request_state="opaque-state", + ) + await middleware( + MiddlewareContext(message=message, method="tools/call"), call_next + ) + + delivered = seen["message"] + assert delivered.arguments == {"text": "hi"} + assert delivered.input_responses == responses + assert delivered.request_state == "opaque-state" + assert delivered.meta is message.meta + # The customer's own message object is untouched. + assert message.arguments == {"text": "hi", "context": "why"} + # A round carrying inputResponses is a continuation (changelog §6.4). + assert _call_events(capture)[0].tags[AGENTCAT_TAG_MRTR] == "continuation" + + +async def test_input_required_round_is_tagged_but_never_decorated(capture): + """`InputRequiredToolResult` is FastMCP 4's real ask-for-input result. + + It is not the completing round, so it carries no mint-back — and it must + come back as the very object the layer below produced. Its own docstring + warns that `content` / `structured_content` carry nothing on this subclass, + so a decorated copy would write a mint-back where the wire handler never + looks; identity is the assertion because it is the only one that fails for + a copy that happens to look right. + """ + from fastmcp.server.middleware import MiddlewareContext + + ask = _input_required_result("s1") + + server = _new_server("mrtr-server") + + @server.tool(output_schema=None) + def needs_input(text: str) -> str: + """Answered by the layer below AgentCat.""" + return text + + track(server, "proj_test") + + async def call_next(ctx): + return ask + + result = await server.middleware[0]( + MiddlewareContext( + message=mt.CallToolRequestParams( + name="needs_input", arguments={"text": "round one"} + ), + method="tools/call", + ), + call_next, + ) + + assert result is ask, "the intermediate round was copied or decorated" + event = _call_events(capture)[0] + assert event.tags[AGENTCAT_TAG_MRTR] == "input_required" + assert event.session_id.startswith("ses_") + + +def _input_required_result(state: str): + from fastmcp.tools import InputRequiredToolResult + + return InputRequiredToolResult(mt.InputRequiredResult(request_state=state)) + + +async def test_a_real_client_drives_a_full_input_required_round_trip(capture): + """Round one asks for state, round two completes — over a real client. + + Only the completing round is decorated, and only it may carry the + mint-back: an agent that echoed a `session_id` off an intermediate round would + be echoing one the server never issued. + """ + rounds: list[str] = [] + server = _new_server("mrtr-e2e") + + @server.tool(output_schema=None) + def guarded(text: str) -> str | mt.InputRequiredResult: + """Asks for opaque state on the first round, completes on the second.""" + rounds.append(text) + if len(rounds) == 1: + return mt.InputRequiredResult(request_state="round-two-please") + return f"completed: {text}" + + track(server, "proj_test") + + async with create_community_test_client(server) as client: + result = await client.call_tool("guarded", {"text": "hello"}) + + assert rounds == ["hello", "hello"] + assert "completed: hello" in _text(result) + assert MINT_BACK_HEADER in _text(result) + + events = _call_events(capture) + assert len(events) == 2 + assert events[0].tags[AGENTCAT_TAG_MRTR] == "input_required" + # Round two answers with `requestState` and NO `inputResponses` — the tool + # asked to be resumed rather than asking the client a question, so the + # SEP-2322 driver retries it after a backoff with nothing else. It is still + # a continuation, and keying the tag on `inputResponses` alone missed it. + assert events[1].tags[AGENTCAT_TAG_MRTR] == "continuation" + # The completing round is the one that mints, and its handle is the one the + # agent was handed. + minted = _text(result).split("session_id=")[1].split(" ")[0] + assert events[1].session_id == minted + + +async def test_a_supplied_session_id_correlates_every_mrtr_round(capture): + """The handle the agent supplied rides every round of the conversation. + + The SEP-2322 driver replays the ORIGINAL arguments verbatim on each retry + (`mcp/client/_input_required.py`, reached through + `fastmcp/client/mixins/tools.py`), so a `session_id` supplied on round one is + on the wire for round two as well. This is the correlation changelog §6.4 + promises; the minted-first-call case is the only one that fragments, and + every fix for it is either server-side state, which design §13 forbids, or + a rewrite of the customer's own `requestState` — that one IS stateless and + does work, but design §12 forbids altering what a customer's tool produced + (see task 13.6's report §5). + """ + rounds: list[str] = [] + server = _new_server("mrtr-supplied") + + @server.tool(output_schema=None) + def guarded(text: str) -> str | mt.InputRequiredResult: + """Asks for opaque state on the first round, completes on the second.""" + rounds.append(text) + if len(rounds) == 1: + return mt.InputRequiredResult(request_state="round-two-please") + return f"completed: {text}" + + track(server, "proj_test") + + async with create_community_test_client(server) as client: + await client.call_tool( + "guarded", {"text": "hello", SESSION_ID_PARAM: sid("supplied")} + ) + + # The injected parameter never reached the tool, on either round. + assert rounds == ["hello", "hello"] + events = _call_events(capture) + assert [e.session_id for e in events] == [sid("supplied"), sid("supplied")] + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == [ + "supplied", + "supplied", + ] + assert [e.tags.get(AGENTCAT_TAG_MRTR) for e in events] == [ + "input_required", + "continuation", + ] + + +async def test_hook_mode_correlates_every_mrtr_round(capture): + """A `resolve_session_id` hook correlates the rounds on this era too. + + The hook runs per request against that round's own message/extra, and every + round of one conversation is the same tool call on the same connection — so + anything a hook keys on returns the same value and derives the same task. + With `supplied` (above) that leaves prompted-mode MINTING as the only + resolution mode an MRTR conversation fragments under, on BOTH modern eras. + That claim is load-bearing input to the design question task 13.6 raised, + so it is pinned on each era rather than inferred from the shared engine. + """ + from agentcat.modules.handles import derive_session_id + + seen: list = [] + rounds: list[str] = [] + server = _new_server("mrtr-hook") + + @server.tool(output_schema=None) + def guarded(text: str) -> str | mt.InputRequiredResult: + """Asks for opaque state on the first round, completes on the second.""" + rounds.append(text) + if len(rounds) == 1: + return mt.InputRequiredResult(request_state="round-two-please") + return f"completed: {text}" + + def hook(message, extra): + seen.append(message) + return "tenant" + + track(server, "proj_test", AgentCatOptions(resolve_session_id=hook)) + + async with create_community_test_client(server) as client: + await client.call_tool("guarded", {"text": "hello"}) + + # Each round resolved afresh, against its own message. + assert len(seen) == 2 and seen[0] is not seen[1] + events = _call_events(capture) + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == ["hook", "hook"] + derived = derive_session_id("tenant", "proj_test") + assert [e.session_id for e in events] == [derived, derived] + + +# ── FastMCP 4's own middleware, above and below us ───────────────────────── + + +async def test_agentcat_is_outermost_of_the_response_cache(capture): + """Index 0 is load-bearing, and `ResponseCachingMiddleware` is what proves it. + + Below us, the cache keys on the STRIPPED arguments and stores the + customer's own result, so every call still reaches AgentCat: two identical + calls publish two events and mint two different handles. Above us it would + key on the raw arguments and cache OUR decorated result — the second agent + would be handed the first agent's `session_id` and its call would never be + recorded at all. + """ + from fastmcp.server.middleware import Middleware + from fastmcp.server.middleware.caching import ResponseCachingMiddleware + + below: dict = {} + + class Probe(Middleware): + async def on_call_tool(self, context, call_next): + below.setdefault("arguments", []).append( + dict(context.message.arguments or {}) + ) + return await call_next(context) + + async def on_list_tools(self, context, call_next): + tools = list(await call_next(context)) + below.setdefault("schemas", []).append( + {t.name: set((t.parameters or {}).get("properties", {})) for t in tools} + ) + return tools + + server = create_community_todo_server() + server.add_middleware(ResponseCachingMiddleware()) + server.add_middleware(Probe()) + track(server, "proj_test") + + assert server.middleware[0] is _agentcat_middleware(server)[0] + + async with create_community_test_client(server) as client: + first = _named(await client.list_tools(), "add_todo") + second = _named(await client.list_tools(), "add_todo") + + r1 = await client.call_tool("add_todo", {"text": "same", "context": "why"}) + r2 = await client.call_tool("add_todo", {"text": "same", "context": "why"}) + + # The listing below us was served from the cache the second time, and the + # injection still reached the agent on both. + assert SESSION_ID_PARAM in first.input_schema["properties"] + assert SESSION_ID_PARAM in second.input_schema["properties"] + assert len(below["schemas"]) == 1, "the cache below us served the second listing" + assert below["schemas"][0]["add_todo"] == {"text"} + assert SESSION_ID_PARAM not in below["schemas"][0]["get_more_tools"] + + # The cache below us never saw an injected argument... + assert below["arguments"] == [{"text": "same"}] + # ...and its hit did not swallow the second call. + minted = [_text(r).split("session_id=")[1].split(" ")[0] for r in (r1, r2)] + assert minted[0] != minted[1] + assert [e.session_id for e in _call_events(capture)] == minted + + +async def test_get_more_tools_survives_the_default_dereference_middleware(capture): + """FastMCP 4 installs `DereferenceRefsMiddleware` on every server. + + It hands back a `model_copy` for any tool carrying `$defs`/`$ref`, and a + copy of our own tool must never read as a customer's — that false positive + un-registers ours while leaving the copy in the listing, advertising a + `get_more_tools` whose next call raises `Unknown tool`. + """ + from fastmcp.server.middleware.dereference import DereferenceRefsMiddleware + + server = _new_server("deref-server") + assert any( + isinstance(mw, DereferenceRefsMiddleware) for mw in server.middleware + ), "FastMCP 4 no longer installs the dereferencing middleware by default" + + @server.tool + def with_refs(payload: dict) -> str: + """A tool whose schema is the kind the dereferencer rewrites.""" + return str(payload) + + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(server) as client: + listed = sorted(t.name for t in await client.list_tools()) + assert listed == ["get_more_tools", "with_refs"] + + result = await client.call_tool("get_more_tools", {"context": "why"}) + assert "Unfortunately" in _text(result) + + assert sorted(t.name for t in await client.list_tools()) == listed + + names = [t.name for t in await server.list_tools(run_middleware=False)] + assert "get_more_tools" in names, "ours was un-registered on a false positive" + + +async def test_a_middleware_that_rebuilds_tools_does_not_lose_get_more_tools(capture): + """The authoritative re-check, and the only shape that needs it. + + `_is_ours` recognizes a copy of our tool three ways: object identity, the + underlying `fn` a `model_copy` carries over, and our canonical description. + A layer that REBUILDS each tool with `Tool.from_function` and a description + of its own defeats all three — and that is not exotic: it is what any + middleware that re-stamps or re-documents a listing does. + + Ours then reads as a foreign `get_more_tools` in the processed listing. + Conceding on that would un-register the real tool while the rebuilt copy + stays advertised, so the very next call to it raises `Unknown tool`. The + re-check asks the RAW provider listing — where our own object is present + and recognizable — and answers "nobody else supplies this". + """ + from fastmcp.server.middleware import Middleware + from fastmcp.tools import Tool + + class Rebuilder(Middleware): + """Hands back tools it built itself, not copies of the originals.""" + + async def on_list_tools(self, context, call_next): + async def rebuilt_body(context: str = "") -> str: + return "rebuilt" + + return [ + Tool.from_function( + rebuilt_body, + name=tool.name, + description=f"rebuilt: {tool.description}", + ).model_copy(update={"parameters": tool.parameters}) + for tool in await call_next(context) + ] + + server = _new_server("rebuilding-server") + + @server.tool + def add_todo(text: str) -> str: + """Add a todo.""" + return f"added {text}" + + server.add_middleware(Rebuilder()) + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_community_test_client(server) as client: + listed = await client.list_tools() + assert sorted(t.name for t in listed) == ["add_todo", "get_more_tools"] + # Nothing in that listing is recognizable as ours any more. + assert all(t.description.startswith("rebuilt: ") for t in listed) + + # The listing advertised it, so it has to answer — and the answer is + # ours, from the provider, because ours is still registered. + result = await client.call_tool("get_more_tools", {"context": "why"}) + assert "Unfortunately" in _text(result) + + names = [t.name for t in await server.list_tools(run_middleware=False)] + assert "get_more_tools" in names, "ours was un-registered on a false positive" + + +# ── the era's second dispatch pass ───────────────────────────────────────── + + +async def test_a_message_that_is_not_the_typed_model_is_passed_straight_through( + capture, +): + """FastMCP 4 runs the chain a SECOND time for a component request that + failed before the interior chain did (`low_level._dispatch_component`). + + That pass is observation only — its `call_next` re-raises the original + failure — and it hands `MiddlewareContext.message` the RAW params mapping, + because reconstructing a typed model is exactly what fails on a malformed + message. A hook that assumed the typed model raised `AttributeError` there, + and that error replaced the customer's own protocol error on the wire. + """ + from fastmcp.server.middleware import MiddlewareContext + from mcp.shared.exceptions import MCPError + + server = create_community_todo_server() + track(server, "proj_test") + # The helper, not `middleware[0]`: index 0 is only ours while nothing else + # inserts ahead of us, and a blind bind would silently exercise FastMCP's + # own middleware instead of AgentCat's. + installed = _agentcat_middleware(server) + assert len(installed) == 1 + middleware = installed[0] + + original = MCPError(-32602, "Invalid request parameters") + + async def re_raise(ctx): + raise original + + # `initialize` is on the list because a failed handshake reconstructs no + # message at all — FastMCP hands the hook `None` there. + for method, message in ( + ("tools/call", {"arguments": {"text": "no name"}}), + ("tools/list", {"cursor": 12345}), + ("initialize", None), + ): + with pytest.raises(MCPError) as raised: + await middleware( + MiddlewareContext(message=message, method=method), re_raise + ) + assert raised.value is original, f"{method} replaced the customer's error" + + assert capture == [], "a failed request published an event" + + +# ── tools that hold live runtime state ───────────────────────────────────── + + +async def test_openapi_generated_tools_are_still_injectable(capture): + """An OpenAPI tool holds a live `httpx` client, and the schema copy is the + only thing that makes injection possible for it. + + Deep-copying the `Tool` reintroduces the `threading.RLock` pickling failure + that silently dropped injection for whole servers in v1, so the guard below + asserts the hazard is still real on this era before asserting the outcome. + """ + requests: list = [] + server = create_community_openapi_server(record_requests=requests) + + raw = await server.list_tools(run_middleware=False) + with pytest.raises(TypeError, match="cannot pickle '_thread.RLock' object"): + copy.deepcopy(raw[0]) + + track(server, "proj_test") + + async with create_community_test_client(server) as client: + listed = {t.name: t for t in await client.list_tools()} + for name in OPENAPI_TOOL_NAMES: + props = listed[name].input_schema["properties"] + assert SESSION_ID_PARAM in props, f"session_id not injected into {name}" + assert "context" in props, f"context not injected into {name}" + + await client.call_tool( + "get_severity", + {"id": "42", "context": "an outage", SESSION_ID_PARAM: sid("openapi")}, + ) + + event = _call_events(capture)[-1] + assert event.resource_name == "get_severity" + assert event.session_id == sid("openapi") + assert event.user_intent == "an outage" + # Neither injected parameter may reach the customer's own backend. + assert requests + assert not any(sid("openapi") in str(r.url) for r in requests) + assert not any("an outage" in str(r.url) for r in requests) + + # ...and the server's own cached tools are never mutated. + raw_now = await server.list_tools(run_middleware=False) + after = {t.name: t.parameters for t in raw_now} + assert SESSION_ID_PARAM not in after["get_severity"]["properties"] diff --git a/tests/test_concurrency_handles.py b/tests/test_concurrency_handles.py new file mode 100644 index 0000000..f0a3195 --- /dev/null +++ b/tests/test_concurrency_handles.py @@ -0,0 +1,190 @@ +"""25 simultaneous tool calls, each carrying its own handle, on every flavor. + +Handles are per REQUEST in v2 — resolved from that call's own arguments, and +never held anywhere between the resolve and the publish that reads it. This +module is the cross-flavor proof, and it is written so that it cannot pass +against an implementation that keeps the resolution anywhere shared. + +**Why the barrier is the whole test.** A concurrency test whose calls do not +actually overlap inside the window under test proves nothing: each call +resolves, publishes and decorates before the next one starts, so a +last-write-wins store looks exactly like per-request state. So every tool body +blocks until all 25 have arrived, which puts all 25 calls provably between +their own `resolve_call` and their own publish at the same moment — and +`peak_concurrency` is asserted, so a transport that could not interleave fails +the test instead of quietly weakening it. + +Each call supplies a DISTINCT `session_id`, so what every event and every response +must name is knowable exactly rather than merely "different from the others". +""" + +import asyncio +import json + +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import ( + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, + MINT_BACK_HEADER_SESSION, + SESSION_ID_PARAM, +) + +from .test_utils import sid +from .test_utils.flavors import flavors + +TOTAL = 25 + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +class Barrier: + """Holds every concurrent tool body until all of them have arrived. + + `peak` is the largest number of bodies that were inside at once. The tests + assert it reaches `total`, which is what makes them real: it is the + difference between "25 calls happened" and "25 calls were simultaneously + between their own resolve and their own publish". + """ + + def __init__(self, total: int) -> None: + self.total = total + self.in_flight = 0 + self.peak = 0 + self.open = asyncio.Event() + + async def wait(self) -> None: + self.in_flight += 1 + self.peak = max(self.peak, self.in_flight) + if self.in_flight >= self.total: + self.open.set() + try: + await self.open.wait() + finally: + self.in_flight -= 1 + + +def _session_id(index: int) -> str: + # Fixed width, so no handle is a prefix of another and "names only its own" + # can be asserted by substring. Must be a SHAPE-VALID id — anything else is + # now rejected as `invalid` and the test would prove nothing about + # cross-attribution. + return sid(f"conc{index:02d}") + + +def _call_events(capture) -> list: + return [e for e in capture if e.event_type == "mcp:tools/call"] + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_simultaneous_calls_never_cross_attribute_a_handle(flavor, capture): + """25 calls, all inside their own window at once, each with its own handle. + + Two independent things must hold, and a shared resolution breaks both: the + event AgentCat publishes for a call names that call's handle, and the + result the agent is handed back mirrors that same one and no other. + """ + barrier = Barrier(TOTAL) + built = flavor.build("concurrency", hook=barrier.wait) + track(built.server, "proj_test", AgentCatOptions()) + + async with flavor.client(built.server) as client: + # Listed first, so the output-injection registry is armed and the + # structured mirror — the handle the AGENT is told — is in play. + listed = await flavor.list_tools(client) + echo = next(tool for tool in listed if tool.name == "echo") + assert SESSION_ID_PARAM in echo.input_schema["properties"] + assert MCP_INSTRUCTIONS_KEY in (echo.output_schema or {})["properties"] + + results = await asyncio.wait_for( + asyncio.gather( + *( + flavor.call( + client, + "echo", + {"text": f"t{index:02d}", SESSION_ID_PARAM: _session_id(index)}, + ) + for index in range(TOTAL) + ) + ), + timeout=60, + ) + + assert barrier.peak == TOTAL, ( + f"only {barrier.peak} of {TOTAL} calls were ever inside the window at " + "once; this transport cannot prove anything about concurrency" + ) + + # ── what the agent was handed ──────────────────────────────────────────── + for index, result in enumerate(results): + mine = _session_id(index) + assert result.text.startswith(f"echo:t{index:02d}") + assert result.structured[MCP_INSTRUCTIONS_KEY][SESSION_ID_PARAM] == mine + # Nobody else's handle is anywhere in this response. + dumped = json.dumps(result.structured) + result.text + others = [_session_id(other) for other in range(TOTAL) if other != index] + assert not [handle for handle in others if handle in dumped] + # Every handle was supplied, so nothing was minted and no mint-back + # text block exists to name one. + assert MINT_BACK_HEADER_SESSION not in result.text + + # ── what AgentCat published ────────────────────────────────────────────── + events = _call_events(capture) + assert len(events) == TOTAL + for event in events: + index = int(event.parameters["arguments"]["text"][1:]) + assert event.session_id == _session_id(index) + assert event.parameters["arguments"][SESSION_ID_PARAM] == _session_id(index) + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "supplied" + assert len({event.session_id for event in events}) == TOTAL + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_simultaneous_calls_each_mint_their_own_handle(flavor, capture): + """The same window with nothing supplied: 25 distinct minted handles. + + The supplied case above can only catch a resolution that leaked between + calls. This one also catches a MINT that did: every call mints, and the + handle each agent is told has to be the one its own event carries. + """ + barrier = Barrier(TOTAL) + built = flavor.build("concurrency-mint", hook=barrier.wait) + track(built.server, "proj_test", AgentCatOptions()) + + async with flavor.client(built.server) as client: + await flavor.list_tools(client) + results = await asyncio.wait_for( + asyncio.gather( + *( + flavor.call(client, "echo", {"text": f"t{index:02d}"}) + for index in range(TOTAL) + ) + ), + timeout=60, + ) + + assert barrier.peak == TOTAL + events = _call_events(capture) + assert len(events) == TOTAL + + published = { + event.parameters["arguments"]["text"]: event.session_id for event in events + } + assert len(set(published.values())) == TOTAL, "two calls minted one handle" + for index, result in enumerate(results): + minted = result.structured[MCP_INSTRUCTIONS_KEY][SESSION_ID_PARAM] + assert minted.startswith("ses_") + # The handle in the mint-back text and the one in the mirror are the + # same object of trust the agent echoes back, and the event has to be + # keyed on it. + assert f"session_id={minted} " in result.text + assert published[f"t{index:02d}"] == minted diff --git a/tests/test_constants_copy.py b/tests/test_constants_copy.py new file mode 100644 index 0000000..ebc1dca --- /dev/null +++ b/tests/test_constants_copy.py @@ -0,0 +1,198 @@ +"""Byte-parity guard for agent-facing copy. + +The TypeScript SDK is the single source of truth for every agent-facing string: +`agentcat-typescript-sdk/src/modules/constants.ts` (and `tools.ts` for the +get_more_tools copy). The `TS_*` literals below were copied verbatim from those +files. If one of these tests fails the SDKs have drifted -- fix the copy; do not +edit the expected literal unless the TypeScript source changed too. +""" + +import ast +from pathlib import Path + +from agentcat.modules import constants as c +from agentcat.modules import tools as t + +SRC_ROOT = Path(__file__).resolve().parents[1] / "src" / "agentcat" + +# ── Expected bytes, copied verbatim from TS constants.ts ──────────────────── +TS_SESSION_ID_PARAM_DESCRIPTION = "REQUIRED on every call after your first. This MCP server associates all of your tool calls for a given task using session_id; a call that arrives without it cannot be associated with your earlier work and is treated as the start of an unrelated task, disconnected from the original goal. Omit it on your first call only — the server will issue one in the _mcp_instructions field of the result (or a trailing [MCP INSTRUCTIONS] text block) — then echo that exact value on every later call. Never invent a value, and do not issue parallel tool calls until the server has issued your session_id. One session_id covers the whole goal from start to finish: when you spawn subagents you MUST give them this same session_id, or their work is severed from yours. Without session_id, this server does not function as intended." # noqa: E501 +TS_AGENT_ID_PARAM_DESCRIPTION = "REQUIRED on every call, including your first. This MCP server distinguishes you from every other agent working this task using agent_id; a call that arrives without it cannot be attributed to you. Generate your own ID when you start work by joining three parts with '|': your model version, your harness name, and a short random suffix of 4-6 letters or digits chosen once. Example: opus-4.80-1m|claude-code|k3n9x. Send that same exact value on every call for your entire task; never change it mid-task. agent_id identifies you alone: a newly spawned subagent MUST generate its own instead of reusing its parent's. Without agent_id, this server does not function as intended." # noqa: E501 +TS_AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE = "REQUIRED on every call, including your first. This MCP server distinguishes you from every other agent using agent_id; a call that arrives without it cannot be attributed to you. Generate your own ID when you start work by joining three parts with '|': your model version, your harness name, and a short random suffix of 4-6 letters or digits chosen once. Example: opus-4.80-1m|claude-code|k3n9x. Send that same exact value on every call for your entire task; never change it mid-task. agent_id identifies you alone: a newly spawned subagent MUST generate its own instead of reusing its parent's. Without agent_id, this server does not function as intended." # noqa: E501 +TS_MINT_BACK_HEADER_SESSION = "[MCP INSTRUCTIONS]: session_id issued." +TS_MINT_BACK_HEADER_INVALID = "[MCP INSTRUCTIONS]: session_id not recognized." +TS_MINT_BACK_CLOSER = "Without session_id, this server does not function as intended." +TS_MINT_BACK_INVALID_LINE = " The session_id you sent was not issued by this server. Re-send the exact session_id this server issued to you earlier in this conversation. Never invent a value. If this server has not issued you a session_id yet, omit the parameter and one will be issued." # noqa: E501 +TS_MCP_INSTRUCTIONS_FIELD_DESCRIPTION = "Your handles for this task, confirmed by this MCP server on every response, and the instructions for echoing them on later calls. Read and follow." # noqa: E501 +TS_MCP_INSTRUCTIONS_SESSION_ID_DESCRIPTION = "Echo this exact value as the session_id argument on every subsequent tool call." # noqa: E501 +TS_MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION = "Your agent_id as this server received it. Keep sending this exact value on every call; a subagent must generate its own." # noqa: E501 +TS_DEFAULT_CONTEXT_PARAMETER_DESCRIPTION = 'Explain why you are calling this tool and how it fits into the user\'s overall goal. This parameter is used for analytics and user intent tracking. YOU MUST provide 15-25 words (count carefully). NEVER use first person (\'I\', \'we\', \'you\') - maintain third-person perspective. NEVER include sensitive information such as credentials, passwords, or personal data. Example (20 words): "Searching across the organization\'s repositories to find all open issues related to performance complaints and latency issues for team prioritization."' # noqa: E501 + +# ── Expected bytes, copied verbatim from TS tools.ts ──────────────────────── +TS_GET_MORE_TOOLS_DESCRIPTION = "Check for additional tools whenever your task might benefit from specialized capabilities - even if existing tools could work as a fallback." # noqa: E501 +TS_GET_MORE_TOOLS_CONTEXT_DESCRIPTION = "A description of your goal and what kind of tool would help accomplish it." # noqa: E501 +TS_REPORT_MISSING_RESPONSE_TEXT = "Unfortunately, we have shown you the full tool list. We have noted your feedback and will work to improve the tool list in the future." # noqa: E501 + + +def test_param_names_and_keys(): + assert c.SESSION_ID_PARAM == "session_id" + assert c.AGENT_ID_PARAM == "agent_id" + assert c.CONTEXT_PARAM == "context" + assert c.GET_MORE_TOOLS_NAME == "get_more_tools" + assert c.MCP_INSTRUCTIONS_KEY == "_mcp_instructions" + assert c.META_CLIENT_INFO_KEY == "io.modelcontextprotocol/clientInfo" + assert c.META_PROTOCOL_VERSION_KEY == "io.modelcontextprotocol/protocolVersion" + assert c.AGENTCAT_TAG_SESSION_SOURCE == "agentcat_session_id_source" + assert c.AGENTCAT_TAG_AGENT_ID == "agentcat_agent_id" + assert c.AGENTCAT_TAG_AGENT_SOURCE == "agentcat_agent_id_source" + assert c.AGENTCAT_TAG_PROTOCOL_VERSION == "agentcat_protocol_version" + assert c.AGENTCAT_TAG_MRTR == "agentcat_mrtr" + assert c.AGENTCAT_CUSTOM_EVENT_TYPE == "agentcat:custom" + assert c.AGENT_ID_PREFIX == "agt" + + +def test_mint_back_assembly(): + assert c.MINT_BACK_HEADER_SESSION == TS_MINT_BACK_HEADER_SESSION + assert c.MINT_BACK_HEADER_SESSION == "[MCP INSTRUCTIONS]: session_id issued." + assert c.MINT_BACK_CLOSER == TS_MINT_BACK_CLOSER + assert ( + c.MINT_BACK_CLOSER + == "Without session_id, this server does not function as intended." + ) + assert ( + c.mint_back_session_line("ses_X") + == " session_id=ses_X — required on every subsequent tool call" + ) + assert c.mint_back_confirmed(["session_id"]) == ( + "[MCP INSTRUCTIONS]: session_id confirmed. " + "Keep sending this exact value on every call." + ) + assert c.mint_back_confirmed(["session_id", "agent_id"]) == ( + "[MCP INSTRUCTIONS]: session_id and agent_id confirmed. " + "Keep sending these exact values on every call." + ) + assert c.mint_back_confirmed(["agent_id"]) == ( + "[MCP INSTRUCTIONS]: agent_id confirmed. " + "Keep sending this exact value on every call." + ) + + +def test_invalid_correction_copy_matches_ts(): + """The `invalid` branch corrects the agent without issuing a replacement. + + The closing sentence is load-bearing: an agent that hallucinated a + session_id on its FIRST call was never issued one, so "re-send what you + were given" names a value that does not exist. Omitting the parameter puts + it back on the `minted` path. + """ + assert c.MINT_BACK_HEADER_INVALID == TS_MINT_BACK_HEADER_INVALID + assert c.MINT_BACK_INVALID_LINE == TS_MINT_BACK_INVALID_LINE + assert c.MINT_BACK_INVALID_LINE.endswith( + "If this server has not issued you a session_id yet, omit the parameter " + "and one will be issued." + ) + # No value is handed out anywhere in the correction. + assert "ses_" not in c.MINT_BACK_HEADER_INVALID + c.MINT_BACK_INVALID_LINE + + +def test_session_id_param_description_matches_ts(): + assert c.SESSION_ID_PARAM_DESCRIPTION == TS_SESSION_ID_PARAM_DESCRIPTION + assert c.SESSION_ID_PARAM_DESCRIPTION.startswith( + "REQUIRED on every call after your first." + ) + assert c.SESSION_ID_PARAM_DESCRIPTION.endswith( + "Without session_id, this server does not function as intended." + ) + assert "session_id and agent_id" not in c.SESSION_ID_PARAM_DESCRIPTION + + +def test_agent_id_param_descriptions_match_ts(): + assert c.AGENT_ID_PARAM_DESCRIPTION == TS_AGENT_ID_PARAM_DESCRIPTION + assert ( + c.AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE + == TS_AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE + ) + assert "working this task" in c.AGENT_ID_PARAM_DESCRIPTION + assert "working this task" not in c.AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE + assert ( + c.AGENT_ID_PARAM_DESCRIPTION.replace(" working this task", "") + == c.AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE + ) + + +def test_mcp_instructions_descriptions_match_ts(): + assert ( + c.MCP_INSTRUCTIONS_FIELD_DESCRIPTION == TS_MCP_INSTRUCTIONS_FIELD_DESCRIPTION + ) + assert ( + c.MCP_INSTRUCTIONS_SESSION_ID_DESCRIPTION + == TS_MCP_INSTRUCTIONS_SESSION_ID_DESCRIPTION + ) + assert ( + c.MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION + == TS_MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION + ) + + +def test_existing_context_description_unchanged(): + """v1 copy must survive the v2 upgrade byte-for-byte.""" + assert c.DEFAULT_CONTEXT_DESCRIPTION == TS_DEFAULT_CONTEXT_PARAMETER_DESCRIPTION + + +async def test_get_more_tools_copy_unchanged(): + """v1 get_more_tools copy must survive the v2 upgrade byte-for-byte.""" + assert t.GET_MORE_TOOLS_DESCRIPTION == TS_GET_MORE_TOOLS_DESCRIPTION + context_schema = t.GET_MORE_TOOLS_SCHEMA["properties"]["context"] + assert context_schema["description"] == TS_GET_MORE_TOOLS_CONTEXT_DESCRIPTION + assert t.REPORT_MISSING_RESPONSE_TEXT == TS_REPORT_MISSING_RESPONSE_TEXT + result = await t.handle_report_missing({"context": "why"}) + assert result.content[0].text == TS_REPORT_MISSING_RESPONSE_TEXT + + +def _declared_descriptions() -> list[tuple[str, int, str]]: + """Every literal `description=` / `"description":` string under src/agentcat. + + Adjacent string literals are joined by the parser, so implicitly + concatenated copy is compared as the single string an agent would see. + """ + found: list[tuple[str, int, str]] = [] + for path in sorted(SRC_ROOT.rglob("*.py")): + tree = ast.parse(path.read_text(encoding="utf-8")) + for node in ast.walk(tree): + values = [] + if isinstance(node, ast.keyword) and node.arg == "description": + values.append(node.value) + elif isinstance(node, ast.Dict): + values.extend( + v + for k, v in zip(node.keys, node.values, strict=True) + if isinstance(k, ast.Constant) and k.value == "description" + ) + for value in values: + if isinstance(value, ast.Constant) and isinstance(value.value, str): + name = str(path.relative_to(SRC_ROOT)) + found.append((name, value.lineno, value.value)) + return found + + +def test_no_adapter_ships_a_second_copy_of_get_more_tools(): + """Any inline get_more_tools copy an adapter grows must match the TS bytes. + + v2 has one home for this copy — `modules/tools.py` — and every adapter + registers from there. The context description is still a literal the walk + can see (the `"description"` key inside GET_MORE_TOOLS_SCHEMA), so its + presence is still asserted; the tool description is now a named constant + the walk cannot reach, which is why only that one lost its presence check. + Byte comparison applies to every match, so a future adapter that re-types + either string inline (as the v1 overrides did) still has to match the TS + source. + """ + context_descriptions = [] + for path, lineno, text in _declared_descriptions(): + where = f"{path}:{lineno}" + if text.startswith("Check for additional tools"): + assert text == TS_GET_MORE_TOOLS_DESCRIPTION, where + elif text.startswith("A description of your goal"): + context_descriptions.append(where) + assert text == TS_GET_MORE_TOOLS_CONTEXT_DESCRIPTION, where + assert context_descriptions, "no context description found under src/agentcat" diff --git a/tests/test_context_parameters.py b/tests/test_context_parameters.py deleted file mode 100644 index 6fefa53..0000000 --- a/tests/test_context_parameters.py +++ /dev/null @@ -1,389 +0,0 @@ -"""Unit tests for context_parameters module.""" - -import pytest -from copy import deepcopy -from typing import Any - -from agentcat.modules.context_parameters import ( - add_context_parameter_to_tools, - add_context_parameter_to_schema, -) - - -class TestAddContextParameterToSchema: - """Unit tests for add_context_parameter_to_schema function.""" - - def test_add_context_to_empty_schema(self): - """Test adding context to an empty schema.""" - schema = {} - custom_desc = "Test description" - - result = add_context_parameter_to_schema(schema, custom_desc) - - # Verify properties were added - assert "properties" in result - assert "context" in result["properties"] - assert result["properties"]["context"]["type"] == "string" - assert result["properties"]["context"]["description"] == custom_desc - - # Verify required was added - assert "required" in result - assert "context" in result["required"] - - # Verify original wasn't modified - assert "properties" not in schema - - def test_add_context_to_schema_with_existing_properties(self): - """Test adding context to schema with existing properties.""" - schema = { - "properties": { - "name": {"type": "string"}, - "age": {"type": "integer"} - }, - "required": ["name"] - } - custom_desc = "Why this tool?" - - result = add_context_parameter_to_schema(schema, custom_desc) - - # Verify original properties still exist - assert "name" in result["properties"] - assert "age" in result["properties"] - - # Verify context was added - assert "context" in result["properties"] - assert result["properties"]["context"]["description"] == custom_desc - - # Verify required array was updated - assert "name" in result["required"] - assert "context" in result["required"] - assert len(result["required"]) == 2 - - # Verify original wasn't modified - assert "context" not in schema["properties"] - assert "context" not in schema["required"] - - def test_add_context_to_schema_with_no_required(self): - """Test adding context when schema has no required field.""" - schema = { - "properties": { - "optional_field": {"type": "string"} - } - } - custom_desc = "Context for optional schema" - - result = add_context_parameter_to_schema(schema, custom_desc) - - # Verify required array was created with context - assert "required" in result - assert result["required"] == ["context"] - - # Verify properties were updated - assert "optional_field" in result["properties"] - assert "context" in result["properties"] - - def test_schema_immutability(self): - """Test that original schema is not modified.""" - original_schema = { - "properties": { - "field1": {"type": "string"}, - "field2": {"type": "integer"} - }, - "required": ["field1"] - } - - # Deep copy to compare later - schema_copy = deepcopy(original_schema) - - result = add_context_parameter_to_schema(original_schema, "Test") - - # Original should be unchanged - assert original_schema == schema_copy - - # Result should be different - assert result != original_schema - assert "context" in result["properties"] - assert "context" not in original_schema["properties"] - - def test_context_already_in_required(self): - """Test when context is already in required array.""" - schema = { - "properties": { - "context": {"type": "string", "description": "Existing context"} - }, - "required": ["context"] - } - custom_desc = "New context description" - - result = add_context_parameter_to_schema(schema, custom_desc) - - # Context should be overwritten with new description - assert result["properties"]["context"]["description"] == custom_desc - - # Required should still contain context (no duplicate) - assert result["required"].count("context") == 1 - - def test_empty_custom_description(self): - """Test with empty string custom description.""" - schema = {"properties": {}} - - result = add_context_parameter_to_schema(schema, "") - - assert result["properties"]["context"]["description"] == "" - assert result["properties"]["context"]["type"] == "string" - - def test_special_characters_in_description(self): - """Test with special characters in custom description.""" - schema = {} - special_desc = "Unicode: 🚀 Quotes: \"test\" Newline:\nTab:\t" - - result = add_context_parameter_to_schema(schema, special_desc) - - assert result["properties"]["context"]["description"] == special_desc - - def test_very_long_description(self): - """Test with very long custom description.""" - schema = {} - long_desc = "A" * 10000 # 10,000 characters - - result = add_context_parameter_to_schema(schema, long_desc) - - assert result["properties"]["context"]["description"] == long_desc - assert len(result["properties"]["context"]["description"]) == 10000 - - def test_nested_properties_preserved(self): - """Test that nested/complex properties are preserved.""" - schema = { - "properties": { - "user": { - "type": "object", - "properties": { - "name": {"type": "string"}, - "email": {"type": "string"} - } - }, - "tags": { - "type": "array", - "items": {"type": "string"} - } - }, - "required": ["user"] - } - - result = add_context_parameter_to_schema(schema, "Test") - - # Verify nested properties are preserved - assert "user" in result["properties"] - assert result["properties"]["user"]["properties"]["name"]["type"] == "string" - assert "tags" in result["properties"] - assert result["properties"]["tags"]["type"] == "array" - - # Verify context was added - assert "context" in result["properties"] - assert "context" in result["required"] - - -class TestAddContextParameterToTools: - """Unit tests for add_context_parameter_to_tools function.""" - - def test_empty_tools_list(self): - """Test with empty tools list.""" - tools = [] - result = add_context_parameter_to_tools(tools, "Test description") - - assert result == [] - - def test_single_tool_with_input_schema(self): - """Test with a single tool that has inputSchema.""" - tools = [ - { - "name": "test_tool", - "description": "A test tool", - "inputSchema": { - "properties": { - "param": {"type": "string"} - }, - "required": ["param"] - } - } - ] - custom_desc = "Tool context" - - result = add_context_parameter_to_tools(tools, custom_desc) - - assert len(result) == 1 - assert "context" in result[0]["inputSchema"]["properties"] - assert result[0]["inputSchema"]["properties"]["context"]["description"] == custom_desc - assert "context" in result[0]["inputSchema"]["required"] - - # Original tools list should be unchanged - assert "context" not in tools[0]["inputSchema"]["properties"] - - def test_tool_without_input_schema(self): - """Test with a tool that has no inputSchema.""" - tools = [ - { - "name": "simple_tool", - "description": "A simple tool" - } - ] - - result = add_context_parameter_to_tools(tools, "Test") - - # Tool should be copied but not modified (no inputSchema) - assert len(result) == 1 - assert result[0]["name"] == "simple_tool" - assert "inputSchema" not in result[0] - - def test_multiple_tools(self): - """Test with multiple tools of different types.""" - tools = [ - { - "name": "tool1", - "inputSchema": {"properties": {}} - }, - { - "name": "tool2", - "inputSchema": { - "properties": {"field": {"type": "string"}}, - "required": ["field"] - } - }, - { - "name": "tool3", - "description": "No schema" - } - ] - custom_desc = "Multi-tool context" - - result = add_context_parameter_to_tools(tools, custom_desc) - - assert len(result) == 3 - - # Tool 1: empty properties - assert "context" in result[0]["inputSchema"]["properties"] - assert result[0]["inputSchema"]["properties"]["context"]["description"] == custom_desc - - # Tool 2: existing properties - assert "field" in result[1]["inputSchema"]["properties"] - assert "context" in result[1]["inputSchema"]["properties"] - assert result[1]["inputSchema"]["properties"]["context"]["description"] == custom_desc - - # Tool 3: no inputSchema - assert "inputSchema" not in result[2] - - def test_tools_immutability(self): - """Test that original tools list is not modified.""" - original_tools = [ - { - "name": "test_tool", - "inputSchema": { - "properties": {"param": {"type": "string"}} - } - } - ] - - tools_copy = deepcopy(original_tools) - - result = add_context_parameter_to_tools(original_tools, "Test") - - # Original should be unchanged - assert original_tools == tools_copy - - # Result should be different - assert result != original_tools - assert "context" in result[0]["inputSchema"]["properties"] - assert "context" not in original_tools[0]["inputSchema"]["properties"] - - def test_tool_with_complex_schema(self): - """Test with a tool that has a complex schema.""" - tools = [ - { - "name": "complex_tool", - "inputSchema": { - "type": "object", - "properties": { - "config": { - "type": "object", - "properties": { - "enabled": {"type": "boolean"}, - "level": {"type": "integer", "minimum": 0, "maximum": 10} - } - }, - "items": { - "type": "array", - "items": { - "type": "object", - "properties": { - "id": {"type": "string"}, - "value": {"type": "number"} - } - } - } - }, - "required": ["config"], - "additionalProperties": False - } - } - ] - - result = add_context_parameter_to_tools(tools, "Complex context") - - # Verify complex properties are preserved - assert "config" in result[0]["inputSchema"]["properties"] - assert "items" in result[0]["inputSchema"]["properties"] - assert result[0]["inputSchema"]["additionalProperties"] == False - - # Verify context was added - assert "context" in result[0]["inputSchema"]["properties"] - assert "context" in result[0]["inputSchema"]["required"] - - def test_special_tool_fields_preserved(self): - """Test that other tool fields are preserved.""" - tools = [ - { - "name": "full_tool", - "description": "A complete tool", - "version": "1.0.0", - "deprecated": False, - "inputSchema": {"properties": {}}, - "outputSchema": {"type": "string"}, - "metadata": {"author": "test"} - } - ] - - result = add_context_parameter_to_tools(tools, "Test") - - # All fields should be preserved - assert result[0]["name"] == "full_tool" - assert result[0]["description"] == "A complete tool" - assert result[0]["version"] == "1.0.0" - assert result[0]["deprecated"] == False - assert result[0]["outputSchema"] == {"type": "string"} - assert result[0]["metadata"] == {"author": "test"} - - # And context should be added - assert "context" in result[0]["inputSchema"]["properties"] - - def test_unicode_in_tool_names_and_descriptions(self): - """Test tools with Unicode characters in various fields.""" - tools = [ - { - "name": "emoji_tool_🚀", - "description": "Tool with emojis 🎉", - "inputSchema": { - "properties": { - "field_with_emoji_🌟": {"type": "string"} - } - } - } - ] - custom_desc = "Context with emoji 🤔" - - result = add_context_parameter_to_tools(tools, custom_desc) - - # Unicode should be preserved everywhere - assert result[0]["name"] == "emoji_tool_🚀" - assert result[0]["description"] == "Tool with emojis 🎉" - assert "field_with_emoji_🌟" in result[0]["inputSchema"]["properties"] - assert result[0]["inputSchema"]["properties"]["context"]["description"] == custom_desc \ No newline at end of file diff --git a/tests/test_customer_owned_parameters.py b/tests/test_customer_owned_parameters.py new file mode 100644 index 0000000..20705d6 --- /dev/null +++ b/tests/test_customer_owned_parameters.py @@ -0,0 +1,160 @@ +"""A customer parameter that happens to share one of AgentCat's names. + +`session_id`, `agent_id` and `context` are ordinary words. A task tracker, a job +runner or a ticketing tool can already have a `session_id` of its own, and the +injection pass is careful about it: on a name collision it logs and skips, and +the strip spares the parameter so the customer's handler still receives it. + +What was missing is the third consumer. The call path read +`arguments["session_id"]` unconditionally, so a parameter AgentCat never injected +was consumed as the analytics handle anyway. Two things went wrong at once: + +- **Analytics.** Every call to that tool collapsed onto one AgentCat session + keyed by a customer-domain value, severed from the agent's real conversation. +- **Privacy.** `session_id` is in `redaction.PROTECTED_FIELDS`, so that value + reached the wire EXEMPT from the customer's own redaction hook — and a + `session_id` in a customer's domain is plausibly an email, an order number or an + account ID. + +The rule this module pins: a `session_id` the customer's own schema declared is +never read, and such calls publish **sessionless** rather than minting. Minting +one per call on a tool that can never carry AgentCat's handle would manufacture +a phantom session per call — noise shaped like data. Sessionless is the honest +signal, and it resolves the moment the customer adopts `resolve_session_id`. + +Ownership is read off `AgentCatData.declared_session_params`, a positive record +of what the customer declared, populated by the injection pass during listing. + +Runs on every server shape the installed dependency set can build, in both +dependency sets — this is a per-flavor property, because the registry is +populated by each adapter's own listing path. +""" + +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import ( + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, + SESSION_ID_PARAM, + SESSION_ID_PARAM_DESCRIPTION, +) + +from .test_utils import sid +from .test_utils.flavors import CUSTOMER_SESSION_ID_DESCRIPTION, flavors + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_a_customers_own_session_id_is_never_the_handle(flavor, capture): + built = flavor.build("customer-owned", customer_session_id=True) + track(built.server, "proj_test", AgentCatOptions()) + + async with flavor.client(built.server) as client: + listed = await flavor.list_tools(client) + complete = next(t for t in listed if t.name == "complete_task") + # The schema is the customer's. A description they wrote survives (the + # lowlevel flavors declare one; the facades generate the schema from a + # typed signature and have none), and on no flavor is it replaced by + # AgentCat's copy telling the agent what session_id means to us. + described = complete.input_schema["properties"][SESSION_ID_PARAM].get( + "description" + ) + assert described in (None, CUSTOMER_SESSION_ID_DESCRIPTION) + assert described != SESSION_ID_PARAM_DESCRIPTION + + first = await flavor.call( + client, "complete_task", {"session_id": "TASK-1234", "note": "done"} + ) + second = await flavor.call( + client, "complete_task", {"session_id": "TASK-1234", "note": "again"} + ) + + # The handler ran on the customer's value, untouched. + assert "completed TASK-1234: done" in first.text + assert first.is_error is False + + events = capture + assert len(events) == 2 + for event in events: + # Sessionless, not minted: their value is never adopted, and no + # phantom session is manufactured in its place. + assert event.session_id is None + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "foreign" + + # And AgentCat never tells the agent to send `session_id=ses_…` on a tool + # whose `session_id` means something else — that would change what the + # customer's tool does — nor confirms their value back to them. + # (Their own tool body still echoes TASK-1234 in its result — that is their + # data. What must not appear is an AgentCat-authored block naming it, which + # is what the absence of MCP_INSTRUCTIONS_KEY asserts.) + for result in (first, second): + assert "[MCP INSTRUCTIONS]" not in result.text + assert MCP_INSTRUCTIONS_KEY not in (result.structured or {}) + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_a_tool_agentcat_did_inject_still_supplies_normally(flavor, capture): + """The gate is per tool, not per server: the colliding tool above and this + one live on the same instance.""" + built = flavor.build("customer-owned", customer_session_id=True) + track(built.server, "proj_test", AgentCatOptions()) + + async with flavor.client(built.server) as client: + listed = await flavor.list_tools(client) + echo = next(t for t in listed if t.name == "echo") + assert SESSION_ID_PARAM in echo.input_schema["properties"] + + await flavor.call(client, "echo", {"text": "hi", SESSION_ID_PARAM: sid("mine")}) + await flavor.call( + client, "complete_task", {"session_id": "TASK-1234", "note": "n"} + ) + + echoed, completed = capture + assert echoed.session_id == sid("mine") + assert echoed.tags[AGENTCAT_TAG_SESSION_SOURCE] == "supplied" + assert completed.session_id is None + assert completed.tags[AGENTCAT_TAG_SESSION_SOURCE] == "foreign" + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_agent_id_is_still_confirmed_on_a_colliding_tool(flavor, capture): + """Suppression is per handle, not per response. + + A `session_id` collision skips only `session_id` injection. `agent_id` is + a separate branch and still lands in that tool's schema, so the agent + still sends one and it is still ours to confirm. Dropping the whole mirror + would withhold a handle AgentCat issued purely because a neighbouring one + belongs to the customer, and would leave agents seeing `agent_id` + confirmed on some tools and not others on the same server. + """ + built = flavor.build("customer-owned", customer_session_id=True) + track(built.server, "proj_test", AgentCatOptions(enable_agent_tracking=True)) + + async with flavor.client(built.server) as client: + await flavor.list_tools(client) + result = await flavor.call( + client, + "complete_task", + {"session_id": "TASK-1234", "note": "n", "agent_id": "opus|cc|k3n9x"}, + ) + + mint = (result.structured or {}).get(MCP_INSTRUCTIONS_KEY) + assert mint is not None, "agent_id was withheld because session_id collided" + assert mint["agent_id"] == "opus|cc|k3n9x" + assert SESSION_ID_PARAM not in mint + assert "TASK-1234" not in str(mint) + + (event,) = capture + assert event.session_id is None + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "foreign" + assert event.tags["agentcat_agent_id"] == "opus|cc|k3n9x" diff --git a/tests/test_detection.py b/tests/test_detection.py new file mode 100644 index 0000000..6889d11 --- /dev/null +++ b/tests/test_detection.py @@ -0,0 +1,336 @@ +"""Per-object server flavor classification (spec §8.1). + +The classifier decides which adapter wraps a customer's server, so a +misclassification silently untracks a fleet or wraps the wrong handler table. +Every double here is built from class name + module path + attribute presence +only — exactly the signals `detect_server` is allowed to read. It must never +import version-specific symbols, and no probe may raise into the customer's +process. +""" + +import pytest + +from agentcat.modules.detection import Detection, ServerFlavor, detect_server + +from .test_utils.flavors import FASTMCP_MAJOR, MCP_MAJOR, flavor_ids, flavors + +# spec §8.1 — the fingerprint keys logged for unrecognized shapes; the beacon +# is only useful for fleet drift detection if every probe always reports. +PROBE_KEYS = [ + "is_fastmcp_class", + "has_local_provider", + "has_add_middleware", + "has_middleware", + "has_tool_manager", + "has_mcp_server_attr", + "has_lowlevel_server_attr", + "has_extensions", + "has_request_state_security", + "has_request_handlers", + "has_private_request_handlers", + "has_add_request_handler", + "has_request_context", +] + +# Every attribute name a probe could touch. +PROBE_NAMES = ( + "_local_provider", + "add_middleware", + "middleware", + "_tool_manager", + "_mcp_server", + "_lowlevel_server", + "_extensions", + "add_extension", + "_request_state_security", + "request_handlers", + "_request_handlers", + "add_request_handler", + "_add_request_handler", + "request_context", +) + + +def make(name, module, **attrs): + cls = type(name, (), {}) + cls.__module__ = module + obj = cls() + for k, v in attrs.items(): + setattr(obj, k, v) + return obj + + +def make_exploding(name, module, raising, **attrs): + """Double whose attribute ACCESS raises on `raising` names. + + `hasattr` only swallows AttributeError, so an unguarded probe of a property + that raises anything else propagates into `track()`. + """ + namespace = {} + for attr in raising: + + def _boom(self, _attr=attr): + raise RuntimeError(f"probing {_attr} exploded") + + namespace[attr] = property(_boom) + cls = type(name, (), namespace) + cls.__module__ = module + obj = cls() + for k, v in attrs.items(): + setattr(obj, k, v) + return obj + + +COMMUNITY_V3_ATTRS = { + "_local_provider": object(), + "add_middleware": lambda m: None, + "middleware": [], +} + + +def lowlevel_v1(): + return make( + "Server", + "mcp.server.lowlevel.server", + request_handlers={}, + request_context=None, + ) + + +def lowlevel_v2(seam="add_request_handler"): + return make( + "Server", + "mcp.server.lowlevel.server", + _request_handlers={}, + **{seam: lambda *a: None}, + ) + + +# The handler-registration seam has been spelled both ways on the 2.x line: +# `_add_request_handler` on the development line (see the vendored checkout at +# model-context-protocol-sdks/python-sdk), `add_request_handler` in 2.0.0. A +# build shipping only the other spelling must not fall through to UNKNOWN — +# that would return every lowlevel-v2 server untracked with no error raised +# and no visible failure, which is the worst way for a fleet to drift. +def test_lowlevel_v2_is_classified_under_either_registration_spelling(): + for seam in ("add_request_handler", "_add_request_handler"): + server = lowlevel_v2(seam) + detected = detect_server(server) + assert detected.flavor is ServerFlavor.LOWLEVEL_V2, seam + assert detected.lowlevel is server + assert detected.fingerprint["has_add_request_handler"] is True, seam + + +def test_mcpserver_v2_is_classified_under_either_registration_spelling(): + for seam in ("add_request_handler", "_add_request_handler"): + lowlevel = lowlevel_v2(seam) + server = make( + "MCPServer", + "mcp.server.mcpserver.server", + _lowlevel_server=lowlevel, + _tool_manager=object(), + ) + detected = detect_server(server) + assert detected.flavor is ServerFlavor.MCPSERVER_V2, seam + assert detected.lowlevel is lowlevel + + +def test_community_v4_vs_v3(): + base = COMMUNITY_V3_ATTRS + v3 = make("FastMCP", "fastmcp.server.server", **base) + v4 = make( + "FastMCP", + "fastmcp.server.server", + **base, + _extensions={}, + add_extension=lambda e: None, + ) + assert detect_server(v3).flavor is ServerFlavor.COMMUNITY_V3 + assert detect_server(v4).flavor is ServerFlavor.COMMUNITY_V4 + + +# spec §8.1 — v4 is v3 plus ANY of the three discriminators, so a build that +# grew only one of them must not fall back to the v3 middleware era. +def test_each_v4_discriminator_alone_is_enough(): + discriminators = ( + {"add_extension": lambda e: None}, + {"_extensions": {}}, + {"_request_state_security": object()}, + ) + for extra in discriminators: + server = make("FastMCP", "fastmcp.server.server", **COMMUNITY_V3_ATTRS, **extra) + assert detect_server(server).flavor is ServerFlavor.COMMUNITY_V4 + + +def test_community_v2_unsupported(): + v2 = make("FastMCP", "fastmcp.server", _mcp_server=object(), _tool_manager=object()) + assert detect_server(v2).flavor is ServerFlavor.COMMUNITY_V2_UNSUPPORTED + + +# The detection-order hazard: community v2 and official FastMCP v1 are +# attribute-identical (`_mcp_server` + `_tool_manager`, class named FastMCP); +# only the module prefix separates them. Guard each against the other so a +# reordered or loosened prefix check fails here and not in a customer's +# process — one direction untracks a supported server, the other adapts an +# unsupported one. +def test_community_v2_and_official_fastmcp_v1_are_never_confused(): + ll1 = lowlevel_v1() + community = make( + "FastMCP", "fastmcp.server", _mcp_server=object(), _tool_manager=object() + ) + official = make( + "FastMCP", "mcp.server.fastmcp.server", _mcp_server=ll1, _tool_manager=object() + ) + assert detect_server(community).flavor is ServerFlavor.COMMUNITY_V2_UNSUPPORTED + assert detect_server(community).flavor is not ServerFlavor.OFFICIAL_FASTMCP_V1 + assert detect_server(official).flavor is ServerFlavor.OFFICIAL_FASTMCP_V1 + assert detect_server(official).flavor is not ServerFlavor.COMMUNITY_V2_UNSUPPORTED + + +def test_official_flavors(): + ll1 = lowlevel_v1() + ll2 = lowlevel_v2() + fm1 = make( + "FastMCP", "mcp.server.fastmcp.server", _mcp_server=ll1, _tool_manager=object() + ) + ms2 = make( + "MCPServer", + "mcp.server.mcpserver.server", + _lowlevel_server=ll2, + _tool_manager=object(), + ) + assert detect_server(ll1).flavor is ServerFlavor.LOWLEVEL_V1 + d = detect_server(ll2) + assert d.flavor is ServerFlavor.LOWLEVEL_V2 and d.lowlevel is ll2 + d = detect_server(fm1) + assert d.flavor is ServerFlavor.OFFICIAL_FASTMCP_V1 and d.lowlevel is ll1 + d = detect_server(ms2) + assert d.flavor is ServerFlavor.MCPSERVER_V2 and d.lowlevel is ll2 + + +# spec §8.1 — a bare lowlevel v1 Server is adapted in place, so `lowlevel` is +# the server itself rather than None. +def test_bare_lowlevel_servers_are_their_own_lowlevel(): + ll1 = lowlevel_v1() + assert detect_server(ll1).lowlevel is ll1 + + +# spec §8.1 — `lowlevel` is the object the adapters wrap; community flavors go +# through middleware and unknown shapes go untracked, so neither has one. +# A non-None value here would send an adapter at a FastMCP instance. +def test_lowlevel_is_none_for_community_and_unknown(): + v3 = make("FastMCP", "fastmcp.server.server", **COMMUNITY_V3_ATTRS) + v2 = make("FastMCP", "fastmcp.server", _mcp_server=object(), _tool_manager=object()) + assert detect_server(v3).lowlevel is None + assert detect_server(v2).lowlevel is None + assert detect_server(object()).lowlevel is None + + +def test_unknown_shape_has_fingerprint(): + d = detect_server(object()) + assert d.flavor is ServerFlavor.UNKNOWN and isinstance(d.fingerprint, dict) + + +# The fingerprint is the payload of the fleet-drift beacon, so every probe must +# report on every shape (including the ones that classified cleanly) and report +# a plain bool — not a truthy handler table or a raw attribute value. +def test_fingerprint_reports_every_probe_as_a_bool(): + for server in (lowlevel_v1(), lowlevel_v2(), object()): + d = detect_server(server) + assert isinstance(d, Detection) + for key in PROBE_KEYS: + assert key in d.fingerprint, key + assert all(isinstance(v, bool) for v in d.fingerprint.values()) + fp = detect_server(lowlevel_v1()).fingerprint + assert fp["has_request_handlers"] is True and fp["has_request_context"] is True + assert fp["is_fastmcp_class"] is False and fp["has_tool_manager"] is False + + +# track() must never raise (spec §3.1), and a customer server can expose a +# property on any probed name — lazy config, a deprecation shim, a proxy — that +# blows up on access. hasattr() re-raises anything that is not AttributeError, +# so every probe has to be wrapped. +def test_probes_never_raise_and_still_classify(): + ll1 = make_exploding( + "Server", + "mcp.server.lowlevel.server", + raising=( + "_tool_manager", + "_mcp_server", + "_lowlevel_server", + "_local_provider", + "middleware", + "_extensions", + "_request_state_security", + ), + request_handlers={}, + request_context=None, + ) + assert detect_server(ll1).flavor is ServerFlavor.LOWLEVEL_V1 + + +def test_a_server_that_explodes_on_every_probe_is_unknown(): + hostile = make_exploding("Mystery", "vendor.server", raising=PROBE_NAMES) + d = detect_server(hostile) + assert d.flavor is ServerFlavor.UNKNOWN + assert all(isinstance(v, bool) for v in d.fingerprint.values()) + + +# The flavor is logged and shipped on the diagnostics beacon, so it has to +# serialize as a string; `str, Enum` is the contract in the interface list. +def test_flavor_is_a_string_enum_with_distinct_values(): + assert isinstance(ServerFlavor.UNKNOWN, str) + values = [f.value for f in ServerFlavor] + assert len(set(values)) == len(values) + assert all(isinstance(v, str) and v for v in values) + + +# ── real SDK objects ───────────────────────────────────────────────────────── +# +# Everything above is a synthetic double, deliberately: the doubles are how the +# classifier's RULES get tested — shapes no installed SDK produces, probes that +# raise, a fingerprint that must report every key. But a double encodes the +# same assumptions the classifier does, so on its own the suite cannot notice +# an upstream rename: FastMCP moving `_local_provider`, or `MCPServer` renaming +# `_lowlevel_server`, would leave every test above green and every real server +# UNKNOWN — silently untracked, in the field. +# +# These two run the classifier against the objects the SDKs actually build. + + +class TestRealServerObjects: + """The classifier, against real servers from the installed dependency set.""" + + def test_this_era_can_build_every_shape_it_is_supposed_to(self): + """Nothing dropped out of the harness the cross-flavor suites use. + + `flavors()` is what those suites parametrize over, so a shape missing + from it is coverage that vanishes without a failure anywhere. The era + tables are restated here rather than imported, so the two have to + agree. + """ + official = { + 1: {"official-fastmcp-v1", "lowlevel-v1"}, + 2: {"mcpserver-v2", "lowlevel-v2"}, + }[MCP_MAJOR] + community = {f"community-v{FASTMCP_MAJOR}"} if FASTMCP_MAJOR else set() + assert set(flavor_ids()) == official | community + + @pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) + def test_a_real_server_classifies_as_the_flavor_it_is(self, flavor): + """The one assertion a synthetic double structurally cannot make.""" + server = flavor.build("detection").server + detection = detect_server(server) + + assert detection.flavor is flavor.flavor + # The object the adapter is handed: the wrapped lowlevel server for the + # official facades, the server itself for a bare lowlevel one, and + # None for the community flavors, which are adapted by middleware. + if flavor.flavor in (ServerFlavor.COMMUNITY_V3, ServerFlavor.COMMUNITY_V4): + assert detection.lowlevel is None + else: + assert detection.lowlevel is not None + # Every probe answered on a real object — none raised, none went + # missing — which is what the fleet-drift beacon carries. + assert sorted(detection.fingerprint) == sorted(PROBE_KEYS) + assert all(isinstance(v, bool) for v in detection.fingerprint.values()) diff --git a/tests/test_diagnostics_export.py b/tests/test_diagnostics_export.py index 7da2e6b..e56b15a 100644 --- a/tests/test_diagnostics_export.py +++ b/tests/test_diagnostics_export.py @@ -50,10 +50,15 @@ def test_flush_swallows_post_errors(): with patch( "agentcat.modules.diagnostics.requests.post", side_effect=RuntimeError("network down"), - ): + ) as mock_post: # Must not raise. diagnostics.flush_diagnostics() + # ...for the right reason. Without this, a flush that never posted at all + # also "swallows the error", and this test would be green on a diagnostics + # path that had stopped exporting entirely. + mock_post.assert_called() + def test_no_post_when_disabled(): diagnostics.init_diagnostics("proj_1", disabled=True) diff --git a/tests/test_diagnostics_test_env.py b/tests/test_diagnostics_test_env.py index 2f257af..22fb243 100644 --- a/tests/test_diagnostics_test_env.py +++ b/tests/test_diagnostics_test_env.py @@ -26,10 +26,11 @@ def test_track_does_not_enable_diagnostics_in_pytest(monkeypatch): monkeypatch.delenv("DISABLE_DIAGNOSTICS", raising=False) with patch("agentcat.modules.diagnostics.requests.post") as mock_post: - # track() runs init_diagnostics before validating the server, so even - # the error path would latch diagnostics on without the guard. - with pytest.raises(TypeError): - agentcat.track(object(), "proj_test_env") + # track() runs init_diagnostics before inspecting the server, so even + # the unrecognized-shape path would latch diagnostics on without the + # guard. track() itself never raises: the object comes back untracked. + sentinel = object() + assert agentcat.track(sentinel, "proj_test_env") is sentinel assert diagnostics.is_diagnostics_enabled() is False diagnostics.flush_diagnostics() diff --git a/tests/test_dynamic_tracking.py b/tests/test_dynamic_tracking.py index 6b985c3..392c37b 100644 --- a/tests/test_dynamic_tracking.py +++ b/tests/test_dynamic_tracking.py @@ -1,21 +1,35 @@ -"""Tests for the dynamic tracking system.""" +"""Tools registered at any point in a server's life are tracked. -import asyncio -from datetime import datetime -from typing import Any, List +v1 achieved this by monkey-patching FastMCP's ToolManager. v2 intercepts one +level down, at the protocol handlers, and the SDK's own `tools/list` handler +reads the live tool manager — so late registrations are picked up for free and +every assertion here runs through a real client rather than a FastMCP-level +method call. +""" + +from typing import Any import pytest -from mcp.server.fastmcp import FastMCP -from mcp.server import Server from mcp import Tool +from mcp.server import Server +from mcp.server.fastmcp import FastMCP +from mcp.types import TextContent from agentcat import track +from agentcat.modules.internal import get_server_tracking_data, reset_all_tracking_data from agentcat.types import AgentCatOptions -from agentcat.modules.internal import ( - get_server_tracking_data, - reset_all_tracking_data, - get_tool_timeline, -) + +from .test_utils.client import create_test_client +from .test_utils.delivery import record_delivered_arguments + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events class TestDynamicTracking: @@ -23,308 +37,195 @@ class TestDynamicTracking: @pytest.fixture(autouse=True) def setup(self): - """Reset the tracker before each test.""" reset_all_tracking_data() yield reset_all_tracking_data() @pytest.fixture def fastmcp_server(self): - """Create a FastMCP server instance.""" return FastMCP("test-server") @pytest.fixture def lowlevel_server(self): - """Create a low-level MCP server instance.""" return Server("test-server") @pytest.mark.asyncio - async def test_dynamic_tracking_fastmcp_early_registration(self, fastmcp_server): - """Test that tools registered before track() are tracked and work correctly.""" + async def test_early_registration_is_listed_and_traced( + self, fastmcp_server, capture + ): + """A tool registered before track() works and publishes an event.""" - # Register tools before tracking @fastmcp_server.tool() def early_tool(x: int) -> str: return str(x) - # Enable tracking (dynamic mode is now always on) track(fastmcp_server, "test-project") - # Test the tool actually works - result, _ = await fastmcp_server.call_tool("early_tool", {"x": 42}) - assert result[0].text == "42", f"Expected '42', got {result[0].text}" + async with create_test_client(fastmcp_server) as client: + listed = await client.list_tools() + assert "early_tool" in [t.name for t in listed.tools] - # Also test with different value - result2, _ = await fastmcp_server.call_tool("early_tool", {"x": 999}) - assert result2[0].text == "999", f"Expected '999', got {result2[0].text}" + result = await client.call_tool("early_tool", {"x": 42}) + assert result.content[0].text == "42" - # Verify tool is tracked - data = get_server_tracking_data(fastmcp_server) - assert data and "early_tool" in data.tool_registry - assert data.tool_registry["early_tool"].tracked + assert [e.resource_name for e in capture] == ["early_tool"] + assert get_server_tracking_data(fastmcp_server) is not None @pytest.mark.asyncio - async def test_dynamic_tracking_fastmcp_late_registration(self, fastmcp_server): - """Test that tools registered after track() are tracked with dynamic mode and work correctly.""" - # Enable tracking first (dynamic mode is now always on) + async def test_late_registration_is_listed_and_traced( + self, fastmcp_server, capture + ): + """A tool registered AFTER track() is picked up with no re-tracking.""" track(fastmcp_server, "test-project") - # Register tool after tracking @fastmcp_server.tool() def late_tool(x: int) -> str: return str(x) - # Test the tool actually works - result, _ = await fastmcp_server.call_tool("late_tool", {"x": 123}) - assert result[0].text == "123", f"Expected '123', got {result[0].text}" + async with create_test_client(fastmcp_server) as client: + listed = await client.list_tools() + late = next(t for t in listed.tools if t.name == "late_tool") + # Late arrivals get the same injection as anything registered early. + properties = list(late.inputSchema["properties"]) + assert properties == ["x", "session_id", "context"] - # Test with another value - result2, _ = await fastmcp_server.call_tool("late_tool", {"x": -456}) - assert result2[0].text == "-456", f"Expected '-456', got {result2[0].text}" + result = await client.call_tool( + "late_tool", {"x": 123, "context": "late registration"} + ) + assert result.content[0].text == "123" - # Verify tool is tracked - data = get_server_tracking_data(fastmcp_server) - assert data and "late_tool" in data.tool_registry - assert data.tool_registry["late_tool"].tracked + assert [e.resource_name for e in capture] == ["late_tool"] + assert capture[0].user_intent == "late registration" @pytest.mark.asyncio - async def test_late_registration_always_tracked(self, fastmcp_server): - """Test that late registrations are always tracked and function correctly.""" - # Enable tracking + async def test_late_registration_without_a_prior_list_still_strips( + self, fastmcp_server, capture + ): + """A call that lands before any tools/list rebuilds the strip registry.""" track(fastmcp_server, "test-project") - # Register tool after tracking @fastmcp_server.tool() - def late_tool_always_tracked(x: int) -> str: - return str(x) - - # Test the tool works correctly - result, _ = await fastmcp_server.call_tool("late_tool_always_tracked", {"x": 777}) - assert result[0].text == "777", f"Expected '777', got {result[0].text}" - - # Test with zero - result2, _ = await fastmcp_server.call_tool("late_tool_always_tracked", {"x": 0}) - assert result2[0].text == "0", f"Expected '0', got {result2[0].text}" - - # Check that it's tracked - data = get_server_tracking_data(fastmcp_server) - assert data and "late_tool_always_tracked" in data.tool_registry - assert data.tool_registry["late_tool_always_tracked"].tracked - - @pytest.mark.asyncio - async def test_dynamic_tool_execution_tracking(self, fastmcp_server): - """Test that dynamically added tools are tracked during execution and return correct results.""" - # Enable tracking (dynamic is now always on) - track(fastmcp_server, "test-project") - - # Add tool after tracking - @fastmcp_server.tool() - async def dynamic_tool(x: int) -> str: + def rebuilt_tool(x: int) -> str: return f"Result: {x}" - # Call the tool and verify result - result, _ = await fastmcp_server.call_tool("dynamic_tool", {"x": 42}) - assert result[0].text == "Result: 42", f"Expected 'Result: 42', got {result[0].text}" - - # Test with different value - result2, _ = await fastmcp_server.call_tool("dynamic_tool", {"x": 100}) - assert result2[0].text == "Result: 100", f"Expected 'Result: 100', got {result2[0].text}" + # The proof that the rebuild happened has to be read at the manager: + # `rebuilt_tool` is typed, and an un-stripped `context` would be dropped + # there silently rather than failing the call. + seen: list[tuple[str, dict]] = [] + record_delivered_arguments(fastmcp_server._tool_manager, seen) - # Test with negative value - result3, _ = await fastmcp_server.call_tool("dynamic_tool", {"x": -5}) - assert result3[0].text == "Result: -5", f"Expected 'Result: -5', got {result3[0].text}" + async with create_test_client(fastmcp_server) as client: + # No list_tools first: the registry has to be rebuilt on demand. + result = await client.call_tool( + "rebuilt_tool", {"x": 42, "context": "no listing yet"} + ) - # Verify tracking - data = get_server_tracking_data(fastmcp_server) - assert data and "dynamic_tool" in data.tool_registry - assert "dynamic_tool" in data.wrapped_tools - assert data.tool_registry["dynamic_tool"].tracked + assert result.isError is False + assert result.content[0].text == "Result: 42" + assert seen == [("rebuilt_tool", {"x": 42})] + # The EVENT still carries the raw pre-strip arguments, by design. + assert capture[0].parameters["arguments"]["context"] == "no listing yet" @pytest.mark.asyncio - async def test_tool_timeline(self, fastmcp_server): - """Test tool registration timeline tracking and that both tools work.""" - - # Register first tool - @fastmcp_server.tool() - def tool1(x: int) -> str: - return str(x) - - # Enable tracking - options = AgentCatOptions() - track(fastmcp_server, "test-project", options) - - # Register second tool - @fastmcp_server.tool() - def tool2(x: int) -> str: - return str(x * 2) # Different logic to distinguish - - # Test both tools work correctly - result1, _ = await fastmcp_server.call_tool("tool1", {"x": 5}) - assert result1[0].text == "5", f"tool1: Expected '5', got {result1[0].text}" - - result2, _ = await fastmcp_server.call_tool("tool2", {"x": 5}) - assert result2[0].text == "10", f"tool2: Expected '10', got {result2[0].text}" - - # Test with different values - result3, _ = await fastmcp_server.call_tool("tool1", {"x": 100}) - assert result3[0].text == "100", f"tool1: Expected '100', got {result3[0].text}" - - result4, _ = await fastmcp_server.call_tool("tool2", {"x": 100}) - assert result4[0].text == "200", f"tool2: Expected '200', got {result4[0].text}" - - # Get timeline - timeline = get_tool_timeline(fastmcp_server) - - # Should have both tools in timeline - tool_names = [t["name"] for t in timeline] - assert "tool1" in tool_names - assert "tool2" in tool_names - - # Timeline should be sorted by registration time - for i in range(1, len(timeline)): - assert timeline[i]["registered_at"] >= timeline[i - 1]["registered_at"] - - @pytest.mark.asyncio - async def test_context_injection_with_dynamic_tracking(self, fastmcp_server): - """Test that context injection works with dynamic tracking and tool still functions.""" - # Enable tracking with context - options = AgentCatOptions(enable_tool_call_context=True) - track(fastmcp_server, "test-project", options) - - # Add tool after tracking - @fastmcp_server.tool() - def context_tool(x: int) -> str: - return str(x * 3) # Multiply by 3 to verify logic - - # Test the tool works with context parameter - result, _ = await fastmcp_server.call_tool( - "context_tool", - {"x": 7, "context": "Testing context injection"} - ) - assert result[0].text == "21", f"Expected '21', got {result[0].text}" - - # Test without context (should still work as context is stripped) - result2, _ = await fastmcp_server.call_tool("context_tool", {"x": 10}) - assert result2[0].text == "30", f"Expected '30', got {result2[0].text}" - - # Test with empty context - result3, _ = await fastmcp_server.call_tool( - "context_tool", - {"x": 4, "context": ""} + async def test_report_missing_tool_answers(self, fastmcp_server, capture): + """get_more_tools is advertised and answers, without being registered.""" + track( + fastmcp_server, + "test-project", + AgentCatOptions(enable_report_missing=True), ) - assert result3[0].text == "12", f"Expected '12', got {result3[0].text}" - - # List tools should show context parameter - tools = await fastmcp_server.list_tools() - - # Find our tool - context_tool_def = next((t for t in tools if t.name == "context_tool"), None) - assert context_tool_def is not None - - # Should have context in parameters - if hasattr(context_tool_def, "inputSchema"): - schema = context_tool_def.inputSchema - else: - schema = context_tool_def.parameters - if schema and "properties" in schema: - assert "context" in schema["properties"] + async with create_test_client(fastmcp_server) as client: + listed = await client.list_tools() + assert [t.name for t in listed.tools] == ["get_more_tools"] - @pytest.mark.asyncio - async def test_report_missing_tool_with_dynamic_tracking(self, fastmcp_server): - """Test that the get_more_tools tool is added with dynamic tracking and works correctly.""" - # Enable tracking with report_missing - options = AgentCatOptions(enable_report_missing=True) - track(fastmcp_server, "test-project", options) - - # List tools - tools = await fastmcp_server.list_tools() - - # Should include get_more_tools - tool_names = [t.name for t in tools] - assert "get_more_tools" in tool_names - - # Test calling get_more_tools - result, _ = await fastmcp_server.call_tool( - "get_more_tools", - {"context": "Need a tool to translate text"} - ) - # Should return the standard "Unfortunately" message - result_text = result[0].text if result else "" - assert "Unfortunately" in result_text, f"Expected 'Unfortunately' in result, got: {result_text}" - assert "tool list" in result_text.lower(), f"Expected 'tool list' in result, got: {result_text}" + result = await client.call_tool( + "get_more_tools", {"context": "Need a tool to translate text"} + ) + text = "".join(c.text for c in result.content if hasattr(c, "text")) + assert "Unfortunately" in text + assert "tool list" in text.lower() - # Test with empty context - result2, _ = await fastmcp_server.call_tool("get_more_tools", {"context": ""}) - result2_text = result2[0].text if result2 else "" - assert "Unfortunately" in result2_text, f"Expected 'Unfortunately' in result, got: {result2_text}" - - # Test with missing context parameter - should raise validation error - # since context is a required parameter - with pytest.raises(Exception, match="(?i)required"): - await fastmcp_server.call_tool("get_more_tools", {}) + # It never reaches the customer's tool manager, so it cannot collide + # with a tool they register later. + registered = [t.name for t in await fastmcp_server.list_tools()] + assert "get_more_tools" not in registered @pytest.mark.asyncio - async def test_lowlevel_server_dynamic_tracking(self, lowlevel_server): - """Test dynamic tracking with low-level server and verify tool execution.""" + async def test_lowlevel_server_tracking(self, lowlevel_server, capture): + """A bare lowlevel Server gets the same treatment as FastMCP.""" - # Define tool handler @lowlevel_server.list_tools() - async def list_tools() -> List[Tool]: + async def list_tools() -> list[Tool]: return [ Tool( name="lowlevel_tool", description="A low-level tool", - inputSchema={"type": "object", "properties": {"value": {"type": "string"}}}, + inputSchema={ + "type": "object", + "properties": {"value": {"type": "string"}}, + }, ) ] @lowlevel_server.call_tool() - async def call_tool(name: str, arguments: dict) -> List[Any]: + async def call_tool(name: str, arguments: dict) -> list[Any]: if name == "lowlevel_tool": - value = arguments.get("value", "default") - return [{"type": "text", "text": f"Low-level result: {value}"}] + # A lowlevel handler is handed the raw dict, so unlike a typed + # FastMCP body it CAN police its own arguments — and it must: + # the tool's declared schema has no `additionalProperties: + # false`, so the SDK's jsonschema pass accepts extras happily + # and an un-stripped `agent_id` would slip through unnoticed. + unexpected = sorted(set(arguments) - {"value"}) + if unexpected: + raise ValueError(f"unexpected arguments: {unexpected}") + return [ + TextContent( + type="text", + text=f"Low-level result: {arguments.get('value', 'default')}", + ) + ] raise ValueError(f"Unknown tool: {name}") - # Enable dynamic tracking - options = AgentCatOptions() - track(lowlevel_server, "test-project", options) - - # List tools to trigger tracking - tools = await list_tools() - assert len(tools) == 1 - assert tools[0].name == "lowlevel_tool" - - # Test tool execution - result = await call_tool("lowlevel_tool", {"value": "test123"}) - assert result[0]["type"] == "text" - assert result[0]["text"] == "Low-level result: test123" + track( + lowlevel_server, + "test-project", + AgentCatOptions(enable_agent_tracking=True), + ) - # Test with empty arguments - result2 = await call_tool("lowlevel_tool", {}) - assert result2[0]["type"] == "text" - assert result2[0]["text"] == "Low-level result: default" + async with create_test_client(lowlevel_server) as client: + listed = await client.list_tools() + tool = next(t for t in listed.tools if t.name == "lowlevel_tool") + assert list(tool.inputSchema["properties"]) == [ + "value", + "session_id", + "agent_id", + "context", + ] + # session_id is the one injected param that is never required. + assert tool.inputSchema["required"] == ["agent_id", "context"] - # Test unknown tool raises error - with pytest.raises(ValueError, match="Unknown tool: nonexistent"): - await call_tool("nonexistent", {}) + # The handler above rejects anything but `value`, so this call + # only succeeds if both injected parameters were stripped. + result = await client.call_tool( + "lowlevel_tool", + {"value": "test123", "agent_id": "a|b|c", "context": "why"}, + ) + assert result.isError is False, result.content + assert result.content[0].text == "Low-level result: test123" - # Verify tracking setup - data = get_server_tracking_data(lowlevel_server) - assert data and data.tracker_initialized + assert capture[0].tags["agentcat_agent_id"] == "a|b|c" + assert get_server_tracking_data(lowlevel_server) is not None @pytest.mark.asyncio - async def test_multiple_servers_isolation(self): - """Test that multiple servers can be tracked independently and both function correctly.""" + async def test_multiple_servers_isolation(self, capture): + """Two tracked servers keep separate tools, options and projects.""" server1 = FastMCP("server1") server2 = FastMCP("server2") - # Track both servers - options = AgentCatOptions() - track(server1, "project1", options) - track(server2, "project2", options) + track(server1, "project1", AgentCatOptions(enable_report_missing=False)) + track(server2, "project2", AgentCatOptions(enable_report_missing=True)) - # Add tools to each server @server1.tool() def server1_tool(x: int) -> str: return f"Server1: {x}" @@ -333,35 +234,25 @@ def server1_tool(x: int) -> str: def server2_tool(x: int) -> str: return f"Server2: {x}" - # Test server1 tool works correctly - result1, _ = await server1.call_tool("server1_tool", {"x": 10}) - assert result1[0].text == "Server1: 10", f"Expected 'Server1: 10', got {result1[0].text}" - - result1b, _ = await server1.call_tool("server1_tool", {"x": 25}) - assert result1b[0].text == "Server1: 25", f"Expected 'Server1: 25', got {result1b[0].text}" - - # Test server2 tool works correctly - result2, _ = await server2.call_tool("server2_tool", {"x": 20}) - assert result2[0].text == "Server2: 20", f"Expected 'Server2: 20', got {result2[0].text}" - - result2b, _ = await server2.call_tool("server2_tool", {"x": 50}) - assert result2b[0].text == "Server2: 50", f"Expected 'Server2: 50', got {result2b[0].text}" - - # Verify tools don't cross-contaminate (server1 shouldn't have server2's tool) - with pytest.raises(Exception): # Should raise some error when tool not found - await server1.call_tool("server2_tool", {"x": 1}) - - with pytest.raises(Exception): # Should raise some error when tool not found - await server2.call_tool("server1_tool", {"x": 1}) + async with create_test_client(server1) as client: + assert [t.name for t in (await client.list_tools()).tools] == [ + "server1_tool" + ] + result = await client.call_tool("server1_tool", {"x": 10}) + assert result.content[0].text == "Server1: 10" + assert (await client.call_tool("server2_tool", {"x": 1})).isError is True + + async with create_test_client(server2) as client: + assert sorted(t.name for t in (await client.list_tools()).tools) == [ + "get_more_tools", + "server2_tool", + ] + result = await client.call_tool("server2_tool", {"x": 20}) + assert result.content[0].text == "Server2: 20" - # Verify both tools are tracked separately - data1 = get_server_tracking_data(server1) - data2 = get_server_tracking_data(server2) - assert data1 and "server1_tool" in data1.tool_registry - assert data2 and "server2_tool" in data2.tool_registry - # NOTE: There's currently cross-contamination between servers - # This is a known issue where tools from different servers - # can appear in each other's registries + assert get_server_tracking_data(server1).project_id == "project1" + assert get_server_tracking_data(server2).project_id == "project2" + assert {e.project_id for e in capture} == {"project1", "project2"} if __name__ == "__main__": diff --git a/tests/test_event_capture_completeness.py b/tests/test_event_capture_completeness.py index 5e4cd93..86f407a 100644 --- a/tests/test_event_capture_completeness.py +++ b/tests/test_event_capture_completeness.py @@ -73,6 +73,10 @@ def capture_event(publish_event_request): assert event.parameters is not None assert event.parameters.get("arguments") == {"text": "Test todo"} + # session_id now carries the task handle, minted on this first call. + assert event.session_id.startswith("ses_") + assert event.tags["agentcat_session_id_source"] == "minted" + # Verify event has its own ID assert event.id is not None assert event.id.startswith("evt_") @@ -214,7 +218,7 @@ def capture_event(publish_event_request): == "User wants to add a reminder to buy groceries for dinner" ) - # Context should be stripped from arguments + # The event records the call as the agent made it: raw, unstripped. assert event.parameters["arguments"] == { "text": "Buy groceries", "context": "User wants to add a reminder to buy groceries for dinner", @@ -263,8 +267,8 @@ def identify_fn(request, context): } @pytest.mark.asyncio - async def test_multiple_event_types_capture_all_fields(self): - """Test that different event types all capture required fields.""" + async def test_only_tool_call_events_are_published(self): + """Only mcp:tools/call events exist in v2, and each is fully stamped.""" mock_api_client = MagicMock() captured_events = [] @@ -281,14 +285,15 @@ def capture_event(publish_event_request): track(server, "test_project", options) async with create_test_client(server) as client: - # Generate various event types - await client.list_tools() # mcp:tools/list - await client.call_tool("add_todo", {"text": "Test"}) # mcp:tools/call - await client.call_tool("list_todos") # Another tool call + # tools/list is intercepted for schema injection only; v2 publishes + # no event for it, and none for initialize or identify either. + await client.list_tools() + await client.call_tool("add_todo", {"text": "Test"}) + await client.call_tool("list_todos") time.sleep(1.0) - # Check all captured events - assert len(captured_events) >= 3 + assert {e.event_type for e in captured_events} == {"mcp:tools/call"} + assert len(captured_events) == 2 # Verify each event has all required fields for event in captured_events: @@ -334,6 +339,10 @@ def capture_event(publish_event_request): # Extract all event IDs event_ids = [e.id for e in captured_events] + # Five calls, five events. Without this the uniqueness check below is + # `0 == 0` on an empty list and the format loop never runs. + assert len(event_ids) == 5 + # All IDs should be unique assert len(event_ids) == len(set(event_ids)), "Event IDs are not unique" @@ -376,47 +385,6 @@ def capture_event(publish_event_request): assert event.duration >= 0 # Should be non-negative assert event.duration < 10000 # Should be less than 10 seconds - @pytest.mark.skip(reason="Initialization event tracking is not implemented") - @pytest.mark.asyncio - async def test_initialization_event_capture(self): - """Test that initialization events are captured with all fields.""" - mock_api_client = MagicMock() - captured_events = [] - - def capture_event(publish_event_request): - captured_events.append(publish_event_request) - - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - - test_queue = EventQueue(api_client=mock_api_client) - set_event_queue(test_queue) - - server = create_todo_server() - options = AgentCatOptions(enable_tracing=True) - track(server, "test_project", options) - - # Creating the client triggers initialization - async with create_test_client(server) as client: - # Just need to wait for events to be processed - time.sleep(1.0) - - # Find initialization event - init_events = [e for e in captured_events if e.event_type == "mcp:initialize"] - assert len(init_events) > 0 - - event = init_events[0] - - # Verify all fields are present - assert event.project_id == "test_project" - assert event.id is not None - assert event.timestamp is not None - assert event.server_name == "todo-server" - assert event.server_version == "1.0.0" - assert event.client_name == "test-client" - assert event.client_version == "1.0.0" - assert event.sdk_language is not None - assert event.agentcat_version is not None - @pytest.mark.asyncio async def test_identify_function_integration(self): """Test that custom identify function affects event actor info.""" @@ -433,8 +401,9 @@ def capture_event(publish_event_request): # Custom identify function def custom_identify(request, server): - # Extract user info from tool arguments - arguments = request.params.arguments + # Extract user info from tool arguments. v2 hands every hook the + # request PARAMS, so `.arguments` is one hop, not two. + arguments = request.arguments if "user_id" in arguments: return UserIdentity( user_id=arguments["user_id"], diff --git a/tests/test_event_queue.py b/tests/test_event_queue.py index 1e5b987..4bc6423 100644 --- a/tests/test_event_queue.py +++ b/tests/test_event_queue.py @@ -9,7 +9,7 @@ from agentcat.modules.event_queue import EventQueue, publish_event from agentcat.modules.logging import write_to_log -from agentcat.types import Event, AgentCatData, AgentCatOptions, SessionInfo, UnredactedEvent +from agentcat.types import Event, AgentCatData, AgentCatOptions, UnredactedEvent class TestEventQueue: @@ -189,6 +189,37 @@ def test_process_event_with_redaction(self, mock_redact): assert called_event.redaction_fn is None mock_send.assert_called_once() + def test_process_event_redacts_for_real(self): + """The same path with nothing mocked. + + `test_process_event_with_redaction` above patches `redact_event`, so it + proves the queue calls it and nothing about what it does — which is how + a `redact_event` that returned its pydantic input untouched survived the + whole v2 branch with the README advertising it as a security control. + """ + eq = EventQueue() + + event = UnredactedEvent( + id="test-id", + event_type="mcp:tools/call", + project_id="project-123", + session_id="session-123", + timestamp=datetime.now(timezone.utc), + parameters={"arguments": {"token": "hunter2"}}, + user_intent="spend hunter2", + redaction_fn=lambda s: s.replace("hunter2", "[REDACTED]"), + ) + + with patch.object(eq, "_send_event") as mock_send: + eq._process_event(event) + + sent = mock_send.call_args[0][0] + assert sent.parameters == {"arguments": {"token": "[REDACTED]"}} + assert sent.user_intent == "spend [REDACTED]" + assert sent.redaction_fn is None + # Protected: the handle still identifies the task on the dashboard. + assert sent.session_id == "session-123" + @patch("agentcat.modules.event_queue.redact_event") @patch("agentcat.modules.event_queue.write_to_log") def test_process_event_redaction_failure(self, mock_log, mock_redact): @@ -552,54 +583,125 @@ def test_worker_thread_exception_handling(self, mock_log): assert eq.worker_thread.is_alive() +def _tracking_data(**overrides) -> AgentCatData: + """Track-time data in its v2 shape: project, options, server identity.""" + fields = { + "project_id": "project-123", + "options": AgentCatOptions(), + "server_name": "test-server", + "server_version": "1.0.0", + } + fields.update(overrides) + return AgentCatData(**fields) + + class TestPublishEvent: """Test publish_event function.""" @patch("agentcat.modules.event_queue.get_server_tracking_data") - @patch("agentcat.modules.event_queue.get_session_info") - @patch("agentcat.modules.event_queue.set_last_activity") @patch("agentcat.modules.event_queue.event_queue") - def test_publish_event_success( - self, mock_eq, mock_set_activity, mock_session, mock_tracking - ): + def test_publish_event_success(self, mock_eq, mock_tracking): """Test publishing event successfully.""" - # Mock server and data mock_server = MagicMock() - mock_data = AgentCatData( - project_id="project-123", - session_id="session-123", - session_info=SessionInfo(), - last_activity=datetime.now(timezone.utc), - options=AgentCatOptions(redact_sensitive_information=None), + mock_data = _tracking_data( + options=AgentCatOptions(redact_sensitive_information=None) ) mock_tracking.return_value = mock_data - mock_session_info = SessionInfo( - server_name="test-server", server_version="1.0.0" - ) - mock_session.return_value = mock_session_info - # Create event event = UnredactedEvent( event_type="mcp:tools/call", - session_id="session-123", + session_id="ses_task_handle", timestamp=datetime.now(timezone.utc), ) publish_event(mock_server, event) mock_tracking.assert_called_once_with(mock_server) - mock_session.assert_called_once_with(mock_server, mock_data) - mock_set_activity.assert_called_once_with(mock_server) - # Check event was added with merged data mock_eq.add.assert_called_once() added_event = mock_eq.add.call_args[0][0] assert added_event.project_id == mock_data.project_id - # Just verify the event has the expected type and required fields assert isinstance(added_event, UnredactedEvent) assert added_event.event_type == "mcp:tools/call" - assert added_event.session_id is not None + assert added_event.session_id == "ses_task_handle" + + @patch("agentcat.modules.event_queue.get_server_tracking_data") + @patch("agentcat.modules.event_queue.event_queue") + def test_publish_event_stamps_server_and_sdk_metadata(self, mock_eq, mock_tracking): + """Server identity comes from the track-time capture on AgentCatData and + the SDK identity from package metadata — there is no session cache to + read them from anymore, but every event still carries all four.""" + import importlib.metadata + + mock_tracking.return_value = _tracking_data( + server_name="todo-server", server_version="4.2.0" + ) + + event = UnredactedEvent( + event_type="mcp:tools/call", + session_id="ses_task_handle", + timestamp=datetime.now(timezone.utc), + ) + publish_event(MagicMock(), event) + + added_event = mock_eq.add.call_args[0][0] + assert added_event.server_name == "todo-server" + assert added_event.server_version == "4.2.0" + assert added_event.sdk_language.startswith("Python ") + # Compared against the distribution directly, not against the helper the + # pipeline calls, so this cannot pass by agreeing with itself. + assert added_event.agentcat_version == importlib.metadata.version("agentcat") + + @patch("agentcat.modules.event_queue.get_server_tracking_data") + @patch("agentcat.modules.event_queue.event_queue") + def test_publish_event_keeps_the_events_own_client_identity( + self, mock_eq, mock_tracking + ): + """The per-request client identity ladder (design §7) already stamped + this event. Publishing must not overwrite it — the v1 pipeline merged a + server-wide session cache OVER the event and defeated the ladder on + every non-stateless server.""" + mock_tracking.return_value = _tracking_data() + + event = UnredactedEvent( + event_type="mcp:tools/call", + session_id="ses_task_handle", + timestamp=datetime.now(timezone.utc), + client_name="Cursor", + client_version="2.6.22", + ) + publish_event(MagicMock(), event) + + added_event = mock_eq.add.call_args[0][0] + assert added_event.client_name == "Cursor" + assert added_event.client_version == "2.6.22" + + @patch("agentcat.modules.event_queue.get_server_tracking_data") + @patch("agentcat.modules.event_queue.event_queue") + def test_publish_event_keeps_the_events_own_actor_and_tags( + self, mock_eq, mock_tracking + ): + """Same rule for everything else the call path resolved per request: + the actor `identify` returned and the tags the handle layer merged.""" + mock_tracking.return_value = _tracking_data() + + event = UnredactedEvent( + event_type="mcp:tools/call", + session_id="ses_task_handle", + timestamp=datetime.now(timezone.utc), + identify_actor_given_id="user-123", + identify_actor_name="Ada", + identify_data={"plan": "pro"}, + tags={"agentcat_session_id_source": "supplied"}, + ) + publish_event(MagicMock(), event) + + added_event = mock_eq.add.call_args[0][0] + assert added_event.identify_actor_given_id == "user-123" + assert added_event.identify_actor_name == "Ada" + assert added_event.identify_data == {"plan": "pro"} + assert added_event.tags == {"agentcat_session_id_source": "supplied"} @patch("agentcat.modules.event_queue.get_server_tracking_data") @patch("agentcat.modules.event_queue.write_to_log") @@ -610,7 +712,7 @@ def test_publish_event_no_tracking_data(self, mock_log, mock_tracking): event = UnredactedEvent( event_type="mcp:tools/call", - session_id="session-123", + session_id="ses_task_handle", timestamp=datetime.now(timezone.utc), ) @@ -622,29 +724,17 @@ def test_publish_event_no_tracking_data(self, mock_log, mock_tracking): ) @patch("agentcat.modules.event_queue.get_server_tracking_data") - @patch("agentcat.modules.event_queue.get_session_info") - @patch("agentcat.modules.event_queue.set_last_activity") @patch("agentcat.modules.event_queue.event_queue") - def test_publish_event_calculates_duration( - self, mock_eq, mock_set_activity, mock_session, mock_tracking - ): + def test_publish_event_calculates_duration(self, mock_eq, mock_tracking): """Test publishing event calculates duration if not provided.""" mock_server = MagicMock() - mock_data = AgentCatData( - project_id="project-123", - session_id="session-123", - session_info=SessionInfo(), - last_activity=datetime.now(timezone.utc), - options=AgentCatOptions(), - ) - mock_tracking.return_value = mock_data - mock_session.return_value = SessionInfo() + mock_tracking.return_value = _tracking_data() # Create event without duration event_timestamp = datetime.now(timezone.utc) event = UnredactedEvent( event_type="mcp:tools/call", - session_id="session-123", + session_id="ses_task_handle", timestamp=event_timestamp, ) @@ -661,26 +751,16 @@ def test_publish_event_calculates_duration( assert event.duration > 0 @patch("agentcat.modules.event_queue.get_server_tracking_data") - @patch("agentcat.modules.event_queue.get_session_info") - @patch("agentcat.modules.event_queue.set_last_activity") @patch("agentcat.modules.event_queue.event_queue") - def test_publish_event_no_duration_no_timestamp( - self, mock_eq, mock_set_activity, mock_session, mock_tracking - ): + def test_publish_event_no_duration_no_timestamp(self, mock_eq, mock_tracking): """Test publishing event with no duration and no timestamp sets duration to None.""" mock_server = MagicMock() - mock_data = AgentCatData( - project_id="project-123", - session_id="session-123", - session_info=SessionInfo(), - last_activity=datetime.now(timezone.utc), - options=AgentCatOptions(), - ) - mock_tracking.return_value = mock_data - mock_session.return_value = SessionInfo() + mock_tracking.return_value = _tracking_data() # Create event without duration or timestamp - event = UnredactedEvent(event_type="mcp:tools/call", session_id="session-123") + event = UnredactedEvent( + event_type="mcp:tools/call", session_id="ses_task_handle" + ) publish_event(mock_server, event) @@ -688,28 +768,18 @@ def test_publish_event_no_duration_no_timestamp( assert event.duration is None @patch("agentcat.modules.event_queue.get_server_tracking_data") - @patch("agentcat.modules.event_queue.get_session_info") - @patch("agentcat.modules.event_queue.set_last_activity") @patch("agentcat.modules.event_queue.event_queue") - def test_publish_event_with_redaction_function( - self, mock_eq, mock_set_activity, mock_session, mock_tracking - ): + def test_publish_event_with_redaction_function(self, mock_eq, mock_tracking): """Test publishing event includes redaction function from options.""" mock_server = MagicMock() mock_redaction_fn = MagicMock() - mock_data = AgentCatData( - project_id="project-123", - session_id="session-123", - session_info=SessionInfo(), - last_activity=datetime.now(timezone.utc), - options=AgentCatOptions(redact_sensitive_information=mock_redaction_fn), + mock_tracking.return_value = _tracking_data( + options=AgentCatOptions(redact_sensitive_information=mock_redaction_fn) ) - mock_tracking.return_value = mock_data - mock_session.return_value = SessionInfo() event = UnredactedEvent( event_type="mcp:tools/call", - session_id="session-123", + session_id="ses_task_handle", timestamp=datetime.now(timezone.utc), ) diff --git a/tests/test_event_tags_properties.py b/tests/test_event_tags_properties.py index 445b67d..9675fba 100644 --- a/tests/test_event_tags_properties.py +++ b/tests/test_event_tags_properties.py @@ -7,7 +7,7 @@ import pytest from agentcat import AgentCatOptions, track -from agentcat.modules.constants import AGENTCAT_SOURCE +from agentcat.modules.constants import AGENTCAT_SOURCE, AGENTCAT_TAG_SESSION_SOURCE from agentcat.modules.event_queue import EventQueue, set_event_queue from agentcat.modules.internal import ( attach_event_metadata, @@ -15,8 +15,9 @@ resolve_event_tags, ) from agentcat.modules.redaction import redact_event -from agentcat.types import EventType, AgentCatData, SessionInfo, UnredactedEvent +from agentcat.types import EventType, AgentCatData, UnredactedEvent +from .test_utils import LEGACY_ONLY from .test_utils.client import create_test_client from .test_utils.todo_server import create_todo_server @@ -24,9 +25,6 @@ def _make_data(event_tags=None, event_properties=None) -> AgentCatData: return AgentCatData( project_id="p", - session_id="ses_x", - last_activity=None, - session_info=SessionInfo(), options=AgentCatOptions( event_tags=event_tags, event_properties=event_properties ), @@ -175,8 +173,13 @@ def test_tags_and_properties_not_redacted(self): assert result["parameters"]["q"] == "[REDACTED]" +@LEGACY_ONLY class TestFastMCPIntegration: - """End-to-end test against the FastMCP test server.""" + """End-to-end test against the FastMCP test server. + + The resolver / attach / redaction tests above are era-agnostic and run on + both majors; only this class needs the mcp 1.x harness. + """ @pytest.fixture(autouse=True) def restore_queue(self): @@ -208,7 +211,11 @@ async def test_callbacks_flow_through_to_published_event(self): tool_events = [e for e in captured if e.event_type == EventType.MCP_TOOLS_CALL.value] assert tool_events, "no tool call event captured" event = tool_events[0] - assert event.tags == {"env": "test"} # bad! dropped by validation + # "bad!" dropped by validation; AgentCat's own namespaced tags merge in + # last, outside the customer's 50-tag budget. + assert event.tags["env"] == "test" + assert "bad!" not in event.tags + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" assert event.properties == {"flag": True, "build": "abc"} @pytest.mark.asyncio @@ -230,7 +237,9 @@ def boom(req, ctx): tool_events = [e for e in captured if e.event_type == EventType.MCP_TOOLS_CALL.value] assert tool_events - assert tool_events[0].tags is None + # Both callbacks blew up: nothing customer-supplied lands, and only the + # SDK's own tags remain. + assert tool_events[0].tags == {AGENTCAT_TAG_SESSION_SOURCE: "minted"} assert tool_events[0].properties is None @pytest.mark.asyncio @@ -260,7 +269,9 @@ async def async_props(req, ctx): tool_events = [e for e in captured if e.event_type == EventType.MCP_TOOLS_CALL.value] assert tool_events, "no tool call event captured" event = tool_events[0] - assert event.tags == {"env": "test"} + assert event.tags["env"] == "test" + assert "bad!" not in event.tags + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" assert event.properties == {"flag": True, "nested": {"x": 1}} diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 208359d..57f20f1 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -19,6 +19,7 @@ stringify_non_exception, ) +from .test_utils import LEGACY_ONLY from .test_utils.client import create_test_client from .test_utils.todo_server import create_todo_server @@ -426,8 +427,14 @@ def test_capture_preserves_all_fields(self): assert "stack" in error_data +@LEGACY_ONLY class TestExceptionIntegration: - """Integration tests for exception capture with real MCP server calls.""" + """Integration tests for exception capture with real MCP server calls. + + The `capture_exception` unit tests above are era-agnostic and run on both + majors; only this class needs the mcp 1.x harness. The 2.x equivalents live + in `test_lowlevel_v2_handles.py`. + """ @pytest.fixture(autouse=True) def setup_and_teardown(self): @@ -606,6 +613,18 @@ async def test_tool_raises_has_in_app_frames(self): # Note: MCP SDK wraps the error, so the original tool function may not appear # but we still verify the in_app detection logic works + # NOTE (Task 13.5): the two tests below are restored verbatim from + # c32cc92^ and pass, but read them for what they are. `is_in_app` is purely + # path-based, and official FastMCP wraps a failing tool in a `ToolError` + # whose traceback stops at the wrapper — so the only top-level in_app frame + # here is AgentCat's own inner-tap seam, in_app ONLY because this is an + # editable checkout. They prove the in_app/context_line machinery runs; + # they prove nothing about the CUSTOMER's context lines. The + # environment-independent assertion for that is, in + # `tests/test_inner_tap.py`, TestOfficialV1's + # `test_fastmcp_v1_publishes_the_tool_error_and_its_cause` — which asserts + # the customer's own frame and context line inside `chained_errors`, where + # FastMCP's wrap actually puts them. @pytest.mark.asyncio async def test_tool_raises_captures_context_lines(self): """Test that context lines are captured for in_app frames.""" @@ -641,6 +660,47 @@ async def test_tool_raises_captures_context_lines(self): assert len(context) > 0 assert context.strip() != "" + @pytest.mark.asyncio + async def test_tool_error_message_survives_the_sdk_wrapping(self): + """The error the agent saw is the error the event records. + + v2 intercepts at the protocol boundary, outside the customer's handler, + so the SDK has already turned the exception into an isError + CallToolResult by the time AgentCat sees a failed call. The inner tap + (Task 13.5) recovers the exception object itself, so the event carries + the type, the stack and the cause chain again — and the message stays + exactly what the agent was told, which is what this asserts. + """ + captured_events = self._create_mock_event_capture() + + server = create_todo_server() + options = AgentCatOptions(enable_tracing=True) + track(server, "test_project", options) + + async with create_test_client(server) as client: + result = await client.call_tool( + "tool_that_raises", {"error_type": "value"} + ) + time.sleep(1.0) + + assert result.isError is True + tool_events = [ + e + for e in captured_events + if e.event_type == "mcp:tools/call" + and e.resource_name == "tool_that_raises" + ] + assert len(tool_events) == 1 + + event = tool_events[0] + assert event.is_error is True + assert event.error is not None + assert "Test value error from tool" in event.error["message"] + # The error message is exactly what the agent was told, verbatim. + assert event.error["message"] in "".join( + c.text for c in result.content if hasattr(c, "text") + ) + @pytest.mark.asyncio async def test_mcp_protocol_error(self): """Test that MCP protocol errors (McpError) are properly handled.""" diff --git a/tests/test_exporter_sdk_version.py b/tests/test_exporter_sdk_version.py index f85ee8d..e3e04b9 100644 --- a/tests/test_exporter_sdk_version.py +++ b/tests/test_exporter_sdk_version.py @@ -11,6 +11,7 @@ from agentcat.modules.exporters.otlp import OTLPExporter from agentcat.modules.exporters.sentry import SentryExporter from agentcat.types import Event +from agentcat.utils import get_agentcat_version INSTALLED_VERSION = importlib.metadata.version("agentcat") @@ -66,3 +67,29 @@ def test_auth_header_falls_back_to_unknown_when_unresolvable(self): ): exporter = SentryExporter({"dsn": self.DSN}) assert "sentry_client=agentcat/unknown" in exporter.auth_header + + +class TestGetAgentcatVersion: + """The single reader of the installed distribution version. + + Every event is stamped with it and both exporters fall back to it, so its + two behaviors — the right lookup key, and never raising — are worth pinning + directly. (Restores the coverage that lived in tests/test_session.py before + the function moved to agentcat.utils.) + """ + + def test_returns_the_installed_distribution_version(self): + assert get_agentcat_version() == INSTALLED_VERSION + + @patch("importlib.metadata.version") + def test_looks_the_version_up_under_the_distribution_name(self, mock_version): + mock_version.return_value = "1.2.3" + assert get_agentcat_version() == "1.2.3" + mock_version.assert_called_once_with("agentcat") + + @patch("importlib.metadata.version") + def test_returns_none_when_the_distribution_cannot_be_read(self, mock_version): + """An un-readable version must never break event publishing: the field + is simply omitted.""" + mock_version.side_effect = importlib.metadata.PackageNotFoundError("agentcat") + assert get_agentcat_version() is None diff --git a/tests/test_handles.py b/tests/test_handles.py new file mode 100644 index 0000000..b844ea3 --- /dev/null +++ b/tests/test_handles.py @@ -0,0 +1,451 @@ +"""Handle primitives: minting, derivation, extraction, mint-back, tags. + +Port of the TypeScript SDK's `src/tests/handles.test.ts`. The four derivation +golden vectors and the mint-back byte expectations are frozen cross-SDK +contracts: a change here changes every previously-derived session id on the +wire and splits customer sessions across an upgrade. Fix the implementation, +never the literal. +""" + +from agentcat.modules.handles import ( + HandleResolution, + build_handle_tags, + build_mint_back_text, + build_structured_mint_back, + derive_session_id, + extract_handle, + mirror_into_structured_content, + new_session_id, + resolve_handles, +) +from agentcat.types import AgentCatOptions + +from .test_utils import sid + +A = "opus-4.80-1m|claude-code|k3n9x" + + +def test_mint_shape(): + a, b = new_session_id(), new_session_id() + assert a.startswith("ses_") and len(a) == 4 + 27 and a != b + + +def test_golden_vectors(): + assert derive_session_id("customer-abc", "proj_1") == "ses_2cOHEO0LYGADMzRvWTXXVbbgxgm" # noqa: E501 + assert derive_session_id("customer-abc") == "ses_2cZY3tvyI25O2AmL2CGVo2B1IIj" + assert derive_session_id(" x ", "p") == "ses_2c3yR5mYKQdLaXsJNgZH6erbfQK" # no trim + assert derive_session_id("x", "p") == "ses_2bw285VY9apdgUgTPXKFnT6P4G0" + + +# TS handles.test.ts:26-44 — the structural properties the golden vectors pin +# by example: derivation is deterministic, project-scoped, and works project-less. +def test_derive_is_deterministic_and_project_scoped(): + assert derive_session_id("customer-abc", "proj_1") == derive_session_id( + "customer-abc", "proj_1" + ) + assert derive_session_id("customer-abc", "proj_1").startswith("ses_") + assert derive_session_id("customer-abc", "proj_1") != derive_session_id( + "customer-abc", "proj_2" + ) + assert derive_session_id("customer-abc") == derive_session_id("customer-abc") + assert derive_session_id("customer-abc") != derive_session_id( + "customer-abc", "proj_1" + ) + + +# extract_handle's contract is UNCHANGED by validation: it still returns any +# non-empty trimmed string. Shape checking happens afterwards, in +# resolve_handles — see test_an_unrecognized_session_id_is_never_adopted. +def test_extract_handle_returns_any_non_empty_string(): + assert extract_handle({"session_id": f" {sid('x')} "}, "session_id") == sid("x") + assert extract_handle({"session_id": "my-own-correlation-id"}, "session_id") == "my-own-correlation-id" # noqa: E501 + bad_values = ({"session_id": ""}, {"session_id": " "}, {"session_id": 4}, None, "s") + for bad in bad_values: + assert extract_handle(bad, "session_id") is None + + +# TS handles.test.ts:71-79 — the agent_id key and the missing-key case. +def test_extract_handle_reads_only_the_named_key(): + assert extract_handle({"agent_id": f" {A} "}, "agent_id") == A + assert extract_handle({"agent_id": A}, "session_id") is None + assert extract_handle({}, "session_id") is None + assert extract_handle(None, "agent_id") is None + + +async def test_prompted_supplied_vs_minted(): + o = AgentCatOptions() + r1 = await resolve_handles({"session_id": sid("supplied")}, o, "proj", None, None) + assert (r1.session_id, r1.session_source, r1.hook_mode) == (sid("supplied"), "supplied", False) # noqa: E501 + r2 = await resolve_handles({}, o, "proj", None, None) + assert r2.session_source == "minted" and r2.session_id.startswith("ses_") + + +# TS handles.test.ts:248-271 — the agent is never minted server-side, so an +# omitted agent_id stays unresolved in both the minted and the supplied +# (subagent-continuation) flows. +async def test_prompted_mode_never_mints_an_agent_id(): + on = AgentCatOptions(enable_agent_tracking=True) + minted = await resolve_handles({}, on, "proj_1", None, None) + assert minted.session_source == "minted" and minted.hook_mode is False + assert minted.agent_id is None and minted.agent_source is None + + supplied = await resolve_handles( + {"session_id": sid("parent")}, on, "proj_1", None, None + ) + assert (supplied.session_id, supplied.session_source) == (sid("parent"), "supplied") + assert supplied.agent_id is None and supplied.agent_source is None + + +# TS handles.test.ts:273-286 — supplied handles are taken verbatim (trimmed only). +async def test_prompted_supplied_handles_are_verbatim(): + """A well-formed session_id is honored byte-for-byte; agent_id always is. + + `agent_id` is deliberately NOT shape-validated: the agent composes it + itself (model|harness|nonce) and AgentCat never issues one, so there is no + "did we mint this" question to ask. It also never reaches + `Event.session_id` — it rides in tags, which the clamp already bounds. + """ + r = await resolve_handles( + {"session_id": sid("supplied"), "agent_id": f" {A} "}, + AgentCatOptions(enable_agent_tracking=True), + "proj_1", + None, + None, + ) + assert (r.session_id, r.session_source) == (sid("supplied"), "supplied") + assert (r.agent_id, r.agent_source) == (A, "supplied") + + +async def test_hook_mode_derives_and_falls_back(): + o = AgentCatOptions(resolve_session_id=lambda req, extra: " customer-abc ") + r = await resolve_handles({"session_id": "ignored"}, o, "proj_1", None, None) + # trimmed by the caller + assert r.session_id == derive_session_id("customer-abc", "proj_1") + assert r.session_source == "hook" and r.hook_mode is True + + async def async_hook(req, extra): + return "customer-abc" + + r = await resolve_handles( + {}, AgentCatOptions(resolve_session_id=async_hook), "proj_1", None, None + ) + assert r.session_source == "hook" + + def boom(req, extra): + raise RuntimeError("hook broke") + + r = await resolve_handles( + {}, AgentCatOptions(resolve_session_id=boom), "proj_1", None, None + ) + assert r.session_source == "minted" and r.hook_mode is True + r = await resolve_handles( + {}, AgentCatOptions(resolve_session_id=lambda q, e: None), None, None, None + ) + assert r.session_source == "minted" and r.hook_mode is True + + +# TS handles.test.ts:311-319 — the same hook value derives the same session id. +async def test_hook_mode_is_deterministic_across_calls(): + o = AgentCatOptions(resolve_session_id=lambda req, extra: "customer-42") + a = await resolve_handles({}, o, "proj_1", None, None) + b = await resolve_handles({}, o, "proj_1", None, None) + assert a.hook_mode is True and a.session_source == "hook" + assert a.session_id == b.session_id and a.session_id.startswith("ses_") + + +# TS handles.test.ts:343-361 — guards the mint-back ack line, which fires on +# session_source == "supplied". That must be unreachable in hook mode: a hook that +# returns None or raises while the agent happens to send session_id is the danger +# case, and it must fall back to "minted", never adopt the agent's value. +async def test_hook_fallback_never_reports_supplied(): + def boom(req, extra): + raise RuntimeError("db down") + + for hook in (lambda req, extra: None, boom): + r = await resolve_handles( + {"session_id": sid("agent_sent")}, + AgentCatOptions(resolve_session_id=hook), + "proj_1", + None, + None, + ) + assert r.session_source == "minted" and r.hook_mode is True + assert r.session_id != sid("agent_sent") + + +# TS handles.test.ts:376-392 — hook mode does not change agent resolution. +async def test_hook_mode_still_resolves_a_supplied_agent_id(): + o = AgentCatOptions( + resolve_session_id=lambda req, extra: "c", enable_agent_tracking=True + ) + supplied = await resolve_handles({"agent_id": A}, o, "proj_1", None, None) + assert (supplied.agent_id, supplied.agent_source) == (A, "supplied") + omitted = await resolve_handles({}, o, "proj_1", None, None) + assert omitted.agent_id is None and omitted.agent_source is None + + +# TS handles.test.ts:394-424 — the flagship documented use reads a header off +# `extra`, so both objects must reach the hook unchanged (identity, not a copy +# or the arguments dict), and the returned header must actually drive derivation. +async def test_hook_receives_the_request_and_extra_objects(): + calls = [] + request = {"params": {"name": "add_todo", "arguments": {"session_id": sid("sent")}}} + extra = {"request_info": {"headers": {"x-correlation-id": "corr-1"}}} + + def hook(req, ext): + calls.append((req, ext)) + return ext["request_info"]["headers"]["x-correlation-id"] + + r = await resolve_handles( + {"session_id": sid("sent")}, + AgentCatOptions(resolve_session_id=hook), + "proj_1", + request, + extra, + ) + assert len(calls) == 1 + assert calls[0][0] is request and calls[0][1] is extra + assert r.session_source == "hook" + assert r.session_id == derive_session_id("corr-1", "proj_1") + + +async def test_a_handle_agentcat_did_not_inject_is_never_read(): + """A parameter the customer's own schema declared is never read. + + It stayed in their handler's arguments (the strip spares it), so reading + it here would sever the agent's real session AND route a customer-domain + value into `session_id`, which is exempt from the customer's redaction + hook. Ownership of `session_id` is `session_param_is_ours`; ownership of + `agent_id` is still the injection registry. + """ + o = AgentCatOptions(enable_agent_tracking=True) + args = {"session_id": "SESSION-1234", "agent_id": "THEIR-AGENT"} + + theirs = await resolve_handles( + args, o, "proj", None, None, frozenset(), session_param_is_ours=False + ) + assert theirs.session_source == "foreign" + # Sessionless, not a fresh mint: a mint per call on a tool that can never + # carry our handle manufactures a phantom session per call. + assert theirs.session_id == "" + assert theirs.agent_id is None and theirs.agent_source is None + # No slot of ours to echo into, so no mint-back: telling the agent to send + # session_id=ses_… would overwrite a parameter that means something else. + assert theirs.prompts_session_id is False + assert build_mint_back_text(theirs) is None + assert build_structured_mint_back(theirs) is None + + ours = await resolve_handles( + {"session_id": sid("mine"), "agent_id": "THEIR-AGENT"}, + o, + "proj", + None, + None, + frozenset({"session_id", "agent_id"}), + ) + assert (ours.session_id, ours.session_source) == (sid("mine"), "supplied") + assert (ours.agent_id, ours.agent_source) == ("THEIR-AGENT", "supplied") + assert ours.prompts_session_id is True + + +async def test_the_gate_is_per_handle(): + """Injecting one handle and colliding on the other is a real shape: the + customer's schema declared `session_id` but not `agent_id`. + + Suppression is per-handle. `agent_id` is a separate injection that DID + land in that tool's schema, so it is still ours to confirm — withholding + it because a neighbouring parameter belongs to the customer would leave + agents seeing agent_id confirmed on some tools and not others. + """ + o = AgentCatOptions(enable_agent_tracking=True) + args = {"session_id": "SESSION-1234", "agent_id": "agt|x|1"} + + r = await resolve_handles( + args, + o, + "proj", + None, + None, + frozenset({"agent_id"}), + session_param_is_ours=False, + ) + assert r.session_source == "foreign" and r.session_id == "" + assert r.agent_id == "agt|x|1" + # There IS something to confirm — the agent_id — but it must not carry a + # session_id the agent has nowhere to put, and must not confirm the + # customer's own value back to the agent. + mint = build_structured_mint_back(r) + assert mint is not None and "session_id" not in mint + assert mint["agent_id"] == "agt|x|1" + assert "SESSION-1234" not in str(mint) + + +async def test_a_composed_schema_tool_is_ours_to_read_but_never_prompted(): + """The one shape where the two gates disagree. + + A oneOf/allOf/anyOf schema skips the injection pass wholesale, so AgentCat + put no `session_id` on it — but the customer declared none either, so + nothing in the arguments belongs to them. It stays ours to correlate, and + stays silent because there is no parameter to name. + + Deliberate divergence from the TS SDK, which emits the instruction here. + """ + o = AgentCatOptions() + supplied = await resolve_handles( + {"session_id": sid("echoed")}, o, "proj", None, None, frozenset() + ) + assert (supplied.session_id, supplied.session_source) == (sid("echoed"), "supplied") + assert supplied.prompts_session_id is False + assert build_mint_back_text(supplied) is None + assert build_structured_mint_back(supplied) is None + + minted = await resolve_handles({}, o, "proj", None, None, frozenset()) + assert minted.session_source == "minted" + assert minted.session_id.startswith("ses_") + assert build_mint_back_text(minted) is None + + +async def test_no_registry_at_all_keeps_the_old_reading(): + """The degraded path (tools/call before any listing, rebuild failed) is + where the strip removes all three names on a hunch. Handle extraction + follows the same hunch, so the two never disagree.""" + o = AgentCatOptions() + r = await resolve_handles({"session_id": sid("x")}, o, "proj", None, None, None) + assert (r.session_id, r.session_source) == (sid("x"), "supplied") + assert r.prompts_session_id is True + + +async def test_hook_mode_never_prompts_for_a_session_id(): + o = AgentCatOptions(resolve_session_id=lambda request, extra: "corr-1") + r = await resolve_handles({}, o, "proj_1", None, None, frozenset()) + assert r.hook_mode is True and r.prompts_session_id is False + + +async def test_agent_extraction_gated_on_option(): + on = AgentCatOptions(enable_agent_tracking=True) + r = await resolve_handles({"agent_id": " a|b|c "}, on, None, None, None) + assert (r.agent_id, r.agent_source) == ("a|b|c", "supplied") + off = AgentCatOptions() + r = await resolve_handles({"agent_id": "a|b|c"}, off, None, None, None) + assert r.agent_id is None + + +def test_mint_back_text_rules(): + minted = HandleResolution(session_id=sid("T"), session_source="minted") + assert build_mint_back_text(minted) == ( + "[MCP INSTRUCTIONS]: session_id issued.\n" + f" session_id={sid('T')} — required on every subsequent tool call\n" + "Without session_id, this server does not function as intended." + ) + assert build_mint_back_text(HandleResolution(sid("T"), "supplied")) is None + assert build_mint_back_text(HandleResolution(sid("T"), "minted", hook_mode=True)) is None # noqa: E501 + + +# TS handles.test.ts:91-118 — the text block is task-only; a supplied agent_id +# never appears in it (the agent is never minted, so there is nothing to announce). +def test_mint_back_text_ignores_a_supplied_agent(): + with_agent = HandleResolution( + sid("T"), "minted", agent_id=A, agent_source="supplied" + ) + text = build_mint_back_text(with_agent) + assert "agent_id" not in text + assert text == build_mint_back_text(HandleResolution(sid("T"), "minted")) + + +def test_structured_mint_back_omission_rules(): + both = HandleResolution(sid("T"), "supplied", agent_id="A", agent_source="supplied") + m = build_structured_mint_back(both) + assert m == { + "session_id": sid("T"), + "agent_id": "A", + "instructions": "[MCP INSTRUCTIONS]: session_id and agent_id confirmed. Keep sending these exact values on every call.", # noqa: E501 + } + hook_agent = HandleResolution( + sid("T"), "hook", agent_id="A", agent_source="supplied", hook_mode=True + ) + m = build_structured_mint_back(hook_agent) + assert "session_id" not in m and m["agent_id"] == "A" and "agent_id confirmed" in m["instructions"] # noqa: E501 + assert build_structured_mint_back(HandleResolution(sid("T"), "hook", hook_mode=True)) is None # noqa: E501 + minted = HandleResolution(sid("T"), "minted") + assert build_structured_mint_back(minted)["instructions"].startswith("[MCP INSTRUCTIONS]: session_id issued.") # noqa: E501 + + +# TS handles.test.ts:428-441 — a minted task with a supplied agent echoes both +# ids but keeps the issued (not confirmed) copy, and never claims to have +# issued an agent_id. +def test_structured_mint_back_minted_task_with_supplied_agent(): + m = build_structured_mint_back( + HandleResolution(sid("T"), "minted", agent_id=A, agent_source="supplied") + ) + assert m["session_id"] == sid("T") and m["agent_id"] == A + assert "session_id issued" in m["instructions"] + assert "agent_id issued" not in m["instructions"] + + +# TS handles.test.ts:458-469 — agent tracking off: task only, singular copy. +def test_structured_mint_back_task_only_uses_singular_confirmed_copy(): + m = build_structured_mint_back(HandleResolution(sid("T"), "supplied")) + assert m == { + "session_id": sid("T"), + "instructions": "[MCP INSTRUCTIONS]: session_id confirmed. Keep sending this exact value on every call.", # noqa: E501 + } + + +def test_mirror_rules(): + mint = {"session_id": sid("T"), "instructions": "i"} + assert mirror_into_structured_content(None, mint) is None + assert mirror_into_structured_content([1], mint) is None + assert mirror_into_structured_content({"_mcp_instructions": "customer"}, mint) is None # noqa: E501 + out = mirror_into_structured_content({"a": 1}, mint) + assert out == {"a": 1, "_mcp_instructions": mint} + + +# TS handles.test.ts:498-516 — customer objects are never mutated, and any +# non-plain-object structured content is left alone. +def test_mirror_never_mutates_and_skips_non_mappings(): + mint = {"session_id": sid("T"), "instructions": "i"} + sc = {"a": 1} + out = mirror_into_structured_content(sc, mint) + assert sc == {"a": 1} and out is not sc + assert mirror_into_structured_content("nope", mint) is None + assert mirror_into_structured_content(42, mint) is None + + +def test_tag_clamp(): + res = HandleResolution(sid("T"), "supplied", agent_id="a\r\nb" + "x" * 300, agent_source="supplied") # noqa: E501 + tags = build_handle_tags(res, protocol_version="2026-07-28", mrtr="continuation") + assert tags["agentcat_session_id_source"] == "supplied" + assert tags["agentcat_agent_id"].startswith("a b") and len(tags["agentcat_agent_id"]) == 200 # noqa: E501 + assert tags["agentcat_agent_id_source"] == "supplied" + assert tags["agentcat_protocol_version"] == "2026-07-28" + assert tags["agentcat_mrtr"] == "continuation" + # The protocol version is read off untrusted client meta and, like + # agent_id, is merged AFTER validate_tags — so nothing else bounds it. + hostile = build_handle_tags(res, protocol_version="2026\n" + "z" * 500) + assert len(hostile["agentcat_protocol_version"]) == 200 + assert "\n" not in hostile["agentcat_protocol_version"] + assert build_handle_tags(HandleResolution("s", "minted")) == {"agentcat_session_id_source": "minted"} # noqa: E501 + + +# TS handles.test.ts:174-240 — the full tag map for a normal agent_id, and the +# clamp/newline-strip applying to the tag copy only, never the resolution. +def test_tags_pass_a_normal_agent_id_through(): + res = HandleResolution(sid("T"), "supplied", agent_id=A, agent_source="supplied") + assert build_handle_tags(res, protocol_version="2026-07-28") == { + "agentcat_session_id_source": "supplied", + "agentcat_agent_id": A, + "agentcat_agent_id_source": "supplied", + "agentcat_protocol_version": "2026-07-28", + } + + +def test_tag_clamp_and_newline_strip_leave_the_resolution_verbatim(): + long_id = "a" * 500 + res = HandleResolution(sid("T"), "supplied", agent_id=long_id, agent_source="supplied") # noqa: E501 + assert build_handle_tags(res)["agentcat_agent_id"] == "a" * 200 + assert res.agent_id == long_id + + multiline = "line1\nline2\r\nline3" + res = HandleResolution(sid("T"), "supplied", agent_id=multiline, agent_source="supplied") # noqa: E501 + assert build_handle_tags(res)["agentcat_agent_id"] == "line1 line2 line3" + assert res.agent_id == multiline diff --git a/tests/test_identify_shape.py b/tests/test_identify_shape.py new file mode 100644 index 0000000..758ed44 --- /dev/null +++ b/tests/test_identify_shape.py @@ -0,0 +1,131 @@ +"""The object AgentCat hands the customer's hooks, pinned on every flavor. + +`identify`, `event_tags`, `event_properties` and `resolve_session_id` all receive +the same `(request, extra)` pair, and `request` is the tool call's **params** — +the model carrying `.name` and `.arguments` — never the enclosing JSON-RPC +request. That is the only shape all four adapters can produce: mcp 2.x hands +its handler `(ctx, params)` with no request object in scope, and community +FastMCP's `context.message` is params as well, so the official 1.x adapter +unwraps `request.params` to match. + +Why this module exists at all: `identify.py` swallows every exception a hook +raises, so a hook written against the WRONG shape does not fail — it silently +yields an anonymous event. The whole v2 branch shipped with `identify` +integration coverage on the legacy e2e suites only, and neither of those reads +the argument dict, so an adapter handing over a different object was invisible. +Here the hook indexes `request.arguments` on every shape a customer can hand +`track()`, and the assertion is on the published event, so a regression is a +failure rather than a `None`. +""" + +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.types import UserIdentity + +from .test_utils.flavors import flavors + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_identify_reads_the_arguments_off_the_request_it_is_given( + flavor, capture +): + """The README's own example, run against every server shape. + + A hook that reaches for `.name` / `.arguments` — one hop, not two — works + everywhere, and the actor it returns reaches the event. + """ + shapes: list = [] + + def identify(request, extra): + shapes.append(request) + return UserIdentity( + user_id=f"user-{request.arguments['text']}", + user_name=request.name, + user_data={"tool": request.name}, + ) + + built = flavor.build("identify-shape") + track(built.server, "proj_test", AgentCatOptions(identify=identify)) + + async with flavor.client(built.server) as client: + await flavor.list_tools(client) + result = await flavor.call(client, "echo", {"text": "hi"}) + + assert result.is_error is False + assert len(shapes) == 1 + # Params, not the enclosing request: a `.params` attribute here would mean + # this flavor hands over one more layer than the contract promises. + assert not hasattr(shapes[0], "params") + + assert len(capture) == 1 + event = capture[0] + assert event.identify_actor_given_id == "user-hi" + assert event.identify_actor_name == "echo" + assert event.identify_data == {"tool": "echo"} + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_every_customer_hook_receives_the_same_pair(flavor, capture): + """`identify`, `event_tags`, `event_properties` and `resolve_session_id` are + documented to share one signature — so they must share one object.""" + seen: dict[str, tuple] = {} + + def record(name): + def hook(request, extra): + seen[name] = (request, extra) + return None + + return hook + + def tags(request, extra): + seen["event_tags"] = (request, extra) + return {"tool": request.name} + + def properties(request, extra): + seen["event_properties"] = (request, extra) + return {"args": dict(request.arguments or {})} + + def resolve_session_id(request, extra): + seen["resolve_session_id"] = (request, extra) + return f"task-for-{request.name}" + + built = flavor.build("identify-shape") + track( + built.server, + "proj_test", + AgentCatOptions( + identify=record("identify"), + event_tags=tags, + event_properties=properties, + resolve_session_id=resolve_session_id, + ), + ) + + async with flavor.client(built.server) as client: + await flavor.list_tools(client) + await flavor.call(client, "echo", {"text": "hi"}) + + assert set(seen) == { + "identify", + "event_tags", + "event_properties", + "resolve_session_id", + } + pairs = list(seen.values()) + assert all(pair[0] is pairs[0][0] for pair in pairs) + assert all(pair[1] is pairs[0][1] for pair in pairs) + + assert len(capture) == 1 + assert capture[0].tags["tool"] == "echo" + assert capture[0].properties == {"args": {"text": "hi"}} diff --git a/tests/test_injection.py b/tests/test_injection.py new file mode 100644 index 0000000..c33d211 --- /dev/null +++ b/tests/test_injection.py @@ -0,0 +1,527 @@ +"""Pure injection pipeline: schema mutation, registries, argument stripping. + +The pipeline is deliberately pure — it takes the adapter's deep copies of the +customer's schemas, mutates them in place, and reports what it did through two +registries. Every assertion here is a wire-visible contract: what an MCP client +sees in tools/list, and what the customer's tool callback receives. +""" + +import copy + +import pytest + +from agentcat.modules import constants as c +from agentcat.modules.injection import ( + InjectionResult, + ToolSpec, + build_injected_schemas, + injected_parameter_names, + mcp_instructions_schema_property, + strip_injected_arguments, +) +from agentcat.types import AgentCatOptions + + +def spec(name="t", props=None, extra=None, out=None): + # props={} must mean "an empty properties bag", not "give me the default". + default = {"q": {"type": "string"}} + schema = {"type": "object", "properties": dict(default if props is None else props)} + schema.update(extra or {}) + return ToolSpec(name=name, input_schema=schema, output_schema=out) + + +# ── Brief cases ────────────────────────────────────────────────────────────── + + +def test_param_order_and_descriptions(): + s = spec() + r = build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + keys = list(s.input_schema["properties"]) + assert keys == ["q", "session_id", "agent_id", "context"] + props = s.input_schema["properties"] + assert props["session_id"]["description"] == c.SESSION_ID_PARAM_DESCRIPTION + assert props["agent_id"]["description"] == c.AGENT_ID_PARAM_DESCRIPTION + assert "session_id" not in s.input_schema.get("required", []) + assert "agent_id" in s.input_schema["required"] + assert r.injected_params["t"] == {"session_id", "agent_id", "context"} + + +def test_hook_mode_omits_session_id_and_switches_agent_copy(): + s = spec() + build_injected_schemas( + [s], + AgentCatOptions( + enable_agent_tracking=True, resolve_session_id=lambda q, e: "x" + ), + ) + props = s.input_schema["properties"] + assert "session_id" not in props + assert props["agent_id"]["description"] == c.AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE + + +def test_tracing_disabled_skips_handles_but_not_context(): + s = spec() + r = build_injected_schemas([s], AgentCatOptions(enable_tracing=False)) + assert set(s.input_schema["properties"]) == {"q", "context"} + assert r.injected_params["t"] == {"context"} + + +def test_additional_properties_false_removed(): + s = spec(extra={"additionalProperties": False}) + build_injected_schemas([s], AgentCatOptions()) + assert "additionalProperties" not in s.input_schema + + +def test_composed_schema_skipped_with_empty_registry_entry(): + s = ToolSpec(name="t", input_schema={"oneOf": [{"type": "object"}]}) + r = build_injected_schemas([s], AgentCatOptions()) + assert s.input_schema == {"oneOf": [{"type": "object"}]} + assert r.injected_params["t"] == set() + + +def test_collision_skips_that_param_only(): + s = spec(props={"session_id": {"type": "string", "description": "customer"}}) + r = build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + assert s.input_schema["properties"]["session_id"]["description"] == "customer" + assert r.injected_params["t"] == {"agent_id", "context"} + + +def test_get_more_tools_gets_handles_but_not_context(): + s = spec(name=c.GET_MORE_TOOLS_NAME, props={"context": {"type": "string"}}) + r = build_injected_schemas([s], AgentCatOptions()) + assert r.injected_params[c.GET_MORE_TOOLS_NAME] == {"session_id"} + + +def test_output_schema_extension_and_registry(): + s = spec(out={"type": "object", "properties": {"answer": {"type": "string"}}}) + r = build_injected_schemas([s], AgentCatOptions()) + prop = s.output_schema["properties"][c.MCP_INSTRUCTIONS_KEY] + assert prop["description"] == c.MCP_INSTRUCTIONS_FIELD_DESCRIPTION + task_prop = prop["properties"]["session_id"] + assert task_prop["description"] == c.MCP_INSTRUCTIONS_SESSION_ID_DESCRIPTION + # Default options are prompted mode with agent tracking off, so the copy + # never mentions an agent_id the agent was not asked for. + assert list(prop["properties"]) == ["session_id", "instructions"] + assert c.MCP_INSTRUCTIONS_KEY not in s.output_schema.get("required", []) + assert r.output_injected == {"t"} + s2 = spec(out={"oneOf": []}) + r2 = build_injected_schemas([s2], AgentCatOptions()) + assert r2.output_injected == set() + + +def test_determinism(): + def make(): + return [spec(), spec(name="u", extra={"additionalProperties": False})] + + a, b = make(), make() + ra = build_injected_schemas(a, AgentCatOptions(enable_agent_tracking=True)) + rb = build_injected_schemas(b, AgentCatOptions(enable_agent_tracking=True)) + assert ra == rb and [t.input_schema for t in a] == [t.input_schema for t in b] + + +def test_strip_registry_driven_and_heuristic(): + args = {"q": 1, "session_id": "s", "agent_id": "a", "context": "c"} + reg = {"t": {"session_id", "context"}} + out = strip_injected_arguments("t", args, reg) + assert out == {"q": 1, "agent_id": "a"} and args["session_id"] == "s" # clone + # Registry present but tool not in it: it was never advertised through the + # pipeline, so nothing was injected for it — strip nothing. + assert strip_injected_arguments("unknown", args, reg) == args + assert strip_injected_arguments("t", args, None) == {"q": 1} + gmt = {"context": "real", "session_id": "s"} + stripped = strip_injected_arguments(c.GET_MORE_TOOLS_NAME, gmt, None) + assert stripped == {"context": "real"} + + +# ── Ported from the TS SDK: required-array semantics ───────────────────────── +# src/tests/handle-injection.test.ts — "creates the required array when the +# schema has none", "does not duplicate agent_id in an existing required +# array", "leaves required untouched when the customer declares agent_id". + + +def test_required_list_preserved_when_appending_agent_id(): + s = spec(props={"text": {"type": "string"}}, extra={"required": ["text"]}) + build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + assert s.input_schema["required"] == ["text", "agent_id", "context"] + + +def test_required_is_created_for_the_params_that_need_it(): + with_agent = spec() + build_injected_schemas([with_agent], AgentCatOptions(enable_agent_tracking=True)) + assert with_agent.input_schema["required"] == ["agent_id", "context"] + + # session_id is the one injected param that is never required — omitting it + # is how an agent asks to be minted one — but context is, so a schema that + # declared no required array does grow one. + without_agent = spec() + build_injected_schemas([without_agent], AgentCatOptions()) + assert without_agent.input_schema["required"] == ["context"] + + # ...and with the context pass off there is nothing to require at all. + neither = spec() + build_injected_schemas([neither], AgentCatOptions(enable_tool_call_context=False)) + assert "required" not in neither.input_schema + + +def test_agent_id_not_duplicated_in_existing_required_array(): + # A schema can list a name in required without declaring the property; + # injection must not push a second copy. + s = spec(props={}, extra={"required": ["agent_id"]}) + build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + assert s.input_schema["required"] == ["agent_id", "context"] + + +def test_customer_declared_agent_id_leaves_required_untouched(): + s = spec( + props={"agent_id": {"type": "string", "description": "mine"}}, + extra={"required": []}, + ) + r = build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + # agent_id is theirs, so it is neither redescribed nor required by us. + # context is still ours, and still required. + assert s.input_schema["required"] == ["context"] + assert s.input_schema["properties"]["agent_id"]["description"] == "mine" + assert "agent_id" not in r.injected_params["t"] + + +def test_empty_properties_tool_receives_all_params(): + s = spec(props={}) + r = build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + assert list(s.input_schema["properties"]) == ["session_id", "agent_id", "context"] + assert r.injected_params["t"] == {"session_id", "agent_id", "context"} + + +# ── Ported: additionalProperties variants ──────────────────────────────────── +# Only the `false` form blocks optional handles; every other form is the +# customer's business and must survive untouched. + + +def test_additional_properties_true_and_dict_forms_untouched(): + permissive = spec(name="p", extra={"additionalProperties": True}) + schema_form = spec(name="s", extra={"additionalProperties": {"type": "string"}}) + build_injected_schemas([permissive, schema_form], AgentCatOptions()) + assert permissive.input_schema["additionalProperties"] is True + assert schema_form.input_schema["additionalProperties"] == {"type": "string"} + + +# ── Ported: deep-copy isolation ────────────────────────────────────────────── +# The adapter hands the pipeline deep copies and the pipeline mutates them in +# place, so nested customer structures must come out byte-identical and the +# minted _mcp_instructions fragment must never be shared between tools. + + +def test_nested_customer_schema_is_not_mutated(): + nested = { + "type": "object", + "properties": { + "filter": { + "type": "object", + "properties": {"tags": {"type": "array", "items": {"type": "string"}}}, + "required": ["tags"], + } + }, + } + original = copy.deepcopy(nested["properties"]["filter"]) + s = ToolSpec(name="t", input_schema=nested) + build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + assert s.input_schema["properties"]["filter"] == original + + +def test_pipeline_mutates_in_place_rather_than_replacing_schemas(): + s = spec() + schema_ref = s.input_schema + build_injected_schemas([s], AgentCatOptions()) + assert s.input_schema is schema_ref + + +def test_mcp_instructions_fragment_is_not_shared_between_tools(): + a = spec(name="a", out={"type": "object", "properties": {}}) + b = spec(name="b", out={"type": "object", "properties": {}}) + build_injected_schemas([a, b], AgentCatOptions()) + frag_a = a.output_schema["properties"][c.MCP_INSTRUCTIONS_KEY] + frag_b = b.output_schema["properties"][c.MCP_INSTRUCTIONS_KEY] + assert frag_a == frag_b + frag_a["properties"]["session_id"]["description"] = "mutated" + assert frag_b["properties"]["session_id"]["description"] != "mutated" + + +def test_mcp_instructions_schema_property_shape(): + frag = mcp_instructions_schema_property(True, True) + assert frag["type"] == "object" + assert frag["description"] == c.MCP_INSTRUCTIONS_FIELD_DESCRIPTION + assert list(frag["properties"]) == ["session_id", "agent_id", "instructions"] + task_prop = frag["properties"]["session_id"] + assert task_prop["description"] == c.MCP_INSTRUCTIONS_SESSION_ID_DESCRIPTION + agent_prop = frag["properties"]["agent_id"] + assert agent_prop["description"] == c.MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION + assert frag["properties"]["instructions"] == {"type": "string"} + assert mcp_instructions_schema_property(True, True) is not frag + + +def test_mcp_instructions_schema_property_tracks_the_flags(): + # The copy never references a parameter the agent cannot see, so each + # sub-property is gated by the handle that produced it. `instructions` is + # unconditional. + prompted_only = mcp_instructions_schema_property(True, False) + assert list(prompted_only["properties"]) == ["session_id", "instructions"] + hook_only = mcp_instructions_schema_property(False, True) + assert list(hook_only["properties"]) == ["agent_id", "instructions"] + + +# ── Ported: registry completeness & injection order ────────────────────────── + + +def test_registry_has_an_entry_for_every_tool(): + plain = spec(name="plain") + composed = ToolSpec(name="composed", input_schema={"allOf": [{"type": "object"}]}) + owns_all = spec( + name="owns_all", + props={ + "session_id": {"type": "string"}, + "agent_id": {"type": "string"}, + "context": {"type": "string"}, + }, + ) + r = build_injected_schemas( + [plain, composed, owns_all], AgentCatOptions(enable_agent_tracking=True) + ) + assert set(r.injected_params) == {"plain", "composed", "owns_all"} + assert r.injected_params["composed"] == set() + assert r.injected_params["owns_all"] == set() + + +def test_context_disabled_leaves_only_handles(): + s = spec() + r = build_injected_schemas( + [s], + AgentCatOptions(enable_agent_tracking=True, enable_tool_call_context=False), + ) + assert list(s.input_schema["properties"]) == ["q", "session_id", "agent_id"] + assert r.injected_params["t"] == {"session_id", "agent_id"} + + +def test_context_uses_custom_description(): + s = spec() + build_injected_schemas([s], AgentCatOptions(custom_context_description="why?")) + assert s.input_schema["properties"]["context"]["description"] == "why?" + + +def test_get_more_tools_keeps_bespoke_context_and_gains_both_handles(): + s = spec( + name=c.GET_MORE_TOOLS_NAME, + props={"context": {"type": "string", "description": "bespoke"}}, + extra={"required": ["context"]}, + ) + r = build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + props = s.input_schema["properties"] + assert list(props) == ["context", "session_id", "agent_id"] + assert props["context"]["description"] == "bespoke" + assert r.injected_params[c.GET_MORE_TOOLS_NAME] == {"session_id", "agent_id"} + + +# ── Ported: outputSchema edges ─────────────────────────────────────────────── +# src/tests/handle-injection.test.ts "outputSchema injection" + v2 +# schema-edges.test.ts "outputSchema injection". + + +def test_output_schema_contract_otherwise_untouched(): + out = { + "type": "object", + "properties": {"count": {"type": "number"}}, + "required": ["count"], + "additionalProperties": False, + } + s = spec(out=out) + build_injected_schemas([s], AgentCatOptions()) + # additionalProperties: false stays on the output side — our property is + # declared, so it does not need loosening. + assert s.output_schema["additionalProperties"] is False + assert s.output_schema["required"] == ["count"] + assert s.output_schema["properties"]["count"] == {"type": "number"} + + +def test_customer_declared_mcp_instructions_output_never_clobbered(): + out = { + "type": "object", + "properties": { + c.MCP_INSTRUCTIONS_KEY: {"type": "string", "description": "customer-owned"} + }, + } + s = spec(out=out) + r = build_injected_schemas([s], AgentCatOptions()) + prop = s.output_schema["properties"][c.MCP_INSTRUCTIONS_KEY] + assert prop == {"type": "string", "description": "customer-owned"} + assert r.output_injected == set() + + +def test_no_output_schema_registers_nothing(): + s = spec() + r = build_injected_schemas([s], AgentCatOptions()) + assert s.output_schema is None + assert r.output_injected == set() + + +def test_output_schema_without_properties_bag_gets_one_created(): + # A declared-but-bare object schema is still a single extendable bag; + # the pipeline mints `properties` rather than skipping the tool. + s = spec(out={"type": "object"}) + r = build_injected_schemas([s], AgentCatOptions()) + assert list(s.output_schema["properties"]) == [c.MCP_INSTRUCTIONS_KEY] + assert r.output_injected == {"t"} + + +def test_composed_input_schema_skips_output_injection_too(): + out = {"type": "object", "properties": {"count": {"type": "number"}}} + s = ToolSpec( + name="mixed", + input_schema={"anyOf": [{"type": "object"}]}, + output_schema=out, + ) + r = build_injected_schemas([s], AgentCatOptions()) + assert c.MCP_INSTRUCTIONS_KEY not in s.output_schema["properties"] + assert r.output_injected == set() + assert r.injected_params["mixed"] == set() + + +# ── Handle-pass gating ─────────────────────────────────────────────────────── +# handle-injection.ts:59 returns early unless at least one handle is +# injectable, and listWrap.ts:50-62 computes the two flags as +# inject_session_id = enable_tracing and resolve_session_id is None +# inject_agent_id = enable_tracing and enable_agent_tracking +# The output-schema extension lives inside that pass, so it is gated too. +# Context injection is a separate pass and runs regardless. + + +def _out(): + return {"type": "object", "properties": {"count": {"type": "number"}}} + + +def test_tracing_disabled_leaves_output_schemas_untouched(): + s = spec(out=_out()) + r = build_injected_schemas([s], AgentCatOptions(enable_tracing=False)) + assert s.output_schema == _out() + assert r.output_injected == set() + assert r.injected_params["t"] == {"context"} + + +def test_hook_mode_without_agent_tracking_skips_the_whole_handle_pass(): + s = spec(out=_out()) + r = build_injected_schemas( + [s], AgentCatOptions(resolve_session_id=lambda q, e: "x") + ) + assert set(s.input_schema["properties"]) == {"q", "context"} + assert s.output_schema == _out() + assert r.output_injected == set() + assert r.injected_params["t"] == {"context"} + + +def test_no_injectable_handle_and_no_context_leaves_an_empty_registry_entry(): + s = spec(out=_out()) + r = build_injected_schemas( + [s], AgentCatOptions(enable_tracing=False, enable_tool_call_context=False) + ) + assert set(s.input_schema["properties"]) == {"q"} + assert r.injected_params["t"] == set() + assert r.output_injected == set() + + +def test_hook_mode_with_agent_tracking_extends_output_without_session_id(): + s = spec(out=_out()) + r = build_injected_schemas( + [s], + AgentCatOptions( + enable_agent_tracking=True, resolve_session_id=lambda q, e: "x" + ), + ) + frag = s.output_schema["properties"][c.MCP_INSTRUCTIONS_KEY] + assert list(frag["properties"]) == ["agent_id", "instructions"] + assert r.output_injected == {"t"} + + +def test_prompted_mode_with_agent_tracking_extends_output_with_both(): + s = spec(out=_out()) + build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + frag = s.output_schema["properties"][c.MCP_INSTRUCTIONS_KEY] + assert list(frag["properties"]) == ["session_id", "agent_id", "instructions"] + + +# ── Input-schema normalization ─────────────────────────────────────────────── +# handle-injection.ts:82-89 — an absent schema becomes a bare object schema, +# and an existing schema missing its properties bag has one created. + + +def test_empty_input_schema_is_normalized_before_injection(): + s = ToolSpec(name="t", input_schema={}) + build_injected_schemas([s], AgentCatOptions()) + assert s.input_schema["type"] == "object" + assert list(s.input_schema["properties"]) == ["session_id", "context"] + assert s.input_schema["required"] == ["context"] + + +def test_input_schema_without_properties_bag_gets_one_created(): + s = ToolSpec(name="t", input_schema={"type": "object", "title": "Bare"}) + r = build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) + assert list(s.input_schema["properties"]) == ["session_id", "agent_id", "context"] + assert s.input_schema["title"] == "Bare" + assert r.injected_params["t"] == {"session_id", "agent_id", "context"} + + +# ── Ported: strip semantics ────────────────────────────────────────────────── + + +def test_strip_preserves_a_customer_owned_session_id(): + # The registry records only what the pipeline injected, so a tool that + # declares its own session_id keeps the caller's value. + reg = {"deploy": {"agent_id", "context"}} + args = {"session_id": "prod-42", "agent_id": "agt_1", "context": "why"} + assert strip_injected_arguments("deploy", args, reg) == {"session_id": "prod-42"} + + +def test_injected_names_is_the_single_source_the_strip_reads(): + """The strip and the handle extraction MUST agree, so they read one + function. A name this does not report is the customer's parameter: it stays + in their arguments and it is not ours to read as a handle.""" + reg = {"deploy": {"agent_id", "context"}, "t": {"session_id", "context"}} + assert injected_parameter_names("deploy", reg) == frozenset({"agent_id", "context"}) + assert injected_parameter_names("t", reg) == frozenset({"session_id", "context"}) + # Registry present, tool absent: never advertised through the pipeline. + assert injected_parameter_names("unknown", reg) == frozenset() + # No registry at all (rebuild failed): the heuristic, which the strip + # follows too — so the two stay consistent even on the degraded path. + assert injected_parameter_names("t", None) == frozenset( + {"session_id", "agent_id", "context"} + ) + assert injected_parameter_names(c.GET_MORE_TOOLS_NAME, None) == frozenset( + {"session_id", "agent_id"} + ) + + +@pytest.mark.parametrize( + "registry", + [{"deploy": {"agent_id", "context"}}, {"deploy": set()}, {}, None], + ids=["own-task-id", "nothing-injected", "unlisted", "no-registry"], +) +def test_what_the_strip_removes_is_what_the_names_report(registry): + args = {"session_id": "prod-42", "agent_id": "agt_1", "context": "why", "q": 1} + names = injected_parameter_names("deploy", registry) + stripped = strip_injected_arguments("deploy", args, registry) + assert set(args) - set(stripped) == names & set(args) + + +def test_strip_always_returns_a_new_dict(): + args = {"q": 1} + for registry in ({"t": set()}, None, {}): + out = strip_injected_arguments("t", args, registry) + assert out is not args + assert strip_injected_arguments("t", {}, None) == {} + + +def test_strip_heuristic_leaves_unrelated_arguments_alone(): + args = {"text": "x", "session_id": "a", "agent_id": "b", "context": "c", "id": 7} + assert strip_injected_arguments("any", args, None) == {"text": "x", "id": 7} + + +def test_injection_result_equality_is_value_based(): + a = InjectionResult(injected_params={"t": {"context"}}, output_injected=set()) + b = InjectionResult(injected_params={"t": {"context"}}, output_injected=set()) + assert a == b diff --git a/tests/test_inner_tap.py b/tests/test_inner_tap.py new file mode 100644 index 0000000..fcc11dc --- /dev/null +++ b/tests/test_inner_tap.py @@ -0,0 +1,1303 @@ +"""The inner tap: one contract, proven on every server generation. + +v2 intercepts at the protocol boundary, where most SDK generations have already +caught the customer's exception and flattened it into an `isError` result. The +tap is what puts the type, the traceback and the `__cause__` chain back on the +event. This module proves three things: + +- **the contract** — `inner_tap()` opens a slot, `capture()` fills it, the slot + closes on every exit path, and `error()` falls back to the flattened result + when nothing local ever raised; +- **the concurrency argument** — parallel calls cannot read each other's + exception, and the proof is structural rather than a lucky single run; +- **per-era placement** — official FastMCP v1, bare lowlevel v1, MCPServer, + bare lowlevel v2 and both community FastMCP eras each recover the detail, + and the customer's wire result is what an untracked server returns. + +Both eras live here on purpose: splitting the file across the two +conftest-gated trees would hide the parity it exists to show. The era classes +carry `LEGACY_ONLY` / `MODERN_ONLY`; the community class runs on both, because +`--extra community` installs FastMCP 3 beside mcp 1.x and FastMCP 4 beside +mcp 2.x. +""" + +import asyncio +import contextlib + +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.modules.adapters._inner_tap import ( + _open_cell, + capture, + capture_in_flight, + inner_tap, + probing, + tap_method, + tapped, +) + +from .test_utils import LEGACY_ONLY, MODERN_ONLY + +try: + import fastmcp # noqa: F401 + + HAS_COMMUNITY = True +except ImportError: # pragma: no cover - community extra not installed + HAS_COMMUNITY = False + + +class Boom(Exception): + """Raised only by this module's tools, so a frame for it is unambiguous.""" + + +@pytest.fixture +def events(monkeypatch): + """Every event the queue is handed, without touching the network.""" + collected: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", collected.append) + return collected + + +def _call_events(events, name): + return [ + e + for e in events + if e.event_type == "mcp:tools/call" and e.resource_name == name + ] + + +def _one(events, name): + matched = _call_events(events, name) + assert len(matched) == 1, f"expected one {name} event, got {len(matched)}" + return matched[0] + + +def _frames_for(error, function): + return [f for f in error.get("frames", []) if f["function"] == function] + + +def _chained_frames_for(error, function): + return [ + f + for chained in error.get("chained_errors", []) + for f in chained.get("frames", []) + if f["function"] == function + ] + + +class Barrier: + """Holds every concurrent tool body until all of them have arrived. + + So the per-era parallel tests stress the window they claim to: every call + is provably inside its own capture slot, at the same time, before any of + them fails. + """ + + def __init__(self, total: int) -> None: + self.total = total + self.arrived = 0 + self.open = asyncio.Event() + self.slots: list = [] + + async def wait(self) -> None: + # Recorded from inside the customer's tool body, which is where the + # adapter's slot is open. The cell OBJECT, not a marker derived from + # it: this is the structural claim the concurrency argument rests on. + self.slots.append(_open_cell.get()) + self.arrived += 1 + if self.arrived == self.total: + self.open.set() + await self.open.wait() + + def assert_every_call_had_its_own_slot(self) -> None: + assert None not in self.slots, "no capture slot was open in the tool body" + assert len(self.slots) == self.total + # The discriminating assertion. A module-global "last error" slot, or + # a slot hoisted out of the per-call path to install time, gives every + # concurrent call the SAME object here — and both would still pass an + # assertion that only checks each event's own marker, because the + # adapter path has no `await` between the capture and the read. + assert len({id(slot) for slot in self.slots}) == self.total, ( + "concurrent calls shared one capture slot" + ) + + +# ── the contract ───────────────────────────────────────────────────────────── + + +class TestTapContract: + """What the tap promises, independent of any server.""" + + def test_a_capture_with_no_slot_open_is_a_no_op(self): + # A tap left armed on a server whose call is not being traced must not + # raise into the customer's process, and must not stash anything that + # a later call could pick up. + capture(Boom("nobody asked for this")) + with inner_tap() as tap: + assert tap.captured is None + + def test_the_last_write_wins(self): + # A tool that composes another tool sees the sub-call's failure first + # and its own second. The event has to describe the one the agent was + # told about, which is always the last one to unwind. + with inner_tap() as tap: + capture(Boom("a sub-call the tool handled")) + capture(RuntimeError("the tool's own failure")) + assert isinstance(tap.captured, RuntimeError) + + def test_the_slot_closes_on_the_error_path(self): + with contextlib.suppress(Boom): + with inner_tap(): + capture(Boom("this call failed")) + raise Boom("this call failed") + with inner_tap() as tap: + assert tap.captured is None + + def test_a_nested_slot_hands_the_outer_one_back(self): + # A tool that calls its own server re-enters the adapter. The inner + # call takes the slot and gives it back, so the outer call still + # records its own failure rather than the inner one's. + with inner_tap() as outer: + with inner_tap() as inner: + capture(Boom("inner call")) + assert isinstance(inner.captured, Boom) + assert outer.captured is None + capture(RuntimeError("outer call")) + assert isinstance(outer.captured, RuntimeError) + + def test_capture_in_flight_records_the_live_exception(self): + with inner_tap() as tap: + try: + raise Boom("caught by the SDK") + except Boom: + capture_in_flight("caught by the SDK") + assert isinstance(tap.captured, Boom) + + def test_capture_in_flight_ignores_a_message_the_sdk_composed(self): + # The lowlevel v1 SDK reaches the same factory for a schema-validation + # failure, handing it a sentence of its own rather than the exception's + # message. Recording there would replace the one-line text the agent saw + # with a multi-line jsonschema dump. + composed = "Input validation error: 'x' is not of type 'integer'" + with inner_tap() as tap: + try: + raise Boom("'x' is not of type 'integer'\n\nOn instance…") + except Boom: + capture_in_flight(composed) + assert tap.captured is None + + def test_capture_in_flight_ignores_a_failure_that_predates_the_slot(self): + # `sys.exc_info` answers for the whole stack, and the lowlevel v1 SDK + # calls its error-result factory outside any `except` too (a bad return + # type). An older frame's exception is not this call's failure. + try: + raise RuntimeError("someone else's failure") + except RuntimeError: + with inner_tap() as tap: + capture_in_flight("someone else's failure") + assert tap.captured is None + + def test_error_uses_the_tapped_exception_when_there_is_one(self): + with inner_tap() as tap: + try: + raise Boom("the real failure") + except Boom as exc: + capture(exc) + payload = tap.error("the flattened message") + assert payload["type"] == "Boom" + assert payload["message"] == "the real failure" + assert payload["frames"] + assert payload["platform"] == "python" + + def test_error_falls_back_when_nothing_local_ever_raised(self): + # A proxy passing an upstream error through, or a tool that simply + # returned is_error: there is no local exception and never will be. + with inner_tap() as tap: + payload = tap.error("upstream said no") + assert payload == { + "message": "upstream said no", + "type": None, + "platform": "python", + } + + @pytest.mark.asyncio + async def test_the_wrapping_form_re_raises_the_very_same_exception(self): + """The tap observes. It must not swallow, replace or delay.""" + raised = Boom("the customer's own failure") + + async def fails(*args, **kwargs): + raise raised + + wrapped = tapped(fails) + with inner_tap() as tap: + with pytest.raises(Boom) as caught: + await wrapped("arg", keyword="value") + assert caught.value is raised + assert tap.captured is raised + + @pytest.mark.asyncio + async def test_the_wrapping_form_returns_the_originals_own_result(self): + sentinel = object() + + async def succeeds(*args, **kwargs): + return sentinel + + assert await tapped(succeeds)() is sentinel + + def test_the_probing_form_returns_the_originals_own_result(self): + sentinel = object() + probe = probing(lambda message: sentinel) + with inner_tap() as tap: + try: + raise Boom("the SDK is converting this right now") + except Boom: + assert probe("the SDK is converting this right now") is sentinel + assert isinstance(tap.captured, Boom) + + def test_the_probing_form_survives_a_call_shape_it_does_not_know(self): + # A capture is what an unrecognized call costs — never the customer's + # error path. + sentinel = object() + probe = probing(lambda **kwargs: sentinel) + with inner_tap() as tap: + try: + raise Boom("live") + except Boom: + assert probe(some_future_kwarg="live") is sentinel + assert tap.captured is None + + def test_a_tap_that_cannot_be_installed_degrades_rather_than_raises(self): + class ReadOnly: + async def call_tool(self): # pragma: no cover - never called + return None + + def __setattr__(self, name, value): + raise AttributeError("this server refuses attributes") + + state: dict = {} + assert tap_method(ReadOnly(), "call_tool", state, "call_tool") is False + assert tap_method(object(), "no_such_method", state, "missing") is False + assert state == {} + + def test_a_synchronous_seam_is_refused_rather_than_broken(self): + """`tapped` awaits what it wraps; a sync override would break every call.""" + + class SyncOverride: + def call_tool(self, name, arguments): # pragma: no cover - never called + return None + + server = SyncOverride() + state: dict = {} + assert tap_method(server, "call_tool", state, "call_tool") is False + assert state == {} + # The customer's own method is exactly where it was. + assert server.call_tool.__func__ is SyncOverride.call_tool + + @pytest.mark.asyncio + async def test_a_capture_a_seam_handled_itself_is_discarded(self): + """A sub-call the caller suppressed did not produce the agent's result.""" + + async def fails(*args, **kwargs): + raise Boom("the sub-call") + + sub_call = tapped(fails) + + async def caller(*args, **kwargs): + with contextlib.suppress(Boom): + await sub_call() + return "answered anyway" + + with inner_tap() as tap: + assert await tapped(caller)() == "answered anyway" + assert tap.captured is None + + @pytest.mark.asyncio + async def test_a_capture_the_seam_re_raised_is_kept(self): + """The community shape: a layer below converts a real failure.""" + + async def fails(*args, **kwargs): + raise Boom("the tool") + + seam = tapped(fails) + with inner_tap() as tap: + with contextlib.suppress(Boom): + await seam() + assert isinstance(tap.captured, Boom) + + @pytest.mark.asyncio + async def test_a_sub_call_in_flight_cannot_erase_an_escaping_capture(self): + """A concurrent sub-call is not "the seam that handled it". + + "Did this failure escape?" is answered per SEAM, not per nesting + level: a seam's normal return drops only what was recorded inside its + own dynamic extent. It used to be answered by a depth counter kept on + the cell — and the cell is shared by every task that inherits it, so a + sub-call the tool left running inflated the count, and then erased a + genuine capture on its own normal return. The failure the agent was + told about would have been published as the no-tap payload. + """ + sub_call_is_inside = asyncio.Event() + let_the_sub_call_finish = asyncio.Event() + + async def fails(*args, **kwargs): + raise Boom("the tool") + + async def sub_call(*args, **kwargs): + sub_call_is_inside.set() + await let_the_sub_call_finish.wait() + return "the sub-call finished" + + failing_seam = tapped(fails) + other_seam = tapped(sub_call) + + with inner_tap() as tap: + # A task the tool spawned: it inherits this call's slot. + spawned = asyncio.create_task(other_seam()) + await sub_call_is_inside.wait() + + with contextlib.suppress(Boom): + await failing_seam() + assert isinstance(tap.captured, Boom) + + # The layer below AgentCat awaits while converting the raise into + # an `is_error` result, and the sub-call lands in that window. + let_the_sub_call_finish.set() + await spawned + assert isinstance(tap.captured, Boom), ( + "a concurrent sub-call's normal return erased the tool's failure" + ) + + +# ── the concurrency argument ───────────────────────────────────────────────── + + +class TestTapIsolation: + """Cross-attribution has to be impossible, not merely absent in one run.""" + + @pytest.mark.asyncio + async def test_parallel_calls_cannot_read_each_others_exception(self): + """Eight calls, all inside their slot at once, capturing out of order. + + A module-global "last error" slot passes a sequential test and fails + this one: every call is provably inside its own slot before any of them + captures, and they capture in reverse order, so a shared slot would + hand call 0 call 7's exception. + """ + total = 8 + arrived = 0 + all_inside = asyncio.Event() + seen: dict[int, str] = {} + + async def one_call(index: int) -> None: + nonlocal arrived + with inner_tap() as tap: + arrived += 1 + if arrived == total: + all_inside.set() + await all_inside.wait() + # Every sibling's slot is open right now. + assert tap.captured is None + # Reverse order, with a yield between each, so the captures + # interleave with every other call's read. + await asyncio.sleep(0.001 * (total - index)) + capture(Boom(f"call-{index}")) + await asyncio.sleep(0.02) + seen[index] = str(tap.captured) + + await asyncio.wait_for( + asyncio.gather(*(one_call(i) for i in range(total))), timeout=10 + ) + assert seen == {i: f"call-{i}" for i in range(total)} + + @pytest.mark.asyncio + async def test_a_capture_from_a_child_task_reaches_the_caller(self): + """The reason the slot is an object and not a ContextVar of exceptions. + + A `ContextVar.set()` inside a child task is invisible to the parent — + which is what the retired `store_captured_error` did. Writing to the + cell the parent holds is visible, and both FastMCP generations reach + the tap through a child of the request task. + """ + + async def child() -> None: + capture(Boom("raised below a task boundary")) + + with inner_tap() as tap: + await asyncio.create_task(child()) + assert isinstance(tap.captured, Boom) + + @pytest.mark.asyncio + async def test_a_capture_from_a_worker_thread_reaches_the_caller(self): + # How every SDK generation runs a synchronous tool body. + with inner_tap() as tap: + await asyncio.to_thread(capture, Boom("raised in a worker thread")) + assert isinstance(tap.captured, Boom) + + +# ── official MCP SDK 1.x ───────────────────────────────────────────────────── + + +def _bare_v1_server(name="bare-v1"): + """A lowlevel v1 `Server` whose own handler raises.""" + import mcp.types as types + from mcp.server.lowlevel import Server + + server = Server(name) + + @server.list_tools() + async def list_tools(): + return [ + types.Tool( + name="boom", + description="raises", + inputSchema={ + "type": "object", + "properties": {"marker": {"type": "string"}}, + }, + ) + ] + + @server.call_tool() + async def call_tool(tool: str, arguments: dict): + raise Boom(f"bare kaboom {arguments.get('marker')}") + + return server + + +@LEGACY_ONLY +class TestOfficialV1: + """Official FastMCP v1 and the bare lowlevel `Server` behind it.""" + + @pytest.mark.asyncio + async def test_fastmcp_v1_publishes_the_tool_error_and_its_cause(self, events): + from .test_utils.client import create_test_client + from .test_utils.todo_server import create_todo_server + + server = create_todo_server() + track(server, "test_project", AgentCatOptions()) + + async with create_test_client(server) as client: + result = await client.call_tool( + "tool_that_raises", {"error_type": "value"} + ) + + assert result.isError is True + error = _one(events, "tool_that_raises").error + # FastMCP wraps a failing tool before the lowlevel SDK flattens it, so + # the recorded type is the wrapper and the customer's own exception is + # the cause — the same shape the community adapter has always had. + assert error["type"] == "ToolError" + assert "Test value error from tool" in error["message"] + assert error["stack"] + assert error["frames"] + cause = error["chained_errors"][0] + assert cause["type"] == "ValueError" + assert cause["message"] == "Test value error from tool" + tool_frames = _chained_frames_for(error, "tool_that_raises") + assert tool_frames, "the customer's own tool is missing from the traceback" + assert tool_frames[0]["in_app"] is True + assert "Test value error from tool" in tool_frames[0]["context_line"] + + @pytest.mark.asyncio + async def test_bare_lowlevel_v1_publishes_the_handlers_own_exception( + self, events + ): + from .test_utils.client import create_test_client + + server = _bare_v1_server() + track(server, "test_project", AgentCatOptions()) + + async with create_test_client(server) as client: + result = await client.call_tool("boom", {"marker": "one"}) + + assert result.isError is True + error = _one(events, "boom").error + # No tool manager in the way: the handler's exception IS the failure. + assert error["type"] == "Boom" + assert error["message"] == "bare kaboom one" + handler_frames = _frames_for(error, "call_tool") + assert handler_frames and handler_frames[0]["in_app"] is True + assert "raise Boom" in handler_frames[0]["context_line"] + + @pytest.mark.asyncio + async def test_the_wire_error_is_what_an_untracked_server_returns(self, events): + from .test_utils.client import create_test_client + from .test_utils.todo_server import create_todo_server + + async def call(server): + async with create_test_client(server) as client: + return await client.call_tool( + "tool_that_raises", {"error_type": "runtime"} + ) + + untracked = await call(create_todo_server()) + tracked_server = create_todo_server() + track(tracked_server, "test_project", AgentCatOptions()) + tracked = await call(tracked_server) + + assert tracked.isError == untracked.isError is True + # The SDK's own error block, byte for byte. (A tracked result also + # carries AgentCat's task mint-back, which is v2 behavior the tap + # neither adds to nor removes from.) + assert tracked.content[0].model_dump() == untracked.content[0].model_dump() + # Positive control. Everything above is an equality between two runs, + # so it passes just as well when track() is a no-op — verified by + # reducing track() to `return server`, which leaves the assertions + # above green and fails the two below. + assert _call_events(events, "tool_that_raises") + assert len(tracked.content) > len(untracked.content) + + @pytest.mark.asyncio + async def test_parallel_failures_each_get_their_own_slot(self, events): + from .test_utils.client import create_test_client + from .test_utils.todo_server import create_todo_server + + total = 6 + barrier = Barrier(total) + server = create_todo_server() + + @server.tool() + async def boom(marker: str) -> str: + """Raises once every parallel call is inside it.""" + await barrier.wait() + raise Boom(f"kaboom {marker}") + + track(server, "test_project", AgentCatOptions()) + + async with create_test_client(server) as client: + await asyncio.wait_for( + asyncio.gather( + *( + client.call_tool("boom", {"marker": f"m{i}"}) + for i in range(total) + ) + ), + timeout=20, + ) + + barrier.assert_every_call_had_its_own_slot() + published = _call_events(events, "boom") + assert len(published) == total + for event in published: + marker = event.parameters["arguments"]["marker"] + cause = event.error["chained_errors"][0] + assert cause["message"] == f"kaboom {marker}" + + @pytest.mark.asyncio + async def test_a_tool_that_composes_a_tool_publishes_its_own_failure( + self, events + ): + """The caller handles a sub-call's failure, then fails on its own. + + The event must describe what the agent was told, not the failure the + caller dealt with. Keeping the FIRST capture published the sub-call's. + """ + from .test_utils.client import create_test_client + from .test_utils.todo_server import create_todo_server + + server = create_todo_server() + + @server.tool() + async def inner(marker: str) -> str: + """Always fails.""" + raise Boom(f"INNER {marker}") + + @server.tool() + async def outer(marker: str) -> str: + """Handles inner's failure, then fails on its own.""" + with contextlib.suppress(Exception): + await server._tool_manager.call_tool("inner", {"marker": marker}) + raise Boom(f"OUTER {marker}") + + track(server, "test_project", AgentCatOptions()) + + async with create_test_client(server) as client: + result = await client.call_tool("outer", {"marker": "one"}) + + wire = "".join(c.text for c in result.content if hasattr(c, "text")) + assert "OUTER one" in wire and "INNER one" not in wire + error = _one(events, "outer").error + assert "OUTER one" in error["message"] + assert "INNER one" not in error["message"] + assert error["chained_errors"][0]["message"] == "OUTER one" + + @pytest.mark.asyncio + async def test_a_handled_sub_call_is_not_published_as_the_result(self, events): + """The caller handles a sub-call's failure and answers with its own error. + + Nothing the agent sees came from a Python exception, so the surfaced + message is the whole payload — the sub-call's stack must not be it. + """ + from mcp.types import CallToolResult, TextContent + + from .test_utils.client import create_test_client + from .test_utils.todo_server import create_todo_server + + server = create_todo_server() + + @server.tool() + async def inner(marker: str) -> str: + """Always fails.""" + raise Boom(f"INNER {marker}") + + @server.tool() + async def outer(marker: str) -> CallToolResult: + """Handles inner's failure and reports its own error result.""" + with contextlib.suppress(Exception): + await server._tool_manager.call_tool("inner", {"marker": marker}) + return CallToolResult( + content=[TextContent(type="text", text=f"OUTER declined {marker}")], + isError=True, + ) + + track(server, "test_project", AgentCatOptions()) + + async with create_test_client(server) as client: + result = await client.call_tool("outer", {"marker": "one"}) + + assert result.isError is True + error = _one(events, "outer").error + assert error == { + "message": "OUTER declined one", + "type": None, + "platform": "python", + } + + @pytest.mark.asyncio + async def test_a_schema_validation_failure_keeps_the_surfaced_message( + self, events + ): + """The lowlevel SDK composes that message itself; the probe skips it.""" + from .test_utils.client import create_test_client + + server = _bare_v1_server("validating-v1") + track(server, "test_project", AgentCatOptions()) + + async with create_test_client(server) as client: + await client.list_tools() + result = await client.call_tool("boom", {"marker": 123}) + + assert result.isError is True + # content[0] is the SDK's own error block; anything after it is + # AgentCat's task mint-back, which every v2 result carries. + surfaced = result.content[0].text + assert surfaced.startswith("Input validation error:") + error = _one(events, "boom").error + assert error == {"message": surfaced, "type": None, "platform": "python"} + + +# ── official MCP SDK 2.x ───────────────────────────────────────────────────── + + +def _mcpserver_with_a_raising_tool(name="boom-mcpserver"): + from mcp.server.mcpserver import MCPServer + + server = MCPServer(name) + + @server.tool() + def boom(marker: str) -> str: + """Raises.""" + raise Boom(f"kaboom {marker}") + + return server + + +def _bare_v2_server(name="bare-v2"): + from mcp import types + from mcp.server import Server + + async def on_list_tools(ctx, params): + return types.ListToolsResult( + tools=[ + types.Tool( + name="boom", + description="raises", + input_schema={ + "type": "object", + "properties": {"marker": {"type": "string"}}, + }, + ) + ] + ) + + async def on_call_tool(ctx, params): + raise Boom(f"bare kaboom {(params.arguments or {}).get('marker')}") + + return Server(name, on_list_tools=on_list_tools, on_call_tool=on_call_tool) + + +@MODERN_ONLY +class TestOfficialV2: + """`MCPServer` and the bare lowlevel v2 `Server` behind it.""" + + @pytest.mark.asyncio + async def test_mcpserver_publishes_the_tool_error_and_its_cause(self, events): + from .test_utils.modern_server import create_modern_client + + server = _mcpserver_with_a_raising_tool() + track(server, "test_project", AgentCatOptions()) + + async with create_modern_client(server) as client: + result = await client.call_tool("boom", {"marker": "one"}) + + assert result.is_error is True + error = _one(events, "boom").error + assert error["type"] == "ToolError" + assert "kaboom one" in error["message"] + assert error["stack"] + assert error["frames"] + cause = error["chained_errors"][0] + assert cause["type"] == "Boom" + assert cause["message"] == "kaboom one" + tool_frames = _chained_frames_for(error, "boom") + assert tool_frames and tool_frames[0]["in_app"] is True + assert "raise Boom" in tool_frames[0]["context_line"] + + @pytest.mark.asyncio + async def test_tracking_the_lowlevel_object_directly_still_taps(self, events): + """`track(mcpserver._lowlevel_server)` hands over no facade at all.""" + from .test_utils.modern_server import create_modern_client + + server = _mcpserver_with_a_raising_tool("tracked-by-lowlevel") + track(server._lowlevel_server, "test_project", AgentCatOptions()) + + async with create_modern_client(server) as client: + await client.call_tool("boom", {"marker": "one"}) + + assert _one(events, "boom").error["type"] == "ToolError" + + @pytest.mark.asyncio + async def test_a_repeated_track_does_not_stack_a_second_tap(self, events): + """Two taps would mean two frames and, worse, two installs to unstack.""" + from .test_utils.modern_server import create_modern_client + + server = _mcpserver_with_a_raising_tool("re-tracked") + track(server, "test_project", AgentCatOptions()) + first = server.call_tool + track(server, "test_project", AgentCatOptions()) + assert server.call_tool is not first + + async with create_modern_client(server) as client: + await client.call_tool("boom", {"marker": "one"}) + + error = _one(events, "boom").error + assert error["type"] == "ToolError" + assert len([f for f in error["frames"] if f["function"] == "tap"]) == 1 + + @pytest.mark.asyncio + async def test_bare_lowlevel_v2_keeps_the_handlers_own_exception(self, events): + """This era already let a handler's exception through; do not regress.""" + from .test_utils.modern_server import create_modern_client + + server = _bare_v2_server() + track(server, "test_project", AgentCatOptions()) + + async with create_modern_client(server) as client: + with contextlib.suppress(Exception): + await client.call_tool("boom", {"marker": "one"}) + + error = _one(events, "boom").error + assert error["type"] == "Boom" + assert error["message"] == "bare kaboom one" + handler_frames = _frames_for(error, "on_call_tool") + assert handler_frames and handler_frames[0]["in_app"] is True + + @pytest.mark.asyncio + async def test_a_customers_protocol_error_reaches_the_wire_unchanged( + self, events + ): + """The Task 13 hazard class: AgentCat must not replace a -32602.""" + from mcp.server.mcpserver import MCPServer + from mcp.shared.exceptions import MCPError + from mcp.types import INVALID_PARAMS + + from .test_utils.modern_server import create_modern_client + + def build(): + server = MCPServer("protocol-error-server") + + @server.tool() + def strict(marker: str) -> str: + """Rejects at the protocol level.""" + raise MCPError(code=INVALID_PARAMS, message="Invalid parameters") + + return server + + async def call(server): + async with create_modern_client(server) as client: + try: + await client.call_tool("strict", {"marker": "x"}) + except Exception as exc: # noqa: BLE001 - the error IS the result + return type(exc).__name__, getattr(exc, "code", None), str(exc) + return None + + untracked = await call(build()) + tracked_server = build() + track(tracked_server, "test_project", AgentCatOptions()) + tracked = await call(tracked_server) + + assert untracked is not None + assert tracked == untracked + # Positive control. This is the sole regression test for the bug fixed + # in 18e68a1, and it is an equality between two runs — a detection + # regression that left MCPServer unclassified would leave it green. + # Verified by reducing track() to `return server`: the assertion above + # still passes, this one does not. + assert _call_events(events, "strict") + + @pytest.mark.asyncio + async def test_the_wire_error_is_what_an_untracked_server_returns(self, events): + from .test_utils.modern_server import create_modern_client + + async def call(server): + async with create_modern_client(server) as client: + return await client.call_tool("boom", {"marker": "one"}) + + untracked = await call(_mcpserver_with_a_raising_tool("untracked")) + tracked_server = _mcpserver_with_a_raising_tool("tracked") + track(tracked_server, "test_project", AgentCatOptions()) + tracked = await call(tracked_server) + + assert tracked.is_error == untracked.is_error is True + # Positive control: see the v1 sibling. An equality between two runs + # holds trivially when track() does nothing. + assert _call_events(events, "boom") + assert len(tracked.content) > len(untracked.content) + assert tracked.content[0].model_dump() == untracked.content[0].model_dump() + + @pytest.mark.asyncio + async def test_parallel_failures_each_get_their_own_slot(self, events): + from mcp.server.mcpserver import MCPServer + + from .test_utils.modern_server import create_modern_client + + total = 6 + barrier = Barrier(total) + server = MCPServer("parallel-boom") + + @server.tool() + async def boom(marker: str) -> str: + """Raises once every parallel call is inside it.""" + await barrier.wait() + raise Boom(f"kaboom {marker}") + + track(server, "test_project", AgentCatOptions()) + + async with create_modern_client(server) as client: + await asyncio.wait_for( + asyncio.gather( + *( + client.call_tool("boom", {"marker": f"m{i}"}) + for i in range(total) + ) + ), + timeout=20, + ) + + barrier.assert_every_call_had_its_own_slot() + published = _call_events(events, "boom") + assert len(published) == total + for event in published: + marker = event.parameters["arguments"]["marker"] + cause = event.error["chained_errors"][0] + assert cause["message"] == f"kaboom {marker}" + + @pytest.mark.asyncio + async def test_a_tool_that_composes_a_tool_publishes_its_own_failure( + self, events + ): + """The caller handles a sub-call's failure, then fails on its own.""" + from mcp.server.mcpserver import MCPServer + + from .test_utils.modern_server import create_modern_client + + server = MCPServer("composing-server") + + @server.tool() + async def inner(marker: str) -> str: + """Always fails.""" + raise Boom(f"INNER {marker}") + + @server.tool() + async def outer(marker: str) -> str: + """Handles inner's failure, then fails on its own.""" + with contextlib.suppress(Exception): + await server.call_tool("inner", {"marker": marker}) + raise Boom(f"OUTER {marker}") + + track(server, "test_project", AgentCatOptions()) + + async with create_modern_client(server) as client: + result = await client.call_tool("outer", {"marker": "one"}) + + wire = "".join(c.text for c in result.content if hasattr(c, "text")) + assert "OUTER one" in wire and "INNER one" not in wire + error = _one(events, "outer").error + assert "OUTER one" in error["message"] + assert "INNER one" not in error["message"] + assert error["chained_errors"][0]["message"] == "OUTER one" + + @pytest.mark.asyncio + async def test_a_handled_sub_call_is_not_published_as_the_result(self, events): + """The caller handles a sub-call's failure and answers with its own error.""" + from mcp.server.mcpserver import MCPServer + from mcp.types import CallToolResult, TextContent + + from .test_utils.modern_server import create_modern_client + + server = MCPServer("declining-server") + + @server.tool() + async def inner(marker: str) -> str: + """Always fails.""" + raise Boom(f"INNER {marker}") + + @server.tool() + async def outer(marker: str) -> CallToolResult: + """Handles inner's failure and reports its own error result.""" + with contextlib.suppress(Exception): + await server.call_tool("inner", {"marker": marker}) + return CallToolResult( + content=[TextContent(type="text", text=f"OUTER declined {marker}")], + is_error=True, + ) + + track(server, "test_project", AgentCatOptions()) + + async with create_modern_client(server) as client: + result = await client.call_tool("outer", {"marker": "one"}) + + assert result.is_error is True + error = _one(events, "outer").error + assert error == { + "message": "OUTER declined one", + "type": None, + "platform": "python", + } + + +# ── community FastMCP (both eras) ──────────────────────────────────────────── + + +class _SwallowingMiddleware: + """A layer that turns a raised tool error into an `is_error` result. + + Exactly what `fastmcp/server/providers/proxy.py` does for an upstream + error, and what any error-handling middleware a customer writes does. It + takes the branch where the community adapter used to have nothing but the + surfaced message. + """ + + async def __call__(self, context, call_next): + if getattr(context, "method", None) != "tools/call": + return await call_next(context) + try: + return await call_next(context) + except Exception as exc: + from fastmcp.tools import ToolResult + from mcp.types import TextContent + + return ToolResult( + content=[TextContent(type="text", text=f"swallowed: {exc}")], + is_error=True, + ) + + +def _community_server(name="boom-community"): + from fastmcp import FastMCP + + server = FastMCP(name) + + @server.tool + def boom(marker: str) -> str: + """Raises.""" + raise Boom(f"kaboom {marker}") + + return server + + +def _create_proxy(backend): + """An in-process FastMCP proxy in front of ``backend``, either era. + + FastMCP 4 exposes `fastmcp.server.create_proxy`; the 3.x line spells the + same thing `FastMCP.as_proxy`. + """ + try: + from fastmcp.server import create_proxy + except ImportError: + from fastmcp import FastMCP + + return FastMCP.as_proxy(backend) + return create_proxy(backend) + + +@pytest.mark.skipif(not HAS_COMMUNITY, reason="Community FastMCP not installed") +class TestCommunity: + """FastMCP 3 and 4 — whichever era this dependency set installed.""" + + @pytest.mark.asyncio + async def test_the_raise_path_still_carries_full_detail(self, events): + """Already true before the tap; this is the do-not-regress guard.""" + from fastmcp import Client + + server = _community_server("raise-path") + track(server, "test_project", AgentCatOptions()) + + async with Client(server) as client: + with contextlib.suppress(Exception): + await client.call_tool("boom", {"marker": "one"}) + + error = _one(events, "boom").error + assert error["type"] is not None + assert error["frames"] + tool_frames = _chained_frames_for(error, "boom") + assert tool_frames and tool_frames[0]["in_app"] is True + + @pytest.mark.asyncio + async def test_an_is_error_result_without_a_raise_still_carries_detail( + self, events + ): + from fastmcp import Client + + server = _community_server("swallowed") + server.add_middleware(_SwallowingMiddleware()) + track(server, "test_project", AgentCatOptions()) + + async with Client(server) as client: + result = await client.call_tool( + "boom", {"marker": "one"}, raise_on_error=False + ) + + assert result.is_error is True + error = _one(events, "boom").error + # No exception reached the adapter — a layer below it answered with an + # is_error result — but one was raised, and the tap kept it. + assert error["type"] is not None + assert "kaboom one" in error["message"] + tool_frames = _chained_frames_for(error, "boom") + assert tool_frames and tool_frames[0]["in_app"] is True + + @pytest.mark.asyncio + async def test_a_repeated_track_does_not_stack_a_second_tap(self, events): + from fastmcp import Client + + server = _community_server("re-tracked") + server.add_middleware(_SwallowingMiddleware()) + track(server, "test_project", AgentCatOptions()) + first = server.call_tool + track(server, "test_project", AgentCatOptions()) + assert server.call_tool is not first + + async with Client(server) as client: + await client.call_tool( + "boom", {"marker": "one"}, raise_on_error=False + ) + + error = _one(events, "boom").error + assert error["type"] is not None + assert len([f for f in error["frames"] if f["function"] == "tap"]) == 1 + + @pytest.mark.asyncio + async def test_a_proxied_upstream_error_keeps_the_surfaced_message(self, events): + """The documented permanent gap, driven through a real proxy. + + `providers/proxy.py` passes an upstream error result through + deliberately — "rather than collapsing it into a raised ToolError" — + from a `call_tool_mcp` that never raises. The failure happened in the + backend; there is no Python exception anywhere in this process to + recover, and no tap placement could change that. Built as an actual + proxy so this fails loudly if a future FastMCP starts raising instead. + """ + from fastmcp import Client + + backend = _community_server("proxy-backend") + front = _create_proxy(backend) + track(front, "test_project", AgentCatOptions()) + + async with Client(front) as client: + result = await client.call_tool( + "boom", {"marker": "one"}, raise_on_error=False + ) + + assert result.is_error is True + # content[0] is the backend's own error block; anything after it is + # AgentCat's task mint-back, which every v2 result carries. + upstream = result.content[0].text + assert "kaboom one" in upstream + error = _one(events, "boom").error + assert error == {"message": upstream, "type": None, "platform": "python"} + + @pytest.mark.asyncio + async def test_the_wire_error_is_what_an_untracked_server_returns(self, events): + from fastmcp import Client + + async def call(server): + async with Client(server) as client: + return await client.call_tool( + "boom", {"marker": "one"}, raise_on_error=False + ) + + untracked_server = _community_server("untracked") + untracked_server.add_middleware(_SwallowingMiddleware()) + untracked = await call(untracked_server) + + tracked_server = _community_server("tracked") + tracked_server.add_middleware(_SwallowingMiddleware()) + track(tracked_server, "test_project", AgentCatOptions()) + tracked = await call(tracked_server) + + assert tracked.is_error == untracked.is_error is True + assert tracked.content[0].model_dump() == untracked.content[0].model_dump() + # Positive control: see the v1 sibling. An equality between two runs + # holds trivially when track() does nothing. + assert _call_events(events, "boom") + assert len(tracked.content) > len(untracked.content) + + @pytest.mark.asyncio + async def test_parallel_failures_each_get_their_own_slot(self, events): + from fastmcp import Client, FastMCP + + total = 6 + barrier = Barrier(total) + server = FastMCP("parallel-community") + server.add_middleware(_SwallowingMiddleware()) + + @server.tool + async def boom(marker: str) -> str: + """Raises once every parallel call is inside it.""" + await barrier.wait() + raise Boom(f"kaboom {marker}") + + track(server, "test_project", AgentCatOptions()) + + async with Client(server) as client: + await asyncio.wait_for( + asyncio.gather( + *( + client.call_tool( + "boom", {"marker": f"m{i}"}, raise_on_error=False + ) + for i in range(total) + ) + ), + timeout=20, + ) + + barrier.assert_every_call_had_its_own_slot() + published = _call_events(events, "boom") + assert len(published) == total + for event in published: + marker = event.parameters["arguments"]["marker"] + cause = event.error["chained_errors"][0] + assert cause["message"] == f"kaboom {marker}" + + @pytest.mark.asyncio + async def test_a_tool_that_composes_a_tool_publishes_its_own_failure( + self, events + ): + """The caller handles a sub-call's failure, then fails on its own.""" + from fastmcp import Client + + server = _community_server("composing-community") + + @server.tool + async def inner(marker: str) -> str: + """Always fails.""" + raise Boom(f"INNER {marker}") + + @server.tool + async def outer(marker: str) -> str: + """Handles inner's failure, then fails on its own.""" + with contextlib.suppress(Exception): + await server.call_tool("inner", {"marker": marker}) + raise Boom(f"OUTER {marker}") + + track(server, "test_project", AgentCatOptions()) + + async with Client(server) as client: + result = await client.call_tool( + "outer", {"marker": "one"}, raise_on_error=False + ) + + wire = "".join(c.text for c in result.content if hasattr(c, "text")) + assert "OUTER one" in wire and "INNER one" not in wire + error = _one(events, "outer").error + assert "OUTER one" in error["message"] + assert "INNER one" not in error["message"] + + @pytest.mark.asyncio + async def test_a_sub_call_still_running_does_not_cost_the_tools_detail( + self, events + ): + """The unit-level sub-call case, live on whichever era is installed. + + Every piece here is something a real server does: a tool that leaves + work running, and a layer below AgentCat that converts the raise into + an `is_error` result and awaits while it does so. The sub-call inherits + the failing call's slot, and its normal return used to erase the + exception — degrading the event from the tool's own `Boom`, with its + frames, to the three-key payload a server with no tap at all produces. + """ + from fastmcp import Client, FastMCP + from fastmcp.tools import ToolResult + from mcp.types import TextContent + + sub_call_is_inside = asyncio.Event() + let_the_sub_call_finish = asyncio.Event() + spawned: list = [] + + class ConvertsWhileTheSubCallFinishes: + """A layer BELOW us doing what a proxy or an error-handling + middleware does — with one await in it.""" + + async def __call__(self, context, call_next): + if getattr(context, "method", None) != "tools/call": + return await call_next(context) + try: + return await call_next(context) + except Exception as exc: + let_the_sub_call_finish.set() + await spawned[0] + return ToolResult( + content=[TextContent(type="text", text=f"swallowed: {exc}")], + is_error=True, + ) + + server = FastMCP("sub-call-in-flight") + + @server.tool + async def slow(marker: str) -> str: + """The sub-call the failing tool left running.""" + sub_call_is_inside.set() + await let_the_sub_call_finish.wait() + return f"slow {marker}" + + @server.tool + async def boom(marker: str) -> str: + """Leaves a sub-call running on this call's slot, then raises.""" + spawned.append( + asyncio.create_task(server.call_tool("slow", {"marker": marker})) + ) + await sub_call_is_inside.wait() + raise Boom(f"kaboom {marker}") + + server.add_middleware(ConvertsWhileTheSubCallFinishes()) + track(server, "test_project", AgentCatOptions()) + + async with Client(server) as client: + result = await asyncio.wait_for( + client.call_tool("boom", {"marker": "one"}, raise_on_error=False), + timeout=20, + ) + + assert result.is_error is True + error = _one(events, "boom").error + assert error["type"] is not None, "the tap's capture was erased" + assert "kaboom one" in error["message"] + tool_frames = _chained_frames_for(error, "boom") + assert tool_frames and tool_frames[0]["in_app"] is True + # The sub-call succeeded, and its own event says so. + assert _one(events, "slow").is_error is False diff --git a/tests/test_lowlevel_v1_handles.py b/tests/test_lowlevel_v1_handles.py new file mode 100644 index 0000000..c606734 --- /dev/null +++ b/tests/test_lowlevel_v1_handles.py @@ -0,0 +1,677 @@ +"""End-to-end handle behavior on the official MCP SDK 1.x lowlevel adapter. + +Everything here drives a real `ClientSession` against a real server, so the +assertions cover the whole wire path: schema injection on `tools/list`, the +stripped arguments the customer's tool actually receives, the mint-back the +agent sees, and the single `mcp:tools/call` event AgentCat publishes. + +The strip is read at the TOOL MANAGER (`tests.test_utils.delivery`), never +inside a tool body: this SDK's manager drops an argument the signature does not +name without complaint, so a body-level recorder would report the same thing +with the strip disabled. + +`create_todo_server()` returns an official `FastMCP`, which v2 tracks through +its `_mcp_server` — the same adapter a bare lowlevel `Server` gets. +""" + +import json + +import pytest +from mcp.server.fastmcp import FastMCP +from mcp.types import TextContent + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import ( + AGENTCAT_TAG_AGENT_ID, + AGENTCAT_TAG_AGENT_SOURCE, + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, +) +from agentcat.modules.handles import derive_session_id + +from .test_utils import sid +from .test_utils.client import create_test_client +from .test_utils.delivery import delivered_arguments_for, record_delivered_arguments +from .test_utils.todo_server import create_todo_server + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +@pytest.fixture +def log_sink(): + """Everything `write_to_log` tees to diagnostics, as the collector sees it.""" + from agentcat.modules import logging as agentcat_logging + + previous = agentcat_logging._diagnostics_sink + lines: list[str] = [] + agentcat_logging.set_diagnostics_sink(lines.append) + yield lines + agentcat_logging.set_diagnostics_sink(previous) + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +def _call_events(capture) -> list: + return [e for e in capture if e.event_type == "mcp:tools/call"] + + +async def test_prompted_mode_end_to_end(capture): + server = create_todo_server() + track(server, "proj_test", AgentCatOptions()) + + async with create_test_client(server) as client: + listed = await client.list_tools() + add = next(t for t in listed.tools if t.name == "add_todo") + assert list(add.inputSchema["properties"])[-2:] == ["session_id", "context"] + assert "session_id" not in add.inputSchema.get("required", []) + # session_id is the one injected param that is never required — omitting + # it is the minting signal. `context` is required, which is the only + # thing that makes agents supply intent at all. + assert "context" in add.inputSchema["required"] + assert any(t.name == "get_more_tools" for t in listed.tools) + + r1 = await client.call_tool( + "add_todo", + { + "text": "hi", + "context": "Adding a todo item for the user's task list to track work", + }, + ) + text = _text(r1) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + assert minted.startswith("ses_") + + r2 = await client.call_tool("add_todo", {"text": "again", "session_id": minted}) + assert MINT_BACK_HEADER not in _text(r2) + + call_events = _call_events(capture) + # v2 publishes tools/call and nothing else: no initialize, no tools/list, + # no agentcat:identify. + assert {e.event_type for e in capture} == {"mcp:tools/call"} + assert len(call_events) == 2 + assert call_events[0].session_id == minted == call_events[1].session_id + # The event records the call as the agent made it: raw, unstripped. + assert call_events[0].parameters["arguments"]["context"] + assert call_events[1].parameters["arguments"]["session_id"] == minted + # ...and the customer's result, undecorated. + assert call_events[0].response is not None + assert "Added todo" in json.dumps(call_events[0].response) + assert "[MCP INSTRUCTIONS]" not in json.dumps(call_events[0].response) + assert call_events[0].tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + assert call_events[1].tags[AGENTCAT_TAG_SESSION_SOURCE] == "supplied" + assert call_events[0].user_intent.startswith("Adding a todo item") + + +async def test_structured_mint_back_mirrors_into_structured_content(capture): + """A tool with an outputSchema gets `_mcp_instructions` mirrored in, and its + schema declares the field so schema-validating clients still accept it.""" + server = create_todo_server() + track(server, "proj_test", AgentCatOptions()) + + async with create_test_client(server) as client: + listed = await client.list_tools() + add = next(t for t in listed.tools if t.name == "add_todo") + assert MCP_INSTRUCTIONS_KEY in add.outputSchema["properties"] + + result = await client.call_tool("add_todo", {"text": "structured"}) + mint = result.structuredContent[MCP_INSTRUCTIONS_KEY] + assert mint["session_id"].startswith("ses_") + assert mint["session_id"] == _call_events(capture)[0].session_id + # The customer's own structured payload survives untouched. + assert result.structuredContent["result"].startswith("Added todo") + + +async def test_handler_sees_stripped_args_and_customer_result_untouched(capture): + """The injected params never reach the tool body, and what the tool returned + is exactly what the agent gets back (minus AgentCat's trailing block). + + `seen` is filled at the tool manager, not inside `probe`. A typed body can + only ever report the parameters it declared, and this manager drops an + undeclared argument SILENTLY rather than raising — so a recorder in the + body would read `{"text": "payload"}` whether or not the strip ran. See + `tests.test_utils.delivery`. + """ + seen: list[tuple[str, dict]] = [] + mcp = FastMCP("probe-server") + + @mcp.tool() + def probe(text: str) -> str: + """A plain typed tool; it cannot police its own arguments.""" + return f"probe:{text}" + + record_delivered_arguments(mcp._tool_manager, seen) + track(mcp, "proj_test") + + async with create_test_client(mcp) as client: + await client.list_tools() + result = await client.call_tool( + "probe", + {"text": "payload", "session_id": sid("supplied"), "context": "why"}, + ) + + assert result.isError is False, _text(result) + assert seen == [("probe", {"text": "payload"})] + assert result.content[0].text == "probe:payload" + # session_id was supplied, so nothing is minted back and nothing is appended. + assert len(result.content) == 1 + assert _call_events(capture)[0].session_id == sid("supplied") + + +async def test_get_more_tools_keeps_its_own_context_and_publishes(capture): + server = create_todo_server() + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_test_client(server) as client: + listed = await client.list_tools() + gmt = next(t for t in listed.tools if t.name == "get_more_tools") + # Its bespoke `context` is a real parameter: still required, still + # described by the tool's own copy — and handles ride alongside. + assert gmt.inputSchema["required"] == ["context"] + assert "session_id" in gmt.inputSchema["properties"] + assert gmt.annotations.readOnlyHint is True + + result = await client.call_tool( + "get_more_tools", {"context": "I need a tool to send emails"} + ) + assert "Unfortunately" in _text(result) + + event = _call_events(capture)[0] + assert event.resource_name == "get_more_tools" + assert event.user_intent == "I need a tool to send emails" + assert event.parameters["arguments"]["context"] == "I need a tool to send emails" + + +async def test_agent_tracking_injection(capture): + server = create_todo_server() + track(server, "proj_test", AgentCatOptions(enable_agent_tracking=True)) + + async with create_test_client(server) as client: + listed = await client.list_tools() + add = next(t for t in listed.tools if t.name == "add_todo") + assert list(add.inputSchema["properties"])[-3:] == [ + "session_id", + "agent_id", + "context", + ] + assert "agent_id" in add.inputSchema["required"] + assert "session_id" not in add.inputSchema["required"] + + result = await client.call_tool( + "add_todo", {"text": "with agent", "agent_id": "opus|claude-code|k3n9x"} + ) + assert result.isError is False, _text(result) + + event = _call_events(capture)[0] + assert event.tags[AGENTCAT_TAG_AGENT_ID] == "opus|claude-code|k3n9x" + assert event.tags[AGENTCAT_TAG_AGENT_SOURCE] == "supplied" + + +async def test_hook_mode(capture): + server = create_todo_server() + track( + server, + "proj_test", + AgentCatOptions(resolve_session_id=lambda request, extra: "cust-1"), + ) + + async with create_test_client(server) as client: + listed = await client.list_tools() + assert listed.tools + for tool in listed.tools: + assert "session_id" not in tool.inputSchema.get("properties", {}) + + r1 = await client.call_tool("add_todo", {"text": "hook one"}) + r2 = await client.call_tool("add_todo", {"text": "hook two"}) + assert "[MCP INSTRUCTIONS]" not in _text(r1) + assert "[MCP INSTRUCTIONS]" not in _text(r2) + assert MCP_INSTRUCTIONS_KEY not in (r1.structuredContent or {}) + + call_events = _call_events(capture) + expected = derive_session_id("cust-1", "proj_test") + assert [e.session_id for e in call_events] == [expected, expected] + assert call_events[0].tags[AGENTCAT_TAG_SESSION_SOURCE] == "hook" + + +async def test_tracing_disabled_strips_but_publishes_nothing(capture): + server = create_todo_server() + track(server, "proj_test", AgentCatOptions(enable_tracing=False)) + + async with create_test_client(server) as client: + listed = await client.list_tools() + add = next(t for t in listed.tools if t.name == "add_todo") + # No handles when tracing is off, but the context parameter is + # independent — so it must still be stripped before the tool runs. + assert "session_id" not in add.inputSchema["properties"] + assert "context" in add.inputSchema["properties"] + + result = await client.call_tool( + "add_todo", {"text": "quiet", "context": "no tracing"} + ) + assert result.isError is False, _text(result) + assert "[MCP INSTRUCTIONS]" not in _text(result) + + # Read at the tool manager: `add_todo` is a typed body, which cannot show + # an argument that arrived and was dropped on the way in. + assert delivered_arguments_for(server, "add_todo") == [{"text": "quiet"}] + assert capture == [] + + +async def test_customer_tool_schema_is_never_mutated(capture): + """Injection works on deep copies: the server's own tool definitions and a + second, untracked server built the same way stay identical.""" + server = create_todo_server() + reference = create_todo_server() + track(server, "proj_test") + + async with create_test_client(server) as client: + await client.list_tools() + + tracked = {t.name: t.inputSchema for t in await server.list_tools()} + untracked = {t.name: t.inputSchema for t in await reference.list_tools()} + assert tracked == untracked + + +async def test_error_result_still_carries_the_handle(capture): + server = create_todo_server() + track(server, "proj_test") + + async with create_test_client(server) as client: + await client.list_tools() + result = await client.call_tool("complete_todo", {"id": 999}) + + assert result.isError is True + # A retry after a failure has to carry the same task, so error results + # decorate on identical terms. + assert MINT_BACK_HEADER in _text(result) + event = _call_events(capture)[0] + assert event.is_error is True + assert event.session_id.startswith("ses_") + # The SDK flattened the exception before this wrapper saw it, so the type + # comes from the inner tap (Task 13.5) rather than from the result — and + # the customer's own ValueError is the recorded cause. + assert "Todo with ID 999 not found" in event.error["message"] + assert event.error["type"] == "ToolError" + assert event.error["chained_errors"][0]["type"] == "ValueError" + assert event.error["platform"] == "python" + + +async def test_customer_get_more_tools_is_never_hijacked(capture): + """A customer tool that happens to be named `get_more_tools` keeps running. + + We refuse to advertise a second one; we must equally refuse to answer for + the one they wrote (spec §12 — nothing may alter customer tool behavior). + """ + mcp = FastMCP("collision-server") + + @mcp.tool() + def get_more_tools(context: str) -> str: + """The customer's own tool, which happens to share our name.""" + return f"customer answered: {context}" + + track(mcp, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_test_client(mcp) as client: + listed = await client.list_tools() + # Exactly one, and it is theirs — ours is not advertised alongside it. + assert [t.name for t in listed.tools] == ["get_more_tools"] + assert listed.tools[0].description.startswith("The customer's own tool") + + result = await client.call_tool("get_more_tools", {"context": "mine"}) + + assert result.isError is False, _text(result) + assert "customer answered: mine" in _text(result) + assert "Unfortunately" not in _text(result) + # Still tracked like any other tool call. + assert _call_events(capture)[0].resource_name == "get_more_tools" + + +async def test_customer_get_more_tools_survives_a_call_before_any_listing(capture): + """The ownership question is settled by the same rebuild that restores the + strip registry, so a first-ever call is not hijacked either.""" + mcp = FastMCP("collision-server") + + @mcp.tool() + def get_more_tools(context: str) -> str: + """The customer's own tool.""" + return f"customer answered: {context}" + + track(mcp, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_test_client(mcp) as client: + # No list_tools first. + result = await client.call_tool("get_more_tools", {"context": "mine"}) + + assert "customer answered: mine" in _text(result) + + +async def test_customer_get_more_tools_survives_a_server_with_no_listing(capture): + """Nothing advertised the tool, so we may not answer for it. + + A server that exposes no `tools/list` at all never runs the pass that would + tell us who owns the name. The gate is stated positively — "AgentCat + advertised it" — so an absent listing keeps the customer's handler. + """ + from mcp.server.lowlevel import Server + from mcp.types import CallToolRequest, CallToolRequestParams + + server = Server("no-listing-server") + + @server.call_tool() + async def call_tool(name: str, arguments: dict): + return [TextContent(type="text", text=f"customer answered: {name}")] + + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + handler = server.request_handlers[CallToolRequest] + result = await handler( + CallToolRequest( + method="tools/call", + params=CallToolRequestParams( + name="get_more_tools", arguments={"context": "mine"} + ), + ) + ) + + assert "customer answered: get_more_tools" in _text(result.root) + assert "Unfortunately" not in _text(result.root) + + +async def test_retracking_updates_options_without_double_wrapping(capture): + server = create_todo_server() + track(server, "proj_test", AgentCatOptions(enable_report_missing=False)) + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_test_client(server) as client: + listed = await client.list_tools() + assert [t.name for t in listed.tools].count("get_more_tools") == 1 + add = next(t for t in listed.tools if t.name == "add_todo") + assert list(add.inputSchema["properties"]) == ["text", "session_id", "context"] + + # A second, stacked wrapper would inject session_id in the inner pass and + # then skip it in the outer one — leaving it out of the strip registry + # and handing the customer's tool a parameter it never declared. + result = await client.call_tool( + "add_todo", {"text": "retracked", "session_id": sid("retrack")} + ) + assert result.isError is False, _text(result) + + assert len(_call_events(capture)) == 1 + assert _call_events(capture)[0].session_id == sid("retrack") + + +async def test_request_arguments_are_never_mutated_in_place(): + """The v1 path popped `context` off the caller's own arguments dict, which + corrupted concurrent retries. Stripping must always clone first.""" + from mcp.types import CallToolRequest, CallToolRequestParams + + server = create_todo_server() + track(server, "proj_test") + handler = server._mcp_server.request_handlers[CallToolRequest] + + request = CallToolRequest( + method="tools/call", + params=CallToolRequestParams( + name="add_todo", + arguments={"text": "hi", "context": "why", "session_id": sid("supplied")}, + ), + ) + stored = request.params.arguments + result = await handler(request) + + assert result.root.isError is False, result.root.content + # The very dict the request holds, still untouched — the handler ran against + # a clone. + assert request.params.arguments is stored + assert stored == {"text": "hi", "context": "why", "session_id": sid("supplied")} + + +def test_a_tracked_server_is_collectable_once_the_customer_drops_it(): + """Nothing AgentCat holds may outlive the server (changelog §6.8). + + A module-level `WeakKeyDictionary` does not give you this for free: the + wrappers filed there close over the server, so the value keeps its own weak + key alive and every tracked server becomes immortal. + """ + import gc + import weakref + + from mcp.server.lowlevel import Server + + alive = [] + for _ in range(3): + server = Server("collectable") + _register_todo_handlers(server) + track(server, "proj_test") + alive.append(weakref.ref(server)) + del server + + gc.collect() + assert [ref() for ref in alive] == [None, None, None] + + +def test_a_tracked_fastmcp_is_collectable_with_its_lowlevel_server(): + """The adapter is installed on `_mcp_server`, so both halves have to go.""" + import gc + import weakref + + server = create_todo_server() + track(server, "proj_test") + facade, lowlevel = weakref.ref(server), weakref.ref(server._mcp_server) + del server + + gc.collect() + assert (facade(), lowlevel()) == (None, None) + + +def _register_todo_handlers(server) -> None: + """The customer's own `@server.list_tools()` / `@server.call_tool()` pair.""" + from mcp.types import Tool + + @server.list_tools() + async def list_tools() -> list: + return [ + Tool( + name="add_todo", + description="Add a new todo item.", + inputSchema={ + "type": "object", + "properties": {"text": {"type": "string"}}, + "required": ["text"], + }, + ) + ] + + @server.call_tool() + async def call_tool(name: str, arguments: dict): + unexpected = sorted(set(arguments) - {"text"}) + if unexpected: + raise ValueError(f"unexpected arguments: {unexpected}") + return [TextContent(type="text", text=f"Added todo: {arguments['text']}")] + + +async def test_handlers_registered_after_track_are_still_wrapped(capture): + """`track()` on a server with no tools handlers yet still takes effect. + + Registration on this generation writes straight into `request_handlers`, so + without a patched decorator the customer's later `@server.call_tool()` + would simply overwrite our wrapper — a fresh `Server()` tracked at import + time would go untracked forever. + """ + from mcp.server.lowlevel import Server + + server = Server("late-server") + track(server, "proj_test") + _register_todo_handlers(server) + + async with create_test_client(server) as client: + listed = await client.list_tools() + add = next(t for t in listed.tools if t.name == "add_todo") + assert "session_id" in add.inputSchema["properties"] + result = await client.call_tool("add_todo", {"text": "late"}) + assert result.isError is False, _text(result) + assert MINT_BACK_HEADER in _text(result) + + assert len(_call_events(capture)) == 1 + + +async def test_reregistering_a_handler_after_track_rewraps_it(capture): + """A customer who replaces their `call_tool` handler after `track()` does + not silently lose tracking.""" + from mcp.server.lowlevel import Server + + server = Server("replaced-server") + _register_todo_handlers(server) + track(server, "proj_test") + + @server.call_tool() + async def replacement(name: str, arguments: dict): + unexpected = sorted(set(arguments) - {"text"}) + if unexpected: + raise ValueError(f"unexpected arguments: {unexpected}") + return [TextContent(type="text", text=f"replaced: {arguments['text']}")] + + async with create_test_client(server) as client: + await client.list_tools() + result = await client.call_tool("add_todo", {"text": "again"}) + assert result.isError is False, _text(result) + assert "replaced: again" in _text(result) + assert MINT_BACK_HEADER in _text(result) + + assert len(_call_events(capture)) == 1 + + +async def test_re_arm_is_not_stacked_by_a_second_track(capture): + """Two `track()` calls leave one wrapper, not two, even on a handler + registered after both.""" + from mcp.server.lowlevel import Server + + server = Server("double-tracked") + track(server, "proj_test") + track(server, "proj_test") + _register_todo_handlers(server) + + async with create_test_client(server) as client: + listed = await client.list_tools() + add = next(t for t in listed.tools if t.name == "add_todo") + # A stacked pair would inject session_id twice or leave it unstrippable. + assert list(add.inputSchema["properties"]) == ["text", "session_id", "context"] + result = await client.call_tool("add_todo", {"text": "twice"}) + assert result.isError is False, _text(result) + + assert len(_call_events(capture)) == 1 + + +async def test_intermediate_mrtr_round_is_tagged_but_never_decorated(capture): + """A round that asks the client for more input is not the completing round, + so it carries no mint-back — text or structured.""" + from mcp.server.lowlevel import Server + from mcp.types import CallToolRequest, CallToolRequestParams, CallToolResult, Tool + + server = Server("mrtr-server") + + @server.list_tools() + async def list_tools() -> list: + return [ + Tool( + name="ask", + description="Needs another round.", + inputSchema={"type": "object", "properties": {}}, + ) + ] + + @server.call_tool() + async def call_tool(name: str, arguments: dict): + return CallToolResult( + content=[TextContent(type="text", text="need more")], + resultType="input_required", + ) + + track(server, "proj_test") + handler = server.request_handlers[CallToolRequest] + result = await handler( + CallToolRequest( + method="tools/call", + params=CallToolRequestParams(name="ask", arguments={}), + ) + ) + + assert [block.text for block in result.root.content] == ["need more"] + assert result.root.structuredContent is None + event = _call_events(capture)[0] + assert event.tags["agentcat_mrtr"] == "input_required" + assert event.session_id.startswith("ses_") + + +def test_track_never_raises(): + sentinel = object() + assert track(sentinel, None) is sentinel + assert track(sentinel, "proj_test") is sentinel + assert track(None, "proj_test") is None + assert track(object(), "proj_test", AgentCatOptions(enable_tracing=False)) + # An options object of the wrong shape used to blow up on attribute access. + assert track(sentinel, "proj_test", {"debug_mode": True}) is sentinel + # Missing project_id with no exporters used to raise ValueError. + server = create_todo_server() + assert track(server, None) is server + + +def test_unrecognized_shape_logs_the_fingerprint_beacon(log_sink): + """The unknown-shape path feeds the diagnostics sink a probe fingerprint — + that is the fleet-drift beacon (changelog 6.7).""" + track(object(), "proj_test") + + beacons = [line for line in log_sink if "fingerprint=" in line] + assert beacons, log_sink + assert "Unrecognized" in beacons[0] + assert "has_request_handlers" in beacons[0] + + +def test_community_fastmcp_v2_is_reported_unsupported(log_sink): + """A FastMCP 2.x-shaped object is refused with actionable copy, not tracked.""" + + class FastMCPV2Shape: + def __init__(self) -> None: + self._mcp_server = object() + self._tool_manager = object() + + FastMCPV2Shape.__module__ = "fastmcp.server.server" + server = FastMCPV2Shape() + + assert track(server, "proj_test") is server + assert any("agentcat<2" in line for line in log_sink), log_sink + + +def test_the_installed_official_sdk_classifies_as_a_lowlevel_v1_flavor(): + """Every other detection test builds doubles from what we *believe* each + generation looks like. This one asks the SDK actually installed here, so an + upstream shape change surfaces as a failure rather than as a silently + untracked fleet. + + Replaces tests/test_mcp_version_compatibility.py, whose `is_compatible_server` + gate the flavor classifier subsumes. + """ + from mcp.server import Server + + from agentcat.modules.detection import ServerFlavor, detect_server + + fastmcp = create_todo_server() + detected = detect_server(fastmcp) + assert detected.flavor is ServerFlavor.OFFICIAL_FASTMCP_V1 + assert detected.lowlevel is fastmcp._mcp_server + + lowlevel = Server("bare") + detected = detect_server(lowlevel) + assert detected.flavor is ServerFlavor.LOWLEVEL_V1 + assert detected.lowlevel is lowlevel diff --git a/tests/test_lowlevel_v2_handles.py b/tests/test_lowlevel_v2_handles.py new file mode 100644 index 0000000..13bb364 --- /dev/null +++ b/tests/test_lowlevel_v2_handles.py @@ -0,0 +1,1312 @@ +"""End-to-end handle behavior on the official MCP SDK 2.x lowlevel adapter. + +Everything here drives a real in-process `Client` against a real server, so the +assertions cover the whole wire path — params validation, the SDK's outbound +result sieve, and the per-version `serverInfo` stamp — rather than a +hand-called handler. What is asserted: schema injection on `tools/list`, the +stripped arguments the customer's tool actually receives, the mint-back the +agent sees, and the single `mcp:tools/call` event AgentCat publishes. + +This is the first era where multi-round-trip tool calls are reachable, so the +`input_required` / `continuation` rounds here are real protocol behavior, not a +simulation. +""" + +import copy +import dataclasses +import gc +import json +import weakref + +import pytest +from mcp import types +from mcp.server import Server +from mcp.server.mcpserver import MCPServer +from mcp.shared.exceptions import MCPError + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import ( + AGENTCAT_TAG_AGENT_ID, + AGENTCAT_TAG_AGENT_SOURCE, + AGENTCAT_TAG_MRTR, + AGENTCAT_TAG_PROTOCOL_VERSION, + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, +) +from agentcat.modules.handles import derive_session_id + +from .test_utils import sid +from .test_utils.delivery import delivered_arguments_for +from .test_utils.modern_server import ( + ADD_TODO_INPUT_SCHEMA, + create_lowlevel_todo_server, + create_mcpserver_todo_server, + create_modern_client, +) + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." +MODERN = "2026-07-28" + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +@pytest.fixture +def log_sink(): + """Everything `write_to_log` tees to diagnostics, as the collector sees it.""" + from agentcat.modules import logging as agentcat_logging + + previous = agentcat_logging._diagnostics_sink + lines: list[str] = [] + agentcat_logging.set_diagnostics_sink(lines.append) + yield lines + agentcat_logging.set_diagnostics_sink(previous) + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +def _call_events(capture) -> list: + return [e for e in capture if e.event_type == "mcp:tools/call"] + + +def _tool(listed, name): + return next(t for t in listed.tools if t.name == name) + + +# ── injection, mint-back, strip, event ─────────────────────────────────────── + + +async def test_prompted_mode_end_to_end(capture): + server = create_lowlevel_todo_server() + track(server, "proj_test", AgentCatOptions()) + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + add = _tool(listed, "add_todo") + assert list(add.input_schema["properties"])[-2:] == ["session_id", "context"] + # session_id is the one injected param that is never required — omitting + # it is the minting signal. `context` is required, which is the only + # thing that makes agents supply intent at all. + assert "session_id" not in add.input_schema.get("required", []) + assert "context" in add.input_schema["required"] + assert any(t.name == "get_more_tools" for t in listed.tools) + + r1 = await client.call_tool( + "add_todo", + { + "text": "hi", + "context": "Adding a todo item for the user's task list to track work", + }, + ) + text = _text(r1) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + assert minted.startswith("ses_") + + r2 = await client.call_tool("add_todo", {"text": "again", "session_id": minted}) + assert MINT_BACK_HEADER not in _text(r2) + + call_events = _call_events(capture) + # v2 publishes tools/call and nothing else: no initialize, no tools/list, + # no agentcat:identify. + assert {e.event_type for e in capture} == {"mcp:tools/call"} + assert len(call_events) == 2 + assert call_events[0].session_id == minted == call_events[1].session_id + # The event records the call as the agent made it: raw, unstripped. + assert call_events[0].parameters["arguments"]["context"] + assert call_events[1].parameters["arguments"]["session_id"] == minted + # ...and the customer's result, undecorated. + assert call_events[0].response is not None + assert "Added todo" in json.dumps(call_events[0].response) + assert "[MCP INSTRUCTIONS]" not in json.dumps(call_events[0].response) + assert call_events[0].tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + assert call_events[1].tags[AGENTCAT_TAG_SESSION_SOURCE] == "supplied" + assert call_events[0].user_intent.startswith("Adding a todo item") + + +async def test_protocol_version_tag_comes_from_the_request(capture): + """The 2026 wire carries the version in `_meta`; the handshake era falls + back to `ctx.protocol_version`. Both must reach the event.""" + server = create_lowlevel_todo_server() + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + await client.call_tool("add_todo", {"text": "modern"}) + assert _call_events(capture)[-1].tags[AGENTCAT_TAG_PROTOCOL_VERSION] == MODERN + + async with create_modern_client(server, mode="legacy") as client: + await client.call_tool("add_todo", {"text": "legacy"}) + version = _call_events(capture)[-1].tags[AGENTCAT_TAG_PROTOCOL_VERSION] + assert version and version != MODERN + + +async def test_client_identity_ladder(capture): + """Envelope `_meta` on the modern wire; the handshake `client_info` the + session kept on the legacy one.""" + server = create_lowlevel_todo_server() + track(server, "proj_test") + info = types.Implementation(name="MyAgent", version="1.2.3") + + for mode in (MODERN, "legacy"): + async with create_modern_client(server, mode=mode, client_info=info) as client: + await client.call_tool("add_todo", {"text": mode}) + event = _call_events(capture)[-1] + assert (event.client_name, event.client_version) == ("MyAgent", "1.2.3"), mode + + +async def test_structured_mint_back_mirrors_into_structured_content(capture): + """A tool with an output schema gets `_mcp_instructions` mirrored in, and + its schema declares the field so schema-validating clients still accept + it.""" + server = create_lowlevel_todo_server() + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + assert MCP_INSTRUCTIONS_KEY in _tool(listed, "add_todo").output_schema[ + "properties" + ] + + result = await client.call_tool("add_todo", {"text": "structured"}) + mint = result.structured_content[MCP_INSTRUCTIONS_KEY] + assert mint["session_id"].startswith("ses_") + assert mint["session_id"] == _call_events(capture)[0].session_id + # The customer's own structured payload survives untouched. + assert result.structured_content["result"].startswith("Added todo") + + +async def test_handler_sees_stripped_args_and_customer_result_untouched(capture): + """The injected params never reach the tool body, and what the tool returned + is exactly what the agent gets back (minus AgentCat's trailing block).""" + server = create_lowlevel_todo_server() + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + result = await client.call_tool( + "add_todo", + {"text": "payload", "session_id": sid("supplied"), "context": "why"}, + ) + + # The tool raises on any argument it did not declare, so a strip regression + # surfaces here rather than passing silently. + assert result.is_error is False, _text(result) + assert result.content[0].text == 'Added todo: "payload" with ID 1' + # session_id was supplied, so nothing is minted back and nothing is appended. + assert len(result.content) == 1 + assert _call_events(capture)[0].session_id == sid("supplied") + + +async def test_customer_tool_schema_is_never_mutated(capture): + """Injection works on copies, never in place on customer objects.""" + pristine = copy.deepcopy(ADD_TODO_INPUT_SCHEMA) + server = create_lowlevel_todo_server() + reference = create_lowlevel_todo_server() + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + assert "session_id" in _tool(listed, "add_todo").input_schema["properties"] + + # The schema constant every todo server builds its tools from. Pydantic + # copies only the outermost dict, so `properties` is shared by reference + # with the listed Tool — an in-place injection pass shows up right here. + assert ADD_TODO_INPUT_SCHEMA == pristine + + untracked = await reference.get_request_handler("tools/list").handler(None, None) + for tool in untracked.tools: + assert "session_id" not in tool.input_schema["properties"], tool.name + assert "context" not in tool.input_schema["properties"], tool.name + + +async def test_agent_tracking_injection(capture): + server = create_lowlevel_todo_server() + track(server, "proj_test", AgentCatOptions(enable_agent_tracking=True)) + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + add = _tool(listed, "add_todo") + assert list(add.input_schema["properties"])[-3:] == [ + "session_id", + "agent_id", + "context", + ] + assert "agent_id" in add.input_schema["required"] + assert "session_id" not in add.input_schema["required"] + + result = await client.call_tool( + "add_todo", {"text": "with agent", "agent_id": "opus|claude-code|k3n9x"} + ) + assert result.is_error is False, _text(result) + + event = _call_events(capture)[0] + assert event.tags[AGENTCAT_TAG_AGENT_ID] == "opus|claude-code|k3n9x" + assert event.tags[AGENTCAT_TAG_AGENT_SOURCE] == "supplied" + + +async def test_hook_mode(capture): + server = create_lowlevel_todo_server() + track( + server, + "proj_test", + AgentCatOptions(resolve_session_id=lambda request, extra: "cust-1"), + ) + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + assert listed.tools + for tool in listed.tools: + assert "session_id" not in tool.input_schema.get("properties", {}) + + r1 = await client.call_tool("add_todo", {"text": "hook one"}) + r2 = await client.call_tool("add_todo", {"text": "hook two"}) + assert "[MCP INSTRUCTIONS]" not in _text(r1) + assert "[MCP INSTRUCTIONS]" not in _text(r2) + assert MCP_INSTRUCTIONS_KEY not in (r1.structured_content or {}) + + call_events = _call_events(capture) + expected = derive_session_id("cust-1", "proj_test") + assert [e.session_id for e in call_events] == [expected, expected] + assert call_events[0].tags[AGENTCAT_TAG_SESSION_SOURCE] == "hook" + + +async def test_tracing_disabled_strips_but_publishes_nothing(capture): + server = create_lowlevel_todo_server() + track( + server, + "proj_test", + AgentCatOptions(enable_tracing=False, enable_report_missing=True), + ) + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + add = _tool(listed, "add_todo") + # No handles when tracing is off, but the context parameter is + # independent — so it must still be stripped before the tool runs. + assert "session_id" not in add.input_schema["properties"] + assert "context" in add.input_schema["properties"] + + result = await client.call_tool( + "add_todo", {"text": "quiet", "context": "no tracing"} + ) + assert result.is_error is False, _text(result) + assert "[MCP INSTRUCTIONS]" not in _text(result) + + # get_more_tools is advertised and still answers with tracing off + # (changelog 6.6) — it is a tool, not telemetry. + reported = await client.call_tool("get_more_tools", {"context": "email"}) + assert "Unfortunately" in _text(reported) + + assert capture == [] + + +async def test_error_result_still_carries_the_handle(capture): + server = create_lowlevel_todo_server() + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + result = await client.call_tool("complete_todo", {"id": 999}) + + assert result.is_error is True + # A retry after a failure has to carry the same task, so error results + # decorate on identical terms. + assert MINT_BACK_HEADER in _text(result) + event = _call_events(capture)[0] + assert event.is_error is True + assert event.session_id.startswith("ses_") + # The no-tap error payload: the tool flattened whatever went wrong before + # we saw it, so type is unrecoverable — but the message is the tool's own + # text, not a repr of the result model, and the shape stays SDK-wide. + assert event.error == { + "message": "Todo with ID 999 not found", + "type": None, + "platform": "python", + } + + +async def test_raising_handler_publishes_the_live_exception(capture): + """A lowlevel v2 handler that raises reaches our wrapper with its traceback + intact, so the event keeps the real type.""" + + async def on_call_tool(ctx, params): + raise RuntimeError("kaboom") + + async def on_list_tools(ctx, params): + return types.ListToolsResult( + tools=[ + types.Tool( + name="boom", + description="Raises.", + input_schema={"type": "object", "properties": {}}, + ) + ] + ) + + server = Server("raiser", on_list_tools=on_list_tools, on_call_tool=on_call_tool) + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + # The runner turns a raised handler into a protocol-level error, so the + # agent sees a failed request rather than an isError result. + with pytest.raises(MCPError): + await client.call_tool("boom", {}) + + event = _call_events(capture)[0] + assert event.is_error is True + assert event.error["type"] == "RuntimeError" + assert event.error["message"] == "kaboom" + + +# ── multi round-trip (§6.4) ────────────────────────────────────────────────── + + +def _mrtr_server() -> Server: + """A tool that needs one extra round before it can complete.""" + + async def on_list_tools(ctx, params): + return types.ListToolsResult( + tools=[ + types.Tool( + name="ask", + description="Needs another round.", + input_schema={"type": "object", "properties": {}}, + output_schema={ + "type": "object", + "properties": {"answer": {"type": "string"}}, + }, + ) + ] + ) + + async def on_call_tool(ctx, params): + if params.input_responses is None: + result = types.InputRequiredResult( + request_state="opaque-state", + input_requests={"roots": types.ListRootsRequest(method="roots/list")}, + ) + else: + result = types.CallToolResult( + content=[types.TextContent(type="text", text="done")], + structured_content={"answer": "done"}, + ) + return result + + return Server("mrtr", on_list_tools=on_list_tools, on_call_tool=on_call_tool) + + +async def test_intermediate_mrtr_round_is_tagged_but_never_decorated(capture): + """Two real rounds over the wire: the intermediate one is tagged + `input_required` and reaches the agent as the server built it, the + completing one is tagged `continuation` and carries the mint-back. + + The tag assertions are what this test is for. What stops the intermediate + round being decorated is asserted by + `test_an_intermediate_round_that_carries_content_is_still_undecorated` — + an `InputRequiredResult` has no `content` or `structured_content` to + decorate in the first place, so it cannot show the gate working. + """ + server = _mrtr_server() + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + first = await client.session.call_tool("ask", {}, allow_input_required=True) + assert isinstance(first, types.InputRequiredResult) + assert first.request_state == "opaque-state" + + second = await client.session.call_tool( + "ask", + {}, + input_responses={"roots": types.ListRootsResult(roots=[])}, + request_state=first.request_state, + allow_input_required=True, + ) + + events = _call_events(capture) + assert len(events) == 2 + assert events[0].tags[AGENTCAT_TAG_MRTR] == "input_required" + assert events[1].tags[AGENTCAT_TAG_MRTR] == "continuation" + # The intermediate round still publishes. + assert events[0].session_id.startswith("ses_") + # Only the completing round carries the mint-back. + assert MINT_BACK_HEADER in _text(second) + assert MCP_INSTRUCTIONS_KEY in second.structured_content + + +async def test_input_responses_alone_still_tags_a_continuation(capture): + """`inputResponses` is a continuation witness on its own. + + The round above carries both witnesses, so it can no longer tell which one + fired. This one carries `inputResponses` with **no** `requestState`, which + is the shape a client resuming from persisted responses sends — and the + path that was pinned before `requestState` was added as a second witness. + """ + server = _mrtr_server() + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + await client.session.call_tool( + "ask", + {}, + input_responses={"roots": types.ListRootsResult(roots=[])}, + allow_input_required=True, + ) + + event = _call_events(capture)[0] + assert event.tags[AGENTCAT_TAG_MRTR] == "continuation" + + +def _state_only_mrtr_server() -> Server: + """A tool that asks to be RESUMED rather than asking the client anything. + + Its intermediate round carries `requestState` and no `inputRequests`, so + the SEP-2322 driver retries it after a backoff with no `inputResponses` at + all — the continuation shape that carries only `requestState`, and the one + FastMCP 4's own `InputRequiredResult(request_state=...)` produces. + """ + rounds: list = [] + + async def on_list_tools(ctx, params): + return types.ListToolsResult( + tools=[ + types.Tool( + name="resume", + description="Asks to be resumed.", + input_schema={ + "type": "object", + "properties": {"text": {"type": "string"}}, + }, + ) + ] + ) + + async def on_call_tool(ctx, params): + rounds.append(params.request_state) + if len(rounds) == 1: + return types.InputRequiredResult(request_state="not-done-yet") + return types.CallToolResult( + content=[types.TextContent(type="text", text="done")] + ) + + server = Server( + "resume", on_list_tools=on_list_tools, on_call_tool=on_call_tool + ) + server.mrtr_rounds = rounds # type: ignore[attr-defined] + return server + + +async def test_a_request_state_only_continuation_is_tagged(capture): + """A real client drives the state-only chain, and round two is tagged. + + Driven through `client.call_tool`, which runs the SDK's own SEP-2322 + driver — so the second round is the one the driver built, not one this + test hand-shaped. Keying the tag on `inputResponses` alone left this round + tagged `None`. + """ + server = _state_only_mrtr_server() + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + await client.call_tool("resume", {"text": "hello"}) + + # The driver really did send state and no responses. + assert server.mrtr_rounds == [None, "not-done-yet"] + events = _call_events(capture) + assert [e.tags.get(AGENTCAT_TAG_MRTR) for e in events] == [ + "input_required", + "continuation", + ] + + +async def test_a_supplied_session_id_correlates_every_mrtr_round(capture): + """The handle the agent supplied rides every round of the conversation. + + The SEP-2322 driver replays the ORIGINAL arguments verbatim on each retry + (`mcp/client/_input_required.py`), so a `session_id` the agent supplied on + round one is on the wire for round two as well and both rounds resolve to + it. This is the correlation changelog §6.4 promises, and it is why the + minted-first-call case is the only one that fragments. + """ + server = _state_only_mrtr_server() + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + await client.call_tool( + "resume", {"text": "hello", "session_id": sid("supplied")} + ) + + events = _call_events(capture) + assert len(events) == 2 + assert [e.session_id for e in events] == [sid("supplied"), sid("supplied")] + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == [ + "supplied", + "supplied", + ] + # The customer's tool never sees the handle, on any round. + assert server.mrtr_rounds == [None, "not-done-yet"] + + +async def test_hook_mode_correlates_every_mrtr_round(capture): + """A `resolve_session_id` hook correlates the rounds too. + + The hook runs per request against that round's own request/extra, and every + round of one conversation is the same tool call on the same connection — so + anything a hook keys on returns the same value and derives the same task. + With `supplied` (above) that leaves prompted-mode MINTING as the only + resolution mode an MRTR conversation fragments under. + """ + seen: list = [] + server = _state_only_mrtr_server() + + def hook(request, extra): + seen.append(request) + return "tenant" + + track(server, "proj_test", AgentCatOptions(resolve_session_id=hook)) + + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + await client.call_tool("resume", {"text": "hello"}) + + events = _call_events(capture) + assert len(seen) == 2 and seen[0] is not seen[1] + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == ["hook", "hook"] + derived = derive_session_id("tenant", "proj_test") + assert [e.session_id for e in events] == [derived, derived] + + +async def test_an_mrtr_conversation_is_byte_identical_tracked_or_not(capture): + """Tagging a round changes the event, never the wire (design §12). + + Both rounds of the same real conversation are compared as serialized JSON + against an untracked run of the identical server. The agent supplies a + handle, so nothing is minted and there is no specified decoration to + subtract: any difference at all would be AgentCat altering what the client + is told. `continuation` and an untagged round take the same wire path — + only `input_required` gates decoration — so re-tagging one cannot move it. + """ + + async def rounds_of(tracked: bool) -> list[str]: + seen: list = [] + server = _state_only_mrtr_server() + if tracked: + track(server, "proj_test") + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + # Driven by hand so the INTERMEDIATE round is observable too; the + # SDK's driver resolves it away before `call_tool` returns. + first = await client.session.call_tool( + "resume", + {"text": "hello", "session_id": sid("supplied")}, + allow_input_required=True, + ) + seen.append(first.model_dump_json()) + second = await client.session.call_tool( + "resume", + {"text": "hello", "session_id": sid("supplied")}, + request_state=first.request_state, + allow_input_required=True, + ) + seen.append(second.model_dump_json()) + return seen + + tracked = await rounds_of(True) + untracked = await rounds_of(False) + assert tracked == untracked + # And the conversation really was tagged on the tracked run. + assert [e.tags.get(AGENTCAT_TAG_MRTR) for e in _call_events(capture)] == [ + "input_required", + "continuation", + ] + + +async def test_a_minted_first_round_does_not_yet_correlate(capture): + """KNOWN GAP, pinned deliberately: a minted MRTR chain fragments. + + Round one mints a handle the agent is never told — §6.4 forbids decorating + an intermediate round — and the driver replays round one's arguments + verbatim, so round two carries no handle either and mints its own. Both + ways of correlating them are closed, but for different reasons: remembering + `requestState -> session_id` across rounds is server-side state, which design + §13 forbids ("no server-side session or handle storage"), while carrying + the handle on the wire INSIDE `requestState` is genuinely stateless and + does work — it just rewrites a value the customer's own tool produced, + which design §12 forbids. See task 13.6's report §5. + + Delete this test when that design question is answered; until then it stops + the fragmentation being rediscovered as a surprise. + """ + server = _state_only_mrtr_server() + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + result = await client.call_tool("resume", {"text": "hello"}) + + events = _call_events(capture) + assert len(events) == 2 + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == ["minted", "minted"] + assert events[0].session_id != events[1].session_id + # What the agent is handed is the COMPLETING round's handle, so every call + # after the conversation joins that task. + minted = _text(result).split("session_id=")[1].split(" ")[0] + assert events[1].session_id == minted + + +async def test_an_intermediate_round_that_carries_content_is_still_undecorated( + capture, +): + """`result_type` is what makes a round intermediate, not the result class: + a `CallToolResult` may report `input_required` while already carrying + partial content and structured output. That round must go back exactly as + the customer built it — asserted by object identity, because the mint-back + would otherwise be indistinguishable from a completing round's.""" + returned: list = [] + + async def on_list_tools(ctx, params): + return types.ListToolsResult( + tools=[ + types.Tool( + name="partial", + description="Answers in installments.", + input_schema={"type": "object", "properties": {}}, + output_schema={ + "type": "object", + "properties": {"answer": {"type": "string"}}, + }, + ) + ] + ) + + async def on_call_tool(ctx, params): + result = types.CallToolResult( + content=[types.TextContent(type="text", text="so far so good")], + structured_content={"answer": "partial"}, + result_type="input_required", + ) + returned.append(result) + return result + + server = Server( + "partial", on_list_tools=on_list_tools, on_call_tool=on_call_tool + ) + track(server, "proj_test") + + handler = server.get_request_handler("tools/call").handler + result = await handler( + None, types.CallToolRequestParams(name="partial", arguments={}) + ) + + assert result is returned[0] + assert MCP_INSTRUCTIONS_KEY not in result.structured_content + assert [block.text for block in result.content] == ["so far so good"] + assert _call_events(capture)[0].tags[AGENTCAT_TAG_MRTR] == "input_required" + + +async def test_a_resolved_call_is_never_reused_across_rounds(capture): + """Each round resolves afresh, so the customer's event callbacks see that + round's own params.""" + seen: list = [] + server = _mrtr_server() + track( + server, + "proj_test", + AgentCatOptions( + event_tags=lambda request, extra: seen.append(request) or {"round": "x"} + ), + ) + + async with create_modern_client(server, mode=MODERN) as client: + first = await client.session.call_tool("ask", {}, allow_input_required=True) + await client.session.call_tool( + "ask", + {}, + input_responses={"roots": types.ListRootsResult(roots=[])}, + request_state=first.request_state, + allow_input_required=True, + ) + + assert len(seen) == 2 + assert seen[0] is not seen[1] + assert seen[0].input_responses is None + assert seen[1].input_responses is not None + + +async def test_the_request_clone_keeps_the_continuation_fields(capture): + """Stripping clones the params rather than rebuilding them, so + `input_responses` / `request_state` / `_meta` survive into the handler.""" + seen: list = [] + + async def on_list_tools(ctx, params): + return types.ListToolsResult( + tools=[ + types.Tool( + name="echo", + description="Echo.", + input_schema={ + "type": "object", + "properties": {"text": {"type": "string"}}, + }, + ) + ] + ) + + async def on_call_tool(ctx, params): + seen.append(params) + return types.CallToolResult( + content=[types.TextContent(type="text", text="ok")] + ) + + server = Server("echo", on_list_tools=on_list_tools, on_call_tool=on_call_tool) + track(server, "proj_test") + + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + await client.session.call_tool( + "echo", + {"text": "hi", "session_id": sid("x"), "context": "why"}, + input_responses={"roots": types.ListRootsResult(roots=[])}, + request_state="carried", + allow_input_required=True, + ) + + params = seen[0] + assert params.arguments == {"text": "hi"} + assert params.request_state == "carried" + assert params.input_responses is not None + assert params.meta is not None + + +# ── get_more_tools ownership ───────────────────────────────────────────────── + + +async def test_get_more_tools_keeps_its_own_context_and_publishes(capture): + server = create_lowlevel_todo_server() + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + gmt = _tool(listed, "get_more_tools") + # Its bespoke `context` is a real parameter: still required, still + # described by the tool's own copy — and handles ride alongside. + assert gmt.input_schema["required"] == ["context"] + assert "session_id" in gmt.input_schema["properties"] + assert gmt.annotations.read_only_hint is True + + result = await client.call_tool( + "get_more_tools", {"context": "I need a tool to send emails"} + ) + assert "Unfortunately" in _text(result) + + event = _call_events(capture)[0] + assert event.resource_name == "get_more_tools" + assert event.user_intent == "I need a tool to send emails" + assert event.parameters["arguments"]["context"] == "I need a tool to send emails" + + +async def test_customer_get_more_tools_is_never_hijacked(capture): + """A customer tool that happens to be named `get_more_tools` keeps running. + + We refuse to advertise a second one; we must equally refuse to answer for + the one they wrote (spec §12 — nothing may alter customer tool behavior). + """ + + async def on_list_tools(ctx, params): + return types.ListToolsResult( + tools=[ + types.Tool( + name="get_more_tools", + description="The customer's own tool.", + input_schema={ + "type": "object", + "properties": {"context": {"type": "string"}}, + "required": ["context"], + }, + ) + ] + ) + + async def on_call_tool(ctx, params): + answer = (params.arguments or {}).get("context") + return types.CallToolResult( + content=[ + types.TextContent(type="text", text=f"customer answered: {answer}") + ] + ) + + server = Server( + "collision", on_list_tools=on_list_tools, on_call_tool=on_call_tool + ) + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + # Exactly one, and it is theirs — ours is not advertised alongside it. + assert [t.name for t in listed.tools] == ["get_more_tools"] + assert listed.tools[0].description.startswith("The customer's own tool") + + result = await client.call_tool("get_more_tools", {"context": "mine"}) + + assert result.is_error is False, _text(result) + assert "customer answered: mine" in _text(result) + assert "Unfortunately" not in _text(result) + assert _call_events(capture)[0].resource_name == "get_more_tools" + + +async def test_customer_get_more_tools_survives_a_server_with_no_listing(capture): + """Nothing advertised the tool, so we may not answer for it. + + A server that exposes no `tools/list` at all never runs the pass that would + tell us who owns the name. The gate is stated positively — "AgentCat + advertised it" — so an absent listing keeps the customer's handler. + + Driven through the registered handler rather than a `Client`: the modern + client revalidates every successful result against the tool's declared + output schema and fetches `tools/list` to get it, so no client can reach a + server that serves no listing at all. + """ + + async def on_call_tool(ctx, params): + return types.CallToolResult( + content=[ + types.TextContent( + type="text", text=f"customer answered: {params.name}" + ) + ] + ) + + server = Server("no-listing", on_call_tool=on_call_tool) + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + handler = server.get_request_handler("tools/call").handler + result = await handler( + None, + types.CallToolRequestParams( + name="get_more_tools", arguments={"context": "mine"} + ), + ) + + assert "customer answered: get_more_tools" in _text(result) + assert "Unfortunately" not in _text(result) + # Still tracked: no listing is not a reason to stop publishing. + assert _call_events(capture)[0].resource_name == "get_more_tools" + + +# ── install semantics: idempotence, re-arm, degrade ────────────────────────── + + +async def test_retracking_updates_options_without_double_wrapping(capture): + server = create_lowlevel_todo_server() + track(server, "proj_test", AgentCatOptions(enable_report_missing=False)) + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + assert [t.name for t in listed.tools].count("get_more_tools") == 1 + add = _tool(listed, "add_todo") + assert list(add.input_schema["properties"]) == ["text", "session_id", "context"] + + # A second, stacked wrapper would inject session_id in the inner pass and + # then skip it in the outer one — leaving it out of the strip registry + # and handing the customer's tool a parameter it never declared. + result = await client.call_tool( + "add_todo", {"text": "retracked", "session_id": sid("retrack")} + ) + assert result.is_error is False, _text(result) + + assert len(_call_events(capture)) == 1 + assert _call_events(capture)[0].session_id == sid("retrack") + + +def test_a_tracked_server_is_collectable_once_the_customer_drops_it(): + """Nothing AgentCat holds may outlive the server. + + This era's documented topology is a fresh server per request with + `track()` inside the factory (cross-SDK changelog §6.8), so per-server + state that survives the server is not a bounded cost — it is one immortal + `Server`, handler table, deep-copied schema set and registry pair per + request. A module-level `WeakKeyDictionary` does not save you: every value + an adapter files there closes over the server, so the value keeps its own + weak key alive. + """ + alive = [] + for _ in range(3): + server = create_lowlevel_todo_server() + track(server, "proj_test") + alive.append(weakref.ref(server)) + del server + + gc.collect() + assert [ref() for ref in alive] == [None, None, None] + + +def test_a_tracked_mcpserver_is_collectable_with_its_lowlevel_server(): + """The adapter is installed on `_lowlevel_server`, so both halves have to + go — a retained lowlevel server pins the MCPServer that owns it, and its + tool manager with it.""" + server = create_mcpserver_todo_server() + track(server, "proj_test") + facade, lowlevel = weakref.ref(server), weakref.ref(server._lowlevel_server) + del server + + gc.collect() + assert (facade(), lowlevel()) == (None, None) + + +def test_a_server_that_cannot_hold_state_is_left_untracked(log_sink): + """State on the server is what keeps a repeated `track()` idempotent, so a + server that refuses the attribute is refused rather than tracked with a + wrapper we could never recognize again.""" + + class Slotted: + # `__weakref__` so it gets as far as the adapter: the tracking-data map + # is weakly keyed and would refuse it one step earlier otherwise. + __slots__ = ("__weakref__", "_request_handlers", "add_request_handler") + + def __init__(self) -> None: + self._request_handlers: dict = {} + self.add_request_handler = lambda *a: None + + server = Slotted() + source = create_lowlevel_todo_server("slotted-source") + server._request_handlers["tools/call"] = source.get_request_handler("tools/call") + + assert track(server, "proj_test") is server + assert server._request_handlers["tools/call"] is source.get_request_handler( + "tools/call" + ) + assert any("could not store AgentCat state" in line for line in log_sink), log_sink + + +async def test_options_are_read_per_request_not_captured_at_install(capture): + """The wrappers re-read the tracking data on every call. + + Captured once at install, a wrapper would serve the first `track()`'s + options forever — so anything that replaces a server's data without + re-installing (a re-`track()` racing a request, a restore) would silently + not take effect. + """ + from agentcat.modules.internal import set_server_tracking_data + from agentcat.types import AgentCatData + + server = create_lowlevel_todo_server() + track(server, "proj_test", AgentCatOptions(enable_tracing=False)) + set_server_tracking_data( + server, + AgentCatData( + project_id="proj_test", options=AgentCatOptions(enable_tracing=True) + ), + ) + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + assert "session_id" in _tool(listed, "add_todo").input_schema["properties"] + result = await client.call_tool("add_todo", {"text": "live"}) + assert result.is_error is False, _text(result) + + assert len(_call_events(capture)) == 1 + + +async def test_handlers_registered_after_track_are_still_wrapped(capture): + """`track()` on a server with no tools handlers yet still takes effect: the + registration seam is re-armed, so a later `add_request_handler` lands + wrapped.""" + server = Server("late") + track(server, "proj_test") + + late = create_lowlevel_todo_server("late-source") + for method in ("tools/list", "tools/call"): + entry = late.get_request_handler(method) + server.add_request_handler(method, entry.params_type, entry.handler) + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + assert "session_id" in _tool(listed, "add_todo").input_schema["properties"] + result = await client.call_tool("add_todo", {"text": "late"}) + assert result.is_error is False, _text(result) + assert MINT_BACK_HEADER in _text(result) + + assert len(_call_events(capture)) == 1 + + +async def test_reregistering_a_handler_after_track_rewraps_it(capture): + """A customer who replaces their `tools/call` handler after `track()` does + not silently lose tracking.""" + server = create_lowlevel_todo_server() + track(server, "proj_test") + + replacement = create_lowlevel_todo_server("replacement") + entry = replacement.get_request_handler("tools/call") + server.add_request_handler("tools/call", entry.params_type, entry.handler) + + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + result = await client.call_tool("add_todo", {"text": "replaced"}) + assert result.is_error is False, _text(result) + assert MINT_BACK_HEADER in _text(result) + + assert len(_call_events(capture)) == 1 + + +async def test_re_arm_is_not_stacked_by_a_second_track(capture): + """Two `track()` calls leave one wrapper, not two, even on a handler + registered after both.""" + server = Server("double") + track(server, "proj_test") + track(server, "proj_test") + + source = create_lowlevel_todo_server("source") + for method in ("tools/list", "tools/call"): + entry = source.get_request_handler(method) + server.add_request_handler(method, entry.params_type, entry.handler) + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + add = _tool(listed, "add_todo") + # A stacked pair would inject session_id twice or leave it unstrippable. + assert list(add.input_schema["properties"]) == ["text", "session_id", "context"] + result = await client.call_tool("add_todo", {"text": "twice"}) + assert result.is_error is False, _text(result) + + assert len(_call_events(capture)) == 1 + + +async def test_resolution_failure_degrades_to_an_untraced_call(capture, log_sink): + """A blown resolver must not fail the customer's call — and the injected + parameters are still stripped on the way through.""" + server = create_lowlevel_todo_server() + track(server, "proj_test", AgentCatOptions(enable_report_missing=True)) + + from agentcat.modules.adapters import lowlevel_v2 + + async def boom(*args, **kwargs): + raise RuntimeError("resolver exploded") + + original = lowlevel_v2.resolve_call + lowlevel_v2.resolve_call = boom + try: + async with create_modern_client(server, mode=MODERN) as client: + await client.list_tools() + result = await client.call_tool( + "add_todo", {"text": "degraded", "context": "why"} + ) + # A tool AgentCat advertised must still be answered by AgentCat, or + # the agent gets "unknown tool" for something it was just offered. + reported = await client.call_tool("get_more_tools", {"context": "email"}) + finally: + lowlevel_v2.resolve_call = original + + assert result.is_error is False, _text(result) + assert "Unfortunately" in _text(reported) + assert _call_events(capture) == [] + assert any("running it untraced" in line for line in log_sink), log_sink + + +# ── MCPServer ──────────────────────────────────────────────────────────────── + + +async def test_mcpserver_end_to_end(capture): + """`MCPServer` is served through its `_lowlevel_server` by the same + adapter.""" + server = create_mcpserver_todo_server() + assert track(server, "proj_test") is server + + async with create_modern_client(server, mode=MODERN) as client: + listed = await client.list_tools() + add = _tool(listed, "add_todo") + assert list(add.input_schema["properties"])[-2:] == ["session_id", "context"] + + result = await client.call_tool( + "add_todo", {"text": "via mcpserver", "context": "why"} + ) + assert result.is_error is False, _text(result) + text = _text(result) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + + # `add_todo(text: str)` is typed and this manager drops an undeclared + # argument silently, so the delivered dict is the only place a failed + # strip would show. See `tests.test_utils.delivery`. + assert delivered_arguments_for(server, "add_todo") == [{"text": "via mcpserver"}] + + events = _call_events(capture) + assert len(events) == 1 + assert events[0].resource_name == "add_todo" + assert events[0].session_id == minted + # Server identity is captured off the lowlevel object at track() time. + assert events[0].tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + + +async def test_mcpserver_tracking_is_keyed_on_the_lowlevel_server(capture): + server = create_mcpserver_todo_server() + track(server, "proj_test") + + from agentcat.modules.internal import get_server_tracking_data + + assert get_server_tracking_data(server._lowlevel_server) is not None + + +class _DevLineServer: + """The 2.x shape from before `HandlerEntry` and the public seam landed. + + Read off the vendored upstream checkout + (`model-context-protocol-sdks/python-sdk`, v1.25.0-156-g3d7b311): bare + callables in `_request_handlers`, registration through a private + `_add_request_handler(method, handler)`. The classifier accepts it, so the + adapter has to survive it — otherwise a build shipping that spelling would + be classified, then explode or half-install. + """ + + def __init__(self) -> None: + self._request_handlers: dict = {} + + def _add_request_handler(self, method, handler) -> None: + self._request_handlers[method] = handler + + +async def test_the_pre_handler_entry_shape_installs_through_its_private_seam( + capture, +): + server = _DevLineServer() + source = create_lowlevel_todo_server("dev-line-source") + server._add_request_handler( + "tools/list", source.get_request_handler("tools/list").handler + ) + + track(server, "proj_test") + + # Registered after track(): it lands wrapped through the private seam. + server._add_request_handler( + "tools/call", source.get_request_handler("tools/call").handler + ) + + listed = await server._request_handlers["tools/list"](None, None) + assert "session_id" in _tool(listed, "add_todo").input_schema["properties"] + + result = await server._request_handlers["tools/call"]( + None, + types.CallToolRequestParams( + name="add_todo", arguments={"text": "dev line", "context": "why"} + ), + ) + assert result.is_error is False, _text(result) + assert MINT_BACK_HEADER in _text(result) + assert _call_events(capture)[0].resource_name == "add_todo" + + +class _DualSeamServer: + """A build exposing BOTH registration spellings. + + The natural refactor shape when a private method is promoted: a public + wrapper delegating to the private one, both live at once. Whichever seam a + customer registers through has to end up wrapped — patching only the first + name found would silently drop re-arm for the other. + """ + + def __init__(self) -> None: + self._request_handlers: dict = {} + + def _add_request_handler(self, method, params_type, handler) -> None: + entry = _DevLineEntry(params_type, handler) + self._request_handlers[method] = entry + + def add_request_handler(self, method, params_type, handler) -> None: + self._add_request_handler(method, params_type, handler) + + +@dataclasses.dataclass(frozen=True) +class _DevLineEntry: + params_type: type + handler: object + + +@pytest.mark.parametrize("seam", ["add_request_handler", "_add_request_handler"]) +async def test_every_registration_seam_is_re_armed(capture, seam): + server = _DualSeamServer() + track(server, "proj_test") + + source = create_lowlevel_todo_server("dual-seam-source") + for method in ("tools/list", "tools/call"): + entry = source.get_request_handler(method) + getattr(server, seam)(method, entry.params_type, entry.handler) + + listed = await server._request_handlers["tools/list"].handler(None, None) + assert "session_id" in _tool(listed, "add_todo").input_schema["properties"] + + result = await server._request_handlers["tools/call"].handler( + None, types.CallToolRequestParams(name="add_todo", arguments={"text": "dual"}) + ) + assert result.is_error is False, _text(result) + assert MINT_BACK_HEADER in _text(result) + # One event, not two: the public seam delegates to the private one, so both + # patches fire on a public registration and the re-swap must stay idempotent. + assert len(_call_events(capture)) == 1 + + +async def test_a_registration_record_keeps_every_field_it_carries(capture): + """The record is rebuilt, not mutated (`HandlerEntry` is frozen), so it must + carry fields by name — a positional rebuild would silently drop anything + upstream adds beyond `params_type` and `handler`.""" + + @dataclasses.dataclass(frozen=True) + class _RicherEntry: + params_type: type + handler: object + title: str = "customer title" + + server = _DualSeamServer() + source = create_lowlevel_todo_server("richer-source") + entry = source.get_request_handler("tools/call") + server._request_handlers["tools/call"] = _RicherEntry( + entry.params_type, entry.handler, title="do not lose me" + ) + + track(server, "proj_test") + + installed = server._request_handlers["tools/call"] + assert installed.handler is not entry.handler + assert installed.params_type is entry.params_type + assert installed.title == "do not lose me" + + +# ── detection ──────────────────────────────────────────────────────────────── + + +def test_the_installed_modern_sdk_classifies_as_a_v2_flavor(): + """Every other detection test builds doubles from what we *believe* each + generation looks like. This one asks the SDK actually installed here, so an + upstream shape change surfaces as a failure rather than as a silently + untracked fleet.""" + from agentcat.modules.detection import ServerFlavor, detect_server + + lowlevel = Server("bare") + detected = detect_server(lowlevel) + assert detected.flavor is ServerFlavor.LOWLEVEL_V2 + assert detected.lowlevel is lowlevel + + mcpserver = MCPServer("bare") + detected = detect_server(mcpserver) + assert detected.flavor is ServerFlavor.MCPSERVER_V2 + assert detected.lowlevel is mcpserver._lowlevel_server + + +def test_track_never_raises(): + sentinel = object() + assert track(sentinel, None) is sentinel + assert track(sentinel, "proj_test") is sentinel + server = create_lowlevel_todo_server() + assert track(server, None) is server + assert track(server, "proj_test", {"debug_mode": True}) is server diff --git a/tests/test_mcp_version_compatibility.py b/tests/test_mcp_version_compatibility.py deleted file mode 100644 index fc2eb11..0000000 --- a/tests/test_mcp_version_compatibility.py +++ /dev/null @@ -1,37 +0,0 @@ -"""Test MCP Version Compatibility.""" - -import pytest - -from agentcat.modules.compatibility import is_compatible_server -from mcp import ClientSession - -from .test_utils.client import create_test_client -from .test_utils.todo_server import create_todo_server - - -class TestMCPVersionCompatibility: - """Test MCP Version Compatibility.""" - - def test_compatible_with_currently_installed_mcp_version(self): - """Should be compatible with currently installed MCP version.""" - # Create a new server instance - server = create_todo_server() - - # Test compatibility using is_compatible_server - result = is_compatible_server(server) - assert result is True - - @pytest.mark.asyncio - async def test_tool_call_via_client(self): - """Test making a tool call using the client helper.""" - # Create a new server instance - server = create_todo_server() - async with create_test_client(server) as client: - result = await client.call_tool("add_todo", {"text": "Test todo item"}) - - # Call the add_todo tool via client - assert result.content[0].text == 'Added todo: "Test todo item" with ID 1' - - # Verify by listing todos - result = await client.call_tool("list_todos") - assert "1: Test todo item ○" in result.content[0].text diff --git a/tests/test_multiple_servers.py b/tests/test_multiple_servers.py index 1c009a1..2b3146f 100644 --- a/tests/test_multiple_servers.py +++ b/tests/test_multiple_servers.py @@ -64,7 +64,7 @@ def capture_event(publish_event_request): # Should have get_more_tools assert "get_more_tools" in tool_names1 - # Should have context in tool parameters + # Should have context in tool parameters — required, as in 1.x. add_todo_tool1 = next(t for t in tools1.tools if t.name == "add_todo") assert "context" in add_todo_tool1.inputSchema["properties"] assert "context" in add_todo_tool1.inputSchema["required"] @@ -80,6 +80,8 @@ def capture_event(publish_event_request): # Should NOT have context in tool parameters add_todo_tool2 = next(t for t in tools2.tools if t.name == "add_todo") assert "context" not in add_todo_tool2.inputSchema.get("properties", {}) + # ...but handles are independent of the context parameter. + assert "session_id" in add_todo_tool2.inputSchema["properties"] # Test server3: should have context and get_more_tools but no tracing async with create_test_client(server3) as client3: @@ -89,9 +91,10 @@ def capture_event(publish_event_request): # Should have get_more_tools assert "get_more_tools" in tool_names3 - # Should have context in tool parameters + # Context injection is independent of tracing; handles are not. add_todo_tool3 = next(t for t in tools3.tools if t.name == "add_todo") assert "context" in add_todo_tool3.inputSchema["properties"] + assert "session_id" not in add_todo_tool3.inputSchema["properties"] # Clear events before testing captured_events.clear() @@ -319,8 +322,8 @@ def capture_event(publish_event_request): def identify1(request, server): from agentcat.types import UserIdentity - if hasattr(request, "params") and hasattr(request.params, "arguments"): - args = request.params.arguments + if hasattr(request, "arguments"): + args = request.arguments if "user" in args: return UserIdentity( user_id=f"s1_{args['user']}", @@ -333,8 +336,8 @@ def identify1(request, server): def identify2(request, server): from agentcat.types import UserIdentity - if hasattr(request, "params") and hasattr(request.params, "arguments"): - args = request.params.arguments + if hasattr(request, "arguments"): + args = request.arguments if "client_id" in args: return UserIdentity( user_id=f"s2_{args['client_id']}", diff --git a/tests/test_options_v2.py b/tests/test_options_v2.py new file mode 100644 index 0000000..f49db98 --- /dev/null +++ b/tests/test_options_v2.py @@ -0,0 +1,14 @@ +from agentcat.types import AgentCatOptions, CustomEventData + +from .test_utils import sid + + +def test_v2_option_defaults(): + o = AgentCatOptions() + assert o.enable_agent_tracking is False + assert o.resolve_session_id is None + + +def test_custom_event_data_keys(): + d: CustomEventData = {"session_id": sid("x"), "is_error": False, "tags": {"a": "b"}} + assert d["session_id"] == sid("x") diff --git a/tests/test_publish_custom_event.py b/tests/test_publish_custom_event.py new file mode 100644 index 0000000..8c05ec2 --- /dev/null +++ b/tests/test_publish_custom_event.py @@ -0,0 +1,447 @@ +"""`publish_custom_event` — the one event v2 publishes by hand. + +TS parity: `publishCustomEvent` (TS `src/index.ts:363`), design §3.4. The task +attribution is VERBATIM in both forms: whatever the caller supplies lands in +`Event.session_id` untouched — never trimmed, prefixed, validated or derived. + +Pure Python fakes for everything the semantics can be shown on: this module +has to run under both SDK eras. The one exception is the last section, which +walks every real server shape the installed dependency set can build — because +"is this a tracked server?" is answered by a key derivation that differs per +facade, and no fake can be wrong about it in the way a real one was. + +The published event is inspected at the queue, so every test asserts what +actually goes on the wire rather than that the call returned. +""" + +from typing import Any + +import pytest + +import agentcat +from agentcat.modules import event_queue as event_queue_module +from agentcat.modules.internal import ( + reset_server_tracking_data, + set_server_tracking_data, +) +from agentcat.types import ( + AgentCatData, + AgentCatOptions, + EventType, + UnredactedEvent, +) + +from .test_utils.flavors import flavors + + +class FakeServer: + """A weakref-able stand-in for a tracked server. No MCP anywhere.""" + + +class FakeQueue: + """The global event queue, replaced so nothing leaves the process.""" + + def __init__(self) -> None: + self.events: list[UnredactedEvent] = [] + + def add(self, event: UnredactedEvent) -> None: + self.events.append(event) + + +@pytest.fixture +def published(monkeypatch: pytest.MonkeyPatch) -> list[UnredactedEvent]: + """Every event that reached the queue, in order.""" + fake = FakeQueue() + monkeypatch.setattr(event_queue_module, "event_queue", fake) + return fake.events + + +@pytest.fixture +def tracked() -> Any: + """A server tracked to `proj_tracked`, cleaned up after the test.""" + server = FakeServer() + set_server_tracking_data( + server, + AgentCatData( + project_id="proj_tracked", + options=AgentCatOptions(), + server_name="todo-server", + server_version="4.2.0", + ), + ) + yield server + reset_server_tracking_data(server) + + +@pytest.fixture +def logged(monkeypatch: pytest.MonkeyPatch) -> list[str]: + """Lines the SDK logged, so a no-op can be shown to be a loud one.""" + lines: list[str] = [] + monkeypatch.setattr(agentcat, "write_to_log", lambda msg: lines.append(str(msg))) + return lines + + +# ── Task attribution: verbatim, both forms ─────────────────────────────────── + + +def test_string_form_uses_the_string_verbatim(published): + """A caller's own correlation ID is the session ID. No `ses_`, no minting.""" + agentcat.publish_custom_event("order-9f2c/checkout", "proj_abc") + + assert len(published) == 1 + assert published[0].session_id == "order-9f2c/checkout" + + +def test_session_id_in_event_data_beats_the_string(published): + agentcat.publish_custom_event( + "ignored-correlation-id", "proj_abc", {"session_id": "ses_from_event_data"} + ) + + assert published[0].session_id == "ses_from_event_data" + + +def test_tracked_server_uses_event_data_session_id_verbatim(published, tracked): + agentcat.publish_custom_event(tracked, "proj_abc", {"session_id": "ses_LIVE"}) + + assert published[0].session_id == "ses_LIVE" + + +def test_tracked_server_without_a_session_id_publishes_untethered(published, tracked): + """Handles are per-request in v2, so a tracked server has no ambient task. + + The event still publishes — it just lands untethered rather than being + attributed to a task that was never supplied. + """ + agentcat.publish_custom_event(tracked, "proj_abc", {"resource_name": "cron"}) + + assert len(published) == 1 + assert published[0].session_id is None + assert published[0].resource_name == "cron" + + +def test_an_empty_session_id_is_no_task_at_all(published, tracked): + agentcat.publish_custom_event("", "proj_abc") + agentcat.publish_custom_event(tracked, "proj_abc", {"session_id": ""}) + + assert len(published) == 2 + assert all(event.session_id is None for event in published) + + +def test_a_non_string_session_id_is_ignored_never_stringified(published, tracked): + """Verbatim cuts both ways: what cannot be sent as-is is not derived.""" + agentcat.publish_custom_event("fallback-id", "proj_abc", {"session_id": 42}) + agentcat.publish_custom_event(tracked, "proj_abc", {"session_id": {"a": 1}}) + + assert published[0].session_id == "fallback-id" + assert published[1].session_id is None + + +# ── Event shape ────────────────────────────────────────────────────────────── + + +def test_event_type_is_agentcat_custom(published, tracked): + agentcat.publish_custom_event("ses_T", "proj_abc") + agentcat.publish_custom_event(tracked, "proj_abc") + + assert [event.event_type for event in published] == ["agentcat:custom"] * 2 + assert published[0].event_type == EventType.AGENTCAT_CUSTOM.value + + +def test_custom_event_data_reaches_the_event(published): + agentcat.publish_custom_event( + "ses_T", + "proj_abc", + { + "resource_name": "checkout", + "parameters": {"cart": 3}, + "response": {"status": "ok"}, + "message": "order confirmed", + "duration": 1234, + "is_error": True, + "error": {"message": "card declined", "code": "ERR_001"}, + "tags": {"env": "prod"}, + "properties": {"amount": 42.5}, + }, + ) + + event = published[0] + assert event.resource_name == "checkout" + assert event.parameters == {"cart": 3} + assert event.response == {"status": "ok"} + # `message` is the human explanation — the same field intent capture uses. + assert event.user_intent == "order confirmed" + assert event.duration == 1234 + assert event.is_error is True + assert event.error == {"message": "card declined", "code": "ERR_001"} + assert event.tags == {"env": "prod"} + assert event.properties == {"amount": 42.5} + + +def test_event_data_is_optional(published, tracked): + agentcat.publish_custom_event(tracked, "proj_abc") + + assert len(published) == 1 + assert published[0].event_type == "agentcat:custom" + assert published[0].timestamp is not None + + +def test_tags_are_validated_and_bad_entries_dropped(published): + """Customer tags ride the same validator every other event's tags do.""" + agentcat.publish_custom_event( + "ses_T", + "proj_abc", + {"tags": {"env": "prod", "bad key!": "x", "numeric": 7}}, + ) + + assert published[0].tags == {"env": "prod"} + + +def test_tags_that_are_not_a_dict_are_dropped_out_loud(published, logged): + """Every other degradation here logs; this one used to be the exception.""" + agentcat.publish_custom_event("ses_T", "proj_abc", {"tags": "env=prod"}) + + assert published[0].tags is None + assert any("tags" in line for line in logged) + + +# ── Nothing a caller can pass may make the event vanish ────────────────────── + + +def test_a_non_dict_response_is_kept_not_dropped(published): + """`PublishEventRequest.response` is `Optional[Dict[str, Any]]`. + + A non-dict fails pydantic construction, and construction failures are + swallowed at the publish site — so an unwrapped string response would take + the whole event down with it, silently. `CustomEventData["response"]` is + typed `Any` and comes straight from the caller, so a string, a list or a + number is a plausible input, not a bug to be punished. + """ + agentcat.publish_custom_event("ses_T", "proj_abc", {"response": "shipped"}) + + assert len(published) == 1 + assert published[0].response == {"value": "shipped"} + + +def test_non_dict_parameters_and_properties_are_kept(published): + agentcat.publish_custom_event( + "ses_T", "proj_abc", {"parameters": [1, 2], "properties": "why"} + ) + + assert published[0].parameters == {"value": [1, 2]} + assert published[0].properties == {"value": "why"} + + +def test_a_non_dict_error_becomes_a_message(published): + """`error` has a known shape (`ErrorData`): the message is what consumers read.""" + agentcat.publish_custom_event( + "ses_T", "proj_abc", {"is_error": True, "error": "card declined"} + ) + + assert published[0].is_error is True + assert published[0].error == {"message": "card declined"} + + +@pytest.mark.parametrize( + ("event_data", "wire_field"), + [ + ({"duration": 12.5}, "duration"), + ({"duration": True}, "duration"), + ({"is_error": 1}, "is_error"), + ({"resource_name": 42}, "resource_name"), + ({"message": {"not": "a string"}}, "user_intent"), + ({"tags": "not-a-dict"}, "tags"), + ], +) +def test_a_mistyped_field_costs_that_field_not_the_event( + published, event_data, wire_field +): + """Strict wire types (`StrictInt`/`StrictBool`/`StrictStr`) reject a near + miss outright, so the field is dropped — not coerced — and the event still + publishes.""" + agentcat.publish_custom_event("ses_T", "proj_abc", event_data) + + assert len(published) == 1 + assert published[0].session_id == "ses_T" + assert getattr(published[0], wire_field) is None + + +def test_custom_events_survive_the_generated_clients_stale_event_type_enum(): + """`agentcat_api` 1.0.0 validates `event_type` against a spec enum that + predates `agentcat:custom`, so the generated model rejects the very event + this API exists to publish. `Event` overrides that check with the SDK's own + `EventType`, which is the source of truth for what v2 publishes.""" + for event_type in EventType: + assert UnredactedEvent(event_type=event_type.value).event_type == ( + event_type.value + ) + + +# ── Fire-and-forget: never raises, whatever it is handed ───────────────────── + + +@pytest.mark.parametrize( + "first_argument", + [None, 42, {"not": "a server"}, ["nope"], FakeServer()], + ids=["none", "int", "dict", "list", "untracked-server"], +) +def test_a_bad_first_argument_never_raises(published, logged, first_argument): + agentcat.publish_custom_event(first_argument, "proj_abc") + + assert published == [] + assert logged, "a dropped event must say so in the log" + + +def test_a_non_dict_event_data_never_raises(published): + agentcat.publish_custom_event("ses_T", "proj_abc", "not-event-data") + + assert len(published) == 1 + assert published[0].session_id == "ses_T" + + +def test_a_queue_that_blows_up_never_raises(monkeypatch, logged, tracked): + class Exploding: + def add(self, event: UnredactedEvent) -> None: + raise RuntimeError("queue is on fire") + + monkeypatch.setattr(event_queue_module, "event_queue", Exploding()) + + agentcat.publish_custom_event("ses_T", "proj_abc") + agentcat.publish_custom_event(tracked, "proj_abc") + + assert logged + + +@pytest.mark.parametrize("project_id", ["", None, 42], ids=["empty", "none", "int"]) +def test_the_string_form_needs_a_project_id(published, logged, project_id): + """Nothing else can supply one: a session ID string carries no tracking data.""" + agentcat.publish_custom_event("ses_T", project_id) + + assert published == [] + assert any("project_id" in line for line in logged) + + +def test_a_mistyped_project_id_never_costs_a_tracked_event(published, tracked): + """The tracked server's own project answers for it.""" + agentcat.publish_custom_event(tracked, 42, {"session_id": "ses_T"}) + + assert published[0].project_id == "proj_tracked" + + +# ── Project and SDK attribution ────────────────────────────────────────────── + + +def test_the_string_form_carries_the_project_it_was_given(published): + agentcat.publish_custom_event("ses_T", "proj_from_argument") + + assert published[0].project_id == "proj_from_argument" + assert published[0].sdk_language.startswith("Python ") + assert published[0].agentcat_version == agentcat.__version__ + + +def test_the_tracked_form_takes_the_project_from_the_tracked_server(published, tracked): + """The server was tracked to a project; that is the event's project, and + the server identity captured at `track()` time rides along with it.""" + agentcat.publish_custom_event(tracked, "", {"session_id": "ses_T"}) + + event = published[0] + assert event.project_id == "proj_tracked" + assert event.server_name == "todo-server" + assert event.server_version == "4.2.0" + assert event.sdk_language.startswith("Python ") + + +def test_a_server_tracked_with_tracing_off_publishes_nothing(published, logged): + """`enable_tracing=False` silences a server's tool calls in every adapter. + + This entry point does not reach an adapter, and `publish_event` has no gate + of its own (TS keeps one inside `publishEvent`), so it carries the gate + itself: a customer who turned tracing off does not start emitting a new + event type because they called a new API. + """ + server = FakeServer() + set_server_tracking_data( + server, + AgentCatData( + project_id="proj_tracked", + options=AgentCatOptions(enable_tracing=False), + ), + ) + try: + agentcat.publish_custom_event(server, "proj_tracked", {"session_id": "ses_T"}) + finally: + reset_server_tracking_data(server) + + assert published == [] + assert any("enable_tracing" in line for line in logged) + + +def test_the_string_form_is_not_gated_on_a_servers_tracing_flag(published): + """A session ID string carries no server, so there are no options to consult — + the same place TS lands, since its string form bypasses `publishEvent`.""" + agentcat.publish_custom_event("ses_T", "proj_abc") + + assert len(published) == 1 + + +def test_the_tracked_form_applies_the_customers_redaction(published): + """A tracked custom event goes through the same publish path every + tool-call event does, so the customer's redaction hook is attached.""" + server = FakeServer() + set_server_tracking_data( + server, + AgentCatData( + project_id="proj_tracked", + options=AgentCatOptions( + redact_sensitive_information=lambda text: "REDACTED" + ), + ), + ) + try: + agentcat.publish_custom_event(server, "proj_tracked", {"session_id": "ses_T"}) + finally: + reset_server_tracking_data(server) + + assert published[0].redaction_fn is not None + + +# ── Every real server shape resolves ───────────────────────────────────────── + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +def test_a_tracked_server_of_any_flavor_resolves_to_its_own_tracking_data( + flavor, published +): + """The customer holds the object they handed `track()`, not what it wraps. + + On both official facades that object is NOT where the data was stored: the + adapter is installed on the lowlevel server underneath, and the data is + filed there with it. TS unwraps `serverOrSessionId.server` at the entry + point; Python re-derives the key inside `_get_server_key`, and nothing + pinned that it did so for every facade — `MCPServer` was missing, and a + custom event published against one was silently dropped. + """ + built = flavor.build("custom-event") + agentcat.track(built.server, "proj_flavor", AgentCatOptions()) + try: + agentcat.publish_custom_event( + built.server, "proj_ignored", {"session_id": "ses_custom", "message": "hi"} + ) + finally: + reset_server_tracking_data(built.server) + + assert len(published) == 1, "the server did not resolve to its tracking data" + event = published[0] + assert event.event_type == EventType.AGENTCAT_CUSTOM.value + assert event.session_id == "ses_custom" + # The project captured at track() time wins over the argument — which is + # only observable if the tracked server really was found. + assert event.project_id == "proj_flavor" + + +# ── Public API ─────────────────────────────────────────────────────────────── + + +def test_exported_from_the_package(): + assert "publish_custom_event" in agentcat.__all__ + assert "CustomEventData" in agentcat.__all__ + assert callable(agentcat.publish_custom_event) diff --git a/tests/test_rebuild_on_demand.py b/tests/test_rebuild_on_demand.py new file mode 100644 index 0000000..88f28f8 --- /dev/null +++ b/tests/test_rebuild_on_demand.py @@ -0,0 +1,253 @@ +"""Registry rebuild-on-demand, and what happens when it cannot happen. + +A 2026 factory builds a fresh server per request, so a `tools/call` routinely +lands on an instance that has never served a `tools/list` — and the strip +registries only exist because a listing built them. The engine answers by +rebuilding them from the adapter's own list source (changelog §6.3); the +injection pipeline is deterministic, so a rebuilt registry matches what any +listing instance advertised. + +`tests/test_callpath.py` pins that contract at the unit level. This module +pins it per flavor, end to end, on the two things only a real server can show: +that the CUSTOMER's tool body receives the stripped arguments, and that the +structured mirror is gated on the rebuilt output registry. + +The failure path is the other half. When the list source is down there is +nothing to rebuild from, and the engine falls back to the heuristic strip — +which must still keep `get_more_tools`' own `context`, because on that one +tool `context` is a real parameter rather than something AgentCat injected. +""" + +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import ( + AGENTCAT_TAG_SESSION_SOURCE, + CONTEXT_PARAM, + GET_MORE_TOOLS_NAME, + MCP_INSTRUCTIONS_KEY, + SESSION_ID_PARAM, +) + +from .test_utils import sid +from .test_utils.flavors import flavors, tracking_data + +SUPPLIED = sid("supplied") + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +@pytest.fixture +def log_sink(): + """Everything `write_to_log` tees to diagnostics, as the collector sees it.""" + from agentcat.modules import logging as agentcat_logging + + previous = agentcat_logging._diagnostics_sink + lines: list[str] = [] + agentcat_logging.set_diagnostics_sink(lines.append) + yield lines + agentcat_logging.set_diagnostics_sink(previous) + + +def _logged(log_sink, fragment: str) -> bool: + return any(fragment in line for line in log_sink) + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_a_call_before_any_listing_rebuilds_the_registries( + flavor, capture, log_sink +): + """No listing has ever run, and the call still behaves as if one had. + + Three things follow from the rebuild, and all three are what a customer + would notice if it stopped happening: their tool body sees only its own + arguments, the event records the call as the agent made it, and the mirror + lands because the rebuilt output registry says the schema declares it. + """ + built = flavor.build("rebuild") + track(built.server, "proj_test", AgentCatOptions()) + data = tracking_data(built.server) + assert data.injected_params_registry is None, "something listed before the call" + + result = await flavor.call_unlisted( + built.server, + "echo", + {"text": "hi", SESSION_ID_PARAM: SUPPLIED, CONTEXT_PARAM: "why I called"}, + ) + + assert _logged(log_sink, "Rebuilt injection registries on demand") + # What the customer's tool layer was actually HANDED — read at the tool + # manager on the facade flavors, whose typed bodies cannot report an + # argument the SDK silently dropped on the way in, and from the raw + # argument dict on the lowlevel ones. Either way an injected parameter that + # survived the strip shows up here. + assert built.seen == [("echo", {"text": "hi"})] + # Rebuilt from the adapter's list source, and stored for the next call. + assert data.injected_params_registry is not None + assert data.injected_params_registry["echo"] == {SESSION_ID_PARAM, CONTEXT_PARAM} + # get_more_tools is in the rebuilt view too — that view is also what + # settles whether AgentCat may advertise it at all. + assert data.injected_params_registry[GET_MORE_TOOLS_NAME] == {SESSION_ID_PARAM} + # The mirror is gated on the rebuilt OUTPUT registry, and `echo` is in it. + assert data.output_injection_registry is not None + assert "echo" in data.output_injection_registry + assert result.structured[MCP_INSTRUCTIONS_KEY][SESSION_ID_PARAM] == SUPPLIED + + event = capture[0] + assert event.session_id == SUPPLIED + # Raw, unstripped: the event records the call as the agent made it. + assert event.parameters["arguments"][CONTEXT_PARAM] == "why I called" + assert event.user_intent == "why I called" + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_the_rebuild_recovers_a_customers_own_session_id_ownership( + flavor, capture +): + """Ownership is rebuilt too, not just the strip registry. + + This is the stateless-HTTP shape: on mcp 2.x every request can reach a + fresh server instance, so the listing that recorded the collision is + routinely NOT the instance serving the call. Without the rebuild + populating `declared_session_params`, that instance would read the + customer's value, find it malformed and tag the call `invalid` — the same + sessionless outcome, but attributed to the agent rather than to the + collision, which is the difference between a dashboard that explains the + gap and one that does not. + """ + built = flavor.build("rebuild-owned", customer_session_id=True) + track(built.server, "proj_test", AgentCatOptions()) + data = tracking_data(built.server) + assert data.declared_session_params == set(), "something listed before the call" + + await flavor.call_unlisted( + built.server, "complete_task", {"session_id": "TICKET-9", "note": "done"} + ) + + assert data.declared_session_params == {"complete_task"} + event = capture[0] + assert event.session_id is None + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "foreign" + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_a_failed_rebuild_degrades_to_the_heuristic_strip( + flavor, capture, log_sink +): + """The list source is down, so the strip has no registry to consult. + + What every era owes on this path, whatever the call then does: fall back + rather than raise, leave the (already absent) parameter registry alone so a + concurrent call that just stored a good one is not robbed of it, and clear + the output registry so the mirror stops gating on knowledge we no longer + have. And still publish the one event, with the call as the agent made it. + """ + built = flavor.build("rebuild-down-any", customer_get_more_tools=True) + track(built.server, "proj_test", AgentCatOptions()) + flavor.break_list_source(built.server) + data = tracking_data(built.server) + + await flavor.call_unlisted( + built.server, + GET_MORE_TOOLS_NAME, + {CONTEXT_PARAM: "I need a tool to send email", SESSION_ID_PARAM: SUPPLIED}, + ) + + assert _logged(log_sink, "rebuild-on-demand failed") + assert data.injected_params_registry is None + assert data.output_injection_registry is None + assert len(capture) == 1 + event = capture[0] + assert event.session_id == SUPPLIED + # Raw arguments: both injected names are still on the event. + assert event.parameters["arguments"][SESSION_ID_PARAM] == SUPPLIED + assert event.parameters["arguments"][CONTEXT_PARAM] == "I need a tool to send email" + + +# The mcp 1.x official flavors cannot answer a call at all while their list +# source is down — see `Flavor.survives_a_down_list_source` for why, and note +# that it is the SDK's behavior rather than AgentCat's. Everything AgentCat +# does on that path is asserted above; what the CUSTOMER's tool sees can only +# be asked of an era where the call completes. +CAN_ANSWER_WITH_A_DOWN_LIST_SOURCE = [ + flavor for flavor in flavors() if flavor.survives_a_down_list_source +] + + +@pytest.mark.parametrize( + "flavor", CAN_ANSWER_WITH_A_DOWN_LIST_SOURCE, ids=lambda f: f.id +) +async def test_a_failed_rebuild_still_protects_get_more_tools_own_context( + flavor, capture, log_sink +): + """The heuristic strips all three injected names — except one. + + `get_more_tools`' `context` is a real parameter the tool needs, not + something AgentCat injected, and a customer tool by that name is what makes + the distinction observable: strip its `context` and the call fails or + answers about nothing. + + And the mirror applies anyway. A cleared output registry means "no schema + we know about can be in play", not "no schema declares the field", so + gating on it would silently drop the mint-back on exactly the instances + that never listed. + """ + built = flavor.build("rebuild-down", customer_get_more_tools=True) + track(built.server, "proj_test", AgentCatOptions()) + flavor.break_list_source(built.server) + data = tracking_data(built.server) + + result = await flavor.call_unlisted( + built.server, + GET_MORE_TOOLS_NAME, + {CONTEXT_PARAM: "I need a tool to send email", SESSION_ID_PARAM: SUPPLIED}, + ) + + # The rebuild really did fail — otherwise the registry strip would keep + # `context` for its own reasons and this would prove nothing. + assert _logged(log_sink, "rebuild-on-demand failed") + assert data.injected_params_registry is None + assert data.output_injection_registry is None + + # `context` reached the customer's tool; `session_id` did not. + assert built.seen == [ + (GET_MORE_TOOLS_NAME, {CONTEXT_PARAM: "I need a tool to send email"}) + ] + assert "customer answered: I need a tool to send email" in result.text + # ...and the handle still rides back with no registry to gate it. + assert result.structured[MCP_INSTRUCTIONS_KEY][SESSION_ID_PARAM] == SUPPLIED + assert capture[0].session_id == SUPPLIED + + +@pytest.mark.parametrize( + "flavor", CAN_ANSWER_WITH_A_DOWN_LIST_SOURCE, ids=lambda f: f.id +) +async def test_a_failed_rebuild_still_strips_context_from_every_other_tool( + flavor, capture, log_sink +): + """The other half of the heuristic: `context` is ours on every tool but one. + + Same broken instance, an ordinary tool — and `echo` never declared a + `context` parameter, so handing it one is the injection leaking through. + """ + built = flavor.build("rebuild-down-echo") + track(built.server, "proj_test", AgentCatOptions()) + flavor.break_list_source(built.server) + + await flavor.call_unlisted( + built.server, + "echo", + {"text": "hi", SESSION_ID_PARAM: SUPPLIED, CONTEXT_PARAM: "why I called"}, + ) + + assert _logged(log_sink, "rebuild-on-demand failed") + assert built.seen == [("echo", {"text": "hi"})] + assert capture[0].parameters["arguments"][CONTEXT_PARAM] == "why I called" diff --git a/tests/test_redaction.py b/tests/test_redaction.py index 533c649..9ec2a0f 100644 --- a/tests/test_redaction.py +++ b/tests/test_redaction.py @@ -309,14 +309,18 @@ def redact_fn(s: str) -> str: assert result["metadata"]["timestamp"] == "[REDACTED]" assert result["metadata"]["ip"] == "[REDACTED]" - def test_identify_event_special_fields(self): - """Test agentcat:identify event with special protected fields.""" + def test_actor_fields_are_never_redacted(self): + """The actor fields are protected wherever they ride. + + v1 carried them on a standalone `agentcat:identify` event; v2 stamps + them onto every tools/call event. Either way redaction leaves them + alone, so the dashboard can still name the actor.""" def redact_fn(s: str) -> str: return "XXX" identify_event = { - "event_type": "agentcat:identify", + "event_type": "mcp:tools/call", "identify_actor_given_id": "user123", # Protected "identify_actor_name": "John Doe", # Protected "identify_data": { # Protected @@ -367,3 +371,97 @@ def faulty_redact_fn(s: str) -> str: # The function should propagate the error with pytest.raises(ValueError, match="Redaction error"): redact_event(event, faulty_redact_fn) + + +class TestRedactEventOnTheRealEventModel: + """The shape the publish path actually holds. + + `redact_strings_in_object` walks `str` / `list` / `dict` and returns + everything else untouched — and `event_queue._process_event` hands + `redact_event` a pydantic `UnredactedEvent`. For the whole of the v2 branch + that meant the documented `redact_sensitive_information` hook was a no-op on + every real event while the README advertised it as a security control. The + dict-shaped cases above never caught it; these are the ones that would. + """ + + @staticmethod + def _event(**overrides): + from agentcat.types import UnredactedEvent + + fields = { + "session_id": "ses_keepme", + "id": "evt_keepme", + "project_id": "proj_keepme", + "event_type": "mcp:tools/call", + "resource_name": "add_todo", + "user_intent": "find the SECRET", + "parameters": {"arguments": {"text": "SECRET body"}}, + "response": {"content": [{"type": "text", "text": "SECRET answer"}]}, + "client_name": "SECRET client", + "identify_actor_given_id": "SECRET actor", + "identify_data": {"email": "SECRET@example.com"}, + "tags": {"env": "SECRET tag"}, + "duration": 12, + } + fields.update(overrides) + return UnredactedEvent(**fields) + + def test_the_hook_actually_runs_on_a_pydantic_event(self): + def redact_fn(s: str) -> str: + return s.replace("SECRET", "[REDACTED]") + + event = self._event() + result = redact_event(event, redact_fn) + + assert result.user_intent == "find the [REDACTED]" + assert result.parameters == {"arguments": {"text": "[REDACTED] body"}} + assert result.response == { + "content": [{"type": "text", "text": "[REDACTED] answer"}] + } + assert result.client_name == "[REDACTED] client" + # ...and the original is untouched, so a failure downstream cannot + # publish a half-redacted object. + assert event.parameters == {"arguments": {"text": "SECRET body"}} + + def test_protected_fields_survive_on_the_model_too(self): + def redact_fn(s: str) -> str: + return "XXX" + + result = redact_event(self._event(), redact_fn) + assert result.session_id == "ses_keepme" + assert result.id == "evt_keepme" + assert result.project_id == "proj_keepme" + assert result.event_type == "mcp:tools/call" + assert result.resource_name == "add_todo" + assert result.identify_actor_given_id == "SECRET actor" + assert result.identify_data == {"email": "SECRET@example.com"} + assert result.tags == {"env": "SECRET tag"} + + def test_the_result_is_still_a_publishable_event(self): + """`model_copy`, not a rebuild: unredacted fields keep their values and + non-string fields keep their types, so the queue can serialize it.""" + result = redact_event(self._event(), lambda s: "XXX") + assert type(result) is type(self._event()) + assert result.duration == 12 + assert result.redaction_fn is None + assert "XXX" in result.model_dump_json() + + def test_a_raising_hook_propagates_so_the_queue_drops_the_event(self): + def boom(_s: str) -> str: + raise RuntimeError("redaction exploded") + + with pytest.raises(RuntimeError, match="redaction exploded"): + redact_event(self._event(), boom) + + def test_an_async_hook_is_driven_to_completion(self): + """`RedactionFunction` permits an async hook and the publish path is a + worker thread with no loop. Un-awaited, every redacted string would + reach the wire as `` — redaction that looks like + it worked.""" + + async def redact_fn(s: str) -> str: + return s.replace("SECRET", "[REDACTED]") + + result = redact_event(self._event(), redact_fn) + assert result.client_name == "[REDACTED] client" + assert "coroutine" not in result.model_dump_json() diff --git a/tests/test_removed_events.py b/tests/test_removed_events.py new file mode 100644 index 0000000..304fdf7 --- /dev/null +++ b/tests/test_removed_events.py @@ -0,0 +1,90 @@ +"""The three retired event types, proven gone on every flavor. + +v1 published `mcp:initialize`, `mcp:tools/list` and `agentcat:identify` beside +the tool call. v2 publishes ONE event type automatically — `mcp:tools/call` — +and `tools/list` is still intercepted, for schema injection only +(changelog §3.1). That is a wire-visible promise to every consumer of the +event stream, and it is made by four different adapters, so it is asserted +against a full lifecycle on each of them rather than inferred from the shared +engine. + +The lifecycle is deliberately the noisy one: connect (which handshakes, and on +the 2026 wire discovers), list, call twice, call the tool AgentCat itself +answers, and fail a call. Every one of those was an event in v1. +""" + +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import GET_MORE_TOOLS_NAME, SESSION_ID_PARAM + +from .test_utils.flavors import BOOM_TEXT, flavors + +# What v1 published beside the tool call. Named rather than implied, so a +# regression reads as "initialize is back" instead of "a set changed". +RETIRED = {"mcp:initialize", "mcp:tools/list", "agentcat:identify"} + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_a_full_lifecycle_publishes_only_tool_calls(flavor, capture): + """Handshake, listing and four calls; four events, all of one type.""" + built = flavor.build("removed-events") + track(built.server, "proj_test", AgentCatOptions()) + + async with flavor.client(built.server) as client: + listed = await flavor.list_tools(client) + assert {tool.name for tool in listed} == {"echo", GET_MORE_TOOLS_NAME} + + first = await flavor.call(client, "echo", {"text": "one"}) + minted = first.text.split("session_id=")[1].split(" ")[0] + await flavor.call(client, "echo", {"text": "two", SESSION_ID_PARAM: minted}) + # AgentCat answers this one itself, and it is still just a tool call. + await flavor.call( + client, GET_MORE_TOOLS_NAME, {"context": "I need a tool to send email"} + ) + + assert {event.event_type for event in capture} == {"mcp:tools/call"} + assert len(capture) == 3 + assert not RETIRED & {event.event_type for event in capture} + assert [event.resource_name for event in capture] == [ + "echo", + "echo", + GET_MORE_TOOLS_NAME, + ] + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_a_failed_call_publishes_only_its_own_tool_call(flavor, capture): + """The error path is where an extra event would be easiest to add back. + + The tool body refuses the sentinel text, so the failure is a real Python + exception on every era — surfaced as a raise on some and as an `is_error` + result on others — and every era still owes exactly one event for it. + """ + built = flavor.build("removed-events-error") + track(built.server, "proj_test", AgentCatOptions()) + + async with flavor.client(built.server) as client: + await flavor.list_tools(client) + try: + await flavor.call(client, "echo", {"text": BOOM_TEXT}) + except Exception: + # Community FastMCP surfaces a failing call as a raised error at + # the client; the official SDKs answer with an `is_error` result. + # Which one it is belongs to the SDK, not to this assertion. + pass + + assert {event.event_type for event in capture} == {"mcp:tools/call"} + assert len(capture) == 1 + assert capture[0].is_error is True + assert capture[0].error is not None diff --git a/tests/test_report_missing.py b/tests/test_report_missing.py index 73a44b9..a4ffde7 100644 --- a/tests/test_report_missing.py +++ b/tests/test_report_missing.py @@ -70,11 +70,12 @@ async def test_report_missing_tool_call_success(self): {"context": "Need a tool to translate text between languages"}, ) - # Verify successful response - assert result.content - assert len(result.content) == 1 + # Verify successful response. get_more_tools publishes events like + # any other tool, so it mints a task and carries the mint-back + # block after its own answer. assert result.content[0].type == "text" assert "Unfortunately" in result.content[0].text + assert "[MCP INSTRUCTIONS]: session_id issued." in result.content[-1].text @pytest.mark.asyncio async def test_report_missing_with_valid_params(self): @@ -110,11 +111,12 @@ async def test_report_missing_with_missing_params(self): track(server, "test_project", options) async with create_test_client(server) as client: - # Test with missing context - should return a validation error - # since context is a required parameter + # `context` is required in the advertised schema, so a strict client + # will not send the call at all — but AgentCat never fails a tool + # call over its own analytics, so a lax client still gets an answer. result = await client.call_tool("get_more_tools", {}) - assert result.content[0].text - assert result.isError is True + assert result.isError is False + assert "Unfortunately" in result.content[0].text # Test with valid context result = await client.call_tool("get_more_tools", {"context": "test_tool"}) @@ -212,11 +214,15 @@ async def test_report_missing_with_context_enabled(self): assert report_missing_tool is not None assert other_tool is not None - # Verify context is NOT added to report_missing tool - assert "context" in report_missing_tool.inputSchema.get("properties", {}) + # get_more_tools keeps its own bespoke context, not the injected one + from agentcat.modules.constants import DEFAULT_CONTEXT_DESCRIPTION + + gmt_context = report_missing_tool.inputSchema["properties"]["context"] + assert gmt_context["description"] != DEFAULT_CONTEXT_DESCRIPTION - # But context should be added to other tools - assert "context" in other_tool.inputSchema.get("properties", {}) + # But the injected context is added to other tools + other_context = other_tool.inputSchema["properties"]["context"] + assert other_context["description"] == DEFAULT_CONTEXT_DESCRIPTION @pytest.mark.skip( reason="Creating empty low-level server is complex and already tested via FastMCP" @@ -237,11 +243,11 @@ async def test_report_missing_with_null_values(self): track(server, "test_project", options) async with create_test_client(server) as client: - # Test with None context - should return a validation error - # since context is required as a string + # A null context is not an explanation, but it is not a reason to + # fail the call either. result = await client.call_tool("get_more_tools", {"context": None}) - assert result.content[0].text - assert result.isError is True + assert result.isError is False + assert "Unfortunately" in result.content[0].text @pytest.mark.asyncio async def test_report_missing_publishes_event(self): @@ -352,8 +358,8 @@ async def test_multiple_tool_calls_publish_multiple_events(self): time.sleep(1.0) - # Should have at least 3 tool call events (plus initialize and list_tools events) - assert mock_api_client.publish_event.call_count >= 3 + # v2 publishes exactly one event per tool call and nothing else. + assert mock_api_client.publish_event.call_count == 3 # Get all published events events = [ diff --git a/tests/test_request_extra.py b/tests/test_request_extra.py index 804b50c..e150a04 100644 --- a/tests/test_request_extra.py +++ b/tests/test_request_extra.py @@ -15,6 +15,7 @@ from agentcat import AgentCatOptions, track from agentcat.modules.event_queue import EventQueue, set_event_queue from agentcat.modules.request_extra import ( + extra_from_request_context, extract_request_extra, params_with_extra, ) @@ -34,6 +35,21 @@ def _http_request_context(headers: dict, request_id="req-123", session=None, met ) +def _capture_into(sink: list): + """A publish_event double that records events. + + `EventsApi.publish_event` is called with a KEYWORD argument, so a bare + `sink.append` raises `TypeError` — which the queue swallows as a send + failure, leaving the sink empty and any "no events published" assertion + passing vacuously. + """ + + def capture(publish_event_request): + sink.append(publish_event_request) + + return capture + + def _stdio_request_context(request_id="req-456"): """Build a mock RequestContext that mimics a stdio-transport request.""" return SimpleNamespace( @@ -310,14 +326,10 @@ def capture_event(publish_event_request): meta={"progressToken": "tok-7"}, ) - from agentcat.modules.overrides import mcp_server as mcp_server_mod - from agentcat.modules.overrides.official import monkey_patch as official_mp + from agentcat.modules.adapters import lowlevel_v1 monkeypatch.setattr( - mcp_server_mod, "safe_request_context", lambda _server: fake_ctx - ) - monkeypatch.setattr( - official_mp, "safe_request_context", lambda _server: fake_ctx + lowlevel_v1, "_safe_request_context", lambda _server: fake_ctx ) async with create_test_client(server) as client: @@ -343,15 +355,60 @@ def capture_event(publish_event_request): assert extra.get("meta") == {"progressToken": "tok-7"} @pytest.mark.asyncio - async def test_list_tools_event_includes_extra(self, monkeypatch): - """tools/list events should also carry parameters.extra when HTTP-shaped.""" + async def test_transport_session_id_never_becomes_the_task_handle( + self, monkeypatch + ): + """`Event.session_id` carries the AgentCat task handle, not the + transport's `mcp-session-id`. + + v1 correlated on the transport session; v2 ignores it entirely + (changelog §3.1) and resolves a `ses_` handle per call. The transport + id still rides along untouched under `parameters.extra.sessionId`, so + customers who need it can still read it. + """ mock_api_client = MagicMock() captured_events: list = [] - def capture_event(publish_event_request): - captured_events.append(publish_event_request) + mock_api_client.publish_event = MagicMock( + side_effect=_capture_into(captured_events) + ) + set_event_queue(EventQueue(api_client=mock_api_client)) - mock_api_client.publish_event = MagicMock(side_effect=capture_event) + server = create_todo_server() + track(server, "test_project", AgentCatOptions(enable_tracing=True)) + + fake_ctx = _http_request_context( + headers={"mcp-session-id": "transport-sess-xyz"}, + request_id="req-handle", + ) + from agentcat.modules.adapters import lowlevel_v1 + + monkeypatch.setattr( + lowlevel_v1, "_safe_request_context", lambda _server: fake_ctx + ) + + async with create_test_client(server) as client: + await client.call_tool("add_todo", {"text": "t", "context": "handles"}) + time.sleep(1.0) + + tool_events = [e for e in captured_events if e.event_type == "mcp:tools/call"] + assert tool_events, "expected a tools/call event" + event = tool_events[0] + extra = (event.parameters or {}).get("extra") or {} + assert extra.get("sessionId") == "transport-sess-xyz" + assert event.session_id != "transport-sess-xyz" + assert event.session_id.startswith("ses_") + + @pytest.mark.asyncio + async def test_tools_list_publishes_no_event(self, monkeypatch): + """v2 intercepts tools/list for schema injection only — it publishes + nothing, so `extra` has no tools/list event to ride.""" + mock_api_client = MagicMock() + captured_events: list = [] + + mock_api_client.publish_event = MagicMock( + side_effect=_capture_into(captured_events) + ) set_event_queue(EventQueue(api_client=mock_api_client)) server = create_todo_server() @@ -361,23 +418,30 @@ def capture_event(publish_event_request): headers={"x-list-header": "list-value"}, request_id="req-list", ) - from agentcat.modules.overrides import mcp_server as mcp_server_mod + from agentcat.modules.adapters import lowlevel_v1 monkeypatch.setattr( - mcp_server_mod, "safe_request_context", lambda _server: fake_ctx + lowlevel_v1, "_safe_request_context", lambda _server: fake_ctx ) async with create_test_client(server) as client: await client.list_tools() time.sleep(1.0) - list_events = [e for e in captured_events if e.event_type == "mcp:tools/list"] - assert list_events, ( - f"expected a tools/list event, got {[e.event_type for e in captured_events]}" - ) - params = list_events[0].parameters or {} - extra = params.get("extra") or {} - headers = (extra.get("requestInfo") or {}).get("headers") or {} - assert headers.get("x-list-header") == "list-value", ( - f"expected list_tools event extra to include header, got params={params}" - ) + assert captured_events == [] + + +class TestExtraFromRequestContext: + """`extra_from_request_context` shapes the adapters' `parameters` merge.""" + + def test_wraps_extra_under_its_key(self): + ctx = _http_request_context({"x-a": "b"}, request_id="req-1") + assert extra_from_request_context(ctx) == { + "extra": { + "requestInfo": {"headers": {"x-a": "b"}}, + "requestId": "req-1", + } + } + + def test_empty_when_nothing_to_report(self): + assert extra_from_request_context(None) == {} diff --git a/tests/test_response_shape.py b/tests/test_response_shape.py new file mode 100644 index 0000000..ff28344 --- /dev/null +++ b/tests/test_response_shape.py @@ -0,0 +1,77 @@ +"""The `response` field's spelling, pinned per flavor rather than normalized. + +An event's `response` is the era-native dump of whatever result object that +generation's tool call produced: `_common.response_payload` calls +`model_dump(mode="json")` with no `by_alias`, so official mcp 1.x publishes +`isError` / `structuredContent` and mcp 2.x and both community eras publish +`is_error` / `structured_content`. + +**That divergence is deliberate — see the ruling recorded at +`_common.response_payload`.** It is not a regression: v1 community already +published FastMCP's snake_case dump, so "normalizing" would change data the +backend has been receiving rather than fix it. What was missing is that +nothing pinned it, which is how a divergence drifts silently or gets "fixed" +by someone who reads it as a bug. This module is that pin. If you are here +because you changed the spelling on purpose, change the ruling first. + +The wire result the agent receives is unaffected either way: this is the +analytics payload, not the tool's answer. +""" + +import json + +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import MCP_INSTRUCTIONS_KEY, SESSION_ID_PARAM + +from .test_utils import sid +from .test_utils.flavors import flavors + +# (error key, structured key) as each flavor's own result model spells them. +EXPECTED_SPELLING = { + "official-fastmcp-v1": ("isError", "structuredContent"), + "lowlevel-v1": ("isError", "structuredContent"), + "mcpserver-v2": ("is_error", "structured_content"), + "lowlevel-v2": ("is_error", "structured_content"), + "community-v3": ("is_error", "structured_content"), + "community-v4": ("is_error", "structured_content"), +} + +BOTH_SPELLINGS = {"isError", "is_error", "structuredContent", "structured_content"} + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_the_event_response_keeps_its_eras_own_field_names(flavor, capture): + error_key, structured_key = EXPECTED_SPELLING[flavor.id] + + built = flavor.build("response-shape") + track(built.server, "proj_test", AgentCatOptions()) + + async with flavor.client(built.server) as client: + await flavor.list_tools(client) + await flavor.call( + client, "echo", {"text": "hi", SESSION_ID_PARAM: sid("supplied")} + ) + + response = capture[0].response + assert isinstance(response, dict) + # This era's spelling is present, and the other era's is nowhere in it. + assert error_key in response + assert structured_key in response + assert not (BOTH_SPELLINGS - {error_key, structured_key}) & set(response) + # ...and it is the customer's own result, undecorated: the mint-back is + # wire-only and must never reach the analytics payload. + assert response[structured_key] == {"result": "echo:hi"} + assert MCP_INSTRUCTIONS_KEY not in json.dumps(response) + assert "[MCP INSTRUCTIONS]" not in json.dumps(response) diff --git a/tests/test_session.py b/tests/test_session.py deleted file mode 100644 index e10550e..0000000 --- a/tests/test_session.py +++ /dev/null @@ -1,426 +0,0 @@ -"""Comprehensive unit tests for session.py module.""" - -import sys -from datetime import datetime, timedelta, timezone -from unittest.mock import MagicMock, patch - -import pytest -from freezegun import freeze_time - -from agentcat.modules.constants import INACTIVITY_TIMEOUT_IN_MINUTES, SESSION_ID_PREFIX -from agentcat.modules.internal import get_server_tracking_data, set_server_tracking_data -from agentcat.modules.session import ( - get_agentcat_version, - get_server_session_id, - get_session_info, - new_session_id, - set_last_activity, -) -from agentcat.types import AgentCatData, AgentCatOptions, SessionInfo - -from .test_utils.todo_server import create_todo_server - - -class TestNewSessionId: - """Test the new_session_id function.""" - - def test_generates_unique_ids(self): - """Test that new_session_id generates unique IDs.""" - ids = [new_session_id() for _ in range(100)] - assert len(set(ids)) == 100 # All IDs should be unique - - def test_session_id_has_correct_prefix(self): - """Test that session ID has the correct prefix.""" - session_id = new_session_id() - assert session_id.startswith(SESSION_ID_PREFIX) - - def test_session_id_format(self): - """Test that session ID follows expected format.""" - session_id = new_session_id() - # Format should be: prefix_ksuid (e.g., ses_2aYXpLJGvKU1234567890abcdef) - parts = session_id.split("_") - assert len(parts) == 2 - assert parts[0] == SESSION_ID_PREFIX - assert len(parts[1]) > 0 # KSUID part should not be empty - - -class TestGetAgentcatVersion: - """Test the get_agentcat_version function.""" - - @patch("importlib.metadata.version") - def test_returns_correct_version(self, mock_version): - """Test that get_agentcat_version returns the correct version.""" - mock_version.return_value = "1.2.3" - assert get_agentcat_version() == "1.2.3" - mock_version.assert_called_once_with("agentcat") - - @patch("importlib.metadata.version") - def test_returns_none_on_exception(self, mock_version): - """Test that get_agentcat_version returns None when an exception occurs.""" - mock_version.side_effect = Exception("Package not found") - assert get_agentcat_version() is None - - -class TestGetSessionInfo: - """Test the get_session_info function.""" - - def setup_method(self): - """Set up test fixtures.""" - self.server = create_todo_server() - - def test_without_agentcat_data(self): - """Test get_session_info without AgentCat data.""" - session_info = get_session_info(self.server, None) - - assert session_info.ip_address is None - assert ( - session_info.sdk_language - == f"Python {sys.version_info.major}.{sys.version_info.minor}" - ) - assert session_info.agentcat_version == get_agentcat_version() - assert session_info.server_name == "todo-server" - assert ( - session_info.server_version is None - ) # FastMCP doesn't have version attribute - assert session_info.client_name is None - assert session_info.client_version is None - assert session_info.identify_actor_given_id is None - assert session_info.identify_actor_name is None - assert session_info.identify_data is None - - def test_with_agentcat_data_no_actor(self): - """Test get_session_info with AgentCat data but no identified actor.""" - data = AgentCatData( - project_id="test_project", - session_id="test_session", - session_info=SessionInfo(client_name="TestClient", client_version="2.0.0"), - last_activity=datetime.now(timezone.utc), - options=AgentCatOptions(), - ) - - session_info = get_session_info(self.server, data) - - assert session_info.client_name == "TestClient" - assert session_info.client_version == "2.0.0" - assert session_info.identify_actor_given_id is None - assert session_info.identify_actor_name is None - assert session_info.identify_data is None - - # Verify that the session_info was updated in the data object - assert data.session_info == session_info - - def test_session_info_never_carries_identity(self): - """get_session_info returns None for identity fields.""" - data = AgentCatData( - project_id="test_project", - session_id="test_session", - session_info=SessionInfo(client_name="TestClient", client_version="2.0.0"), - last_activity=datetime.now(timezone.utc), - options=AgentCatOptions(), - ) - - session_info = get_session_info(self.server, data) - - assert session_info.identify_actor_given_id is None - assert session_info.identify_actor_name is None - assert session_info.identify_data is None - - def test_server_without_name_or_version(self): - """Test get_session_info with a server that doesn't have name or version attributes.""" - mock_server = MagicMock() - # Remove name and version attributes - del mock_server.name - del mock_server.version - - session_info = get_session_info(mock_server, None) - - assert session_info.server_name is None - assert session_info.server_version is None - - def test_get_session_info_with_tracked_server(self): - """Test get_session_info when server has tracked data.""" - # Set up initial data - data = AgentCatData( - project_id="test_project", - session_id="test_session", - session_info=SessionInfo( - client_name="TrackedClient", client_version="3.0.0" - ), - last_activity=datetime.now(timezone.utc), - options=AgentCatOptions(), - ) - - # Store data using set_server_tracking_data - set_server_tracking_data(self.server, data) - - # When called without data, get_session_info returns basic info only - session_info_no_data = get_session_info(self.server, None) - assert session_info_no_data.client_name is None - assert session_info_no_data.client_version is None - assert session_info_no_data.server_name == "todo-server" - - # When called with data, get_session_info uses and updates that data - session_info_with_data = get_session_info(self.server, data) - assert session_info_with_data.client_name == "TrackedClient" - assert session_info_with_data.client_version == "3.0.0" - assert session_info_with_data.server_name == "todo-server" - - -class TestSetLastActivity: - """Test the set_last_activity function.""" - - def setup_method(self): - """Set up test fixtures.""" - self.server = create_todo_server() - - def test_updates_last_activity(self): - """Test that set_last_activity updates the last activity timestamp.""" - initial_time = datetime.now(timezone.utc) - - data = AgentCatData( - project_id="test_project", - session_id="test_session", - session_info=SessionInfo(), - last_activity=initial_time, - options=AgentCatOptions(), - ) - - # Set up the server with tracking data - set_server_tracking_data(self.server, data) - - # Move time forward - with freeze_time(initial_time + timedelta(minutes=5)): - set_last_activity(self.server) - - # Verify the timestamp was updated - assert data.last_activity > initial_time - - def test_raises_exception_when_no_data(self): - """Test that set_last_activity raises exception when no data is found.""" - with pytest.raises(Exception) as exc_info: - set_last_activity(self.server) - - assert str(exc_info.value) == "AgentCat data not initialized for this server" - - -class TestGetServerSessionId: - """Test the get_server_session_id function.""" - - def setup_method(self): - """Set up test fixtures.""" - self.server = create_todo_server() - self.initial_time = datetime.now(timezone.utc) - self.initial_session_id = "ses_initial123" - - self.data = AgentCatData( - project_id="test_project", - session_id=self.initial_session_id, - session_info=SessionInfo(), - last_activity=self.initial_time, - options=AgentCatOptions(), - ) - - def test_returns_existing_session_when_not_timed_out(self): - """Test that existing session ID is returned when not timed out.""" - set_server_tracking_data(self.server, self.data) - - # Test within timeout period (e.g., 10 minutes later) - with freeze_time(self.initial_time + timedelta(minutes=10)): - session_id = get_server_session_id(self.server) - - assert session_id == self.initial_session_id - # Verify last activity was updated - assert self.data.last_activity > self.initial_time - - def test_creates_new_session_when_timed_out(self): - """Test that new session ID is created when session has timed out.""" - set_server_tracking_data(self.server, self.data) - - # Test after timeout period (e.g., 31 minutes later) - timeout_time = self.initial_time + timedelta( - minutes=INACTIVITY_TIMEOUT_IN_MINUTES + 1 - ) - with freeze_time(timeout_time): - session_id = get_server_session_id(self.server) - - # Should have a new session ID - assert session_id != self.initial_session_id - assert session_id.startswith(SESSION_ID_PREFIX) - assert self.data.session_id == session_id - # Verify last activity was updated to current time - assert self.data.last_activity == timeout_time - - def test_exactly_at_timeout_boundary(self): - """Test behavior exactly at the timeout boundary.""" - set_server_tracking_data(self.server, self.data) - - # Test exactly at timeout boundary - boundary_time = self.initial_time + timedelta( - minutes=INACTIVITY_TIMEOUT_IN_MINUTES - ) - with freeze_time(boundary_time): - session_id = get_server_session_id(self.server) - - # Should not timeout at exact boundary (> not >=) - assert session_id == self.initial_session_id - - def test_raises_exception_when_no_data(self): - """Test that get_server_session_id raises exception when no data is found.""" - with pytest.raises(Exception) as exc_info: - get_server_session_id(self.server) - - assert str(exc_info.value) == "AgentCat data not initialized for this server" - - def test_multiple_calls_with_activity(self): - """Test multiple calls to get_server_session_id with activity between them.""" - set_server_tracking_data(self.server, self.data) - - # First call at initial time - with freeze_time(self.initial_time): - session_id1 = get_server_session_id(self.server) - - # Activity at 20 minutes - should reset timeout - activity_time = self.initial_time + timedelta(minutes=20) - with freeze_time(activity_time): - get_server_session_id(self.server) - # This updates last_activity to activity_time - - # Call 40 minutes after initial time (but only 20 minutes after last activity) - with freeze_time(self.initial_time + timedelta(minutes=40)): - session_id2 = get_server_session_id(self.server) - - # Should still be the same session since last activity was only 20 minutes ago - assert session_id1 == session_id2 == self.initial_session_id - - def test_timeout_calculation_edge_cases(self): - """Test edge cases in timeout calculation.""" - set_server_tracking_data(self.server, self.data) - - # Test just before timeout - with freeze_time( - self.initial_time + timedelta(minutes=INACTIVITY_TIMEOUT_IN_MINUTES - 1) - ): - session_id = get_server_session_id(self.server) - assert session_id == self.initial_session_id - - # Re-initialize data to reset the session for the next test - self.data.session_id = self.initial_session_id - self.data.last_activity = self.initial_time - - # Test just after timeout - with freeze_time( - self.initial_time + timedelta(minutes=INACTIVITY_TIMEOUT_IN_MINUTES + 1) - ): - session_id = get_server_session_id(self.server) - assert session_id != self.initial_session_id - - -class TestIntegration: - """Integration tests for session management.""" - - @freeze_time("2024-01-01 12:00:00") - def test_full_session_lifecycle(self): - """Test a complete session lifecycle with timeout and renewal.""" - server = create_todo_server() - - # Create initial session data - initial_session_id = new_session_id() - data = AgentCatData( - project_id="integration_project", - session_id=initial_session_id, - session_info=SessionInfo( - client_name="IntegrationClient", client_version="1.0.0" - ), - last_activity=datetime.now(timezone.utc), - options=AgentCatOptions(), - ) - - set_server_tracking_data(server, data) - - # Get initial session - session_id = get_server_session_id(server) - assert session_id == initial_session_id - - # Get session info - session_info = get_session_info(server, data) - assert session_info.server_name == "todo-server" - assert session_info.client_name == "IntegrationClient" - - assert session_info.identify_actor_given_id is None - assert session_info.identify_actor_name is None - - # Test session timeout and renewal - with freeze_time("2024-01-01 12:31:00"): # 31 minutes later - new_sid = get_server_session_id(server) - assert new_sid != initial_session_id - - new_data = AgentCatData( - project_id="integration_project", - session_id=new_sid, - session_info=SessionInfo( - client_name="IntegrationClient", client_version="1.0.0" - ), - last_activity=datetime(2024, 1, 1, 12, 31, 0), - options=AgentCatOptions(), - ) - session_info = get_session_info(server, new_data) - assert session_info.identify_actor_given_id is None - assert session_info.identify_actor_name is None - - def test_session_persistence_across_function_calls(self): - """Test that session persists correctly across multiple function calls.""" - server = create_todo_server() - - # Initialize tracking data - data = AgentCatData( - project_id="persistence_test", - session_id=new_session_id(), - session_info=SessionInfo(), - last_activity=datetime.now(timezone.utc), - options=AgentCatOptions(), - ) - - set_server_tracking_data(server, data) - - # Multiple calls should return same session - session_ids = [] - for _ in range(5): - session_ids.append(get_server_session_id(server)) - - assert len(set(session_ids)) == 1 # All should be the same - - # Verify activity tracking works - original_activity = data.last_activity - with freeze_time(datetime.now(timezone.utc) + timedelta(seconds=5)): - set_last_activity(server) - - assert data.last_activity > original_activity - - def test_session_info_updates_tracked_data(self): - """get_session_info updates the tracked data's session_info.""" - server = create_todo_server() - - data = AgentCatData( - project_id="update_test", - session_id="update_session", - session_info=SessionInfo( - client_name="UpdateClient", client_version="1.0.0" - ), - last_activity=datetime.now(timezone.utc), - options=AgentCatOptions(), - ) - - set_server_tracking_data(server, data) - - session_info = get_session_info(server, data) - - assert session_info.identify_actor_given_id is None - assert session_info.identify_actor_name is None - assert session_info.identify_data is None - - # Verify the data object was updated - assert data.session_info == session_info - - # Verify that the server's tracked data was also updated via set_server_tracking_data - stored_data = get_server_tracking_data(server) - assert stored_data.session_info == session_info diff --git a/tests/test_session_id_validation.py b/tests/test_session_id_validation.py new file mode 100644 index 0000000..35d605a --- /dev/null +++ b/tests/test_session_id_validation.py @@ -0,0 +1,443 @@ +"""AgentCat trusts only a `session_id` it issued. + +Before this, `resolve_handles` adopted whatever string arrived in +`arguments["session_id"]`, verbatim and unchecked, into `Event.session_id` — +a field in `redaction.PROTECTED_FIELDS` and therefore exempt from the +customer's redaction hook. Two failures followed, and the `task_id` -> +`session_id` rename made both materially likelier, because `session_id` is a +common parameter name on customer tools and the one most likely to hold an +auth token: + +1. **Unredactable adoption.** A hallucinated value, or a token a client + auto-populated into a parameter that happens to be named `session_id`, + reached PostHog `$session_id`, Datadog, Sentry and OTLP with no way to + redact it. +2. **The confirmation loop.** A customer's own `session_id` was echoed back to + the agent as "confirmed. Keep sending this exact value on every call." + AgentCat confirming a value it never issued. + +Everything here follows from one sentence: AgentCat only trusts a session_id +it issued. Cross-SDK reference: +`agentcat-typescript-sdk/docs/superpowers/specs/2026-08-02-session-id-validation-design.md`. +""" + +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import ( + AGENTCAT_TAG_SESSION_SOURCE, + MINT_BACK_HEADER_INVALID, + MINT_BACK_HEADER_SESSION, + SESSION_ID_PARAM, +) +from agentcat.modules.handles import ( + build_mint_back_text, + build_structured_mint_back, + derive_session_id, + is_valid_session_id, + new_session_id, + resolve_handles, +) +from agentcat.modules.injection import ToolSpec, build_injected_schemas + +from .test_utils import sid +from .test_utils.flavors import flavors + +# ── A. the shape predicate ─────────────────────────────────────────────────── + + +def test_accepts_ids_this_sdk_actually_issues(): + """Both issuing paths satisfy the predicate by construction. + + If this ever fails, minted handles are being rejected as invalid and every + conversation is severed — the loudest possible failure, deliberately + asserted against the real minters rather than a hand-typed literal. + """ + for _ in range(50): + assert is_valid_session_id(new_session_id()) + assert is_valid_session_id(derive_session_id("anything", "proj_1")) + assert is_valid_session_id(derive_session_id("anything")) + assert is_valid_session_id(sid("parent")) + + +@pytest.mark.parametrize( + ("label", "value"), + [ + ("wrong prefix", "task_2xF9kQm3rTvB8nLpYw7ZcHd4Ke1"), + ("no prefix", "2xF9kQm3rTvB8nLpYw7ZcHd4Ke1"), + ("too short", "ses_abc"), + ("one char short", "ses_" + "a" * 26), + ("one char long", "ses_" + "a" * 28), + ("empty", ""), + ("prefix only", "ses_"), + ("customer value", "my-app-session-42"), + ("non-base62 body", "ses_" + "-" * 27), + ("underscore body", "ses_" + "_" * 27), + ("inner whitespace", "ses_ " + "a" * 26), + # Python-specific: `re.match(r"...$")` would ACCEPT this, because `$` + # also matches immediately before a final newline. `fullmatch` does + # not, which is what keeps the predicate identical to the TS regex. + ("trailing newline", "ses_" + "a" * 27 + "\n"), + ("leading newline", "\nses_" + "a" * 27), + ], +) +def test_rejects_anything_this_sdk_did_not_issue(label, value): + assert is_valid_session_id(value) is False, label + + +# ── B. the decision table ──────────────────────────────────────────────────── +# +# | args.session_id | ours? | shape | Event.session_id | source | +# | absent | yes | — | new_session_id() | minted | +# | present | yes | valid | verbatim | supplied | +# | present | yes | invalid | "" (sessionless) | invalid | +# | present/absent | no | — | "" (sessionless) | foreign | + + +async def _resolve(arguments, *, ours=True, **options): + return await resolve_handles( + arguments, + AgentCatOptions(**options), + "proj_1", + None, + None, + None, + session_param_is_ours=ours, + ) + + +async def test_absent_and_ours_mints(): + r = await _resolve({}) + assert r.session_source == "minted" + assert is_valid_session_id(r.session_id) + + +async def test_valid_and_ours_is_taken_verbatim(): + r = await _resolve({SESSION_ID_PARAM: sid("parent")}) + assert (r.session_source, r.session_id) == ("supplied", sid("parent")) + + +async def test_malformed_and_ours_publishes_sessionless(): + r = await _resolve({SESSION_ID_PARAM: "nope"}) + assert (r.session_source, r.session_id) == ("invalid", "") + + +async def test_the_rejected_value_is_never_stored_anywhere(): + """The whole point: `Event.session_id` cannot be redacted after the fact. + + Asserted over the entire resolution rather than one field, because any + leak — a tag, a mint-back, a source string — lands somewhere exempt. + """ + secret = "sk_live_51H8xQ2abcdefgHIJKLmnop" + r = await _resolve({SESSION_ID_PARAM: secret}, enable_agent_tracking=True) + assert r.session_id == "" + assert secret not in repr(r) + assert secret not in str(build_mint_back_text(r)) + assert secret not in str(build_structured_mint_back(r)) + + +@pytest.mark.parametrize("arguments", [{}, {SESSION_ID_PARAM: "customer-value"}]) +async def test_a_foreign_param_is_sessionless_whatever_the_agent_sent(arguments): + r = await _resolve(arguments, ours=False) + assert (r.session_source, r.session_id) == ("foreign", "") + + +async def test_hook_mode_wins_over_foreign_and_reads_no_arguments(): + """Hook mode short-circuits before any argument is touched. + + That is what makes `resolve_session_id` the documented remedy for a + collision: the customer's parameter stays entirely theirs while AgentCat + derives its own session from their identifier. + """ + r = await _resolve( + {SESSION_ID_PARAM: "customer-value"}, + ours=False, + resolve_session_id=lambda request, extra: "corr-7", + ) + assert r.session_source == "hook" + assert r.session_id == derive_session_id("corr-7", "proj_1") + + +async def test_a_missing_registry_still_validates(): + """`tools/call` before any `tools/list` on this instance. + + Nothing is in `declared_session_params` yet, so the tool counts as ours + and the value is validated rather than adopted. A customer's foreign value + in that window degrades to `invalid` instead of `foreign` — both + sessionless, only the tag differs. + """ + r = await _resolve({SESSION_ID_PARAM: "TICKET-77"}) + assert (r.session_source, r.session_id) == ("invalid", "") + + +# ── C. what the agent is told ──────────────────────────────────────────────── + + +async def test_invalid_corrects_the_agent_without_issuing_a_replacement(): + r = await _resolve({SESSION_ID_PARAM: "nope"}) + text = build_mint_back_text(r) + assert text.startswith(MINT_BACK_HEADER_INVALID) + assert "Re-send the exact session_id" in text + assert "omit the parameter and one will be issued" in text + # Nothing that looks like an issued ID appears — this branch corrects, it + # does not mint. Handing out a second ID would split a session that was + # never split. + assert "ses_" not in text + assert MINT_BACK_HEADER_SESSION not in text + + +async def test_invalid_mirror_carries_instructions_but_no_session_id(): + """The regression `not names: return None` would cause. + + With no agent_id in play there is nothing echoable, so the old early + return dropped the correction entirely — the one branch that has something + to say and nothing to confirm. + """ + r = await _resolve({SESSION_ID_PARAM: "nope"}) + mint = build_structured_mint_back(r) + assert mint is not None + assert SESSION_ID_PARAM not in mint + assert "not recognized" in mint["instructions"] + + +async def test_foreign_says_nothing_about_session_id_at_all(): + r = await _resolve({SESSION_ID_PARAM: "customer-value"}, ours=False) + assert build_mint_back_text(r) is None + assert build_structured_mint_back(r) is None + + +async def test_foreign_never_confirms_a_value_agentcat_did_not_issue(): + """The confirmation loop, pinned. + + The bug was `mint_back_confirmed` telling the agent its own + customer-semantics value was "confirmed. Keep sending this exact value on + every call." + """ + r = await _resolve( + {SESSION_ID_PARAM: "customer-value", "agent_id": "opus|cc|k3n9x"}, + ours=False, + enable_agent_tracking=True, + ) + mint = build_structured_mint_back(r) + # agent_id is a separate injection and still landed, so it is still ours + # to confirm — suppression is per handle, not per response. + assert mint == { + "agent_id": "opus|cc|k3n9x", + "instructions": ( + "[MCP INSTRUCTIONS]: agent_id confirmed. " + "Keep sending this exact value on every call." + ), + } + assert "customer-value" not in str(mint) + + +# ── D. what the customer is told ───────────────────────────────────────────── + + +@pytest.fixture +def log_sink(): + """Everything `write_to_log` tees to diagnostics, as the collector sees it.""" + from agentcat.modules import logging as agentcat_logging + + previous = agentcat_logging._diagnostics_sink + lines: list[str] = [] + agentcat_logging.set_diagnostics_sink(lines.append) + yield lines + agentcat_logging.set_diagnostics_sink(previous) + + +def _colliding(name: str) -> ToolSpec: + return ToolSpec( + name=name, + input_schema={ + "type": "object", + "properties": {SESSION_ID_PARAM: {"type": "string"}}, + }, + ) + + +def test_the_collision_is_an_error_with_remediation(log_sink): + build_injected_schemas([_colliding("own_session")], AgentCatOptions(), set()) + (line,) = [ln for ln in log_sink if "own_session" in ln] + # `write_to_log` has no severity argument; the convention is a text prefix + # on the message, which follows the timestamp bracket. + assert line.split("] ", 1)[1].startswith("ERROR:") + assert "WARN:" not in line + assert "resolve_session_id" in line + assert "without a session" in line + assert "still reaches your handler" in line + + +def test_the_collision_is_reported_once_per_tool_not_once_per_listing(log_sink): + """`build_injected_schemas` reruns on every `tools/list`. + + Undeduped, this would repeat for the life of the process — which is how a + real signal becomes noise the customer filters out. + """ + reported: set[str] = set() + options = AgentCatOptions() + for _ in range(3): + build_injected_schemas([_colliding("own_session")], options, reported) + + assert len([ln for ln in log_sink if "own_session" in ln and "ERROR" in ln]) == 1 + + # Still once per DISTINCT tool, though. + build_injected_schemas([_colliding("other_tool")], options, reported) + assert len([ln for ln in log_sink if "other_tool" in ln and "ERROR" in ln]) == 1 + + +def test_ownership_is_recorded_so_the_call_path_can_read_it(): + """Per tool, not per server: the colliding tool and a normal one coexist.""" + theirs = _colliding("own_session") + result = build_injected_schemas( + [theirs, ToolSpec(name="echo", input_schema={})], AgentCatOptions() + ) + assert result.declared_session_params == {"own_session"} + # Nothing was injected over their parameter, and nothing was recorded as + # strippable — so their handler still receives it. + assert SESSION_ID_PARAM not in result.injected_params["own_session"] + assert theirs.input_schema["properties"][SESSION_ID_PARAM] == {"type": "string"} + assert SESSION_ID_PARAM in result.injected_params["echo"] + + +def test_a_composed_schema_declaring_session_id_is_still_the_customers(): + """Injection is skipped for oneOf/allOf/anyOf, but ownership is not. + + Only the root properties bag is visible here — a `session_id` nested + inside a branch is unreachable, the same limitation the injection has. + """ + composed = ToolSpec( + name="composed_own", + input_schema={ + "oneOf": [{"type": "object"}], + "properties": {SESSION_ID_PARAM: {"type": "string"}}, + }, + ) + result = build_injected_schemas([composed], AgentCatOptions()) + assert result.declared_session_params == {"composed_own"} + + +def test_a_composed_schema_without_the_name_stays_ours(): + """The bug a naive port of the TS ownership test would introduce. + + A composed schema has an injection entry that stays EMPTY, because the + whole pass is skipped. Reading ownership off that emptiness would call + every such tool the customer's and publish it sessionless, when nobody + declared the name at all. + """ + composed = ToolSpec( + name="composed_plain", + input_schema={"oneOf": [{"type": "object"}], "properties": {}}, + ) + result = build_injected_schemas([composed], AgentCatOptions()) + assert result.injected_params["composed_plain"] == set() + assert result.declared_session_params == set() + + +# ── E. end to end, on every server shape ───────────────────────────────────── + + +@pytest.fixture +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_an_invalid_id_publishes_sessionless_and_corrects_the_agent( + flavor, capture +): + """The whole path, over each flavor's real client and transport. + + The unit tests above can only prove the decision; this proves the decision + reaches both consumers — the event AgentCat publishes and the result the + agent is handed. + """ + built = flavor.build("invalid-session") + track(built.server, "proj_test", AgentCatOptions()) + + async with flavor.client(built.server) as client: + await flavor.list_tools(client) + result = await flavor.call( + client, "echo", {"text": "hi", SESSION_ID_PARAM: "not-a-real-id"} + ) + + assert "session_id not recognized" in result.text + assert "not-a-real-id" not in result.text + + (event,) = capture + assert event.session_id is None + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "invalid" + # The rejected value is nowhere near the unredactable field, but it IS + # still on the event as an argument the agent sent — which is `parameters`, + # where the customer's redaction hook can reach it. + assert event.parameters["arguments"][SESSION_ID_PARAM] == "not-a-real-id" + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_the_correction_lets_an_agent_recover_by_omitting_the_parameter( + flavor, capture +): + """The deadlock the closing sentence of the copy exists to prevent. + + An agent that hallucinates a session_id on its FIRST call was never issued + one, so "re-send what you were given" names nothing. Omitting the + parameter has to put it back on the minting path — otherwise the + conversation can never acquire a session at all. + """ + built = flavor.build("invalid-recovery") + track(built.server, "proj_test", AgentCatOptions()) + + async with flavor.client(built.server) as client: + await flavor.list_tools(client) + await flavor.call(client, "echo", {"text": "a", SESSION_ID_PARAM: "guessed"}) + recovered = await flavor.call(client, "echo", {"text": "b"}) + + assert MINT_BACK_HEADER_SESSION in recovered.text + issued = recovered.structured["_mcp_instructions"][SESSION_ID_PARAM] + assert is_valid_session_id(issued) + + rejected, minted = capture + assert rejected.session_id is None + assert minted.session_id == issued + assert minted.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_the_conflict_report_is_deduped_per_server_not_per_listing( + flavor, log_sink +): + """The dedupe set has to reach the pipeline from `AgentCatData`. + + The unit test above proves `build_injected_schemas` honors a set it is + handed; only a real server proves each adapter actually hands it one. Wire + it wrong and the customer gets this error on every `tools/list` for the + life of the process. + """ + built = flavor.build("dedupe", customer_session_id=True) + track(built.server, "proj_test", AgentCatOptions()) + + async with flavor.client(built.server) as client: + for _ in range(3): + await flavor.list_tools(client) + + errors = [ln for ln in log_sink if "ERROR:" in ln and "complete_task" in ln] + assert len(errors) == 1, f"reported {len(errors)} times across 3 listings" + + +def test_hook_mode_never_reports_a_collision(log_sink): + """Nothing is injected in hook mode, so nothing can collide. + + Reporting here would tell customers who already took the documented remedy + that they still have the problem. + """ + build_injected_schemas( + [_colliding("own_session")], + AgentCatOptions(resolve_session_id=lambda request, extra: "corr-1"), + set(), + ) + assert not [ln for ln in log_sink if "own_session" in ln] diff --git a/tests/test_stateless.py b/tests/test_stateless.py deleted file mode 100644 index 222e8cf..0000000 --- a/tests/test_stateless.py +++ /dev/null @@ -1,200 +0,0 @@ -"""Tests for stateless mode behavior.""" - -from datetime import datetime, timezone -from unittest.mock import MagicMock, patch - -import agentcat -from agentcat.modules.internal import ( - get_server_tracking_data, - set_server_tracking_data, - reset_all_tracking_data, -) -from agentcat.modules.session import get_server_session_id, get_client_info_from_request_context -from agentcat.modules.identify import identify_session -from agentcat.types import AgentCatData, AgentCatOptions, SessionInfo, UserIdentity - -from .test_utils.todo_server import create_todo_server - - -def _make_identify_fn(user_id="user_123", user_name="Test User"): - """Return an identify function that always returns a UserIdentity.""" - def identify(request, context): - return UserIdentity(user_id=user_id, user_name=user_name, user_data=None) - return identify - - -class TestStatelessMode: - """Tests for SDK stateless mode behavior.""" - - def setup_method(self): - reset_all_tracking_data() - self.server = create_todo_server() - - def teardown_method(self): - reset_all_tracking_data() - - def _setup_data(self, stateless=False, identify=None): - """Create and store AgentCatData on the server.""" - options = AgentCatOptions() - if identify: - options.identify = identify - data = AgentCatData( - project_id="test_project", - session_id="ses_existing123", - session_info=SessionInfo(), - last_activity=datetime.now(timezone.utc), - options=options, - is_stateless=stateless, - ) - set_server_tracking_data(self.server, data) - return data - - def test_stateless_option_sets_flag(self): - """AgentCatOptions(stateless=True) should set is_stateless on data.""" - data = self._setup_data(stateless=True) - assert data.is_stateless is True - - def test_stateless_session_id_is_none(self): - """In stateless mode, get_server_session_id() should return None.""" - self._setup_data(stateless=True) - session_id = get_server_session_id(self.server) - assert session_id is None - - @patch("agentcat.modules.identify.event_queue") - def test_stateless_identify_runs_every_time(self, mock_event_queue): - """In stateless mode, identify should run on every call (no early-return guard).""" - mock_fn = MagicMock(return_value=UserIdentity( - user_id="alice", user_name="Alice", user_data=None - )) - self._setup_data(stateless=True, identify=mock_fn) - - identify_session(self.server, MagicMock(), MagicMock()) - identify_session(self.server, MagicMock(), MagicMock()) - - assert mock_fn.call_count == 2 - - @patch("agentcat.modules.identify.event_queue") - def test_stateless_identify_returns_identity(self, mock_event_queue): - """In stateless mode, identify_session() should return the UserIdentity.""" - self._setup_data(stateless=True, identify=_make_identify_fn()) - - result = identify_session(self.server, MagicMock(), MagicMock()) - - assert isinstance(result, UserIdentity) - assert result.user_id == "user_123" - assert result.user_name == "Test User" - - @patch("agentcat.modules.identify.event_queue") - def test_stateful_identify_runs_every_time(self, mock_event_queue): - """Stateful mode runs identify on every request.""" - mock_fn = MagicMock(return_value=UserIdentity( - user_id="alice", user_name="Alice", user_data=None - )) - self._setup_data(stateless=False, identify=mock_fn) - - # Session ID should be a string - session_id = get_server_session_id(self.server) - assert isinstance(session_id, str) - assert session_id.startswith("ses_") - - identify_session(self.server, MagicMock(), MagicMock()) - identify_session(self.server, MagicMock(), MagicMock()) - - assert mock_fn.call_count == 2 - - def test_track_stateless_true_sets_flag(self): - """track() with stateless=True should set is_stateless on data.""" - server = create_todo_server() - options = AgentCatOptions(stateless=True) - agentcat.track(server, "test_project", options) - data = get_server_tracking_data(server) - assert data.is_stateless is True - - def test_track_stateless_false_overrides_detection(self): - """track() with stateless=False should force stateful even if server looks stateless.""" - server = create_todo_server() - # Mock the server to look stateless - server.settings = MagicMock() - server.settings.stateless_http = True - options = AgentCatOptions(stateless=False) - agentcat.track(server, "test_project", options) - data = get_server_tracking_data(server) - assert data.is_stateless is False - - def test_track_stateless_none_auto_detects(self): - """track() with stateless=None (default) should auto-detect from server.""" - server = create_todo_server() - options = AgentCatOptions() # stateless=None by default - agentcat.track(server, "test_project", options) - data = get_server_tracking_data(server) - # create_todo_server() is not stateless, so should be False - assert data.is_stateless is False - - @patch("agentcat.modules.identify.event_queue") - def test_stateless_identify_bad_return(self, mock_event_queue): - """In stateless mode, identify returning non-UserIdentity should return None.""" - bad_fn = MagicMock(return_value="not a UserIdentity") - self._setup_data(stateless=True, identify=bad_fn) - - result = identify_session(self.server, MagicMock(), MagicMock()) - - assert result is None - assert bad_fn.call_count == 1 - - @patch("agentcat.modules.identify.event_queue") - def test_stateless_identify_exception(self, mock_event_queue): - """In stateless mode, identify raising should return None, not propagate.""" - raising_fn = MagicMock(side_effect=RuntimeError("identify exploded")) - self._setup_data(stateless=True, identify=raising_fn) - - result = identify_session(self.server, MagicMock(), MagicMock()) - - assert result is None - assert raising_fn.call_count == 1 - - def _make_request_context(self, user_agent): - """Create a mock request context with a User-Agent header.""" - ctx = MagicMock() - ctx.request.headers = {"user-agent": user_agent} - # No session attribute (stateless HTTP) - ctx.session = None - return ctx - - def test_stateless_client_info_per_request(self): - """In stateless mode, consecutive requests with different clients return different info.""" - self._setup_data(stateless=True) - - ctx1 = self._make_request_context("Cursor/2.6.22") - ctx2 = self._make_request_context("Claude Desktop/1.0") - - result1 = get_client_info_from_request_context(self.server, ctx1) - result2 = get_client_info_from_request_context(self.server, ctx2) - - assert result1 == ("Cursor", "2.6.22") - assert result2 == ("Claude Desktop", "1.0") - - def test_stateless_client_info_returns_values(self): - """In stateless mode, get_client_info_from_request_context returns a tuple.""" - self._setup_data(stateless=True) - - ctx = self._make_request_context("Cursor/2.6.22") - result = get_client_info_from_request_context(self.server, ctx) - - assert isinstance(result, tuple) - assert len(result) == 2 - assert result[0] == "Cursor" - assert result[1] == "2.6.22" - - def test_stateful_client_info_cached_across_requests(self): - """In stateful mode, client info is determined by the first request.""" - self._setup_data(stateless=False) - - ctx1 = self._make_request_context("Cursor/2.6.22") - ctx2 = self._make_request_context("Claude Desktop/1.0") - - get_client_info_from_request_context(self.server, ctx1) - get_client_info_from_request_context(self.server, ctx2) - - data = get_server_tracking_data(self.server) - assert data.session_info.client_name == "Cursor" - assert data.session_info.client_version == "2.6.22" diff --git a/tests/test_tool_context.py b/tests/test_tool_context.py index 92b69fe..6482e4a 100644 --- a/tests/test_tool_context.py +++ b/tests/test_tool_context.py @@ -1,97 +1,87 @@ -"""Test tool context functionality.""" +"""Context-parameter injection on the official SDK, end to end. + +One thing about v2 changes what this file used to assert: every tool now also +receives the `session_id` handle, so the injected property order is +`customer params, session_id, context`. + +`context` stays REQUIRED, as it was in 1.x. Nothing server-side rejects a call +that omits it — a schema-validating client refusing to send one is the whole +enforcement mechanism, and without it agents quietly stop supplying intent. +`session_id` is the one injected parameter that is never required: omitting it is +how an agent asks to be minted one. +""" import time from unittest.mock import MagicMock import pytest -from mcp.server import Server from mcp.server.fastmcp import FastMCP -from mcp.types import Tool from agentcat import AgentCatOptions, track from agentcat.modules.constants import DEFAULT_CONTEXT_DESCRIPTION from agentcat.modules.event_queue import EventQueue, set_event_queue from .test_utils.client import create_test_client +from .test_utils.delivery import delivered_arguments_for from .test_utils.todo_server import create_todo_server +async def _tools(server): + async with create_test_client(server) as client: + return (await client.list_tools()).tools + + +def _named(tools, name): + return next(t for t in tools if t.name == name) + + class TestToolContext: """Test tool context functionality.""" @pytest.mark.asyncio async def test_context_parameter_injection_enabled(self): - """Test that context parameter is added when enable_tool_call_context=True.""" + """Context is added — optional — when enable_tool_call_context=True.""" server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - # Check each tool (except get_more_tools if present) - for tool in tools_result.tools: - if tool.name == "get_more_tools": - continue - - # Verify context parameter exists - assert "context" in tool.inputSchema["properties"] + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) - # Verify context is required - assert "context" in tool.inputSchema["required"] - - # Verify context schema properties - context_schema = tool.inputSchema["properties"]["context"] - assert context_schema["type"] == "string" - assert ( - context_schema["description"] - == DEFAULT_CONTEXT_DESCRIPTION - ) + for tool in await _tools(server): + if tool.name == "get_more_tools": + continue + context_schema = tool.inputSchema["properties"]["context"] + assert context_schema["type"] == "string" + assert context_schema["description"] == DEFAULT_CONTEXT_DESCRIPTION + # Required, as in 1.x: a strict client refusing to send a call + # without it is the only thing that makes agents supply intent. + assert "context" in tool.inputSchema["required"] + # ...and session_id is not, because omitting it is the mint signal. + assert "session_id" not in tool.inputSchema.get("required", []) @pytest.mark.asyncio async def test_context_parameter_not_injected_when_disabled(self): - """Test that context parameter is NOT added when enable_tool_call_context=False.""" + """Context is NOT added when enable_tool_call_context=False.""" server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=False) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() + track(server, "test_project", AgentCatOptions(enable_tool_call_context=False)) - for tool in tools_result.tools: - if tool.name == "get_more_tools": - continue - - # Verify context parameter does NOT exist + for tool in await _tools(server): + if tool.name != "get_more_tools": # its own context is not ours assert "context" not in tool.inputSchema.get("properties", {}) - - # Verify context is NOT in required assert "context" not in tool.inputSchema.get("required", []) + # Handles are independent of the context parameter. + assert "session_id" in tool.inputSchema["properties"] @pytest.mark.asyncio async def test_schema_with_existing_properties(self): - """Test with tools that have existing inputSchema and properties.""" + """Existing properties survive, and the injected ones follow them.""" server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - # Find add_todo which has existing schema - add_todo_tool = next(t for t in tools_result.tools if t.name == "add_todo") - - # Verify original properties still exist - assert "text" in add_todo_tool.inputSchema["properties"] - - # Verify context was added - assert "context" in add_todo_tool.inputSchema["properties"] - assert "context" in add_todo_tool.inputSchema["required"] + add_todo = _named(await _tools(server), "add_todo") + properties = list(add_todo.inputSchema["properties"]) + assert properties == ["text", "session_id", "context"] @pytest.mark.asyncio async def test_schema_with_no_input_schema(self): - """Test with tools that have no inputSchema.""" - # Create a custom server with a tool that has no input schema + """A parameterless tool still gets a usable schema with context.""" mcp = FastMCP("test-server") @mcp.tool() @@ -99,67 +89,40 @@ def simple_tool(): """A tool with no parameters.""" return "success" - server = mcp - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - simple_tool_def = next( - t for t in tools_result.tools if t.name == "simple_tool" - ) + track(mcp, "test_project", AgentCatOptions(enable_tool_call_context=True)) - # Verify inputSchema was created - assert simple_tool_def.inputSchema is not None - assert "properties" in simple_tool_def.inputSchema - assert "context" in simple_tool_def.inputSchema["properties"] - assert "required" in simple_tool_def.inputSchema - assert "context" in simple_tool_def.inputSchema["required"] + simple = _named(await _tools(mcp), "simple_tool") + assert simple.inputSchema is not None + assert "context" in simple.inputSchema["properties"] + assert simple.inputSchema["required"] == ["context"] @pytest.mark.asyncio async def test_schema_with_empty_properties(self): - """Test with tools that have empty properties object.""" + """Context lands in an empty properties object.""" mcp = FastMCP("test-server") - # Create a tool with function that has no parameters @mcp.tool() def empty_tool(): """Tool with empty schema.""" return "success" - server = mcp - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - empty_tool = next(t for t in tools_result.tools if t.name == "empty_tool") + track(mcp, "test_project", AgentCatOptions(enable_tool_call_context=True)) - # Verify context was added to empty properties - assert "context" in empty_tool.inputSchema["properties"] - assert len(empty_tool.inputSchema["properties"]) == 1 + empty = _named(await _tools(mcp), "empty_tool") + assert list(empty.inputSchema["properties"]) == ["session_id", "context"] @pytest.mark.asyncio async def test_schema_with_existing_required_fields(self): - """Test with tools that already have required fields.""" + """A tool's own required fields survive, with context appended.""" server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) - # add_todo has 'text' as required - add_todo_tool = next(t for t in tools_result.tools if t.name == "add_todo") - - # Verify both original and context are required - assert "text" in add_todo_tool.inputSchema["required"] - assert "context" in add_todo_tool.inputSchema["required"] - assert len(add_todo_tool.inputSchema["required"]) >= 2 + add_todo = _named(await _tools(server), "add_todo") + assert add_todo.inputSchema["required"] == ["text", "context"] @pytest.mark.asyncio async def test_schema_with_no_required_fields(self): - """Test with tools that have no required fields.""" + """A tool with no required fields gains one holding only context.""" mcp = FastMCP("test-server") @mcp.tool() @@ -167,67 +130,62 @@ def optional_params_tool(param1: str = "default"): """Tool with optional parameters.""" return f"Result: {param1}" - server = mcp - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(mcp, "test_project", AgentCatOptions(enable_tool_call_context=True)) - async with create_test_client(server) as client: - tools_result = await client.list_tools() - tool = next( - t for t in tools_result.tools if t.name == "optional_params_tool" - ) + tool = _named(await _tools(mcp), "optional_params_tool") + assert tool.inputSchema["required"] == ["context"] - # Verify required array was created with context - assert "required" in tool.inputSchema - assert "context" in tool.inputSchema["required"] - assert len(tool.inputSchema["required"]) == 1 + # With the context pass off there is nothing to require at all, so the + # tool's own (absent) required array is left absent. + untouched = FastMCP("test-server-2") + + @untouched.tool() + def other_tool(param1: str = "default"): + """Tool with optional parameters.""" + return f"Result: {param1}" + + track( + untouched, "test_project", AgentCatOptions(enable_tool_call_context=False) + ) + listed = _named(await _tools(untouched), "other_tool") + assert listed.inputSchema.get("required", []) == [] @pytest.mark.asyncio async def test_server_with_no_tools(self): - """Test with a server that has no tools.""" + """A server with no tools lists only get_more_tools.""" mcp = FastMCP("empty-server") - server = mcp - - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() + track(mcp, "test_project", AgentCatOptions(enable_tool_call_context=True)) - # Should have no tools (or only get_more_tools if enabled) - non_report_tools = [ - t for t in tools_result.tools if t.name != "get_more_tools" - ] - assert len(non_report_tools) == 0 + tools = await _tools(mcp) + assert [t.name for t in tools] == ["get_more_tools"] @pytest.mark.asyncio async def test_get_more_tools_exclusion_with_context(self): - """Test that get_more_tools doesn't get context when both features are enabled.""" + """get_more_tools keeps its own bespoke context, not the injected one.""" server = create_todo_server() - options = AgentCatOptions( - enable_report_missing=True, enable_tool_call_context=True + track( + server, + "test_project", + AgentCatOptions(enable_report_missing=True, enable_tool_call_context=True), ) - track(server, "test_project", options) - async with create_test_client(server) as client: - tools_result = await client.list_tools() + tools = await _tools(server) + get_more_tools = _named(tools, "get_more_tools") + context_schema = get_more_tools.inputSchema["properties"]["context"] + assert context_schema["description"] != DEFAULT_CONTEXT_DESCRIPTION + assert get_more_tools.inputSchema["required"] == ["context"] - # Find get_more_tools tool - get_more_tools_tool = next( - t for t in tools_result.tools if t.name == "get_more_tools" + for tool in tools: + if tool.name == "get_more_tools": + continue + assert ( + tool.inputSchema["properties"]["context"]["description"] + == DEFAULT_CONTEXT_DESCRIPTION ) - # Verify it does NOT have context parameter - assert "context" in get_more_tools_tool.inputSchema.get("properties", {}) - - # Verify other tools DO have context - other_tools = [t for t in tools_result.tools if t.name != "get_more_tools"] - for tool in other_tools: - assert "context" in tool.inputSchema["properties"] - @pytest.mark.asyncio async def test_complex_nested_schema(self): - """Test with tools that have complex nested schemas.""" + """Complex nested parameters are preserved alongside the injection.""" mcp = FastMCP("test-server") @mcp.tool() @@ -237,67 +195,45 @@ def complex_tool( """Tool with complex nested parameters.""" return "success" - server = mcp - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - tool = next(t for t in tools_result.tools if t.name == "complex_tool") + track(mcp, "test_project", AgentCatOptions(enable_tool_call_context=True)) - # Verify original complex properties are preserved - assert "user" in tool.inputSchema["properties"] - assert "settings" in tool.inputSchema["properties"] - assert "tags" in tool.inputSchema["properties"] - - # Verify context was added - assert "context" in tool.inputSchema["properties"] + tool = _named(await _tools(mcp), "complex_tool") + properties = tool.inputSchema["properties"] + assert {"user", "settings", "tags"} <= set(properties) + assert "context" in properties @pytest.mark.asyncio async def test_schema_with_validation_rules(self): - """Test with tools that have schema validation rules.""" + """Pydantic-derived constraints survive injection.""" from typing import Annotated + from pydantic import Field mcp = FastMCP("test-server") - # Create tool with validation rules using Pydantic @mcp.tool() def validated_tool(age: Annotated[int, Field(ge=0, le=150)], email: str): """Tool with validation.""" return "success" - server = mcp - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - tool = next(t for t in tools_result.tools if t.name == "validated_tool") - - # Verify original properties are preserved (Pydantic translates to JSON Schema) - assert "age" in tool.inputSchema["properties"] - assert "email" in tool.inputSchema["properties"] - # Pydantic Field validators are converted to JSON Schema constraints - age_schema = tool.inputSchema["properties"]["age"] - assert age_schema["type"] == "integer" - # Check if Pydantic added the constraints (it may use exclusiveMinimum/Maximum) - assert ( - age_schema.get("minimum") == 0 - or age_schema.get("exclusiveMinimum") == -1 - ) - assert ( - age_schema.get("maximum") == 150 - or age_schema.get("exclusiveMaximum") == 151 - ) + track(mcp, "test_project", AgentCatOptions(enable_tool_call_context=True)) - # Verify context was added - assert "context" in tool.inputSchema["properties"] - assert "context" in tool.inputSchema["required"] + tool = _named(await _tools(mcp), "validated_tool") + age_schema = tool.inputSchema["properties"]["age"] + assert age_schema["type"] == "integer" + assert ( + age_schema.get("minimum") == 0 + or age_schema.get("exclusiveMinimum") == -1 + ) + assert ( + age_schema.get("maximum") == 150 + or age_schema.get("exclusiveMaximum") == 151 + ) + assert "context" in tool.inputSchema["properties"] @pytest.mark.asyncio async def test_tool_with_existing_context_parameter(self): - """Test that existing context parameter is respected and not overwritten.""" + """A tool that already declares `context` keeps its own, untouched.""" mcp = FastMCP("test-server") @mcp.tool() @@ -305,84 +241,78 @@ def tool_with_context(context: str, data: str): """Tool that already has a context parameter.""" return f"Original context: {context}, data: {data}" - server = mcp - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(mcp, "test_project", AgentCatOptions(enable_tool_call_context=True)) - async with create_test_client(server) as client: - tools_result = await client.list_tools() - tool = next(t for t in tools_result.tools if t.name == "tool_with_context") + tool = _named(await _tools(mcp), "tool_with_context") + context_schema = tool.inputSchema["properties"]["context"] + assert context_schema.get("description") != DEFAULT_CONTEXT_DESCRIPTION + # Still the customer's own required parameter. + assert "context" in tool.inputSchema["required"] - # Verify context exists - assert "context" in tool.inputSchema["properties"] - - # Check if the context has been modified or kept original - context_schema = tool.inputSchema["properties"]["context"] - # If context already existed, implementation checks if "context" not in properties - # So it should keep the original schema - # Let's check if it has our custom description or the original - desc = context_schema.get("description", "") - if ( - desc - == DEFAULT_CONTEXT_DESCRIPTION - ): - # Our description was added - this means the implementation overwrote it - # This happens because the check is at the property level not parameter level - pass - else: - # Original schema was kept - verify it has some content - assert context_schema.get("type") == "string" - - # Should still be in required - assert "context" in tool.inputSchema["required"] + # ...and it reaches the tool body, because AgentCat never injected it. + async with create_test_client(mcp) as client: + result = await client.call_tool( + "tool_with_context", {"context": "mine", "data": "d"} + ) + assert "Original context: mine" in result.content[0].text @pytest.mark.asyncio async def test_schema_with_allof_anyof_oneof(self): - """Test with tools that have allOf, anyOf, oneOf schema compositions.""" - from typing import Union - + """Composition inside a property does not block injection.""" mcp = FastMCP("test-server") - # Create tool with complex schema using Union type @mcp.tool() - def composed_tool(data: Union[str, int], required_field: str): + def composed_tool(data: str | int, required_field: str): """Tool with schema composition.""" return f"Data: {data}, Required: {required_field}" - server = mcp - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(mcp, "test_project", AgentCatOptions(enable_tool_call_context=True)) - async with create_test_client(server) as client: - tools_result = await client.list_tools() - tool = next(t for t in tools_result.tools if t.name == "composed_tool") - - # Verify original properties are preserved - # Union types in Python are converted to anyOf in JSON Schema - assert "data" in tool.inputSchema["properties"] - assert "required_field" in tool.inputSchema["properties"] + tool = _named(await _tools(mcp), "composed_tool") + data_schema = tool.inputSchema["properties"]["data"] + assert ( + "anyOf" in data_schema + or "oneOf" in data_schema + or data_schema.get("type") == ["string", "integer"] + ) + assert "context" in tool.inputSchema["properties"] + + @pytest.mark.asyncio + async def test_top_level_composed_schema_is_skipped(self): + """A oneOf/allOf/anyOf schema has no single properties bag to extend.""" + from mcp.server.lowlevel import Server + from mcp.types import Tool + + server = Server("composed-server") + + @server.list_tools() + async def list_tools(): + return [ + Tool( + name="composed_root", + description="Top-level composition.", + inputSchema={ + "anyOf": [ + {"type": "object", "properties": {"a": {"type": "string"}}}, + {"type": "object", "properties": {"b": {"type": "string"}}}, + ] + }, + ) + ] - # Check if Union was converted properly (might be anyOf or oneOf) - data_schema = tool.inputSchema["properties"]["data"] - # FastMCP may handle Union differently, just verify it accepts multiple types - assert ( - "anyOf" in data_schema - or "oneOf" in data_schema - or data_schema.get("type") == ["string", "integer"] - ) + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) - # Verify context was added - assert "context" in tool.inputSchema["properties"] + tool = _named(await _tools(server), "composed_root") + assert "properties" not in tool.inputSchema + assert "anyOf" in tool.inputSchema @pytest.mark.asyncio async def test_tool_call_with_valid_context(self): - """Test calling a tool with valid context parameter.""" + """Calling a tool with a context argument succeeds.""" server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) async with create_test_client(server) as client: - # Call tool with context result = await client.call_tool( "add_todo", { @@ -391,111 +321,56 @@ async def test_tool_call_with_valid_context(self): }, ) - # Should succeed - assert result.content - assert "Added todo" in result.content[0].text + assert "Added todo" in result.content[0].text @pytest.mark.asyncio - async def test_tool_call_without_context_fails(self): - """Test that tool calls without context fail validation.""" + async def test_tool_call_without_context_still_succeeds(self): + """Context is optional: omitting it must not fail the call.""" server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) async with create_test_client(server) as client: - # The implementation strips context before passing to handler - # So this test verifies the behavior is logged but call still works - result = await client.call_tool( - "add_todo", - {"text": "Test todo item"}, # Missing context - ) - - # The call should succeed because context is stripped before passing to handler - assert result.content - assert "Added todo" in result.content[0].text + result = await client.call_tool("add_todo", {"text": "Test todo item"}) - @pytest.mark.asyncio - async def test_tool_call_with_empty_context(self): - """Test calling a tool with empty string context.""" - server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_test_client(server) as client: - # Call with empty context - should still work - result = await client.call_tool( - "add_todo", - { - "text": "Test todo", - "context": "", # Empty but present - }, - ) - - assert result.content - assert "Added todo" in result.content[0].text - - @pytest.mark.asyncio - async def test_tool_call_with_long_context(self): - """Test calling a tool with very long context string.""" - server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_test_client(server) as client: - # Create a very long context - long_context = "This is a very long context. " * 100 - - result = await client.call_tool( - "add_todo", {"text": "Test todo", "context": long_context} - ) - - assert result.content - assert "Added todo" in result.content[0].text + assert "Added todo" in result.content[0].text @pytest.mark.asyncio - async def test_tool_call_with_unicode_context(self): - """Test calling a tool with special characters/unicode in context.""" - server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) - - async with create_test_client(server) as client: - # Unicode context - unicode_context = "Testing with emojis 🚀🎉 and special chars: ñáéíóú" - - result = await client.call_tool( - "add_todo", {"text": "Test todo", "context": unicode_context} - ) - - assert result.content - assert "Added todo" in result.content[0].text + @pytest.mark.parametrize( + "context", + [ + "", + None, + "This is a very long context. " * 100, + "Testing with emojis 🚀🎉 and special chars: ñáéíóú", + ], + ids=["empty", "null", "long", "unicode"], + ) + async def test_tool_call_with_edge_case_context(self, context): + """Every context shape is stripped before the tool body sees it. - @pytest.mark.asyncio - async def test_tool_call_with_null_context(self): - """Test calling a tool with null/None context value.""" + Read at the tool manager: `add_todo(text: str)` is a typed body, and + this SDK's manager drops an undeclared argument silently, so "the call + succeeded" is not evidence that `context` was removed. + """ server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) async with create_test_client(server) as client: - # Try with None/null context - it should work since context is stripped result = await client.call_tool( - "add_todo", {"text": "Test todo", "context": None} + "add_todo", {"text": "Test todo", "context": context} ) - # Should succeed because context is stripped - assert result.content - assert "Added todo" in result.content[0].text + assert result.isError is False + assert "Added todo" in result.content[0].text + assert delivered_arguments_for(server, "add_todo") == [{"text": "Test todo"}] @pytest.mark.asyncio async def test_original_functionality_preserved(self): - """Verify that original tool functionality remains intact with context.""" + """A whole tool workflow behaves identically under tracking.""" server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) async with create_test_client(server) as client: - # Add multiple todos await client.call_tool( "add_todo", {"text": "First todo", "context": "Adding first item"} ) @@ -503,218 +378,119 @@ async def test_original_functionality_preserved(self): "add_todo", {"text": "Second todo", "context": "Adding second item"} ) - # List todos list_result = await client.call_tool( "list_todos", {"context": "Listing all todos to verify they were added"} ) - - # Verify both todos are present assert "First todo" in list_result.content[0].text assert "Second todo" in list_result.content[0].text - # Complete a todo complete_result = await client.call_tool( "complete_todo", {"id": 1, "context": "Completing the first todo"} ) - assert "Completed todo" in complete_result.content[0].text @pytest.mark.asyncio async def test_context_not_passed_to_original_handler(self): - """Verify that context parameter is stripped before passing to original handler.""" - # This test verifies the current implementation behavior - # Context is added to schema but stripped from arguments before passing to handler + """`context` is gone from what the tool layer is handed. + + A successful call proves nothing on its own — the tool manager drops + arguments `add_todo` never declared without raising — so the evidence + is the argument dict the manager itself received. + """ server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) async with create_test_client(server) as client: - # Call with context result = await client.call_tool( "add_todo", {"text": "test data", "context": "This context should be stripped"}, ) - # The call should succeed, proving context was stripped - # (otherwise it would fail since add_todo doesn't accept context param) - assert result.content - assert "Added todo" in result.content[0].text + assert result.isError is False + assert "Added todo" in result.content[0].text + assert delivered_arguments_for(server, "add_todo") == [{"text": "test data"}] @pytest.mark.asyncio async def test_multiple_track_calls(self): - """Test multiple calls to track() on the same server.""" + """The most recent track() call's options are the ones in force.""" server = create_todo_server() + track(server, "project1", AgentCatOptions(enable_tool_call_context=False)) + track(server, "project2", AgentCatOptions(enable_tool_call_context=True)) - # First track with context disabled - options1 = AgentCatOptions(enable_tool_call_context=False) - track(server, "project1", options1) - - # Second track with context enabled - options2 = AgentCatOptions(enable_tool_call_context=True) - track(server, "project2", options2) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - # Should reflect the latest tracking options - for tool in tools_result.tools: - if tool.name != "get_more_tools": - assert "context" in tool.inputSchema["properties"] + for tool in await _tools(server): + if tool.name != "get_more_tools": + assert "context" in tool.inputSchema["properties"] @pytest.mark.asyncio async def test_changing_options_between_calls(self): - """Test changing options between track calls.""" + """Re-tracking with context off removes it — v1 could not undo an injection.""" server = create_todo_server() + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) + assert "context" in _named(await _tools(server), "add_todo").inputSchema[ + "properties" + ] - # Track with context enabled - options_enabled = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options_enabled) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - # Verify context is added - add_todo = next(t for t in tools_result.tools if t.name == "add_todo") - assert "context" in add_todo.inputSchema["properties"] - - # The current implementation updates the tracking data with new options - # Track again with context disabled - options_disabled = AgentCatOptions(enable_tool_call_context=False) - track(server, "test_project", options_disabled) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - add_todo = next(t for t in tools_result.tools if t.name == "add_todo") - # The handlers get wrapped multiple times, so the behavior is: - # - First handler adds context (from first track call) - # - Second handler checks options and doesn't add context - # But the first handler already added it, so context will still be present - # This is the current implementation behavior - assert "context" in add_todo.inputSchema["properties"] + track(server, "test_project", AgentCatOptions(enable_tool_call_context=False)) + assert ( + "context" + not in _named(await _tools(server), "add_todo").inputSchema["properties"] + ) @pytest.mark.asyncio async def test_error_handling_graceful_fallback(self): - """Test that errors in context injection don't break original tools.""" - # This test would require mocking internal functions to force errors - # For now, we'll test that the system is resilient + """Tools remain listable and callable regardless.""" server = create_todo_server() - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) async with create_test_client(server) as client: - # Even if there were errors, tools should still be callable tools_result = await client.list_tools() assert len(tools_result.tools) > 0 - - # Original functionality should work - result = await client.call_tool( - "list_todos", - {"context": "Listing todos"}, # Try with context - ) + result = await client.call_tool("list_todos", {"context": "Listing todos"}) assert result.content @pytest.mark.asyncio - async def test_custom_context_description(self): - """Test that custom context description is correctly applied.""" - server = create_todo_server() - custom_description = "Explain your reasoning for using this tool" - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=custom_description - ) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - # Check each tool (except get_more_tools) - for tool in tools_result.tools: - if tool.name == "get_more_tools": - continue - - # Verify context parameter has custom description - context_schema = tool.inputSchema["properties"]["context"] - assert context_schema["description"] == custom_description - - @pytest.mark.asyncio - async def test_custom_context_description_empty_string(self): - """Test edge case with empty string custom description.""" - server = create_todo_server() - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description="" # Empty string - ) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - # Find a tool to test - add_todo_tool = next(t for t in tools_result.tools if t.name == "add_todo") - - # Verify context exists with empty description - context_schema = add_todo_tool.inputSchema["properties"]["context"] - assert context_schema["description"] == "" - assert context_schema["type"] == "string" - - @pytest.mark.asyncio - async def test_custom_context_description_special_characters(self): - """Test custom description with special characters and Unicode.""" - server = create_todo_server() - special_description = "Why are you using this? 🤔 Include: quotes\"', newlines\n, tabs\t, etc." - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=special_description - ) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - # Verify special characters are preserved - add_todo_tool = next(t for t in tools_result.tools if t.name == "add_todo") - context_schema = add_todo_tool.inputSchema["properties"]["context"] - assert context_schema["description"] == special_description - - @pytest.mark.asyncio - async def test_custom_context_description_very_long(self): - """Test with a very long description string.""" + @pytest.mark.parametrize( + "description", + [ + "Explain your reasoning for using this tool", + "", + "Why are you using this? 🤔 Include: quotes\"', newlines\n, tabs\t, etc.", + "This is a very detailed description. " * 50, + ], + ids=["custom", "empty", "special-characters", "very-long"], + ) + async def test_custom_context_description(self, description): + """Whatever the customer sets is what the agent sees, verbatim.""" server = create_todo_server() - # Create a very long description - long_description = "This is a very detailed description. " * 50 # ~1800 characters - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=long_description + track( + server, + "test_project", + AgentCatOptions( + enable_tool_call_context=True, custom_context_description=description + ), ) - track(server, "test_project", options) - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - # Verify long description is preserved - add_todo_tool = next(t for t in tools_result.tools if t.name == "add_todo") - context_schema = add_todo_tool.inputSchema["properties"]["context"] - assert context_schema["description"] == long_description - assert len(context_schema["description"]) > 1000 + for tool in await _tools(server): + if tool.name == "get_more_tools": + continue + context_schema = tool.inputSchema["properties"]["context"] + assert context_schema["description"] == description @pytest.mark.asyncio async def test_default_context_description(self): - """Verify the default description is used when not specified.""" + """The default description is used when none is specified.""" server = create_todo_server() - # Don't specify custom_context_description, should use default - options = AgentCatOptions(enable_tool_call_context=True) - track(server, "test_project", options) + track(server, "test_project", AgentCatOptions(enable_tool_call_context=True)) - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - # Check for default description - add_todo_tool = next(t for t in tools_result.tools if t.name == "add_todo") - context_schema = add_todo_tool.inputSchema["properties"]["context"] - assert context_schema["description"] == DEFAULT_CONTEXT_DESCRIPTION + add_todo = _named(await _tools(server), "add_todo") + assert ( + add_todo.inputSchema["properties"]["context"]["description"] + == DEFAULT_CONTEXT_DESCRIPTION + ) @pytest.mark.asyncio async def test_custom_context_description_with_multiple_tools(self): - """Test that custom description is applied to all tools consistently.""" + """One description, applied consistently across every tool.""" mcp = FastMCP("test-server") @mcp.tool() @@ -732,166 +508,117 @@ def tool3(): """Third tool with no params.""" return "Tool 3" - server = mcp custom_desc = "Custom context for all tools" - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=custom_desc + track( + mcp, + "test_project", + AgentCatOptions( + enable_tool_call_context=True, custom_context_description=custom_desc + ), ) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - # All tools should have the same custom context description - for tool in tools_result.tools: - if tool.name in ["tool1", "tool2", "tool3"]: - assert "context" in tool.inputSchema["properties"] - assert tool.inputSchema["properties"]["context"]["description"] == custom_desc + for tool in await _tools(mcp): + if tool.name in ("tool1", "tool2", "tool3"): + assert ( + tool.inputSchema["properties"]["context"]["description"] + == custom_desc + ) @pytest.mark.asyncio async def test_custom_context_description_change_between_tracks(self): - """Test changing custom description between track calls.""" + """The latest track() wins outright.""" server = create_todo_server() - - # First track with one description - options1 = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description="First description" + track( + server, + "test_project", + AgentCatOptions( + enable_tool_call_context=True, + custom_context_description="First description", + ), ) - track(server, "test_project", options1) - - # Second track with different description - options2 = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description="Second description" + track( + server, + "test_project", + AgentCatOptions( + enable_tool_call_context=True, + custom_context_description="Second description", + ), ) - track(server, "test_project", options2) - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - # Should use the most recent description - add_todo_tool = next(t for t in tools_result.tools if t.name == "add_todo") - context_schema = add_todo_tool.inputSchema["properties"]["context"] - # Due to wrapping behavior, the first track's description might persist - # This test documents the actual behavior - assert context_schema["description"] in ["First description", "Second description"] + add_todo = _named(await _tools(server), "add_todo") + assert ( + add_todo.inputSchema["properties"]["context"]["description"] + == "Second description" + ) @pytest.mark.asyncio async def test_custom_context_with_tool_call(self): - """Test tool calls work correctly with custom context description.""" - server = create_todo_server() + """A custom description does not change call behavior.""" custom_desc = "Provide detailed reasoning for this action" - options = AgentCatOptions( - enable_tool_call_context=True, - custom_context_description=custom_desc + server = create_todo_server() + track( + server, + "test_project", + AgentCatOptions( + enable_tool_call_context=True, custom_context_description=custom_desc + ), ) - track(server, "test_project", options) async with create_test_client(server) as client: - # Verify the custom description is set tools_result = await client.list_tools() - add_todo_tool = next(t for t in tools_result.tools if t.name == "add_todo") - assert add_todo_tool.inputSchema["properties"]["context"]["description"] == custom_desc + add_todo = _named(tools_result.tools, "add_todo") + assert ( + add_todo.inputSchema["properties"]["context"]["description"] + == custom_desc + ) - # Call the tool with context result = await client.call_tool( "add_todo", { "text": "Test with custom description", - "context": "Adding todo to test custom context description feature" - } + "context": "Adding todo to test custom context description feature", + }, ) - - # Should succeed - assert result.content assert "Added todo" in result.content[0].text class TestGetMoreToolsContextSchema: """Test that get_more_tools has a proper context parameter schema.""" - @pytest.mark.asyncio - async def test_get_more_tools_context_has_string_type(self): - """get_more_tools context parameter should have type 'string', not a union type.""" + @pytest.fixture + async def get_more_tools_def(self): server = create_todo_server() - options = AgentCatOptions( - enable_report_missing=True, - enable_tool_call_context=True, + track( + server, + "test_project", + AgentCatOptions(enable_report_missing=True, enable_tool_call_context=True), ) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - get_more_tools_tool = next( - t for t in tools_result.tools if t.name == "get_more_tools" - ) - - context_schema = get_more_tools_tool.inputSchema["properties"]["context"] - # Context should be a simple string type, not a union/anyOf - assert "anyOf" not in context_schema, ( - f"get_more_tools context should not use anyOf (union type), got: {context_schema}" - ) - assert context_schema.get("type") == "string", ( - f"get_more_tools context should be type 'string', got: {context_schema}" - ) + return _named(await _tools(server), "get_more_tools") @pytest.mark.asyncio - async def test_get_more_tools_context_has_description(self): - """get_more_tools context parameter should have a meaningful description.""" - server = create_todo_server() - options = AgentCatOptions( - enable_report_missing=True, - enable_tool_call_context=True, - ) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() - - get_more_tools_tool = next( - t for t in tools_result.tools if t.name == "get_more_tools" - ) - - context_schema = get_more_tools_tool.inputSchema["properties"]["context"] - assert "description" in context_schema, ( - "get_more_tools context parameter should have a description" - ) - assert len(context_schema["description"]) > 10, ( - "get_more_tools context description should be meaningful" - ) + async def test_get_more_tools_context_has_string_type(self, get_more_tools_def): + """It should be a simple string, not a union type.""" + context_schema = get_more_tools_def.inputSchema["properties"]["context"] + assert "anyOf" not in context_schema, context_schema + assert context_schema.get("type") == "string", context_schema @pytest.mark.asyncio - async def test_get_more_tools_context_is_required(self): - """get_more_tools context parameter should be required.""" - server = create_todo_server() - options = AgentCatOptions( - enable_report_missing=True, - enable_tool_call_context=True, - ) - track(server, "test_project", options) - - async with create_test_client(server) as client: - tools_result = await client.list_tools() + async def test_get_more_tools_context_has_description(self, get_more_tools_def): + """It should carry a meaningful description.""" + context_schema = get_more_tools_def.inputSchema["properties"]["context"] + assert len(context_schema["description"]) > 10 - get_more_tools_tool = next( - t for t in tools_result.tools if t.name == "get_more_tools" - ) - - required = get_more_tools_tool.inputSchema.get("required", []) - assert "context" in required, ( - "get_more_tools context parameter should be required" - ) + @pytest.mark.asyncio + async def test_get_more_tools_context_is_required(self, get_more_tools_def): + """Its bespoke context is a real parameter, so it stays required.""" + assert "context" in get_more_tools_def.inputSchema.get("required", []) class TestUserIntentCaptureInEvents: - """Test that user_intent is captured in events for the official FastMCP monkey patching.""" + """user_intent is captured from the context argument on published events.""" @pytest.fixture(autouse=True) def setup_and_teardown(self): - """Set up and tear down mock event queue.""" from agentcat.modules.event_queue import event_queue as original_queue yield @@ -899,31 +626,29 @@ def setup_and_teardown(self): @pytest.mark.asyncio async def test_get_more_tools_captures_user_intent_in_event(self): - """get_more_tools calls should capture user_intent from context in the event.""" mock_api_client = MagicMock() captured_events = [] - - def capture_event(publish_event_request): - captured_events.append(publish_event_request) - - mock_api_client.publish_event = MagicMock(side_effect=capture_event) - - test_queue = EventQueue(api_client=mock_api_client) - set_event_queue(test_queue) + mock_api_client.publish_event = MagicMock( + side_effect=lambda publish_event_request: captured_events.append( + publish_event_request + ) + ) + set_event_queue(EventQueue(api_client=mock_api_client)) server = create_todo_server() - options = AgentCatOptions( - enable_tracing=True, - enable_report_missing=True, - enable_tool_call_context=True, + track( + server, + "test_project", + AgentCatOptions( + enable_tracing=True, + enable_report_missing=True, + enable_tool_call_context=True, + ), ) - track(server, "test_project", options) async with create_test_client(server) as client: - # Call get_more_tools with context await client.call_tool( - "get_more_tools", - {"context": "I need a tool to send emails"}, + "get_more_tools", {"context": "I need a tool to send emails"} ) time.sleep(1.0) @@ -933,9 +658,5 @@ def capture_event(publish_event_request): if e.event_type == "mcp:tools/call" and e.resource_name == "get_more_tools" ] - assert len(tool_events) > 0, "No get_more_tools event captured" - - event = tool_events[0] - assert event.user_intent == "I need a tool to send emails", ( - f"user_intent should be captured from get_more_tools context, got: {event.user_intent}" - ) + assert len(tool_events) == 1 + assert tool_events[0].user_intent == "I need a tool to send emails" diff --git a/tests/test_truncation.py b/tests/test_truncation.py index 324b104..de20812 100644 --- a/tests/test_truncation.py +++ b/tests/test_truncation.py @@ -5,6 +5,8 @@ import pytest +from .conftest import MCP_MAJOR + from agentcat import AgentCatOptions, track from agentcat.modules.event_queue import EventQueue, set_event_queue from agentcat.modules.truncation import ( @@ -291,6 +293,10 @@ def test_truncation_is_imported_in_event_queue(self): assert "truncate_event" in source +@pytest.mark.skipif( + MCP_MAJOR >= 2, + reason="uses the mcp 1.x in-memory client harness; ported in Task 12", +) class TestTruncationWithTodoServer: """Integration tests: oversized tool calls through the real todo server are truncated.""" diff --git a/tests/test_truncation_json_safe.py b/tests/test_truncation_json_safe.py index cd9a2fe..fd28a4d 100644 --- a/tests/test_truncation_json_safe.py +++ b/tests/test_truncation_json_safe.py @@ -16,12 +16,12 @@ def _poison_response(): - # Mirrors what tool.model_dump() embeds for FastMCP v3 tools: a callable and a set. + # Mirrors what a FastMCP v3 tool's model_dump() embeds: a callable and a set. return {"tools": [{"name": "t", "fn": (lambda: 1), "tags": {"a", "b"}}]} def test_truncate_event_does_not_log_failure_on_callable_and_set(): - event = UnredactedEvent(event_type="mcp:tools/list", response=_poison_response()) + event = UnredactedEvent(event_type="mcp:tools/call", response=_poison_response()) with patch.object(truncation, "write_to_log") as mock_log: result = truncate_event(event) failures = [ @@ -35,7 +35,7 @@ def test_truncate_event_does_not_log_failure_on_callable_and_set(): def test_truncated_event_is_json_serializable(): """After truncation the event's payload must contain only JSON-safe primitives.""" - event = UnredactedEvent(event_type="mcp:tools/list", response=_poison_response()) + event = UnredactedEvent(event_type="mcp:tools/call", response=_poison_response()) result = truncate_event(event) # The event the API client re-serializes on send must not carry a callable/set. json.dumps(result.response) # would raise if a set/function survived diff --git a/tests/test_utils/__init__.py b/tests/test_utils/__init__.py index 7166fb8..a07d9cb 100644 --- a/tests/test_utils/__init__.py +++ b/tests/test_utils/__init__.py @@ -1,12 +1,43 @@ """Test utilities for AgentCat tests.""" import os +from importlib.metadata import version from pathlib import Path import pytest LOG_FILE = "agentcat.log" +MCP_MAJOR = int(version("mcp").split(".")[0]) + +# For the integration tests inside otherwise era-agnostic modules. `conftest.py` +# gates whole FILES by era; a module that mixes plain unit tests with a class +# built on `create_todo_server()` / `create_test_client()` (both mcp 1.x-only) +# would lose its unit tests to that gate, so it marks just the class instead. +LEGACY_ONLY = pytest.mark.skipif( + MCP_MAJOR >= 2, + reason="built on the mcp 1.x FastMCP + in-memory client harness", +) + +# The other half of the same gate, for a module whose eras belong side by side: +# `test_inner_tap.py` proves one contract on every generation, so splitting it +# across the two conftest-gated trees would hide the parity it exists to show. +MODERN_ONLY = pytest.mark.skipif( + MCP_MAJOR < 2, + reason="built on the mcp 2.x MCPServer + in-process Client harness", +) + + +def sid(label: str) -> str: + """A valid 27-char session ID that still reads as its label in failures. + + `resolve_handles` only honors IDs shaped like the ones this SDK issues, so + a fixture cannot be `"ses_parent"` any more. Real KSUIDs are opaque; test + fixtures should not be, hence the label survives in the body. + """ + body = ("".join(c for c in label if c.isalnum()) + "0" * 27)[:27] + return f"ses_{body}" + def cleanup_log_file(): """Remove the log file if it exists.""" diff --git a/tests/test_utils/client.py b/tests/test_utils/client.py index ad2f13e..f4f136f 100644 --- a/tests/test_utils/client.py +++ b/tests/test_utils/client.py @@ -1,10 +1,19 @@ -"""Test client utilities for AgentCat tests.""" +"""Test client utilities for AgentCat tests (official MCP SDK 1.x). + +Import-safe under mcp 2.x, which removed both symbols below; see the note in +`todo_server.py`. `test_utils.modern_server.create_modern_client` is the 2.x +counterpart. +""" from contextlib import asynccontextmanager from typing import Any, AsyncGenerator from mcp import ClientSession -from mcp.shared.memory import create_connected_server_and_client_session + +try: + from mcp.shared.memory import create_connected_server_and_client_session +except ImportError: # mcp 2.x + create_connected_server_and_client_session = None try: from mcp.server import FastMCP @@ -32,6 +41,12 @@ async def create_test_client(server: Any) -> AsyncGenerator[ClientSession, None] async with create_test_client(server) as client: result = await client.call_tool("add_todo", {"text": "Test"}) """ + if create_connected_server_and_client_session is None: + raise ImportError( + "mcp.shared.memory.create_connected_server_and_client_session was " + "removed in mcp 2.x. Use test_utils.modern_server.create_modern_client." + ) + # MCP v1.2.0 doesn't support client_info parameter # Default client name is "mcp" and version is "0.1.0" diff --git a/tests/test_utils/community_openapi_server.py b/tests/test_utils/community_openapi_server.py index 4f2e581..d18df45 100644 --- a/tests/test_utils/community_openapi_server.py +++ b/tests/test_utils/community_openapi_server.py @@ -1,4 +1,4 @@ -"""Factories for FastMCP v3 servers whose tools hold live runtime state. +"""Factories for community FastMCP (v3/v4) servers whose tools hold live state. These build the classes of tool that carry non-deepcopyable runtime state and therefore broke context injection before PR #38: @@ -20,13 +20,28 @@ # Lazy, guarded imports so importing this module never fails the no-FastMCP CI job # or the FastMCP v2 compatibility matrix. Callers gate on HAS_FASTMCP_V3. +# +# The HTTP client has to be the one the INSTALLED FastMCP builds its OpenAPI +# provider on — v3 takes an `httpx.AsyncClient`, v4 an `httpx2.AsyncClient` — +# so the major picks it. Falling back on ImportError instead would be right only +# for as long as the unwanted package stays absent: `httpx` is a common +# transitive dependency, and the day it lands beside FastMCP 4 a "try httpx +# first" guard would hand the v4 provider a client library it does not use, with +# no error to say so. Both packages expose the same `AsyncClient` / +# `MockTransport` / `Response` surface this module needs. try: - import httpx import fastmcp + + _FASTMCP_MAJOR = int(fastmcp.__version__.split(".")[0]) + if _FASTMCP_MAJOR >= 4: + import httpx2 as httpx # type: ignore[no-redef] + else: + import httpx + from fastmcp import FastMCP as CommunityFastMCP from fastmcp.server.providers.openapi import MCPType, RouteMap - HAS_FASTMCP_V3 = int(fastmcp.__version__.split(".")[0]) >= 3 + HAS_FASTMCP_V3 = _FASTMCP_MAJOR >= 3 except Exception: # pragma: no cover - import guard httpx = None # type: ignore CommunityFastMCP = None # type: ignore diff --git a/tests/test_utils/delivery.py b/tests/test_utils/delivery.py new file mode 100644 index 0000000..13cfd07 --- /dev/null +++ b/tests/test_utils/delivery.py @@ -0,0 +1,73 @@ +"""Observe what a facade's tool manager was actually handed. + +The one seam on the official facades where a strip regression is visible. + +A typed tool body cannot witness the strip. `def add_todo(text: str)` can only +ever report `text` — an argument that arrived and was dropped on the way in +leaves no trace in the body, so `seen["text"] = text` inside the function is +the same value whether or not AgentCat stripped anything. + +And both official tool managers DO drop an undeclared argument silently. +Measured on mcp 1.29 (`mcp.server.fastmcp.FastMCP`) and mcp 2.0 (`MCPServer`): +``call_tool("add_todo", {"text": "hi", "session_id": "ses_X"})`` returns the +tool's normal result with no error. Only community FastMCP raises. So a test +that sends an extra parameter to a typed body and asserts "no error" proves +nothing about the strip — it passes identically with the strip disabled. + +Wrapping the manager makes the delivered dict observable. Both eras spell the +seam identically (``call_tool(name, arguments, ...)``), and the wrapper is +installed by the server factories BEFORE ``track()``, so the adapter's inner +tap wraps the same attribute afterwards and sits above this recorder — what it +records is therefore post-strip delivery. + +**Either order works, so do not "fix" a caller that installs this AFTER +``track()``** (`test_dynamic_tracking.py` does). The strip does not happen at +the tool manager at all: it runs at the lowlevel request-handler seam +(`modules/callpath.py`), which is above the manager on every flavor. So the +arguments reaching `call_tool` are already stripped no matter where this +wrapper sits in the manager's own decorator stack. The before-``track()`` +ordering is a convention for the shared factories, not a correctness +requirement. +""" + +from __future__ import annotations + +from typing import Any + +# Where each factory parks its recording, so tests have one name to read. +DELIVERED_ATTR = "delivered_arguments" + + +def record_delivered_arguments( + manager: Any, seen: list[tuple[str, dict[str, Any]]] +) -> None: + """Append ``(tool_name, arguments)`` to `seen` for every call `manager` runs.""" + original = manager.call_tool + + async def recording(name: str, arguments: dict[str, Any], *args: Any, **kw: Any): + seen.append((name, dict(arguments or {}))) + return await original(name, arguments, *args, **kw) + + manager.call_tool = recording + + +def attach_delivery_recorder(server: Any, manager: Any) -> list[tuple[str, dict]]: + """Record `manager`'s deliveries onto ``server.delivered_arguments``. + + Returns the same list the attribute holds, so a factory can hand it back + directly. Call before ``track()``. + """ + seen: list[tuple[str, dict[str, Any]]] = [] + record_delivered_arguments(manager, seen) + setattr(server, DELIVERED_ATTR, seen) + return seen + + +def delivered(server: Any) -> list[tuple[str, dict[str, Any]]]: + """What `server`'s tool manager has been handed so far.""" + return getattr(server, DELIVERED_ATTR) + + +def delivered_arguments_for(server: Any, tool_name: str) -> list[dict[str, Any]]: + """Just the argument dicts `tool_name` was called with, in order.""" + return [args for name, args in delivered(server) if name == tool_name] diff --git a/tests/test_utils/flavors.py b/tests/test_utils/flavors.py new file mode 100644 index 0000000..5b6165d --- /dev/null +++ b/tests/test_utils/flavors.py @@ -0,0 +1,695 @@ +"""Every server shape the v2 adapters serve, behind one small interface. + +The cross-flavor regressions — concurrency, removed events, rebuild-on-demand, +the per-flavor ``response`` spelling — have to hold on every shape a customer +can hand ``track()``. There are six of them, four adapters wide and two +dependency sets deep, and a suite that quietly covered five would be worse than +one that covered none: it would read as complete. + +So the shapes are enumerated once, here. Each `Flavor` is a small explicit +description of ONE real server — how to build it, how to talk to it, and where +its list source is. There is no normalization layer over the SDKs; only the +three era spellings the tests actually read are bridged (``inputSchema`` vs +``input_schema``, ``structuredContent`` vs ``structured_content``, ``isError`` +vs ``is_error``). + +`flavors()` returns exactly the shapes the INSTALLED dependency set can build. +``tests/test_detection.py::TestRealServerObjects`` pins that the list is +complete for its era and that every ``Flavor.flavor`` here is what +`detect_server` actually says about the object `build` returns, so neither can +drift silently. + +Every ``mcp`` / ``fastmcp`` import is function-local: this module is imported +by test files that collect under both SDK majors. +""" + +from __future__ import annotations + +import contextlib +import copy +from collections.abc import AsyncIterator, Awaitable, Callable +from dataclasses import dataclass, field +from importlib.metadata import PackageNotFoundError, version +from typing import Any + +from agentcat.modules.constants import GET_MORE_TOOLS_NAME +from agentcat.modules.detection import ServerFlavor +from tests.test_utils.delivery import record_delivered_arguments + +MCP_MAJOR = int(version("mcp").split(".")[0]) + +try: + FASTMCP_MAJOR: int | None = int(version("fastmcp").split(".")[0]) +except PackageNotFoundError: # pragma: no cover - community extra not installed + FASTMCP_MAJOR = None + +# A tool body's hook, awaited from inside the customer's handler. The +# concurrency test uses it to hold every call inside the adapter's per-call +# window at once. +Hook = Callable[[], Awaitable[None]] + +ECHO_INPUT_SCHEMA: dict[str, Any] = { + "type": "object", + "properties": {"text": {"type": "string"}}, + "required": ["text"], +} +RESULT_OUTPUT_SCHEMA: dict[str, Any] = { + "type": "object", + "properties": {"result": {"type": "string"}}, + "required": ["result"], +} +CONTEXT_INPUT_SCHEMA: dict[str, Any] = { + "type": "object", + "properties": {"context": {"type": "string"}}, + "required": ["context"], +} +# A customer tool whose OWN first parameter is called `session_id` — a task +# tracker, a ticketing system, a job runner. Nothing about it is AgentCat's: +# the injection pass sees the collision and leaves the name alone, the strip +# spares it, and the call path must not read it as the analytics handle. +CUSTOMER_SESSION_ID_DESCRIPTION = "The customer's own session identifier." +COMPLETE_INPUT_SCHEMA: dict[str, Any] = { + "type": "object", + "properties": { + "session_id": { + "type": "string", + "description": CUSTOMER_SESSION_ID_DESCRIPTION, + }, + "note": {"type": "string"}, + }, + "required": ["session_id"], +} + +CUSTOMER_GET_MORE_TOOLS_DESCRIPTION = ( + "The customer's own tool, which happens to share AgentCat's name." +) + +# What each tool body is allowed to receive, for the LOWLEVEL flavors, whose +# handlers are handed the raw argument dict: an argument the tool never declared +# is fatal there rather than ignored, because a body that quietly dropped one +# would let a strip regression pass unnoticed. +# +# The facade flavors cannot use this — their bodies are typed functions and the +# SDK never delivers an argument the signature does not name. Both official tool +# managers drop an unexpected one SILENTLY (community FastMCP is the one that +# raises), so on those two shapes "what was delivered" is observable only at the +# manager, which is what `tests.test_utils.delivery` reads. +ALLOWED_ARGUMENTS = { + "echo": {"text"}, + GET_MORE_TOOLS_NAME: {"context"}, + "complete_task": {"session_id", "note"}, +} + + +# The one text `echo` refuses. Every era reports a failing tool differently — +# a raise here, an `is_error` result there — and a test that wants a failure on +# all of them needs the failure itself to be era-independent. +BOOM_TEXT = "boom" + + +class ListSourceDown(RuntimeError): + """Raised by a deliberately broken list source, so a log line names it.""" + + +class ToolFailed(RuntimeError): + """Raised by `echo` on the sentinel text: one failure shape for every era.""" + + +def _reject_unexpected(tool_name: str, arguments: dict[str, Any]) -> None: + allowed = ALLOWED_ARGUMENTS.get(tool_name, set()) + unexpected = sorted(set(arguments) - allowed) + if unexpected: + raise ValueError(f"unexpected arguments: {unexpected}") + + +def _boom(*args: Any, **kwargs: Any) -> Any: + """A list source that is down. Synchronous on purpose: it raises before an + awaiting caller ever reaches the ``await``, so one function breaks both the + sync tool managers and the async ``list_tools`` seams.""" + raise ListSourceDown("the list source is down") + + +def _answer(tool_name: str, arguments: dict[str, Any]) -> str: + """What every flavor's tool body returns, so only the wiring differs.""" + if tool_name == GET_MORE_TOOLS_NAME: + return f"customer answered: {arguments['context']}" + if tool_name == "complete_task": + return f"completed {arguments['session_id']}: {arguments.get('note')}" + if arguments["text"] == BOOM_TEXT: + raise ToolFailed("the tool failed") + return f"echo:{arguments['text']}" + + +@dataclass +class Built: + """A fresh, UNTRACKED server plus what its tool bodies actually receive.""" + + server: Any + seen: list[tuple[str, dict[str, Any]]] = field(default_factory=list) + + +@dataclass(frozen=True) +class ListedTool: + """One advertised tool, era spellings bridged.""" + + name: str + input_schema: dict[str, Any] + output_schema: dict[str, Any] | None + + +@dataclass(frozen=True) +class Called: + """One ``tools/call`` result, era spellings bridged.""" + + text: str + structured: dict[str, Any] | None + is_error: bool + raw: Any + + +def _bridged(obj: Any, snake: str, camel: str) -> Any: + """The snake_case field when the model HAS one, else the camelCase one. + + Presence, not truthiness: 2.x keeps the old spelling as a deprecated alias, + so a value-based fallback would reach it — and warn — every time the real + field is legitimately None. + """ + if hasattr(obj, snake): + return getattr(obj, snake) + return getattr(obj, camel, None) + + +def _listed(tool: Any) -> ListedTool: + return ListedTool( + name=tool.name, + input_schema=_bridged(tool, "input_schema", "inputSchema"), + output_schema=_bridged(tool, "output_schema", "outputSchema"), + ) + + +def _called(result: Any) -> Called: + blocks = getattr(result, "content", None) or [] + return Called( + text="".join(b.text for b in blocks if hasattr(b, "text")), + structured=_bridged(result, "structured_content", "structuredContent"), + is_error=bool(_bridged(result, "is_error", "isError")), + raw=result, + ) + + +class Flavor: + """One server shape: build it, talk to it, break its list source.""" + + id = "" + flavor: ServerFlavor + + # Whether a `tools/call` can complete at all while the list source is down. + # + # On mcp 1.x it cannot, and that is the SDK's doing rather than AgentCat's: + # the lowlevel `tools/call` handler opens by resolving the tool definition + # from a cache it refreshes THROUGH the same list handler + # (`Server._get_cached_tool_definition`), unconditionally — `validate_input` + # does not gate it, which is why official FastMCP is no different. A listing + # that raises therefore fails the call before the customer's tool body runs, + # tracked or untracked. Everything AgentCat does on that path still happens + # and is asserted; the tool body and the wire mirror are simply out of reach + # on that era. + survives_a_down_list_source = True + + def build( + self, + name: str = "cross-flavor", + *, + hook: Hook | None = None, + customer_get_more_tools: bool = False, + customer_session_id: bool = False, + ) -> Built: + """A fresh untracked server carrying `echo`, and optionally two tools + whose names collide with AgentCat's: a `get_more_tools` whose + ``context`` is a real parameter, and a `complete_task` whose + ``session_id`` is a real parameter.""" + raise NotImplementedError + + def client(self, server: Any) -> Any: + """An async context manager yielding a connected client.""" + raise NotImplementedError + + async def list_tools(self, client: Any) -> list[ListedTool]: + raise NotImplementedError + + async def call( + self, client: Any, name: str, arguments: dict[str, Any] + ) -> Called: + raise NotImplementedError + + async def call_unlisted( + self, server: Any, name: str, arguments: dict[str, Any] + ) -> Called: + """One call on an instance that has never served a listing. + + The default is a real client that simply does not list first; the + community flavors override it, because their client fetches schemas on + its way to a call and so can never reproduce an un-listed instance. + """ + async with self.client(server) as client: + return await self.call(client, name, arguments) + + def break_list_source(self, server: Any) -> None: + """Make the source `rebuild()` reads raise, and nothing else.""" + raise NotImplementedError + + def __repr__(self) -> str: # pragma: no cover - test ids only + return self.id + + +# ── official MCP SDK 1.x ───────────────────────────────────────────────────── + + +class OfficialFastMCPV1(Flavor): + """`mcp.server.fastmcp.FastMCP`, adapted through its `_mcp_server`.""" + + id = "official-fastmcp-v1" + flavor = ServerFlavor.OFFICIAL_FASTMCP_V1 + survives_a_down_list_source = False + + def build( + self, + name: str = "cross-flavor", + *, + hook: Hook | None = None, + customer_get_more_tools: bool = False, + customer_session_id: bool = False, + ) -> Built: + from mcp.server.fastmcp import FastMCP + + built = Built(FastMCP(name)) + server = built.server + + @server.tool() + async def echo(text: str) -> str: + """Echo the text back.""" + if hook is not None: + await hook() + return _answer("echo", {"text": text}) + + if customer_get_more_tools: + + @server.tool(name=GET_MORE_TOOLS_NAME) + async def customers_get_more_tools(context: str) -> str: + """The customer's own tool, which happens to share our name.""" + return f"customer answered: {context}" + + if customer_session_id: + + @server.tool() + async def complete_task(session_id: str, note: str = "") -> str: + """The customer's own session_id, which is not AgentCat's.""" + return _answer( + "complete_task", {"session_id": session_id, "note": note} + ) + + # `seen` is filled at the manager, not in the bodies above: see + # `record_delivered_arguments` for why a typed body cannot report it. + record_delivered_arguments(server._tool_manager, built.seen) + return built + + @contextlib.asynccontextmanager + async def client(self, server: Any) -> AsyncIterator[Any]: + from .client import create_test_client + + async with create_test_client(server) as session: + yield session + + async def list_tools(self, client: Any) -> list[ListedTool]: + return [_listed(tool) for tool in (await client.list_tools()).tools] + + async def call( + self, client: Any, name: str, arguments: dict[str, Any] + ) -> Called: + return _called(await client.call_tool(name, arguments)) + + def break_list_source(self, server: Any) -> None: + # The tool manager is what FastMCP's own `tools/list` handler reads, + # and that handler is what the adapter recorded as the list source. + server._tool_manager.list_tools = _boom + + +class LowlevelV1(OfficialFastMCPV1): + """A bare `mcp.server.lowlevel.Server`: the same adapter, no facade.""" + + id = "lowlevel-v1" + flavor = ServerFlavor.LOWLEVEL_V1 + survives_a_down_list_source = False + + def build( + self, + name: str = "cross-flavor", + *, + hook: Hook | None = None, + customer_get_more_tools: bool = False, + customer_session_id: bool = False, + ) -> Built: + import mcp.types as types + from mcp.server.lowlevel import Server + + built = Built(Server(name)) + server = built.server + broken = {"list": False} + server._cross_flavor_broken = broken + + tools = [ + types.Tool( + name="echo", + description="Echo the text back.", + inputSchema=dict(ECHO_INPUT_SCHEMA), + outputSchema=dict(RESULT_OUTPUT_SCHEMA), + ) + ] + if customer_get_more_tools: + tools.append( + types.Tool( + name=GET_MORE_TOOLS_NAME, + description=CUSTOMER_GET_MORE_TOOLS_DESCRIPTION, + inputSchema=dict(CONTEXT_INPUT_SCHEMA), + outputSchema=dict(RESULT_OUTPUT_SCHEMA), + ) + ) + if customer_session_id: + tools.append( + types.Tool( + name="complete_task", + description="The customer's own session_id, not AgentCat's.", + inputSchema=copy.deepcopy(COMPLETE_INPUT_SCHEMA), + outputSchema=dict(RESULT_OUTPUT_SCHEMA), + ) + ) + + @server.list_tools() + async def list_tools() -> list[Any]: + if broken["list"]: + raise ListSourceDown("the list source is down") + return [tool.model_copy(deep=True) for tool in tools] + + @server.call_tool() + async def call_tool(tool_name: str, arguments: dict[str, Any]) -> Any: + arguments = dict(arguments or {}) + _reject_unexpected(tool_name, arguments) + built.seen.append((tool_name, arguments)) + if tool_name == "echo" and hook is not None: + await hook() + message = _answer(tool_name, arguments) + return ( + [types.TextContent(type="text", text=message)], + {"result": message}, + ) + + return built + + def break_list_source(self, server: Any) -> None: + server._cross_flavor_broken["list"] = True + + +# ── official MCP SDK 2.x ───────────────────────────────────────────────────── + + +class MCPServerV2(Flavor): + """`mcp.server.mcpserver.MCPServer`, adapted through its + `_lowlevel_server`.""" + + id = "mcpserver-v2" + flavor = ServerFlavor.MCPSERVER_V2 + + def build( + self, + name: str = "cross-flavor", + *, + hook: Hook | None = None, + customer_get_more_tools: bool = False, + customer_session_id: bool = False, + ) -> Built: + from mcp.server.mcpserver import MCPServer + + built = Built(MCPServer(name)) + server = built.server + + @server.tool() + async def echo(text: str) -> str: + """Echo the text back.""" + if hook is not None: + await hook() + return _answer("echo", {"text": text}) + + if customer_get_more_tools: + + @server.tool(name=GET_MORE_TOOLS_NAME) + async def customers_get_more_tools(context: str) -> str: + """The customer's own tool, which happens to share our name.""" + return f"customer answered: {context}" + + if customer_session_id: + + @server.tool() + async def complete_task(session_id: str, note: str = "") -> str: + """The customer's own session_id, which is not AgentCat's.""" + return _answer( + "complete_task", {"session_id": session_id, "note": note} + ) + + # `seen` is filled at the manager, not in the bodies above: see + # `record_delivered_arguments` for why a typed body cannot report it. + record_delivered_arguments(server._tool_manager, built.seen) + return built + + @contextlib.asynccontextmanager + async def client(self, server: Any) -> AsyncIterator[Any]: + from .modern_server import create_modern_client + + async with create_modern_client(server) as session: + yield session + + async def list_tools(self, client: Any) -> list[ListedTool]: + return [_listed(tool) for tool in (await client.list_tools()).tools] + + async def call( + self, client: Any, name: str, arguments: dict[str, Any] + ) -> Called: + return _called(await client.call_tool(name, arguments)) + + async def call_unlisted( + self, server: Any, name: str, arguments: dict[str, Any] + ) -> Called: + # The raw request, not `call_tool`: the convenience method revalidates + # the result against the tool's output schema and fetches the listing + # to do it. That listing is harmless to the rebuild — which has already + # happened by then — but fatal to a test that has deliberately taken + # the list source down. Same wire path, without the client's own extra + # round trip. + from mcp import types + + async with self.client(server) as client: + result = await client.session.send_request( + types.CallToolRequest( + params=types.CallToolRequestParams( + name=name, arguments=arguments + ) + ), + types.CallToolResult, + ) + return _called(result) + + def break_list_source(self, server: Any) -> None: + server._tool_manager.list_tools = _boom + + +class LowlevelV2(MCPServerV2): + """A bare `mcp.server.Server`: the same adapter, no facade.""" + + id = "lowlevel-v2" + flavor = ServerFlavor.LOWLEVEL_V2 + + def build( + self, + name: str = "cross-flavor", + *, + hook: Hook | None = None, + customer_get_more_tools: bool = False, + customer_session_id: bool = False, + ) -> Built: + from mcp import types + from mcp.server import Server + + seen: list[tuple[str, dict[str, Any]]] = [] + broken = {"list": False} + + tools = [ + types.Tool( + name="echo", + description="Echo the text back.", + input_schema=dict(ECHO_INPUT_SCHEMA), + output_schema=dict(RESULT_OUTPUT_SCHEMA), + ) + ] + if customer_get_more_tools: + tools.append( + types.Tool( + name=GET_MORE_TOOLS_NAME, + description=CUSTOMER_GET_MORE_TOOLS_DESCRIPTION, + input_schema=dict(CONTEXT_INPUT_SCHEMA), + output_schema=dict(RESULT_OUTPUT_SCHEMA), + ) + ) + if customer_session_id: + tools.append( + types.Tool( + name="complete_task", + description="The customer's own session_id, not AgentCat's.", + input_schema=copy.deepcopy(COMPLETE_INPUT_SCHEMA), + output_schema=dict(RESULT_OUTPUT_SCHEMA), + ) + ) + + async def on_list_tools(ctx: Any, params: Any) -> Any: + if broken["list"]: + raise ListSourceDown("the list source is down") + return types.ListToolsResult( + tools=[tool.model_copy(deep=True) for tool in tools] + ) + + async def on_call_tool(ctx: Any, params: Any) -> Any: + arguments = dict(params.arguments or {}) + _reject_unexpected(params.name, arguments) + seen.append((params.name, arguments)) + if params.name == "echo" and hook is not None: + await hook() + message = _answer(params.name, arguments) + return types.CallToolResult( + content=[types.TextContent(type="text", text=message)], + structured_content={"result": message}, + ) + + server = Server(name, on_list_tools=on_list_tools, on_call_tool=on_call_tool) + server._cross_flavor_broken = broken + return Built(server, seen) + + def break_list_source(self, server: Any) -> None: + server._cross_flavor_broken["list"] = True + + +# ── community FastMCP (3.x beside mcp 1.x, 4.x beside mcp 2.x) ─────────────── + + +class Community(Flavor): + """Community `fastmcp.FastMCP`, adapted by a middleware at index 0.""" + + def __init__(self, era: int) -> None: + self.id = f"community-v{era}" + self.flavor = ( + ServerFlavor.COMMUNITY_V3 if era == 3 else ServerFlavor.COMMUNITY_V4 + ) + + def build( + self, + name: str = "cross-flavor", + *, + hook: Hook | None = None, + customer_get_more_tools: bool = False, + customer_session_id: bool = False, + ) -> Built: + from fastmcp import FastMCP + + built = Built(FastMCP(name)) + server = built.server + + @server.tool + async def echo(text: str) -> str: + """Echo the text back.""" + built.seen.append(("echo", {"text": text})) + if hook is not None: + await hook() + return _answer("echo", {"text": text}) + + if customer_get_more_tools: + + @server.tool(name=GET_MORE_TOOLS_NAME) + async def customers_get_more_tools(context: str) -> str: + """The customer's own tool, which happens to share our name.""" + built.seen.append((GET_MORE_TOOLS_NAME, {"context": context})) + return f"customer answered: {context}" + + if customer_session_id: + + @server.tool + async def complete_task(session_id: str, note: str = "") -> str: + """The customer's own session_id, which is not AgentCat's.""" + built.seen.append( + ("complete_task", {"session_id": session_id, "note": note}) + ) + return _answer( + "complete_task", {"session_id": session_id, "note": note} + ) + + return built + + @contextlib.asynccontextmanager + async def client(self, server: Any) -> AsyncIterator[Any]: + from .community_client import create_community_test_client + + async with create_community_test_client(server) as session: + yield session + + async def list_tools(self, client: Any) -> list[ListedTool]: + return [_listed(tool) for tool in await client.list_tools()] + + async def call( + self, client: Any, name: str, arguments: dict[str, Any] + ) -> Called: + return _called(await client.call_tool(name, arguments)) + + async def call_unlisted( + self, server: Any, name: str, arguments: dict[str, Any] + ) -> Called: + # Driven through the server rather than a client: a real FastMCP client + # fetches output schemas on its way to a call, so it can never + # reproduce a genuinely un-listed instance. `call_tool` runs the + # middleware chain, which is the path under test. + return _called(await server.call_tool(name, arguments)) + + def break_list_source(self, server: Any) -> None: + # `list_tools(run_middleware=False)` is the community rebuild's list + # source, and an instance attribute shadows the bound method. + server.list_tools = _boom + + +# ── what this dependency set can build ─────────────────────────────────────── + +# The official flavors of each era, keyed by the installed `mcp` major. Stated +# as a table rather than derived, so a missing entry reads as a gap. +_OFFICIAL: dict[int, list[Flavor]] = { + 1: [OfficialFastMCPV1(), LowlevelV1()], + 2: [MCPServerV2(), LowlevelV2()], +} + + +def flavors() -> list[Flavor]: + """Every server shape the installed dependency set can build.""" + available = list(_OFFICIAL.get(MCP_MAJOR, [])) + if FASTMCP_MAJOR is not None: + available.append(Community(FASTMCP_MAJOR)) + return available + + +def flavor_ids() -> list[str]: + return [flavor.id for flavor in flavors()] + + +def tracking_data(server: Any) -> Any: + """The `AgentCatData` `track()` stored for ``server``, on any flavor. + + Keyed on the object the adapter was installed on — the lowlevel server for + the official flavors, the FastMCP itself for the community ones — which is + exactly what `detect_server` hands back. + """ + from agentcat.modules.detection import detect_server + from agentcat.modules.internal import get_server_tracking_data + + return get_server_tracking_data(detect_server(server).lowlevel or server) diff --git a/tests/test_utils/modern_server.py b/tests/test_utils/modern_server.py new file mode 100644 index 0000000..72af003 --- /dev/null +++ b/tests/test_utils/modern_server.py @@ -0,0 +1,144 @@ +"""Server and client factories for the modern official SDK (mcp 2.x). + +The legacy siblings (`todo_server.py`, `client.py`) are built on mcp 1.x APIs +that 2.x removed — `mcp.server.fastmcp`, `mcp.shared.memory`. This module is +their 2.x counterpart: a bare lowlevel `Server`, an `MCPServer`, and the +in-process `Client` the modern SDK ships for exactly this purpose. + +Only imported from modern-gated test modules (see `tests/conftest.py`), so the +`mcp` imports are module-scope here. +""" + +from __future__ import annotations + +from typing import Any + +from mcp import types +from mcp.client import Client +from mcp.server import Server +from mcp.server.mcpserver import MCPServer + +from tests.test_utils.delivery import attach_delivery_recorder + +ADD_TODO_INPUT_SCHEMA: dict[str, Any] = { + "type": "object", + "properties": {"text": {"type": "string"}}, + "required": ["text"], +} +ADD_TODO_OUTPUT_SCHEMA: dict[str, Any] = { + "type": "object", + "properties": {"result": {"type": "string"}}, + "required": ["result"], +} + + +def _reject_unexpected(arguments: dict[str, Any], allowed: set[str]) -> None: + """Fail loudly on any argument the tool never declared. + + The point of the strip is that AgentCat's injected parameters never reach + the customer's tool; a handler that quietly ignored them would let a strip + regression pass unnoticed. + """ + unexpected = sorted(set(arguments) - allowed) + if unexpected: + raise ValueError(f"unexpected arguments: {unexpected}") + + +def create_lowlevel_todo_server(name: str = "todo-server-v2") -> Server[Any]: + """A bare lowlevel v2 `Server` with a todo tool set. + + `complete_todo` reports failure the way the 2026 SDK does — an `is_error` + result, not a raised exception — so the error path under test is the one + real servers take. + """ + todos: list[str] = [] + + async def on_list_tools( + ctx: Any, params: types.PaginatedRequestParams | None + ) -> types.ListToolsResult: + return types.ListToolsResult( + tools=[ + types.Tool( + name="add_todo", + description="Add a new todo item.", + input_schema=dict(ADD_TODO_INPUT_SCHEMA), + output_schema=dict(ADD_TODO_OUTPUT_SCHEMA), + ), + types.Tool( + name="complete_todo", + description="Mark a todo item as completed.", + input_schema={ + "type": "object", + "properties": {"id": {"type": "integer"}}, + "required": ["id"], + }, + ), + ] + ) + + async def on_call_tool( + ctx: Any, params: types.CallToolRequestParams + ) -> types.CallToolResult: + arguments = dict(params.arguments or {}) + if params.name == "add_todo": + _reject_unexpected(arguments, {"text"}) + todos.append(str(arguments["text"])) + message = f'Added todo: "{arguments["text"]}" with ID {len(todos)}' + return types.CallToolResult( + content=[types.TextContent(type="text", text=message)], + structured_content={"result": message}, + ) + if params.name == "complete_todo": + _reject_unexpected(arguments, {"id"}) + return types.CallToolResult( + content=[ + types.TextContent( + type="text", + text=f"Todo with ID {arguments.get('id')} not found", + ) + ], + is_error=True, + ) + raise ValueError(f"Unknown tool: {params.name}") + + return Server(name, on_list_tools=on_list_tools, on_call_tool=on_call_tool) + + +def create_mcpserver_todo_server(name: str = "todo-mcpserver") -> MCPServer: + """An `MCPServer` with the same tool set, served through `_lowlevel_server`. + + Its tool bodies are typed functions, so — unlike the lowlevel factory above + — they cannot police their own arguments: measured on mcp 2.0, the + `_tool_manager` DROPS an undeclared argument silently rather than failing + the call, so an un-stripped `session_id` would pass unnoticed. The delivery + recorder installed below is what makes the strip observable; read it with + `tests.test_utils.delivery.delivered_arguments_for(server, "add_todo")`. + """ + todos: list[str] = [] + + server = MCPServer(name) + + @server.tool() + def add_todo(text: str) -> str: + """Add a new todo item.""" + todos.append(text) + return f'Added todo: "{text}" with ID {len(todos)}' + + @server.tool() + def list_todos() -> str: + """List all todo items.""" + return "\n".join(todos) if todos else "No todos found" + + attach_delivery_recorder(server, server._tool_manager) + return server + + +def create_modern_client(server: Any, **kwargs: Any) -> Client: + """An in-process `Client` for a v2 `Server` or `MCPServer`. + + Used as an async context manager, exactly like the SDK's own tests do it, + so every assertion covers the real wire path (params validation, result + serialization, per-version outbound sieve) rather than a hand-called + handler. + """ + return Client(server, **kwargs) diff --git a/tests/test_utils/todo_server.py b/tests/test_utils/todo_server.py index 7383b59..7129824 100644 --- a/tests/test_utils/todo_server.py +++ b/tests/test_utils/todo_server.py @@ -1,14 +1,23 @@ -"""Todo server implementation for testing.""" +"""Todo server implementation for testing (official MCP SDK 1.x). -from mcp.shared.exceptions import McpError -from mcp.types import ErrorData +Import-safe under mcp 2.x, which removed `FastMCP` and renamed `McpError`, so +a module that mixes era-agnostic unit tests with a `create_todo_server()` +integration class can still be collected there — the factory raises, the unit +tests run. `test_utils.modern_server` is the 2.x counterpart. +""" + +from tests.test_utils.delivery import attach_delivery_recorder try: from mcp.server import FastMCP + from mcp.shared.exceptions import McpError + from mcp.types import ErrorData HAS_FASTMCP = True -except ImportError: +except ImportError: # mcp 2.x FastMCP = None + McpError = None + ErrorData = None HAS_FASTMCP = False @@ -32,7 +41,16 @@ def __init__(self, id: int, text: str, completed: bool = False): def create_todo_server(): - """Create a todo server for testing.""" + """Create a todo server for testing. + + Every tool body here is a typed function, so none of them can police its + own arguments: measured on mcp 1.29, `mcp.server.fastmcp`'s tool manager + DROPS an undeclared argument silently rather than failing the call. A test + that sends AgentCat's injected parameters and asserts "no error" therefore + proves nothing about the strip. The delivery recorder installed below is + what makes it observable — read it with + `tests.test_utils.delivery.delivered_arguments_for(server, "add_todo")`. + """ if FastMCP is None: raise ImportError( "FastMCP is not available in this MCP version. Use create_low_level_todo_server() instead." @@ -92,6 +110,8 @@ def tool_with_mcp_error() -> str: error = ErrorData(code=INVALID_PARAMS, message="Invalid parameters") raise McpError(error) + attach_delivery_recorder(server, server._tool_manager) + # Store original handlers for testing server._original_handlers = { "add_todo": add_todo, From 8bce13cbc0a36faae5a63d40a6cf4d4e3ccb74d0 Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Mon, 3 Aug 2026 14:36:51 -0400 Subject: [PATCH 02/13] fix(compat): support the whole declared mcp and fastmcp range MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `--no-sync` this branch added to the compatibility workflow made its 29 legs report honestly for the first time. Main runs `uv run pytest` without it, so uv re-resolved the venv from the lockfile immediately before every test session and discarded the `uv pip install "mcp==X"` pin the step above had just made — main's "1.2.1" leg passes six modules that import `mcp.client.streamable_http`, which does not exist in mcp 1.2.1. Twenty-two legs then failed here, and one of them was a real bug. `install_lowlevel_v1` imported `ToolAnnotations` as its first statement. That model only exists from mcp 1.7, and `track()`'s blanket except swallowed the ImportError, so on mcp 1.2-1.6 AgentCat installed no adapter and published nothing while `set_server_tracking_data` had already run and the server still looked tracked. Both lowlevel adapters now pass the hint as a plain mapping, the way `adapters/community.py` already did, and pydantic coerces it wherever the model exists. Everything else was the harness reaching for era-specific spellings. Fixtures now build through `request_handlers`, whose contract has been stable since mcp 1.0, so one fixture serves every 1.x instead of one that needs the 1.10 tuple return or the 1.19 result passthrough. `tests/conftest.py` gains the two collection axes it was missing — fastmcp presence, and the mcp minor that brought Streamable HTTP — because a module-scope import of an absent symbol fails before any skipif can run. That is what left the mcp 2.0.0 leg running zero tests. Where a capability is genuinely absent upstream rather than spelled differently, the suite gates on a probe and names the missing seam: `Server._make_error_result` and structured output (mcp 1.10), the HTTP request object (1.9.2), concurrent message handling (1.3), `ToolResult.is_error` (fastmcp 3.4). AgentCat runs below all of them; it just records less, and README and MIGRATION now say exactly what goes quiet where. Measured, all with zero failures: mcp 1.2.1 648 passed, mcp 1.9.4 679, mcp 2.0.0 without fastmcp 574 (was a collection error), fastmcp 3.3.1 781 (was 8 failed), legacy 781, modern 625. Ruff 258 and mypy 48-in-13 both unchanged. --- .github/workflows/mcp-compatibility.yml | 26 ++++ MIGRATION.md | 6 +- README.md | 19 ++- pyproject.toml | 2 +- src/agentcat/modules/adapters/lowlevel_v1.py | 18 ++- src/agentcat/modules/adapters/lowlevel_v2.py | 9 +- tests/community/test_community_v3_handles.py | 5 +- tests/conftest.py | 49 +++++- tests/e2e/community_v4/test_session_http.py | 19 ++- tests/test_concurrency_handles.py | 6 +- tests/test_inner_tap.py | 95 +++++++++--- tests/test_lowlevel_v1_handles.py | 49 ++++-- tests/test_response_shape.py | 19 ++- tests/test_utils/__init__.py | 152 ++++++++++++++++++- tests/test_utils/flavors.py | 149 ++++++++++++++++-- 15 files changed, 549 insertions(+), 74 deletions(-) diff --git a/.github/workflows/mcp-compatibility.yml b/.github/workflows/mcp-compatibility.yml index 20c4c0f..5095e37 100644 --- a/.github/workflows/mcp-compatibility.yml +++ b/.github/workflows/mcp-compatibility.yml @@ -17,6 +17,20 @@ on: # server is classified, refused and returned untracked on purpose, so there is # nothing for a compatibility leg to assert. That is also why the old `2.9.*` # carve-out is gone rather than moved: the whole 2.x line is out of range now. +# +# These ranges only started meaning anything when the test steps below gained +# `uv run --no-sync`. Without it `uv run` re-resolves from the lockfile +# immediately before pytest, silently discarding the `uv pip install +# "mcp==X"` pin the step above just made — so every leg ran the lockfile's mcp +# and the matrix was green by construction. Never drop `--no-sync`; the +# "Show installed versions" steps are what prove the pin survived. +# +# Three capabilities are genuinely absent on the oldest legs rather than +# spelled differently, and the suite gates on each rather than pretending: +# concurrent message handling (mcp 1.3), Streamable HTTP plus the request +# object `extra.requestInfo` reads (1.8 / 1.9.2, see `tests/conftest.py`), and +# `Server._make_error_result` — the seam the inner tap hooks — with structured +# tool output (1.10). AgentCat runs below all of them; it just records less. env: MCP_RANGE: ">=1.2,<3" FASTMCP_RANGE: ">=3.0,<5" @@ -589,6 +603,18 @@ jobs: echo "✓ Community FastMCP 2.x — refused and returned untracked, by design" echo "✓ Package works without community FastMCP (official MCP alone)" echo "" + echo "📉 WHAT DEGRADES ON THE OLDEST LEGS (AgentCat still runs)" + echo "─────────────────────────────────────────" + echo "mcp < 1.10 no Server._make_error_result, so a bare lowlevel" + echo " handler's exception type/frames cannot be recovered;" + echo " the surfaced message is still published. No declared" + echo " structured tool output, so no structured mint-back." + echo "mcp < 1.9.2 no RequestContext.request: no header/requestInfo capture." + echo "mcp < 1.8 no Streamable HTTP transport at all." + echo "mcp < 1.3 messages are handled serially, so nothing overlaps." + echo "fastmcp<3.4 no ToolResult.is_error: a proxied upstream error" + echo " arrives as a raised ToolError instead of a result." + echo "" echo "📦 INSTALLATION OPTIONS" echo "─────────────────────────────────────────" echo "• pip install agentcat - Official MCP only. Resolves the" diff --git a/MIGRATION.md b/MIGRATION.md index bae06b1..05fc244 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -160,10 +160,10 @@ The session ID is used **verbatim** — never validated, derived or reformatted, **A server tracked with `enable_tracing=False` publishes no custom events.** Turning tracing off silences this entry point exactly as it silences tool-call events, so a server you deliberately muted does not start emitting a new event type. The session-ID-string form has no options to consult and always publishes. -### Known limitations in 2.0.0b1 +### Known limitations in 2.0.0b2 - **Multi-round tool calls that mint their own handle land on separate sessions.** If a tool call spans several round trips and the *first* round is what mints the handle, each round is attributed to its own session instead of one shared session. The other two modes correlate correctly and are protocol-enforced: supplying `session_id` yourself, or deriving it with a `resolve_session_id` hook. If your server relies on multi-round tool calls, prefer one of those two. -- **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and the upstream returns an error result, no Python exception is raised locally, so the event records the message without a stack trace. Errors raised by your own tool code are unaffected. +- **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and the upstream returns an error result, no Python exception is raised locally, so the event records the message without a stack trace. Errors raised by your own tool code are unaffected. This applies from fastmcp 3.4, which taught the proxy provider to pass an upstream error result through; on 3.0–3.3 the proxy collapsed it into a raised `ToolError` instead, so those versions do record full detail. ### Supported versions @@ -178,6 +178,8 @@ The session ID is used **verbatim** — never validated, derived or reformatted, One `track()` call handles every supported shape; AgentCat classifies the server it is handed and installs the matching adapter. A shape it does not recognize is logged with a diagnostic fingerprint and returned untracked. +The declared floors are `mcp>=1.2.0,<3` and `fastmcp>=3.0.0,<5`, and every minor in both ranges runs the suite on each change. AgentCat works across the whole range, but the oldest MCP releases lack SDK seams that some features are built on — on `mcp<1.10` a bare low-level handler's exception type and stack frames cannot be recovered (the surfaced message is still published) and there is no structured mint-back; `mcp<1.9.2` captures no request headers; `mcp<1.8` has no Streamable HTTP at all. Nothing breaks on those versions; the affected features simply go quiet. See the table in [README.md](./README.md). + > **Installing into a fresh environment resolves `mcp` 2.x**, which removed `mcp.server.fastmcp`. AgentCat's dependency is `mcp>=1.2.0,<3` and both generations are supported, so an existing project that pins `mcp<2` is unaffected — but a `pip install agentcat` into an empty environment will give you the 2.x line, where the 1.x `from mcp.server.fastmcp import FastMCP` import does not exist. Pin `mcp<2` if you need it. --- diff --git a/README.md b/README.md index 0e5d84d..1148c40 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ pip install --pre "agentcat[community]" ``` `--pre` is required while 2.x is a prerelease: without it pip skips -`2.0.0b1` and resolves the 1.x line instead, which has none of the features +`2.0.0b2` and resolves the 1.x line instead, which has none of the features documented below. Drop the flag once a stable 2.0.0 ships. One `track()` call covers every supported server shape: @@ -57,6 +57,21 @@ One `track()` call covers every supported server shape: | Community FastMCP (`fastmcp`) 3.x and 4.x | ✅ (`agentcat[community]`) | | Community FastMCP (`fastmcp`) 2.x | ❌ pin `agentcat<2` | +The floors are `mcp>=1.2.0,<3` and `fastmcp>=3.0.0,<5`, and every minor in +both ranges is exercised on each change by the compatibility matrix. + +AgentCat runs on the whole range, but the oldest MCP releases lack the SDK +seams some features are built on, so those features go quiet rather than +break: + +| On | What is missing upstream | Effect | +| --- | --- | --- | +| `mcp<1.10` | `Server._make_error_result`; declared structured tool output | A bare low-level handler's exception type and stack frames cannot be recovered — the surfaced message is still published. No structured mint-back. | +| `mcp<1.9.2` | `RequestContext.request` | No header or `requestInfo` capture. | +| `mcp<1.8` | Streamable HTTP | stdio only. | +| `mcp<1.3` | Concurrent message handling | The server never has two calls in flight. | +| `fastmcp<3.4` | `ToolResult.is_error` | A proxied upstream error arrives as a raised `ToolError`, so it is published *with* full exception detail rather than as a bare message. | + To learn more about us, check us out [here](https://agentcat.com) ## Why use AgentCat? 🤔 @@ -258,7 +273,7 @@ Learn more about our free and open source [telemetry integrations](https://docs. ### Known limitations -Two behaviors are worth knowing before you read your first dashboard. Both are deliberate for `2.0.0b1`. +Two behaviors are worth knowing before you read your first dashboard. Both are deliberate for `2.0.0b2`. - **Multi-round tool calls that mint their own handle land on separate sessions.** When a tool call runs several round trips and the *first* round is what mints the handle, each round is attributed to its own session rather than one shared session. Supplying a `session_id` yourself, or deriving one with `resolve_session_id`, correlates the rounds correctly — those two modes are protocol-enforced. Only the mint-on-first-round case is affected. - **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and that upstream returns an error result, there is no local Python exception to read, so the event records the error message without a stack trace. Errors raised by your own tool code are unaffected and carry full detail. diff --git a/pyproject.toml b/pyproject.toml index 95fe21c..32e1035 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "agentcat" -version = "2.0.0b1" +version = "2.0.0b2" description = "Analytics tool for MCP (Model Context Protocol) servers and AI agents - tracks tool usage patterns and provides insights" authors = [ { name = "AgentCat, Inc.", email = "support@agentcat.com" }, diff --git a/src/agentcat/modules/adapters/lowlevel_v1.py b/src/agentcat/modules/adapters/lowlevel_v1.py index 6c7cc35..305a2d4 100644 --- a/src/agentcat/modules/adapters/lowlevel_v1.py +++ b/src/agentcat/modules/adapters/lowlevel_v1.py @@ -169,7 +169,6 @@ def install_lowlevel_v1(server: Any, data: AgentCatData, facade: Any = None) -> ServerResult, TextContent, Tool, - ToolAnnotations, ) from agentcat.modules.callpath import ( @@ -217,13 +216,24 @@ def original(key: str) -> Any: return state.get(f"orig_{key}") def make_get_more_tools() -> Tool: + # Spec defaults assume the worst; declare the honest hint so + # annotation-aware clients skip the confirmation prompt. Passed as a + # plain mapping, not the `ToolAnnotations` model — that model only + # exists from mcp 1.7, and importing it unconditionally used to make + # `install_lowlevel_v1` raise on 1.2-1.6, where `track()`'s blanket + # except turned AgentCat into a silent no-op. `Tool` is extra="allow" + # on every 1.x, so the mapping is absorbed below 1.7 and coerced into + # the model at and above it. + # + # Typed `Any` for the same reason `adapters/community.py` does it: the + # field is declared `ToolAnnotations | None`, so a type-check pass + # rejects the mapping that pydantic accepts at runtime. + annotations: Any = {"readOnlyHint": True} return Tool( name=GET_MORE_TOOLS_NAME, description=GET_MORE_TOOLS_DESCRIPTION, inputSchema=copy.deepcopy(GET_MORE_TOOLS_SCHEMA), - # Spec defaults assume the worst; declare the honest hint so - # annotation-aware clients skip the confirmation prompt. - annotations=ToolAnnotations(readOnlyHint=True), + annotations=annotations, ) def advertised_tools(original: Any, options: Any) -> list[Any]: diff --git a/src/agentcat/modules/adapters/lowlevel_v2.py b/src/agentcat/modules/adapters/lowlevel_v2.py index c96abd9..8c87c1e 100644 --- a/src/agentcat/modules/adapters/lowlevel_v2.py +++ b/src/agentcat/modules/adapters/lowlevel_v2.py @@ -127,7 +127,7 @@ def _text_block(text: str) -> Any: def _make_get_more_tools() -> Any: - from mcp.types import Tool, ToolAnnotations + from mcp.types import Tool # Built from a keyword mapping rather than literal kwargs. `input_schema` # and `read_only_hint` are the 2.x field names, and a type-check pass run @@ -141,8 +141,11 @@ def _make_get_more_tools() -> Any: "description": GET_MORE_TOOLS_DESCRIPTION, "input_schema": copy.deepcopy(GET_MORE_TOOLS_SCHEMA), # Spec defaults assume the worst; declare the honest hint so - # annotation-aware clients skip the confirmation prompt. - "annotations": ToolAnnotations(**annotations), + # annotation-aware clients skip the confirmation prompt. Handed over as + # the mapping itself: pydantic coerces it into whichever annotations + # model the running SDK declares, and nothing here has to import a type + # whose availability moved between generations. + "annotations": annotations, } return Tool(**fields) diff --git a/tests/community/test_community_v3_handles.py b/tests/community/test_community_v3_handles.py index 3b93d00..e7fe69f 100644 --- a/tests/community/test_community_v3_handles.py +++ b/tests/community/test_community_v3_handles.py @@ -658,12 +658,13 @@ async def test_a_tool_returning_is_error_records_the_surfaced_message(capture): to tap, so the payload is the SDK-wide no-tap shape built from the wire result — not a pydantic repr of FastMCP's ToolResult.""" from fastmcp.server.middleware import Middleware - from fastmcp.tools import ToolResult from mcp.types import TextContent + from ..test_utils import error_tool_result + class Failing(Middleware): async def on_call_tool(self, context, call_next): - return ToolResult( + return error_tool_result( content=[TextContent(type="text", text="the tool said no")], is_error=True, ) diff --git a/tests/conftest.py b/tests/conftest.py index 0916782..f00f51e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,5 @@ import os -from importlib.metadata import version +from importlib.metadata import PackageNotFoundError, version # Belt-and-suspenders: force diagnostics off before any test imports/runs, so no # test ordering or future change to the auto-disable detection can ever ship OTLP @@ -8,11 +8,26 @@ os.environ["DISABLE_DIAGNOSTICS"] = "true" -# ── Per-era collection gating ──────────────────────────────────────────────── -# The suite runs under two mutually exclusive dependency sets (see pyproject's -# `mcp-legacy` / `mcp-modern` groups). Era-specific test modules import symbols -# that exist on only one side, so each era's collection skips the other's. -MCP_MAJOR = int(version("mcp").split(".")[0]) +# ── Collection gating ──────────────────────────────────────────────────────── +# Three independent reasons a module cannot even be IMPORTED in a given +# environment. They are accumulated below rather than chosen between: the +# compatibility matrix runs legs that trip more than one at once (mcp 2.x with +# fastmcp deliberately uninstalled trips two). +# +# This has to happen at collection, not as a `skipif`. Every case here is a +# module-scope import of a symbol that does not exist, which raises while +# pytest is importing the module — before any mark on any test inside it runs. +# +# Prerelease segments are dropped rather than parsed: `2.0.0b1` yields (2, 0), +# which orders correctly against every bound used here. +MCP_VERSION = tuple(int(p) for p in version("mcp").split(".")[:3] if p.isdigit()) +MCP_MAJOR = MCP_VERSION[0] + +try: + version("fastmcp") + HAS_FASTMCP = True +except PackageNotFoundError: # the `test-without-fastmcp` matrix legs + HAS_FASTMCP = False _LEGACY_ONLY = ( "e2e/official", @@ -44,6 +59,24 @@ "test_community_v4_handles.py", ) +# Needs community FastMCP importable at all, independent of era. The +# `test-without-fastmcp` matrix legs uninstall it and then verify it is gone, +# and these trees reach for `fastmcp` while pytest imports them. +_NEEDS_FASTMCP = ( + "e2e/community_v3", + "e2e/community_v4", + "community", +) + +# Needs a Streamable-HTTP transport AND an HTTP request object to inspect. +# `mcp.client.streamable_http`, `FastMCP.streamable_http_app()` and the +# `stateless_http` setting all arrive in mcp 1.8.0; `RequestContext.request` — +# everything `extra.requestInfo` reads — arrives in 1.9.2. Below that there is +# no transport to exercise and no request to read, so unlike the rest of the +# old-version work there is nothing to reach into: the capability is absent +# upstream, not merely spelled differently. +_NEEDS_REQUEST_CONTEXT = ("e2e/official",) + def _ignore_globs(paths: tuple[str, ...]) -> list[str]: """Ignore each path itself plus everything beneath it. @@ -57,3 +90,7 @@ def _ignore_globs(paths: tuple[str, ...]) -> list[str]: collect_ignore_glob = _ignore_globs(_MODERN_ONLY if MCP_MAJOR < 2 else _LEGACY_ONLY) +if not HAS_FASTMCP: + collect_ignore_glob += _ignore_globs(_NEEDS_FASTMCP) +if MCP_VERSION < (1, 9, 2): + collect_ignore_glob += _ignore_globs(_NEEDS_REQUEST_CONTEXT) diff --git a/tests/e2e/community_v4/test_session_http.py b/tests/e2e/community_v4/test_session_http.py index 5ab27ac..b269fb1 100644 --- a/tests/e2e/community_v4/test_session_http.py +++ b/tests/e2e/community_v4/test_session_http.py @@ -6,6 +6,11 @@ exactly one event type: `mcp:tools/call`. `initialize` only feeds the client-identity ladder and `tools/list` is intercepted for schema injection, so neither produces an event. + +Every `fastmcp` / `httpx2` import is inside a test body, as in the rest of this +tree. `tests/conftest.py` keeps the community trees out of a run with no +fastmcp installed, but a module-scope import here would fail at COLLECTION, +which no conftest gate downstream of it can rescue. """ from __future__ import annotations @@ -13,10 +18,7 @@ import json import time -import httpx2 import pytest -from fastmcp import Client -from fastmcp.client.transports import StreamableHttpTransport from agentcat.modules.constants import ( AGENTCAT_TAG_SESSION_SOURCE, @@ -40,6 +42,9 @@ def _text(result) -> str: async def test_handshake_and_list_publish_nothing(v4_http_server, capture_queue): """A real handshake plus list_tools produces no events at all — and the injected schema survives the SDK's outbound validation.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + url, _ = v4_http_server async with Client(StreamableHttpTransport(url)) as client: listed = await client.list_tools() @@ -54,6 +59,9 @@ async def test_handshake_and_list_publish_nothing(v4_http_server, capture_queue) async def test_task_handle_is_minted_then_echoed(v4_http_server, capture_queue): """The mint-back travels over the wire — text and structured — and the echoed handle keys the next event to the same task.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + url, _ = v4_http_server async with Client(StreamableHttpTransport(url)) as client: first = await client.call_tool( @@ -86,6 +94,9 @@ async def test_task_handle_is_minted_then_echoed(v4_http_server, capture_queue): async def test_client_identity_reaches_the_event(v4_http_server, capture_queue): """The handshake clientInfo is the last rung of the identity ladder, and it reaches the tools/call event over a real connection.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + url, _ = v4_http_server async with Client(StreamableHttpTransport(url)) as client: await client.call_tool("add_todo", {"text": "who", "context": "x"}) @@ -106,6 +117,8 @@ async def test_a_malformed_tools_call_keeps_its_own_protocol_error( customer server's own `-32602` on the wire, and no real client can be made to send this, so only a hand-built request reaches it. """ + import httpx2 + url, _ = v4_http_server headers = { "Content-Type": "application/json", diff --git a/tests/test_concurrency_handles.py b/tests/test_concurrency_handles.py index f0a3195..d325a02 100644 --- a/tests/test_concurrency_handles.py +++ b/tests/test_concurrency_handles.py @@ -31,9 +31,13 @@ SESSION_ID_PARAM, ) -from .test_utils import sid +from .test_utils import NEEDS_CONCURRENT_DISPATCH, sid from .test_utils.flavors import flavors +# Every test here asserts `barrier.peak == TOTAL`, which is unsatisfiable on an +# SDK that handles messages serially. See `NEEDS_CONCURRENT_DISPATCH`. +pytestmark = NEEDS_CONCURRENT_DISPATCH + TOTAL = 25 diff --git a/tests/test_inner_tap.py b/tests/test_inner_tap.py index fcc11dc..dd67cbf 100644 --- a/tests/test_inner_tap.py +++ b/tests/test_inner_tap.py @@ -37,7 +37,12 @@ tapped, ) -from .test_utils import LEGACY_ONLY, MODERN_ONLY +from .test_utils import ( + LEGACY_ONLY, + MODERN_ONLY, + NEEDS_CONCURRENT_DISPATCH, + NEEDS_LOWLEVEL_ERROR_SEAM, +) try: import fastmcp # noqa: F401 @@ -501,6 +506,7 @@ async def test_fastmcp_v1_publishes_the_tool_error_and_its_cause(self, events): assert tool_frames[0]["in_app"] is True assert "Test value error from tool" in tool_frames[0]["context_line"] + @NEEDS_LOWLEVEL_ERROR_SEAM @pytest.mark.asyncio async def test_bare_lowlevel_v1_publishes_the_handlers_own_exception( self, events @@ -550,6 +556,7 @@ async def call(server): assert _call_events(events, "tool_that_raises") assert len(tracked.content) > len(untracked.content) + @NEEDS_CONCURRENT_DISPATCH @pytest.mark.asyncio async def test_parallel_failures_each_get_their_own_slot(self, events): from .test_utils.client import create_test_client @@ -630,8 +637,15 @@ async def test_a_handled_sub_call_is_not_published_as_the_result(self, events): Nothing the agent sees came from a Python exception, so the surfaced message is the whole payload — the sub-call's stack must not be it. + + The error result is produced by a layer BELOW AgentCat rather than by + returning a `CallToolResult` from the tool body, which mcp only honors + from 1.19 (PR #1459) and which JSON-serializes into an `isError=False` + text block below it. Wrapping `request_handlers` before `track()` puts + AgentCat above the layer that answers, which is the arrangement this + test is about, and it behaves identically on every mcp 1.x. """ - from mcp.types import CallToolResult, TextContent + from mcp.types import CallToolRequest, ServerResult, TextContent from .test_utils.client import create_test_client from .test_utils.todo_server import create_todo_server @@ -644,15 +658,33 @@ async def inner(marker: str) -> str: raise Boom(f"INNER {marker}") @server.tool() - async def outer(marker: str) -> CallToolResult: - """Handles inner's failure and reports its own error result.""" + async def outer(marker: str) -> str: + """Handles inner's failure and reports its own message.""" with contextlib.suppress(Exception): await server._tool_manager.call_tool("inner", {"marker": marker}) - return CallToolResult( - content=[TextContent(type="text", text=f"OUTER declined {marker}")], - isError=True, + return f"OUTER declined {marker}" + + low = server._mcp_server + answered = low.request_handlers[CallToolRequest] + + async def declines(req): + result = await answered(req) + return ServerResult( + result.root.model_copy( + update={ + "isError": True, + "content": [ + TextContent( + type="text", + text=f"OUTER declined {req.params.arguments['marker']}", + ) + ], + } + ) ) + low.request_handlers[CallToolRequest] = declines + track(server, "test_project", AgentCatOptions()) async with create_test_client(server) as client: @@ -666,11 +698,17 @@ async def outer(marker: str) -> CallToolResult: "platform": "python", } + @NEEDS_LOWLEVEL_ERROR_SEAM @pytest.mark.asyncio async def test_a_schema_validation_failure_keeps_the_surfaced_message( self, events ): - """The lowlevel SDK composes that message itself; the probe skips it.""" + """The lowlevel SDK composes that message itself; the probe skips it. + + Gated on the same seam: the input validation this asserts arrived in + the very PR that added `_make_error_result`, so below it there is no + "Input validation error:" for AgentCat to keep. + """ from .test_utils.client import create_test_client server = _bare_v1_server("validating-v1") @@ -997,10 +1035,11 @@ async def __call__(self, context, call_next): try: return await call_next(context) except Exception as exc: - from fastmcp.tools import ToolResult from mcp.types import TextContent - return ToolResult( + from .test_utils import error_tool_result + + return error_tool_result( content=[TextContent(type="text", text=f"swallowed: {exc}")], is_error=True, ) @@ -1102,17 +1141,25 @@ async def test_a_repeated_track_does_not_stack_a_second_tap(self, events): @pytest.mark.asyncio async def test_a_proxied_upstream_error_keeps_the_surfaced_message(self, events): - """The documented permanent gap, driven through a real proxy. - - `providers/proxy.py` passes an upstream error result through - deliberately — "rather than collapsing it into a raised ToolError" — - from a `call_tool_mcp` that never raises. The failure happened in the - backend; there is no Python exception anywhere in this process to - recover, and no tap placement could change that. Built as an actual - proxy so this fails loudly if a future FastMCP starts raising instead. + """The documented gap, driven through a real proxy. + + From fastmcp 3.4 `providers/proxy.py` passes an upstream error result + through deliberately — "rather than collapsing it into a raised + ToolError" — from a `call_tool_mcp` that never raises. The failure + happened in the backend; there is no Python exception anywhere in this + process to recover, and no tap placement could change that. + + Below 3.4 the proxy did exactly the collapsing that comment rules out + (`if result.isError: raise ToolError(first.text)`), so there IS a local + exception and the tap keeps it — the gap is a CONSEQUENCE of PR #4217 + making the pass-through expressible, not a property of proxying. Both + branches are asserted rather than one being skipped, so this still + fails loudly if a future FastMCP changes its mind again. """ from fastmcp import Client + from .test_utils import FASTMCP_TOOLRESULT_HAS_IS_ERROR + backend = _community_server("proxy-backend") front = _create_proxy(backend) track(front, "test_project", AgentCatOptions()) @@ -1128,7 +1175,12 @@ async def test_a_proxied_upstream_error_keeps_the_surfaced_message(self, events) upstream = result.content[0].text assert "kaboom one" in upstream error = _one(events, "boom").error - assert error == {"message": upstream, "type": None, "platform": "python"} + assert error["message"] == upstream + if FASTMCP_TOOLRESULT_HAS_IS_ERROR: + assert error == {"message": upstream, "type": None, "platform": "python"} + else: + assert error["type"] == "ToolError" + assert error["frames"] @pytest.mark.asyncio async def test_the_wire_error_is_what_an_untracked_server_returns(self, events): @@ -1242,9 +1294,10 @@ async def test_a_sub_call_still_running_does_not_cost_the_tools_detail( frames, to the three-key payload a server with no tap at all produces. """ from fastmcp import Client, FastMCP - from fastmcp.tools import ToolResult from mcp.types import TextContent + from .test_utils import error_tool_result + sub_call_is_inside = asyncio.Event() let_the_sub_call_finish = asyncio.Event() spawned: list = [] @@ -1261,7 +1314,7 @@ async def __call__(self, context, call_next): except Exception as exc: let_the_sub_call_finish.set() await spawned[0] - return ToolResult( + return error_tool_result( content=[TextContent(type="text", text=f"swallowed: {exc}")], is_error=True, ) diff --git a/tests/test_lowlevel_v1_handles.py b/tests/test_lowlevel_v1_handles.py index c606734..a7e8266 100644 --- a/tests/test_lowlevel_v1_handles.py +++ b/tests/test_lowlevel_v1_handles.py @@ -29,7 +29,7 @@ ) from agentcat.modules.handles import derive_session_id -from .test_utils import sid +from .test_utils import NEEDS_STRUCTURED_OUTPUT, read_only_hint, sid from .test_utils.client import create_test_client from .test_utils.delivery import delivered_arguments_for, record_delivered_arguments from .test_utils.todo_server import create_todo_server @@ -115,6 +115,7 @@ async def test_prompted_mode_end_to_end(capture): assert call_events[0].user_intent.startswith("Adding a todo item") +@NEEDS_STRUCTURED_OUTPUT async def test_structured_mint_back_mirrors_into_structured_content(capture): """A tool with an outputSchema gets `_mcp_instructions` mirrored in, and its schema declares the field so schema-validating clients still accept it.""" @@ -181,7 +182,7 @@ async def test_get_more_tools_keeps_its_own_context_and_publishes(capture): # described by the tool's own copy — and handles ride alongside. assert gmt.inputSchema["required"] == ["context"] assert "session_id" in gmt.inputSchema["properties"] - assert gmt.annotations.readOnlyHint is True + assert read_only_hint(gmt) is True result = await client.call_tool( "get_more_tools", {"context": "I need a tool to send emails"} @@ -237,7 +238,13 @@ async def test_hook_mode(capture): r2 = await client.call_tool("add_todo", {"text": "hook two"}) assert "[MCP INSTRUCTIONS]" not in _text(r1) assert "[MCP INSTRUCTIONS]" not in _text(r2) - assert MCP_INSTRUCTIONS_KEY not in (r1.structuredContent or {}) + # `getattr`, not attribute access: `structuredContent` is a real field + # from mcp 1.10 and an unset extra before it, and pydantic raises + # AttributeError for an extra that was never assigned. The claim here + # is absence either way. + assert MCP_INSTRUCTIONS_KEY not in ( + getattr(r1, "structuredContent", None) or {} + ) call_events = _call_events(capture) expected = derive_session_id("cust-1", "proj_test") @@ -575,9 +582,23 @@ async def test_re_arm_is_not_stacked_by_a_second_track(capture): async def test_intermediate_mrtr_round_is_tagged_but_never_decorated(capture): """A round that asks the client for more input is not the completing round, - so it carries no mint-back — text or structured.""" + so it carries no mint-back — text or structured. + + The round is registered straight into `request_handlers` rather than + through `@server.call_tool()`: returning a `CallToolResult` from the + decorated function is only honored from mcp 1.19 (PR #1459), and below it + the SDK wraps the model itself as content and fails its own validation. + `request_handlers` takes a `ServerResult` on every 1.x, and `resultType` + rides along as an extra field because `CallToolResult` is extra="allow". + """ from mcp.server.lowlevel import Server - from mcp.types import CallToolRequest, CallToolRequestParams, CallToolResult, Tool + from mcp.types import ( + CallToolRequest, + CallToolRequestParams, + CallToolResult, + ServerResult, + Tool, + ) server = Server("mrtr-server") @@ -591,13 +612,16 @@ async def list_tools() -> list: ) ] - @server.call_tool() - async def call_tool(name: str, arguments: dict): - return CallToolResult( - content=[TextContent(type="text", text="need more")], - resultType="input_required", + async def call_tool(req): + return ServerResult( + CallToolResult( + content=[TextContent(type="text", text="need more")], + resultType="input_required", + ) ) + server.request_handlers[CallToolRequest] = call_tool + track(server, "proj_test") handler = server.request_handlers[CallToolRequest] result = await handler( @@ -608,7 +632,10 @@ async def call_tool(name: str, arguments: dict): ) assert [block.text for block in result.root.content] == ["need more"] - assert result.root.structuredContent is None + # See the note in `test_hook_mode`: absence is the claim, and below mcp + # 1.10 an unmirrored `structuredContent` is an unset extra rather than a + # field holding None. + assert getattr(result.root, "structuredContent", None) is None event = _call_events(capture)[0] assert event.tags["agentcat_mrtr"] == "input_required" assert event.session_id.startswith("ses_") diff --git a/tests/test_response_shape.py b/tests/test_response_shape.py index ff28344..60aa586 100644 --- a/tests/test_response_shape.py +++ b/tests/test_response_shape.py @@ -25,16 +25,26 @@ from agentcat import AgentCatOptions, track from agentcat.modules.constants import MCP_INSTRUCTIONS_KEY, SESSION_ID_PARAM -from .test_utils import sid +from .test_utils import FASTMCP_TOOLRESULT_HAS_IS_ERROR, sid from .test_utils.flavors import flavors # (error key, structured key) as each flavor's own result model spells them. +# A `None` error key means this era's result model has no error field at all, +# so the payload correctly carries neither spelling — which is still exactly +# what this module pins: the event keeps the era's OWN field names. EXPECTED_SPELLING = { "official-fastmcp-v1": ("isError", "structuredContent"), "lowlevel-v1": ("isError", "structuredContent"), "mcpserver-v2": ("is_error", "structured_content"), "lowlevel-v2": ("is_error", "structured_content"), - "community-v3": ("is_error", "structured_content"), + # Community FastMCP only grew `ToolResult.is_error` in 3.4 (PR #4217); on + # the 3.0-3.3 line the model has three fields and the dump has no error + # key. The EVENT's own `is_error` is unaffected — the adapter sets it, it + # is not read back off this payload. + "community-v3": ( + "is_error" if FASTMCP_TOOLRESULT_HAS_IS_ERROR else None, + "structured_content", + ), "community-v4": ("is_error", "structured_content"), } @@ -67,8 +77,11 @@ async def test_the_event_response_keeps_its_eras_own_field_names(flavor, capture response = capture[0].response assert isinstance(response, dict) # This era's spelling is present, and the other era's is nowhere in it. - assert error_key in response + if error_key is not None: + assert error_key in response assert structured_key in response + # With `error_key` None this asserts NEITHER error spelling appears, which + # is strictly stronger than the case where one is expected. assert not (BOTH_SPELLINGS - {error_key, structured_key}) & set(response) # ...and it is the customer's own result, undecorated: the mint-back is # wire-only and must never reach the analytics payload. diff --git a/tests/test_utils/__init__.py b/tests/test_utils/__init__.py index a07d9cb..e1e1162 100644 --- a/tests/test_utils/__init__.py +++ b/tests/test_utils/__init__.py @@ -1,14 +1,17 @@ """Test utilities for AgentCat tests.""" +import functools import os from importlib.metadata import version from pathlib import Path +from typing import Any import pytest LOG_FILE = "agentcat.log" -MCP_MAJOR = int(version("mcp").split(".")[0]) +MCP_VERSION = tuple(int(p) for p in version("mcp").split(".")[:3] if p.isdigit()) +MCP_MAJOR = MCP_VERSION[0] # For the integration tests inside otherwise era-agnostic modules. `conftest.py` # gates whole FILES by era; a module that mixes plain unit tests with a class @@ -27,6 +30,153 @@ reason="built on the mcp 2.x MCPServer + in-process Client harness", ) +# ── Upstream capability gates ──────────────────────────────────────────────── +# Both of these were added by mcp 1.10.0 and both are probed on the capability +# rather than compared against a version, so a backport would be honoured and +# the probe cannot drift from what the test actually needs. +# +# The rest of the old-mcp work reaches past era-specific spellings, because the +# thing wanted was there under another name. These two are different: the seam +# is absent, so there is nothing to reach for. AgentCat still runs below them — +# it degrades to the surfaced message with no exception type, and mirrors no +# structured mint-back — which is why these gate tests rather than the package. + +# `Server._make_error_result` is the seam `modules/adapters/_inner_tap.py` +# hooks to recover a handler's real exception before the SDK folds it into an +# `isError` result. mcp 1.10.0 introduced it (PR #1005, "Add schema validation +# to lowlevel server"), together with the lowlevel input validation whose +# message that same PR surfaces. +try: + from mcp.server.lowlevel import Server as _LowlevelServer + + HAS_LOWLEVEL_ERROR_SEAM = hasattr(_LowlevelServer, "_make_error_result") +except Exception: # pragma: no cover - import guard + HAS_LOWLEVEL_ERROR_SEAM = False + +NEEDS_LOWLEVEL_ERROR_SEAM = pytest.mark.skipif( + not HAS_LOWLEVEL_ERROR_SEAM, + reason=( + "needs Server._make_error_result (mcp>=1.10) — below it the lowlevel " + "server catches the handler's exception inline and the tap has no seam" + ), +) + +# Structured tool output as DECLARED fields — `Tool.outputSchema`, +# `CallToolResult.structuredContent`, and `mcp.server.fastmcp` deriving the +# schema from a return annotation — also arrived in mcp 1.10.0. +try: + import mcp.types as _mcp_types + + HAS_STRUCTURED_OUTPUT = "outputSchema" in _mcp_types.Tool.model_fields +except Exception: # pragma: no cover - import guard + HAS_STRUCTURED_OUTPUT = False + +NEEDS_STRUCTURED_OUTPUT = pytest.mark.skipif( + not HAS_STRUCTURED_OUTPUT, + reason="needs declared structured tool output (mcp>=1.10)", +) + +# mcp 1.2.x awaits each incoming message before reading the next, so a server +# never has two tool calls in flight; "Made message handling concurrent" +# (da53a97e) landed in v1.3.0. Any proof built on simultaneous calls therefore +# cannot be satisfied on 1.2 no matter what AgentCat does — measured: peak +# in-flight is 1 of 5 on 1.2.1 and 5 of 5 on 1.9.4. +# +# A version compare rather than a probe, unusually: the capability is a +# scheduling property of the session loop with no symbol to inspect, and +# actually measuring it would mean booting a server at import time. +NEEDS_CONCURRENT_DISPATCH = pytest.mark.skipif( + MCP_VERSION < (1, 3), + reason="mcp<1.3 handles messages serially; simultaneous calls never overlap", +) + + +# Whether the installed community FastMCP models an error result at all. +# `ToolResult.is_error` arrived in fastmcp 3.4 (PR #4217); below it a plain +# `ToolResult` dumps three fields and carries no error key in either spelling. +# Probed on the model, so it cannot drift from what the assertions need. +try: + from fastmcp.tools import ToolResult as _ToolResult + + FASTMCP_TOOLRESULT_HAS_IS_ERROR = "is_error" in _ToolResult.model_fields +except Exception: # pragma: no cover - community extra not installed + FASTMCP_TOOLRESULT_HAS_IS_ERROR = False + + +@functools.lru_cache(maxsize=1) +def _error_tool_result_class() -> Any: + """Built on first use: subclassing needs `ToolResult` to exist, which it + does not on a leg with no community FastMCP installed.""" + from fastmcp.tools import ToolResult + from mcp.types import CallToolResult + + class ErrorToolResult(ToolResult): # type: ignore[misc] + """A tool result that reports an error WITHOUT anything having raised. + + FastMCP 3.4 added `ToolResult.is_error` and taught `to_mcp_result` to + answer with a `CallToolResult` carrying `isError` (PR #4217). Below + that the field does not exist and `to_mcp_result` has no branch that + can set `isError` at all, so the scenario is inexpressible with the + stock model — yet it is exactly what an error-handling middleware, and + FastMCP's own proxy provider, produce. + + Both halves are supplied because both are read: the adapter takes + `getattr(result, "is_error", False)` off the OBJECT + (`adapters/community.py`), while the client sees only the WIRE. A + double that set one and not the other would pass one assertion and + quietly fail the other. + + `__init__` is an explicit signature on the 3.x line with no `**kwargs`, + so the redeclared field cannot arrive through it — hence the wrapper. + On 3.4+ this subclass is a no-op that defers to `super()`. + """ + + is_error: bool = False + + def __init__(self, *args: Any, is_error: bool = False, **kwargs: Any): + super().__init__(*args, **kwargs) + self.is_error = is_error + + def to_mcp_result(self) -> Any: + if not self.is_error: + return super().to_mcp_result() + return CallToolResult( + content=self.content, + structuredContent=self.structured_content, + isError=True, + _meta=self.meta, + ) + + return ErrorToolResult + + +def read_only_hint(tool: Any) -> Any: + """`readOnlyHint` off a tool, whether or not this SDK models annotations. + + AgentCat hands `annotations` over as a plain mapping so it never has to + import a type whose availability moved between generations. From mcp 1.7 + the `Tool.annotations` field exists and pydantic coerces the mapping into + the model; below it there is no such field and the mapping is carried + verbatim as an extra. Both spellings mean the same thing to a client. + """ + annotations = getattr(tool, "annotations", None) + if annotations is None: + return None + if isinstance(annotations, dict): + return annotations.get("readOnlyHint", annotations.get("read_only_hint")) + return getattr( + annotations, "readOnlyHint", getattr(annotations, "read_only_hint", None) + ) + + +def error_tool_result(**kwargs: Any) -> Any: + """An `is_error` tool result on every community FastMCP 3.x and 4.x. + + Use instead of `ToolResult(..., is_error=True)`, which is a TypeError + below fastmcp 3.4. + """ + return _error_tool_result_class()(**kwargs) + def sid(label: str) -> str: """A valid 27-char session ID that still reads as its label in failures. diff --git a/tests/test_utils/flavors.py b/tests/test_utils/flavors.py index 5b6165d..17d46a8 100644 --- a/tests/test_utils/flavors.py +++ b/tests/test_utils/flavors.py @@ -21,9 +21,15 @@ Every ``mcp`` / ``fastmcp`` import is function-local: this module is imported by test files that collect under both SDK majors. -""" -from __future__ import annotations +No ``from __future__ import annotations`` here, deliberately. PEP 563 would +stringify the annotations of the tool bodies defined inside ``build()``, and +``mcp.server.fastmcp``'s ``Tool.from_function`` calls +``issubclass(param.annotation, Context)`` on mcp 1.7-1.13 — which raises +``TypeError: issubclass() arg 1 must be a class`` against a string. Nothing in +this module needs the future import: every annotation is PEP 585/604, which +Python 3.10 evaluates natively, and no name is used before it is defined. +""" import contextlib import copy @@ -265,6 +271,65 @@ def __repr__(self) -> str: # pragma: no cover - test ids only # ── official MCP SDK 1.x ───────────────────────────────────────────────────── +def _backfill_structured_output(fastmcp_server: Any) -> None: + """Give a pre-1.10 `mcp.server.fastmcp.FastMCP` the structured output that + its later selves produce natively. + + From mcp 1.10 the facade derives an ``outputSchema`` from a tool's return + annotation and answers with matching ``structuredContent``. Before that the + feature does not exist at all — not spelled differently, absent. But this + flavor's contract is "a FastMCP server whose tools declare an output + schema", because that is what the cross-flavor parity suites compare + against the other five shapes; a flavor that quietly dropped half its + contract on old mcp would make those suites read as green while covering + less. + + Both patches go on ``_mcp_server.request_handlers`` — the same table the + adapter itself wraps, and the one seam whose contract is stable across all + of 1.x — so what AgentCat sees here is exactly what it sees on 1.10+. + No-ops when the running SDK already does this. + """ + import mcp.types as types + + if "outputSchema" in types.Tool.model_fields: + return + + low = fastmcp_server._mcp_server + list_inner = low.request_handlers[types.ListToolsRequest] + call_inner = low.request_handlers[types.CallToolRequest] + + async def list_handler(req: Any) -> Any: + result = await list_inner(req) + listed = result.root + return types.ServerResult( + listed.model_copy( + update={ + "tools": [ + tool.model_copy( + update={"outputSchema": dict(RESULT_OUTPUT_SCHEMA)} + ) + for tool in listed.tools + ] + } + ) + ) + + async def call_handler(req: Any) -> Any: + result = await call_inner(req) + inner = result.root + if inner.isError: + return result + message = "".join( + block.text for block in inner.content if hasattr(block, "text") + ) + return types.ServerResult( + inner.model_copy(update={"structuredContent": {"result": message}}) + ) + + low.request_handlers[types.ListToolsRequest] = list_handler + low.request_handlers[types.CallToolRequest] = call_handler + + class OfficialFastMCPV1(Flavor): """`mcp.server.fastmcp.FastMCP`, adapted through its `_mcp_server`.""" @@ -311,6 +376,7 @@ async def complete_task(session_id: str, note: str = "") -> str: # `seen` is filled at the manager, not in the bodies above: see # `record_delivered_arguments` for why a typed body cannot report it. record_delivered_arguments(server._tool_manager, built.seen) + _backfill_structured_output(server) return built @contextlib.asynccontextmanager @@ -328,6 +394,31 @@ async def call( ) -> Called: return _called(await client.call_tool(name, arguments)) + async def call_unlisted( + self, server: Any, name: str, arguments: dict[str, Any] + ) -> Called: + # The raw request, not `call_tool`, for the reason `MCPServerV2` gives: + # from mcp 1.15 the convenience method revalidates a result carrying + # `structuredContent` against the tool's output schema, and fetches the + # listing to do it. That listing is harmless to the rebuild — which has + # already happened by then — but fatal to a test that has deliberately + # taken the list source down. + import mcp.types as types + + async with self.client(server) as client: + result = await client.send_request( + types.ClientRequest( + types.CallToolRequest( + method="tools/call", + params=types.CallToolRequestParams( + name=name, arguments=arguments + ), + ) + ), + types.CallToolResult, + ) + return _called(result) + def break_list_source(self, server: Any) -> None: # The tool manager is what FastMCP's own `tools/list` handler reads, # and that handler is what the adapter recorded as the list source. @@ -390,18 +481,48 @@ async def list_tools() -> list[Any]: raise ListSourceDown("the list source is down") return [tool.model_copy(deep=True) for tool in tools] - @server.call_tool() - async def call_tool(tool_name: str, arguments: dict[str, Any]) -> Any: - arguments = dict(arguments or {}) - _reject_unexpected(tool_name, arguments) - built.seen.append((tool_name, arguments)) - if tool_name == "echo" and hook is not None: - await hook() - message = _answer(tool_name, arguments) - return ( - [types.TextContent(type="text", text=message)], - {"result": message}, - ) + # Registered straight into `request_handlers` rather than through + # `@server.call_tool()`, because the decorator's return CONVENTION is + # era-specific and this flavor has to build the same server on every + # mcp 1.x. Returning `(content, structured)` needs mcp >= 1.10, and + # returning a `CallToolResult` needs >= 1.19; below those the SDK + # wraps the value as content and CallToolResult validation fails + # INSIDE its own try, yielding a plausible-looking `isError` result + # instead of an exception. `request_handlers` is the one seam whose + # contract — a `ServerResult` in, a `ServerResult` out — has been + # stable since 1.0, and it is the same table AgentCat itself wraps. + # + # The two behaviours the decorator supplies are reproduced here: a + # successful call answers `isError=False`, and ANY raise becomes an + # `isError=True` result carrying `str(exc)` — which is what makes + # `ToolFailed` and `_reject_unexpected` observable to the tests. + async def call_tool_handler(req: Any) -> Any: + try: + tool_name = req.params.name + arguments = dict(req.params.arguments or {}) + _reject_unexpected(tool_name, arguments) + built.seen.append((tool_name, arguments)) + if tool_name == "echo" and hook is not None: + await hook() + message = _answer(tool_name, arguments) + return types.ServerResult( + types.CallToolResult( + content=[types.TextContent(type="text", text=message)], + # `Tool`/`CallToolResult` are extra="allow" on every + # 1.x, so this reaches the wire below 1.10 too. + structuredContent={"result": message}, + isError=False, + ) + ) + except Exception as exc: + return types.ServerResult( + types.CallToolResult( + content=[types.TextContent(type="text", text=str(exc))], + isError=True, + ) + ) + + server.request_handlers[types.CallToolRequest] = call_tool_handler return built From 4fbb8ccf095859618a4ac0df102868a3c04dbab4 Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Mon, 3 Aug 2026 22:30:59 -0400 Subject: [PATCH 03/13] refactor(logging): extract AGENTCAT_DEBUG_MODE parse into _env_debug_mode() --- src/agentcat/modules/logging.py | 15 +++++++++------ tests/test_logging.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/src/agentcat/modules/logging.py b/src/agentcat/modules/logging.py index 761dac6..c109251 100644 --- a/src/agentcat/modules/logging.py +++ b/src/agentcat/modules/logging.py @@ -7,12 +7,15 @@ from agentcat.types import AgentCatOptions -# Initialize debug_mode from environment variable at module load time -_env_debug = os.getenv("AGENTCAT_DEBUG_MODE") -if _env_debug is not None: - debug_mode = _env_debug.lower() in ("true", "1", "yes", "on") -else: - debug_mode = False +def _env_debug_mode() -> bool: + """True when AGENTCAT_DEBUG_MODE holds a truthy value.""" + raw = os.getenv("AGENTCAT_DEBUG_MODE") + return raw is not None and raw.lower() in ("true", "1", "yes", "on") + + +# Seed from the environment at import time. track() only overrides this when +# AgentCatOptions.debug_mode is explicitly set — None leaves the seed alone. +debug_mode = _env_debug_mode() # Optional sink that receives every (clean, newline-free) log entry. Used by the diff --git a/tests/test_logging.py b/tests/test_logging.py index ecc79d8..2118dc2 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -271,3 +271,33 @@ def test_log_format(self, tmp_path): # Verify message assert message == test_message, "Message content doesn't match" + + +class TestEnvDebugMode: + """The AGENTCAT_DEBUG_MODE parse that seeds debug_mode at import time.""" + + @pytest.mark.parametrize( + "raw,expected", + [ + ("true", True), + ("TRUE", True), + ("1", True), + ("yes", True), + ("on", True), + ("false", False), + ("0", False), + ("", False), + ("garbage", False), + ], + ) + def test_parses_truthy_tokens(self, monkeypatch, raw, expected): + monkeypatch.setenv("AGENTCAT_DEBUG_MODE", raw) + from agentcat.modules.logging import _env_debug_mode + + assert _env_debug_mode() is expected + + def test_unset_means_off(self, monkeypatch): + monkeypatch.delenv("AGENTCAT_DEBUG_MODE", raising=False) + from agentcat.modules.logging import _env_debug_mode + + assert _env_debug_mode() is False From edf269a00bf88f94c8bbc1bcbb31da36baabf35f Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Mon, 3 Aug 2026 22:32:13 -0400 Subject: [PATCH 04/13] fix(logging): stop track() from clobbering AGENTCAT_DEBUG_MODE The env var was read at import but unconditionally overwritten by track() with the options default (False), so the documented debug switch never worked (broken since it shipped in #11). debug_mode is now tri-state: explicit option > AGENTCAT_DEBUG_MODE > off. --- src/agentcat/__init__.py | 3 +- src/agentcat/types.py | 4 ++- tests/test_logging.py | 62 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/src/agentcat/__init__.py b/src/agentcat/__init__.py index 52c2a27..88aa66c 100644 --- a/src/agentcat/__init__.py +++ b/src/agentcat/__init__.py @@ -85,7 +85,8 @@ def track( if options is None: options = AgentCatOptions() - set_debug_mode(options.debug_mode) + if options.debug_mode is not None: + set_debug_mode(options.debug_mode) # Initialize internal diagnostics before anything can fail, so even an # invalid setup still emits a failure beacon. Never throws into the host. diff --git a/src/agentcat/types.py b/src/agentcat/types.py index 0eebc3c..7d02dd7 100644 --- a/src/agentcat/types.py +++ b/src/agentcat/types.py @@ -191,7 +191,9 @@ class AgentCatOptions: identify: IdentifyFunction | None = None redact_sensitive_information: RedactionFunction | None = None exporters: dict[str, ExporterConfig] | None = None - debug_mode: bool = False + # Debug logging to ~/agentcat.log. Tri-state: None (the default) defers to + # the AGENTCAT_DEBUG_MODE env var read at import; explicit True/False wins. + debug_mode: bool | None = None api_base_url: str | None = None # Disables AgentCat's internal SDK diagnostics — anonymous, metadata-only # setup/error reporting used to detect failed installs. On by default; also diff --git a/tests/test_logging.py b/tests/test_logging.py index 2118dc2..ec24476 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -301,3 +301,65 @@ def test_unset_means_off(self, monkeypatch): from agentcat.modules.logging import _env_debug_mode assert _env_debug_mode() is False + + +class TestTrackDebugModePrecedence: + """track() must honor: explicit option > AGENTCAT_DEBUG_MODE seed > off.""" + + @pytest.fixture(autouse=True) + def reset_debug_mode(self): + yield + set_debug_mode(False) + + def _track(self, tmp_path, **track_kwargs): + """Run track(object()) with ~/agentcat.log redirected to tmp_path. + + The untrackable object takes the early no-project/no-exporters warning + path in _apply_tracking, which write_to_log's — enough to observe the + debug gate without touching the event queue. + """ + import agentcat + + log_file = tmp_path / "agentcat.log" + with patch( + "agentcat.modules.logging.os.path.expanduser", + return_value=str(log_file), + ): + agentcat.track(object(), **track_kwargs) + return log_file + + def test_default_options_preserve_env_seeded_debug_mode(self, tmp_path): + from agentcat.modules import logging as logging_module + + set_debug_mode(True) # simulate AGENTCAT_DEBUG_MODE=true import seed + log_file = self._track(tmp_path) + + assert logging_module.debug_mode is True, ( + "track() with default options clobbered the env-seeded debug flag" + ) + assert log_file.exists(), "debug log was not written" + assert "Failed to track server" in log_file.read_text() + + def test_explicit_true_enables_logging(self, tmp_path): + import agentcat + from agentcat.modules import logging as logging_module + + set_debug_mode(False) + log_file = self._track( + tmp_path, options=agentcat.AgentCatOptions(debug_mode=True) + ) + + assert logging_module.debug_mode is True + assert log_file.exists() + + def test_explicit_false_overrides_env_seed(self, tmp_path): + import agentcat + from agentcat.modules import logging as logging_module + + set_debug_mode(True) # simulate env seed + log_file = self._track( + tmp_path, options=agentcat.AgentCatOptions(debug_mode=False) + ) + + assert logging_module.debug_mode is False + assert not log_file.exists() From 37c0a2281b7a91c5ed7eb87695bdec8dbba915cb Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Tue, 4 Aug 2026 11:30:57 -0400 Subject: [PATCH 05/13] feat(logging): stamp SDK, Python, and MCP SDK versions on all diagnostics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every write_to_log entry (local file and diagnostics sink) now carries a once-per-process cached "agentcat=… python=… mcp=… fastmcp=…" suffix, so a shared log excerpt never leaves the reader guessing which environment produced it; an uninstalled MCP distribution reads `absent`, which is itself a diagnostic. The OTLP exporter stamps process.runtime.* and agentcat.{mcp,fastmcp}_sdk.version resource attributes on every exported event, and the diagnostics beacon now reports fastmcp alongside mcp (community servers previously reported only the transitive mcp version). --- src/agentcat/modules/diagnostics.py | 4 ++ src/agentcat/modules/exporters/otlp.py | 25 ++++++++- src/agentcat/modules/logging.py | 24 +++++++-- src/agentcat/utils.py | 17 ++++++ tests/test_diagnostics_attributes.py | 16 ++++++ tests/test_diagnostics_sink.py | 3 +- tests/test_exporter_sdk_version.py | 62 ++++++++++++++++++++++ tests/test_logging.py | 72 +++++++++++++++++++++++++- 8 files changed, 216 insertions(+), 7 deletions(-) diff --git a/src/agentcat/modules/diagnostics.py b/src/agentcat/modules/diagnostics.py index 073c93a..914fbf5 100644 --- a/src/agentcat/modules/diagnostics.py +++ b/src/agentcat/modules/diagnostics.py @@ -167,6 +167,10 @@ def _build_static_attributes(project_id: str | None) -> list[dict[str, Any]]: out += _attr("agentcat.mcp_sdk.version", version("mcp")) except Exception: pass + try: + out += _attr("agentcat.fastmcp_sdk.version", version("fastmcp")) + except Exception: + pass # Runtime out += _attr("process.runtime.name", platform.python_implementation().lower()) diff --git a/src/agentcat/modules/exporters/otlp.py b/src/agentcat/modules/exporters/otlp.py index 1975a3b..067724c 100644 --- a/src/agentcat/modules/exporters/otlp.py +++ b/src/agentcat/modules/exporters/otlp.py @@ -1,6 +1,7 @@ """OpenTelemetry Protocol (OTLP) exporter for AgentCat telemetry.""" import json +import platform from datetime import datetime from typing import Any, Dict, List, Optional @@ -9,7 +10,7 @@ from ...types import Event, OTLPExporterConfig from ...modules.constants import AGENTCAT_SOURCE from ...modules.logging import write_to_log -from ...utils import get_agentcat_version +from ...utils import get_agentcat_version, get_dist_version from . import Exporter from .trace_context import trace_context @@ -164,6 +165,28 @@ def _get_resource_attributes(self, event: Event) -> List[Dict[str, Any]]: } ) + # Runtime + MCP SDK versions; keys mirror the diagnostics beacon + # (modules/diagnostics.py) so both OTLP surfaces share one vocabulary. + attributes.append( + { + "key": "process.runtime.name", + "value": {"stringValue": platform.python_implementation().lower()}, + } + ) + attributes.append( + { + "key": "process.runtime.version", + "value": {"stringValue": platform.python_version()}, + } + ) + for dist, key in ( + ("mcp", "agentcat.mcp_sdk.version"), + ("fastmcp", "agentcat.fastmcp_sdk.version"), + ): + dist_version = get_dist_version(dist) + if dist_version: + attributes.append({"key": key, "value": {"stringValue": dist_version}}) + return attributes def _get_span_attributes(self, event: Event) -> List[Dict[str, Any]]: diff --git a/src/agentcat/modules/logging.py b/src/agentcat/modules/logging.py index c109251..a460a5b 100644 --- a/src/agentcat/modules/logging.py +++ b/src/agentcat/modules/logging.py @@ -1,11 +1,11 @@ """Logging functionality for AgentCat.""" +import functools import os +import platform from collections.abc import Callable from datetime import datetime, timezone -from agentcat.types import AgentCatOptions - def _env_debug_mode() -> bool: """True when AGENTCAT_DEBUG_MODE holds a truthy value.""" @@ -36,9 +36,27 @@ def set_diagnostics_sink(fn: Callable[[str], None] | None) -> None: _diagnostics_sink = fn +@functools.lru_cache(maxsize=1) +def _version_suffix() -> str: + """Environment stamp appended to every log entry, computed once per process. + + A shared log excerpt must never leave the reader guessing which AgentCat + SDK, Python, or MCP SDK produced it; `absent` for an uninstalled MCP + distribution is itself a diagnostic. + """ + from agentcat.utils import get_agentcat_version, get_dist_version + + return ( + f"agentcat={get_agentcat_version() or 'unknown'} " + f"python={platform.python_version()} " + f"mcp={get_dist_version('mcp') or 'absent'} " + f"fastmcp={get_dist_version('fastmcp') or 'absent'}" + ) + + def write_to_log(message: str) -> None: timestamp = datetime.now(timezone.utc).isoformat() - log_entry = f"[{timestamp}] {message}" + log_entry = f"[{timestamp}] {message} | {_version_suffix()}" # Tee to diagnostics FIRST — independent of debug_mode. Must never break logging. if _diagnostics_sink is not None: diff --git a/src/agentcat/utils.py b/src/agentcat/utils.py index 00196fd..e176cb6 100644 --- a/src/agentcat/utils.py +++ b/src/agentcat/utils.py @@ -1,5 +1,6 @@ """Utility functions for AgentCat.""" +import functools from typing import Optional from datetime import datetime, timezone @@ -20,6 +21,22 @@ def get_agentcat_version() -> str | None: return None +@functools.cache +def get_dist_version(name: str) -> str | None: + """Best-effort installed-distribution version; None when absent. + + Shared by the log-line version suffix, the diagnostics beacon, and the + OTLP exporter to stamp the MCP SDK in use (`mcp` and/or `fastmcp`), so + the lookup runs once per distribution per process. + """ + try: + import importlib.metadata + + return importlib.metadata.version(name) + except Exception: + return None + + def generate_ksuid( use_milliseconds: bool = False, dt: Optional[datetime] = None ) -> str: diff --git a/tests/test_diagnostics_attributes.py b/tests/test_diagnostics_attributes.py index e13890b..02070a9 100644 --- a/tests/test_diagnostics_attributes.py +++ b/tests/test_diagnostics_attributes.py @@ -1,5 +1,7 @@ """Tests for static OTLP resource attributes (identity + environment).""" +import importlib.metadata + import pytest from agentcat.modules import diagnostics @@ -56,3 +58,17 @@ def test_sdk_and_environment_metadata_present(): assert attrs.get("os.type") assert attrs.get("process.runtime.name") assert attrs.get("process.runtime.version") + + +def test_mcp_sdk_version_attributes(): + """Both MCP SDK distributions are reported when installed, omitted when not.""" + diagnostics.init_diagnostics("proj_1") + attrs = _attrs() + assert attrs.get("agentcat.mcp_sdk.version") == importlib.metadata.version("mcp") + + try: + fastmcp_version = importlib.metadata.version("fastmcp") + except importlib.metadata.PackageNotFoundError: + assert "agentcat.fastmcp_sdk.version" not in attrs + else: + assert attrs.get("agentcat.fastmcp_sdk.version") == fastmcp_version diff --git a/tests/test_diagnostics_sink.py b/tests/test_diagnostics_sink.py index a2fbdfe..9bf3794 100644 --- a/tests/test_diagnostics_sink.py +++ b/tests/test_diagnostics_sink.py @@ -20,9 +20,10 @@ def test_sink_receives_every_entry(): assert len(seen) == 1 assert "hello world" in seen[0] - # Sink gets the timestamped, newline-free entry. + # Sink gets the timestamped, newline-free entry, version suffix included. assert seen[0].startswith("[") assert "\n" not in seen[0] + assert "agentcat=" in seen[0] def test_sink_raising_never_breaks_write_to_log(): diff --git a/tests/test_exporter_sdk_version.py b/tests/test_exporter_sdk_version.py index e3e04b9..9c59d12 100644 --- a/tests/test_exporter_sdk_version.py +++ b/tests/test_exporter_sdk_version.py @@ -5,6 +5,7 @@ """ import importlib.metadata +import platform from datetime import datetime, timezone from unittest.mock import MagicMock, patch @@ -15,6 +16,11 @@ INSTALLED_VERSION = importlib.metadata.version("agentcat") +try: + FASTMCP_VERSION: str | None = importlib.metadata.version("fastmcp") +except importlib.metadata.PackageNotFoundError: # the test-without-fastmcp legs + FASTMCP_VERSION = None + def make_event(**kwargs) -> Event: defaults = dict( @@ -53,6 +59,62 @@ def test_scope_version_falls_back_to_unknown_when_unresolvable(self): assert scope["version"] == "unknown" +class TestOTLPResourceVersionAttributes: + """Every exported event's OTLP resource carries runtime + MCP SDK versions.""" + + def _export_and_get_resource_attrs(self, event: Event) -> dict: + exporter = OTLPExporter({"endpoint": "http://localhost:4318/v1/traces"}) + exporter.session = MagicMock() + exporter.export(event) + assert exporter.session.post.called + payload = exporter.session.post.call_args.kwargs["json"] + attrs = payload["resourceSpans"][0]["resource"]["attributes"] + return {a["key"]: a["value"]["stringValue"] for a in attrs} + + def test_python_runtime_attributes_present(self): + attrs = self._export_and_get_resource_attrs(make_event()) + assert attrs["process.runtime.name"] == platform.python_implementation().lower() + assert attrs["process.runtime.version"] == platform.python_version() + + def test_mcp_sdk_version_attribute_matches_installed(self): + attrs = self._export_and_get_resource_attrs(make_event()) + assert attrs["agentcat.mcp_sdk.version"] == importlib.metadata.version("mcp") + + def test_fastmcp_attribute_present_iff_installed(self): + attrs = self._export_and_get_resource_attrs(make_event()) + if FASTMCP_VERSION is None: + assert "agentcat.fastmcp_sdk.version" not in attrs + else: + assert attrs["agentcat.fastmcp_sdk.version"] == FASTMCP_VERSION + + def test_absent_distribution_emits_no_attribute(self): + with patch( + "agentcat.modules.exporters.otlp.get_dist_version", return_value=None + ): + attrs = self._export_and_get_resource_attrs(make_event()) + assert "agentcat.mcp_sdk.version" not in attrs + assert "agentcat.fastmcp_sdk.version" not in attrs + # Runtime attributes do not depend on distribution lookups. + assert attrs["process.runtime.version"] == platform.python_version() + + +class TestGetDistVersion: + """Best-effort installed-distribution reader shared by the log-line version + suffix and the exporters.""" + + def test_returns_installed_version(self): + from agentcat.utils import get_dist_version + + get_dist_version.cache_clear() + assert get_dist_version("agentcat") == INSTALLED_VERSION + + def test_returns_none_for_missing_distribution(self): + from agentcat.utils import get_dist_version + + get_dist_version.cache_clear() + assert get_dist_version("definitely-not-a-real-distribution") is None + + class TestSentryAuthHeaderVersion: DSN = "https://abcdef1234567890@o123.ingest.sentry.io/456" diff --git a/tests/test_logging.py b/tests/test_logging.py index ec24476..2cf3ebd 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -1,5 +1,7 @@ """Tests for the logging module.""" +import importlib.metadata +import platform import time import uuid from unittest.mock import patch @@ -269,8 +271,74 @@ def test_log_format(self, tmp_path): assert timestamp[13] == ":", "Invalid hour-minute separator" assert timestamp[16] == ":", "Invalid minute-second separator" - # Verify message - assert message == test_message, "Message content doesn't match" + # Verify message and version suffix: + # "MESSAGE | agentcat=… python=… mcp=… fastmcp=…" + message_part, suffix = message.rsplit(" | ", 1) + assert message_part == test_message, "Message content doesn't match" + for key in ("agentcat=", "python=", " mcp=", "fastmcp="): + assert key in f" {suffix}", f"Version suffix missing {key.strip()}" + + def test_every_line_carries_version_suffix(self, tmp_path): + """Each entry — not just the first — carries the version suffix.""" + set_debug_mode(True) + unique_id = str(uuid.uuid4()) + log_file = tmp_path / f"test_agentcat_{unique_id}.log" + + with patch( + "agentcat.modules.logging.os.path.expanduser", return_value=str(log_file) + ): + write_to_log(f"first {unique_id}") + write_to_log(f"second {unique_id}") + + test_lines = [ + line + for line in log_file.read_text().strip().split("\n") + if unique_id in line + ] + assert len(test_lines) == 2 + for line in test_lines: + for key in ("agentcat=", "python=", " mcp=", "fastmcp="): + assert key in line, f"{key.strip()} missing from line: {line}" + + def test_version_suffix_values_are_truthful(self, tmp_path): + """The suffix reports the real installed/runtime versions.""" + set_debug_mode(True) + unique_id = str(uuid.uuid4()) + log_file = tmp_path / f"test_agentcat_{unique_id}.log" + + with patch( + "agentcat.modules.logging.os.path.expanduser", return_value=str(log_file) + ): + write_to_log(f"versions {unique_id}") + + content = log_file.read_text() + assert f"agentcat={importlib.metadata.version('agentcat')}" in content + assert f"python={platform.python_version()}" in content + + def test_missing_distribution_reported_absent(self, tmp_path): + """A distribution that cannot be resolved shows as `absent`, not an error.""" + from agentcat.modules.logging import _version_suffix + + set_debug_mode(True) + unique_id = str(uuid.uuid4()) + log_file = tmp_path / f"test_agentcat_{unique_id}.log" + + _version_suffix.cache_clear() + try: + with ( + patch("agentcat.utils.get_dist_version", return_value=None), + patch( + "agentcat.modules.logging.os.path.expanduser", + return_value=str(log_file), + ), + ): + write_to_log(f"absent {unique_id}") + finally: + _version_suffix.cache_clear() + + content = log_file.read_text() + assert " mcp=absent" in content + assert " fastmcp=absent" in content class TestEnvDebugMode: From d5c082c97ccd07e1676039fffab73b54e481961c Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Tue, 4 Aug 2026 11:39:13 -0400 Subject: [PATCH 06/13] update --- .mcp.json | 36 ++ 2026-07-28-cross-sdk-changelog.md | 495 ++++++++++++++++++ MIGRATION.md | 2 +- Makefile | 50 ++ README.md | 6 +- examples/README.md | 112 ++++ examples/fastmcp/advanced/main.py | 153 ++++++ examples/fastmcp/basic/main.py | 99 ++++ examples/fastmcp/v3/main.py | 97 ++++ examples/officialsdk/advanced/main.py | 148 ++++++ examples/officialsdk/basic/main.py | 99 ++++ examples/officialsdk/factory/main.py | 89 ++++ examples/officialsdk/legacy/main.py | 96 ++++ pyproject.toml | 2 +- src/agentcat/modules/callpath.py | 2 +- src/agentcat/modules/handles.py | 6 +- src/agentcat/modules/hooks.py | 118 +++++ src/agentcat/modules/identify.py | 12 +- src/agentcat/modules/internal.py | 10 +- src/agentcat/modules/redaction.py | 17 +- src/agentcat/types.py | 14 +- .../community_v3/test_agent_handle_http.py | 203 +++++++ .../community_v3/test_event_capture_http.py | 57 +- tests/e2e/community_v3/test_identify_http.py | 91 +++- tests/e2e/community_v3/test_stateless_http.py | 9 + .../community_v4/test_agent_handle_http.py | 202 +++++++ tests/e2e/community_v4/test_identify_http.py | 199 +++++++ tests/e2e/community_v4/test_session_http.py | 54 +- tests/e2e/community_v4/test_stateless_http.py | 14 +- tests/e2e/official/test_agent_handle_http.py | 237 +++++++++ tests/e2e/official/test_identify_http.py | 28 +- tests/e2e/official/test_session_http.py | 38 ++ tests/e2e/official/test_stateless_http.py | 11 + .../official_modern/test_agent_handle_http.py | 198 +++++++ .../e2e/official_modern/test_identify_http.py | 231 ++++++++ .../e2e/official_modern/test_session_http.py | 96 ++++ .../official_modern/test_stateless_http.py | 23 +- tests/test_async_hooks.py | 319 +++++++++++ tests/test_identify_shape.py | 57 ++ 39 files changed, 3676 insertions(+), 54 deletions(-) create mode 100644 .mcp.json create mode 100644 2026-07-28-cross-sdk-changelog.md create mode 100644 Makefile create mode 100644 examples/README.md create mode 100644 examples/fastmcp/advanced/main.py create mode 100644 examples/fastmcp/basic/main.py create mode 100644 examples/fastmcp/v3/main.py create mode 100644 examples/officialsdk/advanced/main.py create mode 100644 examples/officialsdk/basic/main.py create mode 100644 examples/officialsdk/factory/main.py create mode 100644 examples/officialsdk/legacy/main.py create mode 100644 src/agentcat/modules/hooks.py create mode 100644 tests/e2e/community_v3/test_agent_handle_http.py create mode 100644 tests/e2e/community_v4/test_agent_handle_http.py create mode 100644 tests/e2e/community_v4/test_identify_http.py create mode 100644 tests/e2e/official/test_agent_handle_http.py create mode 100644 tests/e2e/official_modern/test_agent_handle_http.py create mode 100644 tests/e2e/official_modern/test_identify_http.py create mode 100644 tests/test_async_hooks.py diff --git a/.mcp.json b/.mcp.json new file mode 100644 index 0000000..d957aea --- /dev/null +++ b/.mcp.json @@ -0,0 +1,36 @@ +{ + "mcpServers": { + "officialsdk-factory": { + "type": "http", + "url": "http://localhost:8090/mcp" + }, + "officialsdk-basic": { + "type": "http", + "url": "http://localhost:8091/mcp" + }, + "officialsdk-advanced": { + "type": "http", + "url": "http://localhost:8092/mcp" + }, + "officialsdk-legacy": { + "type": "http", + "url": "http://localhost:8093/mcp" + }, + "fastmcp-basic": { + "type": "http", + "url": "http://localhost:8094/mcp" + }, + "fastmcp-advanced": { + "type": "http", + "url": "http://localhost:8095/mcp" + }, + "fastmcp-v3": { + "type": "http", + "url": "http://localhost:8096/mcp" + }, + "agentcat-mcp": { + "type": "http", + "url": "https://mcp.agentcat.com/mcp" + } + } +} \ No newline at end of file diff --git a/2026-07-28-cross-sdk-changelog.md b/2026-07-28-cross-sdk-changelog.md new file mode 100644 index 0000000..f15dfe0 --- /dev/null +++ b/2026-07-28-cross-sdk-changelog.md @@ -0,0 +1,495 @@ +# AgentCat × MCP 2026-07-28 — Cross-SDK Changelog & Implementation Brief + +**Audience:** maintainers of the AgentCat Python and Go SDKs. +**Reference implementation:** `agentcat` (TypeScript) `2.0.0-beta.4`, branch `feat/explicit-handles-v2`. +**Spec context:** [MCP 2026-07-28 release](https://blog.modelcontextprotocol.io/posts/2026-07-28/) (SEP-2567). + +This document is language-agnostic: it describes the *behavior* every AgentCat SDK +must converge on, with the TypeScript implementation as the worked example. Where +exact bytes matter (agent-facing copy, tag names, wire keys, ID derivation), they +are specified verbatim in the appendices — **do not reword or re-derive them.** + +--- + +## 1. What the protocol changed and why we care + +MCP 2026-07-28 makes the protocol **stateless by default**: + +- The `initialize`/`initialized` handshake and the `Mcp-Session-Id` header are + gone. There is no protocol-level session to attach analytics to. +- Every request is self-describing: client identity and protocol version travel + per-request under reserved `io.modelcontextprotocol/*` metadata keys. +- Servers are commonly built from **per-request factories** (a fresh server + object per HTTP request), landing behind round-robin load balancers with no + shared storage. Any instance may serve `tools/call` without ever having + served `tools/list`. +- **Multi Round-Trip Requests (MRTR)** replace held-open elicitation streams: a + single logical tool call can span several HTTP rounds (`input_required` + intermediate results, then a continuation carrying the client's input + responses). +- Tasks moved to the formal `io.modelcontextprotocol/tasks` extension + (poll-based). *Note: AgentCat's `task_id` handle is unrelated to this + extension — see §7 Non-goals.* + +Everything AgentCat previously leaned on for correlation — the initialize +handshake, transport session IDs, inactivity-based session rollover, cached +client identity — is either gone or unreliable in this world. The 2.0 response +replaces all of it with **explicit, stateless, per-request mechanisms**. + +--- + +## 2. TL;DR — old model vs. new model + +| Concern | Pre-2026 (1.x) | 2026-era (2.0) | +| --- | --- | --- | +| Correlation | Transport `sessionId` + inactivity rollover | Explicit `task_id` handle, echoed by the agent as a tool parameter | +| Session events | `mcp:initialize`, `mcp:tools/list`, `agentcat:identify` published | **Removed.** Only tool-call and custom events remain | +| Actor identity | `identify` hook + per-session identity cache | `identify` runs on **every** tool call; result stamped on that event; **no cache** | +| Client name/version | Captured once at initialize, cached | Resolved **per request** from the envelope/`_meta`, stamped on every event | +| Agent identity | (none) | Opt-in self-chosen `agent_id`, carried as event tags | +| Server state | Per-session state | **Stateless resolution** — nothing stored between requests; per-server state only in weak/ephemeral maps keyed by the server object | + +Backward compatibility on the wire: **the task ID is stored in the existing +`sessionId` event field with the existing `ses_` prefix.** Dashboards, queries, +the ingestion API, and exporters are unaffected. No backend changes required. + +--- + +## 3. Task handles replace session maintenance + +### 3.1 What is removed + +- All transport-session logic: reading `extra.sessionId` (or your language's + equivalent), session caches, inactivity-based session rollover/timeouts. + `extra.sessionId` is **ignored entirely**, even when the transport still + provides one. +- The `mcp:initialize` and `mcp:tools/list` event types are no longer + published. (`tools/list` is still *intercepted* — for schema injection — it + just doesn't emit an event.) +- The `agentcat:identify` event type and the identity cache are gone. Actor + fields ride on every event instead. + +### 3.2 The `task_id` handle + +- One `task_id` covers one goal, start to finish. Subagents share their + parent's `task_id`. +- Format: a KSUID with the `ses` prefix (e.g. `ses_2a4F...`), deliberately + reusing the session prefix and the `Event.sessionId` field. +- Injected into **every** tool's input schema as an **optional** string + parameter named `task_id` — including AgentCat's own `get_more_tools` tool + (its calls publish events, so it must be able to carry handles). It is never + added to the schema's `required` list: **omission is the minting signal.** + +### 3.3 Per-call resolution algorithm (prompted mode — the default) + +For each `tools/call`, statelessly: + +``` +supplied = args["task_id"] if it is a string whose trimmed value is non-empty +if supplied: + task_id = supplied # trusted VERBATIM — no shape validation + task_source = "supplied" +else: + task_id = new ses_ KSUID # random mint + task_source = "minted" +``` + +Nothing is stored on the server between requests, so concurrent requests can +never clobber each other. A supplied value is trusted verbatim (agents echo +what we minted; a strict format check would sever tasks over cosmetic +differences). + +### 3.4 Mint-back: telling the agent its handle + +Two delivery channels, both applied to the wire response only: + +**(a) Trailing text content block** — appended **only on the call that minted +a new task** (i.e. `task_source == "minted"`, and never in hook mode): + +``` +[MCP INSTRUCTIONS]: task_id issued. + task_id= — required on every subsequent tool call +Without task_id, this server does not function as intended. +``` + +Append it to error results too (`isError: true`) — the retry after an error +must carry the same task. Only requirement to append: the result has an array +`content`. Never mutate the customer's result object — copy. + +**(b) Structured mirror in `structuredContent`** — unlike (a), this is +persistent handle state present on **every** response (supplied handles are +re-confirmed so an agent can re-read its own handles mid-conversation). The +SDK adds a `_mcp_instructions` object: + +```jsonc +"_mcp_instructions": { + "task_id": "ses_...", // omitted in hook mode + "agent_id": "opus-...|...", // only when the agent supplied one + "instructions": "" +} +``` + +Rules: +- Never name a handle the agent cannot echo: no `task_id` key in hook mode, no + `agent_id` key when the agent didn't supply one. If neither is present, + mirror nothing. +- Only mirror into a **plain-object** `structuredContent`. If the customer's + result already contains a `_mcp_instructions` key, it is customer data — it + wins, skip the mirror. +- Gate the mirror on the output-injection registry (§5.3): only mirror for + tools whose declared `outputSchema` we successfully extended. Exception: if + no registry exists at all (rebuild failed), mirror anyway — the client + cannot be validating against a schema we know about. + +**Why the schema declaration matters:** 2026-era clients ajv/schema-validate +`structuredContent` against the tool's advertised `outputSchema`, and common +schema generators emit `additionalProperties: false`. An undeclared extra key +would fail the customer's *entire* result. So for every tool that declares a +plain-object `outputSchema`, inject an **optional** `_mcp_instructions` +property (object, with the sub-property descriptions from Appendix A) at +list-time. Composed schemas (`oneOf`/`allOf`/`anyOf`) have no single +properties bag — skip them (log a warning; mint-back stays content-only for +that tool). + +**Mint-back is wire-only.** The recorded event's `response` is the customer's +original result — no `[MCP INSTRUCTIONS]` block, no `_mcp_instructions` field. +Same for error messages. + +### 3.5 Hook mode — customers who bring their own correlation IDs + +New option `resolveTaskId(request, extra) -> string | null` (name it +idiomatically per language). When configured: + +- **No `task_id` parameter is injected anywhere** and no task instructions are + ever shown to the agent. The customer owns task state. +- The returned string is combined with the project ID and **deterministically + derived** into a `ses_` KSUID (§3.6), so the same customer ID always maps to + the same task across processes, restarts — and, once you implement this, + across *languages*. `task_source = "hook"`. +- A nullish return or a thrown error mints a random task silently + (`task_source = "minted"`, still no agent-facing instructions — the agent + has no parameter to echo, so announcing an ID it can never send would be + noise). Log the hook error. A configured hook should answer every request. + +### 3.6 Deterministic derivation — MUST match across SDKs + +``` +input = project_id ? f"{customer_id}:{project_id}" : customer_id +hash = SHA-256(input) # 32 bytes +ts_ms = 1704067200000 # 2024-01-01T00:00:00Z, fixed epoch + + (uint32_be(hash[0:4]) % 31536000000) # offset < 365 days, keeps KSUID valid +payload = hash[4:20] # 16 bytes +ksuid = KSUID(timestamp = floor((ts_ms - 1400000000000) / 1000) as uint32-BE, + payload = payload) # standard 20-byte KSUID, base62 → 27 chars +result = "ses_" + base62(ksuid) +``` + +(`1400000000000` is the standard KSUID epoch, 2017-05-13T16:53:20Z. The +customer ID is trimmed before hashing.) Add a cross-language golden-vector +test: pick a few `(customer_id, project_id)` pairs and assert the exact +`ses_…` output matches the TypeScript SDK. + +### 3.7 Custom events + +`publishCustomEvent` no longer derives a task from its session-id string +argument — the string is used **verbatim** as the task ID. Prefer an explicit +`task_id` field on the custom-event data (TS: `CustomEventData.taskId`), which +takes precedence. The tracked-server form publishes **without** a task unless +one is explicitly given. + +--- + +## 4. Optional self-chosen `agent_id` + +Distinguishes parallel agents working the same task. **Off by default** — +opt-in via `enableAgentTracking: true` (breaking-change posture: quiet by +default). + +- Injected into every tool's input schema as a string parameter named + `agent_id`, **marked `required` in the schema**. +- The value is **self-chosen by the agent** — there is no server-side agent + minting (an earlier design minted `agt_` KSUIDs server-side; it was removed, + the `agt` prefix stays reserved). The parameter description instructs the + agent to generate `model|harness|nonce`, e.g. `opus-4.80-1m|claude-code|k3n9x`, + and to keep it stable for the whole task. Subagents MUST generate their own + (opposite of `task_id`, which subagents share). +- **Enforcement is client-side, soft server-side.** A strict schema-validating + MCP client refuses to send a call omitting a required parameter — that is + the actual enforcement mechanism. Server-side, an omitted `agent_id` NEVER + rejects the call: the event is simply published without agent identity, and + no mint-back/echo mentions `agent_id`. +- Extraction mirrors `task_id`: trimmed non-empty string, trusted verbatim, + else treated as omitted. +- Carried on events **as tags**, not as a first-class event field: + - `agentcat_agent_id` — the supplied value, clamped for the tag channel: + CR/LF replaced with spaces, truncated to 200 chars. (The tag channel + bypasses customer tag validation/redaction/truncation, hence the clamp. + The un-clamped value still appears in the recorded raw request.) + - `agentcat_agent_id_source` — always `"supplied"` today. +- Echoed back in `_mcp_instructions.agent_id` (with the "keep sending this + exact value" instructions) only when supplied. Never announced in the text + mint-back block. +- Works in hook mode too: `enableAgentTracking` and `resolveTaskId` compose. + In hook mode use the hook-mode variant of the parameter description + (Appendix A) — it must not reference a `task_id` parameter the agent cannot + see. + +--- + +## 5. Per-request client identity, protocol version, and actor identity + +### 5.1 Client name/version — resolved on every request, never cached + +Resolution ladder (first hit wins): + +1. **2026 envelope** — `extra.mcpReq.envelope["io.modelcontextprotocol/clientInfo"]` + (or your SDK's equivalent). 2026-era server SDKs lift the reserved + `io.modelcontextprotocol/*` keys out of `_meta` before dispatch and expose + them under their **fully-qualified** names on the request envelope; the + envelope is the only place they exist there. +2. **`_meta` passthrough** — `request.params._meta["io.modelcontextprotocol/clientInfo"]` + (pre-2026 server SDKs pass the key through untouched). +3. **Legacy initialize capture** — the server's cached client info from the + old handshake (`getClientVersion()` in TS). Keeps identity working for + pre-2026 clients; absent on 2026-pinned stdio. + +Narrow defensively: accept `name`/`version` only if each is individually a +string; a non-string field must not reach the event payload. + +The resolved `clientName`/`clientVersion` are stamped **directly on every +event** at publish time, alongside server name/version, SDK language, and +AgentCat SDK version. There is no cache and no session-info object shared +between requests. + +### 5.2 Protocol version + +Same ladder (envelope → `_meta`) for +`io.modelcontextprotocol/protocolVersion`. When present, stamp it as the +`agentcat_protocol_version` tag on the event. This gives the platform +fleet-level visibility into protocol adoption. + +### 5.3 Actor identity + +The `identify` hook now runs on **every tool call**, and its result is stamped +directly onto that call's event (`identifyActorGivenId` / `identifyActorName` +/ `identifyActorData`). There is no identity cache and no separate identify +event. Hooks should be cheap; document that for customers. + +**Divergence — Python awaits `identify`, TypeScript's status unverified.** The +Python SDK originally shipped `identify` as the only one of the five customer +hooks that was never awaited, so an `async def` hook built a coroutine, ran none +of its body, and published the call anonymously with no error the customer could +see. Python now resolves all five hooks through one contract +(`src/agentcat/modules/hooks.py`): sync or async, narrowed on `isawaitable` — so +an `asyncio.Task` or any `__await__` implementer works too, not just native +coroutines. A parity sweep should confirm the TypeScript side accepts the same +range before this row is called settled. + +--- + +## 6. Mechanics you must replicate (the parts nobody puts in the headline) + +### 6.1 Schema injection pipeline (at `tools/list` time) + +- Parameter order in each tool's schema: **customer params, `task_id`, + `agent_id`, `context`** (the intent-capture param — its injector runs after + the handle injector). +- Deep-copy every schema before modifying; never mutate the customer's + registered tool in place on the list path. +- If the input schema has `additionalProperties: false`, remove it (injected + params must not fail validation). +- Skip injection entirely for composed input schemas (`oneOf`/`allOf`/`anyOf`) + — log a warning. +- **Name collisions:** if a tool already defines `task_id` (or `agent_id`), + skip injecting that parameter for that tool, log a warning, and — critically + — make sure the customer's own parameter **reaches their handler untouched** + (it must not be stripped). +- Record every (tool → params actually injected) pair in an + **injected-params registry**, and every tool whose `outputSchema` you + extended in an **output-injection registry**. These drive stripping and + mirroring. +- The whole pipeline — config + listed tools in → advertised tools + + registries out — must be **pure and deterministic**. §6.3 depends on it. + +### 6.2 Argument stripping (at `tools/call` time) + +- Before invoking the customer's handler, strip **only** the params the + registry says were injected for that tool, on a **cloned** request. +- The published event records the **raw, unstripped** request (handles and + `context` included) — the event shows exactly what the agent sent. +- Fallback when a call arrives with no registry (see §6.3 for why): strip all + three names (`task_id`, `agent_id`, `context`) heuristically — except + `get_more_tools`, whose `context` is a real parameter and must survive. + +### 6.3 Per-request topology: rebuild-on-demand + +2026-era factories create a fresh server per request, so a `tools/call` can +land on an instance that never served `tools/list`. On the first call, if the +registries are missing, **rebuild them** by invoking the original (unwrapped) +`tools/list` handler and running its result through the same pure injection +pipeline. Because the pipeline is deterministic, the rebuilt registries match +what any listing instance advertised. Only if the rebuild fails do you fall +back to the §6.2 heuristic strip. + +Related invariants for factory topologies: + +- Document `track()`-inside-the-factory as the integration pattern. +- Module-level state (event queue, telemetry manager, diagnostics) initializes + once, first-wins, and is reused across `track()` calls. Per-server state + lives in maps that don't outlive the server object (WeakMap in TS; use your + language's equivalent or explicit lifecycle). +- `track()` **never throws** — any failure logs a warning and returns the + untracked server. + +### 6.4 MRTR (multi round-trip requests) tagging + +A 2026-era tool call can return an intermediate result with +`resultType: "input_required"` and later complete on a continuation round +carrying the client's input responses. + +- **Intermediate round** (`resultType == "input_required"`): tag the event + `agentcat_mrtr = "input_required"`, and **do not decorate the result** — no + text mint-back, no structured mirror. The completing round carries the + mint-back. +- **Continuation round** (the request envelope carries `inputResponses`): tag + the event `agentcat_mrtr = "continuation"`. +- Each round publishes its own event; they correlate through the shared + `task_id` like everything else. + +### 6.5 SDK tag namespace + +All SDK-owned tags (Appendix B) are merged **after** customer tags (SDK wins +on collision) and are **exempt from the customer 50-tag cap**. Every event +gets `agentcat_task_id_source`; the others are conditional. + +### 6.6 `get_more_tools` + +- **Not** exempt from handle injection (it publishes events), but its bespoke + `context` parameter is its own — only `task_id`/`agent_id` are stripped. +- Carries the read-only MCP tool annotation (`readOnlyHint`). +- Still answers when tracing is disabled. + +### 6.7 Dual-generation SDK support + +The TS SDK supports both MCP SDK majors through one `track()` call, using +**per-object feature detection** (never importing either SDK), per-major +adapters for the one property that differs (which field holds the dispatched +function), and a unified interception engine. Mirror the *approach* if your +language has two coexisting SDK generations: detection by probing the object +in hand, single-sourced probe list logged as a shape fingerprint (with a +diagnostics beacon on unrecognized shapes, for fleet-level drift detection), +and version-specific knowledge confined to tiny adapters. + +--- + +## 7. Non-goals — deliberately NOT part of this design + +- **No use of the `io.modelcontextprotocol/tasks` extension** for correlation. + AgentCat's `task_id` is an analytics handle echoed as a tool argument; it is + unrelated to the poll-based tasks extension despite the name. +- **No reliance on the `Mcp-Method` / `Mcp-Name` routing headers.** +- **No server-side session or handle storage of any kind.** Resolution is + fully stateless per request. +- **No server-side minting of `agent_id`** (removed during design — a + server-minted agent ID can't survive the agent's own context boundaries, + and only the agent knows who it is). +- **No hard rejection of calls missing `agent_id`.** Required-in-schema + + strict clients is the enforcement; the server never breaks a customer's + tool over analytics. + +--- + +## 8. Suggested rollout order (mirrors the TS commit history) + +1. Handle primitives: minting, deterministic derivation (+ golden vectors), + extraction, mint-back text builder, tag builder. +2. Per-request resolution (prompted + hook modes) and per-request client + identity/protocol version. +3. Schema injection + injected-params registry + safe stripping. +4. Call-path wiring: resolve → strip → dispatch → mint-back → publish; then + remove session machinery, identity caches, and the retired event types. +5. Structured mint-back: outputSchema declaration + `structuredContent` + mirror. +6. `agent_id`: opt-in flag, required-in-schema, self-chosen copy, tags. +7. 2026-era topology: rebuild-on-demand, MRTR tagging, factory-pattern docs, + concurrency regression tests (parallel calls with distinct handles must + not cross-attribute). + +--- + +## Appendix A — Canonical agent-facing copy (byte-identical across SDKs) + +This copy was iterated for LLM compliance and is the single source of truth +(TS: `src/modules/constants.ts`, spec: +`docs/superpowers/specs/2026-07-29-explicit-handles-copy.md`). Reuse it +verbatim; fleet-wide consistency of the prompt surface is the point. + +**`task_id` parameter description:** + +> REQUIRED on every call after your first. This MCP server associates all of your tool calls for a given task using task_id; a call that arrives without it cannot be associated with your earlier work and is treated as the start of an unrelated task, disconnected from the original goal. Omit it on your first call only — the server will issue one in the _mcp_instructions field of the result (or a trailing [MCP INSTRUCTIONS] text block) — then echo that exact value on every later call. Never invent a value, and do not issue parallel tool calls until the server has issued your task_id. One task_id covers the whole goal from start to finish: when you spawn subagents you MUST give them this same task_id, or their work is severed from yours. Without task_id, this server does not function as intended. + +**`agent_id` parameter description (default mode):** + +> REQUIRED on every call, including your first. This MCP server distinguishes you from every other agent working this task using agent_id; a call that arrives without it cannot be attributed to you. Generate your own ID when you start work by joining three parts with '|': your model version, your harness name, and a short random suffix of 4-6 letters or digits chosen once. Example: opus-4.80-1m|claude-code|k3n9x. Send that same exact value on every call for your entire task; never change it mid-task. agent_id identifies you alone: a newly spawned subagent MUST generate its own instead of reusing its parent's. Without agent_id, this server does not function as intended. + +**`agent_id` parameter description (hook mode):** identical except the first +sentence's task framing — it says "distinguishes you from every other agent" +(no "working this task") so it never references a `task_id` parameter the +agent cannot see. See `AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE` in the TS +constants for the exact string. + +**Text mint-back block (task minted this call):** + +``` +[MCP INSTRUCTIONS]: task_id issued. + task_id= — required on every subsequent tool call +Without task_id, this server does not function as intended. +``` + +**Structured-mirror `instructions` when nothing was minted this call:** + +``` +[MCP INSTRUCTIONS]: confirmed. Keep sending this exact value on every call. +``` + +where `` is `task_id`, `agent_id`, or `task_id and agent_id`, and the +tail pluralizes to "these exact values" when both are present. + +**`_mcp_instructions` outputSchema field descriptions:** + +- field: "Your handles for this task, confirmed by this MCP server on every response, and the instructions for echoing them on later calls. Read and follow." +- `task_id` sub-property: "Echo this exact value as the task_id argument on every subsequent tool call." +- `agent_id` sub-property: "Your agent_id as this server received it. Keep sending this exact value on every call; a subagent must generate its own." + +--- + +## Appendix B — Wire keys, tags, and ID prefixes + +**Reserved metadata keys (read-only, defined by MCP):** + +| Key | Purpose | +| --- | --- | +| `io.modelcontextprotocol/clientInfo` | Per-request client `{name, version}` | +| `io.modelcontextprotocol/protocolVersion` | Per-request protocol version | + +**Injected parameter names:** `task_id`, `agent_id`, `context` (pre-existing). + +**Structured mint-back key:** `_mcp_instructions`. + +**SDK-owned event tags (post-customer merge, exempt from the 50-tag cap):** + +| Tag | Values | +| --- | --- | +| `agentcat_task_id_source` | `supplied` \| `minted` \| `hook` (always present) | +| `agentcat_agent_id` | the supplied agent_id, newlines→space, max 200 chars | +| `agentcat_agent_id_source` | `supplied` | +| `agentcat_protocol_version` | e.g. `2026-07-28` (when the request carries one) | +| `agentcat_mrtr` | `input_required` \| `continuation` | + +**ID prefixes:** `ses_` (tasks — deliberately the session prefix, keeps +`Event.sessionId` compatible), `evt_` (events), `agt_` (reserved; server-side +agent minting was removed). + +**Event field mapping:** task ID → `Event.sessionId`. Client identity → +`Event.clientName` / `Event.clientVersion` on every event. Actor → +`Event.identifyActor*` on every event. diff --git a/MIGRATION.md b/MIGRATION.md index 05fc244..65b60e8 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -160,7 +160,7 @@ The session ID is used **verbatim** — never validated, derived or reformatted, **A server tracked with `enable_tracing=False` publishes no custom events.** Turning tracing off silences this entry point exactly as it silences tool-call events, so a server you deliberately muted does not start emitting a new event type. The session-ID-string form has no options to consult and always publishes. -### Known limitations in 2.0.0b2 +### Known limitations in 2.0.0b3 - **Multi-round tool calls that mint their own handle land on separate sessions.** If a tool call spans several round trips and the *first* round is what mints the handle, each round is attributed to its own session instead of one shared session. The other two modes correlate correctly and are protocol-enforced: supplying `session_id` yourself, or deriving it with a `resolve_session_id` hook. If your server relies on multi-round tool calls, prefer one of those two. - **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and the upstream returns an error result, no Python exception is raised locally, so the event records the message without a stack trace. Errors raised by your own tool code are unaffected. This applies from fastmcp 3.4, which taught the proxy provider to pass an upstream error result through; on 3.0–3.3 the proxy collapsed it into a raised `ToolError` instead, so those versions do record full detail. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6192ffb --- /dev/null +++ b/Makefile @@ -0,0 +1,50 @@ +# AgentCat Python SDK — example server orchestration. +# +# Mirrors the Go SDK's run-examples / stop-examples targets. Each example is a +# self-contained PEP 723 script: `uv run` resolves it into an isolated, cached +# environment (the first run resolves four distinct dependency sets and can +# take a minute; cached thereafter) and never touches the project's .venv — +# safe to use from a legacy-synced checkout (see CONTRIBUTING.md). +# `--no-project` makes that guarantee explicit. + +.PHONY: help run-examples stop-examples smoke-examples + +EXAMPLE_PORTS := 8090 8091 8092 8093 8094 8095 8096 + +# Project ID fallthrough: AGENTCAT_PROJECT_ID > MCPCAT_PROJECT_ID > placeholder. +PROJECT_ID_ENV = AGENTCAT_PROJECT_ID=$${AGENTCAT_PROJECT_ID:-$${MCPCAT_PROJECT_ID:-proj_YOUR_PROJECT_ID}} + +help: + @echo "Available targets:" + @echo " make run-examples - Start all example MCP servers in the background" + @echo " make stop-examples - Stop all example servers (by port)" + @echo " make smoke-examples - POST an initialize request to every server" + +# Start all example servers in the background. +run-examples: + @echo "Starting all example servers (first run resolves each script's env; may take a minute)..." + @$(PROJECT_ID_ENV) uv run --no-project examples/officialsdk/factory/main.py & echo " officialsdk-factory (pid $$!) → http://localhost:8090/mcp" + @$(PROJECT_ID_ENV) uv run --no-project examples/officialsdk/basic/main.py & echo " officialsdk-basic (pid $$!) → http://localhost:8091/mcp" + @$(PROJECT_ID_ENV) uv run --no-project examples/officialsdk/advanced/main.py & echo " officialsdk-advanced (pid $$!) → http://localhost:8092/mcp" + @$(PROJECT_ID_ENV) uv run --no-project examples/officialsdk/legacy/main.py & echo " officialsdk-legacy (pid $$!) → http://localhost:8093/mcp" + @$(PROJECT_ID_ENV) uv run --no-project examples/fastmcp/basic/main.py & echo " fastmcp-basic (pid $$!) → http://localhost:8094/mcp" + @$(PROJECT_ID_ENV) uv run --no-project examples/fastmcp/advanced/main.py & echo " fastmcp-advanced (pid $$!) → http://localhost:8095/mcp" + @$(PROJECT_ID_ENV) uv run --no-project examples/fastmcp/v3/main.py & echo " fastmcp-v3 (pid $$!) → http://localhost:8096/mcp" + @echo "All servers started. Use 'make stop-examples' to stop them." + +# Stop all example servers (by the ports they listen on). +stop-examples: + @echo "Stopping example servers..." + @for port in $(EXAMPLE_PORTS); do kill $$(lsof -ti:$$port) 2>/dev/null || true; done + @echo "Done." + +# Prove every server answers an MCP initialize over Streamable HTTP. +smoke-examples: + @fail=0; for port in $(EXAMPLE_PORTS); do \ + code=$$(curl -s -o /dev/null -w "%{http_code}" -m 5 -X POST "http://localhost:$$port/mcp" \ + -H "Content-Type: application/json" \ + -H "Accept: application/json, text/event-stream" \ + -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0.0.0"}}}'); \ + if [ "$$code" = "200" ]; then echo " port $$port OK"; \ + else echo " port $$port FAIL (HTTP $$code)"; fail=1; fi; \ + done; exit $$fail diff --git a/README.md b/README.md index 1148c40..c6d8d1f 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ pip install --pre "agentcat[community]" ``` `--pre` is required while 2.x is a prerelease: without it pip skips -`2.0.0b2` and resolves the 1.x line instead, which has none of the features +`2.0.0b3` and resolves the 1.x line instead, which has none of the features documented below. Drop the flag once a stable 2.0.0 ships. One `track()` call covers every supported server shape: @@ -171,6 +171,8 @@ def identify_user(request, extra): agentcat.track(server, "proj_0000000", AgentCatOptions(identify=identify_user)) ``` +The hook may be sync or async — `async def identify_user(request, extra)` works the same way, and is the better shape when the lookup is a network call, since a blocking one holds up every other tool call in flight. Returning anything that is not a `UserIdentity`, or raising, publishes the event anonymously rather than failing the call. + ### Bringing your own session IDs If you already have a correlation ID — a trace ID, a job ID, a header your gateway sets — hand it to AgentCat with `resolve_session_id` and no `session_id` parameter is injected into your tools at all: @@ -273,7 +275,7 @@ Learn more about our free and open source [telemetry integrations](https://docs. ### Known limitations -Two behaviors are worth knowing before you read your first dashboard. Both are deliberate for `2.0.0b2`. +Two behaviors are worth knowing before you read your first dashboard. Both are deliberate for `2.0.0b3`. - **Multi-round tool calls that mint their own handle land on separate sessions.** When a tool call runs several round trips and the *first* round is what mints the handle, each round is attributed to its own session rather than one shared session. Supplying a `session_id` yourself, or deriving one with `resolve_session_id`, correlates the rounds correctly — those two modes are protocol-enforced. Only the mint-on-first-round case is affected. - **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and that upstream returns an error result, there is no local Python exception to read, so the event records the error message without a stack trace. Errors raised by your own tool code are unaffected and carry full detail. diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000..d1189e1 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,112 @@ +# AgentCat Python SDK Examples + +These examples show how to integrate AgentCat into MCP servers built with both generations of the official MCP Python SDK and the community FastMCP framework. + +Each example is a standalone echo server that runs over Streamable HTTP, self-contained in a single file via a [PEP 723](https://peps.python.org/pep-0723/) inline-metadata header. + +## Examples + +| Example | Port | Description | +|---------|------|-------------| +| [officialsdk/factory](officialsdk/factory) | 8090 | Stateless per-request serving — `track()` inside `create_server()`, the expected 2026 deployment shape (official MCP SDK 2.x) | +| [officialsdk/basic](officialsdk/basic) | 8091 | Minimal 3-line AgentCat integration with the official MCP SDK 2.x (`MCPServer`) | +| [officialsdk/advanced](officialsdk/advanced) | 8092 | Full AgentCat v2 options (per-call `identify`, `enable_agent_tracking`, hook mode, redaction, debug) with the official MCP SDK 2.x | +| [officialsdk/legacy](officialsdk/legacy) | 8093 | The official MCP SDK **1.x** shape (`mcp.server.fastmcp.FastMCP`) — same `track()` call, prior generation | +| [fastmcp/basic](fastmcp/basic) | 8094 | Minimal 3-line AgentCat integration with community [FastMCP](https://github.com/jlowin/fastmcp) v4 | +| [fastmcp/advanced](fastmcp/advanced) | 8095 | Full AgentCat v2 options with community FastMCP v4 | +| [fastmcp/v3](fastmcp/v3) | 8096 | Community FastMCP **v3** — same `track()` call, prior generation | + +## Running an Example + +Each example is a self-contained script. To run one: + +```bash +uv run --no-project examples/officialsdk/basic/main.py +``` + +The PEP 723 header at the top of each file pins that example's MCP generation and pulls `agentcat` from this checkout as an editable install. `uv run` resolves it into an isolated, cached environment — the first run takes a moment, later runs start instantly — and **never touches the project's `.venv`**. That matters here: the repo's `mcp-legacy` and `mcp-modern` dependency groups conflict, and a bare `uv run` inside a legacy-synced checkout would re-sync it to modern (see [CONTRIBUTING.md](../CONTRIBUTING.md)). Script environments are exempt from all of that, so the legacy examples run from a modern checkout and vice versa. + +The server starts on its configured port (see table above) and accepts Streamable HTTP connections at `/mcp`. + +## Running All of Them + +```bash +make run-examples # start all seven in the background +make smoke-examples # POST an MCP initialize to every port +make stop-examples # stop them all (by port) +``` + +The committed [`.mcp.json`](../.mcp.json) at the repo root points at all seven servers, so Claude Code opened in this repo sees them automatically once they're running — check with `/mcp`. + +To use one with any other MCP client, point the client at the URL. For instance, in a Claude Desktop `claude_desktop_config.json`: + +```json +{ + "mcpServers": { + "echo": { + "url": "http://localhost:8091/mcp" + } + } +} +``` + +Or with the Claude Code CLI outside this repo: + +```bash +claude mcp add echo-server http://localhost:8091/mcp +``` + +## What the Examples Demonstrate + +### Basic + +The basic examples show that AgentCat integration is just 3 lines of code added to a normal MCP server: + +```python +project_id = os.environ.get("AGENTCAT_PROJECT_ID") or "proj_YOUR_PROJECT_ID" +agentcat.track(server, project_id) +``` + +Every tool call is captured automatically. MCP 2026-07-28 has no protocol sessions, so AgentCat correlates the calls belonging to one task through an explicit `session_id` parameter it adds to each tool schema, mints back to the agent on its first call, and strips out again before your handler runs. `track()` never raises — a shape AgentCat does not support is logged to `~/agentcat.log` and your server comes back untracked rather than failing to start. + +### Advanced + +The advanced examples show the v2 options: + +- **`identify`** — attach actor identity (ID, name, metadata) to a call's event. It runs on **every tool call**, uncached, and stamps only that event; keep it cheap and make no network calls in it +- **`enable_agent_tracking`** — also inject a required `agent_id` parameter so parallel agents on one task can be told apart (off by default) +- **`resolve_session_id` (hook mode)** — shown in a comment block: return your own correlation ID and AgentCat derives the session from it deterministically. In hook mode no `session_id` is injected anywhere and no session instructions are shown to the agent +- **`redact_sensitive_information`** — strip sensitive data (e.g. emails) before it leaves the process +- **`debug_mode`** — enable debug logging to `~/agentcat.log` +- **`enable_tool_call_context`** / **`enable_report_missing`** — shown in a comment block: opt out of the injected `context` parameter and the `get_more_tools` tool (both enabled by default) + +AgentCat trusts only a `session_id` it issued (`ses_` plus a 27-character KSUID). Anything else publishes without a session and the agent is told to re-send the real one — so a tool that declares its own `session_id` parameter cannot be correlated. Use `resolve_session_id` if you already manage sessions yourself. + +### Factory + +`officialsdk/factory` is the stateless deployment shape: the server is built in a `create_server()` factory that calls `track()` on the instance it is about to return, then served with `stateless_http=True` so nothing survives between requests. It demonstrates that: + +- module-level state (publisher, logger, diagnostics) initializes once no matter how many servers you track, and per-server state is weakly keyed and released when a server goes away — a factory does not leak; +- correlation survives statelessness, because the `session_id` handle travels on the wire rather than in server memory; +- **rebuild on demand** works: a stateless client can send `tools/call` to an instance that never served a `tools/list`, and AgentCat rebuilds its injection registries from that server's own tool list on the first call; +- shutdown is process-wide: there is no handle to hold, the event queue drains itself at exit. + +### Legacy generations + +`officialsdk/legacy` (official SDK 1.x) and `fastmcp/v3` (community FastMCP v3) are the prior-generation shapes a large installed base still runs. agentcat supports all four from one install — `track()` classifies whatever object you hand it and installs the matching adapter — so these files differ from their modern siblings only in the server class and its serving API, never in the AgentCat integration. + +## Configuration + +All examples read the project ID from the `AGENTCAT_PROJECT_ID` environment variable, falling back to `MCPCAT_PROJECT_ID`, then to `"proj_YOUR_PROJECT_ID"` — the same precedence the SDK itself uses for `AGENTCAT_API_URL` / `MCPCAT_API_URL`. + +```bash +export AGENTCAT_PROJECT_ID="proj_abc123" +uv run --no-project examples/officialsdk/basic/main.py +``` + +Set `AGENTCAT_DEBUG_MODE=true` to get verbose SDK logging in `~/agentcat.log` (the advanced examples turn this on via `debug_mode=True`). + +## Prerequisites + +- [uv](https://docs.astral.sh/uv/) — resolves and runs the self-contained scripts (Python ≥3.10 is fetched automatically if needed) +- An AgentCat project ID from [agentcat.com](https://agentcat.com) — set via `AGENTCAT_PROJECT_ID` or edit the fallback in the code diff --git a/examples/fastmcp/advanced/main.py b/examples/fastmcp/advanced/main.py new file mode 100644 index 0000000..becd51c --- /dev/null +++ b/examples/fastmcp/advanced/main.py @@ -0,0 +1,153 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "agentcat", +# "fastmcp>=4.0.0b1,<5", +# "fastmcp-slim>=4.0.0b1,<5", +# ] +# +# [tool.uv.sources] +# agentcat = { path = "../../..", editable = true } +# /// +"""Example: Full AgentCat v2 options with community FastMCP (v4). + +Demonstrates the options beyond the basic 3-line integration: + +- ``identify`` — attach actor identity to every captured event +- ``enable_agent_tracking`` — inject a required agent_id parameter so + parallel agents working one session can be told apart +- ``redact_sensitive_information`` — strip sensitive data (here: emails) + before it leaves the process +- ``debug_mode`` — verbose logging to ~/agentcat.log +- commented out: ``resolve_session_id`` hook mode, and opt-outs for the + injected context parameter and the get_more_tools tool + +Usage: + + uv run --no-project examples/fastmcp/advanced/main.py + +Serves Streamable HTTP on http://localhost:8095/mcp. +""" + +import os +import re + +from fastmcp import FastMCP + +import agentcat +from agentcat import AgentCatOptions, UserIdentity + +PORT = 8095 + +EMAIL_RE = re.compile(r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}") + + +def identify_user(request, extra): + """Attribute this call's event to an actor. + + Runs on EVERY tool call, uncached, and stamps only that call's event — + keep it cheap and make no network calls. ``request`` carries the call's + params (``request.name``, ``request.arguments``); a real implementation + would derive the actor from auth data rather than hardcoding one. If this + raises or returns None, the event publishes anonymously. + """ + return UserIdentity( + user_id="user-123", + user_name="John Doe", + user_data={"plan": "pro"}, + ) + + +def redact_emails(text: str) -> str: + """Strip email addresses from all captured data before it leaves the process.""" + return EMAIL_RE.sub("[REDACTED_EMAIL]", text) + + +# A three-level call chain so error_test produces a realistic chained +# stack trace for AgentCat's exception capture. +def process_data(data: str) -> str: + if not data: + raise ValueError("input must not be empty") + raise ValueError(f"data processing failed for {data!r}: invalid payload structure") + + +def validate_input(data: str) -> str: + try: + return process_data(data) + except ValueError as e: + raise ValueError("validation error") from e + + +def dangerous_operation(data: str) -> str: + try: + return validate_input(data) + except ValueError as e: + raise RuntimeError("dangerous operation aborted") from e + + +def main() -> None: + server = FastMCP("fastmcp-advanced-example", version="1.0.0") + + project_id = ( + os.environ.get("AGENTCAT_PROJECT_ID") + or os.environ.get("MCPCAT_PROJECT_ID") + or "proj_YOUR_PROJECT_ID" + ) + agentcat.track( + server, + project_id, + AgentCatOptions( + # Write debug logs to ~/agentcat.log. The default (None) defers to + # the AGENTCAT_DEBUG_MODE env var; an explicit True/False wins. + debug_mode=True, + # Also inject a required agent_id parameter into every tool so + # parallel agents on one session can be told apart. Off by + # default; a call that omits it is never rejected server-side. + enable_agent_tracking=True, + identify=identify_user, + redact_sensitive_information=redact_emails, + # Both injected extras are ON by default; uncomment to opt out. + # The "context" parameter powers user-intent analytics: + # enable_tool_call_context=False, + # get_more_tools lets an agent report capabilities you don't + # offer yet: + # enable_report_missing=False, + # + # Hook mode — you own correlation; no session_id parameter is + # injected anywhere and no session instructions are shown to the + # agent. Return your own ID (trace ID, workflow ID, a header) and + # AgentCat derives the same ses_ session from it + # deterministically. `extra` is the request context; on HTTP + # transports `extra.request` is the incoming HTTP request: + # resolve_session_id=lambda request, extra: ( + # extra.request.headers.get("x-correlation-id") + # ), + ), + ) + + @server.tool + def echo(text: str) -> str: + """Echo back the input text.""" + return text + + @server.tool + def reverse(text: str) -> str: + """Reverse the input text.""" + return text[::-1] + + @server.tool + def count_chars(text: str) -> str: + """Count the number of characters in the input text.""" + return str(len(text)) + + @server.tool + def error_test(text: str) -> str: + """Always errors — use this to test stack trace capture.""" + return dangerous_operation(text) + + print(f"MCP server listening on http://localhost:{PORT}/mcp") + server.run(transport="http", host="127.0.0.1", port=PORT, show_banner=False) + + +if __name__ == "__main__": + main() diff --git a/examples/fastmcp/basic/main.py b/examples/fastmcp/basic/main.py new file mode 100644 index 0000000..b3839cd --- /dev/null +++ b/examples/fastmcp/basic/main.py @@ -0,0 +1,99 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "agentcat", +# "fastmcp>=4.0.0b1,<5", +# "fastmcp-slim>=4.0.0b1,<5", +# ] +# +# [tool.uv.sources] +# agentcat = { path = "../../..", editable = true } +# /// +"""Example: Minimal AgentCat integration with community FastMCP (v4). + +This shows the simplest possible AgentCat setup — one track() call — on the +community FastMCP framework. Every tool call is captured automatically, and +AgentCat correlates the calls belonging to one session through the session_id +parameter it adds to each tool schema and mints back to the agent on its +first call. + +The explicit fastmcp-slim pin matters: fastmcp 4 is a prerelease, and uv only +honors prerelease versions named on DIRECT dependencies — the transitive +fastmcp-slim==4.0.0b1 pin would be rejected without it. + +Usage: + + uv run --no-project examples/fastmcp/basic/main.py + +Serves Streamable HTTP on http://localhost:8094/mcp. +""" + +import os + +from fastmcp import FastMCP + +import agentcat + +PORT = 8094 + + +# A three-level call chain so error_test produces a realistic chained +# stack trace for AgentCat's exception capture. +def process_data(data: str) -> str: + if not data: + raise ValueError("input must not be empty") + raise ValueError(f"data processing failed for {data!r}: invalid payload structure") + + +def validate_input(data: str) -> str: + try: + return process_data(data) + except ValueError as e: + raise ValueError("validation error") from e + + +def dangerous_operation(data: str) -> str: + try: + return validate_input(data) + except ValueError as e: + raise RuntimeError("dangerous operation aborted") from e + + +def main() -> None: + server = FastMCP("fastmcp-basic-example", version="1.0.0") + + # --- AgentCat: 3 lines to add analytics --- + project_id = ( + os.environ.get("AGENTCAT_PROJECT_ID") + or os.environ.get("MCPCAT_PROJECT_ID") + or "proj_YOUR_PROJECT_ID" + ) + agentcat.track(server, project_id) + # --- end AgentCat --- + + @server.tool + def echo(text: str) -> str: + """Echo back the input text.""" + return text + + @server.tool + def reverse(text: str) -> str: + """Reverse the input text.""" + return text[::-1] + + @server.tool + def count_chars(text: str) -> str: + """Count the number of characters in the input text.""" + return str(len(text)) + + @server.tool + def error_test(text: str) -> str: + """Always errors — use this to test stack trace capture.""" + return dangerous_operation(text) + + print(f"MCP server listening on http://localhost:{PORT}/mcp") + server.run(transport="http", host="127.0.0.1", port=PORT, show_banner=False) + + +if __name__ == "__main__": + main() diff --git a/examples/fastmcp/v3/main.py b/examples/fastmcp/v3/main.py new file mode 100644 index 0000000..35a9abf --- /dev/null +++ b/examples/fastmcp/v3/main.py @@ -0,0 +1,97 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "agentcat", +# "fastmcp>=3,<4", +# ] +# +# [tool.uv.sources] +# agentcat = { path = "../../..", editable = true } +# /// +"""Example: AgentCat with community FastMCP v3. + +agentcat supports both community FastMCP generations from one install; this +is the v3 shape (which itself pins the official mcp SDK to 1.x). The +integration is identical to the v4 example — the same track() call — the +framework generation is the only difference. + +The PEP 723 header pins fastmcp to the v3 major. `uv run` resolves this into +its own isolated environment, so running it never re-syncs or destroys the +project's .venv. + +Usage: + + uv run --no-project examples/fastmcp/v3/main.py + +Serves Streamable HTTP on http://localhost:8096/mcp. +""" + +import os + +from fastmcp import FastMCP + +import agentcat + +PORT = 8096 + + +# A three-level call chain so error_test produces a realistic chained +# stack trace for AgentCat's exception capture. +def process_data(data: str) -> str: + if not data: + raise ValueError("input must not be empty") + raise ValueError(f"data processing failed for {data!r}: invalid payload structure") + + +def validate_input(data: str) -> str: + try: + return process_data(data) + except ValueError as e: + raise ValueError("validation error") from e + + +def dangerous_operation(data: str) -> str: + try: + return validate_input(data) + except ValueError as e: + raise RuntimeError("dangerous operation aborted") from e + + +def main() -> None: + server = FastMCP("fastmcp-v3-example", version="1.0.0") + + # --- AgentCat: 3 lines to add analytics --- + project_id = ( + os.environ.get("AGENTCAT_PROJECT_ID") + or os.environ.get("MCPCAT_PROJECT_ID") + or "proj_YOUR_PROJECT_ID" + ) + agentcat.track(server, project_id) + # --- end AgentCat --- + + @server.tool + def echo(text: str) -> str: + """Echo back the input text.""" + return text + + @server.tool + def reverse(text: str) -> str: + """Reverse the input text.""" + return text[::-1] + + @server.tool + def count_chars(text: str) -> str: + """Count the number of characters in the input text.""" + return str(len(text)) + + @server.tool + def error_test(text: str) -> str: + """Always errors — use this to test stack trace capture.""" + return dangerous_operation(text) + + print(f"MCP server listening on http://localhost:{PORT}/mcp") + server.run(transport="http", host="127.0.0.1", port=PORT, show_banner=False) + + +if __name__ == "__main__": + main() diff --git a/examples/officialsdk/advanced/main.py b/examples/officialsdk/advanced/main.py new file mode 100644 index 0000000..1152940 --- /dev/null +++ b/examples/officialsdk/advanced/main.py @@ -0,0 +1,148 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "agentcat", +# "mcp>=2,<3", +# ] +# +# [tool.uv.sources] +# agentcat = { path = "../../..", editable = true } +# /// +"""Example: Full AgentCat v2 options with the official MCP SDK (mcp 2.x). + +Demonstrates the options beyond the basic 3-line integration: + +- ``identify`` — attach actor identity to every captured event +- ``enable_agent_tracking`` — inject a required agent_id parameter so + parallel agents working one session can be told apart +- ``redact_sensitive_information`` — strip sensitive data (here: emails) + before it leaves the process +- ``debug_mode`` — verbose logging to ~/agentcat.log +- commented out: ``resolve_session_id`` hook mode, and opt-outs for the + injected context parameter and the get_more_tools tool + +Usage: + + uv run --no-project examples/officialsdk/advanced/main.py + +Serves Streamable HTTP on http://localhost:8092/mcp. +""" + +import os +import re + +from mcp.server.mcpserver import MCPServer + +import agentcat +from agentcat import AgentCatOptions, UserIdentity + +PORT = 8092 + +EMAIL_RE = re.compile(r"[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}") + + +def identify_user(request, extra): + """Attribute this call's event to an actor. + + Runs on EVERY tool call, uncached, and stamps only that call's event — + keep it cheap and make no network calls. ``request`` carries the call's + params (``request.name``, ``request.arguments``); a real implementation + would derive the actor from auth data rather than hardcoding one. If this + raises or returns None, the event publishes anonymously. + """ + return UserIdentity( + user_id="user-123", + user_name="John Doe", + user_data={"plan": "pro"}, + ) + + +def redact_emails(text: str) -> str: + """Strip email addresses from all captured data before it leaves the process.""" + return EMAIL_RE.sub("[REDACTED_EMAIL]", text) + + +# A three-level call chain so error_test produces a realistic chained +# stack trace for AgentCat's exception capture. +def process_data(data: str) -> str: + if not data: + raise ValueError("input must not be empty") + raise ValueError(f"data processing failed for {data!r}: invalid payload structure") + + +def validate_input(data: str) -> str: + try: + return process_data(data) + except ValueError as e: + raise ValueError("validation error") from e + + +def dangerous_operation(data: str) -> str: + try: + return validate_input(data) + except ValueError as e: + raise RuntimeError("dangerous operation aborted") from e + + +def main() -> None: + server = MCPServer("officialsdk-advanced-example", version="1.0.0") + + project_id = ( + os.environ.get("AGENTCAT_PROJECT_ID") + or os.environ.get("MCPCAT_PROJECT_ID") + or "proj_YOUR_PROJECT_ID" + ) + agentcat.track( + server, + project_id, + AgentCatOptions( + # Write debug logs to ~/agentcat.log. The default (None) defers to + # the AGENTCAT_DEBUG_MODE env var; an explicit True/False wins. + debug_mode=True, + # Also inject a required agent_id parameter into every tool so + # parallel agents on one session can be told apart. Off by + # default; a call that omits it is never rejected server-side. + enable_agent_tracking=True, + identify=identify_user, + redact_sensitive_information=redact_emails, + # Both injected extras are ON by default; uncomment to opt out. + # The "context" parameter powers user-intent analytics: + # enable_tool_call_context=False, + # get_more_tools lets an agent report capabilities you don't + # offer yet: + # enable_report_missing=False, + # + # Hook mode — you own correlation; no session_id parameter is + # injected anywhere and no session instructions are shown to the + # agent. Return your own ID (trace ID, workflow ID, a header) and + # AgentCat derives the same ses_ session from it + # deterministically. `extra` is the request context; on HTTP + # transports `extra.request` is the incoming HTTP request: + # resolve_session_id=lambda request, extra: ( + # extra.request.headers.get("x-correlation-id") + # ), + ), + ) + + @server.tool(description="Echo back the input text") + def echo(text: str) -> str: + return text + + @server.tool(description="Reverse the input text") + def reverse(text: str) -> str: + return text[::-1] + + @server.tool(description="Count the number of characters in the input text") + def count_chars(text: str) -> str: + return str(len(text)) + + @server.tool(description="Always errors — use this to test stack trace capture") + def error_test(text: str) -> str: + return dangerous_operation(text) + + print(f"MCP server listening on http://localhost:{PORT}/mcp") + server.run(transport="streamable-http", host="127.0.0.1", port=PORT) + + +if __name__ == "__main__": + main() diff --git a/examples/officialsdk/basic/main.py b/examples/officialsdk/basic/main.py new file mode 100644 index 0000000..5a2a1e5 --- /dev/null +++ b/examples/officialsdk/basic/main.py @@ -0,0 +1,99 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "agentcat", +# "mcp>=2,<3", +# ] +# +# [tool.uv.sources] +# agentcat = { path = "../../..", editable = true } +# /// +"""Example: Minimal AgentCat integration with the official MCP SDK (mcp 2.x). + +This shows the simplest possible AgentCat setup — one track() call. Every tool +call is captured automatically, and AgentCat correlates the calls belonging to +one session through the session_id parameter it adds to each tool schema and +mints back to the agent on its first call. + +The PEP 723 header above makes this file self-contained: `uv run` resolves it +into an isolated, cached environment (mcp 2.x plus agentcat from this checkout) +without ever touching the project's .venv — safe to run even from a +legacy-synced checkout (see CONTRIBUTING.md). + +Usage: + + uv run --no-project examples/officialsdk/basic/main.py + +Serves Streamable HTTP on http://localhost:8091/mcp. +""" + +import os + +from mcp.server.mcpserver import MCPServer + +import agentcat + +PORT = 8091 + + +# A three-level call chain so error_test produces a realistic chained +# stack trace for AgentCat's exception capture. +def process_data(data: str) -> str: + if not data: + raise ValueError("input must not be empty") + raise ValueError(f"data processing failed for {data!r}: invalid payload structure") + + +def validate_input(data: str) -> str: + try: + return process_data(data) + except ValueError as e: + raise ValueError("validation error") from e + + +def dangerous_operation(data: str) -> str: + try: + return validate_input(data) + except ValueError as e: + raise RuntimeError("dangerous operation aborted") from e + + +def main() -> None: + server = MCPServer("officialsdk-basic-example", version="1.0.0") + + # --- AgentCat: 3 lines to add analytics --- + project_id = ( + os.environ.get("AGENTCAT_PROJECT_ID") + or os.environ.get("MCPCAT_PROJECT_ID") + or "proj_YOUR_PROJECT_ID" + ) + agentcat.track(server, project_id) + # --- end AgentCat --- + # + # track() never raises — a misconfiguration logs to ~/agentcat.log and the + # server comes back untracked rather than down. There is no shutdown handle + # to hold: the event queue is process-wide and drains itself at exit. Tools + # registered after track() are picked up automatically. + + @server.tool(description="Echo back the input text") + def echo(text: str) -> str: + return text + + @server.tool(description="Reverse the input text") + def reverse(text: str) -> str: + return text[::-1] + + @server.tool(description="Count the number of characters in the input text") + def count_chars(text: str) -> str: + return str(len(text)) + + @server.tool(description="Always errors — use this to test stack trace capture") + def error_test(text: str) -> str: + return dangerous_operation(text) + + print(f"MCP server listening on http://localhost:{PORT}/mcp") + server.run(transport="streamable-http", host="127.0.0.1", port=PORT) + + +if __name__ == "__main__": + main() diff --git a/examples/officialsdk/factory/main.py b/examples/officialsdk/factory/main.py new file mode 100644 index 0000000..7712e69 --- /dev/null +++ b/examples/officialsdk/factory/main.py @@ -0,0 +1,89 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "agentcat", +# "mcp>=2,<3", +# ] +# +# [tool.uv.sources] +# agentcat = { path = "../../..", editable = true } +# /// +"""Example: Stateless server factory with the official MCP SDK (mcp 2.x). + +This is the expected 2026 deployment shape: the server is built in a factory +and served with stateless HTTP, where nothing survives between requests. +track() mutates the instance it is given, so it runs INSIDE the factory, on +the instance about to serve traffic (see the "Track inside your server +factory" section of the repo README). + +It demonstrates that: + +- module-level AgentCat state (publisher, logger, diagnostics) initializes + once no matter how many servers you track; per-server state is weakly keyed + and released when a server goes away — a factory does not leak; +- correlation survives statelessness, because the session_id handle travels + on the wire (echoed back by the agent) rather than in server memory; +- shutdown is process-wide: there is no handle to hold, the event queue + drains itself at exit. + +Usage: + + uv run --no-project examples/officialsdk/factory/main.py + +Serves stateless Streamable HTTP on http://localhost:8090/mcp. +""" + +import os + +from mcp.server.mcpserver import MCPServer + +import agentcat + +PORT = 8090 + +PROJECT_ID = ( + os.environ.get("AGENTCAT_PROJECT_ID") + or os.environ.get("MCPCAT_PROJECT_ID") + or "proj_YOUR_PROJECT_ID" +) + + +def create_server() -> MCPServer: + """Build and track a server instance. + + In a per-worker or multi-tenant deployment this factory runs once per + instance. track() never raises — analytics must never take a customer + server down — so there is no error path to handle here. + """ + server = MCPServer("officialsdk-factory-example", version="1.0.0") + + @server.tool(description="Echo back the input text") + def echo(text: str) -> str: + return text + + @server.tool(description="Count the number of characters in the input text") + def count_chars(text: str) -> str: + return str(len(text)) + + agentcat.track(server, PROJECT_ID) + return server + + +def main() -> None: + server = create_server() + print(f"Stateless MCP server listening on http://localhost:{PORT}/mcp") + # stateless_http=True builds a fresh transport per REQUEST — no session + # state survives between calls. AgentCat still correlates them: the + # session_id handle rides on the wire, and its injection registries are + # rebuilt on demand from the server's own tool list if a call arrives at + # an instance that never served a tools/list. + server.run( + transport="streamable-http", + host="127.0.0.1", + port=PORT, + stateless_http=True, + ) + + +if __name__ == "__main__": + main() diff --git a/examples/officialsdk/legacy/main.py b/examples/officialsdk/legacy/main.py new file mode 100644 index 0000000..caac6d6 --- /dev/null +++ b/examples/officialsdk/legacy/main.py @@ -0,0 +1,96 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "agentcat", +# "mcp>=1.8,<2", +# ] +# +# [tool.uv.sources] +# agentcat = { path = "../../..", editable = true } +# /// +"""Example: AgentCat with the official MCP SDK 1.x (mcp.server.fastmcp.FastMCP). + +agentcat supports both official-SDK generations from one install; this is the +1.x shape a large installed base still runs. The integration is identical to +the modern example — the same track() call — only the server class and its +serving API differ. (FastMCP 1.x takes no version parameter, so this server +reports no version.) + +The PEP 723 header pins mcp to the 1.x major (>=1.8 for Streamable HTTP). +`uv run` resolves this into its own isolated environment, so running it never +re-syncs or destroys the project's .venv — the mcp-legacy / mcp-modern group +conflict in pyproject.toml does not apply to script environments. + +Usage: + + uv run --no-project examples/officialsdk/legacy/main.py + +Serves Streamable HTTP on http://localhost:8093/mcp. +""" + +import os + +from mcp.server.fastmcp import FastMCP + +import agentcat + +PORT = 8093 + + +# A three-level call chain so error_test produces a realistic chained +# stack trace for AgentCat's exception capture. +def process_data(data: str) -> str: + if not data: + raise ValueError("input must not be empty") + raise ValueError(f"data processing failed for {data!r}: invalid payload structure") + + +def validate_input(data: str) -> str: + try: + return process_data(data) + except ValueError as e: + raise ValueError("validation error") from e + + +def dangerous_operation(data: str) -> str: + try: + return validate_input(data) + except ValueError as e: + raise RuntimeError("dangerous operation aborted") from e + + +def main() -> None: + # Host and port ride on FastMCP settings kwargs in 1.x; run() reads them. + server = FastMCP("officialsdk-legacy-example", host="127.0.0.1", port=PORT) + + # --- AgentCat: 3 lines to add analytics --- + project_id = ( + os.environ.get("AGENTCAT_PROJECT_ID") + or os.environ.get("MCPCAT_PROJECT_ID") + or "proj_YOUR_PROJECT_ID" + ) + agentcat.track(server, project_id) + # --- end AgentCat --- + + @server.tool(description="Echo back the input text") + def echo(text: str) -> str: + return text + + @server.tool(description="Reverse the input text") + def reverse(text: str) -> str: + return text[::-1] + + @server.tool(description="Count the number of characters in the input text") + def count_chars(text: str) -> str: + return str(len(text)) + + @server.tool(description="Always errors — use this to test stack trace capture") + def error_test(text: str) -> str: + return dangerous_operation(text) + + print(f"MCP server listening on http://localhost:{PORT}/mcp") + server.run(transport="streamable-http") + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml index 32e1035..9ddef72 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "agentcat" -version = "2.0.0b2" +version = "2.0.0b3" description = "Analytics tool for MCP (Model Context Protocol) servers and AI agents - tracks tool usage patterns and provides insights" authors = [ { name = "AgentCat, Inc.", email = "support@agentcat.com" }, diff --git a/src/agentcat/modules/callpath.py b/src/agentcat/modules/callpath.py index a3e492b..a2e5a00 100644 --- a/src/agentcat/modules/callpath.py +++ b/src/agentcat/modules/callpath.py @@ -122,7 +122,7 @@ async def resolve_call( injected_parameter_names(tool_name, data.injected_params_registry), tool_name not in data.declared_session_params, ) - actor = resolve_identity(data, request, extra) + actor = await resolve_identity(data, request, extra) client = resolve_client_identity(meta_sources, legacy_client) protocol_version = resolve_protocol_version(meta_sources, protocol_fallback) # Read from the RAW arguments (pre-strip): the event records what the agent diff --git a/src/agentcat/modules/handles.py b/src/agentcat/modules/handles.py index 84c0d01..8d3f7f4 100644 --- a/src/agentcat/modules/handles.py +++ b/src/agentcat/modules/handles.py @@ -6,7 +6,6 @@ """ import hashlib -import inspect import re from dataclasses import dataclass from typing import Any, Literal @@ -28,6 +27,7 @@ mint_back_confirmed, mint_back_session_line, ) +from agentcat.modules.hooks import await_hook_result from agentcat.modules.logging import write_to_log from agentcat.thirdparty.ksuid import Ksuid from agentcat.types import AgentCatOptions @@ -149,9 +149,7 @@ async def resolve_handles( if callable(hook): try: - value = hook(request, extra) - if inspect.isawaitable(value): - value = await value + value = await await_hook_result(hook(request, extra), "resolve_session_id") except Exception as e: # hook errors mint silently write_to_log(f"Warning: resolve_session_id hook raised: {e}") value = None diff --git a/src/agentcat/modules/hooks.py b/src/agentcat/modules/hooks.py new file mode 100644 index 0000000..2d706f3 --- /dev/null +++ b/src/agentcat/modules/hooks.py @@ -0,0 +1,118 @@ +"""What "may be sync or async" means, defined once for every customer hook. + +`AgentCatOptions` takes five customer-supplied callables — `identify`, +`event_tags`, `event_properties`, `resolve_session_id` and +`redact_sensitive_information` — and all five are documented to accept a sync +or an async function. Before this module each site answered that question for +itself, in four different spellings across four files, and `identify` did not +answer it at all: it called the hook and used the return value verbatim, so an +`async def identify` built a coroutine, ran none of its body, failed the +`isinstance(result, UserIdentity)` check and published the call anonymously. +The customer saw no error — only an event with no actor. + +Two entry points, because the SDK runs hooks from two places: + +* `await_hook_result` — the request path. Every adapter reaches the hooks + through `await resolve_call(...)` and `await publish_tool_call_event(...)`, + on every mcp and fastmcp version in the compatibility matrix, so there is a + running loop and awaiting is all it takes. +* `drive_hook_result` — the publish worker (`event_queue.EventQueue._worker`), + a daemon THREAD with no event loop of its own. Redaction runs there and + cannot await, so an awaitable has to be driven to completion with a loop of + its own. + +Both narrow on `inspect.isawaitable`, never `inspect.iscoroutine`. The +difference is not academic: `iscoroutine` matches only native coroutines, so a +hook returning an `asyncio.Task` or `Future` — a cached in-flight lookup, say — +or any object implementing `__await__` would be assigned into the event +verbatim. That is the ``-shaped failure again, and it +looks like the hook worked. + +Both also narrow on the RESULT rather than the callable. `iscoroutinefunction` +would be wrong here: it answers False for a `functools.partial` of an async +function, for a bound method of one on some versions, and for any decorator +that returns a non-async wrapper around async work. Calling the hook and asking +what came back needs none of those special cases. +""" + +import asyncio +import inspect +from collections.abc import Awaitable +from typing import Any, TypeVar, cast + +from agentcat.modules.logging import write_to_log + +T = TypeVar("T") + +# Both signatures below spell `T | Awaitable[Any]` inline rather than sharing an +# alias. A generic alias needs `Union[T, ...]` — mypy rejects a TypeVar as the +# target of a PEP-604 alias — and ruff's UP007 then rewrites that `Union` back +# into the form mypy rejected. Inline, both tools agree. +# +# `Any` rather than `T` on the awaitable half: a customer's hook is untyped at +# runtime and its option alias is itself a union, so the concrete awaitable is +# whatever they returned. +# +# Only the awaited branch casts. `inspect.isawaitable` is a TypeGuard, so its +# NEGATIVE arm already narrows the union to `T` on its own — a cast there is +# redundant, and mypy says so. Awaiting an `Awaitable[Any]` yields `Any`, which +# `warn_return_any` rejects, so that arm does need one. + + +def _report(hook_name: str, error: Exception) -> None: + """Name the await as the cause, since the caller's log cannot. + + Every call site already logs "this hook failed, degrading" from its own + `except`. That line is true but unhelpful when the hook itself was fine and + only the awaiting went wrong — a customer reading it goes looking for a bug + in code that ran correctly. This one says which half broke; the caller's + still says which hook degraded, and both are wanted. + """ + write_to_log( + f"Warning: {hook_name} returned an awaitable that could not be awaited: {error}" + ) + + +async def await_hook_result(value: T | Awaitable[Any], hook_name: str) -> T: + """Resolve a hook's return value on a path that has a running loop. + + Re-raises rather than swallowing: each call site owns its own degradation + rule, and they differ. A failed `identify` yields an anonymous actor, a + failed `resolve_session_id` mints a fresh handle, a failed redaction drops + the event entirely. Deciding that here would flatten three deliberate + behaviors into one. + """ + if not inspect.isawaitable(value): + return value + try: + return cast(T, await value) + except Exception as e: + _report(hook_name, e) + raise + + +def drive_hook_result(value: T | Awaitable[Any], hook_name: str) -> T: + """Resolve a hook's return value from a thread with no event loop. + + `asyncio.run` builds a loop, runs the awaitable to completion and tears the + loop down. That is only valid because the publish worker is a plain thread + that never had one — calling this from inside a running loop raises, which + is why the request path uses `await_hook_result` instead. + + Not cheap, and knowingly so: the one caller is redaction, a security + control, running off the request's hot path. A hook that cannot be driven + raises here and the queue drops the event rather than publishing it + unredacted. + """ + if not inspect.isawaitable(value): + return value + try: + return cast(T, asyncio.run(_resolved(value))) + except Exception as e: + _report(hook_name, e) + raise + + +async def _resolved(awaitable: Any) -> Any: + """`asyncio.run` takes a coroutine, and an arbitrary awaitable is not one.""" + return await awaitable diff --git a/src/agentcat/modules/identify.py b/src/agentcat/modules/identify.py index 0bcfff3..2852784 100644 --- a/src/agentcat/modules/identify.py +++ b/src/agentcat/modules/identify.py @@ -1,10 +1,11 @@ from typing import Any +from agentcat.modules.hooks import await_hook_result from agentcat.modules.logging import write_to_log from agentcat.types import AgentCatData, UserIdentity -def resolve_identity( +async def resolve_identity( data: AgentCatData | None, request: Any, extra: Any ) -> UserIdentity | None: """Run the configured identify hook and return its UserIdentity. @@ -14,12 +15,19 @@ def resolve_identity( stamps the actor onto it, so identity resolution is pure and runs on every call. Never raises — a customer hook that blows up yields an anonymous call, not a failed one. + + Async as of the sync-or-async sweep: the hook may be an `async def`, and + the await lives inside the same `try` as the call, so an awaitable that + fails degrades exactly like a hook that raised. Callers are unaffected — + the one call site (`callpath.resolve_call`) was already async. """ if not data or not data.options or not data.options.identify: return None try: - result = data.options.identify(request, extra) + result = await await_hook_result( + data.options.identify(request, extra), "identify" + ) except Exception as e: write_to_log(f"Error occurred during user identification: {e}") return None diff --git a/src/agentcat/modules/internal.py b/src/agentcat/modules/internal.py index 8f6242c..05b1470 100644 --- a/src/agentcat/modules/internal.py +++ b/src/agentcat/modules/internal.py @@ -1,6 +1,5 @@ """Internal data storage for AgentCat.""" -import inspect import weakref from typing import Any, Dict, Optional @@ -10,6 +9,7 @@ # `_get_server_key`. detection.py imports nothing from this module, so this # does not close a cycle. from .detection import _probe as _attribute_present +from .hooks import await_hook_result from .logging import write_to_log from .validation import validate_tags @@ -112,9 +112,7 @@ async def resolve_event_tags( return None try: - result = callback(request, extra) - if inspect.iscoroutine(result): - result = await result + result = await await_hook_result(callback(request, extra), "event_tags") except Exception as e: write_to_log(f"event_tags callback error: {e}") return None @@ -138,9 +136,7 @@ async def resolve_event_properties( return None try: - result = callback(request, extra) - if inspect.iscoroutine(result): - result = await result + result = await await_hook_result(callback(request, extra), "event_properties") except Exception as e: write_to_log(f"event_properties callback error: {e}") return None diff --git a/src/agentcat/modules/redaction.py b/src/agentcat/modules/redaction.py index 215a73a..44d362c 100644 --- a/src/agentcat/modules/redaction.py +++ b/src/agentcat/modules/redaction.py @@ -1,9 +1,9 @@ """PII redaction for AgentCat logs.""" -import asyncio -import inspect from typing import Any, TYPE_CHECKING, Callable, Set +from agentcat.modules.hooks import drive_hook_result + if TYPE_CHECKING: from agentcat.types import Event, UnredactedEvent @@ -89,10 +89,6 @@ def redact_strings_in_object( return obj -async def _resolved(awaitable: Any) -> Any: - return await awaitable - - def _sync_redactor(redact_fn: Callable[[str], Any]) -> Callable[[str], Any]: """A synchronous view of the customer's hook. @@ -105,13 +101,14 @@ def _sync_redactor(redact_fn: Callable[[str], Any]) -> Callable[[str], Any]: security control wins, and this runs off the request's hot path. A hook that cannot be driven raises, and the queue drops the event rather than publishing it unredacted. + + The driving itself lives in `modules/hooks.py`, which is where all five + customer hooks get their answer to "sync or async" — this is the one that + cannot simply await, not a different contract. """ def redact(value: str) -> Any: - result = redact_fn(value) - if inspect.isawaitable(result): - return asyncio.run(_resolved(result)) - return result + return drive_hook_result(redact_fn(value), "redact_sensitive_information") return redact diff --git a/src/agentcat/types.py b/src/agentcat/types.py index 7d02dd7..fbeaffd 100644 --- a/src/agentcat/types.py +++ b/src/agentcat/types.py @@ -27,7 +27,15 @@ # # `event_tags`, `event_properties` and `resolve_session_id` all receive this same # pair — see EventTagsFunction / EventPropertiesFunction / ResolveSessionIdFunction. -IdentifyFunction = Callable[[Any, Any], Optional["UserIdentity"]] +# +# Accepts sync or async callables (mirrors RedactionFunction). This alias was the +# last of the five to say so: `resolve_identity` used to call the hook and take +# its return value verbatim, so an `async def` hook silently produced an +# anonymous event. `modules/hooks.py` now defines that contract for all of them. +IdentifyFunction = Callable[ + [Any, Any], + Optional["UserIdentity"] | Awaitable[Optional["UserIdentity"]], +] # Type alias for redaction function RedactionFunction = Callable[[str], str | Awaitable[str]] # Type alias for event_tags callback — returns str:str map attached to every auto-captured event. @@ -188,6 +196,10 @@ class AgentCatOptions: enable_tracing: bool = True enable_tool_call_context: bool = True custom_context_description: str = DEFAULT_CONTEXT_DESCRIPTION + # Callback invoked on every auto-captured event to attribute it to an actor. + # May be sync or async. Receives the `(request, extra)` pair every other hook + # receives. If it raises or returns anything but a UserIdentity, the event + # publishes anonymously rather than failing the tool call. identify: IdentifyFunction | None = None redact_sensitive_information: RedactionFunction | None = None exporters: dict[str, ExporterConfig] | None = None diff --git a/tests/e2e/community_v3/test_agent_handle_http.py b/tests/e2e/community_v3/test_agent_handle_http.py new file mode 100644 index 0000000..7e7dab7 --- /dev/null +++ b/tests/e2e/community_v3/test_agent_handle_http.py @@ -0,0 +1,203 @@ +"""The agent handle over real Streamable HTTP (community FastMCP 3). + +`enable_agent_tracking` is off by default, so every OTHER e2e module in this +tree runs with `agent_id` never injected. This module turns it on for its own +server — the fixture reads `AGENTCAT_OPTIONS_FACTORY` per module — and it is a +separate file rather than a flag flipped on a shared one because `agent_id` is +injected as REQUIRED, which changes the schema every sibling test calls against. + +The strip needs no recorder here: the conftest's `add_todo(text: str)` is a +typed FastMCP tool, and community FastMCP — unlike both official tool managers +— raises on an argument the signature never declared. A handle that survived to +the tool body fails the call. + +Every `fastmcp` import is inside a test body, as in the rest of this tree: a +module-scope import fails at COLLECTION on the no-fastmcp matrix legs, which no +conftest gate downstream of it can rescue. +""" + +from __future__ import annotations + +import time + +import pytest + +from agentcat import AgentCatOptions +from agentcat.modules.constants import ( + AGENT_ID_PARAM, + AGENTCAT_TAG_AGENT_ID, + AGENTCAT_TAG_AGENT_SOURCE, + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, + SESSION_ID_PARAM, +) + +pytestmark = pytest.mark.e2e + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." +AGENT = "opus-4.80-1m|claude-code|k3n9x" + + +def _agent_tracking_options() -> AgentCatOptions: + return AgentCatOptions(enable_tracing=True, enable_agent_tracking=True) + + +AGENTCAT_OPTIONS_FACTORY = _agent_tracking_options + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +@pytest.mark.asyncio +async def test_the_agent_handle_survives_the_wire(v3_http_server, capture_queue): + """Listing with agent tracking on: the schema the agent is handed. + + Property order is the contract (`modules/injection.py` §"Resulting property + order"), and `agent_id` is required where `session_id` is not — omission is + the minting signal for one and nothing for the other. + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v3_http_server + async with Client(StreamableHttpTransport(url)) as client: + listed = await client.list_tools() + + add = next(t for t in listed if t.name == "add_todo") + assert list(add.inputSchema["properties"])[-3:] == [ + SESSION_ID_PARAM, + AGENT_ID_PARAM, + "context", + ] + assert AGENT_ID_PARAM in add.inputSchema["required"] + assert SESSION_ID_PARAM not in add.inputSchema["required"] + assert MCP_INSTRUCTIONS_KEY in add.outputSchema["properties"] + + +@pytest.mark.asyncio +async def test_a_supplied_agent_handle_tags_the_event(v3_http_server, capture_queue): + """The handle rides the event as a tag and never reaches the tool.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v3_http_server + async with Client(StreamableHttpTransport(url)) as client: + result = await client.call_tool( + "add_todo", + {"text": "with agent", AGENT_ID_PARAM: AGENT, "context": "why"}, + ) + # The typed tool raises on any argument but `text`, so a surviving + # handle fails here rather than passing silently. + text = _text(result) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + mirror = result.structured_content[MCP_INSTRUCTIONS_KEY] + assert mirror[SESSION_ID_PARAM] == minted + assert mirror[AGENT_ID_PARAM] == AGENT + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert event.tags[AGENTCAT_TAG_AGENT_ID] == AGENT + assert event.tags[AGENTCAT_TAG_AGENT_SOURCE] == "supplied" + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + assert event.parameters["arguments"][AGENT_ID_PARAM] == AGENT + + +@pytest.mark.asyncio +async def test_both_handles_echo_across_calls(v3_http_server, capture_queue): + """The agent echoes session and agent handle together on the next call. + + The two are independent: the session is confirmed rather than re-minted, + while `agent_id` is `supplied` on both calls — the server never issues one, + so it has no `minted` state to pass through. + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v3_http_server + async with Client(StreamableHttpTransport(url)) as client: + first = await client.call_tool( + "add_todo", {"text": "one", AGENT_ID_PARAM: AGENT, "context": "start"} + ) + minted = _text(first).split("session_id=")[1].split(" ")[0] + + second = await client.call_tool( + "add_todo", + {"text": "two", SESSION_ID_PARAM: minted, AGENT_ID_PARAM: AGENT}, + ) + assert MINT_BACK_HEADER not in _text(second) + assert second.structured_content[MCP_INSTRUCTIONS_KEY][AGENT_ID_PARAM] == AGENT + + time.sleep(0.5) + events = _call_events(capture_queue)[-2:] + assert [e.session_id for e in events] == [minted, minted] + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == [ + "minted", + "supplied", + ] + assert [e.tags[AGENTCAT_TAG_AGENT_ID] for e in events] == [AGENT, AGENT] + assert [e.tags[AGENTCAT_TAG_AGENT_SOURCE] for e in events] == [ + "supplied", + "supplied", + ] + + +@pytest.mark.asyncio +async def test_omitting_the_required_agent_handle_degrades_to_absence( + v3_http_server, capture_queue +): + """`required` is advisory: nothing enforces it, and nothing may break. + + AgentCat strips the handles in middleware, before the tool's own argument + validation, so an agent that ignores the `required` marker is served + normally. The event is then simply agent-less: an absent handle must never + become an empty or invented tag, because a customer filtering on + `agentcat_agent_id` has to be able to tell "no agent told us" from "this + agent". + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v3_http_server + async with Client(StreamableHttpTransport(url)) as client: + result = await client.call_tool("add_todo", {"text": "no agent"}) + assert MINT_BACK_HEADER in _text(result) + assert AGENT_ID_PARAM not in result.structured_content[MCP_INSTRUCTIONS_KEY] + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert AGENTCAT_TAG_AGENT_ID not in event.tags + assert AGENTCAT_TAG_AGENT_SOURCE not in event.tags + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + + +@pytest.mark.asyncio +async def test_a_blank_agent_handle_is_a_miss_not_an_empty_tag( + v3_http_server, capture_queue +): + """`extract_handle` trims and rejects, over the wire. + + A whitespace-only value must leave the event with NO agent tags — an + `agentcat_agent_id: ""` would key every such call to one phantom agent + downstream, which is worse than the absence it stands in for. + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v3_http_server + async with Client(StreamableHttpTransport(url)) as client: + await client.call_tool( + "add_todo", {"text": "blank", AGENT_ID_PARAM: " ", "context": "x"} + ) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert AGENTCAT_TAG_AGENT_ID not in event.tags + assert AGENTCAT_TAG_AGENT_SOURCE not in event.tags + # The session handle is unaffected: suppression is per handle. + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" diff --git a/tests/e2e/community_v3/test_event_capture_http.py b/tests/e2e/community_v3/test_event_capture_http.py index 0321a13..a86c714 100644 --- a/tests/e2e/community_v3/test_event_capture_http.py +++ b/tests/e2e/community_v3/test_event_capture_http.py @@ -88,16 +88,65 @@ async def test_v3_event_duration_is_non_negative(v3_http_server, capture_queue): @pytest.mark.asyncio async def test_client_identity_reaches_the_event(v3_http_server, capture_queue): - """The handshake clientInfo is the last rung of the identity ladder, and it - reaches the tools/call event over a real connection.""" + """Name AND version reach the tools/call event over a real connection. + + The handshake capture is the last rung of the identity ladder and the only + one this era can use. Asserted against a `client_info` this test supplies + rather than against "some name resolved": the SDK's own default satisfies a + truthiness check while proving nothing about what the ladder read, and + `client_version` is null-by-default, so a rung that dropped it would go + unnoticed by a name-only assertion. + """ from fastmcp import Client from fastmcp.client.transports import StreamableHttpTransport + from mcp.types import Implementation url, _ = v3_http_server - async with Client(StreamableHttpTransport(url)) as client: + async with Client( + StreamableHttpTransport(url), + client_info=Implementation(name="MyAgent", version="1.2.3"), + ) as client: await client.call_tool("add_todo", {"text": "who", "context": "x"}) time.sleep(0.5) call_events = [e for e in capture_queue if e.event_type == "mcp:tools/call"] assert call_events - assert call_events[-1].client_name, "no client name resolved for the call" + event = call_events[-1] + assert (event.client_name, event.client_version) == ("MyAgent", "1.2.3") + + +@pytest.mark.asyncio +async def test_identity_rides_every_call_not_just_the_first( + v3_http_server, capture_queue +): + """Name AND version on EVERY event of a connection. + + Reading only the last event cannot tell "resolved per request" from + "resolved once and reused", and the two differ exactly where it matters: a + rung that answers only for the call following the handshake leaves every + later event of a long-lived connection anonymous. This is a STATEFUL app, + so the connection whose handshake was captured is still there for all three + calls — the rung has to answer more than once. + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + from mcp.types import Implementation + + url, _ = v3_http_server + async with Client( + StreamableHttpTransport(url), + client_info=Implementation(name="Cursor", version="2.6.22"), + ) as client: + for n in range(3): + await client.call_tool("add_todo", {"text": f"call-{n}", "context": "id"}) + + time.sleep(0.5) + events = [e for e in capture_queue if e.event_type == "mcp:tools/call"][-3:] + assert [e.parameters["arguments"]["text"] for e in events] == [ + "call-0", + "call-1", + "call-2", + ] + assert [(e.client_name, e.client_version) for e in events] == [ + ("Cursor", "2.6.22") + ] * 3 diff --git a/tests/e2e/community_v3/test_identify_http.py b/tests/e2e/community_v3/test_identify_http.py index dfd7a61..0403768 100644 --- a/tests/e2e/community_v3/test_identify_http.py +++ b/tests/e2e/community_v3/test_identify_http.py @@ -34,24 +34,47 @@ def _last_call(capture_queue): async def test_identify_hook_runs_under_the_community_adapter( v3_http_server, capture_queue ): + """`extra` carries the live HTTP request, not a placeholder. + + The header read below is verbatim the idiom the README documents for + `resolve_session_id` ("receives the same `(request, extra)` pair as + `identify`") — keying off a header the customer's gateway set. Only a + socket can prove it: the in-process client has no HTTP request at all, so + `extra.request` is None there and the assertion would be vacuous. + + Recorded rather than asserted in place: `resolve_identity` swallows every + exception the hook raises, so an assertion inside it would surface as a + silently anonymous event instead of a failure. + """ from fastmcp import Client from fastmcp.client.transports import StreamableHttpTransport url, server = v3_http_server seen: list = [] - def identify(_req: Any, extra: Any) -> UserIdentity | None: - seen.append(extra) - return UserIdentity(user_id="v3-user", user_name=None, user_data=None) + def identify(request: Any, extra: Any) -> UserIdentity | None: + headers = getattr(getattr(extra, "request", None), "headers", {}) or {} + seen.append((getattr(request, "name", None), headers.get("x-tenant"))) + return UserIdentity( + user_id="v3-user", user_name="V3 User", user_data={"plan": "pro"} + ) _set_identify(server, identify) try: - async with Client(StreamableHttpTransport(url)) as client: + async with Client( + StreamableHttpTransport(url, headers={"X-Tenant": "acme"}) + ) as client: await client.call_tool("add_todo", {"text": "id-v3", "context": "id"}) time.sleep(0.5) - assert _last_call(capture_queue).identify_actor_given_id == "v3-user" - assert seen, "identify hook never invoked under the community adapter" + assert seen == [("add_todo", "acme")], seen + event = _last_call(capture_queue) + # All three fields, not just the id: `user_name` and `user_data` are + # what a customer segments and displays by, and each lands in a + # differently-named event field. + assert event.identify_actor_given_id == "v3-user" + assert event.identify_actor_name == "V3 User" + assert event.identify_data == {"plan": "pro"} finally: _set_identify(server, None) @@ -82,6 +105,62 @@ def identify(_req: Any, _extra: Any) -> UserIdentity | None: _set_identify(server, None) +@pytest.mark.asyncio +async def test_identity_is_resolved_per_call_never_cached( + v3_http_server, capture_queue +): + """The hook runs on EVERY call, so consecutive calls on one connection can + return different actors — v1 cached the result for the connection's life + and could not express this.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, server = v3_http_server + counter = {"n": 0} + + def identify(_req: Any, _extra: Any) -> UserIdentity | None: + counter["n"] += 1 + return UserIdentity( + user_id=f"user-{counter['n']}", user_name=None, user_data=None + ) + + _set_identify(server, identify) + try: + async with Client(StreamableHttpTransport(url)) as client: + await client.call_tool("add_todo", {"text": "first", "context": "x"}) + await client.call_tool("add_todo", {"text": "second", "context": "x"}) + + time.sleep(0.5) + events = [e for e in capture_queue if e.event_type == "mcp:tools/call"][-2:] + assert counter["n"] == 2, "the hook did not run once per call" + assert [e.identify_actor_given_id for e in events] == ["user-1", "user-2"] + finally: + _set_identify(server, None) + + +@pytest.mark.asyncio +async def test_returning_none_yields_an_anonymous_event(v3_http_server, capture_queue): + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, server = v3_http_server + + def identify(_req: Any, _extra: Any) -> UserIdentity | None: + return None + + _set_identify(server, identify) + try: + async with Client(StreamableHttpTransport(url)) as client: + await client.call_tool("add_todo", {"text": "none", "context": "x"}) + + time.sleep(0.5) + event = _last_call(capture_queue) + assert event.identify_actor_given_id is None + assert event.identify_actor_name is None + finally: + _set_identify(server, None) + + @pytest.mark.asyncio async def test_identify_exception_does_not_break_the_tool_call( v3_http_server, capture_queue diff --git a/tests/e2e/community_v3/test_stateless_http.py b/tests/e2e/community_v3/test_stateless_http.py index ec5a146..685652b 100644 --- a/tests/e2e/community_v3/test_stateless_http.py +++ b/tests/e2e/community_v3/test_stateless_http.py @@ -86,5 +86,14 @@ async def call_as(name: str, version: str, text: str) -> None: attributed = {e.parameters["arguments"]["text"]: e.client_name for e in call_events} # No name at all is the honest answer for a connection that is already # gone; SOMEONE ELSE's name never is. + # + # The tolerance is deliberate and specific to THIS era. FastMCP 3 speaks the + # pre-2026 wire, where `clientInfo` travels once, in `initialize` — so the + # per-connection capture is the only rung that can answer, and a stateless + # server has already discarded the connection that made it. Absence is + # unknowable here, not a defect. FastMCP 4 re-stamps identity into `_meta` + # on every request, so its sibling + # (`tests/e2e/community_v4/test_stateless_http.py`) asserts exact name and + # version. Do not loosen that one to match this. assert attributed["from-cursor"] in (None, "Cursor"), attributed assert attributed["from-claude"] in (None, "Claude"), attributed diff --git a/tests/e2e/community_v4/test_agent_handle_http.py b/tests/e2e/community_v4/test_agent_handle_http.py new file mode 100644 index 0000000..898b3a6 --- /dev/null +++ b/tests/e2e/community_v4/test_agent_handle_http.py @@ -0,0 +1,202 @@ +"""The agent handle over real Streamable HTTP (community FastMCP 4). + +`enable_agent_tracking` is off by default, so every OTHER e2e module in this +tree runs with `agent_id` never injected. This module turns it on for its own +server — the fixture reads `AGENTCAT_OPTIONS_FACTORY` per module — and it is a +separate file rather than a flag flipped on a shared one because `agent_id` is +injected as REQUIRED, which changes the schema every sibling test calls against. + +The strip needs no recorder here: the conftest's `add_todo(text: str)` is a +typed FastMCP tool, and community FastMCP — unlike both official tool managers +— raises on an argument the signature never declared. A handle that survived to +the tool body fails the call. + +Every `fastmcp` import is inside a test body, as in the rest of this tree: a +module-scope import fails at COLLECTION on the no-fastmcp matrix legs, which no +conftest gate downstream of it can rescue. +""" + +from __future__ import annotations + +import time + +import pytest + +from agentcat import AgentCatOptions +from agentcat.modules.constants import ( + AGENT_ID_PARAM, + AGENTCAT_TAG_AGENT_ID, + AGENTCAT_TAG_AGENT_SOURCE, + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, + SESSION_ID_PARAM, +) + +pytestmark = pytest.mark.e2e + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." +AGENT = "opus-4.80-1m|claude-code|k3n9x" + + +def _agent_tracking_options() -> AgentCatOptions: + return AgentCatOptions(enable_tracing=True, enable_agent_tracking=True) + + +AGENTCAT_OPTIONS_FACTORY = _agent_tracking_options + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +async def test_the_agent_handle_survives_the_wire(v4_http_server, capture_queue): + """Listing with agent tracking on: the schema the agent is handed. + + FastMCP validates its own outbound results, so a schema that is malformed + once `agent_id` joins `session_id` and `context` fails server-side here + rather than reaching the agent. Property order is the contract + (`modules/injection.py` §"Resulting property order"), and `agent_id` is + required where `session_id` is not — omission is the minting signal for one + and nothing for the other. + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v4_http_server + async with Client(StreamableHttpTransport(url)) as client: + listed = await client.list_tools() + + add = next(t for t in listed if t.name == "add_todo") + assert list(add.input_schema["properties"]) == [ + "text", + SESSION_ID_PARAM, + AGENT_ID_PARAM, + "context", + ] + assert AGENT_ID_PARAM in add.input_schema["required"] + assert SESSION_ID_PARAM not in add.input_schema["required"] + assert MCP_INSTRUCTIONS_KEY in add.output_schema["properties"] + + +async def test_a_supplied_agent_handle_tags_the_event(v4_http_server, capture_queue): + """The handle rides the event as a tag and never reaches the tool.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v4_http_server + async with Client(StreamableHttpTransport(url)) as client: + result = await client.call_tool( + "add_todo", + {"text": "with agent", AGENT_ID_PARAM: AGENT, "context": "why"}, + ) + # The typed tool raises on any argument but `text`, so a surviving + # handle fails here rather than passing silently. + text = _text(result) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + mirror = result.structured_content[MCP_INSTRUCTIONS_KEY] + assert mirror[SESSION_ID_PARAM] == minted + assert mirror[AGENT_ID_PARAM] == AGENT + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert event.tags[AGENTCAT_TAG_AGENT_ID] == AGENT + assert event.tags[AGENTCAT_TAG_AGENT_SOURCE] == "supplied" + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + assert event.parameters["arguments"][AGENT_ID_PARAM] == AGENT + + +async def test_both_handles_echo_across_calls(v4_http_server, capture_queue): + """The agent echoes session and agent handle together on the next call. + + The two are independent: the session is confirmed rather than re-minted, + while `agent_id` is `supplied` on both calls — the server never issues one, + so it has no `minted` state to pass through. + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v4_http_server + async with Client(StreamableHttpTransport(url)) as client: + first = await client.call_tool( + "add_todo", {"text": "one", AGENT_ID_PARAM: AGENT, "context": "start"} + ) + minted = _text(first).split("session_id=")[1].split(" ")[0] + + second = await client.call_tool( + "add_todo", + {"text": "two", SESSION_ID_PARAM: minted, AGENT_ID_PARAM: AGENT}, + ) + assert MINT_BACK_HEADER not in _text(second) + assert second.structured_content[MCP_INSTRUCTIONS_KEY][AGENT_ID_PARAM] == AGENT + + time.sleep(0.5) + events = _call_events(capture_queue)[-2:] + assert [e.session_id for e in events] == [minted, minted] + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == [ + "minted", + "supplied", + ] + assert [e.tags[AGENTCAT_TAG_AGENT_ID] for e in events] == [AGENT, AGENT] + assert [e.tags[AGENTCAT_TAG_AGENT_SOURCE] for e in events] == [ + "supplied", + "supplied", + ] + + +async def test_omitting_the_required_agent_handle_degrades_to_absence( + v4_http_server, capture_queue +): + """`required` is advisory: nothing enforces it, and nothing may break. + + AgentCat strips the handles in middleware, before the tool's own argument + validation, so an agent that ignores the `required` marker is served + normally. The event is then simply agent-less: an absent handle must never + become an empty or invented tag, because a customer filtering on + `agentcat_agent_id` has to be able to tell "no agent told us" from "this + agent". + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v4_http_server + async with Client(StreamableHttpTransport(url)) as client: + result = await client.call_tool("add_todo", {"text": "no agent"}) + assert MINT_BACK_HEADER in _text(result) + assert AGENT_ID_PARAM not in result.structured_content[MCP_INSTRUCTIONS_KEY] + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert AGENTCAT_TAG_AGENT_ID not in event.tags + assert AGENTCAT_TAG_AGENT_SOURCE not in event.tags + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + + +async def test_a_blank_agent_handle_is_a_miss_not_an_empty_tag( + v4_http_server, capture_queue +): + """`extract_handle` trims and rejects, over the wire. + + A whitespace-only value must leave the event with NO agent tags — an + `agentcat_agent_id: ""` would key every such call to one phantom agent + downstream, which is worse than the absence it stands in for. + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, _ = v4_http_server + async with Client(StreamableHttpTransport(url)) as client: + await client.call_tool( + "add_todo", {"text": "blank", AGENT_ID_PARAM: " ", "context": "x"} + ) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert AGENTCAT_TAG_AGENT_ID not in event.tags + assert AGENTCAT_TAG_AGENT_SOURCE not in event.tags + # The session handle is unaffected: suppression is per handle. + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" diff --git a/tests/e2e/community_v4/test_identify_http.py b/tests/e2e/community_v4/test_identify_http.py new file mode 100644 index 0000000..4dbbe51 --- /dev/null +++ b/tests/e2e/community_v4/test_identify_http.py @@ -0,0 +1,199 @@ +"""Identify-per-event behavior over real Streamable HTTP (community FastMCP 4). + +v2 has no standalone `agentcat:identify` event: the hook runs per tool call and +its result is stamped onto that call's event. + +Tests mutate the running server's `AgentCatData.options.identify` to vary the +hook per scenario, rather than declaring an options factory — the middleware +re-reads the server's tracking data every request, so swapping the hook on the +live server costs no second uvicorn boot. Each test resets it in `finally` so +the next one starts clean. + +Every `fastmcp` / `httpx2` import is inside a test body, as in the rest of this +tree: a module-scope import fails at COLLECTION on the no-fastmcp matrix legs, +which no conftest gate downstream of it can rescue. +""" + +from __future__ import annotations + +import time +from typing import Any + +import pytest + +from agentcat.modules.internal import get_server_tracking_data +from agentcat.types import UserIdentity + +pytestmark = pytest.mark.e2e + + +def _set_identify(server, fn) -> None: + data = get_server_tracking_data(server) + assert data is not None + data.options.identify = fn + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +async def test_the_hook_reads_the_real_http_request(v4_http_server, capture_queue): + """`extra` carries the live HTTP request, not a placeholder. + + The hook's second argument is the SDK's `RequestContext`, and the header + read below is verbatim the idiom the README documents for + `resolve_session_id` ("receives the same `(request, extra)` pair as + `identify`") — keying off a header the customer's gateway set. Only a + socket can prove it: the in-process client has no HTTP request at all, so + `extra.request` is None there and the assertion would be vacuous. + + `request` is the tool call's PARAMS on every flavor, which the same + assertion pins from the other side. + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, server = v4_http_server + # Recorded rather than asserted in place: `resolve_identity` swallows every + # exception the hook raises, so an assertion inside it would surface as a + # silently anonymous event instead of a failure. + seen: list[tuple[str, str | None]] = [] + + def identify(request: Any, extra: Any) -> UserIdentity | None: + headers = getattr(getattr(extra, "request", None), "headers", {}) or {} + tenant = headers.get("x-tenant") + seen.append((getattr(request, "name", None), tenant)) + return UserIdentity(user_id=f"tenant:{tenant}", user_name=None, user_data=None) + + _set_identify(server, identify) + try: + async with Client( + StreamableHttpTransport(url, headers={"X-Tenant": "acme"}) + ) as client: + await client.call_tool("add_todo", {"text": "tenant", "context": "id"}) + + time.sleep(0.5) + assert seen == [("add_todo", "acme")], seen + assert _call_events(capture_queue)[-1].identify_actor_given_id == "tenant:acme" + finally: + _set_identify(server, None) + + +async def test_the_actor_rides_the_tool_call_event_not_a_self_event( + v4_http_server, capture_queue +): + """v2 stamps the actor onto every tools/call event; the standalone + `agentcat:identify` event is gone.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, server = v4_http_server + + def identify(_request: Any, _extra: Any) -> UserIdentity | None: + return UserIdentity( + user_id="bob", + user_name="Bob Bobson", + user_data={"plan": "enterprise"}, + ) + + _set_identify(server, identify) + try: + async with Client(StreamableHttpTransport(url)) as client: + await client.call_tool("add_todo", {"text": "self", "context": "x"}) + + time.sleep(0.5) + assert {e.event_type for e in capture_queue} == {"mcp:tools/call"} + event = _call_events(capture_queue)[-1] + # All three fields, not just the id: `user_name` and `user_data` are + # what a customer segments and displays by, and each lands in a + # differently-named event field. + assert event.identify_actor_given_id == "bob" + assert event.identify_actor_name == "Bob Bobson" + assert event.identify_data == {"plan": "enterprise"} + finally: + _set_identify(server, None) + + +async def test_identity_is_resolved_per_call_never_cached( + v4_http_server, capture_queue +): + """The hook runs on EVERY call, so consecutive calls on one connection can + return different actors — v1 cached the result for the connection's life + and could not express this.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, server = v4_http_server + counter = {"n": 0} + + def identify(_request: Any, _extra: Any) -> UserIdentity | None: + counter["n"] += 1 + return UserIdentity( + user_id=f"user-{counter['n']}", user_name=None, user_data=None + ) + + _set_identify(server, identify) + try: + async with Client(StreamableHttpTransport(url)) as client: + await client.call_tool("add_todo", {"text": "first", "context": "x"}) + await client.call_tool("add_todo", {"text": "second", "context": "x"}) + + time.sleep(0.5) + events = _call_events(capture_queue)[-2:] + assert counter["n"] == 2, "the hook did not run once per call" + assert [e.identify_actor_given_id for e in events] == ["user-1", "user-2"] + finally: + _set_identify(server, None) + + +async def test_returning_none_yields_an_anonymous_event(v4_http_server, capture_queue): + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, server = v4_http_server + + def identify(_request: Any, _extra: Any) -> UserIdentity | None: + return None + + _set_identify(server, identify) + try: + async with Client(StreamableHttpTransport(url)) as client: + await client.call_tool("add_todo", {"text": "none", "context": "x"}) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert event.identify_actor_given_id is None + assert event.identify_actor_name is None + finally: + _set_identify(server, None) + + +async def test_a_raising_hook_does_not_break_the_call(v4_http_server, capture_queue): + """A customer hook that blows up yields an anonymous call, not a failed one + — and not a dropped event either.""" + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + + url, server = v4_http_server + + def identify(_request: Any, _extra: Any) -> UserIdentity | None: + raise RuntimeError("identify exploded") + + _set_identify(server, identify) + try: + async with Client(StreamableHttpTransport(url)) as client: + result = await client.call_tool( + "add_todo", {"text": "boom", "context": "x"} + ) + assert "Added todo" in _text(result) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert event.parameters["arguments"]["text"] == "boom" + assert event.identify_actor_given_id is None + finally: + _set_identify(server, None) diff --git a/tests/e2e/community_v4/test_session_http.py b/tests/e2e/community_v4/test_session_http.py index b269fb1..9107e08 100644 --- a/tests/e2e/community_v4/test_session_http.py +++ b/tests/e2e/community_v4/test_session_http.py @@ -92,17 +92,63 @@ async def test_task_handle_is_minted_then_echoed(v4_http_server, capture_queue): async def test_client_identity_reaches_the_event(v4_http_server, capture_queue): - """The handshake clientInfo is the last rung of the identity ladder, and it - reaches the tools/call event over a real connection.""" + """Name AND version reach the event over a real connection. + + Asserted against a `client_info` this test supplies rather than against + "some name resolved": the SDK's own default satisfies a truthiness check + while proving nothing about what the ladder actually read, and + `client_version` is null-by-default, so a rung that dropped it would go + unnoticed by a name-only assertion. + """ from fastmcp import Client from fastmcp.client.transports import StreamableHttpTransport + from mcp.types import Implementation url, _ = v4_http_server - async with Client(StreamableHttpTransport(url)) as client: + async with Client( + StreamableHttpTransport(url), + client_info=Implementation(name="MyAgent", version="1.2.3"), + ) as client: await client.call_tool("add_todo", {"text": "who", "context": "x"}) time.sleep(0.5) - assert _call_events(capture_queue)[-1].client_name + event = _call_events(capture_queue)[-1] + assert (event.client_name, event.client_version) == ("MyAgent", "1.2.3") + + +async def test_identity_rides_every_call_not_just_the_first( + v4_http_server, capture_queue +): + """Name AND version on EVERY event of a connection. + + Reading only the last event cannot tell "resolved per request" from + "resolved once and reused", and the two differ exactly where it matters: a + rung that answers only for the call following the handshake leaves every + later event of a long-lived connection anonymous. Three calls, three + identities. + """ + from fastmcp import Client + from fastmcp.client.transports import StreamableHttpTransport + from mcp.types import Implementation + + url, _ = v4_http_server + async with Client( + StreamableHttpTransport(url), + client_info=Implementation(name="Cursor", version="2.6.22"), + ) as client: + for n in range(3): + await client.call_tool("add_todo", {"text": f"call-{n}", "context": "id"}) + + time.sleep(0.5) + events = _call_events(capture_queue)[-3:] + assert [e.parameters["arguments"]["text"] for e in events] == [ + "call-0", + "call-1", + "call-2", + ] + assert [(e.client_name, e.client_version) for e in events] == [ + ("Cursor", "2.6.22") + ] * 3 async def test_a_malformed_tools_call_keeps_its_own_protocol_error( diff --git a/tests/e2e/community_v4/test_stateless_http.py b/tests/e2e/community_v4/test_stateless_http.py index ccd836d..a81af17 100644 --- a/tests/e2e/community_v4/test_stateless_http.py +++ b/tests/e2e/community_v4/test_stateless_http.py @@ -88,5 +88,15 @@ async def call_as(name: str, version: str, text: str) -> None: events = _call_events(capture_queue) assert len(events) == 2 - attributed = {e.parameters["arguments"]["text"]: e.client_name for e in events} - assert attributed == {"from-cursor": "Cursor", "from-claude": "Claude"} + # Version as well as name: they travel together on every rung of the + # ladder, and a rung that answered with half an identity would satisfy a + # name-only check while leaving `client_version` silently null on every + # event a customer segments by. + attributed = { + e.parameters["arguments"]["text"]: (e.client_name, e.client_version) + for e in events + } + assert attributed == { + "from-cursor": ("Cursor", "2.6.22"), + "from-claude": ("Claude", "1.0.0"), + } diff --git a/tests/e2e/official/test_agent_handle_http.py b/tests/e2e/official/test_agent_handle_http.py new file mode 100644 index 0000000..78b2ee1 --- /dev/null +++ b/tests/e2e/official/test_agent_handle_http.py @@ -0,0 +1,237 @@ +"""The agent handle over real Streamable HTTP (official MCP SDK 1.x). + +`enable_agent_tracking` is off by default, so every OTHER e2e module in this +tree runs with `agent_id` never injected. This module turns it on for its own +server — the fixture reads `AGENTCAT_OPTIONS_FACTORY` per module — and it is a +separate file rather than a flag flipped on a shared one because `agent_id` is +injected as REQUIRED, which changes the schema every sibling test calls against. + +The strip is read at the TOOL MANAGER (`tests.test_utils.delivery`), never from +the tool's own result: this SDK's manager DROPS an argument the signature does +not name without complaint, so a test that sends `agent_id` and asserts "no +error" passes identically with the strip disabled. + +Structured output is gated: `Tool.outputSchema` and `structuredContent` arrive +in mcp 1.10, and this tree runs as far back as 1.9.2. Below it AgentCat mirrors +nothing, because there is no field to mirror into. +""" + +from __future__ import annotations + +import time + +import pytest +from mcp import ClientSession +from mcp.client.streamable_http import streamablehttp_client + +from agentcat import AgentCatOptions +from agentcat.modules.constants import ( + AGENT_ID_PARAM, + AGENTCAT_TAG_AGENT_ID, + AGENTCAT_TAG_AGENT_SOURCE, + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, + SESSION_ID_PARAM, +) +from tests.test_utils import NEEDS_STRUCTURED_OUTPUT +from tests.test_utils.delivery import delivered_arguments_for + +pytestmark = pytest.mark.e2e + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." +AGENT = "opus-4.80-1m|claude-code|k3n9x" + + +def _agent_tracking_options() -> AgentCatOptions: + return AgentCatOptions(enable_tracing=True, enable_agent_tracking=True) + + +AGENTCAT_OPTIONS_FACTORY = _agent_tracking_options + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +@pytest.mark.asyncio +async def test_the_agent_handle_survives_the_wire(official_http_server, capture_queue): + """Listing with agent tracking on: the schema the agent is handed. + + Property order is the contract (`modules/injection.py` §"Resulting property + order"), and `agent_id` is required where `session_id` is not — omission is + the minting signal for one and nothing for the other. + """ + url, _ = official_http_server + async with streamablehttp_client(url) as (read, write, _): + async with ClientSession(read, write) as client: + await client.initialize() + listed = await client.list_tools() + + add = next(t for t in listed.tools if t.name == "add_todo") + assert list(add.inputSchema["properties"])[-3:] == [ + SESSION_ID_PARAM, + AGENT_ID_PARAM, + "context", + ] + assert AGENT_ID_PARAM in add.inputSchema["required"] + assert SESSION_ID_PARAM not in add.inputSchema["required"] + + +@pytest.mark.asyncio +async def test_a_supplied_agent_handle_tags_the_event( + official_http_server, capture_queue +): + """The handle rides the event as a tag and never reaches the tool.""" + url, server = official_http_server + async with streamablehttp_client(url) as (read, write, _): + async with ClientSession(read, write) as client: + await client.initialize() + result = await client.call_tool( + "add_todo", + {"text": "with agent", AGENT_ID_PARAM: AGENT, "context": "why"}, + ) + assert result.isError is False, _text(result) + assert MINT_BACK_HEADER in _text(result) + + # The tool layer never saw the handles — the only observation on this shape + # that a broken strip would fail. The server runs in-process (uvicorn in a + # thread), so its recorder is readable straight off the fixture's object. + assert delivered_arguments_for(server, "add_todo")[-1] == {"text": "with agent"} + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert event.tags[AGENTCAT_TAG_AGENT_ID] == AGENT + assert event.tags[AGENTCAT_TAG_AGENT_SOURCE] == "supplied" + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + # The event records the call as the agent made it: handles included. + assert event.parameters["arguments"][AGENT_ID_PARAM] == AGENT + + +@pytest.mark.asyncio +async def test_both_handles_echo_across_calls(official_http_server, capture_queue): + """The agent echoes session and agent handle together on the next call. + + The two are independent: the session is confirmed rather than re-minted, + while `agent_id` is `supplied` on both calls — the server never issues one, + so it has no `minted` state to pass through. + """ + url, _ = official_http_server + async with streamablehttp_client(url) as (read, write, _): + async with ClientSession(read, write) as client: + await client.initialize() + first = await client.call_tool( + "add_todo", {"text": "one", AGENT_ID_PARAM: AGENT, "context": "start"} + ) + minted = _text(first).split("session_id=")[1].split(" ")[0] + + second = await client.call_tool( + "add_todo", + {"text": "two", SESSION_ID_PARAM: minted, AGENT_ID_PARAM: AGENT}, + ) + assert second.isError is False, _text(second) + assert MINT_BACK_HEADER not in _text(second) + + time.sleep(0.5) + events = _call_events(capture_queue)[-2:] + assert [e.session_id for e in events] == [minted, minted] + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == [ + "minted", + "supplied", + ] + assert [e.tags[AGENTCAT_TAG_AGENT_ID] for e in events] == [AGENT, AGENT] + assert [e.tags[AGENTCAT_TAG_AGENT_SOURCE] for e in events] == [ + "supplied", + "supplied", + ] + + +@pytest.mark.asyncio +async def test_omitting_the_required_agent_handle_degrades_to_absence( + official_http_server, capture_queue +): + """`required` is advisory: nothing enforces it, and nothing may break. + + The injected schema is what `tools/list` advertises, but AgentCat strips the + handles at the request-handler seam BEFORE any argument validation the tool + layer would do, so an agent that ignores the `required` marker is served + normally. The event is then simply agent-less: an absent handle must never + become an empty or invented tag, because a customer filtering on + `agentcat_agent_id` has to be able to tell "no agent told us" from "this + agent". + """ + url, _ = official_http_server + async with streamablehttp_client(url) as (read, write, _): + async with ClientSession(read, write) as client: + await client.initialize() + result = await client.call_tool("add_todo", {"text": "no agent"}) + assert result.isError is False, _text(result) + assert MINT_BACK_HEADER in _text(result) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert AGENTCAT_TAG_AGENT_ID not in event.tags + assert AGENTCAT_TAG_AGENT_SOURCE not in event.tags + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + + +@pytest.mark.asyncio +async def test_a_blank_agent_handle_is_a_miss_not_an_empty_tag( + official_http_server, capture_queue +): + """`extract_handle` trims and rejects, over the wire. + + A whitespace-only value must leave the event with NO agent tags — an + `agentcat_agent_id: ""` would key every such call to one phantom agent + downstream, which is worse than the absence it stands in for. + """ + url, _ = official_http_server + async with streamablehttp_client(url) as (read, write, _): + async with ClientSession(read, write) as client: + await client.initialize() + result = await client.call_tool( + "add_todo", {"text": "blank", AGENT_ID_PARAM: " ", "context": "x"} + ) + assert result.isError is False, _text(result) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert AGENTCAT_TAG_AGENT_ID not in event.tags + assert AGENTCAT_TAG_AGENT_SOURCE not in event.tags + # The session handle is unaffected: suppression is per handle. + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + + +@NEEDS_STRUCTURED_OUTPUT +@pytest.mark.asyncio +async def test_both_handles_are_mirrored_into_structured_content( + official_http_server, capture_queue +): + """The agent can re-read either handle mid-session, over the wire. + + Unlike the mint-back text (announcements only), the structured mirror is + present on every response — and it names BOTH handles, because suppression + is per handle rather than per response. + """ + url, _ = official_http_server + async with streamablehttp_client(url) as (read, write, _): + async with ClientSession(read, write) as client: + await client.initialize() + listed = await client.list_tools() + add = next(t for t in listed.tools if t.name == "add_todo") + assert MCP_INSTRUCTIONS_KEY in add.outputSchema["properties"] + + result = await client.call_tool( + "add_todo", {"text": "mirrored", AGENT_ID_PARAM: AGENT} + ) + mirror = result.structuredContent[MCP_INSTRUCTIONS_KEY] + assert mirror[SESSION_ID_PARAM].startswith("ses_") + assert mirror[AGENT_ID_PARAM] == AGENT + # The customer's own structured payload survives untouched. + assert result.structuredContent["result"].startswith("Added todo") + + time.sleep(0.5) + assert _call_events(capture_queue)[-1].session_id == mirror[SESSION_ID_PARAM] diff --git a/tests/e2e/official/test_identify_http.py b/tests/e2e/official/test_identify_http.py index fd6ee51..c5dd150 100644 --- a/tests/e2e/official/test_identify_http.py +++ b/tests/e2e/official/test_identify_http.py @@ -40,12 +40,27 @@ def _last_call(capture_queue): async def test_identify_hook_receives_real_request_extra( official_http_server, capture_queue ): + """`extra` carries the live HTTP request, not a placeholder. + + The header read below is verbatim the idiom the README documents for + `resolve_session_id` ("receives the same `(request, extra)` pair as + `identify`") — keying off a header the customer's gateway set. Only a + socket can prove it: the in-process client has no HTTP request at all, so + `extra.request` is None there and the assertion would be vacuous. + + Recorded rather than asserted in place: `resolve_identity` swallows every + exception the hook raises, so an assertion inside it would surface as a + silently anonymous event instead of a failure. + """ url, server = official_http_server - received_extras: list = [] + seen: list = [] def identify(request: Any, extra: Any) -> Optional[UserIdentity]: - received_extras.append(extra) - return UserIdentity(user_id="alice", user_name="Alice", user_data=None) + headers = getattr(getattr(extra, "request", None), "headers", {}) or {} + seen.append((getattr(request, "name", None), headers.get("x-identify-hook"))) + return UserIdentity( + user_id="alice", user_name="Alice", user_data={"plan": "pro"} + ) _set_identify(server, identify) try: @@ -59,9 +74,14 @@ def identify(request: Any, extra: Any) -> Optional[UserIdentity]: ) time.sleep(0.5) - assert received_extras, "identify hook never invoked" + assert seen == [("add_todo", "yes")], seen ev = _last_call(capture_queue) + # All three fields, not just the id: `user_name` and `user_data` are + # what a customer segments and displays by, and each lands in a + # differently-named event field. assert ev.identify_actor_given_id == "alice" + assert ev.identify_actor_name == "Alice" + assert ev.identify_data == {"plan": "pro"} finally: _set_identify(server, None) diff --git a/tests/e2e/official/test_session_http.py b/tests/e2e/official/test_session_http.py index 9f7f773..78fdb6b 100644 --- a/tests/e2e/official/test_session_http.py +++ b/tests/e2e/official/test_session_http.py @@ -68,6 +68,44 @@ async def test_default_clientinfo_used_when_unspecified( assert ev.client_name is not None, "expected non-None client_name" +@pytest.mark.asyncio +async def test_identity_rides_every_call_not_just_the_first( + official_http_server, capture_queue +): + """Name AND version on EVERY event of a connection. + + Reading only the last event cannot tell "resolved per request" from + "resolved once and reused", and the two differ exactly where it matters: a + rung that answers only for the call following the handshake leaves every + later event of a long-lived connection anonymous. This is a STATEFUL app, + so the `ServerSession` that captured the handshake is still there for all + three calls — the rung has to answer more than once. + """ + url, _ = official_http_server + async with streamablehttp_client(url) as (read, write, _): + async with ClientSession( + read, + write, + client_info=Implementation(name="Cursor", version="2.6.22"), + ) as client: + await client.initialize() + for n in range(3): + await client.call_tool( + "add_todo", {"text": f"call-{n}", "context": "id"} + ) + + time.sleep(0.5) + events = [e for e in capture_queue if e.event_type == "mcp:tools/call"][-3:] + assert [e.parameters["arguments"]["text"] for e in events] == [ + "call-0", + "call-1", + "call-2", + ] + assert [(e.client_name, e.client_version) for e in events] == [ + ("Cursor", "2.6.22") + ] * 3 + + @pytest.mark.asyncio async def test_clientinfo_with_special_characters( official_http_server, capture_queue diff --git a/tests/e2e/official/test_stateless_http.py b/tests/e2e/official/test_stateless_http.py index 8818730..3765dcb 100644 --- a/tests/e2e/official/test_stateless_http.py +++ b/tests/e2e/official/test_stateless_http.py @@ -88,5 +88,16 @@ async def call_with_client(name: str, version: str, text: str) -> None: attributed = {e.parameters["arguments"]["text"]: e.client_name for e in call_events} # No name at all is the honest answer for a connection that is already # gone; SOMEONE ELSE's name never is. + # + # The tolerance is deliberate and specific to THIS wire. A pre-2026 client + # sends `clientInfo` once, in `initialize`, so the only rung that can answer + # is the session capture — and a stateless server rebuilds the session per + # REQUEST, which means the handshake that carried the name belongs to an + # object that no longer exists by the time the call arrives. Absence there + # is unknowable, not a defect. On the 2026-07-28 wire the client re-stamps + # its identity into `_meta` on every request, so the same scenario IS + # strictly attributable and the modern sibling + # (`tests/e2e/official_modern/test_stateless_http.py`) asserts exact name + # and version. Do not loosen that one to match this. assert attributed["from-cursor"] in (None, "Cursor"), attributed assert attributed["from-claude"] in (None, "Claude"), attributed diff --git a/tests/e2e/official_modern/test_agent_handle_http.py b/tests/e2e/official_modern/test_agent_handle_http.py new file mode 100644 index 0000000..e38853b --- /dev/null +++ b/tests/e2e/official_modern/test_agent_handle_http.py @@ -0,0 +1,198 @@ +"""The agent handle over real Streamable HTTP (modern official SDK). + +`enable_agent_tracking` is off by default, so every OTHER e2e module in this +tree runs with `agent_id` never injected at all. This module turns it on for +its own server — the fixture reads `AGENTCAT_OPTIONS_FACTORY` per module — and +it is deliberately a separate file rather than an option flipped on a shared +one: `agent_id` is injected as REQUIRED, which changes the listed schema every +sibling test calls against. + +What only a socket proves here is the listing. The SDK validates every outbound +spec result against the negotiated protocol surface, so an injected schema that +is malformed once `agent_id` joins `session_id` and `context` fails server-side +rather than reaching the agent. In-process clients on this shape skip that pass. + +The strip needs no recorder on this shape: `create_lowlevel_todo_server`'s +handler calls `_reject_unexpected(arguments, {"text"})`, so a handle that +survived to the tool body fails the call outright. +""" + +from __future__ import annotations + +import time + +import pytest +from mcp.client import Client + +from agentcat import AgentCatOptions +from agentcat.modules.constants import ( + AGENT_ID_PARAM, + AGENTCAT_TAG_AGENT_ID, + AGENTCAT_TAG_AGENT_SOURCE, + AGENTCAT_TAG_SESSION_SOURCE, + MCP_INSTRUCTIONS_KEY, + SESSION_ID_PARAM, +) + +pytestmark = pytest.mark.e2e + +MINT_BACK_HEADER = "[MCP INSTRUCTIONS]: session_id issued." +AGENT = "opus-4.80-1m|claude-code|k3n9x" + + +def _agent_tracking_options() -> AgentCatOptions: + return AgentCatOptions(enable_tracing=True, enable_agent_tracking=True) + + +AGENTCAT_OPTIONS_FACTORY = _agent_tracking_options + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +async def test_the_agent_handle_survives_the_wire(modern_http_server, capture_queue): + """Listing with agent tracking on: the schema the agent is handed. + + Property order is the contract (`modules/injection.py` §"Resulting property + order"), and `agent_id` is required where `session_id` is not — omission is + the minting signal for one and nothing for the other. + """ + url, _ = modern_http_server + async with Client(url) as client: + listed = await client.list_tools() + + add = next(t for t in listed.tools if t.name == "add_todo") + assert list(add.input_schema["properties"]) == [ + "text", + SESSION_ID_PARAM, + AGENT_ID_PARAM, + "context", + ] + assert AGENT_ID_PARAM in add.input_schema["required"] + assert SESSION_ID_PARAM not in add.input_schema["required"] + assert MCP_INSTRUCTIONS_KEY in add.output_schema["properties"] + + +async def test_a_supplied_agent_handle_tags_the_event( + modern_http_server, capture_queue +): + """The handle rides the event as a tag and never reaches the tool.""" + url, _ = modern_http_server + async with Client(url) as client: + result = await client.call_tool( + "add_todo", + {"text": "with agent", AGENT_ID_PARAM: AGENT, "context": "why"}, + ) + # The handler rejects any argument but `text`, so a surviving handle + # fails here rather than passing silently. + assert result.is_error is False, _text(result) + text = _text(result) + assert MINT_BACK_HEADER in text + minted = text.split("session_id=")[1].split(" ")[0] + # Both handles are mirrored, so an agent can re-read either mid-session. + mirror = result.structured_content[MCP_INSTRUCTIONS_KEY] + assert mirror[SESSION_ID_PARAM] == minted + assert mirror[AGENT_ID_PARAM] == AGENT + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert event.tags[AGENTCAT_TAG_AGENT_ID] == AGENT + assert event.tags[AGENTCAT_TAG_AGENT_SOURCE] == "supplied" + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + # The event records the call as the agent made it: handles included. + assert event.parameters["arguments"][AGENT_ID_PARAM] == AGENT + + +async def test_both_handles_echo_across_calls(modern_http_server, capture_queue): + """The agent echoes session and agent handle together on the next call. + + The two are independent: the session is confirmed rather than re-minted, + while `agent_id` is `supplied` on both calls — it is never issued by the + server, so it has no `minted` state to pass through. + """ + url, _ = modern_http_server + async with Client(url) as client: + first = await client.call_tool( + "add_todo", {"text": "one", AGENT_ID_PARAM: AGENT, "context": "start"} + ) + minted = _text(first).split("session_id=")[1].split(" ")[0] + + second = await client.call_tool( + "add_todo", + {"text": "two", SESSION_ID_PARAM: minted, AGENT_ID_PARAM: AGENT}, + ) + assert second.is_error is False, _text(second) + assert MINT_BACK_HEADER not in _text(second) + assert second.structured_content[MCP_INSTRUCTIONS_KEY][AGENT_ID_PARAM] == AGENT + + time.sleep(0.5) + events = _call_events(capture_queue)[-2:] + assert [e.session_id for e in events] == [minted, minted] + assert [e.tags[AGENTCAT_TAG_SESSION_SOURCE] for e in events] == [ + "minted", + "supplied", + ] + assert [e.tags[AGENTCAT_TAG_AGENT_ID] for e in events] == [AGENT, AGENT] + assert [e.tags[AGENTCAT_TAG_AGENT_SOURCE] for e in events] == [ + "supplied", + "supplied", + ] + + +async def test_omitting_the_required_agent_handle_degrades_to_absence( + modern_http_server, capture_queue +): + """`required` is advisory: nothing enforces it, and nothing may break. + + Measured on mcp 2.0 — the injected schema is what `tools/list` advertises, + but AgentCat strips the handles at the request-handler seam BEFORE any + argument validation the tool layer would do, so an agent that ignores the + `required` marker is served normally. The event is then simply + agent-less: an absent handle must never become an empty or invented tag, + because a customer filtering on `agentcat_agent_id` has to be able to tell + "no agent told us" from "this agent". + + The session handle is untouched by any of it and still mints. + """ + url, _ = modern_http_server + async with Client(url) as client: + result = await client.call_tool("add_todo", {"text": "no agent"}) + assert result.is_error is False, _text(result) + assert MINT_BACK_HEADER in _text(result) + # Nothing to confirm, so the mirror names only the session. + assert AGENT_ID_PARAM not in result.structured_content[MCP_INSTRUCTIONS_KEY] + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert AGENTCAT_TAG_AGENT_ID not in event.tags + assert AGENTCAT_TAG_AGENT_SOURCE not in event.tags + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + + +async def test_a_blank_agent_handle_is_a_miss_not_an_empty_tag( + modern_http_server, capture_queue +): + """`extract_handle` trims and rejects, over the wire. + + A whitespace-only value must leave the event with NO agent tags at all — + an `agentcat_agent_id: ""` would key every such call to one phantom agent + downstream, which is worse than the absence it stands in for. + """ + url, _ = modern_http_server + async with Client(url) as client: + result = await client.call_tool( + "add_todo", {"text": "blank", AGENT_ID_PARAM: " ", "context": "x"} + ) + assert result.is_error is False, _text(result) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert AGENTCAT_TAG_AGENT_ID not in event.tags + assert AGENTCAT_TAG_AGENT_SOURCE not in event.tags + # The session handle is unaffected: suppression is per handle. + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" diff --git a/tests/e2e/official_modern/test_identify_http.py b/tests/e2e/official_modern/test_identify_http.py new file mode 100644 index 0000000..8a2bef3 --- /dev/null +++ b/tests/e2e/official_modern/test_identify_http.py @@ -0,0 +1,231 @@ +"""Identify-per-event behavior over real Streamable HTTP (modern official SDK). + +v2 has no standalone `agentcat:identify` event: the hook runs per tool call and +its result is stamped onto that call's event. + +Tests mutate the running server's `AgentCatData.options.identify` to vary the +hook per scenario, rather than declaring an options factory — the hook is read +per request, so swapping it on the live server costs no second uvicorn boot. +Each test resets it in `finally` so the next one starts clean. +""" + +from __future__ import annotations + +import time +from typing import Any + +import httpx2 +import pytest +from mcp.client import Client +from mcp.client.streamable_http import streamable_http_client + +from agentcat.modules.internal import get_server_tracking_data +from agentcat.types import UserIdentity + +pytestmark = pytest.mark.e2e + + +def _set_identify(server, fn) -> None: + data = get_server_tracking_data(server) + assert data is not None + data.options.identify = fn + + +def _call_events(capture_queue): + return [e for e in capture_queue if e.event_type == "mcp:tools/call"] + + +def _text(result) -> str: + return "".join(c.text for c in result.content if hasattr(c, "text")) + + +async def test_the_hook_reads_the_real_http_request( + modern_http_server, capture_queue +): + """`extra` carries the live HTTP request, not a placeholder. + + The hook's second argument is the SDK's `RequestContext`, and the header + read below is verbatim the idiom the README documents for + `resolve_session_id` ("receives the same `(request, extra)` pair as + `identify`") — keying off a header the customer's gateway set. Only a + socket can prove it: the in-process client has no HTTP request at all, so + `extra.request` is None there and the assertion would be vacuous. + + `request` is the tool call's PARAMS on every flavor, which the same + assertion pins from the other side. + """ + url, server = modern_http_server + # Recorded rather than asserted in place: `resolve_identity` swallows every + # exception the hook raises, so an assertion inside it would surface as a + # silently anonymous event instead of a failure. + seen: list[tuple[str, str | None]] = [] + + def identify(request: Any, extra: Any) -> UserIdentity | None: + headers = getattr(getattr(extra, "request", None), "headers", {}) or {} + tenant = headers.get("x-tenant") + seen.append((getattr(request, "name", None), tenant)) + return UserIdentity(user_id=f"tenant:{tenant}", user_name=None, user_data=None) + + _set_identify(server, identify) + try: + http_client = httpx2.AsyncClient(headers={"X-Tenant": "acme"}) + async with Client( + streamable_http_client(url, http_client=http_client) + ) as client: + result = await client.call_tool( + "add_todo", {"text": "tenant", "context": "id"} + ) + assert result.is_error is False, _text(result) + + time.sleep(0.5) + assert seen == [("add_todo", "acme")], seen + assert _call_events(capture_queue)[-1].identify_actor_given_id == "tenant:acme" + finally: + _set_identify(server, None) + + +async def test_the_actor_rides_the_tool_call_event_not_a_self_event( + modern_http_server, capture_queue +): + """v2 stamps the actor onto every tools/call event; the standalone + `agentcat:identify` event is gone.""" + url, server = modern_http_server + + def identify(_request: Any, _extra: Any) -> UserIdentity | None: + return UserIdentity( + user_id="bob", + user_name="Bob Bobson", + user_data={"plan": "enterprise"}, + ) + + _set_identify(server, identify) + try: + async with Client(url) as client: + await client.call_tool("add_todo", {"text": "self", "context": "x"}) + + time.sleep(0.5) + assert {e.event_type for e in capture_queue} == {"mcp:tools/call"} + event = _call_events(capture_queue)[-1] + # All three fields, not just the id: `user_name` and `user_data` are + # what a customer segments and displays by, and each lands in a + # differently-named event field. + assert event.identify_actor_given_id == "bob" + assert event.identify_actor_name == "Bob Bobson" + assert event.identify_data == {"plan": "enterprise"} + finally: + _set_identify(server, None) + + +async def test_identity_is_resolved_per_call_never_cached( + modern_http_server, capture_queue +): + """The hook runs on EVERY call, so consecutive calls on one connection can + return different actors — v1 cached the result for the connection's life + and could not express this.""" + url, server = modern_http_server + counter = {"n": 0} + + def identify(_request: Any, _extra: Any) -> UserIdentity | None: + counter["n"] += 1 + return UserIdentity( + user_id=f"user-{counter['n']}", user_name=None, user_data=None + ) + + _set_identify(server, identify) + try: + async with Client(url) as client: + await client.call_tool("add_todo", {"text": "first", "context": "x"}) + await client.call_tool("add_todo", {"text": "second", "context": "x"}) + + time.sleep(0.5) + events = _call_events(capture_queue)[-2:] + assert counter["n"] == 2, "the hook did not run once per call" + assert [e.identify_actor_given_id for e in events] == ["user-1", "user-2"] + finally: + _set_identify(server, None) + + +async def test_returning_none_yields_an_anonymous_event( + modern_http_server, capture_queue +): + url, server = modern_http_server + + def identify(_request: Any, _extra: Any) -> UserIdentity | None: + return None + + _set_identify(server, identify) + try: + async with Client(url) as client: + result = await client.call_tool( + "add_todo", {"text": "none", "context": "x"} + ) + assert result.is_error is False, _text(result) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert event.identify_actor_given_id is None + assert event.identify_actor_name is None + finally: + _set_identify(server, None) + + +async def test_an_async_hook_works_over_the_wire(modern_http_server, capture_queue): + """`identify` may be `async def`, and the contract holds on a real socket. + + The cross-flavor suite (`tests/test_async_hooks.py`) proves the hook + contract itself; this proves the request path an actual deployment takes + still has a running loop when the hook is reached — which is what makes + awaiting the hook viable at all, on every adapter and transport. + + The hook awaits something to make the point: a hook that merely returned + from an `async def` would pass even if the coroutine were driven by + accident somewhere upstream. + """ + import asyncio + + url, server = modern_http_server + + async def identify(_request: Any, _extra: Any) -> UserIdentity | None: + await asyncio.sleep(0) + return UserIdentity(user_id="async-alice", user_name="Alice", user_data=None) + + _set_identify(server, identify) + try: + async with Client(url) as client: + result = await client.call_tool( + "add_todo", {"text": "async id", "context": "x"} + ) + assert result.is_error is False, _text(result) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert event.identify_actor_given_id == "async-alice" + assert event.identify_actor_name == "Alice" + finally: + _set_identify(server, None) + + +async def test_a_raising_hook_does_not_break_the_call( + modern_http_server, capture_queue +): + """A customer hook that blows up yields an anonymous call, not a failed one + — and not a dropped event either.""" + url, server = modern_http_server + + def identify(_request: Any, _extra: Any) -> UserIdentity | None: + raise RuntimeError("identify exploded") + + _set_identify(server, identify) + try: + async with Client(url) as client: + result = await client.call_tool( + "add_todo", {"text": "boom", "context": "x"} + ) + assert result.is_error is False, _text(result) + + time.sleep(0.5) + event = _call_events(capture_queue)[-1] + assert event.parameters["arguments"]["text"] == "boom" + assert event.identify_actor_given_id is None + finally: + _set_identify(server, None) diff --git a/tests/e2e/official_modern/test_session_http.py b/tests/e2e/official_modern/test_session_http.py index c09621f..c088817 100644 --- a/tests/e2e/official_modern/test_session_http.py +++ b/tests/e2e/official_modern/test_session_http.py @@ -107,6 +107,102 @@ async def test_custom_clientinfo_propagates_to_event( assert (event.client_name, event.client_version) == ("MyAgent", "1.2.3") +@pytest.mark.asyncio +async def test_identity_rides_every_call_not_just_the_first( + modern_http_server, capture_queue +): + """Name AND version on EVERY event of a connection. + + Reading only the last event — which every other identity assertion in the + e2e suite used to do — cannot tell "resolved per request" from "resolved + once and reused", and the two differ exactly where it matters: a rung that + answers only for the call that follows the handshake leaves every later + event of a long-lived connection anonymous. Three calls, three identities. + """ + url, _ = modern_http_server + async with Client( + url, client_info=Implementation(name="Cursor", version="2.6.22") + ) as client: + for n in range(3): + await client.call_tool("add_todo", {"text": f"call-{n}", "context": "id"}) + + time.sleep(0.5) + events = _call_events(capture_queue)[-3:] + assert [e.parameters["arguments"]["text"] for e in events] == [ + "call-0", + "call-1", + "call-2", + ] + assert [(e.client_name, e.client_version) for e in events] == [ + ("Cursor", "2.6.22") + ] * 3 + + +@pytest.mark.asyncio +async def test_identity_comes_from_the_per_request_meta_rung( + modern_http_server, capture_queue +): + """The FIRST rung of the ladder, isolated from the handshake rung. + + On the 2026-07-28 wire the client stamps + `io.modelcontextprotocol/clientInfo` into `_meta` on every request, so the + identity on the event can be read without any handshake state at all. The + two rungs are indistinguishable while both agree — so this drives the same + connection twice with DIFFERENT identities, which only the per-request + envelope can express: a handshake-only ladder reports the first client's + name on the second call. + """ + url, _ = modern_http_server + + async def call_as(name: str, version: str, text: str) -> None: + async with Client( + url, client_info=Implementation(name=name, version=version) + ) as client: + await client.call_tool("add_todo", {"text": text, "context": "meta"}) + + await call_as("First", "1.0.0", "meta-first") + await call_as("Second", "2.0.0", "meta-second") + + time.sleep(0.5) + events = _call_events(capture_queue)[-2:] + assert { + e.parameters["arguments"]["text"]: (e.client_name, e.client_version) + for e in events + } == { + "meta-first": ("First", "1.0.0"), + "meta-second": ("Second", "2.0.0"), + } + + +@pytest.mark.asyncio +async def test_identity_survives_the_legacy_handshake_rung( + modern_http_server, capture_queue +): + """The LAST rung: a legacy client sends `clientInfo` only in `initialize`. + + `mode="legacy"` has no per-request `_meta` envelope to read, so the ladder + falls through to the identity the SDK's own `ServerSession` captured at + handshake time. On this STATEFUL app that session outlives the handshake, + so both calls are still attributed — the rung has to answer more than once. + (Under `stateless_http=True` it cannot, which is what the looser assertion + in `tests/e2e/official/test_stateless_http.py` records.) + """ + url, _ = modern_http_server + async with Client( + url, + mode="legacy", + client_info=Implementation(name="LegacyAgent", version="0.9.0"), + ) as client: + await client.call_tool("add_todo", {"text": "legacy-1", "context": "id"}) + await client.call_tool("add_todo", {"text": "legacy-2", "context": "id"}) + + time.sleep(0.5) + events = _call_events(capture_queue)[-2:] + assert [(e.client_name, e.client_version) for e in events] == [ + ("LegacyAgent", "0.9.0") + ] * 2 + + @pytest.mark.asyncio async def test_request_headers_ride_the_event(modern_http_server, capture_queue): """`parameters.extra.requestInfo.headers` is only reachable from the HTTP diff --git a/tests/e2e/official_modern/test_stateless_http.py b/tests/e2e/official_modern/test_stateless_http.py index 0d4afde..fa0ccb9 100644 --- a/tests/e2e/official_modern/test_stateless_http.py +++ b/tests/e2e/official_modern/test_stateless_http.py @@ -54,6 +54,16 @@ async def test_concurrent_clients_never_wear_each_others_name( ): """Two named clients at once, on a server that remembers nothing. + Exact attribution of name AND version, not "in (None, 'Cursor')": on the + 2026-07-28 wire identity does not depend on a server-side session at all. + The client stamps `io.modelcontextprotocol/clientInfo` into `_meta` on every + request (`mcp/client/session.py`), and the modern HTTP server re-stamps it + from its own negotiation verdict, so the first rung of the ladder answers + even here. A `None` on this transport is a regression in the `_meta` rung, + not the honest silence it is on the legacy wire — see the sibling assertion + in `tests/e2e/official/test_stateless_http.py`, which keeps the looser form + for exactly that reason. + Each event is matched to the call that produced it by the argument that call sent, so this asserts ATTRIBUTION rather than "both names appear somewhere" — a shared identity slot produces one name on both events, and @@ -75,8 +85,11 @@ async def call_as(name: str, version: str, text: str) -> None: events = _call_events(capture_queue) assert len(events) == 2 - attributed = {e.parameters["arguments"]["text"]: e.client_name for e in events} - # No name at all is the honest answer for a connection that is gone; - # SOMEONE ELSE's name never is. - assert attributed["from-cursor"] in (None, "Cursor"), attributed - assert attributed["from-claude"] in (None, "Claude"), attributed + attributed = { + e.parameters["arguments"]["text"]: (e.client_name, e.client_version) + for e in events + } + assert attributed == { + "from-cursor": ("Cursor", "2.6.22"), + "from-claude": ("Claude", "1.0.0"), + } diff --git a/tests/test_async_hooks.py b/tests/test_async_hooks.py new file mode 100644 index 0000000..4e305b8 --- /dev/null +++ b/tests/test_async_hooks.py @@ -0,0 +1,319 @@ +"""Every customer hook takes a sync OR an async callable, on every server shape. + +`AgentCatOptions` exposes five customer-supplied callables and all five are +documented to accept either. Before `modules/hooks.py` each site decided that +for itself: `identify` never awaited at all, and `event_tags` / +`event_properties` narrowed on `inspect.iscoroutine`, which matches ONLY native +coroutines. A hook returning an `asyncio.Task` — a cached in-flight lookup — or +any object implementing `__await__` was assigned into the event verbatim, which +is the ``-on-the-wire failure that looks like it worked. + +So the parametrization is the test. Four ways of expressing "a value, maybe +later" run through each hook: a plain return, a native coroutine, a Task, and a +bare `__await__` implementer. The last two are the ones the old predicate +dropped. + +`flavors()` builds every server shape the installed dependency set supports, and +CI runs this file on every mcp and fastmcp leg of the compatibility matrix — so +"works on all supported SDK versions" is asserted rather than reasoned about. + +`redact_sensitive_information` is not parametrized over flavors here: it runs on +the publish queue's worker THREAD, not the request path, so it is adapter- and +version-independent by construction and gets its own section against +`redact_event` directly. That thread has no event loop, which is why it needs +`drive_hook_result` rather than an await. +""" + +import asyncio +from typing import Any + +import pytest + +from agentcat import AgentCatOptions, track +from agentcat.modules.constants import AGENTCAT_TAG_SESSION_SOURCE +from agentcat.modules.handles import derive_session_id +from agentcat.modules.hooks import await_hook_result, drive_hook_result +from agentcat.modules.redaction import redact_event +from agentcat.types import UserIdentity + +from .test_utils.flavors import flavors + +PROJECT = "proj_test" + + +@pytest.fixture(autouse=True) +def capture(monkeypatch): + """Collect every event the queue is handed, without touching the network.""" + events: list = [] + from agentcat.modules import event_queue + + monkeypatch.setattr(event_queue.event_queue, "add", events.append) + return events + + +@pytest.fixture +def log_sink(): + """Everything `write_to_log` tees to diagnostics, as the collector sees it.""" + from agentcat.modules import logging as agentcat_logging + + previous = agentcat_logging._diagnostics_sink + lines: list[str] = [] + agentcat_logging.set_diagnostics_sink(lines.append) + yield lines + agentcat_logging.set_diagnostics_sink(previous) + + +# ── the four ways a hook can hand back a value ─────────────────────────────── + + +class Thenable: + """Awaitable, but neither a coroutine nor a Future. + + The shape `inspect.iscoroutine` misses that has no asyncio machinery behind + it at all — what a library wrapping its own scheduler hands back. + """ + + def __init__(self, value: Any) -> None: + self._value = value + + def __await__(self): + async def _inner() -> Any: + return self._value + + return _inner().__await__() + + +def _plain(value: Any): + def hook(_request: Any, _extra: Any) -> Any: + return value + + return hook + + +def _coroutine(value: Any): + async def hook(_request: Any, _extra: Any) -> Any: + return value + + return hook + + +def _task(value: Any): + """A Task, which only exists because the hook is called inside a loop.""" + + def hook(_request: Any, _extra: Any) -> Any: + return asyncio.ensure_future(_coroutine(value)(None, None)) + + return hook + + +def _thenable(value: Any): + def hook(_request: Any, _extra: Any) -> Any: + return Thenable(value) + + return hook + + +WRAPPERS = [ + pytest.param(_plain, id="sync"), + pytest.param(_coroutine, id="coroutine"), + pytest.param(_task, id="task"), + pytest.param(_thenable, id="thenable"), +] + +FLAVORS = pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +WRAPPED = pytest.mark.parametrize("wrap", WRAPPERS) + + +async def _call_once(flavor, options: AgentCatOptions): + built = flavor.build("async-hooks") + track(built.server, PROJECT, options) + async with flavor.client(built.server) as client: + await flavor.list_tools(client) + return await flavor.call(client, "echo", {"text": "hi"}) + + +# ── A. the request-path hooks, on every shape and every wrapper ────────────── + + +@FLAVORS +@WRAPPED +async def test_identify(flavor, wrap, capture): + identity = UserIdentity(user_id="alice", user_name="Alice", user_data=None) + result = await _call_once(flavor, AgentCatOptions(identify=wrap(identity))) + + assert result.is_error is False + (event,) = capture + assert event.identify_actor_given_id == "alice" + assert event.identify_actor_name == "Alice" + + +@FLAVORS +@WRAPPED +async def test_event_tags(flavor, wrap, capture): + result = await _call_once(flavor, AgentCatOptions(event_tags=wrap({"lane": "a"}))) + + assert result.is_error is False + (event,) = capture + assert event.tags["lane"] == "a" + # The SDK's own tags still merge over the customer's, as ever. + assert AGENTCAT_TAG_SESSION_SOURCE in event.tags + + +@FLAVORS +@WRAPPED +async def test_event_properties(flavor, wrap, capture): + payload = {"flag": True, "nested": {"n": 1}} + result = await _call_once(flavor, AgentCatOptions(event_properties=wrap(payload))) + + assert result.is_error is False + (event,) = capture + assert event.properties == payload + + +@FLAVORS +@WRAPPED +async def test_resolve_session_id(flavor, wrap, capture): + """Hook mode, which also proves the awaited value is used rather than merely + consumed: the handle is DERIVED from what the hook returned, so a dropped + result would mint a random one instead and the equality would fail.""" + result = await _call_once( + flavor, AgentCatOptions(resolve_session_id=wrap("corr-7")) + ) + + assert result.is_error is False + (event,) = capture + assert event.session_id == derive_session_id("corr-7", PROJECT) + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "hook" + + +# ── B. an awaitable that fails degrades quietly, and says why ──────────────── + + +def _raising_awaitable(_request: Any, _extra: Any) -> Any: + async def _boom() -> Any: + raise RuntimeError("hook exploded mid-await") + + return _boom() + + +@FLAVORS +@pytest.mark.parametrize( + ("option", "hook_name"), + [ + ("identify", "identify"), + ("event_tags", "event_tags"), + ("event_properties", "event_properties"), + ("resolve_session_id", "resolve_session_id"), + ], +) +async def test_a_failing_awaitable_degrades_and_names_the_await( + flavor, option, hook_name, capture, log_sink +): + """Silent for the customer's agent, loud in the log. + + The degradation contract is unchanged — analytics never fails a tool call — + but the log now distinguishes "your hook raised" from "your hook's awaitable + could not be driven". Without that second line a customer reading + "identify callback error" goes looking for a bug in code that ran fine. + """ + result = await _call_once(flavor, AgentCatOptions(**{option: _raising_awaitable})) + + assert result.is_error is False, "a failing hook must never fail the call" + (event,) = capture + assert event.identify_actor_given_id is None + assert event.properties is None + assert "lane" not in (event.tags or {}) + # resolve_session_id degrades by minting, never by publishing sessionless. + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "minted" + + awaited = [ln for ln in log_sink if "could not be awaited" in ln] + assert len(awaited) == 1, log_sink + assert hook_name in awaited[0], awaited[0] + + +# ── C. redaction, which drives its awaitable from a thread ─────────────────── + + +@pytest.mark.parametrize("wrap", WRAPPERS[:1] + WRAPPERS[3:]) +def test_redaction_accepts_sync_and_non_coroutine_awaitables(wrap): + """`redact_event` runs on the publish worker thread, so it cannot await. + + Parametrized without the coroutine and Task cases: both are already covered + by `test_redaction.py`, and a Task cannot even be constructed here — there + is no running loop on this path, which is the whole reason this hook needs + `drive_hook_result` rather than an await. + """ + from agentcat.types import UnredactedEvent + + def redact(value: str) -> Any: + return wrap(value.replace("secret", "[REDACTED]"))(None, None) + + event = UnredactedEvent( + event_type="mcp:tools/call", + resource_name="echo", + parameters={"arguments": {"text": "a secret value"}}, + ) + redacted = redact_event(event, redact) + assert redacted.parameters["arguments"]["text"] == "a [REDACTED] value" + + +def test_redaction_reports_an_undrivable_awaitable(log_sink): + """A hook that cannot be driven raises, so the queue drops the event rather + than publishing it unredacted — and the log says which half broke.""" + from agentcat.types import UnredactedEvent + + def redact(_value: str) -> Any: + async def _boom() -> str: + raise RuntimeError("redactor exploded mid-await") + + return _boom() + + event = UnredactedEvent( + event_type="mcp:tools/call", + resource_name="echo", + parameters={"arguments": {"text": "a secret value"}}, + ) + with pytest.raises(RuntimeError): + redact_event(event, redact) + + assert [ + ln + for ln in log_sink + if "could not be awaited" in ln and "redact_sensitive_information" in ln + ], log_sink + + +# ── D. the helpers themselves ──────────────────────────────────────────────── + + +async def test_await_hook_result_passes_plain_values_straight_through(): + assert await await_hook_result(7, "h") == 7 + assert await await_hook_result(None, "h") is None + # A callable is a value, not something to invoke: detection is on the + # RESULT, which is what makes partials and decorated hooks work unchanged. + marker = lambda: None # noqa: E731 + assert await await_hook_result(marker, "h") is marker + + +def test_drive_hook_result_passes_plain_values_straight_through(): + assert drive_hook_result(7, "h") == 7 + assert drive_hook_result(None, "h") is None + + +async def test_await_hook_result_reraises_so_call_sites_keep_their_own_rule( + log_sink, +): + """The helper logs and re-raises rather than swallowing. + + Each site degrades differently — anonymous actor, dropped tags, a freshly + minted handle, a dropped event — and collapsing those into one decision + here would flatten four deliberate behaviors. + """ + + async def boom() -> None: + raise ValueError("nope") + + with pytest.raises(ValueError): + await await_hook_result(boom(), "some_hook") + + assert [ln for ln in log_sink if "some_hook" in ln and "could not be awaited" in ln] diff --git a/tests/test_identify_shape.py b/tests/test_identify_shape.py index 758ed44..0beea6b 100644 --- a/tests/test_identify_shape.py +++ b/tests/test_identify_shape.py @@ -75,6 +75,63 @@ def identify(request, extra): assert event.identify_data == {"tool": "echo"} +@pytest.fixture +def log_sink(): + """Everything `write_to_log` tees to diagnostics, as the collector sees it.""" + from agentcat.modules import logging as agentcat_logging + + previous = agentcat_logging._diagnostics_sink + lines: list[str] = [] + agentcat_logging.set_diagnostics_sink(lines.append) + yield lines + agentcat_logging.set_diagnostics_sink(previous) + + +@pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) +async def test_an_async_identify_hook_reaches_the_event(flavor, capture, log_sink): + """`identify` may be written `async def`, on every server shape. + + This test used to assert the opposite. `resolve_identity` called the hook + and took its return value verbatim, so an `async def` was CALLED but never + ran — calling it only builds a coroutine — which then failed the + `isinstance(result, UserIdentity)` check and published the call anonymously, + with no error the customer could see. The inverted version existed to fail + the day the contract moved, so the change would be made on purpose rather + than discovered. `modules/hooks.py` moved it. + + The hook body running at all is asserted separately from the actor landing: + an awaited hook whose result went nowhere and a never-awaited hook both end + in an anonymous event, and only the first assertion tells them apart. + """ + body_ran: list[str] = [] + + async def identify(request, extra): + body_ran.append(request.name) + return UserIdentity( + user_id=f"user-{request.arguments['text']}", + user_name=request.name, + user_data={"tool": request.name}, + ) + + built = flavor.build("identify-shape") + track(built.server, "proj_test", AgentCatOptions(identify=identify)) + + async with flavor.client(built.server) as client: + await flavor.list_tools(client) + result = await flavor.call(client, "echo", {"text": "hi"}) + + assert result.is_error is False + assert body_ran == ["echo"], "the coroutine was created but never driven" + + assert len(capture) == 1 + assert capture[0].identify_actor_given_id == "user-hi" + assert capture[0].identify_actor_name == "echo" + assert capture[0].identify_data == {"tool": "echo"} + + # The old failure mode logged its way past; nothing should now. + assert not [ln for ln in log_sink if "did not return a valid UserIdentity" in ln] + + @pytest.mark.parametrize("flavor", flavors(), ids=lambda f: f.id) async def test_every_customer_hook_receives_the_same_pair(flavor, capture): """`identify`, `event_tags`, `event_properties` and `resolve_session_id` are From fb4549725f96faf30a5dabb1a53308a408895713 Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Tue, 4 Aug 2026 13:18:10 -0400 Subject: [PATCH 07/13] chore(release): bump version to 2.0.0 Graduate the 2.0.0b prerelease train to stable: Development Status classifier moves to Production/Stable, and the --pre install guidance in README and MIGRATION is gone since pip now resolves 2.0.0 directly. --- MIGRATION.md | 8 +++----- README.md | 10 +++------- pyproject.toml | 4 ++-- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 65b60e8..839ce3e 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -49,13 +49,11 @@ Three of them changed *behavior*, and all three are covered below: `identify` an If your integration is a bare `track(server, "proj_...")` with no callbacks, upgrading is a version bump. Handles are injected and stripped inside the SDK, so your tool handlers never see the extra parameters, and handles keep landing in the `session_id` field with the `ses_` prefix — your existing dashboards, queries, and exporter pipelines keep working untouched. If you pass callbacks, read the two sections above first: both changes are one-line edits, but both are silent if you skip them. ```bash -pip install --pre --upgrade "agentcat>=2" +pip install --upgrade "agentcat>=2" # or, for Jlowin's/Prefect's FastMCP support: -pip install --pre --upgrade "agentcat[community]>=2" +pip install --upgrade "agentcat[community]>=2" ``` -`--pre` while 2.x is a prerelease; drop it once a stable 2.0.0 ships. (Plain `pip install agentcat` skips prereleases entirely and resolves the 1.x line.) - ### Update your code only if… **You pass** `AgentCatOptions(stateless=...)`**.** The option is gone, along with its auto-detection. Every handle, actor, and client identity is now resolved per request from the request itself, so a stateless server and a stateful one take exactly the same code path — there is nothing left to configure. Passing it raises `TypeError` from the dataclass constructor; delete the argument. @@ -160,7 +158,7 @@ The session ID is used **verbatim** — never validated, derived or reformatted, **A server tracked with `enable_tracing=False` publishes no custom events.** Turning tracing off silences this entry point exactly as it silences tool-call events, so a server you deliberately muted does not start emitting a new event type. The session-ID-string form has no options to consult and always publishes. -### Known limitations in 2.0.0b3 +### Known limitations in 2.0 - **Multi-round tool calls that mint their own handle land on separate sessions.** If a tool call spans several round trips and the *first* round is what mints the handle, each round is attributed to its own session instead of one shared session. The other two modes correlate correctly and are protocol-enforced: supplying `session_id` yourself, or deriving it with a `resolve_session_id` hook. If your server relies on multi-round tool calls, prefer one of those two. - **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and the upstream returns an error result, no Python exception is raised locally, so the event records the message without a stack trace. Errors raised by your own tool code are unaffected. This applies from fastmcp 3.4, which taught the proxy provider to pass an upstream error result through; on 3.0–3.3 the proxy collapsed it into a raised `ToolError` instead, so those versions do record full detail. diff --git a/README.md b/README.md index c6d8d1f..700a7d3 100644 --- a/README.md +++ b/README.md @@ -38,16 +38,12 @@ This SDK also provides a free and simple way to forward telemetry like logs, tra ```bash # Basic installation (includes official MCP SDK) -pip install --pre agentcat +pip install agentcat # With Jlowin's/Prefect's FastMCP support -pip install --pre "agentcat[community]" +pip install "agentcat[community]" ``` -`--pre` is required while 2.x is a prerelease: without it pip skips -`2.0.0b3` and resolves the 1.x line instead, which has none of the features -documented below. Drop the flag once a stable 2.0.0 ships. - One `track()` call covers every supported server shape: | Runtime | Supported | @@ -275,7 +271,7 @@ Learn more about our free and open source [telemetry integrations](https://docs. ### Known limitations -Two behaviors are worth knowing before you read your first dashboard. Both are deliberate for `2.0.0b3`. +Two behaviors are worth knowing before you read your first dashboard. Both are deliberate in the 2.x line. - **Multi-round tool calls that mint their own handle land on separate sessions.** When a tool call runs several round trips and the *first* round is what mints the handle, each round is attributed to its own session rather than one shared session. Supplying a `session_id` yourself, or deriving one with `resolve_session_id`, correlates the rounds correctly — those two modes are protocol-enforced. Only the mint-on-first-round case is affected. - **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and that upstream returns an error result, there is no local Python exception to read, so the event records the error message without a stack trace. Errors raised by your own tool code are unaffected and carry full detail. diff --git a/pyproject.toml b/pyproject.toml index 9ddef72..17a8751 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "agentcat" -version = "2.0.0b3" +version = "2.0.0" description = "Analytics tool for MCP (Model Context Protocol) servers and AI agents - tracks tool usage patterns and provides insights" authors = [ { name = "AgentCat, Inc.", email = "support@agentcat.com" }, @@ -9,7 +9,7 @@ readme = "README.md" license = { text = "MIT" } requires-python = ">=3.10" classifiers = [ - "Development Status :: 4 - Beta", + "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", From 10f635adacb2a6a8a5424d85f5fcdb65ef488b4f Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Tue, 4 Aug 2026 15:43:24 -0400 Subject: [PATCH 08/13] =?UTF-8?q?fix:=20never=20halt,=20hang,=20or=20corru?= =?UTF-8?q?pt=20the=20customer's=20server=20=E2=80=94=2013=20audit=20findi?= =?UTF-8?q?ngs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An adversarially-verified audit found the SDK violating its core guarantee in 13 ways. This closes all of them: - event_queue: no signal handlers, no os._exit, no exit-time event drain. Lazy daemon workers consume the bounded queue directly (the executor's unbounded backlog is gone), destroy() is bounded, publish HTTP calls carry a 10s timeout. Import is side-effect free and thread-safe. - diagnostics: the one remaining atexit hook skips when empty and caps its POST at 2s. - __init__: the import-time version lookup no longer crashes metadata-less installs. - exceptions: capture_exception is never-raise, with per-step guards so hostile __str__, deleted-cwd abspath, raising content properties, and poisoned cause chains degrade instead of replacing the customer's result on the wire. - injection/callpath: the failed-rebuild strip fallback is shape+config aware — customer-declared session_id/agent_id/context parameters ride through, and the misleading invalid-session correction is suppressed when the registry is unknown. Rebuild root causes fixed (params_type fallback, per-tool copy guards in all three adapters), and the v1 tools/list copy preserves _meta and extra fields. - hooks: customer hooks run contained via run_hook — sync hooks offload to a worker thread (the loop never stalls), everything is capped at 5s, and SystemExit/spontaneous CancelledError are converted to a plain HookExecutionError while genuine task cancellation propagates. New regression suites: tests/test_process_safety.py (subprocess-based lifecycle checks) and tests/test_hook_offload.py, plus per-finding tests across the existing files. Both dependency legs green (776 modern / 919 legacy); ruff and mypy ratchets both improved. --- MIGRATION.md | 2 + README.md | 12 +- src/agentcat/__init__.py | 8 +- src/agentcat/modules/adapters/community.py | 44 ++-- src/agentcat/modules/adapters/lowlevel_v1.py | 59 +++-- src/agentcat/modules/adapters/lowlevel_v2.py | 70 ++++-- src/agentcat/modules/callpath.py | 15 +- src/agentcat/modules/diagnostics.py | 23 +- src/agentcat/modules/event_queue.py | 159 ++++++------- src/agentcat/modules/exceptions.py | 189 +++++++++------ src/agentcat/modules/handles.py | 4 +- src/agentcat/modules/hooks.py | 131 ++++++++++- src/agentcat/modules/identify.py | 6 +- src/agentcat/modules/injection.py | 49 +++- src/agentcat/modules/internal.py | 6 +- tests/e2e/conftest.py | 2 +- tests/test_async_hooks.py | 12 +- tests/test_callpath.py | 36 ++- tests/test_diagnostics_export.py | 59 +++++ tests/test_event_capture_completeness.py | 22 +- tests/test_event_queue.py | 229 ++++++++++--------- tests/test_event_tags_properties.py | 6 +- tests/test_exceptions.py | 142 +++++++++++- tests/test_hook_offload.py | 207 +++++++++++++++++ tests/test_injection.py | 66 +++++- tests/test_lowlevel_v1_handles.py | 48 ++++ tests/test_lowlevel_v2_handles.py | 48 ++++ tests/test_multiple_servers.py | 8 +- tests/test_process_safety.py | 219 ++++++++++++++++++ tests/test_rebuild_on_demand.py | 79 +++++++ tests/test_request_extra.py | 6 +- tests/test_tool_context.py | 2 +- tests/test_truncation.py | 2 +- 33 files changed, 1592 insertions(+), 378 deletions(-) create mode 100644 tests/test_hook_offload.py create mode 100644 tests/test_process_safety.py diff --git a/MIGRATION.md b/MIGRATION.md index 839ce3e..f145e42 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -122,6 +122,8 @@ pip install "agentcat<2" # staying on FastMCP 2.x - **`redact_sensitive_information` now actually runs.** In 1.x the hook was configured, documented, and never invoked on a published event: the redactor walked `str`/`list`/`dict` and was handed the event *model*, so it returned it untouched. 2.0 fixes that, which means a hook you set in 1.x starts taking effect the moment you upgrade. It runs on every string in the event — `parameters`, `response`, `user_intent`, `client_name`, `server_name` and the rest — except the fields AgentCat needs to attribute the event: `session_id`, `id`, `project_id`, `event_type`, `resource_name`, `actor_id`, the three `identify_*` fields, and your own `tags` and `properties`. **If your hook is an aggressive catch-all** (`lambda s: "[REDACTED]"`), it will now blank fields your dashboards read, such as `client_name`. Narrow it to the patterns you actually care about before upgrading. A hook that raises drops the event rather than publishing it unredacted, and an async hook is supported. - **MCP `extra.sessionId` is ignored entirely**, and inactivity-based session rollover is gone. The transport's `mcp-session-id` still rides along untouched under `parameters.extra.sessionId` on each event if you need it. +- **Request-path hooks now run contained: sync hooks on a worker thread, everything under a 5-second cap.** A sync `identify` (or `event_tags` / `event_properties` / `resolve_session_id`) that blocks — a database read, an HTTP call — no longer suspends your server's event loop; it suspends only its own call, exactly how your framework runs a sync tool body. Two consequences. First, a *sync* hook can no longer call asyncio APIs (`asyncio.ensure_future`, reading a loop-bound future): worker threads have no running loop, so make that hook `async def` — its body then runs on the loop as before. Second, a hook slower than 5 seconds has its result discarded and the call proceeds as if the hook had raised (anonymous / untagged / freshly minted, per that hook's documented degradation); the timeout is logged to `~/agentcat.log`. A hook that raises `SystemExit` or `CancelledError` is contained the same way — nothing a hook does reaches your request path. +- **The SDK never touches your process lifecycle.** 2.0.0 beta builds replaced `SIGINT`/`SIGTERM` handlers at import and force-exited via `os._exit(0)` after a drain delay — clobbering `KeyboardInterrupt`, your own handlers, `finally` blocks and `atexit` hooks. Stable 2.0 installs no signal handlers, registers no exit-time event drain, and runs every worker as a daemon thread: your shutdown is entirely yours, and exit is never delayed by AgentCat. The trade is deliberate: telemetry still queued when the process exits is dropped. The one exit hook that remains is the internal-diagnostics beacon — skipped when empty, capped at ~2 seconds. ### Bringing your own session IDs diff --git a/README.md b/README.md index 700a7d3..094a472 100644 --- a/README.md +++ b/README.md @@ -167,7 +167,7 @@ def identify_user(request, extra): agentcat.track(server, "proj_0000000", AgentCatOptions(identify=identify_user)) ``` -The hook may be sync or async — `async def identify_user(request, extra)` works the same way, and is the better shape when the lookup is a network call, since a blocking one holds up every other tool call in flight. Returning anything that is not a `UserIdentity`, or raising, publishes the event anonymously rather than failing the call. +The hook may be sync or async — `async def identify_user(request, extra)` works the same way. A sync hook runs on a worker thread, so a blocking lookup stalls only its own call, never the rest of your server; note that this means a *sync* hook cannot use asyncio APIs (make it `async def` if it needs the loop). Every hook runs under a 5-second cap — a slower one is logged and its call proceeds anonymously. Returning anything that is not a `UserIdentity`, or raising, publishes the event anonymously rather than failing the call. ### Bringing your own session IDs @@ -276,6 +276,16 @@ Two behaviors are worth knowing before you read your first dashboard. Both are d - **Multi-round tool calls that mint their own handle land on separate sessions.** When a tool call runs several round trips and the *first* round is what mints the handle, each round is attributed to its own session rather than one shared session. Supplying a `session_id` yourself, or deriving one with `resolve_session_id`, correlates the rounds correctly — those two modes are protocol-enforced. Only the mint-on-first-round case is affected. - **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and that upstream returns an error result, there is no local Python exception to read, so the event records the error message without a stack trace. Errors raised by your own tool code are unaffected and carry full detail. +### Shutdown behavior + +AgentCat never touches your process lifecycle: no signal handlers, no forced +exits, and no exit-time event drain. Every SDK thread is a daemon, so your +shutdown — `Ctrl-C`, `SIGTERM`, `sys.exit()` — runs exactly as it would +untracked, and is never delayed by AgentCat. The trade: telemetry still queued +at the moment the process exits is dropped rather than flushed. The one exit +hook the SDK keeps is the internal-diagnostics beacon below — skipped when +there is nothing buffered, capped at ~2 seconds when there is. + ### Internal diagnostics To help us catch and fix broken installs, the SDK sends AgentCat a small, anonymized diff --git a/src/agentcat/__init__.py b/src/agentcat/__init__.py index 88aa66c..97ce075 100644 --- a/src/agentcat/__init__.py +++ b/src/agentcat/__init__.py @@ -3,10 +3,14 @@ import os from collections.abc import Mapping from datetime import datetime, timezone -from importlib.metadata import version from typing import Any -__version__ = version("agentcat") +from .utils import get_agentcat_version + +# Guarded: on installs without distribution metadata (vendored source trees, +# PYTHONPATH, PyInstaller bundles) the lookup fails — that must degrade the +# version string, never crash the customer's import. +__version__ = get_agentcat_version() or "0.0.0" from .modules.constants import AGENTCAT_CUSTOM_EVENT_TYPE from .modules.detection import Detection, ServerFlavor, detect_server diff --git a/src/agentcat/modules/adapters/community.py b/src/agentcat/modules/adapters/community.py index e02868c..d3cded4 100644 --- a/src/agentcat/modules/adapters/community.py +++ b/src/agentcat/modules/adapters/community.py @@ -256,22 +256,35 @@ def _remembered_handshake_client(self, key: Any) -> dict[str, Any] | None: except TypeError: return None - def _specs(self, tools: list[Any]) -> list[ToolSpec]: + def _specs(self, tools: list[Any]) -> list[ToolSpec | None]: """Copies of the listed schemas, ready for the in-place injection pass. Only the schema dicts are copied. Deep-copying the ``Tool`` itself raises on every tool holding live runtime state — an OpenAPI tool's ``httpx.AsyncClient`` carries a ``threading.RLock`` — which silently - dropped injection for whole servers in v1. + dropped injection for whole servers in v1. The same lesson applies + per tool: a schema dict whose copy fails yields ``None`` in the + aligned slot (that tool serves verbatim, un-injected) instead of + taking the whole listing down. """ - return [ - ToolSpec( - tool.name, - copy.deepcopy(getattr(tool, "parameters", None) or {}), - copy.deepcopy(_field(tool, "output_schema", "outputSchema")), - ) - for tool in tools - ] + specs: list[ToolSpec | None] = [] + for tool in tools: + try: + specs.append( + ToolSpec( + tool.name, + copy.deepcopy(getattr(tool, "parameters", None) or {}), + copy.deepcopy(_field(tool, "output_schema", "outputSchema")), + ) + ) + except Exception as e: + write_to_log( + "Warning: could not copy the schema of tool " + f"'{getattr(tool, 'name', '')}' for injection; " + f"serving it verbatim without handle parameters - {e}" + ) + specs.append(None) + return specs # ── hooks ─────────────────────────────────────────────────────────────── @@ -313,7 +326,9 @@ async def on_list_tools(self, context: Any, call_next: Any) -> Any: try: specs = self._specs(tools) injected = build_injected_schemas( - specs, tracking.options, tracking.reported_conflicts + [spec for spec in specs if spec is not None], + tracking.options, + tracking.reported_conflicts, ) tracking.injected_params_registry = injected.injected_params tracking.output_injection_registry = injected.output_injected @@ -322,7 +337,9 @@ async def on_list_tools(self, context: Any, call_next: Any) -> Any: # one did not see. tracking.declared_session_params |= injected.declared_session_params return [ - tool.model_copy(update=self._schema_update(spec)) + tool + if spec is None # uncopyable schema: served verbatim + else tool.model_copy(update=self._schema_update(spec)) for tool, spec in zip(tools, specs, strict=True) ] except Exception as e: @@ -456,9 +473,10 @@ async def rebuild() -> list[ToolSpec]: case install_community registers eagerly for. """ listed = list(await self._server.list_tools(run_middleware=False)) - return self._specs( + specs = self._specs( await self._concede_get_more_tools(listed, authoritative=True) ) + return [spec for spec in specs if spec is not None] stripped = await get_stripped_arguments( tracking, options, name, raw_arguments, rebuild diff --git a/src/agentcat/modules/adapters/lowlevel_v1.py b/src/agentcat/modules/adapters/lowlevel_v1.py index 305a2d4..bc0a3d7 100644 --- a/src/agentcat/modules/adapters/lowlevel_v1.py +++ b/src/agentcat/modules/adapters/lowlevel_v1.py @@ -165,7 +165,6 @@ def install_lowlevel_v1(server: Any, data: AgentCatData, facade: Any = None) -> from mcp.types import ( CallToolRequest, ListToolsRequest, - ListToolsResult, ServerResult, TextContent, Tool, @@ -236,17 +235,33 @@ def make_get_more_tools() -> Tool: annotations=annotations, ) - def advertised_tools(original: Any, options: Any) -> list[Any]: + def advertised_tools( + original: Any, options: Any + ) -> tuple[list[Any], set[int]]: """Deep copies of the listed tools, plus get_more_tools when enabled. Copies because the injection pipeline rewrites schemas in place and - FastMCP hands out the very dict its tool manager holds. + FastMCP hands out the very dict its tool manager holds. A tool whose + copy fails is carried through VERBATIM (the customer's object, never + given to the pipeline) with its id() in the returned skip set — one + uncopyable tool must not take down the whole listing. """ nonlocal agentcat_advertises_get_more_tools tools: list[Any] = [] + skipped: set[int] = set() listed = getattr(getattr(original, "root", None), "tools", None) if isinstance(listed, list): - tools = [tool.model_copy(deep=True) for tool in listed] + for tool in listed: + try: + tools.append(tool.model_copy(deep=True)) + except Exception as e: + write_to_log( + "Warning: could not copy tool " + f"'{getattr(tool, 'name', '')}' for injection; " + f"serving it verbatim without handle parameters - {e}" + ) + tools.append(tool) + skipped.add(id(tool)) customer_owns_get_more_tools = any( getattr(tool, "name", None) == GET_MORE_TOOLS_NAME for tool in tools ) @@ -257,11 +272,16 @@ def advertised_tools(original: Any, options: Any) -> list[Any]: # context pass skips it by name, so early placement cannot double-inject. if agentcat_advertises_get_more_tools: tools.append(make_get_more_tools()) - return tools + return tools, skipped - def specs_for(tools: list[Any]) -> list[ToolSpec]: + def specs_for(tools: list[Any], skipped: set[int]) -> list[ToolSpec | None]: + """Specs aligned index-for-index with `tools`; None for skipped ones.""" return [ - ToolSpec(tool.name, tool.inputSchema, getattr(tool, "outputSchema", None)) + None + if id(tool) in skipped + else ToolSpec( + tool.name, tool.inputSchema, getattr(tool, "outputSchema", None) + ) for tool in tools ] @@ -271,16 +291,19 @@ async def rebuild() -> list[ToolSpec]: if list_handler is None: return [] listed = await list_handler(ListToolsRequest(method="tools/list")) - return specs_for(advertised_tools(listed, current_data().options)) + tools, skipped = advertised_tools(listed, current_data().options) + return [spec for spec in specs_for(tools, skipped) if spec is not None] async def wrapped_list(request: Any) -> Any: listed = await original(_LIST)(request) tracking = current_data() try: - tools = advertised_tools(listed, tracking.options) - specs = specs_for(tools) + tools, skipped = advertised_tools(listed, tracking.options) + specs = specs_for(tools, skipped) injected = build_injected_schemas( - specs, tracking.options, tracking.reported_conflicts + [spec for spec in specs if spec is not None], + tracking.options, + tracking.reported_conflicts, ) tracking.injected_params_registry = injected.injected_params tracking.output_injection_registry = injected.output_injected @@ -289,17 +312,15 @@ async def wrapped_list(request: Any) -> Any: # one did not see. tracking.declared_session_params |= injected.declared_session_params for tool, spec in zip(tools, specs, strict=True): + if spec is None: + continue # uncopyable tool: served verbatim, never mutated tool.inputSchema = spec.input_schema if spec.output_schema is not None: tool.outputSchema = spec.output_schema - # Rebuild the result rather than mutate the original: nextCursor and - # any other fields the customer's handler set are carried over. - return ServerResult( - ListToolsResult( - tools=tools, - nextCursor=getattr(listed.root, "nextCursor", None), - ) - ) + # A copy of the customer's result rather than a rebuilt one: _meta + # and any extra fields their handler set survive (Result is + # extra='allow' on 1.x), exactly like the v2 adapter. + return ServerResult(listed.root.model_copy(update={"tools": tools})) except Exception as e: write_to_log( "Warning: tools/list injection failed, serving the customer's " diff --git a/src/agentcat/modules/adapters/lowlevel_v2.py b/src/agentcat/modules/adapters/lowlevel_v2.py index 8c87c1e..8571087 100644 --- a/src/agentcat/modules/adapters/lowlevel_v2.py +++ b/src/agentcat/modules/adapters/lowlevel_v2.py @@ -225,18 +225,37 @@ def original(method: str) -> Any: """ return state.get(f"orig_{method}") - def advertised_tools(result: Any, options: Any) -> list[Any] | None: + def advertised_tools( + result: Any, options: Any + ) -> tuple[list[Any], set[int]] | None: """Deep copies of the listed tools, plus get_more_tools when enabled. None when the handler returned something with no tool list to inject into (a raw dict, an error shape), which the caller serves untouched. - Copies because the injection pipeline rewrites schemas in place. + Copies because the injection pipeline rewrites schemas in place. A + tool whose copy fails is carried through VERBATIM — the customer's + original object, never handed to the pipeline so it is never mutated + — and its id() lands in the returned skip set so the callers exclude + it from injection; one uncopyable tool must not take down the whole + listing (or, on the rebuild path, brand the call's arguments). """ nonlocal agentcat_advertises_get_more_tools listed = getattr(result, "tools", None) if not isinstance(listed, list): return None - tools = [tool.model_copy(deep=True) for tool in listed] + tools: list[Any] = [] + skipped: set[int] = set() + for tool in listed: + try: + tools.append(tool.model_copy(deep=True)) + except Exception as e: + write_to_log( + "Warning: could not copy tool " + f"'{getattr(tool, 'name', '')}' for injection; " + f"serving it verbatim without handle parameters - {e}" + ) + tools.append(tool) + skipped.add(id(tool)) customer_owns_get_more_tools = any( getattr(tool, "name", None) == GET_MORE_TOOLS_NAME for tool in tools ) @@ -247,11 +266,16 @@ def advertised_tools(result: Any, options: Any) -> list[Any] | None: # context pass skips it by name, so early placement cannot double-inject. if agentcat_advertises_get_more_tools: tools.append(_make_get_more_tools()) - return tools + return tools, skipped - def specs_for(tools: list[Any]) -> list[ToolSpec]: + def specs_for(tools: list[Any], skipped: set[int]) -> list[ToolSpec | None]: + """Specs aligned index-for-index with `tools`; None for skipped ones.""" return [ - ToolSpec(tool.name, tool.input_schema, getattr(tool, "output_schema", None)) + None + if id(tool) in skipped + else ToolSpec( + tool.name, tool.input_schema, getattr(tool, "output_schema", None) + ) for tool in tools ] @@ -261,11 +285,21 @@ def empty_list_params() -> Any: The registered params type is all-optional (``PaginatedRequestParams``), which is what the runner would hand a handler for a request that carried none — so a customer handler reading ``params.cursor`` sees the - same thing it always does. + same thing it always does. A bare-callable registration carries no + params_type; the real model is the fallback then, NOT None — a + customer list handler that dereferences its params must not crash the + rebuild (and with it, the call's argument strip). """ params_type = getattr(_entry(server, LIST_METHOD), "params_type", None) + if params_type is None: + try: + from mcp.types import PaginatedRequestParams + + return PaginatedRequestParams() + except Exception: + return None try: - return params_type() if params_type is not None else None + return params_type() except Exception: return None @@ -273,12 +307,15 @@ async def wrapped_list(ctx: Any, params: Any) -> Any: result = await original(LIST_METHOD)(ctx, params) tracking = current_data() try: - tools = advertised_tools(result, tracking.options) - if tools is None: + advertised = advertised_tools(result, tracking.options) + if advertised is None: return result - specs = specs_for(tools) + tools, skipped = advertised + specs = specs_for(tools, skipped) injected = build_injected_schemas( - specs, tracking.options, tracking.reported_conflicts + [spec for spec in specs if spec is not None], + tracking.options, + tracking.reported_conflicts, ) tracking.injected_params_registry = injected.injected_params tracking.output_injection_registry = injected.output_injected @@ -287,6 +324,8 @@ async def wrapped_list(ctx: Any, params: Any) -> Any: # one did not see. tracking.declared_session_params |= injected.declared_session_params for tool, spec in zip(tools, specs, strict=True): + if spec is None: + continue # uncopyable tool: served verbatim, never mutated tool.input_schema = spec.input_schema if spec.output_schema is not None: tool.output_schema = spec.output_schema @@ -317,8 +356,11 @@ async def rebuild() -> list[ToolSpec]: if list_handler is None: return [] listed = await list_handler(ctx, empty_list_params()) - tools = advertised_tools(listed, current_data().options) - return specs_for(tools) if tools is not None else [] + advertised = advertised_tools(listed, current_data().options) + if advertised is None: + return [] + tools, skipped = advertised + return [spec for spec in specs_for(tools, skipped) if spec is not None] # Runs first: on an instance that never served a listing this rebuilds # the registries, which is also what settles whether the customer ships diff --git a/src/agentcat/modules/callpath.py b/src/agentcat/modules/callpath.py index a2e5a00..1ad9b02 100644 --- a/src/agentcat/modules/callpath.py +++ b/src/agentcat/modules/callpath.py @@ -119,7 +119,9 @@ async def resolve_call( data.project_id, request, extra, - injected_parameter_names(tool_name, data.injected_params_registry), + injected_parameter_names( + tool_name, data.injected_params_registry, raw_arguments, data.options + ), tool_name not in data.declared_session_params, ) actor = await resolve_identity(data, request, extra) @@ -152,9 +154,12 @@ async def get_stripped_arguments( `tools/list` rebuilds the registries on demand from the adapter's list source (§6.3); the injection pipeline is deterministic, so a rebuilt registry matches what any listing instance advertised. Only a failed - rebuild falls back to the heuristic strip — and it clears the - output-injection registry, so the structured mirror stops gating on - knowledge we no longer have (§3.4b). + rebuild falls back to the shape+config-aware strip (see + `injected_parameter_names`): a name is removed only when the enabled + options would have injected it AND, for `session_id`, the value matches + our minted shape — a customer-declared parameter rides through to their + handler. The fallback also clears the output-injection registry, so the + structured mirror stops gating on knowledge we no longer have (§3.4b). """ registry = data.injected_params_registry if registry is None and rebuild is not None: @@ -182,7 +187,7 @@ async def get_stripped_arguments( "Rebuilt injection registries on demand " "(tools/call before tools/list on this instance)" ) - return strip_injected_arguments(tool_name, raw_arguments, registry) + return strip_injected_arguments(tool_name, raw_arguments, registry, options) def detect_mrtr( diff --git a/src/agentcat/modules/diagnostics.py b/src/agentcat/modules/diagnostics.py index 914fbf5..d03ece1 100644 --- a/src/agentcat/modules/diagnostics.py +++ b/src/agentcat/modules/diagnostics.py @@ -234,7 +234,7 @@ def capture(entry: str) -> None: pass -def flush_diagnostics() -> None: +def flush_diagnostics(timeout: float = 5.0) -> None: """Swap out the buffer and POST it fire-and-forget. Never raises.""" try: if not _enabled: @@ -267,7 +267,9 @@ def flush_diagnostics() -> None: if token: headers["Authorization"] = f"Bearer {token}" - requests.post(_resolve_endpoint(), json=payload, headers=headers, timeout=5) + requests.post( + _resolve_endpoint(), json=payload, headers=headers, timeout=timeout + ) except Exception: # fire-and-forget: never propagate diagnostics network errors pass @@ -329,5 +331,20 @@ def _build_record_for_test(entry: str) -> dict[str, Any]: return _build_record(entry) +def _flush_at_exit() -> None: + """Exit-time flush, hard-bounded so the customer's shutdown is never held + up: skip without even taking the lock when there is nothing buffered, and + cap the POST at 2s (requests applies the timeout per phase — connect, + then between bytes — so this approximates, not guarantees, 2s wall clock). + This is the only atexit hook the SDK registers. + """ + try: + if not _enabled or not _buffer: + return + flush_diagnostics(timeout=2.0) + except Exception: + pass + + # Flush whatever is buffered on interpreter exit (covers non-destroy() paths). -atexit.register(flush_diagnostics) +atexit.register(_flush_at_exit) diff --git a/src/agentcat/modules/event_queue.py b/src/agentcat/modules/event_queue.py index a10366f..ce8749a 100644 --- a/src/agentcat/modules/event_queue.py +++ b/src/agentcat/modules/event_queue.py @@ -1,14 +1,17 @@ -"""Event queue implementation for AgentCat.""" +"""Event queue implementation for AgentCat. + +Process-safety contract: importing this module must be side-effect free +beyond object construction — no threads, no signal handlers, no atexit +hooks. Workers start lazily on first publish, are always daemon, and are +never drained at interpreter exit: telemetry may be lost on shutdown, the +customer's process may never be delayed or redirected by it. +""" -import atexit import queue -import signal -import os import sys import threading import time from datetime import datetime, timezone -from concurrent.futures import ThreadPoolExecutor from typing import Any, Optional, TYPE_CHECKING if TYPE_CHECKING: @@ -29,6 +32,11 @@ # instead of rebuilt per event inside a per-server session cache. SDK_LANGUAGE = f"Python {sys.version_info.major}.{sys.version_info.minor}" +# Bound on a single publish HTTP attempt so a black-holed connection can +# wedge a worker for at most this long. Lives here, not constants.py — that +# file is byte-parity with the TS SDK and this knob is Python-only. +PUBLISH_TIMEOUT_SECONDS = 10 + class EventQueue: """Manages event queue and sending to AgentCat API.""" @@ -50,12 +58,30 @@ def __init__(self, api_client=None): self._shutdown = False self._shutdown_event = threading.Event() - # Thread pool for processing events - self.executor = ThreadPoolExecutor(max_workers=self.concurrency) - - # Start worker thread - self.worker_thread = threading.Thread(target=self._worker, daemon=True) - self.worker_thread.start() + # Workers start lazily on first add() so constructing the queue — + # which happens at module import — spawns no threads and is safe + # from any thread, main or not. + self._lock = threading.Lock() + self._workers: list[threading.Thread] = [] + self._workers_started = False + self._active = 0 # workers currently inside _process_event + + def _ensure_workers(self) -> None: + """Start the consumer threads on first use.""" + if self._workers_started: + return + with self._lock: + if self._workers_started or self._shutdown: + return + for i in range(self.concurrency): + t = threading.Thread( + target=self._worker, + daemon=True, + name=f"agentcat-event-worker-{i}", + ) + t.start() + self._workers.append(t) + self._workers_started = True def configure(self, api_base_url: str) -> None: """Reconfigure the API client with a new base URL.""" @@ -69,6 +95,7 @@ def add(self, event: UnredactedEvent) -> None: write_to_log("Queue is shutting down, event dropped") return + self._ensure_workers() try: # Try to add without blocking self.queue.put_nowait(event) @@ -79,32 +106,26 @@ def add(self, event: UnredactedEvent) -> None: ) def _worker(self) -> None: - """Worker thread that processes events from the queue.""" + """Consumer thread: pulls events straight off the bounded queue. + + No intermediate executor — when every worker is busy the bounded + queue fills and add() drops, so memory is genuinely capped at + max_queue_size events. + """ while not self._shutdown_event.is_set(): try: - # Wait for an event with timeout event = self.queue.get(timeout=0.1) - - # Submit event processing to thread pool - # The executor will queue it if all workers are busy - try: - self.executor.submit(self._process_event, event) - except Exception as e: - write_to_log(f"Failed to submit event for processing: {e}") - # Put the event back in the queue if possible - try: - self.queue.put_nowait(event) - except queue.Full: - write_to_log( - f"Could not requeue event {event.id or 'unknown'} - queue full" - ) - except queue.Empty: continue + with self._lock: + self._active += 1 + try: + self._process_event(event) except Exception as e: write_to_log(f"Worker thread error (continuing): {e}") - # Sleep briefly to avoid tight error loops - time.sleep(0.1) + finally: + with self._lock: + self._active -= 1 def _process_event(self, event: UnredactedEvent) -> None: """Process a single event.""" @@ -117,7 +138,9 @@ def _process_event(self, event: UnredactedEvent) -> None: # The redacted event is already the full event object, not a dict event = redacted_event event.redaction_fn = None # Clear the function to avoid reprocessing - except Exception as error: + except (Exception, SystemExit) as error: + # SystemExit included: a customer hook calling sys.exit() must + # not kill the worker thread. write_to_log( f"WARNING: Dropping event {event.id or 'unknown'} due to redaction failure: {error}" ) @@ -159,8 +182,12 @@ def _process_event(self, event: UnredactedEvent) -> None: def _send_event(self, event: Event, retries: int = 0) -> None: """Send event to API.""" try: - # Synchronous API call - self.api_client.publish_event(publish_event_request=event) + # Synchronous API call, bounded so a black-holed connection + # cannot wedge this worker indefinitely + self.api_client.publish_event( + publish_event_request=event, + _request_timeout=PUBLISH_TIMEOUT_SECONDS, + ) write_to_log( f"Successfully sent event {event.id} | {event.event_type} | " f"session {event.session_id} | {event.project_id} | " @@ -191,40 +218,33 @@ def _send_event(self, event: Event, retries: int = 0) -> None: def get_stats(self) -> dict[str, Any]: """Get queue stats for monitoring.""" + with self._lock: + active = self._active return { "queueLength": self.queue.qsize(), - "activeRequests": self.executor._threads.__len__(), # Number of active threads - "isProcessing": self.executor._threads.__len__() > 0, + "activeRequests": active, + "isProcessing": active > 0, } def destroy(self) -> None: - """Graceful shutdown - wait for active requests.""" - # Stop accepting new events + """Stop workers and stop accepting events. Bounded; for tests and + explicit shutdown — nothing registers it at exit anymore. A worker + wedged in a customer hook outlives the join as a daemon and dies + with the process. + """ self._shutdown = True self._shutdown_event.set() - # Determine wait time based on queue state - if self.queue.qsize() > 0: - # If there are events in queue, wait 5 seconds - wait_time = 5.0 - write_to_log( - f"Shutting down with {self.queue.qsize()} events in queue, waiting up to {wait_time}s" - ) - else: - # If queue is empty, just wait 1 second for in-flight requests - wait_time = 1.0 - write_to_log(f"Queue empty, waiting {wait_time}s for in-flight requests") - - # Wait for the specified time - time.sleep(wait_time) - - # Shutdown executor, cancelling any queued (not yet running) tasks - self.executor.shutdown(wait=True, cancel_futures=True) + # Shared 1s budget across all joins, never per-thread. + deadline = time.monotonic() + 1.0 + for t in self._workers: + if t is threading.current_thread(): + continue # destroy() called from a worker + t.join(timeout=max(0.0, deadline - time.monotonic())) - # Log final status remaining = self.queue.qsize() if remaining > 0: - write_to_log(f"Shutdown complete. {remaining} events were not processed.") + write_to_log(f"Event queue destroyed with {remaining} events unprocessed.") # Flush any buffered SDK diagnostics on the way out. Lazy import to avoid # an import cycle; never let diagnostics break shutdown. @@ -255,26 +275,13 @@ def set_telemetry_manager(manager: Optional["TelemetryManager"]) -> None: ) -# Global event queue instance +# Global event queue instance. Constructing it starts no threads (workers +# are lazy), so this module is importable from any thread. The SDK installs +# no signal handlers and no exit hooks for events: the customer's process +# owns its own shutdown, and undelivered telemetry is dropped by design. event_queue = EventQueue() -def _shutdown_handler(signum, frame): - """Handle shutdown signals.""" - - write_to_log("Received shutdown signal, gracefully shutting down...") - - # Reset signal handlers to default behavior to avoid recursive calls - signal.signal(signal.SIGINT, signal.SIG_DFL) - signal.signal(signal.SIGTERM, signal.SIG_DFL) - - # Perform graceful shutdown - event_queue.destroy() - - # Force exit after graceful shutdown - os._exit(0) - - def set_event_queue(new_queue: EventQueue) -> None: """Replace the global event queue instance (for testing).""" global event_queue @@ -283,12 +290,6 @@ def set_event_queue(new_queue: EventQueue) -> None: event_queue = new_queue -# Register shutdown handlers -signal.signal(signal.SIGINT, _shutdown_handler) -signal.signal(signal.SIGTERM, _shutdown_handler) -atexit.register(lambda: event_queue.destroy()) - - def publish_event(server: Any, event: UnredactedEvent) -> None: """Publish an event to the queue. diff --git a/src/agentcat/modules/exceptions.py b/src/agentcat/modules/exceptions.py index 6c6fc5f..8f1c275 100644 --- a/src/agentcat/modules/exceptions.py +++ b/src/agentcat/modules/exceptions.py @@ -12,7 +12,44 @@ from agentcat.modules.constants import MAX_EXCEPTION_CHAIN_DEPTH, MAX_STACK_FRAMES +def _safe_str(value: Any) -> str: + """str() for values whose __str__ may itself raise (customer exception + classes are arbitrary code). Degrades str -> repr -> placeholder.""" + try: + return str(value) + except Exception: + try: + return repr(value) + except Exception: + return f"" + + def capture_exception(exc: BaseException | Any) -> ErrorData: + """Never-raise entry point around _capture_exception. + + It runs on the request path at call sites outside every other guard + (evaluated as the `error=` argument before publish's own containment), so + an escape here would replace the customer's result or original error on + the wire. Anything the detailed capture chokes on — hostile __str__, + deleted working directory, raising properties — degrades to a minimal + ErrorData instead. + """ + try: + return _capture_exception(exc) + except Exception: + error: ErrorData = { + "message": "Error details unavailable (exception capture failed)", + "type": None, + "platform": "python", + } + try: + error["type"] = type(exc).__name__ # type() runs no customer code + except Exception: + pass + return error + + +def _capture_exception(exc: BaseException | Any) -> ErrorData: """ Captures detailed exception information including stack traces and cause chains. @@ -38,7 +75,7 @@ def capture_exception(exc: BaseException | Any) -> ErrorData: } error_data: ErrorData = { - "message": str(exc), + "message": _safe_str(exc), "type": type(exc).__name__, "platform": "python", } @@ -75,31 +112,40 @@ def parse_python_traceback(tb: types.TracebackType | None) -> list[StackFrame]: count = 0 while current_tb is not None and count < MAX_STACK_FRAMES: - frame = current_tb.tb_frame - abs_path = os.path.abspath(frame.f_code.co_filename) - try: - module = frame.f_globals.get("__name__") - except (AttributeError, KeyError): - module = None - - in_app = is_in_app(abs_path) - - frame_dict: StackFrame = { - "filename": filename_for_module(module, abs_path), - "abs_path": abs_path, - "function": frame.f_code.co_name or "", - "module": module or "", - "lineno": current_tb.tb_lineno, - "in_app": in_app, - } - - if in_app: - context = extract_context_line(abs_path, current_tb.tb_lineno) - if context: - frame_dict["context_line"] = context - - frames.append(frame_dict) + frame = current_tb.tb_frame + try: + # abspath calls os.getcwd() for relative filenames + # ('', exec'd frames), which raises when the process + # working directory has been deleted — keep the raw path then. + abs_path = os.path.abspath(frame.f_code.co_filename) + except Exception: + abs_path = frame.f_code.co_filename + + try: + module = frame.f_globals.get("__name__") + except (AttributeError, KeyError): + module = None + + in_app = is_in_app(abs_path) + + frame_dict: StackFrame = { + "filename": filename_for_module(module, abs_path), + "abs_path": abs_path, + "function": frame.f_code.co_name or "", + "module": module or "", + "lineno": current_tb.tb_lineno, + "in_app": in_app, + } + + if in_app: + context = extract_context_line(abs_path, current_tb.tb_lineno) + if context: + frame_dict["context_line"] = context + + frames.append(frame_dict) + except Exception: + pass # one unreadable frame skips, the rest of the stack survives current_tb = current_tb.tb_next count += 1 @@ -253,41 +299,48 @@ def unwrap_exception_chain(exc: BaseException) -> list[ChainedErrorData]: seen_ids.add(id(exc)) while current is not None and depth < MAX_EXCEPTION_CHAIN_DEPTH: - if getattr(current, "__suppress_context__", False): - next_exc = getattr(current, "__cause__", None) - else: - next_exc = getattr(current, "__context__", None) - - if next_exc is None: - break - - exc_id = id(next_exc) - if exc_id in seen_ids: - break - seen_ids.add(exc_id) - - if not isinstance(next_exc, BaseException): - chain.append( - { - "message": stringify_non_exception(next_exc), - "type": None, - } - ) + try: + # Guarded as a block: __cause__/__context__/__suppress_context__ + # can be hostile descriptors on exception subclasses, and a + # chained link's __str__ was never exercised by the framework — + # a poisoned link truncates the chain instead of raising. + if getattr(current, "__suppress_context__", False): + next_exc = getattr(current, "__cause__", None) + else: + next_exc = getattr(current, "__context__", None) + + if next_exc is None: + break + + exc_id = id(next_exc) + if exc_id in seen_ids: + break + seen_ids.add(exc_id) + + if not isinstance(next_exc, BaseException): + chain.append( + { + "message": stringify_non_exception(next_exc), + "type": None, + } + ) + break + + chained_data: ChainedErrorData = { + "message": _safe_str(next_exc), + "type": type(next_exc).__name__, + } + + if next_exc.__traceback__: + chained_data["frames"] = parse_python_traceback(next_exc.__traceback__) + chained_data["stack"] = format_exception_string(next_exc) + + chain.append(chained_data) + current = next_exc + depth += 1 + except Exception: break - chained_data: ChainedErrorData = { - "message": str(next_exc), - "type": type(next_exc).__name__, - } - - if next_exc.__traceback__: - chained_data["frames"] = parse_python_traceback(next_exc.__traceback__) - chained_data["stack"] = format_exception_string(next_exc) - - chain.append(chained_data) - current = next_exc - depth += 1 - # TODO: Add ExceptionGroup support for Python 3.11+ # ExceptionGroups have .exceptions attribute with multiple exceptions @@ -310,7 +363,7 @@ def format_exception_string(exc: BaseException) -> str: try: return "".join(traceback.format_exception(type(exc), exc, exc.__traceback__)) except Exception: - return f"{type(exc).__name__}: {exc}" + return f"{type(exc).__name__}: {_safe_str(exc)}" def is_call_tool_result(value: Any) -> bool: @@ -339,11 +392,17 @@ def is_call_tool_result(value: Any) -> bool: Returns: True if value is a CallToolResult object """ - return ( - value is not None - and (hasattr(value, "is_error") or hasattr(value, "isError")) - and isinstance(getattr(value, "content", None), list) - ) + try: + # Whole predicate guarded: `content` may be an arbitrary property + # (lazy proxied results) that raises something other than + # AttributeError, which getattr's default would not suppress. + return ( + value is not None + and (hasattr(value, "is_error") or hasattr(value, "isError")) + and isinstance(getattr(value, "content", None), list) + ) + except Exception: + return False def capture_call_tool_result_error(result: Any) -> ErrorData: @@ -410,7 +469,7 @@ def stringify_non_exception(value: Any) -> str: return json.dumps(value) except Exception: - return str(value) + return _safe_str(value) # The inner-tap trio that used to live here — `store_captured_error` / diff --git a/src/agentcat/modules/handles.py b/src/agentcat/modules/handles.py index 8d3f7f4..1c11d5b 100644 --- a/src/agentcat/modules/handles.py +++ b/src/agentcat/modules/handles.py @@ -27,7 +27,7 @@ mint_back_confirmed, mint_back_session_line, ) -from agentcat.modules.hooks import await_hook_result +from agentcat.modules.hooks import run_hook from agentcat.modules.logging import write_to_log from agentcat.thirdparty.ksuid import Ksuid from agentcat.types import AgentCatOptions @@ -149,7 +149,7 @@ async def resolve_handles( if callable(hook): try: - value = await await_hook_result(hook(request, extra), "resolve_session_id") + value = await run_hook(hook, "resolve_session_id", request, extra) except Exception as e: # hook errors mint silently write_to_log(f"Warning: resolve_session_id hook raised: {e}") value = None diff --git a/src/agentcat/modules/hooks.py b/src/agentcat/modules/hooks.py index 2d706f3..031cbca 100644 --- a/src/agentcat/modules/hooks.py +++ b/src/agentcat/modules/hooks.py @@ -10,13 +10,21 @@ `isinstance(result, UserIdentity)` check and published the call anonymously. The customer saw no error — only an event with no actor. -Two entry points, because the SDK runs hooks from two places: - -* `await_hook_result` — the request path. Every adapter reaches the hooks - through `await resolve_call(...)` and `await publish_tool_call_event(...)`, - on every mcp and fastmcp version in the compatibility matrix, so there is a - running loop and awaiting is all it takes. -* `drive_hook_result` — the publish worker (`event_queue.EventQueue._worker`), +Three entry points, because the SDK runs hooks from three places: + +* `run_hook` — the request path's containment boundary. The hook CALL runs on + an anyio worker thread (a blocking sync hook stalls only its own request, + never the server's event loop — the same offload both FastMCP generations + give customers' sync tool bodies), awaitable results are awaited inline, + and the whole execution sits under a hard timeout. Every failure mode — + raise, wrong thread-behavior, timeout, even SystemExit or a spontaneous + CancelledError — surfaces as `HookExecutionError`, a plain Exception, so + each call site's own `except Exception` degradation rule applies unchanged. + Genuine task cancellation (client disconnect) still propagates. +* `await_hook_result` — resolves a hook's RETURN VALUE on a path with a + running loop. `run_hook` uses it internally; adapters no longer call it + directly for customer hooks. +* `drive_hook_result` — the publish worker (`event_queue.EventQueue`), a daemon THREAD with no event loop of its own. Redaction runs there and cannot await, so an awaitable has to be driven to completion with a loop of its own. @@ -37,13 +45,30 @@ import asyncio import inspect -from collections.abc import Awaitable +from collections.abc import Awaitable, Callable from typing import Any, TypeVar, cast +import anyio +import anyio.to_thread + from agentcat.modules.logging import write_to_log T = TypeVar("T") +# Hard cap on one hook execution. Generous for a lookup, small enough that a +# wedged hook costs one request its metadata instead of stalling the call. +HOOK_TIMEOUT_SECONDS = 5.0 + +# An async hook may legitimately return an awaitable of an awaitable (a hook +# returning an asyncio.Task of a cached lookup); unwrap a few hops, not forever. +_MAX_AWAIT_HOPS = 3 + + +class HookExecutionError(Exception): + """A customer hook failed, timed out, or raised something that must not + ride the request path. Deliberately a plain Exception: every call site's + existing `except Exception` degradation rule catches it unchanged.""" + # Both signatures below spell `T | Awaitable[Any]` inline rather than sharing an # alias. A generic alias needs `Union[T, ...]` — mypy rejects a TypeVar as the # target of a PEP-604 alias — and ruff's UP007 then rewrites that `Union` back @@ -73,6 +98,84 @@ def _report(hook_name: str, error: Exception) -> None: ) +async def run_hook( + hook: Callable[..., Any], + hook_name: str, + request: Any, + extra: Any, + timeout: float = HOOK_TIMEOUT_SECONDS, +) -> Any: + """Execute a customer hook with full containment. The request-path entry. + + Threading: the CALL runs via `anyio.to_thread.run_sync`, so a sync hook + that blocks (a DB lookup, an HTTP call) suspends only this request — the + loop keeps serving every other call. `abandon_on_cancel=True` lets the + timeout fire while the hook still blocks; the abandoned hook keeps running + on its daemon worker thread with its result discarded, and can never hold + the process open. An async hook's coroutine is awaited inline on the loop + (same as before), under the same timeout. + + Exceptions-as-values across the thread boundary make cancellation + unambiguous: a `CancelledError`/`SystemExit` the hook itself raises comes + back as data and becomes `HookExecutionError`, so any `CancelledError` + surfacing from the awaits here is, by construction, the enclosing task + being cancelled — and is re-raised. (On the async-hook path, Python 3.11+ + can additionally distinguish a spontaneous CancelledError via + `Task.cancelling()`; on 3.10 it is conservatively re-raised.) + + Behavior notes, both documented in MIGRATION.md: a sync hook that calls + asyncio APIs must become `async def` (worker threads have no running + loop), and a hook slower than `timeout` degrades that call exactly like a + hook that raised. + """ + + def _call_contained() -> tuple[str, Any]: + try: + return ("ok", hook(request, extra)) + except KeyboardInterrupt: + raise + except BaseException as e: # noqa: BLE001 — the containment boundary + return ("raised", e) + + try: + with anyio.fail_after(timeout): + status, payload = await anyio.to_thread.run_sync( + _call_contained, abandon_on_cancel=True + ) + if status == "raised": + raise HookExecutionError( + f"{hook_name} hook raised {type(payload).__name__}: {payload}" + ) from payload + value = payload + hops = 0 + while inspect.isawaitable(value) and hops < _MAX_AWAIT_HOPS: + value = await await_hook_result(value, hook_name) + hops += 1 + return value + except HookExecutionError: + raise + except TimeoutError: + write_to_log( + f"Warning: {hook_name} hook timed out after {timeout}s; " + "proceeding without its result" + ) + raise HookExecutionError(f"{hook_name} hook timed out") from None + except asyncio.CancelledError: + task = asyncio.current_task() + cancelling = getattr(task, "cancelling", None) + if callable(cancelling) and cancelling() == 0: + # 3.11+: no external cancel is pending, so the async hook raised + # CancelledError spontaneously — contained, not propagated. + raise HookExecutionError( + f"{hook_name} hook raised CancelledError outside a cancellation" + ) from None + raise # genuine task cancellation (or 3.10, which cannot probe) + except (Exception, SystemExit) as e: + raise HookExecutionError( + f"{hook_name} hook raised {type(e).__name__}: {e}" + ) from e + + async def await_hook_result(value: T | Awaitable[Any], hook_name: str) -> T: """Resolve a hook's return value on a path that has a running loop. @@ -111,6 +214,18 @@ def drive_hook_result(value: T | Awaitable[Any], hook_name: str) -> T: except Exception as e: _report(hook_name, e) raise + except (SystemExit, asyncio.CancelledError) as e: + # On a worker thread there is no enclosing task, so either of these + # from the awaitable is definitionally the hook's own doing. Convert + # to a plain Exception so the caller's drop-the-event rule applies + # instead of the worker thread dying. + write_to_log( + f"Warning: {hook_name} returned an awaitable that raised " + f"{type(e).__name__}; treating as hook failure" + ) + raise HookExecutionError( + f"{hook_name} hook raised {type(e).__name__}" + ) from e async def _resolved(awaitable: Any) -> Any: diff --git a/src/agentcat/modules/identify.py b/src/agentcat/modules/identify.py index 2852784..4a541ed 100644 --- a/src/agentcat/modules/identify.py +++ b/src/agentcat/modules/identify.py @@ -1,6 +1,6 @@ from typing import Any -from agentcat.modules.hooks import await_hook_result +from agentcat.modules.hooks import run_hook from agentcat.modules.logging import write_to_log from agentcat.types import AgentCatData, UserIdentity @@ -25,9 +25,7 @@ async def resolve_identity( return None try: - result = await await_hook_result( - data.options.identify(request, extra), "identify" - ) + result = await run_hook(data.options.identify, "identify", request, extra) except Exception as e: write_to_log(f"Error occurred during user identification: {e}") return None diff --git a/src/agentcat/modules/injection.py b/src/agentcat/modules/injection.py index fb0842b..5e62095 100644 --- a/src/agentcat/modules/injection.py +++ b/src/agentcat/modules/injection.py @@ -342,15 +342,30 @@ def build_injected_schemas( def injected_parameter_names( - tool_name: str, registry: dict[str, set[str]] | None + tool_name: str, + registry: dict[str, set[str]] | None, + arguments: dict[str, Any] | None = None, + options: AgentCatOptions | None = None, ) -> frozenset[str]: """The parameter names AgentCat injected into `tool_name`. With a registry, a listed tool reports exactly its recorded entry and an unlisted tool reports nothing (it was never advertised through the pipeline). Without one (tools/call before any tools/list, and the rebuild - failed) fall back to all three names — except get_more_tools' bespoke - context, which is a real parameter. + failed) the fallback mirrors `build_injected_schemas`' own inject gates + instead of blanket-claiming all three names, so a customer-declared + parameter is only ever at risk when its name AND shape AND the enabled + options all collide: + + - `session_id` counts as ours iff prompted-mode tracing would have + injected it (`enable_tracing` on, no `resolve_session_id` hook) AND the + value the agent sent is absent or matches our minted `ses_` KSUID shape. + A non-minted value is presumed the customer's own parameter: it is not + stripped, and — because this same set feeds `resolve_handles` — it is + not branded invalid or corrected on the wire either. + - `agent_id` counts as ours iff agent tracking would have injected it. + - `context` counts as ours iff `enable_tool_call_context` is on + (get_more_tools' bespoke context is always a real parameter). Single source of truth for both consumers, deliberately: what `strip_injected_arguments` removes before the customer's handler runs is @@ -363,18 +378,38 @@ def injected_parameter_names( """ if registry is not None: return frozenset(registry.get(tool_name, ())) - if tool_name == GET_MORE_TOOLS_NAME: - return frozenset((SESSION_ID_PARAM, AGENT_ID_PARAM)) - return frozenset(_ALL_INJECTABLE) + + # Local import: handles.py does not import this module, so no cycle. + from agentcat.modules.handles import is_valid_session_id + + opts = options if options is not None else AgentCatOptions() + args = arguments or {} + + names: set[str] = set() + if opts.enable_tracing and opts.resolve_session_id is None: + value = args.get(SESSION_ID_PARAM) + looks_minted = value is None or ( + isinstance(value, str) and is_valid_session_id(value.strip()) + ) + if looks_minted: + names.add(SESSION_ID_PARAM) + if opts.enable_tracing and opts.enable_agent_tracking: + names.add(AGENT_ID_PARAM) + if opts.enable_tool_call_context and tool_name != GET_MORE_TOOLS_NAME: + names.add(CONTEXT_PARAM) + return frozenset(names) def strip_injected_arguments( tool_name: str, arguments: dict[str, Any], registry: dict[str, set[str]] | None, + options: AgentCatOptions | None = None, ) -> dict[str, Any]: """Return a new dict with ONLY the params AgentCat injected removed.""" - names: Iterable[str] = injected_parameter_names(tool_name, registry) + names: Iterable[str] = injected_parameter_names( + tool_name, registry, arguments, options + ) cleaned = dict(arguments) for name in names: cleaned.pop(name, None) diff --git a/src/agentcat/modules/internal.py b/src/agentcat/modules/internal.py index 05b1470..2ba3d8f 100644 --- a/src/agentcat/modules/internal.py +++ b/src/agentcat/modules/internal.py @@ -9,7 +9,7 @@ # `_get_server_key`. detection.py imports nothing from this module, so this # does not close a cycle. from .detection import _probe as _attribute_present -from .hooks import await_hook_result +from .hooks import run_hook from .logging import write_to_log from .validation import validate_tags @@ -112,7 +112,7 @@ async def resolve_event_tags( return None try: - result = await await_hook_result(callback(request, extra), "event_tags") + result = await run_hook(callback, "event_tags", request, extra) except Exception as e: write_to_log(f"event_tags callback error: {e}") return None @@ -136,7 +136,7 @@ async def resolve_event_properties( return None try: - result = await await_hook_result(callback(request, extra), "event_properties") + result = await run_hook(callback, "event_properties", request, extra) except Exception as e: write_to_log(f"event_properties callback error: {e}") return None diff --git a/tests/e2e/conftest.py b/tests/e2e/conftest.py index 0cf0524..a726a45 100644 --- a/tests/e2e/conftest.py +++ b/tests/e2e/conftest.py @@ -27,7 +27,7 @@ def capture_queue() -> List[Any]: captured: List[Any] = [] mock = MagicMock() - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured.append(publish_event_request) mock.publish_event = MagicMock(side_effect=capture_event) diff --git a/tests/test_async_hooks.py b/tests/test_async_hooks.py index 4e305b8..555d355 100644 --- a/tests/test_async_hooks.py +++ b/tests/test_async_hooks.py @@ -98,9 +98,17 @@ async def hook(_request: Any, _extra: Any) -> Any: def _task(value: Any): - """A Task, which only exists because the hook is called inside a loop.""" + """A Task-returning hook, async because Tasks only exist on a loop. + + Since run_hook, the hook CALL runs on a worker thread with no running + loop, so a SYNC hook can no longer call asyncio APIs — that is a + documented v2 behavior change (MIGRATION.md). An async hook's body runs + on the loop as always, and its returned Task pins the awaitable-unwrap + regression: run_hook must await the coroutine AND then the Task it + returned, not assign either into the event verbatim. + """ - def hook(_request: Any, _extra: Any) -> Any: + async def hook(_request: Any, _extra: Any) -> Any: return asyncio.ensure_future(_coroutine(value)(None, None)) return hook diff --git a/tests/test_callpath.py b/tests/test_callpath.py index 1179d55..b23ee61 100644 --- a/tests/test_callpath.py +++ b/tests/test_callpath.py @@ -259,6 +259,9 @@ async def test_rebuild_failure_falls_back_to_heuristic(monkeypatch): async def broken_rebuild() -> list[ToolSpec]: raise RuntimeError("list source gone") + # "s" is not a minted-shape handle: on the degraded path it is presumed + # the customer's own parameter and rides through to their handler; only + # context — which default options would have injected — is stripped. out = await get_stripped_arguments( data, data.options, @@ -266,10 +269,21 @@ async def broken_rebuild() -> list[ToolSpec]: {"q": 1, "session_id": "s", "context": "c"}, broken_rebuild, ) - assert out == {"q": 1} + assert out == {"q": 1, "session_id": "s"} assert data.output_injection_registry is None # mirror gate bypassed assert any("list source gone" in entry for entry in logged) + # A minted-shape value is ours even without a registry. + data2 = make_data() + out2 = await get_stripped_arguments( + data2, + data2.options, + "t", + {"q": 1, "session_id": sid("mine"), "context": "c"}, + broken_rebuild, + ) + assert out2 == {"q": 1} + # Two calls can race the rebuild on a server that never served tools/list. # A loser's failure must not wipe the registries a winner already stored: every @@ -303,14 +317,26 @@ async def good_rebuild() -> list[ToolSpec]: # No rebuild hook at all (adapter has no list source): straight to the -# heuristic, and get_more_tools keeps its own `context` parameter (§6.6). +# shape+config-aware fallback, and get_more_tools keeps its own `context` +# parameter (§6.6). async def test_strip_without_rebuild_uses_the_heuristic(): data = make_data() - raw = {"q": 1, "session_id": "s", "agent_id": "a", "context": "c"} - assert await get_stripped_arguments(data, data.options, "t", raw, None) == {"q": 1} + # Minted-shape session_id is ours; agent_id survives (tracking off by + # default); context is ours by config. + raw = {"q": 1, "session_id": sid("m"), "agent_id": "a", "context": "c"} + assert await get_stripped_arguments(data, data.options, "t", raw, None) == { + "q": 1, + "agent_id": "a", + } assert await get_stripped_arguments( data, data.options, "get_more_tools", raw, None - ) == {"q": 1, "context": "c"} + ) == {"q": 1, "agent_id": "a", "context": "c"} + # A customer-shaped session_id value survives everywhere on this path. + theirs = {"q": 1, "session_id": "TICKET-9", "context": "c"} + assert await get_stripped_arguments(data, data.options, "t", theirs, None) == { + "q": 1, + "session_id": "TICKET-9", + } # ── resolve_call ───────────────────────────────────────────────────────────── diff --git a/tests/test_diagnostics_export.py b/tests/test_diagnostics_export.py index e56b15a..ca5120b 100644 --- a/tests/test_diagnostics_export.py +++ b/tests/test_diagnostics_export.py @@ -75,3 +75,62 @@ def test_no_post_when_buffer_empty(): with patch("agentcat.modules.diagnostics.requests.post") as mock_post: diagnostics.flush_diagnostics() mock_post.assert_not_called() + + +# ── the exit-time flush is hard-bounded (audit finding 13) ─────────────────── + + +def test_flush_at_exit_with_empty_buffer_never_posts(): + """Nothing buffered: the exit hook returns instantly, no lock, no POST.""" + diagnostics.init_diagnostics("proj_1") + + with patch("agentcat.modules.diagnostics.requests.post") as mock_post: + diagnostics._flush_at_exit() + mock_post.assert_not_called() + + +def test_flush_at_exit_posts_with_a_2s_timeout(): + """Buffered records flush at exit with the tightened 2s cap, not the 5s + in-process default — customer shutdown is never held longer than that.""" + diagnostics.init_diagnostics("proj_1") + write_to_log("Warning: buffered at exit") + + with patch("agentcat.modules.diagnostics.requests.post") as mock_post: + diagnostics._flush_at_exit() + mock_post.assert_called_once() + assert mock_post.call_args.kwargs["timeout"] == 2.0 + + +def test_flush_default_timeout_is_still_5s(): + diagnostics.init_diagnostics("proj_1") + write_to_log("Warning: buffered in process") + + with patch("agentcat.modules.diagnostics.requests.post") as mock_post: + diagnostics.flush_diagnostics() + assert mock_post.call_args.kwargs["timeout"] == 5.0 + + +def test_flush_at_exit_swallows_post_failures(): + diagnostics.init_diagnostics("proj_1") + write_to_log("Warning: buffered at exit") + + with patch( + "agentcat.modules.diagnostics.requests.post", + side_effect=RuntimeError("network gone"), + ): + diagnostics._flush_at_exit() # must not raise + + +def test_the_diagnostics_hook_is_the_only_atexit_in_the_sdk(): + """The no-drain-at-exit decision, pinned: one bounded atexit hook total.""" + import pathlib + + import agentcat + + src_root = pathlib.Path(agentcat.__file__).parent + registrations = [] + for path in src_root.rglob("*.py"): + text = path.read_text() + if "atexit.register" in text: + registrations.append(path.name) + assert registrations == ["diagnostics.py"], registrations diff --git a/tests/test_event_capture_completeness.py b/tests/test_event_capture_completeness.py index 86f407a..0a8a8f1 100644 --- a/tests/test_event_capture_completeness.py +++ b/tests/test_event_capture_completeness.py @@ -35,7 +35,7 @@ async def test_event_contains_all_basic_fields(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -88,7 +88,7 @@ async def test_event_contains_client_info(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -121,7 +121,7 @@ async def test_event_contains_server_info(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -152,7 +152,7 @@ async def test_event_contains_sdk_info(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -184,7 +184,7 @@ async def test_event_contains_user_intent_from_context(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -230,7 +230,7 @@ async def test_event_contains_actor_info_after_identify(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -272,7 +272,7 @@ async def test_only_tool_call_events_are_published(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -318,7 +318,7 @@ async def test_event_ids_are_unique(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -357,7 +357,7 @@ async def test_event_duration_is_calculated(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -391,7 +391,7 @@ async def test_identify_function_integration(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -444,7 +444,7 @@ async def test_server_error_capture_in_event(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) diff --git a/tests/test_event_queue.py b/tests/test_event_queue.py index 4bc6423..5660ae9 100644 --- a/tests/test_event_queue.py +++ b/tests/test_event_queue.py @@ -1,7 +1,6 @@ """Test event queue functionality.""" import queue -import signal import threading import time from datetime import datetime, timezone @@ -16,7 +15,7 @@ class TestEventQueue: """Test EventQueue class.""" def test_init(self): - """Test EventQueue initialization.""" + """Test EventQueue initialization: construction starts no threads.""" eq = EventQueue() assert isinstance(eq.queue, queue.Queue) @@ -26,8 +25,33 @@ def test_init(self): assert eq.concurrency > 0 assert eq._shutdown is False assert isinstance(eq._shutdown_event, threading.Event) - assert eq.worker_thread.is_alive() - assert eq.worker_thread.daemon is True + # Workers are lazy: nothing runs until the first add(), so importing + # the module (which constructs the global queue) is thread-safe. + assert eq._workers == [] + assert eq._workers_started is False + + def test_workers_start_lazily_and_are_daemon(self): + """First add() starts exactly `concurrency` daemon workers.""" + eq = EventQueue() + eq._process_event = lambda event: None # never hit the network + + event = UnredactedEvent( + id="test-id", + event_type="mcp:tools/call", + project_id="project-123", + session_id="session-123", + timestamp=datetime.now(timezone.utc), + ) + eq.add(event) + + assert eq._workers_started is True + assert len(eq._workers) == eq.concurrency + assert all(t.daemon for t in eq._workers) + + eq.add(event) + assert len(eq._workers) == eq.concurrency # no growth on later adds + + eq.destroy() def test_add_event_success(self): """Test adding event to queue successfully.""" @@ -70,6 +94,7 @@ def test_add_event_queue_full(self): """Test adding event when queue is full.""" eq = EventQueue() eq.queue = queue.Queue(maxsize=2) # Small queue for testing + eq._workers_started = True # keep workers off so the queue stays full # Fill the queue event1 = UnredactedEvent( @@ -114,6 +139,7 @@ def test_add_event_queue_full_drops_new_event(self): """Test that new events are dropped when queue is full.""" eq = EventQueue() eq.queue = queue.Queue(maxsize=1) + eq._workers_started = True # keep workers off so the queue stays full # Fill the queue event1 = UnredactedEvent( @@ -291,7 +317,8 @@ def test_send_event_success(self, mock_log): eq._send_event(event) mock_api_client.publish_event.assert_called_once_with( - publish_event_request=event + publish_event_request=event, + _request_timeout=10, ) assert mock_log.call_count >= 1 # At least one success log @@ -464,12 +491,11 @@ def test_get_stats(self): assert "isProcessing" in stats assert isinstance(stats["isProcessing"], bool) - @patch("time.sleep") - def test_destroy(self, mock_sleep): - """Test graceful shutdown.""" + def test_destroy(self): + """destroy() sets flags, stops workers, and returns fast — no sleeps, + no unbounded joins.""" eq = EventQueue() - - # Add an event + eq._process_event = lambda event: None event = UnredactedEvent( id="test-id", event_type="mcp:tools/call", @@ -477,26 +503,21 @@ def test_destroy(self, mock_sleep): session_id="session-123", timestamp=datetime.now(timezone.utc), ) - eq.queue.put_nowait(event) - - # Mock executor - mock_executor = MagicMock() - eq.executor = mock_executor + eq.add(event) + start = time.monotonic() eq.destroy() + elapsed = time.monotonic() - start assert eq._shutdown is True assert eq._shutdown_event.is_set() - mock_executor.shutdown.assert_called_once() + assert elapsed < 1.5 # bounded by the shared 1s join budget - @patch("time.time") - @patch("time.sleep") @patch("agentcat.modules.event_queue.write_to_log") - def test_destroy_with_timeout(self, mock_log, mock_sleep, mock_time): - """Test destroy with events still in queue after timeout.""" + def test_destroy_logs_unprocessed_events(self, mock_log): + """Events still queued when destroy() runs are counted in the log.""" eq = EventQueue() - # Add events that won't be processed num_events = 5 for i in range(num_events): event = UnredactedEvent( @@ -506,14 +527,7 @@ def test_destroy_with_timeout(self, mock_log, mock_sleep, mock_time): session_id="session-123", timestamp=datetime.now(timezone.utc), ) - eq.queue.put_nowait(event) - - # Mock time to simulate timeout - mock_time.side_effect = [0, 0.1, 0.2, 10.0] # Exceeds timeout - - # Mock executor - mock_executor = MagicMock() - eq.executor = mock_executor + eq.queue.put_nowait(event) # no workers started: events sit there eq.destroy() @@ -552,35 +566,30 @@ def mock_process(event): @patch("agentcat.modules.event_queue.write_to_log") def test_worker_thread_exception_handling(self, mock_log): - """Test worker thread handles exceptions gracefully.""" + """A raising _process_event is logged and the workers stay alive.""" eq = EventQueue() + eq._process_event = MagicMock(side_effect=Exception("Test exception")) - # Mock executor.submit to raise an exception - with patch.object( - eq.executor, "submit", side_effect=Exception("Test exception") - ): - # Add an event - event = UnredactedEvent( - id="test-id", - event_type="mcp:tools/call", - project_id="project-123", - session_id="session-123", - timestamp=datetime.now(timezone.utc), - ) - eq.add(event) + event = UnredactedEvent( + id="test-id", + event_type="mcp:tools/call", + project_id="project-123", + session_id="session-123", + timestamp=datetime.now(timezone.utc), + ) + eq.add(event) - # Give worker thread time to process and handle exception - time.sleep(0.2) + # Give a worker time to pick it up and handle the exception + time.sleep(0.3) - # Check that error was logged - assert mock_log.called - assert any( - "Failed to submit event for processing" in str(call) - for call in mock_log.call_args_list - ) + assert mock_log.called + assert any( + "Worker thread error (continuing)" in str(call) + for call in mock_log.call_args_list + ) + assert all(t.is_alive() for t in eq._workers) - # Worker thread should still be alive - assert eq.worker_thread.is_alive() + eq.destroy() def _tracking_data(**overrides) -> AgentCatData: @@ -790,69 +799,63 @@ def test_publish_event_with_redaction_function(self, mock_eq, mock_tracking): assert added_event.redaction_fn == mock_redaction_fn -@patch("agentcat.modules.event_queue.signal.signal") -@patch("agentcat.modules.event_queue.atexit.register") -def test_shutdown_handlers_registered(mock_atexit, mock_signal): - """Test that shutdown handlers are registered on module import.""" - # Import the module to trigger registration - import importlib - import agentcat.modules.event_queue +def test_module_import_installs_no_process_hooks(): + """The SDK must never register signal handlers — the customer's process + owns its own shutdown. (Full subprocess-based checks live in + test_process_safety.py; this pins the module surface.)""" + import agentcat.modules.event_queue as eq_module - importlib.reload(agentcat.modules.event_queue) + assert not hasattr(eq_module, "_shutdown_handler") + source = open(eq_module.__file__).read() + assert "import signal" not in source + assert "signal.signal" not in source + assert "os._exit" not in source + assert "import atexit" not in source + assert "atexit.register" not in source - # Check signal handlers registered - assert mock_signal.call_count >= 2 - signal_calls = mock_signal.call_args_list - registered_signals = [call[0][0] for call in signal_calls] - assert signal.SIGINT in registered_signals - assert signal.SIGTERM in registered_signals - # Check atexit handler registered - assert mock_atexit.called - - -@patch("os._exit") -@patch("agentcat.modules.event_queue.signal.signal") -@patch("agentcat.modules.event_queue.event_queue") -def test_shutdown_handler_function(mock_event_queue, mock_signal, mock_exit): - """Test the _shutdown_handler function.""" - from agentcat.modules.event_queue import _shutdown_handler - - # Call the shutdown handler with proper signal handler arguments - _shutdown_handler(signal.SIGINT, None) - - # Verify signal handlers are reset to default - mock_signal.assert_any_call(signal.SIGINT, signal.SIG_DFL) - mock_signal.assert_any_call(signal.SIGTERM, signal.SIG_DFL) - - # Verify it calls destroy on the event queue - mock_event_queue.destroy.assert_called_once() - - # Verify it exits with code 0 - mock_exit.assert_called_once_with(0) +def test_bounded_queue_is_the_only_buffer(): + """Audit finding 9: with every worker wedged, memory is capped by the + queue's maxsize — there is no second, unbounded buffer behind it (the old + dispatcher drained the bounded queue into ThreadPoolExecutor's unbounded + SimpleQueue, so the advertised cap protected nothing).""" + eq = EventQueue() + eq.queue = queue.Queue(maxsize=5) + wedge = threading.Event() + eq._process_event = lambda event: wedge.wait(10) + def make(i: int) -> UnredactedEvent: + return UnredactedEvent( + id=f"e{i}", + event_type="mcp:tools/call", + project_id="p", + session_id="s", + timestamp=datetime.now(timezone.utc), + ) -@patch("time.sleep") -def test_destroy_cancels_pending_futures(mock_sleep): - """Test destroy method cancels pending futures.""" - eq = EventQueue() + try: + with patch("agentcat.modules.event_queue.write_to_log") as mock_log: + for i in range(30): + eq.add(make(i)) + deadline = time.monotonic() + 2.0 + while ( + eq.get_stats()["activeRequests"] < eq.concurrency + and time.monotonic() < deadline + ): + time.sleep(0.02) + + # concurrency in flight + maxsize buffered is the whole footprint; + # every other event was dropped at add() with a log line. + assert eq.queue.qsize() <= 5 + assert len(eq._workers) == eq.concurrency + assert all(t.daemon for t in eq._workers) - # Add an event - event = UnredactedEvent( - id="test-id", - event_type="mcp:tools/call", - project_id="project-123", - session_id="session-123", - timestamp=datetime.now(timezone.utc), - ) - eq.queue.put_nowait(event) - - # Mock executor - mock_executor = MagicMock() - eq.executor = mock_executor - - eq.destroy() - - assert eq._shutdown is True - assert eq._shutdown_event.is_set() - mock_executor.shutdown.assert_called_once_with(wait=True, cancel_futures=True) + stats = eq.get_stats() + assert stats["activeRequests"] == eq.concurrency + assert stats["isProcessing"] is True + assert any( + "full" in str(c).lower() for c in mock_log.call_args_list + ), "no drop was logged" + finally: + wedge.set() + eq.destroy() diff --git a/tests/test_event_tags_properties.py b/tests/test_event_tags_properties.py index 9675fba..0801e73 100644 --- a/tests/test_event_tags_properties.py +++ b/tests/test_event_tags_properties.py @@ -191,7 +191,7 @@ def restore_queue(self): async def test_callbacks_flow_through_to_published_event(self): captured = [] mock_api = MagicMock() - mock_api.publish_event = MagicMock(side_effect=lambda publish_event_request: captured.append(publish_event_request)) + mock_api.publish_event = MagicMock(side_effect=lambda publish_event_request, **kwargs: captured.append(publish_event_request)) set_event_queue(EventQueue(api_client=mock_api)) server = create_todo_server() @@ -222,7 +222,7 @@ async def test_callbacks_flow_through_to_published_event(self): async def test_callback_exception_does_not_break_publish(self): captured = [] mock_api = MagicMock() - mock_api.publish_event = MagicMock(side_effect=lambda publish_event_request: captured.append(publish_event_request)) + mock_api.publish_event = MagicMock(side_effect=lambda publish_event_request, **kwargs: captured.append(publish_event_request)) set_event_queue(EventQueue(api_client=mock_api)) def boom(req, ctx): @@ -246,7 +246,7 @@ def boom(req, ctx): async def test_async_callbacks_flow_through_to_published_event(self): captured = [] mock_api = MagicMock() - mock_api.publish_event = MagicMock(side_effect=lambda publish_event_request: captured.append(publish_event_request)) + mock_api.publish_event = MagicMock(side_effect=lambda publish_event_request, **kwargs: captured.append(publish_event_request)) set_event_queue(EventQueue(api_client=mock_api)) async def async_tags(req, ctx): diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 57f20f1..39dc687 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -14,6 +14,7 @@ extract_context_line, filename_for_module, format_exception_string, + is_call_tool_result, is_in_app, parse_python_traceback, stringify_non_exception, @@ -449,7 +450,7 @@ def _create_mock_event_capture(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -728,5 +729,144 @@ async def test_mcp_protocol_error(self): assert "Invalid parameters" in event.error["message"] +class TestCaptureExceptionNeverRaises: + """Audit findings 7/8: capture_exception runs at adapter sites OUTSIDE + every other guard, so an escape replaces the customer's result or original + error on the wire. Whatever the input does, it must return an ErrorData.""" + + def test_hostile_str_degrades_to_repr(self): + class BrokenStr(Exception): + def __str__(self): + raise RuntimeError("hostile __str__") + + result = capture_exception(BrokenStr("x")) + assert result["type"] == "BrokenStr" + assert result["platform"] == "python" + assert isinstance(result["message"], str) + + def test_hostile_chained_cause_keeps_the_clean_outer_error(self): + """The TS-parity killer case: the customer's own exception is CLEAN, + only its chained cause has a broken __str__. The framework would have + delivered the customer's message fine; so must we.""" + + class BrokenCause(Exception): + def __str__(self): + raise RuntimeError("hostile cause") + + try: + try: + raise BrokenCause() + except BrokenCause as cause: + raise ValueError("customer's real message") from cause + except ValueError as e: + result = capture_exception(e) + + assert result["message"] == "customer's real message" + assert result["type"] == "ValueError" + # The poisoned link degrades, it does not disappear or raise. + assert result.get("chained_errors"), "cause chain lost entirely" + + def test_deleted_cwd_keeps_frames_with_raw_paths(self, monkeypatch): + """os.path.abspath calls os.getcwd() for relative co_filenames + ('', exec'd plugin frames) and raises under a deleted working + directory. Frames must survive with the raw path.""" + import agentcat.modules.exceptions as exc_module + + def raising_abspath(path): + raise FileNotFoundError("cwd was deleted") + + monkeypatch.setattr(exc_module.os.path, "abspath", raising_abspath) + + try: + exec(compile("raise ValueError('from exec')", "", "exec")) + except ValueError as e: + result = capture_exception(e) + + assert result["message"] == "from exec" + assert result["type"] == "ValueError" + assert result.get("frames"), "frames dropped instead of degrading" + + def test_raising_content_property_is_not_a_call_tool_result(self): + class LazyProxyResult: + is_error = True + + @property + def content(self): + raise RuntimeError("upstream proxy gone") + + assert is_call_tool_result(LazyProxyResult()) is False + result = capture_exception(LazyProxyResult()) + assert result["platform"] == "python" + assert isinstance(result["message"], str) + + def test_outer_guard_returns_minimal_fallback(self, monkeypatch): + """If the detailed capture itself breaks, the fallback still names the + exception type and publishes.""" + import agentcat.modules.exceptions as exc_module + + def broken_capture(exc): + raise RuntimeError("capture machinery broke") + + monkeypatch.setattr(exc_module, "_capture_exception", broken_capture) + + result = capture_exception(ValueError("original")) + assert result["type"] == "ValueError" + assert result["platform"] == "python" + assert "unavailable" in result["message"] + + async def test_hostile_tool_exception_still_publishes_an_event(self): + """Integration: a tracked tool raising a hostile exception ends in a + published event carrying error data — never a protocol-level crash.""" + captured = [] + mock_api = MagicMock() + mock_api.publish_event = MagicMock( + side_effect=lambda publish_event_request, **kw: captured.append( + publish_event_request + ) + ) + queue = EventQueue(api_client=mock_api) + set_event_queue(queue) + + try: # whichever todo server this dependency leg provides + from .test_utils.modern_server import ( + create_mcpserver_todo_server, + create_modern_client, + ) + + server = create_mcpserver_todo_server() + make_client = create_modern_client + except ImportError: + server = create_todo_server() + make_client = create_test_client + + @server.tool() + def hostile_tool() -> str: + class Hostile(Exception): + def __str__(self): + raise RuntimeError("hostile") + + raise Hostile("boom") + + track(server, "proj_test", AgentCatOptions()) + async with make_client(server) as client: + try: + await client.call_tool("hostile_tool", {}) + except Exception: + # A tool-error RESULT surfaced client-side is a valid answer; + # the wire-level regression is asserted through the event below. + pass + time.sleep(1.0) + + events = [ + e + for e in captured + if e.event_type == "mcp:tools/call" and e.resource_name == "hostile_tool" + ] + assert events, "hostile exception suppressed the event entirely" + assert events[0].is_error is True + assert events[0].error is not None + assert events[0].error["platform"] == "python" + + if __name__ == "__main__": pytest.main([__file__, "-v"]) diff --git a/tests/test_hook_offload.py b/tests/test_hook_offload.py new file mode 100644 index 0000000..2f49518 --- /dev/null +++ b/tests/test_hook_offload.py @@ -0,0 +1,207 @@ +"""run_hook: customer hooks may block, raise anything, or hang — never the loop. + +Regression suite for audit findings 10 (sync hooks ran inline on the event +loop, so one blocking hook stalled every concurrent request) and 12 (hook +isolation caught only Exception, so SystemExit / a spontaneous CancelledError +rode the request path). + +The containment contract under test: +- a blocking SYNC hook suspends only its own request — the loop keeps serving; +- a hook slower than the timeout degrades that call and nothing else; +- SystemExit and a hook's own CancelledError become HookExecutionError, a + plain Exception every call site's degradation rule already catches; +- genuine cancellation of the enclosing task still propagates. +""" + +import asyncio +import sys +import time +from typing import Any + +import pytest + +from agentcat.modules.handles import resolve_handles +from agentcat.modules.hooks import HookExecutionError, run_hook +from agentcat.modules.identify import resolve_identity +from agentcat.types import AgentCatData, AgentCatOptions + + +@pytest.fixture +def log_sink(): + """Everything `write_to_log` tees to diagnostics, as the collector sees it.""" + from agentcat.modules import logging as agentcat_logging + + previous = agentcat_logging._diagnostics_sink + lines: list[str] = [] + agentcat_logging.set_diagnostics_sink(lines.append) + yield lines + agentcat_logging.set_diagnostics_sink(previous) + + +def _data(**option_overrides: Any) -> AgentCatData: + return AgentCatData( + project_id="proj_test", + options=AgentCatOptions(**option_overrides), + server_name="test-server", + server_version="1.0.0", + ) + + +# ── the loop stays responsive ──────────────────────────────────────────────── + + +async def test_blocking_sync_hook_does_not_stall_the_loop(): + """Finding 10's repro: while a sync hook sleeps on its worker thread, a + sibling coroutine must keep running. Inline execution scores ~0 ticks.""" + ticks = 0 + running = True + + async def ticker() -> None: + nonlocal ticks + while running: + ticks += 1 + await asyncio.sleep(0.01) + + def slow_hook(_request: Any, _extra: Any) -> str: + time.sleep(0.5) + return "done" + + task = asyncio.create_task(ticker()) + try: + result = await run_hook(slow_hook, "identify", None, None) + finally: + running = False + await task + + assert result == "done" + assert ticks >= 10, f"loop was stalled: only {ticks} ticks during a 0.5s hook" + + +# ── timeout ────────────────────────────────────────────────────────────────── + + +async def test_sync_hook_timeout_degrades_and_logs(log_sink): + def wedged(_request: Any, _extra: Any) -> str: + time.sleep(3) + return "too late" + + start = time.monotonic() + with pytest.raises(HookExecutionError): + await run_hook(wedged, "identify", None, None, timeout=0.2) + elapsed = time.monotonic() - start + + assert elapsed < 1.0, f"timeout did not fire promptly: {elapsed:.1f}s" + assert any("timed out" in line for line in log_sink) + + +async def test_async_hook_timeout_is_enforced_too(): + async def wedged(_request: Any, _extra: Any) -> str: + await asyncio.sleep(3) + return "too late" + + start = time.monotonic() + with pytest.raises(HookExecutionError): + await run_hook(wedged, "event_tags", None, None, timeout=0.2) + assert time.monotonic() - start < 1.0 + + +# ── containment of BaseException escapees ──────────────────────────────────── + + +async def test_sync_hook_system_exit_is_contained(): + def exits(_request: Any, _extra: Any) -> None: + sys.exit(3) + + with pytest.raises(HookExecutionError, match="SystemExit"): + await run_hook(exits, "identify", None, None) + + +async def test_sync_hook_spontaneous_cancelled_error_is_contained(): + """A CancelledError raised BY the hook (e.g. .result() on a cancelled + future from its cache layer) is the hook failing, not us being cancelled.""" + + def cancels(_request: Any, _extra: Any) -> None: + raise asyncio.CancelledError() + + with pytest.raises(HookExecutionError, match="CancelledError"): + await run_hook(cancels, "resolve_session_id", None, None) + + +async def test_async_hook_system_exit_is_contained(): + async def exits(_request: Any, _extra: Any) -> None: + sys.exit(3) + + with pytest.raises(HookExecutionError, match="SystemExit"): + await run_hook(exits, "event_properties", None, None) + + +@pytest.mark.skipif( + sys.version_info < (3, 11), + reason="Task.cancelling() probe needs 3.11; 3.10 conservatively re-raises", +) +async def test_async_hook_spontaneous_cancelled_error_is_contained(): + async def cancels(_request: Any, _extra: Any) -> None: + raise asyncio.CancelledError() + + with pytest.raises(HookExecutionError, match="CancelledError"): + await run_hook(cancels, "identify", None, None) + + +async def test_genuine_task_cancellation_still_propagates(): + """Client disconnects mid-call: the enclosing task's cancellation must not + be swallowed by hook containment.""" + + def wedged(_request: Any, _extra: Any) -> str: + time.sleep(3) + return "unreachable" + + task = asyncio.create_task(run_hook(wedged, "identify", None, None)) + await asyncio.sleep(0.05) # let it enter the hook + task.cancel() + with pytest.raises(asyncio.CancelledError): + await task + + +# ── ordinary failures keep their shape ─────────────────────────────────────── + + +async def test_sync_hook_exception_becomes_hook_execution_error(): + def broken(_request: Any, _extra: Any) -> None: + raise ValueError("boom") + + with pytest.raises(HookExecutionError, match="ValueError"): + await run_hook(broken, "identify", None, None) + + +async def test_well_behaved_hooks_are_unchanged(): + def sync_hook(_request: Any, _extra: Any) -> str: + return "sync" + + async def async_hook(_request: Any, _extra: Any) -> str: + return "async" + + assert await run_hook(sync_hook, "identify", None, None) == "sync" + assert await run_hook(async_hook, "identify", None, None) == "async" + + +# ── the call sites degrade by their own rules ──────────────────────────────── + + +async def test_identify_degrades_to_anonymous_on_system_exit(): + def exits(_request: Any, _extra: Any) -> Any: + sys.exit(3) + + data = _data(identify=exits) + assert await resolve_identity(data, None, None) is None + + +async def test_resolve_session_id_mints_on_system_exit(): + def exits(_request: Any, _extra: Any) -> str: + sys.exit(3) + + resolution = await resolve_handles( + {}, AgentCatOptions(resolve_session_id=exits), "proj_test", None, None + ) + assert resolution.session_source == "minted" + assert resolution.session_id.startswith("ses_") + assert resolution.hook_mode is True diff --git a/tests/test_injection.py b/tests/test_injection.py index c33d211..52d681a 100644 --- a/tests/test_injection.py +++ b/tests/test_injection.py @@ -21,6 +21,8 @@ ) from agentcat.types import AgentCatOptions +from .test_utils import sid + def spec(name="t", props=None, extra=None, out=None): # props={} must mean "an empty properties bag", not "give me the default". @@ -127,8 +129,25 @@ def test_strip_registry_driven_and_heuristic(): # Registry present but tool not in it: it was never advertised through the # pipeline, so nothing was injected for it — strip nothing. assert strip_injected_arguments("unknown", args, reg) == args - assert strip_injected_arguments("t", args, None) == {"q": 1} - gmt = {"context": "real", "session_id": "s"} + # Registry unknown (rebuild failed): shape+config-aware. "s" is not a + # minted-shape handle, so it is presumed the CUSTOMER's parameter and + # spared; agent_id survives because agent tracking is off by default; + # only context — which default options would have injected — is stripped. + assert strip_injected_arguments("t", args, None) == { + "q": 1, + "session_id": "s", + "agent_id": "a", + } + # A minted-shape value IS stripped on the same degraded path... + minted_args = {"q": 1, "session_id": sid("mine"), "context": "c"} + assert strip_injected_arguments("t", minted_args, None) == {"q": 1} + # ...and agent_id joins only when the option that injects it is on. + tracking_on = AgentCatOptions(enable_agent_tracking=True) + assert strip_injected_arguments("t", args, None, tracking_on) == { + "q": 1, + "session_id": "s", + } + gmt = {"context": "real", "session_id": sid("theirs")} stripped = strip_injected_arguments(c.GET_MORE_TOOLS_NAME, gmt, None) assert stripped == {"context": "real"} @@ -486,13 +505,30 @@ def test_injected_names_is_the_single_source_the_strip_reads(): assert injected_parameter_names("t", reg) == frozenset({"session_id", "context"}) # Registry present, tool absent: never advertised through the pipeline. assert injected_parameter_names("unknown", reg) == frozenset() - # No registry at all (rebuild failed): the heuristic, which the strip - # follows too — so the two stay consistent even on the degraded path. + # No registry at all (rebuild failed): the shape+config-aware fallback, + # which the strip follows too — so the two stay consistent even on the + # degraded path. With no arguments, session_id counts as ours (absence is + # the minting signal); agent_id needs its option on. assert injected_parameter_names("t", None) == frozenset( - {"session_id", "agent_id", "context"} + {"session_id", "context"} ) + assert injected_parameter_names( + "t", None, options=AgentCatOptions(enable_agent_tracking=True) + ) == frozenset({"session_id", "agent_id", "context"}) + # A non-minted-shape value flips session_id to "the customer's parameter". + assert injected_parameter_names( + "t", None, {"session_id": "TICKET-9"} + ) == frozenset({"context"}) + # A minted-shape value keeps it ours. + assert injected_parameter_names( + "t", None, {"session_id": sid("mine")} + ) == frozenset({"session_id", "context"}) + # A resolve_session_id hook never injects session_id, so it never strips it. + assert injected_parameter_names( + "t", None, options=AgentCatOptions(resolve_session_id=lambda req, extra: "x") + ) == frozenset({"context"}) assert injected_parameter_names(c.GET_MORE_TOOLS_NAME, None) == frozenset( - {"session_id", "agent_id"} + {"session_id"} ) @@ -503,7 +539,7 @@ def test_injected_names_is_the_single_source_the_strip_reads(): ) def test_what_the_strip_removes_is_what_the_names_report(registry): args = {"session_id": "prod-42", "agent_id": "agt_1", "context": "why", "q": 1} - names = injected_parameter_names("deploy", registry) + names = injected_parameter_names("deploy", registry, args) stripped = strip_injected_arguments("deploy", args, registry) assert set(args) - set(stripped) == names & set(args) @@ -517,8 +553,22 @@ def test_strip_always_returns_a_new_dict(): def test_strip_heuristic_leaves_unrelated_arguments_alone(): + # Non-minted session_id and default options: only context is ours to take. args = {"text": "x", "session_id": "a", "agent_id": "b", "context": "c", "id": 7} - assert strip_injected_arguments("any", args, None) == {"text": "x", "id": 7} + assert strip_injected_arguments("any", args, None) == { + "text": "x", + "session_id": "a", + "agent_id": "b", + "id": 7, + } + # Minted-shape session_id plus agent tracking on: the full strip, with the + # unrelated arguments still untouched. + minted = {"text": "x", "session_id": sid("m"), "agent_id": "b", "context": "c", "id": 7} + tracking_on = AgentCatOptions(enable_agent_tracking=True) + assert strip_injected_arguments("any", minted, None, tracking_on) == { + "text": "x", + "id": 7, + } def test_injection_result_equality_is_value_based(): diff --git a/tests/test_lowlevel_v1_handles.py b/tests/test_lowlevel_v1_handles.py index a7e8266..7e84ddf 100644 --- a/tests/test_lowlevel_v1_handles.py +++ b/tests/test_lowlevel_v1_handles.py @@ -702,3 +702,51 @@ def test_the_installed_official_sdk_classifies_as_a_lowlevel_v1_flavor(): detected = detect_server(lowlevel) assert detected.flavor is ServerFlavor.LOWLEVEL_V1 assert detected.lowlevel is lowlevel + + +async def test_wrapped_list_preserves_meta_and_extra_result_fields(capture): + """Audit finding 11: the v1 tools/list rebuild used to reconstruct + `ListToolsResult(tools=..., nextCursor=...)`, silently dropping `_meta` + and any extra fields a raw list handler set. The result must now be a + `model_copy` of the customer's own object — injection applied, everything + else intact (mcp 1.x `Result` is extra='allow').""" + from mcp.server.lowlevel import Server + from mcp.types import ListToolsRequest, ListToolsResult, ServerResult, Tool + + server = Server("meta-server") + + async def list_tools(req): + return ServerResult( + ListToolsResult( + tools=[ + Tool( + name="echo", + description="Echo the text back.", + inputSchema={ + "type": "object", + "properties": {"text": {"type": "string"}}, + }, + ) + ], + nextCursor="page-2", + # The aliased spelling: this mcp generation does not populate + # the `meta` field by name, only via its `_meta` alias. + **{"_meta": {"total": 41}}, + cacheHint="warm", # an extra field, allowed by Result + ) + ) + + server.request_handlers[ListToolsRequest] = list_tools + + track(server, "proj_test", AgentCatOptions()) + handler = server.request_handlers[ListToolsRequest] + result = await handler(ListToolsRequest(method="tools/list")) + + listed = result.root + # Injection happened... + echo = next(t for t in listed.tools if t.name == "echo") + assert "session_id" in echo.inputSchema["properties"] + # ...and nothing the customer's handler set was dropped. + assert listed.nextCursor == "page-2" + assert listed.meta == {"total": 41} + assert getattr(listed, "cacheHint", None) == "warm" diff --git a/tests/test_lowlevel_v2_handles.py b/tests/test_lowlevel_v2_handles.py index 13bb364..938b9f2 100644 --- a/tests/test_lowlevel_v2_handles.py +++ b/tests/test_lowlevel_v2_handles.py @@ -1310,3 +1310,51 @@ def test_track_never_raises(): server = create_lowlevel_todo_server() assert track(server, None) is server assert track(server, "proj_test", {"debug_mode": True}) is server + + +async def test_an_uncopyable_tool_does_not_take_down_the_listing(log_sink): + """Audit finding 4c's sibling: one tool whose `model_copy(deep=True)` + raises (live runtime state in a schema) must not crash `tools/list` or + leave the whole listing un-injected. The stubborn tool serves verbatim, + un-injected and never mutated; every other tool still gets its handles.""" + + class UncopyableTool(types.Tool): + def model_copy(self, *args, **kwargs): + raise RuntimeError("live client handle in schema") + + async def on_list_tools(ctx, params): + return types.ListToolsResult( + tools=[ + types.Tool( + name="good_tool", + description="Copies fine.", + input_schema={"type": "object", "properties": {}}, + ), + UncopyableTool( + name="stubborn_tool", + description="Cannot be copied.", + input_schema={"type": "object", "properties": {}}, + ), + ] + ) + + async def on_call_tool(ctx, params): + return types.CallToolResult( + content=[types.TextContent(type="text", text="ok")] + ) + + server = Server( + "uncopyable", on_list_tools=on_list_tools, on_call_tool=on_call_tool + ) + track(server, "proj_test", AgentCatOptions()) + + async with create_modern_client(server) as client: + listed = await client.list_tools() + + names = {t.name for t in listed.tools} + assert {"good_tool", "stubborn_tool"} <= names + good = _tool(listed, "good_tool") + stubborn = _tool(listed, "stubborn_tool") + assert "session_id" in good.input_schema["properties"] + assert "session_id" not in (stubborn.input_schema.get("properties") or {}) + assert any("could not copy tool" in line for line in log_sink) diff --git a/tests/test_multiple_servers.py b/tests/test_multiple_servers.py index 2b3146f..534d8d5 100644 --- a/tests/test_multiple_servers.py +++ b/tests/test_multiple_servers.py @@ -22,7 +22,7 @@ async def test_multiple_servers_with_different_options(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -150,7 +150,7 @@ async def test_server_options_update_on_retrack(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -200,7 +200,7 @@ async def test_concurrent_server_operations(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -308,7 +308,7 @@ async def test_custom_identify_per_server(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) diff --git a/tests/test_process_safety.py b/tests/test_process_safety.py new file mode 100644 index 0000000..66a2708 --- /dev/null +++ b/tests/test_process_safety.py @@ -0,0 +1,219 @@ +"""The customer's process is theirs: signals, exit, threads, imports. + +Regression suite for the v2.0.0 never-halt audit. Every test here pins a +process-level guarantee the SDK broke at least once: + +- importing the SDK must not install signal handlers, call os._exit, or + register event-draining atexit hooks (audit finding 1); +- `import agentcat` must survive an install with no distribution metadata + (finding 2); +- importing and publishing from a NON-MAIN thread must work and must not leak + threads (finding 3); +- interpreter exit must be prompt even with a wedged customer hook in flight + (findings 5/6). + +Everything runs in subprocesses: these are properties of a whole process +lifecycle, and asserting them in-suite would let pytest's own state mask a +regression. +""" + +import subprocess +import sys +import tempfile +import time + +import pytest + +pytestmark = pytest.mark.skipif( + sys.platform == "win32", reason="POSIX signal semantics" +) + + +def _run(code: str, timeout: float = 30.0) -> subprocess.CompletedProcess: + return subprocess.run( + [sys.executable, "-c", code], + capture_output=True, + text=True, + timeout=timeout, + env={ + "PATH": "/usr/bin:/bin", + "DISABLE_DIAGNOSTICS": "true", + # Isolated so the subprocess's ~/agentcat.log never touches the + # developer's real one. + "HOME": tempfile.mkdtemp(prefix="agentcat-test-home-"), + }, + ) + + +def test_import_leaves_signal_handlers_alone(): + """Finding 1: the SDK must never replace SIGINT/SIGTERM handlers.""" + result = _run( + """ +import signal +import agentcat +import agentcat.modules.event_queue + +assert signal.getsignal(signal.SIGINT) is signal.default_int_handler, ( + "SIGINT handler replaced: " + repr(signal.getsignal(signal.SIGINT)) +) +assert signal.getsignal(signal.SIGTERM) is signal.SIG_DFL, ( + "SIGTERM handler replaced: " + repr(signal.getsignal(signal.SIGTERM)) +) +print("CLEAN") +""" + ) + assert result.returncode == 0, result.stderr + assert "CLEAN" in result.stdout + + +def test_customer_signal_handler_and_cleanup_still_run(): + """Finding 1: on SIGTERM the CUSTOMER's handler, finally blocks, and + atexit hooks all run, and the exit code is the customer's — no os._exit.""" + result = _run( + """ +import atexit +import os +import signal +import sys +import time + +import agentcat +import agentcat.modules.event_queue # the module that used to hijack signals + +ran = [] +atexit.register(lambda: print("ATEXIT-RAN", flush=True)) + +def customer_handler(signum, frame): + ran.append(signum) + print("CUSTOMER-HANDLER-RAN", flush=True) + sys.exit(7) # the CUSTOMER chooses the exit path and code + +signal.signal(signal.SIGTERM, customer_handler) + +try: + os.kill(os.getpid(), signal.SIGTERM) + time.sleep(5) # never reached; the handler exits +finally: + print("FINALLY-RAN", flush=True) +""" + ) + assert result.returncode == 7, (result.returncode, result.stderr) + assert "CUSTOMER-HANDLER-RAN" in result.stdout + assert "FINALLY-RAN" in result.stdout + assert "ATEXIT-RAN" in result.stdout + + +def test_exit_is_prompt_with_a_wedged_redaction_hook(): + """Findings 5/6: a blocking customer hook on a worker thread must not + hold interpreter exit — workers are daemon and nothing drains at exit.""" + start = time.monotonic() + result = _run( + """ +import time +from datetime import datetime, timezone + +from agentcat.modules.event_queue import event_queue +from agentcat.types import UnredactedEvent + +event_queue.add( + UnredactedEvent( + id="wedge", + event_type="mcp:tools/call", + project_id="proj_test", + session_id="ses_x", + timestamp=datetime.now(timezone.utc), + redaction_fn=lambda s: time.sleep(60) or s, + ) +) +time.sleep(0.3) # let a worker pick it up and enter the hook +print("EXITING", flush=True) +""", + timeout=15.0, + ) + elapsed = time.monotonic() - start + assert result.returncode == 0, result.stderr + assert "EXITING" in result.stdout + assert elapsed < 5.0, f"exit took {elapsed:.1f}s with a wedged hook" + + +def test_import_and_publish_from_non_main_thread(): + """Finding 3: importing and using the queue off the main thread works, + starts exactly `concurrency` workers once, and leaks nothing per call.""" + result = _run( + """ +import sys +import threading +from datetime import datetime, timezone + +def use_from_worker(): + from agentcat.modules.event_queue import event_queue + from agentcat.types import UnredactedEvent + + def make(): + return UnredactedEvent( + id="bg", + event_type="mcp:tools/call", + project_id=None, # no project: nothing leaves the process + session_id="ses_x", + timestamp=datetime.now(timezone.utc), + ) + + event_queue.add(make()) + event_queue.add(make()) + +t = threading.Thread(target=use_from_worker) +t.start() +t.join() + +assert "agentcat.modules.event_queue" in sys.modules, "module evicted on import" +from agentcat.modules.event_queue import event_queue +assert len(event_queue._workers) == event_queue.concurrency, ( + f"expected {event_queue.concurrency} workers, found {len(event_queue._workers)}" +) +assert all(w.daemon for w in event_queue._workers) + +# A second thread's adds must not grow the pool. +t2 = threading.Thread(target=use_from_worker) +t2.start() +t2.join() +assert len(event_queue._workers) == event_queue.concurrency +print("NO-LEAK") +""" + ) + assert result.returncode == 0, result.stderr + assert "NO-LEAK" in result.stdout + + +def test_import_survives_missing_distribution_metadata(): + """Finding 2: PackageNotFoundError at import time degrades the version + string instead of crashing the customer's server at startup.""" + result = _run( + """ +import importlib.metadata +from importlib.metadata import PackageNotFoundError + +_real = importlib.metadata.version + +def fake(name, _real=_real): + if name == "agentcat": + raise PackageNotFoundError(name) + return _real(name) + +importlib.metadata.version = fake + +import agentcat + +assert agentcat.__version__ == "0.0.0", agentcat.__version__ +print("SURVIVED", agentcat.__version__) +""" + ) + assert result.returncode == 0, result.stderr + assert "SURVIVED 0.0.0" in result.stdout + + +def test_version_matches_metadata_when_present(): + from importlib.metadata import version + + import agentcat + + assert agentcat.__version__ == version("agentcat") diff --git a/tests/test_rebuild_on_demand.py b/tests/test_rebuild_on_demand.py index 88f28f8..17fbd31 100644 --- a/tests/test_rebuild_on_demand.py +++ b/tests/test_rebuild_on_demand.py @@ -182,6 +182,85 @@ async def test_a_failed_rebuild_degrades_to_the_heuristic_strip( ] +LOWLEVEL_V2_ONLY = [flavor for flavor in flavors() if flavor.id == "lowlevel-v2"] + + +@pytest.mark.parametrize("flavor", LOWLEVEL_V2_ONLY, ids=lambda f: f.id) +async def test_rebuild_survives_a_list_registration_with_no_params_type( + flavor, capture, log_sink +): + """Audit finding 4c: a `tools/list` registration carrying no params_type + made rebuild-on-demand call the customer's list handler with params=None. + A handler that dereferences its params then crashed the rebuild — and the + degraded strip branded the call's arguments. The fallback params must be + the real all-optional model, so the rebuild SUCCEEDS. + """ + import dataclasses + + built = flavor.build("rebuild-bare") + entry = built.server._request_handlers["tools/list"] + inner = getattr(entry, "handler", entry) + + async def dereferencing_list(ctx, params, _inner=inner): + _ = params.cursor # a customer handler that trusts its params + return await _inner(ctx, params) + + if hasattr(entry, "handler"): + built.server._request_handlers["tools/list"] = dataclasses.replace( + entry, handler=dereferencing_list, params_type=None + ) + else: # pre-2.0 development line stored the bare callable + built.server._request_handlers["tools/list"] = dereferencing_list + + track(built.server, "proj_test", AgentCatOptions()) + await flavor.call_unlisted( + built.server, "echo", {"text": "hi", SESSION_ID_PARAM: SUPPLIED} + ) + + assert _logged(log_sink, "Rebuilt injection registries on demand") + assert not _logged(log_sink, "rebuild-on-demand failed") + assert built.seen == [("echo", {"text": "hi"})] + assert capture[0].session_id == SUPPLIED + + +@pytest.mark.parametrize( + "flavor", CAN_ANSWER_WITH_A_DOWN_LIST_SOURCE, ids=lambda f: f.id +) +async def test_a_failed_rebuild_spares_a_customers_own_session_id( + flavor, capture, log_sink +): + """Audit finding 4: registry unknown + a tool that declares its own + `session_id`. The old fallback deleted the customer's value by name and + appended a correction telling the agent to stop sending their parameter. + The shape-aware fallback must do neither: a non-minted value is presumed + the customer's, reaches their handler, and draws no wire correction — + while the event honestly records the call as sessionless. + """ + built = flavor.build("rebuild-down-owned", customer_session_id=True) + track(built.server, "proj_test", AgentCatOptions()) + flavor.break_list_source(built.server) + data = tracking_data(built.server) + + result = await flavor.call_unlisted( + built.server, "complete_task", {"session_id": "TICKET-9", "note": "done"} + ) + + assert _logged(log_sink, "rebuild-on-demand failed") + assert data.injected_params_registry is None + + # The customer's parameter survived the degraded strip and reached them. + assert built.seen == [ + ("complete_task", {"session_id": "TICKET-9", "note": "done"}) + ] + # No "session_id not recognized" correction steering agents away from the + # customer's own parameter. + assert "not recognized" not in (result.text or "") + # Sessionless, tagged for the dashboard — the honest degraded record. + event = capture[0] + assert event.session_id is None + assert event.tags[AGENTCAT_TAG_SESSION_SOURCE] == "invalid" + + @pytest.mark.parametrize( "flavor", CAN_ANSWER_WITH_A_DOWN_LIST_SOURCE, ids=lambda f: f.id ) diff --git a/tests/test_request_extra.py b/tests/test_request_extra.py index e150a04..283b72a 100644 --- a/tests/test_request_extra.py +++ b/tests/test_request_extra.py @@ -44,7 +44,7 @@ def _capture_into(sink: list): passing vacuously. """ - def capture(publish_event_request): + def capture(publish_event_request, **kwargs): sink.append(publish_event_request) return capture @@ -276,7 +276,7 @@ async def test_stdio_path_omits_request_info(self): mock_api_client = MagicMock() captured_events: list = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) @@ -305,7 +305,7 @@ async def test_http_simulated_path_populates_headers(self, monkeypatch): mock_api_client = MagicMock() captured_events: list = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) diff --git a/tests/test_tool_context.py b/tests/test_tool_context.py index 6482e4a..c5e6bdf 100644 --- a/tests/test_tool_context.py +++ b/tests/test_tool_context.py @@ -629,7 +629,7 @@ async def test_get_more_tools_captures_user_intent_in_event(self): mock_api_client = MagicMock() captured_events = [] mock_api_client.publish_event = MagicMock( - side_effect=lambda publish_event_request: captured_events.append( + side_effect=lambda publish_event_request, **kwargs: captured_events.append( publish_event_request ) ) diff --git a/tests/test_truncation.py b/tests/test_truncation.py index de20812..84bc3b3 100644 --- a/tests/test_truncation.py +++ b/tests/test_truncation.py @@ -310,7 +310,7 @@ def _capture_setup(self): mock_api_client = MagicMock() captured_events = [] - def capture_event(publish_event_request): + def capture_event(publish_event_request, **kwargs): captured_events.append(publish_event_request) mock_api_client.publish_event = MagicMock(side_effect=capture_event) From bf423de5404173345a43228731ae1b63a4a59480 Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Tue, 4 Aug 2026 20:41:18 -0400 Subject: [PATCH 09/13] stable --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 17a8751..cf92891 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "agentcat" version = "2.0.0" -description = "Analytics tool for MCP (Model Context Protocol) servers and AI agents - tracks tool usage patterns and provides insights" +description = "Analytics tool for MCP (Model Context Protocol) servers, Claude Connectors, and ChatGPT Plugins - tracks tool usage patterns and provides insights" authors = [ { name = "AgentCat, Inc.", email = "support@agentcat.com" }, ] From 0e1e3b8c4c374186c26581ecd9ddb2b10c4307ba Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Tue, 4 Aug 2026 21:13:11 -0400 Subject: [PATCH 10/13] fix: park event workers in untimed waits so Linux exit can never SIGABRT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI's compatibility matrix caught the new process-safety tests failing on Linux: a daemon worker waking from queue.get(timeout=0.1) while the interpreter finalizes is killed via pthread_exit(), and glibc's forced unwind aborts the whole process (CPython gh-87135, fixed in 3.14) — replacing the customer's exit code with SIGABRT. Workers now block in an untimed get() and never wake on their own; destroy() wakes parked workers with a _Stop marker. Wake-up markers are excluded from the unprocessed-events count. MIGRATION.md documents the one remaining narrow window (timed retry backoff while the API is unreachable at exit). --- MIGRATION.md | 2 +- src/agentcat/modules/event_queue.py | 38 ++++++++++++++++++++++++----- tests/test_event_queue.py | 27 ++++++++++++++++++++ 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index f145e42..74688db 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -123,7 +123,7 @@ pip install "agentcat<2" # staying on FastMCP 2.x - **`redact_sensitive_information` now actually runs.** In 1.x the hook was configured, documented, and never invoked on a published event: the redactor walked `str`/`list`/`dict` and was handed the event *model*, so it returned it untouched. 2.0 fixes that, which means a hook you set in 1.x starts taking effect the moment you upgrade. It runs on every string in the event — `parameters`, `response`, `user_intent`, `client_name`, `server_name` and the rest — except the fields AgentCat needs to attribute the event: `session_id`, `id`, `project_id`, `event_type`, `resource_name`, `actor_id`, the three `identify_*` fields, and your own `tags` and `properties`. **If your hook is an aggressive catch-all** (`lambda s: "[REDACTED]"`), it will now blank fields your dashboards read, such as `client_name`. Narrow it to the patterns you actually care about before upgrading. A hook that raises drops the event rather than publishing it unredacted, and an async hook is supported. - **MCP `extra.sessionId` is ignored entirely**, and inactivity-based session rollover is gone. The transport's `mcp-session-id` still rides along untouched under `parameters.extra.sessionId` on each event if you need it. - **Request-path hooks now run contained: sync hooks on a worker thread, everything under a 5-second cap.** A sync `identify` (or `event_tags` / `event_properties` / `resolve_session_id`) that blocks — a database read, an HTTP call — no longer suspends your server's event loop; it suspends only its own call, exactly how your framework runs a sync tool body. Two consequences. First, a *sync* hook can no longer call asyncio APIs (`asyncio.ensure_future`, reading a loop-bound future): worker threads have no running loop, so make that hook `async def` — its body then runs on the loop as before. Second, a hook slower than 5 seconds has its result discarded and the call proceeds as if the hook had raised (anonymous / untagged / freshly minted, per that hook's documented degradation); the timeout is logged to `~/agentcat.log`. A hook that raises `SystemExit` or `CancelledError` is contained the same way — nothing a hook does reaches your request path. -- **The SDK never touches your process lifecycle.** 2.0.0 beta builds replaced `SIGINT`/`SIGTERM` handlers at import and force-exited via `os._exit(0)` after a drain delay — clobbering `KeyboardInterrupt`, your own handlers, `finally` blocks and `atexit` hooks. Stable 2.0 installs no signal handlers, registers no exit-time event drain, and runs every worker as a daemon thread: your shutdown is entirely yours, and exit is never delayed by AgentCat. The trade is deliberate: telemetry still queued when the process exits is dropped. The one exit hook that remains is the internal-diagnostics beacon — skipped when empty, capped at ~2 seconds. +- **The SDK never touches your process lifecycle.** 2.0.0 beta builds replaced `SIGINT`/`SIGTERM` handlers at import and force-exited via `os._exit(0)` after a drain delay — clobbering `KeyboardInterrupt`, your own handlers, `finally` blocks and `atexit` hooks. Stable 2.0 installs no signal handlers, registers no exit-time event drain, and runs every worker as a daemon thread: your shutdown is entirely yours, and exit is never delayed by AgentCat. The trade is deliberate: telemetry still queued when the process exits is dropped. The one exit hook that remains is the internal-diagnostics beacon — skipped when empty, capped at ~2 seconds. Idle workers park in untimed waits, so interpreter exit never wakes them — on Linux with CPython ≤3.13, a daemon thread waking from a timed wait during finalization aborts the whole process (CPython gh-87135), which is exactly the corruption this design avoids. One narrow residue of that CPython behavior remains: a publish retrying against an unreachable API holds a short timed backoff wait, and a process that exits during that window can still hit the abort. The window only exists while the AgentCat API is down, and Python 3.14 removes the underlying behavior. ### Bringing your own session IDs diff --git a/src/agentcat/modules/event_queue.py b/src/agentcat/modules/event_queue.py index ce8749a..6049499 100644 --- a/src/agentcat/modules/event_queue.py +++ b/src/agentcat/modules/event_queue.py @@ -38,11 +38,18 @@ PUBLISH_TIMEOUT_SECONDS = 10 +class _Stop: + """Marker destroy() enqueues to wake workers parked in the untimed get().""" + + +_STOP = _Stop() + + class EventQueue: """Manages event queue and sending to AgentCat API.""" def __init__(self, api_client=None): - self.queue: queue.Queue[UnredactedEvent] = queue.Queue(maxsize=10000) + self.queue: queue.Queue[UnredactedEvent | _Stop] = queue.Queue(maxsize=10000) self.max_retries = 3 self.max_queue_size = 10000 # Prevent unbounded growth self.concurrency = 5 # Max parallel requests @@ -111,12 +118,18 @@ def _worker(self) -> None: No intermediate executor — when every worker is busy the bounded queue fills and add() drops, so memory is genuinely capped at max_queue_size events. + + The get() must stay untimed: a daemon thread that wakes from a timed + wait while the interpreter is finalizing is killed via pthread_exit(), + and on Linux/glibc that aborts the whole process — SIGABRT over the + customer's exit code (CPython gh-87135, fixed in 3.14). A thread + parked in an untimed wait never wakes on its own, so interpreter exit + cannot hit that path; destroy() wakes workers with a _Stop marker. """ while not self._shutdown_event.is_set(): - try: - event = self.queue.get(timeout=0.1) - except queue.Empty: - continue + event = self.queue.get() + if isinstance(event, _Stop): + break with self._lock: self._active += 1 try: @@ -235,6 +248,17 @@ def destroy(self) -> None: self._shutdown = True self._shutdown_event.set() + # Wake workers parked in the untimed get(). Best-effort: a full queue + # means no worker is parked (a parked worker would have taken an item + # already), and busy workers re-check the shutdown event before + # parking again. + if self._workers_started: + for _ in range(self.concurrency): + try: + self.queue.put_nowait(_STOP) + except queue.Full: + break + # Shared 1s budget across all joins, never per-thread. deadline = time.monotonic() + 1.0 for t in self._workers: @@ -242,7 +266,9 @@ def destroy(self) -> None: continue # destroy() called from a worker t.join(timeout=max(0.0, deadline - time.monotonic())) - remaining = self.queue.qsize() + remaining = sum( + 1 for item in list(self.queue.queue) if not isinstance(item, _Stop) + ) if remaining > 0: write_to_log(f"Event queue destroyed with {remaining} events unprocessed.") diff --git a/tests/test_event_queue.py b/tests/test_event_queue.py index 5660ae9..e4e545a 100644 --- a/tests/test_event_queue.py +++ b/tests/test_event_queue.py @@ -534,6 +534,33 @@ def test_destroy_logs_unprocessed_events(self, mock_log): assert mock_log.called assert any(str(num_events) in str(call) for call in mock_log.call_args_list) + @patch("agentcat.modules.event_queue.write_to_log") + def test_destroy_wakeup_markers_are_not_counted_as_events(self, mock_log): + """The _Stop markers destroy() enqueues to wake idle parked workers + must never show up in the unprocessed-events count.""" + eq = EventQueue() + eq._process_event = lambda event: None + eq.add( + UnredactedEvent( + id="drains", + event_type="mcp:tools/call", + project_id="project-123", + session_id="session-123", + timestamp=datetime.now(timezone.utc), + ) + ) + deadline = time.monotonic() + 2.0 + while time.monotonic() < deadline: + if eq.queue.qsize() == 0 and eq.get_stats()["activeRequests"] == 0: + break + time.sleep(0.01) + + eq.destroy() + + assert not any( + "unprocessed" in str(logged) for logged in mock_log.call_args_list + ) + def test_worker_thread_processes_events(self): """Test that worker thread processes events from queue.""" eq = EventQueue() From 1cccfdae0356660c3bac1ec5f2e391c9110b1042 Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Tue, 4 Aug 2026 21:36:41 -0400 Subject: [PATCH 11/13] fix: stop the publish worker before interpreter finalization; single worker MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compatibility matrix kept aborting (SIGABRT, 'FATAL: exception not rethrown') after the untimed-get fix: parking idle workers was not enough. Container bisection on Linux showed the real mechanism — a daemon thread still actively executing when finalization sets the finalizing flag is killed via pthread_exit(), and glibc's forced unwind through its C frames aborts the whole process (CPython gh-87135, fixed in 3.14). Pure-threading repros never abort (0/520); the SDK's real workload aborts at ~4% per exit. The fix is lifecycle, not waiting-strategy: first publish now registers a bounded atexit hook that stops the worker — sets the shutdown flag, wakes a parked or backing-off worker, joins with a ~1s budget, sends nothing. atexit runs before the finalizing flag is set, so the worker is gone before the dangerous window opens. Queued events still drop at exit by design. The pool is also simplified to a single worker thread; the bounded queue absorbs bursts and add() drops on overflow. Validated on python:3.12-slim: the two previously-aborting subprocess bodies ran 210 times with zero failures (baseline ~4%) and prompt exits. --- MIGRATION.md | 2 +- README.md | 17 ++++--- src/agentcat/modules/event_queue.py | 77 ++++++++++++++++++++++------- tests/test_diagnostics_export.py | 8 +-- tests/test_event_queue.py | 5 +- tests/test_process_safety.py | 46 +++++++++++++++++ 6 files changed, 123 insertions(+), 32 deletions(-) diff --git a/MIGRATION.md b/MIGRATION.md index 74688db..0531798 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -123,7 +123,7 @@ pip install "agentcat<2" # staying on FastMCP 2.x - **`redact_sensitive_information` now actually runs.** In 1.x the hook was configured, documented, and never invoked on a published event: the redactor walked `str`/`list`/`dict` and was handed the event *model*, so it returned it untouched. 2.0 fixes that, which means a hook you set in 1.x starts taking effect the moment you upgrade. It runs on every string in the event — `parameters`, `response`, `user_intent`, `client_name`, `server_name` and the rest — except the fields AgentCat needs to attribute the event: `session_id`, `id`, `project_id`, `event_type`, `resource_name`, `actor_id`, the three `identify_*` fields, and your own `tags` and `properties`. **If your hook is an aggressive catch-all** (`lambda s: "[REDACTED]"`), it will now blank fields your dashboards read, such as `client_name`. Narrow it to the patterns you actually care about before upgrading. A hook that raises drops the event rather than publishing it unredacted, and an async hook is supported. - **MCP `extra.sessionId` is ignored entirely**, and inactivity-based session rollover is gone. The transport's `mcp-session-id` still rides along untouched under `parameters.extra.sessionId` on each event if you need it. - **Request-path hooks now run contained: sync hooks on a worker thread, everything under a 5-second cap.** A sync `identify` (or `event_tags` / `event_properties` / `resolve_session_id`) that blocks — a database read, an HTTP call — no longer suspends your server's event loop; it suspends only its own call, exactly how your framework runs a sync tool body. Two consequences. First, a *sync* hook can no longer call asyncio APIs (`asyncio.ensure_future`, reading a loop-bound future): worker threads have no running loop, so make that hook `async def` — its body then runs on the loop as before. Second, a hook slower than 5 seconds has its result discarded and the call proceeds as if the hook had raised (anonymous / untagged / freshly minted, per that hook's documented degradation); the timeout is logged to `~/agentcat.log`. A hook that raises `SystemExit` or `CancelledError` is contained the same way — nothing a hook does reaches your request path. -- **The SDK never touches your process lifecycle.** 2.0.0 beta builds replaced `SIGINT`/`SIGTERM` handlers at import and force-exited via `os._exit(0)` after a drain delay — clobbering `KeyboardInterrupt`, your own handlers, `finally` blocks and `atexit` hooks. Stable 2.0 installs no signal handlers, registers no exit-time event drain, and runs every worker as a daemon thread: your shutdown is entirely yours, and exit is never delayed by AgentCat. The trade is deliberate: telemetry still queued when the process exits is dropped. The one exit hook that remains is the internal-diagnostics beacon — skipped when empty, capped at ~2 seconds. Idle workers park in untimed waits, so interpreter exit never wakes them — on Linux with CPython ≤3.13, a daemon thread waking from a timed wait during finalization aborts the whole process (CPython gh-87135), which is exactly the corruption this design avoids. One narrow residue of that CPython behavior remains: a publish retrying against an unreachable API holds a short timed backoff wait, and a process that exits during that window can still hit the abort. The window only exists while the AgentCat API is down, and Python 3.14 removes the underlying behavior. +- **The SDK never touches your process lifecycle.** 2.0.0 beta builds replaced `SIGINT`/`SIGTERM` handlers at import and force-exited via `os._exit(0)` after a drain delay — clobbering `KeyboardInterrupt`, your own handlers, `finally` blocks and `atexit` hooks. Stable 2.0 installs no signal handlers, registers no exit-time event drain, and runs every worker as a daemon thread: your shutdown is entirely yours, and exit is never delayed by AgentCat. The trade is deliberate: telemetry still queued when the process exits is dropped. Exactly two bounded exit hooks exist, and neither sends events: a worker-stop hook (registered on first publish) that tells the single publish worker to exit — instant when the worker is idle, capped by a ~1-second join otherwise — and the internal-diagnostics beacon, skipped when empty and capped at ~2 seconds. The worker stop is itself a process-safety measure: on Linux with CPython ≤3.13, a daemon thread still running when interpreter finalization begins can abort the whole process with SIGABRT (CPython gh-87135, fixed in 3.14). Stopping the worker before finalization — atexit hooks run first — closes that path, including for a publish that is mid-retry against an unreachable API. ### Bringing your own session IDs diff --git a/README.md b/README.md index 094a472..87cc1e2 100644 --- a/README.md +++ b/README.md @@ -279,12 +279,17 @@ Two behaviors are worth knowing before you read your first dashboard. Both are d ### Shutdown behavior AgentCat never touches your process lifecycle: no signal handlers, no forced -exits, and no exit-time event drain. Every SDK thread is a daemon, so your -shutdown — `Ctrl-C`, `SIGTERM`, `sys.exit()` — runs exactly as it would -untracked, and is never delayed by AgentCat. The trade: telemetry still queued -at the moment the process exits is dropped rather than flushed. The one exit -hook the SDK keeps is the internal-diagnostics beacon below — skipped when -there is nothing buffered, capped at ~2 seconds when there is. +exits, and no exit-time event drain. The SDK's single publish worker is a +daemon thread, so your shutdown — `Ctrl-C`, `SIGTERM`, `sys.exit()` — runs +exactly as it would untracked, and is never delayed by AgentCat. The trade: +telemetry still queued at the moment the process exits is dropped rather than +flushed. The SDK keeps exactly two bounded exit hooks, neither of which sends +events: one stops the publish worker before interpreter finalization (instant +when idle, ~1-second cap otherwise — on Linux with CPython ≤3.13 a daemon +thread still running during finalization can abort the process, CPython +gh-87135, and stopping first closes that path), and the internal-diagnostics +beacon below — skipped when there is nothing buffered, capped at ~2 seconds +when there is. ### Internal diagnostics diff --git a/src/agentcat/modules/event_queue.py b/src/agentcat/modules/event_queue.py index 6049499..f2c4e79 100644 --- a/src/agentcat/modules/event_queue.py +++ b/src/agentcat/modules/event_queue.py @@ -1,12 +1,14 @@ """Event queue implementation for AgentCat. Process-safety contract: importing this module must be side-effect free -beyond object construction — no threads, no signal handlers, no atexit -hooks. Workers start lazily on first publish, are always daemon, and are -never drained at interpreter exit: telemetry may be lost on shutdown, the -customer's process may never be delayed or redirected by it. +beyond object construction — no threads, no signal handlers, no exit +hooks. The worker starts lazily on first publish and is always daemon. +First publish also registers one bounded exit hook that STOPS the worker +— it never sends: telemetry may be lost on shutdown, the customer's +process may never be delayed or redirected by it. """ +import atexit import queue import sys import threading @@ -52,7 +54,9 @@ def __init__(self, api_client=None): self.queue: queue.Queue[UnredactedEvent | _Stop] = queue.Queue(maxsize=10000) self.max_retries = 3 self.max_queue_size = 10000 # Prevent unbounded growth - self.concurrency = 5 # Max parallel requests + # One publish at a time keeps the thread footprint minimal; the + # bounded queue absorbs bursts and add() drops on overflow. + self.concurrency = 1 # Allow injection of api_client for testing if api_client is None: @@ -75,6 +79,7 @@ def __init__(self, api_client=None): def _ensure_workers(self) -> None: """Start the consumer threads on first use.""" + global _exit_stop_registered if self._workers_started: return with self._lock: @@ -89,6 +94,12 @@ def _ensure_workers(self) -> None: t.start() self._workers.append(t) self._workers_started = True + # The moment threads exist, the process needs the exit hook that + # stops them (see _stop_workers_at_exit). Registered here, not at + # import, so importing the SDK stays side-effect free. + if not _exit_stop_registered: + atexit.register(_stop_workers_at_exit) + _exit_stop_registered = True def configure(self, api_base_url: str) -> None: """Reconfigure the API client with a new base URL.""" @@ -119,12 +130,14 @@ def _worker(self) -> None: queue fills and add() drops, so memory is genuinely capped at max_queue_size events. - The get() must stay untimed: a daemon thread that wakes from a timed - wait while the interpreter is finalizing is killed via pthread_exit(), + The untimed get() keeps an idle worker fully parked (no periodic + wakes); _stop_workers() wakes it with a _Stop marker. The real exit + safety, though, is the atexit hook: a daemon thread still executing + when interpreter finalization begins is killed via pthread_exit(), and on Linux/glibc that aborts the whole process — SIGABRT over the - customer's exit code (CPython gh-87135, fixed in 3.14). A thread - parked in an untimed wait never wakes on its own, so interpreter exit - cannot hit that path; destroy() wakes workers with a _Stop marker. + customer's exit code (CPython gh-87135, fixed in 3.14). The hook + stops this thread before finalization starts, so that window never + opens. """ while not self._shutdown_event.is_set(): event = self.queue.get() @@ -239,11 +252,11 @@ def get_stats(self) -> dict[str, Any]: "isProcessing": active > 0, } - def destroy(self) -> None: - """Stop workers and stop accepting events. Bounded; for tests and - explicit shutdown — nothing registers it at exit anymore. A worker - wedged in a customer hook outlives the join as a daemon and dies - with the process. + def _stop_workers(self, join_budget: float = 1.0) -> None: + """Flag shutdown, wake parked or backing-off workers, and join them + against one shared budget. Never sends anything. A worker wedged in + a customer hook outlives the join as a daemon and dies with the + process. """ self._shutdown = True self._shutdown_event.set() @@ -259,13 +272,18 @@ def destroy(self) -> None: except queue.Full: break - # Shared 1s budget across all joins, never per-thread. - deadline = time.monotonic() + 1.0 + # Shared budget across all joins, never per-thread. + deadline = time.monotonic() + join_budget for t in self._workers: if t is threading.current_thread(): - continue # destroy() called from a worker + continue # called from a worker t.join(timeout=max(0.0, deadline - time.monotonic())) + def destroy(self) -> None: + """Stop workers and stop accepting events. Bounded; for tests and + explicit shutdown.""" + self._stop_workers() + remaining = sum( 1 for item in list(self.queue.queue) if not isinstance(item, _Stop) ) @@ -303,10 +321,31 @@ def set_telemetry_manager(manager: Optional["TelemetryManager"]) -> None: # Global event queue instance. Constructing it starts no threads (workers # are lazy), so this module is importable from any thread. The SDK installs -# no signal handlers and no exit hooks for events: the customer's process +# no signal handlers and never drains events at exit: the customer's process # owns its own shutdown, and undelivered telemetry is dropped by design. event_queue = EventQueue() +# Set once the exit hook below is registered (on first publish, never at +# import). +_exit_stop_registered = False + + +def _stop_workers_at_exit() -> None: + """Stop, never drain. A daemon thread still executing when interpreter + finalization begins is killed via pthread_exit(), which aborts the whole + process on Linux/glibc (CPython gh-87135, fixed in 3.14). atexit + callbacks run before the finalizing flag is set, so stopping the worker + here removes that abort path — and setting the shutdown event also wakes + a worker parked in the retry backoff. Queued events are dropped by + design; nothing is sent from this hook. Forced exits and unhandled + signals skip atexit but also skip finalization, so they carry no abort + risk to begin with. + """ + try: + event_queue._stop_workers() + except Exception: + pass + def set_event_queue(new_queue: EventQueue) -> None: """Replace the global event queue instance (for testing).""" diff --git a/tests/test_diagnostics_export.py b/tests/test_diagnostics_export.py index ca5120b..d731147 100644 --- a/tests/test_diagnostics_export.py +++ b/tests/test_diagnostics_export.py @@ -121,8 +121,10 @@ def test_flush_at_exit_swallows_post_failures(): diagnostics._flush_at_exit() # must not raise -def test_the_diagnostics_hook_is_the_only_atexit_in_the_sdk(): - """The no-drain-at-exit decision, pinned: one bounded atexit hook total.""" +def test_the_sdk_has_exactly_two_bounded_atexit_hooks(): + """The no-drain-at-exit decision, pinned: two bounded atexit hooks total — + the diagnostics beacon (~2s cap, skipped when empty) and the event-queue + worker stop (~1s join budget, sends nothing). Neither drains events.""" import pathlib import agentcat @@ -133,4 +135,4 @@ def test_the_diagnostics_hook_is_the_only_atexit_in_the_sdk(): text = path.read_text() if "atexit.register" in text: registrations.append(path.name) - assert registrations == ["diagnostics.py"], registrations + assert sorted(registrations) == ["diagnostics.py", "event_queue.py"], registrations diff --git a/tests/test_event_queue.py b/tests/test_event_queue.py index e4e545a..fe3b145 100644 --- a/tests/test_event_queue.py +++ b/tests/test_event_queue.py @@ -828,7 +828,8 @@ def test_publish_event_with_redaction_function(self, mock_eq, mock_tracking): def test_module_import_installs_no_process_hooks(): """The SDK must never register signal handlers — the customer's process - owns its own shutdown. (Full subprocess-based checks live in + owns its own shutdown. The one exit hook this module owns registers on + first publish, never at import. (Full subprocess-based checks live in test_process_safety.py; this pins the module surface.)""" import agentcat.modules.event_queue as eq_module @@ -837,8 +838,6 @@ def test_module_import_installs_no_process_hooks(): assert "import signal" not in source assert "signal.signal" not in source assert "os._exit" not in source - assert "import atexit" not in source - assert "atexit.register" not in source def test_bounded_queue_is_the_only_buffer(): diff --git a/tests/test_process_safety.py b/tests/test_process_safety.py index 66a2708..4cbb727 100644 --- a/tests/test_process_safety.py +++ b/tests/test_process_safety.py @@ -184,6 +184,52 @@ def make(): assert "NO-LEAK" in result.stdout +def test_worker_stop_hook_registers_on_first_publish_not_at_import(): + """Importing the queue module must not register exit hooks; the bounded + worker-stop hook appears only once a publish has started the worker.""" + result = _run( + """ +import atexit +from datetime import datetime, timezone + +# Diagnostics registers its own hook at its import; measure after it. +import agentcat.modules.event_queue # noqa: F401 + +baseline = atexit._ncallbacks() + +from agentcat.modules.event_queue import event_queue +from agentcat.types import UnredactedEvent + +assert atexit._ncallbacks() == baseline, "import registered an exit hook" + +event_queue.add( + UnredactedEvent( + id="first", + event_type="mcp:tools/call", + project_id=None, + session_id="ses_x", + timestamp=datetime.now(timezone.utc), + ) +) +assert atexit._ncallbacks() == baseline + 1, "first publish must register the stop hook" + +event_queue.add( + UnredactedEvent( + id="second", + event_type="mcp:tools/call", + project_id=None, + session_id="ses_x", + timestamp=datetime.now(timezone.utc), + ) +) +assert atexit._ncallbacks() == baseline + 1, "hook must register exactly once" +print("LAZY-HOOK") +""" + ) + assert result.returncode == 0, result.stderr + assert "LAZY-HOOK" in result.stdout + + def test_import_survives_missing_distribution_metadata(): """Finding 2: PackageNotFoundError at import time degrades the version string instead of crashing the customer's server at startup.""" From 5d6fc9b62e4f441f32e98ac89db97e39858477a9 Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Tue, 4 Aug 2026 22:34:26 -0400 Subject: [PATCH 12/13] chore: untrack docs/superpowers and gitignore the directory --- .gitignore | 1 + ...26-08-01-python-sdk-v2-explicit-handles.md | 1364 ----------------- ...26-08-01-mcp-2026-07-28-python-v2-audit.md | 445 ------ ...1-python-sdk-v2-explicit-handles-design.md | 466 ------ 4 files changed, 1 insertion(+), 2275 deletions(-) delete mode 100644 docs/superpowers/plans/2026-08-01-python-sdk-v2-explicit-handles.md delete mode 100644 docs/superpowers/specs/2026-08-01-mcp-2026-07-28-python-v2-audit.md delete mode 100644 docs/superpowers/specs/2026-08-01-python-sdk-v2-explicit-handles-design.md diff --git a/.gitignore b/.gitignore index b8bbe6f..cb44375 100644 --- a/.gitignore +++ b/.gitignore @@ -149,3 +149,4 @@ CLAUDE.md .claude/ .serena/ AGENTS.md +docs/superpowers/ diff --git a/docs/superpowers/plans/2026-08-01-python-sdk-v2-explicit-handles.md b/docs/superpowers/plans/2026-08-01-python-sdk-v2-explicit-handles.md deleted file mode 100644 index 5a6f231..0000000 --- a/docs/superpowers/plans/2026-08-01-python-sdk-v2-explicit-handles.md +++ /dev/null @@ -1,1364 +0,0 @@ -# AgentCat Python SDK v2 — Explicit Handles Implementation Plan - -> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. - -> **Superseded in part (2026-08-03).** Everything below calls the handle -> `task_id`. It is now **`session_id`** throughout — the old name collided with -> the MCP Task extension (`tasks/*`), and AgentCat's handle is not an MCP task. -> The rename is mechanical (`TASK_ID_PARAM` → `SESSION_ID_PARAM`, -> `agentcat_task_id_source` → `agentcat_session_id_source`, `resolve_task_id` → -> `resolve_session_id`, `derive_task_id` → `derive_session_id`, and so on), and -> the four frozen derivation vectors are unchanged. One behavior change came -> with it: AgentCat now honors only handles it issued — see -> `agentcat-typescript-sdk/docs/superpowers/specs/2026-08-02-session-id-validation-design.md` -> and `tests/test_session_id_validation.py`. Read this document for the -> architecture; read the code for the names. - -**Goal:** Upgrade `agentcat` to `2.0.0b1`: replace session machinery with stateless per-call `task_id`/`agent_id` handles (MCP 2026-07-28), supporting official MCP SDK 1.x + 2.x and community FastMCP 3.x + 4.x through one `track()` call. - -**Architecture:** Shared pure engine (`handles.py`, `injection.py`, `callpath.py`, `client_identity.py`, `detection.py`) + three thin adapters (`lowlevel_v1`, `lowlevel_v2`, `community`) replacing `modules/overrides/`. Spec: `docs/superpowers/specs/2026-08-01-python-sdk-v2-explicit-handles-design.md`. Behavior contract: `2026-07-28-cross-sdk-changelog.md` (Appendices A/B byte-authoritative). North star: `/Users/naseemalnaji/Projects/mcpcat/agentcat-typescript-sdk` @ `feat/explicit-handles-v2`. - -**Tech Stack:** Python ≥3.10, pydantic 2, `mcp` 1.x/2.x, `fastmcp` 3.x/4.x, uv (conflict groups), pytest + pytest-asyncio, ruff, mypy --strict, hatch. - -## Global Constraints - -- Agent-facing copy MUST be byte-identical to TS `src/modules/constants.ts` (em dashes, quotes, spacing included). Never reword. -- Golden derivation vectors are frozen: `("customer-abc","proj_1")→ses_2cOHEO0LYGADMzRvWTXXVbbgxgm`, `("customer-abc",None)→ses_2cZY3tvyI25O2AmL2CGVo2B1IIj`, `(" x ","p")→ses_2c3yR5mYKQdLaXsJNgZH6erbfQK`, `("x","p")→ses_2bw285VY9apdgUgTPXKFnT6P4G0`. -- `task_id` is stored in `Event.session_id` with the existing `ses_` prefix. No backend/wire changes. -- v2 publishes ONLY `mcp:tools/call` (+ `agentcat:custom`). No `mcp:initialize`, `mcp:tools/list`, `agentcat:identify` events anywhere. -- `track()` never raises. Failures log via `write_to_log` + return the server untracked. -- Never mutate customer objects: deep-copy schemas, clone requests before stripping, copy results before decorating. The published event carries the RAW request and the UNDECORATED response. -- No module-scope imports of version-specific `mcp`/`fastmcp` symbols in engine/detection modules (must import cleanly under both majors). Adapters may import inside functions. -- Private attributes of the SDKs are fair game (CI change detection covers drift). -- Deps: `mcp>=1.2.0,<3`, `pydantic>=2.0.0,<3`, community extra `fastmcp>=3.0.0,<5`, `requires-python>=3.10`. FastMCP 2.x is unsupported (log + return untracked). -- Style: ruff (88 cols), mypy `--strict` on `src/agentcat`, snake_case, `TypedDict` for shared shapes, Conventional Commits. -- Run tests with `uv run pytest -q` (default env = mcp-modern once Task 1 lands; use `uv sync --group mcp-legacy` env for legacy-only suites). Every task ends green in the env(s) it touches. - ---- - -### Task 1: Packaging & dual-generation dev environments - -**Files:** -- Modify: `pyproject.toml` -- Modify: `CONTRIBUTING.md` (dev-env section) - -**Interfaces:** -- Produces: uv dependency-groups `mcp-legacy` (mcp 1.x) and `mcp-modern` (mcp 2.x + fastmcp 4), mutually exclusive; version `2.0.0b1`. - -- [ ] **Step 1: Edit `pyproject.toml`** - -```toml -[project] -version = "2.0.0b1" -dependencies = [ - "mcp>=1.2.0,<3", - "agentcat-api==1.0.0", - "pydantic>=2.0.0,<3", - "requests>=2.31.0", -] - -[project.optional-dependencies] -community = [ - "fastmcp>=3.0.0,<5", -] -# dev extra unchanged - -[dependency-groups] -dev = [ - "freezegun>=1.5.2", - "pytest-asyncio>=1.0.0", - "pytest-cov>=6.1.1", -] -mcp-legacy = ["mcp>=1.2.0,<2", "fastmcp>=3.0.0,<4"] -mcp-modern = ["mcp>=2.0.0,<3", "fastmcp>=4.0.0b1,<5"] - -[tool.uv] -conflicts = [[{ group = "mcp-legacy" }, { group = "mcp-modern" }]] -default-groups = ["dev", "mcp-modern"] -prerelease = "if-necessary-or-explicit" -``` - -- [ ] **Step 2: Verify both environments resolve** - -Run: `uv sync --extra community && uv pip show mcp fastmcp | grep -E "Name|Version"` -Expected: mcp 2.0.x, fastmcp 4.0.0b1. -Run: `uv sync --extra community --no-group mcp-modern --group mcp-legacy && uv pip show mcp fastmcp | grep -E "Name|Version"` -Expected: mcp 1.x (≥1.24), fastmcp 3.x. - -- [ ] **Step 3: Verify current suite still passes in the LEGACY env** - -Run (still in legacy env): `uv run pytest -q -m "not e2e"` -Expected: PASS (code untouched; legacy env matches today's supported range). The modern env is NOT expected to work until Task 8+ — do not run pytest there yet. - -- [ ] **Step 4: Document in CONTRIBUTING.md** - -Add a "Dev environments" section: default sync = modern (`uv sync --extra community`); legacy = `uv sync --extra community --no-group mcp-modern --group mcp-legacy`; explain the conflict groups and that each suite auto-skips by installed major (Task 8 conftest). - -- [ ] **Step 5: Commit** - -```bash -git add pyproject.toml CONTRIBUTING.md -git commit -m "chore: v2.0.0b1 packaging, dual mcp-generation dev envs" -``` - ---- - -### Task 2: Canonical copy constants + byte-parity tests - -**Files:** -- Modify: `src/agentcat/modules/constants.py` -- Test: `tests/test_constants_copy.py` - -**Interfaces:** -- Produces (all in `agentcat.modules.constants`): `TASK_ID_PARAM = "task_id"`, `AGENT_ID_PARAM = "agent_id"`, `CONTEXT_PARAM = "context"`, `GET_MORE_TOOLS_NAME = "get_more_tools"`, `AGENT_ID_PREFIX = "agt"`, `MCP_INSTRUCTIONS_KEY = "_mcp_instructions"`, `META_CLIENT_INFO_KEY`, `META_PROTOCOL_VERSION_KEY`, `AGENTCAT_TAG_TASK_SOURCE`, `AGENTCAT_TAG_AGENT_ID`, `AGENTCAT_TAG_AGENT_SOURCE`, `AGENTCAT_TAG_PROTOCOL_VERSION`, `AGENTCAT_TAG_MRTR`, `AGENTCAT_CUSTOM_EVENT_TYPE = "agentcat:custom"`, `TASK_ID_PARAM_DESCRIPTION`, `AGENT_ID_PARAM_DESCRIPTION`, `AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE`, `MINT_BACK_HEADER_TASK`, `MINT_BACK_CLOSER`, `MCP_INSTRUCTIONS_FIELD_DESCRIPTION`, `MCP_INSTRUCTIONS_TASK_ID_DESCRIPTION`, `MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION`, `mint_back_task_line(task_id: str) -> str`, `mint_back_confirmed(names: list[str]) -> str`. - -- [ ] **Step 1: Write the failing test** — `tests/test_constants_copy.py` asserts every string equals the TS bytes. Copy each expected literal EXACTLY from `agentcat-typescript-sdk/src/modules/constants.ts:20-62` (open the file; do not retype from this plan). Skeleton with the short ones inline: - -```python -"""Byte-parity guard for agent-facing copy (TS constants.ts is the SoT).""" -from agentcat.modules import constants as c - - -def test_param_names_and_keys(): - assert c.TASK_ID_PARAM == "task_id" - assert c.AGENT_ID_PARAM == "agent_id" - assert c.MCP_INSTRUCTIONS_KEY == "_mcp_instructions" - assert c.META_CLIENT_INFO_KEY == "io.modelcontextprotocol/clientInfo" - assert c.META_PROTOCOL_VERSION_KEY == "io.modelcontextprotocol/protocolVersion" - assert c.AGENTCAT_TAG_TASK_SOURCE == "agentcat_task_id_source" - assert c.AGENTCAT_TAG_AGENT_ID == "agentcat_agent_id" - assert c.AGENTCAT_TAG_AGENT_SOURCE == "agentcat_agent_id_source" - assert c.AGENTCAT_TAG_PROTOCOL_VERSION == "agentcat_protocol_version" - assert c.AGENTCAT_TAG_MRTR == "agentcat_mrtr" - assert c.AGENT_ID_PREFIX == "agt" - - -def test_mint_back_assembly(): - assert c.MINT_BACK_HEADER_TASK == "[MCP INSTRUCTIONS]: task_id issued." - assert ( - c.MINT_BACK_CLOSER - == "Without task_id, this server does not function as intended." - ) - assert ( - c.mint_back_task_line("ses_X") - == " task_id=ses_X — required on every subsequent tool call" - ) - assert c.mint_back_confirmed(["task_id"]) == ( - "[MCP INSTRUCTIONS]: task_id confirmed. " - "Keep sending this exact value on every call." - ) - assert c.mint_back_confirmed(["task_id", "agent_id"]) == ( - "[MCP INSTRUCTIONS]: task_id and agent_id confirmed. " - "Keep sending these exact values on every call." - ) - - -def test_param_descriptions_match_ts(): - # Paste full literals from TS constants.ts lines 20-27; spot anchors: - assert c.TASK_ID_PARAM_DESCRIPTION.startswith("REQUIRED on every call after your first.") - assert c.TASK_ID_PARAM_DESCRIPTION.endswith("Without task_id, this server does not function as intended.") - assert "task_id and agent_id" not in c.TASK_ID_PARAM_DESCRIPTION - assert "working this task" in c.AGENT_ID_PARAM_DESCRIPTION - assert "working this task" not in c.AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE - assert c.AGENT_ID_PARAM_DESCRIPTION.replace(" working this task", "") == c.AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE - # ...plus full == comparisons against the pasted literals. -``` - -- [ ] **Step 2: Run to verify it fails** — `uv run pytest tests/test_constants_copy.py -q` → FAIL (AttributeError). - -- [ ] **Step 3: Implement** — append to `constants.py` (copy long strings from TS source, not from here): - -```python -# ── Explicit handles: injected parameter names & wire keys ─────────────────── -TASK_ID_PARAM = "task_id" -AGENT_ID_PARAM = "agent_id" -CONTEXT_PARAM = "context" -GET_MORE_TOOLS_NAME = "get_more_tools" -AGENT_ID_PREFIX = "agt" # reserved; server-side agent minting was removed -MCP_INSTRUCTIONS_KEY = "_mcp_instructions" -META_CLIENT_INFO_KEY = "io.modelcontextprotocol/clientInfo" -META_PROTOCOL_VERSION_KEY = "io.modelcontextprotocol/protocolVersion" -AGENTCAT_TAG_TASK_SOURCE = "agentcat_task_id_source" -AGENTCAT_TAG_AGENT_ID = "agentcat_agent_id" -AGENTCAT_TAG_AGENT_SOURCE = "agentcat_agent_id_source" -AGENTCAT_TAG_PROTOCOL_VERSION = "agentcat_protocol_version" -AGENTCAT_TAG_MRTR = "agentcat_mrtr" -AGENTCAT_CUSTOM_EVENT_TYPE = "agentcat:custom" - -# ── Explicit handles: agent-facing copy (byte-identical to TS constants.ts) ── -TASK_ID_PARAM_DESCRIPTION = "REQUIRED on every call after your first. ..." # full TS string -AGENT_ID_PARAM_DESCRIPTION = "REQUIRED on every call, including your first. ..." # full TS string -AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE = "..." # full TS string (no "working this task") -MINT_BACK_HEADER_TASK = "[MCP INSTRUCTIONS]: task_id issued." -MINT_BACK_CLOSER = "Without task_id, this server does not function as intended." -MCP_INSTRUCTIONS_FIELD_DESCRIPTION = "Your handles for this task, confirmed by this MCP server on every response, and the instructions for echoing them on later calls. Read and follow." -MCP_INSTRUCTIONS_TASK_ID_DESCRIPTION = "Echo this exact value as the task_id argument on every subsequent tool call." -MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION = "Your agent_id as this server received it. Keep sending this exact value on every call; a subagent must generate its own." - - -def mint_back_task_line(task_id: str) -> str: - return f" task_id={task_id} — required on every subsequent tool call" - - -def mint_back_confirmed(names: list[str]) -> str: - tail = "these exact values" if len(names) > 1 else "this exact value" - return ( - f"[MCP INSTRUCTIONS]: {' and '.join(names)} confirmed. " - f"Keep sending {tail} on every call." - ) -``` - -- [ ] **Step 4: Run** — `uv run pytest tests/test_constants_copy.py -q` → PASS. Also `uv run ruff check src tests` → clean. - -- [ ] **Step 5: Commit** — `git commit -m "feat(handles): canonical agent-facing copy constants (TS byte-parity)"` - ---- - -### Task 3: Options & type additions (additive only) - -**Files:** -- Modify: `src/agentcat/types.py` -- Test: `tests/test_options_v2.py` - -**Interfaces:** -- Produces: `ResolveTaskIdFunction = Callable[[Any, Any], str | None | Awaitable[str | None]]`; `AgentCatOptions.enable_agent_tracking: bool = False`; `AgentCatOptions.resolve_task_id: ResolveTaskIdFunction | None = None`; `class CustomEventData(TypedDict, total=False)` with keys `task_id, resource_name, parameters, response, message, duration, is_error, error, tags, properties`; `AgentCatData` gains `injected_params_registry: dict[str, set[str]] | None = None`, `output_injection_registry: set[str] | None = None`, `original_list_source: Any = None`, `server_name: str | None = None`, `server_version: str | None = None`. Do NOT remove `stateless`/session fields yet (Task 11). -- Docstrings for the two options adapted from TS `src/types.ts:6-26` (types.ts wording, not the stale index.ts `@param`). - -- [ ] **Step 1: Failing test** - -```python -from agentcat.types import AgentCatOptions, CustomEventData - - -def test_v2_option_defaults(): - o = AgentCatOptions() - assert o.enable_agent_tracking is False - assert o.resolve_task_id is None - - -def test_custom_event_data_keys(): - d: CustomEventData = {"task_id": "ses_x", "is_error": False, "tags": {"a": "b"}} - assert d["task_id"] == "ses_x" -``` - -- [ ] **Step 2: Run → FAIL.** `uv run pytest tests/test_options_v2.py -q` -- [ ] **Step 3: Implement in `types.py`** (fields + TypedDict + registry fields on `AgentCatData`). -- [ ] **Step 4: Run → PASS; `uv run mypy src/agentcat --strict` clean for the touched file.** -- [ ] **Step 5: Commit** — `git commit -m "feat(types): v2 options (agent tracking, resolve_task_id) and CustomEventData"` - ---- - -### Task 4: Handle primitives (`modules/handles.py`) - -**Files:** -- Create: `src/agentcat/modules/handles.py` -- Test: `tests/test_handles.py` - -**Interfaces:** -- Produces: - - `@dataclass HandleResolution(task_id: str, task_source: Literal["supplied","minted","hook"], agent_id: str | None = None, agent_source: Literal["supplied"] | None = None, hook_mode: bool = False)` - - `new_task_id() -> str` - - `derive_task_id(id: str, project_id: str | None = None) -> str` - - `extract_handle(arguments: Any, name: str) -> str | None` - - `async resolve_handles(arguments: Any, options: AgentCatOptions, project_id: str | None, request: Any, extra: Any) -> HandleResolution` - - `build_mint_back_text(res: HandleResolution) -> str | None` (non-None only when `task_source=="minted"` and not `hook_mode`) - - `build_structured_mint_back(res: HandleResolution) -> dict[str, Any] | None` - - `mirror_into_structured_content(sc: Any, mint: dict[str, Any]) -> Any | None` (returns the NEW dict, or `None` = leave result untouched) - - `build_handle_tags(res: HandleResolution, protocol_version: str | None = None, mrtr: str | None = None) -> dict[str, str]` - -- [ ] **Step 1: Failing tests** (port of TS `handles.test.ts`): - -```python -import asyncio -import pytest -from agentcat.modules.handles import ( - HandleResolution, build_handle_tags, build_mint_back_text, - build_structured_mint_back, derive_task_id, extract_handle, - mirror_into_structured_content, new_task_id, resolve_handles, -) -from agentcat.types import AgentCatOptions - - -def test_mint_shape(): - a, b = new_task_id(), new_task_id() - assert a.startswith("ses_") and len(a) == 4 + 27 and a != b - - -def test_golden_vectors(): - assert derive_task_id("customer-abc", "proj_1") == "ses_2cOHEO0LYGADMzRvWTXXVbbgxgm" - assert derive_task_id("customer-abc") == "ses_2cZY3tvyI25O2AmL2CGVo2B1IIj" - assert derive_task_id(" x ", "p") == "ses_2c3yR5mYKQdLaXsJNgZH6erbfQK" # no trim - assert derive_task_id("x", "p") == "ses_2bw285VY9apdgUgTPXKFnT6P4G0" - - -def test_extract_handle_trust_model(): - assert extract_handle({"task_id": " ses_x "}, "task_id") == "ses_x" - assert extract_handle({"task_id": "my-own-correlation-id"}, "task_id") == "my-own-correlation-id" - for bad in ({"task_id": ""}, {"task_id": " "}, {"task_id": 42}, None, "str"): - assert extract_handle(bad, "task_id") is None - - -async def test_prompted_supplied_vs_minted(): - o = AgentCatOptions() - r1 = await resolve_handles({"task_id": "ses_supplied"}, o, "proj", None, None) - assert (r1.task_id, r1.task_source, r1.hook_mode) == ("ses_supplied", "supplied", False) - r2 = await resolve_handles({}, o, "proj", None, None) - assert r2.task_source == "minted" and r2.task_id.startswith("ses_") - - -async def test_hook_mode_derives_and_falls_back(): - o = AgentCatOptions(resolve_task_id=lambda req, extra: " customer-abc ") - r = await resolve_handles({"task_id": "ignored"}, o, "proj_1", None, None) - assert r.task_id == derive_task_id("customer-abc", "proj_1") # trimmed by caller - assert r.task_source == "hook" and r.hook_mode is True - - async def async_hook(req, extra): - return "customer-abc" - r = await resolve_handles({}, AgentCatOptions(resolve_task_id=async_hook), "proj_1", None, None) - assert r.task_source == "hook" - - def boom(req, extra): - raise RuntimeError("hook broke") - r = await resolve_handles({}, AgentCatOptions(resolve_task_id=boom), "proj_1", None, None) - assert r.task_source == "minted" and r.hook_mode is True - r = await resolve_handles({}, AgentCatOptions(resolve_task_id=lambda q, e: None), None, None, None) - assert r.task_source == "minted" and r.hook_mode is True - - -async def test_agent_extraction_gated_on_option(): - on = AgentCatOptions(enable_agent_tracking=True) - r = await resolve_handles({"agent_id": " a|b|c "}, on, None, None, None) - assert (r.agent_id, r.agent_source) == ("a|b|c", "supplied") - r = await resolve_handles({"agent_id": "a|b|c"}, AgentCatOptions(), None, None, None) - assert r.agent_id is None - - -def test_mint_back_text_rules(): - minted = HandleResolution(task_id="ses_T", task_source="minted") - assert build_mint_back_text(minted) == ( - "[MCP INSTRUCTIONS]: task_id issued.\n" - " task_id=ses_T — required on every subsequent tool call\n" - "Without task_id, this server does not function as intended." - ) - assert build_mint_back_text(HandleResolution("ses_T", "supplied")) is None - assert build_mint_back_text(HandleResolution("ses_T", "minted", hook_mode=True)) is None - - -def test_structured_mint_back_omission_rules(): - both = HandleResolution("ses_T", "supplied", agent_id="A", agent_source="supplied") - m = build_structured_mint_back(both) - assert m == { - "task_id": "ses_T", "agent_id": "A", - "instructions": "[MCP INSTRUCTIONS]: task_id and agent_id confirmed. Keep sending these exact values on every call.", - } - hook_agent = HandleResolution("ses_T", "hook", agent_id="A", agent_source="supplied", hook_mode=True) - m = build_structured_mint_back(hook_agent) - assert "task_id" not in m and m["agent_id"] == "A" and "agent_id confirmed" in m["instructions"] - assert build_structured_mint_back(HandleResolution("ses_T", "hook", hook_mode=True)) is None - minted = HandleResolution("ses_T", "minted") - assert build_structured_mint_back(minted)["instructions"].startswith("[MCP INSTRUCTIONS]: task_id issued.") - - -def test_mirror_rules(): - mint = {"task_id": "ses_T", "instructions": "i"} - assert mirror_into_structured_content(None, mint) is None - assert mirror_into_structured_content([1], mint) is None - assert mirror_into_structured_content({"_mcp_instructions": "customer"}, mint) is None - out = mirror_into_structured_content({"a": 1}, mint) - assert out == {"a": 1, "_mcp_instructions": mint} - - -def test_tag_clamp(): - res = HandleResolution("ses_T", "supplied", agent_id="a\r\nb" + "x" * 300, agent_source="supplied") - tags = build_handle_tags(res, protocol_version="2026-07-28", mrtr="continuation") - assert tags["agentcat_task_id_source"] == "supplied" - assert tags["agentcat_agent_id"].startswith("a b") and len(tags["agentcat_agent_id"]) == 200 - assert tags["agentcat_agent_id_source"] == "supplied" - assert tags["agentcat_protocol_version"] == "2026-07-28" - assert tags["agentcat_mrtr"] == "continuation" - assert build_handle_tags(HandleResolution("s", "minted")) == {"agentcat_task_id_source": "minted"} -``` - -- [ ] **Step 2: Run → FAIL** (`ModuleNotFoundError`). -- [ ] **Step 3: Implement `handles.py`:** - -```python -"""Explicit-handle primitives: minting, derivation, extraction, mint-back. - -Cross-SDK contract: 2026-07-28-cross-sdk-changelog.md §3-§4; TS reference -src/modules/handles.ts. Derivation golden vectors are frozen — changing them -splits customer tasks across an upgrade. -""" -import hashlib -import inspect -from dataclasses import dataclass -from typing import Any, Literal, Optional - -from agentcat.modules.constants import ( - AGENT_ID_PARAM, AGENTCAT_TAG_AGENT_ID, AGENTCAT_TAG_AGENT_SOURCE, - AGENTCAT_TAG_MRTR, AGENTCAT_TAG_PROTOCOL_VERSION, AGENTCAT_TAG_TASK_SOURCE, - MCP_INSTRUCTIONS_KEY, MINT_BACK_CLOSER, MINT_BACK_HEADER_TASK, - SESSION_ID_PREFIX, TASK_ID_PARAM, mint_back_confirmed, mint_back_task_line, -) -from agentcat.modules.logging import write_to_log -from agentcat.thirdparty.ksuid import Ksuid -from agentcat.utils import generate_prefixed_ksuid - -_KSUID_EPOCH_MS = 1_400_000_000_000 -_DERIVE_EPOCH_MS = 1_704_067_200_000 # 2024-01-01T00:00:00Z -_YEAR_MS = 365 * 24 * 60 * 60 * 1000 - - -@dataclass -class HandleResolution: - task_id: str - task_source: Literal["supplied", "minted", "hook"] - agent_id: Optional[str] = None - agent_source: Optional[Literal["supplied"]] = None - hook_mode: bool = False - - -def new_task_id() -> str: - return generate_prefixed_ksuid(SESSION_ID_PREFIX) - - -def derive_task_id(id: str, project_id: str | None = None) -> str: - # NOTE: does not trim — callers trim (resolve_handles trims hook output). - payload_input = f"{id}:{project_id}" if project_id else id - digest = hashlib.sha256(payload_input.encode("utf-8")).digest() - ts_ms = _DERIVE_EPOCH_MS + (int.from_bytes(digest[0:4], "big") % _YEAR_MS) - ts_field = (ts_ms - _KSUID_EPOCH_MS) // 1000 - raw = ts_field.to_bytes(4, "big") + digest[4:20] - return f"{SESSION_ID_PREFIX}_{Ksuid.from_bytes(raw)}" - - -def extract_handle(arguments: Any, name: str) -> str | None: - if not isinstance(arguments, dict): - return None - value = arguments.get(name) - if isinstance(value, str) and value.strip(): - return value.strip() - return None - - -async def resolve_handles(arguments, options, project_id, request, extra) -> HandleResolution: - hook = options.resolve_task_id - agent_id = ( - extract_handle(arguments, AGENT_ID_PARAM) - if options.enable_agent_tracking else None - ) - agent_source: Literal["supplied"] | None = "supplied" if agent_id else None - - if callable(hook): - try: - value = hook(request, extra) - if inspect.isawaitable(value): - value = await value - except Exception as e: # hook errors mint silently - write_to_log(f"Warning: resolve_task_id hook raised: {e}") - value = None - if isinstance(value, str) and value.strip(): - return HandleResolution( - derive_task_id(value.strip(), project_id), "hook", - agent_id, agent_source, hook_mode=True, - ) - return HandleResolution(new_task_id(), "minted", agent_id, agent_source, hook_mode=True) - - supplied = extract_handle(arguments, TASK_ID_PARAM) - if supplied: - return HandleResolution(supplied, "supplied", agent_id, agent_source) - return HandleResolution(new_task_id(), "minted", agent_id, agent_source) - - -def build_mint_back_text(res: HandleResolution) -> str | None: - if res.task_source != "minted" or res.hook_mode: - return None - return "\n".join( - [MINT_BACK_HEADER_TASK, mint_back_task_line(res.task_id), MINT_BACK_CLOSER] - ) - - -def build_structured_mint_back(res: HandleResolution) -> dict[str, Any] | None: - names: list[str] = [] - if not res.hook_mode: - names.append(TASK_ID_PARAM) - if res.agent_id: - names.append(AGENT_ID_PARAM) - if not names: - return None - mint: dict[str, Any] = {} - if not res.hook_mode: - mint[TASK_ID_PARAM] = res.task_id - if res.agent_id: - mint[AGENT_ID_PARAM] = res.agent_id - mint["instructions"] = build_mint_back_text(res) or mint_back_confirmed(names) - return mint - - -def mirror_into_structured_content(sc: Any, mint: dict[str, Any]) -> Any | None: - if not isinstance(sc, dict) or MCP_INSTRUCTIONS_KEY in sc: - return None - return {**sc, MCP_INSTRUCTIONS_KEY: mint} - - -def build_handle_tags(res, protocol_version=None, mrtr=None) -> dict[str, str]: - tags = {AGENTCAT_TAG_TASK_SOURCE: res.task_source} - if res.agent_id and res.agent_source: - clamped = res.agent_id.replace("\r", " ").replace("\n", " ")[:200] - tags[AGENTCAT_TAG_AGENT_ID] = clamped - tags[AGENTCAT_TAG_AGENT_SOURCE] = res.agent_source - if protocol_version: - tags[AGENTCAT_TAG_PROTOCOL_VERSION] = protocol_version - if mrtr: - tags[AGENTCAT_TAG_MRTR] = mrtr - return tags -``` - -If the golden-vector test fails: diff against TS `src/modules/handles.ts:33-47` and `src/thirdparty/ksuid/index.js:44-50` (`Math.floor((ms-14e11)/1e3)` uint32-BE + `hash[4:20]`). Do NOT adjust the vectors. - -- [ ] **Step 4: Run → PASS**; `uv run mypy src/agentcat/modules/handles.py --strict` clean. -- [ ] **Step 5: Commit** — `git commit -m "feat(handles): mint/derive/extract/mint-back primitives with TS golden parity"` - ---- - -### Task 5: Pure injection pipeline (`modules/injection.py`) - -**Files:** -- Create: `src/agentcat/modules/injection.py` -- Test: `tests/test_injection.py` - -**Interfaces:** -- Produces: - - `@dataclass ToolSpec(name: str, input_schema: dict[str, Any], output_schema: dict[str, Any] | None = None)` — schemas are the adapter's DEEP COPIES; the pipeline mutates them in place. - - `@dataclass InjectionResult(injected_params: dict[str, set[str]], output_injected: set[str])` - - `build_injected_schemas(tools: list[ToolSpec], options: AgentCatOptions) -> InjectionResult` - - `strip_injected_arguments(tool_name: str, arguments: dict[str, Any], registry: dict[str, set[str]] | None) -> dict[str, Any]` — always returns a new dict; `registry=None` → heuristic (strip `task_id`/`agent_id`/`context`, except `get_more_tools` keeps `context`). - - `mcp_instructions_schema_property() -> dict[str, Any]` — the `_mcp_instructions` outputSchema fragment. -- Consumes: Task 2 constants, Task 3 options. - -- [ ] **Step 1: Failing tests** (key cases; write all of these): - -```python -import copy -from agentcat.modules.injection import ( - InjectionResult, ToolSpec, build_injected_schemas, - mcp_instructions_schema_property, strip_injected_arguments, -) -from agentcat.modules import constants as c -from agentcat.types import AgentCatOptions - - -def spec(name="t", props=None, extra=None, out=None): - schema = {"type": "object", "properties": dict(props or {"q": {"type": "string"}})} - schema.update(extra or {}) - return ToolSpec(name=name, input_schema=schema, output_schema=out) - - -def test_param_order_and_descriptions(): - s = spec() - r = build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) - keys = list(s.input_schema["properties"]) - assert keys == ["q", "task_id", "agent_id", "context"] - assert s.input_schema["properties"]["task_id"]["description"] == c.TASK_ID_PARAM_DESCRIPTION - assert s.input_schema["properties"]["agent_id"]["description"] == c.AGENT_ID_PARAM_DESCRIPTION - assert "task_id" not in s.input_schema.get("required", []) - assert "agent_id" in s.input_schema["required"] - assert r.injected_params["t"] == {"task_id", "agent_id", "context"} - - -def test_hook_mode_omits_task_id_and_switches_agent_copy(): - s = spec() - build_injected_schemas([s], AgentCatOptions( - enable_agent_tracking=True, resolve_task_id=lambda q, e: "x")) - props = s.input_schema["properties"] - assert "task_id" not in props - assert props["agent_id"]["description"] == c.AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE - - -def test_tracing_disabled_skips_handles_but_not_context(): - s = spec() - r = build_injected_schemas([s], AgentCatOptions(enable_tracing=False)) - assert set(s.input_schema["properties"]) == {"q", "context"} - assert r.injected_params["t"] == {"context"} - - -def test_additional_properties_false_removed(): - s = spec(extra={"additionalProperties": False}) - build_injected_schemas([s], AgentCatOptions()) - assert "additionalProperties" not in s.input_schema - - -def test_composed_schema_skipped_with_empty_registry_entry(): - s = ToolSpec(name="t", input_schema={"oneOf": [{"type": "object"}]}) - r = build_injected_schemas([s], AgentCatOptions()) - assert s.input_schema == {"oneOf": [{"type": "object"}]} - assert r.injected_params["t"] == set() - - -def test_collision_skips_that_param_only(): - s = spec(props={"task_id": {"type": "string", "description": "customer"}}) - r = build_injected_schemas([s], AgentCatOptions(enable_agent_tracking=True)) - assert s.input_schema["properties"]["task_id"]["description"] == "customer" - assert r.injected_params["t"] == {"agent_id", "context"} - - -def test_get_more_tools_gets_handles_but_not_context(): - s = spec(name=c.GET_MORE_TOOLS_NAME, props={"context": {"type": "string"}}) - r = build_injected_schemas([s], AgentCatOptions()) - assert r.injected_params[c.GET_MORE_TOOLS_NAME] == {"task_id"} - - -def test_output_schema_extension_and_registry(): - s = spec(out={"type": "object", "properties": {"answer": {"type": "string"}}}) - r = build_injected_schemas([s], AgentCatOptions()) - prop = s.output_schema["properties"][c.MCP_INSTRUCTIONS_KEY] - assert prop["description"] == c.MCP_INSTRUCTIONS_FIELD_DESCRIPTION - assert prop["properties"]["task_id"]["description"] == c.MCP_INSTRUCTIONS_TASK_ID_DESCRIPTION - assert c.MCP_INSTRUCTIONS_KEY not in s.output_schema.get("required", []) - assert r.output_injected == {"t"} - s2 = spec(out={"oneOf": []}) - r2 = build_injected_schemas([s2], AgentCatOptions()) - assert r2.output_injected == set() - - -def test_determinism(): - def make(): - return [spec(), spec(name="u", extra={"additionalProperties": False})] - a, b = make(), make() - ra = build_injected_schemas(a, AgentCatOptions(enable_agent_tracking=True)) - rb = build_injected_schemas(b, AgentCatOptions(enable_agent_tracking=True)) - assert ra == rb and [t.input_schema for t in a] == [t.input_schema for t in b] - - -def test_strip_registry_driven_and_heuristic(): - args = {"q": 1, "task_id": "s", "agent_id": "a", "context": "c"} - reg = {"t": {"task_id", "context"}} - out = strip_injected_arguments("t", args, reg) - assert out == {"q": 1, "agent_id": "a"} and args["task_id"] == "s" # clone - # Registry present but tool not in it: it was never advertised through the - # pipeline, so nothing was injected for it — strip nothing. - assert strip_injected_arguments("unknown", args, reg) == args - assert strip_injected_arguments("t", args, None) == {"q": 1} - gmt = {"context": "real", "task_id": "s"} - assert strip_injected_arguments(c.GET_MORE_TOOLS_NAME, gmt, None) == {"context": "real"} -``` - -- [ ] **Step 2: Run → FAIL.** -- [ ] **Step 3: Implement.** Core injector: - -```python -_COMPOSED_KEYS = ("oneOf", "allOf", "anyOf") - - -def _inject_param(schema: dict, name: str, description: str, required: bool, registry_entry: set[str]) -> None: - props = schema.setdefault("properties", {}) - if name in props: - write_to_log(f"Warning: tool already defines '{name}'; skipping injection") - return - props[name] = {"type": "string", "description": description} - if required: - schema.setdefault("required", []) - if name not in schema["required"]: - schema["required"].append(name) - registry_entry.add(name) - - -def build_injected_schemas(tools, options): - hook_mode = callable(options.resolve_task_id) - result = InjectionResult(injected_params={}, output_injected=set()) - for tool in tools: - entry: set[str] = set() - result.injected_params[tool.name] = entry - schema = tool.input_schema - if any(k in schema for k in _COMPOSED_KEYS): - write_to_log(f"Warning: composed input schema on '{tool.name}'; skipping injection") - continue - if schema.get("additionalProperties") is False: - del schema["additionalProperties"] - if options.enable_tracing and not hook_mode: - _inject_param(schema, TASK_ID_PARAM, TASK_ID_PARAM_DESCRIPTION, False, entry) - if options.enable_tracing and options.enable_agent_tracking: - desc = AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE if hook_mode else AGENT_ID_PARAM_DESCRIPTION - _inject_param(schema, AGENT_ID_PARAM, desc, True, entry) - if options.enable_tool_call_context and tool.name != GET_MORE_TOOLS_NAME: - _inject_param(schema, CONTEXT_PARAM, options.custom_context_description, False, entry) - out = tool.output_schema - if isinstance(out, dict): - if any(k in out for k in _COMPOSED_KEYS): - write_to_log(f"Warning: composed output schema on '{tool.name}'; content-only mint-back") - elif isinstance(out.get("properties"), dict): - if MCP_INSTRUCTIONS_KEY not in out["properties"]: - out["properties"][MCP_INSTRUCTIONS_KEY] = mcp_instructions_schema_property() - result.output_injected.add(tool.name) - return result -``` - -`mcp_instructions_schema_property()` returns `{"type": "object", "description": MCP_INSTRUCTIONS_FIELD_DESCRIPTION, "properties": {"task_id": {"type": "string", "description": MCP_INSTRUCTIONS_TASK_ID_DESCRIPTION}, "agent_id": {"type": "string", "description": MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION}, "instructions": {"type": "string"}}}`. `strip_injected_arguments` per the test contract (registry present + tool listed → strip exactly the entry; registry present + tool unknown → strip nothing; registry `None` → heuristic with the `get_more_tools` context exception). - -- [ ] **Step 4: Run → PASS; ruff + mypy clean.** -- [ ] **Step 5: Commit** — `git commit -m "feat(injection): pure schema-injection pipeline with registries"` - ---- - -### Task 6: Detection & client identity - -**Files:** -- Create: `src/agentcat/modules/detection.py`, `src/agentcat/modules/client_identity.py` -- Test: `tests/test_detection.py`, `tests/test_client_identity.py` - -**Interfaces:** -- Produces (`detection.py`): - - `class ServerFlavor(str, Enum)`: `LOWLEVEL_V1, LOWLEVEL_V2, OFFICIAL_FASTMCP_V1, MCPSERVER_V2, COMMUNITY_V3, COMMUNITY_V4, COMMUNITY_V2_UNSUPPORTED, UNKNOWN` - - `@dataclass Detection(flavor: ServerFlavor, lowlevel: Any | None, fingerprint: dict[str, bool])` — `lowlevel` = the object adapters wrap (`_mcp_server` / `_lowlevel_server` / the server itself; `None` for community + unknown). - - `detect_server(server: Any) -> Detection` -- Produces (`client_identity.py`): - - `@dataclass ClientIdentity(name: str | None = None, version: str | None = None)` - - `client_identity_from_meta(meta: Any) -> ClientIdentity | None` — reads `META_CLIENT_INFO_KEY`, per-field `isinstance(str)` narrowing. - - `resolve_client_identity(meta_sources: list[Any], legacy: Callable[[], Any | None]) -> ClientIdentity` — first meta hit wins, then legacy object (accepts objects with `.name`/`.version` attrs or dicts), else empty. - - `resolve_protocol_version(meta_sources: list[Any], fallback: str | None = None) -> str | None` -- Probes (fingerprint keys, spec §8.1): `is_fastmcp_class`, `has_local_provider`, `has_add_middleware`, `has_middleware`, `has_tool_manager`, `has_mcp_server_attr`, `has_lowlevel_server_attr`, `has_extensions`, `has_request_state_security`, `has_request_handlers`, `has_private_request_handlers`, `has_add_request_handler`, `has_request_context`. - -- [ ] **Step 1: Failing tests.** Build minimal doubles — module/class names matter: - -```python -from agentcat.modules.detection import Detection, ServerFlavor, detect_server - - -def make(name, module, **attrs): - cls = type(name, (), {}) - cls.__module__ = module - obj = cls() - for k, v in attrs.items(): - setattr(obj, k, v) - return obj - - -def test_community_v4_vs_v3(): - base = dict(_local_provider=object(), add_middleware=lambda m: None, middleware=[]) - v3 = make("FastMCP", "fastmcp.server.server", **base) - v4 = make("FastMCP", "fastmcp.server.server", **base, _extensions={}, add_extension=lambda e: None) - assert detect_server(v3).flavor is ServerFlavor.COMMUNITY_V3 - assert detect_server(v4).flavor is ServerFlavor.COMMUNITY_V4 - - -def test_community_v2_unsupported(): - v2 = make("FastMCP", "fastmcp.server", _mcp_server=object(), _tool_manager=object()) - assert detect_server(v2).flavor is ServerFlavor.COMMUNITY_V2_UNSUPPORTED - - -def test_official_flavors(): - ll1 = make("Server", "mcp.server.lowlevel.server", request_handlers={}, request_context=None) - ll2 = make("Server", "mcp.server.lowlevel.server", _request_handlers={}, add_request_handler=lambda *a: None) - fm1 = make("FastMCP", "mcp.server.fastmcp.server", _mcp_server=ll1, _tool_manager=object()) - ms2 = make("MCPServer", "mcp.server.mcpserver.server", _lowlevel_server=ll2, _tool_manager=object()) - assert detect_server(ll1).flavor is ServerFlavor.LOWLEVEL_V1 - d = detect_server(ll2); assert d.flavor is ServerFlavor.LOWLEVEL_V2 and d.lowlevel is ll2 - d = detect_server(fm1); assert d.flavor is ServerFlavor.OFFICIAL_FASTMCP_V1 and d.lowlevel is ll1 - d = detect_server(ms2); assert d.flavor is ServerFlavor.MCPSERVER_V2 and d.lowlevel is ll2 - - -def test_unknown_shape_has_fingerprint(): - d = detect_server(object()) - assert d.flavor is ServerFlavor.UNKNOWN and isinstance(d.fingerprint, dict) -``` - -`tests/test_client_identity.py`: - -```python -from agentcat.modules.client_identity import ( - ClientIdentity, client_identity_from_meta, resolve_client_identity, resolve_protocol_version, -) - -KEY = "io.modelcontextprotocol/clientInfo" -PV = "io.modelcontextprotocol/protocolVersion" - - -def test_meta_narrowing(): - assert client_identity_from_meta({KEY: {"name": "cursor", "version": "2.1"}}) == ClientIdentity("cursor", "2.1") - assert client_identity_from_meta({KEY: {"name": "cursor", "version": 7}}) == ClientIdentity("cursor", None) - assert client_identity_from_meta({KEY: "junk"}) is None - assert client_identity_from_meta(None) is None - - -def test_ladder_order_and_legacy(): - envelope = {KEY: {"name": "envelope", "version": "1"}} - passthrough = {KEY: {"name": "meta", "version": "2"}} - class Legacy: # duck-typed clientInfo object - name, version = "legacy", "3" - assert resolve_client_identity([envelope, passthrough], lambda: Legacy()).name == "envelope" - assert resolve_client_identity([None, passthrough], lambda: Legacy()).name == "meta" - assert resolve_client_identity([None, None], lambda: Legacy()).name == "legacy" - assert resolve_client_identity([None], lambda: (_ for _ in ()).throw(RuntimeError())) == ClientIdentity() - - -def test_protocol_version(): - assert resolve_protocol_version([{PV: "2026-07-28"}]) == "2026-07-28" - assert resolve_protocol_version([None], fallback="2026-07-28") == "2026-07-28" - assert resolve_protocol_version([{PV: 9}]) is None -``` - -- [ ] **Step 2: Run → FAIL.** -- [ ] **Step 3: Implement.** Detection order: community v2 check BEFORE official-fastmcp-v1 (both have `_mcp_server`+`_tool_manager`; discriminate on module prefix `fastmcp` vs `mcp.server.fastmcp`). `meta` access supports both Mapping (`meta.get(KEY)`) and pydantic `Meta` objects (try `.model_extra.get(KEY)` then `getattr`). Legacy accepts objects (`.name`/`.version`) or dicts. Everything wrapped so no probe can raise. -- [ ] **Step 4: Run → PASS.** Extra check: `uv run python -c "import agentcat.modules.detection, agentcat.modules.client_identity"` in BOTH envs (legacy + modern) — must import cleanly (no version-specific imports). -- [ ] **Step 5: Commit** — `git commit -m "feat(detection): per-object flavor classifier and per-request client identity ladder"` - ---- - -### Task 7: Call-path orchestration (`modules/callpath.py`) - -**Files:** -- Create: `src/agentcat/modules/callpath.py` -- Test: `tests/test_callpath.py` - -**Interfaces:** -- Produces: - - `@dataclass ResolvedCall(resolution: HandleResolution, actor: UserIdentity | None, client: ClientIdentity, protocol_version: str | None, intent: str | None)` - - `async resolve_call(data: AgentCatData, tool_name: str, raw_arguments: dict, request: Any, extra: Any, meta_sources: list[Any], legacy_client: Callable[[], Any | None], protocol_fallback: str | None = None) -> ResolvedCall` — runs `resolve_handles`, the customer `identify` hook (never raises), the client ladder; captures `intent = raw_arguments.get("context")` when a str. - - `async get_stripped_arguments(data: AgentCatData, options, tool_name: str, raw_arguments: dict, rebuild: Callable[[], Awaitable[list[ToolSpec]]] | None) -> dict` — registry from `data.injected_params_registry`; on `None` awaits `rebuild()` → `build_injected_schemas` → stores registries on `data`; on failure logs + heuristic strip (and sets `data.output_injection_registry = None` so the mirror gate is bypassed). - - `detect_mrtr(result_type: str | None, has_input_responses: bool) -> str | None` → `"input_required" | "continuation" | None`. - - `decorate_content(content: list[Any] | None, res: HandleResolution, make_text_block: Callable[[str], Any]) -> list[Any] | None` — returns a NEW list with the trailing block appended, or `None` when no decoration applies (not minted / hook mode / content not a list). - - `structured_mirror(sc: Any, res: HandleResolution, tool_name: str, output_registry: set[str] | None) -> Any | None` — gate: mirror when `output_registry is None` (rebuild failed) or `tool_name in output_registry`; delegates to `mirror_into_structured_content`. - - `async publish_tool_call_event(server_key: Any, data: AgentCatData, rc: ResolvedCall, tool_name: str, raw_arguments: dict, response: Any, is_error: bool, error_msg: str | None, duration_ms: int | None, mrtr: str | None, extra_params: dict | None) -> None` — builds `UnredactedEvent(event_type="mcp:tools/call", session_id=rc.resolution.task_id, resource_name=tool_name, user_intent=rc.intent, parameters={"arguments": raw_arguments, **(extra_params or {})}, response=response, is_error=is_error, error=..., client_name=rc.client.name, client_version=rc.client.version, identify_actor_given_id=..., ...)`, resolves customer tags/properties via `attach_event_metadata`, then merges `build_handle_tags(rc.resolution, rc.protocol_version, mrtr)` OVER them (SDK wins; exempt from the 50-tag cap — merge after `validate_tags`), and `event_queue.publish_event(server_key, event)`. -- Consumes: Tasks 4–6 symbols exactly as defined there. - -- [ ] **Step 1: Failing tests** — pure-python fakes, no MCP imports. Cover: identify hook error → `actor is None`; `intent` captured; strip with registry / rebuild-success (fake rebuild returns `ToolSpec`s and registries land on `data`) / rebuild-raise → heuristic + `output_injection_registry is None`; `detect_mrtr` matrix; `decorate_content` minted vs supplied vs hook vs non-list content (append also happens on `is_error` results — `decorate_content` never looks at error state); `structured_mirror` gate matrix (in registry / not in registry / registry None); `publish_tool_call_event` → capture `event_queue.publish_event` with monkeypatch and assert `session_id`, raw args, SDK tag merge collision (customer tag `agentcat_task_id_source:"fake"` is overridden), 50-cap exemption (50 customer tags + SDK tags all present). Anchor style: - -```python -from agentcat.modules.callpath import decorate_content, detect_mrtr, get_stripped_arguments -from agentcat.modules.handles import HandleResolution -from agentcat.modules.injection import ToolSpec -from agentcat.types import AgentCatData, AgentCatOptions - - -def test_detect_mrtr_matrix(): - assert detect_mrtr("input_required", False) == "input_required" - assert detect_mrtr("input_required", True) == "input_required" # intermediate wins - assert detect_mrtr(None, True) == "continuation" - assert detect_mrtr("complete", False) is None - - -def test_decorate_content_only_when_minted_prompted(): - minted = HandleResolution("ses_T", "minted") - out = decorate_content([{"type": "text", "text": "x"}], minted, lambda t: {"type": "text", "text": t}) - assert out is not None and "[MCP INSTRUCTIONS]: task_id issued." in out[-1]["text"] - assert decorate_content([{"t": 1}], HandleResolution("ses_T", "supplied"), dict) is None - assert decorate_content([{"t": 1}], HandleResolution("ses_T", "minted", hook_mode=True), dict) is None - assert decorate_content("not-a-list", minted, dict) is None - - -async def test_rebuild_failure_falls_back_to_heuristic(caplog): - data = AgentCatData(project_id="p", options=AgentCatOptions()) - async def broken_rebuild(): - raise RuntimeError("list source gone") - out = await get_stripped_arguments(data, data.options, "t", - {"q": 1, "task_id": "s", "context": "c"}, broken_rebuild) - assert out == {"q": 1} - assert data.output_injection_registry is None # mirror gate bypassed -``` -- [ ] **Step 2: Run → FAIL.** -- [ ] **Step 3: Implement** exactly per the Interfaces block. Reuse `identify` logic from `modules/identify.py` but WITHOUT publishing an event (new helper `resolve_identity(data, request, extra) -> UserIdentity | None` added to `identify.py`; old `identify_session` stays until Task 11). -- [ ] **Step 4: Run → PASS; ruff + mypy clean.** -- [ ] **Step 5: Commit** — `git commit -m "feat(callpath): shared per-call orchestration (resolve/strip/decorate/publish)"` - -### Task 8: Lowlevel-v1 adapter + `track()` cutover (official SDK 1.x flavors) - -**Files:** -- Create: `src/agentcat/modules/adapters/__init__.py`, `src/agentcat/modules/adapters/lowlevel_v1.py` -- Modify: `src/agentcat/__init__.py` (full `track()` rewrite), `src/agentcat/modules/request_extra.py` (expose `extra_from_request_context(request_context) -> dict`), `src/agentcat/modules/identify.py` (add `resolve_identity`), `tests/conftest.py` (env gating) -- Delete: `src/agentcat/modules/overrides/official/` (whole dir) -- Test: `tests/test_lowlevel_v1_handles.py` (new); rewrite `tests/test_tool_context.py`, `tests/test_report_missing.py`, `tests/test_event_capture_completeness.py`, `tests/test_mcp_version_compatibility.py`, `tests/test_dynamic_tracking.py`, `tests/test_multiple_servers.py`, `tests/e2e/official/*` - -**Interfaces:** -- Produces: `install_lowlevel_v1(server: Any, data: AgentCatData) -> None` (wraps type-keyed `request_handlers`); `track()` v2: detection-dispatched, never raises; `agentcat` imports cleanly under BOTH mcp majors (all mcp/fastmcp imports lazy). -- Consumes: `detect_server` (Task 6), `resolve_call`/`get_stripped_arguments`/`decorate_content`/`structured_mirror`/`publish_tool_call_event`/`detect_mrtr` (Task 7), `ToolSpec`/`build_injected_schemas` (Task 5). - -- [ ] **Step 1: conftest env gating.** In `tests/conftest.py`: - -```python -from importlib.metadata import version - -MCP_MAJOR = int(version("mcp").split(".")[0]) -_LEGACY_ONLY = [ - "e2e/official", "e2e/community_v2", "e2e/community_v3", "community", - "test_tool_context.py", "test_report_missing.py", "test_dynamic_tracking.py", - "test_multiple_servers.py", "test_event_capture_completeness.py", - "test_mcp_version_compatibility.py", "test_session.py", "test_stateless.py", - "test_request_extra.py", "test_lowlevel_v1_handles.py", -] -_MODERN_ONLY = ["e2e/official_modern", "e2e/community_v4", "test_lowlevel_v2_handles.py"] -collect_ignore_glob = [ - f"{p}*" for p in (_MODERN_ONLY if MCP_MAJOR < 2 else _LEGACY_ONLY) -] -``` - -- [ ] **Step 2: Failing integration test** `tests/test_lowlevel_v1_handles.py` (legacy env), using `tests/test_utils/todo_server.py` + `client.py`: - -```python -import json -import pytest -from agentcat import AgentCatOptions, track -from tests.test_utils.client import create_test_client -from tests.test_utils.todo_server import create_todo_server - - -@pytest.fixture(autouse=True) -def capture(monkeypatch): - events = [] - from agentcat.modules import event_queue - monkeypatch.setattr(event_queue.event_queue, "add_event", events.append) - return events - - -async def test_prompted_mode_end_to_end(capture): - server = create_todo_server() - track(server, "proj_test", AgentCatOptions()) - async with create_test_client(server) as client: - listed = await client.list_tools() - add = next(t for t in listed.tools if t.name == "add_todo") - assert list(add.inputSchema["properties"])[-2:] == ["task_id", "context"] - assert "task_id" not in add.inputSchema.get("required", []) - assert any(t.name == "get_more_tools" for t in listed.tools) - - r1 = await client.call_tool("add_todo", {"text": "hi", "context": "Adding a todo item for the user's task list to track work"}) - text = "".join(c.text for c in r1.content if hasattr(c, "text")) - assert "[MCP INSTRUCTIONS]: task_id issued." in text - minted = text.split("task_id=")[1].split(" ")[0] - assert minted.startswith("ses_") - - r2 = await client.call_tool("add_todo", {"text": "again", "task_id": minted}) - text2 = "".join(c.text for c in r2.content if hasattr(c, "text")) - assert "[MCP INSTRUCTIONS]: task_id issued." not in text2 - - call_events = [e for e in capture if e.event_type == "mcp:tools/call"] - assert {e.event_type for e in capture} <= {"mcp:tools/call"} # no initialize/list/identify - assert call_events[0].session_id == minted == call_events[1].session_id - assert call_events[0].parameters["arguments"]["context"] # raw request keeps injected params - assert "[MCP INSTRUCTIONS]" not in json.dumps(call_events[0].response) # undecorated - - -async def test_handler_sees_stripped_args_and_customer_result_untouched(capture): - server = create_todo_server() - seen = {} - # register a probe tool BEFORE track (todo_server helper or direct decorator) - track(server, "proj_test") - # call with task_id/context; assert the tool body received neither (todo_server - # tools raise on unexpected kwargs, so a successful call is the assertion). -``` - -Also: `test_track_never_raises()` — `track(object(), None)` returns the object, no exception; `test_agent_tracking_injection()` — with `enable_agent_tracking=True`, `agent_id` in required + tags `agentcat_agent_id` on events when supplied; `test_hook_mode()` — `resolve_task_id=lambda q, e: "cust-1"` → no `task_id` param in schemas, event session = `derive_task_id("cust-1", "proj_test")`, no `[MCP INSTRUCTIONS]` text ever. - -- [ ] **Step 3: Run → FAIL.** - -- [ ] **Step 4: Implement `adapters/lowlevel_v1.py`:** - -```python -"""Adapter for official MCP SDK 1.x lowlevel Server (also serves -mcp.server.fastmcp.FastMCP via its _mcp_server). All mcp imports are lazy so -the package imports under either SDK major.""" - - -def install_lowlevel_v1(server, data): - from mcp.types import (CallToolRequest, CallToolResult, ListToolsRequest, - ListToolsResult, ServerResult, TextContent, Tool) - from agentcat.modules.callpath import (decorate_content, detect_mrtr, - get_stripped_arguments, publish_tool_call_event, resolve_call, structured_mirror) - from agentcat.modules.injection import ToolSpec, build_injected_schemas - from agentcat.modules.tools import GET_MORE_TOOLS_SCHEMA, handle_report_missing - - handlers = server.request_handlers - orig_list = handlers.get(ListToolsRequest) - orig_call = handlers.get(CallToolRequest) - - def make_gmt() -> Tool: - # Reuse the existing description string and GET_MORE_TOOLS_SCHEMA from - # modules/tools.py exactly as-is (the bytes already match the TS SDK). - return Tool( - name="get_more_tools", - description=GET_MORE_TOOLS_DESCRIPTION, - inputSchema=copy.deepcopy(GET_MORE_TOOLS_SCHEMA), - annotations={"readOnlyHint": True}, - ) - - async def list_specs() -> tuple[list[Tool], list[ToolSpec]]: - tools: list[Tool] = [] - if orig_list is not None: - result = await orig_list(ListToolsRequest(method="tools/list")) - tools = [t.model_copy(deep=True) for t in result.root.tools] - if data.options.enable_report_missing and all(t.name != "get_more_tools" for t in tools): - tools.append(make_gmt()) - specs = [ToolSpec(t.name, t.inputSchema, getattr(t, "outputSchema", None)) for t in tools] - return tools, specs - - async def rebuild() -> list[ToolSpec]: - _, specs = await list_specs() - return specs - - async def wrapped_list(req): - tools, specs = await list_specs() - result = build_injected_schemas(specs, data.options) - data.injected_params_registry = result.injected_params - data.output_injection_registry = result.output_injected - for tool, s in zip(tools, specs): - tool.inputSchema = s.input_schema - if s.output_schema is not None: - tool.outputSchema = s.output_schema - return ServerResult(ListToolsResult(tools=tools)) - - async def wrapped_call(req): - name = req.params.name - raw_args = dict(req.params.arguments or {}) - ctx = _safe_request_context(server) - rc = await resolve_call( - data, name, raw_args, req, ctx, - meta_sources=[_meta_extras(req)], - legacy_client=lambda: _legacy_client_info(ctx), - ) - stripped = await get_stripped_arguments(data, data.options, name, raw_args, rebuild) - start = _now_ms() - if name == "get_more_tools" and data.options.enable_report_missing: - inner = CallToolResult(content=await handle_report_missing(stripped.get("context", ""))) - else: - new_params = req.params.model_copy(update={"arguments": stripped}) - inner = (await orig_call(req.model_copy(update={"params": new_params}))).root - mrtr = detect_mrtr(getattr(inner, "resultType", None), False) - is_err = bool(getattr(inner, "isError", False)) - await publish_tool_call_event( - server, data, rc, name, raw_args, - response=inner.model_dump(mode="json"), is_error=is_err, - error_msg=_first_text(inner) if is_err else None, - duration_ms=_now_ms() - start, mrtr=mrtr, - extra_params=extra_from_request_context(ctx), - ) - if mrtr == "input_required": - return ServerResult(inner) - update: dict = {} - new_content = decorate_content( - list(inner.content) if isinstance(inner.content, list) else None, - rc.resolution, lambda t: TextContent(type="text", text=t)) - if new_content is not None: - update["content"] = new_content - mirrored = structured_mirror(getattr(inner, "structuredContent", None), - rc.resolution, name, data.output_injection_registry) - if mirrored is not None: - update["structuredContent"] = mirrored - return ServerResult(inner.model_copy(update=update) if update else inner) - - handlers[ListToolsRequest] = wrapped_list - handlers[CallToolRequest] = wrapped_call -``` - -(`_meta_extras(req)` = `req.params.meta.model_extra` when present; `_legacy_client_info(ctx)` = `ctx.session.client_params.clientInfo` guarded; `decorate_content` internally applies only when `build_mint_back_text` is non-None — keep the single source of truth in callpath, drop the local `text` variable if redundant.) - -- [ ] **Step 5: Rewrite `track()` in `__init__.py`:** keep diagnostics/exporters/api-url blocks; replace compatibility checks + `_apply_server_tracking` with: - -```python -detection = detect_server(server) -if detection.flavor in (ServerFlavor.LOWLEVEL_V1, ServerFlavor.OFFICIAL_FASTMCP_V1): - lowlevel = detection.lowlevel - data = AgentCatData( - project_id=project_id, options=options, - server_name=getattr(lowlevel, "name", None), - server_version=getattr(lowlevel, "version", None), - ) - set_server_tracking_data(lowlevel, data) - from agentcat.modules.adapters.lowlevel_v1 import install_lowlevel_v1 - install_lowlevel_v1(lowlevel, data) -elif detection.flavor is ServerFlavor.COMMUNITY_V3: - data = AgentCatData(project_id=project_id, options=options, - server_name=getattr(server, "name", None), server_version=None) - set_server_tracking_data(server, data) - from agentcat.modules.overrides.community_v3.integration import apply_community_v3_integration - apply_community_v3_integration(server, data) # legacy path; replaced by Task 9 -elif detection.flavor is ServerFlavor.COMMUNITY_V2_UNSUPPORTED: - write_to_log("FastMCP 2.x is not supported by agentcat>=2 — pin agentcat<2 or upgrade FastMCP") -elif detection.flavor in (ServerFlavor.LOWLEVEL_V2, ServerFlavor.MCPSERVER_V2, ServerFlavor.COMMUNITY_V4): - write_to_log(f"{detection.flavor} support arrives in Tasks 12/13; server not tracked yet") -else: - # Unrecognized shape: log fingerprint AND emit a diagnostics beacon - # (fleet-level drift detection, changelog §6.7). - write_to_log(f"Unrecognized server shape; not tracked | fingerprint={detection.fingerprint}") -``` - -The whole body sits in one `try/except Exception` that logs and returns `server` — including the former `ValueError`/`TypeError` paths (breaking change: never raises). - -- [ ] **Step 6: Make imports lazy.** `rg -n "^from mcp|^import mcp|^from fastmcp|^import fastmcp" src/agentcat` — move every hit inside functions or `TYPE_CHECKING`. Then verify in the MODERN env: `uv run python -c "import agentcat; print(agentcat.__version__)"` → prints `2.0.0b1`. - -- [ ] **Step 7: Update the legacy-env test files listed above.** Delete assertions about `mcp:initialize` / `mcp:tools/list` / `agentcat:identify` events and session rollover; identify tests now assert actor fields ON the tools/call event; e2e/official `test_session_http.py` → `test_task_http.py` asserting mint-back + echo across HTTP calls. Run: `uv run pytest -q` (legacy env) → PASS. - -- [ ] **Step 8: Commit** — `git commit -m "feat(adapters)!: lowlevel-v1 engine cutover; official FastMCP unified; track() never raises"` - ---- - -### Task 9: Community adapter (FastMCP 3.x era) + retire overrides/ - -**Files:** -- Create: `src/agentcat/modules/adapters/community.py` -- Modify: `src/agentcat/__init__.py` (route COMMUNITY_V3/V4 → new adapter), `src/agentcat/modules/tools.py` (readOnlyHint on the FastMCP registration) -- Delete: `src/agentcat/modules/overrides/` (entire tree: `mcp_server.py`, `community/`, `community_v3/`, `__init__.py`) -- Test: `tests/community/test_community_v3_handles.py` (new); rewrite `tests/community/test_community_v3_inject_context.py`, `test_community_v3_event_serialization.py`, `test_community_v3_openapi.py`, `test_community_v3_runtime_state_tools.py`, `tests/e2e/community_v3/*`; delete `tests/e2e/community_v2/`, `tests/community/test_community_fastmcp.py`, `test_community_event_capture.py`, `test_community_tool_context.py`, `test_community_report_missing.py`, `test_community_dynamic_tracking.py`, `test_community_tracking_timing.py` (fastmcp-2-era suites; port any still-relevant scenario onto the v3 harness first) - -**Interfaces:** -- Produces: `install_community(server: Any, data: AgentCatData, era: int) -> None` — constructs `AgentCatMiddleware(data, server, era)` and `server.middleware.insert(0, mw)`; registers `get_more_tools` via `server.add_tool(Tool.from_function(...))` with `annotations={"readOnlyHint": True}`. -- Consumes: Tasks 4–7 exactly as defined. - -- [ ] **Step 1: Failing tests** (legacy env = fastmcp 3.x). Mirror Task 8's integration shape using the community harness (`tests/test_utils/community_todo_server.py` + `community_client.py`): schema injection order on `tools/list`; mint-back on first call; echo on second; raw-vs-stripped; hook mode; agent tracking; **only tools/call events**; OpenAPI tool coverage (port from the old inject-context test: injected `context` on OpenAPI-generated tools without breaking pickling). - -- [ ] **Step 2: Run → FAIL.** - -- [ ] **Step 3: Implement `AgentCatMiddleware`** (single class, era flag): - -```python -class AgentCatMiddleware(Middleware): # fastmcp import inside install_community - def __init__(self, data, server, era: int): - self._data, self._server, self._era = data, server, era - self._handshake_client: dict | None = None - - async def on_initialize(self, context, call_next): - params = getattr(context.message, "params", None) or context.message - info = getattr(params, "client_info", None) or getattr(params, "clientInfo", None) - if info is not None: - self._handshake_client = {"name": getattr(info, "name", None), - "version": getattr(info, "version", None)} - return await call_next(context) # NO event - - async def on_list_tools(self, context, call_next): - tools = list(await call_next(context)) - copies = [t.model_copy(deep=True) for t in tools] - specs = [ToolSpec(t.name, t.parameters, getattr(t, "output_schema", None)) for t in copies] - result = build_injected_schemas(specs, self._data.options) - self._data.injected_params_registry = result.injected_params - self._data.output_injection_registry = result.output_injected - return [t.model_copy(update={"parameters": s.input_schema, - **({"output_schema": s.output_schema} if s.output_schema is not None else {})}) - for t, s in zip(copies, specs)] - - async def on_call_tool(self, context, call_next): - msg = context.message - name, raw_args = msg.name, dict(msg.arguments or {}) - meta = self._request_meta(context) # fastmcp_context.request_context.meta, guarded - rc = await resolve_call(self._data, name, raw_args, msg, context.fastmcp_context, - meta_sources=[meta], - legacy_client=lambda: self._handshake_client) - async def rebuild(): - listed = await self._server.list_tools(run_middleware=False) - return [ToolSpec(t.name, copy.deepcopy(t.parameters), - copy.deepcopy(getattr(t, "output_schema", None))) for t in listed] - stripped = await get_stripped_arguments(self._data, self._data.options, name, raw_args, rebuild) - new_msg = msg.model_copy(update={"arguments": stripped}) # preserves input_responses/request_state/_meta - start = _now_ms() - result = await call_next(context.copy(message=new_msg)) - continuation = getattr(msg, "input_responses", None) is not None - intermediate = type(result).__name__ == "InputRequiredToolResult" or \ - getattr(result, "result_type", None) == "input_required" - mrtr = "input_required" if intermediate else ("continuation" if continuation else None) - await publish_tool_call_event(self._server, self._data, rc, name, raw_args, - response=_tool_result_payload(result), is_error=bool(getattr(result, "is_error", False)), - error_msg=None, duration_ms=_now_ms() - start, mrtr=mrtr, - extra_params=_extra_from_fastmcp(context.fastmcp_context)) - if intermediate: - return result - update = {} - new_content = decorate_content(list(result.content) if isinstance(getattr(result, "content", None), list) else None, - rc.resolution, _make_text_content) - if new_content is not None: - update["content"] = new_content - mirrored = structured_mirror(getattr(result, "structured_content", None), - rc.resolution, name, self._data.output_injection_registry) - if mirrored is not None: - update["structured_content"] = mirrored - return result.model_copy(update=update) if update else result -``` - -`get_more_tools` keeps flowing through the provider (`server.add_tool`), so its calls traverse this middleware and publish like any tool. - -- [ ] **Step 4: Route in `track()`** (`COMMUNITY_V3` → `install_community(server, data, era=3)`; leave `COMMUNITY_V4` on the placeholder branch until Task 13), delete `modules/overrides/`, fix stragglers (`rg -n "overrides" src tests`). -- [ ] **Step 5: Run legacy env full suite → PASS.** Commit — `git commit -m "feat(adapters)!: community FastMCP middleware on the shared engine; drop FastMCP 2.x"` - ---- - -### Task 10: Session/identify teardown + event pipeline restamp + migration docs - -**Files:** -- Delete: `src/agentcat/modules/session.py`, `src/agentcat/modules/compatibility.py`, `src/agentcat/modules/version_detection.py`, `tests/test_session.py`, `tests/test_stateless.py` -- Modify: `src/agentcat/types.py` (remove `AgentCatOptions.stateless`, `SessionInfo` deletion, `AgentCatData` slim per spec §3.3, `EventType` → `MCP_TOOLS_CALL` + `AGENTCAT_CUSTOM` only), `src/agentcat/__init__.py` (drop `_detect_stateless`, session imports), `src/agentcat/modules/event_queue.py` (`publish_event` stamps `sdk_language="python"`, `agentcat_version=__version__`, `server_name`/`server_version` from `AgentCatData`; no `get_session_info` merge; no `set_last_activity`), `src/agentcat/modules/identify.py` (delete `identify_session`; keep `resolve_identity`), `src/agentcat/modules/tools.py` (drop version_detection gates), `MIGRATION.md`, `README.md` -- Test: `tests/test_event_queue.py` (update stamping assertions), `tests/test_request_extra.py` (transport `mcp-session-id` still lands in `parameters.extra.sessionId`; AgentCat `session_id` unaffected) - -- [ ] **Step 1: Update tests first** (stamping + request-extra semantics), run → FAIL. -- [ ] **Step 2: Implement removals/restamp.** `rg -n "session_info|get_session_info|last_activity|INACTIVITY|is_stateless|identify_session|SessionInfo" src tests` must return zero hits in `src/` afterward. -- [ ] **Step 3: MIGRATION.md — add section "agentcat 1.x → 2.0":** sessions→tasks table (`Event.sessionId` now carries the task handle, same `ses_` prefix); removed events (`mcp:initialize`, `mcp:tools/list`, `agentcat:identify` — actor fields now ride every tools/call event); removed `AgentCatOptions.stateless`; `identify` runs per call (keep hooks cheap); `track()` no longer raises; FastMCP 2.x unsupported (pin `agentcat<2`); new: `task_id`/`agent_id` injection, `enable_agent_tracking`, `resolve_task_id`, `publish_custom_event`; supported matrix (mcp 1.x/2.x, FastMCP 3.x/4.x). -- [ ] **Step 4: Run both envs' importable checks + legacy full suite → PASS.** -- [ ] **Step 5: Commit** — `git commit -m "feat!: remove session machinery and identify/initialize/list events"` - ---- - -### Task 11: `publish_custom_event` - -**Files:** -- Modify: `src/agentcat/__init__.py`, `src/agentcat/types.py` (only if `CustomEventData` needs export wiring) -- Test: `tests/test_publish_custom_event.py` - -**Interfaces:** -- Produces: `publish_custom_event(server_or_task_id: Any, project_id: str, event_data: CustomEventData | None = None) -> None`, exported in `__all__`. - -- [ ] **Step 1: Failing tests:** string form uses the string verbatim as `session_id` (never derived); `event_data["task_id"]` takes precedence over the string; tracked-server form without `task_id` → `session_id` empty/None; event_type == `"agentcat:custom"`; `resource_name`/`tags`/`properties`/`is_error` pass through; bad input never raises. -- [ ] **Step 2: Run → FAIL. Step 3: Implement** (build `UnredactedEvent(event_type=AGENTCAT_CUSTOM_EVENT_TYPE, session_id=..., ...)`; tracked-server form resolves `AgentCatData` via `get_server_tracking_data` for project fallback; wrap in try/except + log). **Step 4: Run → PASS. Step 5: Commit** — `git commit -m "feat(events): publish_custom_event with verbatim task attribution"` - ---- - -### Task 12: Lowlevel-v2 adapter (official SDK 2.x + MCPServer) - -**Files:** -- Create: `src/agentcat/modules/adapters/lowlevel_v2.py` -- Modify: `src/agentcat/__init__.py` (route `LOWLEVEL_V2` / `MCPSERVER_V2`), `src/agentcat/modules/request_extra.py` (add `extra_from_server_context(ctx) -> dict`: headers from `ctx.request` when HTTP; keep `sessionId` only when transport provides one) -- Test: `tests/test_lowlevel_v2_handles.py`, `tests/e2e/official_modern/{conftest.py,test_task_http.py,test_mcpserver_http.py}` (modern env only) - -**Interfaces:** -- Produces: `install_lowlevel_v2(server: Any, data: AgentCatData) -> None` — swaps `_request_handlers["tools/list"|"tools/call"]` entries and re-arms `add_request_handler`. -- Consumes: Tasks 4–7 symbols; era specifics: snake_case fields, `ctx.meta`, `ctx.protocol_version`, MRTR types. - -- [ ] **Step 1: Failing tests (modern env).** Unit: real `mcp.server.lowlevel.Server` with a `tools/call` + `tools/list` handler registered via v2 API; assert injection order, mint-back, echo, strip, raw event, `agentcat_protocol_version` tag, MRTR: a handler returning `InputRequiredResult` → event tagged `input_required`, result NOT decorated; a continuation call (`params.input_responses={...}`) → tagged `continuation`; re-registration after `track()` still wrapped; `MCPServer` end-to-end via `_lowlevel_server`. E2E: streamable HTTP modern path (mirror `tests/e2e/official/conftest.py` boot pattern with the v2 app API). -- [ ] **Step 2: Run (modern env) → FAIL.** -- [ ] **Step 3: Implement:** - -```python -def install_lowlevel_v2(server, data): - # No mcp imports needed: HandlerEntry is cloned via type(entry)(...). - from agentcat.modules.callpath import ... - from agentcat.modules.injection import ToolSpec, build_injected_schemas - - def swap(method: str, wrap): - entry = server.get_request_handler(method) - if entry is None: - return None - original = entry.handler - server._request_handlers[method] = type(entry)(entry.params_type, wrap(original)) - return original - - def wrap_list(original): - async def wrapped(ctx, params): - result = await original(ctx, params) - tools = [t.model_copy(deep=True) for t in result.tools] - if data.options.enable_report_missing and all(t.name != "get_more_tools" for t in tools): - tools.append(_make_gmt_v2()) # mcp.types.Tool imported lazily here - specs = [ToolSpec(t.name, t.input_schema, t.output_schema) for t in tools] - r = build_injected_schemas(specs, data.options) - data.injected_params_registry = r.injected_params - data.output_injection_registry = r.output_injected - for t, s in zip(tools, specs): - t.input_schema = s.input_schema - if s.output_schema is not None: - t.output_schema = s.output_schema - return result.model_copy(update={"tools": tools}) - return wrapped - - def wrap_call(original): - async def wrapped(ctx, params): - name, raw_args = params.name, dict(params.arguments or {}) - rc = await resolve_call( - data, name, raw_args, params, ctx, - meta_sources=[ctx.meta], - legacy_client=lambda: _v2_legacy_client(ctx), # ctx.session.client_params.client_info - protocol_fallback=getattr(ctx, "protocol_version", None), - ) - async def rebuild(): - entry = ... # captured original list handler; call with (ctx, None) - listed = await original_list(ctx, None) - return [ToolSpec(t.name, t.input_schema.copy() if isinstance(t.input_schema, dict) else {}, ...)] - stripped = await get_stripped_arguments(data, data.options, name, raw_args, rebuild) - call_params = params.model_copy(update={"arguments": stripped}) # keeps input_responses/request_state/_meta - start = _now_ms() - if name == "get_more_tools" and data.options.enable_report_missing: - result = _gmt_result_v2(stripped) - else: - result = await original(ctx, call_params) - mrtr = detect_mrtr(getattr(result, "result_type", None), - getattr(params, "input_responses", None) is not None) - is_err = bool(getattr(result, "is_error", False)) - await publish_tool_call_event(server, data, rc, name, raw_args, - response=result.model_dump(mode="json"), is_error=is_err, - error_msg=None, duration_ms=_now_ms() - start, mrtr=mrtr, - extra_params=extra_from_server_context(ctx)) - if mrtr == "input_required": - return result - update = {} - new_content = decorate_content(list(result.content) if isinstance(result.content, list) else None, - rc.resolution, _make_text_content_v2) - if new_content is not None: - update["content"] = new_content - mirrored = structured_mirror(result.structured_content if isinstance(result.structured_content, dict) else None, - rc.resolution, name, data.output_injection_registry) - if mirrored is not None: - update["structured_content"] = mirrored - return result.model_copy(update=update) if update else result - return wrapped - - original_list = swap("tools/list", wrap_list) - swap("tools/call", wrap_call) - - original_add = server.add_request_handler - def rearming_add(method, params_type, handler): - original_add(method, params_type, handler) - if method in ("tools/list", "tools/call"): - swap(method, wrap_list if method == "tools/list" else wrap_call) - server.add_request_handler = rearming_add # instance attribute shadows the method -``` - -- [ ] **Step 4: Route in `track()`** (replace the placeholder branch); run modern-env suite → PASS; run legacy env → still PASS. -- [ ] **Step 5: Commit** — `git commit -m "feat(adapters): official MCP SDK v2 support (lowlevel + MCPServer)"` - ---- - -### Task 13: Community FastMCP 4 era - -**Files:** -- Modify: `src/agentcat/__init__.py` (route `COMMUNITY_V4` → `install_community(server, data, era=4)`), `src/agentcat/modules/adapters/community.py` (only if a v4-specific fix surfaces — the era paths were built in Task 9) -- Test: `tests/e2e/community_v4/{conftest.py,test_task_http.py}`, `tests/test_community_v4_handles.py` (modern env) - -- [ ] **Step 1: Failing tests (modern env, fastmcp 4.0.0b1):** injection/mint-back/echo end-to-end over `http_app`; **strip preserves MRTR fields** (build a `CallToolRequestParams` with `input_responses={"r1": ...}` + `request_state="s"`, assert the params object reaching the tool retains both after stripping); `InputRequiredToolResult` passes undecorated with `agentcat_mrtr=input_required`; ordering vs `ResponseCachingMiddleware` (register caching, call list twice, injected schema present both times); OpenAPI-generated tools still injectable. -- [ ] **Step 2: Run → FAIL** (routing placeholder). **Step 3:** enable routing; fix any v4 snake/camel drift the tests surface. **Step 4: Run modern env → PASS; legacy env → PASS.** -- [ ] **Step 5: Commit** — `git commit -m "feat(adapters): community FastMCP 4 era support"` - ---- - -### Task 14: Cross-flavor regressions (concurrency, removed events, rebuild) - -**Files:** -- Test: `tests/test_concurrency_handles.py`, `tests/test_removed_events.py`, `tests/test_rebuild_on_demand.py` - -- [ ] **Step 1: Concurrency** — per flavor available in the active env: `asyncio.gather` 25 simultaneous calls, each supplying a distinct `task_id`; assert each captured event's `session_id` matches its own call's handle (no cross-attribution) and each response's mint-back/mirror names only its own handle. -- [ ] **Step 2: Removed events** — full lifecycle (initialize where applicable, tools/list, tools/call ×2) per flavor; assert captured event types `== {"mcp:tools/call"}`. -- [ ] **Step 3: Rebuild-on-demand** — fresh tracked server, call `tools/call` FIRST (no prior list): registry gets rebuilt, customer handler receives stripped args, mirror gating uses the rebuilt output registry. Also the failure path: monkeypatch the list source to raise → heuristic strip still protects `get_more_tools.context`, mirror applies anyway. -- [ ] **Step 4: Run in BOTH envs → PASS. Commit** — `git commit -m "test: concurrency, removed-event, and rebuild regressions across flavors"` - ---- - -### Task 15: CI matrices, docs polish, final validation - -**Files:** -- Modify: `.github/workflows/mcp-compatibility.yml`, `.github/workflows/mcp-prerelease-compatibility.yml`, `README.md`, `MIGRATION.md` (final read-through) - -- [ ] **Step 1: `mcp-compatibility.yml`:** mcp discovery filter accepts `>=1.2,<3` (drop the implicit `<2`); fastmcp discovery accepts `>=3.0,<5`, remove the `2.9.*` carve-out; the fastmcp job's `sed` pins now target the community extra + groups from Task 1; add matrix legs that run `uv sync --group mcp-legacy` and default (modern) with the full suite (conftest gating selects the right subsets). -- [ ] **Step 2: `mcp-prerelease-compatibility.yml`:** discovery uses `pip index versions --pre` for `mcp` 2.x and `fastmcp` 4.x prerelease channels. -- [ ] **Step 3: README:** update quickstart for v2 (task handles paragraph, `enable_agent_tracking`, `resolve_task_id`, `publish_custom_event`, supported matrix, `track()`-inside-factory pattern note). -- [ ] **Step 4: Final validation (both envs):** - -```bash -uv run ruff check . && uv run ruff format --check . -uv run mypy src/agentcat --strict -uv run pytest -q # modern env -uv sync --extra community --no-group mcp-modern --group mcp-legacy && uv run pytest -q # legacy env -uv run hatch build && ls dist/ -``` - -Expected: all green; wheel + sdist for `agentcat-2.0.0b1`. - -- [ ] **Step 5: Commit** — `git commit -m "ci: dual-generation compatibility matrices for mcp 2.x and fastmcp 4"` - ---- - -## Execution notes - -- Tasks 1–11 are fully testable in the legacy env (plus import smoke in modern); Tasks 12–14 need the modern env; Task 15 exercises both. -- If any golden vector or byte-parity test fails, the reference implementation wins: diff against the TS SDK before touching the expected values (they are frozen cross-SDK contracts). -- The changelog's §8 rollout order maps to Tasks 4→7 (primitives/resolution), 5 (injection), 8–9 (wiring + removals), 5/7 (structured mint-back), 3/4 (agent_id), 12–14 (2026-era topology). - diff --git a/docs/superpowers/specs/2026-08-01-mcp-2026-07-28-python-v2-audit.md b/docs/superpowers/specs/2026-08-01-mcp-2026-07-28-python-v2-audit.md deleted file mode 100644 index 97f6e17..0000000 --- a/docs/superpowers/specs/2026-08-01-mcp-2026-07-28-python-v2-audit.md +++ /dev/null @@ -1,445 +0,0 @@ -# AgentCat Python SDK v2 Audit — MCP 2026-07-28 Compatibility - -> **Superseded in part (2026-08-03).** Everything below calls the handle -> `task_id`. It is now **`session_id`** throughout — the old name collided with -> the MCP Task extension (`tasks/*`), and AgentCat's handle is not an MCP task. -> The rename is mechanical (`TASK_ID_PARAM` → `SESSION_ID_PARAM`, -> `agentcat_task_id_source` → `agentcat_session_id_source`, `resolve_task_id` → -> `resolve_session_id`, `derive_task_id` → `derive_session_id`, and so on), and -> the four frozen derivation vectors are unchanged. One behavior change came -> with it: AgentCat now honors only handles it issued — see -> `agentcat-typescript-sdk/docs/superpowers/specs/2026-08-02-session-id-validation-design.md` -> and `tests/test_session_id_validation.py`. Read this document for the -> architecture; read the code for the names. - -**Date:** 2026-08-01 -**Inputs:** `2026-07-28-cross-sdk-changelog.md` (behavioral spec, Appendices A/B are -byte-authoritative), AgentCat TypeScript SDK `2.0.0-beta.4` -(`feat/explicit-handles-v2`, north star), local reference checkouts: -`reference-sdks/mcp-python-sdk` @ v2.0.0, `reference-sdks/mcp-python-sdk-v1` @ -v1.29.0, `reference-sdks/fastmcp` @ v4.0.0b1, `reference-sdks/fastmcp-v3` @ v3.4.5. -**Scope:** what must change in `agentcat` (Python, currently 1.0.2) to ship v2.0.0: -explicit `task_id`/`agent_id` handles, stateless per-request resolution, and -dual-generation support for the official MCP SDK (1.x **and** 2.x) plus community -FastMCP 3.x **and** 4.0. - -Line references are to the repos above as of this date. - ---- - -## 1. Landscape summary - -### 1.1 Protocol 2026-07-28 (what we must absorb) - -Per the cross-SDK changelog: no initialize handshake, no `Mcp-Session-Id`, -per-request self-describing metadata under `io.modelcontextprotocol/*` keys, -MRTR (a tool call may return `resultType: "input_required"` and complete on a -continuation round carrying `inputResponses`). AgentCat replaces all session -machinery with explicit stateless handles: `task_id` (echoed tool parameter, -`ses_` KSUID stored in `Event.sessionId` — zero backend changes) and opt-in -self-chosen `agent_id` (event tags). Canonical agent-facing copy and tag names -are fixed in changelog Appendix A/B and TS `src/modules/constants.ts` — reuse -byte-identical. - -### 1.2 Official MCP Python SDK v2.0.0 — server-side changes that hit us - -The low-level server was **rebuilt, not renamed** (`docs/whats-new.md:48`). - -| Seam we use today (v1.29) | v2.0.0 replacement | -| --- | --- | -| `Server.request_handlers: dict[type, handler]` (public, `lowlevel/server.py:156`) | `Server._request_handlers: dict[str, HandlerEntry]` keyed by method string, `HandlerEntry(params_type, handler)` is **frozen** (`lowlevel/server.py:92,427`); public `add_request_handler(method, params_type, handler)` / `get_request_handler(method)` (`:472,514`) | -| Handler signature `async (req: CallToolRequest) -> ServerResult` | `async (ctx: ServerRequestContext, params: CallToolRequestParams) -> CallToolResult \| InputRequiredResult` | -| `server.request_context` contextvar (`lowlevel/server.py:109,239`) | **Removed** — context is the first handler argument (`docs/migration.md:1625`) | -| `mcp.server.fastmcp.FastMCP` with `_mcp_server` + `_tool_manager` | **Module gone.** New `mcp.server.mcpserver.MCPServer` with `_lowlevel_server` + `_tool_manager` (survives) (`mcpserver/server.py:190,199`; `docs/migration.md:873`) | -| Client identity from initialize: `request_context.session.client_params.clientInfo` | Ladder: `ctx.meta["io.modelcontextprotocol/clientInfo"]` (constants `CLIENT_INFO_META_KEY`, `mcp_types/_types.py:53-63`), `ctx.protocol_version`, synthesized `ctx.session.client_params.client_info` (snake_case, may be `None`) | -| camelCase model fields (`inputSchema`, `isError`, `structuredContent`), `extra="allow"` | **snake_case** (`input_schema`, `is_error`, `structured_content: Any`); unknown extras **silently dropped** — custom data must ride `_meta` (`docs/migration.md:328-358`) | -| Tool results: bare content lists wrapped by SDK | Handlers must return full `ListToolsResult`/`CallToolResult`; bare lists are TypeErrors (`docs/whats-new.md:102`) | - -MRTR types: `InputRequiredResult` (`result_type == "input_required"`, -`mcp_types/_types.py:2074`), continuation params -`CallToolRequestParams.input_responses` / `.request_state` (`:871,1449`). - -Other v2 facts that shape the design: - -- `initialize` **cannot** be overridden via `add_request_handler` (raises, - `lowlevel/server.py:490`); it is legacy-path-only anyway. -- Provisional `Server.middleware` list exists (`docs/migration.md:1577`) but is - marked provisional/TODO — not a stable seam. -- No per-request `Server` factory in this SDK: `StreamableHTTPSessionManager` - holds one `Server`; the 2026 path builds a per-request `Connection` - (`streamable_http_manager.py:79`, `runner.py:781`). Rebuild-on-demand still - matters for replicas behind an LB and late `track()`. -- `stateless_http` still exists but only affects 2025-era clients - (`docs/whats-new.md:159`). -- `requires-python >= 3.10` — no floor bump needed. `mcp-types` requires - `pydantic>=2.12.0`. - -### 1.3 Community FastMCP 4.0.0b1 — changes vs 3.4.5 - -v4 = **v3 middleware surface + mcp SDK v2 engine + sessionless protocol** -(changelog `docs/changelog.mdx` v4.0.0b1; `docs/getting-started/whats-new.mdx`). - -Stable across v3→v4 (our integration surface survives): - -- `fastmcp.server.server.FastMCP`, `_local_provider`, `add_middleware`, - `middleware`, `server.add_tool(...)` (v4 `server.py:344,478,591,1800`). -- Middleware hooks and `MiddlewareContext` fields unchanged: `on_call_tool`, - `on_list_tools`, `message`, `fastmcp_context`, `method`, `.copy()` - (v4 `middleware/middleware.py:93-279`). -- Internal `Tool.parameters` (input schema) / `Tool.output_schema`; - `tool.model_copy(update=...)` is the sanctioned rewrite pattern (their own - `DereferenceRefsMiddleware` does it, `dereference.py:44`). -- Wraps official lowlevel Server as `self._mcp_server` in **both** (v4 - `server.py:429`, v3 `:412`). - -Breaking/behavioral for us: - -- **Detection:** our v3 probe set (`_local_provider` + `add_middleware` + - `middleware`, no `_tool_manager`) matches v4 too → v4 misclassified as v3. - v4 discriminators: `add_extension` / `_extensions` (`server.py:484,594`), - `_request_state_security` (`:402`), `fastmcp.__version__` major. -- v4 imports `mcp_types` (snake_case). camelCase reads (`params.clientInfo`, - `structuredContent`) only work through a deprecation bridge scheduled for - removal. -- `Middleware.on_initialize` **never fires** on modern (2026) connections - (`docs/getting-started/upgrading/from-fastmcp-3.mdx:430`) — initialize-based - capture is dead there. -- Arg-strip must preserve MRTR fields: our v3 strip rebuilds - `CallToolRequestParams(name=..., arguments=...)` and would **drop** - `input_responses` / `request_state` / `_meta` on v4 - (ours: `overrides/community_v3/middleware.py:228-232`; theirs: - `server.py:1407-1420`). -- Results may be `InputRequiredToolResult` — don't treat as payload - (`tools/base.py:187-222`). -- `ResponseCachingMiddleware` caches list/call results — AgentCat middleware - must sit **outermost** so injected schemas/mint-backs aren't cached-around. -- `fastmcp.tools.tool` import path removed (our TYPE_CHECKING import breaks). -- Deps: `mcp>=2.0.0,<3`, `mcp-types>=2.0.0,<3`, `pydantic>=2.12.0`, - `requires-python >= 3.10`. -- FastMCP 2.x remains on mcp 1.x with the old `_tool_manager` architecture — - unchanged from what we support today. - -### 1.4 TypeScript SDK v2 (north star) - -Public surface (`src/types.ts:1-44`, `src/index.ts:213-217,363-367`): - -- `track(server, projectId, options)` — never throws; failure logs + returns - untracked server. -- Options added: `enableAgentTracking` (default false), `resolveTaskId` - (hook mode). Removed/changed: identify runs per call (no cache); no session - options. -- `publishCustomEvent(serverOrSessionId, projectId, eventData)` with - `CustomEventData.taskId` (verbatim, never derived; takes precedence). -- `AgentCatIDPrefixes` now includes `Agent = "agt"` (reserved). - -Mechanics (all specified in changelog §3–§6; implemented in TS -`src/modules/handles.ts`, `src/engine/*`): - -- Mint `ses_` KSUID per call when no `task_id` supplied; supplied values - trusted verbatim (trim-only check). `task_source ∈ supplied|minted|hook`. -- Deterministic hook derivation (changelog §3.6): SHA-256 of - `customer_id[:project_id]`, timestamp = 2024-01-01 epoch + `uint32_be(hash[0:4]) % 31536000000` - ms, payload = `hash[4:20]`, standard KSUID base62 → `ses_` + 27 chars. - **Golden vectors** (TS `src/tests/handles.test.ts:53-68`): - - `("customer-abc", "proj_1")` → `ses_2cOHEO0LYGADMzRvWTXXVbbgxgm` - - `("customer-abc", None)` → `ses_2cZY3tvyI25O2AmL2CGVo2B1IIj` - - `(" x ", "p")` → `ses_2c3yR5mYKQdLaXsJNgZH6erbfQK` - - `("x", "p")` → `ses_2bw285VY9apdgUgTPXKFnT6P4G0` -- Injection pipeline (pure): order customer params → `task_id` → `agent_id` → - `context`; deep copy; drop `additionalProperties: false`; skip composed - schemas; collision-skip + warn; registries (injected-params + output-injection) - drive stripping and mirroring; rebuild-on-demand from the original list - handler when a call lands with no registry; heuristic strip fallback - (`task_id`/`agent_id`/`context`, except `get_more_tools` keeps `context`). -- Mint-back: text block only on mint (never hook mode), also on `isError` - results; `_mcp_instructions` mirror on every response into plain-object - `structuredContent` gated by output registry; customer key wins; event - records the **undecorated** result. -- `agent_id`: required-in-schema, soft server-side; tags - `agentcat_agent_id` (CR/LF→space, ≤200 chars) + `agentcat_agent_id_source`. -- Client identity ladder per request: envelope → `_meta` → legacy initialize - capture. Protocol version → `agentcat_protocol_version` tag. -- MRTR tags `agentcat_mrtr = input_required|continuation`; intermediate rounds - are never decorated. -- Copy constants to reuse byte-identical (TS `src/modules/constants.ts:20-62`): - `TASK_ID_PARAM_DESCRIPTION`, `AGENT_ID_PARAM_DESCRIPTION`, - `AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE`, `MINT_BACK_HEADER_TASK`, - `MINT_BACK_CLOSER`, `mintBackTaskLine`, `mintBackConfirmed`, - `MCP_INSTRUCTIONS_FIELD_DESCRIPTION`, `MCP_INSTRUCTIONS_TASK_ID_DESCRIPTION`, - `MCP_INSTRUCTIONS_AGENT_ID_DESCRIPTION`, `MCP_INSTRUCTIONS_KEY`, - `META_CLIENT_INFO_KEY`, `META_PROTOCOL_VERSION_KEY`, and the five - `agentcat_*` tag names. - ---- - -## 2. Current Python SDK — inventory - -### 2.1 Reusable as-is or with small changes - -- Event queue + processing order (redact → sanitize → truncate → send): - `modules/event_queue.py:106-154,289-326`. -- Exporters (`modules/exporters/*`), diagnostics (`modules/diagnostics.py`), - logging, truncation/sanitization/redaction, exceptions capture. -- Per-server storage via `weakref.WeakKeyDictionary` - (`modules/internal.py:14-16`) — already matches changelog §6.3 guidance. -- Vendored KSUID (`thirdparty/ksuid/ksuid.py`) — has `from_bytes` + - base62 `__str__` (zfill 27); deterministic derivation is implementable as - `bytes(uint32_be((ts_ms - 1400000000000)//1000)) + hash[4:20]` → base62. -- `get_more_tools` handler + schema (`modules/tools.py:13-44`) — description - already byte-identical to TS; needs `readOnlyHint` annotation + handle - injection (not exempt) + context preserved on strip. -- Tag/property callback resolution (`modules/internal.py:123-192`) and tag - validation — needs an SDK-owned-tags merge that bypasses customer validation - and the 50-tag cap. -- Event tags/properties, `identify` (already cache-less per call: - `modules/identify.py:9-42`) — but the separate `agentcat:identify` event goes - away; result gets stamped on the tool-call event instead. - -### 2.2 To be removed (changelog §3.1) - -- `modules/session.py` session machinery: `new_session_id` rollover, - `INACTIVITY_TIMEOUT_IN_MINUTES` (30), `get_server_session_id` - (`session.py:183-200`), `last_activity` bookkeeping, stateless client-info - header fallbacks used for session identity. -- `AgentCatOptions.stateless` + `_detect_stateless` (`__init__.py:35-54`) — - meaningless once sessions are gone. -- `AgentCatData.session_id/session_info/last_activity/is_stateless` and the - identity fields on `SessionInfo` (client name/version become per-request). -- Event emissions for `mcp:initialize`, `mcp:tools/list`, and - `agentcat:identify` (interception of initialize/tools-list remains where it - exists, for capture/injection — they just publish nothing). -- Transport-session reads for correlation (`request_extra.py:158-181` reads - `mcp-session-id` into `parameters.extra.sessionId` — see Open decision 5). - -### 2.3 Not present today (net-new) - -- Handle primitives module: mint, extract, deterministic derive (+ golden - vectors), mint-back text builder, `_mcp_instructions` mirror builder, agent - tag clamp. -- Injected-params + output-injection registries; pure injection pipeline - (today's context injection is inline per flavor and never touches - `additionalProperties` or composed schemas: `context_parameters.py:26-56`). -- Output-schema extension (`_mcp_instructions` optional property) — nothing - touches `outputSchema` today. -- Per-request client identity ladder + protocol version tag; envelope/`_meta` - reads (`rg io.modelcontextprotocol src/` → zero hits today). -- MRTR detection/tagging. -- `agent_id` support end-to-end. -- Official SDK v2 adapter (method-string handlers, ctx-as-argument) and - `MCPServer` support; FastMCP v4 discriminator + snake_case/MRTR-safe - middleware. -- `publish_custom_event` (Python has no custom-event API at all today; TS does - — see Open decision 2). - ---- - -## 3. Gap analysis — required changes by area - -### 3.1 Handle primitives (new `modules/handles.py`) - -- `new_task_id()` → `ses_` KSUID (reuse `generate_prefixed_ksuid`). -- `derive_task_id(id, project_id)` — changelog §3.6 algorithm; pin the four TS - golden vectors in tests (cross-language contract). Caller trims; derive does - not. -- `extract_handle(args, name)` — trimmed non-empty `str` else absent; verbatim - trust. -- `resolve_handles(...)` — prompted vs hook mode; `task_source` - supplied/minted/hook; hook errors/None → silent random mint (log, never - agent-facing); agent extraction only when `enable_agent_tracking`. -- Mint-back builders: text block (exact 3-line format), confirmed copy - (`task_id and agent_id` + pluralization), `_mcp_instructions` object - (omission rules: no `task_id` key in hook mode; no `agent_id` key unless - supplied; nothing if neither). -- Tag builder: `agentcat_task_id_source` always; `agentcat_agent_id` - (CR/LF→space, ≤200), `agentcat_agent_id_source`, `agentcat_protocol_version`, - `agentcat_mrtr` conditionally. SDK tags merge **after** customer tags, - exempt from the 50-tag cap and customer validation. - -### 3.2 Options & public API (`types.py`, `__init__.py`) - -- Add `enable_agent_tracking: bool = False` and - `resolve_task_id: Callable[[Any, Any], str | None | Awaitable[str | None]] | None = None` - (docstrings adapted from TS JSDoc; prefer the types.ts wording — the - index.ts `@param` line for agent tracking is stale on "minted by server"). -- Remove `stateless`. Keep everything else (`identify`, redaction, exporters, - tags/properties, `custom_context_description`, ...). -- `AgentCatData` slims to `project_id`, `options`, plus per-server engine - state: injected-params registry (`dict[str, set[str]]`), output-injection - registry (`set[str]`), original-list-handler ref for rebuild. -- `track()` **never throws** (changelog §6.3): today `ValueError`/`TypeError` - propagate (`__init__.py:198-202`) — v2 logs + returns the server untracked. - Module-level state stays first-wins. -- Version bump to `2.0.0` (see Open decision 6 re: beta), `EventType` prunes to - tool-call (+ custom); constants file gains the Appendix A/B strings. - -### 3.3 Shared injection pipeline (new `modules/injection.py`) - -Pure function: `(options, listed_tools) -> (advertised_tools, injected_params_registry, output_registry)`. - -- Param order customer → `task_id` → `agent_id` → `context`; deep-copy schemas - (per-SDK-flavor copy strategy: `model_copy(deep=True)` for pydantic tools, - `copy.deepcopy` for dict schemas); remove `additionalProperties: false`; - skip composed schemas with warning; collision-skip per param with warning - (customer's own `task_id` must reach their handler — never stripped). -- `task_id` optional; `agent_id` **added to `required`**; hook mode injects no - `task_id` and uses `AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE`. -- `get_more_tools` included (handles injected; its `context` is bespoke). -- Output side: for every tool with plain-object `output_schema`, add optional - `_mcp_instructions` property (sub-descriptions from Appendix A); record in - output registry; composed → warn, content-only mint-back. -- Determinism is a hard requirement (rebuild-on-demand equality). - -### 3.4 Call path (per flavor, shared helpers) - -resolve handles → identify → client-info ladder → strip (cloned) → dispatch → -MRTR probe → mint-back/mirror (wire only) → publish event (raw request, -undecorated response, `Event.sessionId = task_id`, actor + client fields, SDK -tags). Error results also get mint-back. Fallback heuristic strip when no -registry and rebuild failed. - -### 3.5 Per-flavor adapters - -| Flavor | Detection (per-object) | Seam | Notes | -| --- | --- | --- | --- | -| lowlevel v1 | has `request_handlers` (type-keyed dict) + `request_context` in `dir()` | wrap `request_handlers[CallToolRequest/ListToolsRequest]` (as today, `overrides/mcp_server.py:34-241`) | camelCase models; strip via copied `params.arguments` (stop in-place `pop`, `mcp_server.py:207-209`) | -| lowlevel v2 | has `_request_handlers` (str-keyed) + `add_request_handler`; no `request_context` | replace `_request_handlers["tools/call"|"tools/list"]` with new frozen `HandlerEntry(params_type, wrapped)` | ctx arg carries `meta`/`protocol_version`/`session`; snake_case; must return full result models; MRTR union | -| official FastMCP v1 (`mcp.server.fastmcp`) | module `mcp.server.fastmcp` + `_mcp_server` + `_tool_manager` | keep ToolManager patching or re-route through the lowlevel adapter on `_mcp_server` | initialize/tools-list events no longer published — the "minimal override" shrinks | -| MCPServer v2 (`mcp.server.mcpserver`) | `_lowlevel_server` + `_tool_manager`, class `MCPServer` | wrap `_lowlevel_server._request_handlers` (same engine as lowlevel v2) | MCPServer converts tool exceptions to `is_error=True` (`mcpserver/server.py:421`) | -| community FastMCP v3 | current probe set AND NOT v4 discriminators | middleware (as today) with fixes | keep `context.copy(message=...)` strip | -| community FastMCP v4 | v3 probes AND (`add_extension`/`_extensions` or `_request_state_security`) | same middleware, era-aware: snake_case, preserve `input_responses`/`request_state`/`_meta` on strip, handle `InputRequiredToolResult`, register outermost | `on_initialize` dead on modern era — client info via ladder only | -| community FastMCP v2 | `_mcp_server` + `_tool_manager`, module `fastmcp` | **proposed drop** (Open decision 1) | if kept: monkey-patch path needs the full v2 handle treatment | - -Version-specific knowledge stays in thin adapters; probe results logged as a -shape fingerprint with a diagnostics beacon on unrecognized shapes (changelog -§6.7). - -### 3.6 Per-request client identity / actor identity - -- Ladder (changelog §5.1): envelope → `_meta` → legacy initialize capture. - Python mapping: lowlevel v2 `ctx.meta[CLIENT_INFO_META_KEY]` (TypedDict); - lowlevel v1 `request.params.meta` extras (`RequestParams.Meta` is - `extra="allow"`); legacy = v1 `request_context.session.client_params.clientInfo` - / v2 `ctx.session.client_params.client_info`; FastMCP v3/v4 - `fastmcp_context.request_context.meta` + initialize capture only on - handshake era. Narrow: accept `name`/`version` only if individually `str`. -- Protocol version: same ladder; v2 also `ctx.protocol_version`. Tag - `agentcat_protocol_version`. -- Identify: stamp result onto the tool-call event - (`identify_actor_given_id/name`, `identify_data`); delete the - `agentcat:identify` event type; SessionInfo-as-cache disappears — - server name/version + SDK metadata stamped at publish from server object + - package metadata. - -### 3.7 Event pipeline changes - -- `Event.session_id` carries the task ID (`ses_` prefix preserved; wire field - unchanged — zero backend migration). -- Publish only `mcp:tools/call` (+ `agentcat:custom` if custom events land). -- Raw request recorded unstripped; response recorded undecorated. -- SDK tags merged post-customer-tags, exempt from cap/validation. -- `duration`/timestamps, redaction/sanitization/truncation unchanged. - -### 3.8 Packaging, CI, docs - -- `pyproject.toml`: version `2.0.0`; `mcp>=1.2.0,<3`; **relax - `pydantic<2.12`** (pin origin: commit `e594b24`, pre-dates mcp 2/fastmcp 4 - which both require `>=2.12`) → propose `pydantic>=2.0.0,<3`; community extra - → `fastmcp>=3.0.0,<5` (pending Open decision 1); mypy/ruff unchanged; - Python floor stays 3.10 (matches mcp v2 and fastmcp v4). -- Dev/test env: uv **conflict groups** `mcp-legacy` (mcp 1.x) / `mcp-modern` - (mcp 2.x) so the suite can sync either major — the gitignored local - `uv.lock` already models exactly this (`agentcat 2.0.0b1`, conflicting - extras, mcp 1.29.0/2.0.0). -- CI: `mcp-compatibility.yml` discovery keeps testing every mcp minor ≥1.2 - and now <3 with per-major test selection; fastmcp discovery range updates - (drop `!=2.9.*` if 2.x support is dropped); `mcp-prerelease-compatibility.yml` - gains the 4.0.0bX / 2.x prerelease channels. The e2e suites split - official/legacy vs official/modern, community_v3, community_v4. -- Docs: MIGRATION.md gains a "1.x → 2.0" section mirroring TS MIGRATION.md; - README examples; module docstrings for new options (AGENTS.md requirement). - ---- - -## 4. Test plan requirements (mirroring TS suites) - -- **Golden vectors:** the four derivation vectors above, byte-equal. -- **Handles unit:** mint prefix/uniqueness, extraction trust model, tag clamp - (CR/LF, 200), mint-back text exact bytes, confirmed-copy pluralization, - `_mcp_instructions` omission rules (hook mode / no agent). -- **Injection:** param order, additionalProperties removal, composed skip, - collision skip + passthrough of customer's own `task_id`, output-schema - extension, registry contents, determinism (pipeline twice ≡). -- **Call path:** supplied/minted/hook sources; strip-clone (customer handler - sees clean args; raw event keeps handles); error-result mint-back; mirror - gating incl. no-registry-mirror-anyway rule; customer `_mcp_instructions` - wins; MRTR intermediate undecorated + tags; continuation tag. -- **Per-flavor e2e (HTTP):** official v1 (existing harness), official v2 - (new harness on mcp 2 lock), MCPServer v2, community v3 (existing), - community v4 (new; must run against 4.0.0b1). Concurrency regression: - parallel calls with distinct handles never cross-attribute (no shared - mutable per-request state). -- **Removed-events regression:** no initialize/tools-list/identify events - published on any flavor. -- **Dual-generation detection:** shape fingerprints for all seven object - shapes; unrecognized-shape beacon. - ---- - -## 5. Risks & gotchas - -1. **pydantic resolver wall:** `agentcat[community]` with fastmcp 4 forces - pydantic ≥2.12 at install time; our `<2.12` pin makes v2 uninstallable - alongside it. Relaxing risks customers on old pydantic — the original pin - (#16) reason should be re-verified against `agentcat-api==1.0.0` models. -2. **Frozen `HandlerEntry`:** wrapping must replace the entry, not mutate it; - re-registration after `track()` (customer calls `add_request_handler` - later) needs a re-arm story (TS solves via `registrationPatch`). -3. **v2 outbound validation:** `_serialize` validates results per protocol - version — malformed injected schemas / mirrors raise server-side. Injection - must produce schema-valid output on both eras (snake_case vs camelCase - serialization). -4. **Extras dropped in v2 models:** never attach unknown attributes to v2 - pydantic objects; `structured_content` is `Any` (safe), `Tool` extras are - not (use real fields only). -5. **FastMCP 4 strip bug class:** rebuilding params without MRTR fields - severs continuations — must `model_copy(update={"arguments": ...})`. -6. **Middleware ordering (v4):** response caching / dereference middlewares - can cache or rewrite around us; AgentCat must be outermost and re-inject on - whatever list result it sees. -7. **In-place mutation on the v1 path today** (`arguments.pop("context")`, - shared dict) violates the copy rule and can corrupt concurrent retries — - v2 rewrite fixes it, but the v1 adapter must be audited for every mutation. -8. **`get_more_tools` context:** heuristic fallback strip must except it, or - its real parameter is destroyed (changelog §6.2). -9. **Float precision in derivation:** compute the KSUID timestamp in integer - milliseconds (`(ts_ms - 1400000000000) // 1000`), never through - `datetime.timestamp()` floats, or golden vectors will drift on boundaries. -10. **camelCase bridge removal (fastmcp 4.x):** code must be snake_case-first - with camelCase fallback for v3, not the reverse. -11. **Diagnostics/event-queue globals:** first-wins init already holds, but - `track()`-in-factory patterns mean repeated `track()` calls must stay - idempotent per server object (weak-keyed state covers this). - ---- - -## 6. Open decisions (need user input) - -1. **Community FastMCP 2.x support:** drop in agentcat v2 (recommended — the - local uv.lock experiment already excludes it; fastmcp 2.x predates the - provider architecture and carries the heaviest monkey-patch surface) or - keep 7-flavor support. -2. **`publish_custom_event`:** add to Python v2 for TS parity (changelog §3.7 - semantics: verbatim task ID, `CustomEventData.task_id` precedence, - `agentcat:custom` type) or defer to 2.1. -3. **Official-SDK v2 seam:** wrap `_request_handlers` entries directly - (recommended: deterministic, mirrors TS engine, private-API-friendly per - our CI change detection) vs build on the provisional `Server.middleware`. -4. **Official FastMCP v1 path consolidation:** keep today's ToolManager - monkey-patching, or re-route official-FastMCP-v1 through the lowlevel-v1 - engine on `_mcp_server` (one engine, fewer patch surfaces — recommended). -5. **`parameters.extra.sessionId` telemetry:** changelog says transport - session IDs are ignored for correlation; keep capturing `mcp-session-id` - into the raw-request `extra` (telemetry-only, recommended) or remove - entirely. -6. **Release train:** ship `2.0.0b1` prerelease first (matches TS - `2.0.0-beta.4` posture + fastmcp 4.0.0b1 timing) or straight to `2.0.0`. diff --git a/docs/superpowers/specs/2026-08-01-python-sdk-v2-explicit-handles-design.md b/docs/superpowers/specs/2026-08-01-python-sdk-v2-explicit-handles-design.md deleted file mode 100644 index 41a2d54..0000000 --- a/docs/superpowers/specs/2026-08-01-python-sdk-v2-explicit-handles-design.md +++ /dev/null @@ -1,466 +0,0 @@ -# AgentCat Python SDK v2 — Explicit Handles Design - -**Date:** 2026-08-01 -**Status:** Approved (design review 2026-08-01) -**Inputs:** `2026-07-28-cross-sdk-changelog.md` (behavioral spec; Appendices A/B -byte-authoritative), audit -`docs/superpowers/specs/2026-08-01-mcp-2026-07-28-python-v2-audit.md`, -AgentCat TypeScript SDK `2.0.0-beta.4` (`feat/explicit-handles-v2`, north star). - -> **Superseded in part (2026-08-03).** Everything below calls the handle -> `task_id`. It is now **`session_id`** throughout — the old name collided with -> the MCP Task extension (`tasks/*`), and AgentCat's handle is not an MCP task. -> The rename is mechanical (`TASK_ID_PARAM` → `SESSION_ID_PARAM`, -> `agentcat_task_id_source` → `agentcat_session_id_source`, `resolve_task_id` → -> `resolve_session_id`, `derive_task_id` → `derive_session_id`, and so on), and -> the four frozen derivation vectors are unchanged. One behavior change came -> with it: AgentCat now honors only handles it issued — see -> `agentcat-typescript-sdk/docs/superpowers/specs/2026-08-02-session-id-validation-design.md` -> and `tests/test_session_id_validation.py`. Read this document for the -> architecture; read the code for the names. -**Target:** `agentcat` `2.0.0b1` (prerelease train; stable `2.0.0` follows). - -## 0. Locked decisions - -1. Community FastMCP **2.x support dropped**; community support is FastMCP 3.x - and 4.x. FastMCP-2-shaped servers get a clear log ("not supported by - agentcat>=2; pin agentcat<2") and are returned untracked. -2. **`publish_custom_event` ships in v2** with TS-parity semantics. -3. Official MCP SDK v2 integration replaces entries in the private - `Server._request_handlers` dict (frozen `HandlerEntry` swap). -4. Official FastMCP v1 (`mcp.server.fastmcp`) is **unified** through the - lowlevel-v1 adapter via `server._mcp_server`; the ToolManager monkey-patch - layer is deleted. -5. Transport `mcp-session-id` is still captured into the raw request's - `parameters.extra.sessionId` (telemetry only; never correlation). -6. Architecture: **shared engine + thin adapters** (Approach A). - -## 1. Goal - -Replace session machinery with the 2026-07-28 explicit-handles model: a -stateless per-call `task_id` handle (echoed as an injected tool parameter, -stored in `Event.sessionId` with the `ses_` prefix — zero backend changes) and -an opt-in agent-chosen `agent_id` (event tags). Support servers built on the -official MCP Python SDK **1.x and 2.x** and community FastMCP **3.x and 4.x** -through one `track()` call, with per-object feature detection. Agent-facing -copy is byte-identical to the TS SDK (§9). - -## 2. Module layout - -``` -src/agentcat/ - __init__.py track(), publish_custom_event(), exports - types.py AgentCatOptions, AgentCatData, CustomEventData, EventType (pruned) - modules/ - constants.py + Appendix A/B strings, tag names, meta keys, "agt" prefix - handles.py NEW mint / derive / extract / resolve / mint-back / tags - injection.py NEW pure schema-injection pipeline + registries - callpath.py NEW shared tools/call orchestration - client_identity.py NEW per-request client info + protocol version ladder - detection.py NEW six-shape classifier + fingerprint + beacon - (replaces compatibility.py + version_detection.py) - adapters/ NEW (replaces overrides/) - lowlevel_v1.py official SDK 1.x Server; also official FastMCP v1 via _mcp_server - lowlevel_v2.py official SDK 2.x Server; also MCPServer via _lowlevel_server - community.py FastMCP 3.x/4.x middleware (era flag) - identify.py per-call resolver; stamps event fields; no identify event - tools.py get_more_tools (+ readOnlyHint annotation) - request_extra.py kept; per-flavor context accessors injected - session.py DELETED - event_queue.py, exporters/, diagnostics.py, redaction.py, truncation.py, - sanitization.py, validation.py, logging.py, internal.py (kept; targeted edits) -``` - -Per-server state stays in `internal.py`'s `WeakKeyDictionary`, keyed on the -lowlevel server object for official flavors (v1 `_mcp_server` / -v2 `_lowlevel_server` / the `Server` itself) and on the FastMCP instance for -community flavors. Module-level state (event queue, telemetry manager, -diagnostics) initializes once, first-wins; repeated `track()` on the same -server is idempotent. - -## 3. Public API - -### 3.1 `track(server, project_id=None, options=None) -> server` - -Same signature. **Never raises** (changelog §6.3): all failures — including -missing `project_id`+exporters and incompatible servers — log a warning, emit -a diagnostics beacon, and return the server untracked. (v1 raised -`ValueError`/`TypeError`; breaking change documented in MIGRATION.md.) - -### 3.2 `AgentCatOptions` changes - -Added: - -- `enable_agent_tracking: bool = False` — injects a required `agent_id` - parameter into every tool. Agents self-generate `model|harness|nonce`; - echoed in `_mcp_instructions`, stamped as event tags. Omission never rejects - a call server-side; enforcement is client-side schema validation. -- `resolve_task_id: Callable[[Any, Any], str | None | Awaitable[str | None]] | None = None` - — hook mode. When set: no `task_id` parameter injected, no task instructions - prompted; the returned string is trimmed and deterministically derived with - the project ID into a `ses_` KSUID (`task_source="hook"`). `None` return or - a raised exception mints silently (`task_source="minted"`, hook error - logged). Same `(request, extra)` call shape as `identify`; sync or async. - -Removed: `stateless` (and `_detect_stateless`). Unchanged: everything else. -`identify` docs updated: runs on **every** tool call, result stamped on that -event; hooks must be cheap. - -### 3.3 `AgentCatData` (internal) slims to - -`project_id: str | None`, `options: AgentCatOptions`, plus engine state: -`injected_params_registry: dict[str, set[str]] | None`, -`output_injection_registry: set[str] | None`, -`original_list_source: Callable | None` (rebuild seam), -`server_info: (name, version)` captured at track time. -Deleted fields: `session_id`, `session_info`, `last_activity`, `is_stateless`, -`tool_registry`, `wrapped_tools`, `monkey_patched`. - -### 3.4 `publish_custom_event(server_or_task_id, project_id, event_data=None) -> None` - -TS parity (`publishCustomEvent`, TS `src/index.ts:363`): - -- `CustomEventData` (TypedDict, `total=False`): `task_id`, `resource_name`, - `parameters`, `response`, `message`, `duration`, `is_error`, `error`, - `tags`, `properties`. -- Tracked-server form: `event_data["task_id"]` used **verbatim** as - `Event.sessionId`; absent → event publishes **without** a task (empty - session). -- String form: first argument is a task-id string used **verbatim** (never - derived); `event_data["task_id"]` takes precedence. -- Event type `agentcat:custom`. Fire-and-forget; never raises. - -### 3.5 Exports - -Add `publish_custom_event`, `CustomEventData` to `__all__`. Constants gain -`AGENT_ID_PREFIX = "agt"` (reserved — server-side agent minting was removed -from the design; never mint with it). - -## 4. Handle primitives (`modules/handles.py`) - -- `new_task_id() -> str` — `ses_` + random KSUID (existing - `generate_prefixed_ksuid`). -- `derive_task_id(id: str, project_id: str | None) -> str` — changelog §3.6, - integer-only arithmetic: - - ```python - input = f"{id}:{project_id}" if project_id else id - h = sha256(input.encode()).digest() - ts_ms = 1704067200000 + (int.from_bytes(h[0:4], "big") % 31536000000) - ts_field = (ts_ms - 1400000000000) // 1000 # uint32 - raw = ts_field.to_bytes(4, "big") + h[4:20] # 20-byte KSUID - return "ses_" + str(Ksuid.from_bytes(raw)) # base62, zfill 27 - ``` - - Does **not** trim (callers trim). Pinned to the four TS golden vectors - (§10 tests). -- `extract_handle(arguments, name) -> str | None` — `str` whose `.strip()` is - non-empty → trimmed value; anything else → `None`. Supplied values trusted - verbatim (no shape validation). -- `resolve_handles(arguments, options, project_id, request, extra) -> HandleResolution` - — dataclass: `task_id: str`, `task_source: Literal["supplied","minted","hook"]`, - `agent_id: str | None`, `hook_mode: bool`. Prompted mode per changelog §3.3; - hook mode per §3.5. `agent_id` extracted only when - `enable_agent_tracking` (source always `"supplied"`). -- Mint-back builders (§9 copy): - - `build_mint_back_text(task_id)` — exactly - `MINT_BACK_HEADER_TASK + "\n" + mint_back_task_line(task_id) + "\n" + MINT_BACK_CLOSER`. - - `build_confirmed_text(names)` — `mint_back_confirmed` template with - `" and "` join and singular/plural tail. - - `build_mcp_instructions(resolution, minted_this_call) -> dict | None` — - keys: `task_id` (omit in hook mode), `agent_id` (omit unless supplied), - `instructions` (mint-back text if minted this call, else confirmed copy). - Returns `None` when neither handle key would be present. -- `build_sdk_tags(resolution, protocol_version, mrtr) -> dict[str, str]` — - `agentcat_task_id_source` always; `agentcat_agent_id` (CR/LF→`" "`, then - `[:200]`) + `agentcat_agent_id_source="supplied"` when supplied; - `agentcat_protocol_version` when present; `agentcat_mrtr` when applicable. - -## 5. Injection pipeline (`modules/injection.py`) - -Pure, deterministic function used by both list-time injection and -rebuild-on-demand: - -``` -build_injected_list(tools, options) -> (advertised_tools, - injected_params: dict[str, set[str]], - output_injected: set[str]) -``` - -Rules (changelog §6.1): - -1. `get_more_tools` is appended by the adapter **before** the pipeline runs - (when `enable_report_missing`), so it flows through injection like any - tool. -2. Injection order per tool: customer params → `task_id` → `agent_id` → - `context`. Handle injection runs before the context injector. -3. `task_id`: optional string param, description §9.1. Never added to - `required` (omission is the minting signal). Skipped entirely in hook mode - and when `enable_tracing=False`. -4. `agent_id` (only when `enable_agent_tracking`): string param, **appended to - `required`**; description §9.2 (default) or §9.3 (hook mode). -5. `context` (when `enable_tool_call_context`): existing behavior, description - `custom_context_description`; skipped for `get_more_tools` (bespoke param). -6. Deep-copy before modifying — dict schemas via `copy.deepcopy`, pydantic - tool objects via `model_copy(deep=True)`/rebuilt dicts. Never mutate the - customer's registered tool. -7. If the input schema has `additionalProperties: false`, delete it. -8. Composed input schemas (`oneOf`/`allOf`/`anyOf` at top level): skip all - injection for that tool, log warning, record empty registry entry. -9. Name collision (tool already defines `task_id`/`agent_id`/`context`): skip - that parameter only, log warning; the customer's own parameter must reach - their handler (the registry simply omits it, so stripping spares it). -10. Every advertised tool gets a registry entry (possibly empty set). -11. Output side: tools whose `output_schema` is a plain object with a - `properties` bag get an optional `_mcp_instructions` object property - (field + sub-property descriptions §9.5); recorded in `output_injected`. - Composed/missing output schemas: skipped (content-only mint-back), warn - on composed. - -The pipeline operates on a normalized internal representation -(`name`, `description`, `input_schema: dict`, `output_schema: dict | None`, -`annotations`) produced/consumed by per-adapter codecs, so era differences -(camelCase `inputSchema` v1 / snake_case `input_schema` v2 / FastMCP -`parameters`) live in the adapters, not the pipeline. - -## 6. Call path (`modules/callpath.py`) - -Shared orchestration invoked by every adapter for `tools/call`: - -1. **Resolve** handles (§4) from raw arguments. -2. **Identify**: run `options.identify(request, extra)`; never throws; result - stamps `identify_actor_given_id` / `identify_actor_name` / `identify_data` - on this event only. No cache, no identify event. -3. **Client identity + protocol version** via `client_identity.py` ladder - (§7); stamped on the event; protocol version → tag. -4. **Strip** on a cloned request: remove exactly the registry's params for - this tool. Registry missing → **rebuild-on-demand**: invoke the adapter's - `original_list_source`, run the pipeline, store registries; if that fails, - heuristic strip (`task_id`, `agent_id`, `context` — but `get_more_tools` - keeps `context`) and skip the structured mirror gate (mirror anyway, per - changelog §3.4b exception). -5. **Dispatch** the customer handler with stripped arguments. - `get_more_tools` short-circuits to its internal handler (still injected, - still publishes). -6. **MRTR probe**: intermediate = result `result_type`/`resultType` == - `"input_required"` (or `isinstance` of the era's type); continuation = - request params carry `input_responses`/`inputResponses`. Tag accordingly. -7. **Decorate the wire result only** (never the event copy), skipping - intermediate rounds entirely: - - Text block appended to a **copied** `content` array only when - `task_source == "minted"` and not hook mode — including `is_error` - results. Only requirement: result has a list `content`. - - `_mcp_instructions` mirrored into `structured_content` / - `structuredContent` on **every** completing response — but only when the - result already carries a **plain-dict** structured content (absent or - non-dict → no mirror; TS `mirrorStructuredMintBack`, `handles.ts:152-163`), - gated by the output registry (see rebuild exception above); mirror onto a - shallow copy; a customer-supplied `_mcp_instructions` key wins. -8. **Publish** one `mcp:tools/call` event: raw unstripped arguments, - undecorated response, `session_id = task_id`, `user_intent` = captured - `context`, actor + client fields, duration, error capture, customer - tags/properties resolved first, then SDK tags merged (SDK wins on - collision, exempt from the 50-tag customer cap and customer validation). - -`tools/list` path: adapter intercepts, appends `get_more_tools`, runs the -pipeline, caches registries + advertised list, returns it. **No event.** -Initialize interception (where the era has one) captures legacy client info -only; **no event**. - -## 7. Per-request client identity (`modules/client_identity.py`) - -Resolution ladder (first hit wins; changelog §5.1), each rung narrowed to -per-field `isinstance(x, str)`: - -1. **Envelope / lifted meta**: lowlevel v2 `ctx.meta[META_CLIENT_INFO_KEY]`; - FastMCP `fastmcp_context.request_context.meta[...]`. -2. **`_meta` passthrough** (pre-2026 servers): v1 - `request.params.meta` extras (`model_extra`) under the fully-qualified key. -3. **Legacy initialize capture**: v1 - `request_context.session.client_params.clientInfo`; v2 - `ctx.session.client_params.client_info` (may be `None`); community - handshake-era initialize capture (weak-keyed, per server — a convenience - cache of static handshake data, not per-request state). - -Protocol version: same ladder for `META_PROTOCOL_VERSION_KEY`; lowlevel v2 -also has `ctx.protocol_version`. Stamped as `agentcat_protocol_version` tag -when present. - -Server name/version + SDK language + agentcat version are stamped at publish -time from track-time capture and package metadata (no SessionInfo cache -object). - -## 8. Detection & adapters - -### 8.1 Classifier (`modules/detection.py`) - -Probe the object in hand; never import version-specific symbols for the -decision. Returns `(flavor, fingerprint)`: - -| Flavor | Probes | -| --- | --- | -| `community-v4` | class contains `FastMCP`, module starts `fastmcp`, has `_local_provider` + `add_middleware` + `middleware`, AND (`add_extension` or `_extensions` or `_request_state_security`) | -| `community-v3` | same minus the v4 discriminators, and no `_tool_manager` | -| `community-v2` (**unsupported**) | module starts `fastmcp`, has `_mcp_server` + `_tool_manager` → log + return untracked | -| `official-fastmcp-v1` | module starts `mcp.server.fastmcp`, has `_mcp_server` + `_tool_manager` → adapt lowlevel-v1 on `_mcp_server` | -| `mcpserver-v2` | has `_lowlevel_server` + `_tool_manager` (class `MCPServer`) → adapt lowlevel-v2 on `_lowlevel_server` | -| `lowlevel-v1` | has `request_handlers` dict (type-keyed) + `request_context` in `dir()` | -| `lowlevel-v2` | has `_request_handlers` + `add_request_handler`, no `request_context` | - -Unrecognized shape: log the full probe fingerprint, emit a diagnostics beacon -(fleet drift detection), return untracked. - -### 8.2 `adapters/lowlevel_v1.py` - -Wraps `request_handlers[ListToolsRequest]` and `[CallToolRequest]` (and -`[InitializeRequest]` for legacy client-info capture only). Argument stripping -clones `request.params.arguments` — the in-place `pop` from v1 is gone. -Decoration builds a new `CallToolResult` (camelCase era). Serves both the bare -`Server` and official FastMCP v1 (tracked via `_mcp_server`; `get_more_tools` -appended list-side, call short-circuited — no ToolManager registration, -no `_get_cached_tool_definition` patch; the injected params never reach -FastMCP's validation layer because stripping happens above it). - -### 8.3 `adapters/lowlevel_v2.py` - -For `"tools/list"` / `"tools/call"`: read `entry = server.get_request_handler(m)`, -store `entry.handler` as the original, write back -`HandlerEntry(entry.params_type, wrapped)` into `_request_handlers[m]` -(frozen dataclass — replace, never mutate). Wrapped handlers receive -`(ctx, params)`; must return complete result models (era codec produces -`ListToolsResult`/`CallToolResult`; `structured_content` is `Any`, safe for -the mirror; never attach unknown attributes to v2 models). MRTR union -respected: `InputRequiredResult` passes through undecorated (tag only). -Re-arm: after `track()`, `add_request_handler` is patched on the instance so -a customer re-registering `tools/*` gets re-wrapped (TS `registrationPatch` -equivalent). Serves both bare v2 `Server` and `MCPServer` via -`_lowlevel_server`. - -### 8.4 `adapters/community.py` - -One `AgentCatMiddleware(Middleware)` with an era flag (v3/v4), inserted at -**index 0 = outermost** (verified: the chain builds via -`for mw in reversed(self.middleware)`, v4 `server.py:555`, so element 0 is -called first — matching today's v3 integration) so response -caching/dereference middlewares cannot cache around injection; caching below -us keys on **stripped** arguments, which is the desired semantics. `on_list_tools`: run pipeline over the FastMCP `Tool` -objects (`parameters`/`output_schema` attrs, `model_copy(update=...)`). -`on_call_tool`: strip via -`context.copy(message=message.model_copy(update={"arguments": stripped}))` — -preserving `input_responses`, `request_state`, `_meta` and every other field. -Result handling tolerates `ToolResult` and `InputRequiredToolResult` (v4). -snake_case-first field access with camelCase fallback for v3. `on_initialize` -captures legacy client info when it fires (handshake era only). Rebuild seam -(identical in both eras, verified): `await server.list_tools(run_middleware=False)` -(v3 `server.py:651`, v4 `server.py:827`); on failure, heuristic strip. `get_more_tools` registered via -`server.add_tool(Tool.from_function(...))` as today, plus `readOnlyHint`. - -## 9. Byte-authoritative agent-facing copy - -Source of truth: TS `src/modules/constants.ts` (verified on -`feat/explicit-handles-v2`) and changelog Appendix A. Python constants must -be byte-identical (same em-dashes, quotes, spacing). Inventory: - -### 9.1 `TASK_ID_PARAM_DESCRIPTION` - -> REQUIRED on every call after your first. This MCP server associates all of your tool calls for a given task using task_id; a call that arrives without it cannot be associated with your earlier work and is treated as the start of an unrelated task, disconnected from the original goal. Omit it on your first call only — the server will issue one in the _mcp_instructions field of the result (or a trailing [MCP INSTRUCTIONS] text block) — then echo that exact value on every later call. Never invent a value, and do not issue parallel tool calls until the server has issued your task_id. One task_id covers the whole goal from start to finish: when you spawn subagents you MUST give them this same task_id, or their work is severed from yours. Without task_id, this server does not function as intended. - -### 9.2 `AGENT_ID_PARAM_DESCRIPTION` - -> REQUIRED on every call, including your first. This MCP server distinguishes you from every other agent working this task using agent_id; a call that arrives without it cannot be attributed to you. Generate your own ID when you start work by joining three parts with '|': your model version, your harness name, and a short random suffix of 4-6 letters or digits chosen once. Example: opus-4.80-1m|claude-code|k3n9x. Send that same exact value on every call for your entire task; never change it mid-task. agent_id identifies you alone: a newly spawned subagent MUST generate its own instead of reusing its parent's. Without agent_id, this server does not function as intended. - -### 9.3 `AGENT_ID_PARAM_DESCRIPTION_HOOK_MODE` - -Identical to 9.2 except the first body sentence reads "…distinguishes you -from every other agent using agent_id;" (no "working this task"). - -### 9.4 Mint-back text - -``` -MINT_BACK_HEADER_TASK = "[MCP INSTRUCTIONS]: task_id issued." -MINT_BACK_CLOSER = "Without task_id, this server does not function as intended." -mint_back_task_line(task_id) = f" task_id={task_id} — required on every subsequent tool call" -mint_back_confirmed(names) = f"[MCP INSTRUCTIONS]: {' and '.join(names)} confirmed. Keep sending " - + ("these exact values" if len(names) > 1 else "this exact value") - + " on every call." -``` - -### 9.5 `_mcp_instructions` schema descriptions - -- Field: "Your handles for this task, confirmed by this MCP server on every response, and the instructions for echoing them on later calls. Read and follow." -- `task_id`: "Echo this exact value as the task_id argument on every subsequent tool call." -- `agent_id`: "Your agent_id as this server received it. Keep sending this exact value on every call; a subagent must generate its own." - -### 9.6 Wire keys, tags, prefixes - -`MCP_INSTRUCTIONS_KEY = "_mcp_instructions"`, -`META_CLIENT_INFO_KEY = "io.modelcontextprotocol/clientInfo"`, -`META_PROTOCOL_VERSION_KEY = "io.modelcontextprotocol/protocolVersion"`, -tags `agentcat_task_id_source` / `agentcat_agent_id` / -`agentcat_agent_id_source` / `agentcat_protocol_version` / `agentcat_mrtr`, -`AGENTCAT_CUSTOM_EVENT_TYPE = "agentcat:custom"`, prefixes `ses` / `evt` / -`agt` (reserved). Existing `DEFAULT_CONTEXT_DESCRIPTION` and the -`get_more_tools` description/context copy are already byte-identical to TS — -assert, don't retype. - -## 10. Testing - -- **Golden vectors** (cross-language contract, frozen): - `derive_task_id("customer-abc", "proj_1") == "ses_2cOHEO0LYGADMzRvWTXXVbbgxgm"`, - `derive_task_id("customer-abc") == "ses_2cZY3tvyI25O2AmL2CGVo2B1IIj"`, - `derive_task_id(" x ", "p") == "ses_2c3yR5mYKQdLaXsJNgZH6erbfQK"`, - `derive_task_id("x", "p") == "ses_2bw285VY9apdgUgTPXKFnT6P4G0"`. -- **Constants parity test**: assert every §9 string equals the expected bytes - (guards accidental rewording; mirrors TS `constants.test.ts`). -- **Handles unit**: mint prefix; extraction trust model incl. non-string/empty; - agent tag clamp; mint-back exact bytes; confirmed pluralization; - `_mcp_instructions` omission rules. -- **Injection unit**: order, deep-copy isolation, `additionalProperties` - removal, composed skip, collision skip + customer param passthrough, output - extension, registry contents, determinism (run twice, equal). -- **Call-path unit**: supplied/minted/hook; hook error/None → silent mint; - strip-clone (handler sees clean args, event records raw); error-result - mint-back; mirror gating incl. rebuild-failure mirror-anyway; customer - `_mcp_instructions` wins; MRTR intermediate undecorated + tagged; - continuation tagged; identify per call; ladder rungs; removed events never - published. -- **Per-flavor suites** under uv conflict groups `mcp-legacy` / `mcp-modern`: - existing official-v1 + community-v3 harnesses updated; new official-v2 - (lowlevel + MCPServer, streamable HTTP modern path) and community-v4 - (4.0.0b1) harnesses; concurrency regression (parallel calls, distinct - handles, no cross-attribution) on every flavor; late-`track()` / - rebuild-on-demand coverage (call before any list). -- **CI**: `mcp-compatibility.yml` matrix extends to mcp 2.x minors and - fastmcp 3.x/4.x (drop 2.x discovery + the `!=2.9.*` carve-out); - `mcp-prerelease-compatibility.yml` tracks 2.x/4.x prerelease channels. - -## 11. Packaging & migration - -- `pyproject.toml`: version `2.0.0b1`; `mcp>=1.2.0,<3`; - `pydantic>=2.0.0,<3` (re-verify `agentcat-api==1.0.0` under pydantic 2.12 - before merging); community extra `fastmcp>=3.0.0,<5`; keep - `requires-python>=3.10`; add `[tool.uv] conflicts` groups `mcp-legacy` - (`mcp>=1.2.0,<2`) / `mcp-modern` (`mcp>=2.0.0,<3`) for dev/test. -- MIGRATION.md: new "agentcat 1.x → 2.0" section (sessions → tasks; removed - events; removed `stateless`; identify per-call; `track()` never raises; - FastMCP 2.x dropped; new options; `publish_custom_event`), mirroring TS - MIGRATION.md structure. -- README + module docstrings for the new options and factory-pattern - (`track()` inside the request factory) guidance. - -## 12. Error-handling posture - -`track()` never raises. Hook (`resolve_task_id`) errors mint silently + log. -`identify` errors drop actor fields for that event. Injection failure on one -tool skips that tool's injection (registry entry empty) + logs. Decoration -failure returns the customer's original result. Detection failure returns the -server untracked + beacon. Event publishing keeps existing queue semantics -(redact-fail drops event; sanitize/truncate-fail continue). Nothing AgentCat -does may alter customer tool behavior beyond the specified wire decoration. - -## 13. Non-goals (changelog §7) - -No use of the `io.modelcontextprotocol/tasks` extension; no `Mcp-Method` / -`Mcp-Name` routing headers; no server-side session or handle storage; no -server-side `agent_id` minting; no hard rejection of calls missing -`agent_id`; no FastMCP 2.x compatibility layer. From 4e46e9835bef5f045f3f283269c4b0a4238f8ecd Mon Sep 17 00:00:00 2001 From: Naseem AlNaji Date: Tue, 4 Aug 2026 22:57:44 -0400 Subject: [PATCH 13/13] docs: sync README with the TypeScript SDK README Match the TS README section-for-section; code samples stay Python. Deviations: no redactEvent or PostHog (not in this SDK), and the identify paragraph reflects that hooks run ahead of the handler. --- README.md | 225 ++++++++++++--------------------------------- docs/cats/void.jpg | Bin 0 -> 6011875 bytes 2 files changed, 57 insertions(+), 168 deletions(-) create mode 100644 docs/cats/void.jpg diff --git a/README.md b/README.md index 87cc1e2..93ffc5c 100644 --- a/README.md +++ b/README.md @@ -23,14 +23,13 @@ CI

-> [!IMPORTANT] -> **AgentCat 2.0 is here.** MCP 2026-07-28 removed protocol-level sessions, so AgentCat now correlates work with an explicit `session_id` handle that agents echo back as a tool parameter. Handles land in the same `session_id` event field with the same `ses_` prefix, so your dashboards and exporters are unaffected — but tracked tools gain a `session_id` parameter, `AgentCatOptions.stateless` is gone, and FastMCP 2.x is no longer supported. Read the [1.x → 2.0 migration guide](https://github.com/agentcathq/agentcat-python-sdk/blob/main/MIGRATION.md) before upgrading a production server. +> [!NOTE] +> AgentCat v2 introduces compatibility with the [MCP Protocol "Stateless" 2026-07-28 Update](https://blog.modelcontextprotocol.io/posts/2026-07-28/) and the coinciding [MCP Python SDK v2](https://github.com/modelcontextprotocol/python-sdk/releases) release that puts it into effect. The stateless transition has a massive impact on analytics, as sessions were a built-in concept tying related tool calls together. AgentCat has now migrated its session tracking under guidance of the MCP core team's recommendations of using [explicit handles (SEP-2567)](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2567). +> +> As a result AgentCat now injects a `session_id` on every MCP tool call to associate them under the same task umbrella. Our evals show much higher tool correlation accuracy at the cost of < 1% additional context pollution. > [!IMPORTANT] -> **MCPcat is now AgentCat** 🐱 — same team, same product, new name. This package was previously published as [`mcpcat`](https://pypi.org/project/mcpcat/), which keeps working forever, but new features land here. Upgrading takes a few minutes — see the [migration guide](https://github.com/agentcathq/agentcat-python-sdk/blob/main/MIGRATION.md). - -> [!NOTE] -> Looking for the TypeScript SDK? Check it out here [agentcat-typescript](https://github.com/agentcathq/agentcat-typescript-sdk). +> **MCPcat is now AgentCat** 🐱 — same team, same product, new name. This package was previously published as [`mcpcat`](https://pypi.org/project/mcpcat/), which keeps working forever, but new features land here. Upgrading takes a few minutes — see the [migration guide](./MIGRATION.md). AgentCat is an analytics platform for MCP server owners 🐱. It captures user intentions and behavior patterns to help you understand what AI users actually need from your tools — eliminating guesswork and accelerating product development all with one-line of code. @@ -40,181 +39,96 @@ This SDK also provides a free and simple way to forward telemetry like logs, tra # Basic installation (includes official MCP SDK) pip install agentcat -# With Jlowin's/Prefect's FastMCP support +# With community FastMCP support pip install "agentcat[community]" ``` -One `track()` call covers every supported server shape: - -| Runtime | Supported | -| --- | --- | -| Official MCP SDK (`mcp`) 1.x — low-level `Server` and `mcp.server.fastmcp.FastMCP` | ✅ | -| Official MCP SDK (`mcp`) 2.x — low-level server and `MCPServer` | ✅ | -| Community FastMCP (`fastmcp`) 3.x and 4.x | ✅ (`agentcat[community]`) | -| Community FastMCP (`fastmcp`) 2.x | ❌ pin `agentcat<2` | - -The floors are `mcp>=1.2.0,<3` and `fastmcp>=3.0.0,<5`, and every minor in -both ranges is exercised on each change by the compatibility matrix. - -AgentCat runs on the whole range, but the oldest MCP releases lack the SDK -seams some features are built on, so those features go quiet rather than -break: - -| On | What is missing upstream | Effect | -| --- | --- | --- | -| `mcp<1.10` | `Server._make_error_result`; declared structured tool output | A bare low-level handler's exception type and stack frames cannot be recovered — the surfaced message is still published. No structured mint-back. | -| `mcp<1.9.2` | `RequestContext.request` | No header or `requestInfo` capture. | -| `mcp<1.8` | Streamable HTTP | stdio only. | -| `mcp<1.3` | Concurrent message handling | The server never has two calls in flight. | -| `fastmcp<3.4` | `ToolResult.is_error` | A proxied upstream error arrives as a raised `ToolError`, so it is published *with* full exception detail rather than as a bare message. | - -To learn more about us, check us out [here](https://agentcat.com) +To learn more about us, check us out [here](https://agentcat.com). For detailed guides visit our [documentation](https://docs.agentcat.com). ## Why use AgentCat? 🤔 -AgentCat helps developers and product owners build, improve, and monitor their MCP servers by capturing user analytics and tracing tool calls. +AgentCat helps builders of MCP servers, Claude Connectors, and ChatGPT Plugins learn how to improve them by capturing any agents goals and detecting when they get stuck. Use AgentCat for: -- **User session replay** 🎬. Follow alongside your users to understand why they're using your MCP servers, what functionality you're missing, and what clients they're coming from. +- **Agent session replay** 🎬. Follow alongside your users and their agents to understand why they're using your MCP servers, what functionality you're missing, and what clients they're coming from. - **Trace debugging** 🔍. See where your users are getting stuck, track and find when LLMs get confused by your API, and debug sessions across all deployments of your MCP server. - **Existing platform support** 📊. Get logging and tracing out of the box for your existing observability platforms (OpenTelemetry, Datadog, Sentry) — eliminating the tedious work of implementing telemetry yourself. AgentCat architecture — the AgentCat SDK inside your MCP server sends analytics to your observability vendors and session replay to the AgentCat dashboard -## Getting Started +## How it works -To get started with AgentCat, first create an account and obtain your project ID by signing up at [agentcat.com](https://agentcat.com). For detailed setup instructions visit our [documentation](https://docs.agentcat.com). +AgentCat works as a lightweight middleware inside your MCP server. When you call `track()`, it seamlessly modifies your registered tool schemas in place, following the MCP core team's [explicit handles (SEP-2567)](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2567) guidelines. Concretely, AgentCat adds the following to your server: -Once you have your project ID, integrate AgentCat into your MCP server: +- **`session_id`** — a parameter injected into each tool's input schema. Agents echo it back on every call, letting AgentCat group related tool calls into one task even over stateless transports. Values are validated: anything AgentCat did not issue is rejected rather than adopted, and the agent is told to re-send the ID it was given. +- **`agent_id`** _(off by default)_ — enabled with `enable_agent_tracking=True`. Each agent self-generates its own ID, keeping parallel agents working the same task individually attributable. +- **`context`** — a parameter asking the agent to explain, in one sentence, why it is making this call. This is where intent data comes from. +- **`get_more_tools`** — an additional tool, prompt-engineered so that agents readily report the features and tools they looked for but couldn't find — surfacing your missing functionality directly from real usage. -```python -import agentcat -from mcp.server.mcpserver import MCPServer # official MCP SDK 2.x +Injected parameters are stripped from arguments before your tool handler runs, so your code never sees them. For tools that declare an output schema, issued IDs are also mirrored into `structuredContent` (as `_mcp_instructions`), so clients that only read structured results still receive them. -server = MCPServer("echo-mcp") +## Getting Started -agentcat.track(server, "proj_0000000") -``` +To get started with AgentCat, first create an account and obtain your project ID by signing up at [agentcat.com](https://agentcat.com). For detailed setup instructions visit our [documentation](https://docs.agentcat.com). -On the official SDK's 1.x line the server class is `mcp.server.fastmcp.FastMCP` instead; everything after it is identical. +Once you have your project ID, integrate AgentCat into your MCP server: ```python import agentcat -from mcp.server.fastmcp import FastMCP # official MCP SDK 1.x +from mcp.server.mcpserver import MCPServer -server = FastMCP("echo-mcp") +server = MCPServer("echo-mcp", version="0.1.0") +@server.tool(description="Echo a message") +def echo(msg: str) -> str: + return msg + +# Track the server with AgentCat agentcat.track(server, "proj_0000000") ``` -> [!NOTE] -> A fresh `pip install` resolves `mcp` **2.x**, where `mcp.server.fastmcp` no longer exists — the 1.x snippet above only runs on a checkout that already pins `mcp<2`. AgentCat supports both generations from one install; which import you use is decided by the `mcp` you have, not by AgentCat. - -`track()` classifies whatever object you hand it and installs the matching adapter, so the same call covers a low-level `Server`, either official facade, and community FastMCP. It **never raises** — a shape AgentCat does not support is logged to `~/agentcat.log` and your server comes back untracked rather than failing to start. - -### Session handles: how work is correlated - -MCP 2026-07-28 removed protocol-level sessions, so AgentCat correlates a series of calls with an explicit **session handle** instead. Tracked tools gain an optional `session_id` string parameter; AgentCat mints one on the first call, tells the agent to echo it back, and strips it out again before your handler runs. Your tool signatures and your handler code are untouched. - -AgentCat honors only handles it issued. A `session_id` that is not a `ses_` KSUID this server minted is rejected rather than adopted — the call publishes without a session and the agent is told to re-send the ID it was given, or to omit the parameter and be issued one. That keeps a hallucinated value, or an auth token a client auto-populated into a parameter of the same name, out of the event field your redaction hook cannot reach. - -**If one of your own tools already declares a** `session_id` **parameter,** AgentCat leaves it alone: your value reaches your handler untouched and is never read as a handle. Calls to that tool publish **without a session**, so they cannot be correlated, and an `ERROR` naming the tool goes to `~/agentcat.log`. If you already manage sessions, pass `resolve_session_id` — AgentCat then derives its own handle from your identifier and stops injecting `session_id` entirely. - -Handles land in the existing `session_id` event field with the same `ses_` prefix, so dashboards, saved filters, and exporters carry over unchanged. See the [migration guide](https://github.com/agentcathq/agentcat-python-sdk/blob/main/MIGRATION.md) for exactly what this adds to your published schemas. - -### Track inside your server factory - -`track()` mutates the server instance it is given, so it has to run on the *same* instance that serves traffic. If you build servers in a factory — the usual shape for tests, for multi-tenant hosting, or for a per-worker server — call `track()` inside the factory, on the instance you are about to return: +Stateless servers built on [MCP 2026-07-28](https://blog.modelcontextprotocol.io/posts/2026-07-28/) create a fresh server instance per worker or per tenant, serving each request with `stateless_http=True`. Call `track()` inside the factory so every instance is tracked: ```python import agentcat from mcp.server.mcpserver import MCPServer def create_server() -> MCPServer: - server = MCPServer("echo-mcp") - - @server.tool() - def echo(text: str) -> str: - return text - + server = MCPServer("echo-mcp", version="0.1.0") + # register tools... agentcat.track(server, "proj_0000000") return server -``` - -Tools registered *after* `track()` are picked up automatically — there is no need to re-track, and calling `track()` twice on one server is safe (the most recent options win). -### Identifying users - -You can identify the actor behind a call with a simple callback AgentCat exposes, called `identify`. It runs on **every** tool call and its result is stamped on that call's event, so keep it cheap — add your own caching if it does a database or API lookup. - -```python -from agentcat import AgentCatOptions, UserIdentity - -def identify_user(request, extra): - # `request` is the tool call's PARAMS on every server flavor: `.name` and - # `.arguments`, one hop, not two. `arguments` is a plain dict — index it, - # don't reach for an attribute. - user = myapi.get_user(request.arguments["token"]) - return UserIdentity( - user_id=user.id, - user_name=user.name, - user_data={ - "favorite_color": user.favorite_color, - }, - ) - -agentcat.track(server, "proj_0000000", AgentCatOptions(identify=identify_user)) +server = create_server() +server.run(transport="streamable-http", stateless_http=True) ``` -The hook may be sync or async — `async def identify_user(request, extra)` works the same way. A sync hook runs on a worker thread, so a blocking lookup stalls only its own call, never the rest of your server; note that this means a *sync* hook cannot use asyncio APIs (make it `async def` if it needs the loop). Every hook runs under a 5-second cap — a slower one is logged and its call proceeds anonymously. Returning anything that is not a `UserIdentity`, or raising, publishes the event anonymously rather than failing the call. - -### Bringing your own session IDs +Calling `track()` per instance is cheap — the event queue, telemetry exporters, and diagnostics are initialized once and shared across instances. -If you already have a correlation ID — a trace ID, a job ID, a header your gateway sets — hand it to AgentCat with `resolve_session_id` and no `session_id` parameter is injected into your tools at all: - -```python -import agentcat -from agentcat import AgentCatOptions - -def session_from_header(request, extra): - headers = getattr(getattr(extra, "request", None), "headers", {}) or {} - return headers.get("x-correlation-id") - -agentcat.track(server, "proj_0000000", AgentCatOptions(resolve_session_id=session_from_header)) -``` +### Identifying users -The string you return is combined with your project ID into a deterministic `ses_` handle, so the same correlation ID always maps to the same session. The hook may be sync or async, receives the same `(request, extra)` pair as `identify`, and returning `None` (or raising) quietly mints a fresh handle instead. +We strongly encourage identifying every actor. If you can't resolve a real user, return a stable anonymized ID instead — for example, a hash of the auth token or API key — so that all events from the same end user still roll up to one actor in your dashboard rather than scattering into anonymous one-off sessions. -### Tracking individual agents +`identify` (like every AgentCat hook) may be sync or async and runs on every tool call, ahead of your handler: a hook that fails outright — or returns anything that is not a `UserIdentity` — costs analytics data for that event, never the call itself. Every hook runs under a 5-second cap, and a slow lookup delays that call's response — so keep it cheap, and add your own caching if it does a database or API lookup. -Set `enable_agent_tracking=True` to also distinguish *which* agent is working — subagents get their own identity while sharing their parent's session. This adds an `agent_id` parameter to your tools and, unlike `session_id`, marks it **required**, which schema-validating clients will enforce. That is why it is off by default. +The callback receives the tool call's `request` params (`.name` and `.arguments`, a plain dict) and the request context the SDK hands to handlers — the same `(request, extra)` shape on every supported server flavor. On HTTP transports, identity signals like headers and auth live on `extra.request`: ```python -import agentcat -from agentcat import AgentCatOptions - -agentcat.track(server, "proj_0000000", AgentCatOptions(enable_agent_tracking=True)) -``` - -Agent identity rides on events as the `agentcat_agent_id` tag. A call that omits `agent_id` still succeeds — the event is simply published without it. - -### Publishing your own events +from agentcat import AgentCatOptions, UserIdentity -Not everything worth seeing on the timeline is a tool call. `publish_custom_event` records background jobs, webhooks, or checkout steps against a session: +async def identify(request, extra): + http = getattr(extra, "request", None) # incoming HTTP request, when present + token = http.headers.get("authorization") if http else None + org_id = http.headers.get("x-org-id") if http else None + user = await myapi.get_user(token) + if not user: + return None + return UserIdentity(user_id=user.id, user_name=user.name, user_data={"org_id": org_id}) -```python -import agentcat - -agentcat.publish_custom_event(server, "proj_0000000", { - "session_id": "ses_2cOHEO0LYGADMzRvWTXXVbbgxgm", - "resource_name": "checkout", - "message": "order confirmed", -}) +agentcat.track(server, "proj_0000000", AgentCatOptions(identify=identify)) ``` -The first argument may be a tracked server or a bare session-ID string. `session_id` is used **verbatim** — never validated, derived or reformatted, since it is your deliberate server-side call rather than an agent's guess — and an event published without one lands untethered to any session. Events are typed `agentcat:custom`, are fire-and-forget, and never raise. A server tracked with `enable_tracing=False` publishes nothing here either. - ### Redacting sensitive data AgentCat redacts all data sent to its servers and encrypts at rest, but for additional security, it offers a hook to do your own redaction on all text data returned back to our servers. @@ -222,15 +136,14 @@ AgentCat redacts all data sent to its servers and encrypts at rest, but for addi ```python from agentcat import AgentCatOptions -def redact(text): - return custom_redact(text) +async def redact(text: str) -> str: + return await redactor(text) +# or a plain sync function — both are supported agentcat.track(server, "proj_0000000", AgentCatOptions(redact_sensitive_information=redact)) ``` -The hook may be sync or async. It runs on every string in the event except the fields AgentCat needs to attribute it — the session handle, the event, project and resource IDs, the actor your `identify` hook returned, and your own tags and properties. If it raises, the event is dropped rather than published unredacted. - -### Forwarding data to existing observability platforms +### Vendor Support AgentCat seamlessly integrates with your existing observability stack, providing automatic logging and tracing without the tedious setup typically required. Export telemetry data to multiple platforms simultaneously: @@ -241,56 +154,31 @@ from agentcat import AgentCatOptions agentcat.track( server, - "proj_0000000", # Or None if you just want to use the SDK to forward telemetry + "proj_0000", # Project ID can optionally be None if you just want to forward telemetry AgentCatOptions( exporters={ - # OpenTelemetry - works with Jaeger, Tempo, New Relic, etc. "otlp": { "type": "otlp", "endpoint": "http://localhost:4318/v1/traces", }, - # Datadog "datadog": { "type": "datadog", - "api_key": os.getenv("DD_API_KEY"), + "api_key": os.environ["DD_API_KEY"], "site": "datadoghq.com", "service": "my-mcp-server", }, - # Sentry "sentry": { "type": "sentry", - "dsn": os.getenv("SENTRY_DSN"), + "dsn": os.environ["SENTRY_DSN"], "environment": "production", }, } - ) + ), ) ``` Learn more about our free and open source [telemetry integrations](https://docs.agentcat.com/telemetry/integrations). -### Known limitations - -Two behaviors are worth knowing before you read your first dashboard. Both are deliberate in the 2.x line. - -- **Multi-round tool calls that mint their own handle land on separate sessions.** When a tool call runs several round trips and the *first* round is what mints the handle, each round is attributed to its own session rather than one shared session. Supplying a `session_id` yourself, or deriving one with `resolve_session_id`, correlates the rounds correctly — those two modes are protocol-enforced. Only the mint-on-first-round case is affected. -- **Errors forwarded from a proxied community tool carry no stack detail.** When a community FastMCP server proxies a tool to an upstream server and that upstream returns an error result, there is no local Python exception to read, so the event records the error message without a stack trace. Errors raised by your own tool code are unaffected and carry full detail. - -### Shutdown behavior - -AgentCat never touches your process lifecycle: no signal handlers, no forced -exits, and no exit-time event drain. The SDK's single publish worker is a -daemon thread, so your shutdown — `Ctrl-C`, `SIGTERM`, `sys.exit()` — runs -exactly as it would untracked, and is never delayed by AgentCat. The trade: -telemetry still queued at the moment the process exits is dropped rather than -flushed. The SDK keeps exactly two bounded exit hooks, neither of which sends -events: one stops the publish worker before interpreter finalization (instant -when idle, ~1-second cap otherwise — on Linux with CPython ≤3.13 a daemon -thread still running during finalization can abort the process, CPython -gh-87135, and stopping first closes that path), and the internal-diagnostics -beacon below — skipped when there is nothing buffered, capped at ~2 seconds -when there is. - ### Internal diagnostics To help us catch and fix broken installs, the SDK sends AgentCat a small, anonymized @@ -308,7 +196,7 @@ Diagnostics are on by default and can be turned off completely with either: AgentCat is free for qualified open source projects. We believe in supporting the ecosystem that makes MCP possible. If you maintain an open source MCP server, you can access our full analytics platform at no cost. -**How to apply**: Email hi@agentcat.com with your repository link +**How to apply**: Email [hi@agentcat.com](mailto:hi@agentcat.com) with your repository link _Already using AgentCat? We'll upgrade your account immediately._ @@ -319,6 +207,7 @@ Meet the cats behind AgentCat! Add your cat to our community by submitting a PR
bibi zelda + void
-_Want to add your cat? Create a PR adding your cat's photo to `docs/cats/` and update this section!_ +_Want to add your cat? Create a PR adding your cat's photo to_ `docs/cats/` _and update this section!_ diff --git a/docs/cats/void.jpg b/docs/cats/void.jpg new file mode 100644 index 0000000000000000000000000000000000000000..11486d1ffb74367d5a135272ee0468bb85cad40b GIT binary patch literal 6011875 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 z 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

7I_LCDe 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≀uQW&5? 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

pG$|HlA-J?rv0(+P*ir@XfWQ+oqvx(cH|~0lw{b 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 t`lVwP-bM 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%0Att)w8 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

DIOV|TdJlT8AiqW=sW}*`S2p(%pD+@w!0E+v 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

BY{44KP{k=RV;4x>Y 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 z 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%0Dt}X~!hz}1798I_N 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皗u(YVswhvAK#db<{Ykv+TLoK$IrDOWFA7{9- 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%0DpUIPQx(|#BYz~ZbdQU3s}nDL%5Sxl#K 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%0DriuabzvJx;$jA!XxUx$XJbEaG0O>9yy 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�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%0Dq!LkTf42-yu67^)WvZ5T{^A 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