feat(mcp-get-started): fastmcp 4, the SEP-2663 tasks extension, and a task-augmented tool - #11
Merged
Conversation
…ycle Adds `slow_shout`, an async tool with `task=True`, so the MCP 101 lab can walk the SEP-1686 task cycle by hand: a task-augmented `tools/call`, then `tasks/get` while it runs, then `tasks/result` once it settles. `task=True` needs pydocket, which arrives with the `tasks` extra, so both `pyproject.toml` and the `Dockerfile` now ask for `fastmcp[tasks]`. The backend defaults to an in-process queue, so the lab needs no Redis. READMEs regenerated with `export-lab-readme.js --all`, which also picks up unrelated agentgateway-mcp drift that had accumulated on the Hub side. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ReAbCfx4UvDZE3RKSGBDQM
There was a problem hiding this comment.
Nice work! 😎
I didn't find anything of concern
List of skipped files due to configuration
Risk: 🟢 Low
Reviewed with 🤟 by Zenable
…sion FastMCP 4 splits task support into the `fastmcp-tasks` distribution and an explicit `mcp.add_extension(TasksExtension())`, and the wire moves with it: tasks are the `io.modelcontextprotocol/tasks` extension on the 2026-07-28 protocol revision, where `tasks/get` carries the result inline and there is no `tasks/result`. Pins `fastmcp[tasks]>=4,<5` in both pyproject.toml and the Dockerfile. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ReAbCfx4UvDZE3RKSGBDQM
…string
FastMCP 4 deprecates inferring a stdio transport from a string target and
removes it in 5, so `Client("server.py")` printed a FastMCPDeprecationWarning
on every learner's first run.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ReAbCfx4UvDZE3RKSGBDQM
Every evidence file now comes from the Rocky Linux 8 instance the sandbox image recipe builds, rather than a developer laptop, so the versions and output a learner sees are the ones recorded here. Adds discover.txt (the 2026-07-28 server/discover response) and tasks-capability-refusal.txt (the -32021 a task method returns when the request envelope omits the extension). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ReAbCfx4UvDZE3RKSGBDQM
JonZeolla
added a commit
that referenced
this pull request
Sep 3, 2026
The first run of the new update automation, with every bump validated by actually running the lab it touches rather than trusting that it starts. Keycloak 26.7.1 -> 26.7.2 in the a2a and agent-identity rigs. 26.7.3 exists but was 3 days old, so the cooldown correctly held it back. Jaeger all-in-one 1.68.0 -> 1.76.0, held to the 1.x line because Jaeger v2 is a different image with a different CLI. agentgateway stays at v1.4.1 deliberately. v1.5.0 has now cleared the cooldown, but it renames the trace spans this lab teaches: POST /* disappears, delete_session and get_stream become DELETE/GET get-started, and tools/call get-started splits per tool. That invalidates two transcripts and two pieces of navigation prose in agentgateway-mcp.mdx, so it is lab-content work for an author rather than a version bump. update-pins.sh records why, and the pin stays automated so the next run proposes it again. mcp-get-started keeps the fastmcp 4 line from #11 and raises its floor to 4.0.2, resolving against current PyPI rather than the 7-day window. The lab teaches the SEP-2663 tasks extension, which only exists in fastmcp 4 — released days ago — so a cooldown on the lab's own subject leaves the lock unsatisfiable rather than safe. server.py imports fastmcp_tasks directly, so the [tasks] extra stays: base fastmcp pulls only fastmcp-slim. evidence/ regenerated by each lab's own capture-evidence.sh, never by hand. a2a's end-to-end.txt and agent-identity's sdjwt-walkthrough.txt came back byte-identical, and agent-identity reports 22/22 negative tests behaving as documented. ema-mcp passes 7/7. mcp-get-started's evidence is left alone: it was captured on the e2e harness and already records fastmcp 4.0.2. ema-mcp's Keycloak is now pinned by digest. ceposta/keycloak:id-jag is a mutable tag on a third party's personal Docker Hub account with no version and no release feed, so there is nothing for the automation to measure or move it to; the digest at least fixes the bytes. The README files are generated from the better-agentgateway branch in next-gen-governance and exported here, never edited in this repo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Change Description
Adds
slow_shoutto the MCP 101 rig — an async tool withtask=True— and moves the rig to FastMCP 4 so it can drive the MCP task cycle on the 2026-07-28 protocol revision.server.py—slow_shout(text, seconds=10), plusmcp.add_extension(TasksExtension()). FastMCP 4 splits task support into thefastmcp-tasksdistribution and requires registering the extension explicitly; thetasksextra alone is no longer enough.client.py— passesPathfor a file target and a string for a URL. FastMCP 4 deprecates inferring a stdio transport from a bare string (removed in 5), soClient("server.py")printed aFastMCPDeprecationWarningon every learner's first run.pyproject.toml/Dockerfile—fastmcp[tasks]>=4,<5, lockfile re-pinned.evidence/— every file recaptured from the e2e harness instance. New:discover.txt(theserver/discoverresponse) andtasks-capability-refusal.txt(the-32021).export-lab-readme.js --all.Background (Why we did this)
The lab took a server from stdio to a container to goose without ever showing what MCP does when a tool takes minutes. On 2026-07-28 that story is short enough to drive with
curl.What changed between SEP-1686 and SEP-2663 is worth knowing before reviewing:
fastmcp[tasks]extramcp.add_extension(TasksExtension())params.task = {ttl}tasks/getthentasks/resulttasks/getonly, result inline oncecompletedexecution.taskSupporton the toolpydocket's default backend is an in-process queue, so the lab needs no Redis and no extra container.
Testing
The full lab ran on the e2e harness (Rocky Linux 8 EC2, provisioned from the sandbox image recipe): 17 blocks ran, 0 skipped, 0 failed. Evidence in this PR is that run's output, not a laptop's.
client.pypasses over both stdio and Streamable HTTP with no deprecation warning, and goose reached both tools on its first attempt.Pull Request Checklist
fastmcp[tasks]is the same fastmcp already pinned plus the extra carrying task support;fastmcp-tasksandpydocketarrive through it. No new vendor.Hub-side content: Zenable-io/next-gen-governance#6752
🤖 Generated with Claude Code
https://claude.ai/code/session_01ReAbCfx4UvDZE3RKSGBDQM