@santi020k/lumen-mcp 1.6.0 → 1.7.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/README.md CHANGED
@@ -131,11 +131,37 @@ npx -y --package @santi020k/lumen-mcp lumen-mcp-http
131
131
  ```
132
132
 
133
133
  It binds to `127.0.0.1:3000` by default and exposes MCP at
134
- `http://127.0.0.1:3000/mcp` plus a health check at `/health`. Configure it with
134
+ `http://127.0.0.1:3000/mcp`, a liveness check at `/health`, and a catalog readiness check at
135
+ `/ready`. Readiness returns the loaded catalog hash and server version, or a safe 503 response when
136
+ the catalog cannot initialize. Configure the transport with
135
137
  `LUMEN_MCP_HOST`, `LUMEN_MCP_PORT`, and a comma-separated
136
- `LUMEN_MCP_ALLOWED_HOSTS`. Binding to a public interface requires the
137
- deployment's authentication, TLS, rate limiting, and host allowlist; the
138
- package does not provide those infrastructure controls.
138
+ `LUMEN_MCP_ALLOWED_HOSTS`. The transport applies safe response headers and a
139
+ fixed-window request limit of 120 requests per minute by default. Malformed request bodies and
140
+ initialization failures return bounded JSON errors without stack traces or local paths.
141
+
142
+ Public deployments can also set:
143
+
144
+ - `LUMEN_MCP_OPENAI_CHALLENGE` to serve the exact single-line verification token at
145
+ `/.well-known/openai-apps-challenge`.
146
+ - `LUMEN_MCP_RATE_LIMIT_MAX` and `LUMEN_MCP_RATE_LIMIT_WINDOW_MS` to tune positive integer rate
147
+ limits.
148
+ - `LUMEN_MCP_TRUST_PROXY=true` only behind a controlled proxy that sanitizes forwarded headers.
149
+
150
+ The process listens over HTTP. Public hosting must terminate TLS, configure the exact allowed host,
151
+ and add authentication when the deployed data or operating model requires it. The public Lumen
152
+ catalog does not require user authentication.
153
+
154
+ ## AI plugin package
155
+
156
+ The repository includes a submission-ready plugin package in [`plugins/lumen-ui`](../../plugins/lumen-ui).
157
+ It combines the portable `lumen-ui` skill with this MCP server for Codex, ChatGPT, and Claude Code.
158
+ The public OpenAI Plugins Directory submission uses a hosted Streamable HTTP endpoint; see the
159
+ [submission checklist](../../docs/openai-plugin-submission.md) for deployment requirements, listing
160
+ copy, annotation justifications, and reviewer test cases.
161
+
162
+ Claude Code uses the package's stdio configuration and the repository marketplace in
163
+ [`.claude-plugin/marketplace.json`](../../.claude-plugin/marketplace.json). See the
164
+ [Claude Code plugin guide](../../docs/claude-code-plugin.md) for installation and validation.
139
165
 
140
166
  ## Recommended agent workflow
141
167
 
@@ -4,13 +4,42 @@ import { startLumenMcpHttp } from '../dist/index.js'
4
4
  const port = Number.parseInt(process.env.LUMEN_MCP_PORT ?? '3000', 10)
5
5
  const host = process.env.LUMEN_MCP_HOST ?? '127.0.0.1'
6
6
 
7
+ const parsePositiveInteger = (value, fallback, name) => {
8
+ const parsed = Number.parseInt(value ?? String(fallback), 10)
9
+
10
+ if (!Number.isSafeInteger(parsed) || parsed <= 0) {
11
+ throw new Error(`${name} must be a positive integer.`)
12
+ }
13
+
14
+ return parsed
15
+ }
16
+
7
17
  const allowedHosts = process.env.LUMEN_MCP_ALLOWED_HOSTS
8
18
  ?.split(',')
9
19
  .map(value => value.trim())
10
20
  .filter(Boolean)
11
21
 
12
22
  try {
13
- const { url } = await startLumenMcpHttp({ allowedHosts, host, port })
23
+ const maxRequests = parsePositiveInteger(
24
+ process.env.LUMEN_MCP_RATE_LIMIT_MAX,
25
+ 120,
26
+ 'LUMEN_MCP_RATE_LIMIT_MAX'
27
+ )
28
+
29
+ const windowMs = parsePositiveInteger(
30
+ process.env.LUMEN_MCP_RATE_LIMIT_WINDOW_MS,
31
+ 60_000,
32
+ 'LUMEN_MCP_RATE_LIMIT_WINDOW_MS'
33
+ )
34
+
35
+ const { url } = await startLumenMcpHttp({
36
+ allowedHosts,
37
+ host,
38
+ openAiChallenge: process.env.LUMEN_MCP_OPENAI_CHALLENGE,
39
+ port,
40
+ rateLimit: { maxRequests, windowMs },
41
+ trustProxy: process.env.LUMEN_MCP_TRUST_PROXY === 'true'
42
+ })
14
43
 
15
44
  process.stderr.write(`lumen-mcp listening at ${url.href}\n`)
16
45
  } catch (error) {