Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gemini/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"mcpServers": {
"cape_sandbox": {
"url": "http://127.0.0.1:9004/sse",
"type": "sse"
}
}
}
40 changes: 38 additions & 2 deletions docs/book/src/usage/mcp.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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``)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -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")``).
Expand All @@ -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
-------------------

Expand Down
8 changes: 5 additions & 3 deletions utils/dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down
14 changes: 13 additions & 1 deletion web/mcp_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")