io.github.Kumar2421/marlo-mcp

Official registry Search and web

Audit a web page for SEO and technical issues with Marlo, the open-source AI CMO. Read-only.

Install

Add this to your client's MCP configuration (Claude Desktop: claude_desktop_config.json; Cursor: .cursor/mcp.json; VS Code and others use the same "mcpServers" shape).

NPM package marlo-mcp
Claude Code
claude mcp add marlo-mcp -e 'MARLO_BASE_URL=<MARLO_BASE_URL>' -e 'MARLO_ACCESS_PASSWORD=<your marlo_access_password>' -- npx -y marlo-mcp@0.1.0
JSON configuration (Claude Desktop, Cursor, VS Code)
{
    "mcpServers": {
        "marlo-mcp": {
            "command": "npx",
            "args": [
                "-y",
                "marlo-mcp@0.1.0"
            ],
            "env": {
                "MARLO_BASE_URL": "<MARLO_BASE_URL>",
                "MARLO_ACCESS_PASSWORD": "<your marlo_access_password>"
            }
        }
    }
}

Environment variables

  • MARLO_BASE_URL Base URL of your own self-hosted Marlo. Leave empty to use the hosted app at https://app.marlo.mlforge.in.
  • MARLO_ACCESS_PASSWORD secret The MARLO_ACCESS_PASSWORD of your self-hosted Marlo, if you set one. Only sent to MARLO_BASE_URL.

Documentation

From the project's README on GitHub, refreshed weekly. Links open on GitHub.

Contents
  1. What Marlo does
  2. Status
  3. Hosted or self-host
  4. Quick start
  5. How it works
  6. Security
  7. Plans and pricing
  8. Roadmap and known limits
  9. Documentation
  10. Contributing
  11. License

Open-source AI CMO. Marlo audits your website, finds what's holding it back in search and AI answers, helps you fix it, and only calls a fix verified when it has evidence.

Hosted app · Self-host · Docs · Pricing (beta) · Changelog

Marlo is one Next.js app. Use the hosted version, or self-host it for free with your own API keys. Self-host has every feature unlocked and no plan limits.

Marlo is inspired by Okara. It is an independent project: not affiliated with or endorsed by Okara, and not derived from Okara's code.

What Marlo does

Marlo runs one loop: discover → understand → act → verify. "Verified" always means evidence: a later audit, a re-check, or a real AI-answer run. A click alone never verifies anything.

StepWhat happens
DiscoverYou add a website. Setup audits the homepage, writes a description, finds competitors, and drafts Context documents (product info, marketing strategy, competitor analysis, content strategy, design guide). Progress is saved per project, and setup resumes when you come back.
UnderstandIssues become findings, ranked by impact. The Fix first strip shows the top ones. Each finding has its evidence, why it matters, and a recommendation that matches the issue. The Traffic tab (Search Console, GA4) and GEO tracking add search and AI-answer context.
ActMark a finding as in progress, ask the coding agent to open a draft GitHub pull request through the GitHub App, or publish a reviewed change to WordPress or Webflow. You approve every external write. Nothing posts or merges by itself.
VerifyRe-check runs the real check again, either when you click it or automatically on hosted. A finding that a newer audit no longer reports is flagged No longer detected and stays open until a re-check proves it. A GEO gap closes only when a later real run names you.

More screenshots

DashboardTraffic (Search Console and GA4)
Setup progress, saved per projectIntegrations
MobilePricing (beta)

Status

Marlo is in beta. This table says what to rely on today.

