burn-mcp-server 2.0.5 → 2.0.7

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/glama.json ADDED
@@ -0,0 +1,3 @@
1
+ {
2
+ "maintainers": ["Fisher521"]
3
+ }
package/package.json CHANGED
@@ -1,15 +1,20 @@
1
1
  {
2
2
  "name": "burn-mcp-server",
3
- "version": "2.0.5",
3
+ "version": "2.0.7",
4
4
  "mcpName": "io.github.Fisher521/burn-mcp-server",
5
- "description": "MCP Server for Burn 22 tools to let your AI agent search, triage, and organize your reading. Works with Claude, Cursor, Windsurf.",
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",
7
7
  "bin": {
8
8
  "burn-mcp": "dist/index.js"
9
9
  },
10
10
  "scripts": {
11
- "build": "tsc",
12
- "start": "node dist/index.js"
11
+ "build": "esbuild src/index.ts --bundle --platform=node --target=node18 --outfile=dist/index.js --format=cjs --packages=external",
12
+ "build:http": "esbuild src/http-dev.ts --bundle --platform=node --target=node18 --outfile=dist/http.mjs --format=esm --packages=external",
13
+ "build:vercel": "esbuild src/vercel-node-handler.ts --bundle --platform=node --target=node20 --outfile=api/mcp.js --format=cjs",
14
+ "build:all": "npm run build && npm run build:http && npm run build:vercel",
15
+ "typecheck": "node --max-old-space-size=4096 node_modules/typescript/bin/tsc --noEmit",
16
+ "start": "node dist/index.js",
17
+ "dev:http": "npm run build:http && node dist/http.mjs"
13
18
  },
14
19
  "keywords": [
15
20
  "mcp",
@@ -49,7 +54,8 @@
49
54
  "zod": "^3.22.0"
50
55
  },
51
56
  "devDependencies": {
52
- "typescript": "^5.3.0",
53
- "@types/node": "^20.0.0"
57
+ "@types/node": "^20.0.0",
58
+ "esbuild": "^0.28.0",
59
+ "typescript": "^5.3.0"
54
60
  }
55
61
  }
