ObjectStore MCP
Multi-Backend Object Storage | MCP Server
The object-storage connector for the agent-utilities fleet: one MCP tool surface over S3 and S3-compatible stores (MinIO, Cloudflare R2), Google Cloud Storage, Azure Blob Storage, and a zero-infra local-filesystem backend.
Version: 1.0.1
Documentation — Installation, deployment, and usage across the API, CLI, and MCP interfaces are maintained in
docs/.
Table of Contents
- Overview
- What it provides
- Backend × capability matrix
- Installation
- Configuration (environment)
- Usage
- MCP config
- Docker deployment
- Development
- License
Overview
objectstore-mcp wraps heterogeneous object stores behind one typed,
deterministic MCP tool surface, plus an optional Pydantic-AI A2A agent server
(objectstore-agent). Safety caps, explicit buckets, and dry-run-by-default
batch deletes are enforced uniformly in the tool layer, regardless of backend.
What it provides
-
A multi-backend store abstraction (
objectstore_mcp.api, CONCEPT:OBJ-1.0) — every provider implements the sameObjectStoreBackendprotocol, validated by a single conformance test suite that runs for real against the filesystem backend. -
Three consolidated, action-routed MCP tools (
objectstore-mcpconsole script):Tool Actions Description objectslist(prefix/delimiter pagination),head,get(text/base64, size-capped),put(text/base64, size-capped),copy,move,delete,delete_batch(capped, dry-run by default),presign,metadata_get,metadata_setSingle-object lifecycle and listing on any store bucketslist,create,delete(empty-only, opt-in),exists,info,storesBucket/container admin and store registry introspection transferupload,download,upload_dir,download_prefix(all size/batch-capped)Local-filesystem ⇄ object-store transfer, single or by prefix The whole tool set toggles with
OBJECTSTORETOOL. -
Named multi-store routing —
OBJECTSTORE_STORESJSON maps store names to{backend, bucket?, endpoint?, profile?, ...}; every tool takes an optionalstoreargument. A zero-infralocalfilesystem store always exists, so the server works with no cloud credentials at all. -
A safety governor — size caps on get/put/transfer, list/batch key caps, deletes that demand an explicit bucket+key (no wildcards), batch deletes that are prefix-scoped, capped, and dry-run by default, and bucket deletes that are empty-only and disabled unless explicitly enabled.
Available MCP Tools
Condensed action-routed tools (default — MCP_TOOL_MODE=condensed)
| MCP Tool | Toggle Env Var | Description |
|---|---|---|
buckets |
OBJECTSTORETOOL |
Manage buckets/containers and inspect configured stores. |
objects |
OBJECTSTORETOOL |
List, read, write, copy, move, delete, presign, and tag objects. |
transfer |
OBJECTSTORETOOL |
Move data between the local filesystem and object storage. |
Verbose 1:1 API-mapped tools (MCP_TOOL_MODE=verbose or both)
15 per-operation tools — one per public API method (click to expand)
| MCP Tool | Toggle Env Var | Description |
|---|---|---|
objectstore_bucket_exists |
OBJECT_STORE_BACKENDTOOL |
Return True when the bucket exists. |
objectstore_bucket_info |
OBJECT_STORE_BACKENDTOOL |
Describe one bucket. Raises NotFoundError when absent. |
objectstore_capabilities |
OBJECT_STORE_BACKENDTOOL |
Advertise optional capabilities. |
objectstore_copy_object |
OBJECT_STORE_BACKENDTOOL |
Server-side (where possible) copy of one object. |
objectstore_create_bucket |
OBJECT_STORE_BACKENDTOOL |
Create a bucket. Raises AlreadyExistsError if it exists. |
objectstore_delete_bucket |
OBJECT_STORE_BACKENDTOOL |
Delete an EMPTY bucket. Raises BucketNotEmptyError otherwise. |
objectstore_delete_object |
OBJECT_STORE_BACKENDTOOL |
Delete exactly one object. Raises NotFoundError when absent. |
objectstore_get_object |
OBJECT_STORE_BACKENDTOOL |
Download an object's bytes. Raises ObjectStoreError when the |
objectstore_get_object_metadata |
OBJECT_STORE_BACKENDTOOL |
Return the user metadata of one object. |
objectstore_head_object |
OBJECT_STORE_BACKENDTOOL |
Stat one object without downloading it. |
objectstore_list_buckets |
OBJECT_STORE_BACKENDTOOL |
List all buckets/containers visible to the credentials. |
objectstore_list_objects |
OBJECT_STORE_BACKENDTOOL |
List objects under prefix, optionally folding at delimiter. |
objectstore_presigned_url |
OBJECT_STORE_BACKENDTOOL |
Mint a presigned URL. Raises UnsupportedOperationError when the |
objectstore_put_object |
OBJECT_STORE_BACKENDTOOL |
Upload bytes to bucket/key (overwrites). |
objectstore_set_object_metadata |
OBJECT_STORE_BACKENDTOOL |
Replace the user metadata of one object. |
3 action-routed tool(s) (default) · 15 verbose 1:1 tool(s). Each is enabled unless its <DOMAIN>TOOL toggle is set false; MCP_TOOL_MODE selects the surface (condensed default · verbose 1:1 · both). Auto-generated — do not edit.
Backend × capability matrix
| Capability | filesystem | s3 / minio / r2 | gcs | azure |
|---|---|---|---|---|
| buckets (list/create/delete/exists/info) | yes | yes | yes | yes |
| objects (list/head/get/put/copy/move/delete) | yes | yes | yes | yes |
| prefix + delimiter listing, pagination | yes | yes | yes | yes |
| user metadata get/set | yes | yes | yes | yes |
| presigned URLs | no | yes | yes (needs service-account key) | yes (needs account key) |
| bucket location | no | yes | yes | no |
Installation
Pick the extra that matches what you want to run (provider extras are additive):
| Extra | Installs | Use when |
|---|---|---|
objectstore-mcp[mcp] |
Slim MCP server only (agent-utilities[mcp] — FastMCP/FastAPI) |
You only run the MCP server (smallest install / image) |
objectstore-mcp[agent] |
Full agent runtime (agent-utilities[agent,logfire] — Pydantic AI + the epistemic-graph engine) |
You run the integrated A2A agent |
objectstore-mcp[all] |
Everything (mcp + agent + s3 + gcs + azure + logfire) |
Development / both surfaces |
pip install objectstore-mcp # core: local filesystem backend only
pip install objectstore-mcp[mcp] # slim MCP server (FastMCP/FastAPI)
pip install objectstore-mcp[agent] # full A2A agent runtime + epistemic-graph engine
pip install objectstore-mcp[mcp,s3] # + boto3 (S3, MinIO, R2)
pip install objectstore-mcp[mcp,gcs] # + google-cloud-storage
pip install objectstore-mcp[mcp,azure] # + azure-storage-blob
pip install objectstore-mcp[all] # everything (MCP + agent + all providers)
Container images (:mcp vs :agent)
One multi-stage docker/Dockerfile builds two right-sized images, selected by --target:
| Image tag | Build target | Contents | Entrypoint |
|---|---|---|---|
knucklessg1/objectstore-mcp:mcp |
--target mcp |
objectstore-mcp[mcp] — slim, no engine/pydantic-ai/dspy/llama-index/tree-sitter |
objectstore-mcp |
knucklessg1/objectstore-mcp:latest |
--target agent (default) |
objectstore-mcp[agent] — full agent runtime + epistemic-graph engine |
objectstore-agent |
docker build --target mcp -t knucklessg1/objectstore-mcp:mcp docker/ # slim MCP server
docker build --target agent -t knucklessg1/objectstore-mcp:latest docker/ # full agent
Or pull a prebuilt image:
docker pull knucklessg1/objectstore-mcp:mcp # slim MCP server
docker pull knucklessg1/objectstore-mcp:latest # full agent (default)
The
:mcptag is the slim MCP-server image (built fromdocker/Dockerfile --target mcp, installingobjectstore-mcp[mcp]). The default:latesttag is the full agent image (--target agent,objectstore-mcp[agent]) which also bundles the Pydantic AI agent and the epistemic-graph engine — use it when you runobjectstore-agent(the agent), not just the MCP server.
Knowledge-graph database (epistemic-graph)
The full agent ([agent] / :latest) embeds the epistemic-graph engine (pulled in
transitively via agent-utilities[agent]). For production — or to share one knowledge graph
across multiple agents — run epistemic-graph as its own database container and point the
agent at it instead of embedding it. Deployment recipes (single-node + Raft HA), connection
config, and the full database architecture (with diagrams) are documented in the
epistemic-graph deployment guide.
The slim [mcp] server does not require the database.
Configuration (environment)
| Var | Default | Meaning |
|---|---|---|
OBJECTSTORE_STORES |
(empty) | JSON: store name → {backend, bucket?, endpoint?, profile?, region?, root?, project?, connection_string?} |
OBJECTSTORE_DEFAULT_STORE |
first configured store, else local |
Store used when a tool call omits store |
OBJECTSTORE_FS_ROOT |
~/.local/share/objectstore-mcp |
Root of the implicit local filesystem store |
OBJECTSTORE_MAX_GET_BYTES |
10485760 (10 MiB) |
Cap on objects get |
OBJECTSTORE_MAX_PUT_BYTES |
10485760 (10 MiB) |
Cap on objects put |
OBJECTSTORE_MAX_TRANSFER_BYTES |
104857600 (100 MiB) |
Cap per transfer (single or batch total) |
OBJECTSTORE_MAX_BATCH_KEYS |
100 |
Cap on batch delete / dir transfer key counts |
OBJECTSTORE_MAX_LIST_KEYS |
1000 |
Cap on one listing page |
OBJECTSTORE_ALLOW_DELETE |
true |
Object deletes (delete/delete_batch/move) |
OBJECTSTORE_ALLOW_BUCKET_DELETE |
false |
Bucket deletes (empty buckets only) |
OBJECTSTORETOOL |
True |
Register the objectstore tool set |
HOST / PORT / TRANSPORT |
0.0.0.0 / 8000 / stdio |
MCP server bind + transport (stdio, streamable-http, sse) |
AUTH_TYPE |
none |
MCP auth mode (container image) |
ENABLE_OTEL |
True |
OTEL/Langfuse telemetry export |
EUNOMIA_TYPE / EUNOMIA_POLICY_FILE |
none / mcp_policies.json |
Eunomia access-governance middleware |
DEFAULT_AGENT_NAME / AGENT_DESCRIPTION / AGENT_SYSTEM_PROMPT |
identity defaults | A2A agent server identity overrides |
MCP_URL |
(empty) | MCP endpoint the A2A agent connects to |
Provider credentials resolve through each SDK's own chain — boto3's
resolution order for S3 (env keys, ~/.aws profiles via the store's
profile, SSO, instance metadata), GOOGLE_APPLICATION_CREDENTIALS /
Application Default Credentials for GCS, and
AZURE_STORAGE_CONNECTION_STRING for Azure Blob.
Example store registry
{
"media": {"backend": "s3", "bucket": "media-prod", "profile": "prod", "region": "us-east-1"},
"minio": {"backend": "s3", "endpoint": "http://minio.arpa:9000"},
"r2": {"backend": "s3", "endpoint": "https://<account>.r2.cloudflarestorage.com"},
"reports": {"backend": "gcs", "bucket": "acme-reports"},
"archive": {"backend": "azure", "bucket": "archive"},
"scratch": {"backend": "filesystem", "root": "~/scratch-store"}
}
Usage
objectstore-mcp # stdio
objectstore-mcp --transport streamable-http --host 0.0.0.0 --port 8000
Example tool calls (any MCP client):
// Write then read a text object on the zero-infra local store
{"tool": "buckets", "arguments": {"action": "create", "params_json": "{\"bucket\": \"notes\"}"}}
{"tool": "objects", "arguments": {"action": "put", "params_json": "{\"bucket\": \"notes\", \"key\": \"todo.md\", \"text\": \"- ship it\"}"}}
{"tool": "objects", "arguments": {"action": "get", "params_json": "{\"bucket\": \"notes\", \"key\": \"todo.md\"}"}}
// Preview then execute a prefix-scoped batch delete on a named S3 store
{"tool": "objects", "arguments": {"store": "media", "action": "delete_batch", "params_json": "{\"bucket\": \"media-prod\", \"prefix\": \"tmp/\"}"}}
{"tool": "objects", "arguments": {"store": "media", "action": "delete_batch", "params_json": "{\"bucket\": \"media-prod\", \"prefix\": \"tmp/\", \"dry_run\": false}"}}
MCP config
Install the slim
[mcp]extra. The example below installsobjectstore-mcp[mcp]— the MCP-server extra that pulls only the FastMCP / FastAPI tooling (agent-utilities[mcp]). It deliberately excludes the heavy agent runtime (the epistemic-graph engine,pydantic-ai,dspy,llama-index,tree-sitter), souvx/container installs are dramatically smaller and faster. Add the provider extras you need ([mcp,s3],[mcp,gcs],[mcp,azure]); use the full[agent]extra only when you need the integrated Pydantic AI agent (see Installation).
{
"mcpServers": {
"objectstore-mcp": {
"command": "uvx",
"args": ["--from", "objectstore-mcp[mcp]", "objectstore-mcp"],
"env": {
"OBJECTSTORE_STORES": "{\"minio\": {\"backend\": \"s3\", \"endpoint\": \"http://minio.arpa:9000\"}}",
"OBJECTSTORE_DEFAULT_STORE": "local"
}
}
}
}
Run the A2A agent server against a live MCP server:
objectstore-agent --mcp-url http://localhost:8000/mcp --host 0.0.0.0 --port 9001
Additional Deployment Options
objectstore-mcp can also run as a local container (Docker / Podman / uv) or be
consumed from a remote deployment. The
Deployment guide has full, copy-paste
mcp_config.json for all four transports — stdio, streamable-http,
local container / uv, and remote URL:
- Local container / uv — launch the server from
mcp_config.jsonviauvx,docker run, orpodman run, or point at a local streamable-http container byurl. - Remote URL — connect to a server deployed behind Caddy at
http://objectstore-mcp.arpa/mcpusing the"url"key.
Docker deployment
docker compose -f docker/mcp.compose.yml up -d # MCP server only
docker compose -f docker/agent.compose.yml up -d # MCP + A2A agent
curl -s http://localhost:8000/health # {"status":"OK"}
Both services read configuration from ../.env (copy
.env.example); see docs/deployment.md.
Development
pip install -e .[test]
pytest # full suite (cloud SDKs not required)
pip install -e .[test-s3] # adds boto3+moto integration tests
pre-commit run --all-files
See docs/ for architecture, concepts, and deployment details.
License
MIT — see LICENSE.
Deploy with agent-os-genesis
This package can be provisioned for you — skill-guided — by the agent-os-genesis
universal skill (its single-package deploy mode): it picks your install method, seeds
secrets to OpenBao/Vault (or .env), trusts your enterprise CA, registers the MCP
server, and verifies it — the same machinery that stands up the whole Agent OS, narrowed
to just this package. Ask your agent to "deploy objectstore-mcp with agent-os-genesis".
| Install mode | Command |
|---|---|
| Bare-metal, prod (PyPI) | uvx objectstore-mcp · or uv tool install objectstore-mcp |
| Bare-metal, dev (editable) | uv pip install -e ".[all]" · or pip install -e ".[all]" |
| Container, prod | deploy knucklessg1/objectstore-mcp:latest via docker-compose / swarm / podman / podman-compose / kubernetes |
| Container, dev (editable) | deploy docker/compose.dev.yml (source-mounted at /src; edits live on restart) |
Secrets are read-existing + seeded via vault_sync — you are only prompted for what's missing.
Environment Variables
Package environment variables
| Variable | Example | Description |
|---|---|---|
HOST |
0.0.0.0 |
|
PORT |
8000 |
|
TRANSPORT |
stdio |
options: stdio, streamable-http, sse |
ENABLE_OTEL |
True |
|
OTEL_EXPORTER_OTLP_ENDPOINT |
http://localhost:8080/api/public/otel |
|
OTEL_EXPORTER_OTLP_PUBLIC_KEY |
pk-... |
|
OTEL_EXPORTER_OTLP_SECRET_KEY |
sk-... |
|
OTEL_EXPORTER_OTLP_PROTOCOL |
http/protobuf |
|
EUNOMIA_TYPE |
none |
options: none, embedded, remote |
EUNOMIA_POLICY_FILE |
mcp_policies.json |
|
EUNOMIA_REMOTE_URL |
http://eunomia-server:8000 |
|
OBJECTSTORE_STORES |
{"media": {"backend": "s3", "bucket": "media-prod", "profile": "prod"}, "minio": {"backend": "s3", "endpoint": "http://minio.arpa:9000"}, "reports": {"backend": "gcs", "bucket": "acme-reports"}, "archive": {"backend": "azure", "bucket": "archive"}} |
Named stores (JSON). The zero-infra "local" filesystem store always exists. |
OBJECTSTORE_DEFAULT_STORE |
local |
|
OBJECTSTORE_FS_ROOT |
~/.local/share/objectstore-mcp |
|
OBJECTSTORE_MAX_GET_BYTES |
10485760 |
Safety limits (bytes / keys) |
OBJECTSTORE_MAX_PUT_BYTES |
10485760 |
|
OBJECTSTORE_MAX_TRANSFER_BYTES |
104857600 |
|
OBJECTSTORE_MAX_BATCH_KEYS |
100 |
|
OBJECTSTORE_MAX_LIST_KEYS |
1000 |
|
OBJECTSTORE_ALLOW_DELETE |
true |
|
OBJECTSTORE_ALLOW_BUCKET_DELETE |
false |
|
AZURE_STORAGE_CONNECTION_STRING |
— | Azure is the exception — the code reads this connection string directly: |
DEFAULT_AGENT_NAME |
ObjectStore Agent |
|
AGENT_DESCRIPTION |
AI agent for object-storage operations. |
|
AGENT_SYSTEM_PROMPT |
— | |
MCP_URL |
http://localhost:8000/mcp |
|
OBJECTSTORETOOL |
True |
Inherited agent-utilities variables (apply to every connector)
| Variable | Example | Description |
|---|---|---|
MCP_TOOL_MODE |
condensed |
Tool surface: condensed |
MCP_ENABLED_TOOLS |
— | Comma-separated tool allow-list |
MCP_DISABLED_TOOLS |
— | Comma-separated tool deny-list |
MCP_ENABLED_TAGS |
— | Comma-separated tag allow-list |
MCP_DISABLED_TAGS |
— | Comma-separated tag deny-list |
MCP_CLIENT_AUTH |
— | Outbound MCP auth (oidc-client-credentials for fleet calls) |
OIDC_CLIENT_ID |
— | OIDC client id (service-account auth) |
OIDC_CLIENT_SECRET |
— | OIDC client secret (service-account auth) |
DEBUG |
False |
Verbose logging |
PYTHONUNBUFFERED |
1 |
Unbuffered stdout (recommended in containers) |
PROVIDER |
openai |
LLM provider for the agent |
MODEL_ID |
gpt-4o |
Model id for the agent |
ENABLE_WEB_UI |
True |
Serve the AG-UI web interface |
27 package + 13 inherited variable(s). Auto-generated from .env.example + the shared agent-utilities set — do not edit.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file objectstore_mcp-1.0.1.tar.gz.
File metadata
- Download URL: objectstore_mcp-1.0.1.tar.gz
- Upload date:
- Size: 51.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
afe58a9c0f024d84385781fa752d255b9af6470b8275efbec7fcc31f03f24b82
|
|
| MD5 |
5350d15ac4d947a72d909db3e83c7f0d
|
|
| BLAKE2b-256 |
a987a45d9511b9576574e6fe20e686de74da49483bd2ea37464d250db79f2ec6
|
File details
Details for the file objectstore_mcp-1.0.1-py3-none-any.whl.
File metadata
- Download URL: objectstore_mcp-1.0.1-py3-none-any.whl
- Upload date:
- Size: 41.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
28f951126ab18360bf6ab460084542cf1c3831ea398caba2a2519e26c5d8b1dd
|
|
| MD5 |
42e2536ddbb6b92b09156f582d4446ef
|
|
| BLAKE2b-256 |
41f6797945ff7fe6c01db79e579e364bbc92c1e886bbf61439216e501e868c60
|