diff --git a/deployment/Dockerfile-aws b/deployment/Dockerfile-aws new file mode 100644 index 00000000..df4cd814 --- /dev/null +++ b/deployment/Dockerfile-aws @@ -0,0 +1,25 @@ +# Use the command `make build` to build this image. +# Use conda-forge base image consistently across local/CI. +FROM condaforge/miniforge3:23.11.0-0 + +WORKDIR /flowcept + +COPY pyproject.toml Makefile README.md ./ +COPY src ./src +COPY resources ./resources +COPY notebooks ./notebooks +COPY tests ./tests +COPY examples ./examples + +# Create env + install flowcept +RUN conda create -n flowcept python=3.11.10 -y && \ + conda run -n flowcept pip install -e .[lmdb,telemetry,dev,llm_agent,extras] + +# Set env variables properly +ENV FLOWCEPT_SETTINGS_PATH=/flowcept/resources/sample_settings.yaml + +# Expose MCP port +EXPOSE 8003 + +# Start agent directly +CMD ["conda", "run", "--no-capture-output", "-n", "flowcept", "flowcept", "--start-agent"] diff --git a/deployment/docker-compose-local.yaml b/deployment/docker-compose-local.yaml new file mode 100644 index 00000000..e69de29b diff --git a/resources/sample_settings.yaml b/resources/sample_settings.yaml index 01600c0e..341071d1 100644 --- a/resources/sample_settings.yaml +++ b/resources/sample_settings.yaml @@ -1,4 +1,4 @@ -flowcept_version: 0.10.5 # Version of the Flowcept package. Do not update this manually. The CI updates it. This setting file is compatible with this version. +flowcept_version: 0.10.9 # Version of the Flowcept package. Do not update this manually. The CI updates it. This setting file is compatible with this version. project: debug: true # Toggle debug mode. This will add a property `debug: true` to all saved data, making it easier to retrieve/delete them later. @@ -93,8 +93,8 @@ agent: enabled: false mcp_host: localhost mcp_port: 8000 - allowed_hosts: - - "0.1.2.3:*" + mcp_allowed_hosts: ["localhost:*", "127.0.0.1:*"] # Default is ["localhost:*", "127.0.0.1:*"] + mcp_allowed_origins: ["http://localhost:*", "http://127.0.0.1:*"] # Default is ["http://localhost:*", "http://127.0.0.1:*"] llm_server_url: '?' api_key: '?' model: '?' diff --git a/src/flowcept/agents/flowcept_agent.py b/src/flowcept/agents/flowcept_agent.py index 694ae605..8f9705bd 100644 --- a/src/flowcept/agents/flowcept_agent.py +++ b/src/flowcept/agents/flowcept_agent.py @@ -152,7 +152,13 @@ def main(): """ agent = FlowceptAgent().start() # Wake up tool call - print(run_tool(check_liveness, host=AGENT_HOST, port=AGENT_PORT)[0]) + # Flowcept liveness check was calling: http://0.0.0.0:8003/mcp + # This caused error: + # httpx.HTTPStatusError: Client error '421 Misdirected Request' for url 'http://0.0.0.0:8003/mcp' + # The server binds to AGENT_HOST, but wildcard bind addresses (0.0.0.0, ::) are not routable + # as a client destination, so fall back to localhost; otherwise honor the configured host. + liveness_host = "localhost" if AGENT_HOST in ("0.0.0.0", "::", "") else AGENT_HOST + print(run_tool(check_liveness, host=liveness_host, port=AGENT_PORT)[0]) agent.wait() diff --git a/src/flowcept/agents/flowcept_ctx_manager.py b/src/flowcept/agents/flowcept_ctx_manager.py index 8a974496..98626bc7 100644 --- a/src/flowcept/agents/flowcept_ctx_manager.py +++ b/src/flowcept/agents/flowcept_ctx_manager.py @@ -3,7 +3,7 @@ from flowcept.commons.flowcept_dataclasses.task_object import TaskObject from flowcept.commons.flowcept_logger import FlowceptLogger from flowcept.commons.vocabulary import Status -from flowcept.configs import AGENT +from flowcept.configs import AGENT, MCP_ALLOWED_ORIGINS, MCP_ALLOWED_HOSTS from mcp.server.fastmcp import FastMCP import json @@ -286,12 +286,13 @@ def monitor_chunk(self): ctx_manager = FlowceptAgentContextManager() agent_transport_security = None -if "allowed_hosts" in AGENT: +if "mcp_allowed_hosts" in AGENT: from mcp.server.transport_security import TransportSecuritySettings agent_transport_security = TransportSecuritySettings( enable_dns_rebinding_protection=True, - allowed_hosts=AGENT.get("allowed_hosts"), + allowed_hosts=MCP_ALLOWED_HOSTS, + allowed_origins=MCP_ALLOWED_ORIGINS, ) mcp_flowcept = FastMCP( diff --git a/src/flowcept/configs.py b/src/flowcept/configs.py index 4bb30a15..db6947e7 100644 --- a/src/flowcept/configs.py +++ b/src/flowcept/configs.py @@ -3,6 +3,7 @@ import os import socket import getpass +import json from flowcept.version import __version__ @@ -45,6 +46,16 @@ def _get_env_bool(name: str, default=False) -> bool: return str(_get_env(name, str(default))).strip().lower() in _TRUE_VALUES +def _get_env_list(name: str, default: list[str]) -> list[str]: + raw = os.getenv(name) + if not raw: + return default + try: + return json.loads(raw) + except json.JSONDecodeError: + raise ValueError(f"{name} must be valid JSON array") + + if USE_DEFAULT: settings = DEFAULT_SETTINGS.copy() SETTINGS_PATH = "FLOWCEPT_DEFAULT_SETTINGS" @@ -272,6 +283,10 @@ def _get_env_bool(name: str, default=False) -> bool: AGENT_AUDIO = _get_env_bool("AGENT_AUDIO", settings["agent"].get("audio_enabled", "false")) AGENT_HOST = _get_env("AGENT_HOST", settings["agent"].get("mcp_host", "localhost")) AGENT_PORT = int(_get_env("AGENT_PORT", settings["agent"].get("mcp_port", "8000"))) +MCP_ALLOWED_HOSTS = _get_env_list("MCP_ALLOWED_HOSTS", AGENT.get("mcp_allowed_hosts", ["localhost:*", "127.0.0.1:*"])) +MCP_ALLOWED_ORIGINS = _get_env_list( + "MCP_ALLOWED_ORIGINS", AGENT.get("mcp_allowed_origins", ["http://localhost:*", "http://127.0.0.1:*"]) +) #################### # Enabled ADAPTERS # diff --git a/src/flowcept/version.py b/src/flowcept/version.py index a1465a17..61f3f873 100644 --- a/src/flowcept/version.py +++ b/src/flowcept/version.py @@ -7,4 +7,4 @@ # See .github/workflows/version_bumper.py # ✋⚠️⛔❗❗❗ STOP! DANGER!!ONEONEELEVEN! Did you carefully read the warning above?! :) -__version__ = "0.10.5" +__version__ = "0.10.9"