{"id":"f501f54d-859d-4173-a119-f7c8477a393b","slug":"mcpg-plugin-storage-builtin","kind":"mcp","name":"mcpg-plugin-storage-builtin","summary":"Built-in content-store plugins (`in_process` and `file_system`) for the MCPG gateway.","owner":"mcpg-dev","repoUrl":"https://github.com/mcpg-dev/mcpg-plugin-storage-builtin","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":0,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-08-12T04:37:43.000Z","addedAt":"2026-10-21T06:34:58.193Z","logoUrl":"https://avatars.githubusercontent.com/u/263276544?v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["files-documents","memory-knowledge"],"tags":["mcpg","rust"],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-22T16:15:03.883Z","sample":false,"url":"https://conduits.dev/tools/mcpg-plugin-storage-builtin","language":"Rust","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# mcpg-plugin-storage-builtin\n\n> The two content-store backends every MCPG gateway build ships: an in-memory LRU store and an on-disk store.\n\nMCPG gateways hand large tool results, generated images, audio, and other blobs\nto a **content store** instead of inlining them in an MCP response, then serve\nthem back through `mcpg-resource://` URIs. This crate provides the two stores\nthat are always present — `in_process` and `file_system` — as\n`ContentStorePlugin` factories, so operators always have somewhere for bytes to\nlive without installing anything. It is deliberately dependency-free at the\nstorage layer: it holds no client libraries and reaches no network. Backends\nthat talk to an object store, such as `mcpg-plugin-storage-s3`, are separate\ncrates that implement the same trait.\n\n## What's here\n- `InProcessStoragePlugin` — factory for `kind = \"in_process\"`, building an\n  `InProcessContentStore`: an LRU map behind a lock, capped by `max_bytes`,\n  expiring lazily on read and in a periodic sweep. Volatile; contents are lost\n  when the process exits.\n- `FileSystemStoragePlugin` — factory for `kind = \"file_system\"`, building a\n  `FileSystemContentStore` rooted at an operator path. Blobs are written under\n  a BLAKE3-derived path with a JSON metadata sidecar and an alias record,\n  each written to a temporary file and renamed into place so a crash never\n  leaves a half-written object. An in-memory index is rebuilt by walking the\n  metadata tree at startup and drives lookup, `stats()`, and LRU eviction once\n  `max_bytes` is exceeded.\n- Both implement `mcpg_backend_llm_shared::ContentStorePlugin` — `manifest()`,\n  `kind()`, and an async `build_profile(profile_name, spec)` that validates the\n  operator's `config:` object and returns an `Arc<dyn ContentStore>`.\n- Neither store vends presigned URLs; `signed_url` returns\n  `ContentStoreError::SignedUrlNotSupported`.\n\nThis crate is not a cdylib plugin. It has no `plugin.yaml`, exports no\n`mcpg_plugin_register` symbol, and is never signed, packed, or pulled from a\nregistry — it is linked into the gateway binary directly.\n\n## Used by\n- The MCPG gateway, which registers both factories unconditionally while\n  building its content-store registry and dispatches `storage.providers[]`\n  entries to them by `kind`.\n- Anything embedding the MCPG content-store traits that wants a working default\n  store without adding an object-storage dependency.\n\n## Usage\n\n### As a Rust dependency\n\n```toml\n[dependencies]\nmcpg-plugin-storage-builtin = \"<version>\"\nmcpg-backend-llm-shared = \"<version>\"\nserde_json = \"1\"\n```\n\n```rust\nuse std::sync::Arc;\n\nuse mcpg_backend_llm_shared::{ContentStore, ContentStoreError, ContentStorePlugin};\nuse mcpg_plugin_storage_builtin::{FileSystemStoragePlugin, InProcessStoragePlugin};\n\nasync fn open_stores() -> Result<Vec<Arc<dyn ContentStore>>, ContentStoreError> {\n    let scratch: Arc<dyn ContentStorePlugin> = Arc::new(InProcessStoragePlugin::new());\n    let durable: Arc<dyn ContentStorePlugin> = Arc::new(FileSystemStoragePlugin::new());\n\n    Ok(vec![\n        scratch\n            .build_profile(\"scratch\", &serde_json::json!({ \"max_bytes\": 64 * 1024 * 1024 }))\n            .await?,\n        durable\n            .build_profile(\n                \"media\",\n                &serde_json::json!({ \"root\": \"/var/lib/mcpg/content\" }),\n            )\n            .await?,\n    ])\n}\n```\n\n### Operator configuration\n\nBoth stores are selected from the gateway's dedicated top-level `storage:`\nblock, by `kind`. There is no `plugins:` entry to add — the factories are\nalready registered. Bindings route to a provider through their own\n`content_storage:` field, and `storage.default` names the provider used by\nbindings that do not.\n\n```yaml\nstorage:\n  default: scratch\n  providers:\n    - id: scratch\n      kind: in_process\n      config:\n        max_bytes: 268435456          # 256 MiB\n    - id: media\n      kind: file_system\n      config:\n        root: /var/lib/mcpg/content\n        max_bytes: 8589934592         # 8 GiB\n```\n\n`in_process` configuration:\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `max_bytes` | integer | `268435456` (256 MiB) | Aggregate byte cap; `0` means unlimited, with TTL expiry still applied. |\n\n`file_system` configuration:\n\n| Field | Type | Default | Description |\n|---|---|---|---|\n| `root` | path | *(required)* | Directory blobs are written under. Created if missing; must be writable. |\n| `max_bytes` | integer | `8589934592` (8 GiB) | Aggregate byte cap; `0` means unlimited. |\n\nBoth reject unknown fields, and an invalid spec aborts gateway boot rather than\nstarting with an unusable store. When `storage.providers` is empty and no\nbinding names a provider, the gateway creates a single `in_process` provider\nwith the id `default` and the standard 256 MiB cap.\n\nChoose `file_system` when content must survive a restart. It is bound to one\nhost's disk, so a multi-replica deployment needs a shared backend such as\n`mcpg-plugin-storage-s3` instead.\n\n## Build / test\n```bash\ncargo build -p mcpg-plugin-storage-builtin\ncargo test  -p mcpg-plugin-storage-builtin\n```\n\n## See also\n- Full gateway config schema, including the `storage:` block: <https://mcpg.dev/docs/reference/configuration>\n- Plugin classes and the plugin ABI: <https://mcpg.dev/docs/plugins/plugins-and-protocol>\n- `mcpg-plugin-storage-s3` — the S3-compatible store for shared, cross-replica\n  content.\n"}