Google Search Console MCP Server
by ahonn
- src
import { google, searchconsole_v1, webmasters_v3 } from 'googleapis';
import { GoogleAuth } from 'google-auth-library';
type SearchanalyticsQueryRequest =
webmasters_v3.Params$Resource$Searchanalytics$Query['requestBody'];
type ListSitemapsRequest = webmasters_v3.Params$Resource$Sitemaps$List;
type GetSitemapRequest = webmasters_v3.Params$Resource$Sitemaps$Get;
type SubmitSitemapRequest = webmasters_v3.Params$Resource$Sitemaps$Submit;
type IndexInspectRequest =
searchconsole_v1.Params$Resource$Urlinspection$Index$Inspect['requestBody'];
export class SearchConsoleService {
private auth: GoogleAuth;
constructor(credentials: string) {
this.auth = new google.auth.GoogleAuth({
keyFile: credentials,
scopes: ['https://www.googleapis.com/auth/webmasters.readonly'],
});
}
private async getWebmasters() {
const authClient = await this.auth.getClient();
return google.webmasters({
version: 'v3',
auth: authClient,
} as webmasters_v3.Options);
}
private async getSearchConsole() {
const authClient = await this.auth.getClient();
return google.searchconsole({
version: 'v1',
auth: authClient,
} as searchconsole_v1.Options);
}
private normalizeUrl(url: string): string {
const parsedUrl = new URL(url);
if (parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:') {
return `sc-domain:${parsedUrl.hostname}`;
}
return `https://${url}`;
}
private async handlePermissionError<T>(
operation: () => Promise<T>,
fallbackOperation: () => Promise<T>,
): Promise<T> {
try {
return await operation();
} catch (err) {
if (err instanceof Error && err.message.toLowerCase().includes('permission')) {
return await fallbackOperation();
}
throw err;
}
}
async searchAnalytics(siteUrl: string, requestBody: SearchanalyticsQueryRequest) {
const webmasters = await this.getWebmasters();
return this.handlePermissionError(
() => webmasters.searchanalytics.query({ siteUrl, requestBody }),
() => webmasters.searchanalytics.query({ siteUrl: this.normalizeUrl(siteUrl), requestBody }),
);
}
async listSites() {
const webmasters = await this.getWebmasters();
return webmasters.sites.list();
}
async listSitemaps(requestBody: ListSitemapsRequest) {
const webmasters = await this.getWebmasters();
return this.handlePermissionError(
() => webmasters.sitemaps.list(requestBody),
() =>
webmasters.sitemaps.list({
...requestBody,
siteUrl: this.normalizeUrl(requestBody.siteUrl!),
}),
);
}
async getSitemap(requestBody: GetSitemapRequest) {
const webmasters = await this.getWebmasters();
return this.handlePermissionError(
() => webmasters.sitemaps.get(requestBody),
() =>
webmasters.sitemaps.get({
...requestBody,
siteUrl: this.normalizeUrl(requestBody.siteUrl!),
}),
);
}
async submitSitemap(requestBody: SubmitSitemapRequest) {
const webmasters = await this.getWebmasters();
return this.handlePermissionError(
() => webmasters.sitemaps.submit(requestBody),
() =>
webmasters.sitemaps.submit({
...requestBody,
siteUrl: this.normalizeUrl(requestBody.siteUrl!),
}),
);
}
async indexInspect(requestBody: IndexInspectRequest) {
const searchConsole = await this.getSearchConsole();
return searchConsole.urlInspection.index.inspect({ requestBody });
}
}