Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Description from the maker (original English)
Open a React Native app in a simulated phone: read the screen, tap, type, set device state.
These three are never merged into one score: opinions, measurements and popularity are different things.
We have not written a plain-language summary for this one yet. Below are the facts we read from the registry.
Pick the AI app you use, then copy the settings.
AuthorizationValues marked secret are keys to your account. Never share them or paste them into a chat.
You need
Which app do you use?
Pick your app above. We remember it, so next time the button says “Install in …”.
This address needs a key in a request header, which the add-connector menu cannot set. Use Claude Code, Cursor or VS Code instead.
Open Claude Desktop → Settings → Developer → Edit Config, and paste this into claude_desktop_config.json
{
"mcpServers": {
"shipvo": {
"command": "npx",
"args": [
"-y",
"@shipvo/mcp"
]
}
}
}Run this in your terminal
claude mcp add --transport http shipvo https://sim.shipvo.dev/mcp --header 'Authorization: your-value'claude mcp add shipvo -- npx -y @shipvo/mcpFill in the empty values before running it.
Paste into .cursor/mcp.json in your project, or ~/.cursor/mcp.json
{
"mcpServers": {
"shipvo": {
"url": "https://sim.shipvo.dev/mcp",
"headers": {
"Authorization": "your-value"
}
}
}
}Paste into .cursor/mcp.json in your project, or ~/.cursor/mcp.json
{
"mcpServers": {
"shipvo": {
"command": "npx",
"args": [
"-y",
"@shipvo/mcp"
]
}
}
}Your browser asks to open the app, then the app shows the settings and asks you to confirm. Key values are left empty for you to fill in.
Paste into .vscode/mcp.json in your project
{
"servers": {
"shipvo": {
"type": "http",
"url": "https://sim.shipvo.dev/mcp",
"headers": {
"Authorization": "your-value"
}
}
}
}Paste into .vscode/mcp.json in your project
{
"servers": {
"shipvo": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@shipvo/mcp"
]
}
}
}Your browser asks to open the app, then the app shows the settings and asks you to confirm. Key values are left empty for you to fill in.
This address needs a key in a request header, which the add-connector menu cannot set. Use Claude Code, Cursor or VS Code instead.
Your choice stays on this device in a cookie; no account needed.
Authorization secret required HTTP headerThese settings are generated from the maker’s registry entry. If the README says otherwise, follow the README.
We have not read this server’s tool list yet; we check endpoints in rotation.
We check information anyone can see; we have not read the code. Checks that do not apply are left out of the count. · Checked Nov 6, 2026
The registry name was verified with the GitHub account shipvo, which owns the repo
We have not read this repo from GitHub yet
We have not read this repo from GitHub yet
Not checked yet; we check endpoints in rotation
Not checked yet; we check endpoints in rotation
Not checked yet; we read the tool list when we check the endpoint
Compared with every active server in this category in the registry. Stars count only when the publisher owns the repo.
It passed 1 of 1 applicable basic checks. We have not read the code. Before adding a key or token, see what access the server asks for and use a key with only the permissions you need.
You need to fill in: Authorization
Either way works: install it on your computer or connect to the cloud version.
The GitHub repo last changed –, and the latest version (0.0.6) reached the registry 5 days ago.
Apps that support MCP, such as Claude Desktop, Claude Code, Cursor and VS Code. It connects by URL, so apps that accept remote MCP servers work too, such as ChatGPT in developer mode.
In the same category: Spec Driven Development, Remote Desktop Commander, DiffCI
Servers in the same category from other makers, sorted by stars.
Reading a card:★ GitHub starsiThree pillars: reviews · checks · usageiUpdated = latest version published to the registryi
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Fail-closed, change-aware verification for AI coding agents with affected-test guidance.
Copied from the maker’s repo as written. PopNx MCP has not reviewed or endorsed it. HTML, images and scripts are removed. Links lead off this site.
Lets AI agents (Claude, Cursor, Claude Code, PiPilot…) use a Shipvo app without a phone: open it, read the screen as an accessibility tree, tap, type, scroll, go back, take screenshots, and read what the app sent to its backend. Plus the owner API: change content, prices and offers, and publish to every phone.
{ "mcpServers": { "shipvo": {
"command": "npx", "args": ["-y", "@shipvo/mcp"], "env": { "PN_SIM": "http://localhost:4545", "PN_OWNER_TOKEN": "…optional…" } } } }
Start the simulator first (shipvo sim in the app). The server asks the simulator which app it serves, so open_app(" ") works; set PN_APPS (JSON) to override. If the simulator cannot be reached, only the sample app opens. The hosted version needs no local setup: { "url": "https:// /mcp/ " }.
Each tap, type, scroll and back result starts with a line Change: none | content changed | new screen | scrolled, then the screen. type also adds Value of : "...". Pass compact: true to get only the added (+) and removed (-) lines when the change is content changed; refs match the full screen. If the server has no earlier screen for the session (for example after a reconnect), the first line is Change: unknown. The content changed / new screen split is a heuristic (under half the lines kept means a new screen), so on a short screen one change can read as new screen.
tap, type, scroll and back also take optional fields to wait for the effect instead of sleeping:
wait_for: { ref }, { text } or { role, name } that must appear on the screen, or add gone: true to wait for it to disappear. text and name match as substrings.settle: true: wait until the screen stops changing (two reads 100 ms apart that are equal, ignoring ref numbers).timeout_ms: the most time wait_for and settle may take together (default 2000, at most 30000). One read of the simulator can itself take up to the time limit below, so this is not a hard cap on the call.Refs are renumbered between screens, so with gone: true prefer text or role + name over ref.
The result gets a line Waited: matched | timed out after ms and structuredContent.waited = { matched, ms }. On a timeout the action still happened: the result is the latest screen, it is not an error, and the action's own outcome (such as delivered) is unchanged. Without these fields the result is the same as before.
Time limit. Every call to the simulator stops after 30 s; set SHIPVO_SIM_TIMEOUT_MS to change it. A call that gets no answer returns an error result (isError: true, code sim_timeout, also in structuredContent). The action may still have run and the session may still be alive, so call screen to see where it is. Timed-out actions are not retried.
Error codes. A failed call has isError: true and structuredContent: { ok: false, code, error }. Some failures from other causes (for example a read-only key) have code: null; read error.
| Code | Meaning | What the agent should do |
|---|---|---|
no_session | The simulator has no session with that id (it expired or was never opened). | Call list_sessions, or open_app again. |
stale_ref | The ref is not on the current screen, or the screen changed since it was read. | Call screen and use a ref from the new tree. |
unknown_app | The app id is not one this server or key can open. | Call list_apps and use an id from it. |
sim_timeout | The simulator did not answer in time. The action may have run. | Call screen to see where the app is. Do not repeat the action blindly. |
needs_confirm | An owner command that cannot be undone did nothing and returned a plan. | Show the plan to the owner, then call again with confirm: true. |
bad_url | open_url got a URL the app cannot take. | Fix the URL and call again. |
no_url_listener | The app is not listening for URLs. | Use the app's screens instead. |
phone_locked | The phone is locked, so tap, type, scroll and back were not sent. | Call unlock, then try again. |
already_locked | lock was called on a locked phone. | Call unlock if you want to use the app. |
not_locked | unlock was called on a phone that is not locked. | Carry on; nothing to do. |
mock_invalid | A network mock rule is not valid. | Fix the rule. |
Tools: list_apps, open_app, screen, tap, type, scroll, back, screenshot, set_device, push_notification, notifications, open_notification, device_log, export_test, end_session, owner_describe, owner_command.
export_test { session } is read-only. It turns the taps, typing, scrolls, back and set_device calls recorded in a session into a @shipvo/test script and returns the source. Targets are named by visible text; an ambiguous target becomes a // TODO comment, and a password-like field uses process.env.SHIPVO_TEST_ so the typed value is never in the output. Only sessions opened through this server are recorded; an unknown session returns no_session. Steps are dropped when the session ends. payment.pin is removed from recorded set_device calls. Only labels and roles that look like a password, passcode or PIN are treated as secret; other secret-like fields (card number, token) are exported as typed. type with enter: true and scroll with a ref are recorded without the Enter or the ref, so a replay can differ from the session.
Owner commands that cannot be undone need `confirm: true`. owner_command takes an optional confirm. publish, price changes, offers, deletes and API keys first return { code: "needs_confirm", plan } and do nothing; call again with the same args and confirm: true to run. agentPolicy (ask default, deny, allow) and agentDeny in shipvo.json (read from PN_APP_DIR or the current folder) can only tighten the control plane's rules. Details: docs/agents.md.
Native features work with no phone: the simulated device (see @shipvo/device) shows permission dialogs, the camera, the fingerprint prompt, payment prompts, notification banners and the share sheet as real dialogs in the tree; set_device decides what the phone has (location, a barcode in view, whether the fingerprint matches, whether a payment is approved, network off).
The simulator shows only what a phone would: a horizontal rail lists the visible items, so agents swipe it (scroll right with the rail's ref) exactly as on a device. Measured against a real Android emulator and iPhone simulator, see docs/parity-results.md.
tap, type, scroll and back return structuredContent next to the usual text:
delivery: "delivered" or "not_delivered".not_delivered (the result is also isError): reason is stale_ref, not_visible, disabled or covered, and safe_to_retry is true because nothing reached the app. Take a new screen, then retry.type also returns value, the text the field holds after typing.code, error and the text result are unchanged. Other failures (for example sim_timeout) carry no delivery field: the action may have run, so call screen first.
Run the server where the simulator runs and put it behind HTTPS (a Cloudflare Tunnel is enough):
PN_API_KEYS="key-for-claude,key-for-pipilot" shipvo-mcp --http 8787
Clients connect with a URL instead of a command:
{ "mcpServers": { "shipvo": { "url": "https://sim.shipvo.dev/mcp", "headers": { "Authorization": "Bearer key-for-claude" } } } }
The HTTP endpoint is stateless. There is no protocol session: each POST is handled on its own, and the x-shipvo-* scope headers are read per request, so a scope never carries over to another request. GET and DELETE on /mcp answer 405. Phones are separate: each open_app gets its own phone, and you pass its session as a tool argument.
initialize, then calls, with or without Mcp-Session-Id): work. initialize is answered, no session id is issued, and any Mcp-Session-Id a client sends is ignored.tools/list and tools/call work with no session and no initialize. server/discover is answered (supported versions, tools capability, server info). A request counts as 2026-era if it calls server/discover, sends Mcp-Method, or names a 2026 protocol version in params._meta; those must carry Mcp-Method (and Mcp-Name for tools/call, prompts/get, resources/read) matching the body, or get a 400 JSON-RPC error. Requests with no 2026 marker are not checked. Not done yet: ttlMs/cacheScope on list results. tools/list order is fixed (registration order).@modelcontextprotocol/sdk 1.x (the TypeScript SDK v2 is not stable on npm yet; 1.32.2 is latest). Tested by test/http-stateless.test.ts: discover without initialize, header/body mismatch, scope per request, 2025-era initialize clients. Stdio is unchanged.Requests without a valid key are refused. The hosted version at sim.shipvo.dev will issue keys per account with scopes (test, owner, read).