@tanskong/office-mcp 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "@tanskong/office-mcp",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "Excel实时办公助手 MCP服务器",
5
5
  "bin": {
6
6
  "office-mcp": "./bin/office-mcp.js"
7
7
  },
8
8
  "scripts": {
9
- "start": "node bin/office-mcp.js"
9
+ "start": "node bin/office-mcp.js",
10
+ "activate": "python src/activate.py"
10
11
  },
11
12
  "files": [
12
13
  "bin",
@@ -0,0 +1,144 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Office MCP License Activation System
4
+ =====================================
5
+ 1. Student activates with license key
6
+ 2. System captures MAC address and machine fingerprint
7
+ 3. Saves activation record locally
8
+ 4. On every startup, verifies MAC address matches
9
+ """
10
+
11
+ import os
12
+ import sys
13
+ import json
14
+ import hashlib
15
+ import uuid
16
+ import socket
17
+ import subprocess
18
+ from datetime import datetime
19
+
20
+ ACTIVATION_FILE = "activation.dat"
21
+
22
+ def get_mac_address():
23
+ """获取本机MAC地址"""
24
+ mac = ':'.join(['{:02x}'.format((uuid.getnode() >> i) & 0xff) for i in range(0, 48, 8)][::-1])
25
+ return mac.upper().replace(':', '')
26
+
27
+ def get_machine_fingerprint():
28
+ """获取机器指纹(MAC + 主机名 + CPU ID)"""
29
+ mac = get_mac_address()
30
+ hostname = socket.gethostname()
31
+ try:
32
+ result = subprocess.run(['wmic', 'cpu', 'get', 'ProcessorId'], capture_output=True, text=True)
33
+ cpu_id = result.stdout.strip().split('\n')[-1].strip()
34
+ except:
35
+ cpu_id = 'CPU-UNKNOWN'
36
+ combined = f"{mac}|{hostname}|{cpu_id}"
37
+ return hashlib.sha256(combined.encode()).hexdigest()[:32].upper()
38
+
39
+ def get_license_key():
40
+ """获取设置的许可证KEY"""
41
+ return os.environ.get("OFFICE_MCP_LICENSE", "")
42
+
43
+ def check_license_exists(key):
44
+ """检查KEY是否有效"""
45
+ script_dir = os.path.dirname(os.path.abspath(__file__))
46
+ license_file = os.path.join(script_dir, "..", "licenses.txt")
47
+ if not os.path.exists(license_file):
48
+ return False
49
+ with open(license_file, 'r') as f:
50
+ for line in f:
51
+ if line.strip().startswith(key):
52
+ return True
53
+ return False
54
+
55
+ def activate(key):
56
+ """激活许可证"""
57
+ print("\n" + "=" * 50)
58
+ print(" Office MCP Activation")
59
+ print("=" * 50)
60
+
61
+ if not key:
62
+ print("\n❌ No license key provided!")
63
+ print("\nPlease set environment variable OFFICE_MCP_LICENSE")
64
+ print(" Windows: set OFFICE_MCP_LICENSE=你的KEY")
65
+ print(" Linux/Mac: export OFFICE_MCP_LICENSE=你的KEY")
66
+ return False
67
+
68
+ if not check_license_exists(key):
69
+ print(f"\n❌ Invalid license key: {key}")
70
+ return False
71
+
72
+ if os.path.exists(ACTIVATION_FILE):
73
+ print("\n⚠️ Already activated!")
74
+ print(" To re-activate, delete activation.dat first")
75
+ return False
76
+
77
+ mac = get_mac_address()
78
+ fingerprint = get_machine_fingerprint()
79
+
80
+ activation_data = {
81
+ "license_key": key,
82
+ "mac_address": mac,
83
+ "fingerprint": fingerprint,
84
+ "activated_at": datetime.now().isoformat(),
85
+ "hostname": socket.gethostname()
86
+ }
87
+
88
+ with open(ACTIVATION_FILE, 'w') as f:
89
+ json.dump(activation_data, f, indent=2)
90
+
91
+ print("\n✅ Activation Successful!")
92
+ print(f"\n License Key: {key}")
93
+ print(f" MAC Address: {mac}")
94
+ print(f" Fingerprint: {fingerprint}")
95
+ print(f" Activated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
96
+ print("\n This computer is now bound to this license.")
97
+ print("=" * 50)
98
+ return True
99
+
100
+ def is_activated():
101
+ """检查是否已激活"""
102
+ return os.path.exists(ACTIVATION_FILE)
103
+
104
+ def verify_activation():
105
+ """验证激活状态"""
106
+ if not is_activated():
107
+ return False, "Not activated"
108
+
109
+ try:
110
+ with open(ACTIVATION_FILE, 'r') as f:
111
+ data = json.load(f)
112
+
113
+ current_mac = get_mac_address()
114
+ current_fingerprint = get_machine_fingerprint()
115
+ stored_mac = data.get("mac_address", "")
116
+ stored_fingerprint = data.get("fingerprint", "")
117
+
118
+ if current_mac != stored_mac:
119
+ return False, f"MAC changed! Original: {stored_mac}, Current: {current_mac}"
120
+
121
+ if current_fingerprint != stored_fingerprint:
122
+ return False, f"Fingerprint changed! This computer is no longer bound."
123
+
124
+ return True, "Activated"
125
+ except Exception as e:
126
+ return False, f"Verification failed: {str(e)}"
127
+
128
+ if __name__ == "__main__":
129
+ if len(sys.argv) > 1:
130
+ if sys.argv[1] == "--verify":
131
+ ok, msg = verify_activation()
132
+ print(f"\nActivation Status: {'✅ ' + msg if ok else '❌ ' + msg}")
133
+ sys.exit(0 if ok else 1)
134
+ elif sys.argv[1] == "--help":
135
+ print("\nOffice MCP Activation Tool")
136
+ print("\nUsage:")
137
+ print(" python activate.py --verify - Verify activation status")
138
+ print(" python activate.py --help - Show this help")
139
+ sys.exit(0)
140
+ else:
141
+ sys.exit(0 if activate(sys.argv[1]) else 1)
142
+ else:
143
+ key = get_license_key()
144
+ sys.exit(0 if activate(key) else 1)
@@ -7,8 +7,14 @@ Office MCP Server - Real-time Excel Control
7
7
  import json
8
8
  import sys
9
9
  import os
10
+ import hashlib
11
+ import uuid
12
+ import socket
13
+ import subprocess
10
14
  from pathlib import Path
11
15
 
16
+ ACTIVATION_FILE = os.path.join(os.environ.get("APPDATA", os.path.dirname(__file__)), "office-mcp", "activation.dat")
17
+
12
18
  import importlib.metadata
13
19
  orig_version = importlib.metadata.version
14
20
  importlib.metadata.version = lambda name: "3.1.1" if name == "fastmcp" else orig_version(name)
@@ -23,9 +29,61 @@ except Exception as e:
23
29
 
24
30
  MCP = FastMCP("Office Server")
25
31
 
32
+ LICENSE_FILE = os.path.join(os.environ.get("APPDATA", os.path.dirname(__file__)), "office-mcp", "licenses.txt")
33
+
34
+ def get_mac_address():
35
+ """获取本机MAC地址"""
36
+ mac = ':'.join(['{:02x}'.format((uuid.getnode() >> i) & 0xff) for i in range(0, 48, 8)][::-1])
37
+ return mac.upper().replace(':', '')
38
+
39
+ def get_machine_fingerprint():
40
+ """获取机器指纹(MAC + 主机名 + CPU ID)"""
41
+ mac = get_mac_address()
42
+ hostname = socket.gethostname()
43
+ try:
44
+ result = subprocess.run(['wmic', 'cpu', 'get', 'ProcessorId'], capture_output=True, text=True)
45
+ cpu_id = result.stdout.strip().split('\n')[-1].strip()
46
+ except:
47
+ cpu_id = 'CPU-UNKNOWN'
48
+ combined = f"{mac}|{hostname}|{cpu_id}"
49
+ return hashlib.sha256(combined.encode()).hexdigest()[:32].upper()
50
+
51
+ def verify_license():
52
+ """验证许可证(本地MAC绑定)"""
53
+
54
+ if not os.path.exists(ACTIVATION_FILE):
55
+ raise Exception(f"❌ 未激活!\n\n请先激活:\n1. 确保设置了环境变量 OFFICE_MCP_LICENSE=你的KEY\n2. 运行: python activate.py\n\n激活文件路径: {ACTIVATION_FILE}\n\n或联系管理员获取激活码")
56
+
57
+ try:
58
+ with open(ACTIVATION_FILE, 'r') as f:
59
+ data = json.load(f)
60
+
61
+ current_mac = get_mac_address()
62
+ current_fingerprint = get_machine_fingerprint()
63
+ stored_mac = data.get("mac_address", "")
64
+ stored_fingerprint = data.get("fingerprint", "")
65
+ license_key = data.get("license_key", "")
66
+
67
+ if current_mac != stored_mac:
68
+ raise Exception(f"❌ 许可证不匹配此电脑!\n\n此许可证已绑定到其他电脑。\nMAC地址变更:\n 原电脑: {stored_mac}\n 本电脑: {current_mac}\n\n如需重新激活,请联系管理员")
69
+
70
+ if current_fingerprint != stored_fingerprint:
71
+ raise Exception("❌ 机器指纹验证失败!\n\n此许可证已绑定到其他电脑。\n请联系管理员重新获取激活码")
72
+
73
+ print(f"License verified: {license_key[:10]}... (MAC bound)")
74
+
75
+ except json.JSONDecodeError:
76
+ raise Exception(f"❌ 激活文件损坏!\n\n请删除 {ACTIVATION_FILE} 后重新激活")
77
+
26
78
  def run_mcp():
27
79
  MCP.run(transport="stdio")
28
80
 
81
+ if __name__ == "__main__":
82
+ print("Office MCP Server v2.1 - Activating...")
83
+ verify_license()
84
+ print("Activation verified. Starting server...")
85
+ run_mcp()
86
+
29
87
  def show_window(icon, item):
30
88
  import win32api
31
89
  import win32con