Commit 25bf8018 authored by dangdoan's avatar dangdoan

first version

parent 262e5ea9
__pycache__/
*.pyc
*.pyo
.git/
.vscode/
*.md
\ No newline at end of file
GITLAB_URL=https://gitlab.com # hoặc self-hosted
GITLAB_TOKEN=glpat-xxxxxxxxxxxxxxxxxxxxxxxx # PAT của cậu
QDRANT_HOST=192.168.0.29
QDRANT_PORT=7333
\ No newline at end of file
# Copilot Instructions for MeU FastMCP Memory Server
## Project Overview
This is a **FastMCP-based MCP (Model Context Protocol) server** built with Python. It provides semantic memory tools for AI agents (Copilot, Claude Code, Cursor, etc.) by storing and retrieving code context using **Qdrant vector database** and **sentence-transformers** embeddings.
The server enables AI agents across multiple MeU projects to:
- Save and search code context semantically
- Load project-specific agent configuration (`AGENT.md`)
- Index GitLab repositories into vector storage for semantic code search
## Architecture
### System Overview
```
AI Agent (Copilot / Claude / Cursor)
↓ MCP Protocol (stdio)
FastMCP Server (memory_mcp_server.py)
┌─────────────────────────────────────┐
│ Qdrant Vector DB (semantic store) │
│ Collection: multi_project_memory │
└─────────────────────────────────────┘
SentenceTransformer (all-MiniLM-L6-v2)
→ Embedding model (384-dim vectors, cosine similarity)
GitLab API (python-gitlab)
→ Repository indexing
```
### Core Components
| File | Purpose |
|------|---------|
| `memory_mcp_server.py` | **Main server** — FastMCP app with 4 MCP tools |
| `memory_mcp_server_old.py` | Legacy single-project version (reference only) |
| `.env` | Environment config (Qdrant host/port, GitLab credentials) |
| `AGENT.md` | AI agent context file — loaded by `load_agent_context()` tool |
| `AGENT-TEMPLATE.md` | Template for creating AGENT.md for new projects |
| `PROMT.md` | Reusable prompt templates for AI agents |
### MCP Tools Exposed
#### 1. `load_agent_context()`
- Reads `AGENT.md` from workspace root and returns its content
- Also caches the content into Qdrant with key `agent_context` under project `global`
- Called at session start by AI agents to load project context
#### 2. `save_context(project_id, key, content)`
- Saves a context snippet into Qdrant with semantic embedding
- Uses UUID5 based on `{project_id}_{key}` for deterministic point IDs (upsert-safe)
- Payload includes: `project_id`, `key`, `content`
#### 3. `search_context(project_id, query, limit=5)`
- Performs semantic search in Qdrant filtered by `project_id`
- Returns top-k results with `key`, `content`, and `score`
- Uses `query_points()` with `FieldCondition` filter on `project_id`
#### 4. `index_gitlab_repo(project_id, gitlab_project_id)`
- Fetches all files from a GitLab repo's `main` branch
- Indexes each file's content (truncated to 2000 chars) into Qdrant
- Associates indexed content with the given `project_id`
## Technology Stack
| Technology | Version | Purpose |
|------------|---------|---------|
| Python | 3.12+ | Runtime |
| FastMCP | latest | MCP server framework |
| Qdrant | — | Vector database for semantic storage |
| sentence-transformers | — | Text embedding (`all-MiniLM-L6-v2`, 384-dim) |
| python-gitlab | — | GitLab API client |
| python-dotenv | — | Environment variable loading |
## Development
### Environment Variables (`.env`)
```env
GITLAB_URL=https://gitlab.com # GitLab instance URL
GITLAB_TOKEN=glpat-xxx # GitLab Personal Access Token
QDRANT_HOST=192.168.0.29 # Qdrant server host
QDRANT_PORT=7333 # Qdrant server port
```
### Running the Server
```bash
# Direct execution (stdio transport for MCP)
python memory_mcp_server.py
```
The server communicates via **stdio** (standard MCP transport). AI agents connect to it through their MCP client configuration.
### Qdrant Collection
- **Collection name**: `multi_project_memory`
- **Vector size**: 384 (matches `all-MiniLM-L6-v2` output)
- **Distance metric**: Cosine similarity
- **Auto-created** on first startup if not exists
## Code Conventions
### When Modifying This Server
- All MCP tools use the `@mcp.tool()` decorator
- Tool functions must have **docstrings** (used as tool descriptions in MCP protocol)
- Always include `project_id` parameter for multi-project isolation
- Use `embedder.encode(text).tolist()` to generate vectors
- Use deterministic UUIDs (`uuid5`) for upsert operations to avoid duplicates
- Content stored in Qdrant payload should be kept under 2000 chars
- Error handling: use try-except with `print()` for non-critical errors (e.g., file indexing)
### Multi-Project Design
The server uses a **single shared collection** (`multi_project_memory`) with per-project filtering:
- Each point's payload contains `project_id` field
- Search queries use `FieldCondition(key="project_id", match=MatchValue(value=project_id))`
- This allows multiple AI-assisted projects to share one Qdrant instance
### Key Differences from Old Version (`memory_mcp_server_old.py`)
| Aspect | Old (single-project) | Current (multi-project) |
|--------|----------------------|-------------------------|
| Collection | `codebase_memory` | `multi_project_memory` |
| Server name | `asisstant-memory` | `multi-project-memory` |
| `save_context` | `key` only | `project_id` + `key` |
| `search_context` | No filter | Filtered by `project_id` |
| `index_gitlab_repo` | `project_id` (int) | `project_id` (str) + `gitlab_project_id` (int) |
| `load_agent_context` | Not available | Reads & caches `AGENT.md` |
| Point IDs | String key | UUID5 from `{project_id}_{key}` |
## Common Tasks
### Adding a New MCP Tool
1. Define function with `@mcp.tool()` decorator in `memory_mcp_server.py`
2. Add descriptive docstring (becomes tool description for AI agents)
3. Include `project_id` parameter if the tool is project-specific
4. Use `embedder.encode()` if semantic operations are needed
### Connecting a New Project
1. Create an `AGENT.md` file in the project's root with project context
2. Use `save_context(project_id="<new-project-id>", ...)` to store context
3. Use `search_context(project_id="<new-project-id>", ...)` to retrieve context
4. Optionally run `index_gitlab_repo(project_id="<id>", gitlab_project_id=<num>)` to bulk-index
### Testing Tools Manually
Since this is an MCP server, tools are invoked by AI agents via MCP protocol. For manual testing:
- Use the FastMCP CLI or MCP inspector tools
- Or import and call functions directly in a Python script
\ No newline at end of file
// {
// "servers": {
// "asisstant-memory": {
// "command": "python",
// "args": ["c:\\Work\\MeU Solutions\\Project\\meu-fastmcp\\memory_mcp_server.py"],
// "type": "stdio"
// }
// }
// }
//Dùng http server thay stdio để dễ debug hơn
{
"servers": {
"assistant-memory": {
"type": "http",
"url": "http://mcp-dev.meucorp.com"
}
}
}
\ No newline at end of file
# AGENT-CONTEXT.md
**File này dành riêng cho AI agents (Copilot Agent, Claude Code, Cursor, v.v.)**
**Không dùng để đọc cho người, chỉ dùng cho AI để giữ context project.**
## 1. Project Identification
- Project Name: MeU Solutions - RCA (Root Cause Analysis)
- Project ID (dùng trong MCP tools): meu-rca-nextjs
- GitLab Project ID: 13
- Main Branch: main
- Language: TypeScript + Next.js 13+ (App Router)
- Environment: Docker + MongoDB + Prisma ORM
## 2. Codebase Structure (folders quan trọng)
src/
├── app/ # Next.js App Router (routes & pages)
│ ├── page.tsx # Home page
│ ├── layout.tsx # Root layout
│ ├── globals.css # Global styles
│ ├── login/ # Login page
│ ├── incidents/ # Incident listing
│ ├── insights/ # Analytics dashboard
│ ├── projects/ # Projects listing & create
│ ├── project/[projectId]/ # Project detail & RCA create
│ ├── rca/ # RCA listing, detail, create
│ └── api/
│ └── auth/login/ # Login API endpoint (route.ts)
├── lib/ # Core utilities
│ ├── auth.ts # Client auth utilities
│ ├── server-auth.ts # Server auth logic
│ ├── db.ts # Database connection
│ ├── similarity.ts # Text similarity algorithms
│ ├── vector.ts # Vector operations for semantic search
│ └── models/ # Data models
│ ├── User.ts
│ ├── Project.ts
│ ├── ProjectMember.ts
│ ├── RCA.ts
│ └── Incident.ts
├── modules/ # Feature modules (DDD approach)
│ ├── incident/
│ │ ├── actions.ts # Server actions
│ │ ├── service.ts # Business logic
│ │ └── repository-mongo.ts # MongoDB data access
│ ├── project/
│ │ ├── actions.ts
│ │ └── repository-mongo.ts
│ └── rca/
│ ├── actions.ts
│ ├── service.ts
│ ├── repository-mongo.ts
│ ├── detector.ts # Pattern detection
│ ├── schema.ts # Validation schemas
│ └── components/ # React components
│ ├── CreateRcaForm.tsx
│ ├── RcaCard.tsx
│ ├── RcaEditor.tsx
│ └── RcaList.tsx
├── types/ # TypeScript type definitions
│ └── stopword.d.ts
└── middleware.ts # Next.js middleware (auth & routing)
prisma/
└── schema.prisma # Database schema definition
scripts/
├── setup-mongodb.js # MongoDB initialization
└── MONGODB_SETUP.md # Setup documentation
Bỏ qua khi index/search:
- node_modules/
- .next/
- .vercel/
- *.log, *.tmp
- public/ (static assets)
- dist/, build/
## 3. Key Conventions & Rules for Agent
- Follow TypeScript strict mode + ESLint rules
- Use App Router conventions (Server Components by default)
- Server Actions: Export "use server" functions in actions.ts files
- Auth: Custom JWT implementation (lib/auth.ts + lib/server-auth.ts)
- Error handling: try-catch with proper error messages
- Database: Prisma ORM + MongoDB
- Styling: Tailwind CSS utility classes
- Testing: (chưa có - cần setup Jest/Vitest)
## 4. Important Business Context
- User roles: admin, project_manager, team_member
- Projects: Users create projects and assign team members
- RCA Flow: Create RCA → Add analysis → Detect patterns → Link incidents
- Pattern Detection: Uses similarity.ts for matching similar RCAs
- Vector Search: vector.ts enables semantic search across RCAs
- Incidents: Track and link to RCAs for future reference
- Insights: Analytics dashboard showing patterns and trends
## 5. Architecture Patterns
### Repository Pattern (3-layer architecture)
```
Components (UI Layer)
Actions (Server Actions - API Layer)
Services (Business Logic Layer)
Repositories (Data Access Layer - repository-mongo.ts)
Database (MongoDB via Prisma)
```
### Data Model Relationships
```
User ←→ ProjectMember ←→ Project
RCA ←→ Incident
```
### Authentication Flow
- Client auth: lib/auth.ts (token storage, validation)
- Server auth: lib/server-auth.ts (session verification)
- Middleware: middleware.ts (route protection)
- Login API: app/api/auth/login/route.ts
## 6. MCP & Tool Usage Rules (Bắt buộc tuân thủ mọi lúc)
- **Project ID cố định**: Luôn sử dụng `project_id="meu-rca-nextjs"` khi gọi bất kỳ tool MCP nào (save_context, search_context, index_gitlab_repo, v.v.). Không được bỏ qua hoặc dùng giá trị khác.
- **Tự động khởi tạo context**:
1. Mỗi khi bắt đầu task mới hoặc session mới, **bắt buộc gọi** tool `load_agent_context()` (nếu có) hoặc tự đọc file `AGENT.md` từ root workspace để load toàn bộ context project.
2. Nếu chưa có tool `load_agent_context()`, ưu tiên đọc file `AGENT.md` trước khi thực hiện bất kỳ code generation, refactor, hoặc analysis nào.
- **Quy tắc gọi tool MCP**:
- Trước khi viết code, generate component, hoặc refactor: **Bắt buộc gọi** `search_context` với `project_id="meu-rca-nextjs"` để lấy context liên quan (ví dụ: query về "auth flow", "RCA pattern detection", "repository pattern").
- Khi cần lưu kiến thức mới (architecture decision, pattern mới, fix bug recurring): **Bắt buộc gọi** `save_context` với `project_id="meu-rca-nextjs"`, key rõ ràng và mô tả (ví dụ key="rca-pattern-v1", "auth-middleware-v2").
- Khi codebase thay đổi lớn (merge MR, thêm feature): **Gọi** `index_gitlab_repo` với `project_id="meu-rca-nextjs"` và GitLab project ID đúng để cập nhật Qdrant (chỉ gọi khi cần, tránh index thừa tốn tài nguyên).
- **Filter & Prioritize khi search**:
- Luôn thêm `project_id="meu-rca-nextjs"` vào filter để chỉ lấy context của project này.
- Ưu tiên kết quả có score > 0.6 (nếu có thể kiểm tra).
- Nếu không tìm thấy context liên quan → thông báo rõ ràng và đề xuất tạo mới bằng `save_context`.
- **Không được làm**:
- Không giả định context mà không gọi search/load.
- Không gọi tool MCP mà không truyền project_id đúng.
- Không index toàn bộ repo thường xuyên (chỉ khi codebase thay đổi đáng kể hoặc theo yêu cầu).
- **Tối ưu token & performance**:
- Chỉ lấy limit=3–5 khi search_context trừ khi cần nhiều hơn.
- Nếu content quá dài (>2000 chars), tóm tắt trước khi lưu vào Qdrant.
- Nếu agent cảm thấy context chưa đủ → yêu cầu người dùng cung cấp thêm hoặc gọi index lại.
Tất cả các bước trên **phải được thực hiện tự động**, không được hỏi lại người dùng "có cần gọi tool không" hoặc "nhắc project_id".
## 7. Filter Structure for Agent
- Chỉ index files: *.ts, *.tsx, *.md, *.json, *.prisma
- Ưu tiên folders: src/app, src/lib, src/modules
- Tránh index: node_modules/, .next/, public/
- Max content length per file: 2000 chars (để tránh token overflow)
## 8. Configuration Files
- next.config.js - Next.js configuration
- tsconfig.json - TypeScript configuration
- tailwind.config.ts - Tailwind CSS configuration
- postcss.config.js - PostCSS configuration
- docker-compose.yml - Multi-container orchestration
- Dockerfile - Container build instructions
- prisma/schema.prisma - Database schema
## 9. Build & Deployment
- Build scripts: build.bat (Windows), build.sh (Unix/Linux)
- Docker support: Containerized deployment with docker-compose
- Database: MongoDB setup via scripts/setup-mongodb.js
- Environment: Requires .env file with DB connection and secrets
## 10. Documentation References
- README.md - Project overview
- FEATURES.md - Feature documentation
- AUTHENTICATION.md - Auth implementation details
- MONGODB_README.md - MongoDB setup and usage
- api-login.txt - API documentation (login)
- architect.txt - Architecture notes
- req.txt - Requirements specification
- CODE_STRUCTURE.md - Detailed code structure documentation
## 11. Last Updated
- Updated: 2026-02-21
- Next review: Sau khi implement authentication features
- Status: Active development - RCA detection & insights features in progress
## 12. External Knowledge Base (NotebookLM)
- NotebookLM link: [https://notebooklm.google.com/notebook/85ee5d70-5839-4de5-a5de-5a2d74d64b31] (cập nhật link thật)
- Khi cần context từ docs, design spec, hoặc requirement không có trong codebase/Qdrant:
- Truy vấn NotebookLM trước (copy-paste query vào NotebookLM chat).
- Hoặc yêu cầu người dùng cung cấp output từ NotebookLM.
- Ưu tiên: Nếu câu hỏi liên quan đến business logic, spec, hoặc non-code docs → dùng NotebookLM.
\ No newline at end of file
# AGENT-CONTEXT.md
**File này dành riêng cho AI agents (Copilot Agent, Claude Code, Cursor, v.v.)**
**Không dùng để đọc cho người, chỉ dùng cho AI để giữ context project.**
## 1. Project Identification
- Project Name: MeU Solutions - FastMCP Memory Server
- Project ID (dùng trong MCP tools): `meu-fastmcp`
- Main Branch: main
- Language: Python 3.12+
- Framework: FastMCP (MCP server framework)
- Infrastructure: Qdrant Vector DB + SentenceTransformer embeddings
## 2. Project Purpose
Server MCP cung cấp **semantic memory** cho AI agents. Cho phép các agent:
- Lưu trữ và tìm kiếm code context theo ngữ nghĩa (semantic search)
- Load context project từ file `AGENT.md`
- Index toàn bộ GitLab repo vào Qdrant để hỗ trợ code search
- Hỗ trợ **multi-project**: nhiều project chia sẻ chung 1 Qdrant instance
## 3. Codebase Structure
```
meu-fastmcp/
├── memory_mcp_server.py # Main server - FastMCP app, 4 MCP tools
├── memory_mcp_server_old.py # Legacy single-project version (tham khảo)
├── .env # Config: QDRANT_HOST, QDRANT_PORT, GITLAB_URL, GITLAB_TOKEN
├── AGENT.md # File context cho AI agents (file này)
├── AGENT-TEMPLATE.md # Template tạo AGENT.md cho project mới
├── PROMT.md # Prompt templates hay dùng
├── .github/
│ └── copilot-instructions.md # Hướng dẫn cho GitHub Copilot
└── __pycache__/ # Python bytecode cache (bỏ qua)
```
Bỏ qua khi index/search:
- `__pycache__/`
- `.zencoder/`, `.zenflow/`
- `*.pyc`, `*.log`, `*.tmp`
## 4. MCP Tools (4 tools)
### `load_agent_context()`
- Đọc `AGENT.md` từ workspace root
- Cache nội dung vào Qdrant (project=`global`, key=`agent_context`)
- Gọi đầu tiên khi bắt đầu session mới
### `save_context(project_id, key, content)`
- Lưu context vào Qdrant với semantic embedding
- ID point = UUID5 từ `{project_id}_{key}` (deterministic, upsert-safe)
- Payload: `project_id`, `key`, `content`
### `search_context(project_id, query, limit=5)`
- Tìm kiếm semantic trong Qdrant, filter theo `project_id`
- Trả về top-k kết quả: `key`, `content`, `score`
### `index_gitlab_repo(project_id, gitlab_project_id)`
- Lấy tất cả files từ branch `main` của GitLab repo
- Index từng file (giới hạn 2000 chars) vào Qdrant
- Gắn `project_id` cho mỗi point
## 5. Key Technologies
| Thành phần | Chi tiết |
|------|---------|
| FastMCP | Framework MCP server, giao tiếp qua stdio |
| Qdrant | Vector DB, collection `multi_project_memory`, cosine similarity |
| SentenceTransformer | Model `all-MiniLM-L6-v2`, vector 384 chiều |
| python-gitlab | Client gọi GitLab API để lấy source code |
| python-dotenv | Load biến môi trường từ `.env` |
## 6. Key Conventions & Rules for Agent
### Code style
- Mỗi MCP tool dùng decorator `@mcp.tool()`
- Bắt buộc có docstring cho mỗi tool (dùng làm mô tả tool trong MCP protocol)
- Luôn có `project_id` parameter cho các tool cần multi-project isolation
- Dùng `embedder.encode(text).tolist()` để tạo vector
- Dùng `uuid5` cho deterministic IDs (tránh duplicate khi upsert)
- Giới hạn content lưu Qdrant: dưới 2000 chars
### Multi-project design
- 1 collection chung: `multi_project_memory`
- Filter theo `project_id` khi search (dùng `FieldCondition`)
- Cho phép nhiều project MeU chia sẻ cùng Qdrant instance
### Error handling
- `try-except` với `print()` cho lỗi không critical (ví dụ: lỗi index 1 file)
- Không crash server khi 1 file index thất bại
## 7. Environment Configuration
```env
GITLAB_URL=https://gitlab.com # GitLab instance URL
GITLAB_TOKEN=glpat-xxx # Personal Access Token
QDRANT_HOST=192.168.0.29 # Qdrant server host
QDRANT_PORT=7333 # Qdrant server port
```
## 8. Running the Server
```bash
# Chạy trực tiếp (giao tiếp qua stdio, MCP transport)
python memory_mcp_server.py
```
## 9. Qdrant Collection Details
- **Collection**: `multi_project_memory`
- **Vector size**: 384 (khớp output của `all-MiniLM-L6-v2`)
- **Distance**: Cosine
- **Tự tạo** khi khởi động nếu chưa tồn tại
## 10. Sự khác biệt so với phiên bản cũ
| Khía cạnh | Cũ (`memory_mcp_server_old.py`) | Hiện tại (`memory_mcp_server.py`) |
|-----------|------|---------|
| Collection | `codebase_memory` | `multi_project_memory` |
| Server name | `asisstant-memory` | `multi-project-memory` |
| Multi-project | Không | Có (filter theo `project_id`) |
| `load_agent_context` | Không có | Có |
| Point IDs | String key | UUID5 deterministic |
## 11. Các project đang dùng server này
- `meu-rca-nextjs` — MeU RCA (Root Cause Analysis) system, GitLab Project ID: 13
- Có thể thêm project mới bằng cách dùng `project_id` khác khi gọi tools
## 12. MCP Tool Usage Rules (cho các agent kết nối)
- **Project ID**: Mỗi project dùng 1 `project_id` cố định khi gọi tools
- **Khởi tạo session**: Gọi `load_agent_context()` hoặc đọc `AGENT.md` trước mọi thao tác
- **Trước khi code**: Gọi `search_context(project_id, query)` để lấy context liên quan
- **Sau khi code**: Gọi `save_context(project_id, key, content)` để lưu pattern/fix mới
- **Khi codebase thay đổi lớn**: Gọi `index_gitlab_repo(project_id, gitlab_project_id)`
- **Tối ưu**: `limit=3-5` khi search, content dưới 2000 chars khi save
## 13. Last Updated
- Updated: 2026-02-26
- Status: Active — multi-project memory server đang hoạt động
# Context Keys Registry — meu-fastmcp
**Project ID (MCP)**: `meu-fastmcp`
**MCP Server**: `multi-project-memory` (Qdrant)
File này là **registry** các context keys của project MeU FastMCP Memory Server.
Format key tuân theo [CONTEXT-STRUCTURE.md](./CONTEXT-STRUCTURE.md): `{category}:{name}`
---
## 1. `arch:*` — Kiến trúc
| Key | Mô tả | Status |
|-----|--------|:------:|
| `arch:overview` | FastMCP server giao tiếp qua stdio. 4 MCP tools. Qdrant vector DB + SentenceTransformer embeddings. Multi-project isolation bằng `project_id` filter trên 1 collection chung. | ⬜ |
| `arch:tech-stack` | Python 3.12+, FastMCP, Qdrant, sentence-transformers (all-MiniLM-L6-v2, 384-dim), python-gitlab, python-dotenv | ⬜ |
| `arch:folder-structure` | `memory_mcp_server.py` (main), `.env` (config), `AGENT.md` (agent context), `CONTEXT-STRUCTURE.md` (key format), `CONTEXT-KEY.md` (registry) | ⬜ |
| `arch:data-model` | Qdrant collection `multi_project_memory`. Point: vector 384-dim + payload {project_id, key, content}. ID: UUID5 từ `{project_id}_{key}`. | ⬜ |
| `arch:design-pattern:multi-project` | 1 collection chung, filter `FieldCondition(key="project_id", match=MatchValue(value=project_id))`. Cho phép nhiều project chia sẻ 1 Qdrant instance. | ⬜ |
---
## 2. `api:*` — MCP Tools (API)
| Key | Mô tả | Status |
|-----|--------|:------:|
| `api:load-agent-context` | `load_agent_context()` — đọc AGENT.md từ workspace root, cache vào Qdrant (project=global, key=agent_context) | ⬜ |
| `api:save-context` | `save_context(project_id, key, content)` — lưu context với embedding. UUID5 upsert-safe. | ⬜ |
| `api:search-context` | `search_context(project_id, query, limit=5)` — semantic search, filter project_id. Trả key, content, score. | ⬜ |
| `api:index-gitlab-repo` | `index_gitlab_repo(project_id, gitlab_project_id)` — fetch all files từ main branch, index vào Qdrant (truncate 2000 chars). | ⬜ |
---
## 3. `biz:*` — Business Logic
| Key | Mô tả | Status |
|-----|--------|:------:|
| `biz:context-key-format` | Key format: `{category}:{name}`. 10 categories: arch, api, biz, db, comp, fix, config, conv, dep, task. Chi tiết: CONTEXT-STRUCTURE.md | ⬜ |
| `biz:embedding-flow` | Input text → `embedder.encode(text).tolist()` → vector 384-dim → upsert Qdrant với cosine similarity | ⬜ |
| `biz:uuid-generation` | UUID5 từ `{project_id}_{key}` (namespace=DNS). Deterministic → upsert an toàn, không duplicate. | ⬜ |
| `biz:content-limit` | Content lưu Qdrant: max 2000 chars. Tóm tắt trước khi lưu nếu vượt. | ⬜ |
---
## 4. `config:*` — Configuration
| Key | Mô tả | Status |
|-----|--------|:------:|
| `config:env-vars` | `QDRANT_HOST` (default 192.168.0.29), `QDRANT_PORT` (default 7333), `GITLAB_URL`, `GITLAB_TOKEN` | ⬜ |
| `config:docker` | Docker Compose: mcp-server (build .) + qdrant. Server: stdin_open=true (stdio transport). Qdrant: ports 6333/6334. | ⬜ |
| `config:qdrant-collection` | Collection `multi_project_memory`, vector size 384, distance Cosine, auto-create on startup. | ⬜ |
---
## 5. `conv:*` — Code Conventions
| Key | Mô tả | Status |
|-----|--------|:------:|
| `conv:mcp-tool-rules` | Decorator `@mcp.tool()`. Bắt buộc docstring. Luôn có `project_id` param. Dùng `embedder.encode()`. | ⬜ |
| `conv:error-handling` | try-except + print() cho lỗi không critical (file indexing). Không crash server. | ⬜ |
---
## 6. `dep:*` — Dependencies
| Key | Mô tả | Status |
|-----|--------|:------:|
| `dep:fastmcp` | Framework MCP server, giao tiếp stdio. `FastMCP(name="multi-project-memory")` | ⬜ |
| `dep:qdrant-client` | Client kết nối Qdrant. `QdrantClient(host, port)`. API: upsert, query_points, get_collection, create_collection. | ⬜ |
| `dep:sentence-transformers` | Model `all-MiniLM-L6-v2`. Output 384-dim vectors. Dùng `SentenceTransformer.encode()`. | ⬜ |
| `dep:python-gitlab` | `Gitlab(url, token)`. API: `projects.get()`, `repository_tree()`, `files.get()`. | ⬜ |
---
## 7. `task:*` — Decisions & Tracking
| Key | Mô tả | Status |
|-----|--------|:------:|
| `task:decision:single-collection` | Dùng 1 Qdrant collection cho tất cả project, filter project_id. Lý do: đơn giản, dễ maintain, đủ cho scale hiện tại. | ⬜ |
| `task:decision:stdio-transport` | Chọn stdio transport cho MCP thay vì HTTP. Lý do: standard MCP protocol, tương thích mọi AI agent. | ⬜ |
| `task:decision:uuid5-dedup` | UUID5 deterministic từ project_id+key. Lý do: upsert-safe, tránh duplicate khi save lại cùng key. | ⬜ |
---
## Tổng quan
| Status | Ký hiệu | Số lượng |
|--------|:--------:|:--------:|
| Đã lưu MCP | ✅ | 0 |
| Chưa lưu | ⬜ | 24 |
---
## Last Updated
- Updated: 2026-02-26
- Total Keys: 24
# CONTEXT-KEYS.md
**Quy định cấu trúc các context keys cần lưu vào MCP Memory Server (Qdrant)**
**Mỗi project dùng MCP đều phải tuân theo cấu trúc này khi `save_context()`.**
---
## Quy tắc chung
- **Key format**: `{category}:{name}` (ví dụ: `arch:overview`, `api:auth-login`)
- **Content**: Dưới 2000 chars, viết dạng summary/structured text
- **Ngôn ngữ**: Tiếng Việt hoặc Anh đều được, miễn nhất quán trong project
- **Cập nhật**: Khi logic thay đổi → upsert lại cùng key (UUID5 tự xử lý dedup)
---
## 1. `arch:*` — Kiến trúc hệ thống
| Key | Mô tả | Khi nào lưu |
|-----|--------|-------------|
| `arch:overview` | Tổng quan kiến trúc (layers, patterns, flow chính) | Khởi tạo project / kiến trúc thay đổi lớn |
| `arch:tech-stack` | Tech stack chi tiết (framework, DB, libs, versions) | Khởi tạo / thêm dependency mới |
| `arch:folder-structure` | Cấu trúc thư mục quan trọng (bỏ qua node_modules, .next, v.v.) | Thêm module/folder mới |
| `arch:data-model` | Mối quan hệ giữa các entity/model (ERD dạng text) | Thêm/sửa model |
| `arch:design-pattern:{name}` | Pattern cụ thể đang dùng (ví dụ: `arch:design-pattern:repository`) | Áp dụng pattern mới |
**Ví dụ content** cho `arch:overview`:
```
3-layer architecture: UI → Server Actions → Services → Repositories → MongoDB.
App Router (Next.js 13+), Server Components by default.
Auth: Custom JWT (lib/auth.ts + lib/server-auth.ts + middleware.ts).
```
---
## 2. `api:*` — API & Endpoints
| Key | Mô tả | Khi nào lưu |
|-----|--------|-------------|
| `api:{feature}-{action}` | Mô tả endpoint (method, path, params, response) | Tạo/sửa API endpoint |
| `api:auth-flow` | Flow xác thực (login, token, middleware) | Thay đổi auth logic |
| `api:error-codes` | Danh sách error codes và ý nghĩa | Thêm error handling mới |
**Ví dụ key**: `api:auth-login`, `api:rca-create`, `api:incident-list`
---
## 3. `biz:*` — Business Logic & Domain Rules
| Key | Mô tả | Khi nào lưu |
|-----|--------|-------------|
| `biz:{feature}-rules` | Quy tắc nghiệp vụ của feature | Implement/thay đổi logic nghiệp vụ |
| `biz:{feature}-flow` | Flow xử lý của feature (step-by-step) | Tạo/sửa flow |
| `biz:roles-permissions` | Phân quyền theo role (admin, manager, member) | Thay đổi logic phân quyền |
| `biz:validation-rules` | Quy tắc validate input/data | Thêm/sửa validation |
**Ví dụ key**: `biz:rca-create-flow`, `biz:team-access-rules`, `biz:incident-link-rules`
---
## 4. `db:*` — Database Schema & Queries
| Key | Mô tả | Khi nào lưu |
|-----|--------|-------------|
| `db:schema:{model}` | Schema của model (fields, types, relations) | Thêm/sửa model |
| `db:migration:{name}` | Mô tả migration quan trọng | Chạy migration |
| `db:query-pattern:{name}` | Query pattern phức tạp hay dùng lại | Viết query phức tạp |
| `db:indexes` | Danh sách indexes quan trọng | Tạo/sửa index |
**Ví dụ key**: `db:schema:rca`, `db:schema:project-member`, `db:query-pattern:team-filter`
---
## 5. `comp:*` — UI Components & Frontend
| Key | Mô tả | Khi nào lưu |
|-----|--------|-------------|
| `comp:{name}` | Component chính (props, behavior, dependencies) | Tạo/sửa component phức tạp |
| `comp:design-system` | Design tokens, theme, color palette | Thay đổi design system |
| `comp:layout:{name}` | Layout pattern (sidebar, header, responsive) | Tạo/sửa layout |
| `comp:form:{name}` | Form structure (fields, validation, submission) | Tạo/sửa form phức tạp |
**Ví dụ key**: `comp:rca-editor`, `comp:form:create-rca`, `comp:layout:dashboard`
---
## 6. `fix:*` — Bug Fixes & Lessons Learned
| Key | Mô tả | Khi nào lưu |
|-----|--------|-------------|
| `fix:{issue-description}` | Bug đã fix (root cause, solution, files affected) | Sau khi fix bug quan trọng |
| `fix:gotcha:{name}` | Gotcha / trap thường gặp trong project | Phát hiện edge case |
| `fix:perf:{name}` | Performance issue và cách optimize | Fix performance issue |
**Ví dụ key**: `fix:auth-token-expired`, `fix:gotcha:prisma-json-field`, `fix:perf:search-query-slow`
---
## 7. `config:*` — Configuration & Environment
| Key | Mô tả | Khi nào lưu |
|-----|--------|-------------|
| `config:env-vars` | Danh sách env vars và mục đích | Thêm env var mới |
| `config:docker` | Docker setup (services, ports, volumes) | Thay đổi Docker config |
| `config:ci-cd` | CI/CD pipeline config | Thay đổi pipeline |
| `config:third-party:{name}` | Config cho third-party service | Tích hợp service mới |
---
## 8. `conv:*` — Code Conventions & Standards
| Key | Mô tả | Khi nào lưu |
|-----|--------|-------------|
| `conv:naming` | Quy tắc đặt tên (files, functions, variables) | Định nghĩa/thay đổi convention |
| `conv:file-structure` | Quy tắc tổ chức file trong module/feature | Thêm quy tắc mới |
| `conv:error-handling` | Pattern xử lý lỗi chuẩn | Thay đổi error pattern |
| `conv:testing` | Quy tắc viết test (naming, structure, mocks) | Setup/thay đổi testing |
---
## 9. `dep:*` — Dependencies & Integrations
| Key | Mô tả | Khi nào lưu |
|-----|--------|-------------|
| `dep:{lib-name}` | Mục đích, version, cách dùng lib | Thêm dependency mới |
| `dep:upgrade:{lib-name}` | Notes về upgrade (breaking changes, migration) | Upgrade dependency |
| `dep:integration:{service}` | Cách tích hợp với external service | Tích hợp service mới |
---
## 10. `task:*` — Task Tracking & Decisions
| Key | Mô tả | Khi nào lưu |
|-----|--------|-------------|
| `task:decision:{name}` | Architecture/design decision (ADR style) | Quyết định thiết kế quan trọng |
| `task:todo:{feature}` | Việc cần làm cho feature (backlog) | Planning feature mới |
| `task:done:{feature}` | Summary sau khi hoàn thành feature | Hoàn thành feature |
---
## Quy trình cập nhật context (bắt buộc)
```
1. Bắt đầu session → load_agent_context() hoặc đọc AGENT.md
2. Trước khi code → search_context(project_id, query)
3. Sau khi code → save_context(project_id, key, content)
- key theo format: {category}:{name}
- content: tóm tắt dưới 2000 chars
4. Thay đổi lớn → index_gitlab_repo() để cập nhật toàn bộ
```
### Ví dụ save_context thực tế:
```python
# Sau khi implement team-based access control
save_context(
project_id="meu-rca-nextjs",
key="biz:team-access-rules",
content="""
Team-based access control:
- User chỉ thấy Project & RCA của team mình
- Filter: ProjectMember.userId == currentUser.id
- Admin: Thấy tất cả (bypass filter)
- Files: middleware.ts, modules/project/actions.ts, modules/rca/actions.ts
"""
)
```
---
## Last Updated
- Updated: 2026-02-26
- Status: Active — áp dụng cho tất cả project dùng MeU FastMCP
FROM python:3.12-slim
WORKDIR /app
# Cài các thư viện cần thiết cho sentence-transformers, sau đó xóa cache để giảm size
RUN apt-get update && \
apt-get install -y --no-install-recommends gcc g++ && \
rm -rf /var/lib/apt/lists/*
# Cài Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy toàn bộ mã nguồn (nên dùng .dockerignore để loại trừ file không cần thiết)
COPY . .
# Expose port cho FastAPI HTTP
EXPOSE 8090
# Lệnh chạy server FastAPI
CMD ["python3.12", "-m", "uvicorn", "memory_mcp_server:app", "--host", "0.0.0.0", "--port", "8090"]
\ No newline at end of file
# PROMPT.md
**File này chứa các prompt mẫu, template hay dùng khi chat với Copilot / agent local.**
**Không dùng để đọc cho người, chỉ dùng cho AI để giữ context và phong cách nhất quán.**
## Quy tắc sử dụng file này
- Mỗi prompt có ID riêng (Prompt 001, 002...).
- Khi cần dùng: Gõ "@prompt.md [ID]" hoặc copy-paste prompt vào chat.
- Cập nhật khi có prompt mới hay dùng.
- Giới hạn: Giữ ngắn gọn, mỗi prompt dưới 500 token.
## Prompt 001 - Làm chức năng cho req: chỉ cho phép người dùng cùng team được thấy rca và project của team đó
** đọc file api-login.txt để lấy thông tin api get team,và làm chức năng: chỉ cho phép người dùng cùng team được thấy rca và project của team đó **:
## Prompt 002 - Cập nhật Context-key.md
** viết vào file quy định sử dụng CONTEXT-KEY.md: mỗi lần cập nhật logic nghiệp vụ hoặc làm feature mới thì cập nhật context-key theo format hiện tại, và sử dụng asisstant-memory để cập nhật vào mcp. source vừa cập nhật chức năng theo requirement ở Promp 001, cập nhật file CONTEXT-KEY.md và asisstant-memory mcp **
\ No newline at end of file
version: "3.8"
services:
meu-fastmcp:
build: .
env_file:
- .env
stdin_open: true
tty: true
restart: unless-stopped
command: python3.12 -m uvicorn memory_mcp_server:app --host 0.0.0.0 --port 8090
import os
import pathlib
from dotenv import load_dotenv
from fastapi import FastAPI, Request
from pydantic import BaseModel
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter, FieldCondition, MatchValue
from sentence_transformers import SentenceTransformer
from gitlab import Gitlab
import uuid
from datetime import datetime
load_dotenv()
# Config
QDRANT_HOST = os.getenv("QDRANT_HOST", "192.168.0.29")
QDRANT_PORT = int(os.getenv("QDRANT_PORT", 7333))
COLLECTION_NAME = "multi_project_memory" # Collection chung cho tất cả project
GITLAB = Gitlab(os.getenv("GITLAB_URL"), private_token=os.getenv("GITLAB_TOKEN"))
# Clients
qdrant = QdrantClient(host=QDRANT_HOST, port=QDRANT_PORT)
embedder = SentenceTransformer("all-MiniLM-L6-v2")
# Tạo collection nếu chưa có
try:
qdrant.get_collection(COLLECTION_NAME)
except:
qdrant.create_collection(
collection_name=COLLECTION_NAME,
vectors_config=VectorParams(size=384, distance=Distance.COSINE),
)
app = FastAPI()
class SaveContextModel(BaseModel):
project_id: str
key: str
content: str
class SearchContextModel(BaseModel):
project_id: str
query: str
limit: int = 5
class IndexGitlabModel(BaseModel):
project_id: str
gitlab_project_id: int
class DeleteContextModel(BaseModel):
project_id: str
key: str
class DeleteProjectContextModel(BaseModel):
project_id: str
@app.get("/agent-context")
def load_agent_context():
workspace_root = pathlib.Path.cwd()
agent_file = workspace_root / "AGENT.md"
if agent_file.exists():
content = agent_file.read_text(encoding="utf-8")
save_context("global", "agent_context", content)
return {"content": content}
else:
return {"error": "AGENT.md not found in workspace root. Please create it."}
@app.post("/save-context")
def save_context_api(data: SaveContextModel):
return {"result": save_context(data.project_id, data.key, data.content)}
def save_context(project_id: str, key: str, content: str):
unique_string = f"{project_id}_{key}"
unique_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, unique_string))
vector = embedder.encode(content).tolist()
qdrant.upsert(
collection_name=COLLECTION_NAME,
points=[PointStruct(
id=unique_id,
vector=vector,
payload={
"project_id": str(project_id),
"key": key,
"content": content,
"updated_at": datetime.now().isoformat(),
"category": key.split(":")[0] if ":" in key else "unknown"
}
)]
)
# Meta key update logic giữ nguyên như cũ
meta_key = f"{project_id}_meta:context-keys-list"
meta_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, meta_key))
meta_entry = (
f"Key: {key} | "
f"Category: {key.split(':')[0] if ':' in key else 'unknown'} | "
f"Updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} | "
f"ID: {unique_id[:8]}...\n"
)
meta_content = meta_entry
try:
retrieved = qdrant.retrieve(
collection_name=COLLECTION_NAME,
ids=[meta_id],
with_payload=True
)
if retrieved and retrieved[0].payload:
old_content = retrieved[0].payload.get("content", "")
if f"Key: {key} " not in old_content:
meta_content = old_content.rstrip() + "\n" + meta_entry
else:
meta_content = old_content
except Exception as e:
print(f"Meta retrieve error: {e}")
meta_content = meta_entry
meta_vector = embedder.encode(meta_content).tolist()
qdrant.upsert(
collection_name=COLLECTION_NAME,
points=[PointStruct(
id=meta_id,
vector=meta_vector,
payload={
"project_id": str(project_id),
"key": meta_key,
"content": meta_content,
"type": "meta_keys_list",
"updated_at": datetime.now().isoformat()
}
)]
)
return f"Saved context for project '{project_id}' with key: {key}. Meta list updated."
@app.post("/search-context")
def search_context_api(data: SearchContextModel):
return {"results": search_context(data.project_id, data.query, data.limit)}
def search_context(project_id: str, query: str, limit: int = 5):
vector = embedder.encode(query).tolist()
hits = qdrant.query_points(
collection_name=COLLECTION_NAME,
query=vector,
query_filter=Filter(
must=[FieldCondition(
key="project_id",
match=MatchValue(value=str(project_id))
)]
),
limit=limit
).points
return [
{
"key": hit.payload.get("key", hit.id),
"content": hit.payload["content"],
"score": hit.score
}
for hit in hits
]
@app.post("/index-gitlab-repo")
def index_gitlab_repo_api(data: IndexGitlabModel):
return {"result": index_gitlab_repo(data.project_id, data.gitlab_project_id)}
def index_gitlab_repo(project_id: str, gitlab_project_id: int):
project = GITLAB.projects.get(gitlab_project_id)
tree = project.repository_tree(recursive=True)
indexed = 0
for item in tree:
if item["type"] == "blob":
try:
file = project.files.get(item["path"], ref="main")
content = file.decode().decode("utf-8")[:2000]
save_context(project_id, item["path"], content)
indexed += 1
except Exception as e:
print(f"Error indexing {item['path']}: {e}")
continue
return f"Indexed {indexed} files for project '{project_id}' (GitLab ID: {gitlab_project_id})"
@app.get("/list-all-keys/{project_id}")
def list_all_keys(project_id: str):
meta_key = f"{project_id}_meta:context-keys-list"
meta_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, meta_key))
try:
retrieved = qdrant.retrieve(
collection_name=COLLECTION_NAME,
ids=[meta_id],
with_payload=True
)
if retrieved and len(retrieved) > 0 and retrieved[0].payload:
meta_content = retrieved[0].payload.get("content", "Danh sách trống.")
lines = meta_content.strip().split("\n")
formatted = [f"• {line.strip()}" for line in lines if line.strip()]
total = len(formatted)
result = f"Danh sách context keys cho project '{project_id}' ({total} items):\n" + "\n".join(formatted)
return {"result": result if formatted else "Meta list tồn tại nhưng hiện tại trống."}
else:
return {"error": "Không tìm thấy meta list cho project này. Hãy lưu ít nhất một context bằng save_context, sau đó thử lại."}
except Exception as e:
print(f"List all keys error: {str(e)}")
return {"error": f"Lỗi khi lấy meta list: {str(e)}. Kiểm tra log MCP server hoặc Qdrant dashboard."}
@app.post("/delete-context")
def delete_context_api(data: DeleteContextModel):
return {"result": delete_context(data.project_id, data.key)}
def delete_context(project_id: str, key: str):
unique_string = f"{project_id}_{key}"
unique_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, unique_string))
from qdrant_client.models import PointIdsList
qdrant.delete(
collection_name=COLLECTION_NAME,
points_selector=PointIdsList(points=[unique_id])
)
return f"Deleted context for project '{project_id}' with key: {key}"
@app.post("/delete-project-context")
def delete_project_context_api(data: DeleteProjectContextModel):
return {"result": delete_project_context(data.project_id)}
def delete_project_context(project_id: str):
from qdrant_client.models import FilterSelector, Filter, FieldCondition, MatchValue
qdrant.delete(
collection_name=COLLECTION_NAME,
points_selector=FilterSelector(
filter=Filter(
must=[
FieldCondition(
key="project_id",
match=MatchValue(value=project_id)
)
]
)
)
)
return f"Deleted all contexts for project '{project_id}'"
if __name__ == "__main__":
import uvicorn
uvicorn.run("memory_mcp_server:app", host="0.0.0.0", port=8090)
import os
import pathlib
from dotenv import load_dotenv
from fastmcp import FastMCP
from qdrant_client import QdrantClient
from qdrant_client.models import Distance, VectorParams, PointStruct, Filter, FieldCondition, MatchValue
from sentence_transformers import SentenceTransformer
from gitlab import Gitlab
import uuid
from datetime import datetime
load_dotenv()
# Config
QDRANT_HOST = os.getenv("QDRANT_HOST", "192.168.0.29")
QDRANT_PORT = int(os.getenv("QDRANT_PORT", 7333))
COLLECTION_NAME = "multi_project_memory"
GITLAB = Gitlab(os.getenv("GITLAB_URL"), private_token=os.getenv("GITLAB_TOKEN"))
# MCP server
mcp = FastMCP(name="multi-project-memory")
# Clients
qdrant = QdrantClient(host=QDRANT_HOST, port=QDRANT_PORT)
embedder = SentenceTransformer("all-MiniLM-L6-v2")
# Tạo collection nếu chưa có
try:
qdrant.get_collection(COLLECTION_NAME)
except:
qdrant.create_collection(
collection_name=COLLECTION_NAME,
vectors_config=VectorParams(size=384, distance=Distance.COSINE),
)
@mcp.tool()
def load_agent_context():
"""Tự động đọc file AGENT.md từ root workspace và trả về nội dung."""
workspace_root = pathlib.Path.cwd()
agent_file = workspace_root / "AGENT.md"
if agent_file.exists():
content = agent_file.read_text(encoding="utf-8")
save_context(project_id="global", key="agent_context", content=content)
return content
else:
return "AGENT.md not found in workspace root. Please create it."
@mcp.tool()
def save_context(project_id: str, key: str, content: str):
"""Lưu context/code summary vào Qdrant cho một project cụ thể. Tự động update meta key list."""
unique_string = f"{project_id}_{key}"
unique_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, unique_string))
vector = embedder.encode(content).tolist()
qdrant.upsert(
collection_name=COLLECTION_NAME,
points=[PointStruct(
id=unique_id,
vector=vector,
payload={
"project_id": str(project_id),
"key": key,
"content": content,
"updated_at": datetime.now().isoformat(),
"category": key.split(":")[0] if ":" in key else "unknown"
}
)]
)
# Meta key update
meta_key = f"{project_id}_meta:context-keys-list"
meta_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, meta_key))
meta_entry = (
f"Key: {key} | "
f"Category: {key.split(':')[0] if ':' in key else 'unknown'} | "
f"Updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} | "
f"ID: {unique_id[:8]}...\n"
)
meta_content = meta_entry
try:
retrieved = qdrant.retrieve(
collection_name=COLLECTION_NAME,
ids=[meta_id],
with_payload=True
)
if retrieved and retrieved[0].payload:
old_content = retrieved[0].payload.get("content", "")
if f"Key: {key} " not in old_content:
meta_content = old_content.rstrip() + "\n" + meta_entry
else:
meta_content = old_content
except Exception as e:
print(f"Meta retrieve error: {e}")
meta_content = meta_entry
meta_vector = embedder.encode(meta_content).tolist()
qdrant.upsert(
collection_name=COLLECTION_NAME,
points=[PointStruct(
id=meta_id,
vector=meta_vector,
payload={
"project_id": str(project_id),
"key": meta_key,
"content": meta_content,
"type": "meta_keys_list",
"updated_at": datetime.now().isoformat()
}
)]
)
return f"Saved context for project '{project_id}' with key: {key}. Meta list updated."
@mcp.tool()
def search_context(project_id: str, query: str, limit: int = 5):
"""Tìm kiếm semantic context từ Qdrant, chỉ trong project được chỉ định."""
vector = embedder.encode(query).tolist()
hits = qdrant.query_points(
collection_name=COLLECTION_NAME,
query=vector,
query_filter=Filter(
must=[FieldCondition(
key="project_id",
match=MatchValue(value=str(project_id))
)]
),
limit=limit
).points
return [
{
"key": hit.payload.get("key", hit.id),
"content": hit.payload["content"],
"score": hit.score
}
for hit in hits
]
@mcp.tool()
def index_gitlab_repo(project_id: str, gitlab_project_id: int):
"""Index repo GitLab vào Qdrant cho project cụ thể (lấy files và lưu summary)."""
project = GITLAB.projects.get(gitlab_project_id)
tree = project.repository_tree(recursive=True)
indexed = 0
for item in tree:
if item["type"] == "blob":
try:
file = project.files.get(item["path"], ref="main")
content = file.decode().decode("utf-8")[:2000]
save_context(project_id, item["path"], content)
indexed += 1
except Exception as e:
print(f"Error indexing {item['path']}: {e}")
continue
return f"Indexed {indexed} files for project '{project_id}' (GitLab ID: {gitlab_project_id})"
@mcp.tool()
def list_all_keys(project_id: str):
"""Liệt kê tất cả context keys đã lưu cho project bằng cách search trực tiếp meta key."""
meta_key = f"{project_id}_meta:context-keys-list"
meta_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, meta_key))
try:
retrieved = qdrant.retrieve(
collection_name=COLLECTION_NAME,
ids=[meta_id],
with_payload=True
)
if retrieved and len(retrieved) > 0 and retrieved[0].payload:
meta_content = retrieved[0].payload.get("content", "Danh sách trống.")
lines = meta_content.strip().split("\n")
formatted = [f"• {line.strip()}" for line in lines if line.strip()]
total = len(formatted)
result = f"Danh sách context keys cho project '{project_id}' ({total} items):\n" + "\n".join(formatted)
return result if formatted else "Meta list tồn tại nhưng hiện tại trống."
else:
return "Không tìm thấy meta list cho project này. Hãy lưu ít nhất một context bằng save_context, sau đó thử lại."
except Exception as e:
print(f"List all keys error: {str(e)}")
return f"Lỗi khi lấy meta list: {str(e)}. Kiểm tra log MCP server hoặc Qdrant dashboard."
@mcp.tool()
def delete_context(project_id: str, key: str):
"""Xóa một context cụ thể theo key trong project."""
unique_string = f"{project_id}_{key}"
unique_id = str(uuid.uuid5(uuid.NAMESPACE_DNS, unique_string))
from qdrant_client.models import PointIdsList
qdrant.delete(
collection_name=COLLECTION_NAME,
points_selector=PointIdsList(points=[unique_id])
)
return f"Deleted context for project '{project_id}' with key: {key}"
@mcp.tool()
def delete_project_context(project_id: str):
"""Xóa toàn bộ context của một project trong Qdrant."""
from qdrant_client.models import FilterSelector, Filter, FieldCondition, MatchValue
qdrant.delete(
collection_name=COLLECTION_NAME,
points_selector=FilterSelector(
filter=Filter(
must=[
FieldCondition(
key="project_id",
match=MatchValue(value=project_id)
)
]
)
)
)
return f"Deleted all contexts for project '{project_id}'"
if __name__ == "__main__":
mcp.run()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment