Candidate MCP Server Library

by jhgaylor

81 stars
335 downloads
Not rated
GitHub

About

A Model Context Protocol (MCP) server library that gives LLMs access to information about a candidate.

Details

Author
jhgaylor
GitHub stars
81
Downloads
335
Categories
Developer Tools, AI

- Library-first design for easy application integration
- Modular resource system extensible with custom data
- Full Model Context Protocol specification implementation
- Supports STDIO, Streamable HTTP, and Express transports
- TypeScript for type safety and developer experience
- Minimal dependencies

Install via npm install @jhgaylor/candidate-mcp-server. Import createServer, configure with serverConfig and candidateConfig, then connect to an MCP transport (Stdio, Streamable HTTP, or Express). The library provides resource URIs like candidate-info://resume-text and tools like get_resume_text and contact_candidate.

Candidate MCP Server Library

A Model Context Protocol (MCP) server that gives LLMs access to information about a candidate.

Overview

> Important: This server is intended to be used as a library to be integrated into other applications, not as a standalone service. The provided startup methods are for demonstration and testing purposes only.

Resources

This MCP server provides the following resources:

- candidate-info://resume-text: Resume content as text
- candidate-info://resume-url: URL to the resume
- candidate-info://linkedin-url: LinkedIn profile URL
- candidate-info://github-url: GitHub profile URL
- candidate-info://website-url: Personal website URL
- candidate-info://website-text: Content from the personal website

Tools

This MCP server also provides tools that return the same candidate information:

- get_resume_text: Returns the candidate's resume content as text
- get_resume_url: Returns the URL to the candidate's resume
- get_linkedin_url: Returns the candidate's LinkedIn profile URL
- get_github_url: Returns the candidate's GitHub profile URL
- get_website_url: Returns the candidate's personal website URL
- get_website_text: Returns the content from the candidate's personal website
- contact_candidate: Sends an email to the candidate (requires Mailgun configuration)

Usage

npm install @jhgaylor/candidate-mcp-server

Library Usage

This package is designed to be imported and used within your own applications.

Stdio

Starting the process is a breeze with stdio. The interesting part is providing the candidate configuration.

Where you source the candidate configuration is entirely up to you. Maybe you hard code it. Maybe you take a JSONResume url when you start the process. It's up to you!

import { createServer } from '@jhgaylor/candidate-mcp-server';
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

// Configure your server
const serverConfig = {
name: "MyCandidateServer",
version: "1.0.0",
mailgunApiKey: process.env.MAILGUN_API_KEY,
mailgunDomain: process.env.MAILGUN_DOMAIN
};
const candidateConfig = {
name: "John Doe",
email: "john.doe@example.com", // Required for the contact_candidate tool
resumeUrl: "https://example.com/resume.pdf",
// other candidate properties
};

// Create server instance
const server = createServer(serverConfig, candidateConfig);

// Connect with your preferred transport
await server.connect(new StdioServerTransport());
// or integrate with your existing HTTP server

StreamableHttp

Using the example code provided by the typescript sdk we can bind this mcp server to an express server.

import express from 'express';
import { Request, Response } from 'express';
import { createServer } from '@jhgaylor/candidate-mcp-server';
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamablehttp.js";

// Configure your server
const serverConfig = {
name: "MyCandidateServer",
version: "1.0.0",
mailgunApiKey: process.env.MAILGUN_API_KEY,
mailgunDomain: process.env.MAILGUN_DOMAIN,
contactEmail: "john.doe@example.com",
};
const candidateConfig = {
name: "John Doe",
resumeUrl: "https://example.com/resume.pdf",
// other candidate properties
};

// Factory function to create a new server instance for each request
const getServer = () => createServer(serverConfig, candidateConfig);

const app = express();
app.use(express.json());

app.post('/mcp', async (req: Request, res: Response) => {
// In stateless mode, create a new instance of transport and server for each request
// to ensure complete isolation. A single instance would cause request ID collisions
// when multiple clients connect concurrently.

try {
const server = getServer();
const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined,
});
res.on('close', () => {
console.log('Request closed');
transport.close();
server.close();
});
await server.connect(transport);
await transport.handleRequest(req, res, req.body);
} catch (error) {
console.error('Error handling MCP request:', error);
if (!res.headersSent) {
res.status(500).json({
jsonrpc: '2.0',
error: {
code: -32603,
message: 'Internal server error',
},
id: null,
});
}
}
});

app.get('/mcp', async (req: Request, res: Response) => {
console.log('Received GET MCP request');
res.writeHead(405).end(JSON.stringify({
jsonrpc: "2.0",
error: {
code: -32000,
message: "Method not allowed."
},
id: null
}));
});

app.delete('/mcp', async (req: Request, res: Response) => {
console.log('Received DELETE MCP request');
res.writeHead(405).end(JSON.stringify({
jsonrpc: "2.0",
error: {
code: -32000,
message: "Method not allowed."
},
id: null
}));
});

// Start the server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(MCP Stateless Streamable HTTP Server listening on port ${PORT});
});

Express

Instead of writing the binding between express and the mcp transport yourself, you can use express-mcp-handler to do it for you.

npm install express-mcp-handler

import express from 'express';
import { statelessHandler } from 'express-mcp-handler';
import { createServer } from './server';

// You can configure the server factory to include Mailgun settings
const createServerWithConfig = () => {
const serverConfig = {
name: "MyCandidateServer",
version: "1.0.0",
mailgunApiKey: process.env.MAILGUN_API_KEY,
mailgunDomain: process.env.MAILGUN_DOMAIN,
contactEmail: "john.doe@example.com",
};
const candidateConfig = {
name: "John Doe",
resumeUrl: "https://example.com/resume.pdf",
// other candidate properties
};

return createServer(serverConfig, candidateConfig);
};

// Configure the stateless handler
const handler = statelessHandler(createServerWithConfig);

// Create Express app
const app = express();
app.use(express.json());

// Mount the handler (stateless only needs POST)
app.post('/mcp', handler);

// Start the server
const PORT = process.env.PORT || 3002;
app.listen(PORT, () => {
console.log(Stateless MCP server running on port ${PORT});
});

Development

```bash

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.