website: google search console mcp landing page (#237)
This commit is contained in:
parent
7a26be46cc
commit
c8fcdcda20
72
web/content/marketing/google-search-console-mcp.mdx
Normal file
72
web/content/marketing/google-search-console-mcp.mdx
Normal file
@ -0,0 +1,72 @@
|
||||
---
|
||||
title: Free Google Search Console MCP
|
||||
description: Connect Google Search Console to your AI agent for free. Read clicks, impressions, CTR, position, and indexing through the OpenSEO MCP, with no Google Cloud setup.
|
||||
---
|
||||
|
||||
Many Google Search Console (GSC) MCP servers are open source and free, but they take a lot of effort to set up. You need to create a Google Cloud project, enable an API, build an OAuth client, download a `credentials.json`, then keep a local server running. OpenSEO handles the Google connection for you. You sign up, connect your property, and start asking.
|
||||
|
||||
## Setup: Simple, zero-config
|
||||
|
||||
### With OpenSEO
|
||||
|
||||
1. Sign up for OpenSEO.
|
||||
2. Go through the onboarding.
|
||||
2. When prompted, click **Connect Search Console** and pick your property.
|
||||
3. Add the [OpenSEO MCP endpoint](/docs/mcp) to Claude, Cursor, or ChatGPT.
|
||||
|
||||
### The DIY way (every other GSC MCP)
|
||||
|
||||
1. Create a Google Cloud project
|
||||
2. Enable the Search Console API
|
||||
3. Configure the OAuth consent screen
|
||||
4. Create OAuth client credentials
|
||||
5. Download `credentials.json`
|
||||
6. Install and run a local MCP server
|
||||
|
||||
## Things to actually ask it
|
||||
|
||||
- "Which queries am I ranking on page two for that I'm close to pushing onto page one?"
|
||||
- "Show me pages where impressions went up but clicks stayed flat — probably a title or meta problem."
|
||||
- "Are any of my blog posts competing with each other for the same query?"
|
||||
- "Is `/pricing` indexed? If not, what's blocking it?"
|
||||
- "Which queries lost the most clicks over the last 28 days?"
|
||||
|
||||
## What your agent can read
|
||||
|
||||
Two read-only tools over the property you connect. Both pull Google's own numbers, and neither uses credits.
|
||||
|
||||
**Search performance.** Clicks, impressions, CTR, and average position for your site, sliced by query, page, country, device, and date. Pull up to 16 months of history in a single question.
|
||||
|
||||
**URL inspection.** Whether a page is indexed and, if not, why: coverage status, last crawl, the canonical Google chose versus the one you declared, plus mobile and rich-result checks. Up to 10 URLs at a time.
|
||||
|
||||
The agent can read and inspect. It cannot change anything in your account.
|
||||
|
||||
## Why it's free (and what isn't)
|
||||
|
||||
Google doesn't charge you to read your own Search Console data, so neither do we. The Search Console tools use zero credits. When you want more, like keyword research, rank tracking, or backlink data, those tools run through the same MCP and use credits. Connect Search Console first, and reach for the rest when you need it.
|
||||
|
||||
## OpenSEO vs. the alternatives
|
||||
|
||||
<ComparisonTable />
|
||||
|
||||
## FAQ
|
||||
|
||||
### Is it really free?
|
||||
|
||||
Yes, all you need is an OpenSEO account. OpenSEO's other features do use usage credits, but aren't necessary to use the Google Search Console MCP.
|
||||
|
||||
### Is it open source?
|
||||
|
||||
Yes. OpenSEO is open source, so you can self-host the whole thing, including the Search Console MCP. The one-click connection here uses OpenSEO's hosted Google app. If you self-host, you bring your own Google OAuth client, the same Cloud-console step the hosted version saves you. Hosted means no setup; self-hosted means full control.
|
||||
|
||||
### Is it read-only?
|
||||
|
||||
Yes. OpenSEO requests read-only access (`webmasters.readonly`). Your agent can read performance data and inspect URLs, but it can't change your account.
|
||||
|
||||
### Which AI clients work?
|
||||
|
||||
Any MCP client, including Claude Code, Cursor, Codex, and OpenClaw. Add the OpenSEO MCP endpoint and sign in.
|
||||
|
||||
### How fresh is the data?
|
||||
|
||||
It's Google's own data, so the most recent few days can be incomplete. History runs back 16 months, the same as the Search Console interface.
|
||||
@ -25,6 +25,7 @@ const STATIC_PATHS = [
|
||||
"/features",
|
||||
"/features/mcp",
|
||||
"/open-source-seo",
|
||||
"/google-search-console-mcp",
|
||||
...Object.values(FEATURE_PAGE_SLUGS).map((slug) => `/features/${slug}`),
|
||||
];
|
||||
|
||||
|
||||
196
web/src/components/comparison-table.tsx
Normal file
196
web/src/components/comparison-table.tsx
Normal file
@ -0,0 +1,196 @@
|
||||
type Tone = "positive" | "negative" | "neutral";
|
||||
|
||||
type Cell = {
|
||||
text: string;
|
||||
tone?: Tone;
|
||||
code?: boolean;
|
||||
};
|
||||
|
||||
type Column = {
|
||||
name: string;
|
||||
highlight?: boolean;
|
||||
};
|
||||
|
||||
const COLUMNS: Column[] = [
|
||||
{ name: "OpenSEO", highlight: true },
|
||||
{ name: "DIY open-source repos" },
|
||||
{ name: "Data-pipeline tools" },
|
||||
];
|
||||
|
||||
const ROWS: { label: string; cells: Cell[] }[] = [
|
||||
{
|
||||
label: "Setup",
|
||||
cells: [
|
||||
{ text: "Simple, guided onboarding", tone: "positive" },
|
||||
{ text: "~30 min in the Google Cloud console" },
|
||||
{ text: "Account + connector setup" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Google Cloud project",
|
||||
cells: [
|
||||
{ text: "Not needed", tone: "positive" },
|
||||
{ text: "Required", tone: "negative" },
|
||||
{ text: "Usually not needed", tone: "positive" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Price",
|
||||
cells: [
|
||||
{ text: "Free, no credits", tone: "positive" },
|
||||
{ text: "Free (your time + your own quota)" },
|
||||
{ text: "Paid or limited free tier", tone: "negative" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Read-only and safe",
|
||||
cells: [
|
||||
{ text: "webmasters.readonly", tone: "positive", code: true },
|
||||
{ text: "Depends on the scopes you grant" },
|
||||
{ text: "Varies" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Built for SEO",
|
||||
cells: [
|
||||
{
|
||||
text: "Also does keyword, rank, and backlink research",
|
||||
tone: "positive",
|
||||
},
|
||||
{ text: "Search Console only", tone: "negative" },
|
||||
{ text: "Reporting and analytics focus" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Self-host option",
|
||||
cells: [
|
||||
{ text: "Yes", tone: "positive" },
|
||||
{ text: "Yes", tone: "positive" },
|
||||
{ text: "No", tone: "negative" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
export function ComparisonTable() {
|
||||
return (
|
||||
<div className="not-prose my-8">
|
||||
<div className="overflow-x-auto rounded-xl border border-neutral-200">
|
||||
<table className="w-full min-w-[680px] border-collapse text-left">
|
||||
<thead>
|
||||
<tr>
|
||||
<td className="w-[22%] p-4" />
|
||||
{COLUMNS.map((col) => (
|
||||
<th
|
||||
key={col.name}
|
||||
scope="col"
|
||||
className={`p-4 align-bottom text-sm font-semibold ${
|
||||
col.highlight
|
||||
? "border-x border-neutral-200 bg-neutral-50 text-neutral-950"
|
||||
: "text-neutral-900"
|
||||
}`}
|
||||
>
|
||||
<span className="block">{col.name}</span>
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{ROWS.map((row) => (
|
||||
<tr key={row.label}>
|
||||
<th
|
||||
scope="row"
|
||||
className="border-t border-neutral-200 p-4 align-top text-sm font-medium text-neutral-500"
|
||||
>
|
||||
{row.label}
|
||||
</th>
|
||||
{row.cells.map((cell, i) => {
|
||||
const highlight = COLUMNS[i]?.highlight;
|
||||
return (
|
||||
<td
|
||||
key={COLUMNS[i]?.name ?? i}
|
||||
className={`border-t border-neutral-200 p-4 align-top text-sm ${
|
||||
highlight ? "border-x bg-neutral-50" : ""
|
||||
}`}
|
||||
>
|
||||
<CellContent cell={cell} highlight={highlight} />
|
||||
</td>
|
||||
);
|
||||
})}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function CellContent({ cell, highlight }: { cell: Cell; highlight?: boolean }) {
|
||||
const tone = cell.tone ?? "neutral";
|
||||
const textClass =
|
||||
tone === "negative"
|
||||
? "text-neutral-400"
|
||||
: highlight && tone === "positive"
|
||||
? "font-medium text-neutral-900"
|
||||
: "text-neutral-700";
|
||||
|
||||
return (
|
||||
<div className="flex items-start gap-2.5">
|
||||
<span
|
||||
className={`mt-0.5 flex h-4 w-4 shrink-0 items-center justify-center ${
|
||||
tone === "negative" ? "text-neutral-300" : "text-neutral-900"
|
||||
}`}
|
||||
>
|
||||
<ToneIcon tone={tone} />
|
||||
</span>
|
||||
<span className={`leading-snug ${textClass}`}>
|
||||
{cell.code ? (
|
||||
<code className="rounded bg-neutral-100 px-1.5 py-0.5 font-mono text-[0.85em] text-neutral-800">
|
||||
{cell.text}
|
||||
</code>
|
||||
) : (
|
||||
cell.text
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ToneIcon({ tone }: { tone: Tone }) {
|
||||
if (tone === "positive") {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
className="h-4 w-4"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
d="M13.5 4.5 6.5 11.5 3 8"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
if (tone === "negative") {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
className="h-4 w-4"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path
|
||||
d="M4 8h8"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
strokeLinecap="round"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -1,22 +1,57 @@
|
||||
import { Link } from "@tanstack/react-router";
|
||||
import { featureGroups } from "@/lib/feature-pages";
|
||||
|
||||
const featureLinks = featureGroups.flatMap((group) =>
|
||||
group.pages.map((page) => ({
|
||||
label: page.eyebrow,
|
||||
href: `/features/${page.slug}`,
|
||||
})),
|
||||
);
|
||||
|
||||
export function SiteFooter({ className }: { className?: string }) {
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="grid gap-6 sm:grid-cols-3">
|
||||
<Link to="/" className="text-sm font-semibold text-neutral-900">
|
||||
OpenSEO
|
||||
</Link>
|
||||
|
||||
<div className="mt-6 grid grid-cols-2 gap-8 md:grid-cols-4">
|
||||
<div>
|
||||
<p className="font-semibold text-neutral-900">Product</p>
|
||||
<p className="font-semibold text-neutral-900">Features</p>
|
||||
<div className="mt-2 flex flex-col gap-1.5">
|
||||
<Link to="/">OpenSEO</Link>
|
||||
<Link to="/features/mcp">MCP</Link>
|
||||
<Link to="/open-source-seo">Open Source SEO</Link>
|
||||
<Link to="/pricing">Pricing</Link>
|
||||
{featureLinks.map((link) => (
|
||||
<a key={link.href} href={link.href}>
|
||||
{link.label}
|
||||
</a>
|
||||
))}
|
||||
<Link to="/features">All features</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="font-semibold text-neutral-900">AI agents</p>
|
||||
<div className="mt-2 flex flex-col gap-1.5">
|
||||
<Link to="/features/mcp">OpenSEO MCP</Link>
|
||||
<Link to="/google-search-console-mcp">
|
||||
Google Search Console MCP
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="font-semibold text-neutral-900">Resources</p>
|
||||
<div className="mt-2 flex flex-col gap-1.5">
|
||||
<Link to="/open-source-seo">Why Open Source?</Link>
|
||||
<Link to="/guides">Guides</Link>
|
||||
<a href="/docs">Docs</a>
|
||||
<a href="/docs/skills">Skills</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="font-semibold text-neutral-900">Community</p>
|
||||
<p className="font-semibold text-neutral-900">Company</p>
|
||||
<div className="mt-2 flex flex-col gap-1.5">
|
||||
<Link to="/pricing">Pricing</Link>
|
||||
<a
|
||||
href="https://github.com/every-app/open-seo"
|
||||
target="_blank"
|
||||
@ -31,11 +66,6 @@ export function SiteFooter({ className }: { className?: string }) {
|
||||
>
|
||||
Discord
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<p className="font-semibold text-neutral-900">Legal</p>
|
||||
<div className="mt-2 flex flex-col gap-1.5">
|
||||
<Link to="/privacy">Privacy</Link>
|
||||
<Link to="/terms-and-conditions">Terms</Link>
|
||||
</div>
|
||||
|
||||
@ -22,6 +22,7 @@ import { Route as ApiSubscribeRouteImport } from './routes/api/subscribe'
|
||||
import { Route as ApiEventRouteImport } from './routes/api/event'
|
||||
import { Route as MarketingPricingRouteImport } from './routes/_marketing/pricing'
|
||||
import { Route as MarketingOpenSourceSeoRouteImport } from './routes/_marketing/open-source-seo'
|
||||
import { Route as MarketingGoogleSearchConsoleMcpRouteImport } from './routes/_marketing/google-search-console-mcp'
|
||||
import { Route as MarketingFeaturesIndexRouteImport } from './routes/_marketing/features/index'
|
||||
import { Route as MarketingFeaturesSiteAuditRouteImport } from './routes/_marketing/features/site-audit'
|
||||
import { Route as MarketingFeaturesSavedKeywordsRouteImport } from './routes/_marketing/features/saved-keywords'
|
||||
@ -97,6 +98,12 @@ const MarketingOpenSourceSeoRoute = MarketingOpenSourceSeoRouteImport.update({
|
||||
path: '/open-source-seo',
|
||||
getParentRoute: () => MarketingRoute,
|
||||
} as any)
|
||||
const MarketingGoogleSearchConsoleMcpRoute =
|
||||
MarketingGoogleSearchConsoleMcpRouteImport.update({
|
||||
id: '/google-search-console-mcp',
|
||||
path: '/google-search-console-mcp',
|
||||
getParentRoute: () => MarketingRoute,
|
||||
} as any)
|
||||
const MarketingFeaturesIndexRoute = MarketingFeaturesIndexRouteImport.update({
|
||||
id: '/features/',
|
||||
path: '/features/',
|
||||
@ -160,6 +167,7 @@ export interface FileRoutesByFullPath {
|
||||
'/': typeof MarketingIndexRoute
|
||||
'/privacy': typeof PrivacyRoute
|
||||
'/terms-and-conditions': typeof TermsAndConditionsRoute
|
||||
'/google-search-console-mcp': typeof MarketingGoogleSearchConsoleMcpRoute
|
||||
'/open-source-seo': typeof MarketingOpenSourceSeoRoute
|
||||
'/pricing': typeof MarketingPricingRoute
|
||||
'/api/event': typeof ApiEventRoute
|
||||
@ -183,6 +191,7 @@ export interface FileRoutesByFullPath {
|
||||
export interface FileRoutesByTo {
|
||||
'/privacy': typeof PrivacyRoute
|
||||
'/terms-and-conditions': typeof TermsAndConditionsRoute
|
||||
'/google-search-console-mcp': typeof MarketingGoogleSearchConsoleMcpRoute
|
||||
'/open-source-seo': typeof MarketingOpenSourceSeoRoute
|
||||
'/pricing': typeof MarketingPricingRoute
|
||||
'/api/event': typeof ApiEventRoute
|
||||
@ -209,6 +218,7 @@ export interface FileRoutesById {
|
||||
'/_marketing': typeof MarketingRouteWithChildren
|
||||
'/privacy': typeof PrivacyRoute
|
||||
'/terms-and-conditions': typeof TermsAndConditionsRoute
|
||||
'/_marketing/google-search-console-mcp': typeof MarketingGoogleSearchConsoleMcpRoute
|
||||
'/_marketing/open-source-seo': typeof MarketingOpenSourceSeoRoute
|
||||
'/_marketing/pricing': typeof MarketingPricingRoute
|
||||
'/api/event': typeof ApiEventRoute
|
||||
@ -236,6 +246,7 @@ export interface FileRouteTypes {
|
||||
| '/'
|
||||
| '/privacy'
|
||||
| '/terms-and-conditions'
|
||||
| '/google-search-console-mcp'
|
||||
| '/open-source-seo'
|
||||
| '/pricing'
|
||||
| '/api/event'
|
||||
@ -259,6 +270,7 @@ export interface FileRouteTypes {
|
||||
to:
|
||||
| '/privacy'
|
||||
| '/terms-and-conditions'
|
||||
| '/google-search-console-mcp'
|
||||
| '/open-source-seo'
|
||||
| '/pricing'
|
||||
| '/api/event'
|
||||
@ -284,6 +296,7 @@ export interface FileRouteTypes {
|
||||
| '/_marketing'
|
||||
| '/privacy'
|
||||
| '/terms-and-conditions'
|
||||
| '/_marketing/google-search-console-mcp'
|
||||
| '/_marketing/open-source-seo'
|
||||
| '/_marketing/pricing'
|
||||
| '/api/event'
|
||||
@ -412,6 +425,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof MarketingOpenSourceSeoRouteImport
|
||||
parentRoute: typeof MarketingRoute
|
||||
}
|
||||
'/_marketing/google-search-console-mcp': {
|
||||
id: '/_marketing/google-search-console-mcp'
|
||||
path: '/google-search-console-mcp'
|
||||
fullPath: '/google-search-console-mcp'
|
||||
preLoaderRoute: typeof MarketingGoogleSearchConsoleMcpRouteImport
|
||||
parentRoute: typeof MarketingRoute
|
||||
}
|
||||
'/_marketing/features/': {
|
||||
id: '/_marketing/features/'
|
||||
path: '/features'
|
||||
@ -486,6 +506,7 @@ declare module '@tanstack/react-router' {
|
||||
}
|
||||
|
||||
interface MarketingRouteChildren {
|
||||
MarketingGoogleSearchConsoleMcpRoute: typeof MarketingGoogleSearchConsoleMcpRoute
|
||||
MarketingOpenSourceSeoRoute: typeof MarketingOpenSourceSeoRoute
|
||||
MarketingPricingRoute: typeof MarketingPricingRoute
|
||||
MarketingIndexRoute: typeof MarketingIndexRoute
|
||||
@ -502,6 +523,7 @@ interface MarketingRouteChildren {
|
||||
}
|
||||
|
||||
const MarketingRouteChildren: MarketingRouteChildren = {
|
||||
MarketingGoogleSearchConsoleMcpRoute: MarketingGoogleSearchConsoleMcpRoute,
|
||||
MarketingOpenSourceSeoRoute: MarketingOpenSourceSeoRoute,
|
||||
MarketingPricingRoute: MarketingPricingRoute,
|
||||
MarketingIndexRoute: MarketingIndexRoute,
|
||||
|
||||
@ -17,7 +17,7 @@ const mobileNavItems = [
|
||||
label: "Resources",
|
||||
links: [
|
||||
{ label: "Guides", href: "/guides" },
|
||||
{ label: "Open Source SEO", href: "/open-source-seo" },
|
||||
{ label: "Why Open Source?", href: "/open-source-seo" },
|
||||
{ label: "MCP Setup", href: "/docs/mcp" },
|
||||
{ label: "Skills", href: "/docs/skills" },
|
||||
],
|
||||
@ -204,9 +204,9 @@ function ResourcesDropdown() {
|
||||
description: "Founder-focused SEO articles.",
|
||||
},
|
||||
{
|
||||
label: "Open Source SEO",
|
||||
label: "Why Open Source?",
|
||||
href: "/open-source-seo",
|
||||
description: "Why OpenSEO is open source.",
|
||||
description: "Open source puts the power in user's hands.",
|
||||
},
|
||||
{
|
||||
label: "MCP",
|
||||
@ -313,6 +313,17 @@ function FeatureDropdown() {
|
||||
Connect Claude, Codex, and agents.
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
href="/google-search-console-mcp"
|
||||
className="block rounded-md p-2 transition-colors hover:bg-neutral-50"
|
||||
>
|
||||
<span className="text-sm font-semibold text-neutral-900">
|
||||
Search Console MCP
|
||||
</span>
|
||||
<span className="mt-0.5 block text-xs leading-relaxed text-neutral-600">
|
||||
Free first-party GSC data for agents.
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
href="/features"
|
||||
className="block rounded-md border border-neutral-200 bg-neutral-50 px-2 py-1.5 text-sm font-medium text-neutral-900 transition-colors hover:border-neutral-900"
|
||||
|
||||
@ -3,7 +3,7 @@ import { featureGroups } from "@/lib/feature-pages";
|
||||
import { buildPageSeo } from "@/lib/seo";
|
||||
|
||||
const featuresDescription =
|
||||
"Explore OpenSEO's open-source SEO tools for AI-agent workflows, keyword research, rank tracking, backlinks, site audits, competitor analysis, and AI visibility.";
|
||||
"Explore OpenSEO's open-source SEO tools for AI-agent workflows, Google Search Console MCP, keyword research, rank tracking, backlinks, site audits, competitor analysis, and AI visibility.";
|
||||
|
||||
export const Route = createFileRoute("/_marketing/features/")({
|
||||
head: () =>
|
||||
@ -37,15 +37,18 @@ function FeaturesIndex() {
|
||||
AI agent workflows
|
||||
</h2>
|
||||
<p className="mt-1 text-sm leading-relaxed text-neutral-600">
|
||||
Let supported MCP clients research keywords, SERPs, domains, and
|
||||
backlinks through OpenSEO.
|
||||
Let supported MCP clients research keywords, SERPs, domains,
|
||||
backlinks, and first-party Search Console data through OpenSEO.
|
||||
</p>
|
||||
</div>
|
||||
<div className="mt-5 grid gap-4 md:grid-cols-2">
|
||||
<a
|
||||
href="/features/mcp"
|
||||
className="mt-5 block rounded-lg border border-neutral-200 bg-white p-5 transition-colors hover:border-neutral-900"
|
||||
className="block rounded-lg border border-neutral-200 bg-white p-5 transition-colors hover:border-neutral-900"
|
||||
>
|
||||
<p className="text-xs font-medium text-neutral-500">OpenSEO MCP</p>
|
||||
<p className="text-xs font-medium text-neutral-500">
|
||||
OpenSEO MCP
|
||||
</p>
|
||||
<h3 className="mt-2 text-lg font-semibold text-neutral-900">
|
||||
OpenSEO MCP for your AI agent
|
||||
</h3>
|
||||
@ -58,6 +61,25 @@ function FeaturesIndex() {
|
||||
Explore MCP <span aria-hidden="true">→</span>
|
||||
</p>
|
||||
</a>
|
||||
<a
|
||||
href="/google-search-console-mcp"
|
||||
className="block rounded-lg border border-neutral-200 bg-white p-5 transition-colors hover:border-neutral-900"
|
||||
>
|
||||
<p className="text-xs font-medium text-neutral-500">
|
||||
Search Console MCP
|
||||
</p>
|
||||
<h3 className="mt-2 text-lg font-semibold text-neutral-900">
|
||||
Free Google Search Console MCP
|
||||
</h3>
|
||||
<p className="mt-2 text-sm leading-relaxed text-neutral-600">
|
||||
Let your agent read clicks, impressions, CTR, position, and URL
|
||||
inspection data from your connected Search Console property.
|
||||
</p>
|
||||
<p className="mt-3 text-sm font-medium text-neutral-900">
|
||||
Explore GSC MCP <span aria-hidden="true">→</span>
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{featureGroups.map((group) => (
|
||||
|
||||
@ -2,7 +2,7 @@ import { createFileRoute } from "@tanstack/react-router";
|
||||
import { buildPageSeo } from "@/lib/seo";
|
||||
|
||||
const mcpDescription =
|
||||
"Connect OpenSEO MCP so compatible AI clients can call keyword, SERP, domain, backlink, saved keyword, and rank-tracking tools.";
|
||||
"Connect OpenSEO MCP so compatible AI clients can call keyword, SERP, domain, backlink, saved keyword, rank-tracking, and Google Search Console tools.";
|
||||
|
||||
const toolCategories = [
|
||||
{
|
||||
@ -39,13 +39,33 @@ const toolCategories = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Search Console",
|
||||
tools: [
|
||||
{
|
||||
title: "Get GSC performance",
|
||||
description:
|
||||
"Read clicks, impressions, CTR, and position from the connected property.",
|
||||
},
|
||||
{
|
||||
title: "Inspect URLs",
|
||||
description:
|
||||
"Check index coverage, crawl, canonical, mobile, and rich-result signals.",
|
||||
},
|
||||
{
|
||||
title: "Use first-party data",
|
||||
description:
|
||||
"Run read-only Search Console calls for free with no OpenSEO credits.",
|
||||
},
|
||||
],
|
||||
},
|
||||
] as const;
|
||||
|
||||
const workflows = [
|
||||
{
|
||||
title: "Research with live SEO data",
|
||||
description:
|
||||
"Give Codex, Claude, and other MCP clients access to OpenSEO keyword, SERP, domain, backlink, saved keyword, and rank-tracking data.",
|
||||
"Give Codex, Claude, and other MCP clients access to OpenSEO keyword, SERP, domain, backlink, saved keyword, rank-tracking, and Search Console data.",
|
||||
},
|
||||
{
|
||||
title: "Keep the agent focused",
|
||||
@ -80,7 +100,8 @@ function McpPage() {
|
||||
<p className="mt-4 text-neutral-700 leading-relaxed">
|
||||
Connect OpenSEO to your AI agent so it can research keywords, inspect
|
||||
SERPs, compare competitors, summarize backlink context, save keyword
|
||||
opportunities, and review rank-tracking data with live SEO context.
|
||||
opportunities, review rank-tracking data, and read first-party Search
|
||||
Console signals with live SEO context.
|
||||
</p>
|
||||
|
||||
<div className="mt-6 flex flex-col gap-3 sm:flex-row">
|
||||
@ -134,7 +155,7 @@ function McpPage() {
|
||||
|
||||
<section className="mt-12">
|
||||
<h2 className="text-xl font-semibold">Available tool groups</h2>
|
||||
<div className="mt-5 grid gap-x-8 gap-y-8 md:grid-cols-2">
|
||||
<div className="mt-5 grid gap-x-8 gap-y-8 md:grid-cols-3">
|
||||
{toolCategories.map((category) => (
|
||||
<div key={category.label}>
|
||||
<h3 className="text-xs font-semibold uppercase tracking-wide text-neutral-500">
|
||||
@ -157,6 +178,25 @@ function McpPage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mt-12 rounded-lg border border-neutral-200 bg-white p-5">
|
||||
<h2 className="text-lg font-semibold text-neutral-900">
|
||||
New: free Google Search Console MCP
|
||||
</h2>
|
||||
<p className="mt-2 text-sm leading-relaxed text-neutral-600">
|
||||
OpenSEO MCP can read Search Console performance and URL inspection
|
||||
data from a connected hosted project. These tools are read-only and do
|
||||
not use OpenSEO credits.
|
||||
</p>
|
||||
<div className="mt-4">
|
||||
<a
|
||||
href="/google-search-console-mcp"
|
||||
className="inline-flex h-9 items-center justify-center rounded-md border border-neutral-300 px-4 text-sm font-medium text-neutral-900 transition-colors hover:border-neutral-900"
|
||||
>
|
||||
Explore GSC MCP
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className="mt-12 rounded-lg border border-neutral-200 bg-neutral-50 p-5">
|
||||
<h2 className="text-lg font-semibold text-neutral-900">
|
||||
Setup lives in Docs
|
||||
|
||||
133
web/src/routes/_marketing/google-search-console-mcp.tsx
Normal file
133
web/src/routes/_marketing/google-search-console-mcp.tsx
Normal file
@ -0,0 +1,133 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||
import { DocsBody } from "fumadocs-ui/page";
|
||||
import GoogleSearchConsoleMcpContent, {
|
||||
frontmatter,
|
||||
} from "../../../content/marketing/google-search-console-mcp.mdx";
|
||||
import { ComparisonTable } from "@/components/comparison-table";
|
||||
import { buildPageSeo, SITE_URL, toCanonicalUrl } from "@/lib/seo";
|
||||
|
||||
const PATH = "/google-search-console-mcp";
|
||||
|
||||
const softwareApplicationLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
name: "OpenSEO Google Search Console MCP",
|
||||
applicationCategory: "BusinessApplication",
|
||||
operatingSystem: "Web",
|
||||
url: toCanonicalUrl(PATH),
|
||||
description: frontmatter.description,
|
||||
offers: {
|
||||
"@type": "Offer",
|
||||
price: "0",
|
||||
priceCurrency: "USD",
|
||||
},
|
||||
provider: {
|
||||
"@type": "Organization",
|
||||
name: "OpenSEO",
|
||||
url: SITE_URL,
|
||||
},
|
||||
};
|
||||
|
||||
export const Route = createFileRoute("/_marketing/google-search-console-mcp")({
|
||||
head: () =>
|
||||
buildPageSeo({
|
||||
title: "Free Google Search Console MCP",
|
||||
description: frontmatter.description,
|
||||
path: PATH,
|
||||
titleSuffix: "OpenSEO",
|
||||
ogType: "article",
|
||||
}),
|
||||
component: GoogleSearchConsoleMcpPage,
|
||||
});
|
||||
|
||||
function GoogleSearchConsoleMcpPage() {
|
||||
return (
|
||||
<article className="text-neutral-900">
|
||||
<header className="mb-10 border-b border-neutral-200 pb-8">
|
||||
<h1 className="text-3xl font-bold leading-tight tracking-tight text-neutral-950 md:text-4xl">
|
||||
{frontmatter.title}
|
||||
</h1>
|
||||
{frontmatter.description ? (
|
||||
<p className="mt-4 text-lg leading-8 text-neutral-700">
|
||||
{frontmatter.description}
|
||||
</p>
|
||||
) : null}
|
||||
<div className="mt-6 flex flex-col gap-3 sm:flex-row">
|
||||
<a
|
||||
href="https://app.openseo.so/sign-up"
|
||||
className="inline-flex h-10 items-center justify-center rounded-md bg-neutral-950 px-5 text-sm font-medium text-white transition-colors hover:bg-neutral-800"
|
||||
>
|
||||
Try it now
|
||||
<span className="ml-2" aria-hidden="true">
|
||||
→
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<DocsBody className="min-w-0 text-neutral-800 [&_a]:!text-neutral-950 [&_h2]:!text-neutral-950 [&_h2_a]:!no-underline [&_h3]:!text-neutral-950 [&_h3_a]:!no-underline [&_h4]:!text-neutral-950 [&_h4_a]:!no-underline [&_h5_a]:!no-underline [&_h6_a]:!no-underline [&_li]:!text-neutral-700 [&_li_a]:font-medium [&_li_a]:underline [&_li_a]:decoration-neutral-300 [&_li_a]:underline-offset-4 [&_li_a:hover]:!text-neutral-700 [&_p]:!text-neutral-700 [&_p_a]:font-medium [&_p_a]:underline [&_p_a]:decoration-neutral-300 [&_p_a]:underline-offset-4 [&_p_a:hover]:!text-neutral-700 [&_strong]:!text-neutral-950">
|
||||
<GoogleSearchConsoleMcpContent
|
||||
components={{ ...defaultMdxComponents, ComparisonTable }}
|
||||
/>
|
||||
</DocsBody>
|
||||
|
||||
<GoogleSearchConsoleMcpCta />
|
||||
|
||||
<script
|
||||
type="application/ld+json"
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: JSON.stringify(softwareApplicationLd),
|
||||
}}
|
||||
/>
|
||||
</article>
|
||||
);
|
||||
}
|
||||
|
||||
function GoogleSearchConsoleMcpCta() {
|
||||
return (
|
||||
<section className="mt-14 border-t border-neutral-200 pt-8">
|
||||
<p className="text-lg font-semibold text-neutral-950">
|
||||
Point your AI at your real search data
|
||||
</p>
|
||||
<p className="mt-2 text-sm leading-relaxed text-neutral-600">
|
||||
Free to connect. No Google Cloud project. Works with Claude, Cursor, and
|
||||
ChatGPT.
|
||||
</p>
|
||||
<div className="mt-5 flex flex-col gap-3 sm:flex-row">
|
||||
<a
|
||||
href="https://app.openseo.so/sign-up"
|
||||
className="inline-flex h-10 items-center justify-center rounded-md bg-neutral-950 px-4 text-sm font-medium text-white transition-colors hover:bg-neutral-800"
|
||||
>
|
||||
Try it now
|
||||
<span className="ml-2" aria-hidden="true">
|
||||
→
|
||||
</span>
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/every-app/open-seo"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex h-10 items-center justify-center gap-2 rounded-md border border-neutral-300 bg-white px-4 text-sm font-medium text-neutral-950 transition-colors hover:border-neutral-950"
|
||||
>
|
||||
<GitHubIcon />
|
||||
Star on GitHub
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function GitHubIcon() {
|
||||
return (
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
className="h-4 w-4"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M12 0C5.37 0 0 5.37 0 12c0 5.3 3.44 9.8 8.21 11.39.6.11.79-.26.79-.58v-2.23c-3.34.73-4.03-1.42-4.03-1.42-.55-1.39-1.33-1.76-1.33-1.76-1.09-.74.08-.73.08-.73 1.21.08 1.84 1.24 1.84 1.24 1.07 1.83 2.81 1.3 3.49.99.11-.77.42-1.3.76-1.6-2.66-.31-5.47-1.33-5.47-5.93 0-1.31.47-2.38 1.24-3.22-.12-.3-.54-1.52.12-3.18 0 0 1.01-.32 3.3 1.23.96-.27 1.98-.4 3-.4s2.05.14 3 .4c2.29-1.55 3.3-1.23 3.3-1.23.65 1.65.24 2.87.12 3.18.77.84 1.24 1.91 1.24 3.22 0 4.61-2.81 5.62-5.48 5.92.43.37.82 1.1.82 2.22v3.29c0 .32.19.69.8.58A12.01 12.01 0 0 0 24 12c0-6.63-5.37-12-12-12z" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user