MCPcopy Create free account
hub / github.com/adcontextprotocol/adcp / handleGetSignals

Function handleGetSignals

server/src/training-agent/task-handlers.ts:2601–2776  ·  view source on GitHub ↗
(args: ToolArgs, ctx: TrainingContext)

Source from the content-addressed store, hash-verified

2599const MAX_SIGNAL_RESULTS = 10;
2600
2601export async function handleGetSignals(args: ToolArgs, ctx: TrainingContext) {
2602 const req = args as unknown as GetSignalsRequest & ToolArgs & {
2603 brief?: string;
2604 pagination?: { max_results?: number; cursor?: string };
2605 };
2606 // Accept both signal_spec (protocol) and brief (SDK test tool)
2607 const rawSpec = req.signal_spec || req.brief;
2608 const signalSpec = typeof rawSpec === 'string' ? rawSpec : undefined;
2609 // Pagination shape (pagination.max_results, schema cap 100) takes precedence
2610 // over the legacy top-level `max_results` (no schema cap; this handler
2611 // historically capped at 50 to keep semantic-search results focused). The two
2612 // forms have different caps because they have different contracts —
2613 // pagination.max_results is the standard envelope and matches the schema's
2614 // documented 100 cap; top-level max_results is the predecessor and we
2615 // preserve its tighter behavioral cap to avoid silently widening any caller
2616 // currently relying on the 50 ceiling. Spec ambiguity on which form wins
2617 // when both are present is tracked at adcontextprotocol/adcp#3113.
2618 let maxResults: number;
2619 const paginationMax = req.pagination?.max_results;
2620 if (typeof paginationMax === 'number' && paginationMax >= 1) {
2621 maxResults = Math.min(paginationMax, 100);
2622 } else if (typeof req.max_results === 'number' && req.max_results >= 1) {
2623 maxResults = Math.min(req.max_results, 50);
2624 } else {
2625 maxResults = MAX_SIGNAL_RESULTS;
2626 }
2627 const offset = decodeOffsetCursor('signals', req.pagination?.cursor);
2628 if (offset === null) {
2629 return {
2630 errors: [{ code: 'INVALID_REQUEST', message: 'pagination.cursor is malformed' }] as TaskError[],
2631 };
2632 }
2633 const session = await getSession(sessionKeyFromArgs(req, ctx.mode, ctx.userId, ctx.moduleId));
2634
2635 const allSignals = getAllSignals();
2636 let results = allSignals;
2637
2638 // Exact lookup by signal_ids
2639 if (req.signal_ids?.length) {
2640 const idSet = new Set(req.signal_ids.map(sid => sid.id));
2641 results = results.filter(s => idSet.has(s.signalAgentSegmentId));
2642 }
2643
2644 // Natural language search via signal_spec
2645 const rawTerms = signalSpec ? signalSpec.toLowerCase().split(/\s+/) : [];
2646 if (signalSpec) {
2647 const expanded = new Set<string>();
2648 for (const t of rawTerms) {
2649 expanded.add(t);
2650 const synonyms = SYNONYM_MAP[t];
2651 if (synonyms) {
2652 for (const s of synonyms) expanded.add(s);
2653 }
2654 }
2655 const terms = [...expanded];
2656 const scored = results
2657 .map(s => {
2658 const text = `${s.name} ${s.description} ${s.tags.join(' ')} ${s.providerName}`.toLowerCase();

Callers

nothing calls this directly

Calls 9

decodeOffsetCursorFunction · 0.85
getSessionFunction · 0.85
sessionKeyFromArgsFunction · 0.85
getAllSignalsFunction · 0.85
getAgentUrlFunction · 0.85
encodeOffsetCursorFunction · 0.85
hasMethod · 0.80
addMethod · 0.80
getMethod · 0.45

Tested by

no test coverage detected