career-mcp-server

career-mcp-server

A production-grade FastAPI-based MCP server for career-oriented tools, currently exposing GitHub integration (profile, repos, pinned, search, rate limits) to LLM clients via the Model Context Protocol.

Category
Visit Server

README

career-mcp-server

CI Python FastAPI License

A production-grade AI Career MCP Server — a FastAPI application that exposes career-oriented tools to LLM clients via the Model Context Protocol (MCP).

This repository currently contains Phase 1 (foundation), Phase 2 (GitHub integration), and Phase 3 (AI career intelligence & resume engine). LinkedIn integration is not implemented yet — that's the next phase, built on top of this foundation.


Overview

career-mcp-server is designed as a long-lived, extensible service:

  • A FastAPI HTTP layer for health checks, versioning, and REST endpoints.
  • An MCP server, built on the official MCP Python SDK, that exposes tools an LLM client can call directly.
  • A clean separation between API, core (cross-cutting concerns), MCP, integrations, ai, resume, career, services, models, and schemas, so future features plug in without restructuring the app.
  • A GitHub integration (Phase 2): an async REST client, typed Pydantic models, a caching service layer, and the same functionality exposed identically through both REST endpoints and MCP tools.
  • A resume & AI career intelligence engine (Phase 3): PDF upload and parsing, AI-powered analysis and scoring, resume-to-job matching, and AI-generated rewrites, cover letters, and interview prep — all behind a provider-agnostic AI abstraction, again exposed identically through REST and MCP.

Phase 1 registered a single demonstration MCP tool — ping, which returns "pong" — solely to prove the MCP integration initializes and works end-to-end. Phase 2 added 22 GitHub tools, and Phase 3 adds 17 more (13 resume + 4 career) on top of that same registry — 40 MCP tools in total.

Architecture

