Skip to content

Choose a maintained SDK

  • Lesson 7
  • 45 min
  • Module 3: Build and inspect a local server

What you will be able to do

Choose the library that will speak MCP for your server, and make the choice repeatable. You check that the SDK is official, that it speaks the revision you chose and that it is still maintained. Then you install it at an exact version in a fresh environment, and prove that the environment works.

Before you startWhat to know and to have readyAbout 45 minutes

What you need to know

Your project

  • ~/projects/support-mcp at the end of Module 2, with the capability contracts in support_mcp/contracts.py. With the virtual environment active, python -m pytest -q prints 20 passed. If your project is broken, copy the snapshot end-of-m02 (see Reset at the end of this lesson).
  • An internet connection: the packages take about 85 MB on disk. No account and no key.

Imagine a trip to another country. Your laptop charger has one kind of plug, and the wall sockets there have another. You need an adapter.

You do not buy the first adapter that you see. First, you check the standard: the country uses a certain socket type, so the adapter must fit it. Then you check the maker: a known brand that still sells spare parts is safer than an unknown one. You write down the exact model, so you can buy the same one again. And you test it at home, with your own laptop, before you leave.

Four checks: the standard, the maker, the exact model and a test at home. Choosing an SDK for MCP needs the same four.

The problem: “I found a package called mcp-something”

Section titled “The problem: “I found a package called mcp-something””

Tomás wants to start the server today. He searches the package index for “mcp server python” and finds several packages. One has a nice README. He shows it to Amira.

Amira asks four questions. Who publishes it? Which revision of the protocol does it speak? When was its last release? And what will pip install give us next month?

Tomás cannot answer any of them from the README. The example in it starts with an initialize request and the revision 2025-06-18. You saw in Version awareness that this is the older handshake. The package might still work, because the official SDK accepts older clients. But nobody knows if it will receive fixes, or if it will ever speak 2026-07-28.

The risk is not only the protocol. A server is a door to Larkfield’s tickets. If the library that opens that door has a security bug, someone must fix it quickly. A library with no release for a year gives no such promise.

The idea: four questions before you choose

Section titled “The idea: four questions before you choose”

An SDK (software development kit) is the library that writes and reads MCP messages for you. Your code says “this function is a tool”, and the SDK turns it into the right messages. So the SDK decides which protocol revision your server speaks, and how it answers mistakes.

Before you depend on an SDK, ask four questions. They match the travel adapter:

  1. Is it official? The MCP project lists its official SDKs, one for each language, on modelcontextprotocol.io. Each one has a tier, a published level of support. Tier 1 means full support of the protocol and fixed response times.
  2. Does it speak your revision? The SDK’s release notes, or a short script, tell you which revisions it speaks.
  3. Is it maintained? Look at its release history. Regular releases mean that someone fixes bugs and follows the protocol.
  4. Is it pinned and tested here? Install an exact version in a fresh environment, and run your tests.
Four boxes in a row, each a question with Larkfield's answer below it. 1. Is it an official SDK? modelcontextprotocol.io lists the Python SDK in Tier 1: the full protocol, triage in 2 business days. 2. Does it speak your revision? mcp 2.3.0 speaks 2026-07-28, and accepts the older handshake of 2024-11-05 to 2025-11-25. 3. Is it maintained? 36 releases in the 12 months up to 2.3.0, the newest. The 1.x line is in maintenance. 4. Is it pinned and tested here? mcp==2.3.0 in requirements.txt, a fresh venv, pip check OK, python -m pytest -q: 20 passed. A red box below: a no anywhere means choose another SDK, or write down the gap and the work it costs, for example a community SDK with no release in a year, or one that knows only 2025-06-18.
The four questions, with the answers for Larkfield's server. A single no is a reason to stop and think.
Text description of the diagram

Four questions, each with Larkfield’s answer:

  1. Is it an official SDK? modelcontextprotocol.io lists the Python SDK in Tier 1: the full protocol, and issue triage within 2 business days.
  2. Does it speak your revision? mcp 2.3.0 speaks 2026-07-28, and accepts the older handshake of 2024-11-05 to 2025-11-25.
  3. Is it maintained? 36 releases in the 12 months up to 2.3.0, which is the newest. The 1.x line is in maintenance.
  4. Is it pinned and tested here? mcp==2.3.0 in requirements.txt, a fresh virtual environment, pip check reports no problem, and python -m pytest -q prints 20 passed.

A “no” anywhere: choose another SDK, or write down the gap and the work it costs. Two examples: a community SDK with no release in a year, or one that knows only revision 2025-06-18.

