feat(mcp): worked examples on five high-traffic tools, and in the error that rejects a call (#2100)
#2066 asked for input_examples on the top ~20 tools by call volume. The binding constraint turned out to be budget, not writing: after #2089 reclaimed 3 763 tokens, its own policy required ratcheting the tools/list ceiling down with it, so the real headroom was 317 tokens. Ten examples across five tools cost 199, leaving ~118. The ceiling is not raised. Tools picked from 30 days of mcp.tool_called crossed with the combinations the descriptions already warn about and callers still get wrong: account_override without an explicit vat_treatment (books gross, no moms line), representation without deltagare and syfte, confirmed on a high-risk approval, a balanced voucher where the moms leg is its own line, and get_kpi_report, where one caller sent `metric` 604 times over seven days to a tool whose only parameter is period_id. Examples are also surfaced in the unknown-parameter error. That costs nothing in tools/list, because it only ships on the response to a call that already failed, and it reaches the caller that most needs it: a key list told DueCue's agent which parameter was wrong but not what a correct call looks like, and the same rejected call repeated for a week. Every example is validated against its own schema by the same findUnknownArgKeys guard the server runs, plus required/type/enum/pattern checks. An example our own boundary would reject is worse than none: it teaches the exact mistake the guard then punishes. That test caught three invented enum values in this change's own first draft. 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:
co-authored by
Jakob Wennberg
Claude Opus 5
parent
e5fba9471e
commit
169e7eaf4e
@@ -1423,6 +1423,7 @@ One line per decision: `[YYYY-MM-DD] <decision>: <why>`. Appended by agents and
|
||||
[2026-09-01] multi_user seat gate enforced app-side via a NEW gated RPC (resolve_active_company_gated) instead of editing resolve_active_company/current_active_company_id: the zero-arg RPC and the RLS twin also run on self-hosted DBs where the paywall must never bite, and the app picks the gated overload only when isMultiUserEnforced(). RLS convergence rides the existing used_fallback write-back. company_capability_config deliberately does not apply to multi_user (no expiry to hang the 20-day grace on).
|
||||
[2026-09-01] EU reverse-charge packs book directly on 4515/4535 instead of adding a 45xx D / 4598 K basbelopp pair (Anders' literal suggestion): same ruta 20/21 outcome, standard BAS practice for a template that owns the cost account anyway, and a 3-business-line pack would return null from convertLibraryToBookingTemplate and silently vanish from the transaction picker. The 4598 motkonto pattern remains the right tool only where the user's own cost account must be preserved (engine-generated bookings, supplier invoices).
|
||||
[2026-09-01] Floating supplier-invoice underlag gets a standing daily reanchor cron (/api/documents/reanchor/cron) instead of another one-off repair migration: prod case 2026-08-28 (kontantmetod payment verifikat, doc eligible on every static condition, inline anchor silently did nothing, no log line recorded why) is the second time a hand-written sweep (20260727180000, 20260824150000) was needed; the inline anchor is best-effort by design, so the retry belongs in infrastructure. anchorSupplierInvoiceDocument also stops claiming success on a zero-row guarded update and logs its silent bail branches.
|
||||
[2026-09-01] MCP worked examples ship in the inputSchema for five tools only, not the top twenty (#2066): the tools/list ceiling is the binding constraint, not the writing. After #2089 reclaimed 3 763 tokens the policy in payload-size.bench.test.ts required ratcheting the ceiling down with it, so real headroom was 317 tokens, not the 4 300 the #2089 PR body implied. Ten examples cost 199, leaving ~118. Tools were picked by 30 days of mcp.tool_called crossed with the combinations the descriptions already warn about (account_override without vat_treatment, representation without deltagare, confirmed on a high-risk approval, and get_kpi_report where a caller sent `metric` 604 times to a tool whose only parameter is period_id). Examples are also surfaced in the unknown-parameter error, which costs zero catalog budget and reaches the caller that already failed; a test validates every example against its own schema with the same guard the server runs, because an example our boundary would reject teaches exactly the mistake it then punishes.
|
||||
[2026-09-01] SKV connector instance wiring (PR6b-2): system (CCG/ombud) auth is deliberately NOT brokered; it stays on the direct path and fails SYSTEM_AUTH_FAILED on a credential-less self-host, because the org certificate and ombud grants are hosted-only. getSkatteverketEnvironment() hard-reports 'prod' in connector mode: the upstream env is resolved from HOSTED's config, and the instance's unset base URLs would otherwise show a Testmiljo badge on real filings (reporting hosted's actual env via /api/connector/status is a #2090 follow-up). buildAuthorizeUrl stays direct-only rather than going async: the connector authorize needs to return the broker's redirect_uri + connector_state for persistence, so index.ts branches to startConnectorAuthorization instead of overloading one function. Connector-layer 4xx bodies (code CONNECTOR_*) are classified BEFORE the SKV-shaped 401/403 sniffing so a broker refusal never tells a self-host operator to check SKATTEVERKET_APIGW_CLIENT_ID; broker refresh 404 CONNECTOR_NOT_OWNED maps to SESSION_EXPIRED (terminal, reconnect fixes) while broker 502 stays a raw error (transient SKV outage must not re-arm the reconnect banner, #1155).
|
||||
[2026-09-01] multi_user skeptic fixes: Stripe cancel EXPIRES the multi_user stripe grant instead of deleting it (grace anchor; other grants still deleted per freeze-and-retain); app-side state checks go RPC-first via SECURITY DEFINER company_multi_user_state (capability_grants RLS hides team rows from non-team users, byrå clients would misread as frozen); byra-kind teams get a standing team-scoped multi_user grant via backfill + teams trigger (WL-10 assumption made real; partner billing is out-of-band); PGRST202 on resolution fails OPEN (pre-migration DB has no multi_user rows: gated fallback would freeze all non-owners); /api/v1 got the same dormancy gate as MCP. RLS-level enforcement and the mid-session API fallback write-back window stay v2 follow-ups (documented, same class as pre-existing stale-preference fallback).
|
||||
[2026-09-01] Declined CodeRabbit's UpgradeNote suggestion (PR #1758 follow-up) to append the self-host connector sentence to children instead of replacing them: every caller's children is hosted subscription copy ("... kräver ett abonnemang"), so appending would show subscription wording on a self-host, the exact thing the branch exists to avoid; the "CSV/SIE import stays free" text it cited is a code comment in BankSyncNowButton, not children. Replace-on-self-host stays; a dedicated selfHosted children prop can come when a caller actually needs per-panel reassurance there.
|
||||
|
||||
Reference in New Issue
Block a user