Skip to main content
Glama
Xinyuan-LilyGO

lilygo-doc-mcp

Official

lilygo-doc-mcp

English | 简体中文

MCP server for LILYGO product documentation. Exposes LILYGO hardware docs as structured tools for LLM clients via the Model Context Protocol.

Documentation is served from a local sparse git checkout of Xinyuan-LilyGO/documentation. No runtime GitHub API calls — zero rate limit issues. Docs can stay up to date automatically via a GitHub webhook.

Hosted service

The production service is available at these public endpoints:

Endpoint

Method

Description

https://mcp.lilygotech.com/sse

GET

MCP SSE connection endpoint used by MCP clients.

https://mcp.lilygotech.com/health

GET

Health endpoint returning { status, products }.

https://mcp.lilygotech.com/webhook

POST

GitHub push webhook used to update the documentation checkout.

Connect an MCP client to the hosted service with:

{
  "mcpServers": {
    "lilygo-docs": {
      "type": "sse",
      "url": "https://mcp.lilygotech.com/sse"
    }
  }
}

The SSE transport advertises a session-specific https://mcp.lilygotech.com/messages?sessionId=... endpoint automatically. MCP clients manage that endpoint; do not configure or call it manually.

The webhook URL is public but accepts GitHub POST requests only. Configure GITHUB_WEBHOOK_SECRET and use the same value in the GitHub webhook settings before exposing it; when the variable is empty, signature verification is skipped.

Related MCP server: Godot Docs MCP

Architecture

flowchart LR
    CLIENT["MCP clients"]
    MONITOR["Health monitoring"]

    subgraph GITHUB["GitHub"]
        APP_REPO["Xinyuan-LilyGO/lilygo-doc-mcp"]
        ACTIONS["GitHub Actions<br/>test, build, and deploy"]
        GHCR["GitHub Container Registry<br/>latest and sha-* images"]
        DOCS_REPO["Xinyuan-LilyGO/documentation<br/>en/products"]
    end

    subgraph HOST["Production server"]
        COMPOSE["Docker Compose<br/>application deployment"]
        NPM["Nginx Proxy Manager<br/>mcp.lilygotech.com<br/>TLS, SSE proxying, and limits"]
        subgraph CONTAINER["lilygo-doc-mcp container"]
            MCP["Node.js MCP server"]
            DOCS["Sparse documentation checkout<br/>vendor/docs/en/products"]
        end
    end

    APP_REPO -->|"push to master"| ACTIONS
    DOCS_REPO -->|"sparse clone during image build"| ACTIONS
    ACTIONS -->|"build and publish"| GHCR
    ACTIONS -->|"SSH: upload Compose files and restart"| COMPOSE
    GHCR -->|"pull image"| COMPOSE
    COMPOSE -->|"create or update"| MCP

    CLIENT -->|"HTTPS: GET /sse, POST /messages"| NPM
    MONITOR -->|"HTTPS: GET /health"| NPM
    DOCS_REPO -->|"HTTPS: push event to POST /webhook"| NPM
    NPM -->|"HTTP over npm_proxy"| MCP

    MCP -->|"run update-docs.mjs"| DOCS
    DOCS_REPO -->|"git pull --ff-only"| DOCS
    DOCS -->|"reload product cache"| MCP

GitHub Actions deploys the MCP application but does not deploy Nginx Proxy Manager; the production server must provide NPM and the external npm_proxy network. A valid push webhook returns 202 Accepted, then the server updates the sparse checkout and reloads its in-memory product cache asynchronously.

Quick start

1. Clone and install

git clone https://github.com/Xinyuan-LilyGO/lilygo-doc-mcp.git
cd lilygo-doc-mcp
npm install
npm run docs:init
npm run build

npm run docs:init clones only the en/products documentation subtree into vendor/docs.

To point at another docs checkout, set DOCS_REPO_DIR before running the command:

DOCS_REPO_DIR=/path/to/documentation npm run docs:update

2. Start the server

PORT=3000 npm start

3. Connect your MCP client

{
  "mcpServers": {
    "lilygo-docs": {
      "type": "sse",
      "url": "http://localhost:3000/sse"
    }
  }
}

Keeping docs up to date

Manual update

npm run docs:update

Then restart the server (or let the webhook do it automatically).

Automatic via GitHub webhook

Set up a webhook on the Xinyuan-LilyGO/documentation repository:

  1. Go to Settings → Webhooks → Add webhook

  2. Set Payload URL to https://mcp.lilygotech.com/webhook (or the corresponding URL for a self-hosted domain)

  3. Set Content type to application/json

  4. Set Secret to the exact value configured as GITHUB_WEBHOOK_SECRET on the server

  5. Choose Just the push event

Start the server with the webhook secret:

GITHUB_WEBHOOK_SECRET=your-secret PORT=3000 npm start

Do not expose /webhook with an empty GITHUB_WEBHOOK_SECRET, because the server skips signature verification when no secret is configured.

On every push to the documentation repo, the server will:

  1. Run node scripts/update-docs.mjs

  2. Reload the in-memory product cache. Product categories are discovered automatically.

Logging

