返回市场
候选节点MCP服务器

候选节点MCP服务器

作者:jhgaylor82 星标更新:2025-05-08

项目介绍

候选人MCP服务器库

一个模型上下文协议(MCP)服务器,提供LLMs访问候选人信息的功能。

概述

重要提示:此服务器旨在作为库集成到其他应用程序中,而不是作为一个独立的服务。提供的启动方法仅用于演示和测试目的。

资源

此MCP服务器提供以下资源:

  • candidate-info://resume-text:简历内容作为文本
  • candidate-info://resume-url:简历的URL
  • candidate-info://linkedin-url:LinkedIn个人资料URL
  • candidate-info://github-url:GitHub个人资料URL
  • candidate-info://website-url:个人网站URL
  • candidate-info://website-text:个人网站的内容

工具

此MCP服务器还提供了返回相同候选人信息的工具:

  • get_resume_text:返回候选人的简历内容作为文本
  • get_resume_url:返回候选人的简历URL
  • get_linkedin_url:返回候选人的LinkedIn个人资料URL
  • get_github_url:返回候选人的GitHub个人资料URL
  • get_website_url:返回候选人的个人网站URL
  • get_website_text:返回候选人的个人网站内容
  • contact_candidate:向候选人发送电子邮件(需要Mailgun配置)

使用

npm install @jhgaylor/candidate-mcp-server

库使用

此包设计为在您自己的应用程序中导入并使用。

标准I/O

使用标准I/O启动进程非常简单。有趣的部分是提供候选人配置。

您从何处获取候选人配置完全取决于您。也许您硬编码它。也许您在启动进程时提供一个JSONResume URL。这由您决定!

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

// 配置您的服务器
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", // 对于contact_candidate工具是必需的
  resumeUrl: "https://example.com/resume.pdf",
  // 其他候选人属性
};

// 创建服务器实例
const server = createServer(serverConfig, candidateConfig);

// 使用您首选的传输连接
await server.connect(new StdioServerTransport());
// 或者与现有的HTTP服务器集成

可流式HTTP

使用类型脚本SDK提供的示例代码,我们可以将此MCP服务器绑定到一个Express服务器。

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

// 配置您的服务器
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",
  // 其他候选人属性
};

// 工厂函数,为每个请求创建一个新的服务器实例
const getServer = () => createServer(serverConfig, candidateConfig);

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

app.post('/mcp', async (req: Request, res: Response) => {
  // 在无状态模式下,为每个请求创建一个新的传输和服务器实例
  // 以确保完全隔离。单个实例会在多个客户端同时连接时导致请求ID冲突。
  
  try {
    const server = getServer(); 
    const transport = new StreamableHTTPServerTransport({
      sessionIdGenerator: undefined,
    });
    res.on('close', () => {
      console.log('请求已关闭');
      transport.close();
      server.close();
    });
    await server.connect(transport);
    await transport.handleRequest(req, res, req.body);
  } catch (error) {
    console.error('处理MCP请求时出错:', error);
    if (!res.headersSent) {
      res.status(500).json({
        jsonrpc: '2.0',
        error: {
          code: -32603,
          message: '内部服务器错误',
        },
        id: null,
      });
    }
  }
});

app.get('/mcp', async (req: Request, res: Response) => {
  console.log('收到GET MCP请求');
  res.writeHead(405).end(JSON.stringify({
    jsonrpc: "2.0",
    error: {
      code: -32000,
      message: "不允许的方法。",
    },
    id: null
  }));
});

app.delete('/mcp', async (req: Request, res: Response) => {
  console.log('收到DELETE MCP请求');
  res.writeHead(405).end(JSON.stringify({
    jsonrpc: "2.0",
    error: {
      code: -32000,
      message: "不允许的方法。",
    },
    id: null
  }));
});

// 启动服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`MCP无状态可流式HTTP服务器正在端口${PORT}上监听`);
});

