locker-mcp
Version:
MCP server for file locking and access control for AI code tools
223 lines • 9.75 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.LockerMCPServer = void 0;
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
const locker_1 = require("./locker");
class LockerMCPServer {
constructor() {
this.server = new index_js_1.Server({
name: 'locker-mcp',
version: '1.0.0',
}, {
capabilities: {
tools: {},
},
});
this.locker = new locker_1.Locker();
this.setupToolHandlers();
}
validateParams(args, requiredFields) {
if (!args || typeof args !== 'object') {
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, 'Missing or invalid arguments');
}
for (const field of requiredFields) {
if (!(field in args) || args[field] === undefined || args[field] === null) {
throw new types_js_1.McpError(types_js_1.ErrorCode.InvalidParams, `Missing required parameter: ${field}`);
}
}
return args;
}
setupToolHandlers() {
this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'getFileState',
description: 'Get the current lock state of a file',
inputSchema: {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Path to the file to check',
},
},
required: ['filePath'],
},
},
{
name: 'lockFile',
description: 'Lock a file with context description',
inputSchema: {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Path to the file to lock',
},
context: {
type: 'string',
description: 'Description of the file\'s purpose or context',
},
},
required: ['filePath', 'context'],
},
},
{
name: 'unlockFile',
description: 'Unlock a file, removing its lock state',
inputSchema: {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Path to the file to unlock',
},
},
required: ['filePath'],
},
},
{
name: 'updateFile',
description: 'Update a file\'s lock state and context',
inputSchema: {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Path to the file to update',
},
context: {
type: 'string',
description: 'Updated description of the file\'s purpose',
},
state: {
type: 'string',
enum: ['unlocked', 'locked-context', 'locked'],
description: 'New lock state for the file',
},
},
required: ['filePath', 'context', 'state'],
},
},
{
name: 'finalizeFile',
description: 'Mark a file as fully locked (no further edits allowed)',
inputSchema: {
type: 'object',
properties: {
filePath: {
type: 'string',
description: 'Path to the file to finalize',
},
},
required: ['filePath'],
},
},
{
name: 'getAllTrackedFiles',
description: 'Get all files currently tracked by the locker',
inputSchema: {
type: 'object',
properties: {},
},
},
],
};
});
this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case 'getFileState': {
const params = this.validateParams(args, ['filePath']);
const result = this.locker.getFileState(params);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
}
case 'lockFile': {
const params = this.validateParams(args, ['filePath', 'context']);
const result = this.locker.lockFile(params);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
}
case 'unlockFile': {
const params = this.validateParams(args, ['filePath']);
const result = this.locker.unlockFile(params);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
}
case 'updateFile': {
const params = this.validateParams(args, ['filePath', 'context', 'state']);
const result = this.locker.updateFile(params);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
}
case 'finalizeFile': {
const params = this.validateParams(args, ['filePath']);
const result = this.locker.finalizeFile(params.filePath);
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
}
case 'getAllTrackedFiles': {
const result = this.locker.getAllTrackedFiles();
return {
content: [
{
type: 'text',
text: JSON.stringify(result, null, 2),
},
],
};
}
default:
throw new types_js_1.McpError(types_js_1.ErrorCode.MethodNotFound, `Unknown tool: ${name}`);
}
}
catch (error) {
if (error instanceof types_js_1.McpError) {
throw error;
}
throw new types_js_1.McpError(types_js_1.ErrorCode.InternalError, `Tool execution failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
});
}
async run() {
const transport = new stdio_js_1.StdioServerTransport();
await this.server.connect(transport);
}
}
exports.LockerMCPServer = LockerMCPServer;
//# sourceMappingURL=server.js.map