Umbodi
For developers

The engine, not just the app.

The search half of Umbodi is reachable from your own code: a typed client, an HTTP service, an MCP server, or a licensed self-hosted build running on your own provider keys. The AI-answer half is hosted-only today. The tables below say exactly which is which, because a developer surface that overstates its reach costs you an afternoon before you find out.

Pure ESM · no build step Zero runtime deps Node · Deno · edge · browser node --test · 6,900+ tests across the platform

Six ways to ship it.

Three ways it runs — and where each one stops.

The six surfaces above are HOW you call it. These are how much it is allowed to do on its own. Each mode has a different honest ceiling, and the one you pick decides who presses the last button.

MODE 1 · TOOL

No repository access

Umbodi prepares the change and a person applies it — copy, paste, send. It then re-crawls the live page and proves the change is really there. Complete, and needs no trust.

MODE 2 · TOOL + GIT

Opens a pull request

One atomic commit on a namespaced branch, never the default branch. A person reviews and merges. Retry-safe: running twice updates the same pull request instead of opening a second.

MODE 3 · INTEGRATED

Self-heal

Embedded through the API or SDK, the loop closes with nobody in it: merge on green, then verify. Merging is a separate explicit opt-in, never inherited from an autonomy dial.

One word, two meanings — check which you are readingThe engine documentation uses self-healing for operational resilience: retry with backoff, provider failover, and explicitly no self-modifying code. Mode 3 above is a different thing — the write loop that merges a pull request and verifies the deploy. Both are real; they are not the same capability, and only the second one touches your repository.

What the engine gives you, and what is hosted-only.

Measured against the engine source on 30 September 2026, not described from memory. If you are evaluating Umbodi for the AI-answer half, read this before you start.

  • In the engine — six actions. analyze · generate · rankings · competitors · content · status. Every surface — SDK, HTTP service, MCP, the Claude skill, the widgets — is a different way of reaching those same six. All six are search-side. The engine ships its own suite, reported by its own npm test — a different figure from the platform total above, and one this repository cannot re-derive for you.
  • Hosted-only — AI-answer visibility. The five answer engines, citation checking and answer-engine reporting are not in the licensable engine and not reachable by SDK or MCP. They run in the hosted product. Saying so is cheaper for you than discovering it after a licence.
  • Hosted-only — the write channel. Opening a pull request, merging it on green and verifying the deploy live are hosted capabilities; the engine itself researches and drafts and never writes to your repository. A license key reaches the first of those through the hosted API — apply opens a pull request with the changes you approved. It cannot merge one, ever.
  • Bounded on purpose. Whatever the mode, the agent writes content and discoverability files only — it may never modify the code that decides what it is allowed to change. That bound is enforced immediately before any irreversible act, not just when the change is proposed.
About the package namesThe product is Umbodi; the engine package is still @ascent/seo-agent (its MCP server is the seo-agent-mcp bin), and the environment variables are still ASCENT_SERVICE_URL, ASCENT_LICENSE and ASCENT_LOCAL. Those are real identifiers, pinned until a major version — copy them exactly as written. The package is not on a public registry: licensed customers receive it from Umbodi. The hosted API at https://umbodi.ai/v1 needs no package at all.
Honest by designNumbers are always tagged measured on Google (a real rank) vs Umbodi estimate (a projection) — the two are never blurred, in every channel.
Deep dive

Architecture & integration brief

The full developer document — runtime profile, the six surfaces, the action lifecycle, a safe adoption path and the production checklist.

Quickstart

Analyze a site in about a minute.

With a license key, call the hosted API — nothing to install, and analyze is free. With the licensed engine, run the same audit in-process with the sitemap content adapter.

# hosted — your license key, nothing to install
curl -s -X POST https://umbodi.ai/v1/analyze \
  -H "authorization: Bearer $ASCENT_LICENSE" -H 'content-type: application/json' \
  -d '{"url":"https://acme.com"}'          # → { issues: [...] }
// licensed engine, in-process (delivered to licensed customers)
import { createSeoAgent, sitemapAdapter } from '@ascent/seo-agent'

// the sitemap adapter is the no-code source of pages to audit
const { listIndexableEntities } = sitemapAdapter({ origin: 'https://acme.com' })

const seo = createSeoAgent(
  { site: { domain: 'acme.com' } },
  { listIndexableEntities },
)

const { issues } = await seo.analyze()
console.log(issues)

generate() (AI content proposals) and run() (the job loop) take the provider and storage seams — see the SDK section.

Licensed · request accessUmbodi is a commercial engine and isn’t on a public registry yet. The install line shows the intended flow; start in the app or reach out to request developer access.
SP0 · SDK core

The SDK — one facade, four profiles.

