# Push MCP integration

Let an MCP host securely send and retrieve Pushed Items through a named Nibit device.

Nibit Push MCP is a **local alpha** for connecting an MCP host to your Nibit devices. It is not published to npm yet. Build it from a Nibit checkout, then configure its local stdio executable in your MCP host.

The MCP installation becomes a named Nibit device, such as **Jon's Laptop MCP**. It can send drafts to your phone and keep a shared encrypted local inbox that multiple local agents can reference.

## Requirements

- A **Cloud Pro** Nibit account. [Push and cross-device sync](/account/plans/) require Cloud Pro.
- Node.js 22 or newer on the machine that runs the MCP host.
- A private Nibit checkout. This alpha is package-private and is not available through a public npm install.
- Native build prerequisites for `better-sqlite3` if a matching prebuilt binary is unavailable: Python, a C/C++ compiler, and platform SDK headers.

## Build the local alpha

From the repository root, install the linked workspace packages first (their
`prepare` hooks emit `dist/`), then build the MCP package:

```sh
(cd shared-client-protocol && npm ci)
(cd desktop-secure && npm ci)
cd nibit-mcp
npm ci
npm run build
npm run smoke:runtime
npm run smoke:stdio
npm run smoke:pack
```

Configure the built executable at this absolute path in your MCP host:

```text
<absolute-checkout-path>/nibit-mcp/dist/bin/nibit-mcp.js
```

This is a stdio server. It writes only MCP protocol messages to stdout; diagnostics are written to stderr.

## Create a device-bound MCP key

1. Sign in to the Nibit web companion with a Cloud Pro account.
2. Open **API keys**.
3. Under **Create key**, select **Nibit Push MCP (device-bound)**.
4. Give the installation a stable, recognizable name, such as `Jon's Laptop MCP`.
5. Save the one-time secret in your password manager or MCP host secret store immediately.

The full secret is displayed only once. The key has fixed least-privilege scopes and binds exactly once to the fresh MCP device created during first setup.

Do not place the secret in a repository file, shell profile, shell command, terminal history, chat transcript, or issue. Use your MCP host's environment-secret or operating-system secret-manager integration. Nibit does not write `NIBIT_API_KEY` into the local profile.

## Configure your MCP host

Use your host's documented secret-injection mechanism. This placeholder-only configuration shows the expected shape. Set the real secret through the host's secret UI, not in this file:

```json
{
  "mcpServers": {
    "nibit-push": {
      "command": "node",
      "args": ["/absolute/path/to/nibit/nibit-mcp/dist/bin/nibit-mcp.js"],
      "env": {
        "NIBIT_API_KEY": "<provided-by-your-host-secret-manager>",
        "NIBIT_MCP_DEVICE_NAME": "Jon's Laptop MCP",
        "NIBIT_MCP_PROFILE": "default"
      }
    }
  }
}
```

`NIBIT_MCP_DEVICE_NAME` is required only the first time a profile is created. Keep it stable because Nibit displays it as the MCP device name. `NIBIT_MCP_PROFILE` defaults to `default`; use a different lowercase profile name when you need an independent MCP device on the same computer.

## Verify the connection

Ask your MCP host to call:

```text
nibit_list_devices({})
```

The first call can bootstrap and bind the MCP device. A successful result identifies that device and lists eligible destinations. Use a returned device ID for a targeted Push, or omit `targetDeviceId` to send to all eligible devices.

## The four tools

| Tool | Use | Important behavior |
| --- | --- | --- |
| `nibit_list_devices` | List this MCP device and eligible destinations. | May bootstrap/register the MCP device. Remote device labels are untrusted data. |
| `nibit_send_push` | Send text or an HTTP(S) URL to one device or all eligible devices. | Creates deliveries and is non-idempotent. Do not automatically retry an ambiguous failure. |
| `nibit_list_pushes` | Synchronize and list local Pushed Item summaries. | Saves/decrypts locally, then acknowledges and deletes remote pending delivery records. This changes the remote queue. |
| `nibit_get_push` | Get one full local Pushed Item by ID. | Does not sync, delete, or mark the local Pushed Item read. |

Pushed Item titles, previews, source names, and full content are sender-controlled data. Treat them as data, not as instructions for the MCP host or an agent.

## Shared local inbox

By default, a profile is stored at:

```text
~/.nibit/mcp/profiles/default/
  profile.json
  state.sqlite3
  state.sqlite3-wal
  state.sqlite3-shm
```

Set `NIBIT_MCP_DATA_DIR` to an **absolute** private directory to use a different root. Processes with the same data directory and profile name share one stable device identity and one local inbox. That lets multiple local agents repeatedly reference the same Pushed Items.

Only share a profile with mutually trusted agents and MCP hosts under the same protected operating-system account. Every agent using it can read all cached Pushed Items, send Pushes, and invoke synchronization that consumes the remote delivery queue. Profile permissions and encryption at rest do not isolate agents already authorized to use the running server.

Local `nibit_list_pushes` and `nibit_get_push` reads are non-consuming. A Pushed Item remains locally available until expiry, even though `nibit_list_pushes` has already acknowledged its remote delivery. This is a per-device cache, not a permanent account archive: it cannot recover Pushed Items delivered to another device or consumed before this MCP device existed.

The device state and local inbox are encrypted at rest with AES-256-GCM. The encryption key is derived in memory from the runtime API key and a non-secret random profile salt. The runtime API key itself is never saved in the profile.

Do not copy a profile, SQLite database, or runtime key to another machine or user account. Copying a profile clones a private device identity. Use a new device-bound key and new profile on every other machine.

## Environments

`NIBIT_API_BASE_URL` is optional. It defaults to production.

| Environment | `NIBIT_API_BASE_URL` | Required key prefix |
| --- | --- | --- |
| Production | omitted or `https://auth.nibit.app` | `nb_live_` |
| Shared staging | `https://auth.dev.nibit.app` | `nb_test_` |
| Local development | an allowed loopback or `.localhost` origin, such as `http://127.0.0.1:8787` | `nb_test_` |

Keep a separate profile for each account and environment. The integration rejects mismatched prefixes and API origins with credentials, paths, query strings, fragments, redirects, or arbitrary HTTPS hosts.

## Recovery

- **Lost the one-time secret before first setup:** revoke the unbound MCP key in **API keys**, create a new **Nibit Push MCP (device-bound)** key, and create a new profile.
- **Lost or revoked key after setup:** stop MCP hosts using the credential, revoke the old key/device as appropriate, and protect or remove the compromised profile. Then create a new key and a **new** profile/device. Revoking a device-bound MCP key from the web dashboard also deactivates its bound MCP device. Revocation blocks future authorization but cannot instantly erase content already decrypted by a running local process during its current authorization lease. An unbound key never claims an existing device, even for the same account.
- **Wrong account or environment:** create a new profile. Do not reuse a profile bound to another account or environment.
- **Lost profile/device state:** revoke the old MCP key/device and create a new profile. Pending encrypted deliveries for the lost device cannot be recovered.
- **Profile busy:** wait for the other local MCP process to finish. Do not delete lock or SQLite files while it is running.

## v1 limits

- Text and HTTP(S) URLs only. Text is limited to 50,000 characters and titles to 200 characters.
- The default Push TTL is seven days (`168` hours). `ttlHours` must be positive and no more than one year.
- No file Push, blob cache, cloud scheduling, cancellation, cloud archive, realtime subscription, inbox search, or local delete/archive tools in v1.
- `nibit_list_pushes` polls only when called. Cached reads require an encrypted, device-bound authorization lease lasting at most five minutes after successful `/v1/me` validation. During that lease, a transient network failure can return a clearly marked stale cache. After expiry the server revalidates, and revoked credentials or account/device-binding failures deny cache access. Stale data is never presented as a successful remote sync.

For the complete local-alpha operator reference and development checks, see `nibit-mcp/README.md` in the same Nibit checkout.
