Skip to main content
Glama
mcp-tools.js24.9 kB
export class MCPTools { constructor() { this.tools = new Map(); this.initializeTools(); } initializeTools() { const toolDefinitions = [ { name: "list_user_stories", description: "List all user stories with numbers for a project and persona", inputSchema: { type: "object", properties: { project_id: { type: "string", description: "Project ID (required)" }, persona_id: { type: "string", description: "Persona ID (required)" } }, required: ["project_id", "persona_id"] } }, { name: "get_story_range", description: "Get user stories in a range (e.g., stories 1-5) with all details", inputSchema: { type: "object", properties: { start_number: { type: "integer", description: "Start story number (1-based)", minimum: 1 }, end_number: { type: "integer", description: "End story number (1-based)", minimum: 1 }, project_id: { type: "string", description: "Project ID (required)" }, persona_id: { type: "string", description: "Persona ID (required)" } }, required: ["start_number", "end_number", "project_id", "persona_id"] } }, { name: "get_single_story_details", description: "Get detailed information for a single user story by number or ID", inputSchema: { type: "object", properties: { story_number: { type: "integer", description: "Story number (1-based)", minimum: 1 }, story_id: { type: "string", description: "Story ID (e.g., PROJECT-P-XXX-XXX)" }, project_id: { type: "string", description: "Project ID (required)" }, persona_id: { type: "string", description: "Persona ID (required)" } }, required: ["project_id", "persona_id"] } }, { name: "get_project_overview", description: "Get comprehensive project overview with elevator pitch, vision, and personas", inputSchema: { type: "object", properties: { project_id: { type: "string", description: "Project ID (required)" } }, required: ["project_id"] } }, { name: "get_persona_profile", description: "Get detailed persona profile with demographics, goals, and characteristics", inputSchema: { type: "object", properties: { project_id: { type: "string", description: "Project ID (required)" }, persona_id: { type: "string", description: "Persona ID (required)" } }, required: ["project_id", "persona_id"] } }, { name: "get_user_journey", description: "Get detailed user journey events and touchpoints for a persona", inputSchema: { type: "object", properties: { project_id: { type: "string", description: "Project ID (required)" }, persona_id: { type: "string", description: "Persona ID (required)" } }, required: ["project_id", "persona_id"] } }, { name: "get_jobs_to_be_done", description: "Get Jobs to be Done analysis for a persona with functional, emotional, and social jobs", inputSchema: { type: "object", properties: { project_id: { type: "string", description: "Project ID (required)" }, persona_id: { type: "string", description: "Persona ID (required)" } }, required: ["project_id", "persona_id"] } }, { name: "get_user_info", description: "Get authenticated user profile information", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "get_project_environment", description: "Get project environment information including personas", inputSchema: { type: "object", properties: { project_id: { type: "string", description: "Project ID (required)" } }, required: ["project_id"] } }, { name: "check_nda_status", description: "Check NDA status for the authenticated user", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "get_product_info", description: "Get detailed product information for a project", inputSchema: { type: "object", properties: { project_id: { type: "string", description: "Project ID (required)" } }, required: ["project_id"] } }, { name: "list_projects", description: "List all available projects with their names and IDs", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "list_projects_paginated", description: "List projects with pagination support", inputSchema: { type: "object", properties: { page: { type: "integer", description: "Page number (1-based)", minimum: 1, default: 1 }, pageSize: { type: "integer", description: "Number of projects per page", minimum: 1, maximum: 100, default: 20 } }, required: [] } }, { name: "search_projects", description: "Search projects by keyword with pagination", inputSchema: { type: "object", properties: { query: { type: "string", description: "Search query for project name, ID, or description" }, page: { type: "integer", description: "Page number (1-based)", minimum: 1, default: 1 }, pageSize: { type: "integer", description: "Number of projects per page", minimum: 1, maximum: 100, default: 20 } }, required: ["query"] } }, { name: "find_project_by_name", description: "Find a project by its name and get the project ID", inputSchema: { type: "object", properties: { project_name: { type: "string", description: "Project name to search for" } }, required: ["project_name"] } }, { name: "find_persona_by_name", description: "Find a persona by name within a project and get the persona ID", inputSchema: { type: "object", properties: { project_id: { type: "string", description: "Project ID or name" }, persona_name: { type: "string", description: "Persona name to search for" } }, required: ["project_id", "persona_name"] } }, { name: "get_user_stories_by_name", description: "List user stories using project and persona names (more user-friendly)", inputSchema: { type: "object", properties: { project_name: { type: "string", description: "Project name or ID" }, persona_name: { type: "string", description: "Persona name or ID" } }, required: ["project_name", "persona_name"] } }, { name: "get_persona_by_name", description: "Get persona profile using project and persona names (user-friendly)", inputSchema: { type: "object", properties: { project_name: { type: "string", description: "Project name or ID" }, persona_name: { type: "string", description: "Persona name or ID" } }, required: ["project_name", "persona_name"] } }, { name: 'get_project_by_name', description: 'Find and get project details by name. Supports both project names and project IDs', inputSchema: { type: 'object', properties: { project_name: { type: 'string', description: 'Project name or ID to search for' } }, required: ['project_name'] } }, { name: 'find_project_by_name', description: 'Find a project by name and get the project ID (works with known project mappings)', inputSchema: { type: 'object', properties: { project_name: { type: 'string', description: 'Project name to search for (e.g., "Talentally Yours")' } }, required: ['project_name'] } }, { name: "mcp0_getUserInfo", description: "Legacy: Get authenticated user profile information", inputSchema: { type: "object", properties: {}, required: [] } }, { name: "mcp0_fetchPersona", description: "Legacy: Get persona details by project and persona ID", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID (required)" }, personaId: { type: "string", description: "Persona ID (required)" } }, required: ["projectId", "personaId"] } }, { name: "mcp0_fetchElevatorPitch", description: "Legacy: Get project elevator pitch", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID (required)" } }, required: ["projectId"] } }, { name: "mcp0_fetchVisionStatement", description: "Legacy: Get project vision statement", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID (required)" } }, required: ["projectId"] } }, { name: "mcp0_fetchProductInfo", description: "Legacy: Get product information", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID (required)" } }, required: ["projectId"] } }, { name: "mcp0_fetchProjectEnvironment", description: "Legacy: Get project environment information", inputSchema: { type: "object", properties: { projectId: { type: "string", description: "Project ID (required)" } }, required: ["projectId"] } }, { name: "mcp0_checkNdaStatus", description: "Legacy: Check NDA status for the authenticated user", inputSchema: { type: "object", properties: {}, required: [] } } ]; // Store tools in map for quick lookup toolDefinitions.forEach(tool => { this.tools.set(tool.name, tool); }); } getToolDefinitions() { return Array.from(this.tools.values()); } getTool(name) { return this.tools.get(name); } hasTools(name) { return this.tools.has(name); } validateToolInput(toolName, input) { const tool = this.getTool(toolName); if (!tool) { throw new Error(`Unknown tool: ${toolName}`); } const schema = tool.inputSchema; const errors = []; // Check required fields if (schema.required && schema.required.length > 0) { for (const requiredField of schema.required) { if (!(requiredField in input) || input[requiredField] === null || input[requiredField] === undefined) { errors.push(`Missing required field: ${requiredField}`); } } } // Validate field types and constraints if (schema.properties) { for (const [fieldName, fieldSchema] of Object.entries(schema.properties)) { if (fieldName in input) { const value = input[fieldName]; // Type validation if (fieldSchema.type === 'integer' && !Number.isInteger(value)) { errors.push(`Field ${fieldName} must be an integer`); } else if (fieldSchema.type === 'string' && typeof value !== 'string') { errors.push(`Field ${fieldName} must be a string`); } // Constraint validation if (fieldSchema.minimum !== undefined && value < fieldSchema.minimum) { errors.push(`Field ${fieldName} must be at least ${fieldSchema.minimum}`); } if (fieldSchema.maximum !== undefined && value > fieldSchema.maximum) { errors.push(`Field ${fieldName} must be at most ${fieldSchema.maximum}`); } } } } if (errors.length > 0) { throw new Error(`Validation errors: ${errors.join(', ')}`); } return true; } async callTool(toolName, args, client) { // Validate tool exists if (!this.hasTools(toolName)) { throw new Error(`Unknown tool: ${toolName}`); } // Validate input this.validateToolInput(toolName, args); // All other tools require an authenticated client if (!client) { throw new Error('Client is required for this tool'); } // Call the appropriate client method based on tool name switch (toolName) { case 'list_user_stories': return await client.getUserStories(args.project_id, args.persona_id); case 'get_story_range': return await client.getStoryRange( args.project_id, args.persona_id, args.start_number, args.end_number ); case 'get_single_story_details': return await client.getSingleStoryDetails( args.project_id, args.persona_id, args.story_number, args.story_id ); case 'get_project_overview': return await client.getProjectOverview(args.project_id); case 'get_persona_profile': return await client.getPersonaProfile(args.project_id, args.persona_id); case 'get_user_journey': return await client.getUserJourney(args.project_id, args.persona_id); case 'get_jobs_to_be_done': return await client.getJobsToBeDone(args.project_id, args.persona_id); case 'get_user_info': return await client.getUserInfo(); case 'get_project_environment': return await client.getProjectEnvironment(args.project_id); case 'check_nda_status': return await client.checkNdaStatus(); case 'get_product_info': return await client.getProductInfo(args.project_id); case 'list_projects': return await client.getAllProjects(); case 'list_projects_paginated': return await client.listProjects(args.page, args.pageSize); case 'search_projects': return await client.searchProjects(args.query, args.page, args.pageSize); case 'find_project_by_name': return await client.findProjectByName(args.project_name); case 'find_persona_by_name': const findPersonaProjectId = await client.resolveProjectId(args.project_id); return await client.findPersonaByName(findPersonaProjectId, args.persona_name); case 'get_user_stories_by_name': const storiesProjectId = await client.resolveProjectId(args.project_name); const personaId = await client.resolvePersonaId(storiesProjectId, args.persona_name); return await client.getUserStories(storiesProjectId, personaId); case 'get_project_by_name': return await client.getProjectByName(args.project_name); case 'find_project_by_name': // Use direct name-to-ID mapping for known projects const projectId = await client.resolveProjectId(args.project_name); return { id: projectId, name: args.project_name }; case 'get_persona_by_name': const projectIdForPersona = await client.resolveProjectId(args.project_name); const personaIdForProfile = await client.resolvePersonaId(projectIdForPersona, args.persona_name); return await client.getPersonaProfile(projectIdForPersona, personaIdForProfile); // Legacy tools case 'mcp0_getUserInfo': return await client.getUserInfo(); case 'mcp0_fetchPersona': return await client.getPersonaProfile(args.projectId, args.personaId); case 'mcp0_fetchElevatorPitch': const overview = await client.getProjectOverview(args.projectId); return { result: overview.overview?.elevatorPitch || 'No elevator pitch available' }; case 'mcp0_fetchVisionStatement': const visionOverview = await client.getProjectOverview(args.projectId); return { result: visionOverview.overview?.visionStatement || 'No vision statement available' }; case 'mcp0_fetchProductInfo': return await client.getProductInfo(args.projectId); case 'mcp0_fetchProjectEnvironment': return await client.getProjectEnvironment(args.projectId); case 'mcp0_checkNdaStatus': return await client.checkNdaStatus(); default: throw new Error(`Tool ${toolName} not implemented`); } } getToolUsageStats() { return { totalTools: this.tools.size, toolNames: Array.from(this.tools.keys()) }; } }

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/Pratik-911/Rmx-mcp'

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