Parity catch-up to upstream fastmcp v3.4.2 (F1–F8)#46
Merged
Conversation
F1 (Python fastmcp #4058, commit 24b594b1):
utilities/versions.py VersionSpec eq normalization. fastmcpp's
compare_versions already normalized {1, 1.0} via the default-zero
padding, but did not strip a leading 'v'/'V' prefix. After this
change, '�2.5.0' compares equal to '2.5.0' so version filters
match v-prefixed components consistently.
F2 (Python fastmcp #4061, commit 01b971d8):
resources/template.py FunctionResourceTemplate.create_resource()
was dropping annotations/meta/title/icons when materializing a
resource from a template. fastmcpp's ResourceTemplate::create_resource
had the same bug — only uri/name/description/mime_type/app/provider
propagated. Now title/annotations/icons/version/task_support also
carry through.
Tests:
- tests/providers/version_filter.cpp gains v_prefixed_tool case
(versioned 'v2.5.0', expected to fall in [2.0, 3.0)).
- tests/resources/template_metadata.cpp is a new focused test that
builds a ResourceTemplate with title/annotations/icons/version/
task_support set and asserts every field propagates through
create_resource().
ctest -R 'fastmcpp_(provider_version_filter|resources_template_metadata)':
2/2 passed.
Reference: fastmcp v3.4.2 (3b8538e2)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Both findings are already-implemented in fastmcpp; these tests pin the
behavior explicitly so future regressions are caught.
F4 (Python fastmcp #4178, commit 834f96d4 + cosmetic #4023 / 7cfcaf22):
utilities/json_schema.py resolve_root_ref must preserve sibling
metadata (title/description/default/examples) when falling back to
a lookup for circular schemas. fastmcpp's dereference_node
(src/util/json_schema.cpp:152) already merges non- siblings
onto the resolved object. New test root_ref_metadata.cpp asserts
this for a root-level with title+description siblings.
F5 (Python fastmcp #4217, commit e242abee):
tools/base.py ToolResult.is_error so a tool can RETURN an error
(instead of raising), and proxy/caching round-trip is_error. At
the fastmcpp wire level, this already works:
- server-side: build_fastmcp_tool_result preserves isError when
a tool callback returns {"content": [...], "isError": true}
(handler.cpp:817)
- client-side: parse_call_tool_result reads isError into
CallToolResult (client.hpp:1043) and call_tool(raise_on_error=
false) returns without throwing
- ProxyApp passes the remote result through verbatim with
raise_on_error=false (proxy.cpp:268)
- CachingMiddleware caches list endpoints only — not tools/call
— so the Python CachableToolResult is_error round-trip concern
doesn't apply
Prior tests only covered the raise_on_error=true (throw) path
(interactions_part1.cpp test_call_tool_error_handling). New test
tool_result_is_error.cpp covers the no-throw F5 path and asserts
content + structuredContent are preserved (not collapsed).
ctest results (new tests only):
fastmcpp_schema_root_ref_metadata: PASS
fastmcpp_client_tool_result_is_error: PASS
Reference: fastmcp v3.4.2 (3b8538e2)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
F7 (Python fastmcp #4227, commit 2bff3725):
AggregateProvider/FastMCPProxy gained provider_error_strategy
with values 'warn' (default — log + silently skip failed
providers) and 'raise' (propagate the first provider error).
fastmcpp ProxyApp's list_all_* previously hard-coded the
'warn' behavior (catch and continue with local-only). This
change introduces ProxyErrorStrategy enum (Warn|Raise) and
ProxyAppOptions surface, default Warn for back-compat. Under
Raise, list_all_tools/resources/templates/prompts re-raise
the first upstream exception so callers can fail fast.
F8 (Python fastmcp #4228, commit 140d96aa):
FastMCPProxy made validate_on_initialize always-on so the
proxy's MCP initialize forwards to the upstream and surfaces
connection failures as JSON-RPC errors immediately. fastmcpp
keeps this opt-in via ProxyAppOptions::validate_on_initialize
(default false) for back-compat with existing fastmcpp users
that construct proxies whose upstream may be lazily reachable.
When enabled, make_mcp_handler(ProxyApp&) calls upstream
Client::initialize() on inbound initialize, and returns
jsonrpc_error(INTERNAL_ERROR, ...) on any std::exception.
API surface added:
enum class fastmcpp::ProxyErrorStrategy { Warn, Raise };
struct fastmcpp::ProxyAppOptions {
std::string name = "proxy_app";
std::string version = "1.0.0";
std::optional<std::string> instructions;
ProxyErrorStrategy error_strategy = ProxyErrorStrategy::Warn;
bool validate_on_initialize = false;
};
ProxyApp::ProxyApp(ClientFactory, ProxyAppOptions); // new
ProxyErrorStrategy ProxyApp::error_strategy() const;
bool ProxyApp::validate_on_initialize() const;
Files touched:
include/fastmcpp/proxy.hpp — enum, struct, ctor, accessors
src/proxy.cpp — new ctor + strategy check in
each list_all_* error handler
src/mcp/handler.cpp:2580 — F8 initialize-time upstream ping
in make_mcp_handler(ProxyApp&)
tests/proxy/error_strategy.cpp — 4 new test cases covering
Warn (default), Raise, and
both initialize paths
Verification:
ctest --test-dir build -C Debug -j 8:
107/107 passed (was 103/103 baseline + F1/F2/F4/F5 tests
+ this F7+F8 test = 107). No regressions.
Reference: fastmcp v3.4.2 (3b8538e2)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CMakeLists.txt project version and README.md headline updated to reflect the v3.4.2 parity catch-up for upstream fastmcp 3b8538e2. In-scope behavioral findings landed in this cycle: F1 — VersionSpec eq normalization (v-prefix strip) F2 — Resource-template metadata propagation F4 — JSON-schema root-ref metadata (verify-first; already correct) F5 — ToolResult is_error wire-level passthrough (verify-first; already correct) F7 — Proxy upstream error strategy (Warn|Raise; default Warn) F8 — Proxy initialize forwarding (opt-in via ProxyAppOptions) Deferred (documented in kb/sync/review_result.md): F3 — UTF-8 MCP config read (N/A: fastmcpp has no mcp_config equivalent) F6 — Pre-bound HTTP sockets (cpp-httplib limitation; revisit if user needs it) F9 — Proxy template query-params (N/A: fastmcpp passes URIs verbatim) F10 — OTEL spans on sampling (review-first: defer if no spans yet) F-NA-1 — Proxy ContextVar restore (N/A: no StatefulProxyClient in C++) Intentional divergences for the full v3.3.1..v3.4.2 delta (15 commits): - 11 auth/OAuth/JWT/joserfc/WorkOS/Azure/OIDC commits - 2 code-mode (Monty sandbox) commits - 1 fastmcp-remote bridge package - 1 'fastmcp dev apps' browser UI CLI Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Catch-up sync to upstream fastmcp
v3.4.2(3b8538e2) fromv3.3.1(d8dcc273). 56-commit delta triaged: 7 port-needed, 3 review, 15 intentional divergences (auth/OAuth/JWT/code-mode/fastmcp-remote/dev-apps), 29 N/A (docs/CI/deps/Python-only).Ported
compare_versionsstrips leadingvprefix (VersionSpec eq normalization) —src/providers/transforms/version_filter.cppsrc/resources/template.cppToolResultis_errorpassthrough via proxy/handler/cache (verified correct; interop test added)ProxyErrorStrategyenum (Warndefault,Raisepropagates upstream errors) —include/fastmcpp/proxy.hpp,src/proxy.cppinitializeforwarding (opt-invalidate_on_initialize) —src/mcp/handler.cppCMakeLists.txt,README.md)Deferred / N-A
mcp_configin C++), F6 deferred (cpp-httplib has no pre-bound socket API), F9 N/A (proxy passes URIs verbatim), F10 review-only (no existing sampling spans), F-NA-1 N/A (no StatefulProxyClient). Auth/OAuth/JWT/code-mode/fastmcp-remote/dev-apps remain intentional divergences.Verification
New tests:
tests/resources/template_metadata.cpp,tests/schema/root_ref_metadata.cpp,tests/client/tool_result_is_error.cpp,tests/proxy/error_strategy.cpp; extendedtests/providers/version_filter.cpp.