Data Engineering with Jupyter MCP
Build interactive Jupyter notebooks that query databases and visualize data using Cursor with MCP
Introduction
This project has been archived
We're no longer updating this project - we recommend checking out our active projects instead!
If you've already completed this project, don't worry! Your documentation is still available for you to check out and share.
If you have any questions, leave a question in our Discord and we'll get back to you ASAP!
⚡️ 30 second Summary
Imagine you have customer data in a database. You want to explore it - find patterns, test ideas, visualize trends. You could export CSVs, switch between SQL clients, copy results to spreadsheets... or you could work like data engineers do.
They use Jupyter notebooks to explore databases interactively. Write a query, see results instantly. Transform data with Python, visualize it with charts. Document your findings as you go. All in one place, all shareable with your team.
You'll build this workflow through Cursor's chat - connecting Jupyter notebooks directly to your database, running queries, and creating visualizations without juggling tools.
What you'll build
In this project, you'll use Jupyter notebooks to explore customer data from PostgreSQL and create visualizations with Matplotlib.
Why Jupyter notebooks?
Code is read more often than it's written. A few weeks from now, you'll ask yourself: "Why did I join these tables? Why filter values >10?" Comments help, but data analysis needs context, this could be tables, charts, and explanations.
Jupyter notebooks mix code, visualizations, and documentation in one place. This "literate programming" approach (popularized by Donald Knuth) is essential for data work where your source data shapes your decisions. Data teams use notebooks to explore databases, test ideas, and share findings with teammates.
You don't need any prior data engineering or Python experience. This project teaches you how Jupyter notebooks work, how to connect them to databases, and how to create visualizations that reveal insights in your data.
Not sure if this project is right for you? Check if it matches your goals
How you'll build it:
First, you'll build Jupyter notebooks by hand to understand how they work. Then, you'll use Cursor with MCP to manage your Jupyter notebooks through conversation.
By the end of this project, you'll have:
- A working Jupyter notebook connected to your database.
- Python code that queries and analyzes customer data.
- 💎 Secret Mission: A production-ready dbt model based on your notebook query.
If you're up for a bit of a challenge, quiz yourself on the key concepts up ahead in this project! Don't be too nervous, you'll also get a quiz at the end of this project, to recap what you've learned.
Want a complete demo of how to do this project, from start to finish? Check out our 🎬 walkthrough with Kahu 🎬
This project is part of a series:
- Part 1: PostgreSQL MCP (recommended)
- Part 2: DBT MCP (recommended)
- Part 3: You are here!
- Part 4: Grafana MCP
Connect Cursor to Jupyter
Time to connect Cursor to Jupyter notebooks! We'll set up the Jupyter MCP server so you can write Python code, query databases, and see results - all through conversation in Cursor.
In this step, get ready to:
- Add the Jupyter MCP server configuration to Cursor
- Verify the MCP connection is active
Check Your Current MCP Setup
Before we add Jupyter, let's see what MCP servers you already have configured.
- Open Cursor.
- Click the settings icon (gear icon) in the top right.
- Select Tools & MCP from the settings menu.
Now, look at your MCP servers list. What do you see?
✅ I see docker and postgres
Perfect! You already have Docker and PostgreSQL MCP servers configured (likely from the PostgreSQL MCP project).
❌ I don't see docker and postgres
No worries! Here's the fast-track setup (takes about 15 minutes). We'll get you set up with Docker, Postgres, AND Jupyter all at once.
What you'll set up:
- Docker Desktop + PostgreSQL container.
- uv package manager.
- MCP servers (Docker + Postgres).
- Demo data loaded.
1. Install Docker Desktop
First, check if you already have Docker installed.
- Open Terminal (Mac) or PowerShell (Windows).
- Run this command.
docker --version
✅ I see a version number
Perfect! Docker is already installed. Skip to step 2 below.
❌ Command not found
Let's install Docker Desktop:
🍎 macOS
- Download from docker.com/products/docker-desktop.
- Choose Apple Chip (M1/M2/M3) or Intel Chip based on your Mac.
- Drag Docker.dmg to Applications folder.
- Open Docker Desktop, accept terms, click Finish.
- Look for 🐳 whale icon in menu bar (means it's running).
🖼️ Windows
- Download from docker.com/products/docker-desktop.
- Run installer, accept defaults, restart computer when prompted.
- Open Docker Desktop, skip sign-in.
- Look for 🐳 whale icon in system tray (means it's running).
If you see WSL 2 errors: Open PowerShell as Admin, run wsl --install, restart computer.
Need help with Docker installation? Ask the community!
2. Install uv Package Manager
First, check if you already have uv installed.
- Run this command in terminal:
uv --version
✅ I see a version number
Great! uv is already installed.
Now create your project folder:
- Open Cursor (or download it if you don't have it).
- Select Open Project and create a new folder on your Desktop.
- Name the folder MCP-data-series.
❌ Command not found
Let's install uv:
- Open Cursor (or download it if you don't have it).
- Select Open Project and create a new folder on your Desktop called MCP-data-series.
- Open terminal in Cursor (Ctrl/Cmd + Shift + `).
🍎 macOS
🖼️ Windows
Run the install command for your OS:
🍎 macOS
- Run this command in terminal.
curl -LsSf https://astral.sh/uv/install.sh | sh
Then verify:
- Run this command in terminal.
uv --version
🖼️ Windows
- Run this command in terminal.
iwr https://astral.sh/uv/install.ps1 -UseBasicParsing | iex
Then verify:
- Run this command in terminal.
uv --version
If you get permission errors: Close terminal, right-click Cursor → Run as Administrator, try again.
You should see a version number (like uv 0.4.18).
Need help installing uv? Ask the community!
3. Create PostgreSQL Container + Load Data
- Run these commands in terminal one by one.
uv init
docker run -d --name pg-local -p 5432:5432 -e POSTGRES_USER=app -e POSTGRES_PASSWORD=app -e POSTGRES_DB=demo postgres:16
Wait 20 seconds for PostgreSQL to start up, then download and load data:
🍎 macOS
- Run these commands in terminal.
# Download demo data
curl -o demo_data.sql https://storage.googleapis.com/nextwork_course_resources/courses/ai/mcp-data-engineering/demo_data.sql
# Load into database
cat demo_data.sql | docker exec -i pg-local psql -U app -d demo
🖼️ Windows
- Run these commands in terminal.
# Download demo data
Invoke-WebRequest -Uri "https://storage.googleapis.com/nextwork_course_resources/courses/ai/mcp-data-engineering/demo_data.sql" -OutFile "demo_data.sql"
# Load into database
Get-Content demo_data.sql | docker exec -i pg-local psql -U app -d demo
You'll see SQL output scrolling by - that's 40,000+ rows being inserted!
4. Configure Docker and Postgres MCP Servers in Cursor
Let's set up Docker and Postgres MCPs. (We'll add Jupyter in the next section!)
- Click the settings icon (gear icon) in the top right of Cursor.
- Select MCP from the left sidebar.
- Click Add Custom MCP.
Your mcp.json file opens. Paste this config based on your OS:
🍎 macOS
{
"mcpServers": {
"docker": {
"command": "uv",
"args": ["run", "--with", "docker-mcp", "docker-mcp", "--access-mode=unrestricted"],
"env": { "DOCKER_HOST": "unix:///var/run/docker.sock" }
},
"postgres": {
"command": "uv",
"args": ["run", "--with", "postgres-mcp", "postgres-mcp", "--access-mode=unrestricted"],
"env": { "DATABASE_URI": "postgresql://app:app@localhost:5432/demo" }
}
}
}
🖼️ Windows
{
"mcpServers": {
"docker": {
"command": "uv",
"args": ["run", "--with", "docker-mcp", "docker-mcp", "--access-mode=unrestricted"],
"env": { "DOCKER_HOST": "npipe:////./pipe/docker_engine" }
},
"postgres": {
"command": "uv",
"args": ["run", "--with", "postgres-mcp", "postgres-mcp", "--access-mode=unrestricted"],
"env": { "DATABASE_URI": "postgresql://app:app@localhost:5432/demo" }
}
}
}
What does this configuration include?
- docker: Lets Cursor control Docker containers
- postgres: Lets Cursor query your PostgreSQL database
✅ You're all set! You now have the same setup as someone who completed the PostgreSQL MCP project.
What about the DBT MCP project?
The DBT MCP project introduces DBT (Data Build Tool) for transforming data. It's not required for this Jupyter project - you can skip it or come back to it later!
Continue below to add Jupyter to your configuration.
Add Jupyter MCP Configuration
Great! Now let's add Jupyter to your MCP configuration. Since you already have docker and postgres configured, we just need to add Jupyter.
- In the MCP settings menu (should still be open), click New MCP Server to open your mcp.json file.
Closed your settings?
No problem! Click the settings icon (gear icon) in the top right → select Tools & MCP → click New MCP Server.
💡 Have other MCP servers installed?
If you also see a dbt MCP server in your config, that's great! Keep it there. We'll be using it in the Secret Mission to transform your Jupyter analysis into a production-ready dbt model.
Your mcp.json should already have docker and postgres configured. Let's add the Jupyter configuration to your existing servers.
Add this below your existing MCP configs in the mcp.json file.
"jupyter": {
"command": "uv",
"args": [
"run",
"--with",
"mcp-jupyter",
"--with",
"jupyterlab",
"--with",
"jupyter-collaboration",
"--with",
"ipykernel",
"mcp-jupyter"
],
"env": {
"JUPYTER_PORT": "8888"
}
}
What does this Jupyter configuration mean?
- command: Uses uv to run the Jupyter MCP with its dependencies
- args: Installs required packages (mcp-jupyter for MCP integration, jupyterlab for the interface, jupyter-collaboration for sharing, ipykernel for running Python code)
- env: Sets the Jupyter server to run on port 8888
Your file should now include Docker, Postgres, and Jupyter.
Hint: Don't forget to add a comma!
When adding the Jupyter config to your mcp.json, make sure there's a comma (,) after the closing brace of your postgres MCP server. JSON requires commas between objects.
Save and Restart Cursor
Now that you've added Jupyter to your mcp.json, let's restart Cursor so it picks up the new configuration.
- Save the file with Cmd + S (Mac) or Ctrl + S (Windows).
- Quit Cursor completely (not just minimize!)
How do I quit Cursor?
In your menu bar, select:
- Mac: Cursor → Quit Cursor or press Cmd+Q
- Windows: File → Exit or press Alt+F4
- Reopen Cursor.
- Click the Settings icon and select MCP.
Verify All Three MCPs Are Connected
✅ All servers green
You should now see docker, postgres, and jupyter all with green indicators!
Nice work, everything's configured! Let's move on to the next step.
What about the DBT MCP?
If you see a dbt server too, that's fine! Keep it there - we'll use it in the Secret Mission. It won't interfere with this project.
🔴 Jupyter shows red
No worries - this is usually a quick fix! If Jupyter shows a red indicator:
- Check that you saved the mcp.json file correctly.
- Verify the JSON syntax is valid (no missing commas or brackets).
- Make sure uv is installed: run uv --version in terminal.
- Try restarting Cursor again.
Still red? Get help debugging or ask the NextWork community - we've all been here!
🔴 Other servers red
That's okay - these are from the PostgreSQL MCP project! If docker or postgres show red indicators:
- Review the PostgreSQL MCP project setup.
- Ensure Docker Desktop is running.
- Verify PostgreSQL container is running: docker ps.
- Check your mcp.json configuration.
Need help? Get debugging tips or reach out to the NextWork community - these issues are common and fixable!
Build and Run Your First Data Notebook
Great work! Cursor is now connected to Jupyter. Time to create your first Jupyter notebook that mixes code, results, and explanations in one place!
Think of Jupyter notebooks as living reports: you write Python queries, see results immediately, add explanations of what you found, and document your analysis journey. This isn't just running code - it's creating a story that others (and future you!) can understand.
In this step, get ready to:
- Create a notebook with code, explanations, and data
- Query your PostgreSQL database from Python
- See your analysis results in the browser
Create demo.ipynb
Let's build your first notebook. At the root directory of MCP-data-series:
- Create a new file: demo.ipynb (leave it empty for now).
What does .ipynb mean?
The .ipynb extension stands for "Interactive Python Notebook." It's the file format Jupyter uses to store notebooks with code, text, and outputs all together.
💡 How do I create a file in the IDE?
Find the file explorer in the left sidebar (shows your project files and folders). Right-click in any empty space to create a new file!
Build Your Computable Document
Nice! Your notebook file is created. Now let's build a computable document that mixes code, results, and explanations.
Let's build your first analysis document with three cells in the correct order:
First: Add context (Markdown cell)
Start by documenting what you're about to do and why - context comes FIRST!
- Open demo.ipynb in Cursor.
- Click + Markdown to add a markdown cell.
- Add this explanation.
# Customer Data Exploration
**Goal:** Connect to our PostgreSQL database and examine customer distribution
This notebook explores our e-commerce customer data to understand:
- How many customers we have
- What a typical customer record looks like
Why start with markdown?
A few weeks from now, you'll open this notebook and wonder: "What was I trying to find?" Starting with markdown documents your intent - the context that raw code can't convey.
Second: Install database driver (Code cell)
- Click the + Code button at the bottom of your markdown cell to add a code cell below.
- Add this code.
!uv pip install psycopg[binary]
Two types of cells
You've now added both types of cells that Jupyter notebooks use:
- Markdown cells: Hold formatted text (like the "Customer Data Exploration" heading you added). Use these to explain your code, add section headings, and describe results so the notebook reads clearly.
- Code cells: Run Python code (like the installation command above). When you run it, the result appears directly below that cell. This lets you test small pieces of code and see feedback right away!
This mix of explanations and executable code turns raw analysis into a readable story you and your team can follow!
💡 What does the ! do?
The ! at the start tells Jupyter to run this as a shell command rather than Python code. Any line starting with ! executes in your system terminal.
💡 What is psycopg[binary]?
psycopg is the Python library that lets your code connect to PostgreSQL. The bracketed extra, [binary], tells pip to install a prebuilt, ready-to-run package. Without [binary], the install might take longer or fail if your computer is missing developer tools.
Third: Query the database (Code cell)
Let's add code that connects to your PostgreSQL database and queries customer data!
import psycopg
conn = psycopg.connect(
host="[[YOUR_HOST="your-host"]]",
port=[[YOUR_PORT="port-number"]],
dbname="[[YOUR_DATABASE="database-name"]]",
user="[[YOUR_USER="username"]]",
password="[[YOUR_PASSWORD="password"]]"
)
cursor = conn.cursor()
cursor.execute("SELECT * FROM app.customers LIMIT 1")
row = cursor.fetchone()
print(row)
conn.close()
What does this code do?
Let's break down what each part does:
- import psycopg - Loads the PostgreSQL driver library
- conn = psycopg.connect(...) - Opens a connection to your database using your credentials
- cursor = conn.cursor() - Creates a cursor object that lets you run SQL queries
- cursor.execute("SELECT * FROM app.customers LIMIT 1") - Runs a SQL query to get one customer record
- row = cursor.fetchone() - Retrieves the query result
- print-statement - (Should) displays the customer data
- conn.close() - Closes the database connection when done
- Try fill in the placeholders in the code block yourself.
Feel free to check the hints below if you get stuck!
🚀 I don't want a hint
Now add this code to your notebook:
- In Cursor, click the + Code button at the bottom of your previous cell to add another code cell.
- Paste the Python code from above into the new cell.
🕺 I'd like a hint
Connection details from the PostgreSQL MCP project
- host → localhost (this computer)
- port → 5432 (standard PostgreSQL port)
- dbname → demo (your database name)
- user → app (your username)
- password → app (your password)
- Print statement → print(row) (displays the result)
Now add this code to your notebook:
- In Cursor, click the + Code button at the bottom of your previous cell to add another code cell.
- Paste the Python code from above into the new cell.
- Replace the placeholders with the values shown above.
- Save your notebook with Cmd + S (Mac) or Ctrl + S (Windows).
Perfect! Your notebook now tells a clear story - from setting up your database connection to querying actual customer data.
This is a computable document - code you can run AND a report you can read!
Set Up Your Python Environment
First, let's set up the Python environment for Jupyter:
- Open terminal in Cursor (Ctrl/Cmd + Shift + `).
- Run this command to check you're in your MCP-data-series folder.
pwd
I'm not in MCP-data-series!
If the terminal shows a different folder, you need to navigate there first. Get help navigating to your folder
- Run this command in terminal to add Jupyter and database packages.
uv add jupyterlab pandas "psycopg[binary]" matplotlib
What are these packages?
- jupyterlab: A web-based interface for creating and editing notebooks. After we install it, you'll access it through your browser.
- pandas: Python's data analysis library. It contains tools to load, clean, filter, group, summarize, and visualize data in Python. (We'll use this in the secret mission!)
- psycopg[binary]: PostgreSQL driver that lets Python talk to your database
- matplotlib: Python's plotting library for creating charts and visualizations
🙋♀️ Getting "no matches found" on macOS?
If you see zsh: no matches found: psycopg[binary] but the command still works, that's normal! It's just your shell complaining about the square brackets. The packages install successfully despite this warning.
Launch Jupyter Lab
Time to fire up the Jupyter Lab server!
🍎 macOS/Linux
- Run this command in terminal.
uv run jupyter lab --notebook-dir=$(pwd) --ServerApp.port=8888 --ServerApp.disable_check_xsrf=True --ServerApp.token='' --ServerApp.password=''
What does this command do?
This command uses uv to run Jupyter Lab with specific configurations:
- uv run jupyter lab - Starts the Jupyter Lab application using the uv package manager
- --notebook-dir=$(pwd) - Tells Jupyter Lab to open in your current folder
- --ServerApp.port=8888 - Sets Jupyter Lab to be accessible on port 8888 in your web browser
- --ServerApp.disable_check_xsrf=True - Turns off a security check that sometimes causes issues
- --ServerApp.token='' --ServerApp.password='' - Removes the need for a password or token to log in (makes it quicker to get started, but less secure for public access)
🖼️ Windows
- Run this command in terminal.
uv run jupyter lab --notebook-dir="$PWD" --ServerApp.port=8888 --ServerApp.disable_check_xsrf=True --ServerApp.token='' --ServerApp.password=''
What does this command do?
This command uses uv to run Jupyter Lab with specific configurations:
- uv run jupyter lab - Starts the Jupyter Lab application using the uv package manager
- --notebook-dir="$PWD" - Tells Jupyter Lab to open in your current folder
- --ServerApp.port=8888 - Sets Jupyter Lab to be accessible on port 8888 in your web browser
- --ServerApp.disable_check_xsrf=True - Turns off a security check that sometimes causes issues
- --ServerApp.token='' --ServerApp.password='' - Removes the need for a password or token to log in (makes it quicker to get started, but less secure for public access)
✅ Browser opened
Jupyter Lab should open automatically in your browser at http://localhost:8888.
You'll see the Jupyter Lab landing page showing your file explorer:
- In the left sidebar file explorer, double-click on demo.ipynb to open your notebook.
After selecting your notebook, you should see the Jupyter interface ready for editing:
❌ Browser didn't open
If the browser didn't open automatically:
- Look for a URL in the terminal output (usually http://localhost:8888).
- Copy and paste it into your browser.
- Or manually navigate to http://localhost:8888.
Need help opening Jupyter Lab in your browser?
If you see an error about port 8888 being in use:
- Check if you have another Jupyter instance running.
- Stop the other instance with Ctrl + C.
- Or use a different port: change 8888 to 8889 in the command.
Still having issues? Ask the community!
Run Your Notebook
Now let's execute each cell and see your computable document come to life! The first cell should already be selected (your markdown cell with "Customer Data Exploration").
- Click the ▶ Play button or ✓ tick button in the toolbar (or press Shift + Enter)
Markdown cells don't produce output
When you run a markdown cell, it just renders the formatted text - no output appears below. The cursor automatically moves to the next cell. This is normal!
Run the second cell (Install database driver)
The second cell should now be selected (the one with !uv pip install psycopg[binary]).
- Click the ▶ Play button or ✓ tick button again (or press Shift + Enter)
- Wait for the installation to complete
You should see output indicating psycopg was successfully installed.
Troubleshooting installation errors
If you see an error during installation:
- Make sure you're in the correct directory (MCP-data-series folder)
- Verify uv is installed: run uv --version in a terminal
- Try running the Jupyter Lab command again from the correct folder
Run the third cell (Query the database)
- Click the ▶ Play button or ✓ tick button once more (or press Shift + Enter)
✅ I see the query output
You should see a customer record printed below the cell!
Excellent! Your computable document is working:
- Context (markdown) explained what you're doing
- Code (install) prepared your environment
- Code (query) pulled real data from the database
- Results show what you found
This is the power of notebooks - mixing explanation, code, and results!
❌ Connection error
No problem - connection errors are common! If you see a connection error:
- Verify PostgreSQL is running: open a new terminal and run docker ps
- Check that pg-local container has status "Up"
- If stopped, start it: docker start pg-local
- Make sure the connection details match your setup (host, port, dbname, user, password)
- Try running the cell again
Still having connection issues?
Double-check that your PostgreSQL container is running with docker ps in a terminal. The STATUS should say "Up". If it says "Exited", start it with docker start pg-local and wait 10-15 seconds.
Need more help? Ask the community!
❌ Table not found error
This just means your database needs the demo data! If you see "relation app.customers does not exist":
- Your database doesn't have the demo data
- You need to load the sample data from the PostgreSQL MCP project
- Download demo_data.sql
- Load it using the command from the PostgreSQL MCP project setup
Need help loading data? Ask the community!
Visualize Insights That Numbers Can't Show
You've got customer data as text - rows and columns. But here's the thing: patterns hide in numbers. A list of countries and counts doesn't immediately show you distribution, outliers, or trends. That's where visualization comes in!
This is why notebooks are "computable documents" - some information is visual and interactive (charts, maps, plots). You can't convey "our customer base is evenly distributed globally" or "Korea leads but not by much" just from raw query results. You need to SEE it.
Let's use Jupyter MCP to create visualizations using Matplotlib through natural language - turning those numbers into insights you can actually see.
In this step, get ready to:
- Use Cursor to add new cells for visualization to your notebook
- Run the new visualization cells using Jupyter MCP
Use Cursor Chat to Create Visualizations
Now for the magic! ✨ Let's use Cursor's chat to create data visualizations through the Jupyter MCP.
- Open Cursor's chat (Ctrl+L or Cmd+L)
- Send this prompt:
Using the Jupyter MCP, create a new cell in demo.ipynb that installs matplotlib,
then create another cell that queries the top 10 countries by customer count from
app.customers and creates a bar chart visualization
Cursor will use the Jupyter MCP to create the cells. You'll see Cursor's response showing it's interacting with the Jupyter MCP:
Wow! Cursor just created two new cells - one to install matplotlib, another with the visualization code. No manual typing required!
Execute the Cells with MCP
Now let's have Cursor run those cells for you!
- In Cursor chat, send this prompt:
Run the last two cells in demo.ipynb
Cursor will use the Jupyter MCP to execute the cells. You'll see output showing the execution results:
Confirmation that cells executed successfully
Now check your visualization:
- Switch to your Jupyter Lab browser tab.
- Refresh the page.
- You should see a beautiful bar chart!
✅ Chart displayed
Now you can SEE the insights! 📊
Look at that chart - the distribution is surprisingly balanced! Korea leads, but the top 10 countries are all within a similar range. This tells you that your customer base is geographically diverse, not concentrated in one region.
This is why visualizations are essential for computable documents - they reveal insights that numbers alone cannot convey.
Add a Markdown Cell to Document Your Finding
Let's document what the visualization revealed. In Cursor:
- Click + Markdown to add a new markdown cell below the chart
- Write your observation:
## Finding: Balanced Global Distribution
The visualization reveals that our customer base is **evenly distributed** across countries. Korea leads with ~18 customers, but all top 10 countries are within a similar range (12-18). This suggests:
- Good geographic diversity
- No over-reliance on a single market
- Opportunity to understand: Why is distribution so balanced?
This is the essence of computable documents - mixing code, visuals, and insights into a narrative!
❌ MCP didn't work
If Cursor didn't create the cells or you got an error:
Check your Jupyter MCP is connected:
- In Cursor, go to Settings → MCP
- Verify the jupyter server shows a green indicator
- If red, restart Cursor completely
Make sure Jupyter Lab is running:
- Check your terminal - you should see Jupyter Lab output
- The browser should show Jupyter Lab at http://localhost:8888
- If not running, restart with the command from Step 3
Try the prompt again:
- Make sure you're asking Cursor to work with demo.ipynb specifically
- The Jupyter MCP needs the notebook file to be open or specified
Fallback: Manual approach
If the MCP still isn't working, you can manually create the cells in Jupyter Lab browser like you did in Steps 2-3. Ask for help with the visualization code
Still stuck? Ask the community!
Enhance Your Visualization with Cursor
Now let's use Cursor chat again to improve the chart.
- In Cursor chat, send this prompt:
Make the bar chart more professional by adding a color gradient,
increasing the figure size, and adding grid lines.
Then run the updated visualization cell.
Cursor will update the visualization cell code and execute just that cell (not the entire notebook).
Check your enhanced visualization:
- Switch to your Jupyter Lab browser tab.
- Refresh the page.
- You should see the enhanced chart with professional styling!
Experiment with Cursor Chat
Now that you've seen the power of Jupyter MCP, try asking Cursor to create and run more analyses:
- "Add a cell that shows the top 5 products by price and run it"
- "Create a pie chart showing customer distribution instead of a bar chart and execute the cell"
- "Query orders data and show total sales by month, then run the query"
The more you experiment, the more you'll see how MCP accelerates your data exploration workflow!
The MCP advantage
Jupyter notebooks are built for iterative exploration - test a query, see results, refine, repeat. MCP supercharges this workflow by letting you create queries, run cells, and iterate through conversation. You stay focused on exploring your data instead of managing the notebook interface!
Secret mission
Ready to level up? This section is for those who want to take their skills further.
You'll transform your Jupyter exploration into a production-ready dbt model that runs on a schedule and can be queried by your entire team!
Transform Your Analysis into Production
Clean Up Your Resources
Clean Up Your Resources
Nice work completing this project! Let's clean up the resources we created.
Resources to delete:
- Stop the Jupyter Lab server
🍎 macOS/Linux
- Press Ctrl + C in the terminal where Jupyter Lab is running.
- When prompted, press y to confirm shutdown.
🖼️ Windows
- Press Ctrl + C in the terminal where Jupyter Lab is running.
- When prompted, press y to confirm shutdown.
- If that doesn't work, press Ctrl + Break or close the terminal window.
- Close your browser tab with Jupyter Lab
Keep PostgreSQL running
If you plan to continue with more MCP data engineering projects, you can leave the PostgreSQL container running.
Stop PostgreSQL
If you're done with the database:
docker stop pg-local
You can restart it later with docker start pg-local.
Remove PostgreSQL completely
If you want to completely remove the container and its data:
docker stop pg-local
docker rm pg-local
Warning: This deletes all data in the container. You'll need to recreate it and reload data if you want to use it again.
What's the difference between stop and remove?
docker stop pauses the container - it keeps your data and you can restart it later with docker start. docker rm permanently deletes the container and all its data. Only use rm if you're completely done with the project.
That's a wrap!
That's a wrap!
You did it! 🎊 You've built interactive Jupyter notebooks that connect to your database and create data visualizations.
What you learned:
- 📓 How to create and run Jupyter notebooks
- 🔌 Connecting Python applications to PostgreSQL databases
- 📊 Querying databases with SQL from Python
- 📈 Creating data visualizations with Matplotlib
- 🎨 Best practices for presenting data visually
- 💬 Using MCP to manage notebooks through natural language
Ready to quiz yourself? 💪
p.s. Does it say "Still tasks to complete!" at the bottom of the screen?
This means you still have screenshots left to upload, or questions left to answer!
- Press Ctrl+F (Windows) or Command+F (Mac) on your keyboard
- Search for the text Return to later
- Jump straight to your incomplete tasks!
🙋♀️ Still stuck? Ask the community!
Note
If you're EVER stuck - ask the NextWork community. Students like you are already asking questions about this project.