Skip to main content

Huawei PixLab + Raspberry Pi + Poke MCP Printing Deployment Guide

·2191 words ·8 mins
Author
Afterglow Sampling
Notes on technical practice, life, and fragments of thought.
Table of Contents

This guide is for users who want to connect a local-network printer to Poke. The goal is to:

  • connect a Huawei PixLab printer on the local network to a Raspberry Pi;
  • manage the print queue through CUPS;
  • expose printing capabilities to Poke through MCP;
  • let Poke upload files to the Raspberry Pi and print them;
  • protect the public endpoint with a Bearer API key; and
  • automatically delete uploaded files after seven days.

This guide uses a Huawei PixLab V1 as an example. Other printers that support AirPrint, IPP, or driverless printing can follow the same approach.

1. Final Architecture
#

Poke
  │  HTTPS + Authorization: Bearer <MCP_API_KEY>
Cloudflare Tunnel
Raspberry Pi 127.0.0.1:3000
mcp-compat-proxy.mjs
  ├─ Authentication
  ├─ Poke-compatible MCP sessions
  ├─ File upload tools
  ├─ print_url download tool
  └─ Printer alias and option normalization
Raspberry Pi 127.0.0.1:3001
lan-mcp-cups
CUPS
Huawei PixLab driverless queue

Do not expose CUPS port 631 directly to the public internet. Expose only the authenticated MCP endpoint.

2. Included Files
#

The accompanying files are included with this site. Download them from the following paths, or create files with the same names manually on the deployment machine:

/downloads/huawei-printer-mcp/mcp-compat-proxy.mjs
/downloads/huawei-printer-mcp/huawei-printer-mcp-upstream.service
/downloads/huawei-printer-mcp/huawei-printer-mcp-proxy.service
/downloads/huawei-printer-mcp/cleanup-uploads.sh
/downloads/huawei-printer-mcp/huawei-printer-upload-cleanup.service
/downloads/huawei-printer-mcp/huawei-printer-upload-cleanup.timer

When copying these files to the Raspberry Pi, the default installation directory is:

/home/pi/huawei-printer-mcp/

If your username is not pi, replace every /home/pi in the examples and the User=pi and Group=pi values in the systemd units with your actual username.

3. Prerequisites
#

The Raspberry Pi needs:

  • Debian or Raspberry Pi OS;
  • to be on the same local network as the printer;
  • SSH installed and enabled;
  • internet access for Cloudflare Tunnel and npm installation; and
  • a domain that can be used with Cloudflare Tunnel.

Install the base packages:

sudo apt update
sudo apt install -y \
  cups cups-client cups-bsd \
  cups-browsed cups-filters avahi-daemon \
  curl openssl

Notes:

  • cups and cups-client: the CUPS printing system;
  • cups-bsd: provides lpr, which lan-mcp-cups uses for print_file;
  • cups-browsed and cups-filters: provide driverless and auto-discovered queues; and
  • avahi-daemon: discovers .local, Bonjour, and AirPrint devices.

Enable CUPS:

sudo systemctl enable --now cups
sudo systemctl enable --now cups-browsed
sudo systemctl enable --now avahi-daemon

To manage CUPS in a browser:

sudo cupsctl --remote-any --remote-admin --share-printers
sudo usermod -aG lpadmin "$USER"
sudo systemctl restart cups

Open:

https://<Raspberry-Pi-IP>:631

4. Install Node.js and lan-mcp-cups
#

Verify Node.js:

node -v
npm -v

Node.js 20 or later is recommended.

Install lan-mcp-cups:

sudo npm install -g lan-mcp-cups
command -v lan-mcp-cups

The output should resemble:

/usr/local/bin/lan-mcp-cups

5. Configure the CUPS Print Queue
#

First, inspect auto-discovered printers:

lpstat -p -d
lpstat -v
lpoptions -p <printer-name> -l

A typical auto-discovered Huawei PixLab queue looks like this:

HUAWEI_PixLab_V1_0374

Prefer this driverless auto-discovered queue over a manually created generic Printer - IPP Everywhere queue. The latter can produce blank pages or printer-side job cancellation for some PDF or image jobs.

Check the queue driver:

grep -Ei 'NickName|ModelName' /etc/cups/ppd/HUAWEI_PixLab_V1_0374.ppd

The ideal output includes:

