个人MCP服务器

mcp-me是一个将专业数据转化为LLM可消费工具的MCP服务器,适用于招聘代理、LLM和个人助手等场景。

  • by fe-m-bueno
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 fe-m-bueno/mcp-me

使用说明

mcp-me: Personal MCP Server

An MCP (Model Context Protocol) server that turns professional data into tools an LLM can consume. Instead of a recruiter reading a static CV PDF, they (or an agent) ask questions and get real, structured data back.

Status: Production | Version: 1.0.0 | Runtime: Node.js + TypeScript

Overview

mcp-me exposes 4 MCP tools that query:

  • Bilingual CVs (EN / PT-BR) in Markdown as the source of truth
  • Expanded project data (repository, demo, technical highlights, status)
  • Job ↔ profile fit analysis with skill matching
  • Keyword search across the entire professional history

It suits:

  • Recruiting agents that analyze job postings automatically
  • LLMs that need structured biographical data
  • Personal assistants that answer questions about experience
  • Automating candidate-job compatibility analyses

Characteristics

  • Full support for English and Brazilian Portuguese
  • Only 2 dependencies (MCP SDK + Zod)
  • Strict TypeScript with Zod validation
  • Efficient in-memory loading
  • Markdown parsed by hand
  • match_job reports real gaps instead of inflating the profile
  • Structured natural text, not raw JSON

MCP Tools

1. get_cv

Returns the complete CV or a specific section.

Input:

{
  "lang": "en" | "pt-br",  // optional, default: "en"
  "section": "summary" | "skills" | "experience" | "projects" | "education" | "certifications" | "languages"  // optional
}

Output: Formatted Markdown text with the CV or the requested section.

Usage examples:

get_cv({ lang: "pt-br" })
→ Returns the full CV in Portuguese

get_cv({ lang: "en", section: "skills" })
→ Returns only the technical skills section, in English

get_cv({ section: "professional experience" })
→ Partial match: returns the experience section

2. list_projects

Lists projects with full metadata: description, stack, highlights, repository URL, demo URL, and status.

Input:

{
  "tech": "Next.js" | "Python" | "React" | ...  // optional, case-insensitive, partial match
}

Output: A formatted list of projects with structured fields.

Status: "completed" | "in-progress" | "active" | "experimental" Category: "cv" (featured on the CV) | "additional" (extras on GitHub)

Usage examples:

list_projects()
→ Lists all 8+ projects

list_projects({ tech: "next" })
→ Filters projects using Next.js, returns 2-3 results

list_projects({ tech: "python" })
→ Filters projects using Python, returns the AI/data projects

3. match_job

Analyzes the fit between the profile and a job description. It returns:

  • Fit Score (0-100): the percentage of the job description's technical skills present in the CV
  • Matching Skills: skills present on both sides
  • Gaps: required skills that are not in the CV
  • Relevant Experience: excerpts of professional experience aligned with the role
  • Suggested Pitch: an honest assessment calibrated to the score

Input:

{
  "description": "Fullstack Engineer needed for Next.js/React + Python FastAPI microservices..."
}

Output: A structured analysis with the score, matching skills, gaps, and pitch.

Score interpretation:

  • 70-100: Strong fit — the candidate is clearly aligned with the role
  • 40-69: Partial fit — there is overlap, but significant gaps
  • 0-39: Low fit — this would be a career pivot, not a natural next step

Examples:

match_job({ description: "React + TypeScript + Node.js backend engineer needed..." })
→ Score: 92, Matching Skills: React, TypeScript, Node.js, ...
→ Gaps: (none), Suggested Pitch: Strong fit...

match_job({ description: "Lead Golang architect, 10 years Go experience required..." })
→ Score: 15, Matching Skills: (none), Gaps: Go, Kubernetes orchestration, ...
→ Suggested Pitch: Limited overlap, significant career pivot...

4. ask_about_me

Runs a keyword search across the whole profile (CV + projects) and returns the 10 most relevant excerpts, grouped by section.

Input:

{
  "question": "ETL experience?" | "databases usados?" | "tem experiência com IA?" | ...
}

Output: Experience excerpts grouped by section (Professional Experience, Projects, and so on)

Supports:

  • Keywords in English and Portuguese
  • Searching by technology, role, or concept
  • Stop-word filtering to reduce noise

Examples:

ask_about_me({ question: "ETL experience" })
→ Returns experience with data pipelines, Airflow, and so on

ask_about_me({ question: "tem experiência com IA?" })
→ Returns projects and experience with LLMs, CrewAI, and so on

ask_about_me({ question: "Docker Kubernetes" })
→ Returns sections on DevOps, containerization, and orchestration

Stack

Component Technology
Runtime Node.js 22+ (ES Modules)
Language TypeScript 5.7
Protocol MCP SDK @modelcontextprotocol/sdk ^1.12.1
Validation Zod ^3.25.67
Build tsup 8.0
Linting Biome 1.9
Transport stdio (standard stdin/stdout communication)

Installation

Prerequisites

  • Node.js 22+ (check with node --version)
  • npm 10+ (or yarn/pnpm)

Steps

# 1. Clone the repository
git clone https://github.com/fe-m-bueno/mcp-me.git
cd mcp-me

# 2. Install the dependencies
npm install

