import { Tool } from '@modelcontextprotocol/sdk/types.js';
import { JsmClient } from '../api/jsmClient.js';
import { validateAqlQuery, formatError, logDebug, paginateAqlSearch, formatPaginationInfo } from '../utils/index.js';
export const searchAssetsAqlTool: Tool = {
name: 'search_assets_aql',
description: 'Search JSM Assets using AQL (Assets Query Language). Supports complex queries with filters and robust automatic pagination.',
inputSchema: {
type: 'object',
properties: {
aqlQuery: {
type: 'string',
description: 'AQL query string (e.g., "objectType=\\"Installation Package\\" AND Key startswith IASM")'
},
autoPages: {
type: 'boolean',
description: 'Enable automatic pagination to fetch all results (default: false for backward compatibility)',
default: false
},
maxPages: {
type: 'number',
description: 'Maximum number of pages to fetch when autoPages=true (default: 10, safety limit)',
default: 10
},
pageSize: {
type: 'number',
description: 'Number of results per page when autoPages=true (default: 1000)',
default: 1000
},
startAt: {
type: 'number',
description: 'Starting index for single-page requests when autoPages=false (default: 0)',
default: 0
},
maxResults: {
type: 'number',
description: 'Maximum number of results for single-page requests when autoPages=false (default: 1000)',
default: 1000
}
},
required: ['aqlQuery']
}
};
export async function handleSearchAssetsAql(
client: JsmClient,
args: any
): Promise<{ content: Array<{ type: string; text: string }> }> {
try {
const {
aqlQuery,
autoPages = false,
maxPages = 10,
pageSize = 1000,
startAt = 0,
maxResults = 1000
} = args;
validateAqlQuery(aqlQuery);
logDebug('Executing AQL search', {
aqlQuery,
autoPages,
maxPages,
pageSize,
startAt,
maxResults
});
let summary: string;
let allResults: any[];
if (autoPages) {
// Use robust automatic pagination
const paginatedResult = await paginateAqlSearch(
client,
{ qlQuery: aqlQuery },
{ maxPages, pageSize }
);
summary = formatPaginationInfo(paginatedResult);
allResults = paginatedResult.values;
logDebug('Auto-paginated AQL search completed', {
pagesFetched: paginatedResult.pagesFetched,
totalRetrieved: paginatedResult.totalRetrieved,
limitReached: paginatedResult.limitReached
});
} else {
// Traditional single-page request for backward compatibility
const result = await client.searchAssetsAql({
qlQuery: aqlQuery,
startAt,
maxResults
});
logDebug('Single-page AQL search completed', {
total: result.total,
returned: result.values?.length
});
summary = `Found ${result.total} assets (showing ${result.values?.length || 0} results)`;
allResults = result.values || [];
}
let formattedResults = '';
if (allResults.length > 0) {
formattedResults = allResults.map((asset, index) => {
const attributes = asset.attributes
.map((attr: any) =>
attr.objectAttributeValues
.map((val: any) => `${val.displayValue}`)
.join(', ')
)
.filter((val: string) => val.length > 0)
.join(' | ');
const displayIndex = autoPages ? index + 1 : startAt + index + 1;
return `${displayIndex}. ${asset.label} (${asset.objectKey})
Type: ${asset.objectType.name}
Created: ${asset.created}
Attributes: ${attributes || 'None'}`;
}).join('\n\n');
}
return {
content: [
{
type: 'text',
text: `${summary}\n\n${formattedResults}`
}
]
};
} catch (error) {
logDebug('AQL search error', error);
return {
content: [
{
type: 'text',
text: `Error searching assets with AQL: ${formatError(error)}`
}
]
};
}
}