---
title: "MCP Server Hosting"
description: "How to host MCP servers behind TSLink with zero-trust identity verification, encryption, and access control"
url: "https://tslink.md/docs/mcp-hosting"
locale: "en"
product_version: "0.1.1"
source: "https://github.com/anydoor7/tslink/blob/v0.1.1/docs/agents.md"
---

> Documentation index: https://tslink.md/llms.txt · Installed binary is authoritative: `tslink manifest`.

## Why MCP Servers Need Zero-Trust

The Model Context Protocol connects AI assistants to external tools, databases, and APIs. MCP servers typically run on `localhost`, which is secure for single-machine use. The security challenge arises when you need remote access -- accessing your MCP servers from another device, sharing them with team members, or connecting them to AI workflows running on different machines.

Remote access requires a reachable transport and the right authorization. A public HTTP endpoint can be appropriate with application-level controls; a private tailnet endpoint is useful when every client can join the network. This guide uses an already-running HTTP MCP server and preserves its application authorization.

For a detailed analysis of MCP security risks and why network-layer security matters, see [Why Your MCP Server Should Not Be on the Public Internet](https://tslink.md/blog/mcp-server-security).

TSLink provides an alternative: host MCP servers on your private Tailscale network with per-service tailnet identity, WireGuard transport, and optional `--allow` access control for proxy HTTP services. No public exposure by default. No DNS records created by TSLink; tailnet connectivity still depends on Tailscale control-plane and DERP behavior.

This page covers reaching a third-party MCP server across your tailnet. TSLink also ships its own MCP server, so an agent can drive TSLink directly -- that is [TSLink as an MCP Server](https://tslink.md/docs/mcp-server.md).

## Quick Setup

First confirm the backend already serves MCP over HTTP and note its actual endpoint path, such as `http://localhost:8080/mcp`. TSLink proxies that HTTP transport; it does not convert a stdio server into HTTP. Choose any required `--allow` restriction before registering the service:

```bash
tslink add mcp-tavily --proxy localhost:8080 --json
```

Default add ensures the background gateway is running. Inspect its result: if `data.status` is `needs_login`, a human must open `data.auth_url` and complete enrollment and any tailnet approval. Then poll the existing gateway for the exact service origin:

```bash
tslink url mcp-tavily --wait
```

Inspect `tslink status --json` as well; daemon liveness alone is not service readiness. Configure the client with the exact runtime origin plus the backend's actual MCP path: for a backend at `/mcp`, append `/mcp` to that origin. Keep another path if your backend uses one. The [MCP transport specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports) defines a complete endpoint path, not merely a host.

Use an HTTP MCP client whose connection originates on a device inside the tailnet, such as a local CLI client with HTTP transport support. Claude's account-level remote connectors originate from Anthropic's cloud, including when configured in Desktop, and cannot reach this private endpoint merely because your laptop can. Desktop's local MCP configuration is a separate mechanism; local stdio requires a client that can launch the process and is not a `claude.ai` fallback. See [Claude's network requirements](https://support.claude.com/en/articles/11175166-get-started-with-custom-connectors-using-remote-mcp).

Do not run `serve` after default add. A deliberate manual setup uses `--no-daemon-install` and the [manual gateway prerequisites](https://tslink.md/docs/daemon.md#running-as-a-daemon). The tailnet leg uses WireGuard, and proxy HTTP can carry best-effort WhoIs identity headers; keep the backend's MCP authorization.

## Access Control

Restrict which users or groups can reach a specific MCP server with the `--allow` flag:

```bash
tslink add mcp-tavily --proxy localhost:8080 --allow user@example.com
```

Only the specified user can reach this MCP server. All other requests receive a `403 Forbidden` response.

For team scenarios, use Tailscale tags:

```bash
tslink add mcp-tavily --proxy localhost:8080 --allow tag:ai-team
```

Tags are defined in your [Tailscale ACL policy](https://tailscale.com/kb/1018/acls). This lets you manage MCP server access through your existing Tailscale identity infrastructure without additional configuration in TSLink.

For proxy HTTP services, TSLink resolves Tailscale identity via WhoIs and can enforce `--allow` on each request. There are no TSLink session tokens, cookies, or credentials stored in the MCP client configuration. Keep MCP application-layer authorization where the MCP server needs tool-level policy.

## Multiple MCP Servers

Each MCP server gets its own TSLink service with its own identity and access controls:

```bash
# Web search tool -- available to the whole team
tslink add mcp-tavily --proxy localhost:8080 --allow tag:ai-team

# GitHub integration -- restricted to developers
tslink add mcp-github --proxy localhost:8081 --allow tag:developers

# Database access -- restricted to data team
tslink add mcp-postgres --proxy localhost:8082 --allow tag:data-team

# Internal knowledge base -- restricted to a specific user
tslink add mcp-docs --proxy localhost:8083 --allow admin@example.com
```

Each MCP server runs on its own WireGuard node with a distinct tailnet identity — network segmentation, not host isolation. Compromising one server does not by itself grant tailnet access to another server's node, though a compromised process can still reach other resources on the same host through other paths. This per-service microsegmentation reflects a core principle of [NIST SP 800-207](https://csrc.nist.gov/publications/detail/sp/800-207/final) zero-trust architecture (Tenet 1: all computing services are treated as independent resources).

Each `add` ensures the gateway is running. Complete any `needs_login` / `auth_url` handoff, then poll `tslink url <name> --wait` for each exact runtime origin and preserve that backend's MCP path in the client endpoint. Do not start another `serve`.

Add or remove MCP servers while the gateway is running. TSLink watches the service registry and applies changes through hot reload without interrupting other active services.

## Monitoring: Access Logs for MCP Audit

Use `tslink access log --app my-mcp --since 24h` for bounded local HTTP access history with WhoIs-attested identity when available. It records gateway access, not third-party MCP tool semantics. Identity can be absent; records can drop or have gaps. See [access history](https://tslink.md/docs/access-history.md). Backend identity propagation remains separate. `tslink logs` reads daemon diagnostics on stderr, not this complete query surface.

Inspect recent daemon logs with the shipped log viewer:

```bash
tslink logs --source err --last 100
tslink logs --level error
```

Daemon log files are stored under `~/.config/tslink/logs/` (`tslink.out.log` and `tslink.err.log`). TSLink does not ship a `serve` logging format switch; use `tslink logs` or read the log files directly for aggregation.

## What TSLink Provides vs. What It Does Not

TSLink secures MCP servers at the network and transport layer:

| TSLink provides                                                          | TSLink does not provide                                 |
| ------------------------------------------------------------------------ | ------------------------------------------------------- |
| WireGuard-encrypted tailnet transport (backend hop may be plaintext)     | Application-layer authorization within the MCP protocol |
| Best-effort identity checks (WhoIs, cached 60s), enforced with `--allow` | Input validation for MCP tool calls                     |
| Per-service tailnet identity (network segmentation, not host isolation)  | Content filtering for MCP responses                     |
| Access control via `--allow`                                             | Rate limiting per MCP tool (roadmap)                    |
| Bounded local access history                                             | MCP-specific protocol inspection                        |

TSLink is complementary to application-layer MCP security features such as [OAuth authorization](https://modelcontextprotocol.io/specification/2025-03-26/basic/authorization/). Network-layer security (encryption, identity, segmentation) and application-layer security (authorization, input validation) are both necessary. Neither alone is sufficient.
