feat(mcp): second examples batch: five more tools, seven examples, 80 tokens (#2137)

Continues #2100 under the margin the envelope trim (#2123) created:
58 999 to 59 079 against the 60 000 ceiling, spending under half the
room and leaving ~920.

Picked by evidence, not traffic alone: gnubok_search_tools was sent a
nonexistent `offset` in prod today, so its examples show the actual
levers (query, detail, limit) and the description of the mistake; the
create/complete document-upload pair's examples ARE the two-step flow,
same upload_id and file_name on both sides;
list_uncategorized_transactions is the highest-traffic read (15 122
calls/30d) and gets the pagination shape; link_document_to_voucher gets
the minimal linking call.

All seven pass the input-examples validation suite (same unknown-key
guard the server runs, plus required/type/enum/pattern and the
placeholder-id check), and the pinned tool list is updated.


Claude-Session: https://claude.ai/code/session_01L3P2hr19PhQuCoTSGoegcY

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-09-01 21:45:31 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Opus 5
parent 8d9bf383d1
commit 53c9c0c4f9
3 changed files with 22 additions and 0 deletions
@@ -72,9 +72,14 @@ describe('inputSchema examples are calls the server would accept', () => {
expect(withExamples.map((t) => t.name).sort()).toEqual([
'gnubok_approve_pending_operation',
'gnubok_categorize_transaction',
'gnubok_complete_document_upload',
'gnubok_create_document_upload',
'gnubok_create_voucher',
'gnubok_get_kpi_report',
'gnubok_link_document_to_voucher',
'gnubok_list_uncategorized_transactions',
'gnubok_query_journal',
'gnubok_search_tools',
])
})
@@ -375,6 +375,13 @@ describe('tools/list payload size guard', () => {
// costs ~11 800 tokens across those 58 tools, and the structural fix is
// to stop repeating it, not to trim it further.
//
// * 59.0K to 59.1K: second examples batch (2026-09-01, #2066), 7
// examples on 5 more tools for 80 tokens, spending under half the
// margin the envelope trim created. Picked by evidence: search_tools
// was sent a nonexistent `offset` in prod the same day, the upload
// pair's examples ARE the two-step flow, and
// list_uncategorized_transactions is the highest-traffic read.
//
// Long-term answer to growth is no longer a ceiling bump. gnubok_call_tool
// makes `catalogVisibility: 'search'` usable for READ tools on hosts that
// can only invoke what tools/list showed them, which is the constraint that
+10
View File
@@ -3033,6 +3033,9 @@ export const tools: McpTool[] = [
scope: { type: 'string', description: 'Optional filter: only tools requiring this API key scope (e.g. "invoices:write").' },
limit: { type: 'number', description: 'Max results, 1-50 (default 20).' },
},
// No offset exists: a caller paged with one today (2026-09-01) and was
// rejected. Raise limit instead, or narrow the query.
examples: [{ query: 'moms', detail: 'summary' }, { query: 'faktura', limit: 50 }],
},
outputSchema: {
type: 'object',
@@ -5106,6 +5109,7 @@ export const tools: McpTool[] = [
offset: { type: 'number', description: 'Number of results to skip for pagination (default 0)' },
cash_account_id: { type: 'string' },
},
examples: [{}, { limit: 100, offset: 100 }],
},
outputSchema: paginatedSchema('transactions', {
type: 'object',
@@ -12030,6 +12034,9 @@ export const tools: McpTool[] = [
},
},
required: ['file_name'],
// Step 1 of 2: PUT the bytes to upload_url, then complete with the SAME
// upload_id and file_name.
examples: [{ file_name: 'kvitto-sl-2026-03-12.pdf' }],
},
outputSchema: {
type: 'object',
@@ -12097,6 +12104,8 @@ export const tools: McpTool[] = [
},
},
required: ['upload_id', 'file_name'],
// Step 2 of 2: same upload_id and file_name as gnubok_create_document_upload.
examples: [{ upload_id: 'f00d...', file_name: 'kvitto-sl-2026-03-12.pdf' }],
},
outputSchema: {
type: 'object',
@@ -13170,6 +13179,7 @@ export const tools: McpTool[] = [
dry_run: { type: 'boolean', description: 'Preview without staging' },
},
required: ['document_id', 'journal_entry_id'],
examples: [{ document_id: 'd0c1...', journal_entry_id: 'a44e...' }],
},
outputSchema: STAGED_OPERATION_SCHEMA,
annotations: {