project-manager
This MCP server acts as a bridge between Claude and a project management backend, exposing a comprehensive set of tools to manage projects, tasks, users, teams, organizations, tags, comments, and files.
Health Check
Check API liveness with
pm_health.
Projects
Create, list, get, update, and delete projects.
Upload, download, list, update, and delete files attached to projects (base64-encoded transfers).
Tasks
Create, list, get, update, and delete tasks.
Filter by status, priority, project, owner, tags, overdue, starred, and more.
Attach and detach tags to/from tasks.
Comments
Create, list, update, and delete comments on tasks.
Users
Create, list, get, update, and delete users (some actions admin-only).
Attach and detach contact labels to/from users (admin-only).
Export users as joined plain text or CSV with configurable fields and filters.
User Labels (Contact Labels)
Create, list, get, and delete global contact labels.
Organizations
Create, list, and get organizations.
Teams
Create, list, and get teams, optionally filtered by organization.
Tags
Create, list, get, update, and delete tags, optionally scoped to a project or global.
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., "@project-manager Create a task 'Fix login bug' in project 'MainApp'"
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.
What is this project
This project implements stdio MCP server, so that Claude can search data by sending requests to an API backend running on localhost:8000
Documentation: docs/ — implementation overview and full pm_* tool reference.
This is the entry point for your MCP server. Breaking it down:
@click.command() + @click.option — CLI interface with two flags:
--base-url: override the API URL without changing env vars (e.g.--base-url http://staging:8000)--transport: how Claude communicates with the server —stdio(default, used by Claude Desktop via stdin/stdout pipes),sseorstreamable-httpfor network-based transports
def main(...):
Creates a
ProjectManagerClient— your HTTP client that talks to the FastAPI backendCalls
build_mcp(client)— registers all thepm_*tools with the MCP framework, wrapping the client's methods as Claude-callable toolsmcp.run(transport=transport)— starts the server loop, listening for tool calls from Claudeclient.close()infinally— cleanly shuts down the HTTP client when the process exits
Why stdio is the default: Claude Desktop launches this as a subprocess and communicates via stdin/stdout pipes — no network port needed. The sse/streamable-http options would be for remote deployments where Claude connects over HTTP instead.
In short: this boots the bridge between Claude and your project manager API, using whichever communication channel fits the deployment context.
How to register this local MCP server with Claude Desktop
You add below into mcpServers section of %APPDATA%\Claude\claude_desktop_config.json
What does this achieve in %APPDATA%\Claude\claude_desktop_config.json
"project-manager": {
"command": "uv",
"args": [
"run",
"--directory",
"c:\\Users\\amrusub\\programming\\pet_projects\\project_manager_mcp",
"project-manager-mcp"
],
"env": {
"PROJECT_MANAGER_API_BASE": "http://127.0.0.1:8000"
}
}
},This registers a local MCP server called "project-manager" with Claude Desktop. Here's what each part does:
command: "uv" — uses uv (the fast Python package manager) to run the server
args — tells uv to run the project-manager-mcp entry point from your local project directory at c:\Users\amrusub\programming\pet_projects\project_manager_mcp
env — sets an environment variable so the MCP server knows to talk to your locally running API at http://127.0.0.1:8000
Net effect: When Claude Desktop starts, it spins up your local project-manager-mcp Python process in the background. Claude then gets access to whatever tools that server exposes (in your case, the project-manager:pm_* tools visible in this conversation — create tasks, list projects, manage users, etc.), all backed by your local FastAPI server on port 8000.
So it's essentially a bridge: Claude ↔ MCP server process ↔ your local REST API.
Available Tools
46 toolspm_create_commentD
POST /comments — TaskCommentCreate.
Inputs: payload (required), x_user_id. Returns: result
pm_create_organizationD
POST /organizations — OrganizationCreate {name}.
Inputs: payload (required), x_user_id. Returns: result
pm_create_projectC
POST /projects — body matches ProjectCreate (name, description_md, owner, optional slug, color_key, sort_order, settings_json, owner_user_id).
Inputs: payload (required), x_user_id. Returns: result
pm_create_tagB
POST /tags — TagCreate (name, optional project_id).
Inputs: payload (required), x_user_id. Returns: result
pm_create_taskC
POST /tasks — TaskCreate (project_id, title, short_name, plus optional fields).
Inputs: payload (required), x_user_id. Returns: result
pm_create_teamB
POST /teams — TeamCreate {name, optional organization_id}.
Inputs: payload (required), x_user_id. Returns: result
pm_create_userB
POST /users — admin only. UserCreate: display_name; optional email, phone, avatar_url, presence, role (admin|member), user_kind (internal|client), organization_id, team_id.
Inputs: payload (required), x_user_id. Returns: result
pm_create_user_labelC
POST /user-labels — UserLabelCreate {name}.
Inputs: payload (required), x_user_id. Returns: result
pm_delete_commentC
DELETE /comments/{comment_id}.
Inputs: comment_id (required), x_user_id. Returns: result
pm_delete_projectD
DELETE /projects/{project_id}.
Inputs: project_id (required), x_user_id. Returns: result
pm_delete_project_fileD
DELETE /projects/{project_id}/files/{file_id}.
Inputs: file_id (required), project_id (required), x_user_id. Returns: result
pm_delete_tagD
DELETE /tags/{tag_id}.
Inputs: tag_id (required), x_user_id. Returns: result
pm_delete_taskC
DELETE /tasks/{task_id}.
Inputs: task_id (required), x_user_id. Returns: result
pm_delete_userC
DELETE /users/{user_id} — admin only.
Inputs: user_id (required), x_user_id. Returns: result
pm_delete_user_labelD
DELETE /user-labels/{label_id}.
Inputs: label_id (required), x_user_id. Returns: result
pm_download_project_fileA
GET /projects/{project_id}/files/{file_id}/download — returns JSON with content_base64, content_type, size_bytes.
Inputs: file_id (required), project_id (required), x_user_id. Returns: result
pm_export_users_csvC
GET /users/export.csv — CSV export; fields is comma-separated column names; same filters as pm_list_users.
Inputs: fields, team_id, label_id, label_ids, +3 more. Returns: result
pm_export_users_joinedA
GET /users/export/joined — plain text; field: display_name|email|phone; separator: comma|semicolon; same filters as pm_list_users.
Inputs: field, team_id, label_id, label_ids, +4 more. Returns: result
pm_get_organizationD
GET /organizations/{organization_id}.
Inputs: organization_id (required), x_user_id. Returns: result
pm_get_projectD
GET /projects/{project_id}.
Inputs: project_id (required), x_user_id. Returns: result
pm_get_tagD
GET /tags/{tag_id}.
Inputs: tag_id (required), x_user_id. Returns: result
pm_get_taskC
GET /tasks/{task_id}.
Inputs: task_id (required), x_user_id. Returns: result
pm_get_teamC
GET /teams/{team_id}.
Inputs: team_id (required), x_user_id. Returns: result
pm_get_userC
GET /users/{user_id}.
Inputs: user_id (required), x_user_id. Returns: result
pm_get_user_labelD
GET /user-labels/{label_id}.
Inputs: label_id (required), x_user_id. Returns: result
pm_healthB
GET /health — API liveness.
Inputs: no named parameters. Returns: result
pm_list_commentsC
GET /comments?task_id=...
Inputs: task_id (required), x_user_id. Returns: result
pm_list_organizationsD
GET /organizations.
Inputs: x_user_id. Returns: result
pm_list_project_filesC
GET /projects/{project_id}/files.
Inputs: project_id (required), x_user_id. Returns: result
pm_list_projectsB
GET /projects — list projects (optional include_archived).
Inputs: x_user_id, include_archived. Returns: result
pm_list_tagsC
GET /tags — optional project_id or global_only.
Inputs: x_user_id, project_id, global_only. Returns: result
pm_list_tasksC
GET /tasks — filters optional. task_status: todo|in_progress|blocked|done|cancelled; priority: low|medium|high|urgent.
Inputs: tag_id, priority, x_user_id, project_id, +5 more. Returns: result
pm_list_teamsB
GET /teams — optional organization_id filter.
Inputs: x_user_id, organization_id. Returns: result
pm_list_user_labelsA
GET /user-labels — list global contact labels (not task tags).
Inputs: x_user_id. Returns: result
pm_list_usersA
GET /users — optional filters. user_kind: internal|client; label_ids: comma-separated UUIDs (OR); do not combine label_id and label_ids.
Inputs: team_id, label_id, label_ids, user_kind, +2 more. Returns: result
pm_task_attach_tagC
POST /tasks/{task_id}/tags — body {tag_id: ...}; tag_id also accepted as top-level arg for convenience.
Inputs: tag_id (required), task_id (required), x_user_id. Returns: result
pm_task_detach_tagC
DELETE /tasks/{task_id}/tags/{tag_id}.
Inputs: tag_id (required), task_id (required), x_user_id. Returns: result
pm_update_commentD
PATCH /comments/{comment_id}.
Inputs: payload (required), comment_id (required), x_user_id. Returns: result
pm_update_projectC
PATCH /projects/{project_id} — partial ProjectUpdate fields.
Inputs: payload (required), project_id (required), x_user_id. Returns: result
pm_update_project_fileB
PATCH /projects/{project_id}/files/{file_id} — partial ProjectFileUpdate (name, description_md, kind).
Inputs: file_id (required), payload (required), project_id (required), x_user_id. Returns: result
pm_update_tagD
PATCH /tags/{tag_id}.
Inputs: tag_id (required), payload (required), x_user_id. Returns: result
pm_update_taskC
PATCH /tasks/{task_id} — partial TaskUpdate.
Inputs: payload (required), task_id (required), x_user_id. Returns: result
pm_update_userA
PATCH /users/{user_id} — partial UserUpdate; requires X-User-Id (self or admin). Fields: display_name, email, phone, avatar_url, presence, role, user_kind, organization_id, team_id.
Inputs: payload (required), user_id (required), x_user_id. Returns: result
pm_upload_project_fileD
POST /projects/{project_id}/files — multipart upload; file bytes as standard base64.
Inputs: filename (required), project_id (required), file_content_base64 (required), kind, +3 more. Returns: result
pm_user_attach_labelC
POST /users/{user_id}/labels — admin only; attach a contact label to a user.
Inputs: user_id (required), label_id (required), x_user_id. Returns: result
pm_user_detach_labelC
DELETE /users/{user_id}/labels/{label_id} — admin only.
Inputs: user_id (required), label_id (required), x_user_id. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 46 tools
Each tool targets a distinct resource and action (e.g., pm_create_comment vs pm_create_task). The names and descriptions make it clear which entity is being operated on, with no overlapping functionality. The distinction between pm_list_tags and pm_list_user_labels is explicit.
All tools follow the consistent pattern `pm_verb_noun`. Verbs are standard (create, get, list, update, delete, upload, download, export, attach, detach) and nouns correspond to resources. No mixed conventions or vague names.
46 tools is well above the typical well-scoped range (3-15). Even for a comprehensive project manager, this number is high and may overwhelm agents. It borders on excessive, as per calibration (25+ is too many).
The server covers CRUD for many entities (projects, tasks, comments, tags, users, files) but lacks update operations for organizations, teams, and user labels. Also team and organization deletion are missing. These are notable gaps that agents may encounter.
Maintenance
Related MCP Connectors
Create projects, nodes, and tasks in UluP Spaces by conversation with Claude.
Manage Redbooth tasks, task lists, comments, tags and files from Claude and other AI assistants.
Lets Claude, ChatGPT, and Muse read and update your beckett tasks, notes, calendar, and lists.
Read your tracked time and projects, pause tracking or add a note, from Claude or ChatGPT.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceConnects Claude to self-hosted Vikunja instances for conversational task and project management. Supports CRUD operations on projects and tasks, plus labels, comments, weekly reviews, calendar feeds, and task relations.44 npm-
- AlicenseAqualityDmaintenanceEnables Claude to interact with Super Productivity's local REST API for task, project, and tag management, including CRUD operations, status checks, and daily planning prompts.17264 npmMIT
- AlicenseAqualityDmaintenanceEnables Claude to interact with System Task projects, teams, and tasks, providing daily briefs, project reports, team load, and risk identification, as well as creating and updating tasks and demands.15MIT
- AlicenseNot gradedqualityBmaintenanceEnables Claude Code to read and update tasks in the Nexus/TaskBridge project management system through its public API.90 npmISC