Imported from BigKAA/qmcp (
AGENTS.md). Install upstream withnpx skills add BigKAA/qmcp. Copyright stays with the author.
AGENTS.md - Instructions for AI Agents
This file contains instructions for AI agents working on or with this project.
Project Overview
- Project Name: qmcp (QDrant MCP Server)
- Purpose: Semantic search server for code and documentation using Qdrant vector database
- Language: Python 3.11+
- Framework: FastMCP (MCP Python SDK)
Key Commands
Quick Start
# Install dependencies
make install
# Install as MCP server for OpenCode
make mcp-install
# Run tests
make test
# Lint code
make lint
Development
# Run in development mode (with MCP inspector)
make mcp-dev
# Run with coverage
make test-cov
# Format code
make format
Architecture
See ARCHITECTURE.md for detailed system architecture.
File Structure
qmcp/
├── src/
│ ├── qmcp/
│ │ ├── server.py # FastMCP server, tools definition
│ │ ├── client.py # Qdrant client wrapper
│ │ ├── config.py # Pydantic settings
│ │ ├── indexer.py # Code indexing logic
│ │ ├── watcher.py # File system watcher
│ │ ├── cleanup.py # Stale vector cleanup
│ │ ├── logging_config.py # Logging configuration
│ │ ├── parser/ # Multi-language parsers
│ │ │ ├── base.py # Parser interface
│ │ │ ├── python.py # AST parser
│ │ │ └── multi.py # tree-sitter parsers
│ │ └── models.py # Pydantic models
│ └── main.py # Entry point
├── tests/
│ ├── test_server.py
│ ├── test_indexer.py
│ ├── test_parser.py
│ ├── test_watcher.py
│ └── test_cleanup.py
├── chart/ # Helm chart (optional, for production)
├── Makefile
└── pyproject.toml
Adding New Features
Adding a New Tool
-
Add tool function to
src/qmcp/server.py:@mcp.tool() async def my_new_tool(param: str = Field(...)) -> dict: """Tool description for LLM.""" # Implementation return result -
Add tests to
tests/test_server.py -
Update README.md with tool documentation
Adding a New Parser
- Create parser class in
src/qmcp/parser/ - Implement
BaseParserinterface:can_parse(file_path)- check if parser handles this fileparse_file(file_path)- parse file and return chunks
- Add parser to
PARSERSlist inparser/__init__.py - Add tests
Adding Configuration
- Add environment variable to
.env.example - Add to
Settingsclass insrc/qmcp/config.py - Update README.md with documentation
Automatic File Indexing
When implementing features that add or modify files in the project, ensure automatic indexing is enabled:
- Use the
WATCH_PATHSenvironment variable - Set paths that should be watched for changes - Enable the file watcher - Start the watcher with
qdrant_watch_startor automatically on server start - Ensure incremental indexing - New features should support incremental mode (
mode="incremental") to only update changed files
For this project, one global MCP server can be shared across multiple repositories. Implement and use automatic indexing on two levels:
- Server level: start watcher automatically for configured
WATCH_PATHSduring MCP startup - Agent/session level: when an agent starts working in a workspace, call
qdrant_get_statusand ensure the workspace root is covered; if not, callqdrant_watch_ensure(paths=[workspace_root])
Important behavior for multi-project usage:
- Do not replace already watched paths when enabling indexing for the current workspace
- Prefer
qdrant_watch_ensureoverqdrant_watch_startfor agent-driven workspace activation - Use
qdrant_watch_startonly when you intentionally want to replace the full watch set
The indexer automatically respects .gitignore - ensure your implementation follows this pattern:
- Exclude
node_modules/,vendor/,.venv/,__pycache__/ - Exclude build artifacts (
dist/,build/,*.class,*.o) - Exclude generated files (
*.pyc,*.pyo,.pytest_cache/) - Exclude IDE settings (
.idea/,.vscode/,*.swp)
Testing
Running Tests
# All tests
make test
# With coverage
make test-cov
# Specific test file
pytest tests/test_parser.py -v
Test Structure
tests/test_server.py- MCP tools teststests/test_indexer.py- Indexer teststests/test_parser.py- Parser teststests/test_watcher.py- Watcher teststests/test_cleanup.py- Cleanup tests
Integration with OpenCode
Installation
# Add MCP server to OpenCode
opencode mcp add qmcp uv run python -m qmcp.server
Or edit ~/.config/opencode/opencode.json directly (for environment variables):
{
"mcp": {
"qmcp": {
"type": "local",
"command": ["uv", "run", "python", "-m", "qmcp.server"],
"environment": {
"QDRANT_URL": "http://192.168.218.190:6333",
"WATCH_PATHS": "/home/user/shared-docs,/home/user/shared-snippets"
}
}
}
}
Manage MCP Servers
opencode mcp list # List all MCP servers
opencode mcp debug qmcp # Debug connection issues
opencode mcp logout qmcp # Remove MCP server
Available Tools
Once configured, OpenCode will have access to:
qdrant_search- Semantic searchqdrant_index_directory- Index codeqdrant_reindex- Full/incremental reindexqdrant_list_collections- List collectionsqdrant_get_collection_info- Collection detailsqdrant_delete_collection- Delete collectionqdrant_watch_start- Start watcherqdrant_watch_ensure- Ensure current workspace is watched without dropping othersqdrant_watch_stop- Stop watcherqdrant_cleanup- Clean stale vectorsqdrant_get_status- Server status
Troubleshooting
Qdrant Connection Failed
- Verify Qdrant is running:
curl http://192.168.218.190:6333 - Check network connectivity
- Verify QDRANT_URL environment variable
Indexing Not Working
- Check file permissions
- Verify embedding model is available
- Check logs for parsing errors
Code Style
- Linter: ruff
- Formatter: ruff format
- Type Checker: mypy
- Line Length: 100 characters
- Python Version: 3.11+
Common Patterns
Async Tool
@mcp.tool()
async def my_tool(param: str) -> dict:
"""Description for LLM."""
# Async operations
result = await async_function()
return {"result": result}
Adding Configuration
import os
# From environment
value = os.getenv("MY_VAR", "default")
# From pydantic settings
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
my_var: str = "default"
settings = Settings()
Error Handling
@mcp.tool()
async def safe_tool() -> dict:
try:
result = risky_operation()
return {"status": "success", "data": result}
except SpecificError as e:
return {"status": "error", "message": str(e)}
Communication
- Language: All communication with users should be in Russian
- Code comments: All code comments must be in English
- Documentation: Project documentation in English (README.md, etc.)
Code Comments Guidelines
All code should include detailed comments in English. This includes:
- Module-level docstrings explaining the purpose of each module
- Class docstrings with description, parameters, and return values
- Function/method docstrings with:
- Brief description
- Detailed explanation of parameters (type, purpose)
- Return value description
- Any exceptions that may be raised
- Usage examples where helpful
- Inline comments for complex logic or non-obvious decisions
Example:
"""
Module for handling Qdrant client operations.
This module provides a wrapper around the Qdrant client library,
abstracting common operations like collection management and vector search.
"""
class QdrantWrapper:
"""
Wrapper class for Qdrant client operations.
Provides high-level interface for interacting with Qdrant vector database,
including collection CRUD operations and semantic search functionality.
Attributes:
client: The underlying Qdrant client instance
collection_name: Name of the active collection
"""
def search(self, query: str, limit: int = 10) -> list[dict]:
"""
Perform semantic search on the collection.
Args:
query: The search query string
limit: Maximum number of results to return (default: 10)
Returns:
List of dictionaries containing search results with scores
Raises:
ConnectionError: If unable to connect to Qdrant server
ValueError: If collection does not exist
"""
# Implementation...
Publishing to PyPI
Prerequisites
- Store PyPI token in
~/.pypirc(NEVER commit this file to git):[pypi] username = __token__ password = pypi-your-token-here
Build and Publish
# 1. Create build environment
uv venv /tmp/build-venv --clear
source /tmp/build-venv/bin/activate
# 2. Install build tools
uv pip install build twine hatch
# 3. Build package
hatch build wheel
# 4. Upload to PyPI (uses ~/.pypirc config)
twine upload wheel/* -c ~/.pypirc
Security Rules
- Never store PyPI tokens in AGENTS.md, .env, or any git-tracked files
- Never commit
~/.pypircto version control - Use
~/.pypircfor local token storage
Dependencies
Key dependencies in pyproject.toml:
mcp[cli]- MCP server frameworkqdrant-client[fastembed]- Qdrant client + embeddingstree-sitter- Code parsingwatchdog- File system watchingpytest- Testingruff- Linting/formatting