git-paid 2.1.3 → 2.1.4

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/lib/mcp.js CHANGED
@@ -9,8 +9,20 @@ import readline from "node:readline";
9
9
  import { scanTargetUrl, searchBuyerIntentRadar, dispatchDirectories, DIRECTORIES } from "./engine.js";
10
10
  import { verifyCliLicense } from "./auth.js";
11
11
  import { applyLocalSeoFixes } from "./fixer.js";
12
- import { listInboxMessages, sendTestVerificationEmail } from "./inbox.js";
13
- import { withStatefulMcp, createGenericEntityAdapter } from "./stateful-mcp.js";
12
+ import { listInboxMessages, sendTestVerificationEmail, getBotInboxForDomain, markMessageVerified } from "./inbox.js";
13
+ import { withStatefulMcp, createGenericEntityAdapter, spotlightUntrustedText } from "./stateful-mcp.js";
14
+ import { safeFetch } from "./safe-fetch.js";
15
+
16
+ const ALLOWED_VERIFY_DOMAINS = [
17
+ "postbuild.dev",
18
+ ...DIRECTORIES.map((d) => {
19
+ try {
20
+ return new URL(d.url).hostname.replace(/^www\./i, "").toLowerCase();
21
+ } catch {
22
+ return null;
23
+ }
24
+ }).filter(Boolean)
25
+ ];
14
26
 
15
27
  // ─── 1. STATEFUL MCP ENTITY ADAPTERS ──────────────────────────────────────────
16
28
 
@@ -43,7 +55,7 @@ export const inboxEntityAdapter = createGenericEntityAdapter({
43
55
  updatedAtField: "receivedAt",
44
56
  stubFields: ["id", "from", "otpCode", "primaryLink", "autoVerified"],
45
57
  journalFields: ["verificationLinks"],
46
- untrustedTextFields: ["subject", "snippet"],
58
+ untrustedTextFields: ["from", "subject", "snippet", "primaryLink", "otpCode"],
47
59
  isActiveRecord: () => true
48
60
  });
49
61
 
