# Connecting to the server

Location: [gRPC API](https://developer.m-files.com/APIs/gRPC-API/index.md) > [Runtime conventions](https://developer.m-files.com/APIs/gRPC-API/index.md#runtime)

HTML version: https://developer.m-files.com/APIs/gRPC-API/runtime/connecting/

M-Files Server speaks native gRPC over HTTP/2. Every service of the API is served on the same
endpoint; there is no per-vault address. The vault is chosen when you log in
([Authentication and sessions](https://developer.m-files.com/APIs/gRPC-API/runtime/authentication/index.md)).

## Endpoints

| Deployment | Address | Transport |
|---|---|---|
| M-Files Cloud | `<vault-host>:443`, for example `contoso.cloudvault.m-files.com:443` | TLS, public certificate |
| On-premises, default | `<server>:7766` | Plain HTTP/2 (h2c) unless TLS is enabled |
| On-premises, TLS enabled | `<server>:7766` | TLS with the server certificate configured in M-Files |

[Deployments](https://developer.m-files.com/APIs/gRPC-API/runtime/deployments/index.md) compares the two in one table.

**Method path.** Every call is an HTTP/2 POST to `/MFiles.<Service>/<Method>`, for example
`/MFiles.IRPCQueryVersion/QueryVersion`. The package is `MFiles` and the service names are the
wire names (`IRPCSearch`, `IRPCObjectOperations`). Stubs generated from the published `.proto`
files produce these paths; you never write them by hand. On M-Files Cloud the path is used at the
root of the vault host, with no prefix. A method the server does not have answers
`UNIMPLEMENTED`.

## On-premises: finding the port

The gRPC port is the registry value `gRPCEndpoint` (DWORD) under
`HKEY_LOCAL_MACHINE\SOFTWARE\Motive\M-Files\<version>\Server\MFServer`. When the value is missing
or invalid the server uses 7766. The server listens on all network interfaces on that port; open
it in the firewall for remote clients.

Other ports derive from it unless set explicitly:

| Port | Default | Registry value | What |
|---|---|---|---|
| gRPC | 7766 | `gRPCEndpoint` | The API endpoint described on this page. |
| mf-http-grpc gateway | gRPC + 1 (7767) | `GRPCWEBPORT` | `mf-http-grpc`, see [HTTP access](https://developer.m-files.com/APIs/gRPC-API/runtime/http-access/index.md). |
| Local gRPC | - | - | For M-Files' own processes on the server machine. Do not use it. |

The local endpoint picks a random free port when its default is taken and writes the port back to
the registry, so its number is not stable.

Some deployments put the M-Files reverse proxy (Traefik) in front of the server. The proxy then
accepts gRPC over TLS on its HTTPS entry points, routes the `/MFiles` path prefix to the server and
marks the calls as remote (see `mfiles-is-remote-call` in [Call metadata](https://developer.m-files.com/APIs/gRPC-API/runtime/call-metadata/index.md)). Use
the address and certificate of the proxy.

## TLS

**M-Files Cloud** always uses TLS with a publicly trusted certificate. Use your gRPC library's
default TLS credentials.

**On-premises** the endpoint is plain HTTP/2 until an administrator enables TLS. TLS is enabled
and its certificate installed with
[SetServerEndpointSettings](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCServerAdmin/SetServerEndpointSettings/index.md) (`use_tls`
and one certificate with its private key; the server supports a single certificate). The server
stores the settings in its master database and restarts the endpoint.
[GetServerEndpointSettings](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCServerAdmin/GetServerEndpointSettings/index.md) shows the
current state. The server does not request client certificates.

A plain endpoint carries passwords, tokens and session IDs unencrypted. Use it only on a trusted
network or for local development.

**Trusting the certificate.** The client must trust the CA that issued the server certificate,
and the certificate's names must match the host name you connect to. M-Files' own Windows clients
trust the Windows "Trusted Root Certification Authorities" store, so a certificate from an
enterprise CA that is deployed there works for them without further setup. For a self-signed or
private-CA certificate, give your gRPC client the CA certificate in PEM format:

| Language | How to trust a PEM CA file |
|---|---|
| Python (`grpcio`) | `grpc.ssl_channel_credentials(root_certificates=pem_bytes)` |
| Go | `credentials.NewClientTLSFromFile(caFile, "")` |
| Node (`@grpc/grpc-js`) | `grpc.credentials.createSsl(fs.readFileSync(caFile))` |
| C# (`Grpc.Net.Client`) | Install the CA in the machine's trust store, or validate the server certificate against it in `HttpClientHandler.ServerCertificateCustomValidationCallback` |

The Python helper of the samples creates its channel like this (`MFILES_CA_CERT` points to the
PEM file):

```python
options = [("grpc.max_receive_message_length", MAX_RECEIVE_MESSAGE_BYTES),
           ("grpc.max_send_message_length", MAX_SEND_MESSAGE_BYTES)]
if config.tls:
    root_certificates = Path(config.ca_cert).read_bytes() if config.ca_cert else None
    credentials = grpc.ssl_channel_credentials(root_certificates=root_certificates)
    self._channel = grpc.secure_channel(config.address, credentials, options=options)
else:
    self._channel = grpc.insecure_channel(config.address, options=options)
self.channel = grpc.intercept_channel(self._channel, _MetadataInterceptor(self))
```

*Source: [python/mfiles_client.py](https://developer.m-files.com/APIs/gRPC-API/downloads/samples/python/mfiles_client.py)*

## HTTP/2

Native gRPC needs HTTP/2 all the way to the server. With TLS, the client negotiates `h2` with
ALPN, which gRPC libraries do by default. Without TLS, the server expects HTTP/2 with prior
knowledge (h2c); gRPC libraries do this when you create an insecure channel. A proxy or load
balancer between client and server must forward HTTP/2 and response trailers, because the gRPC
status and the M-Files error details travel in trailers ([Errors](https://developer.m-files.com/APIs/gRPC-API/runtime/errors/index.md)).

## Message size limits

| Limit | Server default | Registry value (`...\Server\MFServer`) |
|---|---|---|
| Request message the server accepts | 48 MiB (50 331 648 bytes) | `gRPCMaxMessageLength` |
| Response message the server sends | No limit (2 GiB - 1) | `gRPCMaxResponseLength` |
| Metadata (headers or trailers) of a call | 512 KiB | `gRPCMaxMetadataSize` |

A request over the server's limit fails with `RESOURCE_EXHAUSTED` and the message
`SERVER: Received message larger than max (51380234 vs. 50331648)`.

Most gRPC libraries accept responses of at most 4 MiB by default. M-Files responses can be larger,
for example a 4 MiB file block plus its framing, or a large search result: such a call fails on
the client with `RESOURCE_EXHAUSTED` and `CLIENT: Received message larger than max (4194309 vs.
4194304)`. Do what M-Files' own client does, and what the samples do: accept responses of any
size, and send requests up to the server's limit (48 MiB unless the administrator changed it):

| Language | No receive limit | Send limit |
|---|---|---|
| Python | channel option `grpc.max_receive_message_length` = -1 | `grpc.max_send_message_length` |
| Go | `grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt32))` | `grpc.MaxCallSendMsgSize(n)` |
| C# (`Grpc.Net.Client`) | `GrpcChannelOptions.MaxReceiveMessageSize` = `null` | `MaxSendMessageSize` |
| Node | channel option `grpc.max_receive_message_length` = -1 | `grpc.max_send_message_length` |

Files larger than a single message are transferred in blocks; see [Files](https://developer.m-files.com/APIs/gRPC-API/runtime/files/index.md).

## HTTP/2 keepalive pings (not the session)

The server closes connections whose client sends HTTP/2 keepalive pings more often than every
5 seconds while no data flows (registry value `gRPCMinPingIntervalMilliseconds`, default 5000).
M-Files' own clients ping every 10 seconds, wait 5 seconds for the answer, and ping only while a
call is active. If you enable keepalive in your client, use an interval of 10 seconds or more.

HTTP/2 keepalive only keeps the connection open. The M-Files session expires on its own schedule
unless you call [KeepAlive](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCLogin/KeepAlive/index.md); see
[Authentication and sessions](https://developer.m-files.com/APIs/gRPC-API/runtime/authentication/index.md#keeping-the-session-alive).

## Is the server reachable?

[QueryVersion](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCQueryVersion/QueryVersion/index.md) needs no session and no metadata. It
is the cheapest check that the address, TLS and HTTP/2 path work:

```text
/MFiles.IRPCQueryVersion/QueryVersion   request {}   ->   server_version: 7318397729964032
```

`server_version` is a packed 64-bit version: major, minor, build and revision, 16 bits each, from
the most significant end. `7318397729964032` is 26.11.16645.0:

| Part | Bits | Value |
|---|---|---|
| major | `v >> 48` | 26 |
| minor | `(v >> 32) & 0xFFFF` | 11 |
| build | `(v >> 16) & 0xFFFF` | 16645 |
| revision | `v & 0xFFFF` | 0 |

```csharp
/// <summary>
/// QueryVersion packs a version into 64 bits: major, minor, build and revision, 16 bits each.
/// </summary>
public static string DecodeVersion(ulong version) =>
    $"{version >> 48}.{(version >> 32) & 0xFFFF}.{(version >> 16) & 0xFFFF}.{version & 0xFFFF}";
```

*Source: [csharp/Recipes/Connect.cs](https://developer.m-files.com/APIs/gRPC-API/downloads/samples/csharp/Recipes/Connect.cs)*

[GetServerCapabilities](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCLogin/GetServerCapabilities/index.md) is also anonymous and tells
which optional features the server has; see [Versions and compatibility](https://developer.m-files.com/APIs/gRPC-API/runtime/versioning/index.md).

If the check fails:

| Status | Usual cause |
|---|---|
| `UNAVAILABLE` | Wrong host or port, firewall, an untrusted certificate, or a TLS client against a plain endpoint (`Tls handshake failed`). |
| `UNIMPLEMENTED` | A plain (non-TLS) client against M-Files Cloud (`Received http2 header with status: 404`), a path that reached something other than M-Files Server, or a proxy that rewrote the path. |
| `RESOURCE_EXHAUSTED` | A message size limit; see above. |
