Skip to content

feat: port the hardened HTTP/MCP server and switch to the ESP32Async … - #11

Merged
abcsnowwolf merged 1 commit into
mainfrom
chore/switch-to-esp32async-deps
Aug 15, 2026
Merged

abcsnowwolf merged 1 commit into
mainfrom
chore/switch-to-esp32async-deps

Conversation

@abcsnowwolf

Copy link
Copy Markdown
Contributor

…forks

BREAKING CHANGE: the constructor no longer starts listening. Register every tool, then call begin() once WiFi is connected. Protocol version 2024-11-05 is no longer supported.

  • replace the archived me-no-dev ESPAsyncWebServer/AsyncTCP with the maintained ESP32Async forks (^3.6.0 / ^3.3.2)
  • run tools/call on a dedicated FreeRTOS worker task with a deferred chunked reply and a 20 ms inline fast path, so a blocking handler no longer stalls the async_tcp task that services every connection on the device
  • harden the request path: cap bodies at MCP_HTTP_MAX_BODY_SIZE (413), answer 411 without Content-Length, 415 for non-JSON, 500 on OOM, and 400 on a short body; write chunks by index and clamp clients that overshoot
  • fix a _tempObject leak on the empty-body path and drop the Serial dump of every request body
  • reject browser origins that do not name this device by its current IP or its advertised .local hostname (403), on every route; matching Origin against Host alone does not survive a DNS rebind
  • sanitize the mDNS hostname; a server name with spaces produced an invalid DNS label
  • drop 2024-11-05, which is the deprecated HTTP+SSE transport this server does not implement; negotiate 2025-11-25/2025-06-18/2025-03-26 and reject an unsupported MCP-Protocol-Version header with 400 as the spec requires
  • stay stateless: no MCP-Session-Id is issued, which the spec permits
  • add ping, treat notifications as JSON-RPC requires (202, no body), enforce the envelope, and accept any JSON number as an id
  • return structuredContent and isError; add MCP_OMIT_TEXT_WHEN_STRUCTURED
  • cache the serialized tools/list body between registrations
  • serialize responses without a wrapper document, halving peak JSON residency
  • answer GET/DELETE with 405 + Allow instead of 200
  • drop ASYNCWEBSERVER_REGEX from the example: the library tests it with #ifdef, so -D ASYNCWEBSERVER_REGEX=0 enabled regex routing rather than disabling it, costing 266 KB of flash for a server with one fixed path
  • add native test envs (unity, ASan/UBSan, coverage) with 112 tests at 92.3% line coverage, including a new suite for the Schema builder
  • add CI: native tests, coverage floor, cppcheck, and an example build against the working tree
  • declare -std=gnu++17 in library.json; the sources need C++17
  • bump to 0.2.0 and refresh the README

…forks

BREAKING CHANGE: the constructor no longer starts listening. Register every
tool, then call begin() once WiFi is connected. Protocol version 2024-11-05
is no longer supported.

* replace the archived me-no-dev ESPAsyncWebServer/AsyncTCP with the
  maintained ESP32Async forks (^3.6.0 / ^3.3.2)
* run tools/call on a dedicated FreeRTOS worker task with a deferred chunked
  reply and a 20 ms inline fast path, so a blocking handler no longer stalls
  the async_tcp task that services every connection on the device
* harden the request path: cap bodies at MCP_HTTP_MAX_BODY_SIZE (413), answer
  411 without Content-Length, 415 for non-JSON, 500 on OOM, and 400 on a short
  body; write chunks by index and clamp clients that overshoot
* fix a _tempObject leak on the empty-body path and drop the Serial dump of
  every request body
* reject browser origins that do not name this device by its current IP or its
  advertised <server-name>.local hostname (403), on every route; matching
  Origin against Host alone does not survive a DNS rebind
* sanitize the mDNS hostname; a server name with spaces produced an invalid
  DNS label
* drop 2024-11-05, which is the deprecated HTTP+SSE transport this server does
  not implement; negotiate 2025-11-25/2025-06-18/2025-03-26 and reject an
  unsupported MCP-Protocol-Version header with 400 as the spec requires
* stay stateless: no MCP-Session-Id is issued, which the spec permits
* add ping, treat notifications as JSON-RPC requires (202, no body), enforce
  the envelope, and accept any JSON number as an id
* return structuredContent and isError; add MCP_OMIT_TEXT_WHEN_STRUCTURED
* cache the serialized tools/list body between registrations
* serialize responses without a wrapper document, halving peak JSON residency
* answer GET/DELETE with 405 + Allow instead of 200
* drop ASYNCWEBSERVER_REGEX from the example: the library tests it with #ifdef,
  so -D ASYNCWEBSERVER_REGEX=0 enabled regex routing rather than disabling it,
  costing 266 KB of flash for a server with one fixed path
* add native test envs (unity, ASan/UBSan, coverage) with 112 tests at 92.3%
  line coverage, including a new suite for the Schema builder
* add CI: native tests, coverage floor, cppcheck, and an example build against
  the working tree
* declare -std=gnu++17 in library.json; the sources need C++17
* bump to 0.2.0 and refresh the README
@abcsnowwolf
abcsnowwolf merged commit ceb42f4 into main Aug 15, 2026
8 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.

1 participant