Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

pietrozullo
Copy link
Member

No description provided.

@pietrozullo
Copy link
Member Author

@claude can you have a look at this PR ?

@pietrozullo pietrozullo requested a review from Copilot August 4, 2025 04:19
Copilot

This comment was marked as outdated.

@almalejko
Copy link

@pietrozullo , could you please tell what is blocking the PR? It look like it's covering the MCP spec. Is the merge expected any time soon?

@pietrozullo
Copy link
Member Author

Hey @almalejko it is quite a big PR and I did not have time to review it and make sure it is proper, to me it works. I will try to YOLO it this next few days. Do you need it ?

@almalejko
Copy link

@pietrozullo , thanks for the answer! Are you aware of any public mcp servers that implement dynamic cluent registration? I would test the mcp client with them

@renvins renvins requested a review from Copilot August 17, 2025 17:05
@renvins renvins added the enhancement New feature or request label Aug 17, 2025
Copilot

This comment was marked as outdated.

@pietrozullo
Copy link
Member Author

@pietrozullo , thanks for the answer! Are you aware of any public mcp servers that implement dynamic cluent registration? I would test the mcp client with them

@almalejko Linear, Asana and others (this is a good list) support DCR https://github.com/jaw9c/awesome-remote-mcp-servers

@renvins did you test with them ? Did you test with github ? I know Github does not follow oauth spec properly so it might fail.

@renvins
Copy link
Contributor

renvins commented Aug 17, 2025

@pietrozullo , thanks for the answer! Are you aware of any public mcp servers that implement dynamic cluent registration? I would test the mcp client with them

@almalejko Linear, Asana and others (this is a good list) support DCR https://github.com/jaw9c/awesome-remote-mcp-servers

@renvins did you test with them ? Did you test with github ? I know Github does not follow oauth spec properly so it might fail.

@pietrozullo I've tested Linear and Asana, it's ok. GitHub has some issues.

@pietrozullo
Copy link
Member Author

@renvins one other couple things that I would test here are:

  • backward compatibility -> old non auth http servers work well ?
  • auth token -> if I pass auth header in HTTP server, does it work the same ?

@renvins
Copy link
Contributor

renvins commented Aug 18, 2025

@renvins one other couple things that I would test here are:

  • backward compatibility -> old non auth http servers work well ?
  • auth token -> if I pass auth header in HTTP server, does it work the same ?

The old non auth https servers were fixed in the previous commit. In the next hours/tomorrow I'm going to test all the rest

- Remove auth field to reduce API verbosity
- Add "auth" support for MCPClient's config
- Add "oauth_provider" key to MCPClient's config to provide metadata
- Fix no OAuth servers' errors
@renvins
Copy link
Contributor

renvins commented Aug 19, 2025

Giving you a summary to clarify the ideas as much as possible:

  • I took the liberty of removing the auth field from the client for several reasons including:

    • If there were servers without authentication requirements, they would be overwritten by this (a possible solution was to force servers without auth to put "auth": None, but it was really ugly)
    • Less API verbosity - having both an auth field and also having it in the config for each server was confusing in my opinion,
    • It's rare to find servers with identical authentication using the same data, so it's better to specify it per server rather than having problems with no-auth servers
  • I've also added the OAuth provider which allows inserting server metadata info to avoid discovery

  • Now for servers without OAuth, discovery still happens - if it finds nothing, it continues. Obviously the edge case is caught where discovery finds nothing but returns an authorization error if something went wrong

  • I've updated docs with new usage

I think I made the right architectural decision. Having both the field and the single setting in the config created incompatibilities with servers that didn't need auth and much more.

@pietrozullo let me know!

@renvins
Copy link
Contributor

renvins commented Aug 19, 2025

@pietrozullo What about the auth_token field? In our auth implementation we handle the bearer token case, so should we remove it or not?

@pietrozullo
Copy link
Member Author

Hey @renvins could you please fix the tests and write an integration test for Authorization ?
You see the badges in the readme, those all have a corresponding test that shows that the feature is active and well working.
It'd be great to have this here as well!

@renvins
Copy link
Contributor

renvins commented Aug 24, 2025

Hey @pietrozullo. Of course! Then I proceed updating the bugged test, removing the old field auth_token and creating an integration test for authorization!

@renvins
Copy link
Contributor

renvins commented Sep 2, 2025

@pietrozullo I've manually tested all the features listed in the documentation and they work properly as expected. I updated a little mistake in one example on the doc.