# 3. Build
npm run build

# 4. Verify the build
ls dist/
# You should see: index.js, index.d.ts (sourcemaps), data/ (CVs + projects)

Post-Build Structure

dist/
├── index.js           # Compiled entry point
├── index.js.map       # Sourcemap
├── index.d.ts         # TypeScript types
└── data/
    ├── cv-en.md       # CV in English
    ├── cv-ptbr.md     # CV in Portuguese
    └── projects.json  # Project data

Usage

As an MCP Server (in a client)

Configure it in your MCP client (Claude Desktop, Cline, and so on):

macOS/Linux — ~/.config/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "me": {
      "command": "node",
      "args": ["/home/felipebueno/Development/mcp-me/dist/index.js"]
    }
  }
}

Windows — %APPDATA%/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "me": {
      "command": "node",
      "args": ["C:/Users/felipebueno/Development/mcp-me/dist/index.js"]
    }
  }
}

After configuring it, restart the MCP client. The 4 tools will show up as available.

Local Testing with MCP Inspector

npm run inspect

This opens a web interface at http://localhost:3000 for testing the tools interactively.

Testing with Node.js Directly

# Terminal 1: start the server
node dist/index.js

# Terminal 2: connect via stdio
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0.0"}}}' | node dist/index.js

Development

Code Structure

src/
├── index.ts              # Entry point, stdio transport
├── server.ts             # Definition of the 4 tools with descriptions
├── tools/
│   ├── cv.ts             # get_cv handler
│   ├── projects.ts       # list_projects handler
│   ├── match.ts          # match_job handler
│   └── ask.ts            # ask_about_me handler
├── lib/
│   ├── parser.ts         # Parses Markdown into sections
│   ├── matcher.ts        # Job ↔ profile matching logic
│   ├── projects.ts       # Loads projects.json
│   ├── response.ts       # Response utilities (ToolResponse)
│   └── paths.ts          # Resolves data/ paths
└── data/
    ├── cv-en.md          # CV in English
    ├── cv-ptbr.md        # CV in Portuguese
    └── projects.json     # Project data with metadata

Development Workflow

# 1. Develop with watch
npm run dev

# 2. Lint as you go
npm run lint
npm run lint:fix

# 3. Final build
npm run build

# 4. Test with the Inspector
npm run inspect

Adding a New Tool

  1. Create src/tools/new-tool.ts with an async handler
  2. Register it in server.ts with server.registerTool()
  3. Export it from index.ts (this happens automatically)
  4. Rebuild and test via npm run inspect

Example:

// src/tools/new-tool.ts
import { loadCv } from "../lib/parser.js";
import { ToolResponse, textResult } from "../lib/response.js";

export async function newToolHandler(args: {
  query: string;
}): Promise<ToolResponse> {
  const cv = loadCv("en");
  // your logic here
  return textResult("resultado");
}

Updating the Data

CVs: Copy them from ~/Development/cv/ to src/data/cv-*.md

cp ~/Development/cv/cv-en.md src/data/
cp ~/Development/cv/cv-ptbr.md src/data/
npm run build

Projects: Edit src/data/projects.json directly

vim src/data/projects.json
npm run build

Configuration

Environment Variables

None needed at the moment. All data is static, in src/data/.

Data Directory

The server looks for data in src/data/ at build time (resolved via lib/paths.ts). At runtime, the files live in dist/data/.

TypeScript/Zod

tsconfig.json:

  • Target: ES2022
  • Module: Node16 (ESM)
  • Strict mode enabled
  • JSON resolution enabled

biome.json:

  • Formatter: tabs (indentation)
  • Linter: recommended rules
  • Organize imports: enabled

Performance and Optimizations

In-Memory Cache

CVs and projects are loaded once at startup and kept in a cache:

const cvCache = new Map<string, CvData>();
export function loadCv(lang: "en" | "pt-br"): CvData {
  const cached = cvCache.get(lang);
  if (cached) return cached;
  // load from disk, then cache
}

Efficient Matching

  • Pre-compiled regexes for tech keywords (TECH_PATTERNS)
  • Skill normalization with simple rules (lowercase, strip . - /)
  • Stop-word filtering in ask_about_me

Minimal Size

  • No extra dependencies (just the MCP SDK + Zod)
  • Manual parsing, no libraries
  • Bundle: ~200KB minified

Troubleshooting

"Data file not found"

Make sure you ran npm run build. The build copies src/data/ to dist/data/.

npm run build
ls dist/data/

A Tool Returns an Undefined Error

Check that the absolute path in claude_desktop_config.json is correct:

ls /home/felipebueno/Development/mcp-me/dist/index.js
# It must exist

MCP Inspector Won't Open

Port 3000 may be in use. Change the port or kill the process:

lsof -i :3000
kill -9 <PID>
npm run inspect

Linting Failing

npm run lint:fix

Biome fixes formatting and import problems automatically.

Contributing

This is a personal project, but if you want to suggest improvements:

  1. Fork it
  2. Create a branch for your feature (git checkout -b feature/my-feature)
  3. Commit your changes (git commit -m "Add X")
  4. Push to the branch (git push origin feature/my-feature)
  5. Open a Pull Request

Contact

Felipe Bueno GitHub: @fe-m-bueno Email: felipebueno.dev@gmail.com