L3.1a : pagine get_system_parameters (limit/offset, signal truncated)
La sortie sans filtre (168 paramètres fusionnés) atteignait 70 141
caractères et se faisait rejeter par le client MCP. Ajout de limit
(défaut 50) et offset (défaut 0), déclarés au schéma (D23), appliqués
après filtres et tri. Quand la pagination coupe, la réponse porte
truncated: true et un hint donnant l'offset suivant et les filtres
pour réduire.
totalParameters change de sens : c'était le nombre brut d'entités
Parameter chargées (toujours 168), c'est désormais le total
correspondant aux filtres AVANT pagination — le signal truncated se
vérifie ainsi depuis la réponse (offset + returned < totalParameters).
Sans filtre les deux définitions coïncident.
Mesures via le protocole (LIMAGRAIN, content[0].text) :
- {} : avant 70 141 chars / 168 renvoyés ; après 21 404 chars,
returned 50, totalParameters 168, truncated true, hint présent.
- {"limit":200} : 70 156 chars, les 168, pas de truncated (opt-in
explicite au volume complet).
- {"offset":160} : 3 503 chars, 8 renvoyés, pas de truncated.
- {"search":"PICK"} : 10 041 chars, 23/23, pas de truncated —
comportement inchangé sur petit résultat.
- {"lines":5} : toujours rejeté par le wrapper (D23 intact).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -49,6 +49,16 @@ Examples:
|
||||
description: 'If true, return only parameters that have at least one warehouse override (default: false).',
|
||||
default: false,
|
||||
},
|
||||
limit: {
|
||||
type: 'number',
|
||||
description: 'Maximum number of parameters returned per call (default: 50). The full unfiltered list is ~70,000 characters — raise this only if you really need everything at once.',
|
||||
default: 50,
|
||||
},
|
||||
offset: {
|
||||
type: 'number',
|
||||
description: 'Number of matching parameters to skip, for pagination (default: 0). Combine with limit to walk the full list.',
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -64,9 +74,18 @@ async function executeTool(name, args) {
|
||||
}
|
||||
}
|
||||
|
||||
const DEFAULT_PARAMS_LIMIT = 50;
|
||||
|
||||
async function getSystemParameters(args) {
|
||||
const { warehouse, param_class, search, only_overridden = false } = args || {};
|
||||
|
||||
// Bornes de pagination — valeurs invalides ramenées aux défauts, la
|
||||
// validation du wrapper (D23) ne contrôle que les noms de paramètres.
|
||||
const rawLimit = Number(args && args.limit);
|
||||
const limit = Number.isFinite(rawLimit) && rawLimit >= 1 ? Math.floor(rawLimit) : DEFAULT_PARAMS_LIMIT;
|
||||
const rawOffset = Number(args && args.offset);
|
||||
const offset = Number.isFinite(rawOffset) && rawOffset >= 0 ? Math.floor(rawOffset) : 0;
|
||||
|
||||
try {
|
||||
// Both entities are small (a few hundred rows max) — fetch fully and merge
|
||||
// client-side to avoid LINQ string-injection and null-field pitfalls.
|
||||
@@ -124,18 +143,33 @@ async function getSystemParameters(args) {
|
||||
|
||||
rows.sort((a, b) => String(a.code).localeCompare(String(b.code)));
|
||||
|
||||
// Pagination (L3.1) : sans elle la sortie sans filtre atteint ~70 000
|
||||
// caractères et se fait rejeter par les clients MCP. totalParameters est
|
||||
// le total correspondant aux filtres, AVANT pagination — le signal
|
||||
// truncated se vérifie donc depuis la réponse : offset + returned < total.
|
||||
const matched = rows.length;
|
||||
const page = rows.slice(offset, offset + limit);
|
||||
const truncated = offset + page.length < matched;
|
||||
|
||||
const payload = {
|
||||
success: true,
|
||||
warehouse: warehouse || '(none — effective value = default)',
|
||||
filters: { param_class: param_class || null, search: search || null, only_overridden },
|
||||
totalParameters: matched,
|
||||
totalOverrides: Array.isArray(paramValues) ? paramValues.length : 0,
|
||||
returned: page.length,
|
||||
offset,
|
||||
};
|
||||
if (truncated) {
|
||||
payload.truncated = true;
|
||||
payload.hint = `Showing parameters ${offset + 1}-${offset + page.length} of ${matched}. Call again with offset=${offset + page.length} for the next page, or narrow the result with param_class / search.`;
|
||||
}
|
||||
payload.parameters = page;
|
||||
|
||||
return {
|
||||
content: [{
|
||||
type: 'text',
|
||||
text: JSON.stringify({
|
||||
success: true,
|
||||
warehouse: warehouse || '(none — effective value = default)',
|
||||
filters: { param_class: param_class || null, search: search || null, only_overridden },
|
||||
totalParameters: Array.isArray(parameters) ? parameters.length : 0,
|
||||
totalOverrides: Array.isArray(paramValues) ? paramValues.length : 0,
|
||||
returned: rows.length,
|
||||
parameters: rows,
|
||||
}, null, 2),
|
||||
text: JSON.stringify(payload, null, 2),
|
||||
}],
|
||||
};
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user