Skip to main content
Glama
Leuconoe

ryubing-mcp

by Leuconoe

ryubing-mcp

ryubing-mcp is a local Model Context Protocol (MCP) server for controlling the Ryubing Nintendo Switch emulator. It lets an MCP client start isolated emulator sessions, launch a user-owned game, send controller input, capture the rendered frame, and inspect logs.

IMPORTANT

Use theRyubing MCP Bridge custom build to use the complete MCP feature set. An unmodified Ryubing executable works through the Windows patchless compatibility backend, but analog-stick and touchscreen tools are intentionally unavailable there.

Only use game, update, firmware, and key files that you are legally entitled to use. This project does not distribute any of them.

What is included

  • A stdio MCP server for local MCP clients.

  • Managed Ryubing processes with one retained copied profile per title by default.

  • A full control-bridge backend for the recommended custom Ryubing build.

  • A Windows patchless fallback for an unmodified Ryubing executable.

  • Optional game-path confinement.

  • Cursor-based log reading and renderer screenshots.

  • Persistent per-session manifests and NDJSON logs, including after a managed process exits.

  • Installation/environment checks that do not expose key contents.

  • Read-only launch and patch preflight checks.

  • A versioned capability contract exposed as both an MCP tool and resource so clients can discover bridge/patchless limitations without guessing.

  • One-call diagnostic reports with repeated-log and gameplay-failure hints, exportable bundles, and bounded frame sequences for visual-loop evidence.

  • Read-only font-atlas review harness for canvas/alpha/pixel-format, glyph rectangles, clipping, metric drift, and translated-text glyph coverage.

  • A repository-bundled nsw-workspace-cleanup skill that correlates Ryubing and Eden handoffs, manifests, sessions, and artifacts into a read-only cleanup plan.

  • Automated tests and live smoke-test scripts.

Related MCP server: algorithmaide-mcp

Choose a backend

Capability

Custom build (bridge)

Unmodified build (patchless)

Windows managed sessions

Yes

Yes

Status and current title

Yes

Yes, inferred from the process/window

Digital buttons

Players 1-8 and handheld

Player 1 or handheld keyboard bindings

Analog sticks

Yes

Pending / unavailable

Touch tap, hold, and swipe

Yes

Pending / unavailable

Screenshots

PNG and JPEG renderer frames

Native PNG through the configured hotkey

Logs

Structured in-memory bridge logs

Parsed per-session file logs

Base game and session update launch

Yes

Yes

Window focus/hotkey dependency

No

Yes

Recommended for complete MCP use

Yes

Compatibility fallback only

backend: "auto" selects patchless managed sessions on Windows. Therefore, installing the custom build alone is not enough: set backend to bridge in the JSON config when full controller and touch support is required.

Requirements

  • Windows 10/11 for the patchless backend. The bridge backend follows the platform support of the custom Ryubing build.

  • Node.js 20 or newer.

  • A working Ryubing profile containing its Config.json, keys, firmware, and any other data required to boot your games.

  • The custom Ryubing MCP Bridge release for the complete tool set.

Installation

Option A: portable release layout

  1. Download and extract the custom Ryubing build linked above.

  2. Download the matching v0.5.0 MCP package from the GitHub releases page, or clone this repository and build it with npm ci, npm run build, and npm pack.

  3. Extract the generated .tgz; its files are under the package/ directory.

  4. Place the MCP package contents beside Ryujinx.exe and install production dependencies with npm install --omit=dev.

  5. Prepare the portable/ profile directory before creating a session.

  6. Change backend to bridge in ryubing-mcp.config.json.

The resulting directory is self-contained:

