mcp-server-webos
An MCP server for LG webOS TVs: status, power, screen, apps and inputs, remote keys, typing into search boxes, YouTube search, playback and volume, from Claude Code, Claude Desktop or the mobile app. It talks to each TV directly over LG's SSAP WebSocket protocol, through aiowebostv (the library Home Assistant uses), with no dependency on Home Assistant.
A sibling of mcp-server-onkyo,
mcp-server-shieldtv,
mcp-server-harmony and
mcp-server-sofabaton, with the same
conventions: typed tools with annotations, an ActionResult from every action, dry run, doctor,
a wire-level simulator, an assumptions registry, Streamable HTTP behind Cloudflare Access, and an
OpenRC service for an Alpine LXC.
Status: alpha, and looking for testers with other LG TVs. It runs daily on the three TVs below: pairing, status, screen off, sources, the text tools and YouTube search have run on real sets (2026-10-14 to 2026-11-10), and the HTTP service runs behind Cloudflare Access. Wake-on-LAN, keys and media controls have so far run only on the 2025 C5, and other models only against the simulator. HARDWARE_VALIDATION.md is the checklist, the table at the end of this README says what has been confirmed, and a hardware report for your TV (working or not) is the most useful thing you can send.
The TVs it targets
The owner's three OLEDs, one per generation. Other webOS TVs (2014 onwards) speak the same protocol and will probably work, but nothing is promised for them.
| Room | Model | Platform | Control port | Notes |
|---|---|---|---|---|
| Bedroom | OLED65C7P-U (2017 C7) | webOS 3.5 (reports 3.9.3) | 3000 (ws) | no now_playing (no media service) |
| Family Room | OLED77G1PUA (2021 G1) | webOS 6.5 (reports 6.5.3) | 3000 (ws); 3001 (wss) also open | no now_playing (no media service) |
| Office | OLED65C5PUA (2025 C5) | webOS 25 (26 on offer) | 3001 (wss) | webOS 26 changed pairing (see below) |
A TV usually sits on one HDMI input from an Onkyo receiver, and volume belongs to the receiver: when a TV's sound goes out over eARC/ARC, this server refuses to change its volume and points at the receiver's own server instead. Going through the TV would bypass the receiver server's volume caps (the TV forwards its volume to the receiver over HDMI-CEC). A separate home-theater Skill coordinates the servers; docs/skill-webos.md is this server's cheat sheet for it.
webOS 26 and pairing
In August 2026 LG's webOS 26 firmware started rejecting the signed registration manifest that
every SSAP client had sent since 2014 (403 Pairing rejected: blacklisted certificate detected,
before any dialog). aiowebostv 0.9.2 switched to an unsigned manifest, which webOS 26 accepts;
this server requires at least that version. LG has been rolling webOS 26 out to 2025 sets since
late August, and there is no way back, so HARDWARE_VALIDATION.md captures the C5 on webOS 25
before it updates.
Install
With uv, nothing to install: uvx mcp-server-webos ... fetches it
into a cached environment and runs it (uvx mcp-server-webos pair --host <ip> --name <room>). Or
in a virtualenv:
python -m venv ~/.venvs/webos && . ~/.venvs/webos/bin/activate
pip install mcp-server-webos
From source instead (for the newest code, or to run the tests):
git clone https://github.com/SDNick484/mcp-server-webos.git && cd mcp-server-webos
python -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]" && pytest
Python 3.11 or newer. Every dependency ships a musl wheel, so Alpine needs no compiler.
Pair each TV
The TV must be on. On a webOS 3.x set (the C7), turn on LG Connect Apps in its network
settings first. For webos_set_power on to work, also turn on the setting that lets the network wake
it: "Mobile TV On", "TV On With Mobile" or "Turn on via Wi-Fi", depending on the generation.
mcp-server-webos pair --host 192.168.1.50 --name "Family Room" --alias G1
The TV shows a pairing request: accept it with the remote (pair waits up to 60 s). pair reads
the TV's identity first (its deviceUUID, from the keyless hello), then saves:
- the client key, in
keys.json(0600), by deviceUUID. It is full control of the TV, so it is never logged, never inconfig.json, never in a tool result; - the TV in
config.json: name, aliases (your--aliases and the model), address, MACs for Wake-on-LAN (the connected interface first;--macif they can't be read), model, platform, and the TLS certificate's fingerprint.
Both live in ~/.config/mcp-server-webos (or $WEBOS_CONFIG_DIR), 0700. A running server
notices a new key and connects with it, without a restart. Re-running pair for the same TV
updates its entry and keeps your hand edits.
mcp-server-webos check # connect once to each TV: platform, what works, what doesn't
mcp-server-webos doctor # layer by layer, read-only; each failure names a validation step
mcp-server-webos discover # which webOS TVs answer SSDP (TVs that are off don't)
Choose the apps
webos_select_source only opens apps on the allow-list: a few defaults, plus yours. To see what a TV
actually has installed, and add from it:
mcp-server-webos apps --tv "Office TV" # listed by group, with the name webos_select_source will use
mcp-server-webos apps --tv "Office TV" --add crunchyroll,"Photo & Video"
mcp-server-webos apps --all-tvs --add-all # every third-party app on any TV
| Group | Means | Added by |
|---|---|---|
| Allowed | already on the allow-list | |
| Not allowed yet | third-party apps | --add NAME or --add-all |
| LG's own apps | com.webos., com.palm., com.lge. ids (W-SYSTEM-APP-IDS) |
--add NAME only |
| Excluded | the web browser (it opens any URL), settings, LG's store (it installs apps), inputs (webos_select_source handles them), Live TV, service menus |
never |
It asks the TV over a short session with the stored key and changes nothing on it. New entries go
into config.json's "apps"; restart the server to use them. Run it as the service user on the
LXC (su -s /bin/sh mcp-webos -c '…' with WEBOS_CONFIG_DIR=/var/lib/mcp-server-webos), since
keys.json and config.json are that user's. There is no tool for this: the model can't widen the
allow-list.
config.json
pair writes it; you may edit names, aliases, max_volume and volume_owner:
{
"tvs": [
{"name": "Bedroom", "aliases": ["C7", "OLED65C7P-U"], "host": "192.168.1.52",
"uuid": "...", "macs": ["a8:23:fe:..."], "model": "OLED65C7P-U", "platform": "3.5.0",
"max_volume": 30, "volume_owner": "auto"}
],
"apps": {"crunchyroll": "crunchyroll.app.id"},
"max_volume": 40
}
max_volume(0-100, default 40):webos_set_volumecaps at it, per TV or for all.volume_owner:auto(from the TV's sound output: external outputs mean the receiver owns volume),tv(always allow), orexternal(never).apps: extra apps for the allow-list,name: app id(ids fromwebos_list_sourcesor a capture).wol_broadcast/wol_port: where magic packets go (default 255.255.255.255:9).- Hosts must be private IPv4 addresses. A name or alias that would mean two TVs is refused.
Use it from Claude
Claude Code:
claude mcp add webos -- uvx mcp-server-webos # or the venv's bin/mcp-server-webos
Claude Desktop (claude_desktop_config.json, then restart Claude Desktop):
{
"mcpServers": {
"webos": {"command": "uvx", "args": ["mcp-server-webos"]}
}
}
Claude Desktop doesn't start a login shell, so it may not find uvx on its PATH: if the server
doesn't appear, put the full path from which uvx (where uvx on Windows) in command. With a
virtualenv instead, command is the full path to its bin/mcp-server-webos and args is [].
Both read the TVs and keys that pair saved.
Tools
Fourteen, on purpose: every tool definition costs context in every client.
| Tool | Does | Annotations |
|---|---|---|
webos_list_tvs |
names and aliases tv accepts, model, platform |
read-only |
webos_get_status |
power, what is in front, input, now playing, volume, sound output, capabilities and limitations; all TVs when tv is omitted |
read-only |
webos_set_power |
on (Wake-on-LAN, confirmed) or off (standby); tv="all" for off |
idempotent |
webos_set_screen |
blank the picture while sound plays, or bring it back | idempotent |
webos_list_sources |
allow-listed apps the TV has installed, and its HDMI inputs | read-only |
webos_select_source |
open an app or switch input, confirmed in front | idempotent |
webos_send_key |
one allow-listed remote key, up to 10 times | not idempotent |
webos_media_control |
play, pause, stop, rewind, fast-forward | not idempotent |
webos_set_volume |
0-100, capped; refused when the receiver owns volume | idempotent |
webos_set_mute |
mute or unmute; same rule | idempotent |
webos_insert_text |
type into the focused system text field (LG's search); replace to overwrite it |
not idempotent |
webos_delete_text |
delete characters before the cursor in that field | not idempotent |
webos_submit_text |
press the keyboard's Enter in that field (runs the search) | not idempotent |
webos_search_app |
open YouTube straight on its results for a query | idempotent |
Typing and searching
Typing a search with webos_send_key means walking an on-screen keyboard one arrow at a time. Where
webos_get_status lists text_input, webos_insert_text types the whole string through the TV's input
method (IME) service instead:
webos_get_status(tv="Office") # capabilities include text_input
webos_send_key(key="HOME") ... open LG's search # the search box has the cursor
webos_insert_text(text="lofi beats", tv="Office") # typed, and confirmed by the field's new length
webos_submit_text(tv="Office") # the results
What was seen on the three TVs (2026-11-09; details in HARDWARE_VALIDATION.md step 14):
| Bedroom C7 (3.9.3) | Family Room G1 (6.5.3) | Office C5 (10.3.1) | |
|---|---|---|---|
| Typing into LG's search | works, unconfirmed | works, confirmed | works, confirmed |
| Typing into YouTube's or Netflix's search | refused | refused | refused |
webos_search_app (YouTube) |
refused | works | works |
- Only system text fields take typed text. YouTube and Netflix draw their own keyboards, and
the TV answers "ok" to every IME call there (and with nothing focused at all) while typing
nothing. So each text tool first asks the TV whether a system text field has focus (W-IME-FOCUS)
and refuses, sending nothing, when none does. The refusal points at
webos_search_apporwebos_send_key. - Confirmed where the TV says. The G1 and C5 report the field's length after every change, so the result says whether the text landed; the C7 doesn't, so its results carry an "unconfirmed" warning (W-IME-LENGTH).
- YouTube search by link, not by typing.
webos_search_applaunches YouTube withcontentTarget=https://www.youtube.com/tv?q=<query>, the only link shape that showed results (W-YOUTUBE-SEARCH). The server builds the link; the model only gives the query. webOS 3.x's YouTube ignores links, so it is refused on the C7; webOS 4 and 5 are untested and allowed. - Text is one line of printable characters, at most 200 (a query, 100); no newlines (use
webos_submit_text). Typing shareswebos_send_key's rate limit.
Nothing is destructiveHint: turning a TV off is undone by turning it on. Every action returns an
ActionResult, the siblings' shape:
{"tv": "Bedroom", "outcome": "done", "detail": "Bedroom's volume is 15",
"sent": ["ssap://audio/setVolume 15"], "warnings": []}
outcome is done, unchanged (already so; nothing sent) or dry_run. Failures are tool
errors whose message says what to do ("Which TV? Several are configured: ...", "Volume on Family
Room belongs to the receiver ...", "... needs pairing: run pair").
Resources: webos://tvs (capabilities per TV), webos://keys (the key allow-list, and the keys
left out with the reason for each), webos://apps (the app allow-list). One prompt, watch.
What the model can't do
- No raw SSAP or luna calls. The same reasoning as no
adb shellon the Shield: one generic call would reach everything the TV exposes, including its internal settings services. - No URL tools, and text only where decided: no browser, no "play this URL". The two free-text
arguments are
webos_insert_text's text, which only reaches a focused system text field, andwebos_search_app's query, which the server puts into a link it builds for an allow-listed app. - Keys are an allow-list.
POWER(a toggle), theIN_START/EZ_ADJUSTservice menus, settings menus, the volume keys (they would bypass the cap) and app shortcuts (they would bypass the app allow-list) are left out;webos://keyslists why. - Apps are an allow-list of ids the TV itself lists. Strings from the TV (app titles, input labels) are cleaned of control characters, bounded, and treated as data.
- Never guess a TV: with several configured, an action without
tvis refused and the TVs are listed. Never guess a source: a name that matches an app and an input is refused. - Screen off uses standbyMode "active" only. "passive" can't be undone without unplugging the TV; it isn't an argument anywhere.
docs/OUT_OF_SCOPE.md lists the rest (picture settings, channels, LG's IP control) and why.
Dry run
serve --dry-run (or WEBOS_DRY_RUN=1) reads the TVs but sends nothing that changes anything:
every action returns outcome: "dry_run" with what it would have sent.
How it stays connected
Each TV has one long-lived WebSocket (the TV pushes changes over subscriptions) and a supervisor:
- Off: a TV that is off has no socket. The supervisor retries every ~10 s, so a TV turned on
by its remote shows up within ~10 s.
webos_get_statuson a stale TV first makes one connect attempt of at most 3 s, then answers withstale,as_ofanderror. - Stale key: if the TV no longer accepts the stored key (a reset, or a firmware update), it
wants to show its pairing dialog. The server hangs up at once, marks the TV
needs_pairingand stops trying untilpairwrites a new key. That's one dialog, not one every 10 s. - Moved: the key is only sent after the TV's hello shows the paired deviceUUID. If another device has the address, the server looks for the TV by SSDP and adopts a new address only on a deviceUUID match.
- Pointer socket refused: aiowebostv would fail the whole connection; here only the keys stop
working (see
compat.py).
compat.py holds every dependency on aiowebostv internals, with contract tests; that is why the
dependency is pinned <0.11.
HTTP and Cloudflare Access
To share one server between Claude Code, Claude Desktop and the mobile app, run it as a service and reach it through a Cloudflare Tunnel with Access in front, exactly as the siblings do. Claude's connectors reach it from the internet, so the URL is public; Access is what keeps it yours.
| Flag | Variable | Default |
|---|---|---|
--bind |
MCP_HTTP_BIND |
127.0.0.1 |
--port |
MCP_HTTP_PORT |
8715 (Onkyo 8711, Shield 8712, Harmony 8713, Sofabaton 8714) |
--path |
MCP_HTTP_PATH |
/webos/mcp |
--public-host |
MCP_PUBLIC_HOSTS |
none: only loopback Host headers pass, so Cloudflare's requests get 421 |
CF_ACCESS_TEAM_DOMAIN, CF_ACCESS_AUD |
none: no Access checks | |
MCP_ALLOWED_EMAILS |
anyone Access lets in |
With Access configured, every request needs a valid Cf-Access-Jwt-Assertion; anything else
gets a plain 403. The server refuses to start on a non-loopback address without Access unless
you pass --insecure-no-auth. GET /healthz answers without auth. remote.py and logsafe.py
are shared with the sibling servers, from
mcp-server-shared.
Setting up Cloudflare
This is the setup that works, verified with Claude Code and the Claude app connector on 2026-10-14. Do the Access application first, so the URL is never public.
- One Access application for the whole hostname, shared by every MCP server on it. Zero Trust
→ Access controls → Applications → Add → Self-hosted:
- Destination: subdomain
mcp, your domain, path empty. Managed OAuth serves its sign-in discovery from the root of the hostname (/.well-known/...), so an app limited to/webosmay not cover it; one app also means one sign-in for all the servers. - Policy: Allow → Emails → you. Login method: One-time PIN (or your identity provider).
- Edit the app → Advanced settings → Managed OAuth: on. Allowed redirect URIs:
https://claude.ai/*. Turn on Allow localhost clients (Claude Code signs in through localhost). Access token 15 min, grant session 1-2 weeks. - Copy the app's Application Audience (AUD) tag.
- Make sure no other Access app covers a path on the same hostname: Access applies the most specific match, and a Bypass policy there would let requests through without a token.
- Destination: subdomain
- A route on the tunnel. Networks → Tunnels → the tunnel → Published application routes →
Add: hostname
mcp.example.com, path^/webos/(a regex), servicehttp://<address>:8715. Leave the HTTP Host Header override unset: the server checks the public Host.- The service address is resolved where cloudflared runs. If cloudflared is a Docker
container (the tunnel page lists the replica's hostname as a 12-character hex container ID),
localhostis that container, not the LXC: use the LXC's LAN address or the Docker bridge's (172.17.0.1, reachable only from containers on that host), and setMCP_HTTP_BINDto the same address.
- The service address is resolved where cloudflared runs. If cloudflared is a Docker
container (the tunnel page lists the replica's hostname as a 12-character hex container ID),
/etc/mcp-server-webos/env(seedeploy/alpine/env.example), thenrc-service mcp-server-webos restart:MCP_HTTP_BIND=192.168.1.10 # e.g. the LXC's address: the one the route points at MCP_PUBLIC_HOSTS=mcp.example.com # required: without it every request through Cloudflare gets 421 CF_ACCESS_TEAM_DOMAIN=<team>.cloudflareaccess.com CF_ACCESS_AUD=<the AUD tag from step 1> MCP_ALLOWED_EMAILS=<the email you sign in to Access with>
- Test, then add
https://mcp.example.com/webos/mcpas a custom connector in Claude (andclaude mcp add --transport http webos <url>for Claude Code):curl -s http://192.168.1.10:8715/healthz # {"status": "ok"} curl -si -X POST https://mcp.example.com/webos/mcp -d '{}' | head -5 # 401 + www-authenticate
When it doesn't connect
Watch the server while you press Connect: tail -n 0 -f /var/log/mcp-server-webos/server.log.
| You see | Cause | Fix |
|---|---|---|
The outside curl gets a 302 to …cloudflareaccess.com |
Managed OAuth is off: Claude gets a login page | Turn it on (step 1) |
Claude: "couldn't reach" / "authorized, but … returned an error"; Claude Code: HTTP 502; nothing in the log |
The tunnel can't reach the server: the route's service address isn't where the server listens (usually localhost with cloudflared in a container) |
Step 2's address and MCP_HTTP_BIND must match |
Claude Code: HTTP 421; log: Invalid Host header: mcp.example.com |
MCP_PUBLIC_HOSTS isn't set |
Step 3 |
Log: Denied … no Cloudflare Access assertion |
The request didn't come through Access: a local test with curl, or another Access app/Bypass policy on the path |
Ignore it for local tests; otherwise see step 1's last point |
Log: Denied … Audience doesn't match / Invalid issuer |
CF_ACCESS_AUD is another app's tag, or the team domain is wrong |
Copy both again from the app in step 1 |
Log: Denied … not in MCP_ALLOWED_EMAILS |
You signed in to Access with another address | Make them match |
As a service on Alpine (Proxmox LXC)
sh deploy/alpine/install.sh # as root; or: install.sh /path/to/checkout
su -s /bin/sh mcp-webos -c 'WEBOS_CONFIG_DIR=/var/lib/mcp-server-webos \
/opt/mcp-server-webos/venv/bin/mcp-server-webos pair --host <tv ip> --name "Family Room"'
vi /etc/mcp-server-webos/env # HTTP and Access settings
rc-update add mcp-server-webos default && rc-service mcp-server-webos start
| Path | Owner, mode | Holds |
|---|---|---|
/opt/mcp-server-webos/venv |
root, 0755 | The code |
/etc/mcp-server-webos/env |
root:mcp-webos, 0640 | HTTP and Access settings |
/var/lib/mcp-server-webos/ |
mcp-webos, 0700 (files 0600) | keys.json, config.json |
/var/log/mcp-server-webos/server.log |
mcp-webos, 0750 | Logs, redacted |
/etc/init.d/mcp-server-webos |
root, 0755 | OpenRC script (supervise-daemon) |
Wake-on-LAN from an LXC: the magic packet is a broadcast (plus a copy to the TV's last
address), so the container must be bridged onto the TVs' network, not NATed. doctor shows the
local address it would leave from.
Logs
stderr only (stdout is the MCP stdio transport). Addresses, MACs, serial numbers, deviceUUIDs and
pointer-socket ids are redacted unless --no-redact (or WEBOS_LOG_UNREDACTED=1); client keys,
JWTs and certificates always are. --debug (WEBOS_DEBUG=1) adds aiowebostv's protocol traffic.
Testing without a TV
pip install -e ".[dev]" && pytest && ruff check . && ruff format --check . && mypy
mcp-server-webos simulate --profile g1 --config-dir /tmp/sim --paired # then, in another terminal:
WEBOS_CONFIG_DIR=/tmp/sim mcp-server-webos call webos_get_status
WEBOS_CONFIG_DIR=/tmp/sim mcp-server-webos call webos_select_source source=netflix
The simulator (src/webos_mcp/sim/) speaks SSAP over real WebSockets: the hello, registration
and the pairing dialog, requests and subscriptions with pushed updates, the TV's error replies,
the pointer socket, and Wake-on-LAN. The real aiowebostv connects to it. Profiles: c7, g1,
c5-webos25, c5-webos26, each field naming its source. aiowebostv always dials ports 3000 and
3001, so each simulated TV binds the real ports on its own loopback address (127.0.0.2-5): on
Linux all of 127.0.0.0/8 is loopback. (macOS needs loopback aliases for that.)
WSL2 with mirrored networking (networkingMode=mirrored in .wslconfig): Windows then
handles loopback and answers only 127.0.0.1, so the simulator tests hang and time out. Run them
with scripts/test-wsl.sh [pytest args], which runs pytest in a network namespace of its own
(ordinary Linux loopback, no other network; needs unshare and ip, and root or sudo). WSL2's
default NAT networking doesn't need it.
mcp-server-webos capture --tv <name> --profile <p> records a real TV's answers to read-only
requests, redacted; committed to src/webos_mcp/sim/fixtures/, each capture becomes a contract
test against its simulator profile.
What has been confirmed on hardware
Every protocol detail this server relies on is in src/webos_mcp/assumptions.py, with its source
and how confident that source is. doctor prints the unconfirmed ones; HARDWARE_VALIDATION.md
says which step confirms each.
| Assumption | Confidence | Status |
|---|---|---|
W-MANIFEST |
high | simulator-only |
W-SIGNED-403 |
high | simulator-only |
W-KEY-SURVIVES |
low | simulator-only |
W-REGISTERED-DIRECT |
high | hardware-verified |
W-STALE-KEY |
medium | simulator-only |
W-PROMPT-DISMISS |
low | simulator-only |
W-PAIR-WINDOW |
low | simulator-only |
W-HELLO-VERSION |
high | hardware-verified |
W-SWINFO-401 |
high | hardware-verified |
W-UUID-STABLE |
medium | simulator-only |
W-PORTS |
medium | simulator-only |
W-PORT3000-CLOSE |
medium | simulator-only |
W-TLS-CERT |
low | simulator-only |
W-MULTI-CLIENT |
medium | simulator-only |
W-INPUT-SOCKET |
medium | hardware-verified |
W-SUBSCRIBE |
high | hardware-verified |
W-HELLO-1008 |
medium | hardware-verified |
W-POWER-STATES |
high | simulator-only |
W-C7-NO-POWERSTATE |
low | hardware-contradicted |
W-STANDBY-SOCKET |
low | simulator-only |
W-OFF-GUARD |
low | simulator-only |
W-TURNON-DEAD |
medium | simulator-only |
W-WOL |
medium | simulator-only |
W-WOL-PATH |
low | simulator-only |
W-WAKE-TIME |
medium | hardware-contradicted |
W-MAC-SOURCE |
low | simulator-only |
W-SCREEN-OFF |
medium | simulator-only |
W-KEYS |
medium | simulator-only |
W-MEDIA-CONTROLS |
low | simulator-only |
W-NOW-PLAYING |
medium | hardware-verified |
W-SOUND-OUTPUT |
medium | hardware-verified |
W-VOLUME-ARC |
medium | simulator-only |
W-APP-IDS |
low | simulator-only |
W-SYSTEM-APP-IDS |
medium | simulator-only |
W-INPUT-IDS |
medium | hardware-verified |
W-SSDP |
medium | hardware-verified |
W-IME-FOCUS |
high | hardware-verified |
W-IME-TEXT |
high | hardware-verified |
W-IME-LENGTH |
medium | hardware-verified |
W-YOUTUBE-SEARCH |
medium | hardware-verified |
License
MIT
Metadata
Release files for mcp-server-webos 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| mcp_server_webos-0.1.0.tar.gz | 177.9 kB | With provenance | Details for mcp_server_webos-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| mcp_server_webos-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for mcp_server_webos-0.1.0-py3-none-any.whl |
Total release size: 311.0 kB
Release files / mcp_server_webos-0.1.0.tar.gz
| Download URL | mcp_server_webos-0.1.0.tar.gz |
|---|---|
| Size | 177.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
245639f0d928420d1ace858f855df14b278bc3de17123dc22080b674a13a91d8
|
|
BLAKE2b-256 checksum How to use checksums |
826b9c0d74d2b7eb35558d25621804842c94139e9d38c073a43982725ac623bd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.
Transparency logRelease files / mcp_server_webos-0.1.0-py3-none-any.whl
| Download URL | mcp_server_webos-0.1.0-py3-none-any.whl |
|---|---|
| Size | 133.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dca8f9ac44ee52c6e90de4947f6ef6920e280621e9f19d6d40d2b876b33e4946
|
|
BLAKE2b-256 checksum How to use checksums |
4fc196bbdbbd4cdad0e256d77fb83d5cac7d15add911821fc981deb14e02c79c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.
Transparency logSecurity for mcp-server-webos 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for mcp_server_webos-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 11, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.