AreaStateNotes
SEO auditStableAudits one page in depth. The site crawl on the Links tab samples up to 8 pages, one link deep from the homepage. PageSpeed scores need a PageSpeed key; without one, the audit says "Not measured" rather than guessing.
Findings lifecycle and Re-checkBetaManual Re-check everywhere. Automatic re-check runs only on hosted, because it uses the scheduled jobs. A failed or skipped check never marks anything verified.
No longer detectedBetaWhen a newer audit of the same page stops reporting an issue, the finding is flagged. It is never verified automatically.
Fix first stripBetaShows the top open findings in a predictable, explainable order.
Context documentsBetaGenerated with an LLM from your site and web search. Treat them as drafts.
Traffic (Search Console, GA4)BetaNeeds Google OAuth. Hosted takes a daily Search Console snapshot. Self-host refreshes manually.
GEO trackingBetaA real Gemini answer grounded in Google Search ("real"), or a labelled stand-in built from Tavily and Groq ("simulated"). The two are never mixed or counted together. Marlo does not query ChatGPT, Perplexity or Claude.
GEO gaps as findingsBetaA prompt that keeps missing you becomes a finding. It closes only when a later run of the same prompt and method names you.
GitHub fix PRsBetaHosted uses a GitHub App. Self-host uses a token you save in Settings. PRs open as drafts, and no code path merges them.
Resumable setupBetaProgress is saved per project and resumes when you return. Setup runs in your browser, so it does not continue after you close the tab. On hosted it needs migration 20261022000300_project_setup_state.sql.
NotificationsBetaIn-app bell. Email only when Resend is configured.
AI CMO chatBetaRead-only tools over your project data, scoped to the active project and run under your own session. Marlo picks the model and retries on a backup model if a request fails. Chats are saved on the server for 90 days, and you can delete one or all. Monthly message limits are built but off during beta. Starting an audit from chat is not available yet.
CMS publish (WordPress, Webflow)ExperimentalYou preview and approve every write. WordPress SEO fields need Yoast or Rank Math REST meta. Webflow field names have not been checked against live sites.
Leads, outreach and social draftsExperimentalPeople search needs Tavily. Gmail outreach uses your own Gmail account. X, LinkedIn and Reddit posts are drafts: "Post" opens the network's compose page. Local business search is "Coming soon" on hosted and works on self-host with your own Google Cloud key.
Docker self-hostBetadocker compose up -d --build runs the SQLite self-host with a persistent volume and a non-root user. Optional MARLO_ACCESS_PASSWORD adds HTTP Basic access for servers other people can reach. The image is about 450 MB and is published for amd64 and arm64 as ghcr.io/kumar2421/marlo.
MCP server for AI assistants (marlo-mcp)BetaOne read-only tool, audit_site: audits one page and returns the top findings with evidence and a fix. It calls the public audit endpoint, so it shows 3 findings per page. See packages/marlo-mcp.
Plans and pricingBetaFree, Lite and Pro are defined, but there is no payment gateway yet and enforcement is off. See Plans and pricing.

Hosted or self-host

Hosted (app.marlo.mlforge.in)Self-host (this repo, SQLite)
CostFree during beta. Lite and Pro have a waitlist at /pricingFree (AGPL-3.0)
Plan limitsPlan enforcement is off. Older safety caps still apply: 4 websites and 10 daily leads on the Free tier, and per-user daily GEO caps (20 real Gemini runs, 60 simulated runs)None
Sign-inSupabase Auth (email and password with a one-time code; Google sign-in when enabled)None. It is a single-user local app. Do not expose it to the internet
DataSupabase Postgres with row-level securitydata/okara.db (SQLite) on your machine
API keysPlatform-managed default models, or bring your own keyYour own keys, saved in Settings
Scheduled jobsDaily Search Console snapshots, automatic re-checks, daily leads refresh, weekly GEO runsNone. The cron routes are hosted-only. Refresh and re-check by hand
GitHub fixesGitHub App, draft PRsPersonal token, draft PRs
Local business leadsComing soonYes, with a Google Cloud key that has Places API (New) enabled

You can also run the hosted build on your own Supabase project. See docs/self-hosting.md.

Quick start

Self-host

Requires Node.js 24.12 or newer (engines in package.json) and git.

git clone https://github.com/Kumar2421/okara-alternative.git
cd okara-alternative
npm install
echo "NEXT_PUBLIC_SELF_HOST=true" > .env.local
npm run dev
  1. Open **http://localhost:3000/dashboard**. The root URL redirects to the hosted sign-in page, which needs Supabase.
  2. To check the setup, open http://localhost:3000/api/system/storage-diagnostics. You should see "storageMode":"sqlite" and "available":true under sqlite.
  3. In Settings → LLM Providers, add at least one model key. The providers with drivers are Anthropic, OpenAI, Google, Mistral and Groq, plus a local Ollama or LM Studio server or any other OpenAI-compatible endpoint. Add optional keys under Settings → API Credentials: Tavily for web search, PageSpeed, Gemini for real GEO answers, Google Cloud, and a GitHub token for fix PRs.
  4. Add your website. Setup runs while the tab is open.

