An MCP server for marketing messaging grounding and asset generation via Prefab
MsgStack is an MCP server that provides a structured organizational canon layer for AI grounding. It allows departments to curate approved content (po...
1mcp = FastMCP("MsgStack")
2
3@mcp.tool()
4def search_canon(
5 query: str,
6 section_types: Optional[list[str]] = None,
7 ...
8) -> dict:
9 ...
10 return result// Network-exposed MCP server with no authentication. Any network attacker can call all tools.
397@mcp.tool()
398def generate_artifact(
399 skill_id: str,
400 domain_id: Optional[str] = None,
401 domain_name: Optional[str] = None,
402 custom_context: Optional[dict] = None,
403 ...
404) -> str:
405 ...
406 generator = ArtifactGenerator(store, skills)
407 artifact = generator.generate(skill_id, str(house.id), provided)// Network-exposed MCP server. Attacker can call generate_artifact with arbitrary custom_context.
354def _resolve_house(store, house_id: Optional[str], house_name: Optional[str] = None):
355 from uuid import UUID as _UUID
356 house = None
357 if house_id:
358 try:
359 house = store.get_house(_UUID(house_id))
360 except (ValueError, AttributeError):
361 pass
362 if house is None and house_name:
363 house = store.get_house_by_name(house_name)
364 if house is None and house_id:
365 house = store.get_house_by_name(house_id)
366 return house// Network-exposed MCP server. Attacker can call tools with arbitrary domain_id/domain_name.
650@mcp.tool()
651def export_to_penpot(
652 artifact_id: str,
653 workspace_id: str,
654 domain_id: Optional[str] = None,
655 house_id: Optional[str] = None,
656) -> dict:
657 ...
658 return grounding_tools.export_to_penpot(artifact_id, workspace_id, actual_id)// Network-exposed MCP server. Attacker can call export_to_penpot with arbitrary IDs.
677@mcp.tool()
678def set_penpot_project(workspace_id: str, project_id: str) -> dict:
679 ...
680 return grounding_tools.set_penpot_project(workspace_id, project_id)// Network-exposed MCP server. Attacker can call set_penpot_project with arbitrary IDs.
240if not department or h.get("department", "General").lower() == department.lower()
241...
242return res// Network-exposed MCP server. Attacker can call list_canon_domains with arbitrary department values.
908@mcp.tool()
909def get_graph_connections(
910 domain_id: Optional[str] = None,
911 persona: Optional[str] = None,
912 channel: Optional[str] = None,
913 house_id: Optional[str] = None,
914) -> dict:
915 ...
916 chunks = engine.get_connections(actual_id, persona=persona, channel=channel)// Network-exposed MCP server. Attacker can call get_graph_connections with arbitrary persona/channel.