Scenic MCP
The Scenic MCP server enables remote control of Scenic GUI applications via TCP connection with these capabilities:
Connection Management: Establish and test connectivity with
connect_scenicand check status withget_scenic_statusKeyboard Input: Send text and special keys (enter, escape, tab, arrows, F1-F12) with
send_keys, including modifier key combinations (ctrl, shift, alt, cmd/meta)Mouse Control: Move cursor to precise coordinates with
send_mouse_moveand simulate clicks withsend_mouse_clickusing left, right, or middle buttonsViewport Inspection: Retrieve details of what's currently displayed on the Scenic application with
inspect_viewport
Provides integration with Scenic (an Elixir UI framework), enabling AI-driven automation and testing for Scenic applications through a TCP server that exposes app state and allows interaction with UI elements.
Uses Node.js to implement the MCP server component that bridges between the Elixir TCP server and AI assistants, enabling the control of Scenic applications.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Scenic MCPclick the login button and type my username"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Scenic MCP
Model Context Protocol (MCP) server for Scenic GUI applications
Version: 1.0.0
Enable AI assistants to interact with Scenic GUI applications through keyboard input, mouse control, and visual feedback. Perfect for automated testing, AI-driven development workflows, and accessibility tools.
Features
πΉ Keyboard Input - Send text and special keys with modifier support (Ctrl, Shift, Alt, Cmd)
π±οΈ Mouse Control - Move cursor and click at specific coordinates
π― Semantic Interaction - Click specific components using semantic markup, not just raw coordinates
πΈ Visual Feedback - Inspect viewport structure and capture screenshots
π€ MCP Integration - Works with Claude Desktop, Claude Code, and other MCP clients
Related MCP server: Mobile Next MCP
Quick Start
1. Add to your Scenic app's mix.exs
Note this is still not actually published to hex so you need to clone it and add it as a local dep for now.
defp deps do
[
{:scenic_mcp, "../scenic_mcp"}
]
end2. Configure your viewport and driver
Scenic MCP requires named viewport and driver processes. Update your supervision tree:
# In your application.ex
def start(_type, _args) do
children = [
{Scenic, scenic_viewport_config()}
]
Supervisor.start_link(children, strategy: :one_for_one)
end
defp scenic_viewport_config do
[
name: :main_viewport, # Required!
size: {800, 600},
default_scene: MyApp.RootScene,
drivers: [
[
name: :scenic_driver, # Required!
module: Scenic.Driver.Local,
window: [title: "My App"],
on_close: :stop_system
]
]
]
endNote that name here defines the atom which will become the registered process name for the ViewPort and Driver processes. We need to know this in order to find the pid of this process in order to interact with the ViewPort, and our solution was to look for this specific name main_viewport so you need to set this in your config as above for ScenicMCP to work.
Viewport name: :main_viewport
Driver name: :scenic_driver
Optional: Custom process names
If you need different process names, configure them:
# config/config.exs
config :scenic_mcp,
viewport_name: :my_custom_viewport,
driver_name: :my_custom_driver,
port: 99993. Install TypeScript dependencies
cd scenic_mcp
npm install
npm run build4. Configure Claude Code or Claude Desktop
Using Claude Code CLI (Recommended)
claude mcp add scenic-mcp /path/to/scenic_mcp/dist/index.js
claude mcp list # Verify installationManual Configuration
Edit ~/.claude.json:
{
"projects": {
"/path/to/your/project": {
"mcpServers": {
"scenic-mcp": {
"type": "stdio",
"command": "/path/to/scenic_mcp/dist/index.js",
"args": [],
"env": {}
}
}
}
}
}Optional: Tidewave MCP Configuration
Tidewave provides runtime introspection for Elixir/Phoenix apps (logs, SQL queries, code evaluation, docs). If your project includes Tidewave (Flamelex/Quillex do), you can add it alongside Scenic MCP.
Using Claude Code CLI:
TIDEWAVE_PORT=4000 # Change to your app's port
claude mcp add --transport http tidewave http://localhost:$TIDEWAVE_PORT/tidewave/mcpManual Configuration:
Add this to the same project config in ~/.claude.json:
{
"projects": {
"/path/to/your/project": {
"mcpServers": {
"scenic-mcp": {
"type": "stdio",
"command": "/path/to/scenic_mcp/dist/index.js",
"args": [],
"env": {}
},
"tidewave": {
"type": "http",
"url": "http://localhost:$TIDEWAVE_PORT/tidewave/mcp"
}
}
}
}
}Replace $TIDEWAVE_PORT with your application's HTTP port (e.g., 4000 for Phoenix defaults).
5. Start your Scenic app
cd your_scenic_app
iex -S mixYou should see:
β
ScenicMCP successfully started on port 9999Usage
Available Tools
Connection & Status
connect_scenic- Establish connection to running Scenic appget_scenic_status- Check connection status and server info
User Input
send_keys- Send keyboard input (text, special keys, modifiers)send_mouse_move- Move cursor to coordinatessend_mouse_click- Click at coordinates (left/right/middle button)
Visual Feedback
inspect_viewport- Get text description of viewport structuretake_screenshot- Capture PNG screenshot (path or base64)
Examples
Text Input
send_keys({ text: "Hello, World!" })Special Keys
send_keys({ key: "enter" })
send_keys({ key: "escape" })
send_keys({ key: "tab" })Keyboard Shortcuts
send_keys({ key: "s", modifiers: ["ctrl"] }) // Ctrl+S (Save)
send_keys({ key: "c", modifiers: ["cmd"] }) // Cmd+C (Copy on Mac)
send_keys({ key: "z", modifiers: ["ctrl", "shift"] }) // Ctrl+Shift+Z (Redo)Mouse Control
send_mouse_move({ x: 100, y: 200 })
send_mouse_click({ x: 150, y: 250, button: "left" })
send_mouse_click({ x: 300, y: 100, button: "right" }) // Right-clickVisual Inspection
inspect_viewport() // Get component structure
take_screenshot({ format: "path" }) // Save to /tmp
take_screenshot({
filename: "app_state.png",
format: "base64" // Get base64 data
})Architecture
AI Agent (Claude Desktop/Code)
β stdio
TypeScript MCP Server (this package)
β TCP (port 9999)
Elixir GenServer (ScenicMcp.Server)
β function calls
Scenic Driver Process
β input events
Your Scenic ApplicationHow It Works
TypeScript MCP Server handles MCP protocol via stdio
TCP Bridge maintains persistent connection to Elixir
Elixir GenServer receives JSON commands over TCP
Tool Handlers interact with Scenic viewport and driver
Driver injects input events into your application
Configuration
Available Options
# config/config.exs
config :scenic_mcp,
# TCP port for MCP server (default: 9999)
port: 9999,
# Viewport process name (default: :main_viewport)
viewport_name: :main_viewport,
# Driver process name (default: :scenic_driver)
driver_name: :scenic_driver,
# Application name for logging (default: "Unknown")
app_name: "MyApp"Multiple Scenic Apps
If you're running multiple Scenic apps, configure unique ports:
# In flamelex/config/config.exs
config :scenic_mcp, port: 9999, app_name: "Flamelex"
# In quillex/config/config.exs
config :scenic_mcp, port: 9997, app_name: "Quillex"
# In your_test/config/test.exs
config :scenic_mcp, port: 9996, app_name: "Test"Connect to specific ports:
connect_scenic({ port: 9997 }) // Connect to QuillexDevelopment
Build TypeScript
npm run build # One-time build
npm run dev # Watch mode for developmentBundle for Distribution
npm run bundle # Copies dist/* to priv/mcp_server/Run Tests
# Elixir tests
mix test
# Test specific file
mix test test/scenic_mcp/server_test.exsProject Structure
scenic_mcp/
βββ lib/
β βββ scenic_mcp.ex # Module documentation
β βββ scenic_mcp/
β βββ application.ex # OTP application
β βββ config.ex # Configuration management
β βββ server.ex # TCP server (GenServer)
β βββ tools.ex # Tool handlers
βββ src/
β βββ index.ts # MCP server entry point
β βββ connection.ts # TCP connection management
β βββ tools.ts # Tool definitions
βββ test/
β βββ scenic_mcp/
β βββ server_test.exs # Integration tests
βββ dist/ # Compiled TypeScriptTroubleshooting
MCP Server Not Connecting
Error: MCP server fails to connect or tools are not available in Claude Code/Desktop
Solution: The compiled dist/index.js file must be executable. TypeScript compilation doesn't preserve executable permissions, even if the source file has them.
Fix:
chmod +x /path/to/scenic_mcp/dist/index.jsAutomatic fix: The build script now automatically makes the file executable. If you built before this fix was added, either:
Run
npm run buildagain (recommended)Manually run
chmod +x dist/index.js
After fixing, restart Claude Code or start a new conversation for the change to take effect.
Port Already in Use
Error: Port 9999 is already in use!
Solution: Configure a different port in your config.exs:
config :scenic_mcp, port: 9998Cannot Find Viewport
Error: Unable to find Scenic viewport process ':main_viewport'
Solutions:
Ensure your viewport is named:
name: :main_viewportin your Scenic configOr configure the expected name:
config :scenic_mcp, viewport_name: :your_nameVerify your Scenic app is running:
Process.whereis(:main_viewport)
Cannot Find Driver
Error: Unable to find Scenic driver process ':scenic_driver'
Solutions:
Ensure your driver is named:
name: :scenic_driverin your driver configOr configure the expected name:
config :scenic_mcp, driver_name: :your_nameCheck driver started:
Process.whereis(:scenic_driver)
Connection Timeout
Error: Command timeout after 5000ms
Solutions:
Check if Scenic app is running
Verify correct port:
connect_scenic({ port: YOUR_PORT })Check firewall settings (should allow localhost:9999)
Tests Failing
If tests fail with connection errors:
Ensure no other apps are using test ports (9996-9998)
Run tests with:
mix test --tracefor detailed outputCheck that
scenic_driver_localdependency is properly compiled
Security Considerations
β οΈ Important Security Notes:
Scenic MCP binds to
localhostonly - not accessible from external networksNo authentication - anyone with local access can control your app
Intended for development and testing environments only
Do not expose the TCP port (9999) to untrusted networks
Do not use in production without additional security measures
See SECURITY.md for detailed security guidelines.
Integration Guide
See docs/INTEGRATION.md for step-by-step integration instructions, including:
Adding Scenic MCP to existing applications
Common patterns and best practices
Testing strategies
Example implementations
API Reference
Error Handling
All tool functions return consistent error structures:
{
"error": "Descriptive error message with context and potential solutions"
}Success responses include a status field:
{
"status": "ok",
"message": "Operation completed successfully",
...additional data...
}Contributing
Contributions are welcome! Please:
Fork the repository
Create a feature branch
Add tests for new functionality
Ensure
mix testpassesSubmit a pull request
Requirements
Elixir ~> 1.14
Erlang/OTP 24+
Node.js >= 18.0
Scenic ~> 0.11
Claude Desktop or Claude Code (for MCP client)
License
MIT License - see LICENSE for details
Related Projects
Scenic - 2D UI framework for Elixir
MCP - Model Context Protocol specification
Tidewave - Elixir/Phoenix MCP tools
Changelog
See CHANGELOG.md for version history.
Support
Report bugs: GitHub Issues
Documentation: This README and docs/
Examples: See examples/ directory
Made with β€οΈ for the Elixir and Scenic communities
Available Tools
6 toolsconnect_scenicC
Test connection to a Scenic application via TCP server
| Name | Required | Description | Default |
|---|---|---|---|
| port | No | TCP port (default: 9999) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden but only states the action without behavioral details. It doesn't disclose what 'Test connection' entails (e.g., timeout behavior, error responses, authentication needs, or what constitutes success/failure), leaving the agent to guess about implementation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence with zero wasteβit directly states the tool's purpose without unnecessary elaboration. It's appropriately sized and front-loaded, making it easy for an agent to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's purpose (testing connectivity), lack of annotations, and no output schema, the description is incomplete. It doesn't explain what the test involves, expected outcomes, or error handling, which are critical for an agent to use this tool effectively in context with siblings.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with the parameter 'port' fully documented in the schema. The description adds no additional parameter semantics beyond what the schema provides, so it meets the baseline of 3 where the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Test connection') and target ('to a Scenic application via TCP server'), providing specific verb+resource. However, it doesn't explicitly differentiate from sibling tools like 'get_scenic_status' which might also involve connectivity checks, leaving room for potential confusion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives like 'get_scenic_status' for status checks or other siblings for different interactions. The description implies it's for initial connectivity testing but doesn't specify prerequisites, failure scenarios, or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_scenic_statusB
Check the status of the Scenic TCP connection
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It states what the tool does but doesn't describe what the status check entails (e.g., whether it returns connection health, latency, or error details), potential side effects, or response format. This leaves significant gaps in understanding the tool's behavior beyond its basic purpose.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, clear sentence with no wasted words. It's front-loaded with the core action and resource, making it easy to parse quickly. Every part of the sentence contributes directly to understanding the tool's function.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of annotations and output schema, the description is incomplete for a status-checking tool. It doesn't explain what information the status provides (e.g., connected/disconnected, metrics), how to interpret results, or error handling. For a tool that likely returns structured status data, this omission is significant.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, and schema description coverage is 100%, so there's no need for parameter documentation in the description. The description appropriately avoids discussing parameters, focusing solely on the tool's purpose, which aligns well with the empty input schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Check') and the resource ('status of the Scenic TCP connection'), making the purpose immediately understandable. It doesn't explicitly differentiate from siblings like 'connect_scenic' or 'inspect_viewport', but the specific focus on connection status provides some implicit distinction.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives like 'connect_scenic' (for establishing connection) or 'inspect_viewport' (for checking viewport state). There's no mention of prerequisites, error conditions, or typical use cases, leaving the agent with minimal context for tool selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inspect_viewportB
Inspect the Scenic viewport to see what's currently displayed
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden for behavioral disclosure. It states the tool inspects the viewport but doesn't describe what 'inspect' entails operationally (e.g., returns a screenshot, text description, or structured data), whether it's read-only or has side effects, latency characteristics, or error conditions. For a tool with zero annotation coverage, this leaves significant behavioral gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that directly states the tool's purpose without unnecessary words. It's front-loaded with the core action and target, making it immediately understandable. Every word earns its place with no redundancy or fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no annotations, no output schema, and a simple zero-parameter input schema, the description is incomplete. It doesn't explain what format the inspection returns (e.g., image data, text description, structured metadata), which is critical for an inspection tool. The agent knows what to inspect but not what to expect as a result.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters with 100% schema description coverage (empty schema). The description doesn't need to explain any parameters, and it appropriately doesn't mention any. Since there are no parameters to document, this meets expectations for parameter semantics without needing compensation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('inspect') and target ('Scenic viewport') with a specific purpose ('to see what's currently displayed'). It distinguishes from siblings like 'connect_scenic' or 'get_scenic_status' by focusing on visual content inspection rather than connection or status checking. However, it doesn't explicitly differentiate from potential visual inspection alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives like 'get_scenic_status' (which might provide status information) or other visual inspection methods. There's no mention of prerequisites (e.g., requires connection first), typical use cases, or limitations. The agent must infer usage from the purpose alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_keysC
Send keyboard input to the connected Scenic application
| Name | Required | Description | Default |
|---|---|---|---|
| key | No | Special key name (e.g., enter, escape, tab, backspace, delete, up, down, left, right, home, end, page_up, page_down, f1-f12) | |
| modifiers | No | Modifier keys to hold while pressing the key | |
| text | No | Text to type (each character will be sent as individual key presses) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden but offers minimal behavioral context. It states what the tool does but doesn't disclose important traits like whether this requires an active connection, what happens if no application is connected, whether input is queued or immediate, or any error conditions. For a tool that interacts with external applications, this is a significant gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that directly states the tool's purpose with zero wasted words. It's appropriately sized and front-loaded, making it easy to understand immediately.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (interacting with external applications) and lack of annotations or output schema, the description is incomplete. It doesn't address connection requirements, error handling, or what constitutes successful execution. For a tool with three parameters and no structured safety hints, more context is needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all three parameters thoroughly. The description adds no additional parameter information beyond what's in the schema, maintaining the baseline score of 3 where the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Send keyboard input') and target ('to the connected Scenic application'), providing a specific verb+resource combination. However, it doesn't explicitly differentiate from sibling tools like send_mouse_click or send_mouse_move, which handle different input types.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites (like requiring a connected application via connect_scenic), nor does it explain when keyboard input is appropriate versus mouse actions from sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_mouse_clickC
Click mouse at specific coordinates
| Name | Required | Description | Default |
|---|---|---|---|
| button | No | Mouse button to click (default: left) | left |
| x | Yes | X coordinate | |
| y | Yes | Y coordinate |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden but only states the basic action without disclosing behavioral traits. It doesn't mention if this requires specific permissions, has side effects (e.g., triggering UI events), rate limits, or error conditions, which is inadequate for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence with zero wasteβit directly states the tool's purpose without unnecessary words, making it appropriately sized and front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given this is a mutation tool with no annotations and no output schema, the description is incomplete. It lacks information on behavioral context, prerequisites, or what happens after the click, failing to compensate for the missing structured data.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents all parameters (x, y, button). The description adds no additional meaning beyond implying coordinate usage, meeting the baseline of 3 where the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Click mouse at specific coordinates' clearly states the action (click) and resource (mouse) with specificity about coordinates. However, it doesn't distinguish this from sibling tools like send_mouse_move, which suggests room for improvement in sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives like send_mouse_move or send_keys. There's no mention of prerequisites (e.g., needing to connect_scenic first) or context for coordinate usage, leaving the agent without usage direction.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_mouse_moveC
Move mouse cursor to specific coordinates
| Name | Required | Description | Default |
|---|---|---|---|
| x | Yes | X coordinate | |
| y | Yes | Y coordinate |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It states the action but doesn't disclose behavioral traits like whether this requires specific permissions, if it's immediate or queued, what happens if coordinates are out of bounds, if it affects other UI elements, or any side effects. For a system interaction tool with zero annotation coverage, this is a significant gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence with zero waste. It's front-loaded with the core action and appropriately sized for a simple tool with two parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given this is a system interaction tool (mouse movement) with no annotations, no output schema, and siblings that suggest a UI automation context (Scenic), the description is incomplete. It doesn't address prerequisites, coordinate system, behavioral constraints, or what success/failure looks like, leaving significant gaps for an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with both parameters (x and y) clearly documented in the schema as coordinates. The description adds no additional meaning beyond what the schema provides (e.g., coordinate system origin, units, or valid ranges). Baseline 3 is appropriate when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Move') and resource ('mouse cursor') with the specific action ('to specific coordinates'). It distinguishes from siblings like send_mouse_click (clicking vs moving) and send_keys (keyboard input). However, it doesn't explicitly differentiate from other potential mouse movement tools that might exist in other contexts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites (e.g., needing to connect to Scenic first using connect_scenic), when mouse movement is appropriate versus other input methods, or any constraints on coordinate ranges or system state.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
6 tool updates
v1.0.0- First observed
connect_scenic - First observed
get_scenic_status - First observed
inspect_viewport - First observed
send_keys - First observed
send_mouse_click - First observed
send_mouse_move
TDQS
Scored across 6 tools
Each tool has a clearly distinct purpose with no overlap: connection testing, status checking, viewport inspection, keyboard input, mouse clicking, and mouse movement. The descriptions make it easy to differentiate between these functions, eliminating any ambiguity.
All tools follow a consistent verb_noun pattern with underscores (e.g., connect_scenic, get_scenic_status, inspect_viewport). The naming is predictable and readable throughout the set, with no deviations in style.
With 6 tools, this server is well-scoped for interacting with a Scenic application via TCP. Each tool earns its place by covering essential functions like connection management, input simulation, and display inspection, without being too sparse or bloated.
The toolset provides solid coverage for basic Scenic application interaction, including connection, status, input, and display. A minor gap exists in not having tools for more advanced interactions like drag-and-drop or multi-touch gestures, but core workflows are well-supported.
Maintenance
Related MCP Connectors
A Model Context Protocol server for Wix AI tools
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yoβ¦
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to control Unreal Eβ¦
The Telnyx MCP server is an official implementation of the Model Context Protocol that enables AI clients (like Claude Desktop, Cursor, and OpenAI Agents) to interact with Telnyx's telephony, messaging, and AI assistant APIs. It provides comprehensive capabilities including making and managing phone calls, sending SMS/MMS messages, purchasing and configuring phone numbers, creating AI assistants with custom instructions, managing cloud storage buckets, scraping and embedding website content, and handling integration secrets. The server exists as both a local implementation and a remotely hosted version, allowing developers to integrate real-world communication infrastructure directly into AI applications.
Related MCP Servers
- AlicenseBqualityDmaintenanceA Model Context Protocol server that enables automated end-to-end testing with LLMs using Playwright's accessibility tree rather than pixel-based inputs.12Apache 2.0
- AlicenseAqualityDmaintenanceA Model Context Protocol server that enables scalable mobile automation for iOS and Android through a platform-agnostic interface, allowing LLMs to interact with mobile applications via accessibility snapshots or screenshot-based inputs.1935,456 npm2Apache 2.0
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that enables AI assistants to interact with iOS simulators, perform accessibility testing, manage apps, and automate complex iOS workflows.32Apache 2.0
- FlicenseAqualityDmaintenanceA Model Context Protocol server that enables AI assistants to perform web automation tasks by connecting to remote Playwright/browserless instances, supporting navigation, screenshots, HTML extraction, and element interaction.104-