createSeoAgent(config, deps) wraps the pure cores and returns { analyze, generate, run }. A runtime layer detects Node / Deno / edge / browser and splits trusted (server, holds keys) from untrusted (browser, proxies secret calls to the service). An offline ES256 license gate reuses your entitlements.

import { createSeoAgent, sitemapAdapter, memoryStore } from '@ascent/seo-agent'

const seo = createSeoAgent(
  { site: { domain: 'acme.com' }, serviceUrl: 'https://your-service' },
  {
    listIndexableEntities: sitemapAdapter({ origin: 'https://acme.com' }).listIndexableEntities,
    store: memoryStore(),
    // callClaude, db, auth … wire the seams you need for generate()/run()
  },
)

const { issues } = await seo.analyze()
const draft   = await seo.generate()   // human-approved content proposals
  • @ascent/seo-agent/license — verifyLicense(token, {publicJwk, now}), offline.
  • @ascent/seo-agent/config · /runtime — resolve config + the runtime/trust split.
  • Four init profiles: headless · api · frontend · admin.
SP1 · Service / API

One handler. N routes. Server-side secrets.

A single Web-standard handleRequest(Request) → Response router over every backend shell, with unified Authorization: Bearer license auth, CORS, and fail-soft responses. This is the endpoint the browser SDK proxies to — so keys stay on the server.

Or do not host it at allUmbodi runs this contract at https://umbodi.ai/v1: every action is POST /v1/{action} with your license key, paid actions are charged in credits to the key’s account, and a site must be one of your own projects. GET /v1/status lists the actions.
import { createSeoService, defaultHandlers, toNodeHandler } from '@ascent/seo-agent/service'

const service = createSeoService({
  handlers: defaultHandlers(ctx),   // ctx = your provider + storage seams
  publicJwk,                        // verifies license keys offline
  corsOrigins: ['https://your.site'],
})

// Web-standard (edge / Deno / Bun):
export default (request) => service.handleRequest(request)

// or adapt to a Node http handler:
export const nodeHandler = toNodeHandler(service)
# call it with a license
curl -X POST https://your-service/analyze \
  -H "authorization: Bearer $ASCENT_LICENSE" \
  -H "content-type: application/json" \
  -d '{"site":{"domain":"acme.com"}}'
Reference & downloads
Get it
SP2 · MCP server

Seven tools, and one of them acts.

A hand-rolled, zero-dependency Model Context Protocol server over stdio, exposing analyze · generate · rankings · competitors · content · status · apply. A license key alone uses Umbodi’s hosted API (umbodi.ai/v1); point it at your own service with ASCENT_SERVICE_URL, or run a local in-process SDK.

One tool acts, and it proposesSix tools read or draft. apply asks the service to open a pull request — reviewable, revertible, visible before it is anything else — and it can never merge one. A license key is a string that ends up in client configs, CI variables and screenshots, which a GitHub App installation never does, so no license-authenticated action can merge: the hosted API has no merge action, and the permission check refuses a merge before it examines the key. Merging stays with the project owner. There is still no run or job/worker tool, transport is stdio only, and the JSON-RPC layer is a hand-rolled subset, not the official SDK.
// add to your MCP client config (e.g. Claude Desktop)
{
  "mcpServers": {
    "ascent-seo": {
      "command": "node",
      "args": ["/path/to/seo-agent/mcp/server.mjs"],
      "env": { "ASCENT_LICENSE": "your-license-key" }
    }
  }
}

Prefer to import it? @ascent/seo-agent/mcp exposes runServer, defineTools, and resolveBackend.

Reference & downloads
Get itcurl https://umbodi.ai/v1/status
SP3 · Claude skill

A drop-in Claude skill.

The ascent-seo skill lets Claude run Umbodi tasks for you. It prefers the MCP server when it’s connected and falls back to a zero-dep CLI script otherwise — so it works whether or not MCP is wired up. An honesty reference keeps measured and projected results clearly separated in what Claude reports back.

  • Ships as skill/ascent-seo/ — SKILL.md + honesty reference + fallback CLI.
  • MCP-preferred; the script path needs only ASCENT_SERVICE_URL + ASCENT_LICENSE.
  • Pairs naturally with the MCP server above.
Reference & downloads
SP4 · Frontend widgets

Browser widgets — pure build, thin mount.

Zero-dependency, XSS-escaped browser widgets: a meta injector, a rank badge (measured), a potential gauge (projected), and an honest result card. Each is a pure buildX(data) → html plus a thin mountX(el, data), with a base theme.css.

import { mountRankBadge } from '@ascent/seo-agent/widgets'
import '@ascent/seo-agent/widgets/theme.css'

mountRankBadge(document.querySelector('#rank'), {
  keyword: 'best crm',
  position: 5,          // measured on Google — not a projection
})

