Skip to main content
Glama
SafaAslan

Engwe N1 Air MCP Server

by SafaAslan

🚲 Engwe N1 Air β€” BLE Reverse Engineering + Claude MCP Server

Reverse engineered the Engwe N1 Air e-bike's Bluetooth protocol and built a Claude AI integration to control it from your Mac.

License Python Node

What This Does

  • πŸš€ Unlock speed limit via Bluetooth (up to 40 km/h)

  • πŸ”’ Lock/unlock the bike remotely via IoT API

  • πŸ”Š Find your bike (sound + light alarm)

  • πŸ”‹ Battery, mileage, cadence real-time stats

  • πŸ“ Geo-fence management

  • πŸ’ͺ PAS level control via Bluetooth

  • πŸ€– Claude AI integration β€” control your bike by talking to Claude

  • πŸ–₯️ Mac menubar app β€” one-click access to all features


Related MCP server: Lovense Cloud MCP

How It Was Built

Step 1 β€” API Discovery (Charles Proxy)

Captured network traffic from the Engwe iOS app using Charles Proxy. Found the main API endpoint at app-api.engweapp.com with JWT authentication.

Step 2 β€” APK Decompile (JADX)

Decompiled the Android APK using JADX to find all internal API endpoints and BLE command codes.

jadx -d engwe-source ENGWE_2.7.2_APKPure.xapk
grep -r "iot/device" engwe-source --include="*.java" | grep -o '"[^"]*iot/device[^"]*"' | sort -u

Step 3 β€” BLE Protocol Reverse Engineering

Found the complete BLE protocol in ProtocolUtil.java and BLEBikeCommand.java.

V2 Protocol Format:

456E + CMD(4) + LEN(4) + DATA + CRC16(4) + 7765

BLE UUIDs (from BluetoothRegulate.java):

Service:  00001820-0000-1000-8000-00805f9b34fb
Write:    00001822-0000-1000-8000-00805f9b34fb
Notify:   00001821-0000-1000-8000-00805f9b34fb

BLE Command Reference

All commands use V2 protocol format: 456E + CMD + LEN + DATA + CRC16 + 7765

Command

Hex

Description

Speed Limit

2A65

0x00=0, 0x10=10, 0x20=20, 0x30=30, 0x40=40 km/h

PAS Level

010A

0x00–0x05

Motor Current Limit

2A66

Under investigation

Cruise Control Set

0128

Under investigation

Wheel Diameter

08C3

Under investigation

Factory Reset

8049

⚠️ Irreversible

Lock State

0108

Query lock

Power On/Off

0107

01=on, 02=off

Auto Shutdown Time

1000

Minutes

Speed Limit Example (40 km/h):

# Index 4 * 16 = 0x40
command = "456E2A650001406A237765"

CRC16 Calculation (ModBus):

def crc16(hex_str):
    data = bytes.fromhex(hex_str)
    crc = 0xFFFF
    for byte in data:
        crc ^= byte
        for _ in range(8):
            crc = (crc >> 1) ^ 0xA001 if crc & 1 else crc >> 1
    return format(crc, "04X")

# CRC input = CMD + LEN + DATA
# Example: crc16("2A65" + "0001" + "40") = "6A23"

IoT API Endpoints

Base URL: https://app-api.engweapp.com

Endpoint

Description

/api/app/iot/device/lockSwitch

Lock/unlock bike

/api/app/iot/device/findVehicle

Sound + light alarm

/api/app/iot/device/vibrationAlarmSwitch

Vibration alarm + signal

/api/app/iot/device/fenceSwitch

Geo-fence on/off

/api/app/iot/device/getFenceList

List geo-fences

/api/app/iot/device/bleSenselessSwitch

BLE auto-unlock

/api/app/iot/device/headlightSwitch

Headlight + realtime PAS/charge

/api/app/iot/device/attr/newest

Battery SOC/SOH, mileage, cadence

/api/app/iot/device/version

IoT/BT/4G firmware versions

/api/app/iot/device/attr/newest

Real-time attributes

/api/app/paypal/syDetail

IoT subscription info

/api/app/ride-data/index

Weekly ride statistics


Installation

Requirements

  • Node.js 18+

  • Python 3.9+

  • Mac (for menubar app)

git clone https://github.com/SafaAslan/engwe-n1air-mcp
cd engwe-n1air-mcp
npm install
pip3 install bleak

Get Your Token

Use Charles Proxy to capture traffic from the Engwe iOS/Android app. Find the Authorization header in any request to app-api.engweapp.com.

Configure Claude Desktop

~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "engwe-n1air": {
      "command": "node",
      "args": ["/path/to/engwe-n1air-mcp/index.js"],
      "env": {
        "ENGWE_IMEI": "YOUR_IMEI",
        "ENGWE_BLE_MAC": "YOUR_BLE_MAC",
        "ENGWE_TOKEN": "YOUR_JWT_TOKEN"
      }
    }
  }
}

Find Your IMEI & BLE MAC

# IMEI β€” visible in Engwe app under bike settings
# BLE MAC β€” run while bike is on:
python3 -c "
import asyncio
from bleak import BleakScanner
async def scan():
    devices = await BleakScanner.discover(timeout=10)
    for d in devices:
        if d.name and 'ENGWE' in d.name.upper():
            print(d.address, d.name)
asyncio.run(scan())
"

Usage

Claude AI (via MCP)

Once configured, just talk to Claude:

  • "Lock my bike"

  • "What's my battery level?"

  • "Set speed limit to 35 km/h"

  • "Show my ride stats for this week"

Menubar App (Mac)

npm install electron
./node_modules/.bin/electron tray.js

Auto-start on Boot

chmod +x setup_autostart.sh
bash setup_autostart.sh

Speed Limit Script (standalone)

python3 ble_speed3.py

Project Structure

engwe-n1air-mcp/
β”œβ”€β”€ index.js          # Claude MCP server (18 tools)
β”œβ”€β”€ tray.js           # Mac menubar app
β”œβ”€β”€ ble_speed3.py     # Standalone speed limit script
β”œβ”€β”€ ble_scan2.py      # BLE device scanner
β”œβ”€β”€ setup_autostart.sh # Mac autostart setup
└── README.md

⚠️ Disclaimer

Unlocking the speed limit above 25 km/h is illegal on public roads in the EU. This project is for educational and off-road/private use only. Use at your own risk. This project is not affiliated with Engwe.


Contributing

Pull requests welcome! Especially interested in:

  • Testing on other Engwe models (P275 SE, M20, etc.)

  • Cruise control command (0128)

  • Motor current limit (2A66)

  • Android version of menubar app


License

MIT

Related MCP Connectors

Related MCP Servers