Data Engineering with Postgres & Docker MCP
Build a PostgreSQL database with Docker and chat with it using Cursor through 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
Ever wondered how companies like Instagram, Spotify, and Apple manage their databases? What database technology are they all using? Want to try it for yourself?
In this project, you'll create your own database using PostgreSQL; the same technology that over 500,000 companies use to build and manage their databases.
Why PostgreSQL?
PostgreSQL is one of the most widely used databases in the world. It's known as a reliable and open‑source alternative to commercial databases like Oracle and SQL Server, especially for startups and web apps that needed something powerful but free.
Get ready to...
- ⚙️ Connect Cursor to Docker and PostgreSQL MCPs.
- 🐘 Prompt Cursor to create a Docker container with a PostgreSQL database.
- 📊 Load 40,000+ rows of data into your database.
- 💬 Query and visualize your database.
- 💎 (Secret Mission) Optimise your database's performance.
New to Docker or PostgreSQL?
That's exciting! This project requires no experience with Docker, databases, or MCP, so you can definitely get started here.
It's also project #1 in an epic Data Engineering and MCPs series. Get ready to manage and visualise data with some of the most popular data engineering tools, from PostgreSQL to Jupter Notebook and Grafana!
Not sure if this project is right for you? Check if it matches your goals.
If you're up for a bit of a challenge, quiz yourself on the key concepts up ahead in this project.
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: You are here!
- Part 2: DBT MCP
- Part 3: Jupyter MCP
- Part 4: Grafana MCP
Before we start Step #1...
Traditionally, setting up PostgreSQL meant installing it on your machine, changing lots of settings, and typing many commands by hand.
What is PostgreSQL?
PostgreSQL is a popular open‑source database engine that stores data in tables and speaks SQL, and we’ll be using it in this project to model a realistic e‑commerce system.
💡 What is a database?
A database is a structured place where applications store and organize information (like customers, products, and orders) so they can quickly search, update, and combine that data when users interact with the app.
In this project, Cursor + MCP act like a control tower. You’ll use plain English to ask for what you want and let Cursor and the MCP translate that to commands and SQL that make it happen.
What's MCP? How is it different from just using Cursor's chat?
MCP (Model Context Protocol) is a standard that lets AI models (like Claude in Cursor) connect to external tools and services. Unlike regular Cursor chat which can only read and edit files, when you use MCP servers, Cursor can:
- Create and control Docker containers
- Execute SQL queries on databases
- Manage infrastructure through natural language
This means you can control real infrastructure and services directly from Cursor's chat, rather than just editing code files.
Set Up Your Environment
Let's get your environment ready! We'll install Docker Desktop for running containers and uv for managing Python packages.
In this step, you're going to:
- Install Docker Desktop to run containers.
- Install uv, a fast Python package manager.
Install Docker Desktop
Docker Desktop provides everything you need to run Docker containers on your computer.
What is Docker and Docker Desktop?
Docker is a tool that lets you package an application (like PostgreSQL) together with everything it needs to run into a lightweight bundle called a container. A container is like a self‑contained mini‑computer that always has the right versions of libraries and settings, so your app runs the same way on any machine.
Docker Desktop is the app that makes it easy to run those containers on your laptop – it includes the Docker engine, a graphical dashboard, and all the background services. In this project, Docker Desktop will run a PostgreSQL container for you instead of you installing PostgreSQL directly on your operating system, which keeps your system cleaner and makes it easy to start, stop, or delete the database when you're done.
First, let's check if you already have Docker Desktop installed.
- Open Terminal (Mac) or PowerShell (Windows).
- Run the following command:
docker --version
❌ Command not found
Perfect! Docker isn't installed yet. Let's get it set up. 🐳
- Visit the Docker Desktop download page.
Now download the correct installer for your system:
🍎 macOS
Select the correct download for your Mac
- If you have Apple Silicon (M1, M2, or M3), select Download for Mac - Apple Chip.
- If you have Intel, select Download for Mac - Intel Chip.
I don't know what version I should download for my Mac!
First, let's check what type of Mac you have.
- Click the Apple logo in the top right of your display
- Select About This Mac.
- If you see Apple M1, Apple M2, or Apple M3 under Chip, you have Apple Silicon → Download for Mac - Apple Chip
- If you see Intel Core, you have an Intel Mac → Download for Mac - Intel Chip
Install Docker Desktop
- Open the Docker.dmg file from your Downloads folder.
- Drag the Docker icon to your Applications folder.
- Open Docker from your Applications folder.
Why open Docker Desktop?
Opening Docker Desktop starts the Docker service in the background. This service needs to be running for any Docker commands to work. You'll see a whale icon in your menu bar when Docker is running.
- Click Open at the security warning.
You may see a Docker Subscription Service Agreement screen.
- Click Accept.
You'll see a configuration screen to finish setting up Docker Desktop.
- Keep Use recommended settings selected (the default option).
- Click Finish.
What are recommended settings?
Recommended settings usually include turning on the right virtualization backend for your OS, setting up file sharing so containers can read and write files from key folders on your machine, and giving Docker reasonable CPU and memory limits so it doesn't overwhelm your laptop. For most developers, these defaults are safe and work well out of the box, and you can always fine-tune them later in Settings if you notice Docker is using too many resources or you want to share different folders.
Docker may prompt for your password to apply these configurations.
- Enter your password and click OK.
You'll see a Welcome to Docker screen.
- Click Skip in the top right.
You should now see the Docker Desktop dashboard!
Now let's verify Docker is working!
- Open Terminal on your Mac
- Run this command:
docker --version
What should I see?
You should see something like Docker version 24.0.7, build afdd53b. The version and build ID on your computer will probably be different – that's totally expected and your Docker will work just the same. Why are version numbers different?
Perfect! Docker is installed and working on your Mac.
🖼️ Windows
Download Docker Desktop for Windows
- Click Download for Windows 10/11 (64-bit)
While we wait for the download, lets check if WSL2 is installed (Required for Docker Desktop)
Docker Desktop on Windows requires WSL 2 (Windows Subsystem for Linux 2). Let's check if you have it installed.
- Open PowerShell (right-click Start menu → Windows PowerShell).
- Run the following command to check if WSL 2 is installed:
wsl --version
✅ I see WSL version info
Nice! WSL 2 is already installed.
⚠️ Command not found or error
If you see "command not found" or an error, you need to install WSL 2.
- Open Windows Terminal as Administrator (right-click Start → Windows Terminal (Admin)).
- Run the following command to install WSL 2:
wsl --install
What does wsl --install do?
This command installs WSL 2 and the default Ubuntu Linux distribution. WSL 2 is a lightweight Linux environment that runs inside Windows, which Docker Desktop uses to run Linux containers.
- Wait for the installation to complete (this may take 5-10 minutes).
- Restart your computer when prompted or when the installation completes.
- After restarting, verify WSL 2 is installed by running wsl --version in PowerShell.
Still having WSL 2 issues?
If you continue to have problems installing WSL 2, you may need to:
- Enable virtualization in your BIOS settings
- Make sure Windows is up to date (Settings → Windows Update)
- Share your error message with the NextWork community!
Install Docker Desktop
Let's install Docker Desktop!
- Locate the Docker Desktop Installer.exe in your Downloads folder.
- Double-click it to start the installation.
You'll see a security warning: "Open File - Security Warning".
- Click Run.
You might be prompted: "Do you want this app to make changes to your device?"
- Click Yes.
On the configuration screen, you'll see a checkbox for "Add shortcut to desktop" (optional).
- Click OK.
Pro Tip
The desktop shortcut makes it easy to open Docker Desktop later, but you can also find it in your Start menu.
Docker will now begin "Unpacking files".
What's Docker unpacking?
Docker Desktop is installing its core components: the Docker Engine (runs containers), Docker CLI (command-line tools), and desktop interface. It's also setting up the virtualization layer that lets containers run on Windows using WSL 2.
When unpacking is complete, you'll see "Installation succeeded" with a message that Docker Desktop is installed.
- Click Close.
If you see a "Restart required" popup, restart your computer when you're ready.
- Click Restart to complete the installation.
Why restart?
Docker Desktop needs to install system-level components and drivers. The restart ensures these components are properly loaded before you start using Docker.
After restarting, you'll need to open Docker Desktop.
- Open Docker Desktop from your Start menu.
You'll see a Welcome to Docker screen asking you to sign in.
- Click Skip in the top right corner.
You should now see the Docker Desktop dashboard!
Why open Docker Desktop?
Opening Docker Desktop starts the Docker service in the background. This service needs to be running for any Docker commands to work. You'll see a whale icon in your system tray when Docker is running.
Now let's verify Docker is working!
- Open PowerShell on your Windows computer
- Run this command:
docker --version
What should I see?
You should see something like Docker version 24.0.7, build afdd53b. The version and build ID will likely be different on your computer - this is normal and doesn't affect functionality. Why are version numbers different?
Perfect! Docker is installed and working on your Windows machine.
Wait! ✋ Let's double-check Docker Desktop is running
Quick check before we move on - Docker Desktop needs to be running for the next steps to work:
- Look for the whale icon 🐳 in your menu bar (Mac) or system tray (Windows)
- Don't see it? Open Docker Desktop from your Applications folder (Mac) or Start menu (Windows)
Why check this?
Docker commands won't work unless Docker Desktop is running in the background. The whale icon is your visual confirmation that everything is ready to go!
✅ I see a version number
Perfect! That should mean Docker Desktop is already installed. Now let's make sure it's running.
- Open Docker Desktop from your Applications folder (Mac) or Start menu (Windows).
Hmm, I don't have Docker Desktop
Aha! That means we will still need to download Docker Desktop after all. It's possible for your terminal to show a docker version, but not have Docker Desktop if it was installed, and later deleted, in the past.
Make sure to switch over to the ❌ Command not found tab and check out the steps for installing Docker Desktop.
- Wait for Docker to fully start (the whale icon should be steady, not animated).
You should see the Docker Desktop dashboard:
Install Python 3.12+
We'll also need Python later for MCP servers, so let's check if you have it:
- Head back into your terminal.
🍎 MacOS/Linux
- Run the following command:
python3 --version
What's Python3?
Python is a programming language used for building software and running tools. Python 3 is the current version (Python 2 is outdated).
We need Python 3.12 or higher to run the MCP servers that connect Cursor to Docker and PostgreSQL. By checking now, we can catch any issues before installing the MCP servers!
✅ I see Python 3.12 or higher
Perfect! Your Python version is compatible with MCP servers.
My version number isn't 3.12 exactly
The exact version number may differ - that's normal! As long as it's 3.12+, you're good to go.
If your Python version is any less than 3.12, you'll need to update Python.
⚠️ I see Python 3.11 (or older)
It's totally possible for your Python version to be older - for example, a Mac can come with Python 3.9 already pre-installed, but we need Python 3.12+ for MCP servers.
No worries - we can upgrade Python real quick using Homebrew! 🚀
What is Homebrew?
Homebrew is a package manager for macOS that makes it easy to install and update software like Python. Think of it as an app store for developer tools!
Quick Homebrew check 🍺
First, let's see if you already have Homebrew installed:
brew --version
✅ I see a version number
Great! Homebrew is already installed.
❌ Command not found
You'll need to install Homebrew first.
- Run this command in your terminal:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
What does this command do?
This downloads and runs Homebrew's official installation script from GitHub. It will prompt you for your password and guide you through the installation.
Wait for the installation to complete (this may take 3-5 minutes), then follow any instructions it provides to add Homebrew to your PATH.
Still having issues installing Homebrew?
Hmm interesting! You can:
- Troubleshoot your Homebrew installation here
- Visit brew.sh for detailed installation instructions
- Share your error with the NextWork community!
You've got this!
Time to upgrade Python ⬆️
- Run these commands in your terminal:
brew update && brew install python@3.13
What doe these commands do?
- brew update makes Homebrew download the latest formula and version information for all packages it knows about
- && runs your next command, only if the first succeeds
- brew install python@3.13 installs Python 3.13 specifically, which is the newest version that works with postgres-mcp
Wait for the installation to complete (this may take 2-5 minutes).
- Now let's verify Python was updated successfully:
hash -r
brew link python@3.13 --overwrite
which python3 && python3 --version
Note
What do these commands do?
Together, these commands refresh your terminal’s view of Python, point python3 at the new Homebrew‑installed version, and then confirm that the correct version is now being used.
- hash -r - Clears your terminal’s memory so it can find the new Python files instead of the old ones.
- brew link python@3.13 --overwrite - Points the python3 command to the Homebrew install of Python 3.13, even if something else was there before.
- which python3 - Shows the exact file your computer will run when you type python3, so you can be sure it’s the Homebrew version.
- python3 --version - Prints the version number so you can double-check it now says 3.13.x.
You should see:
- Path: /opt/homebrew/bin/python3 (this means it's using the Homebrew version)
- Version: Python 3.13.x
Still seeing Python 3.9 (or 3.14)?
If python3 --version keeps pointing to the old system version or 3.14 (which is incompatible with some versions of postgres-mcp), your terminal needs to reload its PATH. Why does my terminal still show the old Python version? Try these troubleshooting steps below.
Troubleshooting: Update Your PATH
If you're still seeing Python 3.9 or 3.13, we need to tell your terminal to use Homebrew's Python first.
- Open your shell configuration file:
nano ~/.zshrc
- Add this line at the top of the file:
export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:$PATH"
What does this do?
This tells your terminal to look for programs in Homebrew's directories first. This way, when you type python3, it will find the Homebrew-managed version (3.13) instead of the old system version (3.9) or the incompatible 3.14 build.
- Press Ctrl + X to exit.
- Press Y to save.
- Press Enter to confirm.
Now restart your terminal to apply the changes:
📦 I'm in Cursor
- Click the trash icon to kill the terminal.
- Open a new terminal with Ctrl + Shift + `
🍎 I'm in the Terminal app
- Right-click the Terminal icon in your dock.
- Select Quit.
- Reopen Terminal from Applications.
- Now verify again - run this command:
python3 --version
You should now see Python 3.13!
I'm still having issues!
If your terminal keeps defaulting to Homebrew’s Python 3.14 even after you installed python@3.13, run this these commands to prioritize 3.13 for your terminal session:
# 1) Ensure python 3.13’s is first and clear command cache
export PATH="/opt/homebrew/opt/python@3.13/libexec/bin:$PATH"
hash -r
# 2) Verify python3 now resolves to 3.13
which python3
python3 --version
# 3) Align pip to the same interpreter
python3 -m pip --version
python3 -m pip install --upgrade pip
# 4) Backup Homebrew’s global python3/pip3 symlinks that point to 3.14
mv /opt/homebrew/bin/python3 /opt/homebrew/bin/python3.bak
mv /opt/homebrew/bin/pip3 /opt/homebrew/bin/pip3.bak
hash -r
# 5) Final check
which -a python3
python3 -c "import sys; print(sys.executable, sys.version)"
python3 -m pip --version
Those commands make your terminal choose Python 3.13 over other versions. You can also keep it that way every time you open a terminal by running:
nano ~/.zshrc
- Replace the PATH export at the top of your ~/.zshrc file with:
export PATH="/opt/homebrew/opt/python@3.13/libexec/bin:$PATH"
- Press Ctrl + X to exit.
- Press Y to save.
- Press Enter to confirm.
- Back in your terminal, check your Python version with:
source ~/.zshrc && hash -r && python3 --version
- Your Python version number should show 3.13.x now!
If you continue to have problems, share your error message with the NextWork community!
🖼️ Windows
- Run the following command:
python --version
✅ I see a version number
Perfect! Python is already installed.
❌ Command not found
You'll need to install Python. Don't worry - it's quick!
- Visit python.org/downloads
- Download the latest Python 3 installer for Windows.
- Run the installer.
- Make sure to check the box that says "Add python.exe to PATH"
- Click Install Now and complete the installation
- Close the installer
- Restart your terminal
- Verify the installation:
python --version
You should now see the Python version number!
Still seeing "command not found"?
Make sure you restarted your terminal after installation. Need help troubleshooting Python installation? You can also ask the NextWork community!
Set Up Cursor and Create Project Folder
Time to set up Cursor and create a dedicated folder for this project.
- Close your terminal app.
Why are we closing our terminal?
From now on, you'll run all commands in Cursor's built‑in terminal instead of a separate terminal app. This way, everything for this project stays in one place and is easier to follow.
- Open Cursor from your Applications folder (Mac) or Start menu (Windows).
I don't have Cursor!
No worries! Check out Cursor's download page or see this project for detailed IDE setup instructions.
Now let's create a dedicated folder for this project series using Cursor.
- Select Open Project in Cursor.
- Navigate to your Desktop or another folder where you keep development projects.
- Create a new folder named MCP-data-series.
- Click Select Folder or Open.
Why create a dedicated folder?
This folder will store your Python project files (created by uv), demo data (demo_data.sql), and any scripts you create. Keeping everything in one place makes it easier to manage and clean up later!
Now let's open a terminal inside Cursor.
- Click Terminal in the menu bar.
- Select New Terminal.
🍎 macOS
Pro Tip
You can also use the keyboard shortcut Cmd + Shift + ` to open the terminal.
🖼️ Windows
Pro Tip
You can also use the keyboard shortcut Ctrl + Shift + ` to open the terminal.
Your terminal should open at the bottom of Cursor, already in your MCP-data-series folder!
Let's confirm you're in the right folder:
- Run this command:
pwd
You should see the path to your MCP-data-series folder.
I'm in a different folder!
If your terminal opened in a different location, navigate to MCP-data-series by running: cd Desktop/MCP-data-series (or wherever you created the folder). How do I get back to my MCP-data-series directory?
Install uv Package Manager
Now let's install uv, a fast Python package manager (a tool that installs and manages Python software) we'll use to install the MCP servers.
What is uv?
uv is a modern Python package manager that's 10-100x faster than traditional tools like pip (it's written in Rust, a compiled language, which makes it blazingly fast). We'll use it to install and run the Docker MCP and Postgres MCP servers - it handles setting up Python environments automatically so you don't have to.
First, let's check if you already have uv installed.
- In Cursor's terminal, run the following command:
uv --version
❌ Command not found
Perfect! uv isn't installed yet. Let's get it running.
🍎 macOS
- Run the following command in your terminal:
curl -LsSf https://astral.sh/uv/install.sh | sh
What does this command do?
The command curl -LsSf https://astral.sh/uv/install.sh | sh downloads and runs the uv installer:
- curl -LsSf downloads the uv installer script from astral.sh
- | (pipe) passes it to the next command
- sh executes the script. It's like downloading a file and running it in one step.
🙋♀️ Command not found after installation?
If you get a "command not found" error after installation, you need to add uv to your PATH.
Run uv --version again to verify:
Still seeing errors? Share them with the NextWork community!
💡 Note: You may need to restart your terminal for the uv command to be recognized.
Now verify the installation worked:
uv --version
You should see a version number like uv 0.4.18 - perfect, uv is installed!
🖼️ Windows
In Cursor's terminal at the bottom of the window, run the following command:
iwr https://astral.sh/uv/install.ps1 -UseBasicParsing | iex
What does this command do?
The command iwr https://astral.sh/uv/install.ps1 -UseBasicParsing | iex downloads and runs the uv installer:
- iwr (Invoke-WebRequest) downloads the uv installer script from astral.sh
- | (pipe) passes it to the next command
- iex (Invoke-Expression) executes it. It's like downloading a file and running it in one step.
Wait for the installation to complete (usually 10-20 seconds).
I got an execution policy error!
If you see an error about execution policies, you need to allow PowerShell to run scripts:
- Close your current terminal
- Open a new terminal as Administrator (right-click your IDE → Run as administrator)
- Run: Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
- Type Y and press Enter
- Try the uv installation command again
Still getting errors? Share your error message with the NextWork community!
💡 Note: You may need to restart your terminal for the uv command to be recognized.
Now verify the installation worked:
uv --version
You should see a version number like uv 0.4.18 - perfect, uv is installed!
✅ I see a version number
Perfect! uv is already installed. You can move on to the next step!
Woohoo! 🎊 Nice work, you now have Docker and uv installed and verified. Docker will run PostgreSQL in a container, uv will install the MCP servers, and Cursor will use those MCPs to control Docker and PostgreSQL through chat. Let's set that up now!
Connect Cursor to Docker with MCP
Next up! We'll set up MCP servers that let Cursor talk to Docker and PostgreSQL for you.
What's MCP? How is it different from just using Cursor's chat?
MCP (Model Context Protocol) is a standard that lets AI models (like Claude in Cursor) connect to external tools and services. Unlike regular Cursor chat which can only read and edit files, when you use MCP servers, Cursor can:
- Start and stop Docker containers
- Run SQL queries on your databases from chat
- Help you set up and manage these tools by following your instructions
In other words, MCP lets Cursor work with your actual running tools (like Docker and PostgreSQL), not just the code sitting in your editor.
In this step, you're going to:
- Initialize a Python project with uv.
- Configure Cursor to use both MCP servers.
- Restart Cursor to activate the MCPs.
Initialize Your Python Project
MCP servers need a Python environment to run. Let's create one using uv!
First, make sure you're in your MCP-data-series folder in the terminal.
- Run the following command:
pwd
I'm not in MCP-data-series!
Run cd Desktop/MCP-data-series (or wherever you created the folder) to navigate there.
Now let's initialize a new uv project.
- Run the following command:
uv init
What does uv init do?
This command creates a Python project structure with several files including pyproject.toml (tracks dependencies), .gitignore (excludes files from git), README.md (project documentation), and main.py (example Python script).
You should see a few new files appear in your MCP-data-series folder!
I see "Adding 'MCP-data-series' as member of workspace..."
This message appears if uv detected an existing Python workspace in a parent folder (like your Desktop or home directory). This is fine! Your MCP-data-series project will work correctly as part of that workspace.
Configure Cursor MCP Settings
Now comes the magic - we'll tell Cursor about our MCP servers by adding them to a configuration file. Think of this as giving Cursor the keys to Docker and PostgreSQL. Once configured, Cursor will be able to create containers, run SQL queries, and manage your database infrastructure directly through its chat interface.
- Click the settings icon (gear icon) in the top right of Cursor.
- Select Tools & MCP from the left-hand side settings menu.
- Scroll down.
- Click "Add Custom MCP" (or "New MCP Server" if you already have MCPs configured).
Button says "New MCP Server"?
If you already have other MCP servers configured in Cursor, the button will say "New MCP Server" instead of "Add Custom MCP". This is perfectly normal - just click it to add another MCP server!
The file: mcp.json will open showing your Cursor MCP configurations. We'll add both Docker MCP and Postgres MCP to your configuration.
My mcp.json is empty
If your mcp.json file looks like this (empty), just drop in the complete configuration below based on your operating system:
🍎 macOS/Linux
Add this to your mcp.json:
{
"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
Add this to your mcp.json:
{
"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" }
}
}
}
I already have MCP servers configured
Add these two individual server blocks to your existing mcpServers section.
First, add the Docker MCP based on your OS:
🖼️ Windows
Add this to your mcp.json:
"docker": {
"command": "uv",
"args": ["run", "--with", "docker-mcp", "docker-mcp", "--access-mode=unrestricted"],
"env": { "DOCKER_HOST": "npipe:////./pipe/docker_engine" }
}
🍎 macOS/Linux
Add this to your mcp.json:
"docker": {
"command": "uv",
"args": ["run", "--with", "docker-mcp", "docker-mcp", "--access-mode=unrestricted"],
"env": { "DOCKER_HOST": "unix:///var/run/docker.sock" }
}
Hint: Don't forget to add a comma!
When adding the Docker MCP to your existing mcp.json, make sure there's a comma (,) after the closing brace of your previous MCP server entry. JSON requires commas to separate objects.
Also pay careful attention to the proper nesting and structure - see the example below showing correct comma placement and formatting:
Then, add the Postgres MCP (same for all OS):
"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 do?
This JSON file tells Cursor how to run MCP servers:
- command - The program to execute (we use uv to run Python packages)
- args - Arguments passed to the command (tells uv which MCP package to run)
- env - Environment variables like connection strings and socket paths
Now save the file.
- Press Cmd + S (Mac) or Ctrl + S (Windows/Linux).
Restart Cursor
For Cursor to pick up the new MCP servers, we need to restart it completely.
- Quit Cursor - make sure it's not just minimized!
How do I quit Cursor?
- Mac: Go to Cursor → Quit Cursor, or press Cmd+Q on your keyboard.
- Windows: Go to File → Exit or press Alt+F4 on your keyboard.
- Reopen Cursor from your Applications folder (Mac) or Start menu (Windows).
Why restart Cursor?
MCP configurations are loaded when Cursor starts. Restarting ensures Cursor reads your new configuration and establishes connections to both the Docker and Postgres MCP servers.
Now let's verify the MCP servers connected successfully.
- Click the settings icon (gear icon) in the top right.
- Select MCP from the left sidebar.
You should see both docker and postgres with green indicators showing they're connected!
My MCPs aren't green!
If you see red indicators or error messages instead of green ones, don't worry - this is usually a configuration issue. Get help debugging MCP connection issues. You can also share your error with the NextWork community!
Awesome! You've successfully configured both MCP servers. In the next step, we'll put them to work and build a real PostgreSQL database using nothing but chat.
Build Your Database
It's time! So far, you’ve set up the tooling (Docker, Python, uv, and MCP servers). In this step, you’re finally going to bring the database to life: start PostgreSQL inside Docker, load realistic e‑commerce data, and visualize the tables you’ve created.
What is a database?
A database is a structured place for storing and organizing information so that apps can quickly save, search, and update it. For example, an online store might use a database to keep track of customers, products, and orders instead of trying to manage all that information in separate spreadsheets.
💡 What is PostgreSQL?
PostgreSQL (often shortened to “Postgres”) is a popular open‑source relational database – it stores data in tables with rows and columns, and lets you query that data using SQL. Many startups and large companies use PostgreSQL in production because it’s powerful, reliable, and free, which makes it perfect for projects like this where you want to work with “real world” database tech.
💡 How do Docker, Python, uv, and MCP fit together here?
In this project, the MCP servers (Docker MCP and Postgres MCP) are small Python programs. Python is the language they’re written in, and uv is the tool that installs their dependencies and runs them in a clean Python environment. Docker is responsible for actually running your PostgreSQL database in a container.
When you type in Cursor, Cursor calls the MCP servers (run via uv), the Docker MCP talks to Docker to start or manage the Postgres container, and the Postgres MCP talks directly to the database inside that container to run SQL and manage schemas and users.
In this step, you're going to:
- Prompt Cursor to create a PostgreSQL container using the Docker MCP.
- Prompt Cursor to configure database users using the PostgreSQL MCP.
- Load demo data into your database.
- Visualize your database.
Create PostgreSQL Container
Here's where the magic happens! We're about to create a PostgreSQL database in Docker, ready to store and query thousands of rows of e-commerce data. 🎯
- Open Cursor's AI Chat Pane (you could also press Ctrl + L or Cmd + L on your keyboard).
What's Cursor chat?
Cursor chat is where you interact with the AI assistant. When you type messages here, Cursor can use the MCP servers we configured to actually perform actions - like creating Docker containers!
Now let's create the PostgreSQL container.
- Send this prompt:
Using the Docker MCP, create a PostgreSQL 16 container named
pg-local on port 5432 with user/password 'app' and database 'demo'
What does this prompt do?
This message is asking Cursor (through the Docker MCP) to set up a ready‑to‑use PostgreSQL database for you.
- postgres:16 is the version of PostgreSQL we want. Think of it like saying "install PostgreSQL version 16" instead of some random older version.
- An image is like a template for a container – it's a pre‑packaged recipe that says "here's how to run PostgreSQL with all the right files and settings." Docker uses this PostgreSQL 16 image to create the actual running database.
- A container named pg-local is the running PostgreSQL database created from that image. Giving it a name just makes it easier to find and manage later.
- Mapping port 5432 means "open door number 5432 on your computer and connect it to the database inside Docker." PostgreSQL is configured to listen on port 5432, which just means it watches that door for incoming requests. When tools outside Docker (like MCP, psql, or apps) want to talk to the database, they send network traffic to localhost:5432, and Docker passes it through that door into the container.
- The username and password are like login details for your database. Just like you need an account to sign into a website, tools connecting to PostgreSQL must prove who they are. Using a separate database user (like app with password app) lets you control what that user is allowed to do and keeps things safer than sharing a super‑powerful admin account for everything.
Cursor will analyze your request and propose using the Docker MCP.
You might see a tool call appear in the chat.
- Select Run so Cursor can use the tool call to create the Docker container.
What is a tool call?
A tool call is Cursor's way of making a structured request to an MCP server to run a specific function. When you ask Cursor to create a Docker container, it generates a tool call to says "use this MCP function (like mcp_docker_create-container) with these parameters."
Cursor shows you this tool call in the chat so you can see exactly what's about to happen before it runs.
🙋♀️ Cursor isn't connecting to Docker!
Hmm! Here are a few troubleshooting tips if Cursor can't connect to the Docker MCP...
- Make sure your Cursor chat is in Agent mode - not Ask mode!
- Check the Tools & MCP page in your Cursor Settings - is the Docker MCP showing any errors? Make sure to expand the MCP to view detailed error message, which you can paste into your Cursor chat to troubleshoot!
- Still not connecting? Troubleshoot here!
It'll take about 10-15 seconds for PostgreSQL to fully start up inside the container.
What do you see in your Cursor chat once it's done running MCP tool calls?
✅ Container created successfully
Nice! Your PostgreSQL container is running. Let's move on to configuring it.
⚠️ Docker MCP can't connect
If you see an error like "The Docker MCP server can't connect to Docker" or "Failed to initialize: protocol not available", don't worry - this usually means Docker Desktop isn't running yet. Follow these steps:
1. Make sure Docker Desktop is running
- Look for the whale icon in your menu bar (Mac) or system tray (Windows)
- If you don't see it, open Docker Desktop from your Applications folder or Start menu
- Wait for Docker Desktop to fully start (the whale icon should be steady, not animated)
2. Verify Docker is accessible
- In Cursor's terminal, run:
docker ps
If this shows a list of containers (even if empty), Docker is working!
3. If the MCP still can't connect, create the container manually
You can create the container using the terminal instead:
docker run -d \
--name pg-local \
-p 5432:5432 \
-e POSTGRES_USER=app \
-e POSTGRES_PASSWORD=app \
-e POSTGRES_DB=demo \
postgres:16
Note
The menu bar icon can be hidden while Docker Desktop is still running, so check the terminal command first!
After the container is created, you can still use the Postgres MCP in the following steps.
Still having issues? Share your error message with the NextWork community!
Configure Database Users and Schema
Great! Your container is running. Now let's set up how your application will safely talk to the database.
What's an application user? Why do we have them?
When we started the PostgreSQL container, we set it up with a username and password (app / app) and a demo database. That app login is an application user - it’s the account your app and the Postgres MCP use for everyday work like reading and writing data. In contrast, postgres is the database's built‑in superuser, only for rare admin/maintenance tasks.
That way, if your app (or tools using that account) are ever compromised, the attacker is mostly limited to what the app user can do.
Now let's configure that application user and give it its own schema.
- Send this prompt:
Using the Postgres MCP, configure the database user named 'app' with
password 'app', grant it all permissions on the demo database, and
create a schema called 'app' owned by this user
What does this prompt do?
This prompt tells Cursor (using the Postgres MCP) to:
- Make sure the app user can fully use the demo database (create tables, insert data, run queries, etc.). In production you’d lock this down even further (i.e. you wouldn't give your app user permissions to demo), but this separation is your first step towards separating an application user from the superuser.
- Create a schema called app and make the app user its owner. This keeps your app’s tables grouped together in one place.
💡 What's a schema vs a database?
A database (like demo) is the whole “container” that holds all of your data. A schema (like app) is a named section inside that database where related tables live together.
Think of it like your laptop: the database is the entire hard drive, and schemas are folders inside it. You might keep your main app tables in an app folder and your analytics/reporting tables in a reporting folder, even though they’re all on the same drive.
You should see success messages for each command!
✅ Commands executed successfully
Perfect! Your database is now configured with proper users and schemas. Let's move on to loading demo data!
⚠️ Connection refused error
If you see "connection refused" or "could not connect to server", that's normal - PostgreSQL might still be starting up inside the container. Try these:
- Wait longer - Give it another 10-15 seconds to fully initialize.
- Check Docker Desktop - Make sure your pg-local container is running (green status).
- Restart the container - Ask Cursor: "Using Docker MCP, restart the pg-local container"
- Why does PostgreSQL take time to start up?
- Still having connection issues? Ask the NextWork community!
⚠️ Other SQL error
If you see other SQL errors:
- Check the error message - Share it with Cursor: "I got this error: [paste error]. How do I fix it?"
- Try one command at a time - Execute each SQL statement separately
- How do I interpret SQL error messages?
- Need help debugging? Share your error with the NextWork community!
Download Demo Data
Now let's fill this database with real data! We've prepared a SQL file packed with realistic e-commerce data: customers, products, orders, and more. Over 40,000 rows ready to go. 📊
- Click demo_data.sql to download the file.
- Save it to your MCP-data-series folder with the name demo_data.sql.
Verify the file is in your MCP-data-series folder:
What is SQL?
SQL (Structured Query Language) is the standard language used to tell relational databases like PostgreSQL what to do - for example, “create this table”, “insert this order”, or “find all customers in Canada”. Instead of clicking around in a UI, you write SQL statements, and the database executes them to store, update, or fetch data.
💡 What's in demo_data.sql?
This SQL file contains:
- 4 tables: customers, products, orders, and order_items with their relationships
- 2,000 customers with emails, registration dates, countries, and tier levels (bronze/silver/gold/platinum)
- 1,000 products across different categories with prices and stock quantities
- 10,000 orders with statuses, dates, and regional data
- 30,000+ order items linking orders to products with quantities and prices
This realistic e-commerce dataset is perfect for practicing SQL queries and database analysis!
Load Demo Data
Let's load the demo data into your database.
In Cursor's terminal, run this command:
🍎 macOS/Linux
cat demo_data.sql | docker exec -i pg-local psql -U app -d demo
🖼️ Windows
Get-Content demo_data.sql | docker exec -i pg-local psql -U app -d demo
What does this command do?
- This command reads the demo_data.sql file and pipes it (|) directly into the PostgreSQL container.
- The docker exec -i pg-local psql -U app -d demo part executes the SQL commands inside the container as the app user in the demo database.
You should see SQL output scrolling by as tables are created and data is inserted.
✅ Data loaded successfully
Perfect! Your database now has 40,000+ rows of e-commerce data spread across customers, products, orders, and order items. Let's verify everything works!
⚠️ File not found error
If Cursor says it can't find demo_data.sql:
- Check file location - Make sure the file is in your MCP-data-series folder
- Check filename - Make sure it's named exactly demo_data.sql (not demo_data.sql.txt)
- Specify full path - Try: "Read the file at /full/path/to/MCP-data-series/demo_data.sql"
- Need help? Ask here
⚠️ SQL execution error
If you see SQL errors during data loading:
- Check the error message - Some errors are okay (like "table already exists")
- Try reloading - Ask Cursor: "Drop all tables in the app schema and reload demo_data.sql"
- Share the error - Ask Cursor: "I got this error while loading data: [paste error]. What should I do?"
- Still stuck? Ask here
Verify Your Setup
Let's verify everything is connected and working.
- Send this prompt to Cursor:
Using the Docker MCP, list all running containers. Then using the
Postgres MCP, list all tables in the demo database.
Cursor should respond with information about your running Docker container (pg-local), your PostgreSQL connection details, and the tables in your database (customers, products, orders, order_items).
Visualize Your Database Schema
Let's create a visual diagram showing how all your tables connect together. This is the kind of diagram database architects create when designing systems. 👀
- Send this prompt to Cursor:
Using the Postgres MCP, read the database schema and
sample 3 rows from each table. Create a Mermaid diagram
including the example values. Render the diagram in
the chat only, no files. Use a high-contrast style.
Cursor will read your database schema and generate a visual diagram showing all tables, their columns, relationships, and sample data!
What's an ER diagram?
An Entity-Relationship (ER) diagram is a visual representation of your database structure. It shows tables as boxes, columns inside each box, and arrows connecting tables to show relationships (like how orders connect to customers). The diagram also displays sample data so you can see real values from your database.
💡 How do you “read” this diagram?
Start by picking one table box (for example customers), then follow the arrows to see which other tables depend on it (like orders). The sample rows help you connect column names to real‑world meaning – for example, a customer_id in orders should match an id in customers, just like a lookup between two related spreadsheets.
✅ Everything looks good
Awesome! Your PostgreSQL database is running in Docker, loaded with 40,000+ rows of data, and fully connected to Cursor. You can now query it through Cursor's chat interface. Ready for the Secret Mission?
⚠️ Something's not working
If Cursor reports issues:
- Container not running - Check Docker Desktop, make sure pg-local is running (green status)
- Can't connect to database - Try restarting the container: "Using Docker MCP, restart the pg-local container"
- No tables found - Try reloading the data: "Using Postgres MCP, reload the demo_data.sql file"
- Postgres MCP shows errors mentioning pglast or strchrnul - Totally okay! That usually just means Python 3.14 is installed. [Reinstall Python 3.13(ASK=I'm currently using Python 3.14. How can I downgrade Python to 3.13 instead for this project?), then run uv sync inside your project so the Postgres MCP can recompile against the supported version. You're just a quick downgrade away from getting back on track.
- Need help? Ask here
Secret mission
How do companies like Instagram, Spotify, and Apple keep their databases running fast, even with millions of users?
By now, you’ve built and populated a realistic PostgreSQL database in Docker, and you can explore it through Cursor and the Postgres MCP. In this secret mission, you’ll shift into performance‑tuning mode - you'll learn to spot slow queries, understand how your database thinks, and add smart optimizations that make everything run smoother.
Speed Up Your Database's Performance
Clean Up Your Resources
Clean Up Your Resources
Nice work completing this project! Now let's clean up the resources we created to keep your system tidy.
Resources to delete:
- Stop and remove the PostgreSQL container.
- Remove the MCP-data-series folder.
- Uninstall Docker Desktop if you don't need it.
Stop and Remove Container
Let's use the Docker MCP one last time to clean up! 🧹
In Cursor chat, send this prompt:
Using the Docker MCP:
Stop the pg-local container
Remove the pg-local container
Verify in Docker Desktop that the container is gone:
Delete MCP-data-series Folder
- Navigate to your Desktop (or wherever you created MCP-data-series).
- Delete the MCP-data-series folder.
(Optional) Uninstall Docker Desktop
If you don't need Docker for other projects:
Windows:
- Go to Settings → Apps → Apps & features
- Find Docker Desktop
- Click Uninstall
Mac:
- Open your Applications folder
- Drag Docker to the Trash
- Empty Trash
Should I uninstall Docker?
Only uninstall if you're sure you won't use it again soon. Docker is useful for many projects and doesn't consume resources when not running.
That's a wrap!
That's a wrap!
You did it! You've built a complete PostgreSQL database setup that you can control using natural language in Cursor.
What you learned:
- ⚙️ How MCP (Model Context Protocol) connects code editors to external tools
- 🐳 Docker fundamentals: containers, images, and port mapping
- 🐘 PostgreSQL basics: users and schemas, plus how indexes can speed up queries (explored further in the Secret Mission)
- 📊 Database performance: query plans, execution analysis, and optimization
- 💬 How to manage infrastructure by just typing what you want
Ready to quiz yourself? 💪
What's next?
In Project #2 of this Data Engineering x MCP series (coming soon), get ready to transform your raw data into customer analytics with the DBT MCP!
Make sure to join the NextWork Community to be the first to hear when it's out 🤝
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!