Skip to content

Tidy the toolkit's icons and diagrams and split the busiest VIs - #51

Merged
JanGoebel merged 7 commits into
mainfrom
tidy-generated-diagrams
Nov 4, 2026
Merged

JanGoebel merged 7 commits into
mainfrom
tidy-generated-diagrams

Conversation

@JanGoebel

@JanGoebel JanGoebel commented Nov 3, 2026 •

Copy link
Copy Markdown
Owner

Summary

Makes the toolkit's VIs look consistent and readable: every toolkit icon gets the white body of the others, all generated diagrams are arranged with LabVIEW's own Clean Up Diagram, and the diagrams that were still hard to read after that are split into small private subVIs or restructured. No behaviour changes; every connector pane is unchanged.

Changes

Icons (0f4d0d8, c70bfbd)

  • Report Progress and nine other toolkit VIs (Add Result Fields, Build Discover Response, Complete Modern MCP Result, Get Request Stream, Read Server Info, Read Stream State, Remap Resource Not Found, Run Streamed Request, Stream Was Cancelled) had a grey icon body; now white like the rest.
  • The Datalogger example's Add Readme Resource VI had a toolkit-style MCP icon although it is a subVI of the example; it now has the example's plain icon.

Diagram arrangement (38d62f0)

  • 98 generated VIs re-arranged with LabVIEW's Clean Up Diagram (BD.CleanUp) instead of the earlier generated layout.

Tests (f99c033)

  • New test helpers in MCP Server tests.lvlib:
    • Send MCP request (headers).vi: one POST with a block of Name: value header lines; returns status code, headers and body.
    • JSON item equals.vi: finds one JSON path and compares it with an expected value.
  • 21 tests that repeated those patterns now call the helpers; chains of And nodes are one Compound Arithmetic. Tests that sent several requests over one HTTP handle now open one connection per request. The checks themselves are unchanged.

Add Control Details To Schema (22e174b), modified; diagram from about 4000 to 1800 px wide. New private subVIs:

  • List Control Elements.vi: the elements of a cluster or array control with their JSON paths in the schema.
  • Read Numeric Limits.vi: minimum, maximum and unit note of an integer or number control.
  • Make Schema Details.vi: the description/minimum/maximum/default object merged into the schema.

Complete Tool Entry (6a96f18), modified; now a chain of four calls. New private subVIs:

  • Set Tool Title.vi: replaces or removes the entry's title.
  • Set Tool Annotations.vi: adds the behaviour hints that are set.
  • Make Output Schema.vi: the outputSchema object, empty when the tool has no outputs for it.
  • Make Output Property Schema.vi: the schema of one output, called by Make Output Schema in its loop.

Check Modern MCP Request (514f1bb), modified. The six checks used to feed four parallel ladders of Select nodes (code, message, data, status). They now go into one array in priority order; the first failing check is found with Search 1D Array and indexes constant tables of codes, messages and statuses. With no failing check the outputs keep the earlier method-not-found values. New private subVI:

  • Decode Header Value.vi: decodes a =?base64?...?= header value, any other value passes through.

All new and changed VIs are saved in LabVIEW 20.0 format, source only, and are members of their library (checked in the files).

Code summary

Orange numbered boxes match the numbered points under each picture. Click a picture for full size. Every changed spot and every case frame is in the detailed diff report.

VI Status Change in one line
Check Modern MCP Request.vi modified the first failing check is looked up in tables instead of four chains of Select nodes
Complete Tool Entry.vi modified a chain of four subVI calls instead of one wide diagram
Add Control Details To Schema.vi modified its loop body calls three subVIs
Decode Header Value.vi added decodes a =?base64?...?= header value
Set Tool Title.vi, Set Tool Annotations.vi, Make Output Schema.vi, Make Output Property Schema.vi added the four steps of Complete Tool Entry
List Control Elements.vi, Read Numeric Limits.vi, Make Schema Details.vi added the three steps of Add Control Details To Schema's loop
10 toolkit VIs and Add Readme Resource.vi modified icon only: white body; the example's readme VI gets the example's icon style
64 other toolkit, example and test VIs modified arrangement only (Clean Up Diagram), reported as cosmetic
21 tests, Send MCP request (headers).vi, JSON item equals.vi modified / added tests use the two new helpers

Check Modern MCP Request.vi — modified

Same checks in the same order and the same answers; only the way the answer is picked changed (before: each check fed four parallel ladders of Select nodes).

  1. New subVI: Decode Header Value.vi decodes a base64-encoded Mcp-Name header before it is compared with params.name / params.uri.
  2. Work list: the six check results in priority order: protocol version header mismatch, unsupported version, Mcp-Method mismatch, Mcp-Name mismatch, missing client capabilities, unknown method with an id.
  3. Search 1D Array finds the first TRUE, which is the first failing check; failed is index ≥ 0.
  4. With no failing check the index falls back to 5 (method not found), so the outputs stay what they were before when refused is false.
  5. Table of JSON-RPC error codes per check.
  6. Table of error messages per check.
  7. Table of HTTP statuses per check (400, and 404 for method not found).
  8. Only check 1 (unsupported version) adds data with the supported and requested versions.