makeAscentClient() builds a browser client that talks to your service; only the token is sent, never secrets.

Reference & downloads
Get it↓ Widget kit .zipfree · includes theme.css
SP5 · Admin cockpit

An operator cockpit you control.

Six actionable panels — proposals, keywords, rankings, competitors, autonomy, status — built on a small panel framework. Panels render the data you pass in and write through an onAction callback you wire, so there’s no hidden write endpoint pretending to exist.

import { mountProposals } from '@ascent/seo-agent/admin'

mountProposals(document.querySelector('#proposals'), proposals, {
  onAction: (action) => approve(action), // you own the write path
})
Reference & downloads
Get it
Umbodi credits & billing

Two ways to pay for paid ops.

Paid operations (SERP + AI) cost money to run. How they’re billed depends on where the engine runs — on your infrastructure, or on Umbodi’s hosted API.

Self-hosted / licensed → your keys, no Umbodi credits

Run the engine on your own infrastructure with your own Serper/Anthropic keys. You pay those providers directly — Umbodi credits don’t apply and there’s nothing to top up. Your cost is your provider bill plus the annual license. Generate a key from any 🔒 Generate license button.

Hosted API / Service → Umbodi credits

Call Umbodi’s hosted API at https://umbodi.ai/v1 with your license key (Authorization: Bearer). Umbodi runs the ops on its keys — or yours, if you connected them — and charges Umbodi credits to the key’s account: the same wallet and the same prices as the app. A call that fails at the provider is refunded; an empty wallet returns 402 insufficient_credits, and a project at its monthly cap 402 project_cap_reached. A content topic about one of your tracked competitors is refused with 422 topic_refused before anything is charged.

// a paid call: charged to the key's account, refused if the site is not yours
POST https://umbodi.ai/v1/rankings
Authorization: Bearer <license key>
{ "site": { "domain": "example.com" } }   // → { results: [{ keyword, position, top }] }

// top up from the app, signed in — the account comes from your session
POST /api/payments/mips/create-payment
{ "kind": "credit_pack", "packId": "pack_5k" }   // 401 signed out · 503 payments off

Bring your own keys (BYOK): connect your Serper/Claude keys in Account settings and hosted ops run on your keys at near-zero credits — the natural fit for agencies and high-volume dispatch.

The operator may pause metering — hosted calls then run free (usage is still recorded).

← Back Docs
Downloads

Grab the free components.

The open pieces are yours to download and use now. The licensed engine — SDK core, service/API, MCP server, admin cockpit — is available on request.

Widget kit

Browser widgets + theme.css — rank badge, potential gauge, result card, meta injector.

↓ .zip

Claude skill

The ascent-seo skill — SKILL.md, honesty reference, fallback CLI.

↓ .zip

Type definitions

The .d.ts API surface — entities, adapters, storage, providers.

↓ .zip

Examples

Runnable SDK usage examples.

↓ .zip

🔒 Licensed · SDK core · service/API · MCP · admin

The engine itself is a commercial, licensed product — self-host or white-label. It isn’t a public download — request developer access and we’ll set you up.

Honest by designOnly the free pieces above are downloadable here. Nothing on this page ships the licensed engine — the request-access path is the only way to it.
Watch it

The integration, end to end.

One pass over the surfaces a developer actually touches: where the origin and the SERP provider are set, which researchers run, the GitHub App that lets Umbodi open a pull request, and the worklist where a change is handed back as text to paste rather than written to your site behind your back.

The configuration screen showing the site origin, the SERP provider, the researchers that run, fleet learning, and the GitHub repository pull requests are opened against, followed by the apply worklist handing back a page to paste.
Configuration, the GitHub App, and the worklist — recorded on the live app, read-only.

More walkthroughs, one per surface, as the integration surface grows. See all walkthroughs.

Straight answers

Questions people ask.

How do I call Umbodi from my own code?

Call the hosted API at umbodi.ai/v1 with your licence key. It runs the same endpoints the app uses, at the same prices, charged to your account's credits. Or run the licensed engine on your own infrastructure with your own provider keys.

Can my own agent drive Umbodi?

Yes. Umbodi's MCP server gives an agent seven tools: audit a page, build the site profile, check rankings, find competitors, draft content, report status, and open a pull request with the changes you approved. It can never merge one, and the scheduled loop stays on Umbodi's own schedule.

Can I self-host Umbodi?

Yes. A licensed build runs on your own infrastructure with your own provider keys and an offline-signed licence key, and can be white-labelled under your own brand. Nothing calls back to us to authorise a run.

Umbodi acts on your mandate — an autonomous agent for search and AI-answer visibility. It finds the work, ships the work, and measures what happened.
Umbodi™ is a trademark of I-Novanet Software Ltd. Application accepted in Mauritius (MU/M/2026/44210).