The MCP project publishes a list of official SDKs. When this course was written, it listed ten languages. TypeScript, Python, C#, Go, Rust and Ruby were in Tier 1, and Java in Tier 2. Swift, PHP and Kotlin were in Tier 3. Tiers can change, so check the current page before you choose.

The project’s tier rules make each tier concrete:

Tier 1: fully supported Tier 2: working toward full support Tier 3: experimental
Automated conformance tests 100% pass 80% pass no minimum
New protocol features before the new revision is released within 6 months no commitment
Issue triage within 2 business days within a month no requirement
Critical bug fix within 7 days within two weeks no requirement
Stable release required, with clear versioning at least one not required

The conformance tests are a shared test suite. It sends standard messages to an SDK and checks its answers. A Tier 1 SDK must pass all of them. This gives you a promise that you cannot get from a README.

For Larkfield, the answer is easy. The server is in Python, and the official Python SDK is in Tier 1. Its package on PyPI, the Python package index, has the short name mcp. Its licence is MIT, so Larkfield may use it in its own product.

You chose revision 2026-07-28 in Module 1, because it is the current revision. The SDK must speak it. Your project already has a script that asks the installed SDK, scripts/versions.py. You run it in the steps below. It prints two lines that answer this question:

newest revision the SDK speaks: 2026-07-28
older revisions it still accepts (initialize handshake): 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25

So SDK 2.3.0 answers both a current client and an older one. This matters for Larkfield. Some AI applications that the staff use may still send the older initialize handshake, and the server must not refuse them.

A maintained library has a release history that you can see. PyPI keeps the date of every release. Here is the history of the mcp package, drawn from PyPI’s data:

A timeline from June 2025 to October 2026 with three rows of dots, one dot per release of the mcp package on PyPI. Row 1.x: many dots from June 2025 to December 2025, then fewer: January, April, May, June, July, August and September 2026; the last is 1.30.0. Row 2.x tests: six hollow dots from June to late July 2026, the first labelled 2.0.0a1. Row 2.x: 2.0.0 on the same day as the dashed line for revision 2026-07-28, then four more dots up to 2.3.0 in October 2026, labelled this course. A second dashed line marks revision 2025-11-25. A note: each dot is one release of the official MCP Python SDK on PyPI, 36 in the 12 months up to 2.3.0; 1.x still gets releases after 2.0.0; hollow dots are the alpha, beta and release-candidate tests of 2.0.0.
Every release of the official Python SDK from June 2025 on. The version 2.0.0 came out on the same day as revision 2026-07-28.
Text description of the diagram

One dot per release of the mcp package on PyPI, from June 2025 to October 2026, in three rows:

  • 1.x: many releases from June to December 2025, then about one a month in 2026. The newest is 1.30.0, in September 2026.
  • 2.x tests: six test releases (alpha, beta and release candidate) from June to late July 2026. The first is 2.0.0a1.
  • 2.x: 2.0.0 on 2026-07-28, the same day as revision 2026-07-28. Then 2.0.1, 2.1.0, 2.1.1, 2.2.0 and 2.3.0 (October 2026), the version of this course.

Dashed lines mark revisions 2025-11-25 and 2026-07-28. In the 12 months up to 2.3.0, PyPI shows 36 releases.

Read the picture from left to right. Releases came every week or two in 2025. Test versions of 2.0 appeared from June 2026, so people could try the new major version early. Version 2.0.0 came out on the same day as the new revision: the maintainers prepared it before the revision was final. That is the Tier 1 promise in practice.

Also notice the 1.x row. It did not stop at 2.0.0: 1.29.0, 1.29.1 and 1.30.0 came later. The 1.x line is in maintenance. It gets critical bug fixes and security fixes, so older projects stay safe, but new protocol work goes into 2.x. This is why old tutorials still work for a while, and why you should not start a new project on 1.x.

You can see the same list in a terminal. python -m pip index versions mcp prints every version that PyPI has, newest first. When this course was written, the list started with 2.3.0, 2.2.0, 2.1.1, 2.1.0, 2.0.1, 2.0.0, 1.30.0, ….

The last check is yours. A pin is an exact version in your requirements: mcp==2.3.0, not mcp or mcp>=2. With a pin, every installation of the project gets the same SDK. Without one, pip installs the newest version on the day of the installation. Your server would change without a single change to your code.

Your project already pins the SDK, from Version awareness:

requirements.txt
# The MCP Python SDK. It brings Starlette, uvicorn, httpx2, pydantic, PyJWT and cryptography.
mcp==2.3.0
PyJWT[crypto]==2.15.1
requirements-dev.txt
-r requirements.txt
pytest==9.1.1
ruff==0.17.0

