candidate-mcp-server

candidate-mcp-server

Enables LLMs to access candidate information including resume, LinkedIn, GitHub, and contact via email.

Category
访问服务器

README

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

# Install dependencies
npm install

# Build the project
npm run build

# Run in development mode with auto-restart
npm run dev

Demo / Debug Startup via stdio

# Start with STDIO (demo only)
npm start

When running with STDIO, you can interact with the server by sending MCP messages as single-line JSON objects:

# Example of sending an initialize message via STDIO
echo '{"jsonrpc": "2.0","id": 1,"method": "initialize","params": {"protocolVersion": "2024-11-05","capabilities": {"roots": {"listChanged": true},"sampling": {}},"clientInfo": {"name": "ExampleClient","version": "1.0.0"}}}' | node dist/index.js --stdio

# List resources
echo '{"jsonrpc": "2.0","id": 2,"method": "resources/list","params": {}}' | node dist/index.js --stdio

# Access a resource
echo '{"jsonrpc": "2.0","id": 3,"method": "resources/read","params": {"uri": "candidate-info://resume-text"}}' | node dist/index.js --stdio

# List Tools
echo '{"jsonrpc": "2.0","id": 2,"method": "tools/list","params": {}}' | node dist/index.js --stdio

# Call a tool
echo '{"jsonrpc": "2.0","id": 4,"method": "tools/call","params": {"name": "get_resume_text", "args": {}}}' | node dist/index.js --stdio

# Send an email to the candidate
echo '{"jsonrpc": "2.0","id": 5,"method": "tools/call","params": {"name": "contact_candidate", "args": {"subject": "Hello from AI!", "message": "This is a test email sent via the MCP server.", "reply_address": "recruiter@company.com"}}}' | node dist/index.js --stdio

Each message must be on a single line with no line breaks within the JSON object.

Features

  • 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

Server Structure

src/
  ├── index.ts                # Main package entry point
  ├── server.ts               # MCP server factory with configuration
  ├── config.ts               # Configuration type definitions
  └── resources/              # Modular resource definitions
      └── index.ts            # Resource factory and implementation

MCP Protocol

This library implements the Model Context Protocol (MCP), a standardized way for LLMs to interact with external data and functionality. When integrated into your application, it exposes a stateless API that responds to JSON-RPC requests.

API Usage

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:

Initialize

curl -X POST http://your-application-url/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2024-11-05",
      "capabilities": {
        "roots": {
          "listChanged": true
        },
        "sampling": {}
      },
      "clientInfo": {
        "name": "ExampleClient",
        "version": "1.0.0"
      }
    }
  }'

Access Candidate Resources

curl -X POST http://your-application-url/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Accept: text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "method": "resources/read",
    "params": {
      "uri": "candidate-info://resume-text"
    },
    "id": 2
  }'

Extending the Library

This library is designed to be extended with custom resources, tools, and prompts. Here's how to add your own resources:

import { McpServer, Resource } from '@jhgaylor/candidate-mcp-server';

// Create your custom resource class
class CustomCandidateResource extends Resource {
  constructor(candidateConfig) {
    super(
      `${candidateConfig.name} Custom Data`, 
      "candidate-info://custom-data", 
      async () => {
        return {
          contents: [
            { 
              uri: "candidate-info://custom-data", 
              mimeType: "text/plain", 
              text: "Your custom candidate data here"
            }
          ]
        };
      }
    );
  }
}

// Create server with standard configuration
const server = createServer(serverConfig, candidateConfig);

// Add your custom resource
const customResource = new CustomCandidateResource(candidateConfig);
customResource.bind(server);

// Connect with preferred transport
// ...

Adding Custom Tools

You can also extend the library with custom tools:

import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { createServer } from '@jhgaylor/candidate-mcp-server';

// Create server with standard configuration
const server = createServer(serverConfig, candidateConfig);

// Add a custom tool
server.tool(
  'get_candidate_skills',
  'Returns a list of the candidate skills',
  {},
  async (_args, _extra) => {
    return {
      content: [
        { 
          type: "text", 
          text: "JavaScript, TypeScript, React, Node.js, MCP Protocol" 
        }
      ]
    };
  }
);

// Connect with preferred transport
// ...

Requirements

  • Node.js 20+
  • npm or yarn

License

MIT

Publishing to npm

Log in to npm if you haven't already:

npm login

Publish the package to npm (will run your prepublishOnly build):

npm publish

To bump, tag, and push a new version:

npm version patch    # or minor, major
git push origin main --tags

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选