index-multi-tenant.tsā¢9.8 kB
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import MultiTenantOrchestrator from './multi-tenant-orchestrator.js';
import type { Session } from './multi-tenant-orchestrator.js';
// Initialize the multi-tenant orchestrator
const orchestrator = new MultiTenantOrchestrator();
export default function createServer({ config }) {
const server = new McpServer({
name: "PyForge Multi-Tenant MCP Server",
version: "2.0.0",
});
// Session Management Tools
server.registerTool("session_create", {
title: "Create New Session",
description: "Creates a new isolated workspace session for a user or AI assistant.",
inputSchema: {
gitName: z.string().optional().describe("Git user name for this session."),
gitEmail: z.string().optional().describe("Git user email for this session."),
gitPat: z.string().optional().describe("GitHub Personal Access Token for this session."),
},
}, async ({ gitName, gitEmail, gitPat }) => {
try {
const session = await orchestrator.createSession({
name: gitName,
email: gitEmail,
pat: gitPat
});
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
sessionId: session.id,
workspaceDir: session.workspaceDir,
message: `Session created successfully. Your session ID is: ${session.id}`
})
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: JSON.stringify({
success: false,
error: `Failed to create session: ${error.message}`
})
}]
};
}
});
server.registerTool("session_get", {
title: "Get Session Info",
description: "Retrieves information about an existing session.",
inputSchema: {
sessionId: z.string().describe("The session ID to retrieve."),
},
}, async ({ sessionId }) => {
try {
const session = await orchestrator.getSession(sessionId);
if (!session) {
return {
content: [{
type: "text",
text: JSON.stringify({
success: false,
error: "Session not found or expired"
})
}]
};
}
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
session: {
id: session.id,
workspaceDir: session.workspaceDir,
status: session.status,
createdAt: session.createdAt,
lastActivity: session.lastActivity,
hasGitConfig: !!(session.gitConfig.pat)
}
})
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: JSON.stringify({
success: false,
error: `Failed to get session: ${error.message}`
})
}]
};
}
});
server.registerTool("session_update_git", {
title: "Update Session Git Configuration",
description: "Updates git configuration for a specific session.",
inputSchema: {
sessionId: z.string().describe("The session ID to update."),
gitName: z.string().optional().describe("Git user name for this session."),
gitEmail: z.string().optional().describe("Git user email for this session."),
gitPat: z.string().optional().describe("GitHub Personal Access Token for this session."),
},
}, async ({ sessionId, gitName, gitEmail, gitPat }) => {
try {
const success = await orchestrator.updateSessionGitConfig(sessionId, {
name: gitName,
email: gitEmail,
pat: gitPat
});
if (success) {
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
message: "Git configuration updated successfully"
})
}]
};
} else {
return {
content: [{
type: "text",
text: JSON.stringify({
success: false,
error: "Session not found"
})
}]
};
}
} catch (error) {
return {
content: [{
type: "text",
text: JSON.stringify({
success: false,
error: `Failed to update git configuration: ${error.message}`
})
}]
};
}
});
server.registerTool("session_destroy", {
title: "Destroy Session",
description: "Destroys a session and cleans up its workspace.",
inputSchema: {
sessionId: z.string().describe("The session ID to destroy."),
},
}, async ({ sessionId }) => {
try {
const success = await orchestrator.destroySession(sessionId);
return {
content: [{
type: "text",
text: JSON.stringify({
success,
message: success ? "Session destroyed successfully" : "Session not found"
})
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: JSON.stringify({
success: false,
error: `Failed to destroy session: ${error.message}`
})
}]
};
}
});
server.registerTool("session_info", {
title: "Get All Sessions Info",
description: "Gets information about all active sessions (admin function).",
inputSchema: {},
}, async () => {
try {
const info = orchestrator.getSessionInfo();
return {
content: [{
type: "text",
text: JSON.stringify({
success: true,
info
})
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: JSON.stringify({
success: false,
error: `Failed to get sessions info: ${error.message}`
})
}]
};
}
});
// Command Execution Tools (Session-aware)
server.registerTool("run_bash_command", {
title: "Run Bash Command in Session",
description: "Executes a bash command in a specific session's workspace and returns the output.",
inputSchema: {
sessionId: z.string().describe("The session ID to execute the command in."),
command: z.string().describe("The bash command to execute."),
cwd: z.string().optional().describe("The current working directory to execute the command in (relative to session workspace)."),
},
}, async ({ sessionId, command, cwd }) => {
try {
const result = await orchestrator.executeCommandInSession(sessionId, command, cwd);
return {
content: [{
type: "text",
text: result.output || result.error
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `Command execution failed: ${error.message}`
}]
};
}
});
// Git Tools (Session-aware)
server.registerTool("github_get_status", {
title: "Get Git Repository Status in Session",
description: "Checks if a session's workspace is a git repository and returns its status.",
inputSchema: {
sessionId: z.string().describe("The session ID to check git status for."),
},
}, async ({ sessionId }) => {
try {
const status = await orchestrator.getGitStatus(sessionId);
return {
content: [{
type: "text",
text: JSON.stringify(status)
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: JSON.stringify({
isRepo: false,
error: `Failed to get git status: ${error.message}`
})
}]
};
}
});
server.registerTool("github_commit_and_push", {
title: "Commit and Push to GitHub in Session",
description: "Commits all changes in a session's workspace and pushes them to a specified branch.",
inputSchema: {
sessionId: z.string().describe("The session ID to commit and push from."),
branch: z.string().describe("The branch to push to."),
commitMessage: z.string().describe("The commit message."),
authorName: z.string().describe("The author's name for the commit."),
authorEmail: z.string().describe("The author's email for the commit."),
},
}, async ({ sessionId, branch, commitMessage, authorName, authorEmail }) => {
try {
const result = await orchestrator.commitAndPush(sessionId, branch, commitMessage, authorName, authorEmail);
return {
content: [{
type: "text",
text: result
}]
};
} catch (error) {
return {
content: [{
type: "text",
text: `Commit and push failed: ${error.message}`
}]
};
}
});
console.log("š PyForge Multi-Tenant MCP Server initialized with session management");
console.log("š Available session tools:");
console.log(" - session_create: Create new isolated workspace");
console.log(" - session_get: Get session information");
console.log(" - session_update_git: Update git configuration");
console.log(" - session_destroy: Destroy session and cleanup");
console.log(" - session_info: Get all sessions info (admin)");
console.log("š» Command execution:");
console.log(" - run_bash_command: Execute commands in session workspace");
console.log("š§ Git operations:");
console.log(" - github_get_status: Get repository status");
console.log(" - github_commit_and_push: Commit and push changes");
return server.server;
}