@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 +3 -2
- package/src/activate.py +144 -0
- package/src/office_server.py +58 -0
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanskong/office-mcp",
|
|
3
|
-
"version": "1.0.
|
|
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",
|
package/src/activate.py
ADDED
|
@@ -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)
|
package/src/office_server.py
CHANGED
|
@@ -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
|