feat: Ability to add and control user level MCP Servers

This commit is contained in:
simos
2025-07-13 15:25:45 +00:00
parent 9f65756e2c
commit 6c64ea7552
4 changed files with 1276 additions and 81 deletions

View File

@@ -40,6 +40,7 @@ import { getProjects, getSessions, getSessionMessages, renameProject, deleteSess
import { spawnClaude, abortClaudeSession } from './claude-cli.js';
import gitRoutes from './routes/git.js';
import authRoutes from './routes/auth.js';
import mcpRoutes from './routes/mcp.js';
import { initializeDatabase } from './database/db.js';
import { validateApiKey, authenticateToken, authenticateWebSocket } from './middleware/auth.js';
@@ -131,17 +132,6 @@ async function setupProjectsWatcher() {
}
// Get the first non-localhost IP address
function getServerIP() {
const interfaces = os.networkInterfaces();
for (const name of Object.keys(interfaces)) {
for (const iface of interfaces[name]) {
if (iface.family === 'IPv4' && !iface.internal) {
return iface.address;
}
}
}
return 'localhost';
}
const app = express();
const server = http.createServer(app);
@@ -183,14 +173,16 @@ app.use('/api/auth', authRoutes);
// Git API Routes (protected)
app.use('/api/git', authenticateToken, gitRoutes);
// MCP API Routes (protected)
app.use('/api/mcp', authenticateToken, mcpRoutes);
// Static files served after API routes
app.use(express.static(path.join(__dirname, '../dist')));
// API Routes (protected)
app.get('/api/config', authenticateToken, (req, res) => {
// Always use the server's actual IP and port for WebSocket connections
const serverIP = getServerIP();
const host = `${serverIP}:${PORT}`;
const host = req.headers.host || `${req.hostname}:${PORT}`;
const protocol = req.protocol === 'https' || req.get('x-forwarded-proto') === 'https' ? 'wss' : 'ws';
console.log('Config API called - Returning host:', host, 'Protocol:', protocol);
@@ -428,8 +420,6 @@ app.get('/api/projects/:projectName/files', authenticateToken, async (req, res)
const files = await getFileTree(actualPath, 3, 0, true);
const hiddenFiles = files.filter(f => f.name.startsWith('.'));
console.log('📄 Found', files.length, 'files/folders, including', hiddenFiles.length, 'hidden files');
console.log('🔍 Hidden files:', hiddenFiles.map(f => f.name));
res.json(files);
} catch (error) {
console.error('❌ File tree error:', error.message);
@@ -1006,4 +996,4 @@ async function startServer() {
}
}
startServer();
startServer();