Express

您可以使用express-mcp-handler来代替自己编写Express和MCP传输之间的绑定。

npm install express-mcp-handler

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

// 您可以配置服务器工厂以包括Mailgun设置
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",
    // 其他候选人属性
  };
  
  return createServer(serverConfig, candidateConfig);
};

// 配置无状态处理器
const handler = statelessHandler(createServerWithConfig);

// 创建Express应用
const app = express();
app.use(express.json());

// 安装处理器(无状态只需要POST)
app.post('/mcp', handler);

// 启动服务器
const PORT = process.env.PORT || 3002;
app.listen(PORT, () => {
  console.log(`无状态MCP服务器正在端口${PORT}上运行`);
});

开发

# 安装依赖
npm install

# 构建项目
npm run build

# 在开发模式下运行并自动重启
npm run dev

通过标准I/O进行演示/调试启动

# 通过标准I/O启动(仅限演示)
npm start

当使用标准I/O运行时,可以通过发送MCP消息(作为单行JSON对象)与服务器交互:

# 发送初始化消息的示例
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

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

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

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

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

# 向候选人发送电子邮件
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

每条消息必须在一行内,JSON对象内不能有换行符。

特性

  • 优先库设计,便于集成到其他应用程序中
  • 模块化资源系统,便于扩展自定义候选人信息
  • 使用TypeScript,确保类型安全和更好的开发者体验
  • 实现完整的模型上下文协议规范
  • 支持多种传输类型(标准I/O、HTTP、可流式HTTP)
  • 最小依赖项

服务器结构

src/
  ├── index.ts                # 主包入口点
  ├── server.ts               # 带有配置的MCP服务器工厂
  ├── config.ts               # 配置类型定义
  └── resources/              # 模块化资源定义
      └── index.ts            # 资源工厂和实现

MCP协议

此库实现了模型上下文协议(MCP),这是一种标准化的方式,使LLMs能够与外部数据和功能交互。将其集成到您的应用程序中后,它会暴露一个无状态API,响应JSON-RPC请求。

API使用

一旦集成到您的应用程序中,客户端可以通过发送JSON-RPC请求与MCP服务器交互。以下是集成此库后您的应用程序将处理的一些请求示例:

初始化

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"
      }
    }
  }'

访问候选人资源

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
  }'

扩展库

此库设计为可以扩展自定义资源、工具和提示。这里是如何添加您自己的资源:

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

// 创建您的自定义资源类
class CustomCandidateResource extends Resource {
  constructor(candidateConfig) {
    super(
      `${candidateConfig.name} 自定义数据`, 
      "candidate-info://custom-data", 
      async () => {
        return {
          contents: [
            { 
              uri: "candidate-info://custom-data", 
              mimeType: "text/plain", 
              text: "您的自定义候选人数据在这里"
            }
          ]
        };
      }
    );
  }
}

// 使用标准配置创建服务器
const server = createServer(serverConfig, candidateConfig);

// 添加您的自定义资源
const customResource = new CustomCandidateResource(candidateConfig);
customResource.bind(server);

// 使用您首选的传输连接
// ...

添加自定义工具

您还可以通过自定义工具扩展库:

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

// 使用标准配置创建服务器
const server = createServer(serverConfig, candidateConfig);

// 添加一个自定义工具
server.tool(
  'get_candidate_skills',
  '返回候选人的技能列表',
  {},
  async (_args, _extra) => {
    return {
      content: [
        { 
          type: "text", 
          text: "JavaScript, TypeScript, React, Node.js, MCP协议" 
        }
      ]
    };
  }
);

// 使用您首选的传输连接
// ...

要求

  • Node.js 20+
  • npm或yarn

许可证

MIT

发布到npm

如果您尚未登录,请先登录npm:

npm login

发布包到npm(将运行您的预发布构建):

npm publish

要增加版本号、打标签并推送新版本:

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