Skip to main content
Glama
index.ts6.81 kB
import express, { Request, Response, NextFunction } from 'express'; import { PrismaClient } from '@prisma/client'; import bcrypt from 'bcrypt'; const app = express(); const prisma = new PrismaClient(); const PORT = Number(process.env.PORT) || 4000; app.use(express.json()); // Auth middleware app.use(async (req: Request, res: Response, next: NextFunction) => { // Public endpoints if ( req.path === '/health' || (req.path === '/users/register' && req.method === 'POST') || (req.path === '/users/login' && req.method === 'POST') ) { return next(); } const key = req.headers['x-api-key']; if (!key || typeof key !== 'string') { res.status(401).json({ error: 'Unauthorized' }); return; } // Check API key in DB const apiKey = await prisma.apiKey.findFirst({ where: { key, revoked: false }, include: { user: true } }); if (!apiKey) { res.status(401).json({ error: 'Unauthorized' }); return; } // Attach user to request (req as any).user = apiKey.user; (req as any).apiKey = apiKey; next(); }); app.get('/health', (req: Request, res: Response): void => { res.send('OK'); }); // User registration app.post('/users/register', async (req: Request, res: Response) => { const { email, password } = req.body; if (!email || !password) { res.status(400).json({ error: 'Email and password are required' }); return; } const existing = await prisma.user.findUnique({ where: { email } }); if (existing) { res.status(409).json({ error: 'Email already registered' }); return; } const passwordHash = await bcrypt.hash(password, 10); const user = await prisma.user.create({ data: { email, passwordHash } }); res.status(201).json({ id: user.id, email: user.email }); }); // User login app.post('/users/login', async (req: Request, res: Response) => { const { email, password } = req.body; if (!email || !password) { res.status(400).json({ error: 'Email and password are required' }); return; } const user = await prisma.user.findUnique({ where: { email } }); if (!user) { res.status(401).json({ error: 'Invalid credentials' }); return; } const valid = await bcrypt.compare(password, user.passwordHash); if (!valid) { res.status(401).json({ error: 'Invalid credentials' }); return; } // Find or create API key let apiKey = await prisma.apiKey.findFirst({ where: { userId: user.id, revoked: false } }); if (!apiKey) { const key = require('crypto').randomBytes(32).toString('hex'); apiKey = await prisma.apiKey.create({ data: { key, userId: user.id } }); } res.json({ apiKey: apiKey.key }); }); // List API keys for current user app.get('/users/me/api-keys', async (req: Request, res: Response) => { const user = (req as any).user; const apiKeys = await prisma.apiKey.findMany({ where: { userId: user.id }, select: { id: true, key: true, createdAt: true, revoked: true } }); res.json(apiKeys); }); // Create new API key for current user app.post('/users/me/api-keys', async (req: Request, res: Response) => { const user = (req as any).user; const key = require('crypto').randomBytes(32).toString('hex'); const apiKey = await prisma.apiKey.create({ data: { key, userId: user.id } }); res.status(201).json({ id: apiKey.id, key: apiKey.key, createdAt: apiKey.createdAt, revoked: apiKey.revoked }); }); // Revoke API key app.delete('/users/me/api-keys/:id', async (req: Request, res: Response) => { const user = (req as any).user; const id = Number(req.params.id); const apiKey = await prisma.apiKey.findUnique({ where: { id } }); if (!apiKey || apiKey.userId !== user.id) { res.status(404).json({ error: 'API key not found' }); return; } await prisma.apiKey.update({ where: { id }, data: { revoked: true } }); res.status(204).send(); }); app.get('/agents', async (req: Request, res: Response): Promise<void> => { const agents = await prisma.agent.findMany(); res.json(agents); }); app.get('/agents/:id', async (req: Request, res: Response): Promise<void> => { const id = Number(req.params.id); const agent = await prisma.agent.findUnique({ where: { id } }); if (!agent) { res.status(404).json({ error: 'Agent not found' }); return; } res.json(agent); }); app.post('/agents', async (req: Request, res: Response): Promise<void> => { const { name } = req.body; if (!name) { res.status(400).json({ error: 'Name is required' }); return; } const agent = await prisma.agent.create({ data: { name } }); res.status(201).json(agent); }); app.put('/agents/:id', async (req: Request, res: Response): Promise<void> => { const id = Number(req.params.id); const { name } = req.body; try { const agent = await prisma.agent.update({ where: { id }, data: { name } }); res.json(agent); } catch (e) { res.status(404).json({ error: 'Agent not found' }); } }); app.delete('/agents/:id', async (req: Request, res: Response): Promise<void> => { const id = Number(req.params.id); try { await prisma.agent.delete({ where: { id } }); res.status(204).send(); } catch (e) { res.status(404).json({ error: 'Agent not found' }); } }); // Agent memory endpoints app.post('/agents/:id/memory', async (req: Request, res: Response): Promise<void> => { const agentId = Number(req.params.id); const { content } = req.body; if (!content) { res.status(400).json({ error: 'Content is required' }); return; } try { const memory = await prisma.memory.create({ data: { agentId, content } }); res.status(201).json(memory); } catch (e) { res.status(404).json({ error: 'Agent not found' }); } }); app.get('/agents/:id/memory', async (req: Request, res: Response): Promise<void> => { const agentId = Number(req.params.id); const memory = await prisma.memory.findMany({ where: { agentId }, orderBy: { createdAt: 'desc' } }); res.json(memory); }); // n8n trigger endpoint (robust integration) app.post('/agents/:id/trigger', async (req: Request, res: Response): Promise<void> => { const agentId = Number(req.params.id); const payload = req.body; try { // Check agent exists const agent = await prisma.agent.findUnique({ where: { id: agentId } }); if (!agent) { res.status(404).json({ error: 'Agent not found' }); return; } // Log the trigger event in agent memory await prisma.memory.create({ data: { agentId, content: `n8n trigger received: ${JSON.stringify(payload)}` } }); // Respond with acknowledgement and echo payload res.json({ status: 'Triggered', agentId, received: payload }); } catch (e) { res.status(500).json({ error: 'Failed to process trigger' }); } }); app.listen(PORT, '0.0.0.0', () => { console.log(`Server running on port ${PORT}`); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/LeadBroaf/mcp-agent-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server