Atlas / MCP servers / oyadotai / Oya Browser

Oya BrowserBLOCK

mcp/oyadotai/oya-browser

The browser control plane for AI agents. One API over Oya Cloud, Browserbase, Steel, Anchor, Browser Use and your own Chrome, with persistent personas, CAPTCHA and MFA handling, and live human takeover.

Verdict
BLOCK
Grade
F
Trust score
37 /100
Exposed tools
33 25r · 7w · 1d
Transport
streamable-http
License
NOASSERTION
Stars
347
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

Everyone else drives Chrome from the outside. We built the browser.

The automation lives inside it, not attached over the debugging protocol, so your agents stop looking like a harness. Sign in once and every browser you start is already signed in. Do the task once and Oya replays it forever, with no model in the loop.

Read from source at commit bf3c3cb35362OBSERVED · 2026-10-07
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code
claude mcp add ui --env ANCHOR_API_KEY=${ANCHOR_API_KEY} --env API_KEYS=${API_KEYS} --env AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} --env AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} -- npx -y [email protected]
claude-desktop
{
  "mcpServers": {
    "ui": {
      "command": "npx",
      "args": [
        "-y",
        "[email protected]"
      ],
      "env": {
        "ANCHOR_API_KEY": "${ANCHOR_API_KEY}",
        "API_KEYS": "${API_KEYS}",
        "AWS_ACCESS_KEY_ID": "${AWS_ACCESS_KEY_ID}",
        "AWS_SECRET_ACCESS_KEY": "${AWS_SECRET_ACCESS_KEY}"
      }
    }
  }
}
03

Exposed tools (33)

25 read · 7 write · 1 destructive. Blast radius: 1 tool can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
clickreadClick an interactive element by its ID number (from analyze_page results).
click_coordinatesreadClick at specific x,y pixel coordinates on the page.
close_tabreadClose a tab. Closes active tab if no tab_id specified.
double_clickreadDouble-click an element by ID or at x,y coordinates.
dragdestructiveDrag from one point to another. For sliders, drag-and-drop, or text selection.
handle_dialogreadAnswer a native browser dialog (confirm or prompt) that is blocking the page. Alerts are answered for you. Accept only what the task actually asks for, a confirm may be guarding something destructive.
internal-pdf-viewerreadPortable Document Format
keyboard_typereadType text into whatever is currently focused, without targeting a specific element.
list_tabsreadList all open tabs (ID, title, URL, which is active).
mouse_movewriteMove mouse to x,y coordinates without clicking. Triggers hover states and tooltips.
navigatereadNavigate the browser to a URL.
oneread
open_tabreadOpen a new browser tab, optionally navigating to a URL.
pool_statusreadShow pool size and connected browsers.
press_keyreadPress a safe navigation key. Allowed: Enter, Escape, Tab, ArrowDown, ArrowUp, ArrowLeft, ArrowRight, Backspace, Delete, Space, Home, End, PageUp, PageDown. Do NOT press F-keys, Meta, Control, Alt, or Shift.
read_consolereadRead what the page logged: its own errors and warnings. Use this when a step failed, a page stalled, or the portal showed an error you cannot read on screen, it says what the page itself complained about.
read_elementsreadList interactive elements on the page, with the same ids analyze_page gives. Lighter than analyze_page: no page text.
rememberwriteKeep a short note about how the site you are on works, for the next run that comes here: where a report lives, which menu hides a setting, a login or form quirk that cost you steps. Never task values, personal data or anything secret. Notes come back when a run reaches this site.
request_humanreadAsk a person for help when you are stuck: a question only the user can answer, a login you cannot pass, or something the tools cannot do. Waits for their reply.
restart_recordingwriteCall this right before you start the whole task again from the beginning, after an attempt went wrong. The playbook then keeps only the attempt that worked, so its replay does the task once. Do not call it to fix one field or step; fix that in place.
screenshotreadSee the visible browser tab as an image. Use it when layout, images, icons or a canvas matter, or when analyze_page does not explain what is on screen. Element ids still come from analyze_page.
scrollreadScroll the page up or down.
select_optionreadChoose an option in a native dropdown (a select element from analyze_page) by the option text you see. Accepts {{placeholders}} and filters.
start_browserwrite
stop_browserwrite
switch_tabreadSwitch to a different tab by ID (from list_tabs).
treadd
typereadType text into an input element by its ID (from analyze_page). Clears existing content first.
update_planwriteWrite or update your plan: the steps this task needs, each marked done or not. Call it first for any task of more than a few steps, and again as you finish each one. It does not touch the page.
upload_filewriteAttach one of the task
waitreadWait for an element matching a CSS selector to appear.
wait_forreadWait until the page is ready: some text shows, the url contains something, and/or the network has gone quiet. With no text or url it waits for the network to settle. Use it after an action that loads results in the background, rather than analyzing again and again.
xready
04

Trust audit

BLOCKgrade F · trust 37/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryFAIL
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (11 observation(s))
Network
declared (11 observation(s))
Shell
declared (1 observation(s))
Dependencies
not all pinned
Secrets in source
found

Findings (25)

