Skip to content

Commit 38a1ec8

Browse files
authored
Add MCP server for AI assistant integration (#273)
* Add MCP server for AI assistant integration Implement a Model Context Protocol (MCP) server as a new subcommand (`screenly mcp`) that exposes the Screenly v4 API as tools for AI assistants like Claude, Cursor, and others. Features: - 31 MCP tools covering screens, assets, playlists, labels, and Edge Apps - Stdio transport for seamless AI assistant integration - Reuses existing CLI authentication (API_TOKEN env var or ~/.screenly) - Comprehensive test coverage with 35 new unit tests New files: - src/mcp/mod.rs - Module structure - src/mcp/server.rs - MCP server handler with tool definitions - src/mcp/tests.rs - Unit tests for all tools - src/mcp/tools/*.rs - Tool implementations for each API resource Dependencies: - Add rmcp 0.12 (MCP SDK) and schemars 0.8 (JSON Schema) - Update sentry 0.42 -> 0.46, simple_logger 4 -> 5 - Update dev deps: httpmock 0.6 -> 0.8, swc_common 14 -> 18, swc_ecma_parser 24 -> 32 Other changes: - Update httpmock API calls (body_contains -> body_includes, assert_hits -> assert_calls) - Remove unused SettingValue struct in edge_app/setting.rs - Comment out nightly-only rustfmt options to avoid warnings - Update README with MCP documentation and configuration examples * Bumps version * Rebuild docs * roll back changes * Fixes nightly linting * Improve CLI documentation and help text consistency - Fix grammar issues in command descriptions: - "Logins/Logouts" → "Logs in/Logs out" - Add missing articles ("a web asset", "an Edge App") - Fix verb tenses ("release it" → "releases it") - Standardize "Edge App" title-casing across all user-facing messages - Error messages, success messages, and help text now consistently use "Edge App" instead of "edge app" - Improve help text clarity: - "If not specified CLI will use..." → "Defaults to..." - "Shortcut for setting up..." → "Sets up..." - Clearer parameter descriptions - Add predicate DSL documentation to MCP server instructions - Documents $DATE, $TIME, $WEEKDAY variables - Includes operator reference and common examples - Adds time reference values (9AM, 12PM, 5PM in milliseconds) - Update docs/CommandLineHelp.md to reflect all help text changes * Fixes linting
1 parent d200c21 commit 38a1ec8

24 files changed

Lines changed: 3160 additions & 1402 deletions

Cargo.lock

Lines changed: 934 additions & 1236 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "screenly"
3-
version = "1.0.5"
3+
version = "1.1.0"
44
edition = "2021"
55

66
[[bin]]
@@ -30,28 +30,32 @@ rayon = "1.7.0"
3030
regex = "1.9.3"
3131
reqwest = { version = "0.12.22", features = ["json", "blocking", "multipart"] }
3232
rpassword = "7.2.0"
33-
sentry = "0.42.0"
34-
sentry-anyhow = "0.42.0"
33+
sentry = "0.46"
34+
sentry-anyhow = "0.46"
3535
serde = { version = "1.0.147", features = ["derive"] }
3636
serde_json = "1.0.87"
3737
serde_with = "3.8.3"
3838
serde_yaml = "0.9.17"
3939
sha1 = "0.10.5"
4040
sha2 = "0.10.7"
41-
simple_logger = { version = "4.0.0", features = ["colors"] }
41+
simple_logger = { version = "5", features = ["colors"] }
4242
strum = "0.27"
4343
strum_macros = "0.27"
4444
temp-env = "0.3.6"
4545
term = "1.1.0"
4646
thiserror = "2.0.12"
47-
tokio = { version = "1.32.0", features = ["rt-multi-thread"] }
47+
tokio = { version = "1.32.0", features = ["rt-multi-thread", "macros"] }
4848
tokio-stream = "0.1.14"
4949
walkdir = "2.3.3"
50-
warp = "0.3.5"
50+
warp = "0.3"
51+
52+
# MCP server dependencies
53+
rmcp = { version = "0.12", features = ["schemars", "server", "transport-io"] }
54+
schemars = "0.8"
5155

5256
[dev-dependencies]
5357
envtestkit = "1.1.2"
54-
httpmock = "0.6"
55-
swc_common = { version = "14.0.4", default-features = false, features = [] }
56-
swc_ecma_parser = { version = "24.0.2", default-features = false, features = [] }
58+
httpmock = "0.8"
59+
swc_common = { version = "18", default-features = false, features = [] }
60+
swc_ecma_parser = { version = "32", default-features = false, features = ["typescript"] }
5761
tempfile = "3.8"

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ FROM alpine:3 as builder
33

44
WORKDIR /usr/src/screenly-cli
55
RUN apk add --no-cache wget tar
6-
ARG RELEASE=v1.0.5
6+
ARG RELEASE=v1.1.0
77
RUN wget "https://github.com/Screenly/cli/releases/download/$RELEASE/screenly-cli-x86_64-unknown-linux-musl.tar.gz"
88
RUN tar xfz screenly-cli-x86_64-unknown-linux-musl.tar.gz
99

README.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,57 @@ $ API_SERVER_NAME=local cargo build --release
6767
6868
Explore available commands [here](https://developer.screenly.io/cli/#commands).
6969
70+
## MCP Server (AI Assistant Integration)
71+
72+
The Screenly CLI includes a built-in [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server, enabling AI assistants like Claude, Cursor, and others to interact with your Screenly digital signage network.
73+
74+
### Starting the MCP Server
75+
76+
```bash
77+
$ screenly mcp
78+
```
79+
80+
The server communicates over stdio and exposes the full Screenly API as tools.
81+
82+
### Available Tools
83+
84+
| Category | Tools |
85+
|----------|-------|
86+
| **Screens** | `screen_list`, `screen_get` |
87+
| **Assets** | `asset_list`, `asset_get`, `asset_create`, `asset_update`, `asset_delete` |
88+
| **Asset Groups** | `asset_group_list`, `asset_group_create`, `asset_group_update`, `asset_group_delete` |
89+
| **Playlists** | `playlist_list`, `playlist_create`, `playlist_update`, `playlist_delete` |
90+
| **Playlist Items** | `playlist_item_list`, `playlist_item_create`, `playlist_item_update`, `playlist_item_delete` |
91+
| **Labels** | `label_list`, `label_create`, `label_update`, `label_delete`, `label_link_screen`, `label_unlink_screen`, `label_link_playlist`, `label_unlink_playlist` |
92+
| **Shared Playlists** | `shared_playlist_list`, `shared_playlist_create`, `shared_playlist_delete` |
93+
| **Edge Apps** | `edge_app_list`, `edge_app_list_settings`, `edge_app_list_instances` |
94+
95+
### Configuration Examples
96+
97+
#### Cursor / Claude Desktop
98+
99+
Add to your MCP configuration file:
100+
101+
```json
102+
{
103+
"mcpServers": {
104+
"screenly": {
105+
"command": "screenly",
106+
"args": ["mcp"],
107+
"env": {
108+
"API_TOKEN": "your-api-token-here"
109+
}
110+
}
111+
}
112+
}
113+
```
114+
115+
#### Authentication
116+
117+
The MCP server uses the same authentication as the CLI:
118+
- Set the `API_TOKEN` environment variable, or
119+
- Run `screenly login` to store credentials in `~/.screenly`
120+
70121
## GitHub Action
71122
72123
Integrate Screenly CLI into your GitHub workflows:

0 commit comments

Comments
 (0)