project_list
List and filter projects within an organization to manage project structures and track progress using SQLite database queries.
Instructions
PROJECT MANAGEMENT: List projects in an organization.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| org_id | No | Filter by organization ID (case-insensitive) |
Implementation Reference
- src/tpm_mcp/server.py:520-522 (handler)The main handler logic for the 'project_list' tool within the _handle_tool function. It calls the database helper with optional org_id filter and returns JSON-serialized projects.if name == "project_list": projects = db.list_projects(args.get("org_id")) return _json([p.model_dump() for p in projects])
- src/tpm_mcp/server.py:446-455 (schema)Tool schema definition including name, description, and input schema (optional org_id filter). This is returned by list_tools().Tool( name="project_list", description="PROJECT MANAGEMENT: List projects in an organization.", inputSchema={ "type": "object", "properties": { "org_id": {"type": "string", "description": "Filter by organization ID (case-insensitive)"} }, }, ),
- src/tpm_mcp/server.py:39-476 (registration)The @server.list_tools() decorator registers all tools including 'project_list' by returning the list of Tool objects.@server.list_tools() async def list_tools() -> list[Tool]: return [ # Roadmap view - PRIMARY TOOL for checking status Tool( name="roadmap_view", description="""PROJECT MANAGEMENT (TPM): Get project roadmap showing work status. USE THIS TOOL WHEN: - User asks "what's in progress?" or "what are we working on?" - User asks "TPM status", ":TPM:" prefix, or "show me the roadmap" - User asks about pending/blocked/completed work - Starting a work session to see current state - User completes work and you need to find related tasks to mark done Returns summary of organizations, projects, and tickets. Use project_id filter to reduce output.""", inputSchema={ "type": "object", "properties": { "org_id": { "type": "string", "description": "Filter by organization ID (optional) case-insensitive", }, "project_id": { "type": "string", "description": "Filter by project ID (optional) - recommended to reduce output size", }, "active_only": { "type": "boolean", "description": "Only show non-done tickets (default: true)", "default": True, }, }, }, ), # Ticket operations Tool( name="ticket_create", description="""PROJECT MANAGEMENT (TPM): Create a new ticket, epic, or issue to track. USE THIS TOOL WHEN: - User says ":TPM: Add X feature to the roadmap" - User wants to add a new feature/ticket/issue - User says "add ticket for X" or "create feature for Y" - Breaking down work into trackable items - User asks to scope out or define new work - User discusses new work that should be tracked Use roadmap_view first to get the project_id. Tickets are high-level work items (like Jira epics/stories). ID AUTO-GENERATION: IDs are always auto-generated as {PREFIX}-{NNN} (e.g., FEAT-001, ISSUE-042). The number is automatically incremented based on existing tickets with that prefix. OPTIONAL PREFIX PARAMETER: Provide a prefix to categorize the ticket type: - FEAT: New features or capabilities - ISSUE: Bugs, problems, or issues to fix - TASK: General tasks or chores - INFRA: Infrastructure or DevOps work - DOC: Documentation tasks If no prefix is provided, uses the project ID as the prefix (e.g., FRONTEND-001, BACKEND-042).""", inputSchema={ "type": "object", "properties": { "project_id": { "type": "string", "description": "Project ID (use project_list to find) case-insensitive", }, "prefix": { "type": "string", "description": "Optional prefix for ticket ID (e.g., FEAT, ISSUE, INFRA). Number is auto-generated. If omitted, uses project ID as prefix.", }, "title": {"type": "string", "description": "Ticket title"}, "description": { "type": "string", "description": "Detailed description of the ticket", }, "status": { "type": "string", "enum": ["backlog", "planned", "in-progress", "done", "blocked"], "description": "Ticket status (default: backlog)", }, "priority": { "type": "string", "enum": ["critical", "high", "medium", "low"], "description": "Priority level (default: medium)", }, "tags": { "type": "array", "items": {"type": "string"}, "description": "Tags for categorization", }, "assignees": { "type": "array", "items": {"type": "string"}, "description": "Who is working on this", }, }, "required": ["project_id", "title"], }, ), Tool( name="ticket_update", description="""PROJECT MANAGEMENT (TPM): Update a ticket's status, priority, or details. USE THIS TOOL WHEN: - User says "I just finished implementing X" - mark related ticket as done - User says "I've pushed commits for X" - update status based on progress - Marking work as in-progress, done, or blocked - Changing priority of a ticket - User completes a ticket and needs to update status - Adding/updating tags or assignees Use roadmap_view first to find the ticket_id.""", inputSchema={ "type": "object", "properties": { "ticket_id": {"type": "string", "description": "Ticket ID (e.g., FEAT-001)"}, "title": {"type": "string", "description": "New title"}, "description": {"type": "string", "description": "New description"}, "status": { "type": "string", "enum": ["backlog", "planned", "in-progress", "done", "blocked"], "description": "New status", }, "priority": { "type": "string", "enum": ["critical", "high", "medium", "low"], "description": "New priority", }, "tags": { "type": "array", "items": {"type": "string"}, "description": "Updated tags", }, "assignees": { "type": "array", "items": {"type": "string"}, "description": "Updated assignees", }, }, "required": ["ticket_id"], }, ), Tool( name="ticket_list", description="PROJECT MANAGEMENT: List ticket IDs with status/priority. Returns id, status, priority only - use ticket_get for details.", inputSchema={ "type": "object", "properties": { "project_id": {"type": "string", "description": "Filter by project ID (case-insensitive)"}, "status": { "type": "string", "enum": ["backlog", "planned", "in-progress", "done", "blocked"], "description": "Filter by status", }, "limit": { "type": "integer", "description": "Max tickets to return (default: 50, max: 200)", "default": 50, }, "offset": { "type": "integer", "description": "Skip first N tickets for pagination (default: 0)", "default": 0, }, }, }, ), Tool( name="ticket_search", description="""PROJECT MANAGEMENT (TPM): Search tickets by keyword. USE THIS TOOL WHEN: - User asks "find tickets about X" or "search for Y" - Looking for tickets by keywords in title or description - Need to discover relevant tickets across projects Searches title and description. Supports prefix matching (e.g., "org" matches "organization"). Case-insensitive. All filters are combinable.""", inputSchema={ "type": "object", "properties": { "query": { "type": "string", "description": "Search query (keywords to search in title/description)", }, "project_id": { "type": "string", "description": "Filter by project ID (optional, case-insensitive)", }, "status": { "type": "string", "enum": ["backlog", "planned", "in-progress", "done", "blocked"], "description": "Filter by status (optional)", }, "priority": { "type": "string", "enum": ["critical", "high", "medium", "low"], "description": "Filter by priority (optional)", }, "tags": { "type": "array", "items": {"type": "string"}, "description": "Filter by tags - ticket must have all specified tags (optional)", }, "limit": { "type": "integer", "description": "Maximum results to return (default: 20, max: 100)", "default": 20, }, }, "required": ["query"], }, ), Tool( name="ticket_get", description="""PROJECT MANAGEMENT: Get info about a ticket and its tasks. IMPORTANT: Do NOT pass detail='full' unless explicitly asked for full/all details. The default 'summary' is sufficient for most queries. Only use 'full' when user specifically asks for implementation details, metadata, or complete task information.""", inputSchema={ "type": "object", "properties": { "ticket_id": {"type": "string", "description": "Ticket ID (e.g., FEAT-001)"}, "detail": { "type": "string", "enum": ["minimal", "summary", "full"], "description": "OMIT this param for most requests (defaults to 'summary'). Only use 'full' if user explicitly asks for all details/metadata.", "default": "summary", }, }, "required": ["ticket_id"], }, ), Tool( name="task_get", description="""PROJECT MANAGEMENT: Get full details of ONE specific task. Use this to drill into a single task's implementation details (metadata, files_to_modify, technical_notes). Prefer ticket_get for overview, use this only when you need deep task details.""", inputSchema={ "type": "object", "properties": { "task_id": { "type": "string", "description": "Task ID (e.g., SUBTASK-007-1 or TASK-abc123-1)", } }, "required": ["task_id"], }, ), # Task operations Tool( name="task_create", description="""PROJECT MANAGEMENT (TPM): Create a task (sub-item) under a ticket. USE THIS TOOL WHEN: - Breaking down a ticket into smaller tasks - User asks to add implementation steps - Creating a work breakdown structure""", inputSchema={ "type": "object", "properties": { "ticket_id": {"type": "string", "description": "Parent ticket ID"}, "title": {"type": "string", "description": "Task title"}, "details": { "type": "string", "description": "Task details/implementation notes", }, "status": { "type": "string", "enum": ["pending", "in-progress", "done", "blocked"], "description": "Task status (default: pending)", }, "priority": { "type": "string", "enum": ["critical", "high", "medium", "low"], "description": "Priority (default: medium)", }, "complexity": { "type": "string", "enum": ["simple", "medium", "complex"], "description": "Complexity estimate (default: medium)", }, }, "required": ["ticket_id", "title"], }, ), Tool( name="task_update", description="PROJECT MANAGEMENT (TPM): Update a task's status or details. Use when completing or updating task progress.", inputSchema={ "type": "object", "properties": { "task_id": {"type": "string", "description": "Task ID (e.g., TASK-001-1)"}, "title": {"type": "string", "description": "New title"}, "details": {"type": "string", "description": "New details"}, "status": { "type": "string", "enum": ["pending", "in-progress", "done", "blocked"], "description": "New status", }, "priority": { "type": "string", "enum": ["critical", "high", "medium", "low"], "description": "New priority", }, "complexity": { "type": "string", "enum": ["simple", "medium", "complex"], "description": "New complexity", }, }, "required": ["task_id"], }, ), Tool( name="task_list", description="PROJECT MANAGEMENT (TPM): List task IDs with status. Returns id, ticket_id, status only - use task_get for details.", inputSchema={ "type": "object", "properties": { "ticket_id": {"type": "string", "description": "Filter by ticket ID"}, "status": { "type": "string", "enum": ["pending", "in-progress", "done", "blocked"], "description": "Filter by status", }, "limit": { "type": "integer", "description": "Max tasks to return (default: 50, max: 200)", "default": 50, }, "offset": { "type": "integer", "description": "Skip first N tasks for pagination (default: 0)", "default": 0, }, }, }, ), # Notes Tool( name="note_add", description="PROJECT MANAGEMENT (TPM): Add a note/comment to a ticket or task for context or decisions.", inputSchema={ "type": "object", "properties": { "entity_type": { "type": "string", "enum": ["org", "project", "ticket", "task"], "description": "Type of entity", }, "entity_id": {"type": "string", "description": "ID of the entity"}, "content": {"type": "string", "description": "Note content"}, }, "required": ["entity_type", "entity_id", "content"], }, ), Tool( name="note_list", description="PROJECT MANAGEMENT (TPM): List notes for an entity. Returns id, created_at, preview (first 100 chars). Use note_get for full content.", inputSchema={ "type": "object", "properties": { "entity_type": { "type": "string", "enum": ["org", "project", "ticket", "task"], "description": "Type of entity", }, "entity_id": {"type": "string", "description": "ID of the entity"}, "limit": { "type": "integer", "description": "Max notes to return (default: 20, max: 50)", "default": 20, }, }, "required": ["entity_type", "entity_id"], }, ), Tool( name="note_get", description="PROJECT MANAGEMENT (TPM): Get full content of a specific note by ID.", inputSchema={ "type": "object", "properties": { "note_id": {"type": "string", "description": "Note ID"}, }, "required": ["note_id"], }, ), # Org/Project operations (less frequently used) Tool( name="org_list", description="PROJECT MANAGEMENT: List all organizations. Usually only one org exists.", inputSchema={"type": "object", "properties": {}}, ), Tool( name="org_create", description="PROJECT MANAGEMENT: Create a new organization (rarely needed).", inputSchema={ "type": "object", "properties": {"name": {"type": "string", "description": "Organization name"}}, "required": ["name"], }, ), Tool( name="project_list", description="PROJECT MANAGEMENT: List projects in an organization.", inputSchema={ "type": "object", "properties": { "org_id": {"type": "string", "description": "Filter by organization ID (case-insensitive)"} }, }, ), Tool( name="project_create", description="PROJECT MANAGEMENT: Create a new project under an organization.", inputSchema={ "type": "object", "properties": { "org_id": {"type": "string", "description": "Organization ID (case-insensitive)"}, "name": {"type": "string", "description": "Project name"}, "repo_path": {"type": "string", "description": "Path to git repo"}, "description": {"type": "string", "description": "Project description"}, }, "required": ["org_id", "name"], }, ), # Info tool Tool( name="info", description="Get information about the tracker MCP server: database location, stats, and usage.", inputSchema={"type": "object", "properties": {}}, ), ]
- src/tpm_mcp/db.py:238-256 (helper)Database method that implements the core logic: queries projects table with optional case-insensitive org_id filter, ordered by name, and constructs Project model instances.def list_projects(self, org_id: str | None = None) -> list[Project]: if org_id: org_id = self._normalize_id(org_id) rows = self.conn.execute( "SELECT * FROM projects WHERE LOWER(org_id) = ? ORDER BY name", (org_id,) ).fetchall() else: rows = self.conn.execute("SELECT * FROM projects ORDER BY name").fetchall() return [ Project( id=r["id"], org_id=r["org_id"], name=r["name"], repo_path=r["repo_path"], description=r["description"], created_at=datetime.fromisoformat(r["created_at"]), ) for r in rows ]