HUAWEI PixLab V1, driverless, cups-filters

Set the default printer:

sudo lpadmin -d HUAWEI_PixLab_V1_0374
lpoptions -d HUAWEI_PixLab_V1_0374

Set common default options:

sudo lpadmin \
  -p HUAWEI_PixLab_V1_0374 \
  -o ColorModel=Gray \
  -o PageSize=A4 \
  -o MediaType=Stationery \
  -o cupsPrintQuality=Normal \
  -o sides=one-sided \
  -o print-scaling=auto-fit

Verify the queue:

lpstat -p -d
lpoptions -p HUAWEI_PixLab_V1_0374

6. Deploy the MCP Files
#

Create the directory:

mkdir -p /home/pi/huawei-printer-mcp/uploads
chmod 700 /home/pi/huawei-printer-mcp/uploads

Copy the accompanying files to the Raspberry Pi:

scp huawei-printer-mcp-poke-files/mcp-compat-proxy.mjs \
  pi@<Raspberry-Pi-IP>:/home/pi/huawei-printer-mcp/

scp huawei-printer-mcp-poke-files/huawei-printer-mcp-upstream.service \
  pi@<Raspberry-Pi-IP>:/home/pi/huawei-printer-mcp/

scp huawei-printer-mcp-poke-files/huawei-printer-mcp-proxy.service \
  pi@<Raspberry-Pi-IP>:/home/pi/huawei-printer-mcp/

scp huawei-printer-mcp-poke-files/cleanup-uploads.sh \
  pi@<Raspberry-Pi-IP>:/home/pi/huawei-printer-mcp/

scp huawei-printer-mcp-poke-files/huawei-printer-upload-cleanup.service \
  pi@<Raspberry-Pi-IP>:/home/pi/huawei-printer-mcp/

scp huawei-printer-mcp-poke-files/huawei-printer-upload-cleanup.timer \
  pi@<Raspberry-Pi-IP>:/home/pi/huawei-printer-mcp/

Make the script executable:

chmod 755 /home/pi/huawei-printer-mcp/cleanup-uploads.sh

7. Generate an MCP API Key
#

This key is only for Poke to access your printing MCP. It is neither a Poke API key nor a Cloudflare token.

openssl rand -hex 32 > /home/pi/huawei-printer-mcp/mcp-api-key
chmod 600 /home/pi/huawei-printer-mcp/mcp-api-key

View the key:

cat /home/pi/huawei-printer-mcp/mcp-api-key

Later, enter only the character string itself in Poke’s API Key field. Do not prepend Bearer .

8. Install the systemd Services
#

Install the two MCP services:

sudo install -o root -g root -m 0644 \
  /home/pi/huawei-printer-mcp/huawei-printer-mcp-upstream.service \
  /etc/systemd/system/huawei-printer-mcp-upstream.service

sudo install -o root -g root -m 0644 \
  /home/pi/huawei-printer-mcp/huawei-printer-mcp-proxy.service \
  /etc/systemd/system/huawei-printer-mcp-proxy.service

sudo systemctl daemon-reload
sudo systemctl enable --now huawei-printer-mcp-upstream.service
sudo systemctl enable --now huawei-printer-mcp-proxy.service

The services are:

huawei-printer-mcp-upstream.service
  lan-mcp-cups, listening on 127.0.0.1:3001

huawei-printer-mcp-proxy.service
  Authenticated session bridge, listening on 127.0.0.1:3000

Check them:

systemctl is-enabled huawei-printer-mcp-upstream.service
systemctl is-active huawei-printer-mcp-upstream.service

systemctl is-enabled huawei-printer-mcp-proxy.service
systemctl is-active huawei-printer-mcp-proxy.service

ss -lntp | grep 3000
ss -lntp | grep 3001

View logs:

journalctl -u huawei-printer-mcp-upstream.service -n 50 --no-pager
journalctl -u huawei-printer-mcp-proxy.service -n 50 --no-pager

Important environment variables in huawei-printer-mcp-proxy.service:

MCP_PROXY_API_KEY_FILE=/home/pi/huawei-printer-mcp/mcp-api-key
MCP_UPLOAD_DIR=/home/pi/huawei-printer-mcp/uploads
MCP_MAX_UPLOAD_BYTES=78643200
MCP_PRINTER_ALIAS=Huawei_PixLab
MCP_TARGET_PRINTER=HUAWEI_PixLab_V1_0374

