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
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
registerMemoryMcpTools,
|
|
8
8
|
registerPaaExtractorMcpTools,
|
|
9
9
|
registerSerpIntelligenceCaptureTools
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-HJ3XIHWC.js";
|
|
11
11
|
import "../chunk-R7EETU7Z.js";
|
|
12
12
|
import "../chunk-HPV4VOQX.js";
|
|
13
13
|
import {
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
import "../chunk-XGIPATLV.js";
|
|
17
17
|
import {
|
|
18
18
|
PACKAGE_VERSION
|
|
19
|
-
} from "../chunk-
|
|
19
|
+
} from "../chunk-IDRSO4HX.js";
|
|
20
20
|
import "../chunk-HL33CGJF.js";
|
|
21
21
|
import "../chunk-M2S27J6Z.js";
|
|
22
22
|
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
} from "./chunk-XGIPATLV.js";
|
|
18
18
|
import {
|
|
19
19
|
PACKAGE_VERSION
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-IDRSO4HX.js";
|
|
21
21
|
import {
|
|
22
22
|
MC_PER_CREDIT
|
|
23
23
|
} from "./chunk-HL33CGJF.js";
|
|
@@ -9315,4 +9315,4 @@ export {
|
|
|
9315
9315
|
registerMemoryMcpTools,
|
|
9316
9316
|
MemoryMcpToolExecutor
|
|
9317
9317
|
};
|
|
9318
|
-
//# sourceMappingURL=chunk-
|
|
9318
|
+
//# sourceMappingURL=chunk-HJ3XIHWC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/version.ts"],"sourcesContent":["export const PACKAGE_VERSION = '0.17.2'\n"],"mappings":";AAAO,IAAM,kBAAkB;","names":[]}
|
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
renewConnectedDataArtifactDownload,
|
|
38
38
|
sanitizeAttempts,
|
|
39
39
|
sanitizeHarvestResult
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-HJ3XIHWC.js";
|
|
41
41
|
import {
|
|
42
42
|
auditImages,
|
|
43
43
|
buildLinkReport,
|
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
RawMapsOverviewSchema,
|
|
74
74
|
RawMapsReviewStatsSchema
|
|
75
75
|
} from "./chunk-XGIPATLV.js";
|
|
76
|
-
import "./chunk-
|
|
76
|
+
import "./chunk-IDRSO4HX.js";
|
|
77
77
|
import {
|
|
78
78
|
completeExtractJob,
|
|
79
79
|
countSuccessfulPages,
|
|
@@ -3506,7 +3506,7 @@ async function generateOgImage(post) {
|
|
|
3506
3506
|
}
|
|
3507
3507
|
|
|
3508
3508
|
// src/api/server.ts
|
|
3509
|
-
import { Resend } from "resend";
|
|
3509
|
+
import { Resend as Resend2 } from "resend";
|
|
3510
3510
|
|
|
3511
3511
|
// src/api/url-utils.ts
|
|
3512
3512
|
import { isIP } from "net";
|
|
@@ -5321,7 +5321,7 @@ async function extractSite(opts) {
|
|
|
5321
5321
|
}
|
|
5322
5322
|
|
|
5323
5323
|
// src/api/server.ts
|
|
5324
|
-
import { Hono as
|
|
5324
|
+
import { Hono as Hono23 } from "hono";
|
|
5325
5325
|
import { serve as serveInngest } from "inngest/hono";
|
|
5326
5326
|
|
|
5327
5327
|
// src/inngest/client.ts
|
|
@@ -19976,6 +19976,238 @@ loadActions();
|
|
|
19976
19976
|
</html>`;
|
|
19977
19977
|
}
|
|
19978
19978
|
|
|
19979
|
+
// src/api/resend-inbound-routes.ts
|
|
19980
|
+
import { Hono as Hono22 } from "hono";
|
|
19981
|
+
import { Resend } from "resend";
|
|
19982
|
+
var SUPPORT_ADDRESS = "support@mcpscraper.dev";
|
|
19983
|
+
var DMARC_ADDRESS = "dmarc@mcpscraper.dev";
|
|
19984
|
+
var FORWARD_FROM = "MCP Scraper Support <support@updates.mcpscraper.dev>";
|
|
19985
|
+
function classifyInboundRecipients(recipients, ...receivingDomains) {
|
|
19986
|
+
const normalized = recipients.map((address) => address.trim().toLowerCase());
|
|
19987
|
+
const domains = receivingDomains.map((domain) => domain?.trim().toLowerCase()).filter((domain) => Boolean(domain));
|
|
19988
|
+
const supportAddresses = [SUPPORT_ADDRESS, ...domains.map((domain) => `support@${domain}`)];
|
|
19989
|
+
const dmarcAddresses = [DMARC_ADDRESS, ...domains.map((domain) => `dmarc@${domain}`)];
|
|
19990
|
+
if (supportAddresses.some((address) => normalized.includes(address))) return "support";
|
|
19991
|
+
if (dmarcAddresses.some((address) => normalized.includes(address))) return "dmarc";
|
|
19992
|
+
return "ignore";
|
|
19993
|
+
}
|
|
19994
|
+
function cleanLine(value, fallback) {
|
|
19995
|
+
const clean2 = value.replace(/[\r\n\t]+/g, " ").replace(/\s+/g, " ").trim();
|
|
19996
|
+
return (clean2 || fallback).slice(0, 240);
|
|
19997
|
+
}
|
|
19998
|
+
function quoteUntrusted(value) {
|
|
19999
|
+
const clean2 = value.replace(/\0/g, "").trim().slice(0, 16e3);
|
|
20000
|
+
if (!clean2) return "> _(No plain-text body was available. Review the forwarded email.)_";
|
|
20001
|
+
return clean2.split("\n").map((line) => `> ${line}`).join("\n");
|
|
20002
|
+
}
|
|
20003
|
+
function escapeHtml2(value) {
|
|
20004
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
20005
|
+
}
|
|
20006
|
+
function safeEmailId(value) {
|
|
20007
|
+
return value.replace(/[^a-zA-Z0-9_-]/g, "").slice(0, 100) || "unknown-email";
|
|
20008
|
+
}
|
|
20009
|
+
function buildSupportIssueNote(email) {
|
|
20010
|
+
const sender = cleanLine(email.from, "unknown sender");
|
|
20011
|
+
const subject = cleanLine(email.subject, "(no subject)");
|
|
20012
|
+
const receivedAt = cleanLine(email.created_at, (/* @__PURE__ */ new Date()).toISOString());
|
|
20013
|
+
const attachments = email.attachments?.length ? email.attachments.map((item) => cleanLine(item.filename ?? "unnamed attachment", "unnamed attachment")).join(", ") : "None";
|
|
20014
|
+
const datePrefix = receivedAt.slice(0, 10).replace(/[^0-9-]/g, "") || (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
20015
|
+
const path5 = `support/inbound/${datePrefix}-${safeEmailId(email.id)}`;
|
|
20016
|
+
const title = `Support email \u2014 ${subject} \u2014 ${sender}`.slice(0, 240);
|
|
20017
|
+
const summary = `Inbound MCP Scraper support email from ${sender} about \u201C${subject}\u201D; awaiting review and response.`.slice(0, 500);
|
|
20018
|
+
const content = [
|
|
20019
|
+
"## Observation",
|
|
20020
|
+
"",
|
|
20021
|
+
`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.`,
|
|
20022
|
+
"",
|
|
20023
|
+
"## Impact",
|
|
20024
|
+
"",
|
|
20025
|
+
"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.",
|
|
20026
|
+
"",
|
|
20027
|
+
"## Confirmation",
|
|
20028
|
+
"",
|
|
20029
|
+
"- Status: awaiting human review",
|
|
20030
|
+
"- Confirmed product defect: no",
|
|
20031
|
+
"- Reproducible: not yet assessed",
|
|
20032
|
+
"",
|
|
20033
|
+
"## Evidence",
|
|
20034
|
+
"",
|
|
20035
|
+
`- From: ${sender}`,
|
|
20036
|
+
`- To: ${(email.to ?? []).join(", ") || SUPPORT_ADDRESS}`,
|
|
20037
|
+
`- Received: ${receivedAt}`,
|
|
20038
|
+
`- Subject: ${subject}`,
|
|
20039
|
+
`- Message ID: ${cleanLine(email.message_id, "not supplied")}`,
|
|
20040
|
+
`- Resend email ID: ${email.id}`,
|
|
20041
|
+
`- Attachments: ${attachments}`,
|
|
20042
|
+
"",
|
|
20043
|
+
"### Message body",
|
|
20044
|
+
"",
|
|
20045
|
+
quoteUntrusted(email.text ?? ""),
|
|
20046
|
+
"",
|
|
20047
|
+
"## Resolution",
|
|
20048
|
+
"",
|
|
20049
|
+
"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.",
|
|
20050
|
+
"",
|
|
20051
|
+
"## Tasks",
|
|
20052
|
+
"",
|
|
20053
|
+
"- [ ] Review the forwarded email and attachments.",
|
|
20054
|
+
"- [ ] Reply to the sender.",
|
|
20055
|
+
"- [ ] Confirm whether this is a product defect, question, billing concern, or feedback.",
|
|
20056
|
+
"- [ ] Link any resulting task or Improvement Log receipt.",
|
|
20057
|
+
"",
|
|
20058
|
+
"## Links",
|
|
20059
|
+
"",
|
|
20060
|
+
"_No automatic links were added; support messages should be linked during human triage to avoid false relationships._"
|
|
20061
|
+
].join("\n");
|
|
20062
|
+
return { path: path5, title, content, summary };
|
|
20063
|
+
}
|
|
20064
|
+
async function captureSupportIssue(email, memoryKey) {
|
|
20065
|
+
const note = buildSupportIssueNote(email);
|
|
20066
|
+
const tagCandidates = [
|
|
20067
|
+
{ tag: "customer-support", central: true, reusable: true, description: "Inbound and in-product MCP Scraper customer support requests." },
|
|
20068
|
+
{ tag: "inbound-email", central: true, reusable: true, description: "Messages received through an inbound email integration." },
|
|
20069
|
+
{ tag: "product-feedback", central: true, reusable: true, description: "Customer feedback and reported product problems." }
|
|
20070
|
+
];
|
|
20071
|
+
const prepared = await memoryCall("prepareMemoryWriteTool", {
|
|
20072
|
+
title: note.title,
|
|
20073
|
+
content: note.content,
|
|
20074
|
+
source: `resend:email:${email.id}`,
|
|
20075
|
+
type: "user_friction",
|
|
20076
|
+
vault: "Issues",
|
|
20077
|
+
tagCandidates,
|
|
20078
|
+
maxLinks: 4
|
|
20079
|
+
}, memoryKey);
|
|
20080
|
+
if (!prepared.ok) throw new Error(prepared.error ?? "memory preparation failed");
|
|
20081
|
+
const resolvedTags = (prepared.tagResolutions ?? []).filter((item) => item.action !== "omit").map((item) => item.tag ?? item.candidate).filter((tag) => Boolean(tag));
|
|
20082
|
+
const capture = await memoryCall("memoryCaptureTool", {
|
|
20083
|
+
vault: "Issues",
|
|
20084
|
+
path: note.path,
|
|
20085
|
+
title: note.title,
|
|
20086
|
+
content: note.content,
|
|
20087
|
+
props: {
|
|
20088
|
+
status: "ai_observed",
|
|
20089
|
+
summary: note.summary,
|
|
20090
|
+
tags: resolvedTags,
|
|
20091
|
+
pinned: false,
|
|
20092
|
+
source_type: "channel",
|
|
20093
|
+
source_ref: `resend:email:${email.id}`,
|
|
20094
|
+
related: [],
|
|
20095
|
+
related_vault_notes: [],
|
|
20096
|
+
embed: true,
|
|
20097
|
+
embed_priority: "high",
|
|
20098
|
+
embedding_summary: note.summary,
|
|
20099
|
+
type: "user_friction",
|
|
20100
|
+
severity: "untriaged",
|
|
20101
|
+
system: "MCP Scraper customer support",
|
|
20102
|
+
observed_at: email.created_at,
|
|
20103
|
+
detected_by: "resend-email-webhook",
|
|
20104
|
+
reproducible: false
|
|
20105
|
+
},
|
|
20106
|
+
tagDecisions: tagCandidates
|
|
20107
|
+
}, memoryKey);
|
|
20108
|
+
if (capture.ok) return capture.note?.path ?? note.path;
|
|
20109
|
+
if (capture.conflict) {
|
|
20110
|
+
const existing = await memoryCall("getTool", { vault: "Issues", path: note.path }, memoryKey);
|
|
20111
|
+
if (existing.ok) return note.path;
|
|
20112
|
+
}
|
|
20113
|
+
throw new Error(capture.error ?? "memory capture failed");
|
|
20114
|
+
}
|
|
20115
|
+
async function forwardReceivedEmail(resend, email, destination, label) {
|
|
20116
|
+
const attachmentResult = await resend.emails.receiving.attachments.list({ emailId: email.id });
|
|
20117
|
+
if (attachmentResult.error) throw new Error(`attachment retrieval failed: ${attachmentResult.error.message}`);
|
|
20118
|
+
const attachments = (attachmentResult.data?.data ?? []).filter((item) => item.content_disposition !== "inline").map((item) => ({
|
|
20119
|
+
path: item.download_url,
|
|
20120
|
+
filename: item.filename ?? "attachment",
|
|
20121
|
+
contentId: item.content_id
|
|
20122
|
+
}));
|
|
20123
|
+
const sender = email.reply_to?.[0] || email.from;
|
|
20124
|
+
const subject = cleanLine(email.subject, "(no subject)");
|
|
20125
|
+
const headerText = [
|
|
20126
|
+
`${label} message received at ${(email.to ?? []).join(", ")}`,
|
|
20127
|
+
`From: ${email.from}`,
|
|
20128
|
+
`Reply to: ${sender}`,
|
|
20129
|
+
`Received: ${email.created_at}`,
|
|
20130
|
+
""
|
|
20131
|
+
].join("\n");
|
|
20132
|
+
const headerHtml = [
|
|
20133
|
+
'<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">',
|
|
20134
|
+
`<strong>${label} message received</strong><br>`,
|
|
20135
|
+
`From: ${escapeHtml2(email.from)}<br>`,
|
|
20136
|
+
`Reply to: ${escapeHtml2(sender)}<br>`,
|
|
20137
|
+
`Received: ${escapeHtml2(email.created_at)}`,
|
|
20138
|
+
"</div>"
|
|
20139
|
+
].join("");
|
|
20140
|
+
const sent = await resend.emails.send({
|
|
20141
|
+
from: FORWARD_FROM,
|
|
20142
|
+
to: destination,
|
|
20143
|
+
replyTo: sender,
|
|
20144
|
+
subject: `[${label}] ${subject}`,
|
|
20145
|
+
text: `${headerText}${email.text || "(HTML-only message; view the HTML version.)"}`,
|
|
20146
|
+
html: email.html ? `${headerHtml}${email.html}` : void 0,
|
|
20147
|
+
attachments: attachments.length ? attachments : void 0,
|
|
20148
|
+
tags: [
|
|
20149
|
+
{ name: "category", value: label === "Support" ? "support_forward" : "dmarc_report" },
|
|
20150
|
+
{ name: "inbound_id", value: safeEmailId(email.id) }
|
|
20151
|
+
]
|
|
20152
|
+
}, { idempotencyKey: `mcp-inbound-${label.toLowerCase()}-${safeEmailId(email.id)}` });
|
|
20153
|
+
if (sent.error) throw new Error(`forward failed: ${sent.error.message}`);
|
|
20154
|
+
return sent.data.id;
|
|
20155
|
+
}
|
|
20156
|
+
var resendInboundApp = new Hono22();
|
|
20157
|
+
resendInboundApp.post("/webhooks", async (c) => {
|
|
20158
|
+
const apiKey = process.env.RESEND_API_KEY?.trim();
|
|
20159
|
+
const webhookSecret = process.env.RESEND_WEBHOOK_SECRET?.trim();
|
|
20160
|
+
if (!apiKey || !webhookSecret) return c.json({ error: "inbound email is not configured" }, 503);
|
|
20161
|
+
const rawBody = await c.req.text();
|
|
20162
|
+
const resend = new Resend(apiKey);
|
|
20163
|
+
let event;
|
|
20164
|
+
try {
|
|
20165
|
+
event = resend.webhooks.verify({
|
|
20166
|
+
payload: rawBody,
|
|
20167
|
+
headers: {
|
|
20168
|
+
id: c.req.header("svix-id") ?? "",
|
|
20169
|
+
timestamp: c.req.header("svix-timestamp") ?? "",
|
|
20170
|
+
signature: c.req.header("svix-signature") ?? ""
|
|
20171
|
+
},
|
|
20172
|
+
webhookSecret
|
|
20173
|
+
});
|
|
20174
|
+
} catch {
|
|
20175
|
+
return c.json({ error: "invalid webhook signature" }, 400);
|
|
20176
|
+
}
|
|
20177
|
+
if (event.type !== "email.received") return c.json({ ok: true, ignored: true });
|
|
20178
|
+
const receivedEvent = event;
|
|
20179
|
+
const route = classifyInboundRecipients(
|
|
20180
|
+
receivedEvent.data.to ?? [],
|
|
20181
|
+
process.env.RESEND_RECEIVING_DOMAIN,
|
|
20182
|
+
process.env.RESEND_MANAGED_RECEIVING_DOMAIN
|
|
20183
|
+
);
|
|
20184
|
+
if (route === "ignore") return c.json({ ok: true, ignored: true });
|
|
20185
|
+
const received = await resend.emails.receiving.get(receivedEvent.data.email_id);
|
|
20186
|
+
if (received.error || !received.data) {
|
|
20187
|
+
console.error("[resend/inbound] could not retrieve received email", receivedEvent.data.email_id);
|
|
20188
|
+
return c.json({ error: "received email could not be retrieved" }, 502);
|
|
20189
|
+
}
|
|
20190
|
+
try {
|
|
20191
|
+
if (route === "support") {
|
|
20192
|
+
const destination2 = process.env.SUPPORT_FORWARD_TO?.trim();
|
|
20193
|
+
const memoryKey = process.env.SUPPORT_INBOX_MEMORY_KEY?.trim();
|
|
20194
|
+
if (!destination2 || !memoryKey) return c.json({ error: "support routing is not configured" }, 503);
|
|
20195
|
+
const [forwardedId2, memoryPath] = await Promise.all([
|
|
20196
|
+
forwardReceivedEmail(resend, received.data, destination2, "Support"),
|
|
20197
|
+
captureSupportIssue(received.data, memoryKey)
|
|
20198
|
+
]);
|
|
20199
|
+
return c.json({ ok: true, route, forwardedId: forwardedId2, memoryPath });
|
|
20200
|
+
}
|
|
20201
|
+
const destination = process.env.DMARC_FORWARD_TO?.trim() || process.env.SUPPORT_FORWARD_TO?.trim();
|
|
20202
|
+
if (!destination) return c.json({ error: "DMARC routing is not configured" }, 503);
|
|
20203
|
+
const forwardedId = await forwardReceivedEmail(resend, received.data, destination, "DMARC");
|
|
20204
|
+
return c.json({ ok: true, route, forwardedId });
|
|
20205
|
+
} catch (err) {
|
|
20206
|
+
console.error("[resend/inbound] processing failed", receivedEvent.data.email_id, err instanceof Error ? err.message : String(err));
|
|
20207
|
+
return c.json({ error: "inbound email processing failed" }, 502);
|
|
20208
|
+
}
|
|
20209
|
+
});
|
|
20210
|
+
|
|
19979
20211
|
// src/api/site-audit-worker.ts
|
|
19980
20212
|
var MAX_CONCURRENT_SITE_AUDIT = 1;
|
|
19981
20213
|
async function drainSiteAuditQueue(budget) {
|
|
@@ -20918,6 +21150,17 @@ var CONNECTION_SYNC_REQUIRED_TOOLS = {
|
|
|
20918
21150
|
"get-broadcast",
|
|
20919
21151
|
"list-templates",
|
|
20920
21152
|
"get-template"
|
|
21153
|
+
],
|
|
21154
|
+
"meta-marketing-api": [
|
|
21155
|
+
"list-ad-accounts",
|
|
21156
|
+
"list-campaigns",
|
|
21157
|
+
"list-ad-sets",
|
|
21158
|
+
"list-ads",
|
|
21159
|
+
"list-ad-creatives",
|
|
21160
|
+
"get-insights",
|
|
21161
|
+
"list-catalogs",
|
|
21162
|
+
"list-datasets",
|
|
21163
|
+
"list-custom-audiences"
|
|
20921
21164
|
]
|
|
20922
21165
|
};
|
|
20923
21166
|
function connectionSyncPolicyIssues(selections) {
|
|
@@ -21159,6 +21402,9 @@ async function getNangoCatalog() {
|
|
|
21159
21402
|
const safeDefaultAllowedTools = cleanTools(
|
|
21160
21403
|
row.safeDefaultAllowedTools ?? row.safe_default_allowed_tools ?? row.defaultAllowedTools ?? row.default_allowed_tools ?? row.allowedTools ?? row.allowed_tools
|
|
21161
21404
|
).filter((tool) => !disabledTools?.has(tool));
|
|
21405
|
+
const actionTools = cleanTools(
|
|
21406
|
+
row.actionTools ?? row.action_tools ?? row.writeTools ?? row.write_tools
|
|
21407
|
+
).filter((tool) => !disabledTools?.has(tool));
|
|
21162
21408
|
const platformSetupStatus = firstString(row, [
|
|
21163
21409
|
"platformSetupStatus",
|
|
21164
21410
|
"platform_setup_status",
|
|
@@ -21178,6 +21424,7 @@ async function getNangoCatalog() {
|
|
|
21178
21424
|
authMode,
|
|
21179
21425
|
categories,
|
|
21180
21426
|
safeDefaultAllowedTools,
|
|
21427
|
+
actionTools,
|
|
21181
21428
|
connectionSyncSupported: connectionSyncRequiredTools.length > 0,
|
|
21182
21429
|
connectionSyncRequiredTools,
|
|
21183
21430
|
platformSetupStatus,
|
|
@@ -21912,7 +22159,18 @@ var sessionAuth = createMiddleware3(async (c, next) => {
|
|
|
21912
22159
|
c.set("sessionUser", { ...refreshed, balance_mc: balanceMc });
|
|
21913
22160
|
return next();
|
|
21914
22161
|
});
|
|
21915
|
-
var
|
|
22162
|
+
var requireIntegrationsTier = createMiddleware3(async (c, next) => {
|
|
22163
|
+
const user = c.get("user");
|
|
22164
|
+
if (!user.subscription_tier) {
|
|
22165
|
+
return c.json({
|
|
22166
|
+
ok: false,
|
|
22167
|
+
error: "Integrations require an active Starter plan or higher.",
|
|
22168
|
+
code: "subscription_required"
|
|
22169
|
+
}, 403);
|
|
22170
|
+
}
|
|
22171
|
+
return next();
|
|
22172
|
+
});
|
|
22173
|
+
var app = new Hono23();
|
|
21916
22174
|
var STRIPE_API_VERSION = "2026-02-25.clover";
|
|
21917
22175
|
function requireStripeSecret() {
|
|
21918
22176
|
const secret2 = process.env.STRIPE_SECRET_KEY?.trim();
|
|
@@ -22080,7 +22338,7 @@ app.post("/auth/forgot-password", requireAllowedOrigin, async (c) => {
|
|
|
22080
22338
|
const resetUrl = `${appUrl}/reset-password?token=${token}`;
|
|
22081
22339
|
if (process.env.RESEND_API_KEY) {
|
|
22082
22340
|
try {
|
|
22083
|
-
const resend = new
|
|
22341
|
+
const resend = new Resend2(process.env.RESEND_API_KEY);
|
|
22084
22342
|
const sent = await resend.emails.send({
|
|
22085
22343
|
from: "MCP Scraper <noreply@updates.mcpscraper.dev>",
|
|
22086
22344
|
to: normalizedEmail,
|
|
@@ -22136,9 +22394,11 @@ app.get("/me", async (c) => {
|
|
|
22136
22394
|
return c.json({ authenticated: false });
|
|
22137
22395
|
}
|
|
22138
22396
|
const refreshed = await applyMonthlyFreeRefresh(foundUser);
|
|
22139
|
-
const balanceMc = await
|
|
22397
|
+
const [balanceMc, stats] = await Promise.all([
|
|
22398
|
+
reconcileBalanceMc(refreshed.id),
|
|
22399
|
+
getUserStats(refreshed.id)
|
|
22400
|
+
]);
|
|
22140
22401
|
const user = { ...refreshed, balance_mc: balanceMc };
|
|
22141
|
-
const stats = await getUserStats(user.id);
|
|
22142
22402
|
return c.json({
|
|
22143
22403
|
authenticated: true,
|
|
22144
22404
|
id: user.id,
|
|
@@ -22554,7 +22814,7 @@ app.get("/schedule-connections", auth2, async (c) => {
|
|
|
22554
22814
|
return scheduleConnectionError(c, err, "Unable to load service connections.");
|
|
22555
22815
|
}
|
|
22556
22816
|
});
|
|
22557
|
-
app.post("/schedule-connections/session", auth2, async (c) => {
|
|
22817
|
+
app.post("/schedule-connections/session", auth2, requireIntegrationsTier, async (c) => {
|
|
22558
22818
|
const user = c.get("user");
|
|
22559
22819
|
const body = await c.req.json().catch(() => ({}));
|
|
22560
22820
|
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
@@ -22566,7 +22826,7 @@ app.post("/schedule-connections/session", auth2, async (c) => {
|
|
|
22566
22826
|
return scheduleConnectionError(c, err, "Unable to start the service connection flow.");
|
|
22567
22827
|
}
|
|
22568
22828
|
});
|
|
22569
|
-
app.post("/schedule-connections/:id/reconnect-session", auth2, async (c) => {
|
|
22829
|
+
app.post("/schedule-connections/:id/reconnect-session", auth2, requireIntegrationsTier, async (c) => {
|
|
22570
22830
|
const user = c.get("user");
|
|
22571
22831
|
const body = await c.req.json().catch(() => ({}));
|
|
22572
22832
|
const providerConfigKey = providerConfigKeyFrom(body.providerConfigKey);
|
|
@@ -22591,7 +22851,7 @@ app.delete("/schedule-connections/:id", auth2, async (c) => {
|
|
|
22591
22851
|
return scheduleConnectionError(c, err, "Unable to disconnect this service connection.");
|
|
22592
22852
|
}
|
|
22593
22853
|
});
|
|
22594
|
-
app.post("/schedule-connections/:id/enable-actions", auth2, async (c) => {
|
|
22854
|
+
app.post("/schedule-connections/:id/enable-actions", auth2, requireIntegrationsTier, async (c) => {
|
|
22595
22855
|
const user = c.get("user");
|
|
22596
22856
|
const body = await c.req.json().catch(() => ({}));
|
|
22597
22857
|
if (typeof body.enabled !== "boolean") return c.json({ ok: false, error: "enabled must be a boolean." }, 400);
|
|
@@ -22627,7 +22887,7 @@ app.get("/oauth/resend/callback", async (c) => {
|
|
|
22627
22887
|
return c.html(renderResendOAuthResult(false), 502);
|
|
22628
22888
|
}
|
|
22629
22889
|
});
|
|
22630
|
-
app.post("/schedule-connections/actions/slack/send-message", auth2, async (c) => {
|
|
22890
|
+
app.post("/schedule-connections/actions/slack/send-message", auth2, requireIntegrationsTier, async (c) => {
|
|
22631
22891
|
const user = c.get("user");
|
|
22632
22892
|
const body = await c.req.json().catch(() => ({}));
|
|
22633
22893
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -22641,7 +22901,7 @@ app.post("/schedule-connections/actions/slack/send-message", auth2, async (c) =>
|
|
|
22641
22901
|
return scheduleConnectionError(c, err, "Unable to send the Slack message.");
|
|
22642
22902
|
}
|
|
22643
22903
|
});
|
|
22644
|
-
app.post("/schedule-connections/actions/gmail/send-message", auth2, async (c) => {
|
|
22904
|
+
app.post("/schedule-connections/actions/gmail/send-message", auth2, requireIntegrationsTier, async (c) => {
|
|
22645
22905
|
const user = c.get("user");
|
|
22646
22906
|
const body = await c.req.json().catch(() => ({}));
|
|
22647
22907
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -22655,7 +22915,7 @@ app.post("/schedule-connections/actions/gmail/send-message", auth2, async (c) =>
|
|
|
22655
22915
|
return scheduleConnectionError(c, err, "Unable to send the email.");
|
|
22656
22916
|
}
|
|
22657
22917
|
});
|
|
22658
|
-
app.post("/schedule-connections/actions/google-calendar/create-event", auth2, async (c) => {
|
|
22918
|
+
app.post("/schedule-connections/actions/google-calendar/create-event", auth2, requireIntegrationsTier, async (c) => {
|
|
22659
22919
|
const user = c.get("user");
|
|
22660
22920
|
const body = await c.req.json().catch(() => ({}));
|
|
22661
22921
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -22677,7 +22937,7 @@ app.post("/schedule-connections/actions/google-calendar/create-event", auth2, as
|
|
|
22677
22937
|
return scheduleConnectionError(c, err, "Unable to create the calendar event.");
|
|
22678
22938
|
}
|
|
22679
22939
|
});
|
|
22680
|
-
app.post("/schedule-connections/actions/zoom/create-meeting", auth2, async (c) => {
|
|
22940
|
+
app.post("/schedule-connections/actions/zoom/create-meeting", auth2, requireIntegrationsTier, async (c) => {
|
|
22681
22941
|
const user = c.get("user");
|
|
22682
22942
|
const body = await c.req.json().catch(() => ({}));
|
|
22683
22943
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -22697,7 +22957,7 @@ app.post("/schedule-connections/actions/zoom/create-meeting", auth2, async (c) =
|
|
|
22697
22957
|
return scheduleConnectionError(c, err, "Unable to create the Zoom meeting.");
|
|
22698
22958
|
}
|
|
22699
22959
|
});
|
|
22700
|
-
app.post("/schedule-connections/actions/read", auth2, async (c) => {
|
|
22960
|
+
app.post("/schedule-connections/actions/read", auth2, requireIntegrationsTier, async (c) => {
|
|
22701
22961
|
const user = c.get("user");
|
|
22702
22962
|
const body = await c.req.json().catch(() => ({}));
|
|
22703
22963
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -22714,7 +22974,7 @@ app.post("/schedule-connections/actions/read", auth2, async (c) => {
|
|
|
22714
22974
|
return scheduleConnectionError(c, err, "Unable to read from this connection.");
|
|
22715
22975
|
}
|
|
22716
22976
|
});
|
|
22717
|
-
app.post("/schedule-connections/actions/import-memory", auth2, async (c) => {
|
|
22977
|
+
app.post("/schedule-connections/actions/import-memory", auth2, requireIntegrationsTier, async (c) => {
|
|
22718
22978
|
const user = c.get("user");
|
|
22719
22979
|
const body = await c.req.json().catch(() => ({}));
|
|
22720
22980
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -22771,7 +23031,7 @@ app.post("/schedule-connections/actions/import-memory", auth2, async (c) => {
|
|
|
22771
23031
|
return scheduleConnectionError(c, err, "Unable to import this connected-service snapshot into Memory.");
|
|
22772
23032
|
}
|
|
22773
23033
|
});
|
|
22774
|
-
app.post("/schedule-connections/actions/describe", auth2, async (c) => {
|
|
23034
|
+
app.post("/schedule-connections/actions/describe", auth2, requireIntegrationsTier, async (c) => {
|
|
22775
23035
|
const user = c.get("user");
|
|
22776
23036
|
const body = await c.req.json().catch(() => ({}));
|
|
22777
23037
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -22788,7 +23048,7 @@ app.post("/schedule-connections/actions/describe", auth2, async (c) => {
|
|
|
22788
23048
|
return scheduleConnectionError(c, err, "Unable to describe this connection tool.");
|
|
22789
23049
|
}
|
|
22790
23050
|
});
|
|
22791
|
-
app.post("/schedule-connections/actions/export", auth2, async (c) => {
|
|
23051
|
+
app.post("/schedule-connections/actions/export", auth2, requireIntegrationsTier, async (c) => {
|
|
22792
23052
|
const user = c.get("user");
|
|
22793
23053
|
const body = await c.req.json().catch(() => ({}));
|
|
22794
23054
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -22848,7 +23108,7 @@ app.post("/schedule-connections/actions/export", auth2, async (c) => {
|
|
|
22848
23108
|
return scheduleConnectionError(c, err, "Unable to export this connected service.");
|
|
22849
23109
|
}
|
|
22850
23110
|
});
|
|
22851
|
-
app.post("/schedule-connections/actions/export-download", auth2, async (c) => {
|
|
23111
|
+
app.post("/schedule-connections/actions/export-download", auth2, requireIntegrationsTier, async (c) => {
|
|
22852
23112
|
const user = c.get("user");
|
|
22853
23113
|
const body = await c.req.json().catch(() => ({}));
|
|
22854
23114
|
const artifactId = typeof body.artifactId === "string" ? body.artifactId.trim() : "";
|
|
@@ -22865,7 +23125,7 @@ app.post("/schedule-connections/actions/export-download", auth2, async (c) => {
|
|
|
22865
23125
|
return c.json({ ok: false, error: "Unable to renew this artifact download." }, 502);
|
|
22866
23126
|
}
|
|
22867
23127
|
});
|
|
22868
|
-
app.post("/schedule-connections/actions/call", auth2, async (c) => {
|
|
23128
|
+
app.post("/schedule-connections/actions/call", auth2, requireIntegrationsTier, async (c) => {
|
|
22869
23129
|
const user = c.get("user");
|
|
22870
23130
|
const body = await c.req.json().catch(() => ({}));
|
|
22871
23131
|
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
@@ -22985,7 +23245,7 @@ app.get("/schedule-actions/:id/connections", auth2, async (c) => {
|
|
|
22985
23245
|
return scheduleConnectionError(c, err, "Unable to load scheduled action service connections.");
|
|
22986
23246
|
}
|
|
22987
23247
|
});
|
|
22988
|
-
app.put("/schedule-actions/:id/connections", auth2, async (c) => {
|
|
23248
|
+
app.put("/schedule-actions/:id/connections", auth2, requireIntegrationsTier, async (c) => {
|
|
22989
23249
|
const user = c.get("user");
|
|
22990
23250
|
const body = await c.req.json().catch(() => ({}));
|
|
22991
23251
|
let connections;
|
|
@@ -23270,8 +23530,7 @@ app.get("/history", auth2, async (c) => {
|
|
|
23270
23530
|
location: job.options?.location ?? "",
|
|
23271
23531
|
source: LedgerOperation.SERP,
|
|
23272
23532
|
status: job.status,
|
|
23273
|
-
result_count: job.result ? (job.result.flat?.length ?? 0) + (job.result.organicResults?.length ?? 0) : 0
|
|
23274
|
-
result: job.result ?? null
|
|
23533
|
+
result_count: job.result ? (job.result.flat?.length ?? 0) + (job.result.organicResults?.length ?? 0) : 0
|
|
23275
23534
|
}));
|
|
23276
23535
|
const eventRows = events.map((event) => ({
|
|
23277
23536
|
id: event.id,
|
|
@@ -23281,7 +23540,6 @@ app.get("/history", auth2, async (c) => {
|
|
|
23281
23540
|
source: event.source,
|
|
23282
23541
|
status: event.status,
|
|
23283
23542
|
result_count: event.result_count ?? 0,
|
|
23284
|
-
result: event.result ?? null,
|
|
23285
23543
|
error: event.error ?? null
|
|
23286
23544
|
}));
|
|
23287
23545
|
const rows = [...jobRows, ...eventRows].sort((a, b) => String(b.ts).localeCompare(String(a.ts)));
|
|
@@ -23973,6 +24231,7 @@ app.route("/mcp", mcpApp);
|
|
|
23973
24231
|
app.route("/agent", buildBrowserAgentRoutes());
|
|
23974
24232
|
app.route("/chat", chatApp);
|
|
23975
24233
|
app.route("/schedule", scheduleApp);
|
|
24234
|
+
app.route("/resend", resendInboundApp);
|
|
23976
24235
|
app.get("/console", (c) => c.html(renderConsoleHtml()));
|
|
23977
24236
|
app.get("/console/auth/:id", async (c) => {
|
|
23978
24237
|
const id = c.req.param("id");
|
|
@@ -24102,4 +24361,4 @@ app.get("/blog/:slug/", (c) => {
|
|
|
24102
24361
|
export {
|
|
24103
24362
|
app
|
|
24104
24363
|
};
|
|
24105
|
-
//# sourceMappingURL=server-
|
|
24364
|
+
//# sourceMappingURL=server-U5VODSSW.js.map
|