# Port OS Smart Home (remote · api.portoperatingsystem.com)

Control your Philips lights, Sonos speakers, Roborock vacuums and more with Port OS cloud.

- Trust score: 79/100 (medium)
- Change this week: +1
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-11-05

## Components

- remote · `api.portoperatingsystem.com`: 79/100 (this document), [markdown](https://verifymcp.io/servers/portpowered-portos/api.md), [page](https://verifymcp.io/servers/portpowered-portos/api)

## Channel facts

- Endpoint: `https://api.portoperatingsystem.com/mcp`
- Transports: `streamable-http`
- Auth: `required`
- Version: `1.0.1-metadata.1`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-11-05.

- **Endpoint Security**: 100/100
  - The endpoint's TLS certificate is valid, in date, and uses a strong key.
  - The endpoint enforces authorisation, advertised via RFC 9728 protected-resource metadata.
  - HTTPS is enforced; there's no plaintext access path.
  - The HSTS (Strict-Transport-Security) header is present.
  - DNSSEC is configured correctly; the domain's records validate against the full chain to the root.
  - The authorisation server supports Client ID Metadata Documents, the current MCP client-registration mechanism.
- **Transport & Reachability**: 100/100
  - Verified streamable-http transport via a live MCP handshake.
- **Schema Quality & AI Usability**: 54/100
  - AI-judged instruction clarity (good).
  - Context-footprint check failed: tool/resource definitions use about 4552 tokens (~455/item across 10 items; 10 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 9/100
  - Stability check failed: schema churn in the 9 days we've observed: 0 tool removals, 4 breaking changes, 0 auth/transport breaks, 0 additions.
- **Tool Coverage**: 99/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 96% of tool parameters carry a description.
  - Structured output schemas are declared (100% of tools); any adoption earns full credit.
- **Tool Safety**: 100/100
  - No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.
  - We read all 10 captured tool definition(s), and no name or description among them implies an irreversible operation.
  - An AI judge read all 11 captured unit(s) of tool text and found none that tries to manipulate the model reading it.
- **Capabilities**: 100/100
  - Implements a current MCP spec version (2026-07-28).
  - Supports UI / widget rendering.

## Install

### How do I install the Port OS Smart Home MCP server?

Port OS Smart Home is a hosted endpoint at https://api.portoperatingsystem.com/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.

### Claude

```bash
claude mcp add --transport http portpowered-portos 'https://api.portoperatingsystem.com/mcp'
```

### Cursor

```json
{
  "mcpServers": {
    "portpowered-portos": {
      "url": "https://api.portoperatingsystem.com/mcp"
    }
  }
}
```

### VS Code

```json
{
  "servers": {
    "portpowered-portos": {
      "type": "http",
      "url": "https://api.portoperatingsystem.com/mcp"
    }
  }
}
```

### Codex

```toml
[mcp_servers.portpowered-portos]
url = "https://api.portoperatingsystem.com/mcp"
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "portpowered-portos": {
      "type": "remote",
      "url": "https://api.portoperatingsystem.com/mcp",
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add portpowered-portos --url 'https://api.portoperatingsystem.com/mcp' --transport streamable-http
```

### Hermes

```yaml
mcp_servers:
  portpowered-portos:
    url: "https://api.portoperatingsystem.com/mcp"
```

### Netclaw

```json
{
  "McpServers": {
    "portpowered-portos": {
      "Transport": "http",
      "Url": "https://api.portoperatingsystem.com/mcp"
    }
  }
}
```

### Vellum

```bash
assistant mcp add portpowered-portos -t streamable-http -u 'https://api.portoperatingsystem.com/mcp'
```

### Other

```json
{
  "mcpServers": {
    "portpowered-portos": {
      "type": "http",
      "url": "https://api.portoperatingsystem.com/mcp"
    }
  }
}
```

The mcpServers block is a cross-client convention. Remote transports vary, so check your client's docs.

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-11-05 (score 79, +1)

No change was recorded against any check on this day. Stability & Change Management went from 5 to 9.

### 2026-11-04 (score 78, 0)

- [security] The server rewrote its instructions, which are the text every model session reads
- [security] Tool “control” rewrote its description, which is the text the model reads
- [security] Tool “endpoint_query” rewrote its description, which is the text the model reads

### 2026-11-03 (score 78, 0)

- [security] Tool “control” rewrote its description, which is the text the model reads

### 2026-11-01 (score 78, 0)

- [security] The server rewrote its instructions, which are the text every model session reads
- [security] Tool “control” rewrote its description, which is the text the model reads
- [security] Tool “endpoint_manage” rewrote its description, which is the text the model reads
- [security] Tool “endpoint_query” rewrote its description, which is the text the model reads
- [security] Tool “endpoint_show” rewrote its description, which is the text the model reads
- [security] Tool “group_manage” rewrote its description, which is the text the model reads
- [security] Tool “group_query” rewrote its description, which is the text the model reads
- [functional improvement] Schema quality: 612 → 442
- [functional] Schema quality: excellent → good
- [cosmetic] “control” reworded the description of “idempotencyKey”
- [cosmetic] “control” reworded the description of “query”

### 2026-10-31 (score 78, 0)

- [security] Authorization: The endpoint enforces authorisation, advertised via RFC 9728 protected-resource metadata.
- [security] The server rewrote its instructions, which are the text every model session reads
- [security] Tool “control” rewrote its description, which is the text the model reads
- [security] Tool “endpoint_manage” rewrote its description, which is the text the model reads
- [security] Tool “endpoint_query” rewrote its description, which is the text the model reads
- [security] Tool “endpoint_show” rewrote its description, which is the text the model reads
- [security] Tool “group_query” rewrote its description, which is the text the model reads
- [cosmetic] “control” reworded the description of “id”
- [cosmetic] “control” reworded the description of “message”
- [cosmetic] “control” reworded the description of “waitForResult”
- [cosmetic] “endpoint_manage” reworded the description of “endpointId”
- [cosmetic] “endpoint_query” reworded the description of “query”
- [cosmetic] “endpoint_show” reworded the description of “query”
- [cosmetic] “group_query” reworded the description of “id”
- [cosmetic] “group_query” reworded the description of “query”

### 2026-10-29 (score 78, +1)

- [security improvement] DNSSEC: fail → pass
- [security] The server rewrote its instructions, which are the text every model session reads
- [security] Tool “control” rewrote its description, which is the text the model reads
- [security] Tool “endpoint_query” rewrote its description, which is the text the model reads
- [security] Tool “group_query” rewrote its description, which is the text the model reads
- [functional improvement] Schema quality: 706 → 600
- [cosmetic] “control” reworded the description of “correlationToken”
- [cosmetic] “control” reworded the description of “id”
- [cosmetic] “control” reworded the description of “idempotencyKey”
- [cosmetic] “control” reworded the description of “message”
- [cosmetic] “control” reworded the description of “payload”
- [cosmetic] “control” reworded the description of “query”
- [cosmetic] “control” reworded the description of “waitForResult”
- [cosmetic] “control” dropped the optional parameter “routeId”

### 2026-10-28 (score 77, 0)

- [security regression] Stability: unverified → fail
- [security regression] A breaking change shipped without a version bump: still 1.0.0
- [security] The server rewrote its instructions, which are the text every model session reads
- [security] Tool “control” rewrote its description, which is the text the model reads
- [security] Tool “endpoint_manage” rewrote its description, which is the text the model reads
- [security] Tool “group_manage” rewrote its description, which is the text the model reads
- [functional regression] Schema quality: 633 → 706
- [functional regression] “control” added a required parameter “idempotencyKey”, so existing callers break
- [functional regression] “endpoint_manage” added a required parameter “etag”, so existing callers break
- [functional regression] “endpoint_manage” added a required parameter “idempotencyKey”, so existing callers break
- [functional regression] “subscription_cancel” added a required parameter “idempotencyKey”, so existing callers break
- [functional regression] “subscription_cancel” added a required parameter “ifMatch”, so existing callers break
- [functional regression] “subscription_label_edit” added a required parameter “idempotencyKey”, so existing callers break
- [functional regression] “subscription_label_edit” added a required parameter “ifMatch”, so existing callers break
- [cosmetic] “control” added an optional parameter “query”
- [cosmetic] “endpoint_manage” added an optional parameter “targetEtag”
- [cosmetic] “control” reworded the description of “correlationToken”
- [cosmetic] “control” reworded the description of “waitForResult”
- [cosmetic] “endpoint_manage” reworded the description of “enablement”
- [cosmetic] “endpoint_manage” reworded the description of “name”
- [cosmetic] “endpoint_manage” reworded the description of “type”
- [cosmetic] “control” made “id” optional

### 2026-10-27 (score 77)

First indexed and scored.

## MCP tools (10)

### `control` (~709 tokens)

Control devices/services.

Dispatch a declared message with the payload its discovery entry shows ({} if fieldless) to one discovered logical id or endpoint_query-style query. Named devices, including dim/color, require their endpoint; groups require room/group intent. Unqualified vacuum start is whole-device. Queries freeze 1-100 authorized matches; zero/over-limit sends nothing. Copy references/account; Port OS selects routes.

Whole-home lights: one complete confirmed-lighting query; rooms: resolved lighting group. Query adds no exclusions. Include confirmed lamps/plugs; exclude appliances, fans, simulators, catalogs and duplicates. Discover missing scope only; report unresolved coverage.

Commands: waitForResult=false; acknowledge accepted/pending and stop, without auto-poll/read/card. State/settings: endpoint_query with expand and forceDeviceAttributeQuery:true. Replies (snapshots, SDP, searches, queues, scene creation, authorization challenges): wait true. Empty QUEUED/IN_PROGRESS remains pending; acceptance proves no physical state. Exception: after play-media or launch-application on a TELEVISION, confirm once before saying it plays (an app can stop on a profile picker): endpoint_query forceDeviceAttributeQuery:true, or snapshot/get-snapshot {"responseFormat":"BASE64"} (the default URL cannot be viewed), and follow the TV description if it is stuck.

Tools-only recipes: media-search/search-media {"query":"<search>","type":"track"} (type is lower case; supportedSearchTypes lists TRACK upper case); media-queue/play-queue {"mediaIds":["<returned ID>"]}; get-queue {}; add-to-queue {"mediaId":"<returned ID>"}, plus fresh queueVersion only when requiresQueueVersion=true. Match declared resources/bounds. Queue differs from saved playlist; failed search proves no state. Scenes: group_query expand:["scene"], forceDeviceAttributeQuery:true; scene/activate {"sceneId":"<returned ID>"}; scene/create-scene {"name":"<name>"} captures settings, wait true. Recover uncertain…

Input parameters:

- `correlationToken` (string): Optional token; PIN mutations default to idempotencyKey for query-operation.
- `id` (string): Returned endpoint/group reference, compact or full, copied from discovery.
- `idempotencyKey` (string, required): Required nonempty key for every call, including reads/discovery. New action, new key; copy caller keys exactly. Retries attach to existing receipts for 24h; never auto-retry.
- `message` (string, required): Returned message reference, compact or full; retain @version only when listed.
- `payload` (object, required): Documented command payload object; {} if fieldless.
- `query`: endpoint_query filter, exclusive with id. Freezes 1-100 authorized matches once.
- `waitForResult` (boolean): False for ordinary commands; true when requested data or a protocol reply is needed. Acceptance does not prove physical completion.

### `endpoint_manage` (~294 tokens)

Edit endpoint registry metadata; physical actions use control. Read endpoint ID, document and etag first. Metadata replacement requires complete name/type/enablement, etag and idempotencyKey; rename/type/disabled state survives rediscovery. Disabled endpoints remain explicitly readable but reject controls. DELETE may be rediscovered.

MERGE_INTO disables the source and moves supported references; it creates no ID alias and preserves target enablement. Two simulator endpoints cannot merge (409 CONFLICT); disable/delete the duplicate instead. Confirm exact identity and explain MERGE_INTO/DELETE effects; matching names do not prove duplicates.

Input parameters:

- `enablement` (string): Complete replacement enablement, required with name and type on metadata writes.
- `endpointId` (string, required): returned endpoint ID from endpoint_query.
- `etag` (string, required): Current endpoint writable document etag from endpoint_query.
- `idempotencyKey` (string, required): Unique request key. Reuse it for retries of the same change for 24 hours.
- `mergeInto` (string): Full target endpoint ID; only for MERGE_INTO.
- `name` (string): Complete replacement name, required with type and enablement on metadata writes.
- `operation` (string, required)
- `targetEtag` (string): Current target etag, required for MERGE_INTO.
- `type` (string): Complete replacement type, required with name and enablement on metadata writes.

### `endpoint_query` (~799 tokens)

Find devices/services, declarations and observations. Filter by name/type/capability; follow paginationContext.nextToken for the requested scope. endpointId reads one known endpoint and takes no query, maxResults or nextToken. Copy returned references/account; Port OS selects routes. Use group_query for rooms and management tools for inventory edits.

State reads require declared expand capabilities and forceDeviceAttributeQuery=true. FRESH is current; STALE is last known with sampledAt and cannot support a safety claim. Missing/invalid/errored/PROVIDER_NO_STATE is unknown; PROVIDER_NO_STATE is not offline and retries cannot supply an absent provider value. FRESH UNREACHABLE is offline; STALE connectivity is last known. ID-only lookup reads metadata; an expanded read returns only the expanded capabilities, without the description. simulator:true means all routes are synthetic; routes[].simulator marks mixed routes. Missing flags are unknown. Exclude simulated routes from household claims unless explicitly selected; their readings do not prove physical state.

Types alone do not identify lamps: switches/plugs require confirmed lighting assignment. Temperature setpoints are distinct from ambient readings; clarify indoor/outdoor ambiguity. Check relevant authorized accounts before reporting absence; names alone prove no identity. Select concrete route-backed services, not provider catalogs or obsolete unrouted entries. Default lists include ENABLED; DISABLED or * selects others. Exact endpointId can read disabled metadata. controllableGroups needs group:read. Device workflows and payloads: matching Port OS skill or portos://guides/index.

Input parameters:

- `enablement` (string): Filter by ENABLED (default), DISABLED, or * for both. This filter is preserved by pagination.
- `endpointId` (string): Return one endpoint by its full Port OS identifier. Cannot be combined with other filters or pagination. Results advertise its declared command and outbound message IDs.
- `expand` (array): Select observations to add to each device result, for example ["power", "connectivity"] or ["battery"]. Use capability names or full namespaces declared by the device. This reads attributes; it does…
- `forceDeviceAttributeQuery` (boolean): Read selected attributes from devices instead of cache. Requires nonempty expand. Failed reads remain unavailable.
- `maxResults` (integer): Maximum number of results (default 10, maximum 100).
- `nextToken` (string): Opaque cursor returned by a previous endpoint_query call.
- `query` (object): Optional field-first filter. Omit it to load full context; filter only when the account is large. Each key is a field or a combinator, and all keys of one object must match: {"name": {"like": "living…

### `endpoint_show` (~710 tokens)

Open the Port OS device UI when requested; never draw a second card/map/controls. Answer with the relevant value in words. This tool shares endpoint_query selection, expand and pagination. One matching endpoint opens controls; multiple matches open a selection list. It sends no control and starts no live video.

primary selects a returned cardId (for example battery, fan, closure, camera, location or house-map) and refreshes its readings; unsupported IDs return available choices. Other cards remain in details. Results include cached readings for listed cards, so avoid a second read. FRESH is current; STALE is last known with its age. Ordinary commands require no automatic UI follow-up.

Input parameters:

- `enablement` (string): Filter by ENABLED (default), DISABLED, or * for both. This filter is preserved by pagination.
- `endpointId` (string): Return one endpoint by its full Port OS identifier. Cannot be combined with other filters or pagination. Results advertise its declared command and outbound message IDs.
- `expand` (array): Select observations to add to each device result, for example ["power", "connectivity"] or ["battery"]. Use capability names or full namespaces declared by the device. This reads attributes; it does…
- `forceDeviceAttributeQuery` (boolean): Read selected attributes from devices instead of cache. Requires nonempty expand. Failed reads remain unavailable.
- `maxResults` (integer): Maximum number of results (default 10, maximum 100).
- `nextToken` (string): Opaque cursor returned by a previous endpoint_query call.
- `primary` (string): The card to lead with, one of the device's card ids (shown as cardIds in the result), for example battery, fan, closure, thermostat, camera or remote; house-map for a vacuum's map or room picking (ne…
- `query` (object): Optional field-first filter. Omit it to load full context; filter only when the account is large. Each key is a field or a combinator, and all keys of one object must match: {"name": {"like": "living…

### `group_manage` (~394 tokens)

Create/rename/delete groups, change members/enablement or merge inventory; physical actions use control. Read IDs/etags first. Every batch reference to a group uses its starting etag. MOVE_MEMBER needs memberEndpointId plus source/target IDs and both etags. List order cannot resolve contradictory edits; adding does not implicitly move exclusive membership.

Native-capable changes default to BEST_EFFORT: provider change/readback precedes local intent; failure can fall back locally as PARTIALLY_APPLIED. PORTOS_ONLY sends nothing. FAIL_ON_PROVIDER_ERROR fails intent while retaining received provider facts. Native effects cannot roll back. NOT_DECLARED alone is not partial; OUTSIDE_PRINCIPAL prevents native changes through another principal. MERGE_INTO and aggregate/route enablement require PORTOS_ONLY.

Require explicit user authorization for exact MERGE_INTO/DELETE_GROUP targets/effects. Deletion may delete native groups; unretired routes stay disabled/orphaned against rediscovery. Route enablement needs its native etag and groupEtag when grouped. Use declared provider support; robot room edits do not reshape maps.

validateOnly=true authorizes/plans without sending/writing. Otherwise use a unique idempotencyKey per intent; identical retries retain it. Stale etag: reread/reconsider. Inspect batch status, per-item outcomes and providerDispatches, including on failure. Failed intent can retain provider changes; never claim full synchronization or automatically repeat native writes.

Input parameters:

- `idempotencyKey` (string): Unique key for this intended change, at most 255 characters. Required unless validateOnly is true.
- `operations` (array, required): Compatible intended changes in one customer batch. Reuse each group's starting etag across its references; contradictory edits cannot be resolved by list order.
- `validateOnly` (boolean): Validate and authorize the batch and report planned or unsupported provider dispatches without sending messages or writing.

### `group_query` (~699 tokens)

Find rooms/groups with IDs, etags, hierarchy, members, controllers, providers and declared controls. Query a named room; omit query for inventory. Follow relevant pages. Clarify ambiguous names using parentPath. id reads one group; merged IDs return redirectedFrom. Copy IDs/etags.

Use control on the complete logical group; Port OS selects native/equivalent member delivery. Native capabilities/membershipComplete prove no aggregate coverage. membershipComplete=false means incomplete; absent means unknown. Empty resolved members do not prove an empty native group. Disabled routes cannot control; disabled groups need re-enablement through group_manage.

Controllers accept group-scoped actions: target the vacuum controller with {"groupIds":["<group ID>"]} for room cleaning. Requested maps use endpoint_show on that controller, primary house-map; never draw geometry. expand selects observations; forceDeviceAttributeQuery refreshes them. Omitted/failed fresh values are unavailable. Disabled groups are hidden unless enablement=DISABLED or *.

Input parameters:

- `enablement` (string): Filter by ENABLED (default), DISABLED, or * for both. This filter is preserved by pagination; id reads ignore it.
- `expand` (array): Select declared capabilities whose route observations to return, for example ["speaker", "media-player"]. Requires id. This adds state readings to the selected group; it does not expand group members…
- `forceDeviceAttributeQuery` (boolean): Requires id and nonempty expand; refresh provider state before returning route observations.
- `id` (string): Return one group by its returned group ID. Cannot be combined with query, maxResults or nextToken.
- `maxResults` (integer): Maximum number of groups (default 25, maximum 100).
- `nextToken` (string): Opaque cursor returned by a previous group_query call with the same query and maxResults.
- `query` (object): Optional field-first filter. Omit it to load full context; filter only when the account is large. Each key is a field or a combinator, and all keys of one object must match: {"role": {"eq": "ROOM"},…

### `subscription_cancel` (~136 tokens)

Stop watching by cancelling one Port OS event subscription using its exact ID from subscription_list or subscription_inspect.

Cancellation is idempotent. Select the intended subscription by name, source endpoint and catalog event; names are not cancellation keys. A stopped monitor requires a new subscription to watch again.

Input parameters:

- `id` (string, required): Exact subscription ID returned by subscription_list. Never use a display name or endpoint ID.
- `idempotencyKey` (string, required): Stable unique key for this write; reuse it only to retry the same request for 24 hours.
- `ifMatch` (string, required): Exact strong etag from subscription_inspect or subscription_list.

### `subscription_inspect` (~84 tokens)

Inspect one Port OS event subscription by its exact ID returned by subscription_list.

Returns its safe query, source endpoint, catalog name and lifecycle status. A retained active subscription establishes registration; it does not prove that any client has received or acted on a camera event.

Input parameters:

- `id` (string, required): Exact subscription ID returned by subscription_list. Never use a display name or endpoint ID.

### `subscription_label_edit` (~137 tokens)

Change only the display name of one Port OS event subscription by exact ID.

Use a PLAIN name-value object. The event, endpoint, filter and destination are immutable; to change what is watched, establish a replacement monitor and cancel the old ID.

Input parameters:

- `id` (string, required): Exact subscription ID returned by subscription_list. Never use a display name or endpoint ID.
- `idempotencyKey` (string, required): Stable unique key for this write; reuse it only to retry the same request for 24 hours.
- `ifMatch` (string, required): Exact strong etag from subscription_inspect or subscription_list.
- `name` (object, required)

### `subscription_list` (~113 tokens)

Enumerate the user's Port OS event subscriptions, including their exact IDs, names, source endpoint, catalog event and status.

For requests to stop watching a camera, list subscriptions and follow every nextCursor, select the intended monitor, then use subscription_cancel with its exact ID. Creating a monitor uses the host's events/subscribe capability after discovering supported camera events; these tools never accept callback URLs or signing keys.

Input parameters:

- `cursor` (string): Opaque nextCursor from the preceding subscription_list page. Omit for the first page.

## Diagnostics

Captured diagnostic sections: TLS, DNSSEC, Authorisation, Transports. The full working is on the page: https://verifymcp.io/servers/portpowered-portos/api#diagnostics

## Score history

- 2026-11-05: 79
- 2026-11-04: 78
- 2026-11-03: 78
- 2026-11-02: 78
- 2026-11-01: 78
- 2026-10-31: 78
- 2026-10-30: 78
- 2026-10-29: 78
- 2026-10-28: 77
- 2026-10-27: 77

## Common questions

### What is the Port OS Smart Home MCP server?

Port OS Smart Home is an MCP server listed in the public MCP registry as io.github.portpowered/portos. Control your Philips lights, Sonos speakers, Roborock vacuums and more with Port OS cloud. This page covers its hosted endpoint (https://api.portoperatingsystem.com/mcp).

### Is the Port OS Smart Home MCP server safe to use?

Port OS Smart Home scores 79 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.

### What tools does the Port OS Smart Home MCP server expose?

Port OS Smart Home exposes 10 tools: control, endpoint_manage, endpoint_query, endpoint_show, group_manage, and 5 more. Their descriptions and schemas cost roughly 4,075 tokens of context every time the server is loaded.

### Does the Port OS Smart Home MCP server require authentication?

Yes. Port OS Smart Home asked us for credentials when we connected, so you will need to authorise it in your MCP client before it can do anything.

### Is the Port OS Smart Home MCP server still maintained?

Port OS Smart Home is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.

## Links

- Remote endpoint: https://api.portoperatingsystem.com/mcp
- Website: https://portoperatingsystem.com/
- Changelog RSS feed: https://verifymcp.io/servers/portpowered-portos/api.xml
- Changelog JSON feed: https://verifymcp.io/servers/portpowered-portos/api.json
- HTML version of this page: https://verifymcp.io/servers/portpowered-portos/api
