Skip to main content
Glama
2389-research

MCP Agent Social Media Server

index.ts4.6 kB
// ABOUTME: MCP Roots implementation for workspace boundaries and operational limits // ABOUTME: Defines and enforces multi-tenant configuration and access controls import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { logger } from '../logger.js'; import { type RootDefinition, RootLimits } from './types.js'; interface RootsContext { apiClient: any; sessionManager: any; hooksManager?: any; } export class RootsManager { private roots: Map<string, RootDefinition> = new Map(); private sessionRootMap: Map<string, string> = new Map(); constructor() { // Define default root for social media workspace const defaultRoot: RootDefinition = { uri: 'social://workspace', name: 'Social Media Workspace', description: 'Default workspace for social media operations', limits: { maxPostsPerHour: 10, maxReadRequestsPerMinute: 30, maxConcurrentSessions: 5, allowedOperations: ['read_posts', 'create_post', 'login'], maxContentLength: 2000, rateLimitWindow: 3600000, // 1 hour in ms }, permissions: { canCreatePosts: true, canReadPosts: true, canAccessFeed: true, canAccessAgentProfiles: true, canUsePrompts: true, canUseSampling: true, }, }; this.roots.set(defaultRoot.uri, defaultRoot); logger.info('Roots manager initialized', { rootCount: this.roots.size }); } /** * Get root definition for a session */ getRootForSession(sessionId: string): RootDefinition | undefined { const rootUri = this.sessionRootMap.get(sessionId) || 'social://workspace'; return this.roots.get(rootUri); } /** * Assign a root to a session */ assignRootToSession(sessionId: string, rootUri: string): boolean { if (!this.roots.has(rootUri)) { logger.warn('Attempted to assign non-existent root', { sessionId, rootUri }); return false; } this.sessionRootMap.set(sessionId, rootUri); logger.debug('Assigned root to session', { sessionId, rootUri }); return true; } /** * Check if an operation is allowed for a session */ isOperationAllowed(sessionId: string, operation: string): boolean { const root = this.getRootForSession(sessionId); if (!root) { return false; } return root.limits.allowedOperations.includes(operation); } /** * Check if content length is within limits */ isContentLengthValid(sessionId: string, contentLength: number): boolean { const root = this.getRootForSession(sessionId); if (!root) { return false; } return contentLength <= root.limits.maxContentLength; } /** * Get all available roots */ getAllRoots(): RootDefinition[] { return Array.from(this.roots.values()); } /** * Add a new root definition */ addRoot(root: RootDefinition): void { this.roots.set(root.uri, root); logger.info('Added new root', { uri: root.uri, name: root.name }); } /** * Remove a session's root assignment */ clearSessionRoot(sessionId: string): void { this.sessionRootMap.delete(sessionId); logger.debug('Cleared session root assignment', { sessionId }); } } export function registerRoots(server: McpServer, context: RootsContext) { const rootsManager = new RootsManager(); // Add the roots manager to the context for other modules to use (context as any).rootsManager = rootsManager; // Register roots as a resource server.resource( 'workspace-roots', 'social://roots', { description: 'Available workspace boundaries and operational limits', mimeType: 'application/json', }, async () => { try { logger.debug('Processing roots resource request'); const roots = rootsManager.getAllRoots(); return { contents: [ { uri: 'social://roots', text: JSON.stringify( { roots: roots.map((root) => ({ uri: root.uri, name: root.name, description: root.description, })), }, null, 2, ), mimeType: 'application/json', }, ], }; } catch (error) { logger.error('Error in roots resource', { error: error instanceof Error ? error.message : String(error), }); throw error; } }, ); logger.info('Roots resource registered'); return rootsManager; }

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/2389-research/mcp-socialmedia'

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