MCP Server
Workjournal ships an MCP server that exposes journals, entries, tags, attachments, contributors, invitations, and export as tools. Use it to connect Workjournal to any MCP-compatible AI client that doesn’t support Open Agent Skills yet — Claude Desktop, ChatGPT, Perplexity, Grok, Opera Neon, and others.
If your agent already supports skills (Claude Code, Codex, Cursor, Copilot, Junie, Gemini CLI, …), prefer the skill — it orchestrates the CLI directly and is faster to set up.
Deployment modes
| Mode | Endpoint | When to use |
|---|---|---|
| Remote (preferred) | https://mcp.workjournal.pro | Any client that supports remote MCP — nothing to install |
Local (npx) | runs as a local process over stdio | Fallback for clients that only support local MCP, or when remote isn’t a fit |
Both modes expose the same set of tools against the same backend (api.workjournal.pro). Prefer remote.
The remote endpoint advertises OAuth discovery per RFC 9728 and delegates authorization to Supabase’s OAuth 2.1 server at auth.workjournal.pro/auth/v1. MCP clients that support automatic registration (ChatGPT Connectors, Perplexity remote, Claude Desktop remote) will register themselves, run PKCE, and redirect the user through the branded consent screen at app.workjournal.pro/authorize — no manual configuration.
Claude (claude.ai and Claude Desktop)
Remote (preferred)
claude.ai and Claude Desktop both support remote MCP via the Connectors feature. A connector added on one shows up on the other.
- Settings → Connectors → Add custom connector.
- Name:
Workjournal. Remote MCP server URL:https://mcp.workjournal.pro. - Approve the request on
app.workjournal.pro/authorize— Claude completes OAuth automatically and the connector goes live. - Toggle Workjournal on under the + menu in any conversation.
Local (fallback)
If you’d rather run the server locally over stdio, open Settings → Developer → Edit Config in Claude Desktop and add Workjournal to mcpServers:
{
"mcpServers": {
"workjournal": {
"command": "npx",
"args": ["-y", "@workjournal/mcp-server"]
}
}
}
Restart Claude Desktop. Then authenticate once with the CLI so the MCP server has credentials to read:
npx @workjournal/cli auth login
This opens a browser, you approve, and credentials land at ~/.config/workjournal/credentials.json (or the platform equivalent — see /docs/cli-tool-auth-workflow). The MCP server reads that file on every request.
Claude Code
Same config as Claude Desktop, but in .claude/settings.json at your project root:
{
"mcpServers": {
"workjournal": {
"command": "npx",
"args": ["-y", "@workjournal/mcp-server"]
}
}
}
In practice, Claude Code users are better served by the Workjournal skill — it gives you /workjournal slash commands and doesn’t need the MCP server at all. The MCP server is here mainly for agents that bypass the skill layer.
Perplexity
Perplexity supports both a remote custom connector (all platforms) and a local helper (Mac only). Prefer remote — it uses hosted OAuth and doesn’t need anything installed.
Remote (all platforms)
- Open Settings → Connectors, click the custom connector button, and choose the Remote option.
- Name:
Workjournal. - Server URL:
https://mcp.workjournal.pro. - Perplexity discovers the authorization server, registers itself, and walks you through OAuth. Approve the request on
app.workjournal.pro/authorizeand the connector is ready to use under Sources in any conversation.
Mac (local)
Requires the PerplexityXPC helper app from the Mac App Store.
- Open Settings → Connectors, add a custom connector, and pick the local / Simple option when prompted.
- Name:
Workjournal. Command:npx @workjournal/mcp-server. - Authenticate with
npx @workjournal/cli auth loginin a terminal so the server picks up credentials. - Toggle the connector on under Sources in a new conversation.
Works on Pro, Max, and Enterprise plans.
ChatGPT
Two paths into ChatGPT — pick whichever fits.
Custom GPT (no toggle, all plans)
Open the Workjournal GPT from the GPT Store and click Start chat. Approve OAuth on app.workjournal.pro/authorize. The GPT can then call a curated 15-operation surface (list/get/create/update/delete entries + search + export + tags + journals) without any developer-mode toggle. Works on Free, Plus, Pro. This path uses an OpenAPI Action, not MCP, but goes through the same OAuth server.
Apps SDK / Connectors (full tool catalog)
Workjournal is an approved app in the OpenAI app directory — no Developer Mode toggle required. This path gets you the full 42-tool MCP catalog.
- Open Workjournal in the app directory, or search for Workjournal under Settings → Apps & Connectors.
- Click Connect.
ChatGPT connects server-side, so the hosted endpoint is the only option — there is no local fallback here. ChatGPT discovers the authorization server from the MCP endpoint, registers automatically, and walks you through OAuth at app.workjournal.pro/authorize on first connect.
The connector list is shared across ChatGPT web, desktop, and mobile — set it up once on web or desktop and it shows up on your phone too. The mobile app can’t initiate the OAuth flow itself, so first-time connection has to happen on web or desktop.
Grok
Grok (xAI) supports remote MCP servers in its web app and the standalone mobile app (iOS / Android) via the Connectors integration. The in-X.com Grok chat doesn’t expose connectors.
- Settings → Connectors → Add a connector.
- Name:
Workjournal. MCP server URL:https://mcp.workjournal.pro. - Approve the request on
app.workjournal.pro/authorize— Grok completes OAuth automatically and the connector goes live. - Use the tools by asking Grok to log, search, or summarize journal entries in any conversation.
Opera Neon
Opera Neon (desktop browser) supports remote MCP servers through its MCP Servers settings; the tools are used by Neon Do, the browser’s AI assistant.
- From the start page, open the menu → Settings → MCP Servers.
- Name:
Workjournal. MCP server URL:https://mcp.workjournal.pro. - Approve the request on
app.workjournal.pro/authorize— a green Authenticated chip appears on the server entry. - Ask Neon Do to log, search, or summarize journal entries. Individual tools can be inspected and toggled per server.
Authentication
- Remote (
mcp.workjournal.pro): OAuth 2.1 with PKCE and dynamic client registration. On first connect the client fetcheshttps://mcp.workjournal.pro/.well-known/oauth-protected-resource, follows it tohttps://auth.workjournal.pro/auth/v1, registers itself, and redirects you through the consent screen atapp.workjournal.pro/authorize. Supabase issues JWTs that the MCP worker passes straight through to the API. - Local (
npx): the server reads the credentials file at~/.config/workjournal/credentials.jsonon Linux/macOS or%APPDATA%\workjournal\credentials.jsonon Windows (override withWORKJOURNAL_CONFIG_DIR), created bynpx @workjournal/cli auth login. As a fallback, setWORKJOURNAL_API_KEYin the client’senvblock.
Available tools
All tools follow <operation>_<resource> — plural for collection results, singular for single items. Most non-auth tools take workspace_slug (and, where relevant, journal_slug) as their leading arguments — exceptions are list_workspaces and get_workspace, which operate above the workspace boundary.
| Tool | Description |
|---|---|
list_workspaces | List workspaces you own or belong to |
get_workspace | Get a workspace by slug |
list_journals | List journals in a workspace |
get_journal | Get details of a specific journal |
create_journal | Create a new journal in a workspace |
rename_journal | Change a journal’s display name (slug stays) |
set_journal_slug | Change a journal’s URL slug (breaks existing links — old URLs return 404) |
delete_journal | Delete a journal and all its entries (irreversible) |
list_entries | List recent entries (slim — no body) |
last_entries | Return the N most recent entries with full body |
get_entry | Get a single entry by its per-journal index |
create_entry | Create a new journal entry (optionally with tags — Plus+) |
update_entry | Update title, summary, body, and/or tags of an entry by index (any subset of fields; preserves created_at and index) |
delete_entry | Delete an entry by its per-journal index |
search_entries | Search entries by keyword (slim results — Postgres full-text) |
semantic_search | Semantic (RAG) search — rank chunks by cosine similarity against the query embedding (Pro+). Returns chunks, not whole entries; follow up with get_entry for the full body. |
list_tags | List the workspace tag registry; pass journal_slug to annotate each row with assigned: boolean for that journal (Plus+) |
get_tag | Get a single tag from the workspace registry (Plus+) |
create_tag | Create a tag in the workspace registry (Plus+) |
update_tag | Rename a tag and/or update its description; rename cascades to every entry that carries it (Plus+) |
delete_tag | Delete a tag from the registry; cascade-strips it from every entry across every assigned journal |
assign_tag | Make a registry tag usable on entries in a journal (Plus+; returns 409 if already assigned) |
unassign_tag | Remove a tag from a journal; cascade-strips it from every entry in that journal (returns 404 if not assigned) |
list_attachments | List files in a journal (id, filename, type, size, linked entry indices) |
upload_attachment | Upload an image/PDF (≤ 5 MiB) by passing its bytes as base64 — works on every surface, including the hosted remote worker |
upload_attachment_from_path | Upload an image/PDF (≤ 5 MiB) by local file path — local stdio only (the hosted remote worker has no filesystem) |
delete_attachment | Delete a file from storage and unlink it from every entry (irreversible) |
list_contributors | List contributors of a journal |
delete_contributor | Remove a contributor from a journal |
list_invitations | List invitations for a journal |
create_invitation | Invite a collaborator by email |
delete_invitation | Revoke a pending invitation |
export_journal | Export a journal as JSON, Markdown, or CSV |
search | Cross-journal search across every journal you can see (own workspaces + shared-with-me). Returns {results: [{id, title, text, url}]} per OpenAI’s Connector App spec — the shape ChatGPT expects for an approved connector install |
fetch | Retrieve a full entry by its connector-app id <workspace>/<journal>/<index>. Returns {id, title, text, url, metadata} |
Entries are identified by a per-journal monotonic index (not UUIDs) — the same integer you see in list_entries output is what get_entry, update_entry, delete_entry, and the CLI’s entries get <ws> <j> <index> expect.
Connector-app compatibility (search + fetch). ChatGPT only installs connectors that match OpenAI’s search/fetch tool spec without Developer Mode — Workjournal’s connector implements that spec and is approved in the app directory, so it installs directly. The search tool returns a cross-journal aggregate (slim summaries, no body) and fetch resolves the composite id back to a full entry. The richer per-journal search_entries / get_entry tools stay available for callers that already have a workspace + journal slug — search and fetch are for the case where the agent is discovering content across the user’s whole workjournal.
Workspace creation is API-only today — every signed-in user has their personal workspace auto-provisioned, so there’s no create_workspace tool. That changes when the paid-tier signup flow ships.
Tag validation on entry write. create_entry and update_entry accept a tags: string[] parameter. Names must already be assigned to the entry’s journal (via assign_tag). The MCP server calls list_tags(workspace_slug, journal_slug) at handler time, filters to the assigned subset, and rejects unknown names with the valid options surfaced in the error message. This is the closed-enum constraint: agents discover what’s available without needing per-call enum injection.
Attachments. list_attachments, delete_attachment, and upload_attachment work in both modes. upload_attachment(workspace_slug, journal_slug, filename, data) carries the file bytes as base64 inside the tool call (a JSON-RPC tool call can’t carry a multipart file part), so it works on the hosted remote worker as well as local stdio — the server decodes the base64 and reuses the same multipart upload path as every other surface. On the local stdio server, upload_attachment_from_path(workspace_slug, journal_slug, file_path) reads the file straight off disk, so an agent that already has it locally needn’t base64-encode it; it’s not registered on the remote worker (no filesystem). Files are journal-scoped, images + PDF only, capped at 5 MiB each, and metered against the per-workspace storage quota (Free 0.5 GiB / Plus 2 GiB / Pro 5 GiB). Upload returns { id, url }, where the content URL is journal-scoped — private …/workspaces/:ws/journals/:j/attachments/:id, or public …/public/:slug/attachments/:id for a public journal. Entries link attachments via an attachment_ids array on create_entry / update_entry; in return, get_entry / last_entries (and the create/update responses) include a resolved attachments array of { id, filename }, so an agent pulling an entry sees its attachment filenames without a separate list_attachments call.
Troubleshooting
Server does not support automatic registration— the MCP client can’t reach the discovery metadata. Verifyhttps://mcp.workjournal.pro/.well-known/oauth-protected-resourcereturns JSON andhttps://auth.workjournal.pro/.well-known/oauth-authorization-server/auth/v1returns an OpenID config with a workingregistration_endpoint.- “No credentials found” (local) — run
npx @workjournal/cli auth loginon the machine where the MCP server runs, or setWORKJOURNAL_API_KEYin the client’senvblock. - Tools don’t appear — restart the client after editing its config. Claude Desktop in particular only reloads
mcpServersat startup. - 401 from hosted endpoint — the OAuth access token is expired or invalid and the client didn’t refresh it. The 401 response includes
WWW-Authenticate: Bearer resource_metadata="…"— compliant clients re-run the refresh or authorization flow on that signal.
See CLI Commands for everything the CLI exposes, and Skill Commands for the /workjournal surface in skill-aware agents.