getProjects
Retrieve all Teamwork projects with customizable filters for date ranges, user assignments, and detailed inclusion of project metadata like budget, profitability, and custom fields.
Instructions
Get all projects from Teamwork
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| updatedAfter | No | Filter projects updated after this date-time (format: ISO 8601) | |
| timeMode | No | Profitability time mode | |
| searchTerm | No | Filter by project name | |
| reportType | No | Define the type of the report | |
| reportTimezone | No | Configure the report dates displayed in a timezone | |
| reportFormat | No | Define the format of the report | |
| projectType | No | Filter by project type | |
| orderMode | No | Order mode | |
| orderBy | No | Order by field | |
| notCompletedBefore | No | Filter by projects that have not been completed before the given date (format: YYYY-MM-DD) | |
| minLastActivityDate | No | Filter by min last activity date (format: YYYY-MM-DD) | |
| maxLastActivityDate | No | Filter by max last activity date (format: YYYY-MM-DD) | |
| userId | No | Filter by user id | |
| pageSize | No | Number of items in a page (not used when generating reports) | |
| page | No | Page number (not used when generating reports) | |
| orderByCustomFieldId | No | Order by custom field id when orderBy is equal to customfield | |
| minBudgetCapacityUsedPercent | No | Filter by minimum budget capacity used | |
| maxBudgetCapacityUsedPercent | No | Filter by maximum budget capacity used | |
| includeArchivedProjects | No | Include archived projects | |
| includeCompletedProjects | No | Include completed projects | |
| includeProjectOwner | No | Include project owner | |
| includeProjectCreator | No | Include project creator | |
| includeProjectCompany | No | Include project company | |
| includeProjectCategory | No | Include project category | |
| includeProjectTags | No | Include project tags | |
| includeProjectStatus | No | Include project status | |
| includeProjectHealth | No | Include project health | |
| includeProjectBudget | No | Include project budget | |
| includeProjectProfitability | No | Include project profitability | |
| includeProjectCustomFields | No | Include project custom fields | |
| includeProjectBillingMethod | No | Include project billing method | |
| includeProjectRateCards | No | Include project rate cards | |
| includeProjectRateCardRates | No | Include project rate card rates | |
| includeProjectRateCardCurrencies | No | Include project rate card currencies | |
| includeProjectRateCardUsers | No | Include project rate card users | |
| includeProjectRateCardUserRates | No | Include project rate card user rates | |
| includeProjectRateCardUserCurrencies | No | Include project rate card user currencies | |
| includeProjectRateCardTasks | No | Include project rate card tasks | |
| includeProjectRateCardTaskRates | No | Include project rate card task rates | |
| includeProjectRateCardTaskCurrencies | No | Include project rate card task currencies |
Implementation Reference
- The handleGetProjects function is the tool handler that receives input, calls teamworkService.getProjects(), processes the response, and returns formatted content. It handles null/undefined, arrays, and paginated response objects.
export async function handleGetProjects(input: any) { logger.info('=== getProjects tool called ==='); logger.info(`Query parameters: ${JSON.stringify(input || {})}`); try { logger.info('Calling teamworkService.getProjects()'); const projects = await teamworkService.getProjects(input); // Debug the response logger.info(`Projects response type: ${typeof projects}`); if (projects === null || projects === undefined) { logger.warn('Projects response is null or undefined'); return { content: [{ type: "text", text: "No projects found or API returned empty response." }] }; } else if (Array.isArray(projects)) { logger.info(`Projects array length: ${projects.length}`); if (projects.length === 0) { return { content: [{ type: "text", text: "No projects found. The API returned an empty array." }] }; } } else if (typeof projects === 'object') { // Check if it's a paginated response with 'projects' property if (projects.projects && Array.isArray(projects.projects)) { logger.info(`Projects array found in response object. Length: ${projects.projects.length}`); if (projects.projects.length === 0) { return { content: [{ type: "text", text: "No projects found. The API returned an empty projects array." }] }; } } else { logger.info(`Projects response is an object: ${JSON.stringify(projects).substring(0, 200)}...`); } } else { logger.info(`Projects response is not an array or object: ${JSON.stringify(projects).substring(0, 200)}...`); } try { const jsonString = JSON.stringify(projects, null, 2); logger.info(`Successfully stringified projects response`); logger.info('=== getProjects tool completed successfully ==='); return { content: [{ type: "text", text: jsonString }] }; } catch (jsonError: any) { logger.error(`JSON stringify error: ${jsonError.message}`); return { content: [{ type: "text", text: `Error converting response to JSON: ${jsonError.message}` }] }; } } catch (error: any) { return createErrorResponse(error, 'Retrieving projects'); } } - The getProjectsDefinition object defines the tool name 'getProjects', description, and inputSchema with all supported parameters (string, integer, boolean types) plus annotations.
export const getProjectsDefinition = { name: "getProjects", description: "Get all projects from Teamwork", inputSchema: { type: "object", properties: { // String parameters updatedAfter: { type: "string", description: "Filter projects updated after this date-time (format: ISO 8601)" }, timeMode: { type: "string", enum: ["timelogs", "estimated"], description: "Profitability time mode" }, searchTerm: { type: "string", description: "Filter by project name" }, reportType: { type: "string", enum: ["project", "health"], description: "Define the type of the report" }, reportTimezone: { type: "string", description: "Configure the report dates displayed in a timezone" }, reportFormat: { type: "string", enum: ["csv", "html", "pdf", "xls"], description: "Define the format of the report" }, projectType: { type: "string", description: "Filter by project type" }, orderMode: { type: "string", enum: ["asc", "desc"], description: "Order mode" }, orderBy: { type: "string", enum: ["companyname", "datecreated", "duedate", "lastactivity", "name", "namecaseinsensitive", "ownercompany", "starred", "categoryname"], description: "Order by field" }, notCompletedBefore: { type: "string", description: "Filter by projects that have not been completed before the given date (format: YYYY-MM-DD)" }, minLastActivityDate: { type: "string", description: "Filter by min last activity date (format: YYYY-MM-DD)" }, maxLastActivityDate: { type: "string", description: "Filter by max last activity date (format: YYYY-MM-DD)" }, // Integer parameters userId: { type: "integer", description: "Filter by user id" }, pageSize: { type: "integer", description: "Number of items in a page (not used when generating reports)" }, page: { type: "integer", description: "Page number (not used when generating reports)" }, orderByCustomFieldId: { type: "integer", description: "Order by custom field id when orderBy is equal to customfield" }, minBudgetCapacityUsedPercent: { type: "integer", description: "Filter by minimum budget capacity used" }, maxBudgetCapacityUsedPercent: { type: "integer", description: "Filter by maximum budget capacity used" }, // Boolean parameters includeArchivedProjects: { type: "boolean", description: "Include archived projects" }, includeCompletedProjects: { type: "boolean", description: "Include completed projects" }, includeProjectOwner: { type: "boolean", description: "Include project owner" }, includeProjectCreator: { type: "boolean", description: "Include project creator" }, includeProjectCompany: { type: "boolean", description: "Include project company" }, includeProjectCategory: { type: "boolean", description: "Include project category" }, includeProjectTags: { type: "boolean", description: "Include project tags" }, includeProjectStatus: { type: "boolean", description: "Include project status" }, includeProjectHealth: { type: "boolean", description: "Include project health" }, includeProjectBudget: { type: "boolean", description: "Include project budget" }, includeProjectProfitability: { type: "boolean", description: "Include project profitability" }, includeProjectCustomFields: { type: "boolean", description: "Include project custom fields" }, includeProjectBillingMethod: { type: "boolean", description: "Include project billing method" }, includeProjectRateCards: { type: "boolean", description: "Include project rate cards" }, includeProjectRateCardRates: { type: "boolean", description: "Include project rate card rates" }, includeProjectRateCardCurrencies: { type: "boolean", description: "Include project rate card currencies" }, includeProjectRateCardUsers: { type: "boolean", description: "Include project rate card users" }, includeProjectRateCardUserRates: { type: "boolean", description: "Include project rate card user rates" }, includeProjectRateCardUserCurrencies: { type: "boolean", description: "Include project rate card user currencies" }, includeProjectRateCardTasks: { type: "boolean", description: "Include project rate card tasks" }, includeProjectRateCardTaskRates: { type: "boolean", description: "Include project rate card task rates" }, includeProjectRateCardTaskCurrencies: { type: "boolean", description: "Include project rate card task currencies" } } }, annotations: { title: "Get Projects", readOnlyHint: false, destructiveHint: false, openWorldHint: false } }; - src/tools/index.ts:7-7 (registration)Imports getProjectsDefinition (aliased as getProjects) and handleGetProjects from the tool file.
import { getProjectsDefinition as getProjects, handleGetProjects } from './projects/getProjects.js'; - src/tools/index.ts:66-66 (registration)Registers the getProjects tool in the toolPairs array, pairing its definition with its handler.
{ definition: getProjects, handler: handleGetProjects }, - The service-layer getProjects function that actually calls the Teamwork API. Tries v3 API first, falls back to v1 API. Takes ProjectQueryParams and returns response data.
export const getProjects = async (params?: ProjectQueryParams) => { try { logger.info('Fetching projects from Teamwork API'); try { // Try with v3 API first const api = ensureApiClient(); const response = await api.get('/projects.json', { params }); logger.info('Successfully fetched projects using v3 API'); return response.data; } catch (error: any) { logger.warn(`V3 API request failed: ${error.message}`); // Try the v1 API format as fallback logger.info('Trying v1 API format as fallback'); try { const v1Api = getApiClientForVersion('v1'); const v1Response = await v1Api.get('/projects.json', { params }); logger.info('Successfully fetched projects using v1 API'); return v1Response.data; } catch (v1Error: any) { logger.error(`V1 API request also failed: ${v1Error.message}`); throw error; // Throw the original error } } } catch (error: any) { logger.error(`Teamwork API error: ${error.message}`); throw new Error('Failed to fetch projects from Teamwork API'); } };