# How to Run OpenSEO on a Specific Website: MCP, CLI, and Web UI Methods

> Learn how to run OpenSEO on any website using MCP, CLI, or Web UI. Start your site audit today with these simple methods.

- Repository: [Every App/open-seo](https://github.com/every-app/open-seo)
- Tags: how-to-guide
- Published: 2026-08-06

---

**You can run an OpenSEO site audit on any publicly accessible website via the MCP API endpoint `run_site_audit`, the npm CLI command `npm run audit -- <url>`, or the web UI, all of which invoke `AuditService.startAudit` in [`src/serverFunctions/audit.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/audit.ts) to trigger a Cloudflare Workers background workflow.**

OpenSEO is an open-source SEO auditing platform built for Cloudflare Workers. To analyze a specific domain, you initiate a **site audit** that crawls the target, identifies technical SEO issues like broken links and duplicate titles, and returns a prioritized remediation report. This guide explains the three entry points for running audits in the `every-app/open-seo` repository and the underlying workflow architecture.

## Prerequisites: Self-Hosting Setup

Before running audits locally, you must complete the self-hosting configuration described in [`docs/SELF_HOSTING_DOCKER.md`](https://github.com/every-app/open-seo/blob/main/docs/SELF_HOSTING_DOCKER.md). This setup provisions the Cloudflare Workers environment, KV namespaces, and Durable Objects required to queue and execute audit workflows. Once deployed, your instance exposes the MCP endpoints and web interface needed to target specific websites.

## Method 1: Programmatic Audit via MCP API

The **Machine-Callable Procedures (MCP)** API is the primary programmatic interface for starting audits. In [`src/server/mcp/tools/site-audit-tools.ts`](https://github.com/every-app/open-seo/blob/main/src/server/mcp/tools/site-audit-tools.ts), the `run_site_audit` tool accepts a target URL and project ID, then invokes `AuditService.startAudit` from [`src/serverFunctions/audit.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/audit.ts).

This method returns an `auditId` immediately while queuing the actual crawl as a background workflow. Poll `get_audit_status` with this ID to track progress through the discovery, crawl, and analysis phases. Retrieve final results using `get_audit_issues` or `get_audit_pages`.

```typescript
// Start an audit via MCP client
import { createMcpClient } from '@every-app/sdk';

const client = createMcpClient({ projectId: 'my-project' });
const { auditId } = await client.runSiteAudit({
  url: 'https://example.com'
});

// Poll for completion
let status = await client.getAuditStatus({ auditId });
while (status.phase !== 'completed') {
  await new Promise(r => setTimeout(r, 3000));
  status = await client.getAuditStatus({ auditId });
}

// Fetch prioritized issues
const report = await client.getAuditIssues({ auditId });
console.table(report.issues.map(i => ({
  title: i.title,
  severity: i.severity,
  fix: i.how_to_fix
})));

```

## Method 2: Command-Line Interface

For quick local testing or ad-hoc audits, use the CLI shortcut documented in [`badseo/README.md`](https://github.com/every-app/open-seo/blob/main/badseo/README.md). The command `npm run audit -- <target-url>` invokes the same internal `AuditService.startAudit` method used by the MCP layer, but requires no additional client setup.

```bash

# Run audit against a specific website

npm run audit -- https://example.com

# The command outputs the auditId

# Retrieve results later via HTTP:

curl "https://<your-host>/p/<project-id>/audit?auditId=<auditId>"

```

This approach is ideal for developers debugging specific domains or integrating OpenSEO into shell-based automation pipelines.

## Method 3: Web UI

The hosted or self-hosted interface provides a graphical method to run audits. The UI component calls the `useStartAudit` hook, which internally POSTs to the MCP `run_site_audit` endpoint.

```tsx
import { useStartAudit } from '@/hooks/useStartAudit';

function AuditButton({ url }: { url: string }) {
  const start = useStartAudit();
  return (
    <button onClick={() => start({ url })}>
      Run site audit on {new URL(url).hostname}
    </button>
  );
}

```

This method is best for non-technical users who prefer visual feedback and interactive result exploration.

## The Audit Workflow Lifecycle

Regardless of entry point, all audits execute through [`src/server/workflows/SiteAuditWorkflow.ts`](https://github.com/every-app/open-seo/blob/main/src/server/workflows/SiteAuditWorkflow.ts), orchestrated by Cloudflare Workers. The workflow proceeds through four distinct phases:

### 1. Discovery Phase

The crawler fetches [`robots.txt`](https://github.com/every-app/open-seo/blob/main/robots.txt) and XML sitemaps via [`src/server/lib/audit/discovery.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/audit/discovery.ts) to build an initial URL queue while respecting crawl directives.

### 2. Crawl Phase

[`src/server/workflows/siteAuditWorkflowCrawl.ts`](https://github.com/every-app/open-seo/blob/main/src/server/workflows/siteAuditWorkflowCrawl.ts) visits every same-origin page, extracting links, metadata, and response headers. It respects [`robots.txt`](https://github.com/every-app/open-seo/blob/main/robots.txt) restrictions and handles pagination automatically.

### 3. Analysis Phase

The system runs SEO checks against crawled data, identifying broken links, duplicate titles, canonical mismatches, thin content, and optionally executes Lighthouse audits. These checks live in `src/server/lib/audit/issues/`.

### 4. Result Aggregation

Final data persists to KV storage via [`src/server/lib/audit/progress-kv.ts`](https://github.com/every-app/open-seo/blob/main/src/server/lib/audit/progress-kv.ts), making it available through the `get_audit_issues` and `get_audit_pages` MCP functions.

## Summary

- **Three entry points** exist to run OpenSEO on a specific website: the **MCP API** (`run_site_audit`), the **CLI** (`npm run audit -- <url>`), and the **web UI**.
- All methods ultimately call `AuditService.startAudit` in [`src/serverFunctions/audit.ts`](https://github.com/every-app/open-seo/blob/main/src/serverFunctions/audit.ts), which queues a Cloudflare Workers workflow.
- The audit workflow in [`src/server/workflows/SiteAuditWorkflow.ts`](https://github.com/every-app/open-seo/blob/main/src/server/workflows/SiteAuditWorkflow.ts) progresses through discovery, crawl, analysis, and aggregation phases.
- Results are retrieved via `get_audit_status`, `get_audit_issues`, and `get_audit_pages`, returning JSON with severity ratings and remediation steps.

## Frequently Asked Questions

### Can I audit localhost or private internal websites?

OpenSEO requires publicly accessible URLs because the audit runs from Cloudflare Workers on the public internet. To audit `localhost` or private networks, you must deploy OpenSEO to a local Cloudflare Workers development environment using Wrangler, or expose your local site via a tunnel like Cloudflare Tunnel.

### How long does a site audit take to complete?

Audit duration scales with site size. Small websites (under 100 pages) typically complete in 2-5 minutes, while large e-commerce sites (10,000+ pages) may take 30-60 minutes. The `get_audit_status` MCP function returns real-time progress updates including the current phase and number of pages crawled.

### Do I need API keys to run OpenSEO audits?

Basic crawling and SEO analysis require no external API keys. However, if you configure optional integrations like DataForSEO for additional data enrichment, you must set the corresponding API keys in your environment variables as noted in [`docs/SELF_HOSTING_DOCKER.md`](https://github.com/every-app/open-seo/blob/main/docs/SELF_HOSTING_DOCKER.md).

### What is the difference between the MCP and CLI methods?

The **MCP method** (`run_site_audit`) is designed for programmatic integration, returning structured JSON responses and supporting real-time status polling. The **CLI method** (`npm run audit`) is a convenience wrapper that triggers the same underlying logic but outputs the audit ID to stdout, making it suitable for shell scripts and quick manual checks without writing client code.