Skip to main content
Glama
README.md
# salik-hr-mcp

The MCP protocol server for the Salik Labs HR app — a separate service from the main
`salik-hr` Next.js app, by design. See `docs/MCP_SERVICE_SPLIT.md` in the `salik-hr` repo
for the full design and why this split exists; `docs/MCP_PLAN.md` there covers the tool
inventory and product scope, still accurate here.

## What this is

A thin, **stateless** protocol layer:

- **No database.** No Drizzle, no schema, no employee data model.
- **No business logic.** Every rule (who can approve what, balance checks, the CEO
  auto-approve behavior, the sign-off visibility rule) lives in the main app and is
  enforced there — this service cannot bypass it, because it never has more access than
  the bearer token it was handed.
- **Every tool call is a `fetch()`** to `${HR_APP_BASE_URL}/api/...`, forwarding the
  caller's own token on `Authorization: Bearer`. The main app's `middleware.ts` verifies
  that token and resolves identity — this service trusts it to do that correctly and does
  no verification of its own beyond one `GET /api/me/session` call per connection, to know
  which tools to register (write tools only for a `read_write`-scope token).

## Local development

```bash
npm install
cp .env.example .env.local
# edit .env.local: HR_APP_BASE_URL=http://localhost:3000 (the main app's dev server)
npm run dev
```

Requires the main app (`salik-hr`) running locally with a minted personal access token
(mint one at `/me` → Connected apps, once signed in as a role `MCP_TOKEN_ROLES` allows).

## Connecting a client

Point any MCP client at `http://localhost:8787/mcp` (or the deployed URL) with
`Authorization: Bearer <your slhr_ token>`. Example, Claude Code:

```bash
claude mcp add --transport http salik-hr http://localhost:8787/mcp \
  --header "Authorization: Bearer $SALIK_HR_TOKEN"
```

## Deployment

Deploy as its own service (its own Railway service, or any Node host) with
`HR_APP_BASE_URL` pointed at the main app's production URL. `npm run build && npm start`.