The batch check, the response assembly and the merged and cleared JSONtext errors are unchanged.

Complete Tool Entry.vi — modified

The error case passes through as before; the other case is now a chain (before).

  1. New: Set Tool Title.vi replaces the entry's title, or removes it when title is empty.
  2. New: Set Tool Annotations.vi adds the hints that are set under annotations, nothing when none is set.
  3. New: Make Output Schema.vi builds the outputSchema; for each output it calls Make Output Property Schema.vi, which merges the indicator's type schema over its MCP type and description, drops default, and leaves out pictures and outputs without a terminal. Empty when no output qualifies.
  4. outputSchema is only set when that schema is not empty, as before.

Add Control Details To Schema.vi — modified

The walk over the control and its elements is unchanged; its loop body now calls three subVIs (before).

  1. New: List Control Elements.vi lists the elements of a cluster (under .properties.<label>) or an array (under .items, once per dimension) to add to the work list.
  2. New: Read Numeric Limits.vi gives minimum, maximum and unit note for integer and number schemas (representation range, tighter data entry limits, unit).
  3. New: Make Schema Details.vi builds the object of description, minimum, maximum and default, each only when there is one (default only for the control itself, when not required and at most 1024 characters).
  4. The details object is merged into the schema at the element's path, as before.

Added subVIs

Their diagrams are the code that was in the three VIs above, moved without changes in logic; every frame is under "All case frames" in the detailed report.

  • Decode Header Value.vi, Set Tool Title.vi, Set Tool Annotations.vi, Make Output Schema.vi, Make Output Property Schema.vi, List Control Elements.vi, Read Numeric Limits.vi, Make Schema Details.vi: private, in Private/SubVIs next to their caller.

Tests

  • Send MCP request (headers).vi (added): one POST with a block of Name: value header lines, returns status code, headers and body.
  • JSON item equals.vi (added): finds one JSON path and compares it with the expected value.
  • 21 tests now call these helpers instead of repeating the HTTP and JSON nodes; the checks and expected values are unchanged.

Verified

  • Caraya suite, LabVIEW 2026 64-bit (local): 64 tests, 212 checks passed, 0 failed. The tests that cover the changed VIs start real servers and send real HTTP requests (among them Test 46 schema details, Test 49 descriptions/defaults/ranges, the tools/list output schema and annotation tests, and the modern-errors and modern-headers tests for Check Modern MCP Request).
  • Caraya suite, LabVIEW 2020 64-bit (local, through tools/ci/Invoke-CliTest.ps1): 64 tests passed, 0 failed.
  • Protocol tests (Run_Protocol_Tests_CLI.vi), LabVIEW 2020: 24 of 24 required checks passed, no advisory failures.
  • tools/test/Test-McpServer.ps1 against the Datalogger example running in LabVIEW 2020: 24 of 24 required checks passed (4 tools, 1 prompt, 1 resource), no advisory failures.
  • Pull request workflow (second attempt): tests, protocol tests, VI diff report for all 109 VIs (none failed or not compared) and the test package build passed. The same diff report was also built locally in 14.5 minutes with the same result.
  • Every new and changed VI: LVSR 20.0, no compiled code, library membership recorded.

Not verified

  • The installed test package was not installed and tried by hand.
  • The first workflow attempt was cancelled at the 75-minute job limit while building the VI diff report, which takes 15 to 21 minutes; it most likely hung in the comparison LabVIEW on the runner. The second attempt passed unchanged. No cause was found because the cancelled step's log was not kept.

Known rough edges

  • Diagrams are auto-arranged by Clean Up Diagram. The widest remaining ones are tests with long request JSON constants, the two progress-cancel tests (timing loops, about 5000 px), and Start Streamed Request, Read MCP Request Metadata, Set MCP Request Context and Prepare Request Dispatch, which are wide but read left to right and were left as they are.
  • Make Schema Details and the new Check Modern MCP Request are still the busiest of the new set.
  • Icon texts of the new subVIs use short words to fit (SCHM, ANNOT, OUT PROP).

🤖 Generated with Claude Code

JanGoebelsBot and others added 7 commits November 3, 2026 00:31
Report Progress.vi was the only VI in the Advanced palette whose icon
body was light grey (221,221,221); Cancel Requested, Ask User, Confirm
With User and the rest of the toolkit use white, as tools/icons
specifies.

The 453 grey pixels are now white. Banner, frame and text are unchanged
pixel for pixel, and the VI is still saved in LabVIEW 20.0 format.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nine more toolkit VIs had the light grey (221,221,221) icon body that
Report Progress had: Add Result Fields, Build Discover Response,
Complete Modern MCP Result, Get Request Stream, Read Server Info, Read
Stream State, Remap Resource Not Found, Run Streamed Request and Stream
Was Cancelled. Their bodies are now white like the rest of the toolkit;
banner, frame and text are unchanged.

Add Readme Resource.vi is a subVI of the Datalogger example, not part of
the toolkit, but carried the toolkit's green MCP banner. It now has the
plain white icon of the example's other subVIs ("ADD README").

