Sourcing python-remove-tests-dir-hook Sourcing python-catch-conflicts-hook.sh Sourcing python-remove-bin-bytecode-hook.sh Sourcing pypa-build-hook Using pypaBuildPhase Sourcing python-runtime-deps-check-hook Using pythonRuntimeDepsCheckHook Sourcing pypa-install-hook Using pypaInstallPhase Sourcing python-imports-check-hook.sh Using pythonImportsCheckPhase Sourcing python-namespaces-hook Sourcing python-catch-conflicts-hook.sh Sourcing pytest-check-hook Using pytestCheckPhase Running phase: unpackPhase unpacking source archive /nix/store/gyc4j4ir5ssmqclfbg1rn4p62a9dd9a3-source source root is source setting SOURCE_DATE_EPOCH to timestamp 315619200 of file "source/tests/test_watch.py" Running phase: patchPhase Running phase: updateAutotoolsGnuConfigScriptsPhase Running phase: configurePhase no configure script, doing nothing Running phase: buildPhase Executing pypaBuildPhase Creating a wheel... pypa build flags: --no-isolation --outdir dist/ --wheel * Getting build dependencies for wheel... /nix/store/gyficbimx12q5975523ps3kjzz8ys4pq-python3.14-setuptools-83.0.0/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:82: SetuptoolsDeprecationWarning: `project.license` as a TOML table is deprecated !! ******************************************************************************** Please use a simple string containing a SPDX expression for `project.license`. You can also use `project.license-files`. (Both options available on setuptools>=77.0.0). By 2027-Feb-18, you need to update your project and remove deprecated calls or your builds will no longer be supported. See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! corresp(dist, value, root_dir) /nix/store/gyficbimx12q5975523ps3kjzz8ys4pq-python3.14-setuptools-83.0.0/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: Apache Software License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /nix/store/gyficbimx12q5975523ps3kjzz8ys4pq-python3.14-setuptools-83.0.0/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: Apache Software License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() running egg_info creating src/mcptoon.egg-info writing src/mcptoon.egg-info/PKG-INFO writing dependency_links to src/mcptoon.egg-info/dependency_links.txt writing entry points to src/mcptoon.egg-info/entry_points.txt writing requirements to src/mcptoon.egg-info/requires.txt writing top-level names to src/mcptoon.egg-info/top_level.txt writing manifest file 'src/mcptoon.egg-info/SOURCES.txt' reading manifest file 'src/mcptoon.egg-info/SOURCES.txt' adding license file 'LICENSE' adding license file 'NOTICE' writing manifest file 'src/mcptoon.egg-info/SOURCES.txt' * Building wheel... /nix/store/gyficbimx12q5975523ps3kjzz8ys4pq-python3.14-setuptools-83.0.0/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:82: SetuptoolsDeprecationWarning: `project.license` as a TOML table is deprecated !! ******************************************************************************** Please use a simple string containing a SPDX expression for `project.license`. You can also use `project.license-files`. (Both options available on setuptools>=77.0.0). By 2027-Feb-18, you need to update your project and remove deprecated calls or your builds will no longer be supported. See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! corresp(dist, value, root_dir) /nix/store/gyficbimx12q5975523ps3kjzz8ys4pq-python3.14-setuptools-83.0.0/lib/python3.14/site-packages/setuptools/config/_apply_pyprojecttoml.py:61: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: Apache Software License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! dist._finalize_license_expression() /nix/store/gyficbimx12q5975523ps3kjzz8ys4pq-python3.14-setuptools-83.0.0/lib/python3.14/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated. !! ******************************************************************************** Please consider removing the following classifiers in favor of a SPDX license expression: License :: OSI Approved :: Apache Software License See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details. ******************************************************************************** !! self._finalize_license_expression() running bdist_wheel running build running build_py creating build/lib/mcptoon copying src/mcptoon/packs.py -> build/lib/mcptoon copying src/mcptoon/serve.py -> build/lib/mcptoon copying src/mcptoon/usage.py -> build/lib/mcptoon copying src/mcptoon/cli.py -> build/lib/mcptoon copying src/mcptoon/client.py -> build/lib/mcptoon copying src/mcptoon/__init__.py -> build/lib/mcptoon copying src/mcptoon/skills.py -> build/lib/mcptoon copying src/mcptoon/plugin.py -> build/lib/mcptoon copying src/mcptoon/output.py -> build/lib/mcptoon copying src/mcptoon/errors.py -> build/lib/mcptoon copying src/mcptoon/installer.py -> build/lib/mcptoon copying src/mcptoon/sync.py -> build/lib/mcptoon copying src/mcptoon/bench.py -> build/lib/mcptoon copying src/mcptoon/health.py -> build/lib/mcptoon copying src/mcptoon/schema_simplifier.py -> build/lib/mcptoon copying src/mcptoon/watch.py -> build/lib/mcptoon copying src/mcptoon/discover.py -> build/lib/mcptoon copying src/mcptoon/toon_vendored.py -> build/lib/mcptoon copying src/mcptoon/native_tools.py -> build/lib/mcptoon copying src/mcptoon/cache.py -> build/lib/mcptoon copying src/mcptoon/footer.py -> build/lib/mcptoon copying src/mcptoon/__main__.py -> build/lib/mcptoon copying src/mcptoon/manifest.py -> build/lib/mcptoon copying src/mcptoon/router.py -> build/lib/mcptoon copying src/mcptoon/demo_server.py -> build/lib/mcptoon copying src/mcptoon/demo.py -> build/lib/mcptoon copying src/mcptoon/welcome.py -> build/lib/mcptoon copying src/mcptoon/config.py -> build/lib/mcptoon running egg_info writing src/mcptoon.egg-info/PKG-INFO writing dependency_links to src/mcptoon.egg-info/dependency_links.txt writing entry points to src/mcptoon.egg-info/entry_points.txt writing requirements to src/mcptoon.egg-info/requires.txt writing top-level names to src/mcptoon.egg-info/top_level.txt reading manifest file 'src/mcptoon.egg-info/SOURCES.txt' adding license file 'LICENSE' adding license file 'NOTICE' writing manifest file 'src/mcptoon.egg-info/SOURCES.txt' copying src/mcptoon/packs.json -> build/lib/mcptoon installing to build/bdist.linux-x86_64/wheel running install running install_lib creating build/bdist.linux-x86_64/wheel creating build/bdist.linux-x86_64/wheel/mcptoon copying build/lib/mcptoon/errors.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/output.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/plugin.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/demo.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/manifest.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/packs.json -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/client.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/__main__.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/toon_vendored.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/watch.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/sync.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/bench.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/skills.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/cache.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/discover.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/installer.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/router.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/cli.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/config.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/schema_simplifier.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/demo_server.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/welcome.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/__init__.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/native_tools.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/serve.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/packs.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/footer.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/usage.py -> build/bdist.linux-x86_64/wheel/./mcptoon copying build/lib/mcptoon/health.py -> build/bdist.linux-x86_64/wheel/./mcptoon running install_egg_info Copying src/mcptoon.egg-info to build/bdist.linux-x86_64/wheel/./mcptoon-0.7.22-py3.14.egg-info running install_scripts creating build/bdist.linux-x86_64/wheel/mcptoon-0.7.22.dist-info/WHEEL creating '/build/source/dist/.tmp-dyf9s626/mcptoon-0.7.22-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it adding 'mcptoon/__init__.py' adding 'mcptoon/__main__.py' adding 'mcptoon/bench.py' adding 'mcptoon/cache.py' adding 'mcptoon/cli.py' adding 'mcptoon/client.py' adding 'mcptoon/config.py' adding 'mcptoon/demo.py' adding 'mcptoon/demo_server.py' adding 'mcptoon/discover.py' adding 'mcptoon/errors.py' adding 'mcptoon/footer.py' adding 'mcptoon/health.py' adding 'mcptoon/installer.py' adding 'mcptoon/manifest.py' adding 'mcptoon/native_tools.py' adding 'mcptoon/output.py' adding 'mcptoon/packs.json' adding 'mcptoon/packs.py' adding 'mcptoon/plugin.py' adding 'mcptoon/router.py' adding 'mcptoon/schema_simplifier.py' adding 'mcptoon/serve.py' adding 'mcptoon/skills.py' adding 'mcptoon/sync.py' adding 'mcptoon/toon_vendored.py' adding 'mcptoon/usage.py' adding 'mcptoon/watch.py' adding 'mcptoon/welcome.py' adding 'mcptoon-0.7.22.dist-info/licenses/LICENSE' adding 'mcptoon-0.7.22.dist-info/licenses/NOTICE' adding 'mcptoon-0.7.22.dist-info/METADATA' adding 'mcptoon-0.7.22.dist-info/WHEEL' adding 'mcptoon-0.7.22.dist-info/entry_points.txt' adding 'mcptoon-0.7.22.dist-info/top_level.txt' adding 'mcptoon-0.7.22.dist-info/RECORD' removing build/bdist.linux-x86_64/wheel Successfully built mcptoon-0.7.22-py3-none-any.whl Finished creating a wheel... Finished executing pypaBuildPhase Running phase: pythonRuntimeDepsCheckHook Executing pythonRuntimeDepsCheck Checking runtime dependencies for mcptoon-0.7.22-py3-none-any.whl Finished executing pythonRuntimeDepsCheck Running phase: installPhase Executing pypaInstallPhase Successfully installed mcptoon-0.7.22-py3-none-any.whl Finished executing pypaInstallPhase Running phase: pythonOutputDistPhase Executing pythonOutputDistPhase Finished executing pythonOutputDistPhase Running phase: fixupPhase shrinking RPATHs of ELF executables and libraries in /nix/store/5k7gb9kfh6l8cirhfbxmip87zjckzk5k-mcptoon-0.7.22 checking for references to /build/ in /nix/store/5k7gb9kfh6l8cirhfbxmip87zjckzk5k-mcptoon-0.7.22... patching script interpreter paths in /nix/store/5k7gb9kfh6l8cirhfbxmip87zjckzk5k-mcptoon-0.7.22 stripping (with command strip and flags -S -p) in /nix/store/5k7gb9kfh6l8cirhfbxmip87zjckzk5k-mcptoon-0.7.22/lib /nix/store/5k7gb9kfh6l8cirhfbxmip87zjckzk5k-mcptoon-0.7.22/bin shrinking RPATHs of ELF executables and libraries in /nix/store/bcbmr2dybsqljpsgwgcfnc6sp1bja6js-mcptoon-0.7.22-dist checking for references to /build/ in /nix/store/bcbmr2dybsqljpsgwgcfnc6sp1bja6js-mcptoon-0.7.22-dist... patching script interpreter paths in /nix/store/bcbmr2dybsqljpsgwgcfnc6sp1bja6js-mcptoon-0.7.22-dist Rewriting #!/nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/bin/python3.14 to #!/nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7 wrapping `/nix/store/5k7gb9kfh6l8cirhfbxmip87zjckzk5k-mcptoon-0.7.22/bin/mcptoon'... Executing pythonRemoveTestsDir Finished executing pythonRemoveTestsDir Running phase: installCheckPhase no Makefile or custom installCheckPhase, doing nothing Running phase: pythonCatchConflictsPhase Running phase: pythonRemoveBinBytecodePhase Running phase: pythonImportsCheckPhase Executing pythonImportsCheckPhase Check whether the following modules can be imported: mcptoon Running phase: pytestCheckPhase Executing pytestCheckPhase pytest flags: -m pytest ============================= test session starts ============================== platform linux -- Python 3.14.7, pytest-9.1.1, pluggy-1.6.0 rootdir: /build/source configfile: pyproject.toml testpaths: tests collected 1327 items tests/test_bench.py ............. [ 0%] tests/test_cache.py .... [ 1%] tests/test_calculator.py .......................... [ 3%] tests/test_claude_plugin_package.py ............. [ 4%] tests/test_cli_flags.py ........... [ 5%] tests/test_client.py .............................. [ 7%] tests/test_command_coverage.py ......... [ 7%] tests/test_completion.py ........ [ 8%] tests/test_config.py ......... [ 9%] tests/test_dead_server_diagnostics.py ... [ 9%] tests/test_demo.py ..................... [ 11%] tests/test_demo_dead_package.py ........ [ 11%] tests/test_demo_server.py .............................................. [ 15%] ..... [ 15%] tests/test_discover.py .................................... [ 18%] tests/test_doctor_star_hint.py ..... [ 18%] tests/test_envelope.py ........ [ 19%] tests/test_fallback_json.py ...... [ 19%] tests/test_footprint_claims.py ............ [ 20%] tests/test_gemini_manifest.py ...... [ 21%] tests/test_health.py ............. [ 22%] tests/test_help_shortcircuit.py ......... [ 22%] tests/test_http_user_agent.py ......... [ 23%] tests/test_installer_registry.py ............................ [ 25%] tests/test_lang.py .......................... [ 27%] tests/test_llms_txt.py ...... [ 27%] tests/test_native_tools.py ................................. [ 30%] tests/test_output.py ................................................... [ 34%] ........................................................................ [ 39%] ................ [ 40%] tests/test_plugin_install.py .......... [ 41%] tests/test_plugin_scan.py ............................... [ 43%] tests/test_policy_overrides.py ................ [ 45%] tests/test_presence.py .............................................. [ 48%] tests/test_readme_links.py ... [ 48%] tests/test_registry_sync.py ............ [ 49%] tests/test_reversible.py ............................................... [ 53%] ................. [ 54%] tests/test_router.py .............................................. [ 58%] tests/test_search.py ................................ [ 60%] tests/test_serve.py .................................................... [ 64%] FFF [ 64%] tests/test_serve_perf.py .......... [ 65%] tests/test_serve_prompts.py ........ [ 65%] tests/test_skill_packs.py ............... [ 67%] tests/test_skill_search.py .......... [ 67%] tests/test_skills.py ................................................... [ 71%] ........................................................................ [ 77%] .............. [ 78%] tests/test_stats_toggle.py ......... [ 78%] tests/test_stderr_pipe_deadlock.py .... [ 79%] tests/test_sync.py ................ [ 80%] tests/test_tier_claims_consistent.py .... [ 80%] tests/test_toml_config.py .......................... [ 82%] tests/test_toon_cross_validate.py ............................... [ 84%] tests/test_uninstall_end_to_end.py .......... [ 85%] tests/test_v02_features.py .................................... [ 88%] tests/test_v04_features.py ................ [ 89%] tests/test_v05_features.py ...................... [ 91%] tests/test_v072_delight.py .............s.. [ 92%] tests/test_v073_http_security.py .............................. [ 94%] tests/test_v074_stdio_timeout.py ............ [ 95%] tests/test_v076_stateless_serve.py ................... [ 97%] tests/test_v07_spec2026.py ..................... [ 98%] tests/test_watch.py .................. [100%] =================================== FAILURES =================================== _____________ TestInstallByName.test_search_registry_returns_list ______________ self = def test_search_registry_returns_list(self): """search_registry returns a list (even on network error).""" from mcptoon.installer import search_registry > result = search_registry("nonexistent_test_keyword_xyz123") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_serve.py:633: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ keyword = 'nonexistent_test_keyword_xyz123', limit = 10, strict = False def search_registry(keyword, limit=10, strict=False): """Search MCP registries for available servers. Queries both sources and merges them, best matches first — Smithery holds the hosted half, the official registry the installable-package half, and a query like "filesystem" has good answers in both. Returns: list: [{name, description, command, args, env, source, url}, ...] Raises: RegistryError: only when *every* source failed at the network level (DNS, TLS, timeout, 5xx). A genuine "no matches" still returns []. The distinction matters: the old code returned [] for both, so a dead registry was indistinguishable from an empty result. """ errors = [] merged, seen = [], set() for label, fn in (("smithery", _search_smithery), ("registry", _search_mcp_registry)): try: results = fn(keyword, limit) except Exception as e: errors.append(f"{label}: {type(e).__name__}: {str(e)[:120]}") continue for r in results: key = (r.get("name") or "").lower() if not key or key in seen or not _relevant(keyword, r): continue seen.add(key) merged.append(r) if merged: merged.sort(key=lambda r: _relevance_score(keyword, r), reverse=True) return merged[:limit] # Nothing relevant. If some source was reachable, this is a real empty result; # if none was, the network is the problem and we say so. if len(errors) == 2: > raise RegistryError( "No MCP registry reachable (" + "; ".join(errors) + "). " "Check your connection, or install directly with " "`mcptoon install --npm `." ) E mcptoon.installer.RegistryError: No MCP registry reachable (smithery: URLError: ; registry: URLError: ). Check your connection, or install directly with `mcptoon install --npm `. src/mcptoon/installer.py:171: RegistryError _____________ TestInstallByName.test_search_smithery_returns_list ______________ self = http_class = req = http_conn_args = {'context': } def do_open(self, http_class, req, **http_conn_args): """Return an HTTPResponse object for the request, using http_class. http_class must implement the HTTPConnection API from http.client. """ host = req.host if not host: raise URLError('no host given') # will parse host:port h = http_class(host, timeout=req.timeout, **http_conn_args) h.set_debuglevel(self._debuglevel) headers = dict(req.unredirected_hdrs) headers.update(req.headers) # TODO(jhylton): Should this be redesigned to handle # persistent connections? # We want to make an HTTP/1.1 request, but the addinfourl # class isn't prepared to deal with a persistent connection. # It will try to read all remaining data from the socket, # which will block while the server waits for the next request. # So make sure the connection gets closed after the (only) # request. headers["Connection"] = "close" headers = {name.title(): val for name, val in headers.items()} if req._tunnel_host: tunnel_headers = {} proxy_auth_hdr = "Proxy-Authorization" if proxy_auth_hdr in headers: tunnel_headers[proxy_auth_hdr] = headers[proxy_auth_hdr] # Proxy-Authorization should not be sent to origin # server. del headers[proxy_auth_hdr] h.set_tunnel(req._tunnel_host, headers=tunnel_headers) try: try: > h.request(req.get_method(), req.selector, req.data, headers, encode_chunked=req.has_header('Transfer-encoding')) /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:1320: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1386: in request self._send_request(method, url, body, headers, encode_chunked) /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1432: in _send_request self.endheaders(body, encode_chunked=encode_chunked) /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1381: in endheaders self._send_output(message_body, encode_chunked=encode_chunked) /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1141: in _send_output self.send(msg) /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1085: in send self.connect() /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1520: in connect super().connect() /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1051: in connect self.sock = self._create_connection( /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/socket.py:850: in create_connection for res in getaddrinfo(host, port, 0, SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.smithery.ai', port = 443, family = 0 type = , proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/socket.py:989: gaierror During handling of the above exception, another exception occurred: self = def test_search_smithery_returns_list(self): """_search_smithery returns a list.""" from mcptoon.installer import _search_smithery > result = _search_smithery("test") ^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_serve.py:639: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ src/mcptoon/installer.py:194: in _search_smithery data = _fetch_json(f"{SMITHERY_API_URL}/servers?{params}") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ src/mcptoon/installer.py:186: in _fetch_json with urllib.request.urlopen(req, timeout=timeout) as resp: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:187: in urlopen return opener.open(url, data, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:487: in open response = self._open(req, data) ^^^^^^^^^^^^^^^^^^^^^ /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:504: in _open result = self._call_chain(self.handle_open, protocol, protocol + /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:464: in _call_chain result = func(*args) ^^^^^^^^^^^ /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:1368: in https_open return self.do_open(http.client.HTTPSConnection, req, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = http_class = req = http_conn_args = {'context': } def do_open(self, http_class, req, **http_conn_args): """Return an HTTPResponse object for the request, using http_class. http_class must implement the HTTPConnection API from http.client. """ host = req.host if not host: raise URLError('no host given') # will parse host:port h = http_class(host, timeout=req.timeout, **http_conn_args) h.set_debuglevel(self._debuglevel) headers = dict(req.unredirected_hdrs) headers.update(req.headers) # TODO(jhylton): Should this be redesigned to handle # persistent connections? # We want to make an HTTP/1.1 request, but the addinfourl # class isn't prepared to deal with a persistent connection. # It will try to read all remaining data from the socket, # which will block while the server waits for the next request. # So make sure the connection gets closed after the (only) # request. headers["Connection"] = "close" headers = {name.title(): val for name, val in headers.items()} if req._tunnel_host: tunnel_headers = {} proxy_auth_hdr = "Proxy-Authorization" if proxy_auth_hdr in headers: tunnel_headers[proxy_auth_hdr] = headers[proxy_auth_hdr] # Proxy-Authorization should not be sent to origin # server. del headers[proxy_auth_hdr] h.set_tunnel(req._tunnel_host, headers=tunnel_headers) try: try: h.request(req.get_method(), req.selector, req.data, headers, encode_chunked=req.has_header('Transfer-encoding')) except OSError as err: # timeout error > raise URLError(err) E urllib.error.URLError: /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:1323: URLError ___________ TestInstallByName.test_search_mcp_registry_returns_list ____________ self = http_class = req = http_conn_args = {'context': } def do_open(self, http_class, req, **http_conn_args): """Return an HTTPResponse object for the request, using http_class. http_class must implement the HTTPConnection API from http.client. """ host = req.host if not host: raise URLError('no host given') # will parse host:port h = http_class(host, timeout=req.timeout, **http_conn_args) h.set_debuglevel(self._debuglevel) headers = dict(req.unredirected_hdrs) headers.update(req.headers) # TODO(jhylton): Should this be redesigned to handle # persistent connections? # We want to make an HTTP/1.1 request, but the addinfourl # class isn't prepared to deal with a persistent connection. # It will try to read all remaining data from the socket, # which will block while the server waits for the next request. # So make sure the connection gets closed after the (only) # request. headers["Connection"] = "close" headers = {name.title(): val for name, val in headers.items()} if req._tunnel_host: tunnel_headers = {} proxy_auth_hdr = "Proxy-Authorization" if proxy_auth_hdr in headers: tunnel_headers[proxy_auth_hdr] = headers[proxy_auth_hdr] # Proxy-Authorization should not be sent to origin # server. del headers[proxy_auth_hdr] h.set_tunnel(req._tunnel_host, headers=tunnel_headers) try: try: > h.request(req.get_method(), req.selector, req.data, headers, encode_chunked=req.has_header('Transfer-encoding')) /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:1320: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1386: in request self._send_request(method, url, body, headers, encode_chunked) /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1432: in _send_request self.endheaders(body, encode_chunked=encode_chunked) /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1381: in endheaders self._send_output(message_body, encode_chunked=encode_chunked) /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1141: in _send_output self.send(msg) /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1085: in send self.connect() /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1520: in connect super().connect() /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/http/client.py:1051: in connect self.sock = self._create_connection( /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/socket.py:850: in create_connection for res in getaddrinfo(host, port, 0, SOCK_STREAM): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ host = 'registry.modelcontextprotocol.io', port = 443, family = 0 type = , proto = 0, flags = 0 def getaddrinfo(host, port, family=0, type=0, proto=0, flags=0): """Resolve host and port into list of address info entries. Translate the host/port argument into a sequence of 5-tuples that contain all the necessary arguments for creating a socket connected to that service. host is a domain name, a string representation of an IPv4/v6 address or None. port is a string service name such as 'http', a numeric port number or None. By passing None as the value of host and port, you can pass NULL to the underlying C API. The family, type and proto arguments can be optionally specified in order to narrow the list of addresses returned. Passing zero as a value for each of these arguments selects the full range of results. """ # We override this function since we want to translate the numeric family # and socket type values to enum constants. addrlist = [] > for res in _socket.getaddrinfo(host, port, family, type, proto, flags): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ E socket.gaierror: [Errno -3] Temporary failure in name resolution /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/socket.py:989: gaierror During handling of the above exception, another exception occurred: self = def test_search_mcp_registry_returns_list(self): """_search_mcp_registry returns a list.""" from mcptoon.installer import _search_mcp_registry > result = _search_mcp_registry("test") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tests/test_serve.py:645: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ src/mcptoon/installer.py:235: in _search_mcp_registry data = _fetch_json(f"{MCP_REGISTRY_URL}/servers?{params}") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ src/mcptoon/installer.py:186: in _fetch_json with urllib.request.urlopen(req, timeout=timeout) as resp: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:187: in urlopen return opener.open(url, data, timeout) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:487: in open response = self._open(req, data) ^^^^^^^^^^^^^^^^^^^^^ /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:504: in _open result = self._call_chain(self.handle_open, protocol, protocol + /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:464: in _call_chain result = func(*args) ^^^^^^^^^^^ /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:1368: in https_open return self.do_open(http.client.HTTPSConnection, req, _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = http_class = req = http_conn_args = {'context': } def do_open(self, http_class, req, **http_conn_args): """Return an HTTPResponse object for the request, using http_class. http_class must implement the HTTPConnection API from http.client. """ host = req.host if not host: raise URLError('no host given') # will parse host:port h = http_class(host, timeout=req.timeout, **http_conn_args) h.set_debuglevel(self._debuglevel) headers = dict(req.unredirected_hdrs) headers.update(req.headers) # TODO(jhylton): Should this be redesigned to handle # persistent connections? # We want to make an HTTP/1.1 request, but the addinfourl # class isn't prepared to deal with a persistent connection. # It will try to read all remaining data from the socket, # which will block while the server waits for the next request. # So make sure the connection gets closed after the (only) # request. headers["Connection"] = "close" headers = {name.title(): val for name, val in headers.items()} if req._tunnel_host: tunnel_headers = {} proxy_auth_hdr = "Proxy-Authorization" if proxy_auth_hdr in headers: tunnel_headers[proxy_auth_hdr] = headers[proxy_auth_hdr] # Proxy-Authorization should not be sent to origin # server. del headers[proxy_auth_hdr] h.set_tunnel(req._tunnel_host, headers=tunnel_headers) try: try: h.request(req.get_method(), req.selector, req.data, headers, encode_chunked=req.has_header('Transfer-encoding')) except OSError as err: # timeout error > raise URLError(err) E urllib.error.URLError: /nix/store/d64q19q1xjdwfhqx6czvrjgrhq0n3lcc-python3-3.14.7/lib/python3.14/urllib/request.py:1323: URLError =========================== short test summary info ============================ FAILED tests/test_serve.py::TestInstallByName::test_search_registry_returns_list - mcptoon.installer.RegistryError: No MCP registry reachable (smithery: URLEr... FAILED tests/test_serve.py::TestInstallByName::test_search_smithery_returns_list - urllib.error.URLError: