index.js•6.16 kB
const { Server } = require("@modelcontextprotocol/sdk/server/index.js");
const {
StdioServerTransport,
} = require("@modelcontextprotocol/sdk/server/stdio.js");
const {
CallToolRequestSchema,
ListToolsRequestSchema,
} = require("@modelcontextprotocol/sdk/types.js");
// Import our services (we'll need to compile TypeScript or use require for JS versions)
const { ResumeParser } = require("../services/resumeParser.js");
const { ResumeChatService } = require("../services/resumeChatService.js");
const { EmailService } = require("../services/emailService.js");
// Configuration
const mcpConfig = {
server: {
name: "resume-chat-mcp-server",
version: "1.0.0",
},
tools: {
resumeChat: {
name: "resume_chat",
description:
"Chat about resume/CV information and answer questions about work experience, skills, and education",
},
sendEmail: {
name: "send_email",
description: "Send email notifications with recipient, subject, and body",
},
},
openai: {
apiKey: process.env.OPENAI_API_KEY || "",
model: "gpt-3.5-turbo",
maxTokens: 1000,
temperature: 0.7,
},
};
class ResumeChatMCPServer {
constructor() {
this.server = new Server(
{
name: mcpConfig.server.name,
version: mcpConfig.server.version,
},
{
capabilities: {
tools: {},
},
}
);
// Initialize services
this.resumeParser = new ResumeParser();
this.resumeChatService = new ResumeChatService(this.resumeParser);
this.emailService = new EmailService();
this.setupHandlers();
}
setupHandlers() {
// List available tools
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: mcpConfig.tools.resumeChat.name,
description: mcpConfig.tools.resumeChat.description,
inputSchema: {
type: "object",
properties: {
question: {
type: "string",
description: "The question to ask about the resume/CV",
},
context: {
type: "string",
description: "Additional context for the question (optional)",
},
},
required: ["question"],
},
},
{
name: mcpConfig.tools.sendEmail.name,
description: mcpConfig.tools.sendEmail.description,
inputSchema: {
type: "object",
properties: {
recipient: {
type: "string",
description: "Email address of the recipient",
},
subject: {
type: "string",
description: "Subject of the email",
},
body: {
type: "string",
description: "Body content of the email",
},
from: {
type: "string",
description: "Sender email address (optional)",
},
},
required: ["recipient", "subject", "body"],
},
},
],
};
});
// Handle tool calls
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params;
try {
switch (name) {
case mcpConfig.tools.resumeChat.name:
return await this.handleResumeChat(args);
case mcpConfig.tools.sendEmail.name:
return await this.handleSendEmail(args);
default:
throw new Error(`Unknown tool: ${name}`);
}
} catch (error) {
return {
content: [
{
type: "text",
text: `Error: ${
error instanceof Error ? error.message : "Unknown error"
}`,
},
],
};
}
});
}
async handleResumeChat(args) {
try {
// Ensure resume data is loaded
if (!this.resumeParser.getResumeData()) {
await this.resumeParser.loadResumeData();
}
const response = await this.resumeChatService.answerQuestion(args);
return {
content: [
{
type: "text",
text: `**Answer:** ${response.answer}\n\n**Confidence:** ${(
response.confidence * 100
).toFixed(1)}%\n**Sources:** ${response.sources.join(", ")}`,
},
],
};
} catch (error) {
throw new Error(`Failed to process resume question: ${error}`);
}
}
async handleSendEmail(args) {
try {
const result = await this.emailService.sendEmail(args);
if (result.success) {
return {
content: [
{
type: "text",
text: `✅ Email sent successfully!\nMessage ID: ${result.messageId}\nRecipient: ${args.recipient}\nSubject: ${args.subject}`,
},
],
};
} else {
throw new Error(result.error || "Failed to send email");
}
} catch (error) {
throw new Error(`Failed to send email: ${error}`);
}
}
async run() {
// Load resume data on startup
try {
await this.resumeParser.loadResumeData();
console.error("✅ Resume data loaded successfully");
} catch (error) {
console.error("❌ Failed to load resume data:", error);
}
// Test email configuration
const emailConfigStatus = this.emailService.getConfigStatus();
if (emailConfigStatus.configured) {
console.error("✅ Email configuration is valid");
} else {
console.error("⚠️ Email configuration issues:", emailConfigStatus.issues);
}
const transport = new StdioServerTransport();
await this.server.connect(transport);
console.error("🚀 MCP Server started successfully");
}
}
// Start the server
const server = new ResumeChatMCPServer();
server.run().catch((error) => {
console.error("Fatal error:", error);
process.exit(1);
});