Work Journal MCP Server
A read-only MCP server that lets team members access Simplified HR Work Journal entries and team reports through Claude, with permissions enforced by the existing Work Journal API.
README
Work Journal MCP Server
A hosted MCP server that lets any member of the team read their Simplified HR Work Journal through Claude — their own entries always, and colleagues' entries where their existing Work Journal permissions already allow.
Read-only. No tool here can create, change, or delete an entry.
Connecting, from any Claude client
One flow, whichever client you use: add the server by URL, then sign in in the browser window that opens.
Claude Desktop or claude.ai — Settings → Connectors → Add custom connector →
https://wj-mcp.dev.besimplified.net/mcp
Claude Code
claude mcp add work-journal --transport http https://wj-mcp.dev.besimplified.net/mcp
Either way a browser window opens. Sign in with your Simplified HR email and password. On dev you also enter your workspace, for example development-hr.dev.besimplified.net.
If this is a device the accounts service has not seen before, you are sent a verification code by email or SMS. Enter it once; you will not be asked again from the same client.
Your password never reaches Claude, and this server never stores it.
Tools
work_journal_get_entries
Entries with full task detail for a date or a range of up to 31 days.
| parameter | notes |
|---|---|
date |
single day, YYYY-MM-DD |
start_date, end_date |
inclusive range, used instead of date |
type |
optional, see the alias table below; omit for all types |
member |
optional, another member's id from work_journal_find_member |
include_tasks |
optional, default true; false returns statuses only, in a single request |
Ask: "show my EOD entries for last week"
work_journal_get_day
One date in full: every task with notes and attachments, notified recipients, ETA, and submission time.
| parameter | notes |
|---|---|
date |
required, YYYY-MM-DD |
type |
optional, narrows to one entry type |
member |
optional, another member's id |
Ask: "what did I log on 4 August?"
work_journal_get_summary
Counts by type and status over any period, with no per-day detail. Use this for anything longer than 31 days.
| parameter | notes |
|---|---|
start_date, end_date |
inclusive range |
year |
whole calendar year, used when no explicit range is given |
type |
optional |
member |
optional, another member's id |
Ask: "how many EOW reports did I miss this year?"
work_journal_find_member
Finds a colleague by part of their name or email and returns their member id, for use as member on the tools above.
| parameter | notes |
|---|---|
query |
part of a name or email, at least two characters |
Ask: "find Rahul's member id"
work_journal_get_team_report
One row per member with submitted, pending, and missed counts for a period.
| parameter | notes |
|---|---|
start_date, end_date |
required, inclusive range |
type |
optional, defaults to EOD |
team |
optional team id, or the literal unassigned |
status |
optional: submitted, pending, or missed |
member |
optional, narrows to one member |
limit, page |
optional; default 15 rows, maximum 50 |
Ask: "who missed their EOD last week?"
Type aliases
| you can say | resolves to | shown as |
|---|---|---|
eod, daily, end of day |
daily |
EOD |
eow, weekly, end of week |
weekly |
EOW |
group eow, group weekly |
group_weekly |
Group EOW |
eom, monthly, end of month |
monthly |
EOM |
Matching ignores case and treats spaces, hyphens, and underscores as equivalent.
Who can see whose journal
This server enforces no permissions of its own. Every request carries your own Simplified HR session, and the Work Journal API applies exactly the permissions it applies in the web UI:
- Instance permission — you can read any member of your company
- Group permission — you can read members in your reporting subtree
- Neither — you can read only your own journal, and any attempt at another member's is refused
Two things to know when reading a colleague's entries: the request can be refused outright, and an admin view excludes drafts, scheduled, and private entries. An absent entry therefore does not prove nothing was logged.
Limits
work_journal_get_entriesrejects ranges longer than 31 days and points you atwork_journal_get_summary- At most 4 requests run concurrently per tool call, so a wide range stays gentle on the API
- Relative dates such as "last week" are resolved by Claude before the call; the tools accept
YYYY-MM-DDonly
Running it locally
npm install
cp .env.example .env # then fill in the two secrets
WJ_ENV=dev \
WJ_PUBLIC_BASE_URL=http://localhost:8080 \
WJ_TOKEN_KEY=$(openssl rand -hex 32) \
WJ_FINGERPRINT_SECRET=$(openssl rand -hex 32) \
npm start
GET /healthz should answer {"status":"ok"}. Running node src/index.js with no environment must exit immediately, listing every missing variable.
Environment
| variable | required | purpose |
|---|---|---|
WJ_ENV |
yes | selects the host preset: dev or prod. There is no default, so an empty value cannot silently point production at the dev hosts |
WJ_PUBLIC_BASE_URL |
yes | externally reachable origin, published in the OAuth discovery documents |
WJ_TOKEN_KEY |
yes | 64 hex characters; encrypts the session envelope |
WJ_FINGERPRINT_SECRET |
yes | at least 32 characters; derives each member's device fingerprint |
WJ_API_BASE_URL |
no | plugin API host, when it differs from the preset for WJ_ENV |
WJ_AUTH_BASE_URL |
no | accounts service origin, when it differs from the preset |
WJ_PORT |
no, defaults to 8080 |
listen port |
WJ_REQUEST_TIMEOUT_MS |
no, defaults to 15000 |
per-request timeout |
WJ_FINGERPRINT_SECRET must be identical across every task, and must not be rotated casually. It derives each member's stable device fingerprint; changing it re-challenges the whole team with a verification code.
Deployment notes
-
Cookie stickiness is required on
/authorizeonly. An OTP submission must reach the task that began the login, because the in-progress login is held in that process's memory for five minutes./mcpand/tokenare stateless and must not be sticky. -
Both secrets belong in SSM Parameter Store as
SecureString, referenced from the task definition'ssecretsblock — never as environment literals. Create them once per environment before the first deploy; nothing else in the platform uses the/hr/work-journal-mcp/prefix, so they will not already exist:aws ssm put-parameter --type SecureString --name /hr/work-journal-mcp/<env>/token_key --value "$(openssl rand -hex 32)" aws ssm put-parameter --type SecureString --name /hr/work-journal-mcp/<env>/fingerprint_secret --value "$(openssl rand -hex 32)"ecsTaskExecutionRoleneedsssm:GetParametersandkms:Decrypton both, or the task fails at start withResourceInitializationError, before any of this code runs. -
Production rejects the
workspacelogin field that dev requires, so the login page hides it outside dev.
Security
- Passwords are never stored, never logged, and never returned to the browser in any form. They exist only in memory, for the seconds a login takes.
- Session state travels in an AES-256-GCM encrypted envelope that only this server can open. The Simplified HR JWT never reaches Claude or the model.
- Access, refresh, and authorization-code envelopes are cryptographically bound to their kind, so one cannot be spent as another.
- Login attempts are rate limited per email address.
- Every tool call is logged with the caller, the tool, and the member whose journal was read, so cross-member reads are auditable. Tokens and entry content are never logged.
Tests
npm test
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.