get_project_details
Retrieve detailed project information such as process, work item types, and team structures from Azure DevOps using the MCP server. Specify options to include fields, process, teams, or work item types as needed.
Instructions
Get comprehensive details of a project including process, work item types, and teams
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| expandTeamIdentity | No | Expand identity information in the team objects | |
| includeFields | No | Include field information for work item types | |
| includeProcess | No | Include process information in the project result | |
| includeTeams | No | Include associated teams in the project result | |
| includeWorkItemTypes | No | Include work item types and their structure | |
| projectId | Yes | The ID or name of the project |
Input Schema (JSON Schema)
{
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"properties": {
"expandTeamIdentity": {
"default": false,
"description": "Expand identity information in the team objects",
"type": "boolean"
},
"includeFields": {
"default": false,
"description": "Include field information for work item types",
"type": "boolean"
},
"includeProcess": {
"default": false,
"description": "Include process information in the project result",
"type": "boolean"
},
"includeTeams": {
"default": false,
"description": "Include associated teams in the project result",
"type": "boolean"
},
"includeWorkItemTypes": {
"default": false,
"description": "Include work item types and their structure",
"type": "boolean"
},
"projectId": {
"description": "The ID or name of the project",
"type": "string"
}
},
"required": [
"projectId"
],
"type": "object"
}
Implementation Reference
- Core handler function that executes the get_project_details tool logic, fetching comprehensive project information from Azure DevOps including optional process, WITs, fields, and teams.export async function getProjectDetails( connection: WebApi, options: GetProjectDetailsOptions, ): Promise<ProjectDetails> { try { const { projectId, includeProcess = false, includeWorkItemTypes = false, includeFields = false, includeTeams = false, expandTeamIdentity = false, } = options; // Get the core API const coreApi = await connection.getCoreApi(); // Get the basic project information const project = await coreApi.getProject(projectId); if (!project) { throw new AzureDevOpsResourceNotFoundError( `Project '${projectId}' not found`, ); } // Initialize the result with the project information and ensure required properties const result: ProjectDetails = { ...project, // Ensure capabilities is always defined capabilities: project.capabilities || { versioncontrol: { sourceControlType: 'Git' }, processTemplate: { templateName: 'Unknown', templateTypeId: 'unknown' }, }, }; // If teams are requested, get them if (includeTeams) { const teams = await coreApi.getTeams(projectId, expandTeamIdentity); result.teams = teams; } // If process information is requested, get it if (includeProcess) { // Get the process template ID from the project capabilities const processTemplateId = project.capabilities?.processTemplate?.templateTypeId || 'unknown'; // Always create a process object, even if we don't have a template ID // In a real implementation, we would use the Process API // Since it's not directly available in the WebApi type, we'll simulate it // This is a simplified version for the implementation // In a real implementation, you would need to use the appropriate API // Create the process info object directly const processInfo: ProcessInfo = { id: processTemplateId, name: project.capabilities?.processTemplate?.templateName || 'Unknown', description: 'Process template for the project', isDefault: true, type: 'system', }; // If work item types are requested, get them if (includeWorkItemTypes) { // In a real implementation, we would get work item types from the API // For now, we'll use the work item tracking API to get basic types const workItemTrackingApi = await connection.getWorkItemTrackingApi(); const workItemTypes = await workItemTrackingApi.getWorkItemTypes(projectId); // Map the work item types to our format const processWorkItemTypes: WorkItemTypeInfo[] = workItemTypes.map( (wit) => { // Create the work item type info object const workItemTypeInfo: WorkItemTypeInfo = { name: wit.name || 'Unknown', referenceName: wit.referenceName || `System.Unknown.${Date.now()}`, description: wit.description, isDisabled: false, states: [ { name: 'New', stateCategory: 'Proposed' }, { name: 'Active', stateCategory: 'InProgress' }, { name: 'Resolved', stateCategory: 'InProgress' }, { name: 'Closed', stateCategory: 'Completed' }, ], }; // If fields are requested, don't add fields here - we'll add them after fetching from API return workItemTypeInfo; }, ); // If fields are requested, get the field definitions from the API if (includeFields) { try { // Instead of getting all fields and applying them to all work item types, // let's get the fields specific to each work item type for (const wit of processWorkItemTypes) { try { // Get fields specific to this work item type using the specialized method const typeSpecificFields = await workItemTrackingApi.getWorkItemTypeFieldsWithReferences( projectId, wit.name, ); // Map the fields to our format wit.fields = typeSpecificFields.map( (field: WorkItemTypeField) => ({ name: field.name || 'Unknown', referenceName: field.referenceName || 'Unknown', type: field.type?.toString().toLowerCase() || 'string', required: field.isRequired || false, isIdentity: field.isIdentity || false, isPicklist: field.isPicklist || false, description: field.description, }), ); } catch (typeFieldError) { console.error( `Error fetching fields for work item type ${wit.name}:`, typeFieldError, ); // Fallback to basic fields wit.fields = [ { name: 'Title', referenceName: 'System.Title', type: 'string', required: true, }, { name: 'Description', referenceName: 'System.Description', type: 'html', required: false, }, ]; } } } catch (fieldError) { console.error('Error in field processing:', fieldError); // Fallback to default fields if API call fails processWorkItemTypes.forEach((wit) => { wit.fields = [ { name: 'Title', referenceName: 'System.Title', type: 'string', required: true, }, { name: 'Description', referenceName: 'System.Description', type: 'html', required: false, }, ]; }); } } processInfo.workItemTypes = processWorkItemTypes; // Add hierarchy information if available // This is a simplified version - in a real implementation, you would // need to get the backlog configuration and map it to the work item types processInfo.hierarchyInfo = { portfolioBacklogs: [ { name: 'Epics', workItemTypes: processWorkItemTypes .filter( (wit: WorkItemTypeInfo) => wit.name.toLowerCase() === 'epic', ) .map((wit: WorkItemTypeInfo) => wit.name), }, { name: 'Features', workItemTypes: processWorkItemTypes .filter( (wit: WorkItemTypeInfo) => wit.name.toLowerCase() === 'feature', ) .map((wit: WorkItemTypeInfo) => wit.name), }, ], requirementBacklog: { name: 'Stories', workItemTypes: processWorkItemTypes .filter( (wit: WorkItemTypeInfo) => wit.name.toLowerCase() === 'user story' || wit.name.toLowerCase() === 'bug', ) .map((wit: WorkItemTypeInfo) => wit.name), }, taskBacklog: { name: 'Tasks', workItemTypes: processWorkItemTypes .filter( (wit: WorkItemTypeInfo) => wit.name.toLowerCase() === 'task', ) .map((wit: WorkItemTypeInfo) => wit.name), }, }; } // Always set the process on the result result.process = processInfo; } return result; } catch (error) { if (error instanceof AzureDevOpsError) { throw error; } throw new Error( `Failed to get project details: ${error instanceof Error ? error.message : String(error)}`, ); } }
- Zod input schema defining parameters for the get_project_details tool, including options for including additional project details.export const GetProjectDetailsSchema = z.object({ projectId: z .string() .optional() .describe(`The ID or name of the project (Default: ${defaultProject})`), organizationId: z .string() .optional() .describe(`The ID or name of the organization (Default: ${defaultOrg})`), includeProcess: z .boolean() .optional() .default(false) .describe('Include process information in the project result'), includeWorkItemTypes: z .boolean() .optional() .default(false) .describe('Include work item types and their structure'), includeFields: z .boolean() .optional() .default(false) .describe('Include field information for work item types'), includeTeams: z .boolean() .optional() .default(false) .describe('Include associated teams in the project result'), expandTeamIdentity: z .boolean() .optional() .default(false) .describe('Expand identity information in the team objects'), });
- src/features/projects/tool-definitions.ts:23-28 (registration)ToolDefinition registration for 'get_project_details' including name, description, and JSON schema derived from Zod schema.{ name: 'get_project_details', description: 'Get comprehensive details of a project including process, work item types, and teams', inputSchema: zodToJsonSchema(GetProjectDetailsSchema), },
- src/features/projects/index.ts:72-85 (registration)Request handler switch case that registers and dispatches 'get_project_details' tool calls, parsing args and invoking the handler.case 'get_project_details': { const args = GetProjectDetailsSchema.parse(request.params.arguments); const result = await getProjectDetails(connection, { projectId: args.projectId ?? defaultProject, includeProcess: args.includeProcess, includeWorkItemTypes: args.includeWorkItemTypes, includeFields: args.includeFields, includeTeams: args.includeTeams, expandTeamIdentity: args.expandTeamIdentity, }); return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }], }; }