Banks Jamgbadi

me + my homelab


I’ve always wanted to build a home lab. A few years back, I finally got around to putting one together using a Raspberry Pi SBC; but I quickly ran of storage. Then I got on eBay; purchased a Mac Mini (Late 2012), 16GB of RAM, and a 2TB SSD. I swapped out the original components for the ones I’d bought, then loaded Linux Mint onto it.

I tucked the device away in my study after setting up Portainer and configuring a Cloudflare Tunnel so I could access it over the web from outside my home network. For months afterward, I managed everything from my PC, using a combination of SSH and Portainer to deploy new services and maintain existing ones.

After months of going through this routine, I decided to build a Model Context Protocol (MCP) server that provisions tools for AI agents to interact with my homelab on my behalf.

how it works

Here’s what it looks like in practice: I send a message to an AI agent (Opencode, Hermes, Claude code, etc), it picks the appropriate tools registered on my MCP server, and that tool runs on the homelab, either as Linux commands or Portainer API calls to deploy and manage stacks. All the low-level details are handled by the agents.

When the MCP server is registered with an AI agent, the agent fetches the full tools list. It knows the name, description, and parameters of every tool. When a message comes in, the agent reasons about which tool fits, constructs the arguments, calls it, reads the raw output, and replies in plain English.

examples of things agents can do

What I sayTool calledWhat runs on arrakis
”Is Plex running?”list_containersdocker ps
”Show me Sonarr logs”container_logsdocker logs sonarr
”How much RAM is free?”memory_usagefree -h
”Restart qbittorrent”restart_containerdocker restart qbittorrent
”What’s using port 8080?”open_portsss -tlnp
”Can arrakis reach Google?”ping_hostping -c 4 google.com
”Deploy a new nginx stack”deploy_stackPortainer API
”What failed services are there?”failed_servicessystemctl --failed
”Check the health of /dev/sda”drive_healthsmartctl
”Read the nginx config file”read_filecat
”Find large log files”large_log_filesfind /var/log

tools

docker

ToolDescription
list_containersList running/stopped containers
container_logsGet logs for a container
restart_containerRestart a container by name
container_statsCPU and memory per container

portainer stacks

ToolDescription
list_stacksList all Portainer stacks
deploy_stackDeploy a new stack from a compose string
update_stackUpdate and redeploy an existing stack
get_stack_fileRead the compose file of a stack
start_stackStart a stopped stack
stop_stackStop a running stack
delete_stackPermanently delete a stack

system

ToolDescription
disk_usageDisk usage across mounts
memory_usageRAM and swap usage
system_uptimeUptime and load average
top_processesTop processes by CPU or memory
disk_ioDisk I/O stats per device
vm_statsMemory, swap, and CPU pressure
cpu_infoCPU architecture and core info
kernel_messagesRecent dmesg output
cpu_tempsCPU and board temperatures

services

ToolDescription
failed_servicesList failed systemd services
service_statusStatus of a systemd service
service_controlStart/stop/restart/enable/disable a service
logged_in_usersUsers currently logged in
login_historyRecent login history
list_cron_jobsCron jobs for a user

storage

ToolDescription
block_devicesBlock devices and mount points
inode_usageInode usage per filesystem
drive_healthSMART health status of a drive
large_log_filesFind large files in a directory
pending_updatesPending apt package updates

network

ToolDescription
open_portsListening ports on the host
ping_hostCheck connectivity to a host
active_connectionsActive network connections
routing_tableHost routing table
firewall_rulesiptables firewall rules
http_checkHTTP response code and latency for a URL
dns_lookupDNS lookup from the host

logs

ToolDescription
journal_logsSystemd journal logs for a service

filesystem

ToolDescription
read_fileRead a file from the host
tail_fileRead the last N lines of a file
write_fileWrite content to a file on the host
grep_filesSearch for a pattern in files
find_filesFind files by name or type
dir_sizeDisk size of a directory
list_dirList directory contents
make_dirCreate a directory
copy_fileCopy a file or directory
move_fileMove or rename a file
delete_fileDelete a file or directory
which_commandCheck if commands are available on the host
run_commandRun an arbitrary shell command on the host

boundary

The agent can only use what I give it. Every tool is explicitly defined in the server with specific parameters it can’t go beyond them. Tools like run_command, write_file, delete_file, and deploy_stack are powerful by design, so the server itself stays locked down behind a Cloudflare Tunnel with authentication. The exposed surface is intentional and auditable: I can see exactly which tools exist and what they do.