Service MCP

Service MCP

A production-ready generic FastMCP server template with SQLAlchemy async CRUD, enabling rapid bootstrapping of MCP data-management services. It provides registry-driven CRUD, FK resolution, conflict versioning, and multiple transports.

Category
Visit Server

README

Service MCP — Generic FastMCP + SQLAlchemy CRUD Template

A production-ready, generic FastMCP server template with SQLAlchemy async CRUD, built by distilling a real-world fund NAV MCP service into a reusable skeleton. Use it to bootstrap new MCP data-management services.

Stack: Python 3.12+ · FastMCP 3.x · SQLAlchemy 2.x (async) · Pydantic v2 · Typer CLI · uv


Features

  • Registry-driven CRUD tools — add/update/delete (single + batch) are generated from a one-line entity registry; no per-entity boilerplate.
  • FK code auto-resolution — business codes (product_code) are resolved to internal IDs by the handler layer; callers never see primary keys.
  • Auto-placeholder creation — child records referencing a missing parent create a abnormal=Placeholder stub parent automatically (e.g. price records for an unknown product).
  • Orphan marking — deleting a parent marks dependent child rows abnormal=Orphaned instead of cascade-deleting; a review_abnormal_items tool aggregates all pending-review rows.
  • Composite-key delete — child records can be located by their natural compound key (product_code + price_date).
  • Dynamic Filter/Search — Filter/SearchByKeyword/SearchByFields classes are generated at import time from ORM introspection; .pyi stubs are regenerated by a script for IDE support.
  • Conflict versioning — same-day-same-source price conflicts bump a version column and mark the row for human review.
  • Multi-transport CLI — stdio / sse / streamable-http / ui (FastMCP Apps dashboard).
  • Layered config — env vars → TOML → code defaults (MCP_ prefix, MCP_ENV selects the TOML).
  • Auth-ready — JWT middleware + mcp_perm permission decorators with permission discovery.
  • Docker deployment — compose stack (PostgreSQL 18 + Redis 8, optional pgAdmin) with lifecycle scripts (ctl.sh / ctl.ps1).
  • Extras — mock data generator, idempotent migration example, SQLite/MySQL/PostgreSQL/InfluxDB support, FastMCP Apps config UI.

Quick start

uv venv && uv sync --dev

# Run the server (pick one transport)
uv run service-mcp stdio
uv run service-mcp streamable-http --host 0.0.0.0 --port 8001
uv run service-mcp sse --host 0.0.0.0 --port 8001
uv run service-mcp ui --dev-port 8080 --mcp-port 8001

On first start the server auto-creates configs/config.{MCP_ENV}.toml with a default in-memory SQLite database + Redis cache config — zero configuration to get going.

Example entities

The template ships one minimal domain — Product + ProductPrice — implemented end-to-end to demonstrate every pattern you need to replicate for your own entities:

Entity Demonstrates
Product unique business code, soft-delete flag, auto-placeholder creation (orphan parent)
ProductPrice FK code resolution, composite unique key (product_id + price_date + data_source + version), version conflict detection, orphan marking target, composite-key delete

Follow the chain: add_product → AddHandler → CodeResolveMixin._resolve_fk_codes → ProductPrice rows auto-resolve product_code → product_id; delete_product marks all its prices abnormal=Orphaned; add_product_price with a conflicting same-day-same-source value bumps version and flags abnormal=PriceConflict.

Project structure

