ProjectHub MCP Server
This MCP server lets an AI assistant interact with a ProjectHub workspace to manage projects, tasks, notes, discussions, reminders, notifications, links, files, memories, tags, canvas boards, and time tracking.
User & workspaces: get the current user's profile, list workspaces, list projects, create projects.
Projects: view project details, list members, get activity feeds, and search across notes, tasks, discussions, messages, and memories.
Tasks: list, search, create, update, delete, and toggle tasks; filter by status, tag, assignee, or parent; support subtasks and keyword search.
Time tracking: start and stop timers on tasks.
Notes: list, get, create, update, and delete notes, with tag filtering.
Discussions: list discussions, create discussion rooms, and read messages (read-only).
Reminders: list, create, and dismiss reminders, optionally linked to tasks or notes.
Notifications: list notifications (unread only by default) and mark them read.
Links: list, create, and delete quick links.
Files: list files in a project.
Memories: list, get, create, update, and delete project memories; list workspace-wide memories; filter by category, source, or pinned status.
Canvas: list canvas placements, place notes on the board, move/resize/restack items, and remove placements.
Tags: list, create, rename/recolor, and delete tags.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ProjectHub MCP Server Show me my high-priority tasks for the Website Redesign project"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ProjectHub MCP Server
An MCP (Model Context Protocol) server that connects AI assistants like Claude Desktop to ProjectHub, a collaborative project management tool.
Features
56 tools covering the full ProjectHub API:
Category | Tools |
User |
|
Workspaces |
|
Projects |
|
Tasks |
|
Task comments |
|
Time Tracking |
|
Notes |
|
Tags |
|
Canvas |
|
Discussions |
|
Reminders |
|
Notifications |
|
Links |
|
Files |
|
Memories |
|
Related MCP server: OpenProject MCP Server
Task keys
Every task has a human-readable key such as PR14 — the project's key prefix plus a per-project number that is assigned at creation and never reused. Task objects return key and number; project objects return key. Anywhere a tool takes a task_uuid (get/update/delete/toggle, timers, attachments, parent_uuid, list_tasks parent, upload_file task_uuid) you can pass the key instead, case-insensitively (pr14, PR-14). list_tasks q and search_project match keys too. create_project accepts an optional key (1–5 letters); otherwise it's derived from the name.
Uploading files
upload_file takes the file body from exactly one of four sources:
Source | Where it works | Use for |
| Local stdio server only (Claude Code, Claude Desktop launching | Anything on your disk, up to the 50 MB server limit — the bytes go straight from the MCP process to ProjectHub, never through the model |
| Everywhere, including the hosted connector | Files reachable over https. Private/loopback addresses are refused, redirects are re-checked, 30 s timeout |
| Everywhere | Small text the assistant generates (reports, CSV, Markdown) |
| Everywhere | Small binary the assistant generates |
Inline content / content_base64 travel inside the tool call, so they are practically limited to tens of KB. The hosted connector cannot read your disk; for local files there, use the ProjectHub UI or a url.
filename is required with inline content and defaults to the source's name for path/url. task_uuid attaches the file to a task in the same call. PROJECTHUB_MAX_UPLOAD_BYTES overrides the 50 MB client-side cap (the server enforces its own).
Prerequisites
Node.js 20+
A running ProjectHub instance
A ProjectHub Personal Access Token
Creating an API Token
Log in to ProjectHub
Click your avatar (top-right) → Settings (gear icon)
Scroll to API Tokens → click +
Name the token (e.g. "Claude Desktop MCP") and click Create
Copy the token immediately — it is only shown once
Setup
git clone <repo-url>
cd projecthub-mcp
npm install
npm run buildConfiguration
The server reads two environment variables:
Variable | Required | Default | Description |
| Yes | — | Personal access token ( |
| No |
| ProjectHub base URL |
Claude Desktop
Add to your claude_desktop_config.json:
{
"mcpServers": {
"projecthub": {
"command": "node",
"args": ["/absolute/path/to/projecthub-mcp/dist/index.js"],
"env": {
"PROJECTHUB_URL": "http://localhost:8000",
"PROJECTHUB_API_TOKEN": "ph_your_token_here"
}
}
}
}Claude Code
Add to your Claude Code settings or project config:
{
"mcpServers": {
"projecthub": {
"command": "node",
"args": ["/absolute/path/to/projecthub-mcp/dist/index.js"],
"env": {
"PROJECTHUB_URL": "http://localhost:8000",
"PROJECTHUB_API_TOKEN": "ph_your_token_here"
}
}
}
}Hosted mode — Claude Desktop / claude.ai custom connector
The stdio setup above runs one local process per machine with a pasted token.
For a custom connector (Claude Desktop → Settings → Connectors → Add custom
connector, also usable from claude.ai web and mobile) the server must be hosted
over HTTPS and use OAuth. That is what dist/http.js is:
Transport: Streamable HTTP at
/mcp, stateless (scales horizontally).Auth: ProjectHub itself is the OAuth 2.1 authorization server (PKCE, dynamic client registration, consent page). This service is only a resource server: it 401s with a
WWW-Authenticatechallenge pointing at its/.well-known/oauth-protected-resourcedocument, which names ProjectHub as the authorization server. Claude follows that, the user approves on ProjectHub's consent page, and every subsequent tool call forwards that user's access token to/api/v1. Personal tokens (ph_…) are accepted too.Verification: each presented token is checked against
GET /api/v1/meand cached forMCP_VERIFY_TTL_SECONDS(default 60).
ProjectHub prerequisites
The ProjectHub deployment must be on a build that includes the OAuth provider
(oauth2_provider in INSTALLED_APPS, /oauth/* routes) with these set:
Variable | Example | Purpose |
|
| Advertised as the OAuth issuer; every OAuth endpoint URL in the metadata is anchored to it (must be |
|
| RFC 9728 resource identifier |
ProjectHub must also run with DEBUG off in production. Without APP_BASE_URL, the metadata URLs are derived from the request scheme, and a misread proxy header makes them http://, which Claude refuses at the registration step.
Environment (this service)
Variable | Required | Default | Description |
| Yes |
| Public ProjectHub base URL (also the OAuth issuer) |
| Recommended | derived from request | This service's public |
| No |
| Listen port (Railway sets it) |
| No | unset | Comma-separated Host allowlist (DNS-rebinding protection); unset = off |
| No |
| How long a verified token is trusted before re-checking |
PROJECTHUB_API_TOKEN is not used in hosted mode.
Deploy on Railway
Add a new service in the ProjectHub Railway project from this repo. The
Dockerfile builds and runs node dist/http.js. Generate a public domain for
the service, then set MCP_PUBLIC_URL=https://<that domain>/mcp here and
MCP_PUBLIC_URL / APP_BASE_URL on the ProjectHub web service.
Health check: GET /healthz.
Connect from Claude
Claude Desktop → Settings → Connectors → Add custom connector → URL
https://<mcp domain>/mcp. Leave client ID / secret blank (Claude registers
itself). Sign in to ProjectHub when prompted and click Allow.
Run hosted mode locally
npm run build
PROJECTHUB_URL=http://localhost:8000 npm run start:http
# Inspector: URL http://localhost:3000/mcp, header Authorization: Bearer ph_...Note that ProjectHub only allows https redirect URIs, so the full OAuth
browser flow needs a public HTTPS deployment; locally, test with a personal
token as above.
Tests
npm test # builds, then runs an end-to-end test against a mock ProjectHubDevelopment
# Watch mode — recompiles on file changes
npm run dev
# Test interactively with the MCP Inspector
npm run inspectProject Structure
src/
index.ts stdio entrypoint (local Claude Desktop config, one token per process)
http.ts Hosted entrypoint — Streamable HTTP + OAuth resource-server gate
server.ts createServer(): builds the McpServer with every tool registered
api-client.ts HTTP client (per-request token context), error handling, response helpers
test/ node:test end-to-end tests for the hosted entrypoint
tools/
user.ts get_user_info
workspaces.ts list_workspaces, list_projects
projects.ts get_project, list_project_members, search_project, get_activity
tasks.ts list_tasks, get_task, create_task, update_task, delete_task, toggle_task
timers.ts start_timer, stop_timer
notes.ts list_notes, get_note, create_note, update_note, delete_note
discussions.ts list_discussions, get_discussion_messages
reminders.ts list_reminders, create_reminder, dismiss_reminderCommon Workflows
Task triage — List open tasks, review priorities, update or complete them:
"Show me all open high-priority tasks in the Website Redesign project"
Standup summary — Combine your assigned tasks with recent activity:
"Give me a standup summary for my project"
Find context — Search across notes, discussions, and messages:
"Search for anything about the auth bug in this project"
Quick capture — Create tasks, notes, or reminders from conversation:
"Create a task to review the API documentation, due next Friday"
Project overview — Get project details, members, tasks, and notes at a glance:
"Give me an overview of what's happening in this project"
Notes
Auth: The API token inherits the user's full permissions — no separate scopes
Discussions: Read-only via the API (messages are sent through the ProjectHub UI)
HTML content: Note and message text is returned as HTML
IDs: All resource IDs are UUIDs except
user_idandassignee_id(integers)
Available Tools
47 toolscreate_discussionB
Create a new discussion (chat room) in a project
Inputs: title (required), project_uuid (required).
create_linkB
Create a new quick link in a project
Inputs: url (required), text (required), project_uuid (required), category.
create_memoryA
Create a new memory in a project. Memories are AI-generated knowledge items — decisions, preferences, context, references, or lessons — that persist across conversations. Humans can view them in the platform.
Inputs: title (required), content (required), category (required), project_uuid (required), +4 more.
create_noteC
Create a new note in a project. Only title is required.
Inputs: title (required), project_uuid (required), tags, text, +1 more.
create_projectB
Create a new project in a workspace. Requires add_project permission.
Inputs: name (required), workspace_uuid (required), icon, color, +1 more.
create_reminderB
Create a reminder. Title and remind_at are required. remind_at must include timezone.
Inputs: title (required), remind_at (required), project_uuid (required), notes, +4 more.
create_tagA
Create a tag in a project. Names are unique per project (case-insensitive). Note: you usually don't need this — passing tags: ["July Release"] to create_task/update_task/create_note/update_note auto-creates any tag that doesn't exist yet. Use this when you want to control the colour.
Inputs: name (required), project_uuid (required), color.
create_taskB
Create a new task in a project. Only title is required.
Inputs: title (required), project_uuid (required), tags, status, +6 more.
delete_linkB
Delete a quick link from a project
Inputs: link_uuid (required), project_uuid (required).
delete_memoryA
Delete a memory from a project
Inputs: memory_uuid (required), project_uuid (required).
delete_noteA
Delete a note. Requires being the creator or having delete permission.
Inputs: note_uuid (required), project_uuid (required).
delete_tagA
Delete a tag from a project. It is removed from every task and note it was attached to. The tagged items themselves are NOT deleted.
Inputs: tag_uuid (required), project_uuid (required).
delete_taskB
Delete a task. Requires Project Owner role.
Inputs: task_uuid (required), project_uuid (required).
dismiss_reminderA
Dismiss a reminder (sets its status to dismissed)
Inputs: project_uuid (required), reminder_uuid (required).
get_activityC
Get the recent activity feed for a project
Inputs: project_uuid (required), limit.
get_discussion_messagesB
Get messages from a discussion in chronological order. Messages are read-only via the API.
Inputs: project_uuid (required), discussion_uuid (required), limit, before.
get_memoryB
Get a single memory with its full content
Inputs: memory_uuid (required), project_uuid (required).
get_noteA
Get a single note with its full content
Inputs: note_uuid (required), project_uuid (required).
get_projectB
Get details of a specific project
Inputs: project_uuid (required).
get_taskB
Get details of a specific task
Inputs: task_uuid (required), project_uuid (required).
get_user_infoA
Get the authenticated user's profile information (name, email, username)
Inputs: no named parameters.
list_canvas_itemsA
List the notes placed on the project's shared canvas, with their positions (x, y), sizes (width, height), and stacking order (z). Use this to understand how the board is spatially organized before placing or arranging notes.
Inputs: project_uuid (required).
list_discussionsB
List all discussions (chat rooms) in a project
Inputs: project_uuid (required).
list_filesA
List all files in a project. Requires files_enabled plan feature.
Inputs: project_uuid (required).
list_linksB
List all quick links in a project
Inputs: project_uuid (required).
list_memoriesA
List memories (AI-generated knowledge items) in a project. Memories capture decisions, preferences, context, references, and lessons that persist across conversations.
Inputs: project_uuid (required), source, category, is_pinned.
list_notesA
List all notes in a project, ordered by pinned first then newest. Pass tag to only return notes carrying that tag.
Inputs: project_uuid (required), tag.
list_notificationsA
List notifications for the current user. Returns unread only by default.
Inputs: limit, unread_only.
list_project_membersA
List members of a project with their roles
Inputs: project_uuid (required).
list_projectsA
List projects in a workspace that the user is a member of
Inputs: workspace_uuid (required), include_archived.
list_remindersA
List pending reminders for the current user in a project
Inputs: project_uuid (required).
list_tagsA
List the tags defined in a project, with how many things each tag is attached to. Use this to discover existing tags before tagging something, so you reuse a tag instead of creating a near-duplicate.
Inputs: project_uuid (required), q.
list_tasksA
List tasks in a project with optional filters. Results are paginated (default 50). Use q to keyword-search titles/descriptions, and limit/offset to page through large projects instead of fetching everything.
Inputs: project_uuid (required), q, tag, limit, +4 more.
list_workspace_memoriesB
List memories across all projects in a workspace. Useful for retrieving workspace-wide knowledge and context.
Inputs: workspace_uuid (required), source, category.
list_workspacesA
List all workspaces the authenticated user belongs to
Inputs: no named parameters.
mark_notification_readB
Mark a notification as read
Inputs: notification_id (required).
move_canvas_itemA
Move and/or resize a placed canvas item. Pass the placement's item id (from list_canvas_items or place_on_canvas), not the note id. Only provided fields change. Use z to restack (higher = front). Width/height are clamped to a minimum.
Inputs: item_uuid (required), project_uuid (required), x, y, +3 more.
place_on_canvasA
Place a note on the shared canvas at an (x, y) world coordinate. Idempotent — if the note is already on the canvas, returns its existing placement. Returns the placement (including its item id used by move/remove). Coordinates are in pixels; new notes default near the top-left. Place related notes near each other.
Inputs: note_uuid (required), project_uuid (required), x, y.
remove_from_canvasA
Remove a note's placement from the canvas. The underlying note is NOT deleted — it just leaves the board. Pass the placement's item id, not the note id.
Inputs: item_uuid (required), project_uuid (required).
search_projectA
Search across notes, tasks, discussions, messages, and memories in a project. Strong multi-term keyword matching (every word must match; order-independent); semantic search is also used for embedded types on Pro plans. Returns up to 4 results per type. Pass type to restrict to one entity type (e.g. 'task').
Inputs: q (required), project_uuid (required), type.
start_timerA
Start a time tracking timer on a task. Automatically stops any other running timer.
Inputs: task_uuid (required), project_uuid (required).
stop_timerA
Stop the running time tracking timer on a task
Inputs: task_uuid (required), project_uuid (required).
toggle_taskB
Toggle a task between open and done status
Inputs: task_uuid (required), project_uuid (required).
update_memoryB
Update a memory. Only provided fields are changed (partial update).
Inputs: memory_uuid (required), project_uuid (required), tags, title, +5 more.
update_noteB
Update a note. Only provided fields are changed.
Inputs: note_uuid (required), project_uuid (required), tags, text, +2 more.
update_tagA
Rename or recolour a tag. Renaming updates it everywhere it's used. Only provided fields change.
Inputs: tag_uuid (required), project_uuid (required), name, color.
update_taskA
Update a task. Only provided fields are changed. Set assignee_id to 0 to unassign.
Inputs: task_uuid (required), project_uuid (required), tags, title, +6 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 47 tools
Each tool targets a specific resource or action, but some overlap exists such as search_project vs dedicated list tools, and list_workspace_memories vs list_memories, which could cause minor confusion.
All tools consistently use snake_case and follow a verb_noun pattern (e.g., list_projects, create_task, toggle_task), making the naming highly predictable and clear.
With 47 tools, the count is very high, exceeding the typical well-scoped range. While each tool serves a distinct purpose, the sheer number may overwhelm agents and makes it harder to navigate the surface.
The tool set provides extensive coverage of project management operations (CRUD for tasks, notes, memories, tags, etc.) with only minor gaps such as missing update/delete for discussions and file uploads.
Maintenance
Related MCP Connectors
AI-native project management for tasks, docs, collaboration, and agents.
Manage Redbooth tasks, task lists, comments, tags and files from Claude and other AI assistants.
Manage projects, tasks, time tracking, and team collaboration through natural language.
Create and manage MeisterTask projects, tasks, and notes from your AI assistant.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with OpenProject's API v3 for comprehensive project management operations including work packages, projects, time tracking, users, and all other OpenProject features through natural language.4MIT
- AlicenseBqualityCmaintenanceEnables AI assistants to manage OpenProject work packages, projects, and time tracking. It provides comprehensive tools for creating, updating, and querying tasks and project metadata through the OpenProject API.1159 npm1MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI assistants to manage Todocko application data, including tasks, projects, worklogs, and attachments. It supports comprehensive project management operations such as tracking activity, managing Kanban boards, and handling shared project synchronization.1MIT
- AlicenseAqualityDmaintenanceEnables AI assistants to interact with the Worksection project management platform to manage projects, tasks, comments, and members through natural language. It provides a comprehensive suite of tools for task execution and project oversight while automatically handling API rate limits.219 npmMIT