requirements.txt holds what the server needs to run. requirements-dev.txt adds the tools for development: pytest for the tests, and ruff, which checks the code style. Its first line, -r requirements.txt, includes the other file, so one command installs both.

A tested environment is a fresh virtual environment, built only from these files, in which the tests pass. “Fresh” matters. An old environment can hold packages from experiments, and they hide a missing line in the requirements. So you build a new one, and you prove it.

  1. Open a terminal in your project folder, ~/projects/support-mcp. If a virtual environment is active, leave it:

    Terminal window
    deactivate

    If no environment is active, the command prints an error. That is fine.

  2. Rename the old environment, so you can go back to it:

    Terminal window
    mv .venv .venv-old
  3. Make a new environment with Python 3.12, and activate it:

    Terminal window
    python3.12 -m venv .venv
    source .venv/bin/activate

    Check it: python --version prints Python 3.12.13, or another 3.12 release.

  4. Install the pinned requirements:

    Terminal window
    python -m pip install -r requirements-dev.txt

    The last line names every package that pip installed. It starts like this:

    Successfully installed PyJWT-2.15.1 annotated-types-0.8.0 anyio-4.15.1 attrs-26.1.0 cffi-2.1.1 click-8.5.0 cryptography-50.0.2 …

    The full line names 34 packages. Among them are mcp-2.3.0 and mcp-types-2.3.0, the SDK and its message types.

  5. Look at the SDK that you installed:

    Terminal window
    python -m pip show mcp
    Name: mcp
    Version: 2.3.0
    Summary: Model Context Protocol SDK
    Home-page: https://modelcontextprotocol.io
    Author: Model Context Protocol a Series of LF Projects, LLC.
    Author-email:
    License: MIT
    Location: …/support-mcp/.venv/lib/python3.12/site-packages
    Requires: anyio, httpx2, jsonschema, mcp-types, opentelemetry-api, pydantic, pyjwt, python-multipart, sse-starlette, starlette, typing-extensions, typing-inspection, uvicorn
    Required-by:

    The author is the MCP project, so this is the official package. Requires lists the 13 packages that the SDK itself needs.

  6. Check that the installed packages fit together:

    Terminal window
    python -m pip check
    No broken requirements found.
  7. Ask the SDK which revisions it speaks:

    Terminal window
    python -m scripts.versions
    specification revision (this project): 2026-07-28
    MCP Python SDK (pinned): 2.3.0
    MCP Python SDK (installed): 2.3.0
    newest revision the SDK speaks: 2026-07-28
    older revisions it still accepts (initialize handshake): 2024-11-05, 2025-03-26, 2025-06-18, 2025-11-25
    Python: 3.12.13
  8. Run the tests:

    Terminal window
    python -m pytest -q
    .................... [100%]
    20 passed in 1.64s

    Your time differs. The count must be 20 passed.

  9. If every step passed, delete the old environment:

    Terminal window
    rm -rf .venv-old

You now have the four answers in writing. The SDK is official (step 5), it speaks your revision (step 7), and it is pinned and tested (steps 4, 6 and 8). The release history answered the remaining question.

Count again: your requirements pin 4 packages, mcp, PyJWT, pytest and ruff. pip installed 34. The other 30 came with them, and pip chose their versions inside ranges that the SDK allows. For example, the SDK asks for anyio>=4.9, and pip installed anyio-4.15.1, the newest version on that day.

So an installation next month may get a newer anyio, with the same mcp==2.3.0. Most of the time this is harmless, because these ranges exist to allow fixes. Rarely, a newer package breaks something. Your tests are the safety net: run them after every fresh installation.

Some teams also freeze every version. python -m pip freeze prints all 34 packages with exact versions, and they keep that list in a file. This course does not, to keep the project simple. For a server in production, it is a good choice, because the same list always gives the same environment.

Amira adds three sentences to the project’s notes, so that a later developer understands the choice:

We use the official MCP Python SDK, mcp==2.3.0 (Tier 1, MIT), because it speaks revision 2026-07-28 and accepts the handshake of older clients. We move to a newer SDK version only on a branch, after we read its release notes and run all tests. We do not use SDK 1.x, which is in maintenance, or community packages, unless the official SDK cannot do something we need.

Tomás asks: “So the package I found is bad?” Amira answers: “Not bad, but unknown. If we ever need it, we answer the same four questions for it, and write down the gap.”

When to choose this way, and what it costs

