SemaphoreUI MCP Server
This server lets AI assistants control and monitor SemaphoreUI, the Ansible automation platform, through natural language.
Projects: list, create, update, delete, and fetch details for SemaphoreUI projects
Project backups: export, restore, validate, summarize, and clone project configurations
Project users & roles: view roles, list/add/update/remove project users
Views: list, create, update, delete custom project views
Templates: list, create, update, delete, and fetch Ansible job templates, including task parameter overrides
Schedules: list, create, update, activate/deactivate, delete cron or one-time schedules, and validate cron formats
Tasks: list, filter, run, stop (individually or in bulk), get raw output, and monitor task startup
Failure analysis: analyze single or multiple failed tasks, fetch latest failures, and identify patterns
Events: list global/project events and summarize recent project activity
Environments: list, create, update, delete environment variable sets
Inventory: list, create, update, delete static or file-based inventory items
Repositories: list, create, update, delete Git repository connections
Access keys: list, create, update, delete SSH or login/password credentials
Provides tools to manage Ansible automation through SemaphoreUI, including project, template, task, schedule, inventory, and environment management.
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., "@SemaphoreUI MCP Server Run the database backup playbook on production"
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.
SemaphoreUI MCP Server
A Model Context Protocol (MCP) server that connects AI assistants to SemaphoreUI - enabling natural language control of Ansible automation.

