Install
$ agentstack add mcp-scoutqa-dot-ai-thor ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Thor
An event-driven AI team member that watches Slack and scheduled jobs, resumes OpenCode sessions through the runner, and reaches external systems through remote-cli.
Architecture
ingress -> gateway -> runner -> opencode -> codex-lb -> ChatGPT
\
-> remote-cli -> MCP upstreams / CLI integrations
gatewayaccepts Slack, GitHub webhook, and cron events, batches them, and forwards them to the runner.runnermanages OpenCode session continuity and Slack progress updates.remote-cliexposesPOST /exec/*endpoints for git, gh, sandbox, scoutqa, metabase, ldcli, aws, psql, MCP tool calls (Atlassian, Grafana, PostHog, Langfuse), direct Slack approval-card posting, and approval status/resolution.codex-lbis an OpenAI-compatible proxy that fronts ChatGPT for opencode, pooling one or more ChatGPT account credentials so no paid OpenAI API key is needed. Its account/quota dashboard sits behind the same SSO + admin-email gate as/admin/.
Services
| Service | Port | Package | Role | | ------------ | ---- | ------------------ | ------------------------------------------- | | codex-lb | 2455 | Docker image | ChatGPT-backed OpenAI-compatible proxy | | cron | - | docker/cron | Scheduled prompts | | mitmproxy | 3080 | docker/mitmproxy | Explicit outbound HTTP(S) proxy | | gateway | 3002 | @thor/gateway | Slack/GitHub webhook ingestion and batching | | remote-cli | 3004 | @thor/remote-cli | CLI + MCP policy gateway | | admin | 3005 | @thor/admin | Admin dashboard and workspace configuration | | ingress | 8080 | docker/ingress | Reverse proxy + Vouch integration | | opencode | 4096 | Docker image | Headless agent runtime | | runner | 3000 | @thor/runner | Session lifecycle + Slack progress updates | | vouch | 9090 | Docker image | OAuth/SSO proxy |
Quick Start
- Copy
.env.exampleto.envand fill in the required secrets. Per-integration env vars are documented in each integration's doc (see [Integrations](#integrations) below). - Initialize the mitmproxy CA on the host:
./scripts/mitmproxy-ca-init.sh
All outbound HTTP(S) from OpenCode is routed through mitmproxy; see [docs/feat/security-model.md](docs/feat/security-model.md) Layer 1a for the routing path, built-in defaults, and custom rule format.
- Create
/workspace/config/thor.json(on the host:docker-volumes/workspace/config/thor.json) from [docs/examples/thor.json](docs/examples/thor.json).
- Clone repos into the shared workspace:
docker compose run --rm remote-cli \
git clone https://github.com/your-org/your-repo.git
If the stack is already running, use docker compose exec remote-cli ... instead.
- Start the stack:
mkdir -p docker-volumes/codex-lb && chmod 777 docker-volumes/codex-lb
docker compose up --build -d
curl http://localhost:8080/global/health
codex-lb runs as a non-root user and writes a SQLite store to /var/lib/codex-lb; pre-creating the host directory world-writable avoids a root-owned auto-mount.
- Link a ChatGPT account so opencode has an upstream model:
Visit http://localhost:8080/dashboard (admin-gated by Vouch + THOR_ADMIN_EMAILS), sign in with Google, and add a ChatGPT account from the codex-lb dashboard. Once linked, opencode picks the model from its UI (the provider whitelist surfaces gpt-5.4, gpt-5.4-mini, gpt-5.5).
Integrations
Thor is an internal AI teammate for engineering and product work; it is not meant to mirror production infrastructure exactly. Each integration owns its own env vars, app/manifest setup, required permissions, and troubleshooting reasons.
- Slack — [
docs/slack.md](docs/slack.md). Events API intake, signing-secret verification, per-channel repo override, app manifest. - GitHub App — [
docs/github.md](docs/github.md). Webhook intake, App permissions and event subscriptions, installation IDs, bot commit identity, CI wake gate. - Daytona sandboxes — [
docs/daytona.md](docs/daytona.md). On-demand cloud sandboxes for project builds/tests/lints. Custom snapshot publishing. - Outbound HTTP(S) (mitmproxy) — [
docs/feat/security-model.md](docs/feat/security-model.md) Layer 1a. Routing path, built-in defaults (Atlassian/Slack/OpenAI), custom credential rules.
Runtime integration paths:
| Integration | Path | Auth | Notes | | ---------------- | -------------------------------------------------- | --------------------- | ------------------------------------------------------- | | Git / GitHub CLI | remote-cli /exec/git, /exec/gh | GitHub App token | Repo-scoped worktree edits | | Atlassian MCP | remote-cli /exec/mcp | Auth header | Read + approved writes | | PostHog MCP | remote-cli /exec/mcp | API key | Read + approved writes | | Grafana MCP | remote-cli /exec/mcp | Service account token | Logs and observability | | Langfuse MCP | remote-cli /exec/mcp | API key pair | Read-only LLM observability queries | | Slack Web API | gateway + remote-cli + OpenCode over mitmproxy | Bot token | Mentions, progress, approval cards, thread reads/writes | | LaunchDarkly | remote-cli /exec/ldcli | Access token | Read-only feature flag inspection | | Metabase | remote-cli /exec/metabase | API key | Read-only warehouse access | | Postgres (psql) | remote-cli /exec/psql | Per-profile DB creds | Read-only Postgres access by database alias |
Common usage patterns:
- PR merged, errors spike — a scheduled prompt checks telemetry, inspects recent merges through GitHub tools, prepares a fix in a worktree, and requests approval for the final write action.
- Jira issue triage — a webhook or Slack prompt asks Thor to investigate an issue; Thor reads Jira, checks recent commits, and reports likely owners and suspects.
- Daily delivery digest — a cron job asks Thor to summarize stale PRs, blocked issues, or failing tests and post the result to Slack.
Deployment Configuration
Integration-specific env vars live in each integration's doc. MCP integration credentials (Atlassian, PostHog, Grafana, Langfuse) support _ profile-suffixed overrides; multi-value integrations (Atlassian, Grafana, Langfuse) resolve all-or-nothing per scope — see [docs/feat/profile.md](docs/feat/profile.md). The psql passthrough's PSQL_DATABASES bundle is also profile-suffixed. Metabase uses the unsuffixed global METABASE_* values. Cross-cutting vars:
| Variable | Required | Service | Purpose | | ----------------------------------- | -------- | ------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | CRON_SECRET | Yes | gateway, cron | Shared secret for cron endpoint auth | | THOR_ADMIN_EMAILS | Yes | ingress | Comma-separated authenticated Google emails allowed for OpenCode-backed and /admin/ ingress routes | | THOR_INTERNAL_SECRET | Yes | remote-cli, gateway, admin, ingress | Secret-gates gateway↔remote-cli internal APIs and admin config writes; ingress injects it on /admin/ after Vouch, admin re-validates it | | THOR_E2E_TEST_HELPERS | No | runner | Enables secret-gated deterministic runner e2e helpers | | RUNNER_BASE_URL | Yes | remote-cli | Public base URL for Thor trigger viewer links in PR/Jira content | | INGRESS_PORT | No | ingress | Host port for the reverse proxy | | ATLASSIAN_AUTH | No | remote-cli, mitmproxy | Atlassian MCP auth header and mitmproxy default injection; required (with cloud ID) to enable Atlassian | | ATLASSIAN_CLOUD_ID | No | remote-cli | Atlassian cloud ID; required (with auth) to enable Atlassian; injected server-side into outbound MCP calls, hidden from model-facing tool schemas | | POSTHOG_API_KEY | No | remote-cli | PostHog MCP auth | | GRAFANA_URL | No | remote-cli | Grafana instance URL; required (with token + org ID) to enable Grafana | | GRAFANA_SERVICE_ACCOUNT_TOKEN | No | remote-cli | Grafana service account token; required (with URL + org ID) to enable Grafana | | GRAFANA_ORG_ID | No | remote-cli | Grafana org ID; required (with URL + token) to enable Grafana | | LANGFUSE_BASE_URL | No | remote-cli | Langfuse MCP base URL; all three LANGFUSE_* vars required to enable Langfuse | | LANGFUSE_PUBLIC_KEY | No | remote-cli | Langfuse MCP public key; required (with secret key + host) to enable Langfuse | | LANGFUSE_SECRET_KEY | No | remote-cli | Langfuse MCP secret key; required (with public key + host) to enable Langfuse | | METABASE_URL | No | remote-cli | Metabase instance URL | | METABASE_API_KEY | No | remote-cli | Metabase API key | | METABASE_DATABASE_ID | No | remote-cli | Metabase database ID | | METABASE_ALLOWED_SCHEMAS | No | remote-cli | Comma-separated schema allowlist | | SCOUT_API_KEY | No | remote-cli | Auth for the scoutqa CLI passthrough; the CLI auto-detects it from the environment | | AWS_ACCESS_KEY_ID | No | remote-cli | Credential for the aws CLI passthrough; omit to use an attached IAM role. Pair with AWS_SECRET_ACCESS_KEY (+ AWS_SESSION_TOKEN) | | AWS_SECRET_ACCESS_KEY | No | remote-cli | Secret for the aws CLI passthrough; required with AWS_ACCESS_KEY_ID | | AWS_SESSION_TOKEN | No | remote-cli | Session token for temporary aws CLI credentials | | AWS_REGION / AWS_DEFAULT_REGION | No | remote-cli | Default region for the aws CLI passthrough | | PSQL_DATABASES[_] | No | remote-cli | JSON bundle of Postgres connection targets keyed by database alias for the read-only psql passthrough; profile-suffixed override falls back to the global value. See [docs/feat/profile.md](docs/feat/profile.md) | | LD_ACCESS_TOKEN | No | remote-cli | LaunchDarkly API token for the read-only ldcli passthrough; required (with the other `
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: scoutqa-dot-ai
- Source: scoutqa-dot-ai/thor
- License: MIT
- Homepage: https://thor.scoutqa.cc
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.