Skip to main content
Glama
README.md
# lumind-mcp

**Make Lumind a native tool for any AI agent.**

`lumind-mcp` is a [Model Context Protocol](https://modelcontextprotocol.io) server that
exposes the Lumind agentic-commerce platform as a handful of clean tools. Plug it into an
AI agent (Claude Desktop, an IDE, a custom agent) with a **capped agent key**, and the agent
can, in its own tool language, browse the Lumind service catalogue, check how much budget
it has left, launch a GEO/SEO scan on a domain, and read back the structured report.

## Why it exists

AI agents are great at deciding *what* to do but need safe, well-described tools to actually
*do* it. Lumind already runs the work (GEO/SEO scans) and the billing. This MCP server is the
adapter between the two: every action goes through the agent's **capped LUM key**, so the
agent can spend autonomously but **can never exceed the budget the human set**. The result is
hands-off agentic commerce with a hard spending ceiling.

## How spending stays safe

- Every call carries the agent key (`lmd_agent_...`), a key the human created with a total
  cap and a daily cap.
- `lumind_run_scan` is the only tool that spends LUM. It is **money-first**: budget is debited
  when the scan is accepted, before any report is produced.
- Budget failures come back as plain, actionable messages: insufficient LUM (402), cap reached
  or key revoked (403), daily cap reached (429).
- Pass an `idempotencyKey` when retrying a scan so a retry never double-spends.

## Tools

| Tool | What it does | Spends LUM? |
|------|--------------|-------------|
| `lumind_list_services` | List buyable services and their LUM cost. Call this first. | No |
| `lumind_wallet_balance` | Show balance, total/daily caps, spent and remaining budget. Check before spending. | No |
| `lumind_run_scan` | Launch a GEO/SEO scan on a `domain` (optional `idempotencyKey`). Returns `scanId` + `reportToken`. | **Yes** |
| `lumind_get_report` | Fetch the structured JSON report for a `scanId`. | No |

## Install & build

Requires Node.js >= 18.

```bash
npm install
npm run build
```

## Configuration

The server reads its configuration from the environment:

| Variable | Required | Default | Used by | Notes |
|----------|----------|---------|---------|-------|
| `LUMIND_AGENT_KEY` | stdio only |, | stdio | Your capped agent key, form `lmd_agent_...`. Never hardcode it. **Not used by the HTTP transport** (each request carries its own key). |
| `LUMIND_API_BASE` | no | `https://lumind.io` | both | Override to point at another Lumind environment. |
| `MCP_HTTP_PORT` | no | `8120` | HTTP | TCP port the HTTP transport binds on `127.0.0.1`. |

## Use it in an MCP client

Add this to your MCP client config (e.g. `claude_desktop_config.json`), pointing `args` at the
built entrypoint:

```json
{
  "mcpServers": {
    "lumind": {
      "command": "node",
      "args": ["/absolute/path/to/lumind-mcp/dist/index.js"],
      "env": {
        "LUMIND_AGENT_KEY": "lmd_agent_xxxxxxxxxxxxxxxx",
        "LUMIND_API_BASE": "https://lumind.io"
      }
    }
  }
}
```

After `npm run build` you can also run it directly:

```bash
LUMIND_AGENT_KEY=lmd_agent_xxxx node dist/index.js   # stdio transport
```

## Use it remotely over HTTP

The same four tools are also served over a remote **Streamable HTTP** endpoint, so any MCP
client that supports remote servers can connect to a single URL with its own capped agent key
,  no local subprocess needed.

The key travels in each request's `Authorization` header (never a server env var), so one
HTTP server safely serves many isolated clients at once. Each request gets a fresh, stateless
session.

```json
{
  "mcpServers": {
    "lumind": {
      "type": "http",
      "url": "https://mcp.lumind.io/mcp",
      "headers": {
        "Authorization": "Bearer lmd_agent_xxxxxxxxxxxxxxxx"
      }
    }
  }
}
```

If the dedicated `mcp.lumind.io` host is not yet live, use the fallback path on the main
domain instead:

```json
"url": "https://lumind.io/mcp"
```

Run the HTTP transport yourself:

```bash
npm run build
MCP_HTTP_PORT=8120 LUMIND_API_BASE=https://lumind.io node dist/http.js   # binds 127.0.0.1
```

### HTTP smoke test

A minimal MCP `initialize` against the local endpoint (replace the key with a real one):

```bash
curl -s -X POST http://127.0.0.1:8120/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "Authorization: Bearer lmd_agent_xxxx" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0.0.0"}}}'
```

A healthy server replies `200` with an SSE `data:` line carrying the `initialize` result
(`serverInfo.name = "lumind-mcp"`). A request without the `Authorization` header is rejected
with `401`. There is also a plain `GET /healthz` returning `{"status":"ok"}`.

## Develop & test

```bash
npm run dev      # run from source over stdio (tsx)
npm run dev:http # run the HTTP transport from source (tsx)
npm run smoke    # offline smoke test: checks tool registration + a mocked call, no network
```

## Transport

- **stdio** (`dist/index.js`), the standard way MCP clients spawn a local server as a
  subprocess. One capped key per process via `LUMIND_AGENT_KEY`.
- **Streamable HTTP** (`dist/http.js`), a remote, multi-client endpoint. Each request brings
  its own agent key in the `Authorization` header; sessions are stateless and isolated, so N
  instances run independently with no shared key or cross-request state.

## License

MIT.