No environment variables are required in self-host mode. Optional ones, such as Gmail OAuth or Resend email, are listed in docs/environment.md. For a production-style build, run npm run build and then npm start. For full steps and troubleshooting, see docs/self-hosting.md.

Docker

No Node or npm needed:

git clone https://github.com/Kumar2421/okara-alternative.git
cd okara-alternative
docker compose up -d --build

Or skip the build: docker run -d -p 127.0.0.1:3000:3000 -v marlo-data:/app/data ghcr.io/kumar2421/marlo:latest.

Open http://localhost:3000/dashboard** and add a model key in **Settings → LLM Providers. Your data lives in the marlo-data volume. The port is bound to your machine only; to share it, set MARLO_ACCESS_PASSWORD, put HTTPS in front and change the port mapping. Details: docs/self-hosting.md.

Use Marlo from your AI assistant (MCP)

marlo-mcp lets Claude, Cursor, Windsurf and other MCP clients audit a page from chat. Add it to your client:

{ "mcpServers": { "marlo": { "command": "npx", "args": ["-y", "marlo-mcp"] } } }

Claude Code: claude mcp add marlo -- npx -y marlo-mcp. Then ask: "Audit https://mysite.com and tell me what to fix first."

It is read-only and audits one page. Point it at your own server with MARLO_BASE_URL (and MARLO_ACCESS_PASSWORD if you set one). See packages/marlo-mcp/README.md.

Hosted

Sign up at **https://app.marlo.mlforge.in**. To run your own hosted deployment (Supabase and Vercel), follow docs/hosted-setup.md and docs/self-hosting.md.

How it works

flowchart LR
  U["Browser: dashboard"] -->|setup steps, Re-check| API["Next.js route handlers"]
  API --> D["lib/domain: audit, findings, GEO, search, codefix"]
  D --> S{"Store pair"}
  S -->|self-host| SQ[("SQLite: data/okara.db")]
  S -->|hosted| PG[("Supabase Postgres + RLS")]
  D -->|guarded fetch| WEB["Your site, search and LLM APIs"]
  D -->|GitHub App| GH["Draft pull request"]
  CRON["Vercel Cron (hosted only)"] --> API
  • One app, two modes. lib/features.ts chooses the mode. Self-host uses SQLite. Hosted uses Supabase, and a hosted deployment with missing Supabase config fails closed with HTTP 503.
  • Store pairs. Each domain store has a SQLite file and a Supabase file, for example findingStore.ts and findingStoreSupabase.ts. The domain logic above them is shared and mostly pure.
  • Finding lifecycle. new → acknowledged → fixing → fixed → verified | failed. Only evidence sets verified or failed: a Re-check, the automatic check, or a later GEO run. You cannot set them by hand.
stateDiagram-v2
  [*] --> new: audit / search / GEO gap
  new --> acknowledged
  acknowledged --> fixing
  fixing --> fixed: you mark it, or the fix PR merges
  fixed --> verified: Re-check passes (evidence)
  fixed --> failed: Re-check still detects it
  failed --> fixing
  verified --> fixing: regression
  note right of new: No longer detected is a flag, not a status.<br/>The finding waits for a Re-check.

For data flow, cron jobs, the GitHub App loop and setup state, see docs/architecture.md.

Security

  • Auth. Supabase Auth. Server routes verify the user with auth.getUser() and do not trust a client-side session.
  • Isolation. Row-level security on user tables. Server-trusted tables (profiles, settings, connections) are read-only to users. Project routes check that the signed-in user owns the project.
  • Outbound requests. URLs that users can influence go through one guarded fetcher. It pins DNS, blocks private addresses, re-checks every redirect hop, and caps time and body size.
  • OAuth. Google, Gmail and GitHub connect flows use a single-use, expiring state value. On hosted, only the user who started a flow can complete it. Email unsubscribe links use signed, expiring HMAC tokens.
  • Keys. The operator's provider keys are never sent to a base URL that a user supplied (#170).
  • External writes. Fix PRs and CMS publishes need a signed, expiring approval. PRs are drafts, and nothing auto-merges or auto-posts.
  • Cron routes require a CRON_SECRET bearer token, compared in constant time.
  • The Content-Security-Policy header is still report-only.

Read docs/security.md for details. To report a vulnerability, follow SECURITY.md and use GitHub private vulnerability reporting, not a public issue.