The integration test is done and it tests all the auth flow (mocking only the web browser and the callback server), discovery, DCR, token and auth. I added in the test also test for custom auth and for the direct usage of the Bearer token.

I've also added the badge in the README and the test in GH actions. Hope you enjoy that? What are the next steps now? Waiting for you.

@pietrozullo
Copy link
Member Author

@renvins You are the best! I will now review and merge

pietrozullo and others added 2 commits September 2, 2025 13:05
Co-authored-by: Copilot <[email protected]>
Signed-off-by: Pietro Zullo <[email protected]>
Co-authored-by: Copilot <[email protected]>
Signed-off-by: Pietro Zullo <[email protected]>
@renvins
Copy link
Contributor

renvins commented Sep 2, 2025

@pietrozullo Thank you! We should modify also the examples before merging! (it takes 5 mins). If you want do also some tests on your own!

@pietrozullo
Copy link
Member Author

You can modify the example yes, I just tested with notion mcp and it works great.
Github still does not work because of their weird authentication endpoints, could you write a special handling case for github in the oauthcallback process ? Where instead of following rigidly the spec you try common names for the authorization server ? These common names should include the ones that github uses so that this set up also works for github.
Another option is to just check if the server name contains github and use the different authorization endpoints from github.

Something like this could work:

async def discover_oauth_metadata(self, server_url: str) -> Optional[Dict[str, Any]]:
        """
        Discover OAuth metadata from server following OAuth 2.0 Authorization Server Metadata spec
        """
        logger.info(f"🔍 [MCP Auth] Discovering OAuth metadata for: {server_url}")

        try:
            # Parse base URL
            if "://" in server_url:
                base_url = "/".join(server_url.split("/")[:3])
            else:
                base_url = f"https://{server_url}"

            # Standard OAuth discovery endpoints
            endpoints = [
                f"{base_url}/.well-known/oauth-authorization-server",
                f"{base_url}/.well-known/openid_configuration",
            ]

            # Special handling for Linear MCP
            if "linear.app" in server_url:
                endpoints.insert(0, "https://mcp.linear.app/.well-known/oauth-authorization-server")
                endpoints.insert(1, "https://mcp.linear.app/.well-known/openid_configuration")

            async with httpx.AsyncClient() as client:
                for endpoint in endpoints:
                    try:
                        logger.info(f"📤 [MCP Auth] Trying endpoint: {endpoint}")
                        response = await client.get(endpoint, headers={"Accept": "application/json"})

                        if response.status_code == 200:
                            metadata = response.json()

                            # Validate required fields
                            if metadata.get("authorization_endpoint") and metadata.get("token_endpoint"):
                                logger.info(f"✅ [MCP Auth] Valid metadata found at: {endpoint}")
                                return metadata
                            else:
                                logger.warning(f"⚠️ [MCP Auth] Invalid metadata at {endpoint}")

                    except Exception as e:
                        logger.warning(f"❌ [MCP Auth] Failed to fetch {endpoint}: {e}")
                        continue

            logger.warning(f"❌ [MCP Auth] No OAuth metadata found for {server_url}")
            return None

        except Exception as e:
            logger.error(f"❌ [MCP Auth] OAuth discovery failed: {e}")
            return None
            

@renvins
Copy link
Contributor

renvins commented Sep 2, 2025

@pietrozullo I think that instead of modifying the specs during the callback would be better to try some different discovery for GitHub. Let me know what you think and also I hope you liked my work!

@pietrozullo
Copy link
Member Author

Yes it is okay to use different discovery for github.

@renvins
Copy link
Contributor

renvins commented Sep 2, 2025

Yes it is okay to use different discovery for github.

Also I've seen that for GH you also need to create an OAuth app on GitHub to get client id etc. because of theirs not support for DCR...

@pietrozullo
Copy link
Member Author

Oh my bad, true that. Maybe at some point they did, I had this memory. Then this should be ready outside from the doc example right ?

@renvins
Copy link
Contributor

renvins commented Sep 2, 2025

Oh my bad, true that. Maybe at some point they did, I had this memory. Then this should be ready outside from the doc example right ?

@pietrozullo I've searched around. They don't have an endpoint for discovery. So we should make an example where user has to EXPLICITLY specify the authorization and token endpoint and they should be this: https://github.com/login/oauth/authorize https://github.com/login/oauth/access_token

