seo 0.2.6 → 0.2.8
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/cli.js +2 -2
- package/dist/{dist-PRmi6cXV.js → dist-B8eKKp3B.js} +66 -66
- package/dist/dist-B8eKKp3B.js.map +1 -0
- package/dist/{dist-Xkhuyn70.js → dist-DkWLBABR.js} +1 -1
- package/dist/index.d.ts +41 -9
- package/dist/index.js +122 -39
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +122 -39
- package/dist/mcp.js.map +1 -1
- package/dist/{package-B9-D646K.js → package-BDez60C3.js} +2 -2
- package/dist/{package-B9-D646K.js.map → package-BDez60C3.js.map} +1 -1
- package/package.json +2 -3
- package/dist/dist-PRmi6cXV.js.map +0 -1
package/dist/mcp.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createRequire as __seoCreateRequire } from 'node:module'; const require = __seoCreateRequire(import.meta.url);
|
|
2
|
-
import { n as load, t as version } from "./package-
|
|
2
|
+
import { n as load, t as version } from "./package-BDez60C3.js";
|
|
3
3
|
import { Headers, fetch as fetch$1 } from "undici";
|
|
4
4
|
import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
5
5
|
import { arch, homedir, platform } from "node:os";
|
|
@@ -9,7 +9,7 @@ import lockfile from "proper-lockfile";
|
|
|
9
9
|
import { createHash, randomUUID, sign } from "node:crypto";
|
|
10
10
|
import "node:http";
|
|
11
11
|
import "open";
|
|
12
|
-
import
|
|
12
|
+
import Libsql from "libsql";
|
|
13
13
|
import { Readability } from "@mozilla/readability";
|
|
14
14
|
import Defuddle from "defuddle";
|
|
15
15
|
import { parseHTML } from "linkedom";
|
|
@@ -763,6 +763,52 @@ async function createGoogleAccessTokenClient() {
|
|
|
763
763
|
};
|
|
764
764
|
}
|
|
765
765
|
//#endregion
|
|
766
|
+
//#region packages/core/dist/storage/sqlite.js
|
|
767
|
+
function withoutDriverMetadata(row) {
|
|
768
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) return row;
|
|
769
|
+
const { _metadata: _driverMetadata, ...data } = row;
|
|
770
|
+
return data;
|
|
771
|
+
}
|
|
772
|
+
var Statement = class {
|
|
773
|
+
statement;
|
|
774
|
+
constructor(statement) {
|
|
775
|
+
this.statement = statement;
|
|
776
|
+
}
|
|
777
|
+
run(...params) {
|
|
778
|
+
return this.statement.run(...params);
|
|
779
|
+
}
|
|
780
|
+
get(...params) {
|
|
781
|
+
return withoutDriverMetadata(this.statement.get(...params));
|
|
782
|
+
}
|
|
783
|
+
all(...params) {
|
|
784
|
+
return this.statement.all(...params).map(withoutDriverMetadata);
|
|
785
|
+
}
|
|
786
|
+
};
|
|
787
|
+
var SqliteDatabase = class {
|
|
788
|
+
database;
|
|
789
|
+
constructor(filename) {
|
|
790
|
+
this.database = new Libsql(filename);
|
|
791
|
+
}
|
|
792
|
+
prepare(source) {
|
|
793
|
+
return new Statement(this.database.prepare(source));
|
|
794
|
+
}
|
|
795
|
+
transaction(fn) {
|
|
796
|
+
return this.database.transaction(fn);
|
|
797
|
+
}
|
|
798
|
+
exec(source) {
|
|
799
|
+
this.database.exec(source);
|
|
800
|
+
return this;
|
|
801
|
+
}
|
|
802
|
+
pragma(source) {
|
|
803
|
+
const result = this.database.pragma(source);
|
|
804
|
+
return Array.isArray(result) ? result.map(withoutDriverMetadata) : withoutDriverMetadata(result);
|
|
805
|
+
}
|
|
806
|
+
close() {
|
|
807
|
+
this.database.close();
|
|
808
|
+
return this;
|
|
809
|
+
}
|
|
810
|
+
};
|
|
811
|
+
//#endregion
|
|
766
812
|
//#region packages/core/dist/storage/database.js
|
|
767
813
|
const CREATE_SQL = `
|
|
768
814
|
CREATE TABLE IF NOT EXISTS sites (
|
|
@@ -1046,10 +1092,14 @@ function getDb() {
|
|
|
1046
1092
|
recursive: true,
|
|
1047
1093
|
mode: 448
|
|
1048
1094
|
});
|
|
1049
|
-
db = new
|
|
1095
|
+
db = new SqliteDatabase(path);
|
|
1050
1096
|
initDb(db);
|
|
1051
1097
|
return db;
|
|
1052
1098
|
}
|
|
1099
|
+
function checkDatabaseReadiness() {
|
|
1100
|
+
if (getDb().prepare("SELECT 1 AS ready").get()?.ready !== 1) throw new Error("The local SQLite database did not return a readiness row.");
|
|
1101
|
+
return { dbPath: getSeoCliPaths().cacheDbFile };
|
|
1102
|
+
}
|
|
1053
1103
|
function hashKey(parts) {
|
|
1054
1104
|
const json = JSON.stringify(parts);
|
|
1055
1105
|
return Buffer.from(json).toString("base64url");
|
|
@@ -6241,16 +6291,15 @@ async function inspectMarkdownPage(input) {
|
|
|
6241
6291
|
repeatedHashStable: null,
|
|
6242
6292
|
markdownCanonicalMatchesHtml: null
|
|
6243
6293
|
};
|
|
6244
|
-
|
|
6245
|
-
const explicitUrl = advertisedUrls[0];
|
|
6294
|
+
const explicitUrl = advertisedUrls.length === 1 ? advertisedUrls[0] : void 0;
|
|
6246
6295
|
const [explicit, negotiated, repeated] = await Promise.all([
|
|
6247
|
-
fetchRepresentation({
|
|
6296
|
+
explicitUrl ? fetchRepresentation({
|
|
6248
6297
|
url: explicitUrl,
|
|
6249
6298
|
accept: "text/markdown",
|
|
6250
6299
|
timeoutMs: input.timeoutMs,
|
|
6251
6300
|
fetch: input.fetch,
|
|
6252
6301
|
signal: input.signal
|
|
6253
|
-
}),
|
|
6302
|
+
}) : Promise.resolve(void 0),
|
|
6254
6303
|
fetchRepresentation({
|
|
6255
6304
|
url: input.page.finalUrl,
|
|
6256
6305
|
accept: "text/markdown",
|
|
@@ -6259,20 +6308,21 @@ async function inspectMarkdownPage(input) {
|
|
|
6259
6308
|
signal: input.signal
|
|
6260
6309
|
}),
|
|
6261
6310
|
fetchRepresentation({
|
|
6262
|
-
url: explicitUrl,
|
|
6311
|
+
url: explicitUrl ?? input.page.finalUrl,
|
|
6263
6312
|
accept: "text/markdown",
|
|
6264
6313
|
timeoutMs: input.timeoutMs,
|
|
6265
6314
|
fetch: input.fetch,
|
|
6266
6315
|
signal: input.signal
|
|
6267
6316
|
})
|
|
6268
6317
|
]);
|
|
6269
|
-
observation.explicit = explicit.observation;
|
|
6318
|
+
if (explicit) observation.explicit = explicit.observation;
|
|
6270
6319
|
observation.negotiated = negotiated.observation;
|
|
6271
6320
|
observation.repeated = repeated.observation;
|
|
6272
|
-
observation.explicitMatchesNegotiated = explicit
|
|
6273
|
-
|
|
6274
|
-
observation.
|
|
6275
|
-
|
|
6321
|
+
observation.explicitMatchesNegotiated = explicit?.observation.sha256 && negotiated.observation.sha256 ? explicit.observation.sha256 === negotiated.observation.sha256 : null;
|
|
6322
|
+
const primary = explicit ?? negotiated;
|
|
6323
|
+
observation.repeatedHashStable = primary.observation.sha256 && repeated.observation.sha256 ? primary.observation.sha256 === repeated.observation.sha256 : null;
|
|
6324
|
+
observation.markdownCanonicalMatchesHtml = sameDocument(primary.observation.canonicalUrl, input.page.finalUrl);
|
|
6325
|
+
if (primary.body) observation.quality = markdownQuality(primary.body, input.page);
|
|
6276
6326
|
return observation;
|
|
6277
6327
|
}
|
|
6278
6328
|
async function fetchText(input) {
|
|
@@ -6608,10 +6658,13 @@ async function collectAgentDiscovery(input) {
|
|
|
6608
6658
|
const wwwLocation = www.location ? new URL(www.location, wwwUrl).toString() : void 0;
|
|
6609
6659
|
const qZeroContentType = qZero.observation.contentType;
|
|
6610
6660
|
const advertisedPages = observations.filter((observation) => observation.htmlAlternateUnique).length;
|
|
6611
|
-
const evaluatedPages = observations.filter((observation) =>
|
|
6661
|
+
const evaluatedPages = observations.filter((observation) => {
|
|
6662
|
+
const representation = observation.explicit ?? observation.negotiated;
|
|
6663
|
+
return representation?.status !== void 0 && representation.status >= 200 && representation.status < 300 && /^\s*text\/markdown\b/iu.test(representation.contentType ?? "");
|
|
6664
|
+
}).length;
|
|
6612
6665
|
const warnings = [...pages.length !== input.pages.length ? [`Agent representations were evaluated for ${pages.length} successful HTML pages from ${input.pages.length} retained documents.`] : [], ...routeManifest.valid ? [] : ["No valid public agent route manifest was available for orphan checks."]].sort();
|
|
6613
6666
|
const htmlContentSignals = pages.map((page) => headerValue$1(page.responseHeaders, "content-signal")).filter((value) => Boolean(value));
|
|
6614
|
-
const markdownContentSignals = observations.map((observation) => observation.explicit?.contentSignal).filter((value) => Boolean(value));
|
|
6667
|
+
const markdownContentSignals = observations.map((observation) => observation.explicit?.contentSignal ?? observation.negotiated?.contentSignal).filter((value) => Boolean(value));
|
|
6615
6668
|
const contentSignalValues = [.../* @__PURE__ */ new Set([...htmlContentSignals, ...markdownContentSignals])].sort();
|
|
6616
6669
|
return {
|
|
6617
6670
|
profile: "content",
|
|
@@ -6694,7 +6747,11 @@ function section$1(id, title, checks) {
|
|
|
6694
6747
|
};
|
|
6695
6748
|
}
|
|
6696
6749
|
function failedMarkdownUrls(discovery) {
|
|
6697
|
-
return discovery.markdownAlternates.pages.filter((page) =>
|
|
6750
|
+
return discovery.markdownAlternates.pages.filter((page) => {
|
|
6751
|
+
const negotiatedOk = page.negotiated?.status === 200 && /^\s*text\/markdown\b/iu.test(page.negotiated.contentType ?? "") && page.negotiated.varyAccept;
|
|
6752
|
+
const explicitOk = !page.htmlAlternateUnique ? true : page.httpAlternateUrls.length === 1 && page.explicit?.status === 200 && /^\s*text\/markdown\b/iu.test(page.explicit.contentType ?? "") && page.explicitMatchesNegotiated === true && page.markdownCanonicalMatchesHtml === true;
|
|
6753
|
+
return !negotiatedOk || !explicitOk || page.repeatedHashStable !== true;
|
|
6754
|
+
}).map((page) => page.htmlUrl);
|
|
6698
6755
|
}
|
|
6699
6756
|
function qualityFailureUrls(discovery) {
|
|
6700
6757
|
return discovery.markdownAlternates.pages.filter((page) => {
|
|
@@ -6736,20 +6793,25 @@ function markdownChecks(discovery) {
|
|
|
6736
6793
|
const markdown = discovery.markdownAlternates;
|
|
6737
6794
|
const failedUrls = failedMarkdownUrls(discovery);
|
|
6738
6795
|
const qualityUrls = qualityFailureUrls(discovery);
|
|
6739
|
-
const
|
|
6740
|
-
const
|
|
6796
|
+
const negotiatedPages = markdown.pages.filter((page) => page.negotiated?.status === 200 && /^\s*text\/markdown\b/iu.test(page.negotiated.contentType ?? "")).length;
|
|
6797
|
+
const explicitPages = markdown.pages.filter((page) => page.htmlAlternateUnique).length;
|
|
6798
|
+
const coverageComplete = markdown.eligibleHtmlPages > 0 && markdown.evaluatedPages === markdown.eligibleHtmlPages;
|
|
6799
|
+
const negotiationComplete = markdown.eligibleHtmlPages > 0 && negotiatedPages === markdown.eligibleHtmlPages && markdown.pages.every((page) => page.negotiated?.varyAccept) && markdown.pages.every((page) => !page.htmlAlternateUnique || page.explicitMatchesNegotiated === true);
|
|
6741
6800
|
const stable = markdown.eligibleHtmlPages > 0 && markdown.stableResponses === markdown.eligibleHtmlPages;
|
|
6742
|
-
const tokenHeaders = markdown.pages.filter((page) =>
|
|
6801
|
+
const tokenHeaders = markdown.pages.filter((page) => {
|
|
6802
|
+
return (page.explicit ?? page.negotiated)?.markdownTokens !== void 0 && (!page.explicit || !page.negotiated || page.explicit.markdownTokens === page.negotiated.markdownTokens);
|
|
6803
|
+
}).length;
|
|
6743
6804
|
return [
|
|
6744
6805
|
check$1("representations", {
|
|
6745
6806
|
id: "markdown-coverage",
|
|
6746
6807
|
status: markdown.eligibleHtmlPages === 0 ? "unknown" : coverageComplete ? "pass" : "fail",
|
|
6747
|
-
title: coverageComplete ? "Every successful HTML page
|
|
6748
|
-
plainEnglish: `${markdown.
|
|
6749
|
-
action: coverageComplete ? "Keep
|
|
6808
|
+
title: coverageComplete ? "Every successful HTML page has a Markdown representation" : "Markdown representation coverage is incomplete",
|
|
6809
|
+
plainEnglish: `${markdown.evaluatedPages} of ${markdown.eligibleHtmlPages} successful HTML pages returned Markdown. ${explicitPages} advertised an explicit alternative and ${negotiatedPages} supported content negotiation.`,
|
|
6810
|
+
action: coverageComplete ? "Keep the negotiated or explicit Markdown response stable as routes change." : "Return text/markdown through content negotiation or advertise one working Markdown alternative for each public HTML page.",
|
|
6750
6811
|
evidence: {
|
|
6751
6812
|
eligibleHtmlPages: markdown.eligibleHtmlPages,
|
|
6752
6813
|
advertisedPages: markdown.advertisedPages,
|
|
6814
|
+
negotiatedPages,
|
|
6753
6815
|
evaluatedPages: markdown.evaluatedPages
|
|
6754
6816
|
},
|
|
6755
6817
|
urls: failedUrls.slice(0, 25)
|
|
@@ -6757,18 +6819,22 @@ function markdownChecks(discovery) {
|
|
|
6757
6819
|
check$1("representations", {
|
|
6758
6820
|
id: "markdown-token-estimates",
|
|
6759
6821
|
status: markdown.evaluatedPages === 0 ? "unknown" : tokenHeaders === markdown.evaluatedPages ? "pass" : "warning",
|
|
6760
|
-
title: tokenHeaders === markdown.evaluatedPages ? "Every Markdown response includes
|
|
6761
|
-
plainEnglish: `${tokenHeaders} of ${markdown.evaluatedPages} evaluated pages returned
|
|
6762
|
-
action: "
|
|
6763
|
-
urls: markdown.pages.filter((page) =>
|
|
6822
|
+
title: tokenHeaders === markdown.evaluatedPages ? "Every Markdown response includes a token estimate" : "Some Markdown responses are missing a stable token estimate",
|
|
6823
|
+
plainEnglish: `${tokenHeaders} of ${markdown.evaluatedPages} evaluated pages returned X-Markdown-Tokens. Paired explicit and negotiated responses agreed where both existed. The value is an estimate, not an exact model-specific token count.`,
|
|
6824
|
+
action: "Return a stable token estimate and keep it consistent when both explicit and negotiated responses exist.",
|
|
6825
|
+
urls: markdown.pages.filter((page) => {
|
|
6826
|
+
return (page.explicit ?? page.negotiated)?.markdownTokens === void 0 || page.explicit !== void 0 && page.negotiated !== void 0 && page.explicit.markdownTokens !== page.negotiated.markdownTokens;
|
|
6827
|
+
}).map((page) => page.htmlUrl).slice(0, 25)
|
|
6764
6828
|
}),
|
|
6765
6829
|
check$1("representations", {
|
|
6766
6830
|
id: "markdown-negotiation",
|
|
6767
|
-
status: markdown.eligibleHtmlPages === 0 ? "unknown" :
|
|
6768
|
-
title:
|
|
6769
|
-
plainEnglish: `${
|
|
6770
|
-
action: "
|
|
6831
|
+
status: markdown.eligibleHtmlPages === 0 ? "unknown" : negotiationComplete && discovery.contentNegotiation.qZeroHonoured ? "pass" : "fail",
|
|
6832
|
+
title: negotiationComplete && discovery.contentNegotiation.qZeroHonoured ? "Markdown content negotiation works across the site" : "Markdown content negotiation needs attention",
|
|
6833
|
+
plainEnglish: `${negotiatedPages} of ${markdown.eligibleHtmlPages} pages returned negotiated Markdown. ${markdown.exactByteMatches} of ${explicitPages} paired explicit responses matched byte for byte. A request that refuses Markdown ${discovery.contentNegotiation.qZeroHonoured ? "received HTML" : "did not produce confirmed HTML evidence"}.`,
|
|
6834
|
+
action: "Honour Accept q-values, send Vary: Accept, and keep paired explicit and negotiated responses identical when both exist.",
|
|
6771
6835
|
evidence: {
|
|
6836
|
+
negotiatedPages,
|
|
6837
|
+
explicitPages,
|
|
6772
6838
|
exactByteMatches: markdown.exactByteMatches,
|
|
6773
6839
|
qZero: discovery.contentNegotiation
|
|
6774
6840
|
},
|
|
@@ -6778,8 +6844,8 @@ function markdownChecks(discovery) {
|
|
|
6778
6844
|
id: "markdown-determinism",
|
|
6779
6845
|
status: markdown.eligibleHtmlPages === 0 ? "unknown" : stable ? "pass" : "fail",
|
|
6780
6846
|
title: stable ? "Repeated Markdown responses are stable" : "Repeated Markdown responses changed during the audit",
|
|
6781
|
-
plainEnglish: `${markdown.stableResponses} of ${markdown.eligibleHtmlPages} repeated
|
|
6782
|
-
action: "
|
|
6847
|
+
plainEnglish: `${markdown.stableResponses} of ${markdown.eligibleHtmlPages} repeated Markdown responses kept the same SHA-256 digest.`,
|
|
6848
|
+
action: "Remove timestamps, random output, or other runtime rewriting that changes the same Markdown response between requests.",
|
|
6783
6849
|
evidence: { stableResponses: markdown.stableResponses },
|
|
6784
6850
|
urls: failedUrls.slice(0, 25)
|
|
6785
6851
|
}),
|
|
@@ -6893,10 +6959,10 @@ function identityChecks(report) {
|
|
|
6893
6959
|
const officialProfiles = [...new Set(report.pages.flatMap((page) => [...page.schemaSameAs ?? [], ...page.socialProfileLinks ?? []]))];
|
|
6894
6960
|
return [check$1("identity", {
|
|
6895
6961
|
id: "identity-graph",
|
|
6896
|
-
status:
|
|
6897
|
-
title:
|
|
6898
|
-
plainEnglish: `
|
|
6899
|
-
action: "Connect truthful
|
|
6962
|
+
status: hasWebsite && hasCreator && pageTypes.length > 0 ? "pass" : "warning",
|
|
6963
|
+
title: hasWebsite && hasCreator && pageTypes.length > 0 ? "Structured identity covers the website, creator, and pages" : "The structured identity graph is missing a useful entity layer",
|
|
6964
|
+
plainEnglish: `Website identity: ${hasWebsite ? "present" : "missing"}. Creator or publisher identity: ${hasCreator ? "present" : "missing"}. Page-level types: ${pageTypes.length ? pageTypes.join(", ") : "missing"}. Software identity: ${hasSoftware ? "present" : "not observed and not required for a content site"}.`,
|
|
6965
|
+
action: "Connect truthful WebSite, creator or publisher, and page nodes. Add SoftwareApplication only when the site actually represents software. Use sameAs only for official profiles that identify the same entity.",
|
|
6900
6966
|
evidence: {
|
|
6901
6967
|
schemaTypes: [...types].sort(),
|
|
6902
6968
|
officialProfiles: officialProfiles.sort()
|
|
@@ -7384,7 +7450,7 @@ function aiReadiness(report) {
|
|
|
7384
7450
|
score: 0,
|
|
7385
7451
|
evaluated: Boolean(agentDiscovery),
|
|
7386
7452
|
title: agentDiscovery ? "Markdown alternatives were checked" : "Markdown alternatives were not evaluated",
|
|
7387
|
-
plainEnglish: agentDiscovery ? `${agentDiscovery.markdownAlternates.
|
|
7453
|
+
plainEnglish: agentDiscovery ? `${agentDiscovery.markdownAlternates.evaluatedPages} of ${agentDiscovery.markdownAlternates.eligibleHtmlPages} successful HTML pages returned Markdown through an explicit alternative or content negotiation. ${agentDiscovery.markdownAlternates.exactByteMatches} paired explicit responses matched content negotiation byte for byte.` : "This crawl does not include the focused representation checks, so it cannot say whether HTML pages publish stable Markdown alternatives.",
|
|
7388
7454
|
action: "Use the focused agent-readiness report when you need route coverage, content negotiation, byte stability, or extraction-quality evidence.",
|
|
7389
7455
|
evidence: agentDiscovery ? {
|
|
7390
7456
|
eligibleHtmlPages: agentDiscovery.markdownAlternates.eligibleHtmlPages,
|
|
@@ -25567,7 +25633,7 @@ async function updatePostmortemWorkflow(input, dependencies = {}) {
|
|
|
25567
25633
|
//#endregion
|
|
25568
25634
|
//#region packages/core/dist/doctor.js
|
|
25569
25635
|
const REQUIRED_SCOPES = ["https://www.googleapis.com/auth/webmasters.readonly", "https://www.googleapis.com/auth/analytics.readonly"];
|
|
25570
|
-
async function runDoctor() {
|
|
25636
|
+
async function runDoctor(dependencies = {}) {
|
|
25571
25637
|
const paths = getSeoCliPaths();
|
|
25572
25638
|
const config = readConfig();
|
|
25573
25639
|
const authMode = getAuthModeStatus();
|
|
@@ -25576,6 +25642,23 @@ async function runDoctor() {
|
|
|
25576
25642
|
const oauthClient = readOauthClient();
|
|
25577
25643
|
const tokenClientConfigured = tokens ? Boolean(getClientConfig(tokens.client_source)) : void 0;
|
|
25578
25644
|
const checks = [];
|
|
25645
|
+
try {
|
|
25646
|
+
const database = (dependencies.checkDatabase ?? checkDatabaseReadiness)();
|
|
25647
|
+
checks.push({
|
|
25648
|
+
id: "local-database",
|
|
25649
|
+
label: "Local database",
|
|
25650
|
+
status: "pass",
|
|
25651
|
+
detail: database.dbPath
|
|
25652
|
+
});
|
|
25653
|
+
} catch (error) {
|
|
25654
|
+
checks.push({
|
|
25655
|
+
id: "local-database",
|
|
25656
|
+
label: "Local database",
|
|
25657
|
+
status: "fail",
|
|
25658
|
+
detail: error instanceof Error ? error.message : "The local database could not be opened.",
|
|
25659
|
+
fix: "Upgrade or reinstall `seo`. If this still fails, report it at https://github.com/iannuttall/seo/issues."
|
|
25660
|
+
});
|
|
25661
|
+
}
|
|
25579
25662
|
checks.push({
|
|
25580
25663
|
id: "config-dir",
|
|
25581
25664
|
label: "Config directory",
|
|
@@ -27102,7 +27185,7 @@ function registerCrawlerTools(server) {
|
|
|
27102
27185
|
//#region packages/mcp/src/diagnosis-tools.ts
|
|
27103
27186
|
function registerDiagnosisTools(server, dependencies = {}) {
|
|
27104
27187
|
server.registerTool("seo_doctor", {
|
|
27105
|
-
description: "Check local auth, scopes, config, and defaults",
|
|
27188
|
+
description: "Check the local database, auth, scopes, config, and defaults",
|
|
27106
27189
|
inputSchema: {}
|
|
27107
27190
|
}, async () => {
|
|
27108
27191
|
try {
|