burn-mcp-server 2.0.6 → 2.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "burn-mcp-server",
3
- "version": "2.0.6",
3
+ "version": "2.1.0",
4
4
  "mcpName": "io.github.Fisher521/burn-mcp-server",
5
5
  "description": "Burn MCP — give your AI agent a reading workflow. 26 tools to search, triage, burn, vault, and analyze your saved articles. Works with Claude, Cursor, Windsurf.",
6
6
  "main": "dist/index.js",
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "source": "github"
8
8
  },
9
9
  "websiteUrl": "https://burn451.cloud",
10
- "version": "2.0.6",
10
+ "version": "2.1.0",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "burn-mcp-server",
15
- "version": "2.0.6",
15
+ "version": "2.1.0",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  },
@@ -26,5 +26,19 @@
26
26
  }
27
27
  ]
28
28
  }
29
+ ],
30
+ "remotes": [
31
+ {
32
+ "type": "streamable-http",
33
+ "url": "https://burn-mcp-server.vercel.app/api/mcp",
34
+ "headers": [
35
+ {
36
+ "name": "Authorization",
37
+ "description": "Bearer <BURN_MCP_TOKEN> — generate at https://burn451.cloud → Settings → MCP Server",
38
+ "isRequired": true,
39
+ "isSecret": true
40
+ }
41
+ ]
42
+ }
29
43
  ]
30
44
  }
@@ -0,0 +1,76 @@
1
+ // Vercel Node runtime handler — uses StreamableHTTPServerTransport (non-Web variant).
2
+ // Pre-bundled by esbuild into api/mcp.js (Vercel detects .js as Node function).
3
+
4
+ import type { IncomingMessage, ServerResponse } from 'node:http'
5
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
6
+ import { createClient } from '@supabase/supabase-js'
7
+ import { getOrExchangeSession } from './lib/auth.js'
8
+ import { createBurnServer } from './setup.js'
9
+
10
+ const SUPABASE_URL = process.env.BURN_SUPABASE_URL || 'https://juqtxylquemiuvvmgbej.supabase.co'
11
+ const SUPABASE_ANON_KEY = process.env.BURN_SUPABASE_ANON_KEY || 'sb_publishable_reVgmmCC6ndIo6jFRMM2LQ_wujj5FrO'
12
+
13
+ export default async function handler(req: IncomingMessage, res: ServerResponse): Promise<void> {
14
+ try {
15
+ // --- Auth ---
16
+ const authHeader = (req.headers.authorization || req.headers.Authorization || '') as string
17
+ const m = authHeader.match(/^Bearer\s+(.+)$/i)
18
+ const token = m?.[1]?.trim()
19
+
20
+ if (!token) {
21
+ res.statusCode = 401
22
+ res.setHeader('content-type', 'application/json')
23
+ res.end(JSON.stringify({
24
+ error: 'Missing Authorization header',
25
+ hint: 'Add `Authorization: Bearer <BURN_MCP_TOKEN>` — get yours at https://burn451.cloud → Settings → MCP Server.',
26
+ }))
27
+ return
28
+ }
29
+
30
+ // --- Exchange token → Supabase session (in-memory cache per token) ---
31
+ let session
32
+ try {
33
+ session = await getOrExchangeSession(token)
34
+ } catch (e: any) {
35
+ res.statusCode = 401
36
+ res.setHeader('content-type', 'application/json')
37
+ res.end(JSON.stringify({ error: 'Invalid or expired Burn MCP token', detail: String(e?.message || e) }))
38
+ return
39
+ }
40
+
41
+ // --- Per-request Supabase client with JWT in headers ---
42
+ const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
43
+ auth: { persistSession: false, autoRefreshToken: false, detectSessionInUrl: false },
44
+ global: { headers: { Authorization: `Bearer ${session.access_token}` } },
45
+ })
46
+
47
+ const server = createBurnServer(supabase, { rateLimitPerMin: 60 })
48
+
49
+ // --- Stateless transport, JSON response mode ---
50
+ const transport = new StreamableHTTPServerTransport({
51
+ sessionIdGenerator: undefined,
52
+ enableJsonResponse: true,
53
+ })
54
+
55
+ await server.connect(transport)
56
+
57
+ // Read body — Vercel Node already parses JSON for us at req.body, but let's be safe
58
+ let parsedBody: unknown
59
+ if ((req as any).body !== undefined) {
60
+ parsedBody = (req as any).body
61
+ } else {
62
+ const chunks: Buffer[] = []
63
+ for await (const c of req) chunks.push(c as Buffer)
64
+ const raw = Buffer.concat(chunks).toString('utf8')
65
+ try { parsedBody = raw ? JSON.parse(raw) : undefined } catch { parsedBody = undefined }
66
+ }
67
+
68
+ await transport.handleRequest(req as any, res, parsedBody)
69
+ } catch (e: any) {
70
+ if (!res.headersSent) {
71
+ res.statusCode = 500
72
+ res.setHeader('content-type', 'application/json')
73
+ res.end(JSON.stringify({ error: 'Handler threw', message: String(e?.message || e), stack: String(e?.stack || '').slice(0, 2000) }))
74
+ }
75
+ }
76
+ }
package/vercel.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "functions": {
3
+ "api/mcp.js": {
4
+ "runtime": "nodejs20.x",
5
+ "maxDuration": 30
6
+ }
7
+ },
8
+ "rewrites": [
9
+ { "source": "/mcp", "destination": "/api/mcp" }
10
+ ]
11
+ }