diff --git a/src/fgai/graylog_mcp.py b/src/fgai/graylog_mcp.py index d5b37ec..f1e7799 100644 --- a/src/fgai/graylog_mcp.py +++ b/src/fgai/graylog_mcp.py @@ -20,9 +20,9 @@ class GraylogMcpClient: payload["id"] = 1 if params is not None: payload["params"] = params - credentials = base64.b64encode(f"{self.token}:token".encode("utf-8")).decode("ascii") + authorization = self._authorization_header() headers = { - "Authorization": f"Basic {credentials}", + "Authorization": authorization, "Content-Type": "application/json", "Accept": "application/json, text/event-stream", } @@ -49,6 +49,20 @@ class GraylogMcpClient: raise RuntimeError(f"mcp_error: {response_data['error']}") return response_data + def _authorization_header(self) -> str: + """Accept a raw token or the Basic/Base64 form commonly copied from MCP clients.""" + value = self.token.strip() + if value.lower().startswith("basic "): + return value + try: + decoded = base64.b64decode(value, validate=True).decode("utf-8") + except (ValueError, UnicodeDecodeError): + decoded = "" + if decoded.endswith(":token"): + return f"Basic {value}" + credentials = base64.b64encode(f"{value}:token".encode("utf-8")).decode("ascii") + return f"Basic {credentials}" + def probe(self) -> dict[str, object]: initialized = self._call( "initialize", diff --git a/tests/test_graylog_mcp.py b/tests/test_graylog_mcp.py index caeb949..47097ce 100644 --- a/tests/test_graylog_mcp.py +++ b/tests/test_graylog_mcp.py @@ -21,6 +21,12 @@ class _Response: class GraylogMcpTests(unittest.TestCase): + def test_accepts_raw_or_copied_basic_credentials(self): + raw = GraylogMcpClient("http://graylog/api/mcp", "raw-token")._authorization_header() + encoded = raw.removeprefix("Basic ") + self.assertEqual(GraylogMcpClient("http://graylog/api/mcp", encoded)._authorization_header(), raw) + self.assertEqual(GraylogMcpClient("http://graylog/api/mcp", raw)._authorization_header(), raw) + def test_probe_initializes_and_lists_tools(self): responses = iter([ _Response({"result": {"serverInfo": {"version": "7.1.6"}}}),