Skip to content

Architecture

flowchart LR
    subgraph client["MCP Client / Agent"]
        A["tool call: action + params_json + store"]
    end

    subgraph server["objectstore-mcp (FastMCP)"]
        T1[objects]
        T2[buckets]
        T3[transfer]
        SG["Safety governor<br/>caps + delete flags + dry-run"]
        REG["Store registry<br/>OBJECTSTORE_STORES"]
    end

    subgraph backends["ObjectStoreBackend protocol"]
        FS[FilesystemBackend]
        S3["S3Backend<br/>AWS / MinIO / R2"]
        GCS[GCSBackend]
        AZ[AzureBlobBackend]
    end

    A --> T1
    A --> T2
    A --> T3
    T1 --> SG
    T2 --> SG
    T3 --> SG
    SG --> REG
    REG --> FS
    REG --> S3
    REG --> GCS
    REG --> AZ

Layers

Layer Module Responsibility
Tool surface objectstore_mcp/mcp/mcp_objectstore.py Action routing, parameter parsing, text/base64 encoding, all safety enforcement (CONCEPT:OBJ-1.2/1.3)
Store registry objectstore_mcp/config.py, objectstore_mcp/auth.py OBJECTSTORE_STORES parsing, default-store resolution, per-store backend cache (CONCEPT:OBJ-1.1)
Backend protocol objectstore_mcp/api/api_client_base.py The provider-neutral contract, dataclasses, error taxonomy, name/key validation (CONCEPT:OBJ-1.0)
Backends objectstore_mcp/api/api_client_{filesystem,s3,gcs,azure_blob}.py Pure storage adapters; lazy SDK imports (CONCEPT:OBJ-1.4/1.5)

Design decisions

  • Backends are bucket-agnostic. The bucket is a per-call argument; per-store default buckets are a tool-layer convenience. This keeps each backend a thin adapter and lets one store config span many buckets.
  • Safety lives in the tool layer, not the backends. Backends accept a max_bytes hint for cheap pre-flight size checks, but every cap, flag, and dry-run decision is made once, uniformly, in mcp_objectstore.py. No backend can accidentally weaken policy.
  • Errors are translated, never leaked. Provider SDK exceptions become the shared taxonomy (NotFoundError, AlreadyExistsError, BucketNotEmptyError, UnsupportedOperationError, MissingDependencyError), so the tool layer and tests treat all providers identically.
  • The filesystem backend is a first-class provider, not a mock. It implements the full protocol (including metadata via .meta/ sidecars and delimiter-folded pagination), which is what makes the conformance suite real coverage rather than mock theater.
  • Conformance over per-backend tests. tests/test_backend_conformance.py is parametrized on the backend fixture; cloud adapters get focused translation tests with injected fake clients, plus an optional moto suite (test-s3 extra).