1. Availability and scope
The Mokutori connector lets Muse read page images and OCR text received from a paired Mokutori iPad. This document describes connector version 0.1.0, a private, single-user MCP bridge.
A public multi-user cloud service has not been released. Each installation needs its own receiver data home, secret API key and HTTPS deployment. Account setup and iPad pairing happen in the local Mokutori CLI. The MCP tools cannot create accounts, pair devices, send messages or administer the relay.
The setup below is for an operator who already has the Mokutori agent package and a working receiver. This page does not provide public signup or a one-click marketplace installation. Contact support@mokutori.com for availability. Directory submission, review and approval are separate from operating a private connector.
Scanned paper, OCR and images are untrusted source material. Check names, amounts, dates and instructions against the page image before acting on them. Mokutori is independent; compatibility documentation does not imply endorsement by Meta.
2. Private installation
Use Python 3.8 or later and the complete Mokutori agent package, including its bundled engine. Run these commands from the app repository root, replacing the example path with an isolated private receiver data home for this installation.
export MOKUTORI_AGENT_HOME="/absolute/private/mokutori-agent"
sh agent-plugins/mokutori/scripts/mokutori setup --gateway https://bots.yobiru.com --agent muse
sh agent-plugins/mokutori/scripts/mokutori pair --terminal
sh agent-plugins/mokutori/scripts/mokutori pair-check --wait 120
If the configured gateway requires email verification, use setup's --email option first and finish with --email-code locally. Complete setup and confirm the intended iPad using the local pairing workflow. Keep its one-time QR code, pairing URL and relay credentials private. The receiver must be able to reach its configured relay.
export MOKUTORI_MUSE_API_KEY="$(python3 -c 'import secrets; print(secrets.token_urlsafe(32))')"
export MOKUTORI_MUSE_ALLOWED_ORIGINS="https://your-approved-muse-origin.example"
sh agent-plugins/mokutori/scripts/muse-connector --home "$MOKUTORI_AGENT_HOME" --host 127.0.0.1 --port 8787
The origin above is a placeholder, not a Muse hostname. Configure the exact approved browser origins for your deployment. Store the generated API key in the deployment's secret store; do not publish it in a URL, source file, screenshot or log. Use an HTTPS reverse proxy in front of the localhost process, with authentication preserved and access controls appropriate to the installation. Do not expose the Python HTTP server directly on a public interface.
Give Muse the reachable HTTPS /mcp endpoint and that installation's API key through its credential interface. 127.0.0.1 on your computer is not reachable from Muse's cloud. Keep one receiver data home and key per user; this bridge does not implement tenant isolation or OAuth account provisioning.
3. Authentication and MCP session flow
Every POST /mcp requires Authorization: Bearer <installation-key>. The Python bridge requires a random secret of at least 20 characters; the Cloudflare review deployment requires at least 32. It is a connector credential, distinct from the relay credentials retained on the receiver. In a self-hosted installation, an Origin header must exactly match an entry in MOKUTORI_MUSE_ALLOWED_ORIGINS. The dedicated review endpoint instead rejects every request containing an Origin header and is intended for server-to-server MCP clients.
- Send a JSON-RPC
initializerequest toPOST /mcpwithContent-Type: application/jsonandAccept: application/json, text/event-stream. Supported protocol versions are2025-11-25,2025-06-18and2025-03-26. The server responds with the negotiatedprotocolVersionand anMCP-Session-Idresponse header. - Send
notifications/initializedwith thatMCP-Session-IdandMCP-Protocol-Version. A valid notification returns HTTP202with an empty body. - Include the same session ID, negotiated protocol version, authorization and Accept headers on subsequent calls. Use
tools/listfor authoritative schemas, thentools/callfor the tools below. Tool calls are rejected until initialization is complete. - If the process restarts or returns
unknown_mcp_session, initialize a new session. Sessions are stored in process memory. The bridge currently has no session expiry or session-deletion endpoint.
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"review-client","version":"1.0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"mokutori_list_scans","arguments":{"limit":1}}}
The bridge returns JSON responses. GET /mcp returns 405 with Allow: POST; no SSE stream is offered. When running the Python bridge directly, GET /healthz returns {"ok":true,"service":"mokutori-muse"}. The Cloudflare review deployment distinguishes unauthenticated edge-only health from an authenticated service check, as described below. Health alone does not prove pairing, scan delivery or successful tool access.
4. Common tool result format
Tool responses contain an object in structuredContent, the same object serialized into a text content block, and an isError flag. Image reads add an MCP image block. Outputs omit local filesystem paths and credentials. The currently advertised output schema is an object; the fields documented below describe version 0.1.0.
All tool inputs are objects. Unknown fields are rejected. Both read and write tools currently advertise destructiveHint: false, idempotentHint: true and openWorldHint: false. These are protocol hints, not a substitute for reviewing the concrete effects below.
5. mokutori_status — read
Input: {}; no arguments.
Output: configured (boolean), gateway, bot_id, handle, devices (each with actor_id, name and paired_at), and pending_pairings. Values absent from local setup may be null. The tool does not return a pending scan count.
Effect: reads receiver configuration and paired-device metadata. It does not pair or unpair devices, fetch scans or change delivery acknowledgement.
Errors: malformed local state or a read failure produces a tool result with isError: true and error: connector_operation_failed.
6. mokutori_list_scans — write to cache and relay receipts
Input: optional integer limit, from 1 to 10; default 5. Example: {"limit":1}.
Output: batches, ignored_from_unpaired_senders, acknowledged: false, ingestion_error_count, a receipt explanation and a content_trust reminder. Each batch contains notice_id, from_device, received_at, summary, ocr_markdown and files. Each file contains a safe name, kind and byte count in bytes. The compatible notice_id field carries a gateway message ID on relay version 0.7.14.
Effect: contacts the configured relay, claims eligible delivery jobs, decrypts their content, saves it on the receiver, and marks the gateway messages read after local saving. It returns locally unread OCR to Muse. The local unread marker remains until mokutori_acknowledge_scans is called. Repeated list calls can therefore return the same locally unread batches after their gateway receipt is already complete. No saved page is deleted.
The limit caps returned batches only. Ingestion can process and mark additional eligible gateway messages read during the same call. Treat this tool as a write operation even when requesting a single returned batch.
Errors: ingestion_error_count greater than zero means some receipt, recovery or ingestion operations did not complete successfully. A returned batch can also contain error: scan_not_available with an explanation and no readable files if refused by an integrity check. A failed or timed-out inbox operation produces connector_operation_failed. Inspect the error count and per-batch results even when the overall tool result has isError: false; earlier jobs may already have been saved and marked read.
7. mokutori_get_scan_image — read
Input: required notice_id (1–160 characters) and name (1–120 characters). Use the exact values returned by mokutori_list_scans, for example {"notice_id":"review-batch-001","name":"page-001.png"}. Notice IDs permit ASCII letters, digits, underscore and hyphen; filenames must begin with an ASCII letter or digit and otherwise use those characters, a dot or a hyphen.
Output: notice_id, name, media_type and bytes, plus an MCP image content block containing base64 data and mimeType.
Effect: reads a previously cached image and sends it to Muse. It does not fetch a new batch, acknowledge delivery or modify the saved page. Run mokutori_list_scans first.
Limits and errors: JPEG, PNG, WebP, HEIC and GIF are recognized by extension and checked against their file headers. Empty images and images larger than 4 MiB are refused. Unsafe names, absent files, symlinks, invalid image contents and file-read failures produce connector_operation_failed. A schema violation instead returns invalid_arguments.
8. mokutori_acknowledge_scans — write to local unread state
Input: required notice_ids, an array of 1–50 notice ID strings, each 1–160 characters. Example: {"notice_ids":["review-batch-001"]}. Use only exact IDs already read and reviewed.
Output: acknowledged (an array of successful IDs) and refused (entries containing notice_id and error). A partial result can contain both arrays.
Effect: clears the local unread marker for the selected saved batches, so subsequent lists omit them. The gateway messages were already marked read during successful ingestion. This tool makes no gateway request. Saved images and OCR remain, and content already provided to Muse is not recalled.
Errors: a notice without a successfully saved batch and confirmed gateway receipt is refused with not_read. Invalid input returns invalid_arguments, and a general local operation failure returns connector_operation_failed. Check the returned refused entries even when isError is false.
9. Limits, HTTP errors and retry behavior
The Python bridge has no built-in requests-per-minute quota, connection quota or rate-limit headers. It serializes local list/acknowledgement operations. Self-hosting operators must set suitable request and connection limits at their HTTPS proxy. Avoid parallel polling and unbounded session creation. The inbox subprocess has a 120-second timeout; the Python bridge's request-body ceiling is 12 MiB. The Cloudflare review deployment applies a stricter 64 KiB request ceiling and shared request/concurrency limits. One list call returns at most 10 batches, one image is at most 4 MiB, and one acknowledgement call accepts at most 50 IDs. Upstream relay limits and deployment proxy limits also apply.
| Response | Meaning and next step |
|---|---|
| HTTP 401 | unauthorized: missing or incorrect bearer key. Check the configured credential; do not retry blindly. |
| HTTP 403 | origin_not_allowed: a supplied Origin is not allowed. Self-hosting operators can verify their allowlist; the dedicated review endpoint rejects all Origin headers. |
| HTTP 406 | accept_must_include_json_and_event_stream: include both required Accept media types. |
| HTTP 400 | Invalid JSON/body length, unsupported or missing protocol version, protocol mismatch, or missing session ID. Correct the request. |
| HTTP 404 | unknown_mcp_session requires a fresh initialization; not_found means the URL path is unsupported. |
| HTTP 405 | GET /mcp is unsupported; use POST. |
| JSON-RPC error | -32600 invalid request or repeated initialization; -32601 unknown method; -32602 unknown/invalid tool name; -32002 initialization incomplete. |
Tool isError: true | invalid_arguments includes validation detail. connector_operation_failed intentionally omits private host paths and exception details; check the receiver locally. |
HTTP 200 can contain a JSON-RPC error or a failed tool result. Check all layers, including ingestion error counts and per-batch/per-notice errors. After a transient failure, retry with a bounded delay. After an uncertain ingestion or acknowledgement outcome, inspect receiver state before retrying; do not assume an entire request was rolled back.
10. Reviewer installation and synthetic data
The designated review endpoint is https://review.mokutori.com/mcp. Public HTTPS and the complete four-tool review flow were verified on 26 October 2026. The selected configuration uses a Cloudflare Worker and one basic Container. It is reserved for synthetic review data, with no general signup, public pairing, uploads or customer scan library. A dedicated reviewer key is available through a secure credential handoff. The initial intake form has no secret field; the key is not included in public documentation or ordinary submission notes.
The Container runs the real Python MCP bridge and an isolated, loopback-only Yobiru 0.7.14 gateway; outbound Internet access is disabled. A protocol reference sender supplies a visibly labeled synthetic receipt and matching expected text through encrypted gateway messages. This is protocol review evidence, not real iPad capture or an OCR-quality benchmark. One installation key accesses one shared fixture library, separate from the owner's receiver and personal scans.
Health and startup: unauthenticated GET /healthz returns readiness: edge_only and container_checked: false. It does not start the Container and does not prove that the MCP service is ready. The same request with the valid bearer key checks the actual service and may wake the Container. The Worker validates the key before MCP requests can access the Container. Send an identifying User-Agent header: the zone may reject the default Python-urllib user agent with Cloudflare error 1010 before the request reaches the Worker. Common HTTPX, Requests, Node and Go clients passed public health checks.
Review limits: MCP accepts JSON POST requests without a browser Origin header. Requests are limited to 64 KiB; page images are outputs only. Authenticated traffic shares a limit of 5 requests per second with a burst of 10, and at most 8 concurrent requests across this entire reviewer installation. HTTP 429 with review_rate_limit includes Retry-After: 2. A starting or unavailable Container can return 503 with Retry-After: 5. Oversized bodies return 413; a non-JSON content type returns 415.
Fixture lifetime: after 10 minutes without authenticated activity, the Container sleeps. Its filesystem is ephemeral. A restart recreates the synthetic gateway identities, fixture data and MCP sessions with new IDs. Previously acknowledged sample pages can therefore reappear. An old MCP session receiving HTTP 404 must initialize again; obtain the current notice ID and filename from a fresh list call. The review endpoint is unsuitable for customer data or persistent storage. Hosting is not guaranteed to remain in Japan.
- Initialize a session, send
notifications/initialized, and runtools/list. - Run
mokutori_statusto inspect the test configuration. - Run
mokutori_list_scanswith{"limit":1}. Record the returned notice ID and image filename. - Read that image with
mokutori_get_scan_imageand compare the synthetic OCR with the page. - Acknowledge that exact notice ID with
mokutori_acknowledge_scans, then list again to verify that it is no longer pending. The image remains in the test receiver's cache.
The acknowledgement step changes the shared review fixture until the next restart. Contact support if a fresh review batch is needed during an active session; do not substitute an owner's private data. A reviewer fixture, a submitted listing and marketplace approval are distinct states.
11. Data handling and support
Pages are decrypted and cached on the paired receiver. Calls can then transmit OCR, images and device metadata to Muse. Disconnecting an iPad or changing the connector key does not remove existing receiver files or content already received by Muse. Manage the receiver cache locally and use Muse's own controls for data retained by that service.
For installation and review support, contact support@mokutori.com. For privacy or security reports, use contact@mokutori.com. Do not include API keys, pairing URLs or private page content in an initial report.
See the Privacy Policy, Terms of Service and Support pages for their current publication status and additional details.