Atlas / MCP servers / shiplightai / shiplightai

shiplightaiBLOCK

mcp/shiplightai/shiplight-cli

AI-powered end-to-end testing for Playwright. Write tests as YAML with natural-language steps, with self-healing locators and a visual debugger.

Verdict
BLOCK
Grade
F
Trust score
47 /100
Exposed tools
74 57r · 12w · 5d
Transport
stdio
License
MIT
Stars
0
01

Overview

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

AI-powered end-to-end testing for Playwright. Write tests as YAML with natural-language steps, run them alongside your existing .test.ts files, and get self-healing locators and a visual debugger.

Documentation: [docs.shiplight.ai](https://docs.shiplight.ai)

What ships from this repository

Quick start

npx shiplightai@latest create ./my-tests
cd my-tests
npm install
npx playwright install chromium
npx shiplight test

A test looks like this:

goal: A shopper can add an item to the cart
base_url: https://example.com

statements:
- URL: /products

# Natural language: resolved by a model on the first run
- intent: Click the "Add to cart" button on the first product

# Once resolved, a step carries its locator and replays deterministically
- intent: Open the cart
action: click
locator: "getByRole('link', { name: 'Cart' })"

- VERIFY: The cart shows exactly one item

A statement written as plain intent is resolved by a model at runtime; once resolved it carries a concrete locator, so later runs replay deterministically and only fall back to the model when the page has changed under it.

Self-hosting

Run the CLI and browsers on your own machines or CI runners, with your own AI provider key and the action cache and reports in storage you control: apps/cli/docs/self-hosting.md.

Shiplight Cloud shuts down on October 31, 2026. After that date this is the only way to run Shiplight, and SHIPLIGHT_API_TOKEN stops working.

Working on the code

Requires Node.js >= 22 and p

Read from source at commit 32099b12f2caOBSERVED · 2026-10-12
Advertisement
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 (npm)
claude mcp add mcp -- npx -y @shiplightai/[email protected]
03

Exposed tools (74)

57 read · 12 write · 5 destructive. Blast radius: 5 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
actwriteExecute browser actions using element indices from inspect_page. CRITICAL: Before your first act call, you MUST read resource
ai_actionreadUse AI to perform a specific action on the page. MCP-only tool.
ai_assertreadAssert that a statement is true based on the current screen state
ai_extractwriteUse AI to extract information from the page and save it to a variable. MCP-only tool.
ai_stepwriteUse AI to execute a complete multi-action step. MCP-only tool.
ai_wait_untilreadWait until a specific condition is met on the page (e.g.,
attach_to_browserreadConnect to a browser for testing. Two modes:\n
backreadPress the back button
browser-session-basicsreadBasic browser session management for UI verification
clear_execution_historydestructiveClear the execution history for a session. The execution history tracks past browser operations within a session. Clear it to start fresh or reduce memory usage.
clear_inputdestructiveClear text from an input field
clear_logsdestructiveClear console and network logs for a session
clickreadClick an interactive element.
close_allreadClose all browser sessions
close_sessionreadClose a browser session. Omit session_id entirely to close ALL open sessions.
close_tabreadClose a browser tab by index. If no index is specified, closes the current tab.
constrainedreadfield with a refinement
donereadMark the task as complete
double_clickreadDouble-click an interactive element.
double_click_atreadDouble-click at the given normalized coordinate.
double_tapreadDouble-tap an element
enterreadPress the enter key
extract_email_codereadExtract verification code from email inbox
extract_email_contentreadExtract verification codes, magic links, or custom content from emails received via Mailgun. Polls the Mailgun inbox for matching emails and uses AI to extract the requested content.
generate_2fa_codereadGenerate a 2FA code from an OTP secret key. The code is saved to the
generate_html_reportreadGenerate a self-contained HTML session report.
get_browser_console_logsreadGet console logs from the browser (errors, warnings, etc.)
get_browser_network_logsreadGet network request logs from the browser
get_dropdown_optionsreadGet all options from a native dropdown
get_local_artifactreadGet a local artifact file (screenshot, DOM snapshot, etc.) from a live browser session. Only accepts local file paths, NOT S3 URIs. For test run artifacts, use get_step_artifacts instead.
get_page_inforeadGet basic page information (URL and title) without taking a screenshot. Use this as a lightweight way to check what page you
get_relay_statusreadGet extension relay server status and tab mapping
get_session_statereadGet current state of a session (URL, session type)
go_backreadNavigate back to the previous page in browser history.
go_to_urlwriteNavigate to a specific URL. Use this to visit web pages. Set new_tab=true to open in a new tab.
homereadPress the home button
hoverreadHover over an interactive element.
inputreadType text into the currently focused input field
input_textreadType text into an input field
js_codewriteExecute custom JavaScript code in the browser context. Use for advanced interactions not covered by other tools.
long_pressreadLong press an element
navigatereadNavigate to a URL in an existing browser session. Examples: - Navigate to a specific page: url=
new_sessionwriteCreate a new browser session with optional device emulation. Returns a session_id for subsequent operations.
opt_outreadno resolveArgs
perform_accurate_operationreadPerform an operation that requires accurate interaction like dragging or interacting with a specific area of an element. Only use this action when neccecary.
pick_rolereadenum message embeds the received value
plain_enumreadno redactor
pressreadPress a single keyboard key or key combination. Supports combinations like
press_keyreadPress a system key by key code
raw_argsreadreports rawArgs
reload_pagedestructiveReload the current page. WARNING: This will reset any in-progress forms or multi-step flows (like login). Only use when you need to refresh stale data or clear a stuck state. Do NOT use during login, checkout, or form submission flows.
right_clickreadRight-click an interactive element.
right_click_atreadRight-click at the given normalized coordinate.
save_storage_statewriteSave the browser session
save_variablewriteSave a value to a named variable for later use in the test.
scrollreadScroll content with precise from/to coordinates (preferred for scrolling lists, feeds, etc.)
scroll_on_elementreadScroll on a scrollable element horizontally and vertically.
scroll_to_elementreadScroll to find an element
scroll_to_textreadScroll the page until specified text becomes visible.
select_dropdown_optionreadSelect an option from a dropdown/select element by value, label, or index.
set_date_for_native_date_pickerwriteSet a date in a native HTML date picker input (<input type=
swipereadSwipe gesture for switching tabs, dismissing dialogs, or navigating pages (use scroll for scrolling content)
swipe_pointsdestructiveDrag/swipe between two specific points (for drag-and-drop, picture-in-picture, etc.)
switch_tabreadSwitch to a different browser tab by index (0-based).
tapreadTap an element
unresolvablereadplaceholder has no variable
update_variableswriteUpdate session variables for use in subsequent browser operations. Variables are key-value pairs that can be referenced in browser tasks. Mark sensitive values (passwords, tokens) with sensitive_keys to prevent logging. Example: variables: { username:
upload_filewriteClick on target element (usually contains hints like
upload_file_to_file_inputwriteUpload a file to a file input element. The file path is relative to the test project root.
verifyreadVerify that a statement is true based on the current page state. Use this to check assertions about the page content, element visibility, or any condition.
waitreadWait for a specified duration
wait_for_download_completereadWait for an in-progress download to complete.
wait_for_page_readyreadWait for the page to be fully loaded (network idle and DOM ready). Use this when the page is still loading or not ready for interaction.
with_descriptionreaddescription is stripped before resolution
04

Trust audit

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

LayerWhat it checksResult
L0Provenance & inventoryPASS
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 (5 observation(s))
Network
declared (5 observation(s))
Shell
declared (5 observation(s))
Dependencies
not all pinned
Secrets in source
none-found

Findings (25)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
apps/cli/src/debugger/services/playwrightSandbox.ts:215
const fn = new Function('page', 'agent', `return (async () => { ${code} })();`);
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
apps/cli/src/debugger/services/playwrightSandbox.ts:435
const fn = new Function('page', 'expect', 'agent', `return (async () => { return (${code}); })();`);
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
apps/cli/src/yaml-transpiler/pipeline.ts:139
new Function(codeBody);
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
packages/debugger-ui/src/utils/aiDetectionUtils.ts:20
new Function('return (async () => { ' + code + ' })()');
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
packages/mobile-sdk/scripts/test-agent.ts:198
exec(`emulator -avd ${avdName} -no-snapshot-save -no-audio -no-boot-anim`);
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
packages/mobile-sdk/src/agents/vision/providers/gemini/GeminiVisionProvider.ts:102
console.log(`[Gemini] Debug: useVertexAI=${useVertexAI}, apiKey=${apiKey ? 'set' : 'not set'}, modelConfig.apiKey=${modelConfig.apiKey ? 'set' : 'not set'}`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
packages/sdk-core/src/agent/webAgent.ts:565
logger.debug(`[collectTokenUsages] No token usages to collect (undefined or empty)`);
MEDIUMInformation disclosure · disclose.log_secret · CWE-209, CWE-532
packages/sdk-core/src/agent/webAgent.ts:2474
logger.debug(`Token usages written to: ${tokenUsagesPath}`);
MEDIUMNetwork egress · net.beacon_words · CWE-200, CWE-319
packages/sdk-core/src/browser/browserUtils.ts:137
'analytics', 'tracking', 'telemetry', 'beacon', 'metrics',
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
clear_execution_history, clear_input, clear_logs, reload_page, swipe_points
Why it matters. 5 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWInventory / provenance · inv.binary · CWE-1104
apps/cli/tests/fixtures/web/testing/assets/files/mock-data.xlsx
mock-data.xlsx
Why it matters. a compiled or binary member cannot be reviewed from source
Fix. ship source, or explain the binary in the README
LOWInventory / provenance · inv.hidden_file · CWE-1104
.prettierignore
.prettierignore
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.hidden_file · CWE-1104
apps/cli/src/scaffold/templates/.mcp.json.tpl
.mcp.json.tpl
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInventory / provenance · inv.symlink · CWE-1104
CLAUDE.md
CLAUDE.md
Why it matters. link not followed
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
apps/cli/src/reporter/cloudUpload.ts:816
return createHash('md5').update(data).digest('base64');
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
packages/mcp-tools/src/backends/SessionManager.ts:1672
const hash = crypto.createHash('md5').update(parsed.search).digest('hex').slice(0, 6);
LOWFilesystem / path · fs.credential_store · CWE-22, CWE-59
apps/mcp-server/scripts/signingKey.test.ts:5
const KEY_PATH = '/home/someone/.ssh/MCP_registry-key.pem';
Why it matters. touches a credential store
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/cli/src/debugger/index.ts:112
? path.resolve(currentDir, "../../dist/static")
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/cli/src/debugger/index.ts:115
? path.resolve(currentDir, "../../dist/static-embedded")
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/cli/src/debugger/routes/testFlow.ts:12
import { parseYamlTestFile } from "../../yaml-transpiler";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/cli/src/debugger/services/playwrightSandbox.test.ts:5
import { createTestContext } from "../../fixture.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
apps/cli/src/debugger/services/playwrightSandbox.ts:20
import type { TestContext } from "../../fixture.js";
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
apps/cli/src/commands/setupApiToken.e2e.test.ts:20
SHIPLIGHT_WEB_URL: 'http://127.0.0.1:1',
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
apps/cli/src/debugger/routes/emailForwarding.test.ts:61
return `http://127.0.0.1:${port}${path}`;
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
apps/cli/src/debugger/routes/emailForwarding.test.ts:89
process.env.SHIPLIGHT_API_URL = `http://127.0.0.1:${upstreamPort}`;

Gates applied: no_behavioural_pass.

Audited 2026-10-12 · audit v0.4.1 · source sha 32099b12f2cafull audit observations/trust-audit/mcp-server/shiplightai__shiplight-cli.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-1232099b12f2caBLOCKF47first audit
06

Questions

What is the shiplightai MCP server?

AI-powered end-to-end testing for Playwright. Write tests as YAML with natural-language steps, with self-healing locators and a visual debugger.

What tools does shiplightai expose?

74 in total: 57 read-only, 12 that write, and 5 that can delete or overwrite (clear_execution_history, clear_input, clear_logs, reload_page, swipe_points). Every one is listed on this page with its risk.

Is shiplightai safe to connect to an agent?

No — not without reading the findings first. The audit graded it F (47/100) and found 5 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: 5 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does shiplightai need?

It reads ANTHROPIC_API_KEY, CI_COMMIT_AUTHOR_EMAIL, GEMINI_API_KEY, GOOGLE_API_KEY, GOOGLE_GENERATIVE_AI_API_KEY, MCP_REGISTRY_KEY, MCP_REGISTRY_PRIVATE_KEY, MY_KEY, OPENAI_API_KEY and SHIPLIGHT_API_TOKEN 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 shiplightai run?

It speaks stdio, so it runs as a local process your client starts. It is published on npm as shiplight-types at 0.1.0.

How current is this page?

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

Advertisement