mcp-scraper 0.10.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/bin/api-server.cjs +171 -19
- 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 +2 -2
- package/dist/bin/mcp-scraper-install.cjs.map +1 -1
- package/dist/bin/mcp-scraper-install.js +2 -2
- package/dist/bin/mcp-stdio-server.cjs +57 -8
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +3 -3
- package/dist/{chunk-5HNHYUJ5.js → chunk-D3AJWXA2.js} +2 -2
- package/dist/{chunk-5HNHYUJ5.js.map → chunk-D3AJWXA2.js.map} +1 -1
- package/dist/{chunk-IRYBBEZJ.js → chunk-HXNE5GLG.js} +57 -8
- package/dist/chunk-HXNE5GLG.js.map +1 -0
- package/dist/chunk-YA364G53.js +7 -0
- package/dist/chunk-YA364G53.js.map +1 -0
- package/dist/{server-KTA7CFX6.js → server-TFWBW24U.js} +116 -13
- package/dist/server-TFWBW24U.js.map +1 -0
- package/docs/mcp-tool-manifest.generated.json +11364 -1479
- package/package.json +2 -2
- package/dist/chunk-B7BAJU7K.js +0 -7
- package/dist/chunk-B7BAJU7K.js.map +0 -1
- package/dist/chunk-IRYBBEZJ.js.map +0 -1
- package/dist/server-KTA7CFX6.js.map +0 -1
package/README.md
CHANGED
|
@@ -88,7 +88,7 @@ Build the branded one-click bundle:
|
|
|
88
88
|
npm run build:mcpb
|
|
89
89
|
```
|
|
90
90
|
|
|
91
|
-
The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.
|
|
91
|
+
The generated bundle is written to `build/mcpb/mcp-scraper-<version>.mcpb` and copied to `public/downloads/` for the hosted download. The current public bundle is `https://mcpscraper.dev/downloads/mcp-scraper.mcpb` (`0.12.0`, SHA-256 `2a0dfdc53e93d48588ef672c6daf0ec0e6194b3f938add02b106bf5e86c20ef3`). Install it by opening or dragging it into Claude Desktop. Claude displays the `MCP Scraper` install card, icon, and API-key configuration field from the bundle manifest.
|
|
92
92
|
|
|
93
93
|
The MCPB install exposes every tool — web-intelligence plus all `browser_*` tools — through the one `mcp-scraper` server.
|
|
94
94
|
|
|
@@ -171,7 +171,7 @@ env = { MCP_SCRAPER_API_KEY = "sk_live_your_key" }
|
|
|
171
171
|
- `workflow_run` — run hosted workflows such as `agent-packet`, `local-competitive-audit`, `map-comparison`, `serp-comparison`, `paa-expansion-brief`, and `ai-overview-language`; returns run metadata, summary, and artifact IDs.
|
|
172
172
|
- `workflow_status` — reopen a workflow run and list its current status and artifacts.
|
|
173
173
|
- `workflow_artifact_read` — pull generated workflow artifacts such as `evidence.json`, CSVs, Markdown briefs, and reports back into MCP context.
|
|
174
|
-
- `
|
|
174
|
+
- `rank_tracker_workflow` — generate a database schema, cron/heartbeat plan, ingestion workflow, metrics list, and implementation prompt for building rank trackers. It has modes for Maps rankings via `directory_workflow`/`maps_search`, organic rankings via `search_serp`, AI Overview citation tracking, and PAA source presence tracking. This planning tool does not spend credits.
|
|
175
175
|
- `credits_info`
|
|
176
176
|
|
|
177
177
|
### Browser-agent tools
|
|
@@ -207,7 +207,7 @@ The `mcp-scraper` server (and the MCPB bundle, which runs it) exposes both secti
|
|
|
207
207
|
|
|
208
208
|
All MCP tools expose output schemas and return `structuredContent` with the IDs, URLs, CSV paths, transcripts, browser session handles, replay paths, artifacts, recipe fields, or blueprint fields needed by the next step. Browser Agent tools keep a JSON text block for older clients, but structured data is the primary contract. All tools carry MCP annotations; file-writing tools such as replay downloads and annotations state their filesystem side effects.
|
|
209
209
|
|
|
210
|
-
The canonical tool inventory is generated at `docs/mcp-tool-manifest.generated.json`.
|
|
210
|
+
The canonical tool inventory is generated at `docs/mcp-tool-manifest.generated.json`. Both the `mcp-scraper` stdio server and the hosted endpoint at `https://mcpscraper.dev/mcp` expose the same 153 tools: 68 scraper, browser, workflow, billing, and connected-service tools plus 85 durable-memory tools. Release verification compares the exact local and remote tool-name sets, not only the count.
|
|
211
211
|
|
|
212
212
|
## Resources
|
|
213
213
|
|
|
@@ -244,7 +244,7 @@ npm update -g mcp-scraper
|
|
|
244
244
|
npm install mcp-scraper@latest
|
|
245
245
|
```
|
|
246
246
|
|
|
247
|
-
Users who do not update can keep using the tools their installed package already advertises, but they will not see newly added stdio tools, schemas, or AI-facing descriptions. For example, a client running an older package cannot call `
|
|
247
|
+
Users who do not update can keep using the tools their installed package already advertises, but they will not see newly added stdio tools, schemas, or AI-facing descriptions. For example, a client running an older package cannot call `rank_tracker_workflow`, `directory_workflow`, connected-service actions, or browser tools through stdio even if the hosted API already supports adjacent endpoints.
|
|
248
248
|
|
|
249
249
|
## Branded One-Click Installs
|
|
250
250
|
|
package/dist/bin/api-server.cjs
CHANGED
|
@@ -27452,7 +27452,7 @@ var PACKAGE_VERSION;
|
|
|
27452
27452
|
var init_version = __esm({
|
|
27453
27453
|
"src/version.ts"() {
|
|
27454
27454
|
"use strict";
|
|
27455
|
-
PACKAGE_VERSION = "0.
|
|
27455
|
+
PACKAGE_VERSION = "0.12.0";
|
|
27456
27456
|
}
|
|
27457
27457
|
});
|
|
27458
27458
|
|
|
@@ -27625,7 +27625,7 @@ var init_output_schema_registry = __esm({
|
|
|
27625
27625
|
});
|
|
27626
27626
|
|
|
27627
27627
|
// src/mcp/mcp-tool-schemas.ts
|
|
27628
|
-
var import_zod33, HarvestPaaInputSchema, ExtractUrlInputSchema, DiffPageInputSchema, MapSiteUrlsInputSchema, ExtractSiteInputSchema, AuditSiteInputSchema, YoutubeHarvestInputSchema, YoutubeTranscribeInputSchema, FacebookPageIntelInputSchema, FacebookAdSearchInputSchema, RedditThreadInputSchema, VideoFrameAnalysisInputSchema, VideoFrameAnalysisStatusInputSchema, FacebookAdTranscribeInputSchema, FacebookVideoTranscribeInputSchema, GoogleAdsSearchInputSchema, GoogleAdsPageIntelInputSchema, GoogleAdsTranscribeInputSchema, InstagramProfileContentInputSchema, InstagramMediaDownloadInputSchema, MapsPlaceIntelInputSchema, TrustpilotReviewsInputSchema, G2ReviewsInputSchema, ReviewCardSchema, MapsSearchInputSchema, DirectoryWorkflowInputSchema, ArtifactPointerOutputSchema, RankTrackerModeSchema, RankTrackerBlueprintInputSchema, NullableString, MapsSearchAttemptOutput, MapsSearchOutputSchema, DirectoryMapsBusinessOutput, DirectoryWorkflowOutputSchema, RankTrackerToolPlanOutput, RankTrackerTableOutput, RankTrackerCronJobOutput, RankTrackerBlueprintOutputSchema, OrganicResultOutput, AiOverviewOutput, EntityIdsOutput, HarvestPaaOutputSchema, SearchSerpOutputSchema, ExtractUrlOutputSchema, DiffPageOutputSchema, ExtractSiteOutputSchema, AuditSiteOutputSchema, MapsPlaceIntelOutputSchema, TrustpilotReviewsOutputSchema, G2ReviewsOutputSchema, CreditsInfoOutputSchema, MapSiteUrlsOutputSchema, YoutubeHarvestOutputSchema, FacebookAdSearchOutputSchema, VideoFrameAnalysisOutputSchema, VideoFrameAnalysisStatusOutputSchema, RedditThreadOutputSchema, FacebookPageIntelOutputSchema, GoogleAdsSearchOutputSchema, GoogleAdsPageIntelOutputSchema, FacebookVideoTranscribeOutputSchema, TranscriptChunkOutput, InstagramBrowserOutput, InstagramPaginationOutput, InstagramProfileContentOutputSchema, InstagramMediaTrackOutput, InstagramDownloadOutput, InstagramMediaDownloadOutputSchema, YoutubeTranscribeOutputSchema, FacebookAdTranscribeOutputSchema, GoogleAdsTranscribeOutputSchema, CaptureSerpSnapshotOutputSchema, CaptureSerpPageSnapshotsOutputSchema, CreditsInfoInputSchema, WorkflowIdSchema2, WorkflowListInputSchema, WorkflowSuggestInputSchema, WorkflowRunInputSchema, WorkflowStepInputSchema, WorkflowStatusInputSchema, WorkflowArtifactReadInputSchema, WorkflowRecipeOutput, WorkflowDefinitionOutput, WorkflowArtifactOutput, WorkflowListOutputSchema, WorkflowSuggestOutputSchema, WorkflowRunOutputSchema, WorkflowStepOutputSchema, WorkflowStatusOutputSchema, WorkflowArtifactReadOutputSchema, SearchSerpInputSchema, CaptureSerpSnapshotInputSchema, ScreenshotInputSchema, CaptureSerpPageSnapshotsInputSchema, ReportArtifactReadInputSchema, ReportArtifactReadOutputSchema, ListServiceConnectionsInputSchema, ListServiceConnectionsOutputSchema, ReadServiceConnectionInputSchema, ReadServiceConnectionOutputSchema, SlackSendMessageInputSchema, SlackSendMessageOutputSchema, GmailSendMessageInputSchema, GmailSendMessageOutputSchema, GoogleCalendarCreateEventInputSchema, GoogleCalendarCreateEventOutputSchema, ZoomCreateMeetingInputSchema, ZoomCreateMeetingOutputSchema;
|
|
27628
|
+
var import_zod33, HarvestPaaInputSchema, ExtractUrlInputSchema, DiffPageInputSchema, MapSiteUrlsInputSchema, ExtractSiteInputSchema, AuditSiteInputSchema, YoutubeHarvestInputSchema, YoutubeTranscribeInputSchema, FacebookPageIntelInputSchema, FacebookAdSearchInputSchema, RedditThreadInputSchema, VideoFrameAnalysisInputSchema, VideoFrameAnalysisStatusInputSchema, FacebookAdTranscribeInputSchema, FacebookVideoTranscribeInputSchema, GoogleAdsSearchInputSchema, GoogleAdsPageIntelInputSchema, GoogleAdsTranscribeInputSchema, InstagramProfileContentInputSchema, InstagramMediaDownloadInputSchema, MapsPlaceIntelInputSchema, TrustpilotReviewsInputSchema, G2ReviewsInputSchema, ReviewCardSchema, MapsSearchInputSchema, DirectoryWorkflowInputSchema, ArtifactPointerOutputSchema, RankTrackerModeSchema, RankTrackerBlueprintInputSchema, NullableString, MapsSearchAttemptOutput, MapsSearchOutputSchema, DirectoryMapsBusinessOutput, DirectoryWorkflowOutputSchema, RankTrackerToolPlanOutput, RankTrackerTableOutput, RankTrackerCronJobOutput, RankTrackerBlueprintOutputSchema, OrganicResultOutput, AiOverviewOutput, EntityIdsOutput, HarvestPaaOutputSchema, SearchSerpOutputSchema, ExtractUrlOutputSchema, DiffPageOutputSchema, ExtractSiteOutputSchema, AuditSiteOutputSchema, MapsPlaceIntelOutputSchema, TrustpilotReviewsOutputSchema, G2ReviewsOutputSchema, CreditsInfoOutputSchema, MapSiteUrlsOutputSchema, YoutubeHarvestOutputSchema, FacebookAdSearchOutputSchema, VideoFrameAnalysisOutputSchema, VideoFrameAnalysisStatusOutputSchema, RedditThreadOutputSchema, FacebookPageIntelOutputSchema, GoogleAdsSearchOutputSchema, GoogleAdsPageIntelOutputSchema, FacebookVideoTranscribeOutputSchema, TranscriptChunkOutput, InstagramBrowserOutput, InstagramPaginationOutput, InstagramProfileContentOutputSchema, InstagramMediaTrackOutput, InstagramDownloadOutput, InstagramMediaDownloadOutputSchema, YoutubeTranscribeOutputSchema, FacebookAdTranscribeOutputSchema, GoogleAdsTranscribeOutputSchema, CaptureSerpSnapshotOutputSchema, CaptureSerpPageSnapshotsOutputSchema, CreditsInfoInputSchema, WorkflowIdSchema2, WorkflowListInputSchema, WorkflowSuggestInputSchema, WorkflowRunInputSchema, WorkflowStepInputSchema, WorkflowStatusInputSchema, WorkflowArtifactReadInputSchema, WorkflowRecipeOutput, WorkflowDefinitionOutput, WorkflowArtifactOutput, WorkflowListOutputSchema, WorkflowSuggestOutputSchema, WorkflowRunOutputSchema, WorkflowStepOutputSchema, WorkflowStatusOutputSchema, WorkflowArtifactReadOutputSchema, SearchSerpInputSchema, CaptureSerpSnapshotInputSchema, ScreenshotInputSchema, CaptureSerpPageSnapshotsInputSchema, ReportArtifactReadInputSchema, ReportArtifactReadOutputSchema, ListServiceConnectionsInputSchema, ListServiceConnectionsOutputSchema, ReadServiceConnectionInputSchema, ReadServiceConnectionOutputSchema, CallServiceConnectionActionInputSchema, CallServiceConnectionActionOutputSchema, SetScheduledActionConnectionsInputSchema, SetScheduledActionConnectionsOutputSchema, SlackSendMessageInputSchema, SlackSendMessageOutputSchema, GmailSendMessageInputSchema, GmailSendMessageOutputSchema, GoogleCalendarCreateEventInputSchema, GoogleCalendarCreateEventOutputSchema, ZoomCreateMeetingInputSchema, ZoomCreateMeetingOutputSchema;
|
|
27629
27629
|
var init_mcp_tool_schemas = __esm({
|
|
27630
27630
|
"src/mcp/mcp-tool-schemas.ts"() {
|
|
27631
27631
|
"use strict";
|
|
@@ -28659,6 +28659,7 @@ var init_mcp_tool_schemas = __esm({
|
|
|
28659
28659
|
status: import_zod33.z.string(),
|
|
28660
28660
|
actionsEnabled: import_zod33.z.boolean(),
|
|
28661
28661
|
readTools: import_zod33.z.array(import_zod33.z.string()).describe("Tool names this connection can be read with via read_service_connection."),
|
|
28662
|
+
actionTools: import_zod33.z.array(import_zod33.z.string()).describe("Explicitly allowlisted write or mutation tool names callable through call_service_connection_action after actions are enabled for this connection."),
|
|
28662
28663
|
vaultName: import_zod33.z.string().nullable().describe("Memory vault this connection's digest writes into, if it has run at least once. Search it with memory-search."),
|
|
28663
28664
|
tableName: import_zod33.z.string().nullable().describe("Table this connection's digest writes structured rows into, if it has run at least once. Query it with table-query.")
|
|
28664
28665
|
}))
|
|
@@ -28673,6 +28674,29 @@ var init_mcp_tool_schemas = __esm({
|
|
|
28673
28674
|
result: import_zod33.z.unknown().optional(),
|
|
28674
28675
|
error: NullableString
|
|
28675
28676
|
};
|
|
28677
|
+
CallServiceConnectionActionInputSchema = {
|
|
28678
|
+
connectionId: import_zod33.z.string().min(1).describe("A connectionId from list_service_connections with actionsEnabled true."),
|
|
28679
|
+
tool: import_zod33.z.string().min(1).describe("One exact tool name from that connection's actionTools. Arbitrary Nango action names are rejected server-side."),
|
|
28680
|
+
args: import_zod33.z.record(import_zod33.z.string(), import_zod33.z.unknown()).describe("Arguments required by the selected action. The provider action validates its own typed input before execution.")
|
|
28681
|
+
};
|
|
28682
|
+
CallServiceConnectionActionOutputSchema = {
|
|
28683
|
+
ok: import_zod33.z.boolean(),
|
|
28684
|
+
result: import_zod33.z.unknown().optional(),
|
|
28685
|
+
error: NullableString
|
|
28686
|
+
};
|
|
28687
|
+
SetScheduledActionConnectionsInputSchema = {
|
|
28688
|
+
scheduleActionId: import_zod33.z.string().min(1).describe("A scheduled action id returned by create-scheduled-action or list-scheduled-actions."),
|
|
28689
|
+
connections: import_zod33.z.array(import_zod33.z.object({
|
|
28690
|
+
connectionId: import_zod33.z.string().min(1).describe("A tenant-scoped connectionId from list_service_connections."),
|
|
28691
|
+
providerConfigKey: import_zod33.z.string().min(1).describe("The matching providerConfigKey returned with that connection."),
|
|
28692
|
+
allowedTools: import_zod33.z.array(import_zod33.z.string().min(1)).min(1).max(100).describe("Exact readTools and, only when live actions are enabled, actionTools this schedule may use.")
|
|
28693
|
+
}).strict()).max(20).describe("Exact connection and tool grants for this schedule. Pass an empty array to remove every external-service grant.")
|
|
28694
|
+
};
|
|
28695
|
+
SetScheduledActionConnectionsOutputSchema = {
|
|
28696
|
+
ok: import_zod33.z.boolean(),
|
|
28697
|
+
connections: import_zod33.z.array(import_zod33.z.unknown()).optional(),
|
|
28698
|
+
error: NullableString
|
|
28699
|
+
};
|
|
28676
28700
|
SlackSendMessageInputSchema = {
|
|
28677
28701
|
connectionId: import_zod33.z.string().min(1).describe("A Slack connectionId from list_service_connections, with actionsEnabled true."),
|
|
28678
28702
|
channel: import_zod33.z.string().min(1).describe(`Slack channel ID to send to, e.g. "C1234567890". Get this from the connection's own read tools, not guessed.`),
|
|
@@ -29403,7 +29427,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
29403
29427
|
}, async (input) => formatCreditsInfo(await executor.creditsInfo(input), input));
|
|
29404
29428
|
server.registerTool("list_service_connections", {
|
|
29405
29429
|
title: "List Connected Services",
|
|
29406
|
-
description: "List
|
|
29430
|
+
description: "List every third-party service connection this MCP Scraper account has authorized, including Google Analytics, YouTube, Facebook Pages, LinkedIn, X, Meta Marketing, Slack, Gmail, Calendar, Drive, Zoom, Xero, and others. Returns the tenant-scoped connectionId plus exact readTools and actionTools. Get a connectionId and exact tool name here before calling read_service_connection or call_service_connection_action. For already-digested history, prefer the returned vaultName or tableName.",
|
|
29407
29431
|
inputSchema: ListServiceConnectionsInputSchema,
|
|
29408
29432
|
outputSchema: recordOutputSchema("list_service_connections", ListServiceConnectionsOutputSchema),
|
|
29409
29433
|
annotations: { title: "List Connected Services", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
@@ -29438,11 +29462,25 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
29438
29462
|
}, async (input) => executor.zoomCreateMeeting(input));
|
|
29439
29463
|
server.registerTool("read_service_connection", {
|
|
29440
29464
|
title: "Read Connected Service",
|
|
29441
|
-
description: "Call one live, read-only tool on
|
|
29465
|
+
description: "Call one live, read-only tool on any connected service, including Google Analytics, YouTube, Facebook Pages, LinkedIn, X, Slack, Gmail, Calendar, Drive, Zoom, and Xero. Requires a connectionId and an exact name from that connection's readTools in list_service_connections; an unlisted tool is rejected server-side. For already-digested history, prefer memory-search over vaultName or table-query over tableName.",
|
|
29442
29466
|
inputSchema: ReadServiceConnectionInputSchema,
|
|
29443
29467
|
outputSchema: recordOutputSchema("read_service_connection", ReadServiceConnectionOutputSchema),
|
|
29444
29468
|
annotations: { title: "Read Connected Service", readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: true }
|
|
29445
29469
|
}, async (input) => executor.readServiceConnection(input));
|
|
29470
|
+
server.registerTool("call_service_connection_action", {
|
|
29471
|
+
title: "Run Connected Service Action",
|
|
29472
|
+
description: "Run one explicitly allowlisted write or mutation on a tenant-owned OAuth connection. First call list_service_connections, use a connection with actionsEnabled true, choose one exact actionTools entry, and supply that action's arguments. The server rejects arbitrary action names, inactive or foreign connections, disabled actions, and tools outside the provider allowlist. This may publish, update, send, subscribe, or delete provider data depending on the chosen tool.",
|
|
29473
|
+
inputSchema: CallServiceConnectionActionInputSchema,
|
|
29474
|
+
outputSchema: recordOutputSchema("call_service_connection_action", CallServiceConnectionActionOutputSchema),
|
|
29475
|
+
annotations: { title: "Run Connected Service Action", readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: true }
|
|
29476
|
+
}, async (input) => executor.callServiceConnectionAction(input));
|
|
29477
|
+
server.registerTool("set_scheduled_action_connections", {
|
|
29478
|
+
title: "Set Scheduled Action Connections",
|
|
29479
|
+
description: "Attach exact tenant-owned OAuth connections and exact allowed tools to an existing scheduled action. First create or identify the schedule, call list_service_connections, then grant only the required readTools and\u2014when that account has actionsEnabled true\u2014the required actionTools. The server verifies schedule ownership, connection ownership, provider policy, and the per-account action switch. Pass an empty connections array to remove all external-service access from the schedule.",
|
|
29480
|
+
inputSchema: SetScheduledActionConnectionsInputSchema,
|
|
29481
|
+
outputSchema: recordOutputSchema("set_scheduled_action_connections", SetScheduledActionConnectionsOutputSchema),
|
|
29482
|
+
annotations: { title: "Set Scheduled Action Connections", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false }
|
|
29483
|
+
}, async (input) => executor.setScheduledActionConnections(input));
|
|
29446
29484
|
}
|
|
29447
29485
|
var import_mcp, import_node_fs9, import_node_path12, import_node_crypto10;
|
|
29448
29486
|
var init_paa_mcp_server = __esm({
|
|
@@ -29539,10 +29577,10 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
29539
29577
|
const configuredSerpIntelligenceTimeoutMs = Number(process.env.MCP_SCRAPER_SERP_INTELLIGENCE_HTTP_TIMEOUT_MS ?? this.timeoutMs);
|
|
29540
29578
|
this.serpIntelligenceTimeoutMs = Number.isFinite(configuredSerpIntelligenceTimeoutMs) && configuredSerpIntelligenceTimeoutMs > 0 ? configuredSerpIntelligenceTimeoutMs : this.timeoutMs;
|
|
29541
29579
|
}
|
|
29542
|
-
async call(path6, body, timeoutMs = this.timeoutMs) {
|
|
29580
|
+
async call(path6, body, timeoutMs = this.timeoutMs, method = "POST") {
|
|
29543
29581
|
try {
|
|
29544
29582
|
const res = await fetch(`${this.baseUrl}${path6}`, {
|
|
29545
|
-
method
|
|
29583
|
+
method,
|
|
29546
29584
|
headers: {
|
|
29547
29585
|
"Content-Type": "application/json",
|
|
29548
29586
|
"x-api-key": this.apiKey
|
|
@@ -29769,6 +29807,14 @@ var init_http_mcp_tool_executor = __esm({
|
|
|
29769
29807
|
readServiceConnection(input) {
|
|
29770
29808
|
return this.call("/schedule-connections/actions/read", input);
|
|
29771
29809
|
}
|
|
29810
|
+
callServiceConnectionAction(input) {
|
|
29811
|
+
return this.call("/schedule-connections/actions/call", input);
|
|
29812
|
+
}
|
|
29813
|
+
setScheduledActionConnections(input) {
|
|
29814
|
+
return this.call(`/schedule-actions/${encodeURIComponent(input.scheduleActionId)}/connections`, {
|
|
29815
|
+
connections: input.connections
|
|
29816
|
+
}, void 0, "PUT");
|
|
29817
|
+
}
|
|
29772
29818
|
captureSerpSnapshot(input) {
|
|
29773
29819
|
return this.call("/serp-intelligence/capture", input, this.serpIntelligenceTimeoutMs);
|
|
29774
29820
|
}
|
|
@@ -32823,11 +32869,12 @@ var init_memory_tool_schemas = __esm({
|
|
|
32823
32869
|
CreateScheduledActionSchema = {
|
|
32824
32870
|
id: "create-scheduled-action",
|
|
32825
32871
|
upstreamName: "createScheduledActionTool",
|
|
32826
|
-
description: "Create a scheduled action
|
|
32872
|
+
description: "Create a scheduled action in agent mode (default) or connection_sync mode. Agent mode asks an agent to follow the description and write a result into the target vault. connection_sync deterministically runs the approved read-only tools on bound service connections and ingests their data; it requires at least one connection to be bound before execution. Cadence 'once' runs a single time then completes permanently. Requires an active scheduling subscription and write access to the target vault.",
|
|
32827
32873
|
input: {
|
|
32828
32874
|
description: import_zod35.z.string().min(1).describe("Free-text description of what this action should do each time it runs."),
|
|
32829
32875
|
vault: import_zod35.z.string().min(1).describe("The vault this action writes its results into. You must already have write access to it."),
|
|
32830
32876
|
cadence: import_zod35.z.enum(["once", "daily", "weekly", "monthly"]).describe('How often this action runs. "once" fires a single time and then completes.'),
|
|
32877
|
+
executionMode: import_zod35.z.enum(["agent", "connection_sync"]).default("agent").describe(`How to execute each run. "agent" (default) lets an agent follow the description. "connection_sync" deterministically ingests data from the schedule's bound connections using only their approved read-only tools; bind at least one connection before it runs.`),
|
|
32831
32878
|
timeOfDay: import_zod35.z.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().describe("24-hour HH:MM clock time to run at, in the given timezone. Optional \u2014 omit to run at any time during the period (matches prior default behavior)."),
|
|
32832
32879
|
timezone: import_zod35.z.string().optional().describe('IANA timezone name, e.g. "America/Denver". Only meaningful together with timeOfDay. Defaults to UTC.'),
|
|
32833
32880
|
deployDate: import_zod35.z.string().regex(/^\d{4}-\d{2}-\d{2}$/).optional().describe('Calendar date (YYYY-MM-DD, in the given timezone) this action should first become eligible to run \u2014 its deployment/start date. For recurring cadences, the first occurrence lands on or after this date; every later occurrence still follows the normal cadence. For cadence "once", this (combined with timeOfDay if given) is exactly what day it fires. Omit to start immediately.')
|
|
@@ -32836,6 +32883,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
32836
32883
|
ok: import_zod35.z.boolean().describe("True when the scheduled action was created."),
|
|
32837
32884
|
id: import_zod35.z.string().optional().describe("The new scheduled action id."),
|
|
32838
32885
|
nextRunAt: import_zod35.z.string().optional().describe("When it will first run."),
|
|
32886
|
+
executionMode: import_zod35.z.enum(["agent", "connection_sync"]).optional().describe("The stored execution mode. Defaults to agent when omitted from the request."),
|
|
32839
32887
|
error: import_zod35.z.string().optional().describe("Human-readable failure reason when ok is false."),
|
|
32840
32888
|
code: import_zod35.z.string().optional().describe("Machine-readable denial code: not_enabled when no scheduling subscription is active.")
|
|
32841
32889
|
},
|
|
@@ -32910,7 +32958,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
32910
32958
|
ListScheduledActionsSchema = {
|
|
32911
32959
|
id: "list-scheduled-actions",
|
|
32912
32960
|
upstreamName: "listScheduledActionsTool",
|
|
32913
|
-
description: "List every scheduled action you own \u2014 active, paused, and completed one-time actions \u2014 with cadence, next run time, and last run status.",
|
|
32961
|
+
description: "List every scheduled action you own \u2014 active, paused, and completed one-time actions \u2014 with execution mode, cadence, next run time, and last run status. connection_sync means deterministic read-only ingestion from bound service connections.",
|
|
32914
32962
|
input: {},
|
|
32915
32963
|
output: {
|
|
32916
32964
|
ok: import_zod35.z.boolean(),
|
|
@@ -32919,6 +32967,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
32919
32967
|
description: import_zod35.z.string(),
|
|
32920
32968
|
vault: import_zod35.z.string(),
|
|
32921
32969
|
cadence: import_zod35.z.enum(["once", "daily", "weekly", "monthly"]),
|
|
32970
|
+
executionMode: import_zod35.z.enum(["agent", "connection_sync"]),
|
|
32922
32971
|
timeOfDay: import_zod35.z.string().nullable(),
|
|
32923
32972
|
timezone: import_zod35.z.string(),
|
|
32924
32973
|
status: import_zod35.z.enum(["active", "paused", "completed"]),
|
|
@@ -38838,6 +38887,43 @@ var init_memory_db = __esm({
|
|
|
38838
38887
|
});
|
|
38839
38888
|
|
|
38840
38889
|
// src/api/nango-control.ts
|
|
38890
|
+
function connectionSyncPolicyIssues(selections) {
|
|
38891
|
+
const issues = [];
|
|
38892
|
+
for (const selection of selections) {
|
|
38893
|
+
const required = CONNECTION_SYNC_REQUIRED_TOOLS[selection.providerConfigKey];
|
|
38894
|
+
if (!required) {
|
|
38895
|
+
issues.push({ providerConfigKey: selection.providerConfigKey, code: "unsupported_provider" });
|
|
38896
|
+
continue;
|
|
38897
|
+
}
|
|
38898
|
+
const allowed = new Set(selection.allowedTools);
|
|
38899
|
+
const missingTools = required.filter((tool) => !allowed.has(tool));
|
|
38900
|
+
if (missingTools.length > 0) {
|
|
38901
|
+
issues.push({ providerConfigKey: selection.providerConfigKey, code: "missing_required_tools", missingTools });
|
|
38902
|
+
}
|
|
38903
|
+
const requiredSet = new Set(required);
|
|
38904
|
+
const unexpectedTools = [...allowed].filter((tool) => !requiredSet.has(tool));
|
|
38905
|
+
if (unexpectedTools.length > 0) {
|
|
38906
|
+
issues.push({ providerConfigKey: selection.providerConfigKey, code: "unexpected_tools", unexpectedTools });
|
|
38907
|
+
}
|
|
38908
|
+
}
|
|
38909
|
+
return issues;
|
|
38910
|
+
}
|
|
38911
|
+
function connectionSyncSelectionError(connections) {
|
|
38912
|
+
if (connections.length === 0) {
|
|
38913
|
+
return "Data sync requires at least one bound service connection with approved read-only tools.";
|
|
38914
|
+
}
|
|
38915
|
+
const issues = connectionSyncPolicyIssues(connections);
|
|
38916
|
+
const unsupported = [...new Set(issues.filter((issue) => issue.code === "unsupported_provider").map((issue) => issue.providerConfigKey))];
|
|
38917
|
+
if (unsupported.length > 0) {
|
|
38918
|
+
return `Data sync currently supports only ${Object.keys(CONNECTION_SYNC_REQUIRED_TOOLS).join(", ")}. Unsupported providerConfigKey: ${unsupported.join(", ")}.`;
|
|
38919
|
+
}
|
|
38920
|
+
const missing = issues.filter((issue) => issue.code === "missing_required_tools").map((issue) => `${issue.providerConfigKey}: ${(issue.missingTools ?? []).join(", ")}`);
|
|
38921
|
+
if (missing.length > 0) {
|
|
38922
|
+
return `Data sync is missing required approved read tools (${missing.join("; ")}).`;
|
|
38923
|
+
}
|
|
38924
|
+
const unexpected = issues.filter((issue) => issue.code === "unexpected_tools").map((issue) => `${issue.providerConfigKey}: ${(issue.unexpectedTools ?? []).join(", ")}`);
|
|
38925
|
+
return unexpected.length > 0 ? `Data sync permits only its exact read-only tool set; remove unexpected tools (${unexpected.join("; ")}).` : null;
|
|
38926
|
+
}
|
|
38841
38927
|
function controlBaseUrl() {
|
|
38842
38928
|
return (process.env.NANGO_CONTROL_URL?.trim() || DEFAULT_NANGO_CONTROL_URL).replace(/\/$/, "");
|
|
38843
38929
|
}
|
|
@@ -38959,6 +39045,15 @@ async function getNangoCatalog() {
|
|
|
38959
39045
|
const safeDefaultAllowedTools = cleanTools(
|
|
38960
39046
|
row.safeDefaultAllowedTools ?? row.safe_default_allowed_tools ?? row.defaultAllowedTools ?? row.default_allowed_tools ?? row.allowedTools ?? row.allowed_tools
|
|
38961
39047
|
).filter((tool) => !disabledTools?.has(tool));
|
|
39048
|
+
const platformSetupStatus = firstString(row, [
|
|
39049
|
+
"platformSetupStatus",
|
|
39050
|
+
"platform_setup_status",
|
|
39051
|
+
"setupStatus",
|
|
39052
|
+
"setup_status"
|
|
39053
|
+
], 100);
|
|
39054
|
+
const appReviewStatus = row.appReviewLimited === true || row.app_review_limited === true ? "limited" : firstString(row, ["appReviewStatus", "app_review_status", "reviewStatus", "review_status"], 100);
|
|
39055
|
+
const appReviewNote = firstString(row, ["appReviewNote", "app_review_note", "reviewNote", "review_note"], 500);
|
|
39056
|
+
const connectionSyncRequiredTools = [...CONNECTION_SYNC_REQUIRED_TOOLS[providerConfigKey] ?? []];
|
|
38962
39057
|
result.push({
|
|
38963
39058
|
providerConfigKey,
|
|
38964
39059
|
provider,
|
|
@@ -38968,7 +39063,12 @@ async function getNangoCatalog() {
|
|
|
38968
39063
|
docsUrl,
|
|
38969
39064
|
authMode,
|
|
38970
39065
|
categories,
|
|
38971
|
-
safeDefaultAllowedTools
|
|
39066
|
+
safeDefaultAllowedTools,
|
|
39067
|
+
connectionSyncSupported: connectionSyncRequiredTools.length > 0,
|
|
39068
|
+
connectionSyncRequiredTools,
|
|
39069
|
+
platformSetupStatus,
|
|
39070
|
+
appReviewStatus,
|
|
39071
|
+
appReviewNote
|
|
38972
39072
|
});
|
|
38973
39073
|
}
|
|
38974
39074
|
return result;
|
|
@@ -38996,6 +39096,7 @@ async function getNangoConnections(identity) {
|
|
|
38996
39096
|
reconnectRequired,
|
|
38997
39097
|
actionsEnabled: row.actionsEnabled === true || row.actions_enabled === true,
|
|
38998
39098
|
readTools: cleanTools(row.readTools ?? row.read_tools),
|
|
39099
|
+
actionTools: cleanTools(row.actionTools ?? row.action_tools ?? row.writeTools ?? row.write_tools),
|
|
38999
39100
|
vaultName: firstString(row, ["vaultName", "vault_name"], 100),
|
|
39000
39101
|
tableName: firstString(row, ["tableName", "table_name"], 100),
|
|
39001
39102
|
createdAt: firstString(row, ["createdAt", "created_at"], 100),
|
|
@@ -39112,10 +39213,10 @@ async function setScheduleConnectionActionsEnabled(identity, connectionId, enabl
|
|
|
39112
39213
|
if (!isRecord(data) || !isRecord(data.connection)) return enabled;
|
|
39113
39214
|
return data.connection.actionsEnabled === true;
|
|
39114
39215
|
}
|
|
39115
|
-
async function callScheduleConnectionAction(identity, connectionId, input) {
|
|
39216
|
+
async function callScheduleConnectionAction(identity, connectionId, input, tool) {
|
|
39116
39217
|
const body = await controlRequest("/api/internal/nango/connections/actions/call", {
|
|
39117
39218
|
method: "POST",
|
|
39118
|
-
body: JSON.stringify({ identity, connectionId, input })
|
|
39219
|
+
body: JSON.stringify({ identity, connectionId, ...tool ? { tool } : {}, input })
|
|
39119
39220
|
});
|
|
39120
39221
|
const data = unwrapData(body);
|
|
39121
39222
|
return isRecord(data) ? data.result ?? data : data;
|
|
@@ -39128,7 +39229,7 @@ async function callScheduleConnectionRead(identity, connectionId, tool, args) {
|
|
|
39128
39229
|
const data = unwrapData(body);
|
|
39129
39230
|
return isRecord(data) ? data.result ?? data : data;
|
|
39130
39231
|
}
|
|
39131
|
-
var DEFAULT_NANGO_CONTROL_URL, DISABLED_NANGO_TOOLS, NangoControlError, ScheduleConnectionValidationError;
|
|
39232
|
+
var DEFAULT_NANGO_CONTROL_URL, DISABLED_NANGO_TOOLS, CONNECTION_SYNC_REQUIRED_TOOLS, NangoControlError, ScheduleConnectionValidationError;
|
|
39132
39233
|
var init_nango_control = __esm({
|
|
39133
39234
|
"src/api/nango-control.ts"() {
|
|
39134
39235
|
"use strict";
|
|
@@ -39137,6 +39238,17 @@ var init_nango_control = __esm({
|
|
|
39137
39238
|
"google-mail": /* @__PURE__ */ new Set(["list-filters"]),
|
|
39138
39239
|
slack: /* @__PURE__ */ new Set(["search-files", "search-messages"])
|
|
39139
39240
|
};
|
|
39241
|
+
CONNECTION_SYNC_REQUIRED_TOOLS = {
|
|
39242
|
+
"google-mail": ["list-messages", "get-message"],
|
|
39243
|
+
"google-calendar": ["list-events", "get-event"],
|
|
39244
|
+
zoom: [
|
|
39245
|
+
"list-meetings",
|
|
39246
|
+
"get-meeting",
|
|
39247
|
+
"list-recordings",
|
|
39248
|
+
"get-recording",
|
|
39249
|
+
"get-meeting-transcript"
|
|
39250
|
+
]
|
|
39251
|
+
};
|
|
39140
39252
|
NangoControlError = class extends Error {
|
|
39141
39253
|
status;
|
|
39142
39254
|
constructor(message, status = 502) {
|
|
@@ -40166,6 +40278,26 @@ var init_server = __esm({
|
|
|
40166
40278
|
return scheduleConnectionError(c, err, "Unable to read from this connection.");
|
|
40167
40279
|
}
|
|
40168
40280
|
});
|
|
40281
|
+
app.post("/schedule-connections/actions/call", auth2, async (c) => {
|
|
40282
|
+
const user = c.get("user");
|
|
40283
|
+
const body = await c.req.json().catch(() => ({}));
|
|
40284
|
+
const connectionId = providerConfigKeyFrom(body.connectionId);
|
|
40285
|
+
const tool = providerConfigKeyFrom(body.tool);
|
|
40286
|
+
if (!connectionId || !tool || !body.args || typeof body.args !== "object" || Array.isArray(body.args)) {
|
|
40287
|
+
return c.json({ ok: false, error: "connectionId, tool, and an args object are required." }, 400);
|
|
40288
|
+
}
|
|
40289
|
+
try {
|
|
40290
|
+
const result = await callScheduleConnectionAction(
|
|
40291
|
+
user.email,
|
|
40292
|
+
connectionId,
|
|
40293
|
+
body.args,
|
|
40294
|
+
tool
|
|
40295
|
+
);
|
|
40296
|
+
return c.json({ ok: true, result });
|
|
40297
|
+
} catch (err) {
|
|
40298
|
+
return scheduleConnectionError(c, err, "Unable to run this connection action.");
|
|
40299
|
+
}
|
|
40300
|
+
});
|
|
40169
40301
|
app.post("/schedule-link", auth2, async (c) => {
|
|
40170
40302
|
try {
|
|
40171
40303
|
const user = c.get("user");
|
|
@@ -40188,9 +40320,10 @@ var init_server = __esm({
|
|
|
40188
40320
|
try {
|
|
40189
40321
|
const actions = await Promise.all(r.actions.map(async (action) => {
|
|
40190
40322
|
const id = typeof action.id === "string" ? action.id : "";
|
|
40191
|
-
|
|
40323
|
+
const executionMode = action.executionMode === "connection_sync" ? "connection_sync" : "agent";
|
|
40324
|
+
if (!id) return { ...action, executionMode, connections: [] };
|
|
40192
40325
|
const bindings = await getScheduleConnectionBindings(user.email, id);
|
|
40193
|
-
return { ...action, connections: bindingsForSchedule(bindings, id) };
|
|
40326
|
+
return { ...action, executionMode, connections: bindingsForSchedule(bindings, id) };
|
|
40194
40327
|
}));
|
|
40195
40328
|
return c.json({
|
|
40196
40329
|
...r,
|
|
@@ -40200,7 +40333,7 @@ var init_server = __esm({
|
|
|
40200
40333
|
console.warn("[schedule-actions] connection bindings unavailable:", err instanceof Error ? err.message : String(err));
|
|
40201
40334
|
return c.json({
|
|
40202
40335
|
...r,
|
|
40203
|
-
actions: r.actions.map((action) => ({ ...action, connections: [] })),
|
|
40336
|
+
actions: r.actions.map((action) => ({ ...action, executionMode: action.executionMode === "connection_sync" ? "connection_sync" : "agent", connections: [] })),
|
|
40204
40337
|
connectionBindingsUnavailable: true
|
|
40205
40338
|
});
|
|
40206
40339
|
}
|
|
@@ -40210,6 +40343,10 @@ var init_server = __esm({
|
|
|
40210
40343
|
const { key, error } = await getOrCreateUserMemoryKey(user);
|
|
40211
40344
|
if (!key) return c.json({ ok: false, error: error ?? "memory unavailable" }, 503);
|
|
40212
40345
|
const body = await c.req.json().catch(() => ({}));
|
|
40346
|
+
const executionMode = body.executionMode ?? "agent";
|
|
40347
|
+
if (executionMode !== "agent" && executionMode !== "connection_sync") {
|
|
40348
|
+
return c.json({ ok: false, error: 'executionMode must be "agent" or "connection_sync".' }, 400);
|
|
40349
|
+
}
|
|
40213
40350
|
const hasConnections = Object.prototype.hasOwnProperty.call(body, "connections");
|
|
40214
40351
|
let connections;
|
|
40215
40352
|
try {
|
|
@@ -40217,18 +40354,23 @@ var init_server = __esm({
|
|
|
40217
40354
|
} catch (err) {
|
|
40218
40355
|
return scheduleConnectionError(c, err, "Invalid service connections.");
|
|
40219
40356
|
}
|
|
40220
|
-
|
|
40357
|
+
if (executionMode === "connection_sync") {
|
|
40358
|
+
const policyError = connectionSyncSelectionError(connections);
|
|
40359
|
+
if (policyError) return c.json({ ok: false, error: policyError }, 400);
|
|
40360
|
+
}
|
|
40361
|
+
const actionBody = { ...body, executionMode };
|
|
40221
40362
|
delete actionBody.connections;
|
|
40222
40363
|
const r = await memoryCall("createScheduledActionTool", actionBody, key);
|
|
40223
|
-
|
|
40224
|
-
if (
|
|
40364
|
+
const createResponse = { ...r, executionMode };
|
|
40365
|
+
if (!r.ok || !hasConnections) return c.json(createResponse);
|
|
40366
|
+
if (connections.length === 0) return c.json({ ...createResponse, connections: [] });
|
|
40225
40367
|
if (!r.id) {
|
|
40226
40368
|
console.error("[schedule-actions] create returned no id while service connections were requested");
|
|
40227
40369
|
return c.json({ ok: false, error: "The scheduled action was created without a usable id; service connections were not attached." }, 502);
|
|
40228
40370
|
}
|
|
40229
40371
|
try {
|
|
40230
40372
|
const bound = await putScheduleConnectionBindings(user.email, r.id, connections);
|
|
40231
|
-
return c.json({ ...
|
|
40373
|
+
return c.json({ ...createResponse, connections: bound });
|
|
40232
40374
|
} catch (err) {
|
|
40233
40375
|
const rollback = await memoryCall("deleteScheduledActionTool", { id: r.id }, key).catch(() => ({ ok: false }));
|
|
40234
40376
|
if (!rollback.ok) console.error("[schedule-actions] failed to compensate action after connection binding failure", r.id);
|
|
@@ -40266,6 +40408,16 @@ var init_server = __esm({
|
|
|
40266
40408
|
}
|
|
40267
40409
|
try {
|
|
40268
40410
|
const scheduleActionId = c.req.param("id");
|
|
40411
|
+
const { key, error } = await getOrCreateUserMemoryKey(user);
|
|
40412
|
+
if (!key) return c.json({ ok: false, error: error ?? "memory unavailable" }, 503);
|
|
40413
|
+
const schedules = await memoryCall("listScheduledActionsTool", {}, key);
|
|
40414
|
+
if (!schedules.ok || !Array.isArray(schedules.actions)) return c.json(schedules, 502);
|
|
40415
|
+
const schedule = schedules.actions.find((action) => action.id === scheduleActionId);
|
|
40416
|
+
if (!schedule) return c.json({ ok: false, error: "scheduled action not found" }, 404);
|
|
40417
|
+
if (schedule.executionMode === "connection_sync") {
|
|
40418
|
+
const policyError = connectionSyncSelectionError(connections);
|
|
40419
|
+
if (policyError) return c.json({ ok: false, error: policyError }, 400);
|
|
40420
|
+
}
|
|
40269
40421
|
const bindings = await putScheduleConnectionBindings(user.email, scheduleActionId, connections);
|
|
40270
40422
|
return c.json({ ok: true, connections: bindings });
|
|
40271
40423
|
} catch (err) {
|