Parallels RAS MCP Server
# Parallels RAS MCP Server
A community-maintained, read-only [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server for querying Parallels Remote Application Server (RAS) infrastructure via the [RAS REST API](https://docs.parallels.com/landing/ras-rest-api-guide).
Gives AI assistants visibility into your RAS environment — infrastructure, site settings, policies, publishing, and sessions — without making any changes.
> Not affiliated with Parallels International GmbH. "Parallels" is a trademark of its respective owner.
## Scope and intended use
Two transports are supported, selected via the `MCP_TRANSPORT` environment variable:
- **`stdio`** (default) — launched as a local subprocess by the MCP client (Claude Desktop, Claude Code, Cursor, etc.). Intended for an individual administrator on their own workstation, or for development and test environments. Credentials come from the launching process's environment; there is no network listener.
- **`http`** — streamable-HTTP listener with a required bearer token. Intended for trusted-network deployments where one server is shared by multiple clients (e.g. behind a reverse proxy that adds TLS). Defaults to binding `127.0.0.1:3000`; binding to all interfaces is opt-in.
In either mode this server holds a RAS administrator session and exposes 41 read-only tools. It does not expose write or destructive tools and does not provide multi-tenancy or rate limiting — treat it as an admin-equivalent service and protect access accordingly.
**API compatibility:** verified against the **Parallels RAS v21** REST API. Resources used are stable across v18–v21.
## Prerequisites
- [Node.js](https://nodejs.org/) 18 or later
- npm
- Access to a Parallels RAS server with the REST API enabled (port 20443 by default)
## Installation
```bash
git clone https://github.com/RMITBLOG/ParallelsRAS_MCP.git
cd ParallelsRAS_MCP
npm install
npm run build
```
## Environment Variables
### Connection to RAS
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `RAS_HOST` | Yes | — | RAS server hostname or IP address |
| `RAS_USERNAME` | Yes | — | Administrator username |
| `RAS_PASSWORD` | Yes | — | Administrator password |
| `RAS_PORT` | No | `20443` | REST API port |
| `RAS_IGNORE_TLS` | No | `true` | Skip TLS certificate verification (for self-signed certs) |
### Transport
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `MCP_TRANSPORT` | No | `stdio` | `stdio` or `http` |
| `MCP_HTTP_BEARER_TOKEN` | HTTP only | — | Bearer token clients must present in `Authorization: Bearer …`. Server refuses to start without it. Generate with `openssl rand -hex 32`. |
| `MCP_HTTP_HOST` | No | `127.0.0.1` | Bind address. Set to `0.0.0.0` to expose on all interfaces (front with TLS termination). |
| `MCP_HTTP_PORT` | No | `3000` | Listen port. |
## Configuration
The examples below cover the **stdio** transport, which is the default and what most users want. For the **HTTP** transport, see [Running over HTTP](#running-over-http) further down.
### Claude Desktop
Edit your `claude_desktop_config.json` (typically at `%APPDATA%\Claude\claude_desktop_config.json` on Windows or `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
```json
{
"mcpServers": {
"parallels-ras": {
"command": "node",
"args": ["/path/to/ParallelsRAS_MCP/build/index.js"],
"env": {
"RAS_HOST": "ras-server.example.com",
"RAS_USERNAME": "administrator",
"RAS_PASSWORD": "your-password",
"RAS_PORT": "20443",
"RAS_IGNORE_TLS": "true"
}
}
}
}
```
### Claude Code
```bash
claude mcp add parallels-ras -- node /path/to/ParallelsRAS_MCP/build/index.js
```
Set environment variables in your shell or in the Claude Code MCP configuration.
### Cursor
In Cursor settings, go to **Features → MCP Servers** and add:
- **Name:** `parallels-ras`
- **Command:** `node /path/to/ParallelsRAS_MCP/build/index.js`
- **Environment:** `RAS_HOST`, `RAS_USERNAME`, `RAS_PASSWORD`
### Other MCP-compatible clients
For any client supporting MCP over stdio, point it at:
```
node /path/to/ParallelsRAS_MCP/build/index.js
```
with the required environment variables set in the client's MCP server configuration.
## Running over HTTP
The HTTP transport implements [MCP Streamable HTTP](https://modelcontextprotocol.io/specification/) and runs as a long-lived process. Use it when you want one server shared by multiple clients on a trusted network — typically behind a reverse proxy that terminates TLS.
### Start the server
```bash
export RAS_HOST=ras-server.example.com
export RAS_USERNAME=administrator
export RAS_PASSWORD=your-password
export MCP_TRANSPORT=http
export MCP_HTTP_BEARER_TOKEN=$(openssl rand -hex 32) # required
# export MCP_HTTP_HOST=127.0.0.1 # default; set 0.0.0.0 to expose
# export MCP_HTTP_PORT=3000
npm run start:http
```
The server logs the listen address on startup. The MCP endpoint is `POST /mcp`. Requests must include `Authorization: Bearer <MCP_HTTP_BEARER_TOKEN>`; missing or wrong tokens return `401`.
### Connect a client
For clients that support a streamable-HTTP MCP server, point them at `http://<host>:<port>/mcp` with the bearer token in the `Authorization` header. For example, the Claude Code CLI:
```bash
claude mcp add parallels-ras --transport http \
--header "Authorization: Bearer $MCP_HTTP_BEARER_TOKEN" \
http://your-server:3000/mcp
```
### Production checklist
- **Always** front this with TLS — a reverse proxy (nginx, Caddy, Traefik) terminating HTTPS, with the MCP server bound to `127.0.0.1` and reached only via the proxy.
- Treat `MCP_HTTP_BEARER_TOKEN` as a credential — at least 32 bytes of entropy, stored in a secret manager, rotated when staff leave.
- Restrict network reachability (firewall, VPN, private subnet). The bearer check is the only auth layer in the server itself.
- The RAS admin credentials sit on the same host as the listener — anyone with shell access on that host can read them. Do not run this on a multi-tenant box.
## Available Tools (41 total)
All tools are read-only and annotated with `readOnlyHint: true` for automatic approval in compatible clients.
**List tools** (sessions, hosts, certs, agents, published items, etc.) accept three optional inputs for narrowing large responses:
- `fields: string[]` — keep only these top-level keys on each row.
- `filter: Record<string, string|number|boolean>` — equality match on top-level fields (AND across keys; strings are case-insensitive).
- `limit: number` — cap rows after filtering. Default 50, hard max 200.
Responses lead with a one-line `NOTE:` header summarising total rows, filter matches, and truncation. A 64 KB byte safety net applies to every response.
### Infrastructure (14)
| Tool | Description |
|------|-------------|
| `ras_infra_get_agents` | List all RAS agents and their status |
| `ras_infra_get_connection_brokers` | Connection broker status and priority |
| `ras_infra_get_providers` | Cloud/hypervisor providers (AVD, AWS, Azure, Hyper-V, etc.) |
| `ras_infra_get_rds_hosts` | RDS session hosts |
| `ras_infra_get_rds_hostpools` | RDS host pools |
| `ras_infra_get_certificates` | Certificate inventory |
| `ras_infra_get_halb_status` | HALB device status |
| `ras_infra_get_enrollment_status` | Enrollment server status |
| `ras_infra_get_vdi_hostpools` | VDI host pools |
| `ras_infra_get_vdi_templates` | VDI templates |
| `ras_infra_get_gateway_status` | Secure Client Gateway status |
| `ras_infra_get_sites` | Farm sites and their status |
| `ras_infra_get_saml_idps` | SAML identity providers for SSO |
| `ras_infra_get_themes` | User portal themes and branding |
### Site Settings (9)
| Tool | Description |
|------|-------------|
| `ras_site_get_ad_integration` | Active Directory integration config |
| `ras_site_get_connection_settings` | Connection and authentication settings |
| `ras_site_get_load_balancing` | Load balancing settings |
| `ras_site_get_mfa` | MFA provider configuration |
| `ras_site_get_printing` | Printing settings |
| `ras_site_get_tenant_broker` | Tenant broker status |
| `ras_site_get_notifications` | Notification event configuration |
| `ras_site_get_url_redirection` | URL redirection rules |
| `ras_site_get_cpu_optimization` | CPU optimization settings |
> FSLogix is not exposed at site scope by the REST API — it is configured per host pool / per AVD template, or via PowerShell.
### Policies (1)
| Tool | Description |
|------|-------------|
| `ras_policies_list` | List all client policies |
### Farm Settings (7)
| Tool | Description |
|------|-------------|
| `ras_farm_get_administrators` | Admin accounts and roles |
| `ras_farm_get_config` | Farm configuration |
| `ras_farm_get_licensing` | Licensing status and seat usage |
| `ras_farm_get_version` | Web service version |
| `ras_farm_get_performance` | Performance monitor configuration |
| `ras_farm_get_mailbox` | SMTP mailbox settings |
| `ras_farm_get_reporting` | Reporting configuration |
### Publishing (9)
| Tool | Description |
|------|-------------|
| `ras_pub_get_rds_apps` | Published RDS applications |
| `ras_pub_get_vdi_apps` | Published VDI applications |
| `ras_pub_get_avd_apps` | Published AVD applications |
| `ras_pub_get_rds_desktops` | Published RDS desktops |
| `ras_pub_get_vdi_desktops` | Published VDI desktops |
| `ras_pub_get_avd_desktops` | Published AVD desktops |
| `ras_pub_get_folders` | Resource folders |
| `ras_pub_get_status` | Publishing service status |
| `ras_pub_get_all_items` | All published items (combined view) |
### RD Sessions (1)
| Tool | Description |
|------|-------------|
| `ras_sessions_list` | Active remote desktop sessions |
## Extending
Most tools follow one of two shapes: a **list tool** (the API returns an array of rows) or a **single-object tool** (config/status blob). Both are registered through factories in `src/tools/_format.ts`, so adding a new tool is a small `ToolDef` record plus one factory call.
To add a new tool:
1. Open the appropriate file in `src/tools/` (e.g., `infrastructure.ts` for a new infra resource), or create a new one.
2. Add a `ToolDef` record to the file's `LIST_TOOLS` or `OBJECT_TOOLS` array:
```ts
{
name: "ras_infra_get_widgets",
title: "Widgets",
description: "List widgets in the farm. Supports `fields`, `filter`, `limit`.",
path: "/api/Widget",
errorContext: "Failed to retrieve widgets",
}
```
3. If you created a new file, export a `register(server)` function that loops over your `ToolDef` arrays calling `registerListTool` and/or `registerObjectTool`, then import and call it from `src/index.ts`.
4. Run `npm run build`. The build runs `scripts/verify-tool-paths.mjs`, which fails the build if the `path:` you declared isn't a real GET in the v21 OpenAPI spec.
`registerListTool` automatically wires the `fields` / `filter` / `limit` schema and routes the response through `formatList`. `registerObjectTool` skips the schema but still applies the 64 KB byte safety net.
Module file names (`infrastructure.ts`, `site-settings.ts`, etc.) are an internal grouping for related tools. They do **not** correspond to URL segments — the real RAS API is flat under `/api/<PascalCaseResource>` (e.g. `/api/Agent`, `/api/License`, `/api/MFA`).
### API reference
- Browser reference: <https://docs.parallels.com/landing/ras-rest-api-guide>
- API base URL: `https://<ras-host>:20443/api/`
## Roadmap
- **Write operations** — out of scope for this repo. A separate server should host any tool that mutates RAS state, so the read-only tools here can stay safe to auto-approve.
- **OAuth / OIDC for the HTTP transport** — currently a single shared bearer token. Per-user identity would let multiple clients share a deployment without sharing credentials.
## Contributing
Issues and pull requests are welcome. Please open an issue first for anything beyond a small fix so we can agree on the approach.
## History
See [CHANGELOG.md](CHANGELOG.md) for the full release log. Recent highlights:
- **v1.2.0** — efficiency pass across all 41 tools: `fields` / `filter` / `limit` inputs on every list tool, default row cap of 50, 64 KB byte safety net on every response, shared registration factories. Backward-compatible at the MCP protocol level.
- **v1.1.0** — opt-in streamable-HTTP transport with bearer-token auth, alongside the existing stdio transport.
- **v1.0.1** — corrects all 41 tool paths against the Parallels RAS v21 REST API and adds a build-time path verifier.
## License
[MIT](LICENSE)
TDQS
Scored across 41 tools
Most tools have distinct purposes targeting specific resources (e.g., farm, infra, pub, site) and actions (get, list), with clear boundaries like ras_farm_get_licensing vs. ras_farm_get_config. However, some overlap exists in 'get' operations across similar resources (e.g., ras_infra_get_rds_hostpools and ras_infra_get_rds_hosts), which could cause minor confusion but is mitigated by detailed descriptions.
All tools follow a consistent snake_case pattern with a clear structure: ras_<category>_<action>_<resource> (e.g., ras_farm_get_administrators, ras_pub_get_all_items). This predictability makes it easy for agents to understand the tool's domain and purpose at a glance, with no deviations in naming style.
With 41 tools, the count is excessive for a single server, likely overwhelming for agents to navigate efficiently. While the domain (Parallels RAS management) is broad, the toolset could be streamlined by grouping related operations (e.g., combining multiple 'get' tools into fewer, more general ones) to reduce cognitive load and improve usability.
The toolset provides comprehensive coverage for managing a Parallels RAS farm, including configuration, infrastructure, publishing, sessions, and site settings. It supports full CRUD-like operations (primarily read/get actions) across all key areas, with no obvious gaps—agents can audit, monitor, and troubleshoot the entire system effectively.