Skip to content

simple-auth is not working as expected #2826

Open

Description

@nikodemas

Initial Checks

Description

I am trying to follow the example as described in examples/servers/simple-auth. However, when running the mcp-simple-auth-client I am getting the following error (and I know how to fix it):

$ MCP_SERVER_PORT=8000 MCP_TRANSPORT_TYPE=streamable-http uv run mcp-simple-auth-client
🚀 Simple MCP Auth Client
Connecting to: http://localhost:8000/mcp
Transport type: streamable-http
🔗 Attempting to connect to http://localhost:8000/mcp...
🖥️  Started callback server on http://localhost:3030
📡 Opening StreamableHTTP transport connection with auth...
🤝 Initializing MCP session...
⚡ Starting session initialization...
❌ Failed to connect: unhandled errors in a TaskGroup (1 sub-exception)
  + Exception Group Traceback (most recent call last):
  |   File "/home/python-sdk/examples/clients/simple-auth-client/mcp_simple_auth_client/main.py", line 230, in connect
  |     async with streamable_http_client(url=self.server_url, http_client=custom_client) as (
  |   File "/usr/lib/python3.12/contextlib.py", line 231, in __aexit__
  |     await self.gen.athrow(value)
  |   File "/home/python-sdk/src/mcp/client/streamable_http.py", line 563, in streamable_http_client
  |     async with (
  |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/anyio/_backends/_asyncio.py", line 772, in __aexit__
  |     raise BaseExceptionGroup(
  | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_transports/default.py", line 101, in map_httpcore_exceptions
    |     yield
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_transports/default.py", line 394, in handle_async_request
    |     resp = await self._pool.handle_async_request(req)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_async/connection_pool.py", line 256, in handle_async_request
    |     raise exc from None
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_async/connection_pool.py", line 236, in handle_async_request
    |     response = await connection.handle_async_request(
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_async/connection.py", line 101, in handle_async_request
    |     raise exc
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_async/connection.py", line 78, in handle_async_request
    |     stream = await self._connect(request)
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_async/connection.py", line 124, in _connect
    |     stream = await self._network_backend.connect_tcp(**kwargs)
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_backends/auto.py", line 31, in connect_tcp
    |     return await self._backend.connect_tcp(
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_backends/anyio.py", line 113, in connect_tcp
    |     with map_exceptions(exc_map):
    |   File "/usr/lib/python3.12/contextlib.py", line 158, in __exit__
    |     self.gen.throw(value)
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_exceptions.py", line 14, in map_exceptions
    |     raise to_exc(exc) from exc
    | httpcore.ConnectError: All connection attempts failed
    |
    | The above exception was the direct cause of the following exception:
    |
    | Traceback (most recent call last):
    |   File "/home/python-sdk/src/mcp/client/streamable_http.py", line 475, in handle_request_async
    |     await self._handle_post_request(ctx)
    |   File "/home/python-sdk/src/mcp/client/streamable_http.py", line 261, in _handle_post_request
    |     async with ctx.client.stream(
    |   File "/usr/lib/python3.12/contextlib.py", line 210, in __aenter__
    |     return await anext(self.gen)
    |            ^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1583, in stream
    |     response = await self.send(
    |                ^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1629, in send
    |     response = await self._send_handling_auth(
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1657, in _send_handling_auth
    |     response = await self._send_handling_redirects(
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1694, in _send_handling_redirects
    |     response = await self._send_single_request(request)
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1730, in _send_single_request
    |     response = await transport.handle_async_request(request)
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_transports/default.py", line 393, in handle_async_request
    |     with map_httpcore_exceptions():
    |   File "/usr/lib/python3.12/contextlib.py", line 158, in __exit__
    |     self.gen.throw(value)
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_transports/default.py", line 118, in map_httpcore_exceptions
    |     raise mapped_exc(message) from exc
    | httpx.ConnectError: All connection attempts failed
    +------------------------------------

I think the problem is that the server_url in the examples/servers/simple-auth/mcp_simple_auth/server.py includes the path (the /mcp part) whereas in the README it shows the base URL without the path should be used. Changing this locally fixed the problem for me.

I would also be willing to fix the TODO in examples/servers/simple-auth/mcp_simple_auth/simple_auth_provider.py if that's alright.

Example Code

terminal 1:

uv run mcp-simple-auth-as --port=9000


terminal 2:

uv run mcp-simple-auth-rs --port=8001 --auth-server=http://localhost:9000 --transport=streamable-http


terminal 3:

$ MCP_SERVER_PORT=8000 MCP_TRANSPORT_TYPE=streamable-http uv run mcp-simple-auth-client
🚀 Simple MCP Auth Client
Connecting to: http://localhost:8000/mcp
Transport type: streamable-http
🔗 Attempting to connect to http://localhost:8000/mcp...
🖥️  Started callback server on http://localhost:3030
📡 Opening StreamableHTTP transport connection with auth...
🤝 Initializing MCP session...
⚡ Starting session initialization...
❌ Failed to connect: unhandled errors in a TaskGroup (1 sub-exception)
  + Exception Group Traceback (most recent call last):
  |   File "/home/python-sdk/examples/clients/simple-auth-client/mcp_simple_auth_client/main.py", line 230, in connect
  |     async with streamable_http_client(url=self.server_url, http_client=custom_client) as (
  |   File "/usr/lib/python3.12/contextlib.py", line 231, in __aexit__
  |     await self.gen.athrow(value)
  |   File "/home/python-sdk/src/mcp/client/streamable_http.py", line 563, in streamable_http_client
  |     async with (
  |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/anyio/_backends/_asyncio.py", line 772, in __aexit__
  |     raise BaseExceptionGroup(
  | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_transports/default.py", line 101, in map_httpcore_exceptions
    |     yield
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_transports/default.py", line 394, in handle_async_request
    |     resp = await self._pool.handle_async_request(req)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_async/connection_pool.py", line 256, in handle_async_request
    |     raise exc from None
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_async/connection_pool.py", line 236, in handle_async_request
    |     response = await connection.handle_async_request(
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_async/connection.py", line 101, in handle_async_request
    |     raise exc
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_async/connection.py", line 78, in handle_async_request
    |     stream = await self._connect(request)
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_async/connection.py", line 124, in _connect
    |     stream = await self._network_backend.connect_tcp(**kwargs)
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_backends/auto.py", line 31, in connect_tcp
    |     return await self._backend.connect_tcp(
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_backends/anyio.py", line 113, in connect_tcp
    |     with map_exceptions(exc_map):
    |   File "/usr/lib/python3.12/contextlib.py", line 158, in __exit__
    |     self.gen.throw(value)
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpcore/_exceptions.py", line 14, in map_exceptions
    |     raise to_exc(exc) from exc
    | httpcore.ConnectError: All connection attempts failed
    |
    | The above exception was the direct cause of the following exception:
    |
    | Traceback (most recent call last):
    |   File "/home/python-sdk/src/mcp/client/streamable_http.py", line 475, in handle_request_async
    |     await self._handle_post_request(ctx)
    |   File "/home/python-sdk/src/mcp/client/streamable_http.py", line 261, in _handle_post_request
    |     async with ctx.client.stream(
    |   File "/usr/lib/python3.12/contextlib.py", line 210, in __aenter__
    |     return await anext(self.gen)
    |            ^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1583, in stream
    |     response = await self.send(
    |                ^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1629, in send
    |     response = await self._send_handling_auth(
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1657, in _send_handling_auth
    |     response = await self._send_handling_redirects(
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1694, in _send_handling_redirects
    |     response = await self._send_single_request(request)
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_client.py", line 1730, in _send_single_request
    |     response = await transport.handle_async_request(request)
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_transports/default.py", line 393, in handle_async_request
    |     with map_httpcore_exceptions():
    |   File "/usr/lib/python3.12/contextlib.py", line 158, in __exit__
    |     self.gen.throw(value)
    |   File "/home/python-sdk/.venv/lib/python3.12/site-packages/httpx/_transports/default.py", line 118, in map_httpcore_exceptions
    |     raise mapped_exc(message) from exc
    | httpx.ConnectError: All connection attempts failed
    +------------------------------------

Python & MCP Python SDK

`Python 3.12.3`
`mcp-simple-auth 0.1.0`

and MCP Python SDK:

$ git describe --tags
v1.25.0-180-g5d82649

Activity

  1. added
    bugSomething isn't working
    P2Moderate issues affecting some users, edge cases, potentially valuable feature
    authIssues and PRs related to Authentication / OAuth
    on Aug 14, 2026
  2. basitalisandhu commented on Oct 13, 2026

    @basitalisandhu

    This still reproduces on v2: main at c9356a2, with mcp 2.3.0 from PyPI in the example client's venv, macOS, Python 3.13. Since #2846 was closed in the backlog sweep, here is the current state.

    There are two separate things in the report.

    1. The traceback in the report is a port mismatch. The resource server was started on 8001, but the client was run with MCP_SERVER_PORT=8000, so httpcore.ConnectError: All connection attempts failed just means nothing is listening on 8000. The README now says MCP_SERVER_PORT=8001. The client's default is still 8000 (main.py#L366), which matches the legacy server rather than the RS, so that is easy to trip over.

    2. With the right port, the OAuth flow fails. Running exactly the README steps (AS on 9000, RS on 8001 with --transport=streamable-http, then MCP_SERVER_PORT=8001 MCP_TRANSPORT_TYPE=streamable-http uv run mcp-simple-auth-client):

    mcp.client.auth.exceptions.OAuthFlowError: Protected resource http://localhost:8001/mcp does not match expected http://localhost:8001
    

    Cause: the client strips the path before building the provider, server_url=self.server_url.replace("/mcp", "") at main.py#L217. The RS correctly advertises resource: http://localhost:8001/mcp (server.py#L73). _validate_resource_match (oauth2.py#L590-L592) then asks whether http://localhost:8001 falls under http://localhost:8001/mcp. It does not, since the match only allows a requested path under the configured one.

    Fix: pass the MCP endpoint URL as is.

                 oauth_auth = OAuthClientProvider(
    -                server_url=self.server_url.replace("/mcp", ""),
    +                server_url=self.server_url,

    With that one line, the same three commands complete the flow: PRM discovery, DCR, /authorize with resource=http://localhost:8001/mcp, demo login, token, initialize, and list returns get_time. The legacy server (mcp-simple-auth-legacy --port=8000) still connects with the change, and ruff check / ruff format --check pass on the example. Until it lands, editing that line locally is the workaround. The README's description of the server URL isn't the problem: the server side is already right, and only the client example needs to change.

    Prepared with help from Claude Code. I ran the AS, RS and client locally before and after the change, with the browser step scripted against the demo login form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Moderate issues affecting some users, edge cases, potentially valuable featureauthIssues and PRs related to Authentication / OAuthbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions