Candidate MCP Server Library
About
A Model Context Protocol (MCP) server library that gives LLMs access to information about a candidate.
Details
- License
- MIT
Explore
- Library-first design for integration into other applications
- Modular resource system for extending with custom candidate information
- TypeScript for type safety and better developer experience
- Implements the full Model Context Protocol specification
- Supports multiple transport types (STDIO, HTTP, Streamable HTTP)
- Minimal dependencies
npm install @jhgaylor/candidate-mcp-server
This package is designed to be imported and used within your own applications.
npm install
Once integrated into your application, clients can interact with the MCP server by sending JSON-RPC requests. Here are examples of requests that your application would handle after integrating this library:
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)
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)
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: "[email protected]", // 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: "[email protected]",
};
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: "[email protected]",
};
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
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.



