Repository navigation
Expand file tree
/
Copy pathserver.py
More file actions
104 lines (82 loc) · 3.11 KB
/
Copy pathserver.py
File metadata and controls
104 lines (82 loc) · 3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import uuid
from pathlib import Path
from mcp.server.fastmcp import FastMCP
from models import Node, Style
from xmind_parser import read_xmind, write_xmind
mcp = FastMCP("xmind-tools")
@mcp.tool()
def read_mindmap(path: str) -> dict:
"""读取 .xmind 文件,返回 JSON 树结构"""
return read_xmind(Path(path)).to_dict()
@mcp.tool()
def write_mindmap(path: str, tree: dict) -> dict:
"""写入完整 JSON 树到 .xmind 文件,文件不存在则创建。
tree 格式:{"id": "...", "title": "...", "style": {"bg": "#hex", "fg": "#hex", "branch": "#hex"}, "children": [...]}
style 字段均可选:bg=背景色, fg=文字色, branch=连线色,值为 hex 如 #ff0000
"""
write_xmind(Path(path), Node.from_dict(tree))
return {"ok": True}
def _find_node(root: Node, node_id: str) -> Node | None:
if root.id == node_id:
return root
for child in root.children:
found = _find_node(child, node_id)
if found:
return found
return None
@mcp.tool()
def add_node(path: str, parent_id: str, title: str, style: dict | None = None) -> dict:
"""在指定父节点下新增子节点,立即保存。
style 可选字段:bg=背景色, fg=文字色, branch=连线色,例如 {"bg": "#ff0000", "fg": "#ffffff"}
"""
root = read_xmind(Path(path))
parent = _find_node(root, parent_id)
if parent is None:
raise ValueError(f"parent_id {parent_id!r} not found")
new_id = str(uuid.uuid4())
new_node = Node(id=new_id, title=title)
if style:
new_node.style = Style(**{k: v for k, v in style.items() if k in ("bg", "fg", "branch")})
parent.children.append(new_node)
write_xmind(Path(path), root)
return {"id": new_id}
@mcp.tool()
def update_node(path: str, node_id: str, title: str | None = None, style: dict | None = None) -> dict:
"""修改节点标题或样式,立即保存。
style 可选字段:bg=背景色, fg=文字色, branch=连线色,例如 {"bg": "#ff0000"}
只传入需要修改的字段,其余保持原样。
"""
root = read_xmind(Path(path))
node = _find_node(root, node_id)
if node is None:
raise ValueError(f"node_id {node_id!r} not found")
if title is not None:
node.title = title
if style is not None:
existing = node.style or Style()
for k, v in style.items():
if k in ("bg", "fg", "branch"):
setattr(existing, k, v)
node.style = existing
write_xmind(Path(path), root)
return {"ok": True}
@mcp.tool()
def delete_node(path: str, node_id: str) -> dict:
"""删除节点,立即保存"""
root = read_xmind(Path(path))
def _remove(parent: Node) -> bool:
for i, child in enumerate(parent.children):
if child.id == node_id:
parent.children.pop(i)
return True
if _remove(child):
return True
return False
if not _remove(root):
raise ValueError(f"node_id {node_id!r} not found")
write_xmind(Path(path), root)
return {"ok": True}
def main():
mcp.run()
if __name__ == "__main__":
main()