Skip to content

Conversation

@lukasdotcom
Copy link
Member

The client for mcp servers required it to be an async function so a lot of code was converted to async that also means that context agent can now concurrently deal with multiple requests.

Currently the config is a little basic and only available for admins:
image

For a very simple config to try this out use the config below and ask something about a public github repo:

{"deepwiki": { "url": "https://mcp.deepwiki.com/mcp", "transport": "streamable_http" }}

Also might be worth it to talk about stdio MCP servers. For more info go to https://modelcontextprotocol.io/specification/2025-06-18/basic/transports. Theoretically possible with this code as long as the dependencies for the program exist, but discussed with Julien that we can probable just ignore that type of MCP server.

Also this can't deal with oauth authentication.

description=_("JSON configuration for the MCP"),
type=SettingsFieldType.TEXT,
default="",
placeholder="{\"weather\": {\"url\": \"https://weather.internet/mcp\",\"transport\": \"streamable_http\"}}",
Copy link
Member

@marcelklehr marcelklehr Jul 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can make this a bit nicer. Could we leave out the transport, since we shouln't allow stdio anyway? Passing JSON in a setting is a bit cumbersome

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some other parameters that are useful like the headers parameter if you need any authorization. Also not sure if just overwriting one of the parameters is an expected user experience. WDYT

client = MultiServerMCPClient({
    "github": {
        "transport": "streamable_http", # 
        "url": "https://my-github-mcp-server/mcp",
        "headers": {
            "Authorization": f"Bearer {user['github_token']}"  # This one
        }
    }
})

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. Then I guess it's ok. Can we add an explanation there to make sure people know what to input there?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might also be worth it to add more details to the context agent documentation.

@marcelklehr
Copy link
Member

If you rebase on main, you'll get working CI again :)

@marcelklehr
Copy link
Member

CI fails with:

 Invoking get_tools from mcp
2025-07-29 14:57:06,626 - httpx - INFO - HTTP Request: POST http://localhost:8080/ocs/v1.php/apps/app_api/api/v1/ex-app/config/get-values?format=json "HTTP/1.1 200 OK"
2025-07-29 14:57:06,650 - context_agent - ERROR - Error: Traceback (most recent call last):
  File "/home/runner/work/context_agent/context_agent/context_agent/ex_app/lib/main.py", line 154, in handle_task
    output = await react(task, nextcloud)
  File "/home/runner/work/context_agent/context_agent/context_agent/ex_app/lib/agent.py", line 48, in react
    safe_tools, dangerous_tools = await get_tools(nc)
  File "/home/runner/work/context_agent/context_agent/context_agent/ex_app/lib/all_tools/lib/decorator.py", line 36, in wrapper
    result = await func(*args)
  File "/home/runner/work/context_agent/context_agent/context_agent/ex_app/lib/tools.py", line 40, in get_tools
    imported_tools = await get_tools_from_import(nc)
  File "/home/runner/work/context_agent/context_agent/context_agent/ex_app/lib/all_tools/mcp.py", line 17, in get_tools
    mcp_config = json.loads(mcp_json)
  File "/opt/hostedtoolcache/Python/3.10.18/x64/lib/python3.10/json/__init__.py", line 339, in loads
    raise TypeError(f'the JSON object must be str, bytes or bytearray, '
TypeError: the JSON object must be str, bytes or bytearray, not dict

@lukasdotcom lukasdotcom marked this pull request as ready for review July 29, 2025 15:43
@lukasdotcom
Copy link
Member Author

CI fails with:

 Invoking get_tools from mcp
2025-07-29 14:57:06,626 - httpx - INFO - HTTP Request: POST http://localhost:8080/ocs/v1.php/apps/app_api/api/v1/ex-app/config/get-values?format=json "HTTP/1.1 200 OK"
2025-07-29 14:57:06,650 - context_agent - ERROR - Error: Traceback (most recent call last):
  File "/home/runner/work/context_agent/context_agent/context_agent/ex_app/lib/main.py", line 154, in handle_task
    output = await react(task, nextcloud)
  File "/home/runner/work/context_agent/context_agent/context_agent/ex_app/lib/agent.py", line 48, in react
    safe_tools, dangerous_tools = await get_tools(nc)
  File "/home/runner/work/context_agent/context_agent/context_agent/ex_app/lib/all_tools/lib/decorator.py", line 36, in wrapper
    result = await func(*args)
  File "/home/runner/work/context_agent/context_agent/context_agent/ex_app/lib/tools.py", line 40, in get_tools
    imported_tools = await get_tools_from_import(nc)
  File "/home/runner/work/context_agent/context_agent/context_agent/ex_app/lib/all_tools/mcp.py", line 17, in get_tools
    mcp_config = json.loads(mcp_json)
  File "/opt/hostedtoolcache/Python/3.10.18/x64/lib/python3.10/json/__init__.py", line 339, in loads
    raise TypeError(f'the JSON object must be str, bytes or bytearray, '
TypeError: the JSON object must be str, bytes or bytearray, not dict

Should be fixed in the last commit.

@lukasdotcom lukasdotcom requested a review from marcelklehr July 29, 2025 18:08
Signed-off-by: Lukas Schaefer <[email protected]>
Signed-off-by: Lukas Schaefer <[email protected]>
@marcelklehr
Copy link
Member

marcelklehr commented Jul 31, 2025

Tested and works well! Good work! 🎉

A few concerns:

  • The explanation of how the config works should not be a link as it's likely that this link will stop being available soon. If at all, we should link to our own docs.
  • Currently the new tools from the configured mcp server(s) are just added directly without any namespacing, which may collide with our own internal tools. Not sure if it's possible to fix this.
  • Also it would be nice to be able to add a note to the assistant that these requests go out to the configured MCP server instead of just mentioning the un-translated tool id in the confirmation dialog. This would be nice, but I'm not sure if we want to spend that much effort on this. Daphne decided to leave this for later.

@lukasdotcom
Copy link
Member Author

Tested and works well! Good work! 🎉

A few concerns:

* The explanation of how the config works should not be a link as it's likely that this link will stop being available soon. If at all, we should link to our own docs.

* Currently the new tools from the configured mcp server(s) are just added directly without any namespacing, which may collide with our own internal tools. Not sure if it's possible to fix this.

* ~Also it would be nice to be able to add a note to the assistant that these requests go out to the configured MCP server instead of just mentioning the un-translated tool id in the confirmation dialog. This would be nice, but I'm not sure if we want to spend that much effort on this.~ Daphne decided to leave this for later.

I did change the description to give a short explanation of the format and I added mcp_ in front of all mcp tools so they won't collide with built in tools at least.

@marcelklehr
Copy link
Member

Awesome, then it's good to go :)

@lukasdotcom lukasdotcom merged commit 1ced045 into main Jul 31, 2025
4 checks passed
@lukasdotcom lukasdotcom deleted the add-mcp-client branch July 31, 2025 12:42
lukasdotcom added a commit that referenced this pull request Jul 31, 2025
feat: allow for specifying mcp clients and convert functions to async
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants