Files
sage-mcp-server/src/tools/sage-search.ts

54 lines
1.8 KiB
TypeScript

import { z } from 'zod';
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import type { RestClient } from '../clients/rest-client.js';
import { formatQueryResponse } from '../utils/response.js';
import { formatToolError, classifyError, getErrorHint } from '../utils/errors.js';
function buildWhereClause(entity: string, searchTerm: string, searchFields?: string[]): string {
const fields = searchFields && searchFields.length > 0
? searchFields
: [`${entity}NUM`, `${entity}NAM`];
const conditions = fields.map((field) => `contains(${field},'${searchTerm}')`);
return conditions.length === 1
? conditions[0]
: `(${conditions.join(' or ')})`;
}
export function registerSearchTool(server: McpServer, restClient: RestClient): void {
server.registerTool(
'sage_search',
{
description:
'Search Sage X3 records with flexible text matching. Builds SData where clauses from a search term across common fields.',
inputSchema: {
entity: z.string(),
searchTerm: z.string(),
searchFields: z.array(z.string()).optional(),
count: z.number().min(1).max(200).optional(),
},
annotations: {
readOnlyHint: true,
destructiveHint: false,
idempotentHint: true,
openWorldHint: true,
},
},
async (args) => {
try {
const where = buildWhereClause(args.entity, args.searchTerm, args.searchFields);
const result = await restClient.query({
entity: args.entity,
where,
count: args.count,
});
return formatQueryResponse(result.records, result.pagination);
} catch (error) {
return formatToolError(error, getErrorHint(classifyError(error)));
}
},
);
}
export { buildWhereClause };