Skip to main content
Glama
polloter130

SmartPark Reservation MCP Server

by polloter130

SmartPark Reservation MCP Server — Stage 3

A real MCP (Model Context Protocol) server, built with the official mcp Python SDK, that writes confirmed parking reservations to durable storage once a human administrator has approved them (Stage 2).

This is a separate repository/service from Stages 1 and 2 — Agent 2 calls this server's single tool over the network, the same way any MCP-compliant client would.

What it does

Exposes exactly one MCP tool: write_confirmed_reservation. Once the administrator (Agent 2) approves a reservation, Agent 2 calls this tool, which:

  1. Validates every field (rejects the | delimiter, newlines, null bytes, and overly long values — these would corrupt the file format or let a caller inject a fake extra record).

  2. Appends one line to data/confirmed_reservations.txt in the exact required format:

    Name | Car Number | Reservation Period | Approval Time
  3. Does this atomically and safely under concurrent calls (cross-platform file locking), and logs the attempt (success or rejection) to an audit log.

Related MCP server: rails-mcp

Architecture

 Agent 2 (Stage 2 Admin Agent)              Agent 3 (this repo)
┌──────────────────────────┐   MCP/HTTP    ┌────────────────────────────┐
│ apply_decision(confirmed) │ ────────────▶ │ POST /mcp                  │
│                           │  Bearer token │  BearerAuthMiddleware       │
│ integration/               │  required    │  RateLimitMiddleware        │
│  admin_agent_client.py     │              │  MCPServer                 │
│  -> record_confirmed_      │              │   └─ write_confirmed_       │
│     reservation()          │              │      reservation tool      │
└──────────────────────────┘              │       └─ validate ─┐        │
                                            │                    ▼        │
                                            │      data/confirmed_        │
                                            │      reservations.txt       │
                                            │      (file-locked append)   │
                                            │      + data/audit.log       │
                                            └────────────────────────────┘

Why the official MCP SDK (not just a REST endpoint)

Stage 3 asks for a real MCP server, or a FastAPI stand-in if that's not feasible. The official mcp Python SDK (MCPServer, formerly known as FastMCP) turned out to be fully usable here: it builds a standard streamable-HTTP ASGI app (so it composes with normal Starlette middleware for auth/rate-limiting) and ships with production security features out of the box — DNS-rebinding protection, host/origin allowlisting, and request-body size limits — which is exactly what "secure and resistant to unauthorized access" calls for. Building a hand-rolled JSON-RPC-over-FastAPI server would have meant re-implementing a worse version of these same protections.

Security measures

Concern

Mitigation

Unauthorized callers

BearerAuthMiddleware — every request needs Authorization: Bearer <MCP_API_KEY>, compared with hmac.compare_digest (no timing side-channel). No key configured → the server generates and prints a random one-time key rather than silently allowing unauthenticated access.

Abuse / DoS

RateLimitMiddleware — fixed-window limit per client IP (default 30 req/min, configurable).

DNS rebinding / host spoofing

The MCP SDK's built-in TransportSecuritySettings (enabled by default), with configurable ALLOWED_HOSTS/ALLOWED_ORIGINS for production.

Path traversal

Structurally impossible — the output file path is fixed by server config and is never accepted as a tool argument.

Record/format injection

Every field is validated to reject the `

Concurrent-write corruption

Cross-platform atomic file locking (filelock) around every append — tested with 20 simultaneous threads writing with zero interleaved/corrupted lines.

Oversized/malformed requests

max_request_body_size capped at 64KB (reservation payloads are tiny; anything bigger is rejected outright).

Traceability without leaking secrets

Every write attempt (success or rejection) is appended to data/audit.log, with only a masked token prefix — the real API key is never logged.

Reliability

A stuck lock surfaces as a clear, catchable TimeoutError after 5s rather than hanging the server; invalid input raises a specific InvalidReservationField the MCP layer turns into a normal tool-error result rather than crashing the process.

Project structure

parking_mcp_server/
├── app/
│   ├── config.py               # .env-driven configuration
│   ├── reservation_writer.py    # field validation + atomic file append
│   ├── audit_log.py              # append-only audit trail
│   ├── security.py                # BearerAuthMiddleware, RateLimitMiddleware
│   └── server.py                   # MCPServer + tool + ASGI wiring
├── integration/
│   ├── admin_agent_client.py       # what Stage 2 imports to call this server
│   └── db_patch_example.py         # exact diff for Stage 2's decision endpoint
├── tests/                           # 22 pytest tests across 4 modules
├── demo.py                           # end-to-end demo (live server + real MCP client)
├── view_reservations.py               # quick CLI viewer for the output file/audit log
├── run_server.sh / run_server.ps1
├── requirements.txt
├── .env.example
└── .github/workflows/ci.yml           # runs tests on both ubuntu-latest and windows-latest

Setup

Works identically on Windows, macOS, and Linux — pure Python (the official mcp SDK, Starlette/uvicorn, and the cross-platform filelock package; no OS-specific binaries).

python -m venv .venv && source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# Set MCP_API_KEY in .env for a stable key -- otherwise a random one-time
# key is generated and printed at startup.

Windows-specific notes

  • Use run_server.ps1 instead of run_server.sh.

  • filelock uses msvcrt under the hood on Windows automatically — no extra configuration needed for the concurrency-safety guarantees.

  • CI runs the full test suite on windows-latest as well as ubuntu-latest (see .github/workflows/ci.yml).

Usage

Run the demo (starts its own server, no setup needed):

PYTHONPATH=. python demo.py

Run the real server:

./run_server.sh        # Linux/macOS
.\run_server.ps1        # Windows

It prints a generated MCP_API_KEY on first run if you haven't set one — copy it into your client's Authorization: Bearer <key> header (or into Stage 2's .env as MCP_API_KEY, see Integration below).

View what's been written:

PYTHONPATH=. python view_reservations.py

Run tests:

PYTHONPATH=. python -m pytest tests/ -v

Integration with Agent 2 (Stage 2)

  • integration/admin_agent_client.py — the client Stage 2 imports (record_confirmed_reservation(name, car_number, reservation_period, approval_time)), which opens a real MCP client session, authenticates, and calls the tool.

  • integration/db_patch_example.py — the exact before/after diff for Stage 2's POST /requests/{id}/decision endpoint: once a reservation is marked "confirmed", it now also calls record_confirmed_reservation(...) so the approval is durably recorded here, not just in Stage 2's own request-tracking table.

  • Stage 2's .env needs: MCP_SERVER_URL=http://127.0.0.1:8002/mcp and MCP_API_KEY=<the same key configured on this server>.

Notes / limitations (Stage 3 scope)

  • Rate limiting and the audit log are in-memory/local-file, appropriate for a single-process deployment; a multi-instance deployment would move the rate limiter to a shared store (e.g. Redis) and the audit log to a centralized logging system.

  • MCP_API_KEY is a single shared secret rather than per-client credentials — sufficient for a single trusted caller (Agent 2), but a multi-tenant deployment would want per-client tokens or the MCP SDK's full OAuth 2.1 support (auth_server_provider/AuthSettings, not used here since it requires standing up a separate OAuth issuer).

  • The reservations file is a flat text file, as specified; a higher-volume production deployment would likely write to a database instead, behind the same tool interface.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Records approved parking reservations to a secure text file via the Model Context Protocol, with token authentication and input sanitization.
    -
  • A
    license
    A
    quality
    B
    maintenance
    Default-deny action registry, append-only spend ledger, and human sign-off audit trail (MCP tools).
    6
    MIT
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables administrators to securely record approved parking reservations to a durable text file with validation, concurrency safety, and audit logging.
    -