Skip to content

feat(mcp-get-started): fastmcp 4, the SEP-2663 tasks extension, and a task-augmented tool - #11

Merged
JonZeolla merged 4 commits into
mainfrom
mcp-async-tasks
Sep 3, 2026
Merged

feat(mcp-get-started): fastmcp 4, the SEP-2663 tasks extension, and a task-augmented tool#11
JonZeolla merged 4 commits into
mainfrom
mcp-async-tasks

Conversation

@JonZeolla

@JonZeolla JonZeolla commented Sep 3, 2026

Copy link
Copy Markdown
Member

Change Description

Adds slow_shout to the MCP 101 rig — an async tool with task=True — and moves the rig to FastMCP 4 so it can drive the MCP task cycle on the 2026-07-28 protocol revision.

  • server.pyslow_shout(text, seconds=10), plus mcp.add_extension(TasksExtension()). FastMCP 4 splits task support into the fastmcp-tasks distribution and requires registering the extension explicitly; the tasks extra alone is no longer enough.
  • client.py — passes Path for a file target and a string for a URL. FastMCP 4 deprecates inferring a stdio transport from a bare string (removed in 5), so Client("server.py") printed a FastMCPDeprecationWarning on every learner's first run.
  • pyproject.toml / Dockerfilefastmcp[tasks]>=4,<5, lockfile re-pinned.
  • evidence/ — every file recaptured from the e2e harness instance. New: discover.txt (the server/discover response) and tasks-capability-refusal.txt (the -32021).
  • READMEs regenerated with 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:

SEP-1686 (fastmcp 3) SEP-2663 (fastmcp 4)
Enablement fastmcp[tasks] extra plus mcp.add_extension(TasksExtension())
Requesting a task params.task = {ttl} nothing on the request; declaring the extension in the envelope does it
Polling tasks/get then tasks/result tasks/get only, result inline once completed
Advertising execution.taskSupport on the tool absent from the tool descriptor

pydocket'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.

{"result":"THE SLOW WAY!"}
waited 10s for that
submitted d49tt8EqL5SD0h8g8DbRIFUXxoaMx2HGPyZOMOafufs
{"status":"working","pollIntervalMs":5000.0}
{"status":"completed","result":{"result":"TASKS WORK!"}}

client.py passes over both stdio and Streamable HTTP with no deprecation warning, and goose reached both tools on its first attempt.

Pull Request Checklist

  • If you are adding a dependency, please explain how it was chosen — fastmcp[tasks] is the same fastmcp already pinned plus the extra carrying task support; fastmcp-tasks and pydocket arrive through it. No new vendor.
  • Ensure all items left for future development have been appropriately documented

Hub-side content: Zenable-io/next-gen-governance#6752

🤖 Generated with Claude Code

https://claude.ai/code/session_01ReAbCfx4UvDZE3RKSGBDQM

…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

@ai-coding-guardrails ai-coding-guardrails Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! 😎

I didn't find anything of concern

List of skipped files due to configuration

Risk: 🟢 Low

Reviewed with 🤟 by Zenable

@ai-coding-guardrails ai-coding-guardrails Bot added the zenable/risk:low Zenable assessed this PR as LOW risk. label Sep 3, 2026
JonZeolla and others added 3 commits September 3, 2026 14:36
…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 JonZeolla changed the title feat(mcp-get-started): add a task-augmented tool and drive the task cycle feat(mcp-get-started): fastmcp 4, the SEP-2663 tasks extension, and a task-augmented tool Sep 3, 2026
@JonZeolla
JonZeolla merged commit 239f129 into main Sep 3, 2026
2 checks passed
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

zenable/risk:low Zenable assessed this PR as LOW risk.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant