mcp-scraper 0.30.0 → 0.32.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 +1 -1
- package/dist/bin/api-server.cjs +93 -41
- package/dist/bin/api-server.cjs.map +1 -1
- package/dist/bin/api-server.js +2 -2
- package/dist/bin/mcp-scraper-cli.cjs +4 -1
- package/dist/bin/mcp-scraper-cli.cjs.map +1 -1
- package/dist/bin/mcp-scraper-cli.js +3 -3
- 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 +38 -34
- package/dist/bin/mcp-stdio-server.cjs.map +1 -1
- package/dist/bin/mcp-stdio-server.js +3 -3
- package/dist/bin/paa-harvest.cjs +26 -4
- package/dist/bin/paa-harvest.cjs.map +1 -1
- package/dist/bin/paa-harvest.js +2 -2
- package/dist/{chunk-KAMKTSJQ.js → chunk-55M5CE5L.js} +2 -2
- package/dist/chunk-CPQF3PYW.js +7 -0
- package/dist/chunk-CPQF3PYW.js.map +1 -0
- package/dist/{chunk-ZQSHKWV4.js → chunk-PTHY7NYD.js} +4 -1
- package/dist/chunk-PTHY7NYD.js.map +1 -0
- package/dist/{chunk-YH5DRFWQ.js → chunk-RDCCU7CQ.js} +25 -6
- package/dist/chunk-RDCCU7CQ.js.map +1 -0
- package/dist/{chunk-T2CIPAOK.js → chunk-YOOEAXWP.js} +37 -36
- package/dist/chunk-YOOEAXWP.js.map +1 -0
- package/dist/index.cjs +26 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +2 -2
- package/dist/{server-PBPXND5G.js → server-OBOTNFD6.js} +40 -10
- package/dist/{server-PBPXND5G.js.map → server-OBOTNFD6.js.map} +1 -1
- package/dist/{worker-RYP5EOV5.js → worker-7DJYUACV.js} +3 -3
- package/docs/mcp-tool-manifest.generated.json +29 -29
- package/package.json +2 -2
- package/dist/chunk-T2CIPAOK.js.map +0 -1
- package/dist/chunk-WQUF7AH7.js +0 -7
- package/dist/chunk-WQUF7AH7.js.map +0 -1
- package/dist/chunk-YH5DRFWQ.js.map +0 -1
- package/dist/chunk-ZQSHKWV4.js.map +0 -1
- /package/dist/{chunk-KAMKTSJQ.js.map → chunk-55M5CE5L.js.map} +0 -0
- /package/dist/{worker-RYP5EOV5.js.map → worker-7DJYUACV.js.map} +0 -0
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.32.0`, SHA-256 `f31500fa60ffa96d2bea43feb4f5606a40fdc59b599dd51a11b8a54e5c9bce32`). 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
|
|
package/dist/bin/api-server.cjs
CHANGED
|
@@ -13834,6 +13834,15 @@ function positiveIntFromEnv(name, fallback) {
|
|
|
13834
13834
|
function proxyIdSuffix(proxyId) {
|
|
13835
13835
|
return proxyId ? proxyId.slice(-6) : null;
|
|
13836
13836
|
}
|
|
13837
|
+
function serpArrivalUrl(googleUrl) {
|
|
13838
|
+
const base = process.env.SERP_REDIRECT_BASE?.trim().replace(/\/+$/, "");
|
|
13839
|
+
if (!base) return googleUrl;
|
|
13840
|
+
return `${base}/g/${Buffer.from(googleUrl, "utf8").toString("base64url")}`;
|
|
13841
|
+
}
|
|
13842
|
+
function isUsCountry(country) {
|
|
13843
|
+
if (!country) return false;
|
|
13844
|
+
return /united states|u\.?s\.?a?\.?|^us$/i.test(country.trim());
|
|
13845
|
+
}
|
|
13837
13846
|
function errorText(err) {
|
|
13838
13847
|
return err instanceof Error ? err.message : String(err);
|
|
13839
13848
|
}
|
|
@@ -13988,7 +13997,7 @@ var init_BrowserDriver = __esm({
|
|
|
13988
13997
|
this.kernelProxyType = config.kernelProxyResolution?.proxyType ?? null;
|
|
13989
13998
|
let defaultProxyDisabled = null;
|
|
13990
13999
|
let defaultProxyDisableError = null;
|
|
13991
|
-
if (!config.kernelProxyId) {
|
|
14000
|
+
if (!config.kernelProxyId && !config.keepDefaultProxy) {
|
|
13992
14001
|
try {
|
|
13993
14002
|
await withTimeout2(
|
|
13994
14003
|
this.kernelClient.browsers.update(this.kernelSessionId, { disable_default_proxy: true }),
|
|
@@ -14038,9 +14047,15 @@ var init_BrowserDriver = __esm({
|
|
|
14038
14047
|
await this.installEsbuildHelperShims(this.context);
|
|
14039
14048
|
this.page = await this.context.newPage();
|
|
14040
14049
|
await this.page.setViewportSize(config.viewport);
|
|
14041
|
-
if (this.debugEnabled) {
|
|
14050
|
+
if (this.debugEnabled || config.requireUsEgress) {
|
|
14042
14051
|
this.debugSnapshot.networkLocation = await this.captureBrowserNetworkLocation();
|
|
14043
14052
|
}
|
|
14053
|
+
if (config.requireUsEgress) {
|
|
14054
|
+
const country = this.debugSnapshot.networkLocation?.country ?? null;
|
|
14055
|
+
if (!isUsCountry(country)) {
|
|
14056
|
+
throw new CaptchaError(`Non-US egress (${country ?? "unknown"}) \u2014 retrying with a fresh session`);
|
|
14057
|
+
}
|
|
14058
|
+
}
|
|
14044
14059
|
return;
|
|
14045
14060
|
}
|
|
14046
14061
|
const launchOpts = {
|
|
@@ -14180,6 +14195,7 @@ var init_BrowserDriver = __esm({
|
|
|
14180
14195
|
if (options?.num) params.set("num", String(options.num));
|
|
14181
14196
|
if (uule) params.set("uule", uule);
|
|
14182
14197
|
const url = "https://www.google.com/search?" + params.toString();
|
|
14198
|
+
const navUrl = serpArrivalUrl(url);
|
|
14183
14199
|
const navDebug = options?.debug ? {
|
|
14184
14200
|
requestedUrl: url,
|
|
14185
14201
|
finalUrl: null,
|
|
@@ -14192,7 +14208,7 @@ var init_BrowserDriver = __esm({
|
|
|
14192
14208
|
} : null;
|
|
14193
14209
|
if (navDebug) this.debugSnapshot.serpNavigation = navDebug;
|
|
14194
14210
|
try {
|
|
14195
|
-
await this.page.goto(
|
|
14211
|
+
await this.page.goto(navUrl, { waitUntil: "domcontentloaded", timeout: 45e3 });
|
|
14196
14212
|
} catch (err) {
|
|
14197
14213
|
await this.updateSerpNavigationDebug(navDebug, url, { hasPaa: null, captchaDetected: null });
|
|
14198
14214
|
const diag = await this.captureDiagnostics(url);
|
|
@@ -17339,6 +17355,9 @@ var init_schemas3 = __esm({
|
|
|
17339
17355
|
device: import_zod17.z.enum(["desktop", "mobile"]).default("desktop"),
|
|
17340
17356
|
proxyMode: import_zod17.z.enum(["location", "configured", "none"]).default(DEFAULT_PROXY_MODE),
|
|
17341
17357
|
proxyZip: import_zod17.z.string().regex(/^\d{5}$/).optional(),
|
|
17358
|
+
keepDefaultProxy: import_zod17.z.boolean().optional(),
|
|
17359
|
+
requireUsEgress: import_zod17.z.boolean().optional(),
|
|
17360
|
+
maxAttempts: import_zod17.z.number().int().min(1).max(12).optional(),
|
|
17342
17361
|
debug: import_zod17.z.boolean().default(false),
|
|
17343
17362
|
depth: import_zod17.z.number().int().min(1).max(30).default(3),
|
|
17344
17363
|
maxQuestions: import_zod17.z.number().int().min(1).max(1e3).default(100),
|
|
@@ -19235,6 +19254,12 @@ function buildGoogleLocalResultsUrl(input) {
|
|
|
19235
19254
|
if (input.location) params.set("uule", encodeUule(normalizeLocation(input.location)));
|
|
19236
19255
|
return `https://www.google.com/search?${params.toString()}`;
|
|
19237
19256
|
}
|
|
19257
|
+
function buildGoogleOrganicSearchUrl(input) {
|
|
19258
|
+
const query = [input.query, input.location].filter(Boolean).join(" ");
|
|
19259
|
+
const params = new URLSearchParams({ q: query, gl: input.gl, hl: input.hl, pws: "0" });
|
|
19260
|
+
if (input.location) params.set("uule", encodeUule(normalizeLocation(input.location)));
|
|
19261
|
+
return `https://www.google.com/search?${params.toString()}`;
|
|
19262
|
+
}
|
|
19238
19263
|
var LOCAL_RESULTS_PAGE_LIMIT, LOCAL_RESULTS_WAIT_MS, MapsSearchExtractor;
|
|
19239
19264
|
var init_MapsSearchExtractor = __esm({
|
|
19240
19265
|
"src/extractor/MapsSearchExtractor.ts"() {
|
|
@@ -19251,13 +19276,14 @@ var init_MapsSearchExtractor = __esm({
|
|
|
19251
19276
|
async extract(options) {
|
|
19252
19277
|
const startMs = Date.now();
|
|
19253
19278
|
const searchQuery = [options.query, options.location].filter(Boolean).join(" ");
|
|
19254
|
-
const searchUrl =
|
|
19279
|
+
const searchUrl = buildGoogleOrganicSearchUrl(options);
|
|
19255
19280
|
const config = {
|
|
19256
19281
|
headless: options.headless,
|
|
19257
19282
|
kernelApiKey: options.kernelApiKey,
|
|
19258
19283
|
kernelProxyId: options.kernelProxyId,
|
|
19259
19284
|
kernelProxyResolution: options.kernelProxyResolution,
|
|
19260
19285
|
proxyMode: options.proxyMode,
|
|
19286
|
+
keepDefaultProxy: options.proxyMode !== "location" && options.proxyMode !== "configured" && !options.kernelProxyId,
|
|
19261
19287
|
viewport: { width: 1280, height: 900 },
|
|
19262
19288
|
locale: `${options.hl}-${options.gl.toUpperCase()}`,
|
|
19263
19289
|
debug: options.debug
|
|
@@ -19268,6 +19294,10 @@ var init_MapsSearchExtractor = __esm({
|
|
|
19268
19294
|
await page.goto(searchUrl, { waitUntil: "domcontentloaded", timeout: 6e4 });
|
|
19269
19295
|
await page.waitForTimeout(LOCAL_RESULTS_WAIT_MS);
|
|
19270
19296
|
if (await this.detectBlock(page)) throw new CaptchaError(RECAPTCHA_INSTRUCTIONS);
|
|
19297
|
+
const reachedFinder = await this.clickIntoLocalFinder(page);
|
|
19298
|
+
if (!reachedFinder) throw new ExtractionError('Google "More businesses" control was not found on the organic results page');
|
|
19299
|
+
await page.waitForTimeout(LOCAL_RESULTS_WAIT_MS);
|
|
19300
|
+
if (await this.detectBlock(page)) throw new CaptchaError(RECAPTCHA_INSTRUCTIONS);
|
|
19271
19301
|
const results = await this.collectResults(page, options);
|
|
19272
19302
|
return {
|
|
19273
19303
|
query: options.query,
|
|
@@ -19284,6 +19314,17 @@ var init_MapsSearchExtractor = __esm({
|
|
|
19284
19314
|
await this.driver.close();
|
|
19285
19315
|
}
|
|
19286
19316
|
}
|
|
19317
|
+
async clickIntoLocalFinder(page) {
|
|
19318
|
+
const control = page.getByRole("link", { name: /more (businesses|places|results)/i }).or(page.getByRole("button", { name: /more (businesses|places|results)/i })).first();
|
|
19319
|
+
const visible = await control.isVisible({ timeout: 1e4 }).catch(() => false);
|
|
19320
|
+
if (!visible) return false;
|
|
19321
|
+
await control.click({ timeout: 1e4 }).catch(() => {
|
|
19322
|
+
});
|
|
19323
|
+
await page.waitForTimeout(5e3);
|
|
19324
|
+
return page.evaluate(
|
|
19325
|
+
() => /[?&]udm=1/.test(location.href) || document.querySelectorAll('a[href*="/maps/place/"]').length > 0
|
|
19326
|
+
);
|
|
19327
|
+
}
|
|
19287
19328
|
async detectBlock(page) {
|
|
19288
19329
|
return page.evaluate(() => {
|
|
19289
19330
|
const text2 = document.body.innerText.slice(0, 2e3);
|
|
@@ -28145,6 +28186,8 @@ var init_PAAExtractor = __esm({
|
|
|
28145
28186
|
kernelProxyId: options.kernelProxyId,
|
|
28146
28187
|
kernelProxyResolution: options.kernelProxyResolution,
|
|
28147
28188
|
proxyMode: options.proxyMode,
|
|
28189
|
+
keepDefaultProxy: options.keepDefaultProxy,
|
|
28190
|
+
requireUsEgress: options.requireUsEgress,
|
|
28148
28191
|
viewport: isMobile ? { width: 390, height: 844 } : { width: 1280, height: 800 },
|
|
28149
28192
|
locale: `${options.hl}-${options.gl.toUpperCase()}`,
|
|
28150
28193
|
userAgent: isMobile ? MOBILE_USER_AGENT2 : DESKTOP_USER_AGENT2,
|
|
@@ -28645,7 +28688,8 @@ async function harvest(rawOptions) {
|
|
|
28645
28688
|
};
|
|
28646
28689
|
const requestedDebug = typeof raw.debug === "boolean" ? raw.debug : false;
|
|
28647
28690
|
const needsLocationEvidence = proxyMode === "location" && Boolean(proxyOpts.location);
|
|
28648
|
-
const
|
|
28691
|
+
const requestedMaxAttempts = raw.maxAttempts;
|
|
28692
|
+
const maxAttempts = typeof requestedMaxAttempts === "number" && Number.isInteger(requestedMaxAttempts) && requestedMaxAttempts >= 1 ? requestedMaxAttempts : maxAttemptsForProxyMode(proxyMode) + 1;
|
|
28649
28693
|
const serializer = new OutputSerializer();
|
|
28650
28694
|
let lastError = null;
|
|
28651
28695
|
let effectiveProxyMode = proxyMode;
|
|
@@ -29723,7 +29767,7 @@ var PACKAGE_VERSION;
|
|
|
29723
29767
|
var init_version = __esm({
|
|
29724
29768
|
"src/version.ts"() {
|
|
29725
29769
|
"use strict";
|
|
29726
|
-
PACKAGE_VERSION = "0.
|
|
29770
|
+
PACKAGE_VERSION = "0.32.0";
|
|
29727
29771
|
}
|
|
29728
29772
|
});
|
|
29729
29773
|
|
|
@@ -29845,18 +29889,19 @@ Multi-step orchestrations \u2014 prefer these over hand-chaining primitives when
|
|
|
29845
29889
|
|
|
29846
29890
|
## Memory
|
|
29847
29891
|
mcp-scraper also exposes persistent per-user memory tools (notes, facts, vaults,
|
|
29848
|
-
scheduled actions, tables, channels) backed by memory.mcpscraper.dev. Every account starts with
|
|
29892
|
+
scheduled actions, tables, channels) backed by memory.mcpscraper.dev. Every account starts with 16
|
|
29849
29893
|
vaults \u2014 call **list-vaults** to see what exists before creating anything new. Pick the vault whose job
|
|
29850
29894
|
matches the content: **Ideas** (unvalidated concepts), **Knowledge** (distilled lessons/how-tos),
|
|
29851
|
-
**Library** (raw source material \u2014 articles, transcripts), **People** (one durable note per person
|
|
29852
|
-
**
|
|
29895
|
+
**Library** (raw source material \u2014 articles, transcripts), **People** (one durable note per real person),
|
|
29896
|
+
**Organizations** (one durable hub per company or organization \u2014 never a person),
|
|
29897
|
+
**Deals** (commercial opportunities tied to a known organization or person), **Communication** (individual
|
|
29853
29898
|
conversation records and drafts), **Calendar** (time-anchored entries), **Tasks** (independent Inbox action items
|
|
29854
29899
|
that may link to a known Project), **Projects** (only codebases, known client projects, personal projects, or ongoing siloed
|
|
29855
29900
|
workstreams), **Issues** (something broken),
|
|
29856
29901
|
**Improvement Log** (receipts of changes made and whether they worked), **Experiments** (hypothesis +
|
|
29857
|
-
measured result), **Sprint** (current cycle's scope), **
|
|
29902
|
+
measured result), **Sprint** (current cycle's scope), **Examples and Inspirations** (other people's work worth
|
|
29858
29903
|
studying), **Skills** (reusable skill packages; each requires \`scripts/\` and at least one of
|
|
29859
|
-
\`references/\` or \`templates/\`, and may use both).
|
|
29904
|
+
\`references/\` or \`templates/\`, and may use both). The former names Inspiration and Communications still resolve.
|
|
29860
29905
|
For a normal new narrative note, call **prepare-memory-write** first. It queries the live vault contract,
|
|
29861
29906
|
tag vocabulary, and natural neighbor vaults, and returns interlink candidates that must be read before
|
|
29862
29907
|
acceptance. Compose every returned template section, then call **memory-capture**, which validates the
|
|
@@ -29875,7 +29920,7 @@ compatibility value when the template asks for it); Tasks can be independent Inb
|
|
|
29875
29920
|
project name; and email drafts awaiting human review need \`direction:"draft"\` with
|
|
29876
29921
|
\`approval_state:"pending"\`. Link a known person, project, deal, or communication only when verified.
|
|
29877
29922
|
When the user asks to add Gmail or Google Calendar evidence from a connected account, first resolve the
|
|
29878
|
-
existing People hub. Persist Gmail as one linked **
|
|
29923
|
+
existing People hub. Persist Gmail as one linked **Communication** email and Calendar as one linked
|
|
29879
29924
|
**Calendar** event, each with the provider's stable reference and \`person_refs\`; do not create a person
|
|
29880
29925
|
from a subject line, infer attendees, or silently bulk-import a mailbox/calendar. If a relationship is requested but not clear, ask the user rather than inventing one. Overview is the review queue: editing leaves a draft pending, and
|
|
29881
29926
|
approval or denial records a state only\u2014it does not send email.
|
|
@@ -30354,9 +30399,9 @@ var init_mcp_tool_schemas = __esm({
|
|
|
30354
30399
|
gl: import_zod35.z.string().length(2).default("us").describe("Google country code inferred from location."),
|
|
30355
30400
|
hl: import_zod35.z.string().length(2).default("en").describe("Language inferred from user request."),
|
|
30356
30401
|
maxResults: import_zod35.z.number().int().min(1).max(50).default(10).describe("Number of candidates to return. Default 10, maximum 50."),
|
|
30357
|
-
includeServices: import_zod35.z.boolean().default(false).describe("Open each returned
|
|
30358
|
-
proxyMode: import_zod35.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Leave unset for the default
|
|
30359
|
-
proxyZip: import_zod35.z.string().regex(/^\d{5}$/).optional().describe("Optional US ZIP override when proxyMode is location."),
|
|
30402
|
+
includeServices: import_zod35.z.boolean().default(false).describe("Open each returned business profile to include its configured services and areas served when available. Adds a page visit per business; does not collect review cards."),
|
|
30403
|
+
proxyMode: import_zod35.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Leave unset for the default route (stealth browser on the managed ISP proxy, retried on a fresh session when Google blocks). Localization comes from the city in the query plus gl/hl. location forces an explicit residential proxy \u2014 not recommended for Google."),
|
|
30404
|
+
proxyZip: import_zod35.z.string().regex(/^\d{5}$/).optional().describe("Optional US ZIP override, only used when proxyMode is location."),
|
|
30360
30405
|
debug: import_zod35.z.boolean().default(false).describe("Include sanitized browser/proxy diagnostics.")
|
|
30361
30406
|
};
|
|
30362
30407
|
DirectoryWorkflowInputSchema = {
|
|
@@ -30370,7 +30415,7 @@ var init_mcp_tool_schemas = __esm({
|
|
|
30370
30415
|
includeZipGroups: import_zod35.z.boolean().default(true).describe("Attach ZIP groups from a configured US ZIPS CSV when available (MCP_SCRAPER_USZIPS_CSV_PATH or usZipsCsvPath)."),
|
|
30371
30416
|
usZipsCsvPath: import_zod35.z.string().optional().describe("Local/test-only path to a US ZIPS CSV (state_abbr, zipcode, county, city columns). Deployed APIs should use MCP_SCRAPER_USZIPS_CSV_PATH instead. For ZIP enrichment, set MCP_SCRAPER_USZIPS_CSV_PATH on the server, or pass this in local/test mode."),
|
|
30372
30417
|
saveCsv: import_zod35.z.boolean().default(true).describe("Save a directory-ready CSV of results to the MCP Scraper output directory and return its path."),
|
|
30373
|
-
proxyMode: import_zod35.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Proxy behavior per city search. Leave unset for the
|
|
30418
|
+
proxyMode: import_zod35.z.enum(["location", "configured", "none"]).default(DEFAULT_MAPS_PROXY_MODE).describe("Proxy behavior per city search. Leave unset for the default route (stealth browser on the managed ISP proxy, retried fresh on a Google block). location forces an explicit residential proxy \u2014 not recommended for Google."),
|
|
30374
30419
|
proxyZip: import_zod35.z.string().regex(/^\d{5}$/).optional().describe("Optional ZIP override for proxy targeting; normally omitted."),
|
|
30375
30420
|
debug: import_zod35.z.boolean().default(false).describe("Include sanitized browser/proxy diagnostics.")
|
|
30376
30421
|
};
|
|
@@ -32190,7 +32235,7 @@ function registerPaaExtractorMcpTools(server, executor, options = {}) {
|
|
|
32190
32235
|
}, async (input) => formatMapsPlaceIntel(await executor.mapsPlaceIntel(input), input));
|
|
32191
32236
|
server.registerTool("maps_search", {
|
|
32192
32237
|
title: "Google Maps Business Search",
|
|
32193
|
-
description: "Search Google local results for multiple businesses by category, niche, or local market \u2014 leads, prospects, competitors, or beyond the 3-pack.
|
|
32238
|
+
description: "Search Google local results for multiple businesses by category, niche, or local market \u2014 leads, prospects, competitors, or beyond the 3-pack. Reaches the local-results list from the organic page and paginates it, returning up to 50 candidates (default 10) with names, place URLs, CIDs, and ratings. Leave proxyMode unset. Set includeServices to also open each business profile for its services and areas served; review cards are never collected by this tool.",
|
|
32194
32239
|
inputSchema: MapsSearchInputSchema,
|
|
32195
32240
|
outputSchema: recordOutputSchema("maps_search", MapsSearchOutputSchema),
|
|
32196
32241
|
annotations: liveWebToolAnnotations("Google Maps Business Search")
|
|
@@ -34479,7 +34524,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
34479
34524
|
GetChatLinkSchema = {
|
|
34480
34525
|
id: "get-chat-link",
|
|
34481
34526
|
upstreamName: "getChatLinkTool",
|
|
34482
|
-
description: "Get your durable, bookmarkable link to the hosted
|
|
34527
|
+
description: "Get your durable, bookmarkable link to the hosted Inbox chat page \u2014 a login-free chat UI for every channel you're in. The embedded secret is shown only once, on first call; it cannot be re-shown, only revoked and reissued via revoke-chat-link. Anyone holding the link can post as you.",
|
|
34483
34528
|
input: {},
|
|
34484
34529
|
output: {
|
|
34485
34530
|
ok: import_zod37.z.boolean().describe("True on success; false on auth error."),
|
|
@@ -34498,7 +34543,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
34498
34543
|
GetVaultAppLinkSchema = {
|
|
34499
34544
|
id: "get-vault-app-link",
|
|
34500
34545
|
upstreamName: "getVaultAppLinkTool",
|
|
34501
|
-
description: "Get the durable, bookmarkable link to the mobile-first Vault App for People, Projects, and Tasks. The embedded secret is shown only once; revoke-vault-app-link then call this tool again to replace a link that was shared or leaked. This link is independent from
|
|
34546
|
+
description: "Get the durable, bookmarkable link to the mobile-first Vault App for People, Projects, and Tasks. The embedded secret is shown only once; revoke-vault-app-link then call this tool again to replace a link that was shared or leaked. This link is independent from the Inbox chat link. Anyone holding it can use the Vault App as this identity.",
|
|
34502
34547
|
input: {},
|
|
34503
34548
|
output: {
|
|
34504
34549
|
ok: import_zod37.z.boolean().describe("True when the request succeeded."),
|
|
@@ -34765,7 +34810,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
34765
34810
|
RevokeVaultAppLinkSchema = {
|
|
34766
34811
|
id: "revoke-vault-app-link",
|
|
34767
34812
|
upstreamName: "revokeVaultAppLinkTool",
|
|
34768
|
-
description: "Immediately revoke the current Vault App link without touching the separate
|
|
34813
|
+
description: "Immediately revoke the current Vault App link without touching the separate Inbox chat link. Call get-vault-app-link afterward to mint a replacement.",
|
|
34769
34814
|
input: {},
|
|
34770
34815
|
output: {
|
|
34771
34816
|
ok: import_zod37.z.boolean().describe("True when the request succeeded."),
|
|
@@ -34979,7 +35024,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
34979
35024
|
MemoryCaptureSchema = {
|
|
34980
35025
|
id: "memory-capture",
|
|
34981
35026
|
upstreamName: "memoryCaptureTool",
|
|
34982
|
-
description: "Strict normal-create path for durable memory. Before capture, list the complete tag vocabulary, call prepare-memory-write, run hybrid memory-search for related notes, and read the strongest link candidates. This tool refuses incomplete notes and invalid relationship-domain writes: projects need a project kind, tasks
|
|
35027
|
+
description: "Strict normal-create path for durable memory. Before capture, list the complete tag vocabulary, call prepare-memory-write, run hybrid memory-search for related notes, and read the strongest link candidates. This tool refuses incomplete notes and invalid relationship-domain writes: projects need a project kind, tasks may be independent Inbox todos but must use a matched project when linked, deals need a known party, and draft emails need a pending approval state. It writes through memory-put, registers canonical tags, and verifies persisted content and props. Reserve memory-put for low-level migrations or deliberate edits.",
|
|
34983
35028
|
input: {
|
|
34984
35029
|
vault: import_zod37.z.string(),
|
|
34985
35030
|
folder: import_zod37.z.string().optional(),
|
|
@@ -35037,7 +35082,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
35037
35082
|
PrepareMemoryWriteSchema = {
|
|
35038
35083
|
id: "prepare-memory-write",
|
|
35039
35084
|
upstreamName: "prepareMemoryWriteTool",
|
|
35040
|
-
description: "Mandatory planning pass for a normal new memory. First inspect the complete tag vocabulary with list-memory-tags; then this pass routes the note, returns the live template and natural vault relationships, resolves proposed tags, and shortlists interlinks. For People, Deals, Projects, Tasks, and
|
|
35085
|
+
description: "Mandatory planning pass for a normal new memory. First inspect the complete tag vocabulary with list-memory-tags; then this pass routes the note, returns the live template and natural vault relationships, resolves proposed tags, and shortlists interlinks. For People, Organizations, Deals, Projects, Tasks, and Communication, it also returns relationship and approval guidance: search existing records before linking, but do not invent a project or party. A Task can remain an independent Inbox todo. Use hybrid memory-search (3 focused queries, 50 fused candidates, bounded graph expansion, rerank to 30 by default) and read strong related notes before capture. This is an explicit AI workflow directive, not a claim of persisted call-order enforcement.",
|
|
35041
35086
|
input: {
|
|
35042
35087
|
title: import_zod37.z.string().min(1),
|
|
35043
35088
|
content: import_zod37.z.string().min(1),
|
|
@@ -35101,7 +35146,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
35101
35146
|
CreateChannelSchema = {
|
|
35102
35147
|
id: "create-channel",
|
|
35103
35148
|
upstreamName: "createChannelTool",
|
|
35104
|
-
description: "Create an
|
|
35149
|
+
description: "Create an Inbox channel \u2014 a vault for threaded messages, reactions, and mentions instead of ordinary notes. Starts private to you; optionally invite initial members in the same call, each still gated by the normal sender-approval trust check. Requires write scope.",
|
|
35105
35150
|
input: {
|
|
35106
35151
|
name: import_zod37.z.string().min(1).describe("Channel name. Must match ^[A-Za-z0-9 _-]{1,48}$."),
|
|
35107
35152
|
inviteMembers: import_zod37.z.array(
|
|
@@ -35184,7 +35229,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
35184
35229
|
ListChannelMessagesSchema = {
|
|
35185
35230
|
id: "list-channel-messages",
|
|
35186
35231
|
upstreamName: "listChannelMessagesTool",
|
|
35187
|
-
description: "Read an
|
|
35232
|
+
description: "Read an Inbox channel: top-level messages by default, or one thread's replies when parentMessageId is given. Every message returned is marked read for you, visible to other members via readBy. Requires read access on the channel.",
|
|
35188
35233
|
input: {
|
|
35189
35234
|
vault: import_zod37.z.string().min(1).describe("The channel (vault) to read."),
|
|
35190
35235
|
parentMessageId: import_zod37.z.string().optional().describe("If given, list this thread's replies instead of top-level channel messages.")
|
|
@@ -35219,7 +35264,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
35219
35264
|
MyMentionsSchema = {
|
|
35220
35265
|
id: "my-mentions",
|
|
35221
35266
|
upstreamName: "myMentionsTool",
|
|
35222
|
-
description: "List every place you're @mentioned across all
|
|
35267
|
+
description: "List every place you're @mentioned across all Inbox channels you are CURRENTLY a member of, newest first \u2014 mentions in channels you've since left do not appear.",
|
|
35223
35268
|
input: {
|
|
35224
35269
|
limit: import_zod37.z.number().int().min(1).max(100).optional().describe("Max mentions to return. Optional; default 25.")
|
|
35225
35270
|
},
|
|
@@ -35272,7 +35317,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
35272
35317
|
PostMessageSchema = {
|
|
35273
35318
|
id: "post-message",
|
|
35274
35319
|
upstreamName: "postMessageTool",
|
|
35275
|
-
description: "Post a top-level message to an
|
|
35320
|
+
description: "Post a top-level message to an Inbox channel. @mentioning a member's email surfaces it in their my-mentions inbox; attachNote auto-shares one of your notes with every current channel member. Requires write access on the channel.",
|
|
35276
35321
|
input: {
|
|
35277
35322
|
vault: import_zod37.z.string().min(1).describe("The channel (vault) to post to."),
|
|
35278
35323
|
content: import_zod37.z.string().min(1).describe("The message text."),
|
|
@@ -35345,7 +35390,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
35345
35390
|
ReplyMessageSchema = {
|
|
35346
35391
|
id: "reply-message",
|
|
35347
35392
|
upstreamName: "replyMessageTool",
|
|
35348
|
-
description: "Reply inside a top-level message's thread in an
|
|
35393
|
+
description: "Reply inside a top-level message's thread in an Inbox channel \u2014 one level of nesting only, so always reply on the top-level parentMessageId. @mentions and attachNote behave as in post-message. Requires write access on the channel.",
|
|
35349
35394
|
input: {
|
|
35350
35395
|
vault: import_zod37.z.string().min(1).describe("The channel (vault) the parent message is in."),
|
|
35351
35396
|
parentMessageId: import_zod37.z.string().min(1).describe("The top-level message to reply under (messageId from post-message or list-channel-messages)."),
|
|
@@ -35744,10 +35789,10 @@ var init_memory_tool_schemas = __esm({
|
|
|
35744
35789
|
PutSchema = {
|
|
35745
35790
|
id: "memory-put",
|
|
35746
35791
|
upstreamName: "putTool",
|
|
35747
|
-
description: "Create or deliberately edit one note at a path in a memory vault; content is persisted and indexed for search. For normal new People, Deals, Projects, Tasks, or
|
|
35792
|
+
description: "Create or deliberately edit one note at a path in a memory vault; content is persisted and indexed for search. For normal new People, Organizations, Deals, Projects, Tasks, or Communication records, use prepare-memory-write then memory-capture: People must be real people, Organizations must be real organizations, Deals need a known party, Projects need a supported kind, Tasks can be independent Inbox todos or use a verified Project when linked, and draft emails need pending approval. For row-shaped datasets you'll filter/sort by exact value, use table-create/table-insert-rows/table-query instead. Ordinary vaults are indexed and shareable \u2014 never store real secrets there; use a secure vault (create-secure-vault) instead, which is never indexed or shareable and is encrypted at rest. Requires write scope.",
|
|
35748
35793
|
input: {
|
|
35749
35794
|
vault: import_zod37.z.string().optional().describe(
|
|
35750
|
-
"Vault to write to. Optional; defaults to the session active vault, then the first vault the caller is entitled to. On a default-provisioned account, pick the vault whose job matches the content (see the server instructions for the full
|
|
35795
|
+
"Vault to write to. Optional; defaults to the session active vault, then the first vault the caller is entitled to. On a default-provisioned account, pick the vault whose job matches the content (see the server instructions for the full 16-vault guide) rather than defaulting blindly \u2014 e.g. a lesson learned goes in Knowledge, the raw source it came from goes in Library, a broken feature goes in Issues, a named real-world initiative goes in Projects. Do not use this low-level tool to create ordinary People, Organizations, Deals, Projects, Tasks, or Communication records: first use prepare-memory-write then memory-capture so relationships and approval state are validated."
|
|
35751
35796
|
),
|
|
35752
35797
|
path: import_zod37.z.string().optional().describe("Vault-relative note path to create or overwrite, e.g. projects/q3-plan. Writing an existing path replaces it. Required unless shareId is given."),
|
|
35753
35798
|
shareId: import_zod37.z.string().optional().describe("Edit a note someone individually shared with you and you accepted (accept-share), by its shareId, instead of vault+path. Requires the share to grant edit permission, and baseRevision is mandatory (get the current revision first) since you are editing alongside the owner and possibly others."),
|
|
@@ -35944,12 +35989,12 @@ var init_memory_tool_schemas = __esm({
|
|
|
35944
35989
|
CreateScheduledActionSchema = {
|
|
35945
35990
|
id: "create-scheduled-action",
|
|
35946
35991
|
upstreamName: "createScheduledActionTool",
|
|
35947
|
-
description: "Create a Credit-metered scheduled action for an active MCP Scraper Starter plan or higher, in agent mode (default) or connection_sync mode. Each execution has a 75-Credit base charge; agent model usage is added at 1.5 times OpenRouter's actual reported cost. Agent mode follows the description and writes 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.
|
|
35992
|
+
description: "Create a Credit-metered scheduled action for an active MCP Scraper Starter plan or higher, in agent mode (default) or connection_sync mode. Each execution has a 75-Credit base charge; agent model usage is added at 1.5 times OpenRouter's actual reported cost. Agent mode follows the description and writes 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 write access to the target vault.",
|
|
35948
35993
|
input: {
|
|
35949
35994
|
description: import_zod37.z.string().min(1).describe("Free-text description of what this action should do each time it runs."),
|
|
35950
35995
|
vault: import_zod37.z.string().min(1).describe("The vault this action writes its results into. You must already have write access to it."),
|
|
35951
35996
|
cadence: import_zod37.z.enum(["once", "daily", "weekly", "monthly"]).describe('How often this action runs. "once" fires a single time and then completes.'),
|
|
35952
|
-
executionMode: import_zod37.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
|
|
35997
|
+
executionMode: import_zod37.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.`),
|
|
35953
35998
|
timeOfDay: import_zod37.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)."),
|
|
35954
35999
|
timezone: import_zod37.z.string().optional().describe(`IANA timezone name, e.g. "America/Denver". Only meaningful together with timeOfDay or deployDate. Omit to use the account's default timezone (set via set-schedule-defaults), falling back to UTC.`),
|
|
35955
36000
|
deployDate: import_zod37.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.')
|
|
@@ -36534,9 +36579,9 @@ var init_memory_tool_schemas = __esm({
|
|
|
36534
36579
|
GetVaultContractSchema = {
|
|
36535
36580
|
id: "get-vault-contract",
|
|
36536
36581
|
upstreamName: "getVaultContractTool",
|
|
36537
|
-
description: "Read the machine-enforced purpose, template, statuses, types, natural neighbor vaults, and typed relationship guidance for one of the
|
|
36582
|
+
description: "Read the machine-enforced purpose, template, statuses, types, required and recommended props, natural neighbor vaults, and typed relationship guidance for one of the 16 governed Obsidian-style vaults. Call before composing a note when the correct shape is uncertain.",
|
|
36538
36583
|
input: {
|
|
36539
|
-
vault: import_zod37.z.string().describe("One governed vault: Ideas,
|
|
36584
|
+
vault: import_zod37.z.string().describe("One governed vault: Ideas, Examples and Inspirations, Knowledge, Library, People, Organizations, Deals, Communication, Calendar, Tasks, Projects, Issues, Improvement Log, Experiments, Sprint, or Skills. Former names Inspiration and Communications still resolve.")
|
|
36540
36585
|
},
|
|
36541
36586
|
output: {
|
|
36542
36587
|
ok: import_zod37.z.boolean(),
|
|
@@ -36590,7 +36635,7 @@ var init_memory_tool_schemas = __esm({
|
|
|
36590
36635
|
sharedBy: import_zod37.z.string().optional().describe('Identity that shared the vault with the caller. Present only when role is "shared".'),
|
|
36591
36636
|
notes: import_zod37.z.number().describe("Number of notes currently stored in the vault."),
|
|
36592
36637
|
bytes: import_zod37.z.number().describe("Total stored size of the vault content in bytes (octet_length sum)."),
|
|
36593
|
-
kind: import_zod37.z.enum(["notes", "channel", "secure"]).describe('"channel" for an
|
|
36638
|
+
kind: import_zod37.z.enum(["notes", "channel", "secure"]).describe('"channel" for an Inbox channel (created via create-channel); "secure" for a private, encrypted, unshareable, unindexed vault (created via create-secure-vault) \u2014 safe to store credentials there; "notes" for an ordinary vault.')
|
|
36594
36639
|
})
|
|
36595
36640
|
).optional().describe("Every vault visible in the active account, with role, addressable handle, and live storage usage. Present when ok is true."),
|
|
36596
36641
|
error: import_zod37.z.string().optional().describe("Human-readable failure reason when ok is false.")
|
|
@@ -36606,17 +36651,17 @@ var init_memory_tool_schemas = __esm({
|
|
|
36606
36651
|
ProvisionDefaultsSchema = {
|
|
36607
36652
|
id: "provision-defaults",
|
|
36608
36653
|
upstreamName: "provisionDefaultsTool",
|
|
36609
|
-
description: "Provision the standard
|
|
36654
|
+
description: "Provision the standard 16-vault memory structure (Ideas, Examples and Inspirations, Knowledge, Library, People, Organizations, Deals, Communication, Calendar, Tasks, Projects, Issues, Improvement Log, Experiments, Sprint, Skills) for an identity. Idempotent \u2014 existing records are untouched and existing vault contracts are refreshed. Optionally issues a fresh API key entitled to all 16. Requires admin scope.",
|
|
36610
36655
|
input: {
|
|
36611
|
-
granteeIdentity: import_zod37.z.string().min(1).describe("Identity that should OWN the
|
|
36612
|
-
issueKey: import_zod37.z.boolean().optional().describe("When true, also issue a new API key for the identity entitled to all
|
|
36656
|
+
granteeIdentity: import_zod37.z.string().min(1).describe("Identity that should OWN the 16 default vaults (e.g. an email or user id)."),
|
|
36657
|
+
issueKey: import_zod37.z.boolean().optional().describe("When true, also issue a new API key for the identity entitled to all 16 vaults and return its secret once. Default false."),
|
|
36613
36658
|
plan: import_zod37.z.enum(["free", "pro", "team", "enterprise"]).optional().describe("Subscription plan carried by the issued key. Optional; defaults to free. Only used when issueKey is true.")
|
|
36614
36659
|
},
|
|
36615
36660
|
output: {
|
|
36616
36661
|
ok: import_zod37.z.boolean().describe("True when provisioning succeeded; false on auth/scope error."),
|
|
36617
36662
|
identity: import_zod37.z.string().optional().describe("Identity the vaults were provisioned for."),
|
|
36618
|
-
created: import_zod37.z.array(import_zod37.z.string()).optional().describe("Vault names newly created on this call (empty when all
|
|
36619
|
-
vaults: import_zod37.z.array(import_zod37.z.string()).optional().describe("All
|
|
36663
|
+
created: import_zod37.z.array(import_zod37.z.string()).optional().describe("Vault names newly created on this call (empty when all 16 already existed)."),
|
|
36664
|
+
vaults: import_zod37.z.array(import_zod37.z.string()).optional().describe("All 16 default vault names the identity now owns."),
|
|
36620
36665
|
keyId: import_zod37.z.string().optional().describe("Stable id of the issued key. Present only when issueKey was true."),
|
|
36621
36666
|
secret: import_zod37.z.string().optional().describe("The issued key secret \u2014 RETURNED ONCE. Present only when issueKey was true."),
|
|
36622
36667
|
plan: import_zod37.z.string().optional().describe("Plan assigned to the issued key. Present only when issueKey was true."),
|
|
@@ -41274,6 +41319,7 @@ function normalizeRelationshipProps(vault, props) {
|
|
|
41274
41319
|
}
|
|
41275
41320
|
function defaultType(vault) {
|
|
41276
41321
|
if (vault === "People" || vault === "Communications") return "unclassified";
|
|
41322
|
+
if (vault === "Organizations") return "organization";
|
|
41277
41323
|
if (vault === "Deals") return "deal";
|
|
41278
41324
|
if (vault === "Projects") return "project";
|
|
41279
41325
|
if (vault === "Tasks") return "task";
|
|
@@ -41281,7 +41327,7 @@ function defaultType(vault) {
|
|
|
41281
41327
|
return "unclassified";
|
|
41282
41328
|
}
|
|
41283
41329
|
function defaultStatus(vault) {
|
|
41284
|
-
if (vault === "People") return "active";
|
|
41330
|
+
if (vault === "People" || vault === "Organizations") return "active";
|
|
41285
41331
|
if (vault === "Deals") return "lead";
|
|
41286
41332
|
if (vault === "Projects") return "active";
|
|
41287
41333
|
if (vault === "Tasks") return "to_do";
|
|
@@ -41294,6 +41340,12 @@ function nonEmptyStrings(value) {
|
|
|
41294
41340
|
function validateNewRecord(vault, props) {
|
|
41295
41341
|
const type = typeof props.type === "string" ? props.type : "";
|
|
41296
41342
|
if (vault === "People" && !["person", "organization"].includes(type)) return "People records must be a person or organization";
|
|
41343
|
+
if (vault === "Organizations") {
|
|
41344
|
+
if (type !== "organization") return "Organizations records must have type organization";
|
|
41345
|
+
if (typeof props.organization_name !== "string" || !props.organization_name.trim()) {
|
|
41346
|
+
return "Organizations require organization_name";
|
|
41347
|
+
}
|
|
41348
|
+
}
|
|
41297
41349
|
if (vault === "Deals") {
|
|
41298
41350
|
if (type !== "deal") return "Deals records must have type deal";
|
|
41299
41351
|
if (typeof props.organization_ref !== "string" && nonEmptyStrings(props.person_refs).length === 0) {
|
|
@@ -41369,7 +41421,7 @@ var init_vault_routes = __esm({
|
|
|
41369
41421
|
"use strict";
|
|
41370
41422
|
import_hono22 = require("hono");
|
|
41371
41423
|
init_memory();
|
|
41372
|
-
VAULTS = ["People", "Deals", "Projects", "Tasks", "Communications", "Calendar"];
|
|
41424
|
+
VAULTS = ["People", "Organizations", "Deals", "Projects", "Tasks", "Communications", "Calendar"];
|
|
41373
41425
|
PROJECT_TYPES = ["codebase", "personal", "work", "client"];
|
|
41374
41426
|
PROJECT_KIND_BY_TYPE = {
|
|
41375
41427
|
codebase: "codebase",
|