The internet, readable by agents.
Manifest turns any URL into a structured map of what an AI agent can actually do on a page - every button, form, and input, with the fields it needs to fill and what's required before it can move on.
The problem
Give an AI agent a browser, and it can see a webpage. Give it a scraper, and it can read one. Neither tells it what it's allowed to do there.
Today, agents either take a screenshot and guess, or a developer hand-writes selectors that break the next time the page ships a redesign. There's no layer that tells an agent: here are the actions on this page, here's what each one needs, here's what's required.
That's the gap Manifest fills.
How it works
What you get back
Agent instructions
Paste this into your agent's system prompt to teach it to use Manifest before interacting with a webpage:
Integrate the Manifest API into this project.
Manifest turns a webpage into a structured JSON "action manifest": every clickable, fillable, or submittable element on the page, each with a resolved locator (CSS selector, ARIA role, and accessible name) and a requires field listing the ids of other actions that must be completed first. It sits between raw browser access (a headless browser gives you a DOM, not a list of things you can do) and content extraction (which gives you text, not actions) — reach for it whenever an agent needs to decide what to click or fill next instead of guessing selectors.
Preferred integration: MCP. Add the MCP server "io.omfang/manifest" to this project's MCP client config (also listed on Smithery if your tool installs from there). It exposes a streamable-http endpoint:
url: https://manifest.omfang.io/mcp header: x-api-key: ${apiKey}
Fallback: REST. If this setup doesn't support MCP yet, call the API directly:
Base URL: https://manifest.omfang.io Auth header: x-api-key: ${apiKey} Endpoint: POST /manifest Body: { "url": "<page to inspect>" }
Example response (either path returns this shape):
{ "current_page_state": "Login form with email/password fields", "actions": [ { "id": "email-input", "type": "input", "requires": [], "locator": { "css": "#email", "role": "textbox", "name": "Email" } }, { "id": "submit", "type": "button", "requires": ["email-input", "password-input"], "locator": { "css": "button[type=submit]", "role": "button", "name": "Log in" } } ] }
Prefer locator.role/locator.name over locator.css where possible — they hold up better across redesigns. Use requires to know which actions are still blocked on a prerequisite.