From 9954000c75316e679c9d5c9b519ed7fff0160633 Mon Sep 17 00:00:00 2001 From: doomedraven Date: Mon, 23 Feb 2026 10:27:56 +0000 Subject: [PATCH 1/2] fix dist.py imports --- utils/dist.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/utils/dist.py b/utils/dist.py index c71ff0ac2ef..bf2f36708fa 100644 --- a/utils/dist.py +++ b/utils/dist.py @@ -42,19 +42,21 @@ from lib.cuckoo.common.path_utils import path_delete, path_exists, path_get_size, path_mkdir, path_mount_point, path_write_file from lib.cuckoo.common.socket_utils import send_socket_command from lib.cuckoo.common.utils import get_options -from lib.cuckoo.core.database import ( +from lib.cuckoo.core.data.task import ( TASK_BANNED, TASK_DISTRIBUTED, TASK_DISTRIBUTED_COMPLETED, TASK_FAILED_REPORTING, TASK_PENDING, TASK_REPORTED, - TASK_RUNNING, + TASK_RUNNING +) +from lib.cuckoo.core.database import ( Database, _Database, init_database, ) -from lib.cuckoo.core.database import Task as MD_Task +from lib.cuckoo.core.data.task import Task as MD_Task from dev_utils.mongodb import mongo_update_one dist_conf = Config("distributed") From c9b17645d869440da5d969a13a23d83cc8d9a77c Mon Sep 17 00:00:00 2001 From: doomedraven Date: Mon, 23 Feb 2026 14:30:25 +0000 Subject: [PATCH 2/2] mcp's sse --- .gemini/settings.json | 8 ++++++++ docs/book/src/usage/mcp.rst | 40 +++++++++++++++++++++++++++++++++++-- web/mcp_server.py | 14 ++++++++++++- 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 .gemini/settings.json diff --git a/.gemini/settings.json b/.gemini/settings.json new file mode 100644 index 00000000000..ef9233f3807 --- /dev/null +++ b/.gemini/settings.json @@ -0,0 +1,8 @@ +{ + "mcpServers": { + "cape_sandbox": { + "url": "http://127.0.0.1:9004/sse", + "type": "sse" + } + } +} \ No newline at end of file diff --git a/docs/book/src/usage/mcp.rst b/docs/book/src/usage/mcp.rst index f6f7483ee41..36c0322c7b3 100644 --- a/docs/book/src/usage/mcp.rst +++ b/docs/book/src/usage/mcp.rst @@ -78,6 +78,9 @@ Environment Variables * ``CAPE_API_URL``: (Optional) The full path to your CAPE API v2 endpoint (e.g., ``http://127.0.0.1:8000/apiv2``). If not set, it defaults to the ``url`` in ``api.conf`` + ``/apiv2``. * ``CAPE_API_TOKEN``: (Optional) Your API token. Recommended to set this in the **Client Configuration** (e.g. ``claude_desktop_config.json``) rather than your system's global environment variables to ensure isolation. * ``CAPE_ALLOWED_SUBMISSION_DIR``: (Optional) Restricts ``submit_file`` to a specific local directory for security. Defaults to the current working directory. +* ``CAPE_MCP_TRANSPORT``: (Optional) The transport protocol to use (``stdio``, ``sse``, ``streamable-http``, ``http``). Defaults to ``stdio``. +* ``CAPE_MCP_HOST``: (Optional) Host to bind for network transports. Defaults to ``127.0.0.1``. +* ``CAPE_MCP_PORT``: (Optional) Port to bind for network transports. Defaults to ``8000``. Granular Tool Control (``api.conf``) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -115,6 +118,7 @@ Scenario B: Remote / Shared Server (SSE) In this mode, a single MCP server instance runs continuously and accepts connections from multiple clients over the network. +0. **Execution:** Start the server using ``python3 web/mcp_server.py --transport sse``. 1. **Configuration:** Start the server **without** a ``CAPE_API_TOKEN`` environment variable. 2. **Strict Mode:** Ensure ``token_auth_enabled = yes`` is set in ``conf/api.conf``. 3. **Usage:** Users **must** provide their API token in the ``token`` argument for every tool call (e.g., ``submit_file(..., token="MyKey")``). @@ -133,13 +137,45 @@ If ``token_auth_enabled = yes`` and no token is found in either location, the re Running the Server ------------------ -Standard execution -~~~~~~~~~~~~~~~~~~ +Standard execution (Stdio) +~~~~~~~~~~~~~~~~~~~~~~~~~~ .. code-block:: bash CAPE_API_URL=http://your-cape-ip:8000/apiv2 CAPE_API_TOKEN=your_token python3 web/mcp_server.py +Remote / SSE execution +~~~~~~~~~~~~~~~~~~~~~~ + +To run the server as a persistent service accessible over the network: + +.. code-block:: bash + + python3 web/mcp_server.py --transport sse --port 9004 + +Deployment behind Nginx +~~~~~~~~~~~~~~~~~~~~~~~ + +When running behind an Nginx reverse proxy, you **must** expose both the ``/sse`` and ``/messages`` endpoints and disable buffering to allow the event stream to function. + +.. code-block:: nginx + + location /sse { + proxy_pass http://127.0.0.1:9004/sse; + proxy_http_version 1.1; + proxy_set_header Connection ""; + proxy_buffering off; + proxy_cache off; + proxy_read_timeout 24h; + } + + location /messages { + proxy_pass http://127.0.0.1:9004/messages; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_buffering off; + } + Client Integrations ------------------- diff --git a/web/mcp_server.py b/web/mcp_server.py index 93bd01cd172..af67407bf0f 100644 --- a/web/mcp_server.py +++ b/web/mcp_server.py @@ -562,4 +562,16 @@ async def verify_auth(token: str = "") -> str: return json.dumps({"authenticated": True, "message": "Token is valid.", "user": "Authenticated User"}, indent=2) if __name__ == "__main__": - mcp.run() + import argparse + + parser = argparse.ArgumentParser(description="CAPE MCP Server") + parser.add_argument("--transport", choices=["stdio", "sse", "streamable-http", "http"], default=os.environ.get("CAPE_MCP_TRANSPORT", "stdio"), help="Transport protocol (default: stdio)") + parser.add_argument("--host", default=os.environ.get("CAPE_MCP_HOST", "127.0.0.1"), help="Host to bind for HTTP/SSE (default: 127.0.0.1)") + parser.add_argument("--port", type=int, default=int(os.environ.get("CAPE_MCP_PORT", "8000")), help="Port to bind for HTTP/SSE (default: 8000)") + args = parser.parse_args() + + if args.transport in ["sse", "streamable-http", "http"]: + print(f"Starting {args.transport} server on {args.host}:{args.port}", file=sys.stderr) + mcp.run(transport=args.transport, host=args.host, port=args.port) + else: + mcp.run(transport="stdio")