The server logs MCP SSE connections, message requests, disconnections, and tool calls. Tool-call logs include the tool name and arguments, but not returned document content.

Follow logs from Docker with:

docker logs -f lilygo-doc-mcp

Tools

Tool

Description

list_products

List all products, filter by series / tags / keyword

get_product

Get full docs plus the programming guide, or a specific section (overview, quickstart, features, parameters, pins, faq)

get_product_guide

Get the dedicated quick-start.md programming guide, including SDK setup, dependencies, and code examples

search_products

Full-text search across product pages and programming guides with ranked excerpts

get_product_specs

Extract structured specs: key features, parameter table, pin tables

Environment variables

Variable

Default

Description

PORT

3000

HTTP server port

GITHUB_WEBHOOK_SECRET

(empty)

GitHub webhook secret for signature verification. If unset, signature check is skipped.

DOCS_DIR

vendor/docs/en/products

Path to local documentation directory

DOCS_REPO_DIR

vendor/docs

Path to the local documentation git checkout updated by docs:init, docs:update, and webhook pushes

DOCS_REPO_URL

https://github.com/Xinyuan-LilyGO/documentation.git

Documentation repository URL

DOCS_REPO_BRANCH

master

Documentation repository branch

DOCS_SPARSE_PATH

en/products

Sparse checkout path to serve

Docker deployment

Both deployment methods require Docker Engine with the Docker Compose plugin. Clone this repository on the server before following either method.

Option 1: standalone deployment

Use this method for local-only access, direct LAN access, or when an external reverse proxy is not required. It uses only compose.yaml and creates a private Docker network automatically. It does not provide TLS termination.

Create the runtime configuration:

git clone https://github.com/Xinyuan-LilyGO/lilygo-doc-mcp.git
cd lilygo-doc-mcp
cp .env.example .env

Edit .env before starting the service:

LILYGO_DOC_MCP_IMAGE=ghcr.io/xinyuan-lilygo/lilygo-doc-mcp:latest
LILYGO_DOC_MCP_BIND_ADDRESS=127.0.0.1
LILYGO_DOC_MCP_PORT=3000
GITHUB_WEBHOOK_SECRET=replace-with-a-random-secret
  • Keep LILYGO_DOC_MCP_BIND_ADDRESS=127.0.0.1 when only software on the same server needs access.

  • Set it to 0.0.0.0 only when direct LAN access is intentional and the host firewall restricts access appropriately.

  • Replace GITHUB_WEBHOOK_SECRET with a strong random value before exposing /webhook.

For example, generate a 32-byte hexadecimal secret and place the output in .env:

openssl rand -hex 32

Pull and start the service:

docker compose pull
docker compose up -d --wait

Verify the health endpoint and inspect the service state:

curl http://127.0.0.1:3000/health
docker compose ps
docker compose logs --tail=100 lilygo-doc-mcp

To update or stop a standalone deployment:

# Update
docker compose pull
docker compose up -d --remove-orphans --wait

# Stop and remove the container
docker compose down

To build the current checkout instead of pulling the published image:

docker compose -f compose.yaml -f compose.local.yaml up -d --build --wait

Option 2: deployment with Nginx Proxy Manager

Use this method for the public https://mcp.lilygotech.com endpoint. Nginx Proxy Manager (NPM) remains a separate, server-level service, while compose.npm.yaml attaches this application to NPM's shared Docker network.

Create the shared network before starting either stack:

docker network inspect npm_proxy >/dev/null 2>&1 || docker network create npm_proxy

NPM itself must also join this network. The persistent approach is to add the external network to the NPM Compose configuration and recreate the NPM service:

services:
  app:
    networks:
      - default
      - npm_proxy

networks:
  npm_proxy:
    external: true
    name: npm_proxy

The NPM service is commonly named app; use its actual service name when it differs. Apply the NPM Compose change before deploying this application:

cd /opt/nginx-proxy-manager
docker compose up -d

Then prepare this application's runtime configuration:

git clone https://github.com/Xinyuan-LilyGO/lilygo-doc-mcp.git
cd lilygo-doc-mcp
cp .env.example .env

Keep LILYGO_DOC_MCP_BIND_ADDRESS=127.0.0.1, select the required host port in .env, and replace GITHUB_WEBHOOK_SECRET with a strong random value. Start the application with both Compose files:

docker compose -f compose.yaml -f compose.npm.yaml pull
docker compose -f compose.yaml -f compose.npm.yaml up -d --wait

The service joins both its private default network and the external npm_proxy network. NPM reaches it by container name and port, so the host loopback binding does not prevent proxy access.

Create an NPM Proxy Host with these forwarding settings:

Setting

Value

Domain Names

mcp.lilygotech.com

Scheme

http

Forward Hostname / IP

lilygo-doc-mcp

Forward Port

3000

Configure the SSL certificate and Force SSL in NPM. For reliable long-lived SSE connections, add the following to the Proxy Host's Advanced configuration:

proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;

The following global NPM configuration is recommended for limiting concurrent SSE connections and message request rates. Save it as data/nginx/custom/http.conf inside the NPM installation (for example, /opt/nginx-proxy-manager/data/nginx/custom/http.conf):

