Targetprocess MCP Server
by aaronsb
Verified
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import { z } from 'zod';
import { TPService } from '../../api/client/tp.service.js';
import { searchPresets, applyPresetFilter } from './presets.js';
/**
* Search tool for Target Process entities
*
* Common usage examples:
* 1. Basic search (returns all items of a type):
* search_entities({ type: "UserStory" })
*
* 2. Using preset filters:
* search_entities({
* type: "Bug",
* where: searchPresets.open
* })
*
* 3. Using date-based filters:
* search_entities({
* type: "Task",
* where: searchPresets.createdToday
* })
*
* 4. Using variables in filters:
* search_entities({
* type: "UserStory",
* where: applyPresetFilter("myTasks", { currentUser: "john@example.com" })
* })
*
* 5. Including related data:
* search_entities({
* type: "Bug",
* where: searchPresets.open,
* include: ["Project", "AssignedUser"]
* })
*/
export const searchToolSchema = z.object({
type: z.enum([
'UserStory', 'Bug', 'Task', 'Feature',
'Epic', 'PortfolioEpic', 'Solution',
'Request', 'Impediment', 'TestCase', 'TestPlan',
'Project', 'Team', 'Iteration', 'TeamIteration',
'Release', 'Program'
]),
where: z.string().optional().describe('Filter expression or use searchPresets for common filters'),
include: z.array(z.string()).optional().describe('Related data to include (e.g., Project, Team, AssignedUser)'),
take: z.number().min(1).max(1000).optional().describe('Number of items to return (default: 100)'),
orderBy: z.array(z.string()).optional().describe('Fields to sort by (e.g., ["CreateDate desc"])'),
});
export type SearchToolInput = z.infer<typeof searchToolSchema>;
/**
* Handler for the search entities tool
*/
export class SearchTool {
constructor(private service: TPService) {}
async execute(args: unknown) {
try {
const { type, where, include, take, orderBy } = searchToolSchema.parse(args);
const results = await this.service.searchEntities(
type,
where,
include,
take,
orderBy
);
return {
content: [
{
type: 'text',
text: JSON.stringify(results, null, 2),
},
],
};
} catch (error) {
if (error instanceof z.ZodError) {
throw new McpError(
ErrorCode.InvalidParams,
`Invalid search parameters: ${error.message}`
);
}
throw new McpError(
ErrorCode.InvalidRequest,
`Search failed: ${error instanceof Error ? error.message : String(error)}`
);
}
}
/**
* Get tool definition for MCP
*/
static getDefinition() {
return {
name: 'search_entities',
description: 'Search Target Process entities with powerful filtering capabilities and preset filters for common scenarios',
inputSchema: {
type: 'object',
properties: {
type: {
type: 'string',
enum: [
'UserStory', 'Bug', 'Task', 'Feature',
'Epic', 'PortfolioEpic', 'Solution',
'Request', 'Impediment', 'TestCase', 'TestPlan',
'Project', 'Team', 'Iteration', 'TeamIteration',
'Release', 'Program'
],
description: 'Type of entity to search',
},
where: {
type: 'string',
description: `Filter expression using Target Process query language. Common preset filters available:
- Status filters: searchPresets.open, .inProgress, .done
- Assignment filters: searchPresets.myTasks, .unassigned
- Time-based filters: searchPresets.createdToday, .modifiedToday, .createdThisWeek
- Priority filters: searchPresets.highPriority
- Combined filters: searchPresets.myOpenTasks, .highPriorityUnassigned
Example: searchPresets.open or "EntityState.Name eq 'Open'"`,
},
include: {
type: 'array',
items: {
type: 'string',
},
description: 'Related data to include in results (e.g., ["Project", "Team", "AssignedUser"])',
},
take: {
type: 'number',
description: 'Number of items to return (default: 100)',
minimum: 1,
maximum: 1000,
},
orderBy: {
type: 'array',
items: {
type: 'string',
},
description: 'Sort order for results (e.g., ["CreateDate desc", "Name asc"])',
},
},
required: ['type'],
},
} as const;
}
}