Plans and pricing

Hosted plans are Free, Lite and Pro, per website, and they are in beta. There is no payment gateway yet, so the paid plans have a waitlist at /pricing. The suggested beta prices are Lite $29/month ($24/month billed annually) and Pro $79/month ($66/month billed annually). Plan enforcement is off, so the plan limits are not active and hosted features are unlocked today. Self-host is always unlocked.

The full feature and limit matrix, generated from lib/domain/plans/planMatrix.ts, is in docs/plans-and-pricing.md.

Roadmap and known limits

Coming next, in order: finish the core loop (findings, re-check, GEO gaps), then audit depth, then hardening. Known limits today:

  • Setup runs in your browser. Progress is saved and resumes when you return, but setup does not continue while the tab is closed.
  • Shallow crawl. The audit covers 1 page and samples up to 8. A full crawl of hundreds of pages is not built.
  • Scheduled jobs have limited coverage. Each cron is one time-boxed run per day (GEO: per week), so a large fleet of sites is covered slowly.
  • Payments are not live. Plan limits are defined but not enforced.
  • Limited GEO engines. Marlo measures Gemini grounded answers only, and labels the simulated stand-in as simulated.
  • No automatic posting to X, LinkedIn or Reddit.
  • Lead email checks use SMTP, which most cloud hosts block, so lead emails often show as unverified on hosted.
  • E2E suite. The Playwright suite (layout, accessibility, vitals, visual) runs by hand, not in CI, and some accessibility and visual specs fail today.
  • CSP is report-only.

Documentation

DocFor
docs/README.mdMap of all docs
docs/self-hosting.mdSelf-host step by step (Node or Docker), SQLite or Supabase, access password, cron recipe, troubleshooting
packages/marlo-mcpThe MCP server: install, configuration, limits
docs/architecture.mdData flow, store pairs, crons, GitHub App loop, setup state, finding lifecycle
docs/plans-and-pricing.mdPlan matrix, limits, how enforcement works
docs/security.mdProtections and how to report a vulnerability
docs/FAQ.mdCommon questions
docs/environment.mdEvery environment variable
docs/hosted-setup.mdHosted deployment checklist
docs/google-cloud-setup.mdGoogle OAuth and API setup
CHANGELOG.mdWhat changed, by theme

Contributing

Issues and pull requests are welcome. The rule for features matches the code: use real data or say plainly that it is not available. Never show a plausible-looking fake. If you add a feature, show its empty, loading and error states too.

npm test          # unit tests (node:test, tests/*.test.mts)
npm run lint      # ESLint
npm run build     # production build
npm run e2e       # Playwright (run `npx playwright install chromium` once first)
  • Keep PRs small. Each PR should solve one problem end to end. Avoid broad refactors and new abstractions without a consumer.
  • CI (.github/workflows/ci.yml) lints the files you changed, runs npm test (and fails if no tests ran), and runs a production build. Full-repo lint is informational only.
  • Target main. The pr-base-guard job fails a PR whose base is another branch, unless the PR body says intentional-base.
  • See docs/acceptance-gates.md for the definition of done.

License

Marlo is licensed under the GNU Affero General Public License v3.0. If you run a modified version as a network service, you must make its source available to the people who use it.

Frequently asked questions

What is io.github.Kumar2421/marlo-mcp?

Audit a web page for SEO and technical issues with Marlo, the open-source AI CMO. Read-only.

How do I install io.github.Kumar2421/marlo-mcp?

It runs on your machine. In Claude Code: claude mcp add marlo-mcp -e 'MARLO_BASE_URL=<MARLO_BASE_URL>' -e 'MARLO_ACCESS_PASSWORD=<your marlo_access_password>' -- npx -y marlo-mcp@0.1.0. For other clients, paste the JSON configuration from this page into their MCP settings.

Does io.github.Kumar2421/marlo-mcp need an API key?

Yes. It expects MARLO_ACCESS_PASSWORD, which you set in its configuration.

Is io.github.Kumar2421/marlo-mcp open source?

Yes. Its code is on GitHub under the AGPL-3.0 license.

Who maintains io.github.Kumar2421/marlo-mcp?

It is published by Kumar2421. AI.tn lists it but does not maintain or endorse it.

From the official MCP Registry. Listing is not an endorsement: review a server's code and permissions before giving it access to your data.