Client (HTTP)                         Client (MCP)
     │                                      │
     ▼                                      ▼
 FastAPI app  ───────────────────►   MCPServer instance
     │  middleware, exception             │
     │  handlers, routers                 │  tools from ToolRegistry
     ▼                                     ▼
 app/api/routers/*              app/mcp/{server,registry,tools/*}.py
     │                                     │
     └───────────────┬─────────────────────┘
                      ▼
     ┌────────────────┼─────────────────────┬───────────────────────┐
     ▼                                       ▼                       ▼
 GitHubService                        ResumeService              CareerService
 (caching, validation)      (storage, parsing, analysis,      (advice, summaries,
     │                        matching, AI rewriting)           bio rewriting)
     ▼                               │        │                     │
 GitHubClient                        │        └──────────┬──────────┘
 (httpx, retries,                    ▼                   ▼
  rate limits)              ResumeStorage           AIProvider (abstract)
     │                      (local FS, swappable            │
     ▼                       for S3 later)          ┌────────┴────────┐
 GitHub REST API                                     ▼                 ▼
                                              OpenAIProvider      (future: Anthropic,
                                                                   Gemini, local model)
     │
     ▼
 app/core/*  (DI, exceptions, middleware, startup/shutdown, cache)
     │
     ▼
 app/config/*  (settings, logging)  ◄── app/services, app/models, app/schemas, app/utils

Both the REST routes and the MCP tools are thin pass-throughs to the same service classes — there is exactly one implementation of business logic, validation, caching, and error handling per domain, regardless of which transport a client uses.

Design principles:

  • Dependency injection — routes and services depend on get_settings() / get_logger() / get_github_service() / get_resume_service() / get_career_service() / get_ai_provider() rather than importing configuration or integrations directly.
  • SOLID / clean architecture — each layer has one responsibility; base classes (AppBaseModel, BaseService) exist so domain code stays consistent across integrations.
  • Provider-agnostic AI — ResumeService and CareerService depend on the abstract AIProvider interface (app/ai/provider.py), never on the OpenAI SDK directly. Swapping LLM_PROVIDER swaps the implementation everywhere at once; adding Anthropic, Gemini, or a local model means writing one new provider class, not touching business logic.
  • Structured errors — every handled failure, from either transport, returns the same JSON error envelope ({"success": false, "error": {...}}) or the equivalent MCP is_error result.
  • Typed data only — no integration ever returns raw JSON or unstructured AI text; every method returns a validated Pydantic model or a list of them.
  • Async-first — all I/O-bound code paths are async def, including the GitHub and AI clients.
  • Graceful degradation — the app starts and resume storage (list/get/delete) works fully even with no OPENAI_API_KEY configured; only AI-dependent calls fail, cleanly, when actually invoked. See Graceful Degradation.

Folder Structure

career-mcp-server/
├── app/
│   ├── main.py                 # FastAPI app factory + entry point
│   ├── config/
│   │   ├── settings.py         # Pydantic Settings (env-driven configuration)
│   │   └── logging.py          # Loguru sinks: console + rotating file logs
│   ├── api/
│   │   └── routers/
│   │       ├── health.py       # GET /health
│   │       ├── github.py       # 22 REST endpoints for the GitHub integration
│   │       ├── resume.py       # 13 REST endpoints for resume management & AI features
│   │       ├── career.py       # 4 REST endpoints for general career intelligence
│   │       └── base.py         # Aggregates all routers
│   ├── core/
│   │   ├── exceptions.py       # Exception hierarchy + handlers
│   │   ├── dependencies.py     # DI entry points (get_settings, get_logger)
│   │   ├── cache.py            # Generic in-memory TTL cache
│   │   ├── middleware.py       # Request ID, timing, logging, CORS, etc.
│   │   ├── startup.py          # Graceful startup hook
│   │   └── shutdown.py         # Graceful shutdown hook
│   ├── mcp/
│   │   ├── server.py           # Builds the MCPServer instance, registers all tool modules
│   │   ├── registry.py         # Tool registry + demo `ping` tool
│   │   └── tools/
│   │       ├── github_tools.py # 22 GitHub MCP tools (thin wrappers over GitHubService)
│   │       ├── resume_tools.py # 13 resume MCP tools (thin wrappers over ResumeService)
│   │       └── career_tools.py # 4 career MCP tools (thin wrappers over CareerService)
│   ├── integrations/
│   │   └── github/
│   │       ├── client.py       # Async httpx client: auth, retries, pagination, rate limits
│   │       ├── models.py       # Typed GitHub resource models (User, Repository, Commit, ...)
│   │       ├── errors.py       # Maps GitHub HTTP errors to application exceptions
│   │       ├── validation.py   # owner/repo/pagination/search input validation
│   │       ├── service.py      # GitHubService: business logic + caching
│   │       └── dependencies.py # get_github_client() / get_github_service() DI factories
│   ├── ai/
│   │   ├── provider.py         # AIProvider abstract interface (complete/complete_json)
│   │   ├── base_provider.py    # Shared scaffolding for concrete providers
│   │   ├── openai_provider.py  # OpenAIProvider implementation
│   │   ├── factory.py          # get_ai_provider() DI factory, keyed by LLM_PROVIDER
│   │   └── prompts.py          # Every prompt template used anywhere, centralized
│   ├── resume/
│   │   ├── models.py           # Parsed-resume domain models (ContactInfo, Experience, ...)
│   │   ├── schemas.py          # REST/MCP request & response schemas
│   │   ├── validators.py       # Upload/filename/resume-id validation
│   │   ├── storage.py          # ResumeStorage abstraction + LocalResumeStorage
│   │   ├── parser.py           # PDF text extraction + AI-powered structured parsing
│   │   ├── job_parser.py       # AI-powered job description parsing
│   │   ├── service.py          # ResumeService: storage, analysis, matching, AI rewriting
│   │   └── dependencies.py     # get_resume_service() DI factory
│   ├── career/
│   │   ├── schemas.py          # REST/MCP request & response schemas
│   │   ├── service.py          # CareerService: advice, summaries, bio rewriting
│   │   └── dependencies.py     # get_career_service() DI factory
│   ├── services/
│   │   └── base_service.py     # Base class for future services
│   ├── models/
│   │   └── base_model.py       # Base class for future domain models
│   ├── schemas/
│   │   └── common.py           # Shared response schemas
│   └── utils/
│       └── helpers.py          # Small generic helpers
├── tests/                      # pytest suite
├── Dockerfile
├── docker-compose.yml          # Includes a named volume for uploads/ persistence
├── requirements.txt
├── pyproject.toml              # ruff, mypy, pytest configuration
├── .env.example
└── .github/workflows/ci.yml

Installation

Requires Python 3.12+.

git clone <repository-url> career-mcp-server
cd career-mcp-server
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env

Environment Variables

All configuration is read from environment variables (or a local .env file). See .env.example for defaults.

Variable Default Description
APP_NAME career-mcp-server Application name
APP_VERSION 0.1.0 Application version
HOST 0.0.0.0 Bind host for the HTTP server
PORT 8000 Bind port for the HTTP server
LOG_LEVEL INFO Minimum log level (DEBUG, INFO, ...)
DEBUG false Enables verbose diagnostics
ENVIRONMENT development development / staging / production / test
CORS_ORIGINS * Comma-separated list of allowed CORS origins
GITHUB_TOKEN (none) GitHub Personal Access Token (see Authentication)
GITHUB_API https://api.github.com Base URL for the GitHub REST API
REQUEST_TIMEOUT 30 Outbound HTTP request timeout, in seconds
CACHE_TTL 300 TTL, in seconds, for cached GitHub data (0 effectively disables caching)
OPENAI_API_KEY (none) OpenAI API key (required for AI-powered resume/career features)
LLM_PROVIDER openai Which AIProvider implementation backs AI features
LLM_MODEL gpt-5 Model name requested from the configured provider
MAX_TOKENS 4000 Maximum tokens generated per AI completion
TEMPERATURE 0.3 Sampling temperature for AI completions
UPLOAD_DIRECTORY uploads Local directory where uploaded resumes are stored
MAX_UPLOAD_SIZE_MB 10 Maximum allowed resume upload size, in megabytes

Running Locally

uvicorn app.main:app --reload

Docker

docker compose up --build

This builds a non-root, slim production image and starts the API on the port configured by PORT (default 8000).

Running the MCP Server

The MCP server is built in app/mcp/server.py and initialized automatically when app.main is imported (e.g. on application startup, it's attached to app.state.mcp_server). It registers 40 tools in total:

  • ping — the Phase 1 demonstration tool, proving MCP wiring works end-to-end.
  • 22 GitHub tools from app/mcp/tools/github_tools.py.
  • 13 resume tools + 4 career tools from app/mcp/tools/resume_tools.py and career_tools.py (see Available MCP Tools below).

Each integration owns a register(registry) function in its own app/mcp/tools/* module; app/mcp/server.py just calls each of them once before building the server, so adding a future integration's tools never requires touching existing tool modules.

MCP tool arguments must be JSON-safe, so file uploads (upload_resume, replace_resume) take the PDF's bytes as a base64-encoded string instead of a multipart upload.

GitHub Integration

Authentication

Generate a GitHub Personal Access Token (a fine-grained token with read access to the repositories you want to query is sufficient) and set it in .env:

GITHUB_TOKEN=ghp_your_token_here

The token is sent as a Bearer header on every request and is never logged. Without a token, public endpoints (public repos, search, unauthenticated rate limit) still work — GitHub just applies its much lower unauthenticated rate limit (60 requests/hour) and endpoints that require a user context, like /github/profile, return a structured 401 AuthenticationException.

Available REST Endpoints

All endpoints are under /github and return typed JSON (never raw GitHub payloads):

Method Path Description
GET /github/profile The authenticated user
GET /github/pinned The authenticated user's pinned repositories (GraphQL)
GET /github/repos List the authenticated user's repositories
GET /github/search?q= Search public repositories
GET /github/rate-limit Current GitHub API rate limit status
GET /github/repos/{owner}/{repo} Repository details
GET /github/repos/{owner}/{repo}/stats Aggregated statistics
GET /github/repos/{owner}/{repo}/languages Language breakdown
GET /github/repos/{owner}/{repo}/contributors Top contributors
GET /github/repos/{owner}/{repo}/commits Latest commits
GET /github/repos/{owner}/{repo}/release Latest release
GET /github/repos/{owner}/{repo}/releases All releases
GET /github/repos/{owner}/{repo}/readme Decoded README
GET /github/repos/{owner}/{repo}/topics Repository topics
GET /github/repos/{owner}/{repo}/license Repository license
GET /github/repos/{owner}/{repo}/branches Branches
GET /github/repos/{owner}/{repo}/issues Issues (excludes pull requests)
GET /github/repos/{owner}/{repo}/pulls Pull requests
GET /github/repos/{owner}/{repo}/workflows GitHub Actions workflows
GET /github/repos/{owner}/{repo}/stars Star count
GET /github/repos/{owner}/{repo}/forks Fork count
GET /github/repos/{owner}/{repo}/watchers Watcher count
DELETE /github/cache Manually invalidate the GitHub integration cache

Example:

curl http://localhost:8000/github/repos/octocat/Hello-World/stats

Available MCP Tools

The same functionality, one tool per REST endpoint above: github_profile, pinned_repositories, list_repositories, search_repositories, rate_limit, repository_details, repository_statistics, repository_languages, repository_contributors, latest_commits, latest_release, repository_releases, repository_readme, repository_topics, repository_license, repository_branches, repository_issues, repository_pull_requests, repository_workflows, repository_stars, repository_forks, repository_watchers.

Each tool's input/output schema is generated by the MCP SDK directly from its Python type hints and docstring — there is no separate schema to keep in sync.

Caching

GitHubService caches five read-heavy, slow-changing calls in an in-memory TTL cache (CACHE_TTL seconds, default 300): the authenticated profile, the repository list, repository statistics, language breakdowns, and releases. Everything else (commits, issues, PRs, branches, search, rate limit, etc.) always hits GitHub directly. Call DELETE /github/cache to clear it manually.

Rate Limits

GitHub enforces 5,000 requests/hour for authenticated requests and 60/hour unauthenticated (10/min for search). GET /github/rate-limit reports current usage. The client logs remaining quota on every response and raises a structured RateLimitException (HTTP 429) the moment GitHub signals either the primary or secondary rate limit has been hit — transient 5xx errors and network failures are retried up to 3 times with exponential backoff before that.

Resume & AI Career Intelligence

Phase 3 adds resume upload/management, AI-powered resume analysis and scoring, resume-to-job matching, and AI-generated rewrites, cover letters, and interview prep. All of it sits behind the same provider-agnostic AIProvider abstraction — no business logic imports the OpenAI SDK directly.

AI Provider Architecture

ResumeService / CareerService
        │  depends only on the abstract interface
        ▼
   AIProvider (app/ai/provider.py)
   ├── complete(prompt, system=..., temperature=..., max_tokens=...) -> str      [abstract]
   └── complete_json(...) -> dict                    [concrete, built on complete()]
        │
        ▼
   BaseAIProvider (app/ai/base_provider.py)   — settings storage, default resolution
        │
        ▼
   OpenAIProvider (app/ai/openai_provider.py)  — the only OpenAI-specific code in the app

app/ai/factory.py exposes get_ai_provider(), a cached DI factory keyed by LLM_PROVIDER. Adding a new provider (Anthropic, Gemini, a local model) means writing one new class implementing complete() and registering it in the factory's provider map — nothing in ResumeService, CareerService, the REST routes, or the MCP tools changes.

Supported Providers

Provider LLM_PROVIDER value Status
OpenAI openai Implemented
Anthropic, Gemini, local models — Not yet implemented; add via the factory above

Prompt Library

Every prompt used anywhere in the app lives in app/ai/prompts.py as a small function returning plain text — nothing is hardcoded inline in a service. The module has no dependency on resume or job-description models; callers pass already-serialized text (model.model_dump_json()), which keeps app/ai reusable for any future feature, not just resumes.

Graceful Degradation

The AI provider is injected into ResumeService/CareerService as a factory callable, not a pre-built instance. That means:

  • The app starts successfully with no OPENAI_API_KEY set.
  • GET /resume, GET /resume/{id}, DELETE /resume/{id} work with no AI configured at all.
  • POST /resume/upload still works with no AI configured — parsing degrades to deterministic, regex-based contact extraction (name/email/phone) with every AI-only field (skills, education, experience, ...) left as an empty default, rather than failing the upload.
  • Everything genuinely AI-dependent (analyze, score, match, rewrite, cover letters, interview questions, career advice, ...) fails with a clean 502 ExternalServiceException — "OPENAI_API_KEY is not configured; AI-powered features are unavailable" — the moment it's actually called, not at startup.

Available REST Endpoints

Resume (/resume) — returns typed JSON, never raw AI text:

Method Path Description
POST /resume/upload Upload a PDF resume (multipart), parse, and store it
GET /resume List stored resumes' metadata
GET /resume/{resume_id} Get a stored resume's metadata + parsed content
PUT /resume/{resume_id} Replace a stored resume's file, re-parsing it
DELETE /resume/{resume_id} Delete a stored resume
POST /resume/analyze Full multi-part AI analysis (score, gaps, summaries, strengths/weaknesses)
POST /resume/score Focused resume quality / ATS score
POST /resume/match Compare a resume against a job description
POST /resume/rewrite AI-rewrite the full resume, summary, or experience section
POST /resume/cover-letter Generate a tailored cover letter
POST /resume/interview Generate likely interview questions
POST /resume/project-descriptions Turn raw project notes into a polished description
POST /resume/achievements Turn raw notes into quantified achievement bullets

Career (/career) — general career intelligence, not necessarily tied to a stored resume:

Method Path Description
POST /career/advice AI-powered career advice for a free-form question
POST /career/professional-summary Standalone summary from a stored resume or raw text
POST /career/rewrite-bio AI-rewrite a short personal bio
POST /career/parse-job-description Extract structured fields from raw job posting text

Example Requests & Responses

Upload a resume:

curl -X POST http://localhost:8000/resume/upload \
  -F "file=@resume.pdf;type=application/pdf"
{
  "metadata": {
    "id": "437afbe1254745e89c24197157a92a0c",
    "original_filename": "resume.pdf",
    "content_type": "application/pdf",
    "size_bytes": 48213,
    "uploaded_at": "2026-01-15T10:30:00Z",
    "updated_at": "2026-01-15T10:30:00Z"
  },
  "parsed": {
    "contact": {"name": "Jane Doe", "email": "jane@example.com", "phone": "+1-555-0100", "location": "Remote"},
    "summary": "Backend engineer with 6 years building distributed systems...",
    "skills": ["Python", "FastAPI", "PostgreSQL"],
    "education": ["..."], "experience": ["..."], "projects": ["..."],
    "certifications": [], "languages": [], "publications": [],
    "raw_text": "..."
  }
}

Match a resume against a job description:

curl -X POST http://localhost:8000/resume/match \
  -H "Content-Type: application/json" \
  -d '{"resume_id": "437afbe1254745e89c24197157a92a0c", "job_description": "We need a backend engineer with FastAPI and PostgreSQL experience..."}'
{
  "overall_score": 88,
  "skill_match_score": 90,
  "experience_match_score": 85,
  "keyword_coverage_score": 80,
  "missing_skills": ["Kubernetes"],
  "recommendations": ["Add a metric quantifying the API's scale"],
  "ats_compatibility_score": 92
}

Available MCP Tools

Resume (13): upload_resume, list_resumes, get_resume, replace_resume, delete_resume, analyze_resume, resume_score, match_resume, rewrite_resume, generate_cover_letter, interview_questions, project_descriptions, achievement_generator.

Career (4): career_advice, professional_summary, rewrite_bio, parse_job_description.

Each tool's input/output schema is generated by the MCP SDK directly from its Python type hints and docstring. upload_resume and replace_resume take content_base64 (a base64-encoded PDF) instead of a file upload, since MCP tool arguments must be JSON-safe.

Security

  • File type validation — only application/pdf is accepted; anything else is rejected with a structured 415 UnsupportedMediaTypeException before any file processing happens.
  • PDF signature check — uploaded bytes must start with the %PDF- magic bytes, rejecting mislabeled files even if the declared content type says PDF.
  • Size limits — uploads over MAX_UPLOAD_SIZE_MB are rejected with 413 PayloadTooLargeException.
  • Path traversal prevention — storage is always keyed by a server-generated UUID ({resume_id}.pdf), never by the user-supplied filename, so path traversal via a crafted filename is structurally impossible regardless of storage backend. The original filename is still sanitized (directory components stripped, unsafe characters rejected) before being stored as display metadata.
  • No public file exposure — there is no static file route; the only way to retrieve a resume's content is through the authenticated-by-deployment GET /resume/{resume_id} API, which returns parsed data, not the raw file.

Testing

pytest --cov=app --cov-report=term-missing

Tests cover:

  • The /health and /version endpoints
  • Configuration loading, validation, and caching
  • The MCP server's initialization and the ping tool
  • Application startup/shutdown lifecycle
  • The GitHub HTTP client: auth headers, 401/403/404/429/5xx mapping, retry-with-backoff, pagination — all against httpx.MockTransport, no live network calls
  • GitHubService: every method, JSON-to-model mapping, caching behavior, input validation
  • Every /github/* REST endpoint, including error-envelope translation, via dependency overrides
  • Every GitHub MCP tool: registration, delegation, and typed-exception propagation
  • The AI provider abstraction: complete_json JSON/code-fence parsing, OpenAIProvider (with the OpenAI SDK client mocked), and the get_ai_provider() factory's provider selection/error paths
  • Resume upload validation, local storage (save/get/list/delete/replace), PDF text extraction against a real (hand-built, dependency-free) PDF, and AI-powered field extraction with graceful degradation when the AI provider is unavailable or fails
  • ResumeService and CareerService: every method, against in-memory storage and AI provider fakes — no filesystem I/O beyond a tmp_path, no real AI calls
  • Every /resume/* and /career/* REST endpoint and every resume/career MCP tool: registration, delegation, file upload handling, and error-envelope translation

No test makes a real GitHub API call or a real AI API call — every external client is fully swappable via dependency injection.

CI/CD

GitHub Actions (.github/workflows/ci.yml) runs on every push and pull request to main:

  1. Install dependencies
  2. ruff check . — lint
  3. mypy app — type-check
  4. pytest --cov=app — test
  5. docker build — verify the production image builds

The pipeline fails on any lint, type, or test error.

Roadmap

  • Phase 1 — Project foundation: FastAPI app, MCP server bootstrap, configuration, logging, middleware, structured error handling, Docker, CI.
  • Phase 2 — GitHub integration: async client, typed models, caching service layer, 22 REST endpoints, and 22 matching MCP tools.
  • Phase 3 (this repository) — AI career intelligence & resume engine: provider-agnostic AI abstraction, PDF resume upload/parsing/storage, AI-powered analysis/scoring/matching/rewriting, 17 REST endpoints, and 17 matching MCP tools.
  • Phase 4 — LinkedIn integration.
  • Phase 5 — Further AI-powered career insights and recommendations.

Contributing

  1. Create a feature branch.
  2. Make your changes with type hints, docstrings, and tests.
  3. Run ruff check ., mypy app, and pytest locally.
  4. Open a pull request; CI must pass before merge.

License

Distributed under the MIT License.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured