# Remote MCP

> **Upcoming in 1.0 (preview). These pages describe the main branch of LLMSlim Core, which becomes the 0.13 release candidate and then 1.0. `pip install llmslim` installs 0.12.0 today, which doesn't have everything described here.** Docs for what pip installs: https://www.llmslim.app/docs.md

> One memory across machines: the MCP tools over HTTP, behind bearer keys, for your laptop, desktop and CI.

llmslim mcp --transport http serves remember, recall and the other tools over MCP's Streamable HTTP transport, with bearer keys, one scope per server, and TLS in front.

Category: Guides & Strategies · Version: 1.0 · Updated: November 2026 · 5 min read · Experimental: a minor release may change this API.

## Make a key and start the server

The HTTP transport needs the same `mcp` extra and nothing else. It binds 127.0.0.1 unless you pass `--host`, and refuses any other interface without a key.

terminal:

```bash
export LLMSLIM_MCP_API_KEYS="$(llmslim serve --new-key)"     # keep it; each client sends it
llmslim mcp --transport http --user-id asha --db ~/.llmslim/memory.db
```

output:

```text
LLMSlim MCP server on http://127.0.0.1:8000/mcp, memory of user "asha" (every request needs an API key)
```

Give several keys, one per machine, to revoke one by restarting without it: repeat `--api-key`, or separate them with commas. These keys reach only this server's scope. `llmslim serve`'s keys (`LLMSLIM_API_KEYS`) reach every user, so this server never reads that variable, and warns if one of its keys is also there.

> **Experimental:** The `--transport`, `--host`, `--port`, `--path`, `--api-key` and `--allowed-host` flags and `LLMSLIM_MCP_*` variables may change in a minor release: MCP's HTTP transport is changing, and the trust model may gain per-key scopes. `llmslim mcp` over stdio and its tools stay stable.

## Put it behind TLS

The key travels in a header, so anything past this machine must be HTTPS. Keep the server on 127.0.0.1 and let a reverse proxy on the same host terminate TLS, then pin the name it answers to with `--allowed-host memory.example.com`. With Caddy, which gets the certificate itself:

Caddyfile:

```text
memory.example.com {
    reverse_proxy 127.0.0.1:8000
}
```

Responses are plain JSON, not event streams, so proxies need no buffering settings. A private network such as Tailscale or WireGuard works too: bind its address with `--host` and keep the key.

> **Never expose a keyless server:** Without a key the server answers only requests addressed to this machine by name that no other web page sent, so a reverse proxy in front of it gets a 403. Don't work around that with `--allowed-host`: give it a key.

## Connect each client

Point each client at `https://memory.example.com/mcp` with the header `Authorization: Bearer <key>`. In Claude Code:

terminal:

```bash
claude mcp add --transport http llmslim https://memory.example.com/mcp \
  --header "Authorization: Bearer $LLMSLIM_KEY"
```

VS Code: .vscode/mcp.json (asks for the key once, stores it as a secret):

```json
{
  "inputs": [
    { "type": "promptString", "id": "llmslim-key", "description": "LLMSlim API key", "password": true }
  ],
  "servers": {
    "llmslim": {
      "type": "http",
      "url": "https://memory.example.com/mcp",
      "headers": { "Authorization": "Bearer ${input:llmslim-key}" }
    }
  }
}
```

Cursor: ~/.cursor/mcp.json:

```json
{
  "mcpServers": {
    "llmslim": {
      "url": "https://memory.example.com/mcp",
      "headers": { "Authorization": "Bearer ${env:LLMSLIM_KEY}" }
    }
  }
}
```

Other clients take the same URL and header. `GET /healthz` answers `{"status": "ok"}` without a key, for health checks.

## Check it from Python

With the MCP Python SDK, a client sends the key on every request:

remote_check.py:

```python
import asyncio, os

import httpx2
from mcp import Client
from mcp.client.streamable_http import streamable_http_client


async def main():
    headers = {"Authorization": f"Bearer {os.environ['LLMSLIM_KEY']}"}
    async with httpx2.AsyncClient(headers=headers) as http:
        async with Client(streamable_http_client("http://127.0.0.1:8000/mcp", http_client=http)) as client:
            await client.call_tool("remember", {"text": "My sister's wedding is in Jaipur in December."})
            result = await client.call_tool("recall", {"query": "When is the wedding?"})
            print(result.content[0].text)


asyncio.run(main())
```

A request without the key, or with a wrong one, gets a 401 with `WWW-Authenticate: Bearer`. The key is never logged or echoed.

## Who can read whose memory

Every key reaches the server's one scope, with all five tools, including `forget`. A client can't widen it: as over stdio, no tool takes a user or agent id, and arguments a tool doesn't declare are dropped. For several people, run one server each, with its own `--user-id`, keys and port (or `--path` behind the proxy). They can share one database: SQLite for a few processes on one host, Postgres or MongoDB for more, or for servers on several hosts. To give an application every user's memory, use [`llmslim serve`](https://www.llmslim.app/docs/1.0/quickstart-http) from your backend instead.

## Flags

These apply only with `--transport http`; passing one with stdio is an error. There is no environment variable for the transport itself, so a shell variable can't turn the stdio server a client launches into an HTTP server.

| Flag | Environment variable | Default | Meaning |
|---|---|---|---|
| `--transport stdio\|http` |  | `stdio` | How clients reach the server. |
| `--host` | `LLMSLIM_MCP_HOST` | `127.0.0.1` | Interface to bind; any other than loopback needs a key. |
| `--port` | `LLMSLIM_MCP_PORT` | `8000` | Port. |
| `--path` |  | `/mcp` | URL path of the MCP endpoint. |
| `--api-key` | `LLMSLIM_MCP_API_KEYS` | none | A bearer key of at least 16 characters; repeat for several. |
| `--allowed-host` | `LLMSLIM_ALLOWED_HOSTS` | none | A host name clients reach the server by; `*` for any. Without a key, other names get a 403. |

Request bodies are capped at 1 MB (413), malformed JSON-RPC is a 400, and on shutdown running requests get 10 seconds to finish. Clients on the 2026-07-28 MCP revision and those that start with `initialize` both work.

## FAQ

### Can one server hold several people's memory?

No. One server holds one scope, the `--user-id` and `--agent-id` it was started with, and every key reaches that scope. For several people, run one server each; they can share a database.

### Does it support OAuth?

No: bearer keys only. A key is a password for a machine, not an identity.

### Does a restart break connected clients?

No. The server is stateless and answers in JSON, so it runs behind any load balancer, and several replicas can serve one Postgres or MongoDB memory.

## Related

- [MCP quickstart](https://www.llmslim.app/docs/1.0/quickstart-mcp.md)
- [Storage backends](https://www.llmslim.app/docs/1.0/storage-backends.md)
- [API stability](https://www.llmslim.app/docs/1.0/api-stability.md)

Canonical page: https://www.llmslim.app/docs/1.0/remote-mcp
