Upload 214 files
Browse files- renderer_app.py +2 -1
- tests/test_mcp_metadata.py +14 -2
renderer_app.py
CHANGED
|
@@ -17,7 +17,8 @@ from renderer.templates import apply_creative_style, apply_preset, list_creative
|
|
| 17 |
|
| 18 |
def _mcp_description(summary: str, example: dict[str, Any]) -> str:
|
| 19 |
"""Build a concise MCP description with a machine-readable JSON example."""
|
| 20 |
-
|
|
|
|
| 21 |
|
| 22 |
|
| 23 |
def create_dashboard() -> gr.Blocks:
|
|
|
|
| 17 |
|
| 18 |
def _mcp_description(summary: str, example: dict[str, Any]) -> str:
|
| 19 |
"""Build a concise MCP description with a machine-readable JSON example."""
|
| 20 |
+
payload = json.dumps(example, indent=2, ensure_ascii=True)
|
| 21 |
+
return f"{summary}\n\nExample JSON:\n```json\n{payload}\n```"
|
| 22 |
|
| 23 |
|
| 24 |
def create_dashboard() -> gr.Blocks:
|
tests/test_mcp_metadata.py
CHANGED
|
@@ -14,6 +14,11 @@ class MCPMetadataTests(unittest.TestCase):
|
|
| 14 |
for node in tree.body
|
| 15 |
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
|
| 16 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
events = [
|
| 18 |
node
|
| 19 |
for node in ast.walk(tree)
|
|
@@ -45,8 +50,15 @@ class MCPMetadataTests(unittest.TestCase):
|
|
| 45 |
example = ast.literal_eval(description.args[1])
|
| 46 |
self.assertTrue(summary, f"Empty description: {callback_name}")
|
| 47 |
self.assertIsInstance(example, dict, f"Example must be an object: {callback_name}")
|
| 48 |
-
|
| 49 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 50 |
|
| 51 |
parameters = [argument.arg for argument in functions[callback_name].args.args]
|
| 52 |
self.assertEqual(set(example), set(parameters), f"Example keys do not match: {callback_name}")
|
|
|
|
| 14 |
for node in tree.body
|
| 15 |
if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef))
|
| 16 |
}
|
| 17 |
+
formatter_module = ast.Module(body=[functions["_mcp_description"]], type_ignores=[])
|
| 18 |
+
ast.fix_missing_locations(formatter_module)
|
| 19 |
+
namespace = {"json": json, "Any": object}
|
| 20 |
+
exec(compile(formatter_module, "renderer_app.py", "exec"), namespace)
|
| 21 |
+
format_description = namespace["_mcp_description"]
|
| 22 |
events = [
|
| 23 |
node
|
| 24 |
for node in ast.walk(tree)
|
|
|
|
| 50 |
example = ast.literal_eval(description.args[1])
|
| 51 |
self.assertTrue(summary, f"Empty description: {callback_name}")
|
| 52 |
self.assertIsInstance(example, dict, f"Example must be an object: {callback_name}")
|
| 53 |
+
|
| 54 |
+
rendered = format_description(summary, example)
|
| 55 |
+
marker = "\n\nExample JSON:\n```json\n"
|
| 56 |
+
self.assertIn(marker, rendered, f"Missing JSON code block: {callback_name}")
|
| 57 |
+
self.assertTrue(rendered.endswith("\n```"), f"Unclosed JSON code block: {callback_name}")
|
| 58 |
+
json_payload = rendered.split(marker, 1)[1][:-4]
|
| 59 |
+
self.assertEqual(json.loads(json_payload), example)
|
| 60 |
+
if example:
|
| 61 |
+
self.assertIn('\n "', json_payload, f"Example is not indented: {callback_name}")
|
| 62 |
|
| 63 |
parameters = [argument.arg for argument in functions[callback_name].args.args]
|
| 64 |
self.assertEqual(set(example), set(parameters), f"Example keys do not match: {callback_name}")
|