From e2fc76cea067b8bee8fb88674ccd40f79badab5d Mon Sep 17 00:00:00 2001 From: KaifAhmad1 Date: Tue, 25 Aug 2026 16:18:33 +0530 Subject: [PATCH] fix(mcp): reject unsupported export_graph formats instead of mislabeling JSON _tool_export_graph fell through to json.dumps(kg) for any format outside the RDF set, including values never declared in the tool's own inputSchema enum. Nothing in this server validates tool-call args against inputSchema before dispatch, so a typo'd or unsupported format (e.g. "yaml") silently returned JSON data labeled with the wrong format and no error. Validate against the declared format list up front and reuse the same constant for the inputSchema enum so the two can't drift apart again. --- semantica/mcp_server/__init__.py | 9 ++++++++- tests/test_mcp_server_export_graph.py | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/semantica/mcp_server/__init__.py b/semantica/mcp_server/__init__.py index ebb4cc5c..248a5687 100644 --- a/semantica/mcp_server/__init__.py +++ b/semantica/mcp_server/__init__.py @@ -267,9 +267,16 @@ def _tool_get_graph_analytics(args: dict) -> dict: return {"error": str(exc)} +_EXPORT_GRAPH_FORMATS = ("turtle", "ttl", "nt", "xml", "json-ld", "json") + + def _tool_export_graph(args: dict) -> dict: """Export the current knowledge graph to a serialised format.""" fmt = args.get("format", "json-ld") + if fmt not in _EXPORT_GRAPH_FORMATS: + return { + "error": f"Unsupported format '{fmt}'. Supported: {', '.join(_EXPORT_GRAPH_FORMATS)}" + } graph = _get_graph() try: from semantica.export import RDFExporter @@ -453,7 +460,7 @@ TOOLS = [ "properties": { "format": { "type": "string", - "enum": ["turtle", "ttl", "nt", "xml", "json-ld", "json"], + "enum": list(_EXPORT_GRAPH_FORMATS), "description": "Export format (default: json-ld)", } }, diff --git a/tests/test_mcp_server_export_graph.py b/tests/test_mcp_server_export_graph.py index ca29f7c4..09179fd8 100644 --- a/tests/test_mcp_server_export_graph.py +++ b/tests/test_mcp_server_export_graph.py @@ -70,6 +70,21 @@ class TestExportGraphTool(unittest.TestCase): def test_progress_is_disabled_for_the_server_process(self): self.assertEqual(os.environ.get("SEMANTICA_DISABLE_PROGRESS"), "1") + def test_unsupported_format_returns_error_not_mislabeled_json(self): + """A format outside the declared enum (typo, unsupported value, or a + client that skips schema validation) must error, not silently return + JSON data mislabeled with the requested format string.""" + result = mcp_server._tool_export_graph({"format": "yaml"}) + self.assertIn("error", result) + self.assertIn("yaml", result["error"]) + + def test_export_graph_schema_enum_matches_handled_formats(self): + """The tool's declared inputSchema enum must not drift from the set + of formats the handler actually accepts.""" + tool = next(t for t in mcp_server.TOOLS if t["name"] == "export_graph") + schema_enum = set(tool["inputSchema"]["properties"]["format"]["enum"]) + self.assertEqual(schema_enum, set(mcp_server._EXPORT_GRAPH_FORMATS)) + if __name__ == "__main__": unittest.main()