Module6-New2
In Module 6, you will learn the fundamentals of Python, a popular scripting language, and Regular Expressions, which give you power in text processing.
This article contains your assignments for Module 6.
Learning Goals
- Regular Expressions
- Python
- MCP Fundamentals
Using the Wiki
Text enclosed by < and > should be replaced by content unique to you.
Example
$ sudo useradd -r -m -c "<My Full Name>" <usernameHere>
becomes
$ sudo useradd -r -m -c "Zach Cohn" zcohn
Reading
The following articles on the online class wiki textbook contain information that will help you complete the assignments.
Individual Assignments
Learn Python and Regular Expressions
Up to this point in CSE 3300, you have used two programming languages: PHP and JavaScript. In Module 6, you will learn a new language: Python.
Before starting this assignment review:
You should use Python version 3 or greater.
Write some Regular Expressions
Please write regular expressions that do each of the following:
- Match the substring "hello world"
- Match strings containing three or more consecutive vowels
- Match a flight code of format AA####
Save them as:
regex1.txt
regex2.txt
regex3.txt
Baseball Stats Counter
The St. Louis Cardinals are the most legendary baseball team in the national league.
In this exercise you will create a Python script that reads box scores from a file and computes the Cardinals' players' batting averages.
Input
Sample input files may be found here:
http://classes.engineering.wustl.edu/cse330/content/cardinals/
Output
Each line in the output should have the format:
XXX: #.###
Players should be sorted by batting average.
Baseball Stats MCP Extension
This project builds a custom MCP server that lets Claude Desktop explore St. Louis Cardinals batting data.
Goal
You will build a Python MCP server that:
- reads Cardinals batting averages
- lists team rosters
- returns top hitters
- allows player search
- runs inside Docker
- connects to Claude Desktop
Project Structure
cardinals-mcp/
├── Dockerfile
├── cardinals_server.py
├── requirements.txt
└── data/
├── cardinals-1930.txt
└── cardinals-1940.txt
Step 1: Prerequisites
Install:
- Docker Desktop
- Claude Desktop
Step 2: Create the Files
cardinals_server.py
import os
import sys
import re
from datetime import datetime
from mcp.server.fastmcp import FastMCP
# Initialize MCP server
mcp = FastMCP("CardinalsMCP")
# Data file paths
DATA_DIR = os.path.join(os.path.dirname(__file__), "data")
CARDINALS_1930_FILE = os.path.join(DATA_DIR, "cardinals-1930.txt")
CARDINALS_1940_FILE = os.path.join(DATA_DIR, "cardinals-1940.txt")
# ==== Helper Functions (You DO NOT need to use these) ====
def load_cardinals_data():
"""Load Cardinals player data from both 1930 and 1940 files."""
data = {"1930": [], "1940": []}
for year, file_path in [("1930", CARDINALS_1930_FILE), ("1940", CARDINALS_1940_FILE)]:
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
data[year] = parse_player_data(content)
except FileNotFoundError:
logger.warning(f"Data file not found: {file_path}")
except Exception as e:
logger.error(f"Error loading {year} data: {e}")
return data
def parse_player_data(content):
"""Parse player data from the simplified Cardinals text files."""
players = []
for line in content.split('\n'):
line = line.strip()
if not line or line.startswith('#'):
continue
if ':' in line:
parts = line.split(':')
if len(parts) == 2:
name = parts[0].strip()
try:
batting_avg = float(parts[1].strip())
players.append({
'name': name,
'batting_average': batting_avg
})
except ValueError:
continue
return players
def get_all_players(data):
players=set()
for year_data in data.values():
for player in year_data:
players.add(player['name'])
return sorted(list(players))
def get_player_by_name(data, player_name):
player_data=[]
for year,year_data in data.items():
for player in year_data:
if player['name'].lower()==player_name.lower():
player_data.append({
'year':year,
'name':player['name'],
'batting_average':player['batting_average']
})
return player_data
# ==== MCP Tools ====
@mcp.tool()
async def hello(name: str = "world") -> str:
return f"Hello CSE 3300 Student, {name}!"
@mcp.tool()
async def get_player_stats(player: str = "") -> str:
# TODO
@mcp.tool()
async def get_team_roster(year: str = "1930") -> str:
# TODO
@mcp.tool()
async def get_top_players(year: str = "1930", limit: int = 10) -> str:
# TODO
@mcp.tool()
async def search_players(search_term: str = "") -> str:
# TODO
if __name__=="__main__":
logger.info("Starting Cardinals Historical Data MCP server...")
try:
mcp.run(transport="stdio")
except Exception as e:
logger.error(f"Server error: {e}", exc_info=True)
sys.exit(1)
Grading
We will be grading the following aspects of your work. There are 50 points total.
Assignments (including code) must be committed to Github by the end of class on the due date (commit early and often). Failing to commit by the end of class on the due date will result in a 0.
Upload your baseball code and a file with your Regular expressions.
- Regular Expressions (15 Points):
- Your regex files should contain your regex (with no delimiters or flags) and nothing else.
- Regular Expression 1 Correct and saved in a file named
regex1.txt(5 points) - Regular Expression 2 Correct and saved in a file named
regex2.txt(5 points) - Regular Expression 3 Correct and saved in a file named
regex3.txt(5 points)
- Baseball Stats Counter (25 Points):
- Solution is written entirely in Python and saved in a file named
baseball.py(5 points)- Note: Failing to write your code in Python 3 will result in losing, at a minimum, points for this category.
- Correct usage of one or more regular expressions to parse and extract data from each line of the input file (5 points)
- Note: You should not be using
str.splitto extract data.
- Note: You should not be using
- Script prints a usage message if a command line argument is not present (3 points)
- Note: For an example of a usage message, see https://en.wikipedia.org/wiki/Usage_message#Examples
- Output is correct for all test cases (12 points)
- This includes sorting and rounding.
- Solution is written entirely in Python and saved in a file named
- Baseball Stats MCP Extension (10 Points):
- Docker image builds successfully without errors (5 points)
- MCP server (`cardinals_server.py`) loads player data and returns correct results.
- Includes at least 2 MCP tools (3 points)
- Each tool must function correctly and return expected output through Claude Desktop.
- README includes 3 different example prompts used in Claude (2 points)
- Each example should show the prompt you asked and the MCP’s response.
- Docker image builds successfully without errors (5 points)
--- NEW -----
Verify Your MCP Server Works
Before connecting Claude Desktop, verify that your MCP server runs correctly.
Run your container manually:
docker run --rm -it cardinals-mcp-server:latest
If everything is working correctly, you should see a startup message similar to:
Starting Cardinals Historical Data MCP server...
If the container exits with an error, fix the issue before continuing.
You can stop the container with:
Ctrl+C
Do not attempt to connect Claude until the container runs successfully.
Common Setup Mistakes
If Claude cannot see your MCP server, check the following:
Docker image was not built
You must run:
docker build -t cardinals-mcp-server:latest .
before attempting to run the container.
Container name mismatch
The Docker image name in your Claude configuration must match the image name used during the build step.
Example:
docker build -t cardinals-mcp-server:latest .
must match:
"args": [
"run",
"--rm",
"-i",
"cardinals-mcp-server:latest"
]
Claude Desktop was not restarted
After editing the MCP configuration file, completely quit and reopen Claude Desktop.
The container exits immediately
This usually means your Python script crashed. Run the container manually to view the error:
docker run --rm -it cardinals-mcp-server:latest
What Claude Is Actually Doing
When you ask Claude a question such as:
Use CardinalsMCP to list the top 10 hitters from 1940.
the following process occurs:
User Prompt
↓
Claude reads the prompt
↓
Claude decides which tool to use
↓
Claude calls the MCP server
↓
Docker launches your container
↓
Your Python tool runs
↓
The results are returned to Claude
Claude never directly runs your Python code.
Your MCP server runs the code and sends the results back to Claude.
Debugging Your MCP Server
If Claude does not return results, try the following:
Step 1: Verify the container runs
docker run --rm -it cardinals-mcp-server:latest
Step 2: Verify your Python script loads
Your container should print a startup message when it launches.
Step 3: Verify tools exist
Claude should display available tools in the MCP indicator inside the chat interface.
Step 4: Check Claude configuration
Ensure the file:
claude_desktop_config.json
contains your MCP server configuration.
If necessary, restart Claude Desktop.