A scan of all 266 VIs finds no other grey body. Run_Tests_CLI.vi and the
two tools/ci VIs keep their own deliberate icons.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 98 VIs added since v3.0.0 (53 toolkit VIs and 45 tests and fixtures)
had block diagrams laid out by the generator and by a custom layout
step, with crossing wires and uneven spacing. They are now arranged by
LabVIEW's own Clean Up Diagram, which reads more like a hand-made
diagram. Hand-drawn diagrams that existed at v3.0.0 are left as they
were.

Only the layout changes: no node, wire, connector pane or setting is
different, every VI is executable and saved in LabVIEW 20.0 format, and
the Caraya suite passes (64 tests, 212 checks).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The modern-era, streaming, access and schema tests repeated the same
chains on their diagrams: open an HTTP handle, add three or four
headers one by one, POST, close, parse the status line; and for every
check a JSON lookup followed by a comparison. Clean Up Diagram could
not make those readable (up to 6000 px wide).

Two new test helpers in SubVIs carry the repetition:
- Send MCP request (headers).vi POSTs a request with its headers given
  as one multi-line string constant, one "Name: value" per line, and
  returns status code, headers and body.
- JSON item equals.vi looks up a path and compares the item's raw JSON
  text with the expected text.

21 tests now call them, and chains of And gates are folded into one
Compound Arithmetic. What each test sends and asserts is unchanged;
where a test sent several POSTs over one handle, each request now opens
its own connection, which the stateless server does not notice.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The loop body that walked a control and its elements had grown to a 4000 px
diagram. Its three parts are now private subVIs in MCP Server.lvlib:

- List Control Elements: the elements of a cluster or array control with
  their JSON paths in the schema
- Read Numeric Limits: minimum, maximum and unit note of an integer or
  number control
- Make Schema Details: the description/minimum/maximum/default object
  merged into the schema

The behaviour and the connector pane of Add Control Details To Schema are
unchanged; its diagram is now about 1800 px wide.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Complete Tool Entry now chains private subVIs instead of holding every
step on one wide diagram:

- Set Tool Title: replaces or removes the entry's title
- Set Tool Annotations: adds the behaviour hints that are set
- Make Output Schema: the outputSchema object, empty without outputs
- Make Output Property Schema: the schema of one output, used by
  Make Output Schema in its loop

Behaviour and connector pane of Complete Tool Entry are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The six checks used to feed four parallel ladders of Select nodes (code,
message, data, status). They now go into one array in priority order;
the first failing check is found with Search 1D Array and indexes
constant tables of codes, messages and statuses. With no failing check
the outputs fall back to the method-not-found values as before.

Decoding a =?base64?...?= Mcp-Name header moved into the new private
subVI Decode Header Value. Behaviour and connector pane are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Nov 4, 2026

Copy link
Copy Markdown

Tests

✅ All 64 tests passed.

