[GH-ISSUE #5861] [Bug] Default tools/list schema profile is ~813 KB (~259K tokens); compact cuts it to ~196 KB but is off by default and still 66K context #3551

Open
opened 2026-10-31 00:41:46 +00:00 by bsakaguchi · 5 comments
Owner

Originally created by @RelicOfTesla on GitHub (Oct 21, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/5861

#1065

Area

MCP tool surface — schema definitions / tool registration

Observed behavior

Two measured states of the same 207-tool catalog:

Default (full) profile — REA returns 207 tools with 832,157 B (812.7 KB) of combined JSON schema, ≈259K tokens. The client request is rejected at registration, before any tool call, target load, or analysis:

{"code":400,"message":"request (261559 tokens) exceeds the available context size (227328 tokens), try increasing it","type":"exceed_context_size_error","n_prompt_tokens":261559,"n_ctx":227328}

Conversation content in that request was 381 bytes; tool schemas were ~99% of it.

With REA_MCP_INPUT_SCHEMA_PROFILE=compact — same 207 tools, 200,255 B (195.6 KB), ≈66K tokens. The request now succeeds, but REA still accounts for:

78.8% of the request body  (200,255 of 254,101 B)
~29% of the backend's 227,328-token context  — before any conversation

Residual concentration after compact:

Tool Bytes vs. median (780 B)
inspect_analysis_view 7,337 9.4×
capture_process_scenario 4,991 6.4×
update_unknown 3,277 4.2×
capture_electron_scenario 3,119 4.0×
capture_browser_scenario 2,880 3.7×

Only one tool remains above 5 KB. Mean 967 B, median 780 B.

Reproduction

  1. Register REA as an MCP server (client: dsh / @deepseek-ai/dsh-mcp-client, serverName: rea).
  2. New session against a backend with a 227,328-token context; send any message (e.g. hello).
  3. Default profile: request rejected with exceed_context_size_error, 8/8 requests across two independent fresh sessions:
261463  261772  261495  261853  261527  261885  261559  261917

Narrow band just under 262,144, no growth across a session — a fixed tool-schema baseline, not history accumulation.

  1. Add REA_MCP_INPUT_SCHEMA_PROFILE: compact to the server's env, restart the server, repeat step 2.
  2. With compact: request succeeds; mcp__rea__* schemas total 200,255 B.

Expected behavior

tools/list should fit a bounded prompt budget by default, so that registering REA does not by itself consume a large fraction of the client's context. Concretely:

  1. Make compact (or an equivalent reduced profile) the default. A catalog that overflows a 227K context on registration is not a usable default.
  2. Reduce compact further. ~66K tokens for tool definitions, before any conversation, is still large; the residual is concentrated in a handful of tools (inspect_analysis_view alone is 9.4× the median).
  3. Improve discoverability. REA_MCP_INPUT_SCHEMA_PROFILE is documented but easy to miss — I hit the hard failure without finding it. Surfacing it in the README's install section and in rea doctor output would prevent repeat reports.
  4. Optionally: domain-scoped groups (adb / frida / gdb / rizin / web / native / managed / swift) that a caller can enable selectively, or lazy schema delivery (names + one-line summaries first, full schema on selection).

No documentation or known-good version to cite for an intended budget — items 1–3 are proposals, not cited requirements.

Impact and scope

  • Default profile: blocking, 100% of requests. REA cannot be used at all with any client context under ~262K. Not intermittent.
  • With compact: usable but costly. ~29% of a 227K context consumed by tool definitions before the first turn; correspondingly less room for conversation, tool output, and reconstruction artifacts.
  • Affects context budget and prefill latency.
  • No effect on evidence integrity or process isolation — the failure precedes any analysis.
  • Untested: whether REA_MCP_OUTPUT_SCHEMA_PROFILE=off yields additional savings on this client (OpenAI-style tools[] carries no output schema, so likely zero here); behavior under a client that prunes or lazily loads tools; the full set of accepted values for either variable.

REA version

6.7.0

Runtime and platform

Node v24.19.0; Ubuntu on WSL (x86_64)
Backend: llama.cpp llama-server, router mode, --ctx-size 227328
Analysis engines configured: Ghidra 12.1.4 (GHIDRA_INSTALL_DIR), JDK 21 (JAVA_HOME)
Hopper / Ghidra / IDA: not reached — failure precedes any disassembler interaction

Target and artifact context

Not applicable — both measurements are at tool registration; no binary, app, container, or evidence bundle was involved.

Interface

MCP (stdio; client-side bridge @deepseek-ai/dsh-mcp-client)

Earliest failure stage

Request parsing or validation (backend rejects the assembled prompt). No REA tool is ever invoked.

Relevant output or evidence

How obtained: a local forwarding proxy between the client and the model backend dumped each POST /chat/completions body. Per-tool size = len(json.dumps(tool)) in Python. Two dumps were captured — one per schema profile. Both show 207 mcp__rea__* tools with identical name sets.

Dump A — default profile (request rejected):

  tool: mcp__rea__compare_web_captures               schema=180840B
  tool: mcp__rea__inspect_analysis_view               schema=34505B
  tool: mcp__rea__compare_application_versions        schema=33571B
  tool: mcp__rea__evaluate_reconstruction_coverage    schema=27163B
  tool: mcp__rea__project_managed_application_graph   schema=24679B
  ... (207 mcp__rea__* tools total)
  msg[0] system 46B / msg[1] user 8B / msg[2] user 319B / msg[3] user 8B
  body total: 789958B
Component Tools Bytes ≈ tokens Share of 261,559
mcp__rea__* schemas 207 832,157 (812.7 KB) ~259,016 ~99.0%
Client built-ins 15 7,715 ~2,402 ~0.9%
Conversation 4 msgs 381 ~126 ~0.05%

Dump B — compact profile (request succeeds):

  tool: mcp__rea__inspect_analysis_view               schema=7337B
  tool: mcp__rea__capture_process_scenario            schema=4991B
  tool: mcp__rea__update_unknown                      schema=3277B
  ... (same 207 mcp__rea__* tools)
  msg[0] system 8600B / msg[3] user 7812B / ...
  body total: 254101B
Component Tools Bytes ≈ tokens Share of body
mcp__rea__* schemas 207 200,255 (195.6 KB) ~66,310 78.8%
Client built-ins 40 33,016 (32.2 KB) ~10,932 13.0%
Messages 8 17,807 ~4,452 7.0%
Other (model params) — 3,023 ~864 1.2%
Total 254,101 ~82,558

Aggregate change — REA schemas only:

Default (full) compact Change
Tools 207 207 —
Bytes 832,157 (812.7 KB) 200,255 (195.6 KB) −75.9%
≈ tokens ~259,016 ~66,310 −74.4%
Share of a 227,328 context ~114% (overflow) ~29.2% —

Token estimation method (applies to every ≈ figure): the backend reported n_prompt_tokens = 261559 for the 789,958-byte body in dump A → 3.02 B/token for schema-dominated content. Dumped sizes use json.dumps defaults (spaces) and run ~6% over wire size, so were scaled ×0.94. Cross-check on dump A: 207 REA + 15 built-ins + messages = ~261,559, matching the measured value. For dump B — which succeeded, so no backend token count was returned — schema bytes were divided by 3.02 and message bytes by 4.0 (prose), giving ~82,558; treat this as an estimate, not a measurement.

Missing evidence / uncertainty:

  • tools/list was not invoked directly; sizes come from the client's request body. If the client rewrote schemas before embedding them, figures differ from REA's raw output — no evidence it does, but unverified.
  • The two dumps came from client sessions with different built-in tool sets (15 vs. 40). The REA name sets are identical and the namespace is the same, so the REA comparison is meaningful; the client-side byte totals are not directly comparable.
  • Dump B's token figure is derived, not measured. Reading usage.prompt_tokens from the successful response would replace the estimate.
  • The full set of accepted values for REA_MCP_INPUT_SCHEMA_PROFILE / REA_MCP_OUTPUT_SCHEMA_PROFILE was not found; only compact and off were used here.
  • Schema composition after compact (what remains in inspect_analysis_view) was not analyzed.

Typed outcome or recovery expected

tools/list should return a catalog that fits within a documented budget by default. Where REA cannot bound it, it should expose a typed selection mechanism — e.g. a group listing or a server-side flag naming domain groups — so the caller can choose a subset, rather than returning one 207-tool catalog that overflows typical client contexts with no REA-side signal that this will happen.

Analysis or suspected cause

Confirmed by measurement: the default profile ships full inline description prose and deeply nested parameter objects; compact removes most of that, which accounts for the 75.9% reduction. Hypothesis, not confirmed: what remains in compact is still largely description text, since the residual is concentrated in a few tools rather than spread evenly. Cost was and remains concentrated — under the default profile 9 tools were ~46% of the payload and 1 tool was ~21.5% — so further reduction looks tractable without redesigning the tool surface. No REA source was inspected.

Additional context

Workarounds observed, in order of effectiveness:

Approach REA tools ≈ request tokens Functionality lost
Default profile 207 ~261,559 (overflow) unusable
REA_MCP_INPUT_SCHEMA_PROFILE=compact 207 ~82,558 none
Client-side exclude of 9 largest tools 198 ~140,447 (default profile) 9 tools unavailable
Client-side include of ~27 core tools 27 ~9,846 180 tools unavailable
Disable REA 0 ~2,528 all

compact is the clear win: ~74% smaller with no loss of tool surface. The asks in "Expected behavior" are about making that the default and going further — a user should not have to discover an environment variable to make REA usable at all.

Full per-tool comparison, all 207 tools (default → compact, sorted by default size)
Tool Default (B) compact (B) Change
compare_web_captures 180,840 1,888 −99%
inspect_analysis_view 34,505 7,337 −79%
compare_application_versions 33,571 1,294 −96%
evaluate_reconstruction_coverage 27,163 898 −97%
project_managed_application_graph 24,679 1,067 −96%
capture_browser_scenario 24,139 2,880 −88%
build_reconstruction_obligation_ledger 23,622 1,125 −95%
compare_process_captures 20,444 1,146 −94%
trace_application_feature 20,123 1,024 −95%
correlate_static_and_runtime 18,490 1,143 −94%
compare_javascript_export_shapes 18,488 1,741 −91%
compare_source_to_bundle 18,364 905 −95%
compare_wasm_interfaces 17,610 1,254 −93%
reconcile_javascript_runtime 17,533 1,171 −93%
compare_managed_members 17,116 1,432 −92%
compare_artifacts 16,807 1,123 −93%
verify_managed_native_boundaries 16,702 1,066 −94%
compare_functions 16,538 854 −95%
trace_javascript_semantics 12,838 776 −94%
import_managed_reconstruction 10,663 1,084 −90%
build_call_path 8,872 780 −91%
project_harmony_application_graph 8,727 1,001 −89%
project_apple_application_graph 8,716 990 −89%
find_changed_behavior 8,534 808 −91%
project_android_application_graph 8,526 800 −91%
capture_process_scenario 6,989 4,991 −29%
analyze_javascript_application 4,156 1,948 −53%
update_unknown 4,099 3,277 −20%
capture_electron_scenario 3,817 3,119 −18%
record_unknown 3,573 2,744 −23%
observe_native_calls 3,525 2,370 −33%
inspect_web_network_capture 3,136 2,115 −33%
inspect_sqlite_database 2,850 2,016 −29%
inspect_packet_capture 2,784 1,702 −39%
inspect_web_page 2,754 1,817 −34%
verify_reconstruction 2,734 686 −75%
capture_native_ui_scenario 2,681 2,090 −22%
inspect_managed_members 2,400 1,638 −32%
trace_web_source_location 2,368 1,880 −21%
open_binary 2,358 1,654 −30%
analyze_web_bundle 2,305 1,200 −48%
recover_javascript_sources 2,281 1,394 −39%
extract_firmware 2,246 1,573 −30%
decode_signal_recording 2,208 1,450 −34%
trace_web_module_imports 2,089 1,554 −26%
start_adb_activity 2,008 1,364 −32%
inspect_binary_layout 1,991 1,534 −23%
inspect_packet_fields 1,971 1,347 −32%
instrument_with_frida 1,838 1,486 −19%
compare_web_screenshots 1,811 1,135 −37%
inspect_dart_aot 1,796 1,457 −19%
inspect_evm_interface 1,791 1,480 −17%
inspect_with_objdump 1,786 1,604 −10%
decode_android_resources 1,741 1,193 −31%
trace_native_values 1,741 1,145 −34%
inspect_signal_decoders 1,699 1,194 −30%
inspect_wasm_artifact 1,680 1,498 −11%
search_strings 1,542 1,195 −23%
decode_interface_builder 1,533 1,011 −34%
inspect_recorded_crash 1,525 1,231 −19%
execute_rizin_command 1,497 1,376 −8%
export_web_scripts 1,486 1,118 −25%
observe_javascript_runtime 1,484 1,251 −16%
get_evidence_bundle 1,481 1,220 −18%
inspect_electron_page 1,459 1,087 −25%
inspect_pcap_capture 1,440 1,051 −27%
trace_android_references 1,439 1,056 −27%
search_bytes 1,437 994 −31%
rizin_debug_command 1,433 1,346 −6%
inspect_pe_resources 1,418 1,079 −24%
inspect_artifact 1,411 1,130 −20%
compare_bundles 1,390 987 −29%
inspect_rust_binary 1,383 1,252 −9%
start_rizin_debug_session 1,381 1,247 −10%
start_frida_session 1,376 1,182 −14%
trace_dylib_resolution 1,369 1,295 −5%
observe_web_execution 1,367 1,054 −23%
trace_native_ui_action 1,334 891 −33%
cutter_command 1,323 1,098 −17%
push_adb_file 1,307 906 −31%
analyze_swift_types 1,302 995 −24%
inspect_go_binary 1,288 1,157 −10%
list_unknowns 1,275 972 −24%
pull_adb_package 1,274 921 −28%
inspect_managed_artifact 1,273 1,068 −16%
gdb_console 1,217 1,118 −8%
install_adb_package 1,215 775 −36%
inspect_web_event_listeners 1,207 914 −24%
inspect_android_package 1,204 1,046 −13%
start_gdb_session 1,201 1,038 −14%
annotate_native_function 1,165 898 −23%
observe_web_session 1,141 782 −31%
trace_call_path 1,124 823 −27%
close_binary 1,119 893 −20%
procedure_pseudo_code 1,106 925 −16%
pull_adb_file 1,102 744 −32%
read_adb_logcat 1,099 743 −32%
discover_webmcp_tools 1,096 741 −32%
load_frida_script 1,077 887 −18%
close_gdb_session 1,062 992 −7%
close_rizin_debug_session 1,053 983 −7%
inspect_android_method 1,048 743 −29%
list_jeb_units 1,002 643 −36%
start_adb_app 1,002 790 −21%
decompile_jeb_item 993 684 −31%
inspect_electron_fuses 986 792 −20%
set_address_name 984 688 −30%
search_procedures 982 651 −34%
observe_native_ui 971 788 −19%
set_addresses_names 969 827 −15%
procedure_references 968 664 −31%
procedure_info 959 778 −19%
inspect_native_dispatch_metadata 953 835 −12%
address_to_file_offset 952 726 −24%
collect_adb_bugreport 949 695 −27%
unload_frida_script 949 826 −13%
list_adb_directory 940 700 −26%
list_frida_processes 935 842 −10%
read_adb_setting 930 691 −26%
search_android_classes 929 722 −22%
inspect_keyed_archive 927 757 −18%
inspect_adb_package 922 734 −20%
capture_web_screenshot 921 605 −34%
list_strings 911 704 −23%
get_call_graph 909 669 −26%
inspect_native_instruction 899 799 −11%
list_frida_devices 891 818 −8%
inspect_macho 888 630 −29%
resolve_adb_packages 874 641 −27%
capture_adb_screen 872 636 −27%
binary_session 869 571 −34%
set_inline_comment 858 550 −36%
inspect_android_class 857 661 −23%
rizin_debug_session_status 849 779 −8%
set_comment 845 528 −38%
xrefs 843 636 −25%
identify_flutter_build 838 746 −11%
read_bytes 836 580 −31%
stop_adb_app 830 629 −24%
uninstall_adb_package 827 637 −23%
goto_address 818 592 −28%
list_adb_packages 818 575 −30%
inspect_firmware_regions 814 676 −17%
analyze_function 803 720 −10%
inspect_adb_window 795 684 −14%
procedure_callees 792 611 −23%
procedure_assembly 791 610 −23%
export_evidence_bundle 779 516 −34%
trace_feature 777 553 −29%
resolve_containing_procedure 773 547 −29%
batch_decompile 771 587 −24%
set_bookmark 771 492 −36%
inspect_native_load_image 768 750 −2%
procedure_callers 756 575 −24%
close_frida_session 747 677 −9%
list_browser_targets 744 571 −23%
unset_bookmark 739 513 −31%
binary_overview 723 705 −2%
gdb_session_status 723 653 −10%
open_jeb_project 714 567 −21%
extract_artifact 712 675 −5%
inspect_native_data_type 707 607 −14%
inspect_adb_device 697 586 −16%
inspect_managed_native_boundaries 696 568 −18%
address_name 683 476 −30%
prev_address 683 476 −30%
inspect_address_context 682 582 −15%
frida_session_status 677 607 −10%
resume_frida_session 676 606 −10%
verify_unknown_resolution 670 515 −23%
inspect_native_api 654 571 −13%
list_javascript_runtime_targets 638 575 −10%
comment 637 430 −32%
list_names 637 430 −32%
import_evidence_bundle 632 473 −25%
list_electron_targets 631 504 −20%
read_function_instructions 625 504 −19%
inspect_asset_catalog 619 544 −12%
procedure_address 619 438 −29%
resolve_native_call_targets 619 519 −16%
next_address 617 410 −34%
inline_comment 612 405 −34%
list_cutter_sessions 607 589 −3%
demangle_swift 599 499 −17%
inspect_adb_display 594 483 −19%
get_navigation_context 584 503 −14%
list_adb_processes 582 471 −19%
find_xrefs_to_name 553 466 −16%
list_bookmarks 548 434 −21%
list_segments 546 432 −21%
list_adb_features 545 434 −20%
inspect_plist 533 396 −26%
list_procedures 533 419 −21%
list_adb_devices 519 501 −3%
list_adb_services 513 402 −22%
inspect_pcap_client 509 491 −4%
current_address 508 394 −22%
inspect_jeb_client 481 463 −4%
current_procedure 472 358 −24%
inspect_adb_client 454 436 −4%
get_objc_classes 453 321 −29%
inspect_apktool_client 444 426 −4%
inspect_signature 382 364 −5%
list_documents 366 348 −5%
list_architectures 334 316 −5%
get_objc_protocols 282 264 −6%
current_document 279 261 −6%
Originally created by @RelicOfTesla on GitHub (Oct 21, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/5861 #1065 ### Area MCP tool surface — schema definitions / tool registration ### Observed behavior Two measured states of the same 207-tool catalog: **Default (full) profile** — REA returns 207 tools with **832,157 B (812.7 KB)** of combined JSON schema, ≈**259K tokens**. The client request is rejected at registration, before any tool call, target load, or analysis: ```json {"code":400,"message":"request (261559 tokens) exceeds the available context size (227328 tokens), try increasing it","type":"exceed_context_size_error","n_prompt_tokens":261559,"n_ctx":227328} ``` Conversation content in that request was 381 bytes; tool schemas were ~99% of it. **With `REA_MCP_INPUT_SCHEMA_PROFILE=compact`** — same 207 tools, **200,255 B (195.6 KB)**, ≈**66K tokens**. The request now succeeds, but REA still accounts for: ``` 78.8% of the request body (200,255 of 254,101 B) ~29% of the backend's 227,328-token context — before any conversation ``` Residual concentration after `compact`: | Tool | Bytes | vs. median (780 B) | |---|---|---| | `inspect_analysis_view` | 7,337 | 9.4× | | `capture_process_scenario` | 4,991 | 6.4× | | `update_unknown` | 3,277 | 4.2× | | `capture_electron_scenario` | 3,119 | 4.0× | | `capture_browser_scenario` | 2,880 | 3.7× | Only one tool remains above 5 KB. Mean 967 B, median 780 B. ### Reproduction 1. Register REA as an MCP server (client: `dsh` / `@deepseek-ai/dsh-mcp-client`, `serverName: rea`). 2. New session against a backend with a 227,328-token context; send any message (e.g. `hello`). 3. **Default profile:** request rejected with `exceed_context_size_error`, 8/8 requests across two independent fresh sessions: ``` 261463 261772 261495 261853 261527 261885 261559 261917 ``` Narrow band just under 262,144, no growth across a session — a fixed tool-schema baseline, not history accumulation. 4. Add `REA_MCP_INPUT_SCHEMA_PROFILE: compact` to the server's `env`, restart the server, repeat step 2. 5. **With `compact`:** request succeeds; `mcp__rea__*` schemas total 200,255 B. ### Expected behavior `tools/list` should fit a bounded prompt budget **by default**, so that registering REA does not by itself consume a large fraction of the client's context. Concretely: 1. Make `compact` (or an equivalent reduced profile) the **default**. A catalog that overflows a 227K context on registration is not a usable default. 2. Reduce `compact` further. ~66K tokens for tool definitions, before any conversation, is still large; the residual is concentrated in a handful of tools (`inspect_analysis_view` alone is 9.4× the median). 3. Improve discoverability. `REA_MCP_INPUT_SCHEMA_PROFILE` is documented but easy to miss — I hit the hard failure without finding it. Surfacing it in the README's install section and in `rea doctor` output would prevent repeat reports. 4. Optionally: domain-scoped groups (adb / frida / gdb / rizin / web / native / managed / swift) that a caller can enable selectively, or lazy schema delivery (names + one-line summaries first, full schema on selection). No documentation or known-good version to cite for an intended budget — items 1–3 are proposals, not cited requirements. ### Impact and scope - **Default profile: blocking, 100%** of requests. REA cannot be used at all with any client context under ~262K. Not intermittent. - **With `compact`: usable but costly.** ~29% of a 227K context consumed by tool definitions before the first turn; correspondingly less room for conversation, tool output, and reconstruction artifacts. - Affects context budget and prefill latency. - No effect on evidence integrity or process isolation — the failure precedes any analysis. - Untested: whether `REA_MCP_OUTPUT_SCHEMA_PROFILE=off` yields additional savings on this client (OpenAI-style `tools[]` carries no output schema, so likely zero here); behavior under a client that prunes or lazily loads tools; the full set of accepted values for either variable. ### REA version 6.7.0 ### Runtime and platform ``` Node v24.19.0; Ubuntu on WSL (x86_64) Backend: llama.cpp llama-server, router mode, --ctx-size 227328 Analysis engines configured: Ghidra 12.1.4 (GHIDRA_INSTALL_DIR), JDK 21 (JAVA_HOME) Hopper / Ghidra / IDA: not reached — failure precedes any disassembler interaction ``` ### Target and artifact context Not applicable — both measurements are at tool registration; no binary, app, container, or evidence bundle was involved. ### Interface MCP (stdio; client-side bridge `@deepseek-ai/dsh-mcp-client`) ### Earliest failure stage Request parsing or validation (backend rejects the assembled prompt). No REA tool is ever invoked. ### Relevant output or evidence **How obtained:** a local forwarding proxy between the client and the model backend dumped each `POST /chat/completions` body. Per-tool size = `len(json.dumps(tool))` in Python. Two dumps were captured — one per schema profile. Both show 207 `mcp__rea__*` tools with identical name sets. **Dump A — default profile (request rejected):** ``` tool: mcp__rea__compare_web_captures schema=180840B tool: mcp__rea__inspect_analysis_view schema=34505B tool: mcp__rea__compare_application_versions schema=33571B tool: mcp__rea__evaluate_reconstruction_coverage schema=27163B tool: mcp__rea__project_managed_application_graph schema=24679B ... (207 mcp__rea__* tools total) msg[0] system 46B / msg[1] user 8B / msg[2] user 319B / msg[3] user 8B body total: 789958B ``` | Component | Tools | Bytes | ≈ tokens | Share of 261,559 | |---|---|---|---|---| | `mcp__rea__*` schemas | 207 | 832,157 (812.7 KB) | ~259,016 | ~99.0% | | Client built-ins | 15 | 7,715 | ~2,402 | ~0.9% | | Conversation | 4 msgs | 381 | ~126 | ~0.05% | **Dump B — `compact` profile (request succeeds):** ``` tool: mcp__rea__inspect_analysis_view schema=7337B tool: mcp__rea__capture_process_scenario schema=4991B tool: mcp__rea__update_unknown schema=3277B ... (same 207 mcp__rea__* tools) msg[0] system 8600B / msg[3] user 7812B / ... body total: 254101B ``` | Component | Tools | Bytes | ≈ tokens | Share of body | |---|---|---|---|---| | `mcp__rea__*` schemas | 207 | 200,255 (195.6 KB) | ~66,310 | 78.8% | | Client built-ins | 40 | 33,016 (32.2 KB) | ~10,932 | 13.0% | | Messages | 8 | 17,807 | ~4,452 | 7.0% | | Other (model params) | — | 3,023 | ~864 | 1.2% | | **Total** | | **254,101** | **~82,558** | | **Aggregate change — REA schemas only:** | | Default (full) | `compact` | Change | |---|---|---|---| | Tools | 207 | 207 | — | | Bytes | 832,157 (812.7 KB) | 200,255 (195.6 KB) | **−75.9%** | | ≈ tokens | ~259,016 | ~66,310 | **−74.4%** | | Share of a 227,328 context | ~114% (overflow) | ~29.2% | — | **Token estimation method** (applies to every ≈ figure): the backend reported `n_prompt_tokens = 261559` for the 789,958-byte body in dump A → **3.02 B/token** for schema-dominated content. Dumped sizes use `json.dumps` defaults (spaces) and run ~6% over wire size, so were scaled ×0.94. Cross-check on dump A: 207 REA + 15 built-ins + messages = ~261,559, matching the measured value. For dump B — which succeeded, so no backend token count was returned — schema bytes were divided by 3.02 and message bytes by 4.0 (prose), giving ~82,558; treat this as an estimate, not a measurement. **Missing evidence / uncertainty:** - `tools/list` was not invoked directly; sizes come from the client's request body. If the client rewrote schemas before embedding them, figures differ from REA's raw output — no evidence it does, but unverified. - The two dumps came from client sessions with different built-in tool sets (15 vs. 40). The REA name sets are identical and the namespace is the same, so the REA comparison is meaningful; the client-side byte totals are not directly comparable. - Dump B's token figure is derived, not measured. Reading `usage.prompt_tokens` from the successful response would replace the estimate. - The full set of accepted values for `REA_MCP_INPUT_SCHEMA_PROFILE` / `REA_MCP_OUTPUT_SCHEMA_PROFILE` was not found; only `compact` and `off` were used here. - Schema composition after `compact` (what remains in `inspect_analysis_view`) was not analyzed. ### Typed outcome or recovery expected `tools/list` should return a catalog that fits within a documented budget by default. Where REA cannot bound it, it should expose a typed selection mechanism — e.g. a group listing or a server-side flag naming domain groups — so the caller can choose a subset, rather than returning one 207-tool catalog that overflows typical client contexts with no REA-side signal that this will happen. ### Analysis or suspected cause Confirmed by measurement: the default profile ships full inline `description` prose and deeply nested parameter objects; `compact` removes most of that, which accounts for the 75.9% reduction. Hypothesis, not confirmed: what remains in `compact` is still largely description text, since the residual is concentrated in a few tools rather than spread evenly. Cost was and remains concentrated — under the default profile 9 tools were ~46% of the payload and 1 tool was ~21.5% — so further reduction looks tractable without redesigning the tool surface. No REA source was inspected. ### Additional context Workarounds observed, in order of effectiveness: | Approach | REA tools | ≈ request tokens | Functionality lost | |---|---|---|---| | Default profile | 207 | ~261,559 (overflow) | unusable | | `REA_MCP_INPUT_SCHEMA_PROFILE=compact` | 207 | ~82,558 | none | | Client-side `exclude` of 9 largest tools | 198 | ~140,447 (default profile) | 9 tools unavailable | | Client-side `include` of ~27 core tools | 27 | ~9,846 | 180 tools unavailable | | Disable REA | 0 | ~2,528 | all | `compact` is the clear win: ~74% smaller with no loss of tool surface. The asks in "Expected behavior" are about making that the default and going further — a user should not have to discover an environment variable to make REA usable at all. <details> <summary>Full per-tool comparison, all 207 tools (default → compact, sorted by default size)</summary> | Tool | Default (B) | compact (B) | Change | |---|---|---|---| | `compare_web_captures` | 180,840 | 1,888 | −99% | | `inspect_analysis_view` | 34,505 | 7,337 | −79% | | `compare_application_versions` | 33,571 | 1,294 | −96% | | `evaluate_reconstruction_coverage` | 27,163 | 898 | −97% | | `project_managed_application_graph` | 24,679 | 1,067 | −96% | | `capture_browser_scenario` | 24,139 | 2,880 | −88% | | `build_reconstruction_obligation_ledger` | 23,622 | 1,125 | −95% | | `compare_process_captures` | 20,444 | 1,146 | −94% | | `trace_application_feature` | 20,123 | 1,024 | −95% | | `correlate_static_and_runtime` | 18,490 | 1,143 | −94% | | `compare_javascript_export_shapes` | 18,488 | 1,741 | −91% | | `compare_source_to_bundle` | 18,364 | 905 | −95% | | `compare_wasm_interfaces` | 17,610 | 1,254 | −93% | | `reconcile_javascript_runtime` | 17,533 | 1,171 | −93% | | `compare_managed_members` | 17,116 | 1,432 | −92% | | `compare_artifacts` | 16,807 | 1,123 | −93% | | `verify_managed_native_boundaries` | 16,702 | 1,066 | −94% | | `compare_functions` | 16,538 | 854 | −95% | | `trace_javascript_semantics` | 12,838 | 776 | −94% | | `import_managed_reconstruction` | 10,663 | 1,084 | −90% | | `build_call_path` | 8,872 | 780 | −91% | | `project_harmony_application_graph` | 8,727 | 1,001 | −89% | | `project_apple_application_graph` | 8,716 | 990 | −89% | | `find_changed_behavior` | 8,534 | 808 | −91% | | `project_android_application_graph` | 8,526 | 800 | −91% | | `capture_process_scenario` | 6,989 | 4,991 | −29% | | `analyze_javascript_application` | 4,156 | 1,948 | −53% | | `update_unknown` | 4,099 | 3,277 | −20% | | `capture_electron_scenario` | 3,817 | 3,119 | −18% | | `record_unknown` | 3,573 | 2,744 | −23% | | `observe_native_calls` | 3,525 | 2,370 | −33% | | `inspect_web_network_capture` | 3,136 | 2,115 | −33% | | `inspect_sqlite_database` | 2,850 | 2,016 | −29% | | `inspect_packet_capture` | 2,784 | 1,702 | −39% | | `inspect_web_page` | 2,754 | 1,817 | −34% | | `verify_reconstruction` | 2,734 | 686 | −75% | | `capture_native_ui_scenario` | 2,681 | 2,090 | −22% | | `inspect_managed_members` | 2,400 | 1,638 | −32% | | `trace_web_source_location` | 2,368 | 1,880 | −21% | | `open_binary` | 2,358 | 1,654 | −30% | | `analyze_web_bundle` | 2,305 | 1,200 | −48% | | `recover_javascript_sources` | 2,281 | 1,394 | −39% | | `extract_firmware` | 2,246 | 1,573 | −30% | | `decode_signal_recording` | 2,208 | 1,450 | −34% | | `trace_web_module_imports` | 2,089 | 1,554 | −26% | | `start_adb_activity` | 2,008 | 1,364 | −32% | | `inspect_binary_layout` | 1,991 | 1,534 | −23% | | `inspect_packet_fields` | 1,971 | 1,347 | −32% | | `instrument_with_frida` | 1,838 | 1,486 | −19% | | `compare_web_screenshots` | 1,811 | 1,135 | −37% | | `inspect_dart_aot` | 1,796 | 1,457 | −19% | | `inspect_evm_interface` | 1,791 | 1,480 | −17% | | `inspect_with_objdump` | 1,786 | 1,604 | −10% | | `decode_android_resources` | 1,741 | 1,193 | −31% | | `trace_native_values` | 1,741 | 1,145 | −34% | | `inspect_signal_decoders` | 1,699 | 1,194 | −30% | | `inspect_wasm_artifact` | 1,680 | 1,498 | −11% | | `search_strings` | 1,542 | 1,195 | −23% | | `decode_interface_builder` | 1,533 | 1,011 | −34% | | `inspect_recorded_crash` | 1,525 | 1,231 | −19% | | `execute_rizin_command` | 1,497 | 1,376 | −8% | | `export_web_scripts` | 1,486 | 1,118 | −25% | | `observe_javascript_runtime` | 1,484 | 1,251 | −16% | | `get_evidence_bundle` | 1,481 | 1,220 | −18% | | `inspect_electron_page` | 1,459 | 1,087 | −25% | | `inspect_pcap_capture` | 1,440 | 1,051 | −27% | | `trace_android_references` | 1,439 | 1,056 | −27% | | `search_bytes` | 1,437 | 994 | −31% | | `rizin_debug_command` | 1,433 | 1,346 | −6% | | `inspect_pe_resources` | 1,418 | 1,079 | −24% | | `inspect_artifact` | 1,411 | 1,130 | −20% | | `compare_bundles` | 1,390 | 987 | −29% | | `inspect_rust_binary` | 1,383 | 1,252 | −9% | | `start_rizin_debug_session` | 1,381 | 1,247 | −10% | | `start_frida_session` | 1,376 | 1,182 | −14% | | `trace_dylib_resolution` | 1,369 | 1,295 | −5% | | `observe_web_execution` | 1,367 | 1,054 | −23% | | `trace_native_ui_action` | 1,334 | 891 | −33% | | `cutter_command` | 1,323 | 1,098 | −17% | | `push_adb_file` | 1,307 | 906 | −31% | | `analyze_swift_types` | 1,302 | 995 | −24% | | `inspect_go_binary` | 1,288 | 1,157 | −10% | | `list_unknowns` | 1,275 | 972 | −24% | | `pull_adb_package` | 1,274 | 921 | −28% | | `inspect_managed_artifact` | 1,273 | 1,068 | −16% | | `gdb_console` | 1,217 | 1,118 | −8% | | `install_adb_package` | 1,215 | 775 | −36% | | `inspect_web_event_listeners` | 1,207 | 914 | −24% | | `inspect_android_package` | 1,204 | 1,046 | −13% | | `start_gdb_session` | 1,201 | 1,038 | −14% | | `annotate_native_function` | 1,165 | 898 | −23% | | `observe_web_session` | 1,141 | 782 | −31% | | `trace_call_path` | 1,124 | 823 | −27% | | `close_binary` | 1,119 | 893 | −20% | | `procedure_pseudo_code` | 1,106 | 925 | −16% | | `pull_adb_file` | 1,102 | 744 | −32% | | `read_adb_logcat` | 1,099 | 743 | −32% | | `discover_webmcp_tools` | 1,096 | 741 | −32% | | `load_frida_script` | 1,077 | 887 | −18% | | `close_gdb_session` | 1,062 | 992 | −7% | | `close_rizin_debug_session` | 1,053 | 983 | −7% | | `inspect_android_method` | 1,048 | 743 | −29% | | `list_jeb_units` | 1,002 | 643 | −36% | | `start_adb_app` | 1,002 | 790 | −21% | | `decompile_jeb_item` | 993 | 684 | −31% | | `inspect_electron_fuses` | 986 | 792 | −20% | | `set_address_name` | 984 | 688 | −30% | | `search_procedures` | 982 | 651 | −34% | | `observe_native_ui` | 971 | 788 | −19% | | `set_addresses_names` | 969 | 827 | −15% | | `procedure_references` | 968 | 664 | −31% | | `procedure_info` | 959 | 778 | −19% | | `inspect_native_dispatch_metadata` | 953 | 835 | −12% | | `address_to_file_offset` | 952 | 726 | −24% | | `collect_adb_bugreport` | 949 | 695 | −27% | | `unload_frida_script` | 949 | 826 | −13% | | `list_adb_directory` | 940 | 700 | −26% | | `list_frida_processes` | 935 | 842 | −10% | | `read_adb_setting` | 930 | 691 | −26% | | `search_android_classes` | 929 | 722 | −22% | | `inspect_keyed_archive` | 927 | 757 | −18% | | `inspect_adb_package` | 922 | 734 | −20% | | `capture_web_screenshot` | 921 | 605 | −34% | | `list_strings` | 911 | 704 | −23% | | `get_call_graph` | 909 | 669 | −26% | | `inspect_native_instruction` | 899 | 799 | −11% | | `list_frida_devices` | 891 | 818 | −8% | | `inspect_macho` | 888 | 630 | −29% | | `resolve_adb_packages` | 874 | 641 | −27% | | `capture_adb_screen` | 872 | 636 | −27% | | `binary_session` | 869 | 571 | −34% | | `set_inline_comment` | 858 | 550 | −36% | | `inspect_android_class` | 857 | 661 | −23% | | `rizin_debug_session_status` | 849 | 779 | −8% | | `set_comment` | 845 | 528 | −38% | | `xrefs` | 843 | 636 | −25% | | `identify_flutter_build` | 838 | 746 | −11% | | `read_bytes` | 836 | 580 | −31% | | `stop_adb_app` | 830 | 629 | −24% | | `uninstall_adb_package` | 827 | 637 | −23% | | `goto_address` | 818 | 592 | −28% | | `list_adb_packages` | 818 | 575 | −30% | | `inspect_firmware_regions` | 814 | 676 | −17% | | `analyze_function` | 803 | 720 | −10% | | `inspect_adb_window` | 795 | 684 | −14% | | `procedure_callees` | 792 | 611 | −23% | | `procedure_assembly` | 791 | 610 | −23% | | `export_evidence_bundle` | 779 | 516 | −34% | | `trace_feature` | 777 | 553 | −29% | | `resolve_containing_procedure` | 773 | 547 | −29% | | `batch_decompile` | 771 | 587 | −24% | | `set_bookmark` | 771 | 492 | −36% | | `inspect_native_load_image` | 768 | 750 | −2% | | `procedure_callers` | 756 | 575 | −24% | | `close_frida_session` | 747 | 677 | −9% | | `list_browser_targets` | 744 | 571 | −23% | | `unset_bookmark` | 739 | 513 | −31% | | `binary_overview` | 723 | 705 | −2% | | `gdb_session_status` | 723 | 653 | −10% | | `open_jeb_project` | 714 | 567 | −21% | | `extract_artifact` | 712 | 675 | −5% | | `inspect_native_data_type` | 707 | 607 | −14% | | `inspect_adb_device` | 697 | 586 | −16% | | `inspect_managed_native_boundaries` | 696 | 568 | −18% | | `address_name` | 683 | 476 | −30% | | `prev_address` | 683 | 476 | −30% | | `inspect_address_context` | 682 | 582 | −15% | | `frida_session_status` | 677 | 607 | −10% | | `resume_frida_session` | 676 | 606 | −10% | | `verify_unknown_resolution` | 670 | 515 | −23% | | `inspect_native_api` | 654 | 571 | −13% | | `list_javascript_runtime_targets` | 638 | 575 | −10% | | `comment` | 637 | 430 | −32% | | `list_names` | 637 | 430 | −32% | | `import_evidence_bundle` | 632 | 473 | −25% | | `list_electron_targets` | 631 | 504 | −20% | | `read_function_instructions` | 625 | 504 | −19% | | `inspect_asset_catalog` | 619 | 544 | −12% | | `procedure_address` | 619 | 438 | −29% | | `resolve_native_call_targets` | 619 | 519 | −16% | | `next_address` | 617 | 410 | −34% | | `inline_comment` | 612 | 405 | −34% | | `list_cutter_sessions` | 607 | 589 | −3% | | `demangle_swift` | 599 | 499 | −17% | | `inspect_adb_display` | 594 | 483 | −19% | | `get_navigation_context` | 584 | 503 | −14% | | `list_adb_processes` | 582 | 471 | −19% | | `find_xrefs_to_name` | 553 | 466 | −16% | | `list_bookmarks` | 548 | 434 | −21% | | `list_segments` | 546 | 432 | −21% | | `list_adb_features` | 545 | 434 | −20% | | `inspect_plist` | 533 | 396 | −26% | | `list_procedures` | 533 | 419 | −21% | | `list_adb_devices` | 519 | 501 | −3% | | `list_adb_services` | 513 | 402 | −22% | | `inspect_pcap_client` | 509 | 491 | −4% | | `current_address` | 508 | 394 | −22% | | `inspect_jeb_client` | 481 | 463 | −4% | | `current_procedure` | 472 | 358 | −24% | | `inspect_adb_client` | 454 | 436 | −4% | | `get_objc_classes` | 453 | 321 | −29% | | `inspect_apktool_client` | 444 | 426 | −4% | | `inspect_signature` | 382 | 364 | −5% | | `list_documents` | 366 | 348 | −5% | | `list_architectures` | 334 | 316 | −5% | | `get_objc_protocols` | 282 | 264 | −6% | | `current_document` | 279 | 261 | −6% | </details>
Author
Owner

@CassieFox23 commented on GitHub (Oct 23, 2026):

Thanks, RelicOfTesla, for the clear numbers.

Your first ask is done on main. The change in #5975 (aa51e4343) makes compact the default when REA_MCP_INPUT_SCHEMA_PROFILE is unset. full is now opt-in (README, "MCP uses compact input schemas by default"). It merged after 6.7.0, which still defaults to full. So your compact setting stays right until the next release. #5004 is the open 6.8.0 release PR.

Your second ask is still open. #5975 selects the existing compact schemas. It does not shrink them.

Not run: I did not build main or measure schema sizes.

🤖 Written with Claude Code (Sonnet 5.5, verified by Opus 5.5), posted with my OK 🦊

<!-- gh-comment-id:6370383947 --> @CassieFox23 commented on GitHub (Oct 23, 2026): Thanks, RelicOfTesla, for the clear numbers. Your first ask is done on main. The change in #5975 (aa51e4343) makes `compact` the default when `REA_MCP_INPUT_SCHEMA_PROFILE` is unset. `full` is now opt-in (README, "MCP uses compact input schemas by default"). It merged after 6.7.0, which still defaults to `full`. So your `compact` setting stays right until the next release. #5004 is the open 6.8.0 release PR. Your second ask is still open. #5975 selects the existing compact schemas. It does not shrink them. Not run: I did not build main or measure schema sizes. 🤖 Written with Claude Code (Sonnet 5.5, verified by Opus 5.5), posted with my OK 🦊
Author
Owner

@RicSchonfelder commented on GitHub (Oct 24, 2026):

Adding the missing half of the measurement on 6.7.0: REA_MCP_OUTPUT_SCHEMA_PROFILE=off.

o200k_base, same 207-tool catalog, rea mcp straight over stdio:

profile tokens of tools/list
default 1,033,358
REA_MCP_OUTPUT_SCHEMA_PROFILE=off 242,961 (24%)
off + REA_MCP_INPUT_SCHEMA_PROFILE=compact 56,949 (5.5%)
off + compact + client-side truncation 21,130 (2.0%)

Split of the default payload: outputSchema is 75% (2,559,100 of 3,423,371 chars), inputSchema 21%, descriptions 3%, annotations/title 1%. So compact alone leaves the biggest term untouched, which is why the residual in the first post is still 66K. Turning output schemas off is the single largest cut available, and it is cheap for clients: the env var docs already say REA validates every successful result against its canonical contract.

The last row is a stdio proxy that truncates descriptions to 160 chars and flattens property schemas. tools/call passes byte-identical (checked on list_documents). If the maintainers consider that too aggressive to build in, it still makes a useful reference point for how much of the remaining cost is prose.

Two questions:

  1. Given compact is becoming the default input profile, does the same reasoning apply to REA_MCP_OUTPUT_SCHEMA_PROFILE=off? A client that needs structured output can still ask for it, and the default client just saved 4× the tokens.
  2. The 5.5% row is reachable today with two env vars. Do you want that combination documented in the MCP section of the README? It took me a while to find both, and #5861 only covers the input side.

Repro is a initialize → tools/list over stdio plus tiktoken, ~40 lines, no client needed. Happy to post it if that helps.

<!-- gh-comment-id:6385263815 --> @RicSchonfelder commented on GitHub (Oct 24, 2026): Adding the missing half of the measurement on 6.7.0: **`REA_MCP_OUTPUT_SCHEMA_PROFILE=off`**. `o200k_base`, same 207-tool catalog, `rea mcp` straight over stdio: | profile | tokens of `tools/list` | |---|---| | default | 1,033,358 | | `REA_MCP_OUTPUT_SCHEMA_PROFILE=off` | 242,961 (24%) | | `off` + `REA_MCP_INPUT_SCHEMA_PROFILE=compact` | 56,949 (5.5%) | | `off` + `compact` + client-side truncation | 21,130 (2.0%) | Split of the default payload: `outputSchema` is **75%** (2,559,100 of 3,423,371 chars), `inputSchema` 21%, descriptions 3%, `annotations`/`title` 1%. So `compact` alone leaves the biggest term untouched, which is why the residual in the first post is still 66K. Turning output schemas off is the single largest cut available, and it is cheap for clients: the env var docs already say REA validates every successful result against its canonical contract. The last row is a stdio proxy that truncates descriptions to 160 chars and flattens property schemas. `tools/call` passes byte-identical (checked on `list_documents`). If the maintainers consider that too aggressive to build in, it still makes a useful reference point for how much of the remaining cost is prose. Two questions: 1. Given `compact` is becoming the default input profile, does the same reasoning apply to `REA_MCP_OUTPUT_SCHEMA_PROFILE=off`? A client that needs structured output can still ask for it, and the default client just saved 4× the tokens. 2. The 5.5% row is reachable today with two env vars. Do you want that combination documented in the MCP section of the README? It took me a while to find both, and #5861 only covers the input side. Repro is a `initialize` → `tools/list` over stdio plus `tiktoken`, ~40 lines, no client needed. Happy to post it if that helps.
Author
Owner

@kaoru0822-kitauji commented on GitHub (Oct 25, 2026):

6.8.0 data point (published rea-agents@6.8.0 vs 6.7.0, macOS 26.7.1 arm64, Node 24.22.1, rea mcp over stdio, tools/list read with @modelcontextprotocol/client 2.3.1). Bytes are JSON.stringify(tools).length; token figures are bytes/3.5 estimates, not tokenizer counts.

Profile 6.7.0 6.8.0 Change
Default (6.7.0 full input; 6.8.0 compact input is now the default) 3,158,352 B, 207 tools 3,504,966 B, 229 tools +11%
outputSchema share of default 2,353,893 B 3,199,098 B +36%
Compact input + REA_MCP_OUTPUT_SCHEMA_PROFILE=off (like-for-like) 219,211 B (~63K tok est.) 302,204 B (~86K tok est.) +38%
Same, the 207 tools present in both versions only 219,211 B 258,632 B +18%
description total (always model-visible) 92,739 B 135,500 B +46%

The new compact default worked: input schemas fell from 667,641 B to 121,537 B. But with default settings the output schemas grow by more than input shrinks, and the like-for-like model-visible catalog is 38% larger. That includes +18% on tools that already existed, so it isn't only the 22 new tools.

Largest single contributor: the inspect_analysis_view outputSchema went from 137,985 B to 382,064 B (2.8×); with output schemas off, that tool is still 15,229 B.

Repro:

# stdio MCP client: initialize, tools/list, then measure JSON.stringify(tools).length
REA_MCP_OUTPUT_SCHEMA_PROFILE=off npx -y rea-agents@6.8.0 mcp
<!-- gh-comment-id:6396038868 --> @kaoru0822-kitauji commented on GitHub (Oct 25, 2026): 6.8.0 data point (published `rea-agents@6.8.0` vs `6.7.0`, macOS 26.7.1 arm64, Node 24.22.1, `rea mcp` over stdio, `tools/list` read with `@modelcontextprotocol/client` 2.3.1). Bytes are `JSON.stringify(tools).length`; token figures are bytes/3.5 estimates, not tokenizer counts. | Profile | 6.7.0 | 6.8.0 | Change | |---|---|---|---| | Default (6.7.0 full input; 6.8.0 compact input is now the default) | 3,158,352 B, 207 tools | 3,504,966 B, 229 tools | +11% | | `outputSchema` share of default | 2,353,893 B | 3,199,098 B | +36% | | Compact input + `REA_MCP_OUTPUT_SCHEMA_PROFILE=off` (like-for-like) | 219,211 B (~63K tok est.) | 302,204 B (~86K tok est.) | +38% | | Same, the 207 tools present in both versions only | 219,211 B | 258,632 B | +18% | | `description` total (always model-visible) | 92,739 B | 135,500 B | +46% | The new compact default worked: input schemas fell from 667,641 B to 121,537 B. But with default settings the output schemas grow by more than input shrinks, and the like-for-like model-visible catalog is 38% larger. That includes +18% on tools that already existed, so it isn't only the 22 new tools. Largest single contributor: the `inspect_analysis_view` `outputSchema` went from 137,985 B to 382,064 B (2.8×); with output schemas off, that tool is still 15,229 B. Repro: ```sh # stdio MCP client: initialize, tools/list, then measure JSON.stringify(tools).length REA_MCP_OUTPUT_SCHEMA_PROFILE=off npx -y rea-agents@6.8.0 mcp ```
Author
Owner

@morluto commented on GitHub (Oct 26, 2026):

Thank you for the detailed catalog breakdown. Compact input advertisements became the default in #5975, addressing the first requested change, but the remaining context cost and discoverability questions are distinct and this issue stays open for them. The figures here describe the measured 207-tool catalog; they should not be treated as a current measurement without a new equivalent run.

<!-- gh-comment-id:6428525866 --> @morluto commented on GitHub (Oct 26, 2026): Thank you for the detailed catalog breakdown. Compact input advertisements became the default in #5975, addressing the first requested change, but the remaining context cost and discoverability questions are distinct and this issue stays open for them. The figures here describe the measured 207-tool catalog; they should not be treated as a current measurement without a new equivalent run.
Author
Owner

@AvatarGanymede commented on GitHub (Oct 29, 2026):

Please take the time to seriously study how to design MCP tool schemas for agents. The catalog measurements reported in this issue and in morluto/rea#7155 warrant a proper design review. Making compact input schemas the default was useful, but it does not finish the job. Users should not have to discover environment variables or build filtering proxies just to leave enough context for their actual work.

An agent-facing tool contract needs a deliberate context budget. Exposing extensive nested data models across hundreds of tools, with repeated descriptions and large inline evidence structures, makes that budget harder to control. Schema validity alone is not a sufficient usability standard.

These are useful references and tutorials to work through:

  • MCP specification: Tools — the actual discovery and invocation contracts. outputSchema is optional; when advertised, structured results must conform to it. Evaluate compact output contracts or an explicit profile for clients that need full output schemas, while preserving server-side validation. Optional does not mean useless, but advertising the largest possible schema by default deserves justification.
  • Anthropic: Writing effective tools for agents — with agents — practical guidance on choosing useful tool boundaries, clear names and parameters, informative descriptions, and evaluating tools on real tasks. Use descriptions to explain selection, constraints, and correct arguments; move exhaustive background documentation out of the always-loaded surface.
  • Anthropic: Code execution with MCP — explains the context cost of loading entire catalogs and demonstrates progressive discovery. This requires appropriate client/runtime support; MCP pagination alone does not guarantee lazy loading into the model.
  • JSON Schema: Structuring a complex schema — explains reusable definitions with $defs and $ref. Apply these where supported and test interoperability. Local references do not automatically deduplicate separate tool definitions, and client transformations may expand references again.

Concrete improvements worth prioritizing:

  1. Keep inputs focused on what the model must supply. Where an artifact or evidence object is already stored, accept a stable identifier plus the necessary options instead of requiring the model to resend a large nested object.
  2. Offer documented server-side tool-family selection so users can advertise the capabilities relevant to their workflow. Keep discovery understandable without replacing everything with one opaque, untyped dispatcher.
  3. Add release checks for catalog bytes, per-tool schema size, and actual model-visible token counts in representative clients. Publish the version, profile, tokenizer, and client behavior, and set regression budgets.

The distinction in the last point matters: raw tools/list bytes are not automatically prompt tokens. Some clients omit output schemas or defer tool definitions, so the historical measurements here should not be presented as universal current costs. I am not claiming a fresh measurement. I am asking for the schema surface to be treated as a first-class product interface, with measured limits and usable defaults. Please prioritize that design work.

<!-- gh-comment-id:6504688939 --> @AvatarGanymede commented on GitHub (Oct 29, 2026): Please take the time to seriously study how to design MCP tool schemas for agents. The catalog measurements reported in this issue and in [morluto/rea#7155](https://github.com/morluto/rea/issues/7155) warrant a proper design review. Making compact input schemas the default was useful, but it does not finish the job. Users should not have to discover environment variables or build filtering proxies just to leave enough context for their actual work. An agent-facing tool contract needs a deliberate context budget. Exposing extensive nested data models across hundreds of tools, with repeated descriptions and large inline evidence structures, makes that budget harder to control. Schema validity alone is not a sufficient usability standard. These are useful references and tutorials to work through: - **[MCP specification: Tools](https://modelcontextprotocol.io/specification/2025-06-18/server/tools)** — the actual discovery and invocation contracts. `outputSchema` is optional; when advertised, structured results must conform to it. Evaluate compact output contracts or an explicit profile for clients that need full output schemas, while preserving server-side validation. Optional does not mean useless, but advertising the largest possible schema by default deserves justification. - **[Anthropic: Writing effective tools for agents — with agents](https://www.anthropic.com/engineering/writing-tools-for-agents)** — practical guidance on choosing useful tool boundaries, clear names and parameters, informative descriptions, and evaluating tools on real tasks. Use descriptions to explain selection, constraints, and correct arguments; move exhaustive background documentation out of the always-loaded surface. - **[Anthropic: Code execution with MCP](https://www.anthropic.com/engineering/code-execution-with-mcp)** — explains the context cost of loading entire catalogs and demonstrates progressive discovery. This requires appropriate client/runtime support; MCP pagination alone does not guarantee lazy loading into the model. - **[JSON Schema: Structuring a complex schema](https://json-schema.org/understanding-json-schema/structuring)** — explains reusable definitions with `$defs` and `$ref`. Apply these where supported and test interoperability. Local references do not automatically deduplicate separate tool definitions, and client transformations may expand references again. Concrete improvements worth prioritizing: 1. Keep inputs focused on what the model must supply. Where an artifact or evidence object is already stored, accept a stable identifier plus the necessary options instead of requiring the model to resend a large nested object. 2. Offer documented server-side tool-family selection so users can advertise the capabilities relevant to their workflow. Keep discovery understandable without replacing everything with one opaque, untyped dispatcher. 3. Add release checks for catalog bytes, per-tool schema size, and actual model-visible token counts in representative clients. Publish the version, profile, tokenizer, and client behavior, and set regression budgets. The distinction in the last point matters: raw `tools/list` bytes are not automatically prompt tokens. Some clients omit output schemas or defer tool definitions, so the historical measurements here should not be presented as universal current costs. I am not claiming a fresh measurement. I am asking for the schema surface to be treated as a first-class product interface, with measured limits and usable defaults. Please prioritize that design work.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#3551
No description provided.