HIGHInventory / provenance · inv.suspicious_name · CWE-1104
ui/src/components/dashboard/settings/webhook-payload.tsx
webhook-payload.tsx
Why it matters. member named after an attack tool
Fix. remove or justify
HIGHNetwork egress · net.metadata_ip · CWE-200, CWE-319
k8s/base/browser.yaml:115
- 169.254.169.254/32   # cloud metadata
Why it matters. cloud metadata endpoint: the classic SSRF credential grab
MEDIUMInventory / provenance · inv.binary · CWE-1104
browser/build/icon.icns
icon.icns
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
MEDIUMInventory / provenance · inv.symlink · CWE-1104
.claude/skills/browser-agent
.claude/skills/browser-agent
Why it matters. link not followed
MEDIUMInventory / provenance · inv.symlink · CWE-1104
.claude/skills/frontend-design
.claude/skills/frontend-design
Why it matters. link not followed
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
packages/cli/src/install/report.ts:44
console.log(`\n  ${style.bold('API key')}  ${style.green(apiKey)}\n`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
packages/cli/src/install/report.ts:47
console.log(`  oya login --url ${publicUrl} --key ${apiKey}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
packages/cli/src/install/report.ts:51
console.log(`OYA_API_KEY=${apiKey}`);
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
browser/src/main/connection/cdp-relay.ts:20
const res = await fetch(`http://127.0.0.1:${port}/json/version`);
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
browser/src/main/mirror/cdp-ws.ts:45
const res = await fetch(`http://127.0.0.1:${port}/json/version`);
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
browser/src/main/workflow/validation.ts:324
const endpoint = `http://127.0.0.1:${(this.server!.address() as AddressInfo).port}`;
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
server/tests/unit/drivers/sandbox/tenancy.test.ts:37
auth: { type: 'iam', accessKeyId: 'AKIAABCDEFGHIJKLMNOP', secretAccessKey: 'tenant-secret' },
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
server/tests/unit/drivers/sandbox/tenancy.test.ts:62
accessKeyId: 'AKIAABCDEFGHIJKLMNOP',
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
server/tests/unit/modules/config/ecs.test.ts:16
auth: { type: 'iam', accessKeyId: 'AKIAABCDEFGHIJKLMNOP', secretAccessKey: 'shh' },
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
server/tests/unit/modules/config/ecs.test.ts:78
assert.deepEqual(view.auth, { type: 'iam', accessKeyId: 'AKIAABCDEFGHIJKLMNOP', secretAccessKey: '••3' });
MEDIUMHard-coded secrets · secret.aws · CWE-798, CWE-321
server/tests/unit/modules/config/ecs.test.ts:93
AWS_ACCESS_KEY_ID: 'AKIAABCDEFGHIJKLMNOP',
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
deployments/k8s/README.md:20
--database-url 'postgres://oya:[email protected]:5432/oya?sslmode=require' \
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
packages/cli/tests/unit/install/interview.test.ts:27
const env = { DATABASE_URL: 'postgres://u:p@db/x', BROWSERBASE_API_KEY: 'bb', OPENAI_API_KEY: 'sk' };
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
packages/cli/tests/unit/install/interview.test.ts:45
DATABASE_URL: 'postgres://u:p@db/x',
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
server/tests/unit/platform/storage/postgres.test.ts:161
const local = 'postgresql://postgres:[email protected]:54322/postgres';
MEDIUMHard-coded secrets · secret.db_uri · CWE-798, CWE-321
server/tests/unit/platform/storage/postgres.test.ts:183
verifyFull('postgres://u:p@h:5432/db?sslmode=require&uselibpqcompat=true&application_name=oya', ''),
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
server/tests/integration/challenges.test.js:179
await mfa.set(persona, { type: 'totp', secret: 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ' });
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
server/tests/unit/modules/challenges/mfa-factors.test.ts:24
const SECRET = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ';
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
server/tests/unit/modules/challenges/mfa.test.ts:23
const SECRET = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ';
MEDIUMHard-coded secrets · secret.generic · CWE-798, CWE-321
ui/tests/dashboard.spec.ts:72
if (path === '/auth/projects/prj-two/access') body = { token: 'oya_research-credential' };

Gates applied: no_behavioural_pass.

Audited 2026-10-07 · audit v0.4.1 · source sha bf3c3cb35362full audit observations/trust-audit/mcp-server/oyadotai__oya-browser.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-07bf3c3cb35362BLOCKF37first audit
06

Questions

What is the @oya-ai/browser MCP server?

The browser control plane for AI agents. One API over Oya Cloud, Browserbase, Steel, Anchor, Browser Use and your own Chrome, with persistent personas, CAPTCHA and MFA handling, and live human takeover.

What tools does @oya-ai/browser expose?

33 in total: 25 read-only, 7 that write, and 1 that can delete or overwrite (drag). Every one is listed on this page with its risk.

Is @oya-ai/browser safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (37/100) and found 2 critical or high issues in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 1 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does @oya-ai/browser need?

It reads ANCHOR_API_KEY, API_KEYS, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SSO_ACCESS_TOKEN, BROWSERBASE_API_KEY, BROWSERUSE_API_KEY, DAYTONA_API_KEY, FAKE_SECRET_FAILS, FLEET_TOKEN, GEMINI_API_KEY and LOGIN_PASSWORD from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does @oya-ai/browser run?

It speaks streamable-http, so it runs as a service you connect to over the network. It is published on npm as ui at 0.1.0.

How current is this page?

The grade is for one exact copy of the source (bf3c3cb35362), read on 2026-10-07. The repository is watched and re-audited when it changes.

Advertisement