Productive
FreeNot checkedIntegrates with Productive.io project management platform to access projects, tasks, pages, and teams
About
Integrates with Productive.io project management platform to access projects, tasks, pages, and teams
README
License: MIT
Productive-GET-MCP MCP server
A Model Context Protocol (MCP) server for integrating Productive.io into AI workflows. This server allows AI assistants and tools to access projects, folders, workflow statuses, time entries, tasks, comments, pages, attachments, todos, and people. Built with FastMCP.
This implementation is optimized for read-focused operations, with optional guarded write capabilities (for example, task creation) and LLM-friendly output options (Hybrid, JSON, and TOON). It is optimized for efficiency and simplicity, exposing only the necessary information. For a more comprehensive solution, consider BerwickGeek's implementation: Productive MCP by BerwickGeek.
Features
Read Tools
- List Projects: Retrieve all projects with basic information
- List Folders: Retrieve folders within a project
- Get Folder: Retrieve a specific folder by ID
- List Workflow Statuses: Retrieve workflow statuses with optional filters
- List Time Entries: Retrieve time entries with optional date and relationship filters
- List Tasks: Retrieve tasks with filtering and pagination
- Get Task: Retrieve a specific task by internal ID
- Get Task History: Retrieve task status changes, assignments, milestones, and activity summaries
- List Comments: Retrieve comments with filtering
- List Pages: Retrieve pages/documents with filtering
- Get Page: Retrieve a specific page/document by ID
- List Attachments: Retrieve attachments/files with filtering
- List Todos: Retrieve todo checklist items with filtering
- Get Todo: Retrieve a specific todo by ID
- List People: Retrieve people/team members with pagination
- Get Person: Retrieve a specific person by ID
- List Recent Activity: Summarized activity feed for status updates
- Quick Search: Fast, comprehensive search across projects, tasks, pages, and actions
Write Tools (blocked when READ_ONLY=true)
- Create Task: Create a new task in a project
- Update Task: Update task fields — title, description, assignee, due date, status, board, task list
- Delete Task: Permanently delete a task by ID (irreversible)
- Create Comment: Create a new comment on a task or project
- Update Comment: Update a comment body
- Delete Comment: Permanently delete a comment by ID (irreversible)
- Create Time Entry: Log time spent on tasks or services
- Update Time Entry: Modify existing time entries
- Delete Time Entry: Remove time entries (irreversible)
- Create Page: Create new documents/pages in projects
- Update Page: Edit page content and titles
- Delete Page: Remove pages/documents (irreversible)
- Create Todo: Add checklist items to tasks
- Update Todo: Modify todo items and completion status
- Delete Todo: Remove todo items (irreversible)
Additional Features
- LLM-Optimized Responses: Filtered output removes noise, strips HTML, and reduces token consumption
Requirements
- Python 3.10+
- Productive API token
- FastMCP 3.x
Installation
- Clone or download this repository
- Install dependencies:
pip install -r requirements.txt
or
uv venv && uv sync
Configuration
The server uses environment variables for configuration:
PRODUCTIVE_API_KEY: Your Productive API token (required)PRODUCTIVE_ORGANIZATION: Your Productive organization ID (required)PRODUCTIVE_BASE_URL: Base URL for Productive API (default: https://api.productive.io/api/v2)PRODUCTIVE_TIMEOUT: Request timeout in seconds (default: 30)OUTPUT_FORMAT: Output format for tool responses ("hybrid","toon", or"json", default:"hybrid")READ_ONLY: Global write-protection toggle for write tools — create_task, update_task, delete_task, create_comment, update_comment, delete_comment, create_time_entry, update_time_entry, delete_time_entry, create_page, update_page, delete_page, create_todo, update_todo, delete_todo ("true" or "false", default: "true")
Usage
Using uvx from GitHub (Recommended for MCP clients)
"productive": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/druellan/Productive-Simple-MCP",
"productive-mcp"
],
"env": {
"PRODUCTIVE_API_KEY": "<api-key>",
"PRODUCTIVE_ORGANIZATION": "<organization-id>"
}
}
Using uvx from GitHub with TOON output enabled
"productive": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/druellan/Productive-Simple-MCP",
"productive-mcp"
],
"env": {
"PRODUCTIVE_API_KEY": "<api-key>",
"PRODUCTIVE_ORGANIZATION": "<organization-id>",
"OUTPUT_FORMAT": "toon"
}
}
Local Development (Direct Python Execution)
"productive": {
"command": "python",
"args": [
"server.py"
],
"env": {
"PRODUCTIVE_API_KEY": "<api-key>",
"PRODUCTIVE_ORGANIZATION": "<organization-id>"
}
}
Local Development Using UV
"productive": {
"command": "uv",
"args": [
"--directory", "<path-to-productive-mcp>",
"run", "server.py"
],
"env": {
"PRODUCTIVE_API_KEY": "<api-key>",
"PRODUCTIVE_ORGANIZATION": "<organization-id>"
}
}
Available Tools
Read Tools
list_projects
Retrieve all projects with basic information.
Properties:
- No parameters (returns all projects)
list_folders
Retrieve folders within a specific project.
Productive's API exposes these resources through the /folders endpoint.
Properties:
project_id(int, required): Filter folders by Productive project IDstatus(int, optional): Folder status filter (1active,2archived). Defaults to1limit(int, optional): Maximum number of folders to return (default: 50, max: 200)
get_folder
Retrieve a specific folder by its ID.
Productive's API exposes this resource through the /folders endpoint.
Properties:
folder_id(int): The unique Productive folder identifier
list_workflow_statuses
Retrieve workflow statuses with optional filters.
Properties:
workflow_id(int, optional): Filter statuses by workflow IDcategory_id(int, optional): Filter by category (1Not Started,2Started,3Closed)limit(int, optional): Maximum number of statuses to return (default: 50, max: 200)
list_time_entries
Retrieve time entries with optional date and relationship filters.
Properties:
date(str, optional): Exact date filter (YYYY-MM-DD)after(str, optional): Lower bound date filter (YYYY-MM-DD)before(str, optional): Upper bound date filter (YYYY-MM-DD)person_id(int, optional): Filter by person IDproject_id(int, optional): Filter by project IDtask_id(int, optional): Filter by task IDservice_id(int, optional): Filter by service IDpage_number(int, optional): Page number for paginationlimit(int, optional): Maximum number of entries to return (default: 50, max: 200)
list_people
Retrieve people/team members with optional pagination.
Properties:
page_number(int, optional): Page number for paginationpage_size(int, optional): Number of people to return per page (max: 200)
get_person
Retrieve a specific person by ID.
Properties:
person_id(int): The unique Productive person identifier
list_tasks
Retrieve tasks with optional filtering and pagination.
Properties:
project_id(int, optional): Filter tasks by Productive project IDuser_id(int, optional): Filter tasks by assignee/user IDpage_number(int, optional): Page number for paginationpage_size(int, optional): Page size for pagination (default: 50)sort(str, optional): Sort parameter (e.g., 'last_activity_at', '-last_activity_at', 'created_at', 'due_date')extra_filters(dict, optional): Additional Productive API filters (e.g.,{'filter[status][eq]': 1}for open tasks,{'filter[status][eq]': 2}for closed tasks)
get_task
Retrieve a specific task by its internal ID. Returns task details including title, description, status, dates, time tracking metrics (initial_estimate, worked_time, billable_time, remaining_time), and todo counts.
Properties:
task_id(int): The unique Productive task identifier (internal ID, e.g., 14677418)
get_task_history
Retrieve the full history for a specific task, including status changes, assignment history, milestones, and activity summary.
Properties:
task_id(int): The unique Productive task identifier (internal ID, e.g., 14677418)hours(int, optional): Number of hours to look back for activity history (default: 720 = 30 days, max: 8760)
Returns:
status_history: Timeline of status changes with timestamps (from/to status and changed_at)assignment_history: Assignment changes showing who was assigned and when (assigned_to and changed_at)milestones: Key deliverables and completion markers from comments and activitiesactivity_summary: Counts of comments, changes, status updates, assignments, and milestones
Example:
get_task_history(14677921) # Default 30-day history
get_task_history(14677921, hours=168) # Last week only
get_task_history(14677921, hours=24) # Last 24 hours
list_comments
Retrieve comments with optional filtering and pagination.
Properties:
project_id(int, optional): Filter comments by Productive project IDtask_id(int, optional): Filter comments by Productive task IDpage_number(int, optional): Page number for paginationpage_size(int, optional): Page size for paginationextra_filters(dict, optional): Additional Productive API filters (e.g.,{'filter[discussion_id]': '123'})
list_pages
Retrieve pages/documents with optional filtering and pagination.
Properties:
project_id(int, optional): Filter pages by Productive project IDcreator_id(int, optional): Filter pages by creator IDpage_number(int, optional): Page number for paginationpage_size(int, optional): Page size for pagination
get_page
Retrieve a specific page/document by ID.
Properties:
page_id(int): The unique Productive page identifier
list_attachments
Retrieve attachments/files with optional filtering and pagination.
Properties:
page_number(int, optional): Page number for paginationpage_size(int, optional): Page size for paginationextra_filters(dict, optional): Additional Productive API filters
list_recent_activity
Get a summarized feed of recent activities and updates. Perfect for status updates.
Properties:
hours(int, optional): Number of hours to look back (default: 24, use 168 for a week)user_id(int, optional): Filter by specific user/person IDproject_id(int, optional): Filter by specific project IDactivity_type(int, optional): Filter by activity type (1: Comment, 2: Changeset, 3: Email)item_type(str, optional): Filter by item type (e.g., 'Task', 'Page', 'Deal', 'Workspace')event_type(str, optional): Filter by event type (e.g., 'create', 'copy', 'update', 'delete')task_id(int, optional): Filter by specific task IDmax_results(int, optional): Maximum number of activities to return (default: 100, max: 200)
list_todos
Retrieve todo checklist items with optional filtering and pagination.
Properties:
task_id(int, optional): Filter todos by Productive task IDpage_number(int, optional): Page number for paginationpage_size(int, optional): Page size for paginationextra_filters(dict, optional): Additional Productive API filters
quick_search
Quick search across projects, tasks, pages, and actions.
Properties:
query(str): Search query stringsearch_types(list[str], optional): List of types to search (action, project, task, page). Defaults to all.deep_search(bool, optional): Whether to perform deep search (default: True)page(int, optional): Page number for pagination (default: 1)per_page(int, optional): Results per page (default: 50)
Description: Provides fast, comprehensive search across all Productive content types including projects, tasks, pages, and actions. It's optimized for quick lookups and general search queries.
Response Format: Returns filtered results optimized for LLM consumption with only essential fields:
record_id: Unique identifier for the resourcerecord_type: Type of resource (project, task, page, etc.)title: Display title (with search highlights removed)subtitle: Additional context or descriptionicon_url: URL to the resource's icon/avatar (if available)status: Current status (active, closed, etc.)project_name: Name of the associated projectupdated_at: Last update timestampwebapp_url: Direct link to view the resource in Productive web interface
Examples:
quick_search("deployment") # Search for "deployment" across all content types
quick_search("meeting notes", search_types=["project"]) # Search only in projects
quick_search("this week summary", deep_search=False) # Quick search without deep scan
get_todo
Retrieve a specific todo checklist item by ID.
Properties:
todo_id(int): The unique Productive todo checklist item identifier
Write Tools
create_task
Create a new task in Productive.
When READ_ONLY=true, this tool is blocked globally and returns a write-protection error.
Properties:
title(str, required): Task titleproject_id(int, required): Productive project ID where the task will be createddescription(str, optional): Task descriptionboard_id(int, optional): Board IDtask_list_id(int, optional): Task list IDassignee_id(int, optional): Assignee/person IDdue_date(str, optional): Due date (YYYY-MM-DD)status(str, optional):openorclosed(default:open)
update_task
Update an existing task in Productive. Only provided fields are modified (partial PATCH).
At least one field must be given. When READ_ONLY=true, this tool is blocked globally.
Properties:
task_id(int, required): Productive task ID to updatetitle(str, optional): New task titledescription(str, optional): New task descriptionassignee_id(int, optional): New assignee person ID. Use 0 or negative to unassign.due_date(str, optional): New due date (YYYY-MM-DD)status(str, optional): New status —openorclosedboard_id(int, optional): Move task to this boardtask_list_id(int, optional): Move task to this task list
delete_task
Permanently delete a task from Productive by its ID. This action is irreversible —
the task and all associated data will be removed. When READ_ONLY=true, this tool is
blocked globally.
Properties:
task_id(int, required): Productive task ID to delete
create_comment
Create a new comment on a task or project in Productive. A comment must be attached to
at least one of task or project. When READ_ONLY=true, this tool is blocked globally.
Properties:
body(str, required): Comment body text (HTML supported)task_id(int, optional): Productive task ID to attach the comment toproject_id(int, optional): Productive project ID to attach the comment to
update_comment
Update an existing comment in Productive. Only the body attribute can be modified.
When READ_ONLY=true, this tool is blocked globally.
Properties:
comment_id(int, required): Productive comment ID to updatebody(str, required): New comment body text (HTML supported)
delete_comment
Permanently delete a comment from Productive by its ID. This action is irreversible —
the comment will be removed from the task or project. When READ_ONLY=true, this tool
is blocked globally.
Properties:
comment_id(int, required): Productive comment ID to delete
create_time_entry
Create a new time entry in Productive for time tracking.
Logs time spent on tasks or services. Either task_id or service_id must be provided.
When READ_ONLY=true, this tool is blocked globally.
Properties:
date(str, required): Date for the time entry (YYYY-MM-DD)time(float, required): Time spent in hours (e.g., 2.5)person_id(int, required): Person ID who logged the timetask_id(int, optional): Task ID to associate the time entry withservice_id(int, optional): Service ID to associate the time entry withnote(str, optional): Optional note or description
update_time_entry
Update an existing time entry in Productive. Only provided fields are modified (partial PATCH).
At least one field must be given. When READ_ONLY=true, this tool is blocked globally.
Properties:
time_entry_id(int, required): Productive time entry ID to updatedate(str, optional): New date (YYYY-MM-DD)time(float, optional): New time in hoursperson_id(int, optional): New person IDtask_id(int, optional): New task IDservice_id(int, optional): New service IDnote(str, optional): New note
delete_time_entry
Permanently delete a time entry from Productive by its ID. This action is irreversible —
the time entry will be removed from time tracking records. When READ_ONLY=true, this tool
is blocked globally.
Properties:
time_entry_id(int, required): Productive time entry ID to delete
create_page
Create a new page/document in a Productive project.
Pages are documents that can contain rich text content and are organized within projects.
When READ_ONLY=true, this tool is blocked globally.
Properties:
title(str, required): Page titleproject_id(int, required): Productive project ID where the page will be createdcontent(str, optional): Page content (HTML supported)
update_page
Update an existing page/document in Productive. Only provided fields are modified (partial PATCH).
At least one field must be given. When READ_ONLY=true, this tool is blocked globally.
Properties:
page_id(int, required): Productive page ID to updatetitle(str, optional): New page titlecontent(str, optional): New page content (HTML supported)
delete_page
Permanently delete a page/document from Productive by its ID. This action is irreversible —
the page and all its content will be removed. When READ_ONLY=true, this tool is blocked globally.
Properties:
page_id(int, required): Productive page ID to delete
create_todo
Create a new todo checklist item for a task in Productive.
Todos are checkbox items within tasks for granular tracking of work items.
When READ_ONLY=true, this tool is blocked globally.
Properties:
content(str, required): Todo item content/descriptiontask_id(int, required): Productive task ID to add the todo to
update_todo
Update an existing todo checklist item in Productive. Only provided fields are modified (partial PATCH).
At least one field must be given. When READ_ONLY=true, this tool is blocked globally.
Properties:
todo_id(int, required): Productive todo ID to updatecontent(str, optional): New todo contentcompleted(bool, optional): Mark todo as completed (true) or incomplete (false)
delete_todo
Permanently delete a todo checklist item from Productive by its ID. This action is irreversible —
the todo item will be removed from the task. When READ_ONLY=true, this tool is blocked globally.
Properties:
todo_id(int, required): Productive todo ID to delete
Output Format
The server supports three output formats configured via the OUTPUT_FORMAT environment variable:
| Mode | content (text) |
structured_content |
Description |
|---|---|---|---|
hybrid (default) |
TOON | JSON dict | Both TOON for token efficiency and structured data for programmatic access |
toon |
TOON | { "toon": toonText } |
Pure TOON (Token-Optimized Object Notation) with no dual-format overhead |
json |
JSON string | JSON dict | Standard FastMCP JSON output |
TOON (Token-Optimized Object Notation) reduces token consumption by 30-60% compared to JSON. The hybrid mode is the recommended default: it exposes the TOON rendering as the message text while preserving the full JSON dict as structured output, so agents that rely on structured data can still parse it programmatically.
All tools return filtered data optimized for LLM processing:
LLM Optimizations:
- Unwanted fields removed (e.g.,
creation_method_id,email_key,placementfrom tasks) - HTML stripped from descriptions and comments
- Empty/null values removed
- Pagination links removed
- List views use lightweight output (e.g.,
get_project_tasksexcludes descriptions and relationships) - Web app URLs included: Each resource includes a
webapp_urlfield linking directly to the Productive web interface
Response Structure:
data: Main resource data (array for collections, object for single items)meta: Pagination and metadataincluded: Related resource data (when applicable)webapp_url: Direct link to view the resource in Productive (e.g.,https://app.productive.io/12345/tasks/67890)
Error Handling
The server provides comprehensive error handling:
- 401 Unauthorized: Invalid API token
- 404 Not Found: Resource not found
- 429 Rate Limited: Too many requests
- 500 Server Error: Productive API issues
All errors are logged via MCP context with appropriate severity levels.
Security
- API tokens are loaded from environment variables
- No sensitive data is logged
- HTTPS is used for all API requests
- Error messages don't expose internal details
License
MIT License.
Installing Productive
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/druellan/productive-simple-mcpFAQ
Is Productive MCP free?
Yes, Productive MCP is free — one-click install via Unyly at no cost.
Does Productive need an API key?
No, Productive runs without API keys or environment variables.
Is Productive hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Productive in Claude Desktop, Claude Code or Cursor?
Open Productive on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Gmail
Read, send and search emails from Claude
by GoogleSlack
Send, search and summarize Slack messages
by SlackRunbear
No-code MCP client for team chat platforms, such as Slack, Microsoft Teams, and Discord.
Discord Server
A community discord server dedicated to MCP by [Frank Fiegel](https://github.com/punkpeye)
Compare Productive with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All communication MCPs
