Changelog¶
This page documents all notable changes to the toolregistry-hub project since the first official release version 0.4.14.
The format is based on Keep a Changelog, with project-specific grouping where useful.
[Unreleased]¶
Added¶
tools.jsonchot reload (#144): with--config-reloadthe running server watches its config file (mtime/size polling, no new dependency) and applies a source-level diff to the live registry: an added source is registered, a removed source is unregistered, a source that leaves the configured scope (enabled: false, or filtered bymode/disabled/enabled) is disabled instead of unregistered, and a changed declaration is replaced. Reordering the list is not a change. A malformed file is logged and ignored, and the current registry keeps serving. The first poll after startup always runs, so an edit made between the registry build and the watcher start is not lost. Removing atool_metadataentry keeps the value it set until restart, because the same fields are also writable from the admin panel; the panel can reset it immediately. The watcher is opt-in and per process; the built-in default tool list has no file to watch, and cross-process coordination for a multi-service deployment is not included.
Fixed¶
- Config hot reload bypassed
--profile(#234): a source registered by a reload did not pass through the deployment profile filter, so editing its declaration could re-expose afile_system,destructive, orprivilegedtool under--profile remote(or anetworktool under--profile local). A reload now applies the same tag mapping to the tools it registers, without touching tools that were already registered. - Hub metadata defaults reset admin-panel edits on every reload (#232):
apply_hub_overridesreplayed_TOOL_METADATAover the whole registry on every applied diff, so a change totags,defer,title,search_hintor an execution hint made from the admin panel was silently undone by the next unrelated config change.reload_registrynow passes the names it registered toon_reload, and the callback annotates only those tools. Tools that already existed keep their current values; a tool registered by the reload still gets the Hub defaults, and the file'stool_metadatastill wins afterwards. - A zero-tool source is no longer re-registered on every reload (#233): an empty name set meant an excluded source, a failed registration, or a successful registration that produced no tools, so the diff treated all three as needing registration and an MCP server that advertises no tools reconnected on every unrelated config change. A per-source status now records
applied,excludedorfailed: an applied source with no tools is left alone, a failed one retries, and an excluded one registers once it enters scope.
Changed¶
- Vendored
httpclient0.6.4 → 0.7.1 (zerodep48606bf): a redirect to a different origin no longer forwardsAuthorization,Proxy-AuthorizationorCookie, and Digest authentication is attempted only while the request stays on the credential's origin (#287); every member of a multi-member gzip body is decoded instead of only the first; andClient/AsyncClientplus the convenience functions accept an optionalmax_response_sizethat caps a buffered body and raisesResponseTooLargeErrorabove it. The parameter defaults toNone, so every existing call buffers exactly as before, and astream=Trueresponse is never capped. No hub code changes.
Security¶
- Fetch applies an outbound address policy (#240, refs):
fetch_contentnow validates the caller-supplied URL and proxy before any request. Only http/https are allowed; every resolved address must be globally routable (loopback, RFC 1918, link-local including169.254.169.254, CGNAT, multicast, NAT64, 6to4, Teredo, ORCHID, and documentation/benchmarking ranges are refused), and a resolution failure is refused. IPv4-mapped and NAT64-embedded addresses are checked as IPv4. Redirects are checked after the fact: the body is discarded andFetchPolicyErroris raised whenresponse.urlpoints into a private address. CDP checksdocument.location.hrefafter navigation; VeilRender checksmetadata.url; both refuse content when the final address is missing. Operators can opt in withFetch(allow_private_hosts=True),FETCH_ALLOW_PRIVATE_HOSTS=1, or the constructor keyword intools.jsonc; there is no per-call switch. Residual risk: the request that produced a refused redirect response has already been sent (blind SSRF), and DNS is resolved again at connect time (rebinding window) until zerodep shipsfollow_redirects=Falseand connect-time address pinning. - Fetch bounds the response body (#243): every request — markdown negotiation, the raw fetch, the Jina Reader call and VeilRender — now passes a 10 MiB
max_response_sizeto the vendored HTTP client, which refuses an oversizedContent-Lengthbefore reading any body and stops a chunked body as soon as it crosses the cap.ResponseTooLargeErroris mapped toFetchErrornaming the caller-supplied host and the limit, never a resolved address. Previously the whole body was buffered before the content-type check ran, so one multi-gigabyte response could OOM a shared hub.
[0.12.0] - 2026-10-23¶
Fixed¶
- The bare install now pulls the core library (#226, #225):
[project].dependencieswas empty, sopip install toolregistry-hubinstalled nothing thattoolregistry_hubimports — every tool subclassestoolregistry.Toolandfile_searchimportstoolregistry.parameter_models. The core library only arrived through theserverextras, which is why server deployments worked and the documented library quickstart (pip install toolregistry-hub, thenfrom toolregistry_hub import Calculator) failed withModuleNotFoundError.toolregistry>=0.19.0,<1.0.0is now a runtime dependency, matching the floortoolregistry-server>=0.7.0already required; a packaging test asserts it stays there. This affects every published version, including 0.11.0.
Changed¶
- Tool names are client-safe and consistent (#186, breaking): namespaces no longer contain
/and the redundant prefixes are gone.web/websearch-search→web-search,web/websearch-list_engines→web-list_engines,web/fetch-fetch_content→web-fetch_content,fs/file_search-*→fs-*,fs/path_info-info→fs-info; the individual providers register asbrave-search,tavily-search,searxng-search,brightdata-search,scrapeless-searchandserper-search. Every name now matches[A-Za-z0-9_.-]{1,64}, so a client can forward it to a provider's function-name field unchanged. HTTP paths follow the same scheme (/tools/fs/glob,/tools/web/search). A regression test asserts that the default registry and the shippeddata/tools.yamlonly ever register client-safe, unique names. Update prompts, saved tool names and per-namespace configs.
[0.11.0] - 2026-10-23¶
Added¶
FileSearchhonours.gitignore(#73):glob(),grep()andtree()skip ignored paths by default when the search root is inside a git repository, so results no longer fill up withnode_modules/,__pycache__/and build artifacts. Rules are read hierarchically (root file first, nested files on top) by a new dependency-freetoolregistry_hub.gitignorematcher supporting negation, directory-only rules, anchoring,**,?and character classes; git's rule that a path under an ignored directory cannot be re-included is preserved. A newrespect_gitignoreparameter (None= follow the repository,True= always apply rules found under the root,False= off) overrides the default on all three tools, and an explicitly named file passed togrep()is always searched.- Declared result schemas for structured tools (#189): ten tools now publish an MCP
outputSchemaand returnstructuredContentalongside the text block, so a client can read the result as data instead of re-parsing JSON out of a text block:weather-get_current/get_forecast/get_astronomy,datetime-convert_timezone,file_ops-read/edit/write,fs/path_info-info,web/fetch-fetch_contentandbash-execute. The schemas are declared onToolMetadata.extra["output_schema"]from a newtoolregistry_hub.server.output_schemastable and describe the keys each tool always emits — norequiredlist andadditionalProperties: true, so a field the upstream API omits (fs/path_info-inforeturns only{"exists": false}for a missing path) never contradicts its published schema. Array-returning tools (fs/file_search-glob/grep,web/websearch-search,academics-search) deliberately declare nothing, because MCPstructuredContentis an object. - MCP execution hints for the built-in tool set (#280): every tool now declares
readOnlyHint, and most declaredestructiveHint,idempotentHintandopenWorldHint, so MCP hosts can auto-approve read-only calls (datetime-now,weather-*,websearch-search,academics-search,reader-*,fs/*,think,calculator,unit_converter,todolist) and reserve confirmation forbash-execute,file_ops-edit/writeandcron-create/delete/shutdown.file_ops-readis now correctly declared read-only instead of inheriting the namespace's destructive tag, andcron-listis read-only. Human-readable titles are set for the main entry points. - Hub metadata overrides accept
titleand execution hints:_TOOL_METADATAentries can settitle,read_only_hint,destructive_hint,idempotent_hintandopen_world_hint, at namespace or method level. Fields the installedtoolregistrydoes not define are skipped, so the hub keeps working against older cores.
Fixed¶
bash-executedeny list judges whatrmdeletes, not how the path is spelled (#6):rm -rf /tmp/build,/srv/app/cacheand/etc/nginx/cachework again, while the root, the system directory names, unrecoverable trees (/usr/lib,/boot,/dev,/var/lib,/etc/ssh, …),$HOME/~,./..and shell spellings of them (//etc,./,/et?,/{etc,usr}) stay blocked. Onlyrm's own operands are judged, soecho 'rm -rf /'runs. Commands are split on;,&,|and newlines outside quotes and grouping/compound syntax is unwrapped (( … ),{ …; },!,then/do, case arms, function bodies), substitutions ($(…), backticks) andfind -exec/sh -c/bash -lcpayloads are checked,xargswithout operands is refused, and GNU long-option prefixes (rm --rec -f) are recognised. Behaviour comes frombashtool0.3.2 + 0.3.3, which this release pins; the mirrored cases are intests/test_bash_tool.pyand the security section of the Bash Tool page describes the new rules.todolist-updateacknowledges a simple update instead of returningNone(#212):format="simple"is the default and ended inreturn None, so the common call handed the model the literal string"None"— it could not tell "recorded" from "nothing happened", the same symptom #185 and #202 fixed elsewhere. The default path now returns"todo list updated"(or"todo list cleared"for an empty input), the annotation isstr, and the markdown/ascii renderings are unchanged.cron-shutdownacknowledges the stop instead of returningNone(#202): the method was annotated-> None, sotools/callhanded the model the literal stringNone, which reads like a failed or empty call. It now returns"scheduler stopped". Together with #185 (think) this was the lastNoneTypereturn among the toolsbuild_registry()produces.- SearXNG and Bright Data timeouts are errors, not empty results (#211): the last two engines of the #193 class turned a timeout into
[], so a pinned engine during an outage looked like "no results for this topic". Both now raiseSearchBackendErrorwith a "timed out after Ns" message, like every other engine; a successful response with no results still returns[], andauto/parallelfall back to another engine rather than reporting an empty result. - A Reddit timeout is an error, not an empty result (#205):
redditwas the one engine in_ENGINE_REGISTRYthat still returned[]when Arctic Shift timed out, so pinningengine="reddit"during an outage looked like "this topic has no posts" — the symptom #193 describes, one engine over. It now raisesSearchBackendError, like the other engines; a successful response with no posts still returns[].autoandparallelfall back to another engine instead of reporting an empty result. thinkreturns an acknowledgement instead ofNone(#185): the method was annotated-> Noneand ended in a barereturn, so everytools/callhanded the model the literal text"None"— meaningless in the transcript and easily read as a failure marker. It now returns e.g."[reasoning] probe recorded"(mode only whenfocus_areais omitted).
Changed¶
- Server floor is
toolregistry-server>=0.7.0(#187): the server now encodes dataclass tool results structurally, soweb/websearch-searchandacademics-searchreturn real JSON objects (title,url,content,score, …) instead of Pythonrepr()strings inside the text block. No hub API change. - A developer's
.envno longer changes which tests run (#210):tests/websearch/test_brightdata_engines.pycalledload_dotenv()at module scope, so every test collected after it inherited the keys and theskipifguards in unrelated modules stopped skipping — with a.envpresent, the live-call modules hit real APIs and failed on quota or response shape, and without one they skipped. The call now sits underif __name__ == "__main__":,test_debug_google_apis.pyandtest_serper_integration.pycarrypytestmark = pytest.mark.integrationand are deselected by default (pytest -m integrationto run them), andtests/test_no_implicit_dotenv.pyfails if a new module reintroduces an import-scopeload_dotenv(). - Vendored zerodep modules are flat again, with stale duplicates removed:
soupandreadabilityexisted both as single modules and as package directories (soup.py+soup/soup.py), andcdp/websocketwere package-only, sozerodep outdatedcould not see them. Everything is re-vendored withzerodep addin its default (flat) layout, which is what the CLI and the update workflow expect; the package copies are gone andzerodep outdatednow reports all nine modules. Along the waysoupgoes 0.6.0 → 0.8.1 andhttpclient0.5.0 → 0.5.1. No hub code changes. bash-executetimeouts are errors (#188, #190):BashTool.execute()now raisesCommandTimeoutErrorinstead of returning{"timed_out": true, "exit_code": -1}as a successful result, so MCP reportsisError: trueand the model sees why the command produced no output. The exception carries the partial stdout/stderr written before the kill. The timeout also kills the whole process tree now — previously only theshell=Truechild died and background children such assleep 300 &kept running. Behaviour comes frombashtool0.3.0, which this release pins.
Fixed¶
- A failing search engine is now an error, not an empty list (#193):
brave,tavily,serper,githubandscrapelessreturned[]on HTTP errors, timeouts, exhausted API keys and unparseable responses, so a caller could not tell "no results" from "this engine is broken" — and a pinnedengine=looked like an empty topic. They now raiseSearchBackendError, matching the policysearxngandbrightdataalready followed.autoandparallelstill fall back to other engines; only a request that cannot be served raises, and it surfaces asisError: truewith the provider's message.
Fixed¶
bash-executedeny list precision (#191):eval/execare only blocked when they are the invoked command, sofind … -exec,grep evalandecho > eval.txtwork again.rmflags are normalised, sorm -r -f /x,rm --recursive --force /xandrm -Rf /xare blocked likerm -rf /x, including behind wrappers (sudo -u root,env -i,nice -n,timeout,xargs) and insidefind -exec/-execdirpayloads andsh -cstrings. Segments now split on a single|, so checks see both sides of a pipe.rm -rf ./buildremains allowed. Behaviour comes frombashtool0.3.1, which this release pins.
[0.10.0] - 2026-09-16¶
Added¶
- Academic search tools — new
academicsnamespace with OpenAlex and arXiv engines. OpenAlex supports keyless polite-pool mode viaOPENALEX_MAILTO. Priority order configurable viaACADEMIC_SEARCH_PRIORITY. - GitHub search engine — search GitHub repositories via REST API. No token required for public repos; optional
GITHUB_TOKENfor higher rate limits with multi-key rotation. - Reddit search engine — search Reddit posts via Arctic Shift API (free, no auth). Requires subreddit scope in query (e.g.
r/python web scraping). - Docker CI workflow — multi-arch (amd64 + arm64) Docker builds integrated into the release pipeline. Images published to DockerHub as
oaklight/toolregistry-hub-server. - Test PyPI release workflow — CI workflow for publishing dev versions to Test PyPI, with Docker build support via
testpypiflag. - Admin panel Caddy routing — centralized admin panel access at
/admin/openapi/,/admin/mcp-http/,/admin/mcp-sse/with HTTP basic auth. Admin panel binds to the same host as the main server for Docker networking compatibility.
Changed¶
toolregistry-serverdependency bumped to>=0.6.0.- Adapted to toolregistry 0.18.0 — frozen
Tool/ToolMetadatadataclasses andcall_deferredintegration.
Fixed¶
- Engine schema narrowing —
_configured_engine_names()now includes all configured engines (including reddit, github), not just priority-list engines. Previouslyengine="reddit"andengine="github"failed API schema validation. - File digest loss — prevent digest loss when
file_ops-readoutput is truncated.
Improved¶
- Streaming digest in
file_ops-readdigest_only mode for better performance.
[0.9.3] - 2026-08-06¶
Fixed¶
- Release CI: include git submodules in build — v0.9.2 shipped without the
bashtoolsubmodule, causingModuleNotFoundErroron import. Addedsubmodules: recursiveto the release workflow's checkout step.
[0.9.2] - 2026-08-06 [YANKED]¶
Changed¶
- BashTool extracted to submodule: Replaced the inline
BashToolimplementation with thebashtoolsubmodule (v0.2.0). Removessudofrom the default deny list; addsBASHTOOL_UNSAFEenv var to opt into unrestricted mode. Simplifies unsafe-mode tests. - Core dependency bumped to
toolregistry>=0.15.0: Ensures users get the execution-stack refactor (ainvoke,aexecute_tool_calls, per-tool backend resolution, MCP v2 compatibility) from core. - Server dependency bumped to
toolregistry-server>=0.4.3: Ensures server-side MCP v2 compatibility layer matches core.
Fixed¶
- User config
tool_metadataoverrides hub defaults: Previously hub-supplied metadata silently won over user configuration; user-suppliedtool_metadatanow takes precedence. - Stable import path for
_validate_commandin shim: Fixes breakage when internal paths changed in thebashtoolsubmodule. - ty 0.0.53+ type-check warnings resolved.
Infrastructure¶
- Vendored dependencies updated:
httpclient0.4.4 → 0.4.5,readability0.1.0 → 0.2.0,validate0.4.3 → 0.6.1. - Dev tool versions pinned:
ruff==0.15.20,ty==0.0.54,complexipy==5.6.1.
[0.9.1] - 2026-06-22¶
Changed¶
- Server: Adopt toolregistry-server 0.4.0 architecture (#147) — migrates Hub to the upstream
App/Adapter/registry_builderarchitecture.HubApp(App)overrides onlyprepare_registry()for Hub-specific registry construction;run_cli()andAdapter.add_cli_arguments()replace hand-rolled equivalents. Removesserver/auth.py,server/routes/, and associated re-exports. Net −798 lines. - Server: Adopt
ServerIdentity+CLIclass from toolregistry-server (#149) —HubAppnow accepts aServerIdentity(HUB_IDENTITY: name, version, description, banner art) that flows automatically to the OpenAPI title, MCP server name, and CLI banner.HubCLIsubclassestoolregistry_server.cli.CLI, overriding four methods (configure_subparsers,get_version_string,print_banner,dispatch) instead of reimplementing the main loop.main()reduced to one line:HubCLI().main(args). No user-visible CLI changes.
Improved¶
- Server: Lazy-init
HubApp+configure_subparsershook — module-levelHubAppis now created on first use, preventing double-instantiation whenHubCLIcreates its own instance.create_parserno longer digs into argparse private API (_subparsers._actions); Hub-specific arguments are now injected via theconfigure_subparsers(subparsers: dict[str, ArgumentParser])callback. - Server:
_run_update_check()helper — async event-loop boilerplate in_get_version_stringand_print_hub_bannerextracted into a shared_run_update_check()helper, eliminating duplication.
Fixed¶
- Docker: add
*.keyand*.pemto.dockerignore— prevents private keys and certificates from being inadvertently included in Docker build context.
Docs¶
- Fix jina strategy description and clarify that
VEILRENDER_TOKENis optional.
[0.9.0] - 2026-06-21¶
Added¶
- Weather tool (#131) - new
weathernamespace with three methods powered by the free wttr.in JSON API. No API key required; uses the existing zero-dephttpclient.get_current(location, units)- current conditions: temperature, feels-like, humidity, wind, precipitation, cloud cover, UV index, visibility, pressure.get_forecast(location, days, units, include_hourly)- up to 3-day forecast with optional 3-hourly breakdowns.get_astronomy(location)- sunrise/sunset, moonrise/moonset, moon phase and illumination.- Supports metric/imperial units, city names, coordinates, and airport codes. Tagged
NETWORK + READ_ONLY.
Improved¶
- Fetch: Reuse markdown negotiation response body (#132) - when Cloudflare Content Negotiation returns
text/htmlinstead oftext/markdown(the common case), the response body is now preserved and passed directly to the Readability/Soup extraction pipeline, eliminating a redundant HTTP round-trip. Previously the HTML response was discarded and_fetch_rawissued an identical GET request to the same URL. - Fetch: Binary content-type early rejection (#132) - URLs returning binary content types (
image/*,audio/*,video/*,font/*,application/pdf,application/zip,application/octet-stream, etc.) are now detected before entering the extraction pipeline and raiseFetchErrorwith a descriptive message. Previously binary responses were decoded as text and fed through Readability/Soup, producing garbage output. - Fetch: URL-level result cache (#135) - adds a per-instance URL result cache with configurable TTL (default 5 minutes) and LRU eviction (default 128 entries). Repeated fetches of the same URL within the TTL window return the cached result instantly. Only successful results are cached; errors always retry. Cache can be disabled with
cache_ttl=0or cleared viaFetch.clear_cache(). - Fetch: Improved SPA detection with readability score (#138) - when the readability algorithm scores a page above the confidence threshold (score ≥ 20), SPA shell indicator matching is skipped entirely, preventing false positives on legitimate pages that happen to contain phrases like "loading...". Also tightens the SPA indicator list and adds a short-text threshold for broader indicators.
- Fetch: Skip soup extraction when readability is sufficient (#139) - when readability produces a high-confidence result (
score ≥ 100andlength ≥ 2000characters), the soup extraction pass is skipped entirely. Profiling showed soup adds ~30-35% to local extraction time but contributes <16% additional content in these cases, saving 30-180 ms per page depending on document size. Applied to both the main_extractpipeline and the CDP rendering path. A debug log records skipped soup calls with score and length for post-deployment threshold tuning. - Fetch: Reduce cognitive complexity of
_extractand_is_content_sufficient(#139) — refactored_extract(complexipy 26→16) and_is_content_sufficient(22→4) by extracting four helper functions, bringing both under the project’s complexity threshold of 15. - WebSearch: Parallel multi-engine search with BM25 dedup (#142) — new
engine="parallel"mode that queries multiple search engines concurrently viaThreadPoolExecutor, deduplicates results by URL, and re-ranks with BM25 scoring. Default parallel engines configurable viaWEBSEARCH_PARALLEL_ENGINESenv var (default:brightdata,brave). Auto-skips unconfigured or failed engines with graceful fallback to auto mode. Also renamesmax_results→countin thesearch()signature and removes**kwargsfor a cleaner LLM tool schema. - WebSearch: URL normalization for deduplication (#143) — dedup now normalizes URLs before comparison: strips
www.prefix, removes trailing slashes, and filters common tracking parameters (utm_*,fbclid,gclid,msclkid,mc_*). Original URLs in search results are preserved unchanged. - Docker: Caddy gateway with unified entry point (#141) — adds a Caddy reverse proxy to unify three service backends behind a single port:
/mcp→ MCP streamable-http,/sse→ MCP SSE, everything else → OpenAPI. Includesflush_interval -1on all backends to prevent SSE/streaming buffering, backend services changed fromportstoexpose(no longer exposed to host directly), and/openapiconvenience redirect to/docs. - Docker:
deploy-devMakefile target (#141) —make deploy-dev SSH_TARGET=hostbuilds a wheel, builds the Docker image, transfers via zstd compression, and restarts the remote stack with health check. - FileOps: Claude Code-style read/edit/write digest workflow (#146) — replaces the deprecated
read_file/write_file/append_filesurface with a stateless, digest-based API:read(path)→{content, digest, is_symlink, real_path}— reads file bytes, returns SHA-256 digest as a version token. Symlinks are allowed for reading;is_symlinkandreal_pathare reported so callers can pass the real path to write operations.edit(path, old_string, new_string, digest, replace_all=False, start_line=None)→{diff, digest}— exact string replacement guarded by digest; returns an updated digest so edits can chain without re-reading.write(path, content, digest=None, mode="overwrite"|"append")→{digest}— atomic overwrite or append; new files need no digest, existing files require a matching digest to prevent silent overwrites.appendmode decodes the existing file with its original encoding/BOM, appends as a string, then re-encodes, preserving UTF-16 and BOM-prefixed files correctly.editandwritereject symlink paths (including.tmpintermediates). External modifications invalidate the digest and force a freshread. 30 tests; no server-side state.
Internal¶
- Rename
_get_content_with_markdown_negotiation→_try_markdown_negotiation; return type changed fromstrto(md_content, fallback_body, fallback_ct)tuple for response reuse. - Add
_is_binary_content_type()helper with prefix-based and exact-match detection. - 10 new tests covering response reuse path, fallback-to-
_fetch_rawpath, binary rejection, and parametrized binary/non-binary detection. - Add
_should_skip_soup()predicate with_SOUP_SKIP_SCORE_THRESHOLD(100.0) and_SOUP_SKIP_MIN_LENGTH(2000) constants. - 11 new tests for soup-skip behaviour: 8 unit tests for
_should_skip_soup, 3 integration tests for the full_extractpipeline. - Add
dedup.pymodule with_normalize_url(),_tokenize(),_bm25_score(), anddeduplicate_results(). 14 new tests for BM25 scoring, URL normalization, and dedup behaviour. - Add
_search_parallel()strategy withThreadPoolExecutor. 7 new tests for parallel mode (configured engines, skip unconfigured, handle failure, dedup, fallback, count cap). - Add
Caddyfilereverse proxy config; refactorcompose.yamlto use gateway service withIMAGE_TAGandGATEWAY_PORTvariables; adddeploy-devtarget to Makefile.
Fixed¶
- Fix
README.mdsymlink target fromreadme_en.md(nonexistent) toREADME_en.md.
Improved (continued)¶
- Fetch: VeilRender browser fallback (#140) — adds VeilRender as an optional remote headless browser fallback, positioned before CDP in the auto fallback chain. VeilRender renders JS-heavy pages via a REST API (
POST /render) and re-parses the returned HTML with Readability/Soup. Configure viaVEILRENDER_ENDPOINTand optionallyVEILRENDER_TOKEN. When unconfigured, the strategy is hidden from thestrategyLiteral annotation at runtime. - Fetch: Structured return value (#140) —
fetch_contentnow returns aFetchResultTypedDict instead of a plain string:{content, url, strategy, quality, content_type, cached, elapsed_ms, metadata}. Thequalityfield is"high"or"low";metadatacarries strategy-specific fields such asreadability_scoreandcontent_length. - Fetch: Explicit
strategyparameter (#140) —fetch_contentaccepts an optionalstrategyargument (default"auto"). Available choices:auto,markdown,readability,soup,jina(always present), plusveilrenderandcdpwhen their respective endpoints are configured. The Literal annotation is narrowed to available strategies at__init__time via_narrow_strategy_annotation(). Explicit strategies bypass the fallback chain and run a single targeted extraction. - Fetch: Updated fallback chain (#140) — auto pipeline order:
markdown → readability → soup → veilrender → cdp → jina → local_fallback. Dockercompose.yamlretains direct service port mappings (55093/55094/55095) alongside the Caddy gateway.
Internal (continued)¶
- Add
FetchResultTypedDict,_make_result()factory, and_extract_with_strategy()/_extract_auto()split to replace the monolithic_extract(). Strategy-specific handlers factored into_strategy_markdown(),_strategy_local(),_strategy_browser(),_strategy_jina(). - Add
_render_with_veilrender()and_try_veilrender_extraction()mirroring the existing CDP helpers. - Add
_try_browser_rendering()to encapsulate the VeilRender → CDP cascade in the auto pipeline. Fetch._available_strategies()drives both runtime validation and Literal narrowing;veilrender/cdpappear only when their endpoints are set.- Server: Adopt
ServerIdentity+CLIclass from toolregistry-server (#149) —HubAppnow accepts aServerIdentity(HUB_IDENTITYwith name, version, description, banner art), which flows automatically to the OpenAPI title, MCP server name, and CLI banner.HubCLIsubclassestoolregistry_server.cli.CLI, overriding four methods (create_parser,get_version_string,print_banner,dispatch) instead of reimplementing the main loop.main()is reduced to one line:HubCLI().main(args). No user-visible CLI interface changes.
[0.8.3] - 2026-06-03¶
Added¶
- CDP rendering stage for Fetch - when a
CDP_ENDPOINTis configured,fetch-fetchattempts headless-browser rendering for SPA pages whose initial HTML is mostly empty JavaScript shells. Falls back to the plain HTTP response when CDP is unavailable or the page is already server-rendered. - New
toolregistry_hub.utils.bind_literal()helper that returns a copy of a function with one parameter's annotation rewritten toLiteral[*choices]. Used by tools that need to surface a runtime-driven enum in their MCP / JSON input schema without hand-rollingFunctionTypeshenanigans.
Fixed¶
- SearXNG: switch JSON API requests from GET to POST (#115). Modern SearXNG instances with
limiter: trueblock GET requests forformat=jsonviaSec-Fetch-*header checks; POST bypasses the limiter and matches the upstream-documented JSON API usage. Also replaces silentreturn []on HTTP errors with a typedSearchBackendErrorso callers can distinguish "no results" from "backend rejected the request". unit_converter-convertinput schema now exposesconversionas a closed enum of all 41 conversion function names instead of a free-form string (#117). MCP clients can validate locally and no longer need a discovery round-trip vialist_conversions.todolist-updateacceptsin_progress(alsoin-progress,inprogress) as an alias forpending(#116). The status enum is also now spelled out explicitly in theupdatedocstring so it shows up in the generated tool description.fetch-fetchnow raisesFetchErroron HTTP failures and treatstimeoutas a wall-clock budget rather than per-request.- Bright Data websearch: align with official MCP package interface and increase default timeout.
- Scrapeless websearch: increase default timeout; add
cast()for ty type-checker compatibility.
Changed¶
unit_converter-helpandcalculator-helpnow accept calls withoutfn_name, returning an overview of all available functions (#120).cron-listcolumn header is nowJob IDinstead ofID, matching thejob_idparameter oncron-delete(#118).- Breaking:
file_ops-editfirst parameter renamed fromfile_pathtopathfor consistency with every otherfile_ops-*method and thereader-*family (#119). Callers usingfile_path=by keyword must switch topath=; positional usage is unaffected. - Vendor
httpclient0.4.2 and simplify SearXNG POST internals. - Rebuilt and pushed
oaklight/toolregistry-hub-server:0.8.3andlatest.
Removed¶
FileOps.validate_path()(#113). The helper only screened for empty strings and a few shell-glob characters but its name implied real path validation, which misled MCP/LLM callers into treating nonexistent paths as valid. Usefs/path_info-infofor actual path checks.
[0.8.2] - 2026-05-28¶
Changed¶
- Apply
tool_metadataconfig overrides when building the hub registry. - Support method-level tag and defer overrides from
_TOOL_METADATA. - Bump server extras to require
toolregistry-server>=0.3.2. - Fix package README metadata path to use
README_en.md. - Switch the complexipy pre-commit hook to the official
complexipy-pre-commithook with explicit file filtering.
[0.8.1] - 2026-05-19¶
Added¶
--profile {remote,local}CLI flag for deployment context filtering.remotedisables filesystem/shell/cron tools (they access the server's own filesystem, not the user's machine);localkeeps only those local-machine tools and disables network/compute tools. Default: no filter.- Default
tools.yamlmanifest packaged with the hub for config-driven deployments.
Changed¶
- Converged server layer to upstream APIs (resolves #109): deleted hub-specific
tool_config.py(~355 lines) and its tests, replaced bytoolregistry.config.{load_config, PythonSource, ToolConfig}from core. Hub now re-usestoolregistry-server'srun_openapi_server(registry=, profile=)andrun_mcp_server(registry=, profile=)directly for profile filtering. _DEFAULT_TOOLSinregistry.pymigrated tolist[PythonSource]; post-register hook wired viaToolRegistry.add_post_register_hook().- Config auto-discovery checks
TOOLS_CONFIGenv var, thentools.jsonc/tools.yaml/tools.ymlin the current directory. - Bumped
toolregistry-serverrequirement to>=0.3.1across server extras. - Renamed README files to uppercase names used by package metadata and repository conventions.
Fixed¶
- Use
Callable[..., None]for_register_python_source_fnto satisfy type checking. - Wait for upstream PyPI availability before installing upstream releases in CI.
Dependencies¶
- Update vendored
httpclientmodule from 0.3.1 to 0.4.1 (zerodep)
[0.8.0] - 2026-04-06¶
New Features¶
-
Tool discovery with progressive disclosure
- Call
registry.enable_tool_discovery()to register adiscover_toolstool for BM25F search across all registered tools - Less-used tools (FileReader, FileSearch, PathInfo, BashTool, CronTool, TodoList, UnitConverter) marked as deferred - discoverable via
discover_toolsbut excluded from initial schema for smart clients - Add
--tool-discovery / --no-tool-discoveryCLI flag (default: enabled)
- Call
-
Think-augmented function calling
- Inject a
thoughtproperty into tool schemas for chain-of-thought reasoning (arXiv:2601.18282) - Built-in dedup prevents double injection when both server and harness enable it
- Add
--think-augment / --no-think-augmentCLI flag (default: enabled)
- Inject a
-
ToolTag metadata for all registered tools
- Assign
ToolTaglabels (READ_ONLY,DESTRUCTIVE,NETWORK,FILE_SYSTEM,PRIVILEGED) to every default tool based on its behavior - Tags are available via
tool.metadata.tagsfor filtering and display
- Assign
-
Fetch: Jina API key support with multi-key rotation
Fetchclass now accepts optionalapi_keysparameter for Jina Reader authentication- Falls back to
JINA_API_KEYenvironment variable (comma-separated for multiple keys) - Round-robin key rotation with automatic failure tracking (HTTP 401/403 → 1h cooldown, HTTP 429 → 5min cooldown)
-
Fetch: User-specified extraction engine
- Add
engineparameter to_extract():"auto"(default fallback chain),"markdown","readability","soup","jina" - Direct engine mode skips fallback chain - only the specified engine is tried
- Add
-
Fetch: Replace BS4 with readability + soup extraction pipeline (#87, #83)
- Replace simplistic BeautifulSoup CSS selector extraction with multi-strategy pipeline: readability (Mozilla Readability.js port, intelligent article scoring) → soup (structural CSS fallback)
- HTML fetched once and shared across both local strategies; readability preferred unless soup extracts >2x more content
- Vendor readability and soup modules from zerodep into
_vendor/with nested layout
-
Fetch: Content-Type detection for non-HTML responses (#93, #92)
- Rename
_fetch_html→_fetch_rawreturning(body, content_type)tuple - Short-circuit non-HTML content types (JSON, plain text, CSV, Markdown, XML, YAML) before the HTML extraction pipeline
- Prevents mangling of structured data that was previously run through readability/soup extraction
- Rename
-
Fetch: SPA content quality detection (#96, #94)
- Add text structure analysis to
_is_content_sufficient()to detect navigation-only extractions - Heuristic inspired by jusText: if >70% of lines are short (<30 chars) and fewer than 2 paragraph-length lines (>80 chars) exist, content is rejected as navigation garbage
- Conservative: only triggers when text has >5 lines, so short valid content is unaffected
- Add text structure analysis to
-
WebSearch: Unified entry point with dynamic engine selection
- New
WebSearchclass registered atweb/websearchnamespace; the 6 individual provider tools (web/brave_search,web/tavily_search, etc.) are now deferred and discoverable viadiscover_tools search(query, engine="auto", fallback=False, ...)-engine="auto"tries configured providers in priority order; specific engines fail loudly when their key is missing, or fall through to auto whenfallback=True- Configurable priority via
WEBSEARCH_PRIORITYenvironment variable (comma-separated names); default order is paid-providers-first - Per-instance dynamic narrowing of the
engineLiteralannotation: at construction time, the JSON schema seen by LLM clients only includes engines whose API keys are actually configured on this server list_engines()helper for runtime introspection of available providers
- New
Code Cleanup¶
- Remove dead code from
fetch.py:_get_lynx_useragent(),HEADERS_LYNX,_remove_emojis(), unusedrandomimport - Move Lynx-based user-agent generation to
_legacyfor future Chrome CDP reference - Convert
Fetchfrom static utility to instance class for API key state management
Deprecations¶
- FileSystem removed from default server registry
FileSystemclass is no longer registered in server mode; replaced by PathInfo, FileSearch, and FileReader- The class itself is kept for library backward compatibility and still emits
DeprecationWarning
Internal Changes¶
-
Zero external runtime dependencies (#98)
- Replace
httpxwith vendoredhttpclientfrom zerodep - sync+async HTTP client using only stdlib - Replace
ua-generatorwith vendoreduseragentmodule from zerodep - Replace
pydanticwith plaindataclassesinTodoList - Re-vendor all modules via
zerodepCLI for consistent metadata and versioning - Result:
dependencies = []- the base package has zero PyPI runtime dependencies
- Replace
-
Remove
websearch_legacymodule- Legacy Bing and Google HTML-scraping search providers archived to
archive/websearch-legacybranch - Associated
filter.pyblocklist module also removed - All search functionality now served by API-based providers in
websearch/
- Legacy Bing and Google HTML-scraping search providers archived to
-
Add cognitive complexity analysis with complexipy (#103)
- Add
complexipy>=5.2.0to dev dependencies with threshold 15, excluding_vendor/ - Refactor 10 functions exceeding the threshold:
build_registry(31→7),load_tool_config(24→8),compare_versions(21→1)SerperSearch::_search_impl(21→10),BraveSearch::_search_impl(20→9),_extract(20→11)CronTool::_make_callback(19→9),FileSearch::_build_tree(17→14)BrightDataSearch::_search_impl(17→14),TavilySearch::_search_impl(17→14)
- Extract shared
_handle_http_errorintoBaseSearchfor websearch API key failover
- Add
-
Consolidate all zerodep vendored modules (structlog, scheduler, readability, soup) into
_vendor/with nested layout (#87) - Remove
beautifulsoup4external dependency; migratewebsearch_legacy(bing, google) to zerodep soup (#87) - Exclude
_vendor/from ruff UP035 lint rule and ty type checking - Refactor CLI to always build registry with CLI flags instead of only when
--configis set - Fix deprecated
with_namespace=parameter inregister_from_class()calls (now usesnamespace=)
Fixes¶
- SearXNG: Support optional X-API-Key header for protected instances (#85)
- Add optional
api_keyparameter toSearXNGSearch, with fallback toSEARXNG_API_KEYenvironment variable - When set, sends
X-API-Keyheader with JSON API requests; fully backwards compatible
- Add optional
[0.8.0] - 2026-04-06¶
Breaking Changes¶
- FileOps: Replace diff-based editing with exact string replacement (#70, #62)
- Removed
replace_by_diff()andreplace_by_git()methods - Added
edit(file_path, old_string, new_string)with exact string matching - Supports
replace_allfor bulk replacement andstart_linefor disambiguation when multiple matches exist - Preserves file encoding (UTF-8/UTF-8-sig/UTF-16) and line endings (CRLF/LF)
- Returns unified diff of changes
- Removed
New Features¶
-
BashTool: Shell command execution with safety validation (#77, #66)
- Execute shell commands via
subprocess.runwith configurable timeout and working directory - Built-in deny list blocks dangerous patterns (rm -rf, sudo, fork bombs, pipe-to-shell, git force push, etc.)
- Deny list based on security survey of 6 AI coding CLI tools
- Lazy upstream
ToolMetadataintegration for future permission system support - stdout/stderr truncation at 64KB to prevent memory exhaustion
- Execute shell commands via
-
FileReader: Multi-format file reading (#75, #65, #79)
read()- text files with line numbers and pagination (10MB cap, 2000 lines default)read_notebook()- Jupyter notebooks with cell types and outputs (stdlib only)read_pdf()- PDF text extraction via pypdf or pdfplumber (optional dependency)read_image()- image files as multimodal content blocks ([TextBlock, ImageBlock]) with adaptive downsampling via Pillow (#79, #74)- Supports
.png,.jpg,.jpeg,.gif,.webpformats - Auto-downsamples images exceeding the base64 size budget (default 5 MB) with format-specific quality floors
- Add
reader_image = ["Pillow>=10.0.0"]optional dependency group
-
FileSearch: File discovery tools (#72)
glob()- find files by pattern, sorted by modification time (1000 results cap)grep()- regex content search with file filtering (200 results cap)tree()- directory tree display with depth control (2000 entries cap)
-
PathInfo: Unified metadata query (#71)
- Single
info()call returns existence, type, size, modification time, and permissions - Replaces five separate
FileSystemmethods - Recursive size calculation for directories
- Single
-
CronTool: Scheduled prompt execution (#69, 4864ca7)
- Cron expression scheduling with standard 5-field format
- Recurring and one-shot modes with
on_triggercallback for agent runtime integration - 7-day TTL auto-expiry for recurring jobs
- Optional durable persistence via JSON file
- Vendored zerodep/scheduler (v0.3.0) as internal dependency
-
API key failover with retry on auth/rate-limit errors (#53, 29bdd13)
- Thread-safe failed key tracking in
APIKeyParserwith TTL-based auto-recovery (1h for 401/403, 5min for 429) - Fix double key consumption bug: replace
_headersproperty with_build_headers(api_key)method - Retry loop in all API-key-based websearch providers (Brave, Tavily, Serper, Scrapeless, BrightData) that automatically tries the next valid key on 401/403/429 errors
- Thread-safe failed key tracking in
Deprecations¶
-
FileSystem class deprecated (#76)
- Replaced by PathInfo (metadata), FileSearch (discovery), and FileReader (reading)
- All methods emit
DeprecationWarningwith migration guidance - Will be removed in a future major release
-
FileOps legacy methods deprecated (#76)
read_file()→ useFileReader.read()write_file()→ useFileOps.edit()for modifications
Internal¶
- Replace loguru with vendored zerodep/structlog (#80, 7e17fb4)
- Remove
loguruexternal dependency, replaced with vendored zero-dependency structlog module - All logging now uses
get_logger()from internal_structlogmodule
- Remove
Fixes¶
- ty type-check error in tool_config.py (5890365)
- Fixed dict type narrowing issue between ty 0.0.23 and 0.0.27
Build¶
- Bump
toolregistry-serverminimum to>=0.1.2for MCP parameter validation fix
CI¶
- Enhanced upstream compatibility tests to cover
toolregistry-server - Support multiple upstream packages in compat check (d8d25e4)
- Add version validation and issues permission to upstream-compat workflow (f590cc0)
[0.7.0] - 2026-03-18¶
Breaking Changes¶
-
Server Code Migrated to
toolregistry-server(#56, #57)- Server-related functionality (OpenAPI adapter, MCP adapter, CLI server commands) has been moved to the standalone
toolregistry-serverpackage - Users who relied on server features should install
toolregistry-serverseparately
- Server-related functionality (OpenAPI adapter, MCP adapter, CLI server commands) has been moved to the standalone
-
Minimum Python Version Upgraded to 3.10 (#54)
- Python 3.8 and 3.9 no longer supported
- Aligns with Python 3.9 EOL and MCP SDK requirements
-
is_configuredRenamed to_is_configured(#58)- The method is now private and no longer exposed as a tool endpoint
New Features¶
-
Admin Panel Support (a88ab25)
- Add
--admin-portflag to enable admin panel for server management - Requires
toolregistry-server>=0.1.1
- Add
-
Serper Search Provider (2305551)
- Add Serper (serper.dev) search provider for Google search results
- 2,500 free queries per month
- Supports country, language, and location targeting
-
.envFile Loading Support (#59)- Support for loading environment variables from
.envfiles - Added
--env-fileand--no-envCLI options
- Support for loading environment variables from
Improvements¶
-
Dependency Updates
- Bump
toolregistryminimum to>=0.6.0 - Bump
toolregistry-serverminimum to>=0.1.1
- Bump
-
CI/CD
Refactoring¶
-
Modernize Type Annotations to Python 3.10+
- Replaced legacy typing imports with modern Python 3.10+ syntax
-
MCP Server FastMCP Rewrite
- Refactored MCP server implementation using FastMCP (official MCP SDK high-level API)
- Fixed streamable-http transport timing issues
- Fixed ASGI duplicate response errors
Documentation¶
-
Brave Search Pricing Update
- Document Brave Search API free plan removal (Feb 2026)
- Update to credit-based pricing: $5/1k requests with $5 free monthly credits (~1,000 queries)
-
Web Search Docs Refresh
- Add Serper search documentation (EN/ZH)
- Update free tier summary tables
- Remove outdated "(Recommended)" labels
[0.6.0] - 2026-03-10¶
New Features¶
-
Startup Tool Configuration via JSONC (#37, #38)
- Add JSONC (JSON with Comments) configuration file support for declarative tool loading at server startup
- New
tool_config.pymodule with JSONC parser and tool configuration loader - Add
--tools-configCLI option to specify configuration file path - Provide
tools.jsonc.exampleas a documented example configuration - Graceful fallback: loads all tools if no config file is specified
-
Auto-Route Generation from ToolRegistry (#31, #36)
- Add
autoroute.pymodule for automatic FastAPI route generation from registered tools in ToolRegistry - Introspect tools registered in ToolRegistry and automatically generate endpoint handlers
- Eliminate the need for hand-written route boilerplate
- Integrate auto-route into server startup with fallback to manual routes
- Add comprehensive tests for autoroute functionality
- Add
-
Tool Environment Requirements and Central Registry (#30, #35)
- Add
@requires_envdecorator to declare required environment variables on tool classes - Add
Configurableprotocol withis_configured()for instance-state readiness checks (structural subtyping) - Add
build_registry()/get_registry()central registry that auto-disables unconfigured tools - Defer
APIKeyParserandSearXNGSearchvalidation to call time, allowing graceful initialization without env vars
- Add
-
Nested Namespaces for WebSearch Tools (#39, #40)
- Support nested namespaces like
web/brave_search, producing URLs like/tools/web/brave_search/search - Hide internal methods (
is_configured) from API endpoints via_HIDDEN_METHODS
- Support nested namespaces like
Bug Fixes¶
-
Jina Reader Multi-Engine Retry (#43)
- Separate httpx transport timeout from Jina
X-Timeout(add 10s buffer) to prevent race conditions - Add
X-Wait-For-Selectorheader with common content selectors for dynamic content - Add multi-engine retry: try
browserfirst, fall back tocf-browser-renderingengine for JS-heavy websites - Extract
_jina_reader_request()as low-level single-request function
- Separate httpx transport timeout from Jina
-
Dockerfile Missing Server Dependencies
- Local wheel install path now uses
[server]extra instead of hardcoded dependency list - Ensures all dependencies are managed by
pyproject.toml, preventingModuleNotFoundErrorin Docker containers
- Local wheel install path now uses
Refactoring¶
-
Remove Legacy Hand-Written Route Files (#39, #40)
- Remove
calculator.py,datetime_tools.py,fetch.py,think.py,todo_list.py,unit_converter.py, androutes/websearch/directory - Replace with auto-generated routes from ToolRegistry
- Simplify
routes/__init__.pyto export onlyversion_router server_core.pyuses auto-generated routes alongsideversion_router
- Remove
-
Remove BingSearch (#34)
- Remove deprecated
BingSearchclass, server route, and related tests - Rewrite and modernize websearch test suite for remaining engines
- Remove deprecated
-
Restructure Server Optional Dependencies (#29, #33)
- Update
server_openapiandserver_mcpextras to requiretoolregistry>=0.5.0 - Refactor
serverextra to use self-referencing composition
- Update
-
Replace pyright with ty for type checking
APIKeyParser.__init__no longer raises on missing keys; defers validation to call time
[0.5.6] - 2026-03-05¶
New Features¶
- Web Fetch Improvements
- Add Cloudflare content negotiation strategy for markdown extraction, increasing default timeout
- Add strategy tracking logs to
_extract()for better observability and debugging - Improve Jina Reader fallback: fix headers (remove placeholder selectors, add
X-Engine: browser,X-Timeout), use POST with JSON body and structured JSON response parsing - Add
_is_content_sufficient()to evaluate BeautifulSoup content quality (minimum length threshold + SPA shell indicator detection) - Improve
_extract()fallback logic: low-quality BS4 content triggers Jina Reader; if Jina also fails, fall back to BS4 result - Enhance logging with strategy reasons and content quality metrics
- Add comprehensive unit tests (43 test cases)
[0.5.5] - 2026-01-31¶
Refactoring¶
- Think Tool Enhancement
- Unify reason and think endpoints into single think endpoint
- Reorder parameters and simplify thinking modes
Maintenance¶
- Docker Improvements
- Add
REGISTRY_MIRRORbuild argument to Dockerfile for custom registry support - Add
references/directory to.dockerignoreto reduce image size
- Add
[0.5.4.post1] - 2026-01-13¶
Bug Fixes¶
- Version Endpoint Visibility
- Hide version endpoints (
/version/and/version/check) from OpenAPI documentation usinginclude_in_schema=False - Version endpoints remain fully functional and accessible via HTTP requests
- Prevents version endpoints from being exposed as LLM tools in MCP mode
- Hide version endpoints (
[0.5.4] - 2026-01-13¶
Refactoring¶
- Unified Cognitive Tools Architecture
- Consolidate reason and think endpoints into single think endpoint, combining structured reasoning and exploratory thinking
- Merge thinking modes: analysis, hypothesis, planning, verification, correction (structured) with brainstorming, mental_simulation, perspective_taking, intuition (exploratory)
- Simplify API surface by removing separate /reason endpoint and updating request models
- Unify parameter naming: 'thought' → 'thought_process', 'thinking_type' → 'thinking_mode'
- Refactor test suite with comprehensive coverage of all thinking modes and parameter combinations
- Update documentation to reflect "recall + think" dual-tool cognitive architecture
New Features¶
-
PyPI Version Check & Update Notifications
- Add comprehensive PyPI version checking system, inspired by argo-proxy implementation
- New
version_check.pymodule with async PyPI API calls and intelligent version comparison - Implement pre-release version support (alpha, beta, rc) and event loop safety handling
- Add
/version/and/version/checkAPI endpoints returning version info and update status - CLI adds
--versionparameter to display current version and check for updates - Enhanced startup banner with automatic version info and update notifications
- Use standard library for version comparison without additional dependencies
- Include complete synchronous test suite (10 tests)
-
ASCII Art Banner
- Add new banner.py module with ASCII art banner
- Implement centered alignment and consistent border styling (80-char width)
- Display banner on CLI startup with show_banner=False parameter to disable
Documentation¶
-
Time-Sensitive Query Guidance for Web Search
- Add IMPORTANT note in all websearch class docstrings
- Emphasize LLMs have no inherent sense of time and training data may be outdated
- Require checking current time with datetime tools for queries like "recent news"
- Applied to all search provider classes
-
DateTime Tools Documentation Enhancement
- Add detailed descriptions for now() and convert_timezone() methods
- Expand parameter documentation with timezone format examples
- Route descriptions directly reference method docstrings for better consistency
Maintenance¶
- Version Attribute Fix
- Update pyproject.toml to use version attribute instead of version
- Add version variable in init.py following Python version convention
- Maintain backward compatibility by keeping version variable
[0.5.3] - 2025-12-13¶
Refactoring¶
-
Multi-API Key Management System
- Consolidate scattered API key implementations into centralized APIKeyParser utility
- Replace individual API key management across websearch engines with unified system
- Implement consistent API key rotation and error handling across all search providers
- Refactor all websearch engines (Brave, Brightdata, Scrapeless, Tavily) to use centralized API key management
- Improve search engine reliability and performance
- Add rate limiting support to API key parser
-
Utils Module Structure
- Migrate utils module to package structure for better organization
- Add fn_namespace.py module for function namespace utilities
- Improve module imports and dependencies
- Simplify version extraction from pyproject.toml
- Update build configuration for better reproducibility
-
Version Management System
- Configure pyproject.toml to use dynamic version loading from toolregistry_hub.version
- Remove hardcoded version from pyproject.toml, use setuptools dynamic version attribute
- Centralize version management with single source of truth in
__init__.py - Improve build process with setuptools dynamic version support
Bug Fixes¶
-
Docker Build Process
- Fix Dockerfile package installation with server extras (fastapi, uvicorn, fastmcp)
- Improve Makefile build logic for better package installation handling
- Remove redundant docker/requirements.txt file
- Enhance package installation logic for local wheel, specific version, and latest from PyPI
-
Type Annotations & Compatibility
- Resolve type annotation and parameter naming issues for pyright compatibility
- Fix type hints in server_core.py and websearch modules
- Improve test compatibility and type safety
Documentation¶
- Docker Documentation
- Add comprehensive Docker documentation and migration guide
- Add Docker README files in both English and Chinese
- Provide OpenWebUI tool server migration documentation
[0.5.2] - 2025-12-12¶
New Features¶
-
Unit Converter API Routes
- Add unit converter API routes
- Refactor unit converter with base class and utility methods
- Update unit converter tests
-
Web Search Enhancements
- Add Scrapeless DeepSERP API (Google SERP) integration
- Add Bright Data search (Google SERP) integration
- Implement universal Google search results parser
- Add Bright Data engines test for Bing and Yandex
- Add environment variable support for Bing search proxy
Deprecations¶
- Bing Search: Mark BingSearch as deprecated due to bot detection issues
Documentation¶
- Update badge styles in README
- Add DeepWiki badge to documentation
- Update project description and README file
- Add references directory to gitignore
[0.5.1] - 2025-12-05¶
Security & Authentication¶
- MCP Server Authentication (#15)
- Add Bearer Token authentication support for MCP server
- Implement
DebugTokenVerifierfor MCP authentication - Support authenticated and open modes based on token configuration
- Add comprehensive authentication event logging
- Move token verification to FastAPI global dependencies
- Refactor authentication architecture, decoupling routes and authentication concerns
Task Management¶
- Todo List Tool Enhancements (#15)
- Add Todo List tool with flexible input format support
- Support both dictionary format and simple string format
"[id] content (status)" - Implement comprehensive input validation with detailed error messages
- Enhance status options with "pending" status
- Support multiple output formats: 'simple' (no output), 'markdown', and 'ascii'
- Add Markdown table generation API endpoint
- Improve documentation and type annotations
Server¶
- Architecture Refactoring
- Create
server_core.pymodule providing base FastAPI application - Remove authentication dependencies from all routes
- Enable creation of both authenticated and non-authenticated server variants
- Improve router discovery logging logic
- Optimize server architecture for better maintainability
- Create
Date and Time¶
- API Enhancements
- Add
TimeNowRequestmodel fortime_nowendpoint - Use structured request body instead of query parameters
- Maintain backward compatibility with existing timezone name functionality
- Improve API documentation structure
- Add
Documentation¶
- Project Documentation
- Update project description and README files
- Change README reference from
README.mdtoreadme_en.md - Update PyPI and GitHub badge links
- Improve documentation visual consistency
[0.5.0] - 2025-11-11¶
Security & Authentication¶
- Multi Bearer Token Authentication (#11)
- Support multiple Bearer tokens via environment variables or file configuration
- Support
API_BEARER_TOKENenvironment variable (comma-separated) - Support
API_BEARER_TOKENS_FILEfile configuration (one token per line) - Add token caching mechanism for improved efficiency
- Enhanced authentication logging and debugging features
- New standalone multi-token authentication test suite
Server (#9)¶
- REST API Server
- New
toolregistry-serverCLI command-line tool - Support for OpenAPI and MCP server modes
- Individual REST API endpoints for each tool:
- Calculator API (
/calculator) - DateTime API (
/datetime) - Web Fetch API (
/fetch) - Think Tool API (
/think) - Web Search API (
/websearch)
- Calculator API (
- Automatic router discovery and registration mechanism
- Recursive router discovery for nested modules
- New
Docker¶
- Complete Containerized Deployment Solution
- Add Dockerfile for building container images
- Provide
.env.sampleenvironment variable reference - Add
requirements.txtfor dependency installation - Provide
compose.yamlandcompose.dev.yamlorchestration configs - Add automated build and push Makefile
- Optimize
.dockerignoreto reduce image size
Web Search (#8)¶
-
New Search Engine Support
- Add Brave Search API integration
- Add Tavily Search API integration
- Add SearXNG search engine support
- Refactor Bing search with modern implementation
-
Unified Search Architecture
- Introduce
BaseSearchabstract base class - Standardize search API method signatures
- Use
SearchResultdataclass for type safety - Unified header generation and content fetching logic
- Introduce
-
Advanced Search Features
- Multi API key support (Brave and Tavily)
- Pagination support for up to 180 results
- Flexible search parameters and filtering options
- Improved result parsing and error handling
-
User Agent Optimization
- Replace
fake-useragentwithua-generator - Dynamic user agent generation for better anti-bot evasion
- Enhanced browser fingerprinting realism
- Replace
-
Module Restructuring
- Move modern search engines to
websearch/directory - Move legacy search implementations to
websearch_legacy/directory - Clean up outdated Google search modules
- Move modern search engines to
Timezone Enhancements (#5)¶
-
Timezone Support
DateTime.now()supports timezone parameter specification- New
convert_timezone()timezone conversion functionality - Support IANA timezone names (e.g., "Asia/Shanghai")
- Support UTC/GMT offset formats (e.g., "UTC+5:30", "GMT-3")
- Handle fractional hour offsets (e.g., Nepal UTC+5:45)
-
Python Compatibility
- Support Python 3.8 via
backports.zoneinfo - Unified timezone parsing logic
- Improved error handling and exception messages
- Support Python 3.8 via
Documentation (#10)¶
- Documentation Structure Optimization
- Refactor documentation structure for improved readability
- Add multi-language documentation support
- Detailed Docker deployment guides
- Web search engine usage documentation
- API endpoint and configuration instructions
Testing (#12)¶
- Enhanced Test Coverage
- Add 0.4.16a0 version testing
- Multi-token authentication test suite
- Timezone functionality unit tests
- Web search engine testing
Refactoring¶
- think_tool: Simplify think method return type
- Change return type from
Dict[str, str]toNone - Remove unused typing import for Dict
- Remove thought logging return value since it's not used
- Change return type from
Documentation¶
- Documentation hosting: Migrate documentation to ReadTheDocs hosting
[0.4.15] - 2025-08-11¶
New Features¶
- DateTime Tool: Add DateTime utility for current time retrieval
- ThinkTool: Add reasoning and brainstorming tool providing cognitive processing space for AI tool integration
Documentation¶
- Enhance tool descriptions and usage examples
- Update independence notice and package context
- Improve README documentation structure
Maintenance¶
- Bump version to 0.4.15
- Update and optimize dependencies
[0.4.14] - First Official Release¶
Initial Release¶
- Basic tool collection
- Core functionality implementation
- Basic documentation structure
- Test framework establishment
Version Notes¶
Semantic Versioning¶
This project follows Semantic Versioning specification:
- Major version: Incompatible API changes
- Minor version: Backward-compatible functionality additions
- Patch version: Backward-compatible bug fixes
Change Type Legend¶
- New Features - New functionality or features
- Refactoring - Code refactoring without functional changes
- Bug Fixes - Error corrections
- Documentation - Documentation updates
- Security - Security-related improvements
- Server - Server functionality
- Docker - Containerization related
- Search - Search functionality related
- Timezone - Timezone functionality related
- Testing - Testing-related improvements
- Maintenance - Maintenance updates
Getting Updates¶
To get the latest version, use:
Feedback and Suggestions¶
If you find any issues or have improvement suggestions, please submit an Issue in our GitHub repository.