78643200 bytes equals 75 MiB.

9. Automatically Clean Uploaded Files After Seven Days
#

Install the cleanup service and timer:

sudo install -o root -g root -m 0644 \
  /home/pi/huawei-printer-mcp/huawei-printer-upload-cleanup.service \
  /etc/systemd/system/huawei-printer-upload-cleanup.service

sudo install -o root -g root -m 0644 \
  /home/pi/huawei-printer-mcp/huawei-printer-upload-cleanup.timer \
  /etc/systemd/system/huawei-printer-upload-cleanup.timer

sudo systemctl daemon-reload
sudo systemctl enable --now huawei-printer-upload-cleanup.timer

The cleanup policy is:

Directory: /home/pi/huawei-printer-mcp/uploads
Retention: 7 days
Frequency: once per day

Run a dry run first:

sudo -u pi -H env \
  DRY_RUN=1 \
  MCP_UPLOAD_DIR=/home/pi/huawei-printer-mcp/uploads \
  MCP_UPLOAD_RETENTION_DAYS=7 \
  /home/pi/huawei-printer-mcp/cleanup-uploads.sh

View the timer:

systemctl list-timers --all huawei-printer-upload-cleanup.timer --no-pager

Run cleanup manually now:

sudo systemctl start huawei-printer-upload-cleanup.service

10. Configure Cloudflare Tunnel
#

Create a tunnel in Cloudflare Zero Trust:

Zero Trust
→ Networks
→ Tunnels
→ Create a tunnel

After installing cloudflared on the Raspberry Pi, install the service using the command provided by the Cloudflare page.

Example public hostname:

Hostname: printer-mcp.example.com
Service Type: HTTP
Service URL: http://127.0.0.1:3000

Notes:

  • Cloudflare points to 127.0.0.1:3000;
  • do not point it to 3001;
  • do not point it to CUPS port 631; and
  • add /mcp when entering the URL in Poke.

Check:

systemctl status cloudflared --no-pager
curl -i https://printer-mcp.example.com/mcp

Without an API key, it should return:

HTTP 401 Unauthorized

11. Add the MCP Server in Poke
#

Fill in Poke’s custom integration as follows:

Name:
Huawei Printer

MCP Server URL:
https://printer-mcp.example.com/mcp

API Key:
<the complete contents of /home/pi/huawei-printer-mcp/mcp-api-key>

Do not enter:

Bearer xxxxx

Enter only:

xxxxx

12. Tools Available in Poke
#

After deployment, Poke should show these tools:

list_printers
print_file
add_printer
upload_file
upload_and_print_file
print_url

Recommended:

print_url

When Poke can obtain an attachment download URL, let the Raspberry Pi download and print it.

You can also use:

upload_and_print_file

When Poke can send file contents to MCP as base64 or plain text, this uploads and prints the file immediately.

To upload without printing:

upload_file

13. Tool Call Examples
#

1. Upload Text Only
#

{
  "name": "upload_file",
  "arguments": {
    "file_name": "note.txt",
    "content_text": "hello printer\n"
  }
}

2. Upload a Base64 File and Print It
#

{
  "name": "upload_and_print_file",
  "arguments": {
    "file_name": "document.pdf",
    "content_base64": "<base64>",
    "printer": "Huawei_PixLab",
    "copies": 1,
    "options": "ColorModel=Gray PageSize=A4 MediaType=Stationery cupsPrintQuality=Normal sides=one-sided print-scaling=auto-fit"
  }
}

The proxy automatically maps Huawei_PixLab to:

HUAWEI_PixLab_V1_0374

3. Download a URL and Print It
#

{
  "name": "print_url",
  "arguments": {
    "url": "https://example.com/file.pdf",
    "file_name": "file.pdf",
    "printer": "Huawei_PixLab",
    "copies": 1,
    "options": "ColorModel=Gray PageSize=A4 sides=one-sided"
  }
}

Security limits:

  • only http and https are supported;
  • localhost and private-network addresses are rejected by default;
  • the maximum file size is 75 MiB; and
  • uploaded files are deleted automatically after seven days.

14. Verification Commands
#

Requests Without an API Key Must Be Rejected
#

curl -i https://printer-mcp.example.com/mcp

Expected:

HTTP/2 401
www-authenticate: Bearer