Section titled “When to choose this way, and what it costs”

Use the four questions for every library that speaks to the outside world for you: an MCP SDK, an HTTP client, a database driver. They take a few minutes, and they prevent a whole class of surprises.

The costs are small but real:

  • Upgrades are your job. A pin never moves by itself. Plan a short review when a new SDK version appears, and read its release notes. A new major version, such as 1.x to 2.x, renames things and needs real work.
  • A fresh environment takes time. Here it took a few seconds, because pip had the files in its cache. The first time, it downloads about 85 MB.
  • An official SDK is not a security review. It speaks the protocol correctly. Whether the caller may read a ticket is still your code’s decision, from Module 5 on.

Common mistake

No matching distribution found for mcp==2.3.0

Symptom: the installation stops at the first package:

ERROR: Could not find a version that satisfies the requirement mcp==2.3.0 (from versions: none)
ERROR: No matching distribution found for mcp==2.3.0

Cause: the environment uses a Python that is too old. On macOS, /usr/bin/python3 is Python 3.9.6, and the SDK needs Python 3.10 or later. pip hides every version that does not fit, so it says “from versions: none”.

Fix: delete .venv, and make it again with python3.12 -m venv .venv (Windows: py -3.12 -m venv .venv). Check with python --version before you install.

Common mistake

error: externally-managed-environment

Symptom: pip install refuses to run:

error: externally-managed-environment
× This environment is externally managed
╰─> To install Python packages system-wide, try brew install
xyz, where xyz is the package you are trying to
install.

Cause: no virtual environment is active, so pip tried to install into the Python that Homebrew manages. Homebrew protects it, and that is good: system tools depend on it.

Fix: activate the project’s environment (source .venv/bin/activate; Windows: .venv\Scripts\Activate.ps1), then install again. Never add --break-system-packages to make the message go away.

Reset. If your project is broken, keep your files and start from the snapshot. Rename your folder to support-mcp-old. Then copy nextia-learning-labs/C28/snapshots/end-of-m02 to support-mcp, as in Where MCP fits, and do the steps of this lesson again.

Check your understanding

Name the four questions that you ask before you depend on an MCP SDK, and give Larkfield's evidence for each one.

Show the answer
  1. Is it official? The MCP project lists the Python SDK, package mcp, in Tier 1. pip show mcp names the MCP project as the author.
  2. Does it speak your revision? python -m scripts.versions prints that SDK 2.3.0 speaks 2026-07-28 and accepts the handshake of four older revisions.
  3. Is it maintained? PyPI shows 36 releases in the 12 months up to 2.3.0. Version 2.0.0 came out on the day of revision 2026-07-28.
  4. Is it pinned and tested here? mcp==2.3.0 is in requirements.txt. A fresh environment passes pip check, and python -m pytest -q prints 20 passed.

Check your understanding

Predict: a teammate changes the line in requirements.txt from mcp==2.3.0 to mcp, with no version. Today, a fresh installation gives the same result. What can happen in three months, and which script or test tells you?

Show the answer

Without a pin, pip installs the newest mcp on the day of each installation. In three months that may be a newer version, perhaps a new major version with renamed parts. The server code does not change, but its behaviour can. python -m scripts.versions would print a WARNING, because the installed version differs from SDK_VERSION in support_mcp/__init__.py. The test test_the_installed_sdk_is_the_pinned_one would fail. Keep the pin, and move it on purpose.

Check your understanding

Practical check: build a fresh environment from requirements-dev.txt. What do pip check and python -m pytest -q print, and how many packages did pip install?

Show the answer

pip check prints No broken requirements found. and python -m pytest -q ends with 20 passed. The line Successfully installed … names 34 packages: the 4 that the requirements pin, and 30 that came with them. If the test count differs, check that your project is at the end of Module 2. Then check that the environment is the new one: python -m pip show mcp must print Version: 2.3.0.

Recap

  • An SDK writes and reads the protocol’s messages for you, so it decides which revision your server speaks.
  • Ask four questions. Official: the MCP project’s list, Tier 1 for Python. Your revision: 2.3.0 speaks 2026-07-28. Maintained: 36 releases in 12 months. Pinned and tested: mcp==2.3.0, a fresh environment, 20 passed.
  • A pin fixes the SDK, not the 30 packages that come with it. Run the tests after every fresh installation.
  • SDK 1.x is in maintenance. Recognize it in old tutorials, and do not start new work on it.

Your project has a fresh, tested environment. Next, you look at what the SDK writes for you: the JSON-RPC messages.

Next: JSON-RPC messages