get-rounds
Retrieve and summarize security assessment rounds (pentest, scan, or radar) from OnSecurity with filtering, sorting, and pagination options.
Instructions
Get all rounds data from OnSecurity from client in a high level summary. When replying, only include the summary, not the raw data and be sure to present the data in a way that is easy to understand for the client. Rounds can be pentest rounds, scan rounds, or radar rounds.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| round_type | No | Optional round type to filter rounds, 1 = pentest round, 3 = scan round | |
| sort | No | Optional sort parameter in format 'field-direction'. Available values: name-asc, start_date-asc, end_date-asc, authorisation_date-asc, hours_estimate-asc, created_at-asc, updated_at-asc, name-desc, start_date-desc, end_date-desc, authorisation_date-desc, hours_estimate-desc, created_at-desc, updated_at-desc. Default: id-asc | |
| limit | No | Optional limit parameter for max results per page (e.g. 15) | |
| page | No | Optional page number to fetch (default: 1) | |
| includes | No | Optional related data to include as comma-separated values (e.g. 'client,findings,targets') | |
| fields | No | Optional comma-separated list of fields to return (e.g. 'id,name,started'). Use * as wildcard. | |
| filters | No | Optional additional filters in format {field: value} or {field-operator: value} where operator can be mt (more than), mte (more than equal), lt (less than), lte (less than equal), eq (equals, default) | |
| search | No | Search term to find rounds by name of round or name of client |
Implementation Reference
- src/index.ts:379-437 (handler)The main handler function for the 'get-rounds' tool. Processes input parameters to build filters, fetches paginated rounds data from the OnSecurity API using fetchPage, formats the results using formatRound and formatPaginationInfo, constructs a markdown summary, and returns it as MCP text content.async (params) => { const filters: Record<string, string | number> = {}; // Add additional filters if provided if (params.filters) { Object.entries(params.filters).forEach(([key, value]) => { filters[key] = value; }); } // Add round_type filter if provided if (params.round_type) { filters['round_type_id-eq'] = params.round_type; } const response = await fetchPage<ApiResponse<RoundFeature>>( 'rounds', params.page || 1, filters, params.sort, params.includes, params.fields, params.limit, params.search ); if (!response) { return { content: [ { type: "text", text: "Error fetching rounds data. Please try again." } ] }; } const paginationInfo = formatPaginationInfo(response); const formattedRounds = response.result.map(formatRound); const responseText = [ "# Rounds Summary", "", "## Pagination Information", paginationInfo, "", "## Rounds Data", ...formattedRounds ].join('\n'); return { content: [ { type: "text", text: responseText } ] }; }
- src/index.ts:370-378 (schema)Zod input schema defining optional parameters for filtering, sorting, pagination, includes, fields, custom filters, and search for the 'get-rounds' tool.round_type: z.number().optional().describe("Optional round type to filter rounds, 1 = pentest round, 3 = scan round"), sort: z.string().optional().describe("Optional sort parameter in format 'field-direction'. Available values: name-asc, start_date-asc, end_date-asc, authorisation_date-asc, hours_estimate-asc, created_at-asc, updated_at-asc, name-desc, start_date-desc, end_date-desc, authorisation_date-desc, hours_estimate-desc, created_at-desc, updated_at-desc. Default: id-asc"), limit: z.number().optional().describe("Optional limit parameter for max results per page (e.g. 15)"), page: z.number().optional().describe("Optional page number to fetch (default: 1)"), includes: z.string().optional().describe("Optional related data to include as comma-separated values (e.g. 'client,findings,targets')"), fields: z.string().optional().describe("Optional comma-separated list of fields to return (e.g. 'id,name,started'). Use * as wildcard."), filters: FilterSchema, search: z.string().optional().describe("Search term to find rounds by name of round or name of client") },
- src/index.ts:366-438 (registration)Registration of the 'get-rounds' tool using server.tool(), including name, description, input schema, and inline handler function.server.tool( "get-rounds", "Get all rounds data from OnSecurity from client in a high level summary. When replying, only include the summary, not the raw data and be sure to present the data in a way that is easy to understand for the client. Rounds can be pentest rounds, scan rounds, or radar rounds.", { round_type: z.number().optional().describe("Optional round type to filter rounds, 1 = pentest round, 3 = scan round"), sort: z.string().optional().describe("Optional sort parameter in format 'field-direction'. Available values: name-asc, start_date-asc, end_date-asc, authorisation_date-asc, hours_estimate-asc, created_at-asc, updated_at-asc, name-desc, start_date-desc, end_date-desc, authorisation_date-desc, hours_estimate-desc, created_at-desc, updated_at-desc. Default: id-asc"), limit: z.number().optional().describe("Optional limit parameter for max results per page (e.g. 15)"), page: z.number().optional().describe("Optional page number to fetch (default: 1)"), includes: z.string().optional().describe("Optional related data to include as comma-separated values (e.g. 'client,findings,targets')"), fields: z.string().optional().describe("Optional comma-separated list of fields to return (e.g. 'id,name,started'). Use * as wildcard."), filters: FilterSchema, search: z.string().optional().describe("Search term to find rounds by name of round or name of client") }, async (params) => { const filters: Record<string, string | number> = {}; // Add additional filters if provided if (params.filters) { Object.entries(params.filters).forEach(([key, value]) => { filters[key] = value; }); } // Add round_type filter if provided if (params.round_type) { filters['round_type_id-eq'] = params.round_type; } const response = await fetchPage<ApiResponse<RoundFeature>>( 'rounds', params.page || 1, filters, params.sort, params.includes, params.fields, params.limit, params.search ); if (!response) { return { content: [ { type: "text", text: "Error fetching rounds data. Please try again." } ] }; } const paginationInfo = formatPaginationInfo(response); const formattedRounds = response.result.map(formatRound); const responseText = [ "# Rounds Summary", "", "## Pagination Information", paginationInfo, "", "## Rounds Data", ...formattedRounds ].join('\n'); return { content: [ { type: "text", text: responseText } ] }; } );
- src/index.ts:262-275 (helper)Helper function used by the handler to format individual RoundFeature objects into readable multi-line strings.function formatRound(round: RoundFeature): string { return [ `Round ID: ${round.id}`, `Client ID: ${round.client_id}`, `Round Type: ${round.round_type_id === 1 ? "pentest round" : round.round_type_id === 3 ? "scan round" : round.round_type_id}`, `Estimated: ${round.estimate.time} ${round.estimate.period}`, `Start Date: ${round.start_date || "Unknown"}`, `End Date: ${round.end_date || "Unknown"}`, `Started: ${round.started}`, `Completed: ${round.finished}`, `Name: ${round.name}`, `Executive Summary Published: ${round.executive_summary_published}`, `--------------------------------`, ].join('\n');
- src/index.ts:221-258 (helper)Generic helper function used by the handler to fetch a paginated page of data from the OnSecurity API, building query parameters from inputs.async function fetchPage<T>( basePath: string, page: number = 1, filters: Record<string, string | number> = {}, sort?: string, includes?: string, fields?: string, limit?: number, search?: string ): Promise<T | null> { // Build query parameters const queryParams = new URLSearchParams(); // Add page parameter queryParams.append('page', page.toString()); // Add limit if provided if (limit) queryParams.append('limit', limit.toString()); // Add sort if provided if (sort) queryParams.append('sort', sort); // Add includes if provided if (includes) queryParams.append('include', includes); // Add fields if provided if (fields) queryParams.append('fields', fields); // Add search if provided if (search) queryParams.append('search', search); // Add filters Object.entries(filters).forEach(([key, value]) => { queryParams.append(`filter[${key}]`, value.toString()); }); const url = `${ONSECURITY_API_BASE}/${basePath}?${queryParams.toString()}`; return await makeOnSecurityRequest<T>(url);