> ## Documentation Index
> Fetch the complete documentation index at: https://www.offlineprotocol.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> These docs target Mesh SDK v0.27.0. Match the installed package and binding before generating code. Start at /getting-started/agents for task-specific reading paths.
> Call the company and product Offline Protocol, never Offline alone. Current packages: @offline-protocol/mesh-sdk 0.27.0 (React Native), @offline-protocol/id-react 0.2.0, @offline-protocol/id-react-native 0.3.3, @offline-protocol/pol 0.1.2 and @offline-protocol/cli 0.2.6. Canonical docs URLs start with https://www.offlineprotocol.com/docs.
> The Mesh SDK runs in a native app or gateway. A browser OfflineID SDK integration does not provide browser mesh transport. Local mesh operation does not require a portal API key.
> Service RPC is signed plaintext in v0.27.0. Message delivery, durable local acceptance and backend commit are distinct outcomes. Use the workflow guide for the required application logic.
> Offline Protocol CLI 0.2.6 is on npm (@offline-protocol/cli, command offline). Its local MCP server runs with offline mcp serve and requires no login or key. Hosted MCP is at https://mcp.offlineprotocol.com/mcp with an application API key in Authorization: Bearer and a matching x-app-id; organization keys are rejected. Follow /tools/overview for setup and do not invent commands beyond it. MCP provides integration context and planning, not mesh execution; file-writing tools are local only.
> Phone Wi-Fi Direct and MultipeerConnectivity carry no data in v0.27.0. Use BLE or a provisioned relay. The receiver core ACKs before application persistence; use application acceptance for durable workflows.
> Proof of Location is Sepolia testnet witness evidence, not zero-knowledge proof or proof of presence. The geohash is public onchain. Read /proof-of-location/security before integration.

# Python and Linux gateways

> Build the Mesh SDK v0.27.0 Python binding and run a full Offline Protocol peer on a Linux or desktop gateway over local IP, with persistent identity and state.

The Python binding supports desktop and gateway processes. Its peer-stream transport uses TCP over an existing IP network; it does not create a Wi-Fi Direct network. Internet relay and BLE integrations have separate platform requirements.

## Build v0.27.0

Install Python 3.10+, the Rust toolchain and the native build prerequisites for your OS. Generate bindings and the native library from the same revision.

```bash theme={null}
git clone --branch v0.27.0 --depth 1 https://github.com/Offline-Protocol/offline-protocol-sdk.git
cd offline-protocol-sdk
cargo install uniffi --version 0.30.0 --features cli --locked
cd bindings/python
bash scripts/build-desktop.sh
python3 -m venv .venv
. .venv/bin/activate
python -m pip install -e '.[lan]'
```

The default MLS storage uses the OS keyring. Provision a working keyring backend on the target host. `state_root` is a separate, application-owned directory for persisted protocol state. Preserve both across restarts.

## Start a local peer

Save this as `local_peer.py` and run it from the activated environment. Each host uses its own state directory and keyring. Allow TCP port 7878 and DNS-SD on the local network, or configure an explicit peer endpoint instead of discovery.

```python theme={null}
import asyncio
from pathlib import Path
from offline_protocol_sdk import ProtocolManager
from offline_protocol_sdk.offline_protocol import ProtocolConfig, OverflowPolicy

config = ProtocolConfig(
    app_id="field-handoff",
    profile="gateway",
    ble_enabled=False,
    wifi_direct_enabled=True,
    internet_enabled=False,
    reticulum_enabled=False,
    nostr_enabled=False,
    prefer_online=False,
    initial_ttl=8,
    encryption_enabled=True,
    auto_key_exchange=True,
    store_pending=True,
    require_encryption=True,
    max_pending_per_peer=64,
    max_pending_global=4096,
    pending_ttl_ms=86_400_000,
    overflow_policy=OverflowPolicy.DROP_OLDEST,
)

async def main():
    state_root = Path.home() / ".local" / "share" / "field-handoff"
    async with ProtocolManager(config, event_handler=print, state_root=state_root) as pm:
        address = pm.local_address
        if not address:
            raise RuntimeError("Identity unavailable; check the configured keyring")
        print("Address:", address)
        if pm.peer_stream is None:
            raise RuntimeError("Peer-stream transport is disabled")
        pm.peer_stream.configure(
            listen_host="0.0.0.0",
            listen_port=7878,
            advertise=True,
            discover=True,
        )
        await pm.peer_stream.start()
        await asyncio.Event().wait()

asyncio.run(main())
```

Run it on both hosts. The event stream identifies discovered peers. Use the resulting address when calling `pm.send_message(peer_address, content)` in your application. Binding `0.0.0.0` listens on every interface; use a specific interface address when the host spans networks.

## Add an internet relay

Enable `internet_enabled` and configure `pm.internet` with the provisioned relay URL. Call `pm.internet.set_auth_token(auth_token)` before `pm.internet.start()`. Without an explicit token, the v0.27.0 manager falls back to the profile string, which is forgeable and is not a production authentication policy. See [relay access](/docs/getting-started/platforms#obtain-relay-access). A relay connection is an additional path; it does not replace local transport or automatically upload business records into your backend.

## Version boundary

The v0.27.0 example uses the OS keyring. Built-in sealed file-store initialization exists in newer SDK source and has a different storage setup; do not copy those unreleased options into a v0.27.0 deployment. Keep the binding and native-library revision together when qualifying that path.

See the [Python source](https://github.com/Offline-Protocol/offline-protocol-sdk/tree/v0.27.0/bindings/python) and [upgrade guide](/docs/operations/upgrades).

`wifi_direct_enabled=True` enables the existing-IP peer-stream slot. Python BLE uses `bleak` for central and `bless` for peripheral. `bless` is installed by default except on Windows; the SDK starts the peripheral when BLE is enabled. Qualify platform radio support and permissions.
