fix(gx-cli mcp): expone notes/append_notes en MCP y bloquea regresion
Bug encontrado por el agente Echo: el MCP server gx-cli (subcomando `mcp-server`) llamaba a cmd_node_create / cmd_node_update con un SimpleNamespace que NO incluia `notes`, asi que `args.notes` lanzaba AttributeError. Causa raiz: MCP_DISPATCH no defaulteaba `notes` ni `append_notes`, y el inputSchema de las tools tampoco los anunciaba. Cambios: * MCP_TOOLS["node_create"].inputSchema.properties anyade `notes`. * MCP_TOOLS["node_update"].inputSchema.properties anyade `notes` + `append_notes` (boolean, default false). * MCP_DISPATCH["node_create"] defaultea `notes: None`. * MCP_DISPATCH["node_update"] defaultea `notes: None`, `append_notes: False`. Tests nuevos en tests/test_gx_cli.py (30 tests): * CLI: node create/update/delete con notes (replace + append), list/show/search, rel create/list/delete con cascada, query read-only que rechaza writes, autodetect de tipos. * MCP dispatcher: cada cmd_* tolera args opcionales omitidos, notes y append_notes funcionan via dispatch, MCP_TOOLS y MCP_DISPATCH coinciden 1:1 (sanity contractual). * Regresion 0035d: tests dedicados que congelan el contrato notes/append_notes en defaults e inputSchema — si alguien vuelve a quitarlos el test se queja inmediatamente. WSL 74 / Windows 63 + 11 skipped.
This commit is contained in:
@@ -726,20 +726,24 @@ MCP_TOOLS = [
|
||||
"limit": {"type": "integer", "default": 50, "minimum": 1, "maximum": 200}},
|
||||
"required": ["query"]}},
|
||||
{"name": "node_create",
|
||||
"description": "Crea una entidad nueva. Si type se omite, se infiere heuristicamente del name (email/url/domain/ip/phone/text).",
|
||||
"description": "Crea una entidad nueva. Si type se omite, se infiere heuristicamente del name (email/url/domain/ip/phone/text). Pasa `notes` para inicializar el panel Note del nodo (es lo que leen los enrichers split_sentences y extract_iocs_text como fuente de texto).",
|
||||
"inputSchema": {"type": "object", "properties": {
|
||||
"name": {"type": "string"},
|
||||
"type": {"type": "string", "description": "Opcional. Auto-detectado si se omite."},
|
||||
"description": {"type": "string"}},
|
||||
"description": {"type": "string"},
|
||||
"notes": {"type": "string", "description": "Texto largo libre del nodo (panel Note)."}},
|
||||
"required": ["name"]}},
|
||||
{"name": "node_update",
|
||||
"description": "Modifica campos de una entidad existente. Al menos un campo aparte de id debe pasarse.",
|
||||
"description": "Modifica campos de una entidad existente. Al menos un campo aparte de id debe pasarse. `notes` reemplaza el contenido completo del panel Note; combinalo con `append_notes=true` para anyadir al final preservando lo existente.",
|
||||
"inputSchema": {"type": "object", "properties": {
|
||||
"id": {"type": "string"},
|
||||
"name": {"type": "string"},
|
||||
"type": {"type": "string"},
|
||||
"status": {"type": "string", "enum": ["active", "stale", "corrupted", "archived"]},
|
||||
"description": {"type": "string"},
|
||||
"notes": {"type": "string", "description": "Texto del panel Note. Reemplaza el contenido salvo que append_notes=true."},
|
||||
"append_notes": {"type": "boolean", "default": False,
|
||||
"description": "Si true, anyade `notes` al final con doble newline en vez de reemplazar."},
|
||||
"tags": {"type": "string", "description": "JSON array literal o CSV 'a,b,c'"}},
|
||||
"required": ["id"]}},
|
||||
{"name": "node_delete",
|
||||
@@ -830,9 +834,11 @@ MCP_DISPATCH = {
|
||||
"node_list": (cmd_node_list, {"type": None, "status": None, "limit": 100}),
|
||||
"node_show": (cmd_node_show, {}),
|
||||
"node_search": (cmd_node_search, {"limit": 50}),
|
||||
"node_create": (cmd_node_create, {"type": None, "description": None}),
|
||||
"node_create": (cmd_node_create, {"type": None, "description": None,
|
||||
"notes": None}),
|
||||
"node_update": (cmd_node_update, {"name": None, "type": None,
|
||||
"status": None, "description": None,
|
||||
"notes": None, "append_notes": False,
|
||||
"tags": None}),
|
||||
"node_delete": (cmd_node_delete, {}),
|
||||
"rel_create": (cmd_rel_create, {"name": None}),
|
||||
|
||||
Reference in New Issue
Block a user