Also needs to be specified the client_id that is generated from the oauth application that every user should create. If you want, instead of making users set these endpoints manually, we can hardcode them if we see GitHub in the url, preventing discovery. Let me know! And this is where auth is needed: https://api.github.com/user
image

@renvins
Copy link
Contributor

renvins commented Sep 2, 2025

@pietrozullo Another problem is that the OAuth application wants the Homepage URL and the callback URL. But since the port is not defined from start, how can we handle this...

@renvins
Copy link
Contributor

renvins commented Sep 3, 2025

@pietrozullo Let me know any ideas you have!

- Add customizable port for callback
- Remove dynamic port
- Fix bug of registration before checking port
@renvins
Copy link
Contributor

renvins commented Sep 7, 2025

@pietrozullo Added port support and removed dynamic port. Default port will be 8080 and modified url to localhost. Added also the edge case for automatic discovery for GitHub MCP server. Now I'm going to update docs! LEEEETSGOOO

@renvins
Copy link
Contributor

renvins commented Sep 8, 2025

@pietrozullo Updated also docs. Waiting for your review!

@pietrozullo
Copy link
Member Author

Hey @renvins great stuff.
I just ran the linear example, I did these steps:
1 - Cleared the cached tokens to make sure we are in clean state
2 - Ran the example - worked fine
3 - Re ran the example works fine but logging shows error

@pietrozullo
Copy link
Member Author

pietrozullo commented Sep 8, 2025

Hey @renvins great stuff.
I just ran the linear example, I did these steps:
1 - Cleared the cached tokens to make sure we are in clean state
2 - Ran the example - worked fine
3 - Re ran the example works fine but logging shows error

Here logs:

(.venv) ➜  mcp-use git:(feat/authorization) python examples/simple_oauth_example.py
2025-09-08 11:36:06,474 - mcp_use.telemetry.telemetry - INFO - Anonymized telemetry enabled. Set MCP_USE_ANONYMIZED_TELEMETRY=false to disable.
2025-09-08 11:36:06,474 - mcp_use - INFO - 🚀 Initializing MCP agent and connecting to services...
2025-09-08 11:36:06,474 - mcp_use - INFO - 🔌 Found 0 existing sessions
2025-09-08 11:36:06,474 - mcp_use - INFO - 🔄 No active sessions found, creating new ones...
2025-09-08 11:36:06,474 - mcp_use - INFO - Using default callback port 8080
2025-09-08 11:36:06,602 - mcp_use - INFO - OAuth authentication required
2025-09-08 11:36:06,602 - mcp_use - INFO - Attempting Dynamic Client Registration
2025-09-08 11:36:07,004 - mcp_use - INFO - Dynamic Client Registration successful: zVYHH2pqkluWj
Opening browser for authorization: https://mcp.linear.app/authorize?response_type=code&client_id=zVYHH2pkluWj&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Fcallback&state=4d93v9qhZCZKzYmp7Z9XBXqE3RcJ2jffQGDw90
2025-09-08 11:36:13,846 - mcp_use - ERROR - MCP protocol error during initialization: Session terminated
2025-09-08 11:36:14,961 - mcp_use - INFO - ✅ Created 1 new sessions
2025-09-08 11:36:15,088 - mcp_use - INFO - 🛠️ Created 24 LangChain tools from client
2025-09-08 11:36:15,088 - mcp_use - INFO - 🧰 Found 24 tools across all connectors
2025-09-08 11:36:15,088 - mcp_use - INFO - 🧠 Agent ready with tools: list_comments, create_comment, list_cycles, get_document, list_documents, get_issue, list_issues, create_issue, update_issue, list_issue_statuses, get_issue_status, list_my_issues, list_issue_labels, create_issue_label, list_projects, get_project, create_project, update_project, list_project_labels, list_teams, get_team, list_users, get_user, search_documentation
2025-09-08 11:36:15,137 - mcp_use - INFO - ✨ Agent initialization complete
2025-09-08 11:36:15,137 - mcp_use - INFO - 💬 Received query: 'What are my latest linear tickets'
2025-09-08 11:36:15,137 - mcp_use - INFO - 🏁 Starting agent execution with max_steps=5
2025-09-08 11:36:15,137 - mcp_use - INFO - 👣 Step 1/5
2025-09-08 11:36:20,116 - mcp_use - INFO - 💭 Reasoning:  Invoking: `list_my_issues` with `{'limit': 5}`   
2025-09-08 11:36:20,116 - mcp_use - INFO - 🔧 Tool call: list_my_issues with input: {'limit': 5}
2025-09-08 11:36:20,116 - mcp_use - INFO - 📄 Tool result: [{"id":"8290d94e-85a5-43f3-a850-719502088cfe","identifier":"MCP-93","title":"LLM in MCPAgent Fail...
2025-09-08 11:36:20,116 - mcp_use - INFO - 👣 Step 2/5
2025-09-08 11:36:29,525 - mcp_use - INFO - ✅ Agent finished at step 2
2025-09-08 11:36:29,525 - mcp_use - INFO - 🎉 Agent execution complete in 23.05090618133545 seconds
Here are your latest Linear tickets:
REDACTED
Let me know if you need more information on any of these tickets!
(.venv) ➜  mcp-use git:(feat/authorization) python examples/simple_oauth_example.py
2025-09-08 11:36:32,864 - mcp_use.telemetry.telemetry - INFO - Anonymized telemetry enabled. Set MCP_USE_ANONYMIZED_TELEMETRY=false to disable.
2025-09-08 11:36:32,865 - mcp_use - INFO - 🚀 Initializing MCP agent and connecting to services...
2025-09-08 11:36:32,865 - mcp_use - INFO - 🔌 Found 0 existing sessions
2025-09-08 11:36:32,865 - mcp_use - INFO - 🔄 No active sessions found, creating new ones...
2025-09-08 11:36:32,865 - mcp_use - INFO - Using default callback port 8080
2025-09-08 11:36:32,991 - mcp_use - ERROR - MCP protocol error during initialization: Session terminated
2025-09-08 11:36:34,175 - mcp_use - INFO - ✅ Created 1 new sessions
2025-09-08 11:36:34,287 - mcp_use - INFO - 🛠️ Created 24 LangChain tools from client
2025-09-08 11:36:34,287 - mcp_use - INFO - 🧰 Found 24 tools across all connectors
2025-09-08 11:36:34,287 - mcp_use - INFO - 🧠 Agent ready with tools: list_comments, create_comment, list_cycles, get_document, list_documents, get_issue, list_issues, create_issue, update_issue, list_issue_statuses, get_issue_status, list_my_issues, list_issue_labels, create_issue_label, list_projects, get_project, create_project, update_project, list_project_labels, list_teams, get_team, list_users, get_user, search_documentation
2025-09-08 11:36:34,333 - mcp_use - INFO - ✨ Agent initialization complete
2025-09-08 11:36:34,333 - mcp_use - INFO - 💬 Received query: 'What are my latest linear tickets'
2025-09-08 11:36:34,333 - mcp_use - INFO - 🏁 Starting agent execution with max_steps=5
2025-09-08 11:36:34,333 - mcp_use - INFO - 👣 Step 1/5
2025-09-08 11:36:43,463 - mcp_use - INFO - 💭 Reasoning:  Invoking: `list_my_issues` with `{'limit': 5}`   
2025-09-08 11:36:43,463 - mcp_use - INFO - 🔧 Tool call: list_my_issues with input: {'limit': 5}
2025-09-08 11:36:43,463 - mcp_use - INFO - 📄 Tool result: [{"id":"8290d94e-85a5-43f3-a850-719502088cfe","identifier":"MCP-93","title":"LLM in MCPAgent Fail...
2025-09-08 11:36:43,464 - mcp_use - INFO - 👣 Step 2/5
2025-09-08 11:36:53,405 - mcp_use - INFO - ✅ Agent finished at step 2
2025-09-08 11:36:53,405 - mcp_use - INFO - 🎉 Agent execution complete in 20.540530920028687 seconds
Here are your latest Linear tickets:
REDACTED
Let me know if you need more information on any of these tickets!
(.venv) ➜  mcp-use git:(feat/authorization) 

As you see in both succesfull runs the logs return an error in the MCP protocol initialization:

2025-09-08 11:36:32,865 - mcp_use - INFO - Using default callback port 8080
2025-09-08 11:36:32,991 - mcp_use - ERROR - MCP protocol error during initialization: Session terminated

@pietrozullo
Copy link
Member Author

Issue found, and flagged

@renvins
Copy link
Contributor

renvins commented Sep 9, 2025

@pietrozullo for me is finished definitely. If you want have a look also at the tests. By the way check also integration tests if you mean to.

@pietrozullo pietrozullo merged commit 1b6d77f into main Sep 11, 2025
16 checks passed
@pietrozullo pietrozullo deleted the feat/authorization branch September 11, 2025 23:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants