Mirror of https://github.com/modelcontextprotocol/quickstart-resources — A repository of servers and clients from the Model Context Protocol tutorials
  • JavaScript 19.6%
  • Rust 17.3%
  • Go 16.6%
  • TypeScript 13.2%
  • Ruby 11.8%
  • Other 21.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Alex Akimov 470d1ba328
Some checks failed
Smoke Tests / test (push) Has been cancelled
Fix the tool-use loop in the Go, Rust, and Ruby clients and add a tool-loop smoke test (#200)
* Fix the tool-use loop in the Go, Rust, and Ruby clients and add a tool-loop smoke test

## Motivation and Context

Only the Python and TypeScript clients implemented a correct tool-use loop. The other three
had bugs that break ordinary multi-step requests:

- **Go, Rust, Ruby** did a single tool round and then called Claude once more *without*
  `tools`, so any request that needs a second tool call stalled. Go silently dropped
  `tool_use` blocks from that final response.
- **Ruby** called Claude once per `tool_use` block, each time with a single `tool_result`.
  Parallel tool calls produced a malformed message sequence and an API 400.
- **max_tokens** was 1000 in TypeScript and Ruby, 1024 in Go, and unset in Rust. Sonnet 5
  thinks adaptively, so 1000 tokens is regularly exhausted mid-thought. Python already used
  10000 with a comment explaining why.
- **Ruby** never forwarded MCP `isError` as `is_error`, so the model could not tell a failed
  tool call from a successful one. Rust cannot set the flag either (see below).
- **TypeScript** forwarded raw MCP content blocks to Anthropic. The two block shapes differ,
  so a non-text result would have failed.

The existing smoke test never noticed because it only checks that each client calls
`tools/list`. None of these bugs was reachable without an API key.

### What changed

All five clients now run the same loop: call tools until Claude answers without one, send
every `tool_result` of a turn in one user message, pass `tools` on every call, and stop
after `MAX_TOOL_TURNS = 10`. `max_tokens` is 10000 everywhere, with the same comment.
Python and TypeScript also keep the last response's text when the turn cap is hit; it used
to be dropped.

Rust keeps the `genai` crate. Its tool-response type has no `is_error` field, so an error
result is marked with an `Error:` prefix in the text and the limitation is commented.

### New smoke test

`tests/helpers/tool-loop-test.ts` starts a fake Anthropic Messages API on a loopback port,
points a client at it through `ANTHROPIC_BASE_URL`, pipes in one query, and checks every
request the client sends. It scripts two parallel tool calls, then a call to a tool the mock
server lacks (an `isError` result), then a final answer, and asserts that tools are passed
each time, `max_tokens` is 10000, all `tool_result`s arrive in one message with matching
ids, and the error is forwarded. `smoke-test.sh` runs it for Python, TypeScript, Go, and
Ruby.

The Rust client is excluded for now: `genai` reads no endpoint variable, and the client
negotiates protocol `2025-11-25`, under which the mock's array-rooted tool is refused at call
time. Both will be addressed in a follow-up that brings all examples to current SDK versions.

## How Has This Been Tested?

- `./tests/smoke-test.sh` passes for every example.
- The new tool-loop test passes all 19 checks for Python, TypeScript, Go, and Ruby.
- The Rust client was driven through the same scripted conversation with a temporary
  endpoint resolver (not committed) and passes.
- As a negative check, the Ruby client from `main` was run through the new test. It fails 10
  of 19 checks, on exactly the bugs listed above.
- Go and Ruby were built and run in `golang:1.25` and `ruby:3.4` containers.

## Breaking Changes

None. The clients' command lines, output format, and no-key behavior are unchanged.

## Types of changes

- [x] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [x] Documentation update

## Checklist

- [x] I have read the [MCP Documentation](https://modelcontextprotocol.io)
- [x] My code follows the repository's style guidelines
- [x] New and existing tests pass locally
- [x] I have added appropriate error handling
- [x] I have added or updated documentation as needed

## Additional context

Two pre-existing issues surfaced while testing and are left for a follow-up:

- The Rust client (rmcp 3.1.2) negotiates `2025-11-25`. The TypeScript mock server and the
  Python weather server both reject its calls to array-rooted tools under that revision.
  Even current rmcp defaults to `2025-11-25`, so the client must request `2026-07-28`
  explicitly.
- The Go SDK's tool-result helper sends content as a list of text blocks rather than a
  string. The API accepts both, so it is unchanged.

AI assistance: the analysis, code changes, test helper, and this description were prepared
partially manually, partially with Claude Code and reviewed by me.

* Improvements

* Address comments
2026-09-19 18:25:02 -07:00
.github/workflows Address the code scanning report (#189) 2026-08-23 09:29:35 -07:00
mcp-client-go Fix the tool-use loop in the Go, Rust, and Ruby clients and add a tool-loop smoke test (#200) 2026-09-19 18:25:02 -07:00
mcp-client-python Fix the tool-use loop in the Go, Rust, and Ruby clients and add a tool-loop smoke test (#200) 2026-09-19 18:25:02 -07:00
mcp-client-ruby Fix the tool-use loop in the Go, Rust, and Ruby clients and add a tool-loop smoke test (#200) 2026-09-19 18:25:02 -07:00
mcp-client-rust Fix the tool-use loop in the Go, Rust, and Ruby clients and add a tool-loop smoke test (#200) 2026-09-19 18:25:02 -07:00
mcp-client-typescript Fix the tool-use loop in the Go, Rust, and Ruby clients and add a tool-loop smoke test (#200) 2026-09-19 18:25:02 -07:00
tests Fix the tool-use loop in the Go, Rust, and Ruby clients and add a tool-loop smoke test (#200) 2026-09-19 18:25:02 -07:00
weather-server-go Improve all readmes (#188) 2026-08-27 20:32:29 -07:00
weather-server-python Upgrade Python libraries to mcp 2.2.0, and bump others as well (#197) 2026-09-15 15:13:25 -07:00
weather-server-ruby Correct README claims that do not match the repo 2026-08-28 10:51:08 -07:00
weather-server-rust Correct README claims that do not match the repo 2026-08-28 10:51:08 -07:00
weather-server-typescript Upgrade TypeScript libraries to newer versions (#198) 2026-09-15 15:12:34 -07:00
.gitattributes Add .gitattributes to mark lock files as generated 2025-12-12 09:52:25 -06:00
.gitignore Assert on structured output in the smoke tests and update to v2 (#163) 2026-08-03 19:42:57 +02:00
LICENSE chore: update licensing to Apache 2.0 for new contributions 2026-01-12 22:49:32 +00:00
README.md Add smoke tests for Go and Rust clients (#196) 2026-09-15 15:14:06 -07:00
SECURITY.md docs: add security notes for network-exposed MCP servers 2026-02-07 12:55:02 +01:00

MCP Quickstart Resources

Example servers and clients for the Model Context Protocol (MCP), in five languages. These are companion examples for two official tutorials:

  • Build an MCP server – a simple MCP weather server exposing two tools backed by the US National Weather Service API
  • Build an MCP client – an LLM-powered chatbot MCP client that connects to any stdio server and lets Claude call its tools

What's in this repository

Each example lives in its own directory with its own README covering prerequisites, setup, and how to run it:

Language Weather server (MCP server) Chatbot (MCP client)
Python weather-server-python mcp-client-python
TypeScript weather-server-typescript mcp-client-typescript
Go weather-server-go mcp-client-go
Rust weather-server-rust mcp-client-rust
Ruby weather-server-ruby mcp-client-ruby

All servers communicate over stdio and expose the same two tools: get_forecast and get_alerts (or get-forecast and get-alerts in TypeScript).

All clients launch a server, list its tools, and start an interactive chat loop in which Claude can call those tools. The Python, TypeScript, and Ruby clients take a path to a server script; the Go and Rust clients take the command to run, plus any arguments.

Note: These example clients need an ANTHROPIC_API_KEY to operate. Without a key, each client still connects and lists the server's tools before exiting, so you can verify the MCP wiring without credentials.

You can mix and match across languages: for example, the Python client can drive the TypeScript server. Each client's README lists which server launch forms it supports.

The tests directory contains the smoke tests that run in CI against these examples. See tests/README.md for how they work.

Prerequisites

Each example only needs its own language toolchain. To work across the whole repository (for example, to run the smoke tests) you need:

  • Node.js 24+ and npm
  • Python 3.10+ and uv
  • Go 1.25+
  • Rust 1.88+ and Cargo
  • Ruby 3.4+ and Bundler

Running the tests

./tests/smoke-test.sh

The smoke tests verify that every server starts and answers MCP requests (including validating structured tool results against the schemas each tool advertises), and that every client can connect to a mock server and list tools. They run automatically on every pull request via GitHub Actions.

Contributing

Contributions are welcome. To submit a change:

  1. Fork the repository and create a branch from main.
  2. Make your change. Keep the examples minimal - they exist to teach the protocol, not to be production services.
  3. If you change an example's behavior, setup, or dependencies, update that example's README to match.
  4. Run ./tests/smoke-test.sh and make sure it passes.
  5. Open a pull request against main describing what changed and why.

A few conventions to follow, in line with the broader Model Context Protocol contributing guidelines:

  • Keep documentation clear, concise, and technically accurate. Include code examples where appropriate, and test the commands and links you add.
  • Disclose AI assistance. If you used any kind of AI assistance to prepare your contribution, say so in the pull request or issue. See AI_POLICY.md for what the disclosure should cover.
  • Be respectful. This project follows the MCP community's Code of Conduct. Concerns can be reported to mcp-coc@anthropic.com.

Security note

These examples are intentionally minimal. If you expose an MCP server over a network (HTTP/SSE/WebSocket), add authentication and basic hardening (CORS allowlist, request size limits, timeouts, rate limits, and log redaction). See SECURITY.md.

License

The MCP project is transitioning from the MIT License to Apache-2.0. New code contributions are licensed under Apache-2.0, and documentation (excluding specifications) under CC-BY-4.0. Earlier contributions whose authors have not consented to relicensing remain under the MIT License. See LICENSE for the full terms.