diff --git a/docs/toolhive/guides-cli/custom-permissions.md b/docs/toolhive/guides-cli/custom-permissions.md deleted file mode 100644 index c683073c..00000000 --- a/docs/toolhive/guides-cli/custom-permissions.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Custom permissions -description: - How to create and apply custom permission profiles for MCP servers in - ToolHive. -sidebar_position: 50 ---- - -ToolHive includes a permission system that lets you control an MCP server's -access to the file system and network resources. This is crucial for maintaining -security and ensuring that MCP servers operate within defined boundaries. - -This guide shows you how to create and apply custom permission profiles for MCP -servers, including built-in profiles and examples of common use cases. - -:::important - -Network access rules referenced in this document aren't currently implemented in -ToolHive. They're a roadmap feature planned for future releases. For now, only -file system permissions are enforced. - -Contributions to help implement this feature are welcome! You can contribute by -visiting our [GitHub repository](https://github.com/stacklok/toolhive). - -::: - -## Understanding permission profiles - -Permissions are defined using JSON permission profiles. These profiles specify: - -- File system access (read and/or write access to specific paths) -- Network access rules (outbound connections from the MCP server) - -:::note - -Since the MCP server runs in a container, it can't access the host file system -by default. File system access is relative to the container's file system. - -When you run a server with the `--volume` flag to mount a local path, ToolHive -adds the path to the MCP server's permission profile automatically. - -::: - -Profiles include the following sections: - -- `read`: List of file system paths that the MCP server can read, relative to - the container's file system. -- `write`: List of file system paths that the MCP server can write to (this also - implies read access). -- `network`: Network access rules for outbound connections. - - `outbound`: Outbound network access rules, which include: - - `insecure_allow_all`: If set to `true`, allows unrestricted outbound - network access. This isn't recommended for production use. - - `allow_transport`: List of allowed transport protocols (e.g., `tcp`, - `udp`). - - `allow_host`: List of allowed hostnames or IP addresses for outbound - connections. - - `allow_port`: List of allowed ports for outbound connections. - -## Default permissions in the ToolHive registry - -ToolHive includes default least-privilege permissions for MCP servers in the -built-in registry. These defaults are designed to balance functionality and -security, but you should review them to make sure they meet your specific -requirements. - -View these permissions using the following command: - -```bash -thv registry info -``` - -In the output, look for the "Permissions" section: - -```test -Permissions: - Read: - - /data - Write: - - /tmp - Network: - Allow Transport: tcp - Allow Host: google.com - Allow Port: 443 -``` - -This example shows that the MCP server has read access to `/data`, read/write -access to `/tmp`, and can make outbound TCP connections to `google.com` on -port 443. - -Always verify the default permissions and override them with a custom profile if -needed to meet your security policies. - -:::tip - -Add `--format json` to the -[`thv registry info`](../reference/cli/thv_registry_info.md) command to get the -output in JSON format for easier customization. Use the contents of the -`permissions` section as a starting point for creating a custom profile. - -::: - -## Built-in profiles - -ToolHive includes two built-in profiles that you can use without creating a -custom file: - -- The `network` profile permits outbound network access. It's the default - profile applied to MCP servers when you run a server without the - `--permission-profile` flag. - - :::important - - This profile is useful for development and testing but isn't recommended for - production use since it doesn't restrict network destinations. If possible, - create a custom profile that specifies the allowed hosts and ports. - - ::: - -- The `none` profile provides no network access. It's useful for MCP servers - that don't require any external connectivity. File system access is limited to - paths you explicitly mount using the `--volume` flag. - -## Create a custom permissions profile - -Create a JSON file with your desired permissions, like `~/custom-profile.json`. -For example: - -```json -{ - "read": ["/example/path1", "/example/path2"], - "write": ["/example/path3"], - "network": { - "outbound": { - "insecure_allow_all": false, - "allow_transport": ["tcp", "udp"], - "allow_host": ["localhost", "google.com"], - "allow_port": [80, 443] - } - } -} -``` - -This profile: - -- Allows read-only access to `/example/path1` and `/example/path2` -- Allows read and write access to `/example/path3` (note that the `write` - setting also implies read access) -- Allows outbound TCP or UDP connections to localhost and google.com on ports 80 - and 443 - -## Apply a permissions profile - -### Using a built-in profile - -To run an MCP server with a built-in profile: - -```bash -# This is equivalent to running a server without the --permission-profile flag -thv run --permission-profile network -``` - -or - -```bash -thv run --permission-profile none -``` - -### Using a custom profile file - -To run an MCP server with your custom profile: - -```bash -thv run --permission-profile -``` - -## Example: Restrict network access - -The GitHub MCP server in the registry has a default profile that allows access -to `github.com`, but you might need to customize it for a self-hosted GitHub -Enterprise instance: - -1. Create a file named `github-profile.json`: - - ```json - { - "network": { - "outbound": { - "insecure_allow_all": false, - "allow_transport": ["tcp"], - "allow_host": ["github.example.com"], - "allow_port": [443] - } - } - } - ``` - -2. Run the GitHub MCP server with this profile: - - ```bash - thv run --permission-profile ./github-profile.json --secret github,target=GITHUB_PERSONAL_ACCESS_TOKEN github - ``` - -This restricts the GitHub MCP server to make HTTPS connections only to -`github.example.com`. - -## Security best practices - -When creating and using permission profiles: - -- Use the `none` profile when possible (for MCP servers that don't require - network or file access) -- Only grant necessary permissions -- Avoid enabling `network.outbound.insecure_allow_all`, as this allows - unrestricted outbound network access -- Review and test custom profiles thoroughly -- Keep permission profiles in version control to track changes and share them - with your team - -## Related information - -- [`thv run` command reference](../reference/cli/thv_run.md) -- [Run MCP servers](run-mcp-servers.mdx) - -## Troubleshooting - -### File system access issues - -If your MCP server can't access the file system as expected: - -1. Verify that the path(s) in your profile are correct -2. Check that the permissions are set correctly (read/write) -3. Make sure the paths are accessible from within the container. You can execute - a shell in the container to check (this assumes the container includes an - interactive shell): - - ```bash - docker exec -it /bin/sh - ``` - -4. Restart the server with the updated profile or a corrected volume mount - -### Network connectivity issues - -If your MCP server can't connect to external services: - -1. Verify that your profile allows the necessary hosts and ports -2. Check that the transport protocol (TCP/UDP) is allowed -3. Try temporarily using the default `network` profile to confirm it's a - permissions issue diff --git a/docs/toolhive/guides-cli/custom-permissions.mdx b/docs/toolhive/guides-cli/custom-permissions.mdx new file mode 100644 index 00000000..18644dd5 --- /dev/null +++ b/docs/toolhive/guides-cli/custom-permissions.mdx @@ -0,0 +1,383 @@ +--- +title: Custom permissions +description: + How to create and apply filesystem permissions and network isolation for MCP + servers using permission profiles in ToolHive. +sidebar_position: 50 +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +ToolHive includes a permission system that lets you control an MCP server's +access to your host's file system and to network resources. This is crucial for +maintaining security and ensuring that MCP servers operate within defined +boundaries. + +This guide shows you how to create and apply custom permission profiles for MCP +servers, including built-in profiles and examples of common use cases. + +## Understanding permission profiles + +Permissions are defined using permission profiles. These profiles specify: + +- Host file system access (read and/or write access to specific paths) +- Network access rules (outbound connections from the MCP server) + +:::note + +Since the MCP server runs in a container, it can't access the host file system +by default. File system access is relative to the container's file system. + +When you run a server with the `--volume` flag to mount a local path, ToolHive +adds the path to the MCP server's permission profile automatically. + +::: + +Profiles include the following sections: + +- `read`: List of file system paths that the MCP server can read, relative to + the container's file system. +- `write`: List of file system paths that the MCP server can write to (this also + implies read access). +- `network`: Network access rules for outbound connections (see + [Network isolation](#network-isolation) for details): + - `outbound`: Outbound network access rules, which include: + - `insecure_allow_all`: If set to `true`, allows unrestricted outbound + network access. This isn't recommended for production use. + - `allow_host`: List of allowed hostnames or IP addresses for outbound + connections. To allow all subdomains of a domain, prefix the domain with a + period (e.g., `.github.com` allows any subdomain of `github.com`). + Wildcards are not supported. + - `allow_port`: List of allowed ports for outbound connections. + - `allow_transport`: List of allowed transport protocols (e.g., `tcp`, + `udp`). + +## Default permissions in the ToolHive registry + +ToolHive includes default least-privilege permissions for MCP servers in the +built-in registry. These defaults are designed to balance functionality and +security, but you should review them to make sure they meet your specific +requirements. + +View these permissions using the following command: + +```bash +thv registry info +``` + +In the output, look for the "Permissions" section: + +```test +Permissions: + Read: + - /data + Write: + - /tmp + Network: + Allow Transport: tcp + Allow Host: .google.com + Allow Port: 443 +``` + +This example shows that the MCP server has read access to `/data`, read/write +access to `/tmp`, and can make outbound TCP connections to `*.google.com` (note +the leading `.` which enables subdomain matching) on port 443. + +Always verify the default permissions and override them with a custom profile if +needed to meet your security policies. + +:::tip + +Add `--format json` to the +[`thv registry info`](../reference/cli/thv_registry_info.md) command to get the +output in JSON format for easier customization. Use the contents of the +`permissions` section as a starting point for creating a custom profile. + +::: + +## Built-in profiles + +ToolHive includes two built-in profiles that you can use without creating a +custom file: + +- The `network` profile permits all outbound network access. It's the default + profile applied to MCP servers when you run a custom server without the + `--permission-profile` flag. + + :::important + + This profile is useful for development and testing but isn't recommended for + production use since it doesn't restrict network destinations. If possible, + create a custom profile that specifies the allowed hosts and ports. + + ::: + +- The `none` profile provides no network access. It's useful for MCP servers + that don't require any external connectivity. File system access is limited to + paths you explicitly mount using the `--volume` flag. + +## Create a custom permission profile + +Create a JSON file with your desired permissions, like `~/custom-profile.json`. +For example: + +```json +{ + "read": ["/example/path1", "/example/path2"], + "write": ["/example/path3"], + "network": { + "outbound": { + "insecure_allow_all": false, + "allow_transport": ["tcp", "udp"], + "allow_host": ["localhost", ".google.com"], + "allow_port": [80, 443] + } + } +} +``` + +This profile: + +- Allows read-only access to `/example/path1` and `/example/path2` +- Allows read and write access to `/example/path3` (note that the `write` + setting also implies read access) +- Allows outbound TCP or UDP connections to `localhost` and `google.com` + (including subdomains) on ports 80 and 443 + +## Apply a permission profile + +### Using a built-in profile + +To run an MCP server with a built-in profile: + +```bash +# This is equivalent to running a server without the --permission-profile flag +thv run --permission-profile network +``` + +or + +```bash +thv run --permission-profile none +``` + +Add the `--isolate-network` flag to enforce network restrictions: + +```bash +thv run --isolate-network --permission-profile none +``` + +### Using a custom profile file + +To run an MCP server with your custom profile: + +```bash +thv run --isolate-network --permission-profile +``` + +## Network isolation + +To enforce the network access rules defined in the registry or your custom +permission profile, use the `--isolate-network` flag when running the MCP +server: + +```bash +thv run --isolate-network [--permission-profile ] +``` + +When you enable network isolation, ToolHive creates a secure network +architecture around your MCP server. This architecture includes several +components that work together to control network access. + +### Network architecture components + +Along with the main MCP server container, ToolHive launches additional +containers to manage network traffic: + +- An egress proxy container that filters outgoing network traffic +- A DNS container that provides controlled domain name resolution +- An ingress proxy container that handles incoming requests (only for MCP + servers using SSE or Streamable HTTP transport; stdio MCP servers don't need + this since they don't expose ports) + +### Network topology + +ToolHive creates two separate networks in the container runtime: + +- A shared external network (`toolhive-external`) that connects to your host's + network +- An internal network (`toolhive--internal`) for each MCP server + that isolates it from external access + +The MCP server container only connects to the internal network, while the proxy +and DNS containers connect to both networks. This design ensures that all +network traffic flows through controlled points, allowing ToolHive to enforce +the access rules you specify in your permission profile. + +The following diagrams show how network traffic flows through the isolation +architecture for different transport types: + + + + +For MCP servers using stdio transport, the ToolHive proxy process communicates +directly with the MCP server container through standard input and output. All +outbound network requests from the MCP server flow through the egress proxy and +DNS containers: + +```mermaid +architecture-beta + service mcp_client(server)[MCP client] + service toolhive_proxy(server)[ToolHive HTTP proxy process] + + group container_runtime[Container runtime] + group thv_internal[Isolated network] in container_runtime + service egress(server)[Egress proxy container] in container_runtime + service mcp_server(server)[MCP server container] in thv_internal + service dns_container(server)[DNS container] in container_runtime + + group external[External Resources] + service external_service(internet)[External service] in external + service external_dns(internet)[External DNS] in external + + junction outbound in container_runtime + + mcp_client:R --> L:toolhive_proxy + toolhive_proxy:R --> L:mcp_server + mcp_server:R -- L:outbound + egress:B <-- T:outbound + dns_container:T <-- B:outbound + egress:R --> L:external_service + dns_container:R --> L:external_dns +``` + + + + +For MCP servers using SSE or Streamable HTTP transport, ToolHive includes an +additional ingress proxy container. This proxy handles incoming HTTP requests +and ensures the MCP server remains isolated from direct external access: + +```mermaid +architecture-beta + service mcp_client(server)[MCP client] + service toolhive_proxy(server)[ToolHive HTTP proxy process] + + group container_runtime[Container runtime] + group thv_internal[Isolated network] in container_runtime + service ingress(server)[Ingress proxy container] in container_runtime + service egress(server)[Egress proxy container] in container_runtime + service mcp_server(server)[MCP server container] in thv_internal + service dns_container(server)[DNS container] in container_runtime + + group external[External resources] + service external_service(internet)[External service] in external + service external_dns(internet)[External DNS] in external + + junction outbound in container_runtime + + mcp_client:R --> L:toolhive_proxy + toolhive_proxy:R --> L:ingress + ingress:R --> L:mcp_server + mcp_server:R -- L:outbound + egress:B <-- T:outbound + dns_container:T <-- B:outbound + egress:R --> L:external_service + dns_container:R --> L:external_dns +``` + + + + +:::important + +Network isolation supports HTTP and HTTPS protocols. If your MCP server needs to +use other protocols (like direct TCP connections for database access), you'll +need to run it without the `--isolate-network` flag and rely on the container's +built-in isolation instead. + +::: + +## Example: Restrict network access + +The GitHub MCP server in the registry has a default profile that allows access +to `github.com`, but you might need to customize it for a self-hosted GitHub +Enterprise instance: + +1. Create a file named `github-profile.json`: + + ```json + { + "network": { + "outbound": { + "insecure_allow_all": false, + "allow_transport": ["tcp"], + "allow_host": ["github.example.com"], + "allow_port": [443] + } + } + } + ``` + +2. Run the GitHub MCP server with this profile: + + ```bash + thv run --isolate-network --permission-profile ./github-profile.json --secret github,target=GITHUB_PERSONAL_ACCESS_TOKEN github + ``` + +This restricts the GitHub MCP server to make HTTPS connections only to +`github.example.com`. + +## Security best practices + +When creating and using permission profiles: + +- Use the `none` profile when possible (for MCP servers that don't require + network or file access) +- Only grant necessary permissions +- Avoid enabling `network.outbound.insecure_allow_all`, as this allows + unrestricted outbound network access +- Review and test custom profiles thoroughly +- Keep permission profiles in version control to track changes and share them + with your team + +## Related information + +- [`thv run` command reference](../reference/cli/thv_run.md) +- [Run MCP servers](run-mcp-servers.mdx) + +## Troubleshooting + +### File system access issues + +If your MCP server can't access the file system as expected: + +1. Verify that the path(s) in your profile are correct +2. Check that the permissions are set correctly (read/write) +3. Make sure the paths are accessible from within the container. You can execute + a shell in the container to check (this assumes the container includes an + interactive shell): + + ```bash + docker exec -it /bin/sh + ``` + +4. Restart the server with the updated profile or a corrected volume mount + +### Network connectivity issues + +If your MCP server can't connect to external services: + +1. Verify that your profile allows the necessary hosts and ports +2. Check that the transport protocol (TCP/UDP) is allowed +3. Check the logs of the egress proxy container for any blocked requests: + + ```bash + docker logs -egress + ``` + + Look for messages indicating denied connections. + +4. Try temporarily using the default `network` profile to confirm it's a + permissions issue diff --git a/docs/toolhive/guides-cli/registry.md b/docs/toolhive/guides-cli/registry.md index e90fa078..e713e40d 100644 --- a/docs/toolhive/guides-cli/registry.md +++ b/docs/toolhive/guides-cli/registry.md @@ -119,9 +119,9 @@ and security profile before running it. - **Tools list** (line 8): The list of tools this MCP server provides - **Configuration** (line 16): Required and optional environment variables needed to run the server -- **Permissions** (line 21): The permissions profile applied to the server, +- **Permissions** (line 21): The permission profile applied to the server, including file system and network access (see - [Custom permissions](./custom-permissions.md)) + [Custom permissions](./custom-permissions.mdx)) ## Use a remote registry diff --git a/docs/toolhive/guides-cli/run-mcp-servers.mdx b/docs/toolhive/guides-cli/run-mcp-servers.mdx index 375df8fe..651f770b 100644 --- a/docs/toolhive/guides-cli/run-mcp-servers.mdx +++ b/docs/toolhive/guides-cli/run-mcp-servers.mdx @@ -110,7 +110,7 @@ The optional `:ro` suffix makes the volume read-only in the container. This is useful for sharing files without letting the MCP server modify them. ToolHive automatically adds mounted paths to the MCP server's -[permissions profile](./custom-permissions.md). +[permission profile](./custom-permissions.mdx). For example, to mount a local directory to the Filesystem MCP server: @@ -371,7 +371,7 @@ control your servers. - [`thv run` command reference](../reference/cli/thv_run.md) - [Client configuration](client-configuration.md) - [Secrets management](secrets-management.mdx) -- [Custom permissions](custom-permissions.md) +- [Custom permissions](custom-permissions.mdx) ## Troubleshooting diff --git a/docs/toolhive/guides-cli/secrets-management.mdx b/docs/toolhive/guides-cli/secrets-management.mdx index f2ccd2bb..8831c9f1 100644 --- a/docs/toolhive/guides-cli/secrets-management.mdx +++ b/docs/toolhive/guides-cli/secrets-management.mdx @@ -15,7 +15,7 @@ configuration files. ## Secrets providers -ToolHive supports multiple secret providers to fit different security and +ToolHive supports multiple secrets providers to fit different security and workflow requirements: - `encrypted` - ToolHive encrypts secrets using a password stored in your diff --git a/docs/toolhive/guides-k8s/run-mcp-k8s.md b/docs/toolhive/guides-k8s/run-mcp-k8s.md index caef7b0f..5ca94cd3 100644 --- a/docs/toolhive/guides-k8s/run-mcp-k8s.md +++ b/docs/toolhive/guides-k8s/run-mcp-k8s.md @@ -412,7 +412,18 @@ Permission profiles can be configured in two ways: ``` The ConfigMap should contain a JSON -[permissions profile](../guides-cli/custom-permissions.md#create-a-custom-permissions-profile). +[permission profile](../guides-cli/custom-permissions.mdx#create-a-custom-permission-profile). + +:::important + +Outbound network filtering using permission profiles isn't currently implemented +in the ToolHive Operator. This is a roadmap feature planned for future releases. +For now, only file system permissions are enforced. + +Contributions to help implement this feature are welcome! You can contribute by +visiting our [GitHub repository](https://github.com/stacklok/toolhive). + +::: ## Next steps @@ -423,7 +434,7 @@ to learn how to connect to MCP servers using different clients. - [Deploy the operator using Helm](./deploy-operator-helm.md) - Install the ToolHive operator -- [Custom permissions](../guides-cli/custom-permissions.md) - Configure +- [Custom permissions](../guides-cli/custom-permissions.mdx) - Configure permission profiles ## Troubleshooting diff --git a/docs/toolhive/index.mdx b/docs/toolhive/index.mdx index 8a523390..3236390a 100644 --- a/docs/toolhive/index.mdx +++ b/docs/toolhive/index.mdx @@ -67,15 +67,11 @@ configurations. flowchart LR subgraph container["**Docker/Podman**"] direction LR - subgraph container1["Container"] - mcp1["MCP Server"] - end - subgraph container2["Container"] - mcp2["MCP Server"] - end + mcp1["MCP server
container"] + mcp2["MCP server
container"] end proxy1["SSE proxy"] -- stdio --> mcp1 - proxy2["SSE proxy"] -- stdio --> mcp2 + proxy2["SSE proxy"] -- SSE --> mcp2 T["ToolHive CLI"] -- Socket API --> container C["Client"] -- HTTP/SSE --> proxy1 & proxy2 T ~~~ C @@ -97,9 +93,10 @@ ToolHive offers the following features to simplify MCP deployment: servers that you can discover and run effortlessly. - **Comprehensive security**: Run MCP servers in isolated containers with - customizable, fine-grained permissions using JSON profiles. Securely manage - secrets and configurations using built-in encrypted storage or 1Password - integration, eliminating plaintext secrets in configuration files. + customizable, fine-grained permissions and network access filtering using JSON + profiles. Securely manage secrets and configurations using built-in encrypted + storage or 1Password integration, eliminating plaintext secrets in + configuration files. - **Enterprise readiness**: Implement robust OAuth-based authorization controls for enterprise environments that integrate seamlessly with existing diff --git a/docs/toolhive/tutorials/quickstart.mdx b/docs/toolhive/tutorials/quickstart.mdx index ad338a77..f6907f52 100644 --- a/docs/toolhive/tutorials/quickstart.mdx +++ b/docs/toolhive/tutorials/quickstart.mdx @@ -276,7 +276,7 @@ server. Here are some next steps to explore: [`thv run `](../reference/cli/thv_run.md) - Learn about [secrets management](../guides-cli/secrets-management.mdx) for MCP servers that require authentication -- Explore [custom permissions](../guides-cli/custom-permissions.md) for MCP +- Explore [custom permissions](../guides-cli/custom-permissions.mdx) for MCP servers - Set up [shell completion](../guides-cli/install.mdx#enable-shell-completion) to make ToolHive commands easier to use