Quick Start
Prerequisites
Docker (or Podman)
A running SemaphoreUI instance with an API token
Claude Desktop or Claude Code (or another MCP client)
Node.js (for Claude Desktop only - required for
mcp-remote)
1. Get a SemaphoreUI API Token
Login to your SemaphoreUI instance
Go to User Settings
Generate a new API token
2. Run the MCP Server
docker run -d --name semaphore-mcp \
--network host \
-e SEMAPHORE_URL=http://localhost:3000 \
-e SEMAPHORE_API_TOKEN=your-token-here \
-e MCP_PORT=8500 \
ghcr.io/cloin/semaphore-mcp:latestNote:
SEMAPHORE_URLis where the MCP server connects to SemaphoreUI.MCP_PORTis where the MCP server listens for client connections (Claude Desktop/Code). Use this port in your client configuration below.
3a. Configure Claude Desktop
Claude Desktop requires the mcp-remote proxy to connect to HTTP-based MCP servers. This requires Node.js to be installed (npx comes with npm).
Edit your config file:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.jsonLinux:
~/.config/claude-desktop/claude_desktop_config.json
{
"mcpServers": {
"semaphore": {
"command": "npx",
"args": ["mcp-remote", "http://127.0.0.1:8500/mcp"]
}
}
}3b. Configure Claude Code
Claude Code supports remote MCP servers directly:
claude mcp add --transport http semaphore http://127.0.0.1:8500/mcpVerify it's configured:
claude mcp list4. Test It
Restart Claude Desktop and try:
"List all projects in SemaphoreUI"
Related MCP server: semaphore-mcp-server
Docker Networking
The MCP server container needs to reach your SemaphoreUI instance.
SemaphoreUI on the same host:
Use --network host so the container can access localhost:
docker run -d --name semaphore-mcp \
--network host \
-e SEMAPHORE_URL=http://localhost:3000 \
-e SEMAPHORE_API_TOKEN=your-token \
-e MCP_PORT=8500 \
ghcr.io/cloin/semaphore-mcp:latestSemaphoreUI on a different host:
Use the IP or hostname directly (no --network host needed):
docker run -d --name semaphore-mcp \
-e SEMAPHORE_URL=http://192.168.1.100:3000 \
-e SEMAPHORE_API_TOKEN=your-token \
-p 8500:8000 \
ghcr.io/cloin/semaphore-mcp:latestFor more details, see Docker's networking documentation.
Configuration
Variable | Required | Default | Description |
| Yes | - | URL to your SemaphoreUI instance |
| stdio: Yes, http: No | - | API token from SemaphoreUI. When set it is always used. With the |
| No |
| Transport mode: |
| No |
| Host to bind to |
| No |
| Port to listen on |
Per-client tokens (token passthrough)
With the http transport and no SEMAPHORE_API_TOKEN, the MCP server forwards the Authorization: Bearer <token> header of each incoming MCP request to SemaphoreUI. Every client (a user, an agent, an automation) then acts with its own SemaphoreUI token and permissions, and the server needs no shared token of its own:
docker run -d --name semaphore-mcp \
--network host \
-e SEMAPHORE_URL=http://localhost:3000 \
-e MCP_PORT=8500 \
ghcr.io/cloin/semaphore-mcp:latestClaude Code:
claude mcp add --transport http semaphore http://127.0.0.1:8500/mcp \
--header "Authorization: Bearer your-token-here"Claude Desktop (mcp-remote passes headers with --header; the value is read from an environment variable because Claude Desktop does not handle spaces in args well):
{
"mcpServers": {
"semaphore": {
"command": "npx",
"args": ["mcp-remote", "http://127.0.0.1:8500/mcp", "--header", "Authorization:${AUTH_HEADER}"],
"env": {
"AUTH_HEADER": "Bearer your-token-here"
}
}
}
}Rules:
If
SEMAPHORE_API_TOKENis set, it is always used and tokens sent by clients are ignored. The operator decides which mode the server runs in.Without
SEMAPHORE_API_TOKEN, each request uses the client's header; a request without one reaches SemaphoreUI unauthenticated and gets401.The
stdiotransport carries no HTTP headers, so it always needsSEMAPHORE_API_TOKEN.The server does not validate forwarded tokens; it relays them. Expose it over TLS (a reverse proxy) or keep it on localhost, and treat it as trusted only as far as SemaphoreUI itself is.
What You Can Do
Once connected, you can interact with SemaphoreUI through natural conversation:
Run automation:
"Run the database backup playbook on production"
Monitor tasks:
"Show me all failed tasks from the last hour and analyze the errors"
Manage infrastructure:
"Create a new staging environment with APP_ENV=staging"
Troubleshoot:
"Get the output from task 42 and tell me why it failed"
Available Tools
Projects: list_projects, get_project, create_project, update_project, delete_project
Project backups: backup_project, restore_project_backup, validate_project_backup, summarize_project_backup, clone_project
Project users: get_project_role, list_project_users, add_project_user, update_project_user, remove_project_user
Views: list_views, get_view, create_view, update_view, delete_view
Templates: list_templates, get_template, create_template, update_template, delete_template
Schedules: list_schedules, list_template_schedules, get_schedule, create_schedule, update_schedule, set_schedule_active, delete_schedule, validate_schedule_cron_format
Tasks: list_tasks, get_task, run_task, stop_task, get_task_raw_output, filter_tasks, bulk_stop_tasks
Analysis: analyze_task_failure, bulk_analyze_failures, get_latest_failed_task
Events: list_events, get_last_events, list_project_events, summarize_project_activity
Environments: list_environments, get_environment, create_environment, update_environment, delete_environment
Inventory: list_inventory, get_inventory, create_inventory, update_inventory, delete_inventory
Repositories: list_repositories, get_repository, create_repository, update_repository, delete_repository
Access keys: list_access_keys, get_access_key, create_access_key, update_access_key, delete_access_key
Troubleshooting
Container won't start or exits immediately:
docker logs semaphore-mcpCan't connect to SemaphoreUI from container:
If SemaphoreUI is on localhost, use
--network hostCheck that the URL is reachable from inside the container
Verify the API token is correct
Claude Desktop not seeing the MCP server:
Ensure the container is running:
docker psCheck the port is accessible:
curl http://127.0.0.1:8500/mcpRestart Claude Desktop after config changes
Enable debug logging:
docker run -d --name semaphore-mcp \
--network host \
-e SEMAPHORE_URL=http://localhost:3000 \
-e SEMAPHORE_API_TOKEN=your-token \
-e MCP_PORT=8500 \
-e MCP_LOG_LEVEL=DEBUG \
ghcr.io/cloin/semaphore-mcp:latestDevelopment
For local development and contributing, see DEVELOPMENT.md.
For testing documentation (unit tests, E2E tests, CI/CD), see TESTING.md.
Resources
License
This project is licensed under the GNU Affero General Public License v3.0 - see the LICENSE file for details.
Note: Versions prior to 1.0.0 were released under the MIT License.
Available Tools
69 toolsadd_project_userA
Link a user to a project with a role.
Args: project_id: ID of the project user_id: ID of the user to link role: Project role: owner, manager, task_runner, or guest
Returns: Empty dict on success
Inputs: role (required), user_id (required), project_id (required). Returns: object
analyze_task_failureA
Analyze a failed task for LLM processing, gathering comprehensive failure context.
Args: project_id: ID of the project task_id: ID of the task to analyze
Returns: Comprehensive failure analysis data including task details, template context, and outputs
Inputs: task_id (required), project_id (required). Returns: object
backup_projectA
Export a Semaphore project backup.
Args: project_id: ID of the project to back up
Returns: Backup payload and a resource summary.
Inputs: project_id (required). Returns: object
bulk_analyze_failuresA
Analyze multiple failed tasks to identify patterns and common issues.
Args: project_id: ID of the project limit: Maximum number of failed tasks to analyze (default: 10)
Returns: Analysis of multiple failed tasks with pattern detection
Inputs: project_id (required), limit. Returns: object
bulk_stop_tasksA
Stop multiple tasks with confirmation.
Args: project_id: ID of the project task_ids: List of task IDs to stop confirm: Set to True to execute the bulk stop operation
Returns: Confirmation details or bulk stop results
Inputs: task_ids (required), project_id (required), confirm. Returns: object
clone_projectA
Clone a project by backing it up and restoring it with a new name.
Args: project_id: ID of the source project name: Name for the cloned project validate: Validate backup payload before restore
Returns: Source project ID, created clone, and backup summary.
Inputs: name (required), project_id (required), validate. Returns: object
create_access_keyA
Create a new access key.
Args: project_id: ID of the project name: Name for the access key key_type: Type of key - one of: - "none": For public repositories (no credentials needed) - "ssh": For SSH key authentication - "login_password": For username/password authentication login: Username (for ssh or login_password types) password: Password (for login_password type) private_key: Private key content (for ssh type)
Returns: Created access key details
Inputs: name (required), key_type (required), project_id (required), login, +2 more. Returns: object
create_environmentB
Create a new environment.
Args: project_id: ID of the project name: Environment name env_data: Environment variables as key-value pairs
Returns: Created environment details
Inputs: name (required), env_data (required), project_id (required). Returns: object
create_inventoryA
Create a new inventory item.
Args: project_id: ID of the project name: Inventory name inventory_data: Inventory content (for "static") or file path on the Semaphore server (for "file") inventory_type: Semaphore inventory type, such as "static", "static-yaml", or "file". Defaults to "static".
Returns: Created inventory item details
Inputs: name (required), project_id (required), inventory_data (required), inventory_type. Returns: object
create_projectA
Create a new project.
Args: name: Project name alert: Enable alerts (default: False) alert_chat: Chat channel for alerts (optional) max_parallel_tasks: Maximum parallel tasks, 0 = unlimited (default: 0) project_type: Project type (optional) demo: Create demo resources (default: False)
Returns: Created project details
Inputs: name (required), demo, alert, alert_chat, +2 more. Returns: object
create_repositoryC
Create a new repository.
Args: project_id: ID of the project name: Repository name git_url: Git repository URL git_branch: Git branch to use ssh_key_id: SSH key ID for authentication
Returns: Created repository details
Inputs: name (required), git_url (required), git_branch (required), project_id (required), +1 more. Returns: object
create_scheduleC
Create a new schedule.
Args: project_id: ID of the project template_id: ID of the template to run name: Schedule name cron_format: Cron expression for recurring schedules active: Whether the schedule is enabled schedule_type: Schedule type: "" for cron, or "run_at" for one-time runs run_at: RFC3339 timestamp for one-time schedules task_params: Optional task parameters to pass when the schedule runs delete_after_run: Delete the one-time schedule after it runs repository_id: Optional repository ID for commit-check schedules
Returns: Created schedule details
Inputs: name (required), project_id (required), template_id (required), active, +6 more. Returns: object
create_templateB
Create a new template.
Args: project_id: ID of the project name: Template name playbook: Playbook file path (e.g., "playbook.yml") inventory_id: Inventory ID repository_id: Repository ID environment_id: Environment ID description: Template description (optional) arguments: Extra arguments as JSON string (optional) allow_override_args_in_task: Allow overriding arguments in task (default: False) suppress_success_alerts: Suppress success alerts (default: False) app: Application type (default: "ansible") git_branch: Git branch to use (optional) survey_vars: Survey variables for prompting (optional) vaults: Vault configurations (optional) template_type: Template type - "", "build", or "deploy" (optional) start_version: Start version (optional) build_template_id: Build template ID for deploy templates (optional) autorun: Enable autorun (default: False) view_id: View ID (optional) task_params: App-specific task parameters (optional). For Ansible templates: - allow_override_limit: Allow task-level --limit override (required for run_task limit) - allow_override_inventory: Allow task-level inventory override - allow_override_tags: Allow task-level --tags override - allow_override_skip_tags: Allow task-level --skip-tags override - limit: Default limit (list of hosts/groups) - tags: Default tags (list) - skip_tags: Default skip tags (list) allow_parallel_tasks: Allow several tasks of this template to run at once (default: False) allow_override_branch_in_task: Allow overriding the git branch in task (default: False) runner_tag: Runner tag (optional)
Returns: Created template details
Inputs: name (required), playbook (required), project_id (required), inventory_id (required), +19 more. Returns: object
create_viewC
Create a new view.
Args: project_id: ID of the project title: View title position: View ordering position
Returns: Created view details
Inputs: title (required), project_id (required), position. Returns: object
delete_access_keyB
Delete an access key by ID.
Args: project_id: ID of the project key_id: ID of the access key to delete
Returns: Empty dict on success
Inputs: key_id (required), project_id (required). Returns: object
delete_environmentC
Delete an environment.
Args: project_id: ID of the project environment_id: ID of the environment to delete
Returns: Deletion result
Inputs: project_id (required), environment_id (required). Returns: object
delete_inventoryB
Delete an inventory item.
Args: project_id: ID of the project inventory_id: ID of the inventory item to delete
Returns: Deletion result
Inputs: project_id (required), inventory_id (required). Returns: object
delete_projectB
Delete a project.
Args: project_id: ID of the project to delete
Returns: Empty dict on success
Inputs: project_id (required). Returns: object
delete_repositoryC
Delete a repository.
Args: project_id: ID of the project repository_id: ID of the repository to delete
Returns: Deletion result
Inputs: project_id (required), repository_id (required). Returns: object
delete_scheduleC
Delete a schedule.
Args: project_id: ID of the project schedule_id: ID of the schedule to delete
Returns: Empty dict on success
Inputs: project_id (required), schedule_id (required). Returns: object
delete_templateC
Delete a template.
Args: project_id: ID of the project template_id: ID of the template to delete
Returns: Empty dict on success
Inputs: project_id (required), template_id (required). Returns: object
delete_viewB
Delete a view.
Args: project_id: ID of the project view_id: ID of the view to delete
Returns: Empty dict on success
Inputs: view_id (required), project_id (required). Returns: object
filter_tasksB
Filter tasks by multiple criteria with bulk operation support.
Args: project_id: ID of the project status: List of statuses to filter by (e.g., ['success', 'error']) limit: Maximum number of tasks to return use_last_tasks: Use efficient last 200 tasks endpoint
Returns: Filtered tasks with statistics
Inputs: project_id (required), limit, status, use_last_tasks. Returns: object
get_access_keyB
Get an access key by ID.
Args: project_id: ID of the project key_id: ID of the access key
Returns: Access key details
Inputs: key_id (required), project_id (required). Returns: object
get_environmentA
Get details of a specific environment.
Args: project_id: ID of the project environment_id: ID of the environment to fetch
Returns: Environment details
Inputs: project_id (required), environment_id (required). Returns: object
get_inventoryB
Get details of a specific inventory item.
Args: project_id: ID of the project inventory_id: ID of the inventory item to fetch
Returns: Inventory item details
Inputs: project_id (required), inventory_id (required). Returns: object
get_last_eventsA
List the last global events visible to the current user.
Semaphore returns the last 200 events. The optional limit trims that response further on the MCP side.
Args: limit: Return only the most recent N events; 0 returns all returned events
Returns: Dictionary containing the list of events
Inputs: limit. Returns: object
get_latest_failed_taskB
Get the most recent failed task for a project.
Args: project_id: ID of the project
Returns: The most recent failed task or a message if no failed tasks are found
Inputs: project_id (required). Returns: object
get_projectA
Get details of a specific project.
Args: project_id: ID of the project to fetch
Returns: Project details
Inputs: project_id (required). Returns: object
get_project_roleA
Get the current user's role and permissions for a project.
Args: project_id: ID of the project
Returns: Role and permissions for the current user
Inputs: project_id (required). Returns: object
get_repositoryB
Get details of a specific repository.
Args: project_id: ID of the project repository_id: ID of the repository to fetch
Returns: Repository details
Inputs: project_id (required), repository_id (required). Returns: object
get_scheduleA
Get details of a specific schedule.
Args: project_id: ID of the project schedule_id: ID of the schedule to fetch
Returns: Schedule details
Inputs: project_id (required), schedule_id (required). Returns: object
get_taskB
Get details of a specific task.
Args: project_id: ID of the project task_id: ID of the task to fetch
Returns: Task details
Inputs: task_id (required), project_id (required). Returns: object
get_task_raw_outputA
Get raw output from a completed task for LLM analysis.
Args: project_id: ID of the project task_id: ID of the task
Returns: Raw task output as plain text
Inputs: task_id (required), project_id (required). Returns: result
get_templateB
Get details of a specific template.
Args: project_id: ID of the project template_id: ID of the template to fetch
Returns: Template details
Inputs: project_id (required), template_id (required). Returns: object
get_viewB
Get details of a specific view.
Args: project_id: ID of the project view_id: ID of the view to fetch
Returns: View details
Inputs: view_id (required), project_id (required). Returns: object
get_waiting_tasksA
Get all tasks in waiting state for bulk operations.
Args: project_id: ID of the project
Returns: List of waiting tasks with bulk operation guidance
Inputs: project_id (required). Returns: object
list_access_keysA
List all access keys for a project.
Args: project_id: ID of the project key_type: Optional key type filter ("none", "ssh", or "login_password") sort: Sort field ("name" or "type") order: Sort order ("asc" or "desc")
Returns: Dictionary containing list of access keys
Inputs: project_id (required), sort, order, key_type. Returns: object
list_environmentsA
List all environments for a project.
Args: project_id: ID of the project
Returns: A list of environments for the project
Inputs: project_id (required). Returns: object
list_eventsA
List global events visible to the current user.
Args: limit: Return only the most recent N events; 0 returns all events
Returns: Dictionary containing the list of events
Inputs: limit. Returns: object
list_inventoryA
List all inventory items for a project.
Args: project_id: ID of the project
Returns: A list of inventory items for the project
Inputs: project_id (required). Returns: object
list_project_eventsA
List events related to a project.
Args: project_id: ID of the project limit: Return only the most recent N events; 0 returns all events
Returns: Dictionary containing the list of project events
Inputs: project_id (required), limit. Returns: object
list_projectsA
List all projects in SemaphoreUI.
Returns: A dictionary containing the list of projects.
Inputs: no named parameters. Returns: object
list_project_usersA
List users linked to a project.
Args: project_id: ID of the project sort: Field to sort by: name, username, email, or role order: Sort order: asc or desc
Returns: Dictionary containing the list of project users
Inputs: project_id (required), sort, order. Returns: object
list_repositoriesA
List all repositories for a project.
Args: project_id: ID of the project
Returns: A list of repositories for the project
Inputs: project_id (required). Returns: object
list_schedulesB
List all schedules for a project.
Args: project_id: ID of the project
Returns: Dictionary containing list of schedules
Inputs: project_id (required). Returns: object
list_tasksA
List tasks for a project with a default limit of 5 to avoid overloading context windows.
Args: project_id: ID of the project limit: Maximum number of tasks to return (default: 5) status: Optional status filter (e.g., 'success', 'error', 'running') tags: Optional list of tags to filter by
Returns: A list of tasks for the project, limited by the specified count
Inputs: project_id (required), tags, limit, status. Returns: object
list_templatesA
List all templates for a project.
Args: project_id: ID of the project
Returns: A list of templates for the project
Inputs: project_id (required). Returns: object
list_template_schedulesA
List schedules attached to a template.
Args: project_id: ID of the project template_id: ID of the template
Returns: Dictionary containing list of template schedules
Inputs: project_id (required), template_id (required). Returns: object
list_viewsB
List all views for a project.
Args: project_id: ID of the project
Returns: Dictionary containing the list of views
Inputs: project_id (required). Returns: object
remove_project_userB
Remove a user from a project.
Args: project_id: ID of the project user_id: ID of the user to remove
Returns: Empty dict on success
Inputs: user_id (required), project_id (required). Returns: object
restore_project_backupA
Restore a Semaphore project from a backup payload.
Args: backup: Backup payload returned by backup_project project_name: Optional name override for the restored project validate: Validate payload shape and references before restore
Returns: Created project and summary of the restored backup payload.
Inputs: backup (required), validate, project_name. Returns: object
run_taskA
Run a task from a template with optional 30-second monitoring.
Args: template_id: ID of the template to run project_id: Optional project ID (if not provided, will attempt to determine from template) environment: Optional environment variables for the task as dictionary limit: Restrict execution to specific hosts/groups (Ansible --limit) dry_run: Run without making changes (Ansible --check) diff: Show differences when changing files (Ansible --diff) debug: Enable verbose debug output playbook: Override playbook file path git_branch: Override git branch to use message: Task description/message arguments: Additional CLI arguments as a JSON string or string list inventory_id: Override inventory to use follow: Enable 30-second monitoring for startup verification (default: False)
Returns: Task execution result with immediate web URLs and optional monitoring summary
Template Override Requirements: Some parameters require the template to have overrides enabled in task_params. Use create_template() or update_template() with task_params to enable:
- limit: requires task_params={"allow_override_limit": true}
- inventory_id: requires task_params={"allow_override_inventory": true}
Without these settings, the parameter will be ignored silently.Examples: # Just start the task and get URLs result = await run_task(template_id=5)
# Start task with 30-second monitoring and get URLs
result = await run_task(template_id=5, follow=True)
# Run with limit to specific hosts (template must allow override)
result = await run_task(template_id=5, limit="webservers")
# Dry run with diff to preview changes
result = await run_task(template_id=5, dry_run=True, diff=True)
Inputs: template_id (required), diff, debug, limit, +9 more. Returns: object
set_schedule_activeA
Enable or disable a schedule.
Args: project_id: ID of the project schedule_id: ID of the schedule to update active: Whether the schedule should be active
Returns: Empty dict on success
Inputs: active (required), project_id (required), schedule_id (required). Returns: object
stop_all_template_tasksC
Stop all running tasks for a template.
Args: project_id: ID of the project template_id: ID of the template
Returns: Empty dict on success
Inputs: project_id (required), template_id (required). Returns: object
stop_taskB
Stop a running task.
Args: project_id: ID of the project task_id: ID of the task to stop
Returns: Task stop result
Inputs: task_id (required), project_id (required). Returns: object
summarize_project_activityA
Summarize recent project activity from Semaphore events.
Args: project_id: ID of the project limit: Number of most recent events to analyze recent_limit: Number of recent event objects to include
Returns: Counts and recent event details for project activity
Inputs: project_id (required), limit, recent_limit. Returns: object
summarize_project_backupA
Summarize the resources contained in a project backup.
Args: backup: Backup payload to summarize
Returns: Counts, names, and secret-reference indicators for the backup.
Inputs: backup (required). Returns: object
update_access_keyB
Update an existing access key.
Args: project_id: ID of the project key_id: ID of the access key name: New access key name (optional) key_type: New key type (optional) login: Username for ssh or login_password keys (optional) password: Password for login_password keys (optional) private_key: Private key for ssh keys (optional) override_secret: Force updating stored secret material (optional)
Returns: Empty dict on success
Inputs: key_id (required), project_id (required), name, login, +4 more. Returns: object
update_environmentB
Update an existing environment.
Args: project_id: ID of the project environment_id: ID of the environment to update name: Environment name (optional) env_data: Environment variables as key-value pairs (optional)
Returns: Updated environment details
Inputs: project_id (required), environment_id (required), name, env_data. Returns: object
update_inventoryB
Update an existing inventory item.
Args: project_id: ID of the project inventory_id: ID of the inventory item to update name: Inventory name (optional) inventory_data: Inventory content for "static", or file path for "file" (optional) inventory_type: Semaphore inventory type, such as "static", "static-yaml", or "file". Defaults to "static"; pass the existing type if you don't intend to change it.
Returns: Updated inventory item details
Inputs: project_id (required), inventory_id (required), name, inventory_data, +1 more. Returns: object
update_projectB
Update an existing project.
Args: project_id: ID of the project to update name: Project name (optional) alert: Enable alerts (optional) alert_chat: Chat channel for alerts (optional) max_parallel_tasks: Maximum parallel tasks (optional) project_type: Project type (optional)
Returns: Empty dict on success
Inputs: project_id (required), name, alert, alert_chat, +2 more. Returns: object
update_project_userA
Update a linked user's project role.
Args: project_id: ID of the project user_id: ID of the linked user role: Project role: owner, manager, task_runner, or guest
Returns: Empty dict on success
Inputs: role (required), user_id (required), project_id (required). Returns: object
update_repositoryB
Update an existing repository.
Args: project_id: ID of the project repository_id: ID of the repository to update name: Repository name (optional) git_url: Git repository URL (optional) git_branch: Git branch to use (optional) ssh_key_id: SSH key ID for authentication (optional)
Returns: Updated repository details
Inputs: project_id (required), repository_id (required), name, git_url, +2 more. Returns: object
update_scheduleB
Update an existing schedule.
Args: project_id: ID of the project schedule_id: ID of the schedule to update template_id: ID of the template to run name: Schedule name cron_format: Cron expression for recurring schedules active: Whether the schedule is enabled schedule_type: Schedule type: "" for cron, or "run_at" for one-time runs run_at: RFC3339 timestamp for one-time schedules task_params: Optional task parameters to pass when the schedule runs delete_after_run: Delete the one-time schedule after it runs repository_id: Optional repository ID for commit-check schedules
Returns: Updated schedule details or empty dict on success
Inputs: project_id (required), schedule_id (required), name, active, +7 more. Returns: object
update_templateA
Update an existing template.
Args: project_id: ID of the project template_id: ID of the template to update name: Template name (optional) playbook: Playbook file path (optional) inventory_id: Inventory ID (optional) repository_id: Repository ID (optional) environment_id: Environment ID (optional) description: Template description (optional) arguments: Extra arguments (optional) allow_override_args_in_task: Allow overriding arguments (optional) suppress_success_alerts: Suppress success alerts (optional) app: Application type (optional) git_branch: Git branch (optional) survey_vars: Survey variables (optional) vaults: Vault configurations (optional) template_type: Template type (optional) start_version: Start version (optional) build_template_id: Build template ID (optional) autorun: Enable autorun (optional) view_id: View ID (optional) task_params: App-specific task parameters (optional). For Ansible templates: - allow_override_limit: Allow task-level --limit override (required for run_task limit) - allow_override_inventory: Allow task-level inventory override - allow_override_tags: Allow task-level --tags override - allow_override_skip_tags: Allow task-level --skip-tags override - limit: Default limit (list of hosts/groups) - tags: Default tags (list) - skip_tags: Default skip tags (list) allow_parallel_tasks: Allow parallel tasks (optional) allow_override_branch_in_task: Allow overriding the git branch in task (optional) runner_tag: Runner tag (optional)
Fields not passed keep their current value.
Returns: Empty dict on success
Inputs: project_id (required), template_id (required), app, name, +20 more. Returns: object
update_viewC
Update an existing view.
Args: project_id: ID of the project view_id: ID of the view to update title: View title position: View ordering position
Returns: Empty dict on success
Inputs: view_id (required), project_id (required), title, position. Returns: object
validate_project_backupA
Validate a project backup before attempting restore.
Args: backup: Backup payload to inspect
Returns: Validation result, errors, warnings, and a summary.
Inputs: backup (required). Returns: object
validate_schedule_cron_formatC
Validate a cron expression for Semaphore schedules.
Args: project_id: ID of the project cron_format: Cron expression to validate
Returns: Empty dict on success
Inputs: project_id (required), cron_format (required). Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 69 tools
Most tools are clearly separated by resource (template, inventory, repository, environment, schedule, view, access key, project user), but there is notable overlap in the events/activity area: list_events, get_last_events, list_project_events, and summarize_project_activity all deal with event retrieval/analysis. Similarly, list_tasks, filter_tasks, get_latest_failed_task, and get_waiting_tasks have overlapping task-listing purposes, though their filters differ.
The vast majority of tools follow a consistent verb_noun pattern (list_templates, create_template, update_template, delete_template, get_template). Minor deviations exist: get_last_events is not a list_* verb, summarize_project_activity and bulk_analyze_failures use different verb styles, and stop_all_template_tasks is a compound noun phrase. Overall the pattern is strong and predictable.
69 tools is a very large surface for an MCP server. While SemaphoreUI is a broad product, the tool count is excessive and will likely overwhelm an agent's context and tool-selection process. Many tools are highly specialized (validate_schedule_cron_format, summarize_project_backup, get_project_role) and could be consolidated or removed.
The server covers CRUD for the main Semaphore resources (projects, templates, inventories, repositories, environments, schedules, views, access keys, project users) plus task execution, monitoring, failure analysis, and backup/restore. Minor gaps exist: there is no create/update for schedules' task_params in a structured way (though update_schedule exists), and there is no explicit 'get_schedule' for listing all schedules without a template (list_schedules exists but no get_schedule by ID is present—wait, get_schedule does exist). Actually, the surface is quite complete; the only notable gap is the lack of a direct 'get_all_schedules' vs 'list_schedules' distinction, and no tool for managing project-level API tokens or user management beyond project linking. Overall, the domain is well covered.
Maintenance
Related MCP Connectors
Plan Salesforce deploys, open pull requests and trigger pipelines from your AI client.
Direct access to Cypress tests results and accessibility reports in your AI workflow.
Connect AI assistants to GitHub - manage repos, issues, PRs, and workflows through natural language.
Connect AI agents to CloudBees Unify: feature flags, CI/CD, release orchestration, and security
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables comprehensive Ansible automation management through natural language, including playbook creation and execution, inventory management, role scaffolding, and project workflows. Supports both local inventories and full project lifecycle management with syntax validation and idempotency testing.30-
- AlicenseCqualityCmaintenanceEnables AI assistants to interact with Semaphore UI for managing Ansible, Terraform, and other automation workflows through project, task, template, and inventory management.371MIT
- FlicenseNot gradedqualityDmaintenanceEnables LLMs to discover and launch Ansible job templates on Ansible Automation Platform, monitor job status, and retrieve outputs.4-
- AlicenseBqualityDmaintenanceEnables AI assistants to manage Rundeck operations including jobs, executions, projects, nodes, system management, key storage, webhooks, and ACL policies via natural language.5050 npm1Apache 2.0