{"id":35128968,"url":"https://github.com/samerfarida/mcp-ssh-orchestrator","last_synced_at":"2026-04-01T22:04:06.961Z","repository":{"id":320282170,"uuid":"1080676035","full_name":"samerfarida/mcp-ssh-orchestrator","owner":"samerfarida","description":"Secure SSH access for AI agents via MCP. Execute commands across your server fleet with policy enforcement, network controls, and comprehensive audit logging.","archived":false,"fork":false,"pushed_at":"2026-03-02T15:06:13.000Z","size":15872,"stargazers_count":20,"open_issues_count":7,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-03-28T01:33:01.708Z","etag":null,"topics":["ai-agents","automation","claude","cursor","docker","mcp","mcp-server","network-control","python","security-policy","server-management","ssh"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/samerfarida.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"docs/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-10-21T17:52:21.000Z","updated_at":"2026-03-24T13:33:10.000Z","dependencies_parsed_at":"2025-10-31T06:15:06.461Z","dependency_job_id":null,"html_url":"https://github.com/samerfarida/mcp-ssh-orchestrator","commit_stats":null,"previous_names":["samerfarida/mcp-ssh-orchestrator"],"tags_count":23,"template":false,"template_full_name":null,"purl":"pkg:github/samerfarida/mcp-ssh-orchestrator","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samerfarida%2Fmcp-ssh-orchestrator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samerfarida%2Fmcp-ssh-orchestrator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samerfarida%2Fmcp-ssh-orchestrator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samerfarida%2Fmcp-ssh-orchestrator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/samerfarida","download_url":"https://codeload.github.com/samerfarida/mcp-ssh-orchestrator/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samerfarida%2Fmcp-ssh-orchestrator/sbom","scorecard":{"id":1239369,"data":{"date":"2025-10-31T05:30:51Z","repo":{"name":"github.com/samerfarida/mcp-ssh-orchestrator","commit":"f097f63a61d23a848994ac6cbfe652c7e0293586"},"scorecard":{"version":"v5.1.1","commit":"cd152cb6742c5b8f2f3d2b5193b41d9c50905198"},"score":6.2,"checks":[{"name":"Dependency-Update-Tool","score":10,"reason":"update tool detected","details":["Info: detected update tool: Dependabot: .github/dependabot.yml:1"],"documentation":{"short":"Determines if the project uses a dependency update tool.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#dependency-update-tool"}},{"name":"Token-Permissions","score":6,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'contents' permission set to 'read': .github/workflows/build.yml:32","Info: jobLevel 'contents' permission set to 'read': .github/workflows/build.yml:61","Info: jobLevel 'contents' permission set to 'read': .github/workflows/build.yml:96","Info: jobLevel 'packages' permission set to 'read': .github/workflows/build.yml:97","Info: jobLevel 'packages' permission set to 'read': .github/workflows/codeql.yml:20","Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql.yml:23","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql.yml:24","Info: jobLevel 'contents' permission set to 'read': .github/workflows/labeler.yml:16","Info: jobLevel 'contents' permission set to 'read': .github/workflows/lint-docs.yml:22","Info: jobLevel 'contents' permission set to 'read': .github/workflows/lint.yml:26","Info: jobLevel 'contents' permission set to 'read': .github/workflows/lint.yml:46","Info: jobLevel 'contents' permission set to 'read': .github/workflows/lint.yml:66","Info: jobLevel 'contents' permission set to 'read': .github/workflows/release.yml:17","Info: jobLevel 'checks' permission set to 'read': .github/workflows/release.yml:18","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:35","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/sync-wiki.yml:15","Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/codeql.yml:1","Warn: no topLevel permission defined: .github/workflows/labeler.yml:1","Warn: no topLevel permission defined: .github/workflows/lint-docs.yml:1","Warn: no topLevel permission defined: .github/workflows/lint.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Info: topLevel permissions set to 'read-all': .github/workflows/scorecards.yml:18","Warn: no topLevel permission defined: .github/workflows/sync-wiki.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#binary-artifacts"}},{"name":"Code-Review","score":0,"reason":"Found 0/28 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"project was created in last 90 days. please review its contents carefully","details":["Warn: Repository was created in last 90 days."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#maintained"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: SECURITY.md:1","Info: Found linked content: SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: SECURITY.md:1","Info: Found text in security policy: SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#security-policy"}},{"name":"Pinned-Dependencies","score":1,"reason":"dependency not pinned by hash detected -- score normalized to 1","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:67: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:70: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:84: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:99: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:102: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/build.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/build.yml:105: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/build.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/codeql.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/codeql.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/codeql.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/codeql.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/labeler.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/labeler.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint-docs.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/lint-docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint-docs.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/lint-docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/lint.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/lint.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:48: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/lint.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/lint.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:68: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/lint.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/lint.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:57: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:67: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/release.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:89: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/release.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/scorecards.yml:76: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/scorecards.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/sync-wiki.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/samerfarida/mcp-ssh-orchestrator/sync-wiki.yml/main?enable=pin","Warn: pipCommand not pinned by hash: Dockerfile:21-23","Warn: pipCommand not pinned by hash: Dockerfile:21-23","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:43","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:44","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:76","Warn: pipCommand not pinned by hash: .github/workflows/build.yml:77","Warn: npmCommand not pinned by hash: .github/workflows/lint-docs.yml:33","Warn: pipCommand not pinned by hash: .github/workflows/lint.yml:37","Warn: pipCommand not pinned by hash: .github/workflows/lint.yml:57","Warn: pipCommand not pinned by hash: .github/workflows/lint.yml:77","Info:   2 out of  23 GitHub-owned GitHubAction dependencies pinned","Info:   1 out of  10 third-party GitHubAction dependencies pinned","Info:   1 out of   1 containerImage dependencies pinned","Info:   1 out of  10 pipCommand dependencies pinned","Info:   0 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#cii-best-practices"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-7f5h-v6xp-fcq8"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#vulnerabilities"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/build.yml:91"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#packaging"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#fuzzing"}},{"name":"Branch-Protection","score":4,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Warn: 'branch protection settings apply to administrators' is disabled on branch 'main'","Warn: 'stale review dismissal' is disabled on branch 'main'","Warn: required approving review count is 1 on branch 'main'","Warn: codeowners review is not required on branch 'main'","Warn: 'last push approval' is disabled on branch 'main'","Warn: 'up-to-date branches' is disabled on branch 'main'","Info: status check found to merge onto on branch 'main'","Info: PRs are required in order to make changes on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#branch-protection"}},{"name":"SAST","score":10,"reason":"SAST tool is run on all commits","details":["Info: SAST configuration detected: CodeQL","Info: all commits (2) are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#sast"}},{"name":"CI-Tests","score":10,"reason":"2 out of 2 merged PRs checked by a CI test -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project runs tests before pull requests are merged.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#ci-tests"}},{"name":"License","score":9,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Warn: project license file does not contain an FSF or OSI license."],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#license"}},{"name":"Contributors","score":3,"reason":"project has 1 contributing companies or organizations -- score normalized to 3","details":["Info: found contributions from: pwc"],"documentation":{"short":"Determines if the project has a set of contributors from multiple organizations (e.g., companies).","url":"https://github.com/ossf/scorecard/blob/cd152cb6742c5b8f2f3d2b5193b41d9c50905198/docs/checks.md#contributors"}}]},"last_synced_at":"2025-10-31T06:25:52.898Z","repository_id":320282170,"created_at":"2025-10-31T06:25:52.899Z","updated_at":"2025-10-31T06:25:52.899Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31292631,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T21:15:39.731Z","status":"ssl_error","status_checked_at":"2026-04-01T21:15:34.046Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ai-agents","automation","claude","cursor","docker","mcp","mcp-server","network-control","python","security-policy","server-management","ssh"],"created_at":"2025-12-28T04:27:33.406Z","updated_at":"2026-04-01T22:04:06.950Z","avatar_url":"https://github.com/samerfarida.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003ch1\u003eMCP SSH Orchestrator\u003c/h1\u003e\n  \u003cimg src=\"assets/logo/logo-v1.png\" alt=\"MCP SSH Orchestrator Logo\" width=\"200\" height=\"200\"\u003e\n  \u003ch1\u003eZero-Trust SSH Orchestration for AI Assistants\u003c/h1\u003e\n  \u003cp\u003e\u003cstrong\u003eEnforce declarative policy-as-code and audited access for Claude Desktop, Cursor, and any MCP-aware client.\u003c/strong\u003e\u003c/p\u003e\n  \u003cp\u003eLaunch in minutes with Docker + MCP tooling, deny-by-default controls, and hardened SSH key management.\u003c/p\u003e\n\u003c/div\u003e\n\n[![License](https://img.shields.io/badge/License-Apache%202.0-A020F0)](LICENSE)\n[![MCP](https://img.shields.io/badge/MCP-v1.21.1-7393B3)](https://modelcontextprotocol.io)\n[![Python](https://img.shields.io/badge/Python-v3.13+-blue.svg)](https://python.org)\n[![Docker](https://img.shields.io/badge/Docker-Ready-success)](https://github.com/samerfarida/mcp-ssh-orchestrator)\n[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/samerfarida/mcp-ssh-orchestrator/badge)](https://scorecard.dev/viewer/?uri=github.com/samerfarida/mcp-ssh-orchestrator)\n[![GitHub release](https://img.shields.io/github/v/release/samerfarida/mcp-ssh-orchestrator)](https://github.com/samerfarida/mcp-ssh-orchestrator/releases)\n[![GitHub stars](https://img.shields.io/github/stars/samerfarida/mcp-ssh-orchestrator)](https://github.com/samerfarida/mcp-ssh-orchestrator/stargazers)\n[![GitHub forks](https://img.shields.io/github/forks/samerfarida/mcp-ssh-orchestrator)](https://github.com/samerfarida/mcp-ssh-orchestrator/network/members)\n[![GitHub issues](https://img.shields.io/github/issues/samerfarida/mcp-ssh-orchestrator)](https://github.com/samerfarida/mcp-ssh-orchestrator/issues)\n[![GitHub pull-requests](https://img.shields.io/github/issues-pr/samerfarida/mcp-ssh-orchestrator)](https://github.com/samerfarida/mcp-ssh-orchestrator/pulls)\n[![GitHub contributors](https://img.shields.io/github/contributors/samerfarida/mcp-ssh-orchestrator)](https://github.com/samerfarida/mcp-ssh-orchestrator/graphs/contributors)\n[![GitHub last commit](https://img.shields.io/github/last-commit/samerfarida/mcp-ssh-orchestrator)](https://github.com/samerfarida/mcp-ssh-orchestrator/commits/main)\n[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/samerfarida/mcp-ssh-orchestrator/build.yml?branch=main\u0026label=Build)](https://github.com/samerfarida/mcp-ssh-orchestrator/actions)\n[![CodeQL Analysis](https://github.com/samerfarida/mcp-ssh-orchestrator/actions/workflows/codeql.yml/badge.svg)](https://github.com/samerfarida/mcp-ssh-orchestrator/actions/workflows/codeql.yml)\n\n---\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"assets/demo.gif\" alt=\"MCP SSH Orchestrator Demo\"\u003e\n\u003c/div\u003e\n\n## What Problem Does This Solve?\n\n**Imagine this:** Your AI assistant (Claude, ChatGPT, etc.) can access your servers, but you're terrified of what it might do. `rm -rf /`? Delete your databases? Change firewall rules?\n\n**Now imagine this:** Your AI has governed, auditable access to your infrastructure. It can check logs, restart services, and manage your fleet, **but only if your security policies allow it.**\n\nThat's exactly what MCP SSH Orchestrator provides: **the power of AI-driven server management with deny-by-default access control, IP allowlists, host key verification, and comprehensive audit logging backed by declarative YAML policy-as-code (`config/servers.yml`, `config/credentials.yml`, `config/policy.yml`)**.\n\n## Why This Matters\n\n### Zero-Trust Security Model\n\n- **Deny-by-default**: Nothing runs unless explicitly allowed\n- **Network controls**: IP allowlists prevent lateral movement\n- **Command whitelisting**: Only approved commands can execute\n- **Declarative policy-as-code**: Versioned YAML files define hosts, credentials, and allowed commands\n- **Comprehensive audit trails**: Every action is logged in JSON\n\n### Prevents Common Attack Vectors\n\n- **Dangerous commands blocked**: `rm -rf`, `dd`, file deletions\n- **Network isolation**: Servers can't access external internet\n- **No privilege escalation**: Runs as non-root in containers\n- **Resource limits**: CPU and memory caps prevent DOS\n\n### Production-Ready Audit \u0026 Security\n\n- **OWASP LLM Top 10 protected**: Mitigates LLM07 (Insecure Plugin Design), LLM08 (Excessive Agency), LLM01 (Prompt Injection)\n- **MITRE ATT\u0026CK aligned**: Prevents T1071 (Application Layer Protocol), T1659 (Content Injection)\n- **Structured JSON audit logs**: Complete audit trail with timestamps, hashes, and IPs\n- **Forensics ready**: Command hashing, IP tracking, detailed metadata\n- **Real-time monitoring**: Progress logs for long-running tasks\n\n## Who Is This For?\n\n### Homelab Enthusiasts\n\n- Automate routine server maintenance with AI\n- Safely manage Proxmox, TrueNAS, Docker hosts\n- Get help troubleshooting without losing SSH security\n\n### Security Engineers\n\n- Audit and control AI access to infrastructure\n- Implement zero-trust principles with declarative policy-as-code configs\n- Meet compliance requirements with structured logging\n\n### DevOps Teams\n\n- Let AI handle routine tasks: log checks, service restarts, updates\n- Manage fleets of servers through conversational interface\n- Reduce manual toil while maintaining security standards\n\n### Platform Engineers\n\n- Enable AI-powered infrastructure management\n- Provide secure self-service access to developers\n- Bridge the gap between AI and infrastructure securely\n\n## Real-World Use Cases\n\n### Scenario 1: Homelab Automation (Homelab Enthusiasts)\n\n**You say:** *\"Claude, my Proxmox host is running slow. Can you check disk usage and memory on all my VMs?\"*\n\n### What happens\n\n- Policy allows `df -h` and `free -m` on Proxmox hosts\n- Network check: Private IP allowlist permits access\n- Tag-based execution checks all hosts tagged `proxmox`\n- Commands execute safely with no destructive operations\n- Complete audit trail stored in JSON logs\n\n### Scenario 2: Incident Response (DevOps Teams)\n\n**You say:** *\"We're seeing 500 errors. Check nginx logs across all production web servers and show me the last 100 error lines.\"*\n\n### What happens\n\n- Tag-based execution: `tail -n 100 /var/log/nginx/error.log` runs on all `web-prod` servers\n- Network isolation enforced: No external API calls or egress allowed\n- Real-time progress logs stream via MCP context events\n- Structured output aggregates results for quick triage\n- Full audit trail with timestamps for post-incident review\n\n### Scenario 3: Fleet-Wide Maintenance (Platform Engineers)\n\n**You say:** *\"Update system packages on all staging servers, but show me what would change first before running the upgrade.\"*\n\n### What happens\n\n- Use `ssh_plan` to preview `apt list --upgradable` across `staging` tagged hosts\n- Review dry-run output to see pending updates\n- Policy validates `apt update \u0026\u0026 apt upgrade -y` is allowed on staging\n- Tag-based execution runs upgrade on all staging servers in parallel\n- Audit logs track which servers were updated and when\n\n## Quick Start\n\n### 1. Prepare local configuration (one-time)\n\n```bash\n# Optional: bootstrap everything with the compose helper script\n# (runs from the repo root or from your target config directory)\n./compose/setup.sh enduser\n\n# Or download it separately\ncurl -fsSLO https://raw.githubusercontent.com/samerfarida/mcp-ssh-orchestrator/main/compose/setup.sh\nchmod +x setup.sh\n./setup.sh enduser\n```\n\nIf you prefer to lay things out manually, follow the steps below.\n\n```bash\n# Pull the latest release\ndocker pull ghcr.io/samerfarida/mcp-ssh-orchestrator:latest\n\n# Create directories for config, keys, and secrets\nmkdir -p ~/mcp-ssh/{config,keys,secrets}\n\n# Copy example configs to get started quickly\ncp examples/example-servers.yml ~/mcp-ssh/config/servers.yml\ncp examples/example-credentials.yml ~/mcp-ssh/config/credentials.yml\ncp examples/example-policy.yml ~/mcp-ssh/config/policy.yml\n\n# Add your SSH key (replace with your private key file)\ncp ~/.ssh/id_ed25519 ~/mcp-ssh/keys/\nchmod 0400 ~/mcp-ssh/keys/id_ed25519\n\n# (Optional) Pin trusted hosts and prepare secret files\ncp ~/.ssh/known_hosts ~/mcp-ssh/keys/known_hosts\n\n# Option 1: Individual secret files (Docker secrets compatible)\ncat \u003e ~/mcp-ssh/secrets/prod_db_password.txt \u003c\u003c'EOF'\nCHANGE-ME\nEOF\nchmod 600 ~/mcp-ssh/secrets/prod_db_password.txt\n\n# Option 2: Consolidated .env file (recommended for easier management)\ncat \u003e ~/mcp-ssh/secrets/.env \u003c\u003c'EOF'\n# SSH Passwords\nprod_db_password=CHANGE-ME\nlab_password=CHANGE-ME-TOO\n\n# SSH Key Passphrases\nprod_key_passphrase=CHANGE-ME-PASSPHRASE\nEOF\nchmod 600 ~/mcp-ssh/secrets/.env\n# Note: .env file supports KEY=value format, comments, and quoted values\n# See docs/wiki/06.2-credentials.yml.md for details\n```\n\n### 2. Launch the orchestrator container\n\n```bash\ndocker run -d --name mcp-ssh-orchestrator \\\n  -v ~/mcp-ssh/config:/app/config:ro \\\n  -v ~/mcp-ssh/keys:/app/keys:ro \\\n  -v ~/mcp-ssh/secrets:/app/secrets:ro \\\n  ghcr.io/samerfarida/mcp-ssh-orchestrator:latest\n```\n\nRestart later with `docker start mcp-ssh-orchestrator`. Prefer disposable containers? Use `docker run -i --rm ...` instead.\n\n### 3. Connect your MCP client\n\n- **Cursor:** Add to `~/.cursor/mcp.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"mcp-ssh-orchestrator\": {\n      \"command\": \"docker\",\n      \"args\": [\"start\", \"-a\", \"mcp-ssh-orchestrator\"],\n      \"env\": {\"PYTHONUNBUFFERED\": \"1\"}\n    }\n  }\n}\n```\n\n- **Claude Desktop (macOS):** Update `~/Library/Application Support/Claude/claude_desktop_config.json`\n\n```json\n{\n  \"mcpServers\": {\n    \"ssh-orchestrator\": {\n      \"command\": \"docker\",\n      \"args\": [\n        \"run\", \"-i\", \"--rm\",\n        \"-v\", \"/Users/YOUR_USERNAME/mcp-ssh/config:/app/config:ro\",\n        \"-v\", \"/Users/YOUR_USERNAME/mcp-ssh/keys:/app/keys:ro\",\n        \"-v\", \"/Users/YOUR_USERNAME/mcp-ssh/secrets:/app/secrets:ro\",\n        \"ghcr.io/samerfarida/mcp-ssh-orchestrator:latest\"\n      ]\n    }\n  }\n}\n```\n\n(Windows path: `%APPDATA%\\\\Claude\\\\claude_desktop_config.json`.)\n\nMore examples (Docker Desktop, multi-environment, SDK usage) live in the [Integrations guide](docs/wiki/10-Integrations.md).\n\n### 4. Test the connection\n\n```bash\n# List configured hosts through the MCP server\necho '{\"jsonrpc\":\"2.0\",\"method\":\"tools/call\",\"params\":{\"name\":\"ssh_list_hosts\",\"arguments\":{}},\"id\":1}' | \\\n  docker run -i --rm \\\n    -v ~/mcp-ssh/config:/app/config:ro \\\n    -v ~/mcp-ssh/keys:/app/keys:ro \\\n    -v ~/mcp-ssh/secrets:/app/secrets:ro \\\n    ghcr.io/samerfarida/mcp-ssh-orchestrator:latest\n```\n\nCursor/Claude should now show the orchestrator as connected. Jump to the [Usage Cookbook](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/08-Usage-Cookbook) for guided scenarios.\n\n## How Security Works (The Technical Details)\n\n**Policy-as-code workflow:** `config/servers.yml`, `config/credentials.yml`, and `config/policy.yml` are parsed on startup, enforced during every `ssh_*` tool invocation, and mirrored in the structured audit logs so the same declarative files you review in Git gate what your AI can execute.\n\n### Defense-in-Depth Architecture\n\n```mermaid\ngraph TB\n    subgraph \"Layer 1: Transport Security\"\n        L1A[stdio Communication]\n        L1B[Container Isolation]\n    end\n    subgraph \"Layer 2: Network Security\"\n        L2A[IP Allowlists]\n        L2B[Host Key Verification]\n    end\n    subgraph \"Layer 3: Policy Security\"\n        L3A[Deny-by-Default]\n        L3B[Pattern Matching]\n    end\n    subgraph \"Layer 4: Application Security\"\n        L4A[Non-Root Execution]\n        L4B[Resource Limits]\n    end\n\n    L1A --\u003e L2A\n    L1B --\u003e L2B\n    L2A --\u003e L3A\n    L2B --\u003e L3B\n    L3A --\u003e L4A\n    L3B --\u003e L4B\n\n    style L1A fill:#e1f5ff\n    style L1B fill:#e1f5ff\n    style L2A fill:#d4edda\n    style L2B fill:#d4edda\n    style L3A fill:#fff3cd\n    style L3B fill:#fff3cd\n    style L4A fill:#f8d7da\n    style L4B fill:#f8d7da\n```\n\n### What Gets Blocked\n\n```yaml\n# Dangerous commands automatically denied\ndeny_substrings:\n# Destructive operations\n  - \"rm -rf /\"\n  - \":(){ :|:\u0026 };:\"\n  - \"mkfs \"\n  - \"dd if=/dev/zero\"\n  - \"shutdown -h\"\n  - \"reboot\"\n  - \"userdel \"\n  - \"passwd \"\n# Lateral movement / egress tools\n  - \"ssh \"\n  - \"scp \"\n  - \"rsync -e ssh\"\n  - \"curl \"\n  - \"wget \"\n  - \"nc \"\n  - \"nmap \"\n  - \"telnet \"\n  - \"kubectl \"\n  - \"aws \"\n  - \"gcloud \"\n  - \"az \"\n\n# Network isolation enforced\nnetwork:\n  allow_cidrs:\n    - \"10.0.0.0/8\"      # Only private IPs\n    - \"192.168.0.0/16\"\n  block_ips: []         # Explicit IP blocks (if needed)\n\n```\n\n### What Gets Allowed (Examples)\n\n```yaml\n# Safe, read-only commands (using simple_binaries)\nrules:\n  - action: \"allow\"\n    aliases:\n      - \"*\"\n    tags:\n      - \"observability\"\n    simple_binaries:\n      - uptime\n      - whoami\n      - hostname\n    simple_max_args: 6\n\n# Disk and memory inspection (using structured rules)\n  - action: \"allow\"\n    aliases:\n      - \"*\"\n    tags:\n      - \"observability\"\n    binary: \"df\"\n    arg_prefix: [\"-h\"]\n    allow_extra_args: false\n\n  - action: \"allow\"\n    aliases:\n      - \"*\"\n    tags:\n      - \"observability\"\n    binary: \"free\"\n    arg_prefix: [\"-m\"]\n    allow_extra_args: false\n\n# Log inspection (using structured rules with path restrictions)\n  - action: \"allow\"\n    aliases:\n      - \"*\"\n    tags:\n      - \"observability\"\n    binary: \"tail\"\n    arg_prefix: [\"-n\", \"200\"]\n    allow_extra_args: false\n    path_args:\n      indices: [3]\n      patterns:\n        - \"/var/log/*\"\n\n# Service management (controlled)\n  - action: \"allow\"\n    aliases:\n      - \"web-*\"\n      - \"db-*\"\n    tags:\n      - \"production\"\n      - \"critical-service\"\n    binary: \"systemctl\"\n    arg_prefix: [\"restart\", \"nginx\"]\n    allow_extra_args: false\n\n  - action: \"allow\"\n    aliases:\n      - \"web-*\"\n      - \"db-*\"\n    tags:\n      - \"production\"\n      - \"critical-service\"\n    binary: \"systemctl\"\n    arg_prefix: [\"status\"]\n    allow_extra_args: true\n```\n\n### Protection Against Real Threats\n\nMCP SSH Orchestrator directly addresses documented vulnerabilities in the MCP ecosystem:\n\n- **CVE-2025-49596**: Localhost-exposed MCP services → Mitigated with stdio-only transport\n- **CVE-2025-6514**: Command injection in MCP servers → Mitigated with policy-based validation\n- **43% of MCP servers** have command injection flaws → Zero-trust security model\n\n**[Full Security Model Documentation](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/05-Security-Model)** | **[Security Risks Analysis](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/02-Risks)**\n\n## Documentation\n\n### [Complete Documentation Wiki](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki)\n\n| Section | What You'll Learn |\n|---------|-------------------|\n| **[Quick Start \u0026 Examples](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/08-Usage-Cookbook)** | Practical examples and common workflows |\n| **[Architecture](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/04-Architecture)** | How it works under the hood |\n| **[Security Model](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/05-Security-Model)** | Zero-trust design and controls |\n| **[Configuration](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/06-Configuration)** | Setting up hosts, credentials, policies |\n| **[Observability \u0026 Audit](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/11-Observability-Audit)** | Logging, monitoring, compliance |\n| **[Deployment](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/09-Deployment)** | Production setup guide |\n\n## Supply Chain Integrity\n\n**Signed release artifacts**: Every tarball/zip in GitHub Releases ships with a detached GPG signature produced by the maintainer key (`openpgp4fpr:6775BF3F439A2A8A198DE10D4FC5342A979BD358`). Import the key and verify before unpacking:\n\n```bash\ngpg --receive-keys 4FC5342A979BD358\ngpg --verify mcp-ssh-orchestrator-v1.0.0.tar.gz.asc mcp-ssh-orchestrator-v1.0.0.tar.gz\n```\n\n**Cosign-signed container images**: The images under `ghcr.io/samerfarida/mcp-ssh-orchestrator` are signed via Sigstore keyless signing in the release workflow. Verify the signature (and optional attestations) before deploying:\n\n```bash\nCOSIGN_EXPERIMENTAL=1 cosign verify \\\n  --certificate-identity-regexp \"https://github.com/samerfarida/mcp-ssh-orchestrator/.github/workflows/release.yml@.*\" \\\n  --certificate-oidc-issuer https://token.actions.githubusercontent.com \\\n  ghcr.io/samerfarida/mcp-ssh-orchestrator:latest\n```\n\nImage digests and signatures are published with every tag in GitHub Packages so you can pin exact references when promoting builds between environments ([package feed](https://github.com/samerfarida/mcp-ssh-orchestrator/pkgs/container/mcp-ssh-orchestrator/versions)).\n\n**OpenSSF Scorecard**: The repository maintains an automated Scorecard run to track security posture across dependencies, build settings, branch protections, and more ([scorecard summary](https://api.scorecard.dev/projects/github.com/samerfarida/mcp-ssh-orchestrator)).\n\n## What Can AI Do With This? (MCP Tools)\n\nYour AI assistant gets 13 powerful tools with built-in security:\n\n### Discovery \u0026 Planning\n\n- `ssh_list_hosts` - See all available servers\n- `ssh_describe_host` - Get host details and tags\n- `ssh_plan` - **Test commands before running** (dry-run mode)\n\n### Execution\n\n- `ssh_run` - Execute single command on one server\n- `ssh_run_on_tag` - Run command on multiple servers (e.g., all \"web\" servers)\n- `ssh_run_async` - Start long-running tasks in background\n\n### Monitoring \u0026 Control\n\n- `ssh_get_task_status` - Check progress of async tasks\n- `ssh_get_task_output` - Stream output in real-time\n- `ssh_get_task_result` - Get final result when done\n- `ssh_cancel` - Stop a running synchronous task safely\n- `ssh_cancel_async_task` - Stop a running async task safely\n\n### Management\n\n- `ssh_reload_config` - Update hosts/credentials without restart\n- `ssh_ping` - Verify connectivity to a host\n\n### MCP Resources + Context\n\n- `ssh://hosts` – discover sanitized host inventory (alias, tags, description, credential presence)\n- `ssh://host/{alias}` – inspect a single host without exposing credentials\n- `ssh://host/{alias}/tags` – fetch tag-only view for planning tag executions\n- `ssh://host/{alias}/capabilities` – derived policy summary, limits, and sample command allowances per host\n\n**Context-aware logging:** Streams lightweight `ctx.debug` / `ctx.info` events (task start, completion, cancellations) in supported clients for `ssh_run`, `ssh_run_on_tag`, config reloads, and async task polling—all without exposing raw commands or secrets.\n\n**LLM-friendly hints:** Policy/network denials (and `ssh_plan` previews) include helpful hints so assistants automatically retry with `ssh_plan`, consult the orchestrator prompts, **or ask whether a policy/network update is appropriate** instead of looping on blocked commands.\n\n### [Complete Tools Reference with Examples](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/07-Tools-Reference)\n\n## Learn More\n\n### Key Differentiators\n\n- **Production-Ready Security**: OpenSSF Scorecard 7.5+ score\n- **Zero-Trust Architecture**: Deny-by-default, allow-by-exception\n- **OWASP LLM Top 10 Protected**: Mitigates insecure plugin design, excessive agency, prompt injection\n- **MITRE ATT\u0026CK Aligned**: Prevents content injection and unauthorized protocol usage\n- **Security-Focused**: Built on security-first principles against real CVEs (CVE-2025-49596, CVE-2025-6514)\n- **Easy Integration**: Works with Claude, ChatGPT, and any MCP client\n- **Open Source**: Apache 2.0 licensed, community-driven\n\n### What Users Are Saying\n\n\u003e *\"Finally, I can let Claude manage my Proxmox cluster without fear!\"* - Homelab Admin\n\u003e\n\u003e *\"This is what infrastructure-as-code should have been. Declarative security for AI access.\"* - Platform Engineer\n\u003e\n\u003e *\"The structured audit logs make incident response so much easier.\"* - Security Engineer\n\u003e\n## Contributing\n\nWe welcome contributions! See our [Contributing Guide](https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/13-Contributing) for:\n\n- Development setup\n- Code of conduct\n- How to submit PRs\n- Architecture decisions\n\n## License\n\nApache 2.0 - See [LICENSE](LICENSE) for details.\n\n## Links\n\n- **[GitHub Repository](https://github.com/samerfarida/mcp-ssh-orchestrator)** - Star us on GitHub!\n- **[Issue Tracker](https://github.com/samerfarida/mcp-ssh-orchestrator/issues)** - Report bugs or request features\n- **[CHANGELOG](CHANGELOG.md)** - Version history and release notes\n- **[MCP Specification](https://modelcontextprotocol.io)** - Learn about MCP\n- **[Docker MCP Security Guide](https://www.docker.com/blog/mcp-security-explained/)** - Security best practices\n\n---\n\n\u003cdiv align=\"center\"\u003e\n  \u003ch3\u003eReady to give AI secure server access?\u003c/h3\u003e\n  \u003cp\u003eStart with \u003ca href=\"https://github.com/samerfarida/mcp-ssh-orchestrator/wiki/08-Usage-Cookbook\"\u003eour Usage Cookbook\u003c/a\u003e →\u003c/p\u003e\n\u003c/div\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamerfarida%2Fmcp-ssh-orchestrator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamerfarida%2Fmcp-ssh-orchestrator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamerfarida%2Fmcp-ssh-orchestrator/lists"}