Create Your Python Project
Objectives
- Create and activate a virtual environment using the correct platform commands.
- Run a typed Python function and install dependencies with the environment's interpreter.
- Record the selected package versions without assuming the combined stack is already tested.
1. Your first milestone: a project, not an agent yet
In about 20 minutes, you will create an isolated Python workspace, run a small function, install two course dependencies, and record what actually installed. You do not need a model, API key, cloud account, or running MCP server for this lesson. Package installation does require access to your configured package index.
A Python interpreter runs Python code. A module is a file you can import. A third-party package adds code installed separately from Python. A virtual environment gives this project its own interpreter entry point and installed packages, so another project's dependencies need not change yours. It is dependency isolation, not a security sandbox. [S1]
Use Python 3.11 or newer as the starting baseline: the supplied MCP installation documentation specifies 3.11+. That is a minimum starting point, not a guarantee that every newer interpreter and every package combination will work. Before proceeding, check the selected release's Python requirements and your actual installation results rather than assuming compatibility from the baseline alone. [S2]
Our design is deliberately small: two Python files for the first program and one helper to record the environment. We will postpone JSON and API requests until the next lesson.
Check yourself: Will creating a virtual environment automatically download a different Python version? No. The interpreter used to run venv determines the environment's Python version. [S1]
2. Create and activate the right environment
Open a terminal. These are terminal commands, not lines to enter at Python's >>> prompt. If you see that prompt, enter exit() first. Choose only the block for your platform.
macOS or Linux, Bash or Zsh:
python3 --version
mkdir agent-course
cd agent-course
python3 -m venv .venv
source .venv/bin/activate
Confirm the first command reports Python 3.11 or newer before creating the environment. If python3 selects an older interpreter, use an installed qualifying interpreter, such as python3.11, for both the version check and environment creation. venv does not upgrade Python. [S1]
Windows, PowerShell: this example deliberately selects an installed Python 3.11 through the Python launcher.
py -3.11 --version
mkdir agent-course
cd agent-course
py -3.11 -m venv .venv
.\.venv\Scripts\Activate.ps1
If you have a different qualifying version installed, use that launcher's version selector instead. If the launcher or selected Python is unavailable, install a supported Python interpreter before continuing; do not treat an unrecognized command as successful setup.
Windows, Command Prompt: use the same version-check, directory, and creation commands as above, but activate with:
.venv\Scripts\activate.bat
Activation selects the environment for the current terminal session; Unix and Windows use different activation scripts. [S1] If PowerShell blocks its script, do not weaken machine-wide execution policy for this lesson. You can use Command Prompt, or explicitly run .\.venv\Scripts\python.exe wherever subsequent commands say python. On macOS/Linux, the equivalent explicit path is .venv/bin/python.
After activation, run:
python --version
python -c "import sys; print(sys.executable); print(sys.prefix != sys.base_prefix)"
python -m pip --version
Expected checks, not a transcript from your machine: Python is 3.11+, the executable path points inside this project's .venv, the comparison prints True, and pip's location is inside .venv. Activation changes command lookup, so checking the interpreter is more reliable than trusting the prompt alone. [S1]
If pip is missing or environment creation reports a missing venv component, stop and repair your Python installation using your platform's installation guidance. Do not switch to a global or administrator pip as a workaround.
Check yourself: Why inspect sys.executable before installing anything? You want evidence of which Python the terminal will actually use.
3. Write a typed function and import it
Use a text editor to create greetings.py and main.py directly inside agent-course, not inside .venv. Copy the corresponding Python code examples below into those files. Save them with a .py extension, not .py.txt.
In greetings.py, def defines a reusable function. The name parameter receives an input, : str documents that the intended input is text, and -> str documents a text result. These are type hints, not automatic runtime input validation. The indented body uses return to send a value back to the caller. Our own explicit empty-input check raises ValueError; the type hints do not perform that check.
In main.py, from greetings import make_greeting imports the function from your neighboring file. import sys accesses Python's built-in system module; it needs no pip installation. Python's standard library includes system interfaces and small testing utilities, so not every import represents an external dependency. [S5]
Run this from the project root:
python main.py
Expected behavior for the supplied code: it prints Hello, builder! followed by your actual interpreter path. The assertion checks the returned string before printing. This checks one small piece of Python behavior; it does not exercise MCP or LangGraph.
Keep all four spaces at the start of each indented function-body line. The if __name__ == "__main__": guard makes main() run when the file is executed as a program, rather than automatically whenever another file imports it.
Try it: change the argument in main.py to " explorer " and also change the assertion to assert greeting == "Hello, explorer!". Predict the greeting, then run python main.py again: the function strips the surrounding spaces, so it prints Hello, explorer! followed by the interpreter path. If you change only the argument, the old assertion raises AssertionError before either print. Next, change the argument to " " and run again to observe the deliberate ValueError; the function raises it before reaching the assertion. Afterward, restore both the argument to " builder " and the assertion to assert greeting == "Hello, builder!", then rerun to confirm the original greeting. If importing greetings fails, check the file name, file extension, and that both files are in the project root.
4. Install course dependencies with this interpreter
Now add dependencies to the environment you just verified. We will request the MCP v2 API family described by the supplied documentation, rather than silently accepting a future major version. That documentation identifies v2 as its stable line and warns that v1 code needs migration. This version range is a lesson selection policy, not an exact tested pin. [S2]
python -m pip install "mcp[cli]>=2,<3" langgraph
python -m pip check
python -m pip show mcp langgraph
python -c "import mcp; import langgraph; print('Dependency imports passed')"
python -m pip runs pip through the interpreter named python; this keeps installation aligned with the program's interpreter. The quoted MCP requirement includes the optional CLI dependencies and limits resolution to the 2.x family. Exact selected versions will be recorded next. [S1][S2]
LangGraph's base package is installed separately. You do not need to install all of LangChain just to begin using LangGraph; provider integrations are separate packages and will be added when needed. [S9]
Interpret the evidence narrowly:
- Successful installation means pip found and installed a set of distributions for this environment.
- A successful
pip checkmeans installed packages' declared dependency requirements are satisfied, not that their behavior is correct together. - The import command is a basic smoke check, not a protocol or model test.
- None of these steps proves that a later MCP server, graph, and local model interoperate. Integration tests are a separate kind of evidence. [S8]
If pip reports no matching distribution, a Python-version mismatch, or conflicting requirements, keep the error. Check the selected Python version and release-specific package requirements. Do not remove the major-version constraint merely to get a successful install, and do not substitute older v1 imports into a v2 lesson. If the requested release family cannot be resolved, this dependency milestone is blocked; the standard-library function exercise can still run. [S2]
Check yourself: Does importing both packages prove a complete agent works? No: you have not created an MCP connection, run a graph, or called a model.
5. Record what installed and keep a reproducible layout
A dependency request expresses what you want; a snapshot records what you got. pip freeze produces requirements-format entries for installed dependencies, and pip install -r can request those recorded versions in another environment. [S1]
Create record_environment.py using the final code example, then run:
python record_environment.py
The helper uses sys.executable to run this same interpreter's pip. It writes requirements.txt in UTF-8 only after freeze succeeds, plus an environment.txt recording Python, platform, and the limited validation status. This avoids relying on different shells' output-file encoding behavior. Inspect the two generated files in your editor: use the actual package versions, never numbers copied from an illustrative tutorial. A freeze snapshot is not a cross-platform lockfile or proof of combined-stack compatibility. [S1][S9]
Your layout should now look like this; generated files appear only after the helper succeeds:
agent-course/
.venv/
greetings.py
main.py
record_environment.py
requirements.txt
environment.txt
README.md
.gitignore
Create README.md with your platform, Python version, chosen MCP major line, setup commands, and the checks you actually ran and their results. Explicitly record MCP + LangGraph + local model: not integration-tested yet. No local model was configured in this lesson. Do not change that status based only on installation or imports. A course release needs dependencies resolved together and compatibility tests before it can present a tested stack. [S9]
Create .gitignore with these lines as a project convention:
.venv/
__pycache__/
.env
Keep source and environment records in version control if you use it; do not commit the environment directory. Treat .env as a reserved local configuration file, not as another name for .venv. No secrets are needed here.
For a later recreation, make and select a fresh environment using the recorded interpreter version, then run:
python -m pip install -r requirements.txt
python -m pip check
python main.py
The requirements file does not install Python itself. Different operating systems or missing package artifacts may still prevent recreation, so record and investigate failures rather than claiming universal reproducibility. [S1][S9]
Check yourself: Which file records package versions, and which records Python and validation status? requirements.txt and environment.txt, respectively.
6. Exit check and next-session routine
Before moving on, verify these outcomes on your own computer:
- Environment: the interpreter check points inside
.venvand reports Python 3.11+. - Function and import:
python main.pyprints the greeting and your environment's interpreter path; the empty-input experiment raises the intended error. - Dependencies: installation, dependency checking, and the import smoke check completed. If not, mark this item blocked and retain the real error.
- Record:
requirements.txtcontains the versions that actually installed;environment.txtandREADME.mddistinguish basic checks from unperformed integration tests.
For a new terminal session, enter the project directory and repeat only the activation command for your shell, then check sys.executable. You do not recreate .venv on every visit. When finished, enter deactivate to undo activation in the current shell. Activation and deactivation change the shell's interpreter selection, not your source files. [S1]
Final self-test: Someone says, “I froze the dependencies, so the agent stack is tested.” Explain the missing step. A version snapshot records installation state; an integration test must actually exercise the components together. Neither your greeting assertion nor a successful import has done that. [S8][S9]
You now have the workspace for the next lesson, where ordinary Python values will become structured JSON data.
def make_greeting(name: str) -> str:
cleaned = name.strip()
if not cleaned:
raise ValueError("name must contain non-space text")
return f"Hello, {cleaned}!"
import sys
from greetings import make_greeting
def main() -> None:
greeting = make_greeting(" builder ")
assert greeting == "Hello, builder!"
print(greeting)
print(sys.executable)
if __name__ == "__main__":
main()
from pathlib import Path
import platform
import subprocess
import sys
def main() -> None:
project = Path(__file__).resolve().parent
snapshot = subprocess.run(
[sys.executable, "-m", "pip", "freeze"],
check=True,
capture_output=True,
text=True,
encoding="utf-8",
)
(project / "requirements.txt").write_text(
snapshot.stdout, encoding="utf-8"
)
details = (
f"Python: {platform.python_version()}\n"
f"Platform: {platform.system()} {platform.machine()}\n"
"MCP API family requested: 2.x\n"
"Validation: record actual command outcomes in README.md\n"
"MCP + LangGraph + local model: not integration-tested yet\n"
)
(project / "environment.txt").write_text(details, encoding="utf-8")
print("Wrote requirements.txt and environment.txt")
if __name__ == "__main__":
main()
Key takeaways
- The interpreter that runs venv determines the environment's Python version; activation does not upgrade Python. [S1]
- Use the activation script for your platform and verify sys.executable before installing dependencies. [S1]
- Use python -m pip so package installation targets the interpreter you intend to run. [S1]
- A typed function documents intended inputs and results; explicit checks, not type hints alone, reject invalid inputs.
- Select the MCP API family deliberately; v1 and v2 examples are not interchangeable. [S2]
- Record actual package versions and the interpreter, but distinguish installation and smoke checks from integration testing. [S1][S8][S9]
Common mistakes
- Installing packages globally because the terminal prompt looks correct.: Check sys.executable and python -m pip --version; both should point into the project's .venv before installation. [S1]
- Copying a Unix activation command into Windows PowerShell.: Use .\.venv\Scripts\Activate.ps1 in PowerShell, activate.bat in Command Prompt, or source .venv/bin/activate in Bash/Zsh. [S1]
- Expecting a type hint to validate every argument at runtime.: Treat hints as the intended contract. Add explicit checks or validation where the program must reject inputs.
- Saving greetings.py inside .venv or as greetings.py.txt.: Save it beside main.py in the project root, with the actual .py extension, then run from that directory.
- Dropping the MCP major-version constraint after an installation error.: Keep the real failure and inspect interpreter and release requirements. Do not mix v1 code with v2 documentation just to finish setup. [S2]
- Calling a frozen package list a tested agent stack.: Record only checks actually run. Later test the MCP connection, graph, and chosen model together before making a compatibility claim. [S8][S9]
References
- Virtual Environments and Packages, Python Software Foundation
- MCP Python SDK installation, Model Context Protocol
- Brief Tour of the Standard Library, Python Software Foundation
- Install LangGraph, LangChain
- Agent Evals, LangChain
See the full course: Building AI Agents with MCP and LangGraph: Local LLMs to Production