camel icon indicating copy to clipboard operation
camel copied to clipboard

feat: Agent as MCP server

Open MuggleJinx opened this issue 8 months ago • 8 comments

Description

Finish #1912. Expose chat agent as MCP server.

Usage

Just provide config for MCP client like Cursor, Claude, etc.

    "camel-chat-agent": {
        "command": "uv",
        "args": [
            "--directory",
            "/PATH/TO/camel/services",
            "run",
            "agent_mcp_server.py"
        ]
    }

Features

  1. User can customize the list of agents available in server via the agent_config.py script.
  2. Interaction with agents.
  3. Resources
    • Chat history
    • Agent info
    • Tool lists

MuggleJinx avatar Apr 08 '25 08:04 MuggleJinx

Thanks for the effort @MuggleJinx 🔥 I added some comments in the code. Please consider the following:

  • If you decide to make agent_as_mcp.py as a script, consider moving it to a different folder than camel.
  • The model_from_json_schema needs further improvement to handle nested objects and complex schemas, or better error handling for malformed schemas. Alternatively, maybe use an existing tool, such as datamodel-code-generator.
  • Please consider adding test cases, or providing some guidance in the examples
  • Is it better to put the FastMCP's context parameter to a good use, for example for better logging and reporting progress?

Thanks, Hesam @hesamsheikh , for the review and all the great suggestions!!! Your comments are very helpful, especially since there’s still a lot of room for improvement in this PR. I will work on it!

MuggleJinx avatar Apr 14 '25 06:04 MuggleJinx

Hi @hesamsheikh, thanks again! I adapted ur suggestions:

  1. Update the folder structure, separate the config.py and server.py/
  2. For model_from_json_schema function, I improve the logic so that it now handles nested object, etc. I think should be enough for now.. I looked into datamodel-code-generator you mentioned, seems not so simple to use at runtime, and it requires extra dependency. Moreover, I think this feature is not that important, since it's the LLM using the MCP server, and LLM does not care much about strictly structured output as programming language do... Anyway, we can of course improve this part in the future whenever necessary.
  3. I added the test cases. However, any ideas for adding examples? Not so obvious to me since it's a script..
  4. Added the ctx argument for logging as well.

MuggleJinx avatar Apr 15 '25 06:04 MuggleJinx

The MCP client like Cursor, Claude, Cline, need to run the server as scripts, I think we still need to provide the entry script for the MCP client to start like this:

    "camel-chat-agent": {
        "command": "uv",
        "args": [
            "--directory",
            "/PATH/TO/camel/services",
            "run",
            "agent_mcp_server.py"
        ]
    }

Starting the subprocess from chatAgent module seems hard to achieve this, what do you think? @lightaime @Wendong-Fan

MuggleJinx avatar Apr 21 '25 14:04 MuggleJinx

Starting the subprocess from chatAgent module

Hi @MuggleJinx. Could you please elaborate more why starting the subprocess from ChatAgent module is hard?

lightaime avatar Apr 21 '25 20:04 lightaime

Starting the subprocess from chatAgent module

Hi @MuggleJinx. Could you please elaborate more why starting the subprocess from ChatAgent module is hard?

@lightaime Sure, for example, in current approach, user can define a list of agents, in config.py, and just set the MCP config of MCP client in, e.g., Claude desktop, in the following JSON format. Then the Claude desktop can easily launch the MCP server and interact with pre-defined chatAgents.

    "camel-chat-agent": {
        "command": "uv",
        "args": [
            "--directory",
            "/PATH/TO/camel/services",
            "run",
            "agent_mcp_server.py"
        ]
    }

Basically I think the MCP client needs some entry scripts to launch the MCP server as its own subprocess. If we define, say, to_mcp in chatAgent, and starting a subprocess MCP server by ourselves, this way maybe workable with the sse connection, not stdio. Let me research more and compare.

MuggleJinx avatar Apr 22 '25 08:04 MuggleJinx

Starting the subprocess from chatAgent module

Hi @MuggleJinx. Could you please elaborate more why starting the subprocess from ChatAgent module is hard?

@lightaime Sure, for example, in current approach, user can define a list of agents, in config.py, and just set the MCP config of MCP client in, e.g., Claude desktop, in the following JSON format. Then the Claude desktop can easily launch the MCP server and interact with pre-defined chatAgents.

    "camel-chat-agent": {
        "command": "uv",
        "args": [
            "--directory",
            "/PATH/TO/camel/services",
            "run",
            "agent_mcp_server.py"
        ]
    }

Basically I think the MCP client needs some entry scripts to launch the MCP server as its own subprocess. If we define, say, to_mcp in chatAgent, and starting a subprocess MCP server by ourselves, this way maybe workable with the sse connection, not stdio. Let me research more and compare.

What if we generate a script in to_mcp?

lightaime avatar Apr 22 '25 16:04 lightaime

Starting the subprocess from chatAgent module

Hi @MuggleJinx. Could you please elaborate more why starting the subprocess from ChatAgent module is hard?

@lightaime Sure, for example, in current approach, user can define a list of agents, in config.py, and just set the MCP config of MCP client in, e.g., Claude desktop, in the following JSON format. Then the Claude desktop can easily launch the MCP server and interact with pre-defined chatAgents.

    "camel-chat-agent": {
        "command": "uv",
        "args": [
            "--directory",
            "/PATH/TO/camel/services",
            "run",
            "agent_mcp_server.py"
        ]
    }

Basically I think the MCP client needs some entry scripts to launch the MCP server as its own subprocess. If we define, say, to_mcp in chatAgent, and starting a subprocess MCP server by ourselves, this way maybe workable with the sse connection, not stdio. Let me research more and compare.

What if we generate a script in to_mcp?

Sure, I think that would do, let me try

MuggleJinx avatar Apr 23 '25 08:04 MuggleJinx

Hi @lightaime, I created another PR to implement the to_mcp method for creating MCP server at runtime. Can you check #2272?

MuggleJinx avatar Apr 24 '25 12:04 MuggleJinx

hey @lightaime , based on the comment https://github.com/camel-ai/camel/pull/2272#issuecomment-2827496119 and review https://github.com/camel-ai/camel/pull/2272#pullrequestreview-2817202052, I will merge this PR first, feel free to leave you comment

Wendong-Fan avatar May 06 '25 20:05 Wendong-Fan