SEO Skill

Use SEO reports inside a TypeScript app

Install the seo npm package, call typed crawl and report functions, discover schemas, and handle structured SEO errors in Node 22 or newer.

The seo npm package is the CLI, MCP server, and TypeScript library. Install it inside a Node 22 or newer project when your own app needs to crawl a site, audit a page, or run one of the same structured reports used by agents.

npm install seo

The package is ESM-only and includes its TypeScript declarations. There are no separate @seo/core or @seo/mcp packages to install.

Run a report by its public id

Use the report catalog when you want the same ids, input validation, and underlying report evidence as the CLI and local MCP server. The outer transport shape differs: the CLI prints structuredContent in JSON mode, while the library and MCP return the complete ToolResult envelope.

import { describeReport, executeReport, listReports } from 'seo/mcp'

const reports = listReports('opportunities')
const description = describeReport('quick-wins')

const result = await executeReport('quick-wins', {
  site: 'sc-domain:example.com',
  days: 90,
})

console.log({ reports, description, result })

describeReport() returns the current JSON Schema plus the reason to use or avoid the report. Check it when parameters may change between package versions.

executeReport() rejects an unknown report id or invalid parameters. Once the input is valid, it returns the same ToolResult envelope as MCP. Check isError because provider and runtime failures are returned as structured results.

Use runReport() when ids or parameters come from a user or agent and your app wants discovery and validation errors returned in that envelope too.

import { runReport } from 'seo/mcp'

const result = await runReport('audit-page', {
  url: 'https://example.com/pricing',
})

if (result.isError) console.error(result.content)

Call typed core functions directly

The root export gives application code direct access to the crawler, page audit, analysis, storage, Google clients, and rendering functions.

Audit one live page:

import { auditPage } from 'seo'

const report = await auditPage({
  url: 'https://example.com/pricing',
})

console.log(report.page.title, report.issues)

Create a limited site crawl:

import { crawlSite } from 'seo'

const report = await crawlSite({
  url: 'https://example.com',
  maxPages: 100,
  maxDepth: 4,
})

console.log(report.summary, report.issueGroups)

Direct functions are useful when your application already knows which analysis it needs. The report catalog is a better fit when users or agents choose a report at runtime.

Use local Google access from an app

Google-backed functions use the same local OAuth token, project profiles, and cache as the CLI. Run the guided setup once on the machine that will execute the app:

seo start

Search Console and GA4 access stays read-only. A server, container, or CI runner needs its own service account credential. Set SEO_GOOGLE_SERVICE_ACCOUNT_JSON from the runtime secret store, or mount a key file and set SEO_GOOGLE_SERVICE_ACCOUNT_FILE. Do not copy a personal token file into a deployment image.

The Google data guide covers local OAuth, service accounts, property permissions, provider limits, and incomplete rows.

Embed the local MCP server

Use the MCP subpath when another Node process needs to construct the server itself:

import { createServer } from 'seo/mcp'

const server = createServer()

Most applications should use executeReport() directly. createServer() is for MCP hosts that will attach their own transport.

Keep output handling honest

Structured reports include source dates, thresholds, limits, warnings, and skipped work because SEO provider data is often partial. Keep those fields when you store or transform a result. A missing Search Console row is not zero, a limited crawl is not a complete site inventory, and timing around a change is not proof of causation.

The report catalog documents the evidence and limits for every public report id.