mcpserve-py
# mcpserve-py



A **Model Context Protocol (MCP)** server built in Python ā exposes database query tools and document resources over JSON-RPC 2.0 stdio transport, enabling AI assistants to interact with SQLite databases and markdown documents.
## What is MCP?
The [Model Context Protocol](https://modelcontextprotocol.io/) is an open standard for connecting AI assistants to external tools and data sources. MCP servers expose **tools** (functions the AI can call) and **resources** (data the AI can read) over a JSON-RPC 2.0 transport.
This server implements the MCP protocol from scratch using raw JSON-RPC 2.0 over stdio ā no SDK dependency required.
## Features
- š§ **8 tools** ā database queries, document CRUD, search, date/time
- š **Resource providers** ā documents and database schemas as readable resources
- š”ļø **SQL injection protection** ā only SELECT queries allowed, with regex validation
- š **YAML frontmatter** ā documents stored as markdown with structured metadata
- š **Stdio transport** ā line-delimited JSON-RPC 2.0 over stdin/stdout
- ā” **Zero SDK dependency** ā hand-rolled MCP protocol implementation
- ā
**Well-tested** ā 113 tests covering protocol, tools, resources, and integration
## Quick Start
```bash
# Clone and install
git clone https://github.com/devaloi/mcpserve-py.git
cd mcpserve-py
pip install -e ".[dev]"
# Run the server
python -m mcpserve_py
# Run tests
python -m pytest -v
```
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `MCPSERVE_DATA_DIR` | `data` | Directory for documents and data |
| `MCPSERVE_DB_PATH` | `data/mcpserve.db` | Path to SQLite database |
| `MCPSERVE_LOG_LEVEL` | `INFO` | Log level (DEBUG, INFO, WARNING, ERROR) |
## Claude Desktop Configuration
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
```json
{
"mcpServers": {
"mcpserve-py": {
"command": "python",
"args": ["-m", "mcpserve_py"],
"env": {
"MCPSERVE_DATA_DIR": "./data",
"MCPSERVE_DB_PATH": "./data/mcpserve.db"
}
}
}
}
```
## Tools
| Tool | Description | Parameters |
|------|-------------|------------|
| `query_database` | Execute read-only SQL query | `sql: str`, `params?: list` |
| `list_tables` | List all tables in database | ā |
| `describe_table` | Get table schema | `table: str` |
| `create_document` | Create a markdown document | `title: str`, `content: str`, `tags?: list[str]` |
| `read_document` | Read document by title | `title: str` |
| `list_documents` | List all documents | `tag?: str` |
| `search_documents` | Full-text search across documents | `query: str` |
| `get_datetime` | Current date/time | `timezone?: str` |
## Resources
| URI Pattern | Description | MIME Type |
|-------------|-------------|-----------|
| `docs:///{title}` | Document content | `text/markdown` |
| `db:///schema` | Full database schema | `text/plain` |
| `db:///tables/{name}` | Single table schema | `text/plain` |
## Architecture
```
src/mcpserve_py/
āāā __main__.py # Entry point: python -m mcpserve_py
āāā server.py # MCP server: receive ā dispatch ā respond
āāā protocol.py # JSON-RPC 2.0 types and encoding
āāā transport.py # Stdio transport (line-delimited JSON)
āāā config.py # Pydantic settings
āāā tools/
ā āāā registry.py # Tool registry
ā āāā database.py # SQLite tools (query, list_tables, describe)
ā āāā documents.py # Document tools (CRUD + search)
ā āāā system.py # System tools (get_datetime)
āāā resources/
āāā provider.py # Resource provider interface + registry
āāā documents.py # Document resource provider
āāā database.py # Database schema resource provider
```
### Design Decisions
- **No MCP SDK** ā The protocol is implemented directly using JSON-RPC 2.0 dataclasses. This demonstrates deep understanding of the protocol rather than SDK usage.
- **Synchronous** ā Stdio is inherently sequential; async adds complexity without benefit here.
- **Pydantic Settings** ā Configuration via environment variables with type validation and `.env` file support.
- **Tool registry pattern** ā Tools register themselves with a central registry, keeping the server dispatch clean.
- **Read-only SQL** ā Mutations are rejected via regex before reaching SQLite, preventing data corruption by AI assistants.
- **YAML frontmatter** ā Documents use the same format as static site generators (Jekyll, Hugo), making them human-readable and tool-friendly.
## Development
```bash
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
make test
# Lint
make lint
# Type check
make typecheck
# Format
make format
# All checks
make all
```
## License
MIT
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md). PRs welcome ā run `make all` before submitting.
TDQS
Scored across 8 tools
Most tools target clearly distinct resources and actions, so an agent can pick correctly with little hesitation. The only mild overlap is between list_documents (tag filter) and search_documents (content/title query), which descriptions do disentangle.
Every tool follows a clean verb_noun snake_case pattern: query_database, list_tables, describe_table, create_document, read_document, list_documents, search_documents, get_datetime. No deviations or mixed conventions.
Eight tools is well-scoped for a lightweight multi-purpose server covering database introspection, document management, and a datetime utility. Each tool earns its place with no redundancy.
Document handling lacks update and delete operations, and the database surface is read-only with no insert/update/delete, so lifecycle coverage is partial. The lone get_datetime tool also sits outside either domain, leaving a somewhat heterogeneous surface.