workfullcircle-mcp 1.0.1
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/bin/workfullcircle-mcp.js +59 -0
- package/package.json +26 -0
- package/src/auth.js +11 -0
- package/src/config-writer.js +104 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { validateToken } = require('../src/auth');
|
|
4
|
+
const { getTargets, writeConfig } = require('../src/config-writer');
|
|
5
|
+
|
|
6
|
+
const args = process.argv.slice(2);
|
|
7
|
+
|
|
8
|
+
function printUsage() {
|
|
9
|
+
console.log('Usage: workfullcircle-mcp install --token uam_...');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function parseArgs(argv) {
|
|
14
|
+
if (argv.length < 2) {
|
|
15
|
+
printUsage();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const command = argv[0];
|
|
19
|
+
const tokenIndex = argv.indexOf('--token');
|
|
20
|
+
const token = tokenIndex !== -1 ? argv[tokenIndex + 1] : null;
|
|
21
|
+
const projectIndex = argv.indexOf('--project');
|
|
22
|
+
const projectId = projectIndex !== -1 ? argv[projectIndex + 1] : null;
|
|
23
|
+
|
|
24
|
+
if (command !== 'install' || !token) {
|
|
25
|
+
printUsage();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const validation = validateToken(token);
|
|
29
|
+
if (!validation.valid) {
|
|
30
|
+
console.error(`Error: ${validation.error}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return { token, projectId };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function install(token, projectId) {
|
|
38
|
+
const targets = getTargets();
|
|
39
|
+
let updated = 0;
|
|
40
|
+
targets.forEach((target) => {
|
|
41
|
+
if (!target.path) return;
|
|
42
|
+
const result = writeConfig(target, token, projectId);
|
|
43
|
+
if (result.success) {
|
|
44
|
+
console.log(`Updated ${target.name} config.`);
|
|
45
|
+
updated += 1;
|
|
46
|
+
} else {
|
|
47
|
+
console.warn(`Skipping ${target.name}: ${result.error}`);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
if (updated === 0) {
|
|
52
|
+
console.log('No configs found. Please create a config file manually.');
|
|
53
|
+
} else {
|
|
54
|
+
console.log('Setup complete. Restart your IDE to load WorkFullCircle.');
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const { token, projectId } = parseArgs(args);
|
|
59
|
+
install(token, projectId);
|
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "workfullcircle-mcp",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "WorkFullCircle MCP installer CLI",
|
|
5
|
+
"bin": {
|
|
6
|
+
"workfullcircle-mcp": "bin/workfullcircle-mcp.js"
|
|
7
|
+
},
|
|
8
|
+
"main": "bin/workfullcircle-mcp.js",
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node bin/workfullcircle-mcp.js"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"mcp",
|
|
14
|
+
"workfullcircle",
|
|
15
|
+
"installer",
|
|
16
|
+
"cli"
|
|
17
|
+
],
|
|
18
|
+
"author": "Afreensiyad",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"fs-extra": "^11.2.0"
|
|
22
|
+
},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=16.0.0"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/auth.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function validateToken(token) {
|
|
2
|
+
if (!token) {
|
|
3
|
+
return { valid: false, error: 'Token is required.' };
|
|
4
|
+
}
|
|
5
|
+
if (!token.startsWith('uam_')) {
|
|
6
|
+
return { valid: false, error: 'Token must start with uam_.' };
|
|
7
|
+
}
|
|
8
|
+
return { valid: true };
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
module.exports = { validateToken };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
function getTargets() {
|
|
6
|
+
const home = os.homedir();
|
|
7
|
+
return [
|
|
8
|
+
{
|
|
9
|
+
name: 'Claude Desktop',
|
|
10
|
+
path: os.platform() === 'win32'
|
|
11
|
+
? path.join(process.env.APPDATA || '', 'Claude', 'claude_desktop_config.json')
|
|
12
|
+
: path.join(home, 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json')
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'Cursor',
|
|
16
|
+
path: os.platform() === 'win32'
|
|
17
|
+
? path.join(process.env.APPDATA || '', 'Cursor', 'User', 'globalStorage', 'storage.json')
|
|
18
|
+
: path.join(home, '.cursor', 'mcp.json')
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'Windsurf',
|
|
22
|
+
path: os.platform() === 'win32'
|
|
23
|
+
? path.join(process.env.APPDATA || '', 'Windsurf', 'User', 'globalStorage', 'storage.json')
|
|
24
|
+
: path.join(home, '.windsurf', 'mcp.json')
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
name: 'VS Code',
|
|
28
|
+
path: os.platform() === 'win32'
|
|
29
|
+
? path.join(process.env.APPDATA || '', 'Code', 'User', 'globalStorage', 'storage.json')
|
|
30
|
+
: os.platform() === 'darwin'
|
|
31
|
+
? path.join(home, 'Library', 'Application Support', 'Code', 'User', 'globalStorage', 'storage.json')
|
|
32
|
+
: path.join(home, '.config', 'Code', 'User', 'globalStorage', 'storage.json')
|
|
33
|
+
}
|
|
34
|
+
];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function buildConfig(token, projectId) {
|
|
38
|
+
const args = [
|
|
39
|
+
'-y',
|
|
40
|
+
'workfullcircle-remote',
|
|
41
|
+
'https://workfullcircle.com/sse',
|
|
42
|
+
'--header',
|
|
43
|
+
`Authorization: Bearer ${token}`
|
|
44
|
+
];
|
|
45
|
+
if (projectId) {
|
|
46
|
+
args.push('--project', projectId);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
mcpServers: {
|
|
50
|
+
workfullcircle: {
|
|
51
|
+
command: 'npx',
|
|
52
|
+
args
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function mergeConfig(existing, token, projectId) {
|
|
59
|
+
const config = existing && typeof existing === 'object' ? existing : {};
|
|
60
|
+
if (!config.mcpServers) {
|
|
61
|
+
config.mcpServers = {};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Handle VS Code's different JSON structure
|
|
65
|
+
const workfullcircleConfig = buildConfig(token, projectId).mcpServers.workfullcircle;
|
|
66
|
+
if (existing.mcpServers && existing.mcpServers.workfullcircle) {
|
|
67
|
+
// VS Code might store in different format, merge properly
|
|
68
|
+
config.mcpServers.workfullcircle = {
|
|
69
|
+
...existing.mcpServers.workfullcircle,
|
|
70
|
+
...workfullcircleConfig
|
|
71
|
+
};
|
|
72
|
+
} else {
|
|
73
|
+
config.mcpServers.workfullcircle = workfullcircleConfig;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return config;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function writeConfig(target, token, projectId) {
|
|
80
|
+
const dir = path.dirname(target.path);
|
|
81
|
+
if (!fs.existsSync(dir)) {
|
|
82
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let existing = {};
|
|
86
|
+
if (fs.existsSync(target.path)) {
|
|
87
|
+
try {
|
|
88
|
+
existing = JSON.parse(fs.readFileSync(target.path, 'utf8'));
|
|
89
|
+
} catch (error) {
|
|
90
|
+
return { success: false, error: `Invalid JSON in ${target.path}` };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const merged = mergeConfig(existing, token, projectId);
|
|
95
|
+
fs.writeFileSync(target.path, JSON.stringify(merged, null, 2));
|
|
96
|
+
return { success: true };
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
module.exports = {
|
|
100
|
+
getTargets,
|
|
101
|
+
writeConfig,
|
|
102
|
+
buildConfig,
|
|
103
|
+
mergeConfig
|
|
104
|
+
};
|