@@ -84,7 +96,7 @@ export const mcpRadar = withStatefulMcp({
84
96
 
85
97
  const domainDirectoryState = new Map();
86
98
 
87
- function getDomainDirectories(targetUrl = "https://postbuild.dev", report = null) {
99
+ function getDomainDirectories(targetUrl = "https://www.postbuild.dev", report = null) {
88
100
  const domain = targetUrl.replace(/^https?:\/\//i, "").replace(/^www\./i, "").split("/")[0] || "postbuild.dev";
89
101
  if (!domainDirectoryState.has(domain)) {
90
102
  const baseDirs = (report?.directories || DIRECTORIES).map((d, idx) => ({
@@ -111,46 +123,56 @@ function getDomainDirectories(targetUrl = "https://postbuild.dev", report = null
111
123
  return domainDirectoryState.get(domain);
112
124
  }
113
125
 
114
- // ─── 2. HANDS-FREE INBOX AUTO-VERIFIER ────────────────────────────────────────
126
+ // ─── 2. HANDS-FREE INBOX AUTO-VERIFIER (OPT-IN & SSRF-ALLOWLISTED) ────────────
115
127
 
116
- export async function autoVerifyInboxLinks(inboxAddress = "postbuild-bot@postbuild.dev") {
117
- const res = await listInboxMessages(inboxAddress);
128
+ export async function autoVerifyInboxLinks(inboxAddress = "", options = {}) {
129
+ const shouldAutoVerify = options.autoVerify === true;
130
+ const targetMessageId = options.messageId ? String(options.messageId).trim() : "";
131
+ const res = await listInboxMessages(inboxAddress || getBotInboxForDomain("postbuild.dev"), {
132
+ allowRemoteFallback: options.allowRemoteFallback,
133
+ bearerToken: options.bearerToken
134
+ });
118
135
  const verificationResults = [];
119
136
 
120
137
  for (const m of res.messages) {
138
+ const shouldVerifyThisRow =
139
+ shouldAutoVerify && (!targetMessageId || m.id === targetMessageId);
121
140
  const entry = {
122
141
  id: m.id,
123
142
  from: m.from,
124
143
  subject: m.subject,
125
144
  otpCode: m.otpCode || null,
126
- primaryLink: m.primaryLink || null,
127
- autoVerified: false,
128
- httpStatus: null,
145
+ primaryLink: m.primaryLink ? spotlightUntrustedText(m.primaryLink) : null,
146
+ verificationUrl: m.verificationUrl || (m.primaryLink && /^https:\/\//i.test(m.primaryLink) ? m.primaryLink : null),
147
+ autoVerified: Boolean(m.autoVerified || m.status === "verified"),
148
+ status: m.status,
149
+ httpStatus: m.httpStatus ?? null,
129
150
  version_etag: m.autoVerified ? "v2" : "v1",
130
151
  receivedAt: m.receivedAt,
131
152
  snippet: m.snippet
132
153
  };
133
154
 
134
- if (m.primaryLink && /^https?:\/\//i.test(m.primaryLink)) {
155
+ if (shouldVerifyThisRow && !entry.autoVerified && m.primaryLink && /^https?:\/\//i.test(m.primaryLink)) {
135
156
  try {
136
- const controller = new AbortController();
137
- const timer = setTimeout(() => controller.abort(), 4500);
138
- const resp = await fetch(m.primaryLink, {
157
+ const resp = await safeFetch(m.primaryLink, {
139
158
  method: "GET",
140
- redirect: "follow",
141
- signal: controller.signal,
159
+ timeoutMs: 4500,
160
+ allowedDomains: ALLOWED_VERIFY_DOMAINS,
161
+ lookupFn: options.lookupFn,
142
162
  headers: {
143
- "User-Agent": "Postbuild-Autonomous-Verifier/2.1 (+https://postbuild.dev)"
163
+ "User-Agent": "Postbuild-Verifier/2.1 (+https://www.postbuild.dev)"
144
164
  }
145
165
  });
146
- clearTimeout(timer);
147
166
  entry.autoVerified = resp.ok || resp.status < 400;
148
167
  entry.httpStatus = resp.status;
168
+ entry.status = entry.autoVerified ? "verified" : m.status;
149
169
  entry.version_etag = "v2";
170
+ if (entry.autoVerified) {
171
+ markMessageVerified(m.id, true, resp.status);
172
+ }
150
173
  } catch {
151
- entry.autoVerified = m.primaryLink.includes("postbuild.dev") || m.primaryLink.includes("confirm");
152
- entry.httpStatus = entry.autoVerified ? 200 : 0;
153
- entry.version_etag = "v2";
174
+ entry.autoVerified = false;
175
+ entry.httpStatus = 0;
154
176
  }
155
177
  }
156
178
 
@@ -161,7 +183,9 @@ export async function autoVerifyInboxLinks(inboxAddress = "postbuild-bot@postbui
161
183
  inboxAddress: res.inboxAddress,
162
184
  totalMessages: verificationResults.length,
163
185
  verifiedCount: verificationResults.filter((x) => x.autoVerified).length,
164
- extractedOtps: verificationResults.filter((x) => x.otpCode).map((x) => ({ from: x.from, otp: x.otpCode })),
186
+ extractedOtps: verificationResults
187
+ .filter((x) => x.otpCode)
188
+ .map((x) => ({ from: spotlightUntrustedText(x.from), otp: spotlightUntrustedText(x.otpCode) })),
165
189
  messages: verificationResults
166
190
  };
167
191
  }
@@ -243,21 +267,20 @@ export async function runStatefulMcpSimulation({
243
267
  // ─── 4. OBSIDIAN VAULTOS TELEMETRY & DASHBOARD SYNC ───────────────────────────
244
268
 
245
269
  export async function syncPostbuildToVault({
246
- vaultPath = "C:\\Users\\Bennett\\Bennett Labs",
247
- urls = ["https://postbuild.dev", "https://payarity.com"],
248
- sessionId = "vaultos-sync"
270
+ vaultPath = process.cwd(),
271
+ urls = ["https://www.postbuild.dev"],
272
+ sessionId = "vaultos-sync",
273
+ bearerToken = ""
249
274
  } = {}) {
250
275
  const projectsData = [];
251
276
 
252
277
  for (const targetUrl of urls) {
253
278
  const report = await scanTargetUrl(targetUrl);
254
279
  const state = getDomainDirectories(targetUrl, report);
255
-
256
- const currentInbox = await listInboxMessages(report.botEmail);
257
- if (currentInbox.count === 0) {
258
- await sendTestVerificationEmail(report.botEmail, report.domain);
259
- }
260
- const verifiedInbox = await autoVerifyInboxLinks(report.botEmail);
280
+ const verifiedInbox = await autoVerifyInboxLinks(report.botEmail, {
281
+ autoVerify: false,
282
+ bearerToken
283
+ });
261
284
 
262
285
  const dirsQuery = await mcpDirectories.queryWithSupersetCache({
263
286
  sessionId,
@@ -282,7 +305,7 @@ export async function syncPostbuildToVault({
282
305
  botEmail: report.botEmail,
283
306
  inboxCount: verifiedInbox.totalMessages,
284
307
  autoVerifiedLinks: verifiedInbox.verifiedCount,
285
- latestOtp: verifiedInbox.extractedOtps[0]?.otp || "849204",
308
+ latestOtp: verifiedInbox.extractedOtps[0]?.otp || "None",
286
309
  mcpReductionPct: mcpPass2._mcp?.payload_bytes?.reduction_pct || "-75.4%",
287
310
  mcpQueryMs: mcpPass2._mcp?.query_ms || 0.04,
288
311
  updatedAt: new Date().toISOString()
@@ -312,26 +335,54 @@ export async function syncPostbuildToVault({
312
335
  };
313
336
 
314
337
  const writtenVaultFiles = [];
338
+ const effectiveTarget = fs.existsSync(vaultPath) ? vaultPath : process.cwd();
339
+ const isObsidianVault =
340
+ fs.existsSync(path.join(effectiveTarget, ".obsidian")) ||
341
+ fs.existsSync(path.join(effectiveTarget, "_dashboards"));
315
342
 
316
- if (fs.existsSync(vaultPath)) {
317
- const metaDir = path.join(vaultPath, "_meta");
343
+ if (isObsidianVault) {
344
+ const metaDir = path.join(effectiveTarget, "_meta");
318
345
  fs.mkdirSync(metaDir, { recursive: true });
319
346
  const metaFile = path.join(metaDir, "postbuild-telemetry.json");
320
347
  fs.writeFileSync(metaFile, JSON.stringify(telemetryPayload, null, 2), "utf8");
321
348
  writtenVaultFiles.push(metaFile);
322
349
 
323
- const dashboardsDir = path.join(vaultPath, "_dashboards");
350
+ const dashboardsDir = path.join(effectiveTarget, "_dashboards");
324
351
  if (fs.existsSync(dashboardsDir)) {
325
352
  const pbDashboardPath = path.join(dashboardsDir, "Postbuild Launch.md");
326
353
  const pbDashboardContent = buildVaultOsPostbuildDashboardMarkdown();
327
354
  fs.writeFileSync(pbDashboardPath, pbDashboardContent, "utf8");
328
355
  writtenVaultFiles.push(pbDashboardPath);
329
356
  }
357
+ } else {
358
+ const pbDir = path.join(effectiveTarget, ".postbuild");
359
+ fs.mkdirSync(pbDir, { recursive: true });
360
+ const jsonFile = path.join(pbDir, "telemetry.json");
361
+ fs.writeFileSync(jsonFile, JSON.stringify(telemetryPayload, null, 2), "utf8");
362
+ writtenVaultFiles.push(jsonFile);
363
+
364
+ const mdLines = [
365
+ "# postbuild Launch & SEO Status Report",
366
+ "",
367
+ `> Synced: \`${telemetryPayload.generatedAt}\` via \`postbuild-mcp\``,
368
+ "",
369
+ "| Domain | Readiness Score | Checks | Programmatic SEO | Directories | Bot Inbox | Latest OTP |",
370
+ "| :--- | :--- | :--- | :--- | :--- | :--- | :--- |",
371
+ ...telemetryPayload.projects.map(
372
+ (p) =>
373
+ `| **${p.domain}** | **${p.readinessScore}/100** | ${p.passedChecks}/${p.totalChecks} | ${p.pseoCount} Routes | ${p.directoryCount} (${p.autoVerifiedLinks} Verified) | \`${p.botEmail}\` | \`${p.latestOtp}\` |`
374
+ ),
375
+ ""
376
+ ];
377
+ const mdFile = path.join(effectiveTarget, "LAUNCH_STATUS.md");
378
+ fs.writeFileSync(mdFile, mdLines.join("\n"), "utf8");
379
+ writtenVaultFiles.push(mdFile);
330
380
  }
331
381
 
332
382
  return {
333
383
  ok: true,
334
- vaultPath,
384
+ mode: isObsidianVault ? "obsidian_vault" : "markdown_repo",
385
+ vaultPath: effectiveTarget,
335
386
  writtenVaultFiles,
336
387
  telemetry: telemetryPayload
337
388
  };
@@ -340,7 +391,7 @@ export async function syncPostbuildToVault({
340
391
  function buildVaultOsPostbuildDashboardMarkdown() {
341
392
  return `---
342
393
  aliases:
343
- - Postbuild Launch Cockpit
394
+ - Postbuild Launch Dashboard
344
395
  - "_dashboards/Postbuild Launch"
345
396
  tags:
346
397
  - dashboard
@@ -352,7 +403,7 @@ cssclasses:
352
403
  ---
353
404
 
354
405
  \`\`\`dataviewjs
355
- // ─── POSTBUILD MCP LAUNCH COCKPIT ────────────────────────────────────────────
406
+ // ─── POSTBUILD MCP LAUNCH DASHBOARD ──────────────────────────────────────────
356
407
  // Reads cached telemetry from _meta/postbuild-telemetry.json (<2ms render)
357
408
  // ─────────────────────────────────────────────────────────────────────────────
358
409
 
@@ -392,8 +443,8 @@ root.innerHTML = \`
392
443
 
393
444
  <div class="hero-strip">
394
445
  <div>
395
- <div class="hero-title">Postbuild Launch &amp; SEO Command Center</div>
396
- <div class="hero-subtitle">Managed autonomously by Gemini × Postbuild MCP (<code>npx postbuild mcp</code>)</div>
446
+ <div class="hero-title">Postbuild Launch &amp; SEO Dashboard</div>
447
+ <div class="hero-subtitle">Managed autonomously by Postbuild MCP (<code>npx git-paid mcp</code>)</div>
397
448
  </div>
398
449
  <div class="stat-group">
399
450
  <div class="stat-block">
@@ -423,7 +474,7 @@ root.innerHTML = \`
423
474
  <span class="badge" style="background:rgba(16,185,129,0.15); color:#10b981; border:1px solid rgba(16,185,129,0.3);">LIVE AUDITS</span>
424
475
  Domain Readiness, pSEO &amp; Directory Dispatch
425
476
  </div>
426
- <a class="action-btn" href="https://postbuild.dev" style="text-decoration:none;">Open Studio -></a>
477
+ <a class="action-btn" href="https://www.postbuild.dev" style="text-decoration:none;">Open Studio -></a>
427
478
  </div>
428
479
  <div style="display:flex; flex-direction:column; gap:8px;">
429
480
  \${projects.map(p => \`
@@ -432,7 +483,7 @@ root.innerHTML = \`
432
483
  <strong style="font-size:14px;">\${p.domain}</strong>
433
484
  <span class="badge badge-cyan" style="margin-left:8px;">\${p.passedChecks}/\${p.totalChecks} Checks Passed</span>
434
485
  <div style="font-size:11.5px; color:var(--text-muted); margin-top:4px;">
435
- <code>\${p.botEmail}</code> · \${p.pseoCount} pSEO Routes · \${p.directoryCount} Directories (\${p.autoVerifiedLinks} Auto-Verified) · Latest OTP: <code>\${p.latestOtp}</code>
486
+ <code>\${p.botEmail}</code> · \${p.pseoCount} pSEO Routes · \${p.directoryCount} Directories (\${p.autoVerifiedLinks} Verified) · Latest OTP: <code>\${p.latestOtp}</code>
436
487
  </div>
437
488
  </div>
438
489
  <div style="text-align:right;">
@@ -470,7 +521,7 @@ root.innerHTML = \`
470
521
  `;
471
522
  }
472
523
 
473
- // ─── 5. AGENT SKILL & CONFIG SCAFFOLDER (`npx postbuild init-agent`) ──────────
524
+ // ─── 5. AGENT SKILL & CONFIG SCAFFOLDER (`npx git-paid skill`) ───────────────
474
525
 
475
526
  export function installAgentSkillFiles({ cwd = process.cwd() } = {}) {
476
527
  const skillDir = path.join(cwd, ".agent", "skills", "postbuild");
@@ -479,12 +530,12 @@ export function installAgentSkillFiles({ cwd = process.cwd() } = {}) {
479
530
  const skillMdPath = path.join(skillDir, "SKILL.md");
480
531
  const skillMd = `---
481
532
  name: postbuild
482
- description: Autonomous Post-Build SEO, 85-Directory Dispatch, @postbuild.dev Inbox Auto-Verifier, and Obsidian VaultOS Sync powered by Postbuild MCP (postbuild-mcp v2.1.0).
533
+ description: Autonomous Post-Build SEO, 85-Directory Launch Kit, @postbuild.dev Inbox Verifier, and Markdown Launch Status Sync powered by Postbuild MCP (git-paid).
483
534
  ---
484
535
 
485
- # Postbuild (\`git paid\`) Agent Skill
536
+ # Postbuild (\`git-paid\`) Agent Skill
486
537
 
487
- Use the \`postbuild\` MCP server (\`npx postbuild mcp\`) or CLI (\`npx postbuild\`) to audit, fix, monetize, and launch any web project.
538
+ Use the \`git-paid\` MCP server (\`npx -y git-paid mcp\`) or CLI (\`npx git-paid\`) to audit, fix, monetize, and launch any web project.
488
539
 
489
540
  ## MCP Server Configuration (\`.mcp.json\` / \`mcp_config.json\`)
490
541
  \`\`\`json
@@ -492,7 +543,7 @@ Use the \`postbuild\` MCP server (\`npx postbuild mcp\`) or CLI (\`npx postbuild
492
543
  "mcpServers": {
493
544
  "postbuild": {
494
545
  "command": "npx",
495
- "args": ["-y", "postbuild", "mcp"]
546
+ "args": ["-y", "git-paid", "mcp"]
496
547
  }
497
548
  }
498
549
  }
@@ -500,11 +551,11 @@ Use the \`postbuild\` MCP server (\`npx postbuild mcp\`) or CLI (\`npx postbuild
500
551
 
501
552
  ## Available Postbuild MCP Tools
502
553
  1. \`postbuild_scan\` — Run the 8-check live Monetization & SEO audit on any URL.
503
- 2. \`postbuild_directories\` — Query the 85 startup & AI directories using In-Memory Superset Caching (1ms subset filtering) + Watermark Context Residuals (\`unchanged@vN\`, -75% to -90% tokens).
554
+ 2. \`postbuild_directories\` — Query the 85 startup & AI directories using In-Memory Superset Caching + Watermark Context Residuals (\`unchanged@vN\`).
504
555
  3. \`postbuild_pseo\` — Query the 25 Programmatic SEO routes with stateful delta compaction.
505
- 4. \`postbuild_dispatch\` — Dispatch a project to directories protected by Two-Phase Cryptographic OCC (\`dry_run: true\` issues \`commit_token: "ct_..."\`; \`dry_run: false\` commits).
506
- 5. \`postbuild_inbox\` — Read \`<slug>-bot@postbuild.dev\` with Untrusted Content Spotlighting and automatically click/confirm directory verification links (\`auto_verify: true\`).
507
- 6. \`postbuild_vault_sync\` — Sync all live readiness scores, inbox OTPs, MCP token savings, and Buyer Radar threads directly into an Obsidian VaultOS dashboard (\`_meta/postbuild-telemetry.json\` & \`_dashboards/Postbuild Launch.md\`).
556
+ 4. \`postbuild_dispatch\` — Prepare 85 prefilled launch links and ping IndexNow/WebSub protected by Two-Phase Cryptographic OCC (\`dry_run: true\` issues \`commit_token: "ct_..."\`; \`dry_run: false\` commits).
557
+ 5. \`postbuild_inbox\` — Read \`<slug>-<hash>@postbuild.dev\` with Untrusted Content Spotlighting and optionally verify allowlisted directory confirmation links (\`auto_verify: true\`).
558
+ 6. \`postbuild_vault_sync\` — Write \`LAUNCH_STATUS.md\` and \`.postbuild/telemetry.json\` to any repository (or sync to an Obsidian VaultOS dashboard if present).
508
559
  `;
509
560
  fs.writeFileSync(skillMdPath, skillMd, "utf8");
510
561
 
@@ -515,24 +566,24 @@ Use the \`postbuild\` MCP server (\`npx postbuild mcp\`) or CLI (\`npx postbuild
515
566
  mcpServers: {
516
567
  postbuild: {
517
568
  command: "npx",
518
- args: ["-y", "postbuild", "mcp"]
569
+ args: ["-y", "git-paid", "mcp"]
519
570
  }
520
571
  }
521
572
  }
522
573
  };
523
574
  }
524
575
 
525
- // ─── 6. STDIO JSON-RPC 2.0 MCP SERVER (`npx postbuild mcp`) ───────────────────
576
+ // ─── 6. STDIO JSON-RPC 2.0 MCP SERVER (`npx git-paid mcp`) ───────────────────
526
577
 
527
578
  export const MCP_TOOLS = [
528
579
  {
529
580
  name: "postbuild_scan",
530
581
  description:
531
- "Run an 8-point Post-Build Monetization, AI Crawler, & SEO audit on any URL and provision a dedicated <slug>-bot@postbuild.dev verification inbox.",
582
+ "Run an 8-point Post-Build Monetization, AI Crawler, & SEO audit on any URL and provision a dedicated <slug>-<hash>@postbuild.dev verification inbox.",
532
583
  inputSchema: {
533
584
  type: "object",
534
585
  properties: {
535
- url: { type: "string", description: "Target URL or domain (e.g. https://postbuild.dev)" }
586
+ url: { type: "string", description: "Target URL or domain (e.g. https://www.postbuild.dev)" }
536
587
  },
537
588
  required: ["url"]
538
589
  }
@@ -540,11 +591,11 @@ export const MCP_TOOLS = [
540
591
  {
541
592
  name: "postbuild_directories",
542
593
  description:
543
- "Search and filter the 85 startup, AI, and developer directories using In-Memory Superset Cache and Watermark Context Residuals (unchanged@vN / updated@vN) for >75% token reduction.",
594
+ "Search and filter the 85 startup, AI, and developer directories using In-Memory Superset Cache and Watermark Context Residuals (unchanged@vN / updated@vN).",
544
595
  inputSchema: {
545
596
  type: "object",
546
597
  properties: {
547
- url: { type: "string", description: "Target URL (default: https://postbuild.dev)" },
598
+ url: { type: "string", description: "Target URL (default: https://www.postbuild.dev)" },
548
599
  category: { type: "string", description: "Optional category filter (e.g. AI, SaaS, Developer, Launch)" },
549
600
  status: { type: "string", description: "Optional status filter (ready_auto, queued, dispatched)" },
550
601
  min_da: { type: "number", description: "Minimum Domain Rating (0-100)" },
@@ -569,7 +620,7 @@ export const MCP_TOOLS = [
569
620
  {
570
621
  name: "postbuild_dispatch",
571
622
  description:
572
- "Dispatch a domain across the 85 directories with Two-Phase Cryptographic OCC Guard. Call with dry_run: true first to receive a commit_token (ct_...), then call with dry_run: false and commit_token to commit.",
623
+ "Prepare 85 prefilled directory links and ping IndexNow/WebSub with Two-Phase Cryptographic OCC Guard. Call with dry_run: true first to receive a commit_token (ct_...), then call with dry_run: false and commit_token to commit.",
573
624
  inputSchema: {
574
625
  type: "object",
575
626
  properties: {
@@ -577,7 +628,7 @@ export const MCP_TOOLS = [
577
628
  directory_ids: {
578
629
  type: "array",
579
630
  items: { type: "string" },
580
- description: "Optional subset of directory IDs (omit for all auto-dispatch directories)"
631
+ description: "Optional subset of directory IDs"
581
632
  },
582
633
  expected_version: { type: "string", description: "Expected version watermark (e.g. v1)" },
583
634
  dry_run: { type: "boolean", description: "Phase 1 preview mode (default: true)" },
@@ -589,13 +640,12 @@ export const MCP_TOOLS = [
589
640
  {
590
641
  name: "postbuild_inbox",
591
642
  description:
592
- "Check the dedicated <slug>-bot@postbuild.dev verification inbox with Untrusted Content Spotlighting. Set auto_verify: true to have the agent automatically click confirmation links and extract 6-digit OTPs.",
643
+ "Check the dedicated <slug>-<hash>@postbuild.dev verification inbox with Untrusted Content Spotlighting. Set auto_verify: true to follow allowlisted directory confirmation links.",
593
644
  inputSchema: {
594
645
  type: "object",
595
646
  properties: {
596
- inbox: { type: "string", description: "Bot inbox address (e.g. postbuild-bot@postbuild.dev)" },
597
- auto_verify: { type: "boolean", description: "Automatically follow confirmation links (default: true)" },
598
- send_test: { type: "boolean", description: "Send a test verification email first" }
647
+ inbox: { type: "string", description: "Bot inbox address" },
648
+ auto_verify: { type: "boolean", description: "Opt-in: follow allowlisted confirmation links (default: false)" }
599
649
  }
600
650
  }
601
651
  },
@@ -615,13 +665,13 @@ export const MCP_TOOLS = [
615
665
  {
616
666
  name: "postbuild_vault_sync",
617
667
  description:
618
- "Sync live Postbuild SEO scores, 85-directory status, inbox OTPs, Buyer Radar threads, and MCP token telemetry into an Obsidian VaultOS dashboard (_meta/postbuild-telemetry.json & _dashboards/Postbuild Launch.md).",
668
+ "Write LAUNCH_STATUS.md and .postbuild/telemetry.json into a local project directory (or sync to an Obsidian VaultOS dashboard if .obsidian/ is present).",
619
669
  inputSchema: {
620
670
  type: "object",
621
671
  properties: {
622
672
  vault_path: {
623
673
  type: "string",
624
- description: "Absolute path to Obsidian vault (default: C:\\Users\\Bennett\\Bennett Labs)"
674
+ description: "Target repository or Obsidian vault path (defaults to current working directory)"
625
675
  },
626
676
  urls: {
627
677
  type: "array",
@@ -633,10 +683,10 @@ export const MCP_TOOLS = [
633
683
  }
634
684
  ];
635
685
 
636
- export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio-session") {
686
+ export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio-session", authToken = "") {
637
687
  if (name === "postbuild_scan") {
638
- const report = await scanTargetUrl(args.url || "https://postbuild.dev");
639
- const license = await verifyCliLicense({ domain: report.domain });
688
+ const report = await scanTargetUrl(args.url || "https://www.postbuild.dev");
689
+ const license = await verifyCliLicense({ domain: report.domain, token: authToken });
640
690
  getDomainDirectories(report.targetUrl, report);
641
691
  return {
642
692
  domain: report.domain,
@@ -658,9 +708,9 @@ export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio
658
708
  }
659
709
 
660
710
  if (name === "postbuild_directories") {
661
- const targetUrl = args.url || "https://postbuild.dev";
711
+ const targetUrl = args.url || "https://www.postbuild.dev";
662
712
  const state = getDomainDirectories(targetUrl);
663
- const license = await verifyCliLicense({ domain: state.domain });
713
+ const license = await verifyCliLicense({ domain: state.domain, token: authToken });
664
714
  const catFilter = (args.category || "").toLowerCase();
665
715
  const statusFilter = (args.status || "").toLowerCase();
666
716
  const minDa = Number(args.min_da) || 0;
@@ -698,8 +748,8 @@ export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio
698
748
  }
699
749
 
700
750
  if (name === "postbuild_pseo") {
701
- const targetUrl = args.url || "https://postbuild.dev";
702
- const license = await verifyCliLicense({ domain: targetUrl.replace(/^https?:\/\//, "") });
751
+ const targetUrl = args.url || "https://www.postbuild.dev";
752
+ const license = await verifyCliLicense({ domain: targetUrl.replace(/^https?:\/\//, ""), token: authToken });
703
753
  const intentFilter = (args.intent || "").toLowerCase();
704
754
  const maxAllowed = license.valid ? 25 : 3;
705
755
 
@@ -738,9 +788,9 @@ export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio
738
788
  }
739
789
 
740
790
  if (name === "postbuild_dispatch") {
741
- const targetUrl = args.url || "https://postbuild.dev";
791
+ const targetUrl = args.url || "https://www.postbuild.dev";
742
792
  const state = getDomainDirectories(targetUrl);
743
- const license = await verifyCliLicense({ domain: state.domain });
793
+ const license = await verifyCliLicense({ domain: state.domain, token: authToken });
744
794
  if (!license.valid) {
745
795
  return {
746
796
  isError: true,
@@ -798,7 +848,7 @@ export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio
798
848
  state.updated_at = nowIso;
799
849
  for (const d of state.directories) {
800
850
  if (!targetIds.length || targetIds.includes(d.id)) {
801
- d.status = d.autoSubmit ? "dispatched" : "guided_ready";
851
+ d.status = d.autoSubmit ? "indexnow_pinged_form_ready" : "prefilled_ready";
802
852
  d.version_etag = nextVer;
803
853
  d.updated_at = nowIso;
804
854
  }
@@ -815,7 +865,7 @@ export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio
815
865
  }
816
866
 
817
867
  if (name === "postbuild_inbox") {
818
- const license = await verifyCliLicense({ domain: "postbuild.dev" });
868
+ const license = await verifyCliLicense({ domain: "postbuild.dev", token: authToken });
819
869
  if (!license.valid) {
820
870
  return {
821
871
  isError: true,
@@ -826,14 +876,12 @@ export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio
826
876
  };
827
877
  }
828
878
 
829
- const inboxAddr = args.inbox || "postbuild-bot@postbuild.dev";
830
- if (args.send_test) {
831
- await sendTestVerificationEmail(inboxAddr, "postbuild.dev");
832
- }
833
- const autoVerify = args.auto_verify !== undefined ? Boolean(args.auto_verify) : true;
834
- const result = autoVerify
835
- ? await autoVerifyInboxLinks(inboxAddr)
836
- : await listInboxMessages(inboxAddr);
879
+ const inboxAddr = args.inbox || license.inbox || getBotInboxForDomain(license.domain || "postbuild.dev", license.email);
880
+ const autoVerify = Boolean(args.auto_verify);
881
+ const result = await autoVerifyInboxLinks(inboxAddr, {
882
+ autoVerify,
883
+ bearerToken: license.token
884
+ });
837
885
 
838
886
  const compacted = mcpInbox.compactList({
839
887
  sessionId,
@@ -850,8 +898,8 @@ export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio
850
898
  }
851
899
 
852
900
  if (name === "postbuild_fix") {
853
- const report = await scanTargetUrl(args.url || "https://postbuild.dev");
854
- const license = await verifyCliLicense({ domain: report.domain });
901
+ const report = await scanTargetUrl(args.url || "https://www.postbuild.dev");
902
+ const license = await verifyCliLicense({ domain: report.domain, token: authToken });
855
903
  if (!license.valid) {
856
904
  return {
857
905
  isError: true,
@@ -871,7 +919,7 @@ export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio
871
919
  }
872
920
 
873
921
  if (name === "postbuild_vault_sync") {
874
- const license = await verifyCliLicense({ domain: "postbuild.dev" });
922
+ const license = await verifyCliLicense({ domain: "postbuild.dev", token: authToken });
875
923
  if (!license.valid) {
876
924
  return {
877
925
  isError: true,
@@ -883,9 +931,10 @@ export async function executeMcpToolCall(name, args = {}, sessionId = "mcp-stdio
883
931
  }
884
932
 
885
933
  return await syncPostbuildToVault({
886
- vaultPath: args.vault_path || "C:\\Users\\Bennett\\Bennett Labs",
887
- urls: Array.isArray(args.urls) && args.urls.length ? args.urls : ["https://postbuild.dev", "https://payarity.com"],
888
- sessionId
934
+ vaultPath: args.vault_path || process.cwd(),
935
+ urls: Array.isArray(args.urls) && args.urls.length ? args.urls : ["https://www.postbuild.dev"],
936
+ sessionId,
937
+ bearerToken: license.token
889
938
  });
890
939
  }
891
940