service_mcp/
├── server.py          # FastMCP app + Typer CLI (stdio/sse/streamable-http/ui)
├── config.py          # MCPSettings layered config (env → TOML → code)
├── apps/              # FastMCP Apps UI (config_app: DB/cache management dashboard)
├── auth/              # JWT middleware, mcp_perm decorator, permission/entity discovery
├── db/                # DBManager (async SQLAlchemy CRUD/paginate) + InfluxDBManager
├── handlers/          # CodeResolveMixin + Add/Update/Delete/Query handlers
├── models/
│   ├── orm/           # SQLAlchemy models (base.py audit columns, product.py example)
│   ├── pydantic/      # dynamic Filter/Search generators + per-entity request/response models
│   └── schemas.py     # DB/cache config schemas + pagination
├── tools/             # crud_factory (registry-driven), query_tools, basic_tools, dict_tools
└── utils/             # enums, logging, path helpers
configs/               # config.example.toml skeleton (per-env TOMLs are git-ignored)
docker/                # compose files, entrypoint, ctl.sh/ctl.ps1
mock/                  # mock_product_data.py
scripts/               # rename_project.py, refresh_project_stub.py, migrate_example.py
tests/                 # pytest suite (in-memory SQLite)

Add a new entity

  1. ORM: create service_mcp/models/orm/<entity>.py subclassing Base (audit columns are inherited); add a unique business code column with a comment (used by friendly duplicate messages) and an abnormal: AbnormalType | None column for orphan marking. Export it in models/orm/__init__.py (import base first).
  2. Pydantic: create <Entity>Base / Create / Update / Delete (extends BaseDeleteModel, requires at least one lookup field) / Response in models/pydantic/<entity>.py; reuse the validator helpers in product_validators.py as a template.
  3. Filter/Search: add create_filter_class(...) / create_search_class(...) calls in models/pydantic/filter.py / search.py. If you override the generated class with an explicit class, re-register it with register_pyi_class(..., explicit=True).
  4. Regenerate stubs: uv run python scripts/refresh_project_stub.py (run twice; the second run must produce no diff).
  5. Handlers: add registry rows — _CODE_RESOLVE_MAP (FK codes), _NAME_RESOLVE_MAP (name fallback), _OWN_CODE_FIELDS (own unique codes), _AUTO_CREATE_MODELS (placeholder auto-creation), _DELETE_NAME_LOOKUP, _COMPOUND_TARGET_REGISTRY (compound delete keys), _ORPHAN_REGISTRY (children to mark on delete), FIELD_MAPPING_CONFIG (FK display fields for query results).
  6. Tools: add a row to crud_factory._ENTITIES (gives you add/update/delete single+batch tools) and list/search tools in query_tools.py.
  7. Enums: add EntityType / AuthResource entries and any domain enums in utils/enums.py.
  8. Mock/tests: add a TABLE_META row in mock/mock_product_data.py and seeded fixtures in tests/conftest.py.

Rename the project (one command)

The template uses placeholder naming (service_mcp / service-mcp / "Service MCP"). To create a new project from this template:

uv run python scripts/rename_project.py my_company \
    --project my-company-mcp --display "My Company MCP" --db my_company_data
uv sync            # regenerate uv.lock / reinstall
uv run pytest      # confirm green

The script rewrites all file contents and renames the package directory. Run with --dry-run to preview. uv.lock is intentionally skipped — regenerate it with uv sync.

Docker deployment

cp docker/.env.example docker/.env   # edit passwords/DB names
./docker/ctl.sh deploy -e prod       # or: ctl.ps1 on Windows

Infra only (app runs locally):

cd docker && docker compose up -d

Services: PostgreSQL 18 (5432), Redis 8 (6379), optional pgAdmin (5050).

Configuration reference

Env var Meaning Default
MCP_ENV environment name; selects configs/config.{env}.toml dev
MCP_CONFIG_PRIORITY init_first / env_first / toml_first / env_only / toml_only init_first
MCP_TRANSPORT default transport stdio
MCP_HOST / MCP_PORT / MCP_UI_PORT HTTP transport bindings 0.0.0.0 / 8001 / 8080
MCP_CACHE_ENABLED enable Redis cache true
MCP_AUTH_MODE tool or admin (JWT) tool
MCP_DATABASES__<NAME>__* per-database config (nested __) —
MCP_LOGGING__* logging config (console/file/JSON rotation) —

Testing & quality

pytest                          # all tests (in-memory SQLite, no external services)
ruff check .                    # lint
ruff format .                   # format
mypy service_mcp                # type check

License

MIT

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