> ## 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.32.0. Match the installed package and binding before generating code. Start at /getting-started/agents for task-specific reading paths. Apps that call enableTelemetry on 0.26.0 to 0.29.0 should update to 0.30.0 or later: the telemetry uploader trusts only the telemetry endpoint's issuing roots from 0.30.0.
> Call the company and product Offline Protocol, never Offline alone. Current packages: @offline-protocol/mesh-sdk 0.32.0 (React Native), offline-protocol-sdk 0.32.0 on PyPI (Python 3.10 to 3.13; wheels for macOS 14+ arm64, Linux x86_64 and aarch64 with glibc 2.34+, Windows x86_64; other hosts build from source; extras lan and http add LAN discovery, the HTTP front and offline-protocol-verify), the offline-protocol crates 0.32.0 on crates.io, the OfflineProtocolSDK Swift package 0.32.0 (preview, iOS 13+ only), the Android library com.offlineprotocol:offline-protocol-sdk 0.32.0 on Maven Central (preview, minSdk 24), the Java binding com.offlineprotocol:offline-protocol-java 0.32.0 on Maven Central (JDK 22+, native library from the GitHub release's desktop archives), the C header offline_protocol.h with the native library in the GitHub release's desktop archives, the Ruby binding offline_protocol 0.32.0 on RubyGems (Ruby 3.3+, native library from the GitHub release's desktop archives), the C# binding (preview, .NET 8; source in bindings/csharp in the SDK repository at tag v0.32.0, a project reference over the C API, not on NuGet), the browser binding (experimental; the offline-protocol-web crate 0.32.0 on crates.io, with the JavaScript in bindings/web built from the SDK repository, not on npm), the offline_protocol Flutter plugin (preview, not on pub.dev; a path dependency on the SDK repository at tag v0.32.0; MeshSdk carries the React Native module's native surface), the service container image ghcr.io/offline-protocol/offline-protocol-service 0.32.0 (linux/amd64 and linux/arm64), @offline-protocol/id-react 0.3.0, @offline-protocol/id-react-native 0.4.0, @offline-protocol/pol 0.1.2 and @offline-protocol/cli 0.3.2 (account setup commands such as offline apps status, offline apps native and offline apply since 0.3.0). Canonical docs URLs start with https://www.offlineprotocol.com/docs.
> The Mesh SDK runs in a native app or gateway, and from 0.31.0 in a browser through the experimental browser binding (a full node in a Web Worker; see /mesh-sdk/web). The OfflineID SDK for React does not provide browser mesh transport. Local mesh operation does not require a portal account or API key. The Mesh SDK appId is a mesh app identifier the developer chooses, not the portal App ID (app_...) that OfflineID and Proof of Location require.
> In v0.32.0 service RPC bodies are sealed in the 1:1 MLS session once the recipient runs 0.29 or later and the session is confirmed; discovery, the first request to a provider never met, and requests to older peers are signed plaintext, so keep secrets out of service bodies unless the event says encrypted: true. Service subscriptions (subscribeService, publishServiceUpdate, from 0.32.0) are always sealed in the 1:1 MLS session with no plaintext fallback; under the default restricted policy the provider app must answer service_subscribe_received with acceptServiceSubscription or rejectServiceSubscription within 60 seconds. Content that begins with __MEMBER__ is a reserved prefix and is refused. The HTTP front (offline-protocol-service --http) always carries calls inside encrypted direct messages but does not authorize callers. Message delivery, durable local acceptance and backend commit are distinct outcomes. Use the workflow guide for the required application logic.
> Offline Protocol CLI 0.3.2 is on npm (@offline-protocol/cli, command offline). Its local MCP server, named offline-protocol, runs with npx -y @offline-protocol/cli@0.3.2 mcp serve and requires no login or key. Hosted MCP is at https://mcp.offlineprotocol.com/mcp with an app API key in Authorization: Bearer and the matching App ID in x-app-id; organization keys are rejected, and Claude Desktop and Claude.ai cannot send these headers; there, use the public read-only endpoint https://mcp.offlineprotocol.com/public/mcp as a custom connector, or local MCP to scaffold or edit projects. 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.
> In v0.32.0 phone Wi-Fi peer streams carry data: Android over Wi-Fi Direct (the SDK forms the group with autoAccept on Android 10+) and over the Wi-Fi network it is on (DNS-SD), iOS over Network framework (LAN or AWDL). Android and iOS meet over that slot only on a shared Wi-Fi network that allows multicast; iOS 0.28 and later does not see iOS 0.27 or earlier over it. Otherwise use BLE or a provisioned relay across platforms. The Swift and Android packages are previews; the Android library is on Maven Central from 0.29.0 only, so never give a Gradle line for an earlier version. The receiver core ACKs before application persistence; use application acceptance for durable workflows.
> OfflineID App IDs are public. A request naming an application needs a credential: an allowed browser origin, an API key in X-Api-Key from a server, or, from an iOS or Android app, an attestation from a build registered to the application (iOS bundle ID and Team ID, Android package and signing certificate SHA-256). Register native apps with offline apps native add or offline apply, pass attestation providers (createExpoAppIntegrityProviders with @expo/app-integrity) to OfflineAppProvider, sign in on a physical device, and check readiness with offline apps status. Follow /getting-started/agent-quickstart and /id-sdk/app-attestation; error responses list the fixing commands in data.next_steps.
> 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.

# C# binding

> Use the Mesh SDK v0.32.0 from C# on .NET 8 for desktop and server hosts: an async ProtocolEngine over the C API and the native library from the release.

From v0.32.0 the SDK has a C# binding for .NET 8 desktop and server hosts, in preview. It drives the native library through the [C API](https://www.offlineprotocol.com/docs/mesh-sdk/c.md) with P/Invoke, runs every engine call on one dedicated thread, and gives you an async `ProtocolEngine` with typed configuration, storage providers, events, telemetry and transport callbacks. Every engine method has a typed wrapper generated from the SDK's interface definition, so a new method or configuration field reaches C# when the binding is regenerated.

## Install

The binding ships as source in [`bindings/csharp`](https://github.com/Offline-Protocol/offline-protocol-sdk/tree/v0.32.0/bindings/csharp) and is not on NuGet. Check out the release and add a project reference:

```bash theme={null}
git clone --branch v0.32.0 --depth 1 https://github.com/Offline-Protocol/offline-protocol-sdk.git
dotnet add reference offline-protocol-sdk/bindings/csharp/src/OfflineProtocol.Sdk/OfflineProtocol.Sdk.csproj
```

It needs the .NET 8 SDK or later. Take the native library for your platform from the [v0.32.0 GitHub release](https://github.com/Offline-Protocol/offline-protocol-sdk/releases/tag/v0.32.0):

| Platform | Archive | Library |
| - | - | - |
| Windows x86\_64 | `offline-protocol-0.32.0-windows-x86_64.zip` | `offline_protocol_uniffi.dll` |
| Linux x86\_64 | `offline-protocol-0.32.0-linux-x86_64.tar.gz` | `liboffline_protocol_uniffi.so` |
| Linux aarch64 | `offline-protocol-0.32.0-linux-aarch64.tar.gz` | `liboffline_protocol_uniffi.so` |
| macOS arm64 | `offline-protocol-0.32.0-macos-arm64.tar.gz` | `liboffline_protocol_uniffi.dylib` |

The SDK loads the library from the directory in `OFFLINE_PROTOCOL_LIBRARY_DIR` when it is set, and otherwise from the application directory and the system paths. Take the source and the library from the same release.

## Quick start

```csharp theme={null}
using OfflineProtocol.Sdk;
using OfflineProtocol.Sdk.Config;
using OfflineProtocol.Sdk.LocalApi;

Console.WriteLine(ProtocolEngine.LibraryVersion); // "0.32.0"

// Name the fields the definition leaves without a default; the rest take the engine's.
var config = new ProtocolConfig
{
    AppId = "com.example.mesh",
    Profile = "desk-01",
    BleEnabled = false,
    WifiDirectEnabled = false,
    InternetEnabled = true,
    ReticulumEnabled = false,
    NostrEnabled = false,
    PreferOnline = false,
    InitialTtl = 8,
    EncryptionEnabled = true,
    AutoKeyExchange = true,
    StorePending = true,
    MaxPendingPerPeer = 64,
    MaxPendingGlobal = 4096,
    PendingTtlMs = 60_000,
    OverflowPolicy = OverflowPolicy.DropOldest,
};

await using var engine = await ProtocolEngine.CreateAsync(config);
await engine.InitializeMlsWithFileStoresAsync(mlsDir, stateDir, storeKeyBase64);
await engine.SetEventCallbackAsync(json => Console.WriteLine(json));
await engine.StartAsync();

Console.WriteLine(await engine.LocalAddressAsync()); // "off1..."
await engine.SendMessageAsync(LocalApiParams.SendMessage(peerAddress, "hello"));
```

Method names, parameters and results follow the [local API](https://github.com/Offline-Protocol/offline-protocol-sdk/blob/v0.32.0/docs/spec/local-api.md#method-table): parameters are JSON objects and results and events are JSON text. Service and document calls are on `engine.Services` and `engine.Data`, for example service subscriptions:

```csharp theme={null}
var subId = await engine.Services.SubscribeServiceAsync(
    """{"provider":"off1...","service_id":"equipment-status.v1","topic":"battery","mode":"Latest","params":"","keys":[]}""");
```

## Storage

`InitializeMlsWithFileStoresAsync` uses the built-in file stores, sealed under a 32-byte store key, given in base64, that you keep out of the source. For your own backend, implement `IProtocolStorage`, wrap it in a `NativeStorageProvider` and pass two providers to `InitializeMlsAsync`. Prove a backend first with `ProtocolEngine.RunStorageConformanceAsync`. A provider is single use: to probe a backend and then use it, wrap the same `IProtocolStorage` in a new provider. `MemoryProtocolStorage` is an in-memory backend for tests.

## Threads, events and callbacks

* **One engine thread.** Every call for an engine runs on its own .NET thread behind a bounded queue (512 calls by default). Await each call; a slow call such as `StartAsync` delays every call queued behind it. Cancelling a call ends your wait, not a call already queued.
* **Events off the engine thread.** `SetEventCallbackAsync` delivers each event as JSON on a dedicated delivery thread. A handler that throws is counted in `EventHandlerFailureCount` and never ends the process. `PollEventAsync` reads the same events without a callback. Keep handlers short and never call the same engine synchronously from one.
* **Transport callbacks.** `SetBleTransportCallbackAsync`, `SetWifiDirectTransportCallbackAsync`, `SetReticulumTransportCallbackAsync` and `SetNostrTransportCallbackAsync` signal that a carrier has outbound frames. Drain them with the generated methods, such as `BleGetNextFragmentAsync`, until the queue answers `null`. Install them before `StartAsync`.
* **Dispose before exit.** WinUI, WPF and MAUI hosts call `DisposeAsync` before the application shuts down, so telemetry flushes and transports stop cleanly.

## What your host provides

* **Transports.** The radios and sockets, through the transport callbacks and the generated transport methods.
* **Storage.** The built-in file stores or two providers, as above.
* **Telemetry lifecycle.** If you enable telemetry with `EnableTelemetryAsync`, the library fills `os` and the binding fills `os_major`. Call `NotifyAppStateAsync` when a desktop app leaves and returns to the foreground.

## Reference

* [C# binding README](https://github.com/Offline-Protocol/offline-protocol-sdk/blob/v0.32.0/bindings/csharp/README.md): building, testing and the consumer check.
* [C# binding contract](https://github.com/Offline-Protocol/offline-protocol-sdk/blob/v0.32.0/docs/bridges/csharp.md): the engine thread, events, storage providers, telemetry, typed configuration and transport callbacks.
* [C binding](https://www.offlineprotocol.com/docs/mesh-sdk/c.md): the C API the binding calls.

The SDK is AGPL-3.0-only with a commercial license available; see [licensing](https://www.offlineprotocol.com/docs/operations/licensing.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.