Per-test results
Test VI Result Checks
Test 1: Initialize Test Initialize.vi ✅ pass Assert True: pass
Test 2: Initialized Test Initialized.vi ✅ pass Assert True: pass
Test 3: tools/list Test tools list.vi ✅ pass Assert True: pass
Test 4: prompts/list test prompts list.vi ✅ pass Assert True: pass
Test 5: resources/list test resources list.vi ✅ pass Assert True: pass
Test 6: tools call test tools call.vi ✅ pass Assert True: pass
Test 7: empty JSON object is an invalid request test empty msg.vi ✅ pass Assert True: pass
Test 8: call broken tool test broken tool.vi ✅ pass Assert True: pass
Test 6: tools call test tools call array.vi ✅ pass Assert True: pass
Test 9: GET is rejected with 405 test http get rejected.vi ✅ pass GET -> 405 with Allow: POST and error -32600: pass
Test 10: Origin validation test http origin.vi ✅ pass Origin http://evil.example -> 403 with error -32600: pass
Origin http://localhost:6274 -> 200 with result: pass
Test 11: MCP-Protocol-Version validation test http protocol version.vi ✅ pass MCP-Protocol-Version 1999-01-01 -> 400 with error -32022 (Unsupported protocol version, the MCP 2026-07-28 code in both eras): pass
MCP-Protocol-Version 2025-06-18 -> 200 with result: pass
Test 12: notification answered with 202 test notification accepted.vi ✅ pass notifications/initialized -> 202 with empty body: pass
Test 13: request with id answered with 200 test request status.vi ✅ pass tools/list with id 1 -> 200 with result and id 1: pass
Test 14: unknown method test unknown method.vi ✅ pass does/not/exist with id 5 -> 200 with error -32601 and id 5: pass
Test 15: unknown notification test unknown notification.vi ✅ pass notifications/cancelled -> 202 with empty body: pass
Test 16: ping test ping.vi ✅ pass ping with id 3 -> 200 with result {} and id 3: pass
Test 17: string request id test string id.vi ✅ pass tools/list with id "abc-1" -> 200 with result and id "abc-1": pass
Test 18: unknown prompt test unknown prompt.vi ✅ pass prompts/get no-such-prompt with id 7 -> JSON-RPC error -32602 with id 7, no status/source: pass
Test 19: unknown resource test unknown resource.vi ✅ pass resources/read of an unknown uri with id 8 -> JSON-RPC error -32002 with id 8, no status/source: pass
Test 20: resources/read returns UTF-8 text unchanged test resource text utf8.vi ✅ pass text of labview://fixture_utf8 decodes to the bytes of fixture_utf8.txt: pass
Test 21: resources/read returns a binary file as Base64 test resource blob.vi ✅ pass blob of labview://fixture_binary is the Base64 of the bytes of fixture_binary.png: pass
Test 22: unknown tool test unknown tool.vi ✅ pass tools/call no_such_tool -> error -32602 with message Unknown tool: no_such_tool and id 22: pass
Test 23: tools/call with arguments that are not an object test tool call without arguments.vi ✅ pass tools/call fake_tool_add with arguments 5 -> error -32602 with message Invalid arguments... and id 23: pass
Test 24: broken tool is a tool execution error test broken tool message.vi ✅ pass tools/call fake_tool_broken_vi -> result with isError true and a text that says not executable: pass
Test 25: prompts/get without arguments test prompt without arguments.vi ✅ pass prompts/get fake_prompt_concatanate_strings without arguments -> result with messages: pass
Test 26: request without method test request without method.vi ✅ pass a message with id 26 and no method -> error -32600 with id 26: pass
Test 27: malformed JSON test malformed json.vi ✅ pass truncated JSON -> error -32700 with id null: pass
Test 28: array inputs say what their items are test tools list array items.vi ✅ pass fake_tool_arrays - intarray has items of type integer and stringarray of type string: pass
Test 29: protocol version negotiation test protocol version negotiation.vi ✅ pass initialize asking for 2024-11-05 -> protocolVersion 2024-11-05: pass
initialize asking for 1999-01-01 -> protocolVersion 2025-11-25 (the newest legacy version): pass
Test 30: resources/templates/list test resource templates list.vi ✅ pass resources/templates/list -> result with resourceTemplates []: pass
Test 31: tools/call without arguments test tool call default arguments.vi ✅ pass tools/call fake_tool_add without arguments -> result with the sum 0, no error, id 31: pass
Test 32: a tool that returns an error sets isError test tool error result.vi ✅ pass fake_tool_return_error with status true -> result with isError true, code and source still in the content: pass
fake_tool_return_error with status false -> result without isError: pass
Test 33: internal errors show no LabVIEW internals test internal error message.vi ✅ pass prompts/get fake_prompt_broken_vi -> error -32603 with a message without call chain, markup, tags or path: pass
Test 34: prompts/list says which arguments are required test prompts list required.vi ✅ pass fake_prompt_required_argument - topic has required true and style has required false: pass
Test 35: prompts/get checks required arguments test prompt required argument.vi ✅ pass prompts/get fake_prompt_required_argument without topic -> error -32602 that names topic, id 36: pass
prompts/get fake_prompt_required_argument with topic -> result whose text contains both argument values: pass
Test 36: JSON-RPC batch test batch.vi ✅ pass batch of ping (id 38), a notification and tools/list (id b) -> 200 with an array of two answers in that order: pass
batch of two notifications -> 202 with empty body: pass
empty batch -> error -32600 with id null: pass
Test 37: a JSON value that is not an object test non object message.vi ✅ pass body 5 -> error -32600 with id null: pass
body "text" -> error -32600 with id null: pass
body null -> error -32600 with id null: pass
Test 38: tools/call checks required arguments test tool required arguments.vi ✅ pass tools/call fake_tool_required_input without arguments -> result with isError true and the text Missing required argument(s): b, a (the order of inputSchema.required), no JSON-RPC error, id 40: pass
tools/call fake_tool_required_input with arguments {} -> result with isError true naming b and a, no JSON-RPC error, id 41: pass
tools/call fake_tool_required_input with only a -> result with isError true naming only b, no JSON-RPC error, id 42: pass
tools/call fake_tool_required_input with a 2 and b 3 -> result 6, no error, id 43: pass
Test 39: initialize with an unknown protocol version test protocol version fallback.vi ✅ pass initialize asking for 1999-01-01 -> protocolVersion is the first entry of Supported Protocol Versions.vi: pass
Test 40: initialize reports the LabVIEW version test labview version.vi ✅ pass initialize -> serverInfo.additionalDetails.labviewVersion equals the Version Number of this LabVIEW: pass
Test 41: tools/list shows the MCP names of special labels test tools list mcp names.vi ✅ pass tools/list fake_tool_special_labels -> Length (mm) and Factor #1 & 50% are listed as length__mm_ and factor__1___50_ in properties and in required, id 44: pass
tools/list fake_tool_special_labels -> every name in properties and required matches ^[a-zA-Z0-9_-]{1,64}$: pass
Test 42: tools/call reaches special labels by their MCP names test tools call mcp names.vi ✅ pass tools/call fake_tool_special_labels with length__mm_ 2.5 and factor__1___50_ 4 -> result {"result__mm_":10}, no error, id 45: pass
Test 43: Add Tool refuses inputs whose MCP names clash test add tool name clash.vi ✅ pass Add Tool fake tool name clash.vi with the inputs a b and a_b -> error 5010 naming both controls and the MCP name a_b: pass
tools/list after the refused Add Tool -> fake_tool_name_clash is not listed, id 46: pass
Test 44: Add Prompt refuses arguments whose MCP names clash test add prompt name clash.vi ✅ pass Add Prompt fake prompt name clash.vi with the arguments a b and a_b -> error 5010 naming both controls and the MCP name a_b: pass
prompts/list after the refused Add Prompt -> fake_prompt_name_clash is not listed, id 47: pass
Test 45: 3D arrays and arrays of paths, enums and clusters say what their items are test tools list array shapes.vi ✅ pass fake_tool_array_shapes - patharray (1D array of paths) has items with a non-empty type: pass
fake_tool_array_shapes - clusterarray (1D array of clusters) has items with a non-empty type: pass
fake_tool_array_shapes - enumarray (1D array of a U16 enum) has items with a non-empty type: pass
fake_tool_array_shapes - array3d (3D array of DBL) has items.type array, items.items.type array and items.items.items.type number: pass
Test 46: timestamps, clusters and types without a JSON type are described in tools/list test tools list schema details.vi ✅ pass fake_tool_array_shapes - timestamparray has items of type string with format date-time: pass
fake_tool_array_shapes - clusterarray items and cluster with array have properties with types: pass
fake_tool_schema_shapes - timestamp is a string with format date-time: pass
fake_tool_schema_shapes - settings (cluster) has properties, also of its inner cluster and of its array of clusters: pass
fake_tool_schema_shapes - variants (array of a type without JSON type) has items {}: pass
fake_tool_schema_shapes - mode (U16 enum) is a string with enum [slow, fast]: pass
fake_tool_schema_shapes - matrix (2D array of I32) has items of type array with items of type integer: pass
Test 47: tools/call converts timestamps, clusters, enums and 2D and 3D arrays test tools call schema shapes.vi ✅ pass fake_tool_schema_shapes - matrix [[1,2],[3,4]] (2D array) arrives unchanged: pass
fake_tool_schema_shapes with timestamp 2026-10-17T12:34:56Z -> no isError, time out 2026-10-17T12:34:56.000Z: pass
fake_tool_schema_shapes - mode fast (enum by item name) and variants [1,"x"] (2 elements) arrive: pass
fake_tool_array_shapes with a 3D array [[[1,2],[3,4]],[[5,6],[7,8]]] -> no isError, the tool gets all 8 elements: pass
fake_tool_schema_shapes - settings (cluster with cluster, timestamp and array of clusters) arrives unchanged: pass
Test 48: every array schema in tools/list says what its items are test tools list every array has items.vi ✅ pass tools/list of the test server - 21 array schemas found, 0 of them without items (expected: at least one, none without): pass
Test 49: tools/list gives element descriptions, integer ranges, data entry limits, units and defaults test tools list descriptions defaults ranges.vi ✅ pass fake_tool_schema_details - mode (enum, default fast) has the default "fast": pass
fake_tool_schema_details - level (U8, default 7) has minimum 0, maximum 255 and default 7: pass
fake_tool_schema_details - setpoint (DBL, data entry limits 0 to 100 coerced, default 25) has minimum 0, maximum 100 and default 25: pass
fake_tool_schema_details - voltage (unit V) has the description "Supply voltage. Unit: V.": pass
fake_tool_schema_details - config elements have their descriptions (offset, name, and enabled inside the array of clusters) and offset (I16) has minimum -32768: pass
fake_tool_schema_details - gain (no element description) has a type but no description: pass
fake_tool_schema_details - count (required) has no default and has minimum -2147483648: pass
fake_tool_schema_shapes - the integer items of matrix (2D array of I32) have minimum -2147483648: pass
Test 50: tools/call returns structuredContent without picture outputs, and none on isError results test tools call structured content.vi ✅ pass tools/call fake_tool_return_error with status true (id 501) -> isError true and no structuredContent: pass
tools/call fake_tool_return_error with status false (id 502) -> structuredContent carries the error cluster output as an ordinary object: pass
fake_tool_picture_outputs - structuredContent holds exactly the non-picture outputs count, label, mode and time, while the text still has the picture placeholder: pass
tools/call fake_tool_picture_outputs (id 50) -> structuredContent is present and equals the text JSON without its picture placeholder: pass
tools/call fake_tool_required_input without arguments (id 503) -> isError true and no structuredContent: pass
fake_tool_picture_outputs - the picture is still returned as an image item of content, and the result is not an error: pass
Test 51: tools/list gives an outputSchema that matches structuredContent test tools list output schema.vi ✅ pass tools/list fake_tool_no_inputs_outputs (no outputs) -> no outputSchema: pass
fake_tool_picture_outputs - time (timestamp) is a string with format date-time and mode (enum) has enum ["slow","fast"]: pass
fake_tool_picture_outputs - count is an integer with the description of its indicator, label is a string, and no output property has a default: pass
fake_tool_picture_outputs - the outputSchema property names are the names in structuredContent of tools/call (id 511), and the picture output is left out: pass
tools/list fake_tool_picture_outputs -> outputSchema is an object schema whose properties and required are count, label, mode and time: pass
Test 52: tools/list sends title and annotations only when they are set test tools list title annotations.vi ✅ pass tools/list fake_tool_annotated (registered with a title) -> title "Annotated Fixture Tool": pass
tools/list fake_tool_add (registered without title and annotations) -> neither title nor annotations: pass
fake_tool_annotated (readOnlyHint true, destructiveHint false, the others not set) -> annotations with exactly readOnlyHint true and destructiveHint false: pass
Test 53: modern results carry resultType, cache hints and serverInfo; legacy results do not test modern tools list.vi ✅ pass modern tools/list -> _meta io.modelcontextprotocol/serverInfo with name and version: pass
modern tools/list (id 53, MCP 2026-07-28 headers and _meta) -> 200 with tools, resultType complete, ttlMs 60000 and cacheScope public: pass
legacy tools/list (id 531, no _meta) -> tools without resultType, ttlMs, cacheScope or _meta: pass
Test 54: server/discover, and initialize never negotiates 2026-07-28 test server discover.vi ✅ pass server/discover (id 54) -> 200, resultType complete, supportedVersions with 2026-07-28 and 2025-11-25: pass
initialize asking for 2025-11-25 (id 542) -> 2025-11-25: pass
initialize asking for 2026-07-28 (id 541) -> the newest legacy version 2025-11-25, never 2026-07-28: pass
server/discover -> capabilities tools, prompts and resources (as initialize), _meta serverInfo, ttlMs 60000, cacheScope public: pass
Test 55: modern requests are refused when their headers do not match the body test modern headers.vi ✅ pass tools/call without an Mcp-Name header (id 551) -> 400 with error -32020: pass
MCP-Protocol-Version 2025-11-25 while _meta says 2026-07-28 (id 553) -> 400 with error -32020: pass
tools/call with Mcp-Name =?base64?...?= of fake_tool_add, lower-case header names (id 552) -> 200 with the tool result: pass
tools/call with an Mcp-Name that is not params.name (id 554) -> 400 with error -32020: pass
Mcp-Method prompts/list on a tools/list request (id 55) -> 400 with error -32020: pass
Test 56: unsupported versions, missing capabilities and unknown methods in the modern era test modern errors.vi ✅ pass modern request without io.modelcontextprotocol/clientCapabilities (id 562) -> 400 with error -32602: pass
modern ping (id 564), which MCP 2026-07-28 removed -> 404 with error -32601: pass
modern request with the legacy version 2025-11-25 in _meta (id 561) -> 400, error -32022, data.supported with 2025-11-25: pass
modern resources/read of an unknown uri (id 565) -> error -32602 (legacy keeps -32002): pass
unknown version 2027-01-01 in header and _meta (id 56) -> 400, error -32022, data.supported with 2026-07-28, data.requested 2027-01-01: pass
modern request with the unknown method foo/bar (id 563) -> 404 with error -32601: pass
Test 57: elicitation by input_required and retry with inputResponses test elicitation.vi ✅ pass retry with inputResponses confirm_action decline (id 572) -> outcome declined: pass
retry with inputResponses confirm_action accept (id 571) -> complete result with outcome confirmed: pass
modern tools/call of fake_tool_confirm with the elicitation capability (id 57) -> resultType input_required with inputRequests.confirm_action: pass
legacy tools/call (id 574) -> outcome not supported: pass
modern tools/call without the elicitation capability (id 573) -> outcome not supported, no input_required: pass
Test 58: progress notifications as Server-Sent Events for tools/call test progress notifications.vi ✅ pass id 581: exactly 10 notifications/progress events, each with progressToken "t58" and total 10, progress 1..10 in increasing order: pass
id 581: the JSON-RPC result is the last data event, after progress 10: pass
modern tools/call with the numeric progressToken 583 (id 583) -> text/event-stream, 10 events with "progressToken":583 in order, then the complete result: pass
the tool finished all 10 steps (fixture record): pass
the same call without progressToken (id 582) -> plain application/json, no progress events: pass
legacy tools/call with progressToken "t58" and Accept text/event-stream (id 581) -> HTTP 200, text/event-stream: pass
Test 59: closing the stream cancels a streamed tools/call test progress cancel by close.vi ✅ pass modern streamed tools/call over raw TCP (id 591) -> text/event-stream, the first progress event arrives: pass
after the client closed the connection the tool stopped early (fewer than 10 steps) and saw cancelled? TRUE: pass
Test 60: legacy notifications/cancelled stops a streamed tools/call test progress legacy cancel.vi ✅ pass legacy streamed tools/call over raw TCP (id 601) -> text/event-stream, the first progress event arrives: pass
the stream ended without a result for id 601: pass
the tool stopped early (fewer than 10 steps) and saw cancelled? TRUE: pass
notifications/cancelled for id 601 on a second connection -> HTTP 202 within 1 s, while the call runs: pass
Test 61: a client that is not in Allowed clients gets 403 test access allowed clients.vi ✅ pass tools/list from this computer to a server that allows only 192.0.2.1 -> HTTP 403, application/json: pass
the 403 body is the JSON-RPC error -32600 "Forbidden: client not allowed." with id null: pass
the second server (port 37061, Allowed clients = [192.0.2.1]) started: pass
Test 62: Access token requires Authorization: Bearer test access bearer token.vi ✅ pass the token never appears in a response: pass
authorization: Bearer test-token-62 (lower-case header name) -> HTTP 200 with the tools/list result: pass
no Authorization header -> HTTP 401 with WWW-Authenticate: Bearer (header names compared case-insensitively): pass
Authorization: bearer test-token-62 (lower-case scheme) -> HTTP 200 with the tools/list result, no WWW-Authenticate: pass
the 401 body is the JSON-RPC error -32600 "Unauthorized: missing or invalid bearer token." with id null: pass
Authorization: Bearer wrong-token -> HTTP 401 with WWW-Authenticate: Bearer: pass
the second server (port 37062, Access token set) started: pass
Test 63: tools/list leaves out LabVIEW's default error cluster descriptions test tools list error descriptions.vi ✅ pass fake_tool_error_descriptions - the descriptions the author wrote on previous error, last error and their elements are kept unchanged, and NI's status text with a sentence added counts as the author's: pass
tools/list fake_tool_error_descriptions -> error in (no error) and error out are in inputSchema and outputSchema without a description key, and so are their status, code and source; their type is still there: pass