ryubing-portable/
|-- Ryujinx.exe
|-- Ryujinx.dll and other Ryubing runtime files
|-- portable/                         # ready profile template copied once per title
|   |-- Config.json
|   `-- system/                       # prod.keys, title.keys, firmware/NAND data
|-- dist/
|   `-- index.js
|-- node_modules/
|-- package.json
|-- ryubing-mcp.config.json
|-- ryubing-mcp.config.schema.json
`-- mcp-sessions/                     # created automatically

Run this once inside the directory:

npm install --omit=dev
node .\dist\index.js

The second command starts an MCP stdio process and normally appears to wait; that is expected. MCP clients start and communicate with it automatically.

Option B: build from source

git clone https://github.com/Leuconoe/ryubing-mcp.git
Set-Location ryubing-mcp
npm install
npm run typecheck
npm test
npm run build

Either copy the custom Ryubing runtime/profile into this directory or keep them elsewhere and point an external JSON config at those paths.

MCP client registration

Zero-environment portable registration

When Ryujinx.exe, portable/, and the default config are beside dist/, no environment variables are required:

{
  "mcpServers": {
    "ryubing": {
      "command": "node",
      "args": ["D:/Apps/ryubing-portable/dist/index.js"]
    }
  }
}

Externally managed config

To keep runtime paths and settings outside the MCP package, inject only the config file path:

{
  "mcpServers": {
    "ryubing": {
      "command": "node",
      "args": ["D:/Apps/ryubing-mcp/dist/index.js"],
      "env": {
        "RYUBING_MCP_CONFIG": "D:/Config/ryubing-mcp.config.json"
      }
    }
  }
}

Use forward slashes or escaped backslashes in JSON paths. Restart the MCP client after changing its server registration or the Ryubing config.

Configuration file

The server loads configuration in this order:

  1. The file named by RYUBING_MCP_CONFIG.

  2. ryubing-mcp.config.json in the MCP process working directory.

  3. ryubing-mcp.config.json shipped beside the server package.

Relative portable.root paths are resolved from the directory containing the selected config. Its three child paths are then resolved from portable.root. Unknown settings and invalid values fail at startup instead of being ignored.

Complete bridge-oriented example:

{
  "$schema": "./ryubing-mcp.config.schema.json",
  "backend": "bridge",
  "portable": {
    "root": ".",
    "executable": "Ryujinx.exe",
    "profileTemplate": "portable",
    "sessionRoot": "mcp-sessions"
  },
  "bridge": {
    "host": "127.0.0.1",
    "port": 49600,
    "timeoutMs": 10000,
    "launchTimeoutMs": 120000
  },
  "managed": {
    "maxSessions": 4,
    "portStart": 49610,
    "startupTimeoutMs": 30000,
    "retention": {
      "keepLatest": 3,
      "olderThanDays": 7,
      "autoPrune": true
    }
  }
}

JSON setting

Default

Description

backend

auto

bridge for full custom-build control, patchless for the Windows fallback, or auto

portable.root

.

Base directory for the following three portable paths

portable.executable

Ryujinx.exe

Custom or unmodified Ryubing apphost; a .dll is also accepted by bridge sessions

portable.profileTemplate

portable

Ready default profile copied for each title's first managed session

portable.sessionRoot

mcp-sessions

Parent directory for isolated session profiles

bridge.host

127.0.0.1

External/default bridge host; loopback values only

bridge.port

49600

External/default bridge port

bridge.timeoutMs

10000

Timeout for each bridge request

bridge.launchTimeoutMs

120000

Longer timeout for game.launch, which may perform application discovery and decryption

managed.maxSessions

4

Concurrent managed-session limit; maximum 32

managed.portStart

49610

First port considered for managed bridge sessions

managed.startupTimeoutMs

30000

Time allowed for a newly launched emulator to become ready

managed.retention.keepLatest

3

Number of newest inactive unbound/exception profiles to retain; canonical title profiles are protected

managed.retention.olderThanDays

7

Remove inactive profiles older than this many days; active processes are never removed

managed.retention.autoPrune

true

Run the safe inactive-profile cleanup before creating and after stopping a session; explicit cleanup remains available when disabled

allowedGameDirs

omitted

Optional array of permitted game/update roots; omitted means unrestricted

To restrict launchable files, add an allowlist. Relative entries are resolved from the config directory:

{
  "allowedGameDirs": [
    "games",
    "E:/NSW/_titles/_waitng"
  ]
}

allowedGameDirs is not required. Leave it out when arbitrary absolute game paths must be usable. A configured allowlist rejects files outside its roots.

Optional environment overrides

Operational settings should normally remain in JSON. These variables exist for legacy launchers, CI, and secret injection, and override JSON when present:

Environment variable

Purpose

RYUBING_MCP_CONFIG

Select one external JSON config; normally the only injected variable

RYUBING_BACKEND

Override backend

RYUBING_CONTROL_HOST

Override external bridge host

RYUBING_CONTROL_PORT

Override external bridge port

RYUBING_CONTROL_TOKEN

Inject the external bridge bearer token without storing it in JSON

RYUBING_CONTROL_TIMEOUT_MS

Override bridge request timeout

RYUBING_GAME_LAUNCH_TIMEOUT_MS

Override the operation-specific game.launch timeout

RYUBING_ALLOWED_GAME_DIRS

Platform-delimited path allowlist override

RYUBING_EXECUTABLE

Override the managed executable path

RYUBING_PROFILE_TEMPLATE

Override the profile-template path

RYUBING_SESSION_ROOT

Override the session-root path

RYUBING_SESSION_PORT_START

Override the first managed bridge port

RYUBING_MAX_SESSIONS

Override the managed-session limit

RYUBING_SESSION_STARTUP_TIMEOUT_MS

Override managed startup timeout

Profile and session model

There are two kinds of session:

  • default represents an emulator bridge started outside this MCP server at bridge.host:bridge.port. Omitting sessionId targets it.

  • A managed session is created by ryubing_create_session. A title's first session copies the configured ready default profile, including Config.json, system/ keys, and registered firmware/NAND. Later calls for that title reuse the running process or restart the retained profile instead of cloning again.

  • Each managed profile contains .ryubing-mcp-session.json and .ryubing-mcp/logs.ndjson. The manifest records lifecycle phase, last status, launch paths, exit code, and the last error. These files are retained when a process exits so diagnostics can distinguish a game failure from an MCP or bridge connection failure.

  • Base, update, and child-program IDs belonging to one application share one title-session owner. For example, ...6000, ...6001, and ...6005 all map to the ...6000 owner. Exact patch paths and runtime evidence must still use the actual child program ID selected by the emulator.

For normal automation, use managed sessions:

  1. Call ryubing_check_environment and resolve every error before a runtime test.

  2. Call ryubing_validate_launch with the base/update paths. Resolve every error before starting a title.

  3. Call ryubing_create_session with the validated applicationId. Normally omit sessionId; the server selects title-<applicationId> and returns the existing title session when one is already active.

  4. Call ryubing_launch_game with the returned sessionId and use waitFor: "running" when the caller needs a readiness guarantee. A timeout is returned as retryable evidence by default; continue with ryubing_wait_for_state instead of issuing a second launch.

  5. Use input, screenshot, frame-sequence, and log tools with the same sessionId.

  6. If the game does not progress, call ryubing_get_diagnostics and, when sharing evidence, ryubing_export_diagnostics before stopping.

  7. Call ryubing_stop_session when finished and retain the profile for diagnosis.

Tool-level failures use a stable JSON envelope even when the MCP result has isError: true:

{
  "error": {
    "code": "SESSION_TITLE_CONFLICT",
    "message": "...",
    "retryable": false
  }
}

Callers should inspect isError and error.code before consuming the result. Timeout/readiness errors are marked retryable when the existing session can be polled safely. The managed launcher also removes MCP configuration overrides from the child emulator environment and injects only the per-session control token and launch-specific variables.

ryubing_launch_game requires an explicit sessionId, including sessionId: "default" when intentionally using an externally started bridge. This prevents a caller that created a managed session from accidentally sending the next title to the unrelated default emulator. Each normal managed session is bound to one normalized application ID, and only one canonical managed session may own that ID. Base/update paths for the same application ID can change inside that retained session; a different title is rejected with SESSION_TITLE_CONFLICT. Concurrent launches for one session are rejected with SESSION_LAUNCH_IN_PROGRESS, so a timed-out request must be observed with ryubing_wait_for_state rather than retried. Until a wait reaches a requested state, another launch is rejected with SESSION_LAUNCH_OUTCOME_UNKNOWN, even when it targets the same title.

The ready template is copied only for a title's first session, so the original default emulator profile is never rewritten. A stopped canonical title profile is automatically protected from retention and restarted in place; its copied keys, firmware, saves, title keys, and settings therefore remain available. Use removeProfile: true only when deliberately discarding that title profile. Unbound sessions and reason-authorized parallel comparison sessions remain subject to normal inactive retention so exceptions do not become another unbounded storage source. Active processes and unrecognized directories are never removed.

Patchless sessions also create a hard-linked runtime mirror, falling back to normal copies when hard links are unavailable. This gives every process an isolated Logs directory without normally duplicating the entire runtime. Native PNG files used for patchless screenshots are temporary MCP evidence and are pruned before and after each capture; returned image data remains available to the MCP caller without building an unbounded screenshots/ archive.

MCP tool reference

Most emulator-control tools accept optional sessionId; omit it only when you intentionally target an externally started default bridge. ryubing_launch_game is the exception and requires an explicit ID to prevent title/session mix-ups.

ryubing_create_session

Starts a managed process and returns its session metadata and initial status. For normal use, provide the 16-digit base applicationId and omit sessionId; the stable ID is title-<applicationId>. Repeating the call returns the running canonical session (reusedExisting=true) or restarts its retained profile (reusedProfile=true). It does not recopy the template or require keys and firmware to be injected again. reuseExisting remains only for legacy unbound profiles.

Creating an unbound session or a deliberate second session for the same title requires exceptionReason (10-500 characters), for example a simultaneous baseline/patched comparison. The reason is persisted in the owned manifest. Without it, duplicate creation fails with TITLE_SESSION_EXISTS and identifies the session to reuse.

ryubing_list_sessions

Lists the external default entry plus all managed sessions, including backend, state, PID, port where applicable, and profile directory.

ryubing_stop_session

Stops one managed process. sessionId is required. removeProfile defaults to false; setting it to true recursively removes that isolated profile after the process exits. Canonical title profiles are protected automatically so they can be restarted without key/firmware setup. protectProfile: true remains useful for unbound or exception sessions whose evidence must survive automatic retention. The external default session cannot be stopped here.

ryubing_get_session_storage

Returns a read-only inventory of directories directly under portable.sessionRoot, including ownership classification (active, reclaimable, protected, legacy, or unconfirmed) and byte estimates. Owned entries also expose applicationId and any duplicateTitleReason, making pre-existing same-title profiles identifiable before explicit removal. Directories without a matching MCP manifest are reported but never removed by automatic cleanup.

ryubing_cleanup_sessions

Lists or removes inactive managed profiles under portable.sessionRoot. dryRun defaults to true; set it to false only after reviewing the matched session IDs, paths, and byte estimate. The default policy keeps the newest three inactive profiles and removes profiles beyond that count or older than seven days. Canonical title profiles are excluded; remove one explicitly with ryubing_stop_session(removeProfile=true) when it is no longer needed. The cleanup tool only accepts MCP manifests directly under the configured session root, skips active PIDs, and never scans games, saves, keys, firmware, patches, or arbitrary directories. It still works when managed.retention.autoPrune is disabled.

Ryubing/Eden workspace cleanup skill

The repository includes skills/nsw-workspace-cleanup for shared title workspaces used by Ryubing MCP and Eden MCP. Cleanup is inferred from the complete handoff chain, exact paths and hashes, title/project IDs, ownership manifests, active PIDs, and pending review state. Names such as tmp, copy, old, or a timestamp and duplicate hashes are never deletion authority by themselves.

The bundled collector is read-only and rejects --apply/--delete. Supply the title or repository roots, both emulators' relevant handoffs, and their session roots when applicable:

node .\skills\nsw-workspace-cleanup\scripts\build-cleanup-context.mjs `
  --root "E:\NSW\_titles\Title [0100000000000000]" `
  --handoff "D:\workspace\____personal____\ryubing-mcp\HANDOFF.md" `
  --handoff "D:\workspace\____personal____\eden-mcp\HANDOFF.md" `
  --session-root "ryubing=E:\NSW\_tools\Ryubing\mcp-bridge-v0.1.0\sessions" `
  --session-root "eden=E:\NSW\_tools\Eden\mcp-v0.4.0\sessions" `
  --json

Use the resulting snapshot to generate cleanup-plan.v1 with exact KEEP, REVIEW, and ELIGIBLE_AFTER_APPROVAL records. A failed candidate can still be the only evidence for an open diagnosis; an artifact referenced by either emulator remains protected. If the inventory is truncated, a handoff is missing, or title/session ownership conflicts, the plan must be BLOCKED. Actual cleanup requires a separate user approval of exact instruction IDs and a fresh matching snapshot. Prefer each emulator's MCP retention tools for owned sessions and diagnostic bundles.

ryubing_get_status

Returns protocol/emulator version, process ID, state, title ID/name, and frame dimensions where available. States are idle, loading, running, paused, or stopping.

ryubing_get_capabilities

Returns the emulator-mcp-capabilities contract version 1.0 for the selected session. It explicitly reports bridge-only analog/touch/multi-touch support, available launch/capture/diagnostic operations, and current limitations. The same default-session contract is available through the emulator://ryubing/capabilities MCP resource for clients that discover capabilities before selecting a tool.

ryubing_check_environment

Checks the managed executable, profile template, Config.json, standard system/prod.keys and system/title.keys locations, registered firmware, allowlisted game roots, session-root write access, and the selected session. The result has overall: "ok", "warning", or "error" plus a checks array; it does not read or return key contents. Set probeControl: true to query the selected bridge status as part of the report. This is the first tool to call when setup or firmware/key installation is uncertain.

Ryubing uses profile/system/ for keys with --root-data-dir. A legacy profile/keys/ directory is reported as a warning and is not treated as a successful standard key installation.

ryubing_press_buttons

Presses one or more buttons simultaneously and releases them after durationMs (16-10000, default 100). player is 1-8 or handheld.

Supported button names:

A B X Y L R ZL ZR PLUS MINUS L_STICK R_STICK
DPAD_UP DPAD_DOWN DPAD_LEFT DPAD_RIGHT
SL_LEFT SR_LEFT SL_RIGHT SR_RIGHT

Patchless mode accepts only Player 1/handheld and maps these names through the WindowKeyboard bindings in the copied profile's Config.json.

ryubing_set_sticks

Sets any supplied leftX, leftY, rightX, or rightY coordinate in the inclusive range -1 to 1. At least one axis is required. durationMs: 0 retains the state; a positive duration up to 60000 resets both sticks afterward. Requires the custom bridge build.

ryubing_touch

Sends tap, long_press, or swipe using Switch logical-screen coordinates: x 0-1279 and y 0-719. A swipe also requires endX and endY. durationMs is 16-10000. Requires the custom bridge build.

ryubing_take_screenshot

Returns metadata plus MCP image content. Bridge mode accepts png or jpeg and JPEG quality 1-100. Patchless mode accepts PNG only, invokes Ryubing's screenshot hotkey, and waits for the renderer PNG in the session profile. Before bridge capture, the MCP checks control.status and requires non-zero frameWidth/frameHeight; an early request returns retryable SCREENSHOT_NOT_READY without calling the renderer capture path.

ryubing_get_logs

Reads up to 2000 entries (limit, default 200). Levels are trace, debug, info, notice, warning, error, and critical. Pass the returned nextCursor as the next call's cursor to receive newer entries only. The optional contains value performs a case-insensitive match against each entry's category and message and returns filter metadata while preserving the source cursor.

ryubing_get_diagnostics

Collects a shareable JSON report without stopping or restarting the emulator. It includes a reportVersion, capture time, selected session metadata, runtime backend/platform, status, the requested trace-to-error log window, cursor/truncation state, level counts, repeated-message first/last cursors, and up to 100 warning/error/negative-log events with surrounding context. It still returns logs when status collection fails; the errors object identifies which part failed.

The focus argument prioritizes one of the common failure patterns:

focus

What it looks for

game_load_failure

stuck loading/stopping state and boot/load/guest errors

patch_loop

repeated patch/mod/LayeredFS/RomFS/ExeFS/retry messages

video_loop

repeated video/movie/cutscene/NVDEC/codec/decoder messages

patch_not_applied

explicit missing, skipped, disabled, invalid, or failed patch messages

all

all four heuristic categories (default)

Hints are evidence-based heuristics, not a proof of the root cause. Each hint contains summary, bounded evidence, and recommendations; a focused call with no matching signature returns a low-confidence “inconclusive” hint rather than an empty result. Always pass the original logs.entries, observations.events, and observations.repeatedMessages to the report when escalating an issue. A useful capture is:

{
  "sessionId": "qa-01",
  "cursor": "0",
  "limit": 2000,
  "minimumLevel": "trace",
  "focus": "all"
}

Capture a fresh diagnostic after the failure, before launching another title or deleting the managed profile; the retained profile and cursor make repeated failures comparable.

When the managed process has already exited, the tool falls back to the manifest's last status and the persisted NDJSON log. The report exposes sources.status (live or manifest) and sources.logs (live or persisted) and adds a warning instead of hiding the original failure behind ECONNREFUSED.

ryubing_export_diagnostics

Collects the same report and writes report.json, the captured logs.ndjson, and a SHA-256 manifest.json under the selected managed profile's .ryubing-mcp/diagnostics/<timestamp>-<pid>/ directory. The result includes the exact paths, byte count, and redaction count. Absolute paths and secret-like fields or inline values are redacted by default. Export is local-only; game contents, screenshots, keys, firmware, and environment variables are not copied. Only set redact: false when the bundle remains on the same trusted machine.

ryubing_get_runtime_metrics and ryubing_advise_compatibility

The metrics tool summarizes bounded FPS and frame-time samples plus shader and video-failure signals found in structured logs. Missing counters remain null or empty instead of being estimated. The advisor combines those metrics with diagnostic hints and returns reversible, one-variable experiments with their reason, tradeoff, and rollback. It never changes emulator settings.

ryubing_list_artifacts and ryubing_cleanup_artifacts

Artifact listing is limited to Ryubing MCP's exact diagnostic-directory naming convention. Cleanup applies age and keep-latest retention to the same bounded set and defaults to dryRun: true. It does not scan or delete games, managed profiles, saves, patches, keys, firmware, or arbitrary user files.

ryubing_capture_sequence

Captures 2-12 frames at a bounded interval (50-10000 ms). The metadata includes SHA-256 hashes, dimensions, optional bridge frame numbers, byte sizes, and changedFromPrevious. It classifies exact-byte sequences as frozen, periodic, or moving and reports the period and compared pairs. Image blocks are included only while the total payload is under 24 MiB. Exact PNG/JPEG hashes are strong evidence for identical output but less tolerant than Eden MCP's grayscale perceptual comparison; compression differences can make equivalent frames appear changed.

ryubing_run_input_script

Validates all operations before sending the first input, then executes up to 100 wait, buttons, sticks, touch, or wait_frame_change steps. The declared wait/hold/timeout budget is limited to five minutes. Each result contains the operation, duration, success, and result or failure. Stick players touched by the script are reset to zero after failure and by default after completion.

{
  "sessionId": "qa-01",
  "steps": [
    {"op":"buttons","buttons":["L","R"],"player":1,"durationMs":120},
    {"op":"buttons","buttons":["A"],"player":1,"durationMs":80},
    {"op":"wait_frame_change","timeoutMs":10000,"pollMs":500}
  ]
}

Patchless sessions support wait, buttons, and screenshot-based frame checkpoints. Stick and touch steps return the existing explicit Pending error and the script preserves completed-step evidence.

ryubing_validate_launch

Performs the launch checks without starting Ryubing: path allowlist and extension, file/directory metadata, filename title-ID hints, and base/update compatibility. overall: "error" blocks ryubing_launch_game; warnings are non-fatal but should be reviewed.

ryubing_inspect_patch

Scans an unpacked patch directory without modifying it. It reports title-ID hints, romfs/exefs/LayeredFS markers, patch archive extensions, duplicate relative paths, file count, and total bytes. This is a layout check only; it does not decrypt NCA files or prove that a translation rendered in-game.

For the current Ryubing profile layout, install mods under mods/contents/<program-id>/<mod-name>/romfs|exefs, or Atmosphere-compatible content under sdcard/atmosphere/contents/<program-id>/. A legacy load/ directory is not searched by this build. In a multi-program title, <program-id> is the exact child ID that consumes the patch, not necessarily the base application ID used for session ownership.

ryubing_validate_font_atlas

Runs a read-only before/after check for a translated PNG font atlas. Supply the original atlas, candidate atlas, a JSON glyph map, and the translated text sample used for required glyph coverage. The map can be a single glyphs array, separate reference/candidate arrays, or section objects with glyphs and kernings. Each glyph identifies one Unicode code point and its x, y, width, height, optional advance, baseline, and signed offsetX/offsetY (xOffset/yOffset aliases are accepted). Kerning records identify first, second, and signed amount values.

The harness fails on canvas or pixel-format changes, missing alpha, duplicate or overlapping rectangles, out-of-bounds glyphs, empty/clipped candidate glyphs, position/advance/baseline/offset/kerning drift, suspicious ink-size or occupancy changes, and missing glyphs in the supplied translated text sample. PNG and map sizes, decompression output, glyph count, rectangle work, and overlap comparisons are bounded to keep malformed inputs from exhausting the MCP process.

A clean first run is PENDING_USER_REVIEW and returns approval.reviewToken. That token binds the reference PNG, candidate PNG, glyph-map JSON, translated text, and tolerances. After the user approves the exact before/after evidence, rerun with approvedReviewToken set to that token. Any artifact or parameter change invalidates it with APPROVAL_TOKEN_MISMATCH; a boolean approval flag is not accepted. This static PASS is still not a runtime or release PASS.

Example glyph map:

{
  "reference": [{"codePoint":"U+AC00","x":2,"y":2,"width":32,"height":40,"advance":32,"baseline":30,"offsetY":-2}],
  "candidate": [{"codePoint":"U+AC00","x":2,"y":2,"width":32,"height":40,"advance":32,"baseline":30,"offsetY":-2}],
  "referenceKernings": [{"first":"U+AC00","second":"U+B098","amount":-1}],
  "candidateKernings": [{"first":"U+AC00","second":"U+B098","amount":-1}]
}

Keep failed candidates and the returned SHA-256 values in the title-local QA evidence. Fix the atlas in a new temporary staging path, rerun the harness, and request user review again; never overwrite the only reference/candidate pair.

ryubing_launch_game

sessionId is required. Use the returned ID from ryubing_create_session, or use the literal default only when the external bridge is the intended target. The server checks the bridge state before launching, serializes launches per session, and verifies any reported title ID against the requested application. Once a session has a launch identity, switching to another title is blocked. A different base/update path with the same normalized application ID stays in that title's existing session.

Launches an absolute .xci, .nsp, .nca, .nro, or unpacked game directory. Optional updatePath must be a matching update .nsp. The update applies only to the isolated session. Supply the 16-digit hexadecimal applicationId when the update filename does not expose a title ID.

For a user-owned encrypted dump that requires an external title key, either call ryubing_inject_title_key first or pass the same object as titleKey on ryubing_launch_game:

{
  "sessionId": "qa-01",
  "basePath": "E:/Games/Example.nsp",
  "titleKey": {
    "rightsId": "00112233445566778899AABBCCDDEEFF",
    "key": "FFEEDDCCBBAA99887766554433221100"
  }
}

Both values must be exactly 32 hexadecimal characters. Injection is limited to an idle isolated managed session and atomically merges into that session's system/title.keys; the external default profile and profile template are never changed. The key itself is not returned. Repeating the same pair is a no-op. A different key for an existing Rights ID fails with TITLE_KEY_CONFLICT unless overwrite: true is included. Ryubing reloads the session key set as the title is initialized, so launch-time injection does not require restarting the managed process.

waitFor defaults to "accepted" for compatibility. Set it to "running" to poll the selected bridge until control.status.state is running; the bounded waitTimeoutMs (default managed.startupTimeoutMs) returns targetReached=false, timedOut=true, and retryable=true without stopping the selected process. Set keepRunningOnTimeout=false only when legacy tool error behavior is required. bridge.launchTimeoutMs is a separate, longer timeout for the launch RPC itself.

If that RPC deadline expires before the bridge acknowledges the launch, the default result is also non-terminal: launch.accepted is "unknown", launch.requestTimedOut=true, and retryable=true. This does not prove that the emulator rejected the game. Keep the owned process, poll ryubing_wait_for_state, and collect diagnostics from that session. Do not issue a second game.launch while the first request's outcome is unknown; SESSION_LAUNCH_OUTCOME_UNKNOWN remains active until a state wait reaches its target or the session is stopped/recreated.

ryubing_wait_for_state

Continues polling the existing selected session for idle, loading, running, paused, or stopping without sending another game.launch. Use it after a retryable launch timeout. The response includes the last status/error, elapsed time, and whether another wait remains safe.

Example call arguments:

{
  "sessionId": "qa-01",
  "basePath": "E:/NSW/_titles/_waitng/Example [0100000000000000].xci",
  "updatePath": "E:/NSW/_titles/_waitng/Example Update [0100000000000800].nsp",
  "applicationId": "0100000000000000"
}

Full bridge security model

  • The bridge binds only to 127.0.0.1, ::1, or localhost; remote network control is deliberately unsupported.

  • Managed bridge sessions choose separate ports and generate a cryptographically random token for each process.

  • On Windows the token is passed through a per-session token file rather than a visible command-line argument.

  • The MCP server validates protocol version 0.1, input ranges, paths, response IDs, screenshot encoding, and screenshot size.

  • Keep MCP access local and do not expose stdio or bridge ports through an unauthenticated network proxy.

Patchless behavior and limitations

Patchless mode is a compatibility implementation, not the complete control protocol. It:

  • Detects PID, emulator version, title name, and title ID from the process and Ryubing window title.

  • Delivers configured digital keyboard keys directly to the Ryubing window.

  • Uses Ryubing's configured screenshot hotkey and returns the new PNG.

  • Parses the latest isolated runtime log using a numeric cursor.

  • Writes a session-local games/<titleId>/updates.json when an update is used, then restarts Ryubing with the base game path.

  • Returns a clear Pending error for analog-stick and touch requests.

Because it relies on native window/input behavior, keyboard bindings must exist and security or overlay software may interfere. Switch to backend: "bridge" before treating input automation as release-quality evidence.

Troubleshooting

First response for any abnormal gameplay

Do not immediately restart, delete the profile, or apply another patch. Preserve the failing session so its cursor and profile remain useful:

  1. Call ryubing_check_environment({"sessionId":"qa-01","probeControl":true}).

  2. Call ryubing_get_status({"sessionId":"qa-01"}).

  3. Call ryubing_get_diagnostics with cursor: "0", limit: 2000, minimumLevel: "trace", and the most relevant focus value below.

  4. Save the complete JSON response, emulator build, firmware version, title ID, base/update paths, session ID, and the fresh screenshot separately.

  5. Only then restart the title or try one controlled change.

The diagnostic hints are heuristics. A loader message, a running process, or a successful patch copy alone does not prove that the game reached the expected screen or that Korean data was rendered.

Game does not load or remains on loading

Run ryubing_validate_launch first and resolve any title-ID mismatch. Then use focus: "game_load_failure". Check the environment report first: the executable, profile, system/prod.keys, system/title.keys, and registered firmware must be present. Confirm the base path exists and that an update is matched to the base title. If the update filename does not contain the base title ID, pass applicationId explicitly. Compare status.state, titleId, and the last load/guest/error entries in the diagnostic report.

Wrong patch causes a loop or prevents progression

Run ryubing_inspect_patch on each candidate and keep its output with the report. Then use focus: "patch_loop". Inspect observations.repeatedMessages and the patch_loop evidence rather than only the final error. Keep exactly one enabled patch candidate for the selected title root, verify the consumer title ID, and restart the title after changing patch files. A retained managed profile should be used for the before/after comparison; do not mix a default profile log with a managed-session result.

Video or cutscene repeats instead of progressing

Use ryubing_capture_sequence first, then focus: "video_loop" and the complete diagnostic log window. Look for repeated NVDEC, codec, decoder, movie, cutscene, media, or frame messages. Separate a video decoder failure from a patch loop: the process can remain running while the render surface is not advancing. Record the title ID, firmware, graphics backend, and whether the same scene repeats after a clean unpatched launch.

Patch exists but Korean data is not displayed

Use focus: "patch_not_applied". Verify that the patch is staged under the actual consumer title ID, that only the intended candidate is enabled, and that the managed profile is the profile being launched. Restart the title after staging; LayeredFS/ExeFS or file-copy messages are not proof that the selected translation reached the rendered text. Compare a baseline capture with a fresh patched capture and retain both diagnostic reports.

Keys or firmware were installed manually but the game still fails

For a --root-data-dir profile, Ryubing reads key files from <profile>/system/, not <profile>/keys/. Use the environment report to detect the legacy location. Supply a real firmware ZIP containing NCA entries; an incomplete archive or an unrelated executable ZIP will fail before installation. New titles receive the corrected ready template automatically. An existing canonical title session intentionally retains its own working copy to avoid repeated key/firmware setup; correct that profile in place, or explicitly stop it with removeProfile: true and create it again with the same applicationId when a full reset is intended.

Ryubing MCP config file not found

Check RYUBING_MCP_CONFIG, use an absolute path, and remember that JSON paths need forward slashes or escaped backslashes.

Managed executable or profile does not exist

Confirm portable.root, portable.executable, and portable.profileTemplate. The executable must be a file and the template must already be a usable directory. sessionRoot is created automatically.

Bridge startup/readiness timeout

Verify that the executable is the custom bridge release and that config uses backend: "bridge". Increase managed.startupTimeoutMs for slow firmware/game startup. The managed session searches available loopback ports beginning at managed.portStart.

Pending: analog stick or Pending: touchscreen

The session is using patchless mode. Install the custom build and explicitly set backend to bridge.

Patchless button is unbound or unsupported

Open the template profile in Ryubing and configure Player 1 WindowKeyboard bindings so new titles inherit them. For an existing canonical title session, either update its copied Config.json or explicitly remove and recreate that title profile.

Patchless screenshot times out

Confirm the screenshot hotkey in Config.json is bound and that Ryubing can write PNG files under the session profile's screenshots/ directory.

Game path is rejected

Use an absolute supported path. If allowedGameDirs is present, the real file must be inside one of those directories. Remove the setting to allow all paths.

Update title ID cannot be inferred

Pass the base game's 16-digit applicationId explicitly. Do not pass the update title ID ending in the update suffix.

Old session directory already exists

Call ryubing_create_session with the same applicationId; a canonical title profile is restarted in place automatically. reuseExisting: true is only for legacy unbound profiles. If an intentional reset is required, remove the previous session through ryubing_stop_session with removeProfile: true and then create it again. Directories without a valid MCP manifest are never deleted automatically.

Emulator exits without an error log

When a managed process exits with exitCode: null and the persisted log has no error or critical entry, diagnostics label the result as an inconclusive runtime anomaly. A briefly reported child program, connection refusal after exit, or absence of patch-loader records does not prove that the title or patch failed. Preserve the session, collect diagnostics, and require an exact child program plus PatchExeFS/PatchRomFS evidence before assigning a patch verdict.

Verification and development

Run the local quality checks:

npm run typecheck
npm test
npm run build

With an external bridge already running at the configured default endpoint:

npm run smoke:live

For two managed patchless processes, configure the managed paths and set RYUBING_LIVE_BASE_A, RYUBING_LIVE_UPDATE_A, and RYUBING_LIVE_BASE_B before running:

npm run smoke:parallel

The smoke tests require user-owned games and are not part of the normal unit test run.

For a read-only preflight matrix over a directory such as E:/NSW/_titles/_waitng, set the directory outside the MCP process config and run:

$env:RYUBING_GAME_MATRIX_DIR = 'E:\NSW\_titles\_waitng'
npm run qa:matrix

The matrix reports one ryubing_validate_launch result per .xci, .nsp, .nca, or .nro file. It does not launch games or copy/modify their files; use it before a controlled runtime matrix with one retained managed profile per title.

Releases and source

License

This MCP server is licensed under the MIT License. Ryubing and its dependencies retain their respective licenses.

Available Tools

10 tools
ryubing_create_sessionCreate isolated Ryubing sessionA

Start a new Ryubing process with an isolated profile, bridge port, and authentication token.

ParametersJSON Schema
NameRequiredDescriptionDefault
sessionIdNoStable session ID; omit to generate one

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate a mutating operation (readOnlyHint=false), and the description adds meaningful context about what the session includes (isolated profile, bridge port, authentication token). It does not mention process lifecycle, resource usage, or that sessions should be stopped later, but the key side effect of starting a process is disclosed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, concise sentence that is front-loaded with the action ('Start a new Ryubing process') and adds essential details without redundancy. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a low-complexity tool with one optional parameter and no output schema, the description covers the core purpose and key behavioral elements. It does not mention return values or explicitly tie to stop_session, but the overall context from annotations and the simple schema makes it reasonably complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema fully describes the single parameter (sessionId) with pattern and description, so baseline is 3. The tool description does not add extra parameter semantics beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Start') and resource ('Ryubing process') with distinct attributes ('isolated profile, bridge port, authentication token'), clearly differentiating it from siblings like list_sessions and stop_session. The title confirms the creation nature.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the tool name and description (creates a session before other actions), but there is no explicit guidance on when to use it vs alternatives, prerequisites, or exclusions. Sibling tools suggest lifecycle but the description itself lacks direct instructions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ryubing_get_logsGet Ryubing logsA
Read-only

Read structured emulator logs. Pass the returned cursor to get only newer entries on the next call.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
cursorNo
sessionIdNoManaged Ryubing session ID; omit for the external default session
minimumLevelNoinfo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, establishing the safe read-only nature. The description goes beyond annotations by disclosing the cursor-based incremental pagination behavior, which is not evident from schema or annotations. This adds meaningful behavioral context without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description consists of two concise front-loaded sentences. The first clearly states the core purpose, and the second provides a crucial operational detail without any redundancy or fluff. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 4 optional parameters and no output schema, the description is adequate but minimal. It covers the key pagination concept and benefits from strong read-only annotations. However, it does not mention filtering by minimum level, default limits, or what the response structure looks like beyond implying a cursor, leaving some gaps for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is low (25%, only sessionId has a description). The description adds meaning to the cursor parameter by explaining its role in fetching newer entries. However, limit and minimumLevel are not elaborated in the description, though their names and schema defaults provide some intrinsic semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description 'Read structured emulator logs' uses a specific verb ('read') and resource ('structured emulator logs'), clearly distinguishing it from sibling tools that control the emulator or manage sessions. Even though the title says 'Get logs', the description adds 'structured' and clarifies the read-only nature, making the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when logs need to be retrieved, but does not explicitly discuss alternatives or when not to use the tool. However, the cursor instruction ('Pass the returned cursor to get only newer entries on the next call') provides a clear usage tip for incremental reading, which adds some guidance beyond mere implication.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ryubing_get_statusGet Ryubing statusA
Read-onlyIdempotent

Check bridge compatibility and the currently running game.

ParametersJSON Schema
NameRequiredDescriptionDefault
sessionIdNoManaged Ryubing session ID; omit for the external default session

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and idempotentHint=true, so the agent knows this is a safe read operation. The description adds the specific items being checked but does not disclose response format or potential edge cases. This is adequate for a simple status tool but not rich behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise sentence, front-loaded with the action and outcome. Every word earns its place with no redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple tool with one optional parameter and no output schema, the description names the two key outputs (bridge compatibility and running game). However, it does not elaborate on what 'bridge compatibility' means or the response structure, which would be helpful given no output schema. Overall, it is fairly complete for the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema fully describes the single optional parameter sessionId with a pattern and explanation, giving 100% schema coverage. The description adds no additional parameter details, so the baseline score of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function with a specific verb 'Check' and identifies exactly what it reports: bridge compatibility and the currently running game. This distinguishes it from sibling tools like launch_game, stop_session, and take_screenshot, which perform different actions.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use when you need to verify status or compatibility, but it provides no explicit guidance on when to prefer this over other tools like get_logs or list_sessions. No alternatives or exclusions are mentioned, so usage context is only implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ryubing_launch_gameLaunch a Switch gameA

Launch a user-owned base game file, optionally applying a matching update for this session only.

ParametersJSON Schema
NameRequiredDescriptionDefault
basePathYesAbsolute path to .xci, .nsp, .nca, .nro, or an unpacked game directory
sessionIdNoManaged Ryubing session ID; omit for the external default session
updatePathNoAbsolute path to a matching update .nsp

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are all false, indicating a mutating, non-idempotent, non-destructive operation. The description adds the behavioral detail that updates apply only for the session, which is useful. However, it does not mention potential side effects like starting or stopping the emulator, or any state changes beyond the session update.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence, front-loaded with the verb 'Launch,' and conveys the essential purpose and optional behavior with zero waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple launch tool with three well-documented parameters and no output schema, the description plus schema provides sufficient context. It could have mentioned what the return value or success/failure indication looks like, but that is not strictly necessary for invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with all three parameters already well-described (e.g., basePath formats, sessionId format, updatePath purpose). The description adds no new parameter semantics beyond the schema, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Launch a user-owned base game file' with a specific verb and resource, and mentions the optional update application. It is immediately distinguishable from sibling tools like ryubing_get_status or ryubing_take_screenshot.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies clear usage: to start a game, possibly with an update. It does not explicitly name alternatives or exclusions, but the context of launching a game is unambiguous given the sibling set. The mention of 'for this session only' also provides a usage constraint.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ryubing_list_sessionsList Ryubing sessionsA
Read-onlyIdempotent

List the external default bridge and all managed Ryubing processes.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds specificity about the list's contents, but does not disclose any additional behavioral traits like return format or whether authentication is needed. This matches the baseline where annotations do the heavy lifting.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single focused sentence with no filler or repetition. It efficiently conveys the tool's purpose without wasting words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a simple list operation with no parameters and no output schema. The description sufficiently indicates what will be listed, though it does not explicitly mention the return format. Given the tool's simplicity, this is adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, and schema coverage is trivially 100%. The baseline for no parameters is 4, and the description correctly does not attempt to describe non-existent parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses the specific verb 'List' and names the exact resources ('external default bridge and all managed Ryubing processes'), making the purpose unmistakable and distinguishing it from sibling tools like get_status or create_session.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool rather than alternatives such as ryubing_get_status or ryubing_stop_session. The description states only what the tool does, not the context or conditions for its use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ryubing_press_buttonsPress Switch buttonsA

Press one or more Nintendo Switch controller buttons simultaneously, then release them after a duration.

ParametersJSON Schema
NameRequiredDescriptionDefault
playerNoController player number or handheld mode
buttonsYesButtons to press together
sessionIdNoManaged Ryubing session ID; omit for the external default session
durationMsNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses the key behavioral trait: buttons are pressed simultaneously and held for a specified duration before release. Annotations provide no safety hints (all false), so the description carries the burden, and it does so well for a simple input tool. It does not mention side effects like blocking or output, but these are not critical.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that front-loads the action and outcome. Every word is necessary and there is no fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple action tool, the description covers the core behavior and timing. The schema handles parameter details. It lacks an explicit statement about return values, but no output schema exists, and the action is straightforward enough that this is not a significant gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 75% (3 of 4 params have descriptions). The description itself does not add detail about parameters beyond what the schema provides, and durationMs is left without a description. The baseline for high schema coverage is 3, and the description does not compensate for the missing parameter description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: pressing one or more Nintendo Switch controller buttons simultaneously and releasing after a duration. It uses a specific verb ('Press') and resource ('Switch controller buttons'), and is distinct from sibling tools like ryubing_set_sticks or ryubing_touch.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly implies the tool is for button inputs, and no exclusions are stated. However, it does not explicitly mention alternatives or when-not-to-use, so it falls short of a 5. The context is clear: use this when you need digital button presses.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ryubing_set_sticksSet analog sticksA

Set left and/or right analog stick coordinates. Values range from -1 to 1. Omitted sticks keep their prior state.

ParametersJSON Schema
NameRequiredDescriptionDefault
leftXNo
leftYNo
playerNo
rightXNo
rightYNo
sessionIdNoManaged Ryubing session ID; omit for the external default session
durationMsNoReset both sticks after this delay; 0 keeps the state until the next call

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With annotations all set to false, the description carries the burden of behavioral disclosure. It reveals the stateful nature of sticks (omitted sticks retain their previous state), which is valuable beyond the annotations. It does not address idempotency or side effects, but the 'set' action is clear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is one concise, front-loaded sentence that conveys the essential purpose and a key behavioral note. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 7 parameters and no output schema, the description is minimal. It covers the core stick-setting behavior but omits important context like player targeting and the durationMs reset mechanism, which remain only in the schema. This is adequate but not fully comprehensive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 29% (2 of 7 params documented). The description adds range and omission semantics for the stick coordinates, partially compensating for the low coverage. However, it does not explain the 'player' parameter or the durationMs reset behavior, though durationMs is described in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the tool's function with a specific verb and resource: 'Set left and/or right analog stick coordinates.' This clearly distinguishes it from sibling tools like press_buttons and touch, which handle different input types.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a practical usage hint ('Omitted sticks keep their prior state'), but it does not explicitly say when to use this tool instead of alternatives. No exclusions or alternative tool names are mentioned, so the agent must infer tool selection from the name and context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ryubing_stop_sessionStop managed Ryubing sessionA
Destructive

Stop one managed Ryubing process. Its isolated profile is retained unless explicitly removed.

ParametersJSON Schema
NameRequiredDescriptionDefault
sessionIdYes
removeProfileNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds behavioral context beyond annotations by clarifying that the process is stopped individually and the profile is retained by default, unless explicitly removed. This complements the destructiveHint=true annotation without contradicting it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two concise sentences. The first states the primary action, and the second adds a crucial caveat about profile retention. No unnecessary words, and it is front-loaded with the main purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter destructive tool, the description is fairly complete. It explains the core action and a key side effect. It lacks details about error conditions or post-stop state, but given the simplicity and annotations, this is acceptable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description must compensate. It partially does by hinting at the 'removeProfile' parameter ('unless explicitly removed'), but it does not add details about 'sessionId' or clarify parameter syntax. The meaning of sessionId is obvious from the name, but the description could be more explicit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with a specific verb ('Stop') and resource ('one managed Ryubing process'). It distinguishes this from sibling tools like ryubing_create_session or ryubing_launch_game by focusing solely on termination.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool: to stop a managed session. It also implies usage for the 'removeProfile' behavior by noting the profile is retained unless explicitly removed, but it does not explicitly mention alternatives or when-not-to-use scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ryubing_take_screenshotTake a Ryubing screenshotA
Read-only

Capture the emulator's rendered game frame without desktop window chrome.

ParametersJSON Schema
NameRequiredDescriptionDefault
formatNopng
qualityNoUsed only for JPEG
sessionIdNoManaged Ryubing session ID; omit for the external default session

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, covering the safety profile. The description adds the 'without desktop window chrome' scoping but does not disclose how the screenshot is returned (e.g., file path, base64) or any side effects. With annotations covering safety, this is acceptable but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no waste. 'Capture the emulator's rendered game frame without desktop window chrome' is specific and succinct, earning every word.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description defines what is captured but omits details about the return value or output format, which is critical since no output schema exists. It also lacks explicit usage guidelines. Given the simple optional parameters and strong annotations, it is minimally adequate but has a clear gap on return behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema covers 67% of parameters with descriptions (quality, sessionId), while format lacks a description. The tool description adds no parameter-specific context, relying on the schema. At the high schema coverage baseline, this is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses the specific verb 'Capture' with the resource 'the emulator's rendered game frame' and adds the scope 'without desktop window chrome,' clearly distinguishing it from less specific screenshot tools. There are no competing siblings, so the purpose is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for capturing pure gameplay visuals ('without desktop window chrome') but does not explicitly state when to use it, when not to, or mention alternatives. Sibling tools do not include another screenshot tool, so the guidance is minimal but not misleading.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ryubing_touchTouch the Switch screenA

Send a tap, long press, or swipe using native Switch touchscreen coordinates (1280x720).

ParametersJSON Schema
NameRequiredDescriptionDefault
xYes
yYes
endXNo
endYNo
actionYes
sessionIdNoManaged Ryubing session ID; omit for the external default session
durationMsNo

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are all false, offering no meaningful behavioral signal. The description adds useful context about the coordinate system (1280x720) and action types, but does not disclose whether the tool blocks until completion, requires specific permissions, or has side effects beyond the input. This leaves some ambiguity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, concise sentence that front-loads the essential information (action types and coordinate system) without redundancy or extra filler. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 7 parameters, no output schema, and sparse annotations, the description is adequate but not comprehensive. It gives essential orientation but leaves questions about swipe endpoints, duration semantics, and sessionId usage. The schema fills some gaps, but the overall package is not rich.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is only 14%, so the description must compensate. It clarifies that x/y are native Switch coordinates and that action can be tap, long_press, or swipe, which helps interpret the core parameters. However, it does not explicitly explain endX/endY or durationMs, relying on schema defaults and inference.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool sends touch inputs (tap, long press, swipe) to the Switch screen using native coordinates. This specific verb+resource combination distinguishes it from sibling tools like ryubing_press_buttons and ryubing_set_sticks, which handle other input types.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for touchscreen interactions, providing clear context for when it applies (e.g., tapping UI elements) versus other input tools. However, it does not explicitly mention alternatives or exclusions, so it falls just short of full explicit guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 10 tool updatesv0.1.0
    • First observedryubing_create_session
    • First observedryubing_get_logs
    • First observedryubing_get_status
    • First observedryubing_launch_game
    • First observedryubing_list_sessions
    • First observedryubing_press_buttons
    • First observedryubing_set_sticks
    • First observedryubing_stop_session
    • First observedryubing_take_screenshot
    • First observedryubing_touch

TDQS

A4/5.0

Scored across 10 tools

Disambiguation5/5

Each tool targets a distinct resource or action: session management, status, game launch, input methods, screenshot, and logs. There is no overlap, and descriptions clearly distinguish between session status and active game status.

Naming Consistency4/5

All tools use the 'ryubing_' prefix and mostly follow a verb_noun pattern (e.g., press_buttons, set_sticks, launch_game, list_sessions). The only deviation is ryubing_touch, which is a single verb, but it remains clear and does not cause confusion.

Tool Count5/5

Ten tools is a well-scoped size for an emulator control server, covering session lifecycle, input, diagnostics, and game launching without redundancy. Each tool earns its place.

Completeness4/5

The tool set covers the core workflow: create session, launch game, control input, take screenshots, read logs, and stop session. Missing advanced features like save states or configuration settings are minor gaps for the apparent purpose.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    B
    maintenance
    MCP server for the mGBA Game Boy Advance emulator. Read and write GBA memory, inject button presses, take screenshots, save/load state, and step the emulator through a Lua bridge.
    18
    10
    2
    MIT
  • A
    license
    C
    quality
    D
    maintenance
    An MCP server for real-device Android reversing workflows, wrapping AlgorithmAide config writes, AppSwitch/logList sync, LSPosed scope sync, Frida script injection, and runtime log queries into a stable MCP toolset.
    23
    13
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Local MCP server for Android and iOS mobile automation and performance telemetry, enabling device control (screenshot, tap, swipe, input, app launch) and metric collection (CPU, memory, launch time) via ADB, simctl, and WebDriverAgent with SQLite session history.
    13
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for controlling Hyprland Wayland compositor: screen capture, mouse/keyboard injection, and automation via native Hyprland IPC and wlr protocols.
    MIT