@lightninglabs/lightning-mcp-server 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +36 -0
- package/.claude-plugin/plugin.json +12 -0
- package/README.md +307 -0
- package/bin/lightning-mcp-server +15 -0
- package/docs/architecture.md +455 -0
- package/docs/commerce.md +357 -0
- package/docs/l402-and-lnget.md +267 -0
- package/docs/mcp-server.md +285 -0
- package/docs/quickref.md +263 -0
- package/docs/security.md +298 -0
- package/docs/two-agent-setup.md +394 -0
- package/package.json +52 -0
- package/postinstall.js +160 -0
- package/skills/aperture/SKILL.md +330 -0
- package/skills/aperture/scripts/install.sh +68 -0
- package/skills/aperture/scripts/setup.sh +155 -0
- package/skills/aperture/scripts/start.sh +81 -0
- package/skills/aperture/scripts/stop.sh +57 -0
- package/skills/aperture/templates/aperture-regtest.yaml +36 -0
- package/skills/aperture/templates/aperture.yaml.template +64 -0
- package/skills/aperture/templates/docker-compose-aperture.yml +59 -0
- package/skills/commerce/SKILL.md +211 -0
- package/skills/lib/config-gen.sh +127 -0
- package/skills/lib/rest.sh +69 -0
- package/skills/lightning-security-module/SKILL.md +253 -0
- package/skills/lightning-security-module/references/architecture.md +133 -0
- package/skills/lightning-security-module/scripts/docker-start.sh +117 -0
- package/skills/lightning-security-module/scripts/docker-stop.sh +53 -0
- package/skills/lightning-security-module/scripts/export-credentials.sh +268 -0
- package/skills/lightning-security-module/scripts/install.sh +178 -0
- package/skills/lightning-security-module/scripts/setup-signer.sh +307 -0
- package/skills/lightning-security-module/scripts/start-signer.sh +152 -0
- package/skills/lightning-security-module/scripts/stop-signer.sh +240 -0
- package/skills/lightning-security-module/templates/docker-compose-signer.yml +35 -0
- package/skills/lightning-security-module/templates/signer-lnd.conf.template +69 -0
- package/skills/lnd/SKILL.md +441 -0
- package/skills/lnd/profiles/debug.env +4 -0
- package/skills/lnd/profiles/default.env +3 -0
- package/skills/lnd/profiles/regtest.env +4 -0
- package/skills/lnd/profiles/taproot.env +3 -0
- package/skills/lnd/profiles/wumbo.env +3 -0
- package/skills/lnd/references/security.md +156 -0
- package/skills/lnd/scripts/create-wallet.sh +464 -0
- package/skills/lnd/scripts/docker-start.sh +256 -0
- package/skills/lnd/scripts/docker-stop.sh +109 -0
- package/skills/lnd/scripts/import-credentials.sh +145 -0
- package/skills/lnd/scripts/install.sh +195 -0
- package/skills/lnd/scripts/lncli.sh +150 -0
- package/skills/lnd/scripts/start-lnd.sh +241 -0
- package/skills/lnd/scripts/stop-lnd.sh +218 -0
- package/skills/lnd/scripts/unlock-wallet.sh +134 -0
- package/skills/lnd/templates/docker-compose-regtest.yml +122 -0
- package/skills/lnd/templates/docker-compose-watchonly.yml +71 -0
- package/skills/lnd/templates/docker-compose.yml +49 -0
- package/skills/lnd/templates/litd-regtest.conf.template +61 -0
- package/skills/lnd/templates/litd-watchonly.conf.template +57 -0
- package/skills/lnd/templates/litd.conf.template +88 -0
- package/skills/lnd/templates/lnd.conf.template +91 -0
- package/skills/lnget/SKILL.md +288 -0
- package/skills/lnget/scripts/install.sh +69 -0
- package/skills/macaroon-bakery/SKILL.md +179 -0
- package/skills/macaroon-bakery/scripts/bake.sh +337 -0
- package/skills/mcp-lnc/SKILL.md +280 -0
- package/skills/mcp-lnc/scripts/configure.sh +130 -0
- package/skills/mcp-lnc/scripts/install.sh +103 -0
- package/skills/mcp-lnc/scripts/setup-claude-config.sh +162 -0
- package/skills/mcp-lnc/templates/env.template +16 -0
- package/versions.env +23 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Generate aperture configuration from template.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# setup.sh # Defaults (mainnet, lnd)
|
|
6
|
+
# setup.sh --network testnet --insecure # Testnet, no TLS
|
|
7
|
+
# setup.sh --no-auth # Disable L402 auth
|
|
8
|
+
# setup.sh --port 8081 # Custom listen port
|
|
9
|
+
|
|
10
|
+
set -e
|
|
11
|
+
|
|
12
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
|
+
APERTURE_DIR="$HOME/.aperture"
|
|
14
|
+
CONFIG_FILE="$APERTURE_DIR/aperture.yaml"
|
|
15
|
+
NETWORK="mainnet"
|
|
16
|
+
PORT="8081"
|
|
17
|
+
INSECURE=false
|
|
18
|
+
NO_AUTH=false
|
|
19
|
+
LND_HOST="localhost:10009"
|
|
20
|
+
LND_TLS="$HOME/.lnd/tls.cert"
|
|
21
|
+
LND_MACDIR=""
|
|
22
|
+
SERVICE_PORT="8080"
|
|
23
|
+
SERVICE_PRICE="100"
|
|
24
|
+
|
|
25
|
+
# Parse arguments.
|
|
26
|
+
while [[ $# -gt 0 ]]; do
|
|
27
|
+
case $1 in
|
|
28
|
+
--network)
|
|
29
|
+
NETWORK="$2"
|
|
30
|
+
shift 2
|
|
31
|
+
;;
|
|
32
|
+
--port)
|
|
33
|
+
PORT="$2"
|
|
34
|
+
shift 2
|
|
35
|
+
;;
|
|
36
|
+
--insecure)
|
|
37
|
+
INSECURE=true
|
|
38
|
+
shift
|
|
39
|
+
;;
|
|
40
|
+
--no-auth)
|
|
41
|
+
NO_AUTH=true
|
|
42
|
+
shift
|
|
43
|
+
;;
|
|
44
|
+
--lnd-host)
|
|
45
|
+
LND_HOST="$2"
|
|
46
|
+
shift 2
|
|
47
|
+
;;
|
|
48
|
+
--lnd-tls)
|
|
49
|
+
LND_TLS="$2"
|
|
50
|
+
shift 2
|
|
51
|
+
;;
|
|
52
|
+
--lnd-macdir)
|
|
53
|
+
LND_MACDIR="$2"
|
|
54
|
+
shift 2
|
|
55
|
+
;;
|
|
56
|
+
--service-port)
|
|
57
|
+
SERVICE_PORT="$2"
|
|
58
|
+
shift 2
|
|
59
|
+
;;
|
|
60
|
+
--service-price)
|
|
61
|
+
SERVICE_PRICE="$2"
|
|
62
|
+
shift 2
|
|
63
|
+
;;
|
|
64
|
+
-h|--help)
|
|
65
|
+
echo "Usage: setup.sh [options]"
|
|
66
|
+
echo ""
|
|
67
|
+
echo "Generate aperture configuration."
|
|
68
|
+
echo ""
|
|
69
|
+
echo "Options:"
|
|
70
|
+
echo " --network NETWORK Bitcoin network (default: mainnet)"
|
|
71
|
+
echo " --port PORT Listen port (default: 8081)"
|
|
72
|
+
echo " --insecure Disable TLS"
|
|
73
|
+
echo " --no-auth Disable L402 authentication"
|
|
74
|
+
echo " --lnd-host HOST lnd gRPC host (default: localhost:10009)"
|
|
75
|
+
echo " --lnd-tls PATH lnd TLS cert path"
|
|
76
|
+
echo " --lnd-macdir PATH lnd macaroon directory"
|
|
77
|
+
echo " --service-port PORT Backend service port (default: 8080)"
|
|
78
|
+
echo " --service-price SATS Price per request in sats (default: 100)"
|
|
79
|
+
exit 0
|
|
80
|
+
;;
|
|
81
|
+
*)
|
|
82
|
+
echo "Unknown option: $1" >&2
|
|
83
|
+
exit 1
|
|
84
|
+
;;
|
|
85
|
+
esac
|
|
86
|
+
done
|
|
87
|
+
|
|
88
|
+
# Auto-detect lnd macaroon directory if not specified.
|
|
89
|
+
if [ -z "$LND_MACDIR" ]; then
|
|
90
|
+
LND_MACDIR="$HOME/.lnd/data/chain/bitcoin/$NETWORK"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
echo "=== Aperture Configuration Setup ==="
|
|
94
|
+
echo ""
|
|
95
|
+
echo "Network: $NETWORK"
|
|
96
|
+
echo "Listen port: $PORT"
|
|
97
|
+
echo "Insecure: $INSECURE"
|
|
98
|
+
echo "Auth: $([ "$NO_AUTH" = true ] && echo "disabled" || echo "enabled")"
|
|
99
|
+
echo "LND host: $LND_HOST"
|
|
100
|
+
echo "Config: $CONFIG_FILE"
|
|
101
|
+
echo ""
|
|
102
|
+
|
|
103
|
+
# Create aperture directory.
|
|
104
|
+
mkdir -p "$APERTURE_DIR"
|
|
105
|
+
|
|
106
|
+
# Build config.
|
|
107
|
+
cat > "$CONFIG_FILE" << YAML
|
|
108
|
+
# Aperture configuration generated by setup.sh
|
|
109
|
+
# Edit as needed: ~/.aperture/aperture.yaml
|
|
110
|
+
|
|
111
|
+
listenaddr: "localhost:$PORT"
|
|
112
|
+
debuglevel: "info"
|
|
113
|
+
dbbackend: "sqlite"
|
|
114
|
+
|
|
115
|
+
sqlite:
|
|
116
|
+
dbfile: "$APERTURE_DIR/aperture.db"
|
|
117
|
+
|
|
118
|
+
insecure: $INSECURE
|
|
119
|
+
|
|
120
|
+
authenticator:
|
|
121
|
+
YAML
|
|
122
|
+
|
|
123
|
+
if [ "$NO_AUTH" = true ]; then
|
|
124
|
+
cat >> "$CONFIG_FILE" << YAML
|
|
125
|
+
disable: true
|
|
126
|
+
YAML
|
|
127
|
+
else
|
|
128
|
+
cat >> "$CONFIG_FILE" << YAML
|
|
129
|
+
network: "$NETWORK"
|
|
130
|
+
lndhost: "$LND_HOST"
|
|
131
|
+
tlspath: "$LND_TLS"
|
|
132
|
+
macdir: "$LND_MACDIR"
|
|
133
|
+
YAML
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
cat >> "$CONFIG_FILE" << YAML
|
|
137
|
+
|
|
138
|
+
services:
|
|
139
|
+
- name: "default-api"
|
|
140
|
+
hostregexp: ".*"
|
|
141
|
+
pathregexp: '^/api/.*$'
|
|
142
|
+
address: "127.0.0.1:$SERVICE_PORT"
|
|
143
|
+
protocol: http
|
|
144
|
+
price: $SERVICE_PRICE
|
|
145
|
+
timeout: 31557600
|
|
146
|
+
authwhitelistpaths:
|
|
147
|
+
- '^/health$'
|
|
148
|
+
YAML
|
|
149
|
+
|
|
150
|
+
echo "Config written to $CONFIG_FILE"
|
|
151
|
+
echo ""
|
|
152
|
+
echo "Next steps:"
|
|
153
|
+
echo " 1. Start a backend on port $SERVICE_PORT"
|
|
154
|
+
echo " 2. Start aperture: skills/aperture/scripts/start.sh"
|
|
155
|
+
echo " 3. Test: lnget -k https://localhost:$PORT/api/test"
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Start aperture reverse proxy.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# start.sh # Background, default config
|
|
6
|
+
# start.sh --foreground # Foreground mode
|
|
7
|
+
# start.sh --config /path/to/yaml # Custom config
|
|
8
|
+
|
|
9
|
+
set -e
|
|
10
|
+
|
|
11
|
+
APERTURE_DIR="$HOME/.aperture"
|
|
12
|
+
CONFIG_FILE="$APERTURE_DIR/aperture.yaml"
|
|
13
|
+
FOREGROUND=false
|
|
14
|
+
|
|
15
|
+
# Parse arguments.
|
|
16
|
+
while [[ $# -gt 0 ]]; do
|
|
17
|
+
case $1 in
|
|
18
|
+
--config)
|
|
19
|
+
CONFIG_FILE="$2"
|
|
20
|
+
shift 2
|
|
21
|
+
;;
|
|
22
|
+
--foreground)
|
|
23
|
+
FOREGROUND=true
|
|
24
|
+
shift
|
|
25
|
+
;;
|
|
26
|
+
-h|--help)
|
|
27
|
+
echo "Usage: start.sh [--foreground] [--config PATH]"
|
|
28
|
+
exit 0
|
|
29
|
+
;;
|
|
30
|
+
*)
|
|
31
|
+
echo "Unknown option: $1" >&2
|
|
32
|
+
exit 1
|
|
33
|
+
;;
|
|
34
|
+
esac
|
|
35
|
+
done
|
|
36
|
+
|
|
37
|
+
# Verify aperture is installed.
|
|
38
|
+
if ! command -v aperture &>/dev/null; then
|
|
39
|
+
echo "Error: aperture not found. Run install.sh first." >&2
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
# Verify config exists.
|
|
44
|
+
if [ ! -f "$CONFIG_FILE" ]; then
|
|
45
|
+
echo "Error: Config not found at $CONFIG_FILE" >&2
|
|
46
|
+
echo "Run setup.sh first to generate config." >&2
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Check if aperture is already running.
|
|
51
|
+
if pgrep -x aperture &>/dev/null; then
|
|
52
|
+
echo "aperture is already running (PID: $(pgrep -x aperture))."
|
|
53
|
+
echo "Use stop.sh to stop it first."
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
echo "=== Starting Aperture ==="
|
|
58
|
+
echo "Config: $CONFIG_FILE"
|
|
59
|
+
echo ""
|
|
60
|
+
|
|
61
|
+
LOG_FILE="$APERTURE_DIR/aperture-start.log"
|
|
62
|
+
|
|
63
|
+
if [ "$FOREGROUND" = true ]; then
|
|
64
|
+
exec aperture --configfile="$CONFIG_FILE"
|
|
65
|
+
else
|
|
66
|
+
nohup aperture --configfile="$CONFIG_FILE" \
|
|
67
|
+
> "$LOG_FILE" 2>&1 &
|
|
68
|
+
APERTURE_PID=$!
|
|
69
|
+
echo "aperture started in background (PID: $APERTURE_PID)"
|
|
70
|
+
echo "Log file: $LOG_FILE"
|
|
71
|
+
|
|
72
|
+
# Wait briefly and verify it's running.
|
|
73
|
+
sleep 2
|
|
74
|
+
if kill -0 "$APERTURE_PID" 2>/dev/null; then
|
|
75
|
+
echo "aperture is running."
|
|
76
|
+
else
|
|
77
|
+
echo "Error: aperture exited immediately. Check $LOG_FILE" >&2
|
|
78
|
+
tail -20 "$LOG_FILE" 2>/dev/null
|
|
79
|
+
exit 1
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Stop aperture reverse proxy.
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# stop.sh # Graceful stop
|
|
6
|
+
# stop.sh --force # SIGKILL
|
|
7
|
+
|
|
8
|
+
set -e
|
|
9
|
+
|
|
10
|
+
FORCE=false
|
|
11
|
+
|
|
12
|
+
# Parse arguments.
|
|
13
|
+
while [[ $# -gt 0 ]]; do
|
|
14
|
+
case $1 in
|
|
15
|
+
--force)
|
|
16
|
+
FORCE=true
|
|
17
|
+
shift
|
|
18
|
+
;;
|
|
19
|
+
-h|--help)
|
|
20
|
+
echo "Usage: stop.sh [--force]"
|
|
21
|
+
exit 0
|
|
22
|
+
;;
|
|
23
|
+
*)
|
|
24
|
+
echo "Unknown option: $1" >&2
|
|
25
|
+
exit 1
|
|
26
|
+
;;
|
|
27
|
+
esac
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
APERTURE_PID=$(pgrep -x aperture 2>/dev/null || true)
|
|
31
|
+
if [ -z "$APERTURE_PID" ]; then
|
|
32
|
+
echo "aperture is not running."
|
|
33
|
+
exit 0
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
echo "Stopping aperture (PID: $APERTURE_PID)..."
|
|
37
|
+
|
|
38
|
+
if [ "$FORCE" = true ]; then
|
|
39
|
+
kill -9 "$APERTURE_PID"
|
|
40
|
+
echo "Sent SIGKILL."
|
|
41
|
+
else
|
|
42
|
+
kill "$APERTURE_PID"
|
|
43
|
+
echo "Sent SIGTERM."
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
# Wait for exit.
|
|
47
|
+
for i in {1..10}; do
|
|
48
|
+
if ! kill -0 "$APERTURE_PID" 2>/dev/null; then
|
|
49
|
+
echo "aperture stopped."
|
|
50
|
+
exit 0
|
|
51
|
+
fi
|
|
52
|
+
sleep 1
|
|
53
|
+
done
|
|
54
|
+
|
|
55
|
+
echo "Warning: aperture did not exit within 10 seconds." >&2
|
|
56
|
+
echo "Use --force to send SIGKILL." >&2
|
|
57
|
+
exit 1
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Aperture L402 Reverse Proxy — Regtest Configuration
|
|
2
|
+
#
|
|
3
|
+
# Used with docker-compose-aperture.yml for integration testing.
|
|
4
|
+
# Connects to litd on the litd-regtest Docker network for invoice creation.
|
|
5
|
+
|
|
6
|
+
# Listen on all interfaces so Docker port mapping works.
|
|
7
|
+
listenaddr: "0.0.0.0:8082"
|
|
8
|
+
|
|
9
|
+
debuglevel: "debug"
|
|
10
|
+
|
|
11
|
+
# No TLS — regtest only.
|
|
12
|
+
insecure: true
|
|
13
|
+
|
|
14
|
+
# SQLite database for token storage.
|
|
15
|
+
dbbackend: "sqlite"
|
|
16
|
+
sqlite:
|
|
17
|
+
dbfile: "/root/.aperture/aperture.db"
|
|
18
|
+
|
|
19
|
+
# L402 authenticator — connects to litd's embedded lnd.
|
|
20
|
+
authenticator:
|
|
21
|
+
network: "regtest"
|
|
22
|
+
lndhost: "litd:10009"
|
|
23
|
+
tlspath: "/root/.lnd-creds/tls.cert"
|
|
24
|
+
macdir: "/root/.lnd-creds"
|
|
25
|
+
|
|
26
|
+
# Backend service protected by L402.
|
|
27
|
+
services:
|
|
28
|
+
- name: "test-api"
|
|
29
|
+
hostregexp: ".*"
|
|
30
|
+
pathregexp: '^/api/.*$'
|
|
31
|
+
address: "litd-backend:9999"
|
|
32
|
+
protocol: http
|
|
33
|
+
price: 1
|
|
34
|
+
timeout: 31557600
|
|
35
|
+
authwhitelistpaths:
|
|
36
|
+
- '^/health$'
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Aperture L402 Reverse Proxy Configuration Template
|
|
2
|
+
#
|
|
3
|
+
# Copy to ~/.aperture/aperture.yaml and modify as needed.
|
|
4
|
+
# Or use: skills/aperture/scripts/setup.sh to generate automatically.
|
|
5
|
+
#
|
|
6
|
+
# Documentation: https://github.com/lightninglabs/aperture
|
|
7
|
+
|
|
8
|
+
# Listen address for incoming requests.
|
|
9
|
+
listenaddr: "localhost:8081"
|
|
10
|
+
|
|
11
|
+
# Log level: trace, debug, info, warn, error, critical.
|
|
12
|
+
debuglevel: "info"
|
|
13
|
+
|
|
14
|
+
# Disable TLS (development only). Set to false for production.
|
|
15
|
+
insecure: true
|
|
16
|
+
|
|
17
|
+
# Database backend: sqlite, postgres, or etcd.
|
|
18
|
+
dbbackend: "sqlite"
|
|
19
|
+
sqlite:
|
|
20
|
+
dbfile: "~/.aperture/aperture.db"
|
|
21
|
+
|
|
22
|
+
# LND authentication configuration.
|
|
23
|
+
authenticator:
|
|
24
|
+
# Network: regtest, simnet, testnet, mainnet, signet.
|
|
25
|
+
network: "mainnet"
|
|
26
|
+
|
|
27
|
+
# Direct lnd connection.
|
|
28
|
+
lndhost: "localhost:10009"
|
|
29
|
+
tlspath: "~/.lnd/tls.cert"
|
|
30
|
+
macdir: "~/.lnd/data/chain/bitcoin/mainnet"
|
|
31
|
+
|
|
32
|
+
# Or disable auth entirely for testing.
|
|
33
|
+
# disable: true
|
|
34
|
+
|
|
35
|
+
# Backend services protected by L402.
|
|
36
|
+
services:
|
|
37
|
+
- name: "default-api"
|
|
38
|
+
# Match all hosts.
|
|
39
|
+
hostregexp: ".*"
|
|
40
|
+
|
|
41
|
+
# Protect /api/ paths.
|
|
42
|
+
pathregexp: '^/api/.*$'
|
|
43
|
+
|
|
44
|
+
# Backend server address.
|
|
45
|
+
address: "127.0.0.1:8080"
|
|
46
|
+
protocol: http
|
|
47
|
+
|
|
48
|
+
# Price per request in satoshis.
|
|
49
|
+
price: 100
|
|
50
|
+
|
|
51
|
+
# Token expires after 1 year (seconds).
|
|
52
|
+
timeout: 31557600
|
|
53
|
+
|
|
54
|
+
# Free paths (no payment required).
|
|
55
|
+
authwhitelistpaths:
|
|
56
|
+
- '^/health$'
|
|
57
|
+
- '^/public/.*$'
|
|
58
|
+
|
|
59
|
+
# Optional rate limits.
|
|
60
|
+
# ratelimits:
|
|
61
|
+
# - pathregexp: '^/api/.*$'
|
|
62
|
+
# requests: 100
|
|
63
|
+
# per: 1m
|
|
64
|
+
# burst: 150
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Aperture L402 Reverse Proxy — Docker container on regtest.
|
|
2
|
+
#
|
|
3
|
+
# Requires a running litd + bitcoind regtest stack (docker-compose-regtest.yml).
|
|
4
|
+
# Aperture connects to litd's lnd gRPC for invoice creation and L402 auth.
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# docker compose -f docker-compose-aperture.yml up -d
|
|
8
|
+
# docker compose -f docker-compose-aperture.yml down -v
|
|
9
|
+
#
|
|
10
|
+
# The aperture container runs under Rosetta on Apple Silicon since no
|
|
11
|
+
# arm64 image is published.
|
|
12
|
+
#
|
|
13
|
+
# Ports:
|
|
14
|
+
# 8082 — Aperture HTTP proxy (insecure mode for regtest)
|
|
15
|
+
#
|
|
16
|
+
# A simple backend HTTP server is included as a second container (busybox
|
|
17
|
+
# httpd serving static files from /www).
|
|
18
|
+
|
|
19
|
+
services:
|
|
20
|
+
aperture:
|
|
21
|
+
image: ${APERTURE_IMAGE:-lightninglabs/aperture}:${APERTURE_VERSION:-v0.4.2}
|
|
22
|
+
platform: linux/amd64
|
|
23
|
+
container_name: litd-aperture
|
|
24
|
+
restart: unless-stopped
|
|
25
|
+
depends_on:
|
|
26
|
+
- backend
|
|
27
|
+
entrypoint: ["/bin/sh", "-c", "cp /tmp/aperture.yaml /root/.aperture/aperture.yaml && exec aperture --configfile=/root/.aperture/aperture.yaml"]
|
|
28
|
+
ports:
|
|
29
|
+
- "${APERTURE_PORT:-8082}:8082"
|
|
30
|
+
volumes:
|
|
31
|
+
- aperture-data:/root/.aperture
|
|
32
|
+
- ${APERTURE_CONF_PATH:-./aperture-regtest.yaml}:/tmp/aperture.yaml:ro
|
|
33
|
+
# Mount litd's TLS cert and macaroon from the litd container volume.
|
|
34
|
+
# These are copied in by the test setup after wallet creation.
|
|
35
|
+
- litd-aperture-creds:/root/.lnd-creds:ro
|
|
36
|
+
networks:
|
|
37
|
+
- litd-regtest
|
|
38
|
+
- aperture-net
|
|
39
|
+
|
|
40
|
+
backend:
|
|
41
|
+
image: busybox:latest
|
|
42
|
+
container_name: litd-backend
|
|
43
|
+
restart: unless-stopped
|
|
44
|
+
# Serve a simple HTTP response on port 9999.
|
|
45
|
+
command: ["sh", "-c", "mkdir -p /www/api && echo '{\"status\":\"ok\",\"message\":\"Hello from L402 backend\"}' > /www/api/data.json && echo '{\"status\":\"ok\"}' > /www/health && httpd -f -p 9999 -h /www"]
|
|
46
|
+
networks:
|
|
47
|
+
- aperture-net
|
|
48
|
+
|
|
49
|
+
volumes:
|
|
50
|
+
aperture-data:
|
|
51
|
+
litd-aperture-creds:
|
|
52
|
+
external: true
|
|
53
|
+
|
|
54
|
+
networks:
|
|
55
|
+
aperture-net:
|
|
56
|
+
driver: bridge
|
|
57
|
+
litd-regtest:
|
|
58
|
+
external: true
|
|
59
|
+
name: templates_litd-regtest
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: commerce
|
|
3
|
+
description: End-to-end agentic commerce workflow using Lightning Network. Use when an agent needs to set up a full payment stack (lnd + lnget + aperture), buy or sell data via L402, or enable agent-to-agent micropayments.
|
|
4
|
+
user-invocable: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Agentic Commerce Toolkit
|
|
8
|
+
|
|
9
|
+
This plugin provides a complete toolkit for agent-driven Lightning Network
|
|
10
|
+
commerce. Three skills work together to enable agents to send and receive
|
|
11
|
+
micropayments over the Lightning Network using the L402 protocol.
|
|
12
|
+
|
|
13
|
+
## Components
|
|
14
|
+
|
|
15
|
+
| Skill | Purpose |
|
|
16
|
+
|-------|---------|
|
|
17
|
+
| **lnd** | Run Lightning Terminal (litd: lnd + loop + pool + tapd) |
|
|
18
|
+
| **lnget** | Fetch L402-protected resources (pay for data) |
|
|
19
|
+
| **aperture** | Host paid API endpoints (sell data) |
|
|
20
|
+
|
|
21
|
+
## Full Setup Workflow
|
|
22
|
+
|
|
23
|
+
### Step 1: Install All Components
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Install litd (Lightning Terminal — bundles lnd + loop + pool + tapd)
|
|
27
|
+
skills/lnd/scripts/install.sh
|
|
28
|
+
|
|
29
|
+
# Install lnget (Lightning HTTP client)
|
|
30
|
+
skills/lnget/scripts/install.sh
|
|
31
|
+
|
|
32
|
+
# Install aperture (L402 reverse proxy)
|
|
33
|
+
skills/aperture/scripts/install.sh
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Step 2: Set Up the Lightning Node
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Start litd container (testnet by default)
|
|
40
|
+
skills/lnd/scripts/start-lnd.sh
|
|
41
|
+
|
|
42
|
+
# Create an encrypted wallet
|
|
43
|
+
skills/lnd/scripts/create-wallet.sh --mode standalone
|
|
44
|
+
|
|
45
|
+
# Verify node is running
|
|
46
|
+
skills/lnd/scripts/lncli.sh getinfo
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Step 3: Fund the Wallet
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Generate a Bitcoin address
|
|
53
|
+
skills/lnd/scripts/lncli.sh newaddress p2tr
|
|
54
|
+
|
|
55
|
+
# Send BTC to this address from an exchange or another wallet
|
|
56
|
+
|
|
57
|
+
# Verify balance
|
|
58
|
+
skills/lnd/scripts/lncli.sh walletbalance
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Step 4: Open a Channel
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Connect to a well-connected node (e.g., ACINQ, Bitfinex)
|
|
65
|
+
skills/lnd/scripts/lncli.sh connect <pubkey>@<host>:9735
|
|
66
|
+
|
|
67
|
+
# Open a channel
|
|
68
|
+
skills/lnd/scripts/lncli.sh openchannel --node_key=<pubkey> --local_amt=1000000
|
|
69
|
+
|
|
70
|
+
# Wait for channel to confirm (6 blocks)
|
|
71
|
+
skills/lnd/scripts/lncli.sh listchannels
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Step 5: Configure lnget
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Initialize lnget config (auto-detects local lnd)
|
|
78
|
+
lnget config init
|
|
79
|
+
|
|
80
|
+
# Verify connection
|
|
81
|
+
lnget ln status
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Step 6: Fetch Paid Resources
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
# Fetch an L402-protected resource
|
|
88
|
+
lnget --max-cost 1000 https://api.example.com/paid-data
|
|
89
|
+
|
|
90
|
+
# Preview without paying
|
|
91
|
+
lnget --no-pay https://api.example.com/paid-data
|
|
92
|
+
|
|
93
|
+
# Check cached tokens
|
|
94
|
+
lnget tokens list
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### Step 7: Host Paid Endpoints (Optional)
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
# Start your backend service
|
|
101
|
+
python3 -m http.server 8080 &
|
|
102
|
+
|
|
103
|
+
# Configure aperture to protect it
|
|
104
|
+
skills/aperture/scripts/setup.sh --insecure --port 8081
|
|
105
|
+
|
|
106
|
+
# Start the L402 paywall
|
|
107
|
+
skills/aperture/scripts/start.sh
|
|
108
|
+
|
|
109
|
+
# Other agents can now pay to access your endpoints
|
|
110
|
+
# lnget --max-cost 100 https://your-host:8081/api/data
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Agent-to-Agent Commerce
|
|
114
|
+
|
|
115
|
+
The full loop for autonomous agent commerce:
|
|
116
|
+
|
|
117
|
+
```
|
|
118
|
+
Agent A (buyer) Agent B (seller)
|
|
119
|
+
───────────── ─────────────
|
|
120
|
+
lnd node running lnd node running
|
|
121
|
+
↓ ↓
|
|
122
|
+
lnget fetches URL ──────────────→ aperture receives request
|
|
123
|
+
↓
|
|
124
|
+
Returns 402 + invoice
|
|
125
|
+
↓
|
|
126
|
+
lnget pays invoice ─────────────→ lnd receives payment
|
|
127
|
+
↓ ↓
|
|
128
|
+
lnget retries with token ───────→ aperture validates token
|
|
129
|
+
↓
|
|
130
|
+
Proxies to backend
|
|
131
|
+
↓ ↓
|
|
132
|
+
Agent A receives data ←────────── Backend returns data
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### Buyer Agent Setup
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
# One-time setup
|
|
139
|
+
skills/lnd/scripts/install.sh
|
|
140
|
+
skills/lnget/scripts/install.sh
|
|
141
|
+
skills/lnd/scripts/start-lnd.sh
|
|
142
|
+
skills/lnd/scripts/create-wallet.sh --mode standalone
|
|
143
|
+
lnget config init
|
|
144
|
+
|
|
145
|
+
# Fund wallet and open channels (one-time)
|
|
146
|
+
skills/lnd/scripts/lncli.sh newaddress p2tr
|
|
147
|
+
# ... send BTC ...
|
|
148
|
+
skills/lnd/scripts/lncli.sh openchannel --node_key=<pubkey> --local_amt=500000
|
|
149
|
+
|
|
150
|
+
# Ongoing: fetch paid resources
|
|
151
|
+
lnget --max-cost 100 -q https://seller-api.example.com/api/data | jq .
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Seller Agent Setup
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
# One-time setup
|
|
158
|
+
skills/lnd/scripts/install.sh
|
|
159
|
+
skills/aperture/scripts/install.sh
|
|
160
|
+
skills/lnd/scripts/start-lnd.sh
|
|
161
|
+
skills/lnd/scripts/create-wallet.sh --mode standalone
|
|
162
|
+
|
|
163
|
+
# Configure and start paywall
|
|
164
|
+
skills/aperture/scripts/setup.sh --port 8081 --insecure
|
|
165
|
+
|
|
166
|
+
# Start backend with content to sell
|
|
167
|
+
mkdir -p /tmp/api-data
|
|
168
|
+
echo '{"market_data": "..."}' > /tmp/api-data/data.json
|
|
169
|
+
cd /tmp/api-data && python3 -m http.server 8080 &
|
|
170
|
+
|
|
171
|
+
# Start aperture
|
|
172
|
+
skills/aperture/scripts/start.sh
|
|
173
|
+
|
|
174
|
+
# Buyers can now access:
|
|
175
|
+
# https://your-host:8081/api/data.json (100 sats per request)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## Cost Management
|
|
179
|
+
|
|
180
|
+
Agents should always control spending:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
# Set a hard limit per request
|
|
184
|
+
lnget --max-cost 500 https://api.example.com/data
|
|
185
|
+
|
|
186
|
+
# Check cost before paying
|
|
187
|
+
lnget --no-pay --json https://api.example.com/data | jq '.invoice_amount_sat'
|
|
188
|
+
|
|
189
|
+
# Track spending via token list
|
|
190
|
+
lnget tokens list --json | jq '[.[] | .amount_paid_sat] | add'
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Security Summary
|
|
194
|
+
|
|
195
|
+
| Component | Security Model |
|
|
196
|
+
|-----------|---------------|
|
|
197
|
+
| **Wallet passphrase** | Stored at `~/.lnget/lnd/wallet-password.txt` (0600) |
|
|
198
|
+
| **Seed mnemonic** | Stored at `~/.lnget/lnd/seed.txt` (0600) |
|
|
199
|
+
| **L402 tokens** | Stored at `~/.lnget/tokens/<domain>/` per domain |
|
|
200
|
+
| **lnd macaroons** | Standard lnd paths at `~/.lnd/data/chain/...` |
|
|
201
|
+
| **Aperture DB** | SQLite at `~/.aperture/aperture.db` |
|
|
202
|
+
|
|
203
|
+
For production use with significant funds, use watch-only mode with a remote
|
|
204
|
+
signer container. See the `lightning-security-module` skill for details.
|
|
205
|
+
|
|
206
|
+
## Stopping Everything
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
skills/aperture/scripts/stop.sh
|
|
210
|
+
skills/lnd/scripts/stop-lnd.sh
|
|
211
|
+
```
|