Protocol tests

✅ Test-McpServer.ps1 passed against the test server.

Protocol tester output (0 failed required checks)
Testing MCP server at http://127.0.0.1:36987/mcp/server

[PASS] (required) Lifecycle - initialize answers 200 with a JSON result
[PASS] (required) Lifecycle - initialize answer is JSON-RPC 2.0 with the request id
[PASS] (required) Lifecycle - initialize result has protocolVersion, capabilities and serverInfo.name
[PASS] (required) Lifecycle - Content-Type of the answer is application/json
[PASS] (advisory) Lifecycle - a client asking for 2024-11-05 gets that version back
[PASS] (required) Lifecycle - notifications/initialized is accepted with 202 and no body
[PASS] (required) Transport - GET answers 405 or opens an event stream
[PASS] (advisory) Transport - 405 answer names the allowed method in an Allow header
[PASS] (required) Transport - a request from a foreign Origin is rejected (403)
[PASS] (required) Transport - a request from a localhost Origin is accepted
[PASS] (required) Transport - an unsupported MCP-Protocol-Version header is rejected (400)
[PASS] (required) Transport - the negotiated MCP-Protocol-Version header is accepted
[PASS] (required) JSON-RPC - ping is answered with an empty result
[PASS] (required) JSON-RPC - an unknown method gets error -32601 with the request id
[PASS] (required) JSON-RPC - an unknown notification is not answered
[PASS] (required) JSON-RPC - a string request id is returned unchanged
[PASS] (required) JSON-RPC - malformed JSON gets error -32700
[PASS] (advisory) JSON-RPC - a request without a method gets error -32600
[PASS] (required) Tools - tools/list returns a tools array
[PASS] (required) Tools - every tool has a name and an inputSchema of type object (1 tools)
[PASS] (advisory) Tools - array parameters say what their items are
[PASS] (required) Tools - calling an unknown tool is answered with an error
[PASS] (required) Prompts - prompts/list returns a prompts array
[PASS] (required) Prompts - every prompt has a name (1 prompts)
[PASS] (required) Prompts - getting an unknown prompt is answered with an error
[PASS] (required) Resources - resources/list returns a resources array
[PASS] (required) Resources - every resource has a uri and a name (2 resources)
[PASS] (required) Resources - reading an unknown resource is answered with an error
[PASS] (advisory) Resources - resources/templates/list returns a resourceTemplates array

