Zepto MCP¶
Blacki connects to Zepto's hosted
MCP server through the supported
mcp-remote bridge. Zepto rejects
Blacki's generic dynamic OAuth registration with HTTP 403 during validation,
so Blacki uses the same standards-based bridge path documented for other MCP
clients.
Security model¶
- One private bridge directory represents one Zepto account and shared cart.
- Only explicitly allowlisted positive private Telegram chat IDs can connect. Groups, topics, task workers, and arbitrary HTTP user IDs are rejected.
- Zepto is loaded into a Telegram-only ADK runner. The unauthenticated ADK HTTP runner never receives the Zepto skill or toolset, even if a caller spoofs an allowlisted Telegram user ID.
- Only final order or payment calls with
confirmOrder=truerequire ADK confirmation. Reads, cart changes, address changes, and order previews run without approval. - Credentials are plaintext protected by
0700directories and0600files. - ADK session history retains shopping prompts, tool arguments, and results. The configured model also receives tool data needed to answer the request.
- Secure Zepto mode disables content-rich ADK tracing and OpenInference ADK instrumentation, removes the ADK content logging plugin, and suppresses user/model/tool payloads from Blacki's lifecycle and Telegram preview logs. It does not erase session history.
Authenticate locally¶
From the repository root, leave ZEPTO_MCP_ENABLED=false and run:
uv run python -m blacki.zepto.auth login
Blacki starts the exact locked mcp-remote bridge, which opens Zepto's
mobile-number and OTP flow in the browser. The bridge requests Zepto's
tools:read MCP scope with PKCE. That scope authorizes access to the tool
server; Blacki separately confirms only final order or payment placement. The
command then lists the complete tool manifest without calling any shopping
tool.
The default credential directory is:
data/credentials/zepto-mcp-remote/
The existing ./data:/app/data Compose mount makes that same directory
available to the container. Do not copy its contents into .env, logs, chat,
or source control.
Verify the stored credentials without opening a browser:
uv run python -m blacki.zepto.auth status
uv run python -m blacki.zepto.auth probe
If Zepto access is revoked or you intentionally want to switch accounts, use:
uv run python -m blacki.zepto.auth login --force
The force option deletes only the four known Zepto bridge files inside the dedicated credential directory, then starts a fresh browser login.
Enable the root-agent skill¶
Set the positive numeric ID of the private Telegram chat:
ZEPTO_MCP_ENABLED=true
ZEPTO_MCP_ALLOWED_TELEGRAM_CHAT_IDS=123456789
ZEPTO_MCP_CONFIG_DIR=data/credentials/zepto-mcp-remote
Restart Blacki, then ask it to search Zepto or inspect the cart. The first
request loads the Zepto skill and non-final tools run directly. When a final
order or payment call is ready, Blacki shows its exact tool name and arguments;
reply exactly yes or no.
Verification boundary¶
Tool discovery and read calls are safe local verification. Order and payment
tools can generate a preview with confirmOrder=false; confirmOrder=true
stops at the confirmation interrupt before the real final action. Cart,
address, store, and profile mutations execute without approval and affect the
shared account immediately. Never place, pay for, cancel, or reorder a real
order only to test this integration.
Runtime and deployment notes¶
The production image includes Node 22 and installs mcp-remote 0.1.38 from the
committed npm lockfile. It never downloads npm packages at runtime. Local
development falls back to the same pinned package through npx when no global
bridge exists.
Blacki is intentionally single-process and single-replica when Zepto is enabled: all allowlisted chats share one account, cart, bridge session, and credential store. If credentials are revoked, the runtime connection fails within 15 seconds. Run the login command locally again; do not try to complete OAuth inside the long-running server.