mcp-scraper 0.17.0 → 0.17.2
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/dist/bin/api-server.cjs +294 -27
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +1 -1
- package/dist/bin/mcp-scraper-cli.cjs +1 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +1 -1
- package/dist/bin/mcp-scraper-install.cjs +1 -1
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +1 -1
- package/dist/bin/mcp-stdio-server.cjs +1 -1
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +2 -2
- package/dist/{chunk-LENCALSN.js → chunk-HJ3XIHWC.js} +2 -2
- package/dist/chunk-IDRSO4HX.js +7 -0
- package/dist/chunk-IDRSO4HX.js.map +1 -0
- package/dist/{server-5KTVLL3L.js → server-U5VODSSW.js} +285 -26
- package/dist/server-U5VODSSW.js.map +1 -0
- package/package.json +12 -3
- package/dist/chunk-L3FT4JBT.js +0 -7
- package/dist/chunk-L3FT4JBT.js.map +0 -1
- package/dist/server-5KTVLL3L.js.map +0 -1
- /package/dist/{chunk-LENCALSN.js.map → chunk-HJ3XIHWC.js.map} +0 -0
package/dist/bin/api-server.cjs
CHANGED
|
@@ -27642,7 +27642,7 @@ var PACKAGE_VERSION;
|
|
|
27642
27642
|
var init_version = __esm({
|
|
27643
27643
|
"src/version.ts"() {
|
|
27644
27644
|
"use strict";
|
|
27645
|
-
PACKAGE_VERSION = "0.17.
|
|
27645
|
+
PACKAGE_VERSION = "0.17.2";
|
|
27646
27646
|
}
|
|
27647
27647
|
});
|
|
27648
27648
|
|
|
@@ -38754,6 +38754,245 @@ var init_schedule_routes = __esm({
|
|
|
38754
38754
|
}
|
|
38755
38755
|
});
|
|
38756
38756
|
|
|
38757
|
+
// src/api/resend-inbound-routes.ts
|
|
38758
|
+
function classifyInboundRecipients(recipients, ...receivingDomains) {
|
|
38759
|
+
const normalized = recipients.map((address) => address.trim().toLowerCase());
|
|
38760
|
+
const domains = receivingDomains.map((domain) => domain?.trim().toLowerCase()).filter((domain) => Boolean(domain));
|
|
38761
|
+
const supportAddresses = [SUPPORT_ADDRESS, ...domains.map((domain) => `support@${domain}`)];
|
|
38762
|
+
const dmarcAddresses = [DMARC_ADDRESS, ...domains.map((domain) => `dmarc@${domain}`)];
|
|
38763
|
+
if (supportAddresses.some((address) => normalized.includes(address))) return "support";
|
|
38764
|
+
if (dmarcAddresses.some((address) => normalized.includes(address))) return "dmarc";
|
|
38765
|
+
return "ignore";
|
|
38766
|
+
}
|
|
38767
|
+
function cleanLine(value, fallback) {
|
|
38768
|
+
const clean2 = value.replace(/[\r\n\t]+/g, " ").replace(/\s+/g, " ").trim();
|
|
38769
|
+
return (clean2 || fallback).slice(0, 240);
|
|
38770
|
+
}
|
|
38771
|
+
function quoteUntrusted(value) {
|
|
38772
|
+
const clean2 = value.replace(/\0/g, "").trim().slice(0, 16e3);
|
|
38773
|
+
if (!clean2) return "> _(No plain-text body was available. Review the forwarded email.)_";
|
|
38774
|
+
return clean2.split("\n").map((line) => `> ${line}`).join("\n");
|
|
38775
|
+
}
|
|
38776
|
+
function escapeHtml3(value) {
|
|
38777
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
38778
|
+
}
|
|
38779
|
+
function safeEmailId(value) {
|
|
38780
|
+
return value.replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 100) || "unknown-email";
|
|
38781
|
+
}
|
|
38782
|
+
function buildSupportIssueNote(email) {
|
|
38783
|
+
const sender = cleanLine(email.from, "unknown sender");
|
|
38784
|
+
const subject = cleanLine(email.subject, "(no subject)");
|
|
38785
|
+
const receivedAt = cleanLine(email.created_at, (/* @__PURE__ */ new Date()).toISOString());
|
|
38786
|
+
const attachments = email.attachments?.length ? email.attachments.map((item) => cleanLine(item.filename ?? "unnamed attachment", "unnamed attachment")).join(", ") : "None";
|
|
38787
|
+
const datePrefix = receivedAt.slice(0, 10).replace(/[^0-9-]/g, "") || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
38788
|
+
const path6 = `support/inbound/${datePrefix}-${safeEmailId(email.id)}`;
|
|
38789
|
+
const title = `Support email \u2014 ${subject} \u2014 ${sender}`.slice(0, 240);
|
|
38790
|
+
const summary = `Inbound MCP Scraper support email from ${sender} about \u201C${subject}\u201D; awaiting review and response.`.slice(0, 500);
|
|
38791
|
+
const content = [
|
|
38792
|
+
"## Observation",
|
|
38793
|
+
"",
|
|
38794
|
+
`An email was received at ${(email.to ?? []).join(", ") || SUPPORT_ADDRESS} from ${sender}. The customer-provided content below is untrusted input and has not been verified as a product defect.`,
|
|
38795
|
+
"",
|
|
38796
|
+
"## Impact",
|
|
38797
|
+
"",
|
|
38798
|
+
"A customer or prospect may be waiting for a response. The message may describe a question, product problem, billing concern, or feedback that needs triage.",
|
|
38799
|
+
"",
|
|
38800
|
+
"## Confirmation",
|
|
38801
|
+
"",
|
|
38802
|
+
"- Status: awaiting human review",
|
|
38803
|
+
"- Confirmed product defect: no",
|
|
38804
|
+
"- Reproducible: not yet assessed",
|
|
38805
|
+
"",
|
|
38806
|
+
"## Evidence",
|
|
38807
|
+
"",
|
|
38808
|
+
`- From: ${sender}`,
|
|
38809
|
+
`- To: ${(email.to ?? []).join(", ") || SUPPORT_ADDRESS}`,
|
|
38810
|
+
`- Received: ${receivedAt}`,
|
|
38811
|
+
`- Subject: ${subject}`,
|
|
38812
|
+
`- Message ID: ${cleanLine(email.message_id, "not supplied")}`,
|
|
38813
|
+
`- Resend email ID: ${email.id}`,
|
|
38814
|
+
`- Attachments: ${attachments}`,
|
|
38815
|
+
"",
|
|
38816
|
+
"### Message body",
|
|
38817
|
+
"",
|
|
38818
|
+
quoteUntrusted(email.text ?? ""),
|
|
38819
|
+
"",
|
|
38820
|
+
"## Resolution",
|
|
38821
|
+
"",
|
|
38822
|
+
"Pending review and a reply to the sender. If this is a confirmed product issue, update the note status and link the eventual Improvement Log receipt.",
|
|
38823
|
+
"",
|
|
38824
|
+
"## Tasks",
|
|
38825
|
+
"",
|
|
38826
|
+
"- [ ] Review the forwarded email and attachments.",
|
|
38827
|
+
"- [ ] Reply to the sender.",
|
|
38828
|
+
"- [ ] Confirm whether this is a product defect, question, billing concern, or feedback.",
|
|
38829
|
+
"- [ ] Link any resulting task or Improvement Log receipt.",
|
|
38830
|
+
"",
|
|
38831
|
+
"## Links",
|
|
38832
|
+
"",
|
|
38833
|
+
"_No automatic links were added; support messages should be linked during human triage to avoid false relationships._"
|
|
38834
|
+
].join("\n");
|
|
38835
|
+
return { path: path6, title, content, summary };
|
|
38836
|
+
}
|
|
38837
|
+
async function captureSupportIssue(email, memoryKey) {
|
|
38838
|
+
const note = buildSupportIssueNote(email);
|
|
38839
|
+
const tagCandidates = [
|
|
38840
|
+
{ tag: "customer-support", central: true, reusable: true, description: "Inbound and in-product MCP Scraper customer support requests." },
|
|
38841
|
+
{ tag: "inbound-email", central: true, reusable: true, description: "Messages received through an inbound email integration." },
|
|
38842
|
+
{ tag: "product-feedback", central: true, reusable: true, description: "Customer feedback and reported product problems." }
|
|
38843
|
+
];
|
|
38844
|
+
const prepared = await memoryCall("prepareMemoryWriteTool", {
|
|
38845
|
+
title: note.title,
|
|
38846
|
+
content: note.content,
|
|
38847
|
+
source: `resend:email:${email.id}`,
|
|
38848
|
+
type: "user_friction",
|
|
38849
|
+
vault: "Issues",
|
|
38850
|
+
tagCandidates,
|
|
38851
|
+
maxLinks: 4
|
|
38852
|
+
}, memoryKey);
|
|
38853
|
+
if (!prepared.ok) throw new Error(prepared.error ?? "memory preparation failed");
|
|
38854
|
+
const resolvedTags = (prepared.tagResolutions ?? []).filter((item) => item.action !== "omit").map((item) => item.tag ?? item.candidate).filter((tag) => Boolean(tag));
|
|
38855
|
+
const capture = await memoryCall("memoryCaptureTool", {
|
|
38856
|
+
vault: "Issues",
|
|
38857
|
+
path: note.path,
|
|
38858
|
+
title: note.title,
|
|
38859
|
+
content: note.content,
|
|
38860
|
+
props: {
|
|
38861
|
+
status: "ai_observed",
|
|
38862
|
+
summary: note.summary,
|
|
38863
|
+
tags: resolvedTags,
|
|
38864
|
+
pinned: false,
|
|
38865
|
+
source_type: "channel",
|
|
38866
|
+
source_ref: `resend:email:${email.id}`,
|
|
38867
|
+
related: [],
|
|
38868
|
+
related_vault_notes: [],
|
|
38869
|
+
embed: true,
|
|
38870
|
+
embed_priority: "high",
|
|
38871
|
+
embedding_summary: note.summary,
|
|
38872
|
+
type: "user_friction",
|
|
38873
|
+
severity: "untriaged",
|
|
38874
|
+
system: "MCP Scraper customer support",
|
|
38875
|
+
observed_at: email.created_at,
|
|
38876
|
+
detected_by: "resend-email-webhook",
|
|
38877
|
+
reproducible: false
|
|
38878
|
+
},
|
|
38879
|
+
tagDecisions: tagCandidates
|
|
38880
|
+
}, memoryKey);
|
|
38881
|
+
if (capture.ok) return capture.note?.path ?? note.path;
|
|
38882
|
+
if (capture.conflict) {
|
|
38883
|
+
const existing = await memoryCall("getTool", { vault: "Issues", path: note.path }, memoryKey);
|
|
38884
|
+
if (existing.ok) return note.path;
|
|
38885
|
+
}
|
|
38886
|
+
throw new Error(capture.error ?? "memory capture failed");
|
|
38887
|
+
}
|
|
38888
|
+
async function forwardReceivedEmail(resend, email, destination, label) {
|
|
38889
|
+
const attachmentResult = await resend.emails.receiving.attachments.list({ emailId: email.id });
|
|
38890
|
+
if (attachmentResult.error) throw new Error(`attachment retrieval failed: ${attachmentResult.error.message}`);
|
|
38891
|
+
const attachments = (attachmentResult.data?.data ?? []).filter((item) => item.content_disposition !== "inline").map((item) => ({
|
|
38892
|
+
path: item.download_url,
|
|
38893
|
+
filename: item.filename ?? "attachment",
|
|
38894
|
+
contentId: item.content_id
|
|
38895
|
+
}));
|
|
38896
|
+
const sender = email.reply_to?.[0] || email.from;
|
|
38897
|
+
const subject = cleanLine(email.subject, "(no subject)");
|
|
38898
|
+
const headerText = [
|
|
38899
|
+
`${label} message received at ${(email.to ?? []).join(", ")}`,
|
|
38900
|
+
`From: ${email.from}`,
|
|
38901
|
+
`Reply to: ${sender}`,
|
|
38902
|
+
`Received: ${email.created_at}`,
|
|
38903
|
+
""
|
|
38904
|
+
].join("\n");
|
|
38905
|
+
const headerHtml = [
|
|
38906
|
+
'<div style="font-family:Arial,sans-serif;font-size:13px;line-height:1.5;color:#5f5a54;border-bottom:1px solid #e9e4db;padding-bottom:12px;margin-bottom:18px">',
|
|
38907
|
+
`<strong>${label} message received</strong><br>`,
|
|
38908
|
+
`From: ${escapeHtml3(email.from)}<br>`,
|
|
38909
|
+
`Reply to: ${escapeHtml3(sender)}<br>`,
|
|
38910
|
+
`Received: ${escapeHtml3(email.created_at)}`,
|
|
38911
|
+
"</div>"
|
|
38912
|
+
].join("");
|
|
38913
|
+
const sent = await resend.emails.send({
|
|
38914
|
+
from: FORWARD_FROM,
|
|
38915
|
+
to: destination,
|
|
38916
|
+
replyTo: sender,
|
|
38917
|
+
subject: `[${label}] ${subject}`,
|
|
38918
|
+
text: `${headerText}${email.text || "(HTML-only message; view the HTML version.)"}`,
|
|
38919
|
+
html: email.html ? `${headerHtml}${email.html}` : void 0,
|
|
38920
|
+
attachments: attachments.length ? attachments : void 0,
|
|
38921
|
+
tags: [
|
|
38922
|
+
{ name: "category", value: label === "Support" ? "support_forward" : "dmarc_report" },
|
|
38923
|
+
{ name: "inbound_id", value: safeEmailId(email.id) }
|
|
38924
|
+
]
|
|
38925
|
+
}, { idempotencyKey: `mcp-inbound-${label.toLowerCase()}-${safeEmailId(email.id)}` });
|
|
38926
|
+
if (sent.error) throw new Error(`forward failed: ${sent.error.message}`);
|
|
38927
|
+
return sent.data.id;
|
|
38928
|
+
}
|
|
38929
|
+
var import_hono22, import_resend, SUPPORT_ADDRESS, DMARC_ADDRESS, FORWARD_FROM, resendInboundApp;
|
|
38930
|
+
var init_resend_inbound_routes = __esm({
|
|
38931
|
+
"src/api/resend-inbound-routes.ts"() {
|
|
38932
|
+
"use strict";
|
|
38933
|
+
import_hono22 = require("hono");
|
|
38934
|
+
import_resend = require("resend");
|
|
38935
|
+
init_memory();
|
|
38936
|
+
SUPPORT_ADDRESS = "support@mcpscraper.dev";
|
|
38937
|
+
DMARC_ADDRESS = "dmarc@mcpscraper.dev";
|
|
38938
|
+
FORWARD_FROM = "MCP Scraper Support <support@updates.mcpscraper.dev>";
|
|
38939
|
+
resendInboundApp = new import_hono22.Hono();
|
|
38940
|
+
resendInboundApp.post("/webhooks", async (c) => {
|
|
38941
|
+
const apiKey = process.env.RESEND_API_KEY?.trim();
|
|
38942
|
+
const webhookSecret = process.env.RESEND_WEBHOOK_SECRET?.trim();
|
|
38943
|
+
if (!apiKey || !webhookSecret) return c.json({ error: "inbound email is not configured" }, 503);
|
|
38944
|
+
const rawBody = await c.req.text();
|
|
38945
|
+
const resend = new import_resend.Resend(apiKey);
|
|
38946
|
+
let event;
|
|
38947
|
+
try {
|
|
38948
|
+
event = resend.webhooks.verify({
|
|
38949
|
+
payload: rawBody,
|
|
38950
|
+
headers: {
|
|
38951
|
+
id: c.req.header("svix-id") ?? "",
|
|
38952
|
+
timestamp: c.req.header("svix-timestamp") ?? "",
|
|
38953
|
+
signature: c.req.header("svix-signature") ?? ""
|
|
38954
|
+
},
|
|
38955
|
+
webhookSecret
|
|
38956
|
+
});
|
|
38957
|
+
} catch {
|
|
38958
|
+
return c.json({ error: "invalid webhook signature" }, 400);
|
|
38959
|
+
}
|
|
38960
|
+
if (event.type !== "email.received") return c.json({ ok: true, ignored: true });
|
|
38961
|
+
const receivedEvent = event;
|
|
38962
|
+
const route = classifyInboundRecipients(
|
|
38963
|
+
receivedEvent.data.to ?? [],
|
|
38964
|
+
process.env.RESEND_RECEIVING_DOMAIN,
|
|
38965
|
+
process.env.RESEND_MANAGED_RECEIVING_DOMAIN
|
|
38966
|
+
);
|
|
38967
|
+
if (route === "ignore") return c.json({ ok: true, ignored: true });
|
|
38968
|
+
const received = await resend.emails.receiving.get(receivedEvent.data.email_id);
|
|
38969
|
+
if (received.error || !received.data) {
|
|
38970
|
+
console.error("[resend/inbound] could not retrieve received email", receivedEvent.data.email_id);
|
|
38971
|
+
return c.json({ error: "received email could not be retrieved" }, 502);
|
|
38972
|
+
}
|
|
38973
|
+
try {
|
|
38974
|
+
if (route === "support") {
|
|
38975
|
+
const destination2 = process.env.SUPPORT_FORWARD_TO?.trim();
|
|
38976
|
+
const memoryKey = process.env.SUPPORT_INBOX_MEMORY_KEY?.trim();
|
|
38977
|
+
if (!destination2 || !memoryKey) return c.json({ error: "support routing is not configured" }, 503);
|
|
38978
|
+
const [forwardedId2, memoryPath] = await Promise.all([
|
|
38979
|
+
forwardReceivedEmail(resend, received.data, destination2, "Support"),
|
|
38980
|
+
captureSupportIssue(received.data, memoryKey)
|
|
38981
|
+
]);
|
|
38982
|
+
return c.json({ ok: true, route, forwardedId: forwardedId2, memoryPath });
|
|
38983
|
+
}
|
|
38984
|
+
const destination = process.env.DMARC_FORWARD_TO?.trim() || process.env.SUPPORT_FORWARD_TO?.trim();
|
|
38985
|
+
if (!destination) return c.json({ error: "DMARC routing is not configured" }, 503);
|
|
38986
|
+
const forwardedId = await forwardReceivedEmail(resend, received.data, destination, "DMARC");
|
|
38987
|
+
return c.json({ ok: true, route, forwardedId });
|
|
38988
|
+
} catch (err) {
|
|
38989
|
+
console.error("[resend/inbound] processing failed", receivedEvent.data.email_id, err instanceof Error ? err.message : String(err));
|
|
38990
|
+
return c.json({ error: "inbound email processing failed" }, 502);
|
|
38991
|
+
}
|
|
38992
|
+
});
|
|
38993
|
+
}
|
|
38994
|
+
});
|
|
38995
|
+
|
|
38757
38996
|
// src/api/site-audit-worker.ts
|
|
38758
38997
|
async function drainSiteAuditQueue(budget) {
|
|
38759
38998
|
const processedIds = [];
|
|
@@ -39953,6 +40192,9 @@ async function getNangoCatalog() {
|
|
|
39953
40192
|
const safeDefaultAllowedTools = cleanTools(
|
|
39954
40193
|
row.safeDefaultAllowedTools ?? row.safe_default_allowed_tools ?? row.defaultAllowedTools ?? row.default_allowed_tools ?? row.allowedTools ?? row.allowed_tools
|
|
39955
40194
|
).filter((tool) => !disabledTools?.has(tool));
|
|
40195
|
+
const actionTools = cleanTools(
|
|
40196
|
+
row.actionTools ?? row.action_tools ?? row.writeTools ?? row.write_tools
|
|
40197
|
+
).filter((tool) => !disabledTools?.has(tool));
|
|
39956
40198
|
const platformSetupStatus = firstString(row, [
|
|
39957
40199
|
"platformSetupStatus",
|
|
39958
40200
|
"platform_setup_status",
|
|
@@ -39972,6 +40214,7 @@ async function getNangoCatalog() {
|
|
|
39972
40214
|
authMode,
|
|
39973
40215
|
categories,
|
|
39974
40216
|
safeDefaultAllowedTools,
|
|
40217
|
+
actionTools,
|
|
39975
40218
|
connectionSyncSupported: connectionSyncRequiredTools.length > 0,
|
|
39976
40219
|
connectionSyncRequiredTools,
|
|
39977
40220
|
platformSetupStatus,
|
|
@@ -40359,6 +40602,17 @@ var init_nango_control = __esm({
|
|
|
40359
40602
|
"get-broadcast",
|
|
40360
40603
|
"list-templates",
|
|
40361
40604
|
"get-template"
|
|
40605
|
+
],
|
|
40606
|
+
"meta-marketing-api": [
|
|
40607
|
+
"list-ad-accounts",
|
|
40608
|
+
"list-campaigns",
|
|
40609
|
+
"list-ad-sets",
|
|
40610
|
+
"list-ads",
|
|
40611
|
+
"list-ad-creatives",
|
|
40612
|
+
"get-insights",
|
|
40613
|
+
"list-catalogs",
|
|
40614
|
+
"list-datasets",
|
|
40615
|
+
"list-custom-audiences"
|
|
40362
40616
|
]
|
|
40363
40617
|
};
|
|
40364
40618
|
NangoControlError = class extends Error {
|
|
@@ -41065,7 +41319,7 @@ async function checkHarvestLimits(user, reuseLockId) {
|
|
|
41065
41319
|
}
|
|
41066
41320
|
return null;
|
|
41067
41321
|
}
|
|
41068
|
-
var
|
|
41322
|
+
var import_resend2, import_hono23, import_hono24, import_factory6, import_cookie2, import_stripe2, secureCookies2, isProduction2, sessionCookieOptions2, requireAllowedOrigin, auth2, adminAuth, sessionAuth, requireIntegrationsTier, app, STRIPE_API_VERSION, SYNC_HARVEST_TIMEOUT_OVERRIDE_MS;
|
|
41069
41323
|
var init_server = __esm({
|
|
41070
41324
|
"src/api/server.ts"() {
|
|
41071
41325
|
"use strict";
|
|
@@ -41076,15 +41330,15 @@ var init_server = __esm({
|
|
|
41076
41330
|
init_template();
|
|
41077
41331
|
init_attribution_pixel();
|
|
41078
41332
|
init_og();
|
|
41079
|
-
|
|
41333
|
+
import_resend2 = require("resend");
|
|
41080
41334
|
init_url_utils();
|
|
41081
41335
|
init_kpo_extractor();
|
|
41082
41336
|
init_screenshot();
|
|
41083
41337
|
init_media_extractor();
|
|
41084
41338
|
init_site_mapper();
|
|
41085
41339
|
init_site_extractor();
|
|
41086
|
-
|
|
41087
|
-
|
|
41340
|
+
import_hono23 = require("hono");
|
|
41341
|
+
import_hono24 = require("inngest/hono");
|
|
41088
41342
|
init_client();
|
|
41089
41343
|
init_site_audit();
|
|
41090
41344
|
init_site_extract();
|
|
@@ -41115,6 +41369,7 @@ var init_server = __esm({
|
|
|
41115
41369
|
init_oauth_routes();
|
|
41116
41370
|
init_chat_routes();
|
|
41117
41371
|
init_schedule_routes();
|
|
41372
|
+
init_resend_inbound_routes();
|
|
41118
41373
|
init_site_audit_worker();
|
|
41119
41374
|
import_factory6 = require("hono/factory");
|
|
41120
41375
|
import_cookie2 = require("hono/cookie");
|
|
@@ -41183,7 +41438,18 @@ var init_server = __esm({
|
|
|
41183
41438
|
c.set("sessionUser", { ...refreshed, balance_mc: balanceMc });
|
|
41184
41439
|
return next();
|
|
41185
41440
|
});
|
|
41186
|
-
|
|
41441
|
+
requireIntegrationsTier = (0, import_factory6.createMiddleware)(async (c, next) => {
|
|
41442
|
+
const user = c.get("user");
|
|
41443
|
+
if (!user.subscription_tier) {
|
|
41444
|
+
return c.json({
|
|
41445
|
+
ok: false,
|
|
41446
|
+
error: "Integrations require an active Starter plan or higher.",
|
|
41447
|
+
code: "subscription_required"
|
|
41448
|
+
}, 403);
|
|
41449
|
+
}
|
|
41450
|
+
return next();
|
|
41451
|
+
});
|
|
41452
|
+
app = new import_hono23.Hono();
|
|
41187
41453
|
STRIPE_API_VERSION = "2026-02-25.clover";
|
|
41188
41454
|
app.use("*", async (c, next) => {
|
|
41189
41455
|
await next();
|
|
@@ -41301,7 +41567,7 @@ var init_server = __esm({
|
|
|
41301
41567
|
const resetUrl = `${appUrl}/reset-password?token=${token}`;
|
|
41302
41568
|
if (process.env.RESEND_API_KEY) {
|
|
41303
41569
|
try {
|
|
41304
|
-
const resend = new
|
|
41570
|
+
const resend = new import_resend2.Resend(process.env.RESEND_API_KEY);
|
|
41305
41571
|
const sent = await resend.emails.send({
|
|
41306
41572
|
from: "MCP Scraper <noreply@updates.mcpscraper.dev>",
|
|
41307
41573
|
to: normalizedEmail,
|
|
@@ -41357,9 +41623,11 @@ var init_server = __esm({
|
|
|
41357
41623
|
return c.json({ authenticated: false });
|
|
41358
41624
|
}
|
|
41359
41625
|
const refreshed = await applyMonthlyFreeRefresh(foundUser);
|
|
41360
|
-
const balanceMc = await
|
|
41626
|
+
const [balanceMc, stats] = await Promise.all([
|
|
41627
|
+
reconcileBalanceMc(refreshed.id),
|
|
41628
|
+
getUserStats(refreshed.id)
|
|
41629
|
+
]);
|
|
41361
41630
|
const user = { ...refreshed, balance_mc: balanceMc };
|
|
41362
|
-
const stats = await getUserStats(user.id);
|
|
41363
41631
|
return c.json({
|
|
41364
41632
|
authenticated: true,
|
|
41365
41633
|
id: user.id,
|
|
@@ -41685,7 +41953,7 @@ var init_server = __esm({
|
|
|
41685
41953
|
return scheduleConnectionError(c, err, "Unable to load service connections.");
|
|
41686
41954
|
}
|
|
41687
41955
|
});
|
|
41688
|
-
app.post("/schedule-connections/session", auth2, async (c) => {
|
|
41956
|
+
app.post("/schedule-connections/session", auth2, requireIntegrationsTier, async (c) => {
|
|
41689
41957
|
const user = c.get("user");
|
|
41690
41958
|
const body = await c.req.json().catch(() => ({}));
|
|
41691
41959
|
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
@@ -41697,7 +41965,7 @@ var init_server = __esm({
|
|
|
41697
41965
|
return scheduleConnectionError(c, err, "Unable to start the service connection flow.");
|
|
41698
41966
|
}
|
|
41699
41967
|
});
|
|
41700
|
-
app.post("/schedule-connections/:id/reconnect-session", auth2, async (c) => {
|
|
41968
|
+
app.post("/schedule-connections/:id/reconnect-session", auth2, requireIntegrationsTier, async (c) => {
|
|
41701
41969
|
const user = c.get("user");
|
|
41702
41970
|
const body = await c.req.json().catch(() => ({}));
|
|
41703
41971
|
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
@@ -41722,7 +41990,7 @@ var init_server = __esm({
|
|
|
41722
41990
|
return scheduleConnectionError(c, err, "Unable to disconnect this service connection.");
|
|
41723
41991
|
}
|
|
41724
41992
|
});
|
|
41725
|
-
app.post("/schedule-connections/:id/enable-actions", auth2, async (c) => {
|
|
41993
|
+
app.post("/schedule-connections/:id/enable-actions", auth2, requireIntegrationsTier, async (c) => {
|
|
41726
41994
|
const user = c.get("user");
|
|
41727
41995
|
const body = await c.req.json().catch(() => ({}));
|
|
41728
41996
|
if (typeof body.enabled !== "boolean") return c.json({ ok: false, error: "enabled must be a boolean." }, 400);
|
|
@@ -41758,7 +42026,7 @@ var init_server = __esm({
|
|
|
41758
42026
|
return c.html(renderResendOAuthResult(false), 502);
|
|
41759
42027
|
}
|
|
41760
42028
|
});
|
|
41761
|
-
app.post("/schedule-connections/actions/slack/send-message", auth2, async (c) => {
|
|
42029
|
+
app.post("/schedule-connections/actions/slack/send-message", auth2, requireIntegrationsTier, async (c) => {
|
|
41762
42030
|
const user = c.get("user");
|
|
41763
42031
|
const body = await c.req.json().catch(() => ({}));
|
|
41764
42032
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -41772,7 +42040,7 @@ var init_server = __esm({
|
|
|
41772
42040
|
return scheduleConnectionError(c, err, "Unable to send the Slack message.");
|
|
41773
42041
|
}
|
|
41774
42042
|
});
|
|
41775
|
-
app.post("/schedule-connections/actions/gmail/send-message", auth2, async (c) => {
|
|
42043
|
+
app.post("/schedule-connections/actions/gmail/send-message", auth2, requireIntegrationsTier, async (c) => {
|
|
41776
42044
|
const user = c.get("user");
|
|
41777
42045
|
const body = await c.req.json().catch(() => ({}));
|
|
41778
42046
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -41786,7 +42054,7 @@ var init_server = __esm({
|
|
|
41786
42054
|
return scheduleConnectionError(c, err, "Unable to send the email.");
|
|
41787
42055
|
}
|
|
41788
42056
|
});
|
|
41789
|
-
app.post("/schedule-connections/actions/google-calendar/create-event", auth2, async (c) => {
|
|
42057
|
+
app.post("/schedule-connections/actions/google-calendar/create-event", auth2, requireIntegrationsTier, async (c) => {
|
|
41790
42058
|
const user = c.get("user");
|
|
41791
42059
|
const body = await c.req.json().catch(() => ({}));
|
|
41792
42060
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -41808,7 +42076,7 @@ var init_server = __esm({
|
|
|
41808
42076
|
return scheduleConnectionError(c, err, "Unable to create the calendar event.");
|
|
41809
42077
|
}
|
|
41810
42078
|
});
|
|
41811
|
-
app.post("/schedule-connections/actions/zoom/create-meeting", auth2, async (c) => {
|
|
42079
|
+
app.post("/schedule-connections/actions/zoom/create-meeting", auth2, requireIntegrationsTier, async (c) => {
|
|
41812
42080
|
const user = c.get("user");
|
|
41813
42081
|
const body = await c.req.json().catch(() => ({}));
|
|
41814
42082
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -41828,7 +42096,7 @@ var init_server = __esm({
|
|
|
41828
42096
|
return scheduleConnectionError(c, err, "Unable to create the Zoom meeting.");
|
|
41829
42097
|
}
|
|
41830
42098
|
});
|
|
41831
|
-
app.post("/schedule-connections/actions/read", auth2, async (c) => {
|
|
42099
|
+
app.post("/schedule-connections/actions/read", auth2, requireIntegrationsTier, async (c) => {
|
|
41832
42100
|
const user = c.get("user");
|
|
41833
42101
|
const body = await c.req.json().catch(() => ({}));
|
|
41834
42102
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -41845,7 +42113,7 @@ var init_server = __esm({
|
|
|
41845
42113
|
return scheduleConnectionError(c, err, "Unable to read from this connection.");
|
|
41846
42114
|
}
|
|
41847
42115
|
});
|
|
41848
|
-
app.post("/schedule-connections/actions/import-memory", auth2, async (c) => {
|
|
42116
|
+
app.post("/schedule-connections/actions/import-memory", auth2, requireIntegrationsTier, async (c) => {
|
|
41849
42117
|
const user = c.get("user");
|
|
41850
42118
|
const body = await c.req.json().catch(() => ({}));
|
|
41851
42119
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -41902,7 +42170,7 @@ var init_server = __esm({
|
|
|
41902
42170
|
return scheduleConnectionError(c, err, "Unable to import this connected-service snapshot into Memory.");
|
|
41903
42171
|
}
|
|
41904
42172
|
});
|
|
41905
|
-
app.post("/schedule-connections/actions/describe", auth2, async (c) => {
|
|
42173
|
+
app.post("/schedule-connections/actions/describe", auth2, requireIntegrationsTier, async (c) => {
|
|
41906
42174
|
const user = c.get("user");
|
|
41907
42175
|
const body = await c.req.json().catch(() => ({}));
|
|
41908
42176
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -41919,7 +42187,7 @@ var init_server = __esm({
|
|
|
41919
42187
|
return scheduleConnectionError(c, err, "Unable to describe this connection tool.");
|
|
41920
42188
|
}
|
|
41921
42189
|
});
|
|
41922
|
-
app.post("/schedule-connections/actions/export", auth2, async (c) => {
|
|
42190
|
+
app.post("/schedule-connections/actions/export", auth2, requireIntegrationsTier, async (c) => {
|
|
41923
42191
|
const user = c.get("user");
|
|
41924
42192
|
const body = await c.req.json().catch(() => ({}));
|
|
41925
42193
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -41979,7 +42247,7 @@ var init_server = __esm({
|
|
|
41979
42247
|
return scheduleConnectionError(c, err, "Unable to export this connected service.");
|
|
41980
42248
|
}
|
|
41981
42249
|
});
|
|
41982
|
-
app.post("/schedule-connections/actions/export-download", auth2, async (c) => {
|
|
42250
|
+
app.post("/schedule-connections/actions/export-download", auth2, requireIntegrationsTier, async (c) => {
|
|
41983
42251
|
const user = c.get("user");
|
|
41984
42252
|
const body = await c.req.json().catch(() => ({}));
|
|
41985
42253
|
const artifactId = typeof body.artifactId === "string" ? body.artifactId.trim() : "";
|
|
@@ -41996,7 +42264,7 @@ var init_server = __esm({
|
|
|
41996
42264
|
return c.json({ ok: false, error: "Unable to renew this artifact download." }, 502);
|
|
41997
42265
|
}
|
|
41998
42266
|
});
|
|
41999
|
-
app.post("/schedule-connections/actions/call", auth2, async (c) => {
|
|
42267
|
+
app.post("/schedule-connections/actions/call", auth2, requireIntegrationsTier, async (c) => {
|
|
42000
42268
|
const user = c.get("user");
|
|
42001
42269
|
const body = await c.req.json().catch(() => ({}));
|
|
42002
42270
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -42116,7 +42384,7 @@ var init_server = __esm({
|
|
|
42116
42384
|
return scheduleConnectionError(c, err, "Unable to load scheduled action service connections.");
|
|
42117
42385
|
}
|
|
42118
42386
|
});
|
|
42119
|
-
app.put("/schedule-actions/:id/connections", auth2, async (c) => {
|
|
42387
|
+
app.put("/schedule-actions/:id/connections", auth2, requireIntegrationsTier, async (c) => {
|
|
42120
42388
|
const user = c.get("user");
|
|
42121
42389
|
const body = await c.req.json().catch(() => ({}));
|
|
42122
42390
|
let connections;
|
|
@@ -42362,8 +42630,7 @@ var init_server = __esm({
|
|
|
42362
42630
|
location: job.options?.location ?? "",
|
|
42363
42631
|
source: LedgerOperation.SERP,
|
|
42364
42632
|
status: job.status,
|
|
42365
|
-
result_count: job.result ? (job.result.flat?.length ?? 0) + (job.result.organicResults?.length ?? 0) : 0
|
|
42366
|
-
result: job.result ?? null
|
|
42633
|
+
result_count: job.result ? (job.result.flat?.length ?? 0) + (job.result.organicResults?.length ?? 0) : 0
|
|
42367
42634
|
}));
|
|
42368
42635
|
const eventRows = events.map((event) => ({
|
|
42369
42636
|
id: event.id,
|
|
@@ -42373,7 +42640,6 @@ var init_server = __esm({
|
|
|
42373
42640
|
source: event.source,
|
|
42374
42641
|
status: event.status,
|
|
42375
42642
|
result_count: event.result_count ?? 0,
|
|
42376
|
-
result: event.result ?? null,
|
|
42377
42643
|
error: event.error ?? null
|
|
42378
42644
|
}));
|
|
42379
42645
|
const rows = [...jobRows, ...eventRows].sort((a, b) => String(b.ts).localeCompare(String(a.ts)));
|
|
@@ -43045,7 +43311,7 @@ var init_server = __esm({
|
|
|
43045
43311
|
const bundle = stored.find((a) => a.key.endsWith("bundle.zip"));
|
|
43046
43312
|
return c.json({ ok: true, jobId, artifacts: stored.length, settlement, bundleUrl: bundle?.url ?? null, bundleBytes: bundle?.bytes ?? null });
|
|
43047
43313
|
});
|
|
43048
|
-
app.on(["GET", "POST", "PUT"], "/api/inngest", (0,
|
|
43314
|
+
app.on(["GET", "POST", "PUT"], "/api/inngest", (0, import_hono24.serve)({ client: inngest, functions: [siteAuditFn, siteExtractFn] }));
|
|
43049
43315
|
app.route("/api/internal/site-architecture-auditor", siteAuditApp);
|
|
43050
43316
|
app.route("/api/internal/memory", internalMemoryApp);
|
|
43051
43317
|
app.route("/youtube", youtubeApp);
|
|
@@ -43065,6 +43331,7 @@ var init_server = __esm({
|
|
|
43065
43331
|
app.route("/agent", buildBrowserAgentRoutes());
|
|
43066
43332
|
app.route("/chat", chatApp);
|
|
43067
43333
|
app.route("/schedule", scheduleApp);
|
|
43334
|
+
app.route("/resend", resendInboundApp);
|
|
43068
43335
|
app.get("/console", (c) => c.html(renderConsoleHtml()));
|
|
43069
43336
|
app.get("/console/auth/:id", async (c) => {
|
|
43070
43337
|
const id = c.req.param("id");
|