MCP Server
Dynoxide includes a built-in MCP (Model Context Protocol) server with 35 tools. Your coding agent can create tables, query data, manage snapshots, and more - all without leaving the conversation.
Setup for Claude Code
Add this to your MCP configuration:
{
"mcpServers": {
"dynoxide": {
"command": "dynoxide",
"args": ["mcp", "--db-path", "dev.db"]
}
}
}
The agent now has full DynamoDB access through Dynoxide.
Setup for Cursor
Same config format. Add it to your Cursor MCP settings with the dynoxide mcp command.
Streamable HTTP transport
If you prefer HTTP over stdio:
dynoxide mcp --http --port 19280
As of v0.10.0 the HTTP transport requires a bearer token on every request - the stdio setup above is unaffected. On a loopback bind, Dynoxide generates a token the first time you run it, saves it to a per-user config file (~/.config/dynoxide/mcp-token on Linux, ~/Library/Application Support/dynoxide/mcp-token on macOS), and prints a ready-to-paste client snippet. Later runs reuse it silently.
Point your agent at the /mcp endpoint and send the token in an Authorization header:
{
"mcpServers": {
"dynoxide": {
"type": "http",
"url": "http://127.0.0.1:19280/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
Upgrading from before v0.10.0? Existing HTTP clients break until you add that Authorization header. The stdio transport needs no changes.
Binding beyond loopback
The server binds to 127.0.0.1 by default. To reach it from elsewhere - another container, say - bind a wider host and set a token explicitly. A non-loopback bind won't start without one:
dynoxide mcp --http --host 0.0.0.0 --token "$DYNOXIDE_MCP_AUTH_TOKEN"
| Flag | What it does |
|---|---|
--token / DYNOXIDE_MCP_AUTH_TOKEN |
Use a fixed token instead of the persisted one. Required for any non-loopback bind. |
--host |
Bind beyond 127.0.0.1. |
--allowed-host |
Accept an extra Host header by name (repeatable) - needed to reach it by hostname. |
--no-auth |
Disable auth. Loopback binds only. |
Prefer the environment variable or the persisted file over --token - flag values leak into shell history and ps. On the serve subcommand these flags are prefixed (--mcp-host, --mcp-token, and so on) because serve already owns --host/--port for the DynamoDB server.
The transport also checks the Host and Origin headers against an allowlist, closing the DNS-rebinding and cross-origin gaps a loopback server can otherwise expose. The full threat model is in SECURITY.md.
Available tools
The 35 tools are grouped by category:
| Category | Tools | What they do |
|---|---|---|
| Tables | 5 | Create, describe, list, update, delete tables |
| Items | 4 | Get, put, update, delete individual items |
| Batch | 3 | Batch get, batch write, bulk put (up to 10K items) |
| Query & Scan | 2 | Query with key conditions and filters, full table scans |
| Transactions | 2 | Atomic multi-item reads and writes |
| PartiQL | 3 | SQL-like queries via ExecuteStatement |
| TTL | 3 | Manage time-to-live settings and sweep expired items |
| Streams | 4 | List, describe, and read DynamoDB Streams |
| Snapshots | 4 | Point-in-time backups and rollback |
| Tags | 3 | Tag and untag resources |
| Vector search | 1 | Nearest-neighbour search over a vector index |
| Info | 1 | Database size, table count, storage mode, and any notices the import raised |
Table configuration
As of 0.12.0 the table tools accept the billing and capacity settings that HTTP and wasm could already set:
create_tabletakesbilling_mode,provisioned_throughputandon_demand_throughput. Before 0.12.0 it took none of them, so every table created over MCP came outPROVISIONEDwith default throughput regardless of what you asked for.update_tabletakesbilling_mode,provisioned_throughput,table_classandon_demand_throughput. The handler previously hardcoded the first three to none, so the engine saw an empty update and a table could not be switched betweenPROVISIONEDandPAY_PER_REQUESTover MCP at all.describe_tablenow reportsbilling_mode,table_classand the capacity settings for whichever mode the table is in, in its default view. They used to appear only underraw: true.
An invalid billing mode is rejected with DynamoDB's own enum validation message, on every surface rather than just over HTTP.
Capacity and condition failures
From 1.3.0, return_consumed_capacity accepts TOTAL, INDEXES or NONE on the item tools, query, scan, search_vectors, batch get/write, both transaction tools and all three PartiQL tools. TOTAL returns the DynamoDB ConsumedCapacity block; INDEXES includes the table and index breakdowns. Other values are refused. Reporting capacity doesn't enable throughput enforcement or AWS load-based throttling.
execute_partiql also takes return_values_on_condition_check_failure, with ALL_OLD or NONE. With ALL_OLD, a failed condition returns the item it was evaluated against on the tool error. Item write tools return it too; older builds accepted that option but omitted the item. A missing item returns no failure item. See PartiQL condition failures for batch and transaction statement options.
describe_table reports live item counts and size_bytes. Its raw DynamoDB view includes table and index counts and sizes. See capacity and statistics for the vector sizing rules and the difference from AWS's periodically refreshed statistics.
Snapshots
The snapshot tools create, list, restore and delete local snapshots. From 1.3.0, restoring an older snapshot migrates a private copy before it replaces the database. If the restore fails, the database is left as it was. A snapshot with a newer, unsupported schema is refused.
After a restore, cached transaction retries and vector index creation windows are cleared, because they describe data that has been replaced. Backup and restore retry a busy database for five seconds (plus at most one SQLite busy wait), and stop after 50 restarts if another connection keeps changing the data being copied.
If a persistent file has a multi-attribute GSI or a vector index and you may return to 1.2.x, keep a copy before upgrading to 1.3.0. Files without either still read correctly in 1.2.x. See database upgrades.
TTL sweeps
From 1.3.0, sweep_ttl releases the database lock between pages of 25 items so waiting reads and writes can proceed. It reads no more rows from a table than that table held when the sweep reached it; items written during a sweep may remain until the next one.
Safety controls
For read-only access (good for pointing at production snapshots):
dynoxide mcp --read-only --db-path prod-snapshot.db
To cap response sizes:
dynoxide mcp --max-items 100 --max-size-bytes 65536
From 1.4.0, --max-items 0 is refused at startup, and the scan and query tools refuse a limit of 0, as DynamoDB refuses a Limit of 0.
--log quiet suppresses informational startup and shutdown output on either transport. Warnings, errors and first-run token instructions still print.
Persistent storage and encryption work here as they do on serve, via --db-path and --encryption-key-file. The CLI reference has every flag on the subcommand.
Data model context
If you're using a single-table design with OneTable, you can pass the schema so the agent understands your entity model:
dynoxide mcp --data-model schema.json
The agent will see entity names, key templates, and GSI mappings in its instructions. This is context only - Dynoxide doesn't validate writes against the schema.
--data-model-summary-limit caps how many entities appear in that summary (20 by default; 0 suppresses it). On a large single-table design the full entity list can crowd out the rest of the agent's context, so trimming it is worth doing.