Commit cd38774
fix(mcp): steer read_scope vs search by scope size so the client self-selects (#131)
## Problem
When testing the MCP connect flow against `app-dev.vana.org`, Claude
reliably **hung on "Working"** after issuing `read_scope` on large
scopes (`spotify.playlists` 546 KB, `chatgpt.conversations` 1.6 MB),
while small scopes (`linkedin.profile` 39 KB) returned instantly. The
reads *succeeded* on the PS side — but a full read of a large scope
comes back as many 256 KB pages the client must walk via `nextCursor`,
and that pagination loop stalls the agent.
The client had **no reliable signal** to choose read vs search, and the
signal it did have was actively misleading: `list_granted_scopes`
emitted `searchRecommended: false` for large/huge scopes. Under that
field name a model reads it as *"search not recommended → read the whole
thing"* — i.e. it steers toward the exact slow path. (The flag actually
meant "eligible for un-named broad search," not "should you search
this.")
The goal: the client should pick the right tool **by itself**, no
operator hand-holding.
## Changes
- **Directive routing field.** `isSearchRecommended` →
`recommendAccessForScope`, emitting `recommendedAccess: "read" |
"search" | "wait"` per scope:
- tiny/small/medium ready → `read`
- large/huge / unknown size → `search` (+ reason: name the scope
explicitly; a full read returns many pages via nextCursor)
- still indexing → `wait`
- **In-band steer at point of action.** `read_scope` now fetches
lightweight index-only metadata (best-effort, never blocks the read) and
attaches a `guidance` hint **only when the scope is large enough that
search is better** — so even if the model skips `list_granted_scopes`,
the first page tells it to pivot. Small reads get no extra noise.
- **Sharper tool descriptions.** `list_granted_scopes` ("Call first,
then follow recommendedAccess"); `read_scope` ("best for
tiny/small/medium; for large/huge prefer search_personal_context");
`search_personal_context` ("preferred way to pull from large/huge
scopes… name scopes explicitly").
## Scope / non-goals
This is a tool-definition + advisory-signal fix. It does **not** address
the deeper pagination-completion issue (large-scope `nextCursor` loops
through the browser PS); that's runtime/storage and tracked separately.
## Testing
- `npx vitest run packages/core/src/mcp/tools.test.ts
packages/core/src/mcp/read-client.test.ts` → **22/22 pass** (updated
`list_granted_scopes` expectations to `recommendedAccess`; added
coverage for the `read_scope` guidance steer — present for large scopes,
absent for small).
- `npm run build`, `npm run lint` (tsc --noEmit), `npm run format:check`
→ clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Tim Nunamaker <tnunamak@gmail.com>1 parent 4dc329c commit cd38774
5 files changed
Lines changed: 258 additions & 35 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
56 | | - | |
| 56 | + | |
57 | 57 | | |
58 | 58 | | |
59 | 59 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
245 | 245 | | |
246 | 246 | | |
247 | 247 | | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
248 | 345 | | |
249 | 346 | | |
250 | 347 | | |
| |||
743 | 840 | | |
744 | 841 | | |
745 | 842 | | |
746 | | - | |
| 843 | + | |
747 | 844 | | |
748 | | - | |
| 845 | + | |
749 | 846 | | |
750 | 847 | | |
751 | 848 | | |
752 | | - | |
| 849 | + | |
753 | 850 | | |
754 | | - | |
| 851 | + | |
755 | 852 | | |
756 | 853 | | |
757 | 854 | | |
| |||
769 | 866 | | |
770 | 867 | | |
771 | 868 | | |
772 | | - | |
| 869 | + | |
773 | 870 | | |
774 | 871 | | |
775 | 872 | | |
| |||
801 | 898 | | |
802 | 899 | | |
803 | 900 | | |
804 | | - | |
| 901 | + | |
805 | 902 | | |
806 | 903 | | |
807 | 904 | | |
| |||
836 | 933 | | |
837 | 934 | | |
838 | 935 | | |
839 | | - | |
| 936 | + | |
840 | 937 | | |
841 | 938 | | |
842 | 939 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
359 | 359 | | |
360 | 360 | | |
361 | 361 | | |
362 | | - | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
363 | 371 | | |
364 | 372 | | |
365 | | - | |
| 373 | + | |
366 | 374 | | |
367 | 375 | | |
368 | | - | |
| 376 | + | |
369 | 377 | | |
370 | | - | |
| 378 | + | |
371 | 379 | | |
372 | 380 | | |
373 | 381 | | |
374 | 382 | | |
375 | | - | |
376 | | - | |
| 383 | + | |
| 384 | + | |
377 | 385 | | |
378 | 386 | | |
379 | 387 | | |
380 | 388 | | |
381 | | - | |
382 | | - | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
383 | 392 | | |
384 | 393 | | |
385 | | - | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
386 | 398 | | |
387 | 399 | | |
388 | 400 | | |
| |||
523 | 535 | | |
524 | 536 | | |
525 | 537 | | |
526 | | - | |
| 538 | + | |
527 | 539 | | |
528 | 540 | | |
529 | 541 | | |
| |||
543 | 555 | | |
544 | 556 | | |
545 | 557 | | |
546 | | - | |
| 558 | + | |
547 | 559 | | |
548 | 560 | | |
549 | 561 | | |
| |||
554 | 566 | | |
555 | 567 | | |
556 | 568 | | |
557 | | - | |
| 569 | + | |
558 | 570 | | |
559 | 571 | | |
560 | 572 | | |
561 | 573 | | |
562 | | - | |
| 574 | + | |
563 | 575 | | |
564 | 576 | | |
565 | 577 | | |
| |||
572 | 584 | | |
573 | 585 | | |
574 | 586 | | |
575 | | - | |
576 | | - | |
| 587 | + | |
| 588 | + | |
577 | 589 | | |
578 | 590 | | |
579 | 591 | | |
| |||
585 | 597 | | |
586 | 598 | | |
587 | 599 | | |
588 | | - | |
| 600 | + | |
589 | 601 | | |
590 | 602 | | |
591 | 603 | | |
| |||
639 | 651 | | |
640 | 652 | | |
641 | 653 | | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
642 | 697 | | |
643 | 698 | | |
644 | 699 | | |
| |||
658 | 713 | | |
659 | 714 | | |
660 | 715 | | |
| 716 | + | |
661 | 717 | | |
662 | 718 | | |
663 | 719 | | |
| |||
762 | 818 | | |
763 | 819 | | |
764 | 820 | | |
765 | | - | |
| 821 | + | |
766 | 822 | | |
767 | 823 | | |
768 | 824 | | |
| |||
0 commit comments