Initialize With an API Key
#

MCP_KEY="$(cat /home/pi/huawei-printer-mcp/mcp-api-key)"

curl -i \
  -X POST https://printer-mcp.example.com/mcp \
  -H "Authorization: Bearer $MCP_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  --data-raw '{
    "jsonrpc":"2.0",
    "id":1,
    "method":"initialize",
    "params":{
      "protocolVersion":"2025-03-26",
      "capabilities":{},
      "clientInfo":{"name":"manual-test","version":"1.0.0"}
    }
  }'

The response headers should include:

mcp-session-id: ...

15. Common Issues
#

1. spawn lpr ENOENT
#

Cause: cups-bsd is not installed, so the system does not have lpr.

Fix:

sudo apt install -y cups-bsd
command -v lpr

2. lpr: unable to access "127.0.0.1"
#

Cause: MCP_CUPS_SERVER=127.0.0.1 was set for lan-mcp-cups. It adds -h 127.0.0.1 to lpr, causing 127.0.0.1 to be treated as a file name.

Fix: do not set these for a local CUPS installation:

MCP_CUPS_SERVER
MCP_CUPS_PORT

Keep only:

MCP_CUPS_DEFAULT_PRINTER
MCP_CUPS_HTTP_HOST
MCP_CUPS_HTTP_PORT

3. Invalid Request: Server already initialized
#

Cause: the HTTP transport in lan-mcp-cups does not handle repeated initialization well. This can be triggered when Poke or the proxy retries.

Fix: use the mcp-compat-proxy.mjs session bridge from this guide. It exposes multiple client sessions to Poke while reusing a single upstream session.

4. Blank Pages or Printer-Side Job Cancellation
#

First check the queue driver:

grep -Ei 'NickName|ModelName' /etc/cups/ppd/<queue-name>.ppd

Use a driver that resembles:

HUAWEI PixLab V1, driverless, cups-filters

Avoid the generic queue:

Printer - IPP Everywhere

Also ensure the print options use names supported by the queue:

ColorModel=Gray
PageSize=A4
MediaType=Stationery
cupsPrintQuality=Normal
sides=one-sided
print-scaling=auto-fit

5. Poke Shows No Tools
#

Check:

journalctl -u huawei-printer-mcp-proxy.service -n 100 --no-pager
journalctl -u huawei-printer-mcp-upstream.service -n 100 --no-pager

Confirm the public endpoint can show tools with an API key:

MCP_KEY="$(cat /home/pi/huawei-printer-mcp/mcp-api-key)"
curl -i https://printer-mcp.example.com/mcp \
  -H "Authorization: Bearer $MCP_KEY"

If Poke has cached an old tool list, remove and add the integration again, or refresh the connection in Poke.

16. Maintenance Commands
#

Restart MCP:

sudo systemctl restart huawei-printer-mcp-upstream.service huawei-printer-mcp-proxy.service

View status:

systemctl status huawei-printer-mcp-upstream.service --no-pager
systemctl status huawei-printer-mcp-proxy.service --no-pager

View uploaded files:

ls -lh /home/pi/huawei-printer-mcp/uploads

Adjust the upload size, for example to 100 MiB:

sudo systemctl edit huawei-printer-mcp-proxy.service

Enter:

[Service]
Environment=MCP_MAX_UPLOAD_BYTES=104857600

Then:

sudo systemctl daemon-reload
sudo systemctl restart huawei-printer-mcp-proxy.service

Adjust the retention period, for example to 14 days:

sudo systemctl edit huawei-printer-upload-cleanup.service

Enter:

[Service]
Environment=MCP_UPLOAD_RETENTION_DAYS=14

Then:

sudo systemctl daemon-reload
sudo systemctl restart huawei-printer-upload-cleanup.timer

17. Security Recommendations
#

  • Give the API key only to Poke.
  • Do not share /home/pi/huawei-printer-mcp/mcp-api-key with anyone.
  • Have Cloudflare Tunnel forward only to 127.0.0.1:3000.
  • Do not expose CUPS port 631 to the public internet.
  • Regularly check the upload directory size:
du -sh /home/pi/huawei-printer-mcp/uploads
  • For a Poke integration shared by multiple people, limit the default copy count. In Poke rules, require confirmation for jobs longer than 10 pages or with more than one copy.

评论将在滚动到此处时加载。