@opencoop/opencode-plugin 1.0.0
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/LICENSE +178 -0
- package/README.fa.md +221 -0
- package/README.md +245 -0
- package/dist/auth/auth-manager.d.ts +45 -0
- package/dist/auth/auth-manager.js +157 -0
- package/dist/auth/auth-manager.js.map +1 -0
- package/dist/auth/session-manager.d.ts +14 -0
- package/dist/auth/session-manager.js +50 -0
- package/dist/auth/session-manager.js.map +1 -0
- package/dist/filesystem/change-tracker.d.ts +18 -0
- package/dist/filesystem/change-tracker.js +96 -0
- package/dist/filesystem/change-tracker.js.map +1 -0
- package/dist/filesystem/file-manager.d.ts +39 -0
- package/dist/filesystem/file-manager.js +189 -0
- package/dist/filesystem/file-manager.js.map +1 -0
- package/dist/filesystem/lock-manager.d.ts +15 -0
- package/dist/filesystem/lock-manager.js +120 -0
- package/dist/filesystem/lock-manager.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/server/mcp-server.d.ts +20 -0
- package/dist/server/mcp-server.js +392 -0
- package/dist/server/mcp-server.js.map +1 -0
- package/dist/types/index.d.ts +80 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/config.d.ts +3 -0
- package/dist/utils/config.js +38 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/database.d.ts +12 -0
- package/dist/utils/database.js +110 -0
- package/dist/utils/database.js.map +1 -0
- package/dist/utils/logger.d.ts +2 -0
- package/dist/utils/logger.js +11 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/web/public/assets/app.js +446 -0
- package/dist/web/public/assets/style.css +639 -0
- package/dist/web/public/index.html +190 -0
- package/dist/web/public/invite.html +132 -0
- package/dist/web/server.d.ts +3 -0
- package/dist/web/server.js +150 -0
- package/dist/web/server.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from "uuid";
|
|
2
|
+
import { runQuery, getAllRows, getRow, getScalar, } from "../utils/database.js";
|
|
3
|
+
const LOCK_TTL_MINUTES = 30;
|
|
4
|
+
export class LockManager {
|
|
5
|
+
async initialize() {
|
|
6
|
+
runQuery(`
|
|
7
|
+
CREATE TABLE IF NOT EXISTS file_locks (
|
|
8
|
+
id TEXT PRIMARY KEY,
|
|
9
|
+
workspace_id TEXT NOT NULL,
|
|
10
|
+
file_path TEXT NOT NULL,
|
|
11
|
+
user_id TEXT NOT NULL,
|
|
12
|
+
session_id TEXT NOT NULL,
|
|
13
|
+
lock_type TEXT DEFAULT 'exclusive',
|
|
14
|
+
reason TEXT,
|
|
15
|
+
acquired_at TEXT DEFAULT (datetime('now')),
|
|
16
|
+
expires_at TEXT NOT NULL,
|
|
17
|
+
UNIQUE(workspace_id, file_path)
|
|
18
|
+
)
|
|
19
|
+
`);
|
|
20
|
+
runQuery(`
|
|
21
|
+
CREATE INDEX IF NOT EXISTS idx_locks_workspace
|
|
22
|
+
ON file_locks(workspace_id)
|
|
23
|
+
`);
|
|
24
|
+
runQuery(`
|
|
25
|
+
CREATE INDEX IF NOT EXISTS idx_locks_user
|
|
26
|
+
ON file_locks(user_id)
|
|
27
|
+
`);
|
|
28
|
+
}
|
|
29
|
+
async acquireLock(params) {
|
|
30
|
+
await this.cleanupExpiredLocks(params.workspaceId);
|
|
31
|
+
const existingLock = getRow("SELECT * FROM file_locks WHERE workspace_id = ? AND file_path = ? AND user_id != ?", [params.workspaceId, params.filePath, params.userId]);
|
|
32
|
+
if (existingLock) {
|
|
33
|
+
if (new Date(existingLock.expires_at) > new Date()) {
|
|
34
|
+
return {
|
|
35
|
+
granted: false,
|
|
36
|
+
blockedBy: {
|
|
37
|
+
id: existingLock.id,
|
|
38
|
+
filePath: existingLock.file_path,
|
|
39
|
+
userId: existingLock.user_id,
|
|
40
|
+
userName: existingLock.user_id,
|
|
41
|
+
reason: existingLock.reason || "No reason provided",
|
|
42
|
+
acquiredAt: new Date(existingLock.acquired_at),
|
|
43
|
+
expiresAt: new Date(existingLock.expires_at),
|
|
44
|
+
},
|
|
45
|
+
message: `File is locked by another user. Reason: ${existingLock.reason || "Not specified"}`,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
runQuery("DELETE FROM file_locks WHERE workspace_id = ? AND file_path = ? AND user_id = ?", [params.workspaceId, params.filePath, params.userId]);
|
|
50
|
+
const lockId = uuidv4();
|
|
51
|
+
const expiresAt = new Date(Date.now() + LOCK_TTL_MINUTES * 60 * 1000);
|
|
52
|
+
runQuery(`INSERT INTO file_locks (id, workspace_id, file_path, user_id, session_id, reason, expires_at)
|
|
53
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`, [
|
|
54
|
+
lockId,
|
|
55
|
+
params.workspaceId,
|
|
56
|
+
params.filePath,
|
|
57
|
+
params.userId,
|
|
58
|
+
params.sessionId,
|
|
59
|
+
params.reason || null,
|
|
60
|
+
expiresAt.toISOString(),
|
|
61
|
+
]);
|
|
62
|
+
const lock = {
|
|
63
|
+
id: lockId,
|
|
64
|
+
filePath: params.filePath,
|
|
65
|
+
userId: params.userId,
|
|
66
|
+
userName: params.userId,
|
|
67
|
+
reason: params.reason || "",
|
|
68
|
+
acquiredAt: new Date(),
|
|
69
|
+
expiresAt,
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
granted: true,
|
|
73
|
+
lock,
|
|
74
|
+
message: `Lock acquired for: ${params.filePath}`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async releaseLock(workspaceId, filePath, userId) {
|
|
78
|
+
runQuery("DELETE FROM file_locks WHERE workspace_id = ? AND file_path = ? AND user_id = ?", [workspaceId, filePath, userId]);
|
|
79
|
+
}
|
|
80
|
+
async checkLock(workspaceId, filePath) {
|
|
81
|
+
const lock = getRow("SELECT * FROM file_locks WHERE workspace_id = ? AND file_path = ?", [workspaceId, filePath]);
|
|
82
|
+
if (!lock)
|
|
83
|
+
return null;
|
|
84
|
+
if (new Date(lock.expires_at) <= new Date()) {
|
|
85
|
+
runQuery("DELETE FROM file_locks WHERE id = ?", [lock.id]);
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
id: lock.id,
|
|
90
|
+
filePath: lock.file_path,
|
|
91
|
+
userId: lock.user_id,
|
|
92
|
+
userName: lock.user_id,
|
|
93
|
+
reason: lock.reason || "",
|
|
94
|
+
acquiredAt: new Date(lock.acquired_at),
|
|
95
|
+
expiresAt: new Date(lock.expires_at),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
async getActiveLocks(workspaceId) {
|
|
99
|
+
await this.cleanupExpiredLocks(workspaceId);
|
|
100
|
+
const locks = getAllRows("SELECT * FROM file_locks WHERE workspace_id = ? ORDER BY acquired_at DESC", [workspaceId]);
|
|
101
|
+
return locks.map((lock) => ({
|
|
102
|
+
id: lock.id,
|
|
103
|
+
filePath: lock.file_path,
|
|
104
|
+
userId: lock.user_id,
|
|
105
|
+
userName: lock.user_id,
|
|
106
|
+
reason: lock.reason || "",
|
|
107
|
+
acquiredAt: new Date(lock.acquired_at),
|
|
108
|
+
expiresAt: new Date(lock.expires_at),
|
|
109
|
+
}));
|
|
110
|
+
}
|
|
111
|
+
async cleanupExpiredLocks(workspaceId) {
|
|
112
|
+
runQuery("DELETE FROM file_locks WHERE workspace_id = ? AND expires_at <= datetime('now')", [workspaceId]);
|
|
113
|
+
}
|
|
114
|
+
async forceReleaseAll(workspaceId) {
|
|
115
|
+
const count = getScalar("SELECT COUNT(*) as value FROM file_locks WHERE workspace_id = ?", [workspaceId]);
|
|
116
|
+
runQuery("DELETE FROM file_locks WHERE workspace_id = ?", [workspaceId]);
|
|
117
|
+
return count || 0;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=lock-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lock-manager.js","sourceRoot":"","sources":["../../src/filesystem/lock-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { loadConfig } from "./utils/config.js";
|
|
2
|
+
import { logger } from "./utils/logger.js";
|
|
3
|
+
import { OpenCOOPServer } from "./server/mcp-server.js";
|
|
4
|
+
let serverInstance = null;
|
|
5
|
+
const server = async (input, options) => {
|
|
6
|
+
logger.info("OpenCOOP plugin loading...");
|
|
7
|
+
try {
|
|
8
|
+
const config = await loadConfig(input.project);
|
|
9
|
+
const port = config.port || 31313;
|
|
10
|
+
// Start the MCP server
|
|
11
|
+
serverInstance = new OpenCOOPServer(config);
|
|
12
|
+
await serverInstance.startHttp(port);
|
|
13
|
+
logger.info("OpenCOOP server started on port %d", port);
|
|
14
|
+
logger.info("MCP endpoint: http://localhost:%d/mcp", port);
|
|
15
|
+
logger.info("Web UI: http://localhost:%d", port);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
logger.error("Failed to start OpenCOOP: %s", error instanceof Error ? error.message : String(error));
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
dispose: async () => {
|
|
22
|
+
logger.info("OpenCOOP plugin disposing...");
|
|
23
|
+
if (serverInstance) {
|
|
24
|
+
await serverInstance.stop();
|
|
25
|
+
serverInstance = null;
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
const plugin = {
|
|
31
|
+
id: "opencoop",
|
|
32
|
+
server,
|
|
33
|
+
};
|
|
34
|
+
export default plugin;
|
|
35
|
+
export { OpenCOOPServer };
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,IAAI,cAAc,GAA0B,IAAI,CAAC;AAEjD,MAAM,MAAM,GAAG,KAAK,EAAE,KAAkB,EAAE,OAAiC,EAAkB,EAAE;IAC7F,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;IAE1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC/C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,KAAK,CAAC;QAElC,uBAAuB;QACvB,cAAc,GAAG,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;QAC5C,MAAM,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAErC,MAAM,CAAC,IAAI,CAAC,oCAAoC,EAAE,IAAI,CAAC,CAAC;QACxD,MAAM,CAAC,IAAI,CAAC,uCAAuC,EAAE,IAAI,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,6BAA6B,EAAE,IAAI,CAAC,CAAC;IACnD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACvG,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK,IAAI,EAAE;YAClB,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;YAC5C,IAAI,cAAc,EAAE,CAAC;gBACnB,MAAM,cAAc,CAAC,IAAI,EAAE,CAAC;gBAC5B,cAAc,GAAG,IAAI,CAAC;YACxB,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,MAAM,GAAiB;IAC3B,EAAE,EAAE,UAAU;IACd,MAAM;CACP,CAAC;AAEF,eAAe,MAAM,CAAC;AAEtB,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ServerConfig } from "../types/index.js";
|
|
2
|
+
export declare class OpenCOOPServer {
|
|
3
|
+
private config;
|
|
4
|
+
private fileManager;
|
|
5
|
+
private lockManager;
|
|
6
|
+
private changeTracker;
|
|
7
|
+
private authManager;
|
|
8
|
+
private sessionManager;
|
|
9
|
+
private transports;
|
|
10
|
+
private httpServer;
|
|
11
|
+
constructor(config: ServerConfig);
|
|
12
|
+
initialize(): Promise<void>;
|
|
13
|
+
private createMcpServer;
|
|
14
|
+
private registerFileTools;
|
|
15
|
+
private registerLockTools;
|
|
16
|
+
private registerMonitoringTools;
|
|
17
|
+
private registerTeamTools;
|
|
18
|
+
startHttp(port: number): Promise<void>;
|
|
19
|
+
stop(): Promise<void>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
3
|
+
import { randomUUID } from "crypto";
|
|
4
|
+
import express from "express";
|
|
5
|
+
import cors from "cors";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
import { FileManager } from "../filesystem/file-manager.js";
|
|
8
|
+
import { LockManager } from "../filesystem/lock-manager.js";
|
|
9
|
+
import { ChangeTracker } from "../filesystem/change-tracker.js";
|
|
10
|
+
import { AuthManager } from "../auth/auth-manager.js";
|
|
11
|
+
import { SessionManager } from "../auth/session-manager.js";
|
|
12
|
+
import { logger } from "../utils/logger.js";
|
|
13
|
+
import { initDatabase, startAutoSave, stopAutoSave } from "../utils/database.js";
|
|
14
|
+
import { createWebUI } from "../web/server.js";
|
|
15
|
+
export class OpenCOOPServer {
|
|
16
|
+
config;
|
|
17
|
+
fileManager;
|
|
18
|
+
lockManager;
|
|
19
|
+
changeTracker;
|
|
20
|
+
authManager;
|
|
21
|
+
sessionManager;
|
|
22
|
+
transports = new Map();
|
|
23
|
+
httpServer = null;
|
|
24
|
+
constructor(config) {
|
|
25
|
+
this.config = config;
|
|
26
|
+
}
|
|
27
|
+
async initialize() {
|
|
28
|
+
// Initialize database
|
|
29
|
+
await initDatabase(this.config.databasePath);
|
|
30
|
+
startAutoSave();
|
|
31
|
+
// Initialize managers
|
|
32
|
+
this.fileManager = new FileManager(this.config.workspacePath);
|
|
33
|
+
this.lockManager = new LockManager();
|
|
34
|
+
this.changeTracker = new ChangeTracker();
|
|
35
|
+
this.authManager = new AuthManager(this.config.jwtSecret);
|
|
36
|
+
this.sessionManager = new SessionManager();
|
|
37
|
+
// Initialize all tables
|
|
38
|
+
await this.lockManager.initialize();
|
|
39
|
+
await this.changeTracker.initialize();
|
|
40
|
+
await this.authManager.initialize();
|
|
41
|
+
await this.sessionManager.initialize();
|
|
42
|
+
logger.info("All managers initialized");
|
|
43
|
+
}
|
|
44
|
+
createMcpServer() {
|
|
45
|
+
const server = new McpServer({
|
|
46
|
+
name: "opencoop",
|
|
47
|
+
version: "1.0.0",
|
|
48
|
+
});
|
|
49
|
+
this.registerFileTools(server);
|
|
50
|
+
this.registerLockTools(server);
|
|
51
|
+
this.registerMonitoringTools(server);
|
|
52
|
+
this.registerTeamTools(server);
|
|
53
|
+
return server;
|
|
54
|
+
}
|
|
55
|
+
registerFileTools(server) {
|
|
56
|
+
server.tool("read_file", "Read the contents of a file in the shared project. Use this to view code, configs, or any text file.", {
|
|
57
|
+
path: z.string().describe("Relative file path from project root"),
|
|
58
|
+
start_line: z.number().optional().describe("Start line number (1-based)"),
|
|
59
|
+
end_line: z.number().optional().describe("End line number (1-based)"),
|
|
60
|
+
}, async ({ path, start_line, end_line }) => {
|
|
61
|
+
const userId = "user-" + randomUUID().slice(0, 8);
|
|
62
|
+
const content = await this.fileManager.readFile(path, {
|
|
63
|
+
startLine: start_line,
|
|
64
|
+
endLine: end_line,
|
|
65
|
+
});
|
|
66
|
+
await this.changeTracker.logChange({
|
|
67
|
+
workspaceId: this.config.workspacePath,
|
|
68
|
+
filePath: path,
|
|
69
|
+
userId,
|
|
70
|
+
action: "read",
|
|
71
|
+
});
|
|
72
|
+
return {
|
|
73
|
+
content: [{ type: "text", text: content }],
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
server.tool("write_file", "Create or overwrite a file in the shared project. This will be tracked in the audit log.", {
|
|
77
|
+
path: z.string().describe("Relative file path from project root"),
|
|
78
|
+
content: z.string().describe("Full file content to write"),
|
|
79
|
+
create_dirs: z.boolean().optional().describe("Create parent directories if they do not exist"),
|
|
80
|
+
}, async ({ path, content, create_dirs }) => {
|
|
81
|
+
const userId = "user-" + randomUUID().slice(0, 8);
|
|
82
|
+
await this.fileManager.writeFile(path, content, { createDirs: create_dirs });
|
|
83
|
+
await this.changeTracker.logChange({
|
|
84
|
+
workspaceId: this.config.workspacePath,
|
|
85
|
+
filePath: path,
|
|
86
|
+
userId,
|
|
87
|
+
action: "update",
|
|
88
|
+
newContentHash: await this.fileManager.hash(path),
|
|
89
|
+
});
|
|
90
|
+
return {
|
|
91
|
+
content: [{ type: "text", text: `File written successfully: ${path}` }],
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
server.tool("edit_file", "Make a targeted edit to a file using search and replace. Preferred over write_file for modifying existing files.", {
|
|
95
|
+
path: z.string().describe("Relative file path"),
|
|
96
|
+
search: z.string().describe("Exact text to find (must be unique in file)"),
|
|
97
|
+
replace: z.string().describe("Text to replace with"),
|
|
98
|
+
replace_all: z.boolean().optional().describe("Replace all occurrences (default: false)"),
|
|
99
|
+
}, async ({ path, search, replace, replace_all }) => {
|
|
100
|
+
const userId = "user-" + randomUUID().slice(0, 8);
|
|
101
|
+
const oldHash = await this.fileManager.hash(path);
|
|
102
|
+
const result = await this.fileManager.editFile(path, search, replace, {
|
|
103
|
+
replaceAll: replace_all,
|
|
104
|
+
});
|
|
105
|
+
const newHash = await this.fileManager.hash(path);
|
|
106
|
+
await this.changeTracker.logChange({
|
|
107
|
+
workspaceId: this.config.workspacePath,
|
|
108
|
+
filePath: path,
|
|
109
|
+
userId,
|
|
110
|
+
action: "update",
|
|
111
|
+
oldContentHash: oldHash,
|
|
112
|
+
newContentHash: newHash,
|
|
113
|
+
metadata: JSON.stringify({ changes: result.changes }),
|
|
114
|
+
});
|
|
115
|
+
return {
|
|
116
|
+
content: [
|
|
117
|
+
{
|
|
118
|
+
type: "text",
|
|
119
|
+
text: `Edit applied: ${result.changes} occurrence(s) replaced in ${path}`,
|
|
120
|
+
},
|
|
121
|
+
],
|
|
122
|
+
};
|
|
123
|
+
});
|
|
124
|
+
server.tool("list_files", "List files and directories in the shared project.", {
|
|
125
|
+
path: z.string().optional().describe("Directory path (default: project root)"),
|
|
126
|
+
recursive: z.boolean().optional().describe("List recursively"),
|
|
127
|
+
}, async ({ path, recursive }) => {
|
|
128
|
+
const files = await this.fileManager.listFiles(path || ".", { recursive });
|
|
129
|
+
return {
|
|
130
|
+
content: [{ type: "text", text: JSON.stringify(files, null, 2) }],
|
|
131
|
+
};
|
|
132
|
+
});
|
|
133
|
+
server.tool("search_files", "Search for files matching a glob pattern.", {
|
|
134
|
+
pattern: z.string().describe("Glob pattern (e.g., '**/*.ts', 'src/**/*.js')"),
|
|
135
|
+
max_results: z.number().optional().describe("Maximum results (default: 50)"),
|
|
136
|
+
}, async ({ pattern, max_results }) => {
|
|
137
|
+
const results = await this.fileManager.searchFiles(pattern, {
|
|
138
|
+
maxResults: max_results,
|
|
139
|
+
});
|
|
140
|
+
return {
|
|
141
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
server.tool("grep_content", "Search file contents using regex pattern.", {
|
|
145
|
+
pattern: z.string().describe("Regex pattern to search for"),
|
|
146
|
+
path: z.string().optional().describe("Directory to search in (default: project root)"),
|
|
147
|
+
include: z.string().optional().describe("File pattern to include (e.g., '*.ts')"),
|
|
148
|
+
}, async ({ pattern, path, include }) => {
|
|
149
|
+
const results = await this.fileManager.grep(pattern, { path, include });
|
|
150
|
+
return {
|
|
151
|
+
content: [{ type: "text", text: JSON.stringify(results, null, 2) }],
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
server.tool("directory_tree", "Get a tree view of the project directory structure.", {
|
|
155
|
+
path: z.string().optional().describe("Root path (default: project root)"),
|
|
156
|
+
max_depth: z.number().optional().describe("Maximum depth (default: 3)"),
|
|
157
|
+
exclude: z.array(z.string()).optional().describe("Patterns to exclude"),
|
|
158
|
+
}, async ({ path, max_depth, exclude }) => {
|
|
159
|
+
const tree = await this.fileManager.getDirectoryTree(path || ".", {
|
|
160
|
+
maxDepth: max_depth,
|
|
161
|
+
excludePatterns: exclude,
|
|
162
|
+
});
|
|
163
|
+
return {
|
|
164
|
+
content: [{ type: "text", text: JSON.stringify(tree, null, 2) }],
|
|
165
|
+
};
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
registerLockTools(server) {
|
|
169
|
+
server.tool("lock_file", "Acquire an exclusive lock on a file before editing. Prevents other users from editing the same file simultaneously.", {
|
|
170
|
+
path: z.string().describe("File path to lock"),
|
|
171
|
+
reason: z.string().optional().describe("Brief description of what you plan to do"),
|
|
172
|
+
}, async ({ path, reason }) => {
|
|
173
|
+
const userId = "user-" + randomUUID().slice(0, 8);
|
|
174
|
+
const sessionId = randomUUID();
|
|
175
|
+
const result = await this.lockManager.acquireLock({
|
|
176
|
+
workspaceId: this.config.workspacePath,
|
|
177
|
+
filePath: path,
|
|
178
|
+
userId,
|
|
179
|
+
sessionId,
|
|
180
|
+
reason,
|
|
181
|
+
});
|
|
182
|
+
return {
|
|
183
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
184
|
+
};
|
|
185
|
+
});
|
|
186
|
+
server.tool("unlock_file", "Release a lock on a file after editing.", {
|
|
187
|
+
path: z.string().describe("File path to unlock"),
|
|
188
|
+
}, async ({ path }) => {
|
|
189
|
+
const userId = "user-" + randomUUID().slice(0, 8);
|
|
190
|
+
await this.lockManager.releaseLock(this.config.workspacePath, path, userId);
|
|
191
|
+
return {
|
|
192
|
+
content: [{ type: "text", text: `Lock released for: ${path}` }],
|
|
193
|
+
};
|
|
194
|
+
});
|
|
195
|
+
server.tool("list_locks", "List all currently active file locks in the project.", {}, async () => {
|
|
196
|
+
const locks = await this.lockManager.getActiveLocks(this.config.workspacePath);
|
|
197
|
+
return {
|
|
198
|
+
content: [{ type: "text", text: JSON.stringify(locks, null, 2) }],
|
|
199
|
+
};
|
|
200
|
+
});
|
|
201
|
+
server.tool("check_lock", "Check if a specific file is currently locked and by whom.", {
|
|
202
|
+
path: z.string().describe("File path to check"),
|
|
203
|
+
}, async ({ path }) => {
|
|
204
|
+
const lock = await this.lockManager.checkLock(this.config.workspacePath, path);
|
|
205
|
+
return {
|
|
206
|
+
content: [{ type: "text", text: JSON.stringify(lock) }],
|
|
207
|
+
};
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
registerMonitoringTools(server) {
|
|
211
|
+
server.tool("view_changes", "View recent changes made by all team members in the project.", {
|
|
212
|
+
file_path: z.string().optional().describe("Filter by specific file"),
|
|
213
|
+
user_id: z.string().optional().describe("Filter by specific user"),
|
|
214
|
+
limit: z.number().optional().describe("Number of changes to show (default: 20)"),
|
|
215
|
+
}, async ({ file_path, user_id, limit }) => {
|
|
216
|
+
const changes = await this.changeTracker.getChanges({
|
|
217
|
+
workspaceId: this.config.workspacePath,
|
|
218
|
+
filePath: file_path,
|
|
219
|
+
userId: user_id,
|
|
220
|
+
limit: limit || 20,
|
|
221
|
+
});
|
|
222
|
+
return {
|
|
223
|
+
content: [{ type: "text", text: JSON.stringify(changes, null, 2) }],
|
|
224
|
+
};
|
|
225
|
+
});
|
|
226
|
+
server.tool("view_stats", "View statistics about the project: total files, changes per user, recent activity.", {}, async () => {
|
|
227
|
+
const stats = await this.changeTracker.getStats(this.config.workspacePath);
|
|
228
|
+
return {
|
|
229
|
+
content: [{ type: "text", text: JSON.stringify(stats, null, 2) }],
|
|
230
|
+
};
|
|
231
|
+
});
|
|
232
|
+
server.tool("who_is_online", "See which team members are currently connected to this project.", {}, async () => {
|
|
233
|
+
const online = await this.sessionManager.getOnlineUsers(this.config.workspacePath);
|
|
234
|
+
return {
|
|
235
|
+
content: [{ type: "text", text: JSON.stringify(online, null, 2) }],
|
|
236
|
+
};
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
registerTeamTools(server) {
|
|
240
|
+
server.tool("invite_member", "Generate an invite link for a new team member. Only the project owner can use this.", {
|
|
241
|
+
email: z.string().describe("Email of the person to invite"),
|
|
242
|
+
permissions: z
|
|
243
|
+
.array(z.enum(["read", "write", "admin"]))
|
|
244
|
+
.describe("Permissions to grant"),
|
|
245
|
+
expires_in_days: z
|
|
246
|
+
.number()
|
|
247
|
+
.optional()
|
|
248
|
+
.describe("Link expiry in days (default: 7)"),
|
|
249
|
+
}, async ({ email, permissions, expires_in_days }) => {
|
|
250
|
+
const userId = "user-" + randomUUID().slice(0, 8);
|
|
251
|
+
const link = await this.authManager.generateInviteLink({
|
|
252
|
+
workspaceId: this.config.workspacePath,
|
|
253
|
+
email,
|
|
254
|
+
permissions,
|
|
255
|
+
expiresInDays: expires_in_days || 7,
|
|
256
|
+
createdBy: userId,
|
|
257
|
+
});
|
|
258
|
+
return {
|
|
259
|
+
content: [{ type: "text", text: JSON.stringify(link) }],
|
|
260
|
+
};
|
|
261
|
+
});
|
|
262
|
+
server.tool("list_members", "List all team members and their permissions.", {}, async () => {
|
|
263
|
+
const members = await this.authManager.getTeamMembers(this.config.workspacePath);
|
|
264
|
+
return {
|
|
265
|
+
content: [{ type: "text", text: JSON.stringify(members, null, 2) }],
|
|
266
|
+
};
|
|
267
|
+
});
|
|
268
|
+
server.tool("revoke_access", "Revoke a team member's access. Only the project owner can use this.", {
|
|
269
|
+
user_id: z.string().describe("User ID to revoke"),
|
|
270
|
+
reason: z.string().optional().describe("Reason for revocation"),
|
|
271
|
+
}, async ({ user_id }) => {
|
|
272
|
+
const ownerId = "owner-" + randomUUID().slice(0, 8);
|
|
273
|
+
await this.authManager.revokeAccess(this.config.workspacePath, user_id, ownerId);
|
|
274
|
+
return {
|
|
275
|
+
content: [
|
|
276
|
+
{ type: "text", text: `Access revoked for user: ${user_id}` },
|
|
277
|
+
],
|
|
278
|
+
};
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
async startHttp(port) {
|
|
282
|
+
await this.initialize();
|
|
283
|
+
const app = express();
|
|
284
|
+
app.use(express.json());
|
|
285
|
+
app.use(cors({ origin: true }));
|
|
286
|
+
// Health check
|
|
287
|
+
app.get("/health", (req, res) => {
|
|
288
|
+
res.json({ status: "ok", version: "1.0.0" });
|
|
289
|
+
});
|
|
290
|
+
// MCP endpoint
|
|
291
|
+
app.post("/mcp", async (req, res) => {
|
|
292
|
+
try {
|
|
293
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
294
|
+
let transport;
|
|
295
|
+
if (sessionId && this.transports.has(sessionId)) {
|
|
296
|
+
transport = this.transports.get(sessionId);
|
|
297
|
+
}
|
|
298
|
+
else if (!sessionId) {
|
|
299
|
+
const server = this.createMcpServer();
|
|
300
|
+
transport = new StreamableHTTPServerTransport({
|
|
301
|
+
sessionIdGenerator: () => randomUUID(),
|
|
302
|
+
});
|
|
303
|
+
await server.connect(transport);
|
|
304
|
+
this.transports.set(transport.sessionId, transport);
|
|
305
|
+
transport.onclose = () => {
|
|
306
|
+
const sid = transport.sessionId;
|
|
307
|
+
if (sid)
|
|
308
|
+
this.transports.delete(sid);
|
|
309
|
+
};
|
|
310
|
+
await transport.handleRequest(req, res, req.body);
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
res.status(400).json({
|
|
315
|
+
jsonrpc: "2.0",
|
|
316
|
+
error: { code: -32000, message: "Bad Request: No valid session ID" },
|
|
317
|
+
id: req.body?.id,
|
|
318
|
+
});
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
await transport.handleRequest(req, res, req.body);
|
|
322
|
+
}
|
|
323
|
+
catch (error) {
|
|
324
|
+
logger.error("Error handling MCP request: %s", error instanceof Error ? error.message : String(error));
|
|
325
|
+
if (!res.headersSent) {
|
|
326
|
+
res.status(500).json({
|
|
327
|
+
jsonrpc: "2.0",
|
|
328
|
+
error: { code: -32603, message: "Internal server error" },
|
|
329
|
+
id: req.body?.id,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
// SSE endpoint for server-initiated messages
|
|
335
|
+
app.get("/mcp", async (req, res) => {
|
|
336
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
337
|
+
if (!sessionId || !this.transports.has(sessionId)) {
|
|
338
|
+
res.status(400).json({
|
|
339
|
+
jsonrpc: "2.0",
|
|
340
|
+
error: { code: -32000, message: "Bad Request: No valid session ID" },
|
|
341
|
+
});
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
const transport = this.transports.get(sessionId);
|
|
345
|
+
await transport.handleRequest(req, res, req.body);
|
|
346
|
+
});
|
|
347
|
+
// Delete session
|
|
348
|
+
app.delete("/mcp", async (req, res) => {
|
|
349
|
+
const sessionId = req.headers["mcp-session-id"];
|
|
350
|
+
if (!sessionId || !this.transports.has(sessionId)) {
|
|
351
|
+
res.status(400).json({
|
|
352
|
+
jsonrpc: "2.0",
|
|
353
|
+
error: { code: -32000, message: "Bad Request: No valid session ID" },
|
|
354
|
+
});
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const transport = this.transports.get(sessionId);
|
|
358
|
+
await transport.handleRequest(req, res, req.body);
|
|
359
|
+
});
|
|
360
|
+
// Web UI routes
|
|
361
|
+
const webApp = await createWebUI(this.config);
|
|
362
|
+
app.use(webApp);
|
|
363
|
+
return new Promise((resolve) => {
|
|
364
|
+
this.httpServer = app.listen(port, () => {
|
|
365
|
+
logger.info(`OpenCOOP server listening on port ${port}`);
|
|
366
|
+
resolve();
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
async stop() {
|
|
371
|
+
stopAutoSave();
|
|
372
|
+
// Close all transports
|
|
373
|
+
for (const [sid, transport] of this.transports) {
|
|
374
|
+
try {
|
|
375
|
+
await transport.close();
|
|
376
|
+
}
|
|
377
|
+
catch {
|
|
378
|
+
// Ignore
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
this.transports.clear();
|
|
382
|
+
// Close HTTP server
|
|
383
|
+
if (this.httpServer) {
|
|
384
|
+
this.httpServer.close();
|
|
385
|
+
}
|
|
386
|
+
// Save and close database
|
|
387
|
+
const { saveDatabase, closeDatabase } = await import("../utils/database.js");
|
|
388
|
+
await saveDatabase();
|
|
389
|
+
await closeDatabase();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=mcp-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/server/mcp-server.ts"],"names":[],"mappings":"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"}
|