map "$host:$uri" $mcp_sse_ip_key {
    default "";
    "mcp.lilygotech.com:/sse" $binary_remote_addr;
}

map "$host:$uri" $mcp_sse_total_key {
    default "";
    "mcp.lilygotech.com:/sse" $host;
}

map "$host:$uri" $mcp_message_key {
    default "";
    "mcp.lilygotech.com:/messages" $binary_remote_addr;
}

limit_conn_zone $mcp_sse_ip_key zone=mcp_sse_ip:10m;
limit_conn_zone $mcp_sse_total_key zone=mcp_sse_total:10m;
limit_req_zone $mcp_message_key zone=mcp_messages:10m rate=600r/m;

limit_conn mcp_sse_ip 10;
limit_conn mcp_sse_total 500;
limit_req zone=mcp_messages burst=60 nodelay;

limit_conn_status 429;
limit_req_status 429;

This configuration allows up to 10 concurrent /sse connections per client IP, 500 total /sse connections, and an average of 600 /messages requests per minute per client IP with a burst of 60. Requests for other hosts and paths use empty map keys and are not counted by these limits.

If a different domain is used, replace all three occurrences of mcp.lilygotech.com before loading the configuration. Validate and reload NPM after changing it:

cd /opt/nginx-proxy-manager
docker compose exec app nginx -t
docker compose restart app

The NPM Compose service is normally named app; adjust the command if the local service name is different.

Verify the public endpoint after NPM reloads:

curl https://mcp.lilygotech.com/health
docker compose -f compose.yaml -f compose.npm.yaml ps

To update or stop this deployment, always specify both Compose files:

# Update
docker compose -f compose.yaml -f compose.npm.yaml pull
docker compose -f compose.yaml -f compose.npm.yaml up -d --remove-orphans --wait

# Stop and remove the application container
docker compose -f compose.yaml -f compose.npm.yaml down

GitHub Actions deployment

The workflow in .github/workflows/deploy.yml runs tests for pull requests. A push to master runs the tests, publishes latest and sha-* images to GHCR, and deploys the latest image to the production server using Option 2, including compose.npm.yaml. It can also be started manually with Run workflow; select the master branch to run the publish and deploy jobs.

GitHub environment configuration

Create an Environment named production under Settings > Environments > New environment, then configure these Environment secrets:

Secret

Required

Description

DEPLOY_HOST

Yes

Production server hostname or IP address, without a URL scheme.

DEPLOY_USER

Yes

SSH user used for deployment.

DEPLOY_SSH_KEY

Yes

Complete, passphrase-free OpenSSH private key dedicated to deployment. Install its public key in the deployment user's ~/.ssh/authorized_keys.

DEPLOY_KNOWN_HOSTS

Yes

Trusted known_hosts entry for the production SSH server.

Configure these Environment variables when the defaults are not suitable:

Variable

Required

Default

Description

DEPLOY_PORT

No

22

Production server SSH port.

DEPLOY_PATH

No

/opt/lilygo-doc-mcp

Directory receiving the deployment files and persistent .env.

GITHUB_TOKEN is created automatically by GitHub Actions and is used to publish the container image. Do not add a separate secret for it. The workflow has only the contents: read and packages: write permissions required for this operation.

Generate DEPLOY_KNOWN_HOSTS from a trusted machine, then verify the server fingerprint before saving the output as a GitHub secret:

ssh-keyscan -p 22 -H your-server.example.com

Use the configured DEPLOY_PORT instead of 22 when SSH listens on a different port.

Production server requirements

Before the first Actions deployment, verify that:

  • Docker Engine and the Docker Compose plugin are installed.

  • DEPLOY_USER can run docker without an interactive password prompt.

  • DEPLOY_USER can create and write to DEPLOY_PATH. Pre-create the directory when the user cannot write to its parent directory.

  • The GHCR package is public, or the server has already authenticated to ghcr.io with permission to pull it.

  • Nginx Proxy Manager is attached to the external Docker network named npm_proxy and has the Proxy Host configuration described above.

  • DNS for mcp.lilygotech.com points to the production server and inbound ports 80 and 443 are available to NPM.

The first deployment creates DEPLOY_PATH/.env and generates GITHUB_WEBHOOK_SECRET. Later deployments preserve this file. To change runtime settings such as the published port, image, or webhook secret, edit the server-side .env:

cd /opt/lilygo-doc-mcp
vi .env
docker compose -f compose.yaml -f compose.npm.yaml up -d --remove-orphans --wait

When DEPLOY_PATH is customized, use that path instead. For a fork or renamed repository, set LILYGO_DOC_MCP_IMAGE in the server-side .env to the image published by that repository, for example ghcr.io/owner/lilygo-doc-mcp:latest.

License

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • @latest documentation and code examples to 9000+ libraries for LLMs and AI code editors in a singl…

  • Search and read the StitchAPI docs: search_docs finds relevant sections, get_doc reads a page.

  • Get up-to-date, version-specific documentation and code examples from official sources directly in…

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Xinyuan-LilyGO/lilygo-doc-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server