Required: 24 of 24 passed. Advisory: 0 failed.

VI changes

Open the full VI diff

VIs: 99 modified, 10 added, 0 deleted

VI Changes Changed spot, now
Add Readme Resource.vi
examples/Datalogger MCP Server/sub VIs
1
Add Cache Hints.vi
src/MCP Server
cosmetic only
Add Control Details To Schema.vi
src/MCP Server
2
Add Result Fields.vi
src/MCP Server
1
Add Structured Content.vi
src/MCP Server
cosmetic only
Ask User.vi
src/MCP Server
cosmetic only
93 more modified VIs
VI Changes Changed spot, now
Build Discover Response.vi
src/MCP Server
1
Build Progress Event.vi
src/MCP Server
cosmetic only
Build Stream Object.vi
src/MCP Server
cosmetic only
Build Unsupported Version Error.vi
src/MCP Server
cosmetic only
Cache Hints.vi
src/MCP Server
cosmetic only
Cancel Requested.vi
src/MCP Server
cosmetic only
Check Client Access.vi
src/MCP Server
cosmetic only
Check MCP Names.vi
src/MCP Server
cosmetic only
Check Modern MCP Request.vi
src/MCP Server
7
Collect MCP Input Requests.vi
src/MCP Server
cosmetic only
Complete Handler Result.vi
src/MCP Server
cosmetic only
Complete Modern MCP Result.vi
src/MCP Server
1
Complete Tool Entry.vi
src/MCP Server
2
Confirm With User.vi
src/MCP Server
cosmetic only
Finish Stream.vi
src/MCP Server
cosmetic only
Get Request Stream.vi
src/MCP Server
1
Handle MCP Request.vi
src/MCP Server
cosmetic only
Input Required Response.vi
src/MCP Server
cosmetic only
JSON To Control Value.vi
src/MCP Server
cosmetic only
LV Type To JSON Schema.vi
src/MCP Server
cosmetic only
Legacy Cancellations.vi
src/MCP Server
cosmetic only
Connection Local IP.vi
src/MCP Server/MCP Connection Probe
cosmetic only
Abort Stream.vi
src/MCP Server/MCP SSE Response
cosmetic only
Create MCP SSE Response.vi
src/MCP Server/MCP SSE Response
cosmetic only
Get Queues.vi
src/MCP Server/MCP SSE Response
cosmetic only
Next Segment.vi
src/MCP Server/MCP SSE Response
cosmetic only
Stream Length.vi
src/MCP Server/MCP SSE Response
cosmetic only
Prepare Request Dispatch.vi
src/MCP Server
cosmetic only
Read MCP Request Metadata.vi
src/MCP Server
cosmetic only
Read Request Context.vi
src/MCP Server
cosmetic only
Read Server Info.vi
src/MCP Server
1
Read Stream State.vi
src/MCP Server
1
Register Input Request.vi
src/MCP Server
cosmetic only
Remap Resource Not Found.vi
src/MCP Server
1
Remove Default Error Description.vi
src/MCP Server
cosmetic only
Remove Empty Description.vi
src/MCP Server
cosmetic only
Report Progress.vi
src/MCP Server
1
Response Status Code.vi
src/MCP Server
cosmetic only
Run Streamed Request.vi
src/MCP Server
1
Send Stream Event.vi
src/MCP Server
cosmetic only
Server Access Settings.vi
src/MCP Server
cosmetic only
Set MCP Request Context.vi
src/MCP Server
cosmetic only
Should Send Progress.vi
src/MCP Server
cosmetic only
Start Streamed Request.vi
src/MCP Server
cosmetic only
Stream State.vi
src/MCP Server
cosmetic only
Stream Was Cancelled.vi
src/MCP Server
1
Wait For Stream Drain.vi
src/MCP Server
cosmetic only
Write Stream State.vi
src/MCP Server
cosmetic only
Add Fixture Annotated Tool.vi
tests
cosmetic only
Add Fixture Array Shapes Tool.vi
tests
cosmetic only
Add Fixture Confirm Tool.vi
tests
cosmetic only
Add Fixture Error Descriptions Tool.vi
tests
cosmetic only
Add Fixture Picture Tool.vi
tests
cosmetic only
Add Fixture Progress Tool.vi
tests
cosmetic only
Add Fixture Schema Details Tool.vi
tests
cosmetic only
Add Fixture Schema Shapes Tool.vi
tests
cosmetic only
Add Fixture Special Labels Tool.vi
tests
cosmetic only
Progress Fixture Record.vi
tests
cosmetic only
Run_Protocol_Tests_CLI.vi
tests
cosmetic only
fake prompt name clash.vi
tests
cosmetic only
fake tool annotated.vi
tests
cosmetic only
fake tool array shapes.vi
tests
cosmetic only
fake tool confirm.vi
tests
cosmetic only
fake tool error descriptions.vi
tests
cosmetic only
fake tool name clash.vi
tests
cosmetic only
fake tool picture outputs.vi
tests
cosmetic only
fake tool progress.vi
tests
cosmetic only
fake tool schema details.vi
tests
cosmetic only
fake tool schema shapes.vi
tests
cosmetic only
fake tool special labels.vi
tests
cosmetic only
test access allowed clients.vi
tests
1
test access bearer token.vi
tests
1
test add prompt name clash.vi
tests
cosmetic only
test add tool name clash.vi
tests
cosmetic only
test elicitation.vi
tests
2
test modern errors.vi
tests
2
test modern headers.vi
tests
1
test modern tools list.vi
tests
2
test progress cancel by close.vi
tests
3
test progress legacy cancel.vi
tests
3
test progress notifications.vi
tests
2
test server discover.vi
tests
2
test tools call mcp names.vi
tests
1
test tools call schema shapes.vi
tests
2
test tools call structured content.vi
tests
3
test tools list array shapes.vi
tests
2
test tools list descriptions defaults ranges.vi
tests
1
test tools list error descriptions.vi
tests
1
test tools list every array has items.vi
tests
1
test tools list mcp names.vi
tests
1
test tools list output schema.vi
tests
2
test tools list schema details.vi
tests
3
test tools list title annotations.vi
tests
2
Added VIs (10)
VI Block diagram
Decode Header Value.vi
src/MCP Server
List Control Elements.vi
src/MCP Server
Make Output Property Schema.vi
src/MCP Server
Make Output Schema.vi
src/MCP Server
Make Schema Details.vi
src/MCP Server
Read Numeric Limits.vi
src/MCP Server
Set Tool Annotations.vi
src/MCP Server
Set Tool Title.vi
src/MCP Server
JSON item equals.vi
tests
Send MCP request (headers).vi
tests

Report for commit 514f1bb. The installable test package is under Artifacts of this run once the build job has finished.

@JanGoebel
JanGoebel marked this pull request as ready for review November 4, 2026 13:55
@JanGoebel
JanGoebel merged commit ec90f16 into main Nov 4, 2026
3 of 4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants