Most HR platforms force a trade-off: SaaS products take your data and limit customization, while open-source options lack native AI integration. MintHCM targets organizations that want both full data ownership and AI-agent-driven HR processes without vendor lock-in.
What This Does
MintHCM is an open-source HCM platform built around AI agent integration. The api/ directory (4,134 files) contains the PHP backend handling auth, modules, and OAuth2. The mcp/ directory (927 files) implements the Model Context Protocol layer for AI agent connectivity, and vue/ (724 files) holds the frontend. A legacy/ directory (34,590 files) carries the original PHP codebase, so this is a mature project with substantial history.
Core HR functions—recruitment, onboarding, leave management, performance tracking—are implemented as modules under api/app/Controllers/, including RecruitmentController, LeaveController, and PerformanceController.
How It Is Wired
Execution starts at docker/docker-compose.yml, which orchestrates the stack. The API entry point is api/app/ApiManager.php, routing requests through api/app/Controllers/. The AuthController and OAuth2/ directory handle authentication, with FrontendGrant.php and MobileGrant.php managing token issuance.
The McpController.php is the critical hub—it exposes HR data and processes to external AI agents via MCP. This is where the "AI-native" claim materializes: agents authenticate, query employee data, and trigger workflows through this single controller. Everything routes through ApiManager.php first, so that file carries the widest blast radius—any change there affects all 4,000+ API files.
The dependency graph shows a cycle between api/app/Controllers/ and api/app/Entities/—entities are referenced by controllers and vice versa. Changing entity structures will ripple through controllers, requiring coordinated updates.
How To Use It
Setup: The docker/ directory provides the fastest path:
git clone https://github.com/moses-y/minthcm
cd minthcm
docker compose -f docker/docker-compose.yml up -d
Configuration: Environment variables live in docker/.env (flagged as containing secret-shaped paths—verify before production). Database credentials and OAuth keys go there.
Running it: The Docker compose file handles everything. For development, kanban/package.json implies npm scripts for the frontend, and api/composer.json handles PHP dependencies.
Real-World Use
A recruitment team deploys MintHCM on-premises. An AI agent connects via MCP to McpController.php, queries open positions, screens candidates from the Candidate entity, and updates application statuses—all without exposing the underlying database. The agent orchestrates interview scheduling and sends offers through the same API layer, and HR retains full control over data and infrastructure.
Code Health & Issues
Static analysis found one issue:
Low/Security - Secret-shaped paths present in docker/.env—verify whether actual credentials are committed or just placeholders.
Other observations from structure:
Med - 26,677 PHP files in legacy/ suggest significant technical debt; migrating to the newer api/ structure will be substantial.
Low - 934 test files exist, but no CI workflow beyond .github/workflows/main.yml—test coverage for the MCP layer is unclear.
Low - No license file detected at root, despite README claiming AGPL v3—confirm before production use.
The Bottom Line
MintHCM offers genuine AI-agent integration with real deployment flexibility, and the MCP architecture is a legitimate differentiator. The codebase is large and carries legacy weight, so plan for migration effort. It suits organizations that need AI-driven HR with full data control and have engineering resources to manage the complexity.
Ranked by severity × confidence × production reach. Reach is the honest discriminator across a collection that is mostly other people's code: the same finding matters more in something that ships.
high4
medium7
low1
Pin third-party GitHub Actions to a commit SHAhigh7 occurrences
A tag can be moved, so the action running with your token and secrets is whatever its owner last pushed; this is how tj-actions/changed-files leaked secrets from thousands of repos.
Fix: Replace each @vN with the 40-character commit SHA, keep # vN as a comment, and let Dependabot bump the SHAs.
Remove the committed .env and rotate what it holdshigh
docker/.env
docker/.env
A tracked .env is the most common route for a working key to reach a public clone, and it is the file the app actually loads, so the value is usually live.
Fix: git rm --cached the file, add it to .gitignore, rotate every credential it names, commit a .env.example with empty values.
Make CI invoke the test suite it hashigh27 occurrences
.github/workflows
27 test files, no test command in any workflow
A green check that never executed an assertion is worse than no check, because reviewers trust it.
Fix: Add a test step to the existing workflow rather than a new workflow.
Remove the committed database dumphigh
legacy/install/demo_data/dashboardbackups.sql
legacy/install/demo_data/dashboardbackups.sql
A dump is the one artefact that leaks other people's data rather than the owner's, which turns a hygiene problem into a notification obligation.
Fix: Remove and purge from history; if it held personal data, assess it as a disclosure.
Declare least-privilege permissions for GITHUB_TOKENmedium
.github/workflows/main.yml
1 workflow(s) declare no permissions, 1 of them reference secrets
With no declaration the token inherits the repository default, so any injected step can push commits or mint releases from inside your own CI.
Fix: Add permissions: contents: read at the top of the workflow and widen per job only where needed.
Enable Dependabot or Renovatemedium
9 manifest(s), no update bot configured
Without a bot a published advisory sits unpatched until someone audits by hand, which across 1,322 repositories means never.
Fix: Commit .github/dependabot.yml covering the repo ecosystems plus github-actions.
Pin the container base image by digestmedium
docker/Dockerfile
ubuntu:24.04
An untagged or mutable base means today's build and last month's contain different libc and a different CVE set, with no record of which shipped.
Fix: Use image:tag@sha256:<digest> and enable Dependabot's docker ecosystem.
Gate pull requests on a dependency vulnerability scanmedium
.github/workflows
no dependency scan in CI
This is the one gate that would catch a known-vulnerable package before it reaches a build, and no repository in the sample had it.
Fix: Add dependency-review-action on pull_request, or osv-scanner on push and a schedule.
Add a pre-commit secret gatemedium
a secret-shaped file is tracked and no repo-level gate is visible
Without a gate the same class of leak recurs on the next commit, so a leak finding is the symptom and this is the cause.
Fix: Add a pre-commit hook scanning staged content, and enable push protection.
Move large binaries to Git LFS or out of the repositorymedium2 occurrences
api/vendor/phpstan/phpstan/phpstan.phar
2 blobs over 5MB: phpstan.phar 26.0MB, phpstan.phar 26.0MB
One repository here carries twenty blobs over 5MB including a 10.9MB spreadsheet, so every clone and every CI checkout pays for data nobody diffs.
Fix: Track those extensions with LFS, or move datasets to object storage and fetch them in a setup step.
Add a non-root USER to the imagemedium
docker/Dockerfile
CMD or ENTRYPOINT with no USER directive
A process running as root in the container is root against every mounted volume, and it turns any container escape or writable-mount mistake from a contained problem into a host one.
Fix: Create an unprivileged user, chown what it needs, and end the Dockerfile with USER.
Add the repository convention files this project lackslow3 occurrences
missing .editorconfig, .gitattributes, a formatter config
Without them one contributor's editor writes tabs into a Python file, a shell script commits with CRLF and fails in the container, and a notebook diff is unreviewable.
Fix: Add .editorconfig, .gitattributes with text=auto eol=lf, and a formatter config.
Checked deterministically against the repository tree and a bounded set of its files: committed credentials, unpinned actions and base images, missing lockfiles and update bots, workflows that discard failures, published advisories against the declared dependencies, runtime configuration, licensing and notebook reproducibility. No language model is involved in this section.