# NetLicensing MCP Server [![CI](https://github.com/Labs64/NetLicensing-MCP/actions/workflows/netlicensing-ci.yml/badge.svg)](https://github.com/Labs64/NetLicensing-MCP/actions/workflows/netlicensing-ci.yml) [![PyPI](https://img.shields.io/pypi/v/netlicensing_mcp)](https://pypi.org/project/netlicensing-mcp/) [![GHCR](https://img.shields.io/github/v/release/Labs64/NetLicensing-MCP?label=ghcr.io%2Flabs64%2Fnetlicensing-mcp&logo=docker&logoColor=white&style=flat-square)](https://github.com/Labs64/NetLicensing-MCP/pkgs/container/netlicensing-mcp) [![Docker Hub](https://img.shields.io/docker/v/labs64/netlicensing-mcp?logo=docker&logoColor=white&label=Docker%20Hub&color=2496ED)](https://hub.docker.com/r/labs64/netlicensing-mcp) [![MCP Registry](https://img.shields.io/badge/MCP_Registry-netlicensing--mcp-blue?logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PHBhdGggZmlsbD0id2hpdGUiIGQ9Ik0xMiAyQzYuNDggMiAyIDYuNDggMiAxMnM0LjQ4IDEwIDEwIDEwIDEwLTQuNDggMTAtMTBTMTcuNTIgMiAxMiAyek0xMSAxN3YtNkg5bDMtNCAzIDRoLTJ2NmgtMnoiLz48L3N2Zz4=&style=flat-square)](https://registry.modelcontextprotocol.io/?q=netlicensing-mcp) [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/) [![License](https://img.shields.io/badge/license-Apache%202.0-green.svg)](LICENSE) **The official [Labs64 NetLicensing](https://netlicensing.io) MCP Server** — a natural language interface that lets AI agents manage software licenses, customers, and entitlements through conversational commands. Works with Claude Desktop, GitHub Copilot (Agent mode), VS Code, JetBrains / IntelliJ IDEA, and any other MCP-compatible client. --- ## Why use this? - **Natural Language Licensing** — Ask your AI assistant to create products, issue licenses, validate entitlements, and generate shop URLs without touching the NetLicensing UI or writing API calls. - **Full API coverage** — Various tools spanning the entire NetLicensing [REST API](https://netlicensing.io/wiki/restful-api): products, modules, templates, licensees, licenses, bundles, tokens, transactions, and payment methods. - **Built-in audit prompts** — Five ready-to-run prompt templates for account audits, expiry sweeps, anomaly detection, and cleanup workflows. - **Safe by default** — All delete operations expose a `force_cascade` option; nothing is silently cascaded. - **Zero-dependency quick start** — Run with `uvx` or Docker without a local Python install. --- ## What can you ask? Once connected, you can talk to NetLicensing in plain language: - *"List all products in my NetLicensing account."* - *"Create a new licensee for `customer@example.com` under product PTEST."* - *"Validate the license for licensee L001 — does it pass?"* - *"Generate a shop URL for licensee L001 so they can self-serve their renewal."* - *"Which licenses are expiring in the next 30 days?"* - *"Find any licensees with no active licenses — flag them for cleanup."* - *"Transfer all licenses from licensee L001 to L002."* - *"Create an API key token scoped to read-only access."* - *"Show me all transactions from the last month."* --- ## Features | Area | Tools | |---|---| | **Products** | list, get, create, update, delete | | **Product Modules** | list, get, create, update, delete | | **License Templates** | list, get, create, update, delete | | **Licensees** | list, get, create, update, delete, validate, transfer | | **Licenses** | list, get, create, update (activate/deactivate), delete | | **Bundles** | list, get, create, update, delete, obtain | | **Tokens** | list, get, create shop URL, create API token, revoke | | **Transactions** | list, get, create, update | | **Payment Methods** | list, get, update | | **Utilities** | list licensing models, list license types | | **Audit Prompts** | full account, single customer, expiry sweep, cleanup, anomaly detection | | **Delete Safety** | `force_cascade` option on all delete tools | | **Redaction** | secrets (`apiKey`, `licenseeSecret`, `nodeSecret`, …) masked in all responses and logs | --- ## Security defaults The server is designed to be safe by default: - **No silent credential fallback** — if `NETLICENSING_API_KEY` is not set and `NETLICENSING_ALLOW_DEMO` is not explicitly enabled, the server refuses to start (stdio) or returns `503` (HTTP) rather than silently using demo credentials. - **Redaction layer** — every tool response passes through a redaction filter. Sensitive fields (`apiKey`, `licenseeSecret`, `nodeSecret`, `password`, `secret`) are masked to a partial form (e.g. `s3c****ecret`). The set is extendable via `MCP_REDACT_FIELDS`. - **One-time credentials** — `create_api_token` and `create_shop_token` tag their response with `"shown_once": true` so clients know the credential will not be visible in full again. Subsequent `get_token` / `list_tokens` calls return masked values. - **Delete confirmation** — all destructive operations require a two-step confirmation token flow; nothing is silently cascaded. --- ## Quick Start ### Option A — uvx (no install required) ```bash NETLICENSING_API_KEY=your_key uvx netlicensing-mcp ``` ### Option B — pip ```bash pip install netlicensing-mcp NETLICENSING_API_KEY=your_key netlicensing-mcp ``` ### Option C — Docker #### stdio (default) — for Claude Desktop / VS Code ```bash docker run -i --rm \ -e NETLICENSING_API_KEY=your_key \ ghcr.io/labs64/netlicensing-mcp:latest ``` #### HTTP mode — for remote/shared deployments ```bash docker run -d -p 8000:8000 \ -e NETLICENSING_API_KEY=your_key \ ghcr.io/labs64/netlicensing-mcp:latest http ``` #### Verbose logging (any mode) ```bash # CLI flag docker run -i --rm \ -e NETLICENSING_API_KEY=your_key \ ghcr.io/labs64/netlicensing-mcp:latest -v # Or via env var docker run -i --rm \ -e NETLICENSING_API_KEY=your_key \ -e MCP_VERBOSE=true \ ghcr.io/labs64/netlicensing-mcp:latest ``` #### Demo / sandbox mode (no API key) ```bash docker run -i --rm \ -e NETLICENSING_ALLOW_DEMO=true \ ghcr.io/labs64/netlicensing-mcp:latest ``` > **No API key?** Set `NETLICENSING_ALLOW_DEMO=true` to run against NetLicensing's built-in > sandbox with demo credentials — no account required. > The server will tag every response with `"demo_mode": true` and emit a periodic warning > so it is always clear you are not using a real account. --- ## Configuration ### Environment Variables | Variable | Required | Default | Description | |---|---|---|---| | `NETLICENSING_API_KEY` | **Yes*** | — | NetLicensing API key. Required unless `NETLICENSING_ALLOW_DEMO=true` is set. | | `NETLICENSING_ALLOW_DEMO` | No | `false` | Set to `true` to explicitly opt in to sandbox demo mode when no API key is configured. Every tool response is tagged with `"demo_mode": true` and a warning is logged every 60 seconds. **Never set this in production.** | | `NETLICENSING_BASE_URL` | No | `https://go.netlicensing.io/core/v2/rest` | Override the NetLicensing REST API base URL (e.g. for on-prem deployments). | | `MCP_TRANSPORT` | No | `stdio` | Transport mode: `stdio` (default) or `http`. Can also be passed as a CLI argument. | | `MCP_HOST` | No | `127.0.0.1` | Host address to bind the HTTP server (HTTP mode only). | | `MCP_PORT` | No | `8000` | Port to bind the HTTP server (HTTP mode only). | | `MCP_VERBOSE` | No | `false` | Enable verbose debug logging (`true`, `1`, or `yes`). Logs raw API requests/responses **with sensitive fields automatically redacted**. Can also be set via `-v` CLI flag. | | `MCP_REDACT_FIELDS` | No | — | Comma-separated list of additional field names to redact from all tool responses and log output (e.g. `MCP_REDACT_FIELDS=ssn,phone`). Extends the built-in default set: `apiKey`, `licenseeSecret`, `nodeSecret`, `password`, `secret`. | > **\* `NETLICENSING_API_KEY` and demo mode:** If neither `NETLICENSING_API_KEY` nor `NETLICENSING_ALLOW_DEMO=true` is set, the server will **refuse to start** (stdio mode) or return `503 Service Unavailable` for all tool calls (HTTP mode). This prevents accidental use of demo credentials in production. > **Note on HTTP deployments (e.g. AWS):** When running in HTTP mode over a network, you can skip setting `NETLICENSING_API_KEY` on the server. The MCP server will automatically extract the key per-request if the connecting client provides it via the `X-NetLicensing-API-Key` HTTP header, `Authorization: Bearer ` header, or `?apikey=` query parameter. --- ### Claude Desktop Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows): ```json { "mcpServers": { "netlicensing": { "command": "uvx", "args": ["netlicensing-mcp"], "env": { "NETLICENSING_API_KEY": "your_key_here" } } } } ``` Or use the official Docker image: #### stdio (default) — for Claude Desktop / VS Code ```json { "mcpServers": { "netlicensing": { "command": "docker", "args": [ "run", "-i", "--rm", "-e", "NETLICENSING_API_KEY=your_key_here", "ghcr.io/labs64/netlicensing-mcp:latest" ] } } } ``` #### HTTP mode — for remote/shared deployments ```json { "mcpServers": { "netlicensing": { "command": "docker", "args": [ "run", "-d", "-p", "8000:8000", "-e", "NETLICENSING_API_KEY=your_key_here", "ghcr.io/labs64/netlicensing-mcp:latest", "http" ] } } } ``` ### VS Code / GitHub Copilot The repo ships a `.vscode/mcp.json` that auto-configures Copilot Agent mode. Set `NETLICENSING_API_KEY` in your shell environment or a `.env` file, then click **Start** in the editor banner that appears above `mcp.json`. ### JetBrains / IntelliJ IDEA In Copilot Chat → Agent mode → Tools icon → **Add More Tools…** — paste the same JSON block shown in the Claude Desktop section above. --- ## Audit Prompt Templates Five built-in prompts accessible in Copilot Agent and Claude Desktop: | Prompt | Purpose | |---|---| | `audit_full` | End-to-end account audit for a product | | `audit_customer` | Deep-dive on a single licensee | | `audit_expiry` | Find licenses expiring within N days and generate renewal URLs | | `audit_cleanup` | Identify inactive / orphaned licenses for cleanup | | `audit_anomaly` | Detect unusual usage patterns across all customers | --- ## Troubleshooting **Check MCP server logs** ```bash # macOS / Claude Desktop tail -f ~/Library/Logs/Claude/mcp-server-netlicensing.log # Windows Get-Content "$env:APPDATA\Claude\Logs\mcp-server-netlicensing.log" -Wait ``` **Run the MCP Inspector** (browser UI at `http://localhost:5173`) ```bash mcp dev src/netlicensing_mcp/server.py ``` **Common issues** | Symptom | Likely cause | Fix | |---|---|---| | `401 Unauthorized` responses | Invalid or expired API key | Regenerate your key at [ui.netlicensing.io](https://ui.netlicensing.io) | | Server not listed in Claude | Config file JSON syntax error | Validate with `python -m json.tool claude_desktop_config.json` | | `uvx: command not found` | `uv` not installed | `pip install uv` or see [docs.astral.sh/uv](https://docs.astral.sh/uv) | | Server exits immediately / `503` on all calls | `NETLICENSING_API_KEY` not set and demo mode not enabled | Set `NETLICENSING_API_KEY`, or set `NETLICENSING_ALLOW_DEMO=true` for sandbox testing | | Demo data instead of live data | `NETLICENSING_API_KEY` not set; `NETLICENSING_ALLOW_DEMO=true` active | Ensure `NETLICENSING_API_KEY` is exported in the shell that starts the client and unset `NETLICENSING_ALLOW_DEMO` | --- ## Development ```bash git clone https://github.com/Labs64/NetLicensing-MCP cd NetLicensing-MCP # Create a virtual environment python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate # ... and install dependencies pip install -e ".[dev]" pip install hatch hatch-vcs # Add your API key to a .env file (or export it in your shell) cp .env.example .env # Run the MCP Inspector mcp dev src/netlicensing_mcp/server.py # Run tests pytest tests/ -v # Clean previous builds rm -rf dist/ # Build a wheel for local testing hatch build --target wheel # Build the Docker image locally docker build -t ghcr.io/labs64/netlicensing-mcp:latest . ``` ### HTTP mode (for remote / shared deployments) ```bash python -m netlicensing_mcp.server http # Server listens on MCP_HOST:MCP_PORT (default: 127.0.0.1:8000) ``` Use `ngrok` or a reverse proxy to expose the HTTP endpoint to remote MCP clients: ```bash ngrok http 8000 # Then point your client at the generated HTTPS URL ``` ### Cloud Deployment (AWS) Deploy the MCP server to AWS for a **public HTTPS endpoint** that remote AI agents can connect to: | Option | Best for | Scale-to-zero | Setup | |---|---|---|---| | **ECS Fargate** | Production, consistent traffic | No | ALB + Fargate | | **App Runner** | Low-traffic, development | ✅ Yes | Auto-provisioned HTTPS | #### Quick deploy with the helper script ```bash cd deploy/aws # Option A — ECS Fargate # Deploy (with optional HTTPS via ACM certificate) ./deploy.sh fargate \ --certificate-arn arn:aws:acm:us-east-1:123456789:certificate/your-cert-id # Option B — App Runner (mirror image to ECR first) ./deploy.sh mirror --ecr-repo 123456789.dkr.ecr.us-east-1.amazonaws.com/netlicensing-mcp ./deploy.sh apprunner \ --ecr-image 123456789.dkr.ecr.us-east-1.amazonaws.com/netlicensing-mcp:latest ``` #### Connect MCP clients to the public URL To use a shared, remote deployment, do not bake the `NETLICENSING_API_KEY` into the remote server settings. Instead, pass the API key from the client side using query parameters or HTTP headers. For example, using the URL configuration in your MCP client with a query parameter: ```json { "mcpServers": { "netlicensing": { "url": "https://your-endpoint.us-east-1.elb.amazonaws.com/mcp?apikey=YOUR_API_KEY" } } } ``` If you use a client or tool that supports passing HTTP headers directly, you can alternatively provide the key via `X-NetLicensing-API-Key: YOUR_API_KEY` or `Authorization: Bearer YOUR_API_KEY`. 📖 Full instructions, architecture diagrams, and cost estimates: **[deploy/aws/README.md](deploy/aws/README.md)** --- ## Contributing Contributions are welcome! Please open an issue or pull request on [GitHub](https://github.com/Labs64/NetLicensing-MCP). For significant changes, open an issue first to discuss the approach. --- ## License Apache 2.0 — see [LICENSE](LICENSE) --- [![NetLicensing-MCP MCP server](https://glama.ai/mcp/servers/Labs64/NetLicensing-MCP/badges/card.svg)](https://glama.ai/mcp/servers/Labs64/NetLicensing-MCP)