Token measurements¶
Read just what you need. Send only what changed. Windows MCP gives your assistant both ways to save tokens, with screenshots available when it needs a picture.
Tokens are the units AI services count when processing text and images. The real-task comparison covers full tasks. Smaller measurements below cover reading a single field and sending only changes instead of repeating a window's controls.
Real tasks in Notepad, Word, PowerPoint, and Chrome¶
The 16-trial run compares GPT-6.1 Sol and GPT-6 Luna on Notepad, Word, PowerPoint, and Chrome. Controls first completed 8 of 8 tasks. Screenshots only completed 7 of 8.
Across the seven app/model pairs where both routes completed, controls first used a median 34.9% fewer input tokens and took a median 34.3% less framework session time. The detailed table below includes the failed trial and the pair where controls used more.
Saved files and submitted values are checked independently. The framework also checks actual model requests, tools, reasoning, image detail, usage, and stop reasons before a result can be published.
Real-app tasks, safeguards, and how to run the comparison
This benchmark asks an AI to finish work in Notepad, Word, PowerPoint, and Chrome, then checks the saved result independently. It measures the whole conversation and its Windows actions, not just reading a saved image.
Results¶
The 30 September 2026 run completed all 16 trials. The controls-first route completed 8 of 8 tasks. The screenshot-only route completed 7 of 8. GPT-6 Luna reached the 80-call limit without saving the PowerPoint copy in its screenshot-only trial. That failure remains part of the result.
Across the seven app/model pairs where both routes completed, controls first used a median 34.9% fewer input tokens and took a median 34.3% less framework session time.
| App | Model | Controls first | Screenshots only | Controls-first input tokens | Controls-first time |
|---|---|---|---|---|---|
| Notepad | GPT-6.1 Sol | Passed | Passed | 70.4% fewer | 51.5% less |
| Notepad | GPT-6 Luna | Passed | Passed | 56.8% fewer | 42.3% less |
| Word | GPT-6.1 Sol | Passed | Passed | 30.8% fewer | 9.4% less |
| Word | GPT-6 Luna | Passed | Passed | 21.5% fewer | 5.9% less |
| PowerPoint | GPT-6.1 Sol | Passed | Passed | 58.1% more | 35.0% more |
| PowerPoint | GPT-6 Luna | Passed | Failed at 80 calls | Not compared | Not compared |
| Chrome | GPT-6.1 Sol | Passed | Passed | 34.9% fewer | 34.3% less |
| Chrome | GPT-6 Luna | Passed | Passed | 88.0% fewer | 79.0% less |
This is one run per combination, not a general model ranking. PowerPoint with GPT-6.1 Sol is an important counterexample: controls completed the task but used more tokens and time than screenshots. Token counts measure model input, not price.
Download the privacy-safe evidence. It contains settings, counts, hashes, request-audit metadata, and stop reasons. Raw screenshots, messages, desktop text, and local paths remain private.
Tasks¶
| App | Requested work | Independent check |
|---|---|---|
| Notepad | Change a review date and status, add an action, and save a copy | Exact saved text, including the final line break, with the original unchanged |
| Word | Apply Heading 1, change a date, preserve the other paragraphs and styles, and save a copy | Text and paragraph styles in the saved Word file |
| PowerPoint | Change a title and a bullet, reorder two slides, and save a copy | Saved slide order and text on every slide |
| Chrome | Complete and submit a workshop booking with seven fields, including a department, date, and projector checkbox | Values received by the local booking server |
The agent does not get the complete source document text in its task prompt. It must inspect the open application, make the changes, and save or submit them. A claim that the task is finished does not count as success.
Two routes through the same server¶
Controls first: the agent can find, read, click, type into, and select Windows controls. It can request complete or changes-only views and use the file-saving helper. Screenshots, mouse, and keyboard input remain available.
Screenshots: the agent gets unannotated images and uses mouse and keyboard input. It cannot read control names, values, element IDs, or text through the control tools. It must handle save dialogs itself.
Both routes use Windows MCP. This compares two tool sets within the same product, not separate products.
The benchmark adapter restricts actions, window listings, and screenshots to the test-owned application. Batch operations, macros, the clipboard, launching other apps, shell commands, Office APIs, browser page source, and developer tools are unavailable to the agent.
Models and run order¶
The matrix has 16 trials: four apps, two models, and two routes. The model IDs are gpt-6.1-sol and gpt-6-luna. Every trial starts a fresh, tool-restricted model session with medium reasoning, high-detail images, a ten-minute limit, and an 80-tool-call limit.
Route order alternates across app/model pairs. The apps run one at a time on the same reserved desktop. Each pair starts with copies of the same input file. Notepad, Word, and PowerPoint must not already be open. Chrome uses a separate test profile and local booking page.
What is counted¶
Completion comes first. Saved files and submitted form values are checked outside the model session. The original input must remain unchanged.
The framework records the actual model requests, tools, reasoning setting, image detail, usage, stop reason, and admitted tool calls. Unsupported or incomplete request formats stop the run rather than producing incomplete evidence.
Token and time comparisons are calculated only for matching app/model pairs where both routes complete within their limits. Failed attempts remain in the run and are not credited as efficiency wins. One trial per combination is an initial comparison, not a general model ranking.
Framework session time includes model-runtime startup and cleanup. It excludes Windows app setup and the independent saved-result check.
Evidence and privacy¶
Keep the framework JSON, JUnit report, task artifacts, and app checks together in a fresh private directory. Raw reports may contain local paths, screenshots, model messages, or unrelated text visible in dialogs, so do not publish them.
Any future public export must contain only settings, counts, request-audit metadata, and result hashes. It must exclude desktop images, raw window text, model messages, authentication, and local file paths.
Reproduce the real-app comparison¶
Use an unlocked Windows desktop reserved for the benchmark. Install Notepad, Word, PowerPoint, and Chrome. Build the server and authenticate the GitHub CLI or provide GITHUB_TOKEN; never put a token in source files or reports.
Run the no-model checks first:
dotnet build src\Sbroenne.WindowsMcp -c Release
uv run --project tests\usage_evals pytest tests\usage_evals\tests\unit -q
uv run --project tests\usage_evals pytest tests\usage_evals\tests\comparison --collect-only -q
The live command is in the evaluation guide. It requires approval for 16 model sessions and an exclusive desktop. Without that opt-in, the comparison is skipped.
Do not resume retired standalone runners or combine interrupted runs. Optional AI-generated report analysis is a separate paid operation and is not part of the comparison.
Screenshots versus direct reads¶
The AI read the field correctly every time. Direct reads used 51.4% fewer input tokens than low-detail screenshots and 70.5% fewer than high-detail screenshots.
We gave GPT-6 Astra, GPT-6 Luna, GPT-5.6 Sol, and GPT-5.6 Luna the same 25 saved form views in three ways: field text, low-detail screenshots, and high-detail screenshots. All 300 answers matched the entered value exactly. Each read started fresh, without previous answers or tools that could look up the answer.
- GPT-6 Astra 51.4%
- GPT-6 Luna 51.4%
- GPT-5.6 Sol 51.4%
- GPT-5.6 Luna 51.4%
Compared with low-detail screenshots of the same form. All 300 answers across four models and three input types were correct.
The chart uses actual input-token counts reported by the model service, including the question and instructions. Savings use the totals from all 25 reads per input type, including the first view.
Screenshots worked too. Every model returned 25 correct answers out of 25 at both image settings. Focused reads returned those same answers with less input. That is the point: send what the task needs, with a picture available when useful.
The test used five values, captured five times each in one form. It measures reading the field, not completing an entire task or comparing separate products.
What differed in the single-field test?¶
Accuracy and input tokens were the same. Every model used a middle input count of 170 tokens for direct text, 350 for a low-detail image, and 576 for a high-detail image. None was more accurate on this form.
Response times differed. The table shows the middle time in seconds across 25 reads for each model and input type.
| Model | Direct text | Low-detail image | High-detail image |
|---|---|---|---|
| GPT-6 Astra | 2.74 | 3.21 | 3.17 |
| GPT-6 Luna | 2.12 | 2.10 | 1.99 |
| GPT-5.6 Sol | 1.96 | 2.41 | 2.39 |
| GPT-5.6 Luna | 2.35 | 2.59 | 2.91 |
GPT-5.6 Sol was quickest for text reads; GPT-6 Luna was quickest for images in this run. Smaller input did not always mean a quicker answer. These times include network and service delays, and the models ran in separate batches, so they are observations rather than a guaranteed speed ranking.
GPT-6 Luna reported more output tokens: 1,277 over its 75 reads, compared with 690 for each other model. That includes 514 reported reasoning tokens for GPT-6 Luna. Input savings and output use are different measurements.
All four handled this form successfully. The useful difference here was how much they returned and how long they took, not whether they could read it.
All four models: detailed results, recorded answers, and how to repeat the tests
All 300 answers were correct. With every model, direct field reads used 51.4% fewer input tokens than low-detail screenshots and 70.5% fewer than high-detail screenshots.
This comparison measures GPT-6 Astra, GPT-6 Luna, GPT-5.6 Sol, and GPT-5.6 Luna reading the same Windows form. Each model receives 25 direct text reads, 25 low-detail screenshots, and 25 high-detail screenshots.
Live AI reading results¶
Each row contains 25 reads. Token counts and response times below are medians per read; seconds include network and service time.
| Model / input | Correct reads | Input tokens | Output tokens | Seconds |
|---|---|---|---|---|
| GPT-6 Astra / Direct text | 25/25 | 170 | 9 | 2.74 |
| GPT-6 Astra / Low-detail image | 25/25 | 350 | 9 | 3.21 |
| GPT-6 Astra / High-detail image | 25/25 | 576 | 9 | 3.17 |
| GPT-6 Luna / Direct text | 25/25 | 170 | 25 | 2.12 |
| GPT-6 Luna / Low-detail image | 25/25 | 350 | 10 | 2.10 |
| GPT-6 Luna / High-detail image | 25/25 | 576 | 9 | 1.99 |
| GPT-5.6 Sol / Direct text | 25/25 | 170 | 9 | 1.96 |
| GPT-5.6 Sol / Low-detail image | 25/25 | 350 | 9 | 2.41 |
| GPT-5.6 Sol / High-detail image | 25/25 | 576 | 9 | 2.39 |
| GPT-5.6 Luna / Direct text | 25/25 | 170 | 9 | 2.35 |
| GPT-5.6 Luna / Low-detail image | 25/25 | 350 | 9 | 2.59 |
| GPT-5.6 Luna / High-detail image | 25/25 | 576 | 9 | 2.91 |
Differences between the models¶
Accuracy and input usage were tied. All four models read every value correctly from text and both image settings. Each used the same input tokens for each matching observation. This task does not distinguish their accuracy on harder forms or other apps.
Response time differed. GPT-5.6 Sol had the lowest median time for direct text; GPT-6 Luna had the lowest for both image settings in these runs. Direct text was quicker than images for three models. GPT-6 Luna was slightly quicker with images, so fewer input tokens did not always mean a quicker answer.
GPT-6 Luna reported more output. Across its 75 reads it used 1,277 output tokens, including 514 reported reasoning tokens. Each other model reported 690 output tokens and zero reasoning tokens. These are service-reported counts, not a claim about how much unreported computation each model performs.
Sample totals¶
Every model completed five samples of five observations for each input type. Each sample used 851 direct-text input tokens, 1,750 low-detail image tokens, and 2,880 high-detail image tokens. The table totals all five samples; no first views or unfavorable results are omitted.
| Model | Text input | Low-detail input | High-detail input | Text output | Low-detail output | High-detail output |
|---|---|---|---|---|---|---|
| GPT-6 Astra | 4,255 | 8,750 | 14,400 | 230 | 230 | 230 |
| GPT-6 Luna | 4,255 | 8,750 | 14,400 | 619 | 344 | 314 |
| GPT-5.6 Sol | 4,255 | 8,750 | 14,400 | 230 | 230 | 230 |
| GPT-5.6 Luna | 4,255 | 8,750 | 14,400 | 230 | 230 | 230 |
There were exactly 300 model requests: no failed requests, retries, incorrect answers, or malformed answers. None reported cached input or cache writes.
How to interpret the comparison¶
Input tokens are reported by the model service, including the question and system instruction. Direct text includes both the field-discovery reply and the value-reading reply. Savings compare the total input across all 25 reads, including each sample's first view, rather than rounding the median first.
Output tokens include any reasoning tokens reported by the service. They are shown separately from input, not silently added to the input-saving claim. Token counts are not currency costs: models and services can charge differently.
Response time runs from sending the observation to receiving the completed answer. It includes network and service time, but excludes session creation and Windows capture time. Requests run one at a time; models run in the order Astra, GPT-6 Luna, Sol, GPT-5.6 Luna. Input types rotate within each model. Times describe these batches, not a guaranteed model-speed ranking: service load and the time of each batch can affect them.
Method¶
The question and expected answers¶
Every read starts a fresh session with no tools, skills, repository instructions, or previous answers. The question is:
What is the username entered in this form? Reply with JSON only: {"username": "the exact value"}.
The system instruction is identical for every model and input type: Answer the user's question using only the supplied observation. The text route appends both saved JSON replies under Observed form controls:. The image routes attach the original JPEG as form.jpg, without the answer in the filename or prompt. Expected values stay in the scorer.
The five values are Baseline, Alice, Alice Smith, Bob, and Carol. There are five captures of each value: 25 images of one form, not 25 different apps or forms. Images are 700 by 550 pixels. The form also repeats the username in a status heading; the image route can read either visible occurrence. Scoring requires an exact string match in the requested JSON format.
Images, controls, and model settings¶
The runner sets the actual Responses API input_image.detail field to low or high through the Copilot SDK's supported request-handler hook. It checks that the submitted bytes match the saved screenshot's SHA-256 hash. It does not simulate low detail by resizing a file.
All four models use medium reasoning effort, the same question, instructions, and saved inputs. The comparison checks outgoing model IDs, image detail, reported response models, usage, and input hashes. Models are called explicitly, not selected through automatic routing.
The saved images come from Windows MCP's production ScreenshotService: window-only JPEG, quality 60, without cursor or annotations. The full control tree is read before and after each screenshot. Both reads must succeed, be nonempty, contain no truncation warning, and match. This checks control-state stability, not purely visual animations.
Direct reads discover the unique UsernameInput edit control and read its value. Both replies are included every time. Choosing this selector is outside the reading test, just as deciding where to inspect an image is.
Scope¶
This compares reading a field from an observation. It does not include choosing tools, navigating the app, entering values, or completing a whole user task. It is not a comparison of separate products. A full-window control list is not a focused field read and can contain much more information.
Run evidence¶
The live model requests ran on 2026-09-27 through GitHub Copilot, using Copilot SDK 1.0.14 and runtime 1.0.85.
The complete machine-readable evidence contains every answer, expected value, outgoing detail setting, usage count, duration, and image/text hash, plus a checked summary for each model. Each run records its source revision, dirty working-tree state, and SHA-256 of the exact runner. Wrong and malformed answers are retained. Transport failures stop the runner and preserve the incomplete trial rather than silently retrying.
The source captures are from screenshot-winforms-field-editing-9a1e0081953948b1ac39f960ac0932bc, recorded on Windows 10.0.26220.0 and .NET 10.0.12, Release build with SDK 10.0.401. Source was an uncommitted working tree based on 67ba78d6b3a99bdabee27898dab64b38aafb55ed, including the benchmark and the branch's automation changes, not a released package.
| Capture binary | SHA-256 |
|---|---|
Sbroenne.WindowsMcp.Tests.dll | CB9103F1EB18154FC8A783150A7AE55D3695E592E0854FB37005DFA272D4E0A2 |
Sbroenne.WindowsMcp.dll | 5DD7C47215AA1B495CCFF4A46414B6D300A9A1AF88958E8A8E3C2272069614FA |
Raw screenshots and response JSON remain local; the commands below produce fresh captures. Control identifiers can vary between capture runs, so text counts can vary slightly. All four model runs here use the same saved captures.
Reproduce¶
Capture the form¶
Use an unlocked Windows desktop and the test prerequisites in the testing instructions. Do not use the desktop while this capture runs. These commands do not make paid model requests.
$env:MCP_SNAPSHOT_BENCHMARK_OUTPUT = Join-Path $env:TEMP "windows-mcp-screenshot-benchmark"
dotnet build tests\Sbroenne.WindowsMcp.Tests -c Release
dotnet test tests\Sbroenne.WindowsMcp.Tests -c Release --no-build --filter "FullyQualifiedName~Unit.ScreenshotComparisonBenchmarkTests|FullyQualifiedName~Unit.SnapshotBenchmarkRunnerTests"
dotnet test tests\Sbroenne.WindowsMcp.Tests -c Release --no-build --filter "FullyQualifiedName~Benchmark_ScreenshotVersusControls_WinForms" --logger "console;verbosity=detailed"
A completed capture writes report.md, observations.json, and a JPEG plus response JSON for each observation. Use its uniquely named folder below. The live comparison uses actual model usage, not the capture report's size estimates.
Model reads¶
The published 300 reads remain historical evidence. Their standalone SDK runner is retired; the retained Python helpers only read and validate saved evidence. Do not use that script to start more paid requests.
New model-driven comparisons must run through pytest-skill-engineering. The current live suite measures complete real-app tasks, not another set of single-field reads. Reintroducing live single-field reads requires a framework-based test and separate approval of its model-call budget. The summary command rejects incomplete runs, duplicate cases, mismatched inputs/settings, and inconsistent usage or scoring.
Offline checks make no model requests:
python -m unittest discover -s scripts\tests -p "*readability*.py" -v
python -m unittest discover -s gh-pages\tests -v
The changes-only measurement compares text updates with full text. It measures a separate capability, not another saving to add to the screenshot comparison.
Changes-only text versus full text¶
84.0% to 96.6% fewer approximate tokens in changes-only text updates. That is the range measured in our Excel, Word, and desktop test-app workloads, compared with returning the same controls in full after each action.
Unlike the screenshot comparison above, these figures exclude the first view and use a different text-counting method. They measure repeated text updates, not savings against screenshots. Do not add the two benchmarks' percentages together or with the real-task results.
- Excel worksheet editing 84.0%
- Word document editing 86.1%
- Desktop test app navigation 96.6%
Longer bars mean greater savings. Compared with repeating the whole window as text. First read not counted.
Windows MCP sends a full view when a changes-only reply would be unsafe or too large. Smaller updates are useful, but they are not guaranteed at every step. The detailed measurements are expandable below.
Put the results to use¶
Ask your assistant to read the field, checkbox, or table needed for the task, rather than the whole window. For repeated checks, it can request only changes. Use screenshots when appearance matters or an app does not provide useful controls.
You do not need to learn tool settings for normal use. Your assistant chooses which view to request.
Does it make tasks faster?¶
The real-task comparison measures full framework session time for both routes. Its seven completed pairs had a median 34.3% reduction with controls first, but one PowerPoint pair took 35.0% more time. The single-field test did not show a consistent speed advantage. An app's speed and the time the AI takes to decide also affect the task.
For scripts and tool settings, use the command reference.
Compare controls and screenshots
Changes-only text benchmark: method and individual samples
A snapshot describes the controls in a window. Automatic snapshots can send just the changes since the last view, rather than repeating the whole window.
The server still reads the complete window before comparing it. It sends changes only when they are safe to apply and take less than 80% of a complete automatic response. Otherwise it sends a complete view. Explicit mode=full requests always return the full tree of controls.
Recorded measurements: 27 September 2026¶
These runs used source revision 67ba78d6b3a99bdabee27898dab64b38aafb55ed, Release mode, .NET SDK 10.0.401, and Windows 10.0.26220.0. The Word run includes the document-startup fix in this change: wait for the document window, not the temporary "Opening" window. The Chrome run used an earlier implementation that removed a selected address-completion suggestion inside the typing tool. Current typing reports that mismatch without changing it. The benchmark caller now explicitly checks the selected suggestion before rejecting it and verifies the final URL. The Chrome figures below are retained as earlier snapshot measurements, not validation or timing measurements of the current typing workflow. The tests ran one at a time on a Windows desktop, using temporary test content.
| Workload | Environment | Fewer bytes | Fewer approximate tokens | Full views / changes-only views |
|---|---|---|---|---|
| Electron test app navigation | Electron 44.2.0 | 95.6% | 96.6% | 0/20 |
| Excel worksheet editing | Excel 16.0.20326.20158 | 81.0% | 84.0% | 0/20 |
| GitHub repository navigation | Chrome 154.0.8037.57 | 10.6% | 11.3% | 20/0 |
| Word document editing | Word 16.0.20326.20158 | 82.7% | 86.1% | 0/20 |
Chrome completed all 15 runs: five samples in each of the three modes, covering 60 page changes. All 20 measured automatic replies were complete views, not changes-only replies. Their 11.3% token saving came from the more compact automatic output. This page-to-page workload behaves differently from small edits within the same window.
What the percentages mean¶
Each workload runs five times in each of three modes:
- Action-only: perform four actions without taking snapshots. This measures action time, not information savings.
- Full: request a complete snapshot after each action.
- Auto: take one initial snapshot, then request changes after each action. The initial snapshot is not included in the measured totals.
For each auto run, the test also saves the same captured controls as full responses. The savings compare those two versions of the same captures. The reported percentage is the median of the five run-level percentages. This avoids treating differences between separate live webpages as savings.
Tokens are the small pieces of text an AI model processes. Counts here use SharpToken's cl100k_base tokenizer as an approximation. They do not measure the cost of a whole agent conversation, and other models may count differently.
Timing and response sizes¶
These are median totals for four actions or snapshots, not per-call times.
| Workload | Mode | Action ms | Snapshot ms | Bytes | Approximate tokens |
|---|---|---|---|---|---|
| Electron | action-only | 2663.7 | 0.0 | 0 | 0 |
| Electron | full | 3341.1 | 7909.3 | 80385 | 30928 |
| Electron | auto | 2912.8 | 6879.2 | 3543 | 1054 |
| Excel | action-only | 8.8 | 0.0 | 0 | 0 |
| Excel | full | 23.0 | 6465.8 | 15996 | 6261 |
| Excel | auto | 7.9 | 4296.9 | 3032 | 1005 |
| Chrome | action-only | 25165.4 | 0.0 | 0 | 0 |
| Chrome | full | 20494.1 | 34256.9 | 312581 | 124179 |
| Chrome | auto | 22791.2 | 37659.0 | 289265 | 113903 |
| Word | action-only | 21.0 | 0.0 | 0 | 0 |
| Word | full | 15.3 | 3715.7 | 10765 | 4198 |
| Word | auto | 15.6 | 3101.3 | 1864 | 586 |
Smaller responses do not necessarily mean faster capture. Timing depends on the application, its startup state, and the machine's other work.
Workloads¶
- Electron: move through Forms, Data, Settings, and Home in the project's test application. This does not measure all Electron applications.
- Chrome: visit Issues, Pull requests, Actions, and Code in the public
microsoft/vscodeGitHub repository, using a separate browser profile. The address bar is discovered during setup and its exact ID is reused. The current benchmark caller handles a verified selected URL suggestion explicitly; it does not repeat a failed navigation. Setup observations are outside the measured actions. Measured snapshots include the webpage, not just the browser's toolbar. - Word: edit, append text, undo, and edit a temporary RTF document.
- Excel: enter four values in a temporary CSV file. This does not test formulas, ribbon commands, or every Excel feature.
The order of the three modes rotates between samples. Each starts with equivalent test content. Response sizes use the server's normal JSON output.
Chrome startup checks read the window once per attempt and require the webpage controls to appear. Popup handling uses buttons already found in that view, rather than searching repeatedly for popups that may not exist. Those searches could previously consume the entire startup waiting time. Startup failures now record the timing of each attempt and the last window view.
Raw samples¶
Each row covers four actions. The "Same-capture full" columns are the complete versions used to calculate auto savings.
Electron 44.2.0¶
| Sample | Mode | Action ms | Snapshot ms | Bytes | Tokens | Same-capture full bytes | Same-capture full tokens | Full/diff |
|---|---|---|---|---|---|---|---|---|
| 1 | action-only | 7017.9 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 1 | full | 3015.7 | 7909.3 | 80385 | 30927 | 80385 | 30927 | 4/0 |
| 1 | auto | 2912.8 | 6879.2 | 3543 | 1054 | 80385 | 30927 | 0/4 |
| 2 | full | 2726.3 | 6724.5 | 80385 | 30928 | 80385 | 30928 | 4/0 |
| 2 | auto | 2669.9 | 6786.5 | 3543 | 1055 | 80385 | 30927 | 0/4 |
| 2 | action-only | 2663.7 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 3 | auto | 4099.0 | 8825.2 | 3543 | 1043 | 80385 | 30925 | 0/4 |
| 3 | action-only | 2369.2 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 3 | full | 3763.8 | 10510.2 | 80385 | 30928 | 80385 | 30928 | 4/0 |
| 4 | action-only | 4146.8 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 4 | full | 4791.7 | 10409.4 | 80385 | 30928 | 80385 | 30928 | 4/0 |
| 4 | auto | 5419.0 | 12897.9 | 3543 | 1050 | 80385 | 30926 | 0/4 |
| 5 | full | 3341.1 | 7725.3 | 80385 | 30924 | 80385 | 30924 | 4/0 |
| 5 | auto | 2455.7 | 5933.1 | 3543 | 1054 | 80385 | 30928 | 0/4 |
| 5 | action-only | 2299.8 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
Excel 16.0.20326.20158¶
| Sample | Mode | Action ms | Snapshot ms | Bytes | Tokens | Same-capture full bytes | Same-capture full tokens | Full/diff |
|---|---|---|---|---|---|---|---|---|
| 1 | action-only | 110.6 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 1 | full | 70.9 | 7289.2 | 16015 | 6286 | 16015 | 6286 | 4/0 |
| 1 | auto | 19.7 | 6466.3 | 3032 | 1005 | 15980 | 6300 | 0/4 |
| 2 | full | 8.9 | 6465.8 | 15980 | 6261 | 15980 | 6261 | 4/0 |
| 2 | auto | 8.1 | 4832.0 | 3030 | 1002 | 15978 | 6274 | 0/4 |
| 2 | action-only | 29.5 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 3 | auto | 5.6 | 3572.8 | 3029 | 988 | 15977 | 6252 | 0/4 |
| 3 | action-only | 4.2 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 3 | full | 23.0 | 6271.8 | 15980 | 6226 | 15980 | 6226 | 4/0 |
| 4 | action-only | 8.8 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 4 | full | 41.3 | 6526.9 | 15996 | 6213 | 15996 | 6213 | 4/0 |
| 4 | auto | 5.6 | 3673.7 | 3037 | 1005 | 16101 | 6299 | 0/4 |
| 5 | full | 5.3 | 3330.6 | 16101 | 6287 | 16101 | 6287 | 4/0 |
| 5 | auto | 7.9 | 4296.9 | 3038 | 1010 | 16102 | 6314 | 0/4 |
| 5 | action-only | 3.6 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
Chrome 154.0.8037.57¶
| Sample | Mode | Action ms | Snapshot ms | Bytes | Tokens | Same-capture full bytes | Same-capture full tokens | Full/diff |
|---|---|---|---|---|---|---|---|---|
| 1 | action-only | 28199.4 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 1 | full | 19267.0 | 28588.1 | 303946 | 119809 | 303946 | 119809 | 4/0 |
| 1 | auto | 16727.7 | 24395.0 | 289519 | 113903 | 323753 | 128347 | 4/0 |
| 2 | full | 16909.0 | 31351.3 | 309501 | 123353 | 309501 | 123353 | 4/0 |
| 2 | auto | 22791.2 | 37659.0 | 289544 | 114786 | 323778 | 129252 | 4/0 |
| 2 | action-only | 26388.5 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 3 | auto | 19097.5 | 23316.1 | 283677 | 112239 | 317911 | 126654 | 4/0 |
| 3 | action-only | 16792.4 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 3 | full | 20494.1 | 34571.7 | 312581 | 124179 | 312581 | 124179 | 4/0 |
| 4 | action-only | 25165.4 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 4 | full | 23491.2 | 34256.9 | 323779 | 127923 | 323779 | 127923 | 4/0 |
| 4 | auto | 24840.9 | 37936.3 | 283702 | 111546 | 317936 | 126034 | 4/0 |
| 5 | full | 25194.7 | 43828.0 | 323782 | 128628 | 323782 | 128628 | 4/0 |
| 5 | auto | 23463.7 | 38803.8 | 289265 | 114123 | 323436 | 128529 | 4/0 |
| 5 | action-only | 22832.2 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
Word 16.0.20326.20158¶
| Sample | Mode | Action ms | Snapshot ms | Bytes | Tokens | Same-capture full bytes | Same-capture full tokens | Full/diff |
|---|---|---|---|---|---|---|---|---|
| 1 | action-only | 41.9 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 1 | full | 12.6 | 3471.2 | 10746 | 4198 | 10746 | 4198 | 4/0 |
| 1 | auto | 31.3 | 4110.3 | 1866 | 589 | 10766 | 4238 | 0/4 |
| 2 | full | 13.5 | 3720.7 | 10766 | 4154 | 10766 | 4154 | 4/0 |
| 2 | auto | 15.6 | 3435.4 | 1861 | 589 | 10761 | 4213 | 0/4 |
| 2 | action-only | 39.5 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 3 | auto | 13.6 | 2560.9 | 1864 | 556 | 10764 | 4132 | 0/4 |
| 3 | action-only | 14.2 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 3 | full | 15.4 | 3611.0 | 10765 | 4213 | 10765 | 4213 | 4/0 |
| 4 | action-only | 21.0 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
| 4 | full | 24.6 | 3715.7 | 10762 | 4198 | 10762 | 4198 | 4/0 |
| 4 | auto | 20.8 | 3078.7 | 1866 | 586 | 10766 | 4186 | 0/4 |
| 5 | full | 15.3 | 3979.0 | 10766 | 4218 | 10766 | 4218 | 4/0 |
| 5 | auto | 13.3 | 3101.3 | 1864 | 564 | 10764 | 4096 | 0/4 |
| 5 | action-only | 14.5 | 0.0 | 0 | 0 | 0 | 0 | 0/0 |
CLI continuity check¶
Separate wincli commands can share the same remembered view. Pass the returned snapshotToken as --since on the next automatic snapshot. A missing or outdated token returns a complete view.
On 27 September 2026, a Release-mode check against the project's Windows test app returned:
| Response | UTF-8 bytes | End-to-end CLI call |
|---|---|---|
| First automatic snapshot | 5,861 | 5,266.7 ms |
| Next snapshot with matching token | 251 | 460.6 ms |
That unchanged-window response was 95.7% smaller. Missing and interleaved tokens returned complete views as required. Both continuity tests passed, including rejecting an old ID when a control with the same label replaced it. The test's CLI service was stopped afterward.
These are single-check measurements, not a multi-application benchmark or a cost estimate. The first call includes startup only if the service was not already running.
Reproduce¶
Run on a Windows desktop that the tests can use without interruption. They take control of the mouse and keyboard. Chrome, Word, and Excel must be installed for their workloads. Tests explicitly skip an unavailable application.
Run the workloads one at a time:
$project = '.\tests\Sbroenne.WindowsMcp.Tests\Sbroenne.WindowsMcp.Tests.csproj'
$env:MCP_TEST_CHROME = '1'
$env:MCP_SNAPSHOT_BENCHMARK_OUTPUT = "$env:TEMP\mcp-windows-snapshot-benchmark"
dotnet build $project -c Release
dotnet test $project -c Release --no-build --filter 'FullyQualifiedName~SnapshotBenchmarkRunnerTests'
dotnet test $project -c Release --no-build --filter 'FullyQualifiedName~ElectronSnapshotBenchmarkTests'
dotnet test $project -c Release --no-build --filter 'FullyQualifiedName~Benchmark_PublicGitHubRepositoryWorkflow_Chrome'
dotnet test $project -c Release --no-build --filter 'FullyQualifiedName~Benchmark_RealOfficeWorkflow&DisplayName~Word'
dotnet test $project -c Release --no-build --filter 'FullyQualifiedName~Benchmark_RealOfficeWorkflow&DisplayName~Excel'
dotnet test $project -c Release --no-build --filter 'FullyQualifiedName~CliSnapshotContinuityTests'
Each benchmark writes a Markdown report with medians and raw samples to MCP_SNAPSHOT_BENCHMARK_OUTPUT.
Limits¶
Live webpages, application versions, network conditions, and machine load vary. These results describe the listed runs, not a guaranteed saving for every task. Large changes may need a complete view. Smaller responses do not necessarily mean faster capture or lower total agent costs.