Skip to main content
Glama

MCP Resume Chat Server

by TharakaJayz
ResumeViewer.tsx•13.7 kB
"use client"; import { useState, useEffect } from "react"; interface ResumeData { personalInfo: { name: string; email: string; phone?: string; location?: string; linkedin?: string; github?: string; }; summary: string; experience: Array<{ company: string; position: string; startDate: string; endDate?: string; current: boolean; description: string; achievements: string[]; technologies: string[]; }>; education: Array<{ institution: string; degree: string; field: string; startDate: string; endDate?: string; gpa?: string; achievements?: string[]; }>; skills: string[]; projects?: Array<{ name: string; description: string; technologies: string[]; url?: string; github?: string; startDate: string; endDate?: string; }>; certifications?: Array<{ name: string; issuer: string; date: string; credentialId?: string; url?: string; }>; } export default function ResumeViewer() { const [resumeData, setResumeData] = useState<ResumeData | null>(null); const [loading, setLoading] = useState(true); const [error, setError] = useState<string | null>(null); const [activeSection, setActiveSection] = useState<string>("personal"); useEffect(() => { loadResumeData(); }, []); const loadResumeData = async () => { try { const response = await fetch("/api/resume"); if (!response.ok) { throw new Error("Failed to load resume data"); } const data = await response.json(); setResumeData(data); } catch (err) { setError( "Failed to load resume data. Please check if the data file exists." ); } finally { setLoading(false); } }; const sections = [ { id: "personal", label: "Personal Info", icon: "šŸ‘¤" }, { id: "summary", label: "Summary", icon: "šŸ“" }, { id: "experience", label: "Experience", icon: "šŸ’¼" }, { id: "education", label: "Education", icon: "šŸŽ“" }, { id: "skills", label: "Skills", icon: "šŸ› ļø" }, { id: "projects", label: "Projects", icon: "šŸš€" }, { id: "certifications", label: "Certifications", icon: "šŸ†" }, ]; if (loading) { return ( <div className="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-8"> <div className="flex items-center justify-center"> <div className="w-8 h-8 border-4 border-blue-600 border-t-transparent rounded-full animate-spin mr-3"></div> <span className="text-gray-600 dark:text-gray-400"> Loading resume data... </span> </div> </div> ); } if (error || !resumeData) { return ( <div className="bg-white dark:bg-gray-800 rounded-lg shadow-lg p-8"> <div className="text-center"> <div className="text-red-500 text-4xl mb-4">āŒ</div> <h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-2"> Error Loading Resume </h3> <p className="text-gray-600 dark:text-gray-400"> {error || "Resume data not found"} </p> </div> </div> ); } const renderPersonalInfo = () => ( <div className="space-y-4"> <div className="text-center"> <h2 className="text-3xl font-bold text-gray-900 dark:text-white"> {resumeData.personalInfo.name} </h2> <p className="text-lg text-gray-600 dark:text-gray-400 mt-2"> {resumeData.personalInfo.email} </p> {resumeData.personalInfo.phone && ( <p className="text-gray-600 dark:text-gray-400"> {resumeData.personalInfo.phone} </p> )} {resumeData.personalInfo.location && ( <p className="text-gray-600 dark:text-gray-400"> {resumeData.personalInfo.location} </p> )} </div> <div className="flex justify-center space-x-4 mt-6"> {resumeData.personalInfo.linkedin && ( <a href={resumeData.personalInfo.linkedin} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" > LinkedIn </a> )} {resumeData.personalInfo.github && ( <a href={resumeData.personalInfo.github} target="_blank" rel="noopener noreferrer" className="text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-300" > GitHub </a> )} </div> </div> ); const renderSummary = () => ( <div className="prose dark:prose-invert max-w-none"> <p className="text-gray-700 dark:text-gray-300 leading-relaxed"> {resumeData.summary} </p> </div> ); const renderExperience = () => ( <div className="space-y-6"> {resumeData.experience.map((exp, index) => ( <div key={index} className="border-l-4 border-blue-500 pl-4"> <div className="flex justify-between items-start mb-2"> <div> <h3 className="text-xl font-semibold text-gray-900 dark:text-white"> {exp.position} </h3> <p className="text-lg text-blue-600 dark:text-blue-400 font-medium"> {exp.company} </p> </div> <div className="text-right text-sm text-gray-600 dark:text-gray-400"> <p> {exp.startDate} - {exp.endDate || "Present"} </p> {exp.current && ( <span className="inline-block bg-green-100 dark:bg-green-900 text-green-800 dark:text-green-200 px-2 py-1 rounded-full text-xs mt-1"> Current </span> )} </div> </div> <p className="text-gray-700 dark:text-gray-300 mb-3"> {exp.description} </p> <div className="mb-3"> <h4 className="font-medium text-gray-900 dark:text-white mb-2"> Key Achievements: </h4> <ul className="list-disc list-inside space-y-1 text-gray-700 dark:text-gray-300"> {exp.achievements.map((achievement, idx) => ( <li key={idx}>{achievement}</li> ))} </ul> </div> <div> <h4 className="font-medium text-gray-900 dark:text-white mb-2"> Technologies: </h4> <div className="flex flex-wrap gap-2"> {exp.technologies.map((tech, idx) => ( <span key={idx} className="bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 px-2 py-1 rounded text-sm" > {tech} </span> ))} </div> </div> </div> ))} </div> ); const renderEducation = () => ( <div className="space-y-4"> {resumeData.education.map((edu, index) => ( <div key={index} className="border-l-4 border-green-500 pl-4"> <h3 className="text-xl font-semibold text-gray-900 dark:text-white"> {edu.degree} in {edu.field} </h3> <p className="text-lg text-green-600 dark:text-green-400 font-medium"> {edu.institution} </p> <p className="text-gray-600 dark:text-gray-400"> {edu.startDate} - {edu.endDate || "Present"} {edu.gpa && ` • GPA: ${edu.gpa}`} </p> {edu.achievements && edu.achievements.length > 0 && ( <div className="mt-2"> <h4 className="font-medium text-gray-900 dark:text-white mb-1"> Achievements: </h4> <ul className="list-disc list-inside text-gray-700 dark:text-gray-300"> {edu.achievements.map((achievement, idx) => ( <li key={idx}>{achievement}</li> ))} </ul> </div> )} </div> ))} </div> ); const renderSkills = () => ( <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3"> {resumeData.skills.map((skill, index) => ( <div key={index} className="bg-blue-50 dark:bg-blue-900/20 text-blue-800 dark:text-blue-200 px-3 py-2 rounded-lg text-center font-medium" > {skill} </div> ))} </div> ); const renderProjects = () => ( <div className="space-y-6"> {resumeData.projects?.map((project, index) => ( <div key={index} className="border border-gray-200 dark:border-gray-700 rounded-lg p-4" > <div className="flex justify-between items-start mb-2"> <h3 className="text-xl font-semibold text-gray-900 dark:text-white"> {project.name} </h3> <div className="text-sm text-gray-600 dark:text-gray-400"> {project.startDate} - {project.endDate || "Present"} </div> </div> <p className="text-gray-700 dark:text-gray-300 mb-3"> {project.description} </p> <div className="mb-3"> <h4 className="font-medium text-gray-900 dark:text-white mb-2"> Technologies: </h4> <div className="flex flex-wrap gap-2"> {project.technologies.map((tech, idx) => ( <span key={idx} className="bg-gray-100 dark:bg-gray-700 text-gray-800 dark:text-gray-200 px-2 py-1 rounded text-sm" > {tech} </span> ))} </div> </div> <div className="flex space-x-4"> {project.url && ( <a href={project.url} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" > View Project </a> )} {project.github && ( <a href={project.github} target="_blank" rel="noopener noreferrer" className="text-gray-600 hover:text-gray-800 dark:text-gray-400 dark:hover:text-gray-300" > GitHub </a> )} </div> </div> ))} </div> ); const renderCertifications = () => ( <div className="space-y-4"> {resumeData.certifications?.map((cert, index) => ( <div key={index} className="border border-gray-200 dark:border-gray-700 rounded-lg p-4" > <h3 className="text-lg font-semibold text-gray-900 dark:text-white"> {cert.name} </h3> <p className="text-gray-600 dark:text-gray-400"> {cert.issuer} • {cert.date} </p> {cert.credentialId && ( <p className="text-sm text-gray-500 dark:text-gray-500"> Credential ID: {cert.credentialId} </p> )} {cert.url && ( <a href={cert.url} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 text-sm" > View Certificate </a> )} </div> ))} </div> ); const renderContent = () => { switch (activeSection) { case "personal": return renderPersonalInfo(); case "summary": return renderSummary(); case "experience": return renderExperience(); case "education": return renderEducation(); case "skills": return renderSkills(); case "projects": return renderProjects(); case "certifications": return renderCertifications(); default: return renderPersonalInfo(); } }; return ( <div className="bg-white dark:bg-gray-800 rounded-lg shadow-lg"> {/* Header */} <div className="p-6 border-b border-gray-200 dark:border-gray-700"> <h2 className="text-2xl font-semibold text-gray-900 dark:text-white mb-2"> šŸ“„ Resume Viewer </h2> <p className="text-gray-600 dark:text-gray-400"> View and explore your resume data </p> </div> <div className="flex"> {/* Sidebar Navigation */} <div className="w-64 border-r border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-900"> <nav className="p-4"> <ul className="space-y-2"> {sections.map((section) => ( <li key={section.id}> <button onClick={() => setActiveSection(section.id)} className={`w-full text-left px-3 py-2 rounded-lg transition-colors ${ activeSection === section.id ? "bg-blue-600 text-white" : "text-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-700" }`} > <span className="mr-2">{section.icon}</span> {section.label} </button> </li> ))} </ul> </nav> </div> {/* Content */} <div className="flex-1 p-6">{renderContent()}</div> </div> </div> ); }

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/TharakaJayz/mcp-server'

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