Loading
0x90Lesson 10 of 16

Build client workflows with MCP

Discover capabilities, page through and cache lists, avoid name collisions, and keep the user in control.

20 min 7-question quiz 2 code exercises
By the end of this lesson you can
  • Page through tools/list with cursors and cache it with ttlMs
  • Combine tools from several servers without name collisions
  • Route a model’s tool call and keep the user in the loop

The host’s job, in a loop:

  1. Discover each server’s tools (and resources, prompts).
  2. Offer the tools to the model, alongside the conversation.
  3. When the model asks for a call, show it to the user and confirm if it is sensitive.
  4. Route the call through the right client, then hand the result (or tool error) back to the model.

Pagination and caching

Long lists come in pages: a result with nextCursor means there is more - send the same request again with params.cursor set to it, until a page has no nextCursor. In the current revision, list results also carry ttlMs (how long the answer may be reused) and cacheScope, so a client doesn’t need to re-fetch the tool list before every message. Servers should return tools in a stable order, which also helps model prompt caching.

paging.py
1pages = {
2    None: {"tools": ["search", "fetch"], "nextCursor": "p2"},
3    "p2": {"tools": ["summarize"], "nextCursor": "p3"},
4    "p3": {"tools": ["translate"]},
5}
6cursor, tools = None, []
7while True:
8    page = pages[cursor]
9    tools += page["tools"]
10    cursor = page.get("nextCursor")
11    if cursor is None:
12        break
13print(tools)
Output
['search', 'fetch', 'summarize', 'translate']

Many servers, one model

Tool names are only unique within one server. Connect a GitHub server and a Jira server that both expose search, and the model sees two tools with the same name. The spec says hosts should disambiguate - typically by prefixing each tool with a server identifier the host chose (github__search, jira__search). Don’t rely on a server’s self-reported name for this: it isn’t guaranteed unique.

Key takeaways

  • Follow nextCursor until it disappears; reuse list results within their ttlMs.

  • Prefix tool names with your own server label to avoid collisions.

  • The host decides, shows and confirms - the model only suggests calls.

Lesson quiz

7 questions · pass with 5 correct · up to 50 XP

Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.

Practice: build an MCP server

Write Python in the editor and run it against sample inputs. Python runs locally in your browser using a WebAssembly runtime.

Exercise 1

Merge tools from several servers

+25 XP

Each input line is a server label followed by a JSON list of its tool names, like github ["search", "create_issue"]. Print every tool as LABEL__NAME, sorted alphabetically, one per line.

  • A collision
  • One server
main.py
Loading editor…

Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.

Exercise 2

Decide whether to re-fetch

+25 XP

The first line is fetched_at_ms ttl_ms for a cached tools/list result. Each following line is a current time in milliseconds. For each, print cached if the result is still fresh (now − fetched_at < ttl), otherwise refetch.

  • Before and after expiry
  • Zero TTL
main.py
Loading editor…

Python runs in a sandboxed browser worker with a 60 second time limit. Its runtime loads from the Pyodide CDN; your code stays in this browser.

Questions about this lesson

Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.

Loading posts…