@@ -0,0 +1,47 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Burn MCP Server</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1">
7
+ <style>
8
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; max-width: 640px; margin: 80px auto; padding: 0 20px; line-height: 1.6; color: #1a1a1a; }
9
+ h1 { font-size: 28px; margin-bottom: 8px; }
10
+ .tag { display: inline-block; background: #ff6a00; color: white; padding: 2px 10px; border-radius: 10px; font-size: 12px; margin-right: 6px; }
11
+ pre { background: #f5f5f5; padding: 16px; border-radius: 8px; overflow-x: auto; font-size: 13px; }
12
+ a { color: #ff6a00; text-decoration: none; }
13
+ a:hover { text-decoration: underline; }
14
+ code { background: #f5f5f5; padding: 2px 6px; border-radius: 4px; font-size: 13px; }
15
+ </style>
16
+ </head>
17
+ <body>
18
+ <h1>Burn MCP Server</h1>
19
+ <p><span class="tag">MCP</span> <span class="tag">Streamable HTTP</span> Read less, absorb more.</p>
20
+ <p>This is the remote HTTP endpoint for <a href="https://burn451.cloud">Burn</a>'s Model Context Protocol server. 26 tools to let Claude / Cursor / Windsurf search, triage, and analyze your saved reading.</p>
21
+
22
+ <h2>Connect</h2>
23
+ <p>Paste this into your MCP client (Claude Desktop, Cursor, Windsurf, etc.):</p>
24
+ <pre>{
25
+ "mcpServers": {
26
+ "burn": {
27
+ "url": "https://mcp.burn451.cloud/mcp",
28
+ "headers": {
29
+ "Authorization": "Bearer &lt;your-token&gt;"
30
+ }
31
+ }
32
+ }
33
+ }</pre>
34
+
35
+ <p>Get your token: <a href="https://burn451.cloud">burn451.cloud</a> → Settings → MCP Server → Copy Access Token</p>
36
+
37
+ <h2>Links</h2>
38
+ <ul>
39
+ <li><a href="https://github.com/Fisher521/burn-mcp-server">Source code on GitHub</a></li>
40
+ <li><a href="https://www.npmjs.com/package/burn-mcp-server">npm package (stdio mode)</a></li>
41
+ <li><a href="https://burn451.cloud">Burn web app</a></li>
42
+ <li><a href="https://x.com/hawking520">Built by @hawking520</a></li>
43
+ </ul>
44
+
45
+ <p style="color: #888; font-size: 13px; margin-top: 40px;">MIT licensed. Part of an open ecosystem of AI-era reading tools.</p>
46
+ </body>
47
+ </html>
package/server.json CHANGED
@@ -1,27 +1,42 @@
1
1
  {
2
2
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
3
  "name": "io.github.Fisher521/burn-mcp-server",
4
- "description": "22 tools to let your AI agent search, triage, and organize your reading list.",
4
+ "description": "AI-powered reading triage MCP. 26 tools with a 24h burn timer. Read less, absorb more.",
5
5
  "repository": {
6
6
  "url": "https://github.com/Fisher521/burn-mcp-server",
7
7
  "source": "github"
8
8
  },
9
- "version": "2.0.4",
9
+ "websiteUrl": "https://burn451.cloud",
10
+ "version": "2.0.7",
10
11
  "packages": [
11
12
  {
12
13
  "registryType": "npm",
13
14
  "identifier": "burn-mcp-server",
14
- "version": "2.0.4",
15
+ "version": "2.0.7",
15
16
  "transport": {
16
17
  "type": "stdio"
17
18
  },
18
19
  "environmentVariables": [
19
20
  {
20
- "description": "Long-lived MCP access token from Burn App Settings",
21
+ "name": "BURN_MCP_TOKEN",
22
+ "description": "Long-lived MCP token from Burn App → Settings → MCP Server",
21
23
  "isRequired": true,
22
24
  "format": "string",
23
- "isSecret": true,
24
- "name": "BURN_MCP_TOKEN"
25
+ "isSecret": true
26
+ }
27
+ ]
28
+ }
29
+ ],
30
+ "remotes": [
31
+ {
32
+ "type": "streamable-http",
33
+ "url": "https://burn-mcp-server.vercel.app/mcp",
34
+ "headers": [
35
+ {
36
+ "name": "Authorization",
37
+ "description": "Bearer <BURN_MCP_TOKEN> — get your token at https://burn451.cloud → Settings → MCP Server",
38
+ "isRequired": true,
39
+ "isSecret": true
25
40
  }
26
41
  ]
27
42
  }
@@ -0,0 +1,56 @@
1
+ // Burn MCP — standalone Node HTTP dev server for local testing.
2
+ // For production deploy, see api/mcp.ts (Vercel Edge) or src/http.ts (the handler).
3
+
4
+ import { createServer } from 'node:http'
5
+ import { handleMcpRequest } from './http.js'
6
+
7
+ const PORT = Number(process.env.PORT) || 3001
8
+
9
+ const server = createServer(async (nodeReq, nodeRes) => {
10
+ try {
11
+ const url = new URL(nodeReq.url || '/', `http://${nodeReq.headers.host || 'localhost'}`)
12
+ const headers = new Headers()
13
+ for (const [k, v] of Object.entries(nodeReq.headers)) {
14
+ if (typeof v === 'string') headers.set(k, v)
15
+ }
16
+ const body = ['GET', 'HEAD'].includes(nodeReq.method || 'GET')
17
+ ? null
18
+ : await new Promise<Buffer>((resolve, reject) => {
19
+ const chunks: Buffer[] = []
20
+ nodeReq.on('data', c => chunks.push(c))
21
+ nodeReq.on('end', () => resolve(Buffer.concat(chunks)))
22
+ nodeReq.on('error', reject)
23
+ })
24
+
25
+ const webReq = new Request(url, {
26
+ method: nodeReq.method,
27
+ headers,
28
+ body: body && body.length > 0 ? body : null,
29
+ })
30
+
31
+ const webRes = await handleMcpRequest(webReq)
32
+
33
+ nodeRes.statusCode = webRes.status
34
+ webRes.headers.forEach((v, k) => nodeRes.setHeader(k, v))
35
+ if (webRes.body) {
36
+ const reader = webRes.body.getReader()
37
+ while (true) {
38
+ const { done, value } = await reader.read()
39
+ if (done) break
40
+ nodeRes.write(value)
41
+ }
42
+ }
43
+ nodeRes.end()
44
+ } catch (e: any) {
45
+ nodeRes.statusCode = 500
46
+ nodeRes.setHeader('content-type', 'application/json')
47
+ nodeRes.end(JSON.stringify({ error: 'Internal error', detail: String(e?.message || e) }))
48
+ }
49
+ })
50
+
51
+ server.listen(PORT, () => {
52
+ console.log(`Burn MCP HTTP server listening on http://localhost:${PORT}`)
53
+ console.log(`Test: curl -H "Authorization: Bearer <TOKEN>" -X POST http://localhost:${PORT}/mcp \\`)
54
+ console.log(` -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \\`)
55
+ console.log(` -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'`)
56
+ })
package/src/http.ts ADDED
@@ -0,0 +1,62 @@
1
+ // Burn MCP — HTTP transport entry (Web Standard fetch API)
2
+ //
3
+ // Works on Vercel Edge / Node runtime, Cloudflare Workers, Deno, Bun.
4
+ // Users connect by adding ONE URL to Claude/Cursor/Windsurf MCP settings instead of installing npx.
5
+ //
6
+ // Auth: each request carries `Authorization: Bearer <BURN_MCP_TOKEN>` header.
7
+ // Stateless: fresh Supabase client per request (short in-memory session cache for performance).
8
+
9
+ import { WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js'
10
+ import { createClient } from '@supabase/supabase-js'
11
+ import { getOrExchangeSession, applySession } from './lib/auth.js'
12
+ import { createBurnServer } from './setup.js'
13
+
14
+ const SUPABASE_URL = process.env.BURN_SUPABASE_URL || 'https://juqtxylquemiuvvmgbej.supabase.co'
15
+ const SUPABASE_ANON_KEY = process.env.BURN_SUPABASE_ANON_KEY || 'sb_publishable_reVgmmCC6ndIo6jFRMM2LQ_wujj5FrO'
16
+
17
+ /** Main handler — turn an incoming HTTP Request into a JSON-RPC MCP Response. */
18
+ export async function handleMcpRequest(req: Request): Promise<Response> {
19
+ // --- Auth: require Bearer token ---
20
+ const authHeader = req.headers.get('authorization') || req.headers.get('Authorization') || ''
21
+ const match = authHeader.match(/^Bearer\s+(.+)$/i)
22
+ const token = match?.[1]?.trim()
23
+
24
+ if (!token) {
25
+ return new Response(JSON.stringify({
26
+ error: 'Missing Authorization header',
27
+ hint: 'Add `Authorization: Bearer <BURN_MCP_TOKEN>` header. Get your token at https://burn451.cloud → Settings → MCP Server.',
28
+ }), { status: 401, headers: { 'content-type': 'application/json' } })
29
+ }
30
+
31
+ // --- Exchange token → Supabase session (cached in memory 5 min per token) ---
32
+ let session
33
+ try {
34
+ session = await getOrExchangeSession(token)
35
+ } catch (e: any) {
36
+ return new Response(JSON.stringify({
37
+ error: 'Invalid or expired Burn MCP token',
38
+ detail: String(e?.message || e),
39
+ }), { status: 401, headers: { 'content-type': 'application/json' } })
40
+ }
41
+
42
+ // --- Build per-request Supabase client with JWT in headers (faster than setSession, Edge-safe) ---
43
+ const supabase = createClient(SUPABASE_URL, SUPABASE_ANON_KEY, {
44
+ auth: { persistSession: false, autoRefreshToken: false, detectSessionInUrl: false },
45
+ global: {
46
+ headers: { Authorization: `Bearer ${session.access_token}` },
47
+ },
48
+ })
49
+
50
+ const server = createBurnServer(supabase, { rateLimitPerMin: 60 })
51
+
52
+ // --- Streamable HTTP transport (stateless mode — no session reuse across requests) ---
53
+ const transport = new WebStandardStreamableHTTPServerTransport({
54
+ sessionIdGenerator: undefined, // stateless mode — MCP SDK treats each request as a new conversation
55
+ enableJsonResponse: true,
56
+ })
57
+
58
+ await server.connect(transport)
59
+ return transport.handleRequest(req)
60
+ }
61
+
62
+ // Standalone Node dev server is in src/http-dev.ts (npm run dev:http)