Skip to main content
Glama

Role-Specific Context MCP Server

by Chris-June
roleManager.ts7.16 kB
import { MemoryManager } from "../memory/memoryManager"; import { OpenAIClient } from "../ai/openaiClient"; import { ContextManager } from "../context/contextManager"; import { config } from "../config"; import { ImportanceLevel, MemoryType } from "../memory/types"; import { ContextType } from "../context/types"; // Types for role management export interface Role { id: string; name: string; description: string; instructions: string; domains: string[]; tone: string; systemPrompt: string; customInstructions?: string; createdAt: Date; updatedAt: Date; } export interface ToneProfile { description: string; modifiers: string; } export class RoleManager { private roles: Map<string, Role> = new Map(); private toneProfiles: Map<string, ToneProfile> = new Map(); private memoryManager: MemoryManager; private aiClient: OpenAIClient; private contextManager: ContextManager; constructor(memoryManager: MemoryManager, aiClient: OpenAIClient, contextManager: ContextManager) { this.memoryManager = memoryManager; this.aiClient = aiClient; this.contextManager = contextManager; this.initializeDefaultRoles(); this.initializeToneProfiles(); } private initializeDefaultRoles(): void { for (const roleConfig of config.roles.defaults) { const role: Role = { ...roleConfig, createdAt: new Date(), updatedAt: new Date() }; this.roles.set(role.id, role); } } private initializeToneProfiles(): void { for (const [tone, profile] of Object.entries(config.roles.toneProfiles)) { this.toneProfiles.set(tone, profile as ToneProfile); } } /** * Get all available roles */ public getAllRoles(): Role[] { return Array.from(this.roles.values()); } /** * Get a specific role by ID */ public getRole(roleId: string): Role | undefined { return this.roles.get(roleId); } /** * Create a new custom role */ public createRole(roleData: Omit<Role, 'createdAt' | 'updatedAt'>): Role { if (this.roles.has(roleData.id)) { throw new Error(`Role with ID ${roleData.id} already exists`); } const role: Role = { ...roleData, createdAt: new Date(), updatedAt: new Date() }; this.roles.set(role.id, role); return role; } /** * Update an existing role */ public updateRole(roleId: string, updates: Partial<Omit<Role, 'id' | 'createdAt' | 'updatedAt'>>): Role { const existingRole = this.roles.get(roleId); if (!existingRole) { throw new Error(`Role with ID ${roleId} not found`); } const updatedRole: Role = { ...existingRole, ...updates, updatedAt: new Date() }; this.roles.set(roleId, updatedRole); return updatedRole; } /** * Delete a role */ public deleteRole(roleId: string): boolean { // Don't allow deletion of default roles const isDefaultRole = config.roles.defaults.some((r: any) => r.id === roleId); if (isDefaultRole) { throw new Error(`Cannot delete default role: ${roleId}`); } const deleted = this.roles.delete(roleId); if (deleted) { // Clean up associated memories this.memoryManager.clearRoleMemories(roleId); } return deleted; } /** * Get all available tone profiles */ public getAllToneProfiles(): Map<string, ToneProfile> { return this.toneProfiles; } /** * Get a specific tone profile */ public getToneProfile(tone: string): ToneProfile | undefined { return this.toneProfiles.get(tone); } /** * Change a role's tone */ public async changeRoleTone(roleId: string, newTone: string): Promise<Role> { if (!this.toneProfiles.has(newTone)) { throw new Error(`Tone profile '${newTone}' not found`); } const role = this.updateRole(roleId, { tone: newTone }); // Also update the context tone if this role is active await this.contextManager.switchContext({ agentId: roleId, contextType: ContextType.TONE, contextValue: newTone, metadata: { source: 'role_tone_change' } }); return role; } /** * Generate a complete system prompt for a role, including tone modifiers */ public generateCompletePrompt(roleId: string, customInstructions?: string): string { const role = this.getRole(roleId); if (!role) { throw new Error(`Role with ID ${roleId} not found`); } const toneProfile = this.getToneProfile(role.tone); if (!toneProfile) { throw new Error(`Tone profile '${role.tone}' not found`); } let prompt = role.systemPrompt; // Add tone modifiers prompt += `\n\nTone and Style Guidelines: ${toneProfile.modifiers}`; // Add domain knowledge context prompt += `\n\nYour expertise is specifically in: ${role.domains.join(', ')}.`; // Add role-specific instructions prompt += `\n\nSpecific Instructions: ${role.instructions}`; // Add custom instructions if provided if (customInstructions || role.customInstructions) { prompt += `\n\nAdditional Context: ${customInstructions || role.customInstructions}`; } return prompt; } /** * Get relevant memories for a role and query */ public async getRelevantContext(roleId: string, query: string): Promise<string> { const role = this.getRole(roleId); if (!role) { throw new Error(`Role with ID ${roleId} not found`); } // Get relevant memories for this role and query const memories = await this.memoryManager.getRelevantMemories({ roleId, query, limit: 10 }); if (memories.length === 0) { return ""; } // Format memories as context return `Relevant context from previous interactions:\n\n${memories.map(m => `- ${m.content} (${new Date(m.timestamp).toLocaleString()})` ).join('\n')}`; } /** * Process a query using a specific role */ public async processQuery(roleId: string, query: string, customInstructions?: string): Promise<string> { const role = this.getRole(roleId); if (!role) { throw new Error(`Role with ID ${roleId} not found`); } // Check for context triggers in the query await this.contextManager.checkAndApplyTriggers(roleId, query); // Generate the complete system prompt const systemPrompt = this.generateCompletePrompt(roleId, customInstructions); // Get relevant context from role-specific memory const contextMemories = await this.getRelevantContext(roleId, query); // Get context-aware modifiers const contextModifiers = this.contextManager.generateContextPromptModifiers(roleId); // Process with AI const response = await this.aiClient.generateResponse( systemPrompt + contextModifiers, query, contextMemories ); // Store this interaction in memory await this.memoryManager.storeMemory({ roleId, content: `Q: ${query}\nA: ${response}`, type: MemoryType.SESSION, importance: ImportanceLevel.MEDIUM, metadata: { type: 'interaction' } }); return response; } }

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/Chris-June/MCP-Server'

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