Intermediate7 min read

DynamoDB MCP for Cursor

Cursor can query your DynamoDB tables from the editor once you give it an server to call.

Below: the mcp.json config, the project-vs-global choice, enabling and approving the server, and how to avoid AWS access keys in a config file in your repo.

Point Cursor at DynoTable running as a local MCP server and there are no keys in mcp.json at all: DynoTable never passes them to Cursor, and they stay in your AWS config files. Not installing DynoTable? See the read-only profile setup. The DynamoDB MCP server overview compares all the options.

What Cursor can do once it's connected

Most bad DynamoDB code an editor agent writes starts with an invented key schema. With the server connected, Cursor reads your real one (tables, key schema, indexes, the attributes that appear in items) before it writes a function.

Through DynoTable it can also run PartiQL SELECT, GetItem and item counts against the live table, aggregate through Workbench SQL, and stage edits in a reviewable staging area.

There is no raw Query or Scan tool, and PartiQL results come back capped to a small sample.

Before you start

  1. Install DynoTable: download it and add the AWS profile you want Cursor to see.
  2. Expose that profile: its MCP section → Expose via MCP. The connection is bound to one profile's credentials and region; with nothing exposed, every connection is refused.
  3. Turn the MCP server on in Settings → MCP. Off by default, bound to 127.0.0.1 only.

Copy the endpoint (with the real port) from the profile's MCP section.

Add the server to mcp.json

Cursor reads MCP servers from two files:

  • .cursor/mcp.json in the project: scoped to that repo, and committed unless you ignore it.
  • ~/.cursor/mcp.json in your home directory: global, every project, never committed.

For a 127.0.0.1 server, use the global file. DynoTable's snippet names ~/.cursor/mcp.json, so paste it there:

{
  "mcpServers": {
    "dynotable-prod": {
      "url": "http://127.0.0.1:<port>/mcp?profile=prod"
    }
  }
}

The url key (rather than command) selects the HTTP transport, and DynoTable speaks streamable HTTP. ?profile=prod pre-selects the profile in DynoTable's approval prompt; you still approve the connection in the app.

Servers that need a token

Cursor resolves ${env:NAME} in command, args, env, url and headers, so a server that needs a token can read it from your environment instead of the file:

{
  "mcpServers": {
    "some-remote-server": {
      "url": "https://example.com/mcp",
      "headers": {"Authorization": "Bearer ${env:MY_SERVICE_TOKEN}"}
    }
  }
}

Use that for any MCP server whose config would otherwise contain a secret. A raw AWS_SECRET_ACCESS_KEY pasted into a project mcp.json ends up in your git history.

Enable it and approve the connection

Enable the server from Customize in Cursor's sidebar (older builds: Cursor Settings → MCP or Tools & Integrations).

DynoTable's endpoint is OAuth-protected, so Cursor opens a browser login on first connect and DynoTable shows a consent prompt naming the client.

Grant Read only to start; the overview's scopes section covers Read & stage and Full access.

A grant can't be narrowed in place: Revoke in the MCP pane blocks the client's next request, and a different scope means revoking and approving the reconnect.

Without an active plan or trial, DynoTable clamps every connection to Read only and hides the Workbench SQL tool.

In Cursor's default Auto-review run mode, a classifier approves MCP tool calls, not you. For this server, use the Allowlist run mode and leave its tools off the allowlist, so each call asks you first: Read only scope stops writes, not a full-table scan, and the approval shows you each statement. The cost section covers the other controls.

Verify it actually loaded

Its tools appear under Available Tools in chat. If the server fails, open the Output panel (Cmd+Shift+U) and pick MCP Logs for connection and authentication errors. Then ask the agent something only your data can answer: "list the tables in this profile and their key schemas."

If it answers from the table rather than hedging, the tools are live.

Why not put AWS keys in mcp.json?

Because that file is read by an agent that also reads untrusted content. A tool result (a row, a document, a fetched page) can carry instructions. That's , and against write-capable credentials it can act on your tables.

A project mcp.json also gets committed, and keys in that file are keys in your git history.

Through DynoTable the file holds a loopback URL, the agent gets no key over MCP, and there is no write tool, so at Read & stage a steered agent can only stage a diff you read. The keys still sit in ~/.aws, where Cursor's agent terminal could read them.

Set "readBoundary": "workspace" in ~/.cursor/sandbox.json (Cursor 3.23 or later). Sandboxed terminal commands then can't read outside the workspace, and the agent asks before reading files there. The limit covers sandboxed commands only. In Cursor's default Auto-review run mode, a classifier, not you, approves a rerun outside the sandbox, so use the Allowlist run mode (Settings → Agents → Approvals & Execution) to have those come to you (run modes). The overview covers the full model.

Without DynoTable: a read-only profile

For another DynamoDB MCP server, use a read-only AWS profile instead of keys: a role with the managed AmazonDynamoDBReadOnlyAccess policy (the overview shows the profile block). Pass its name in the server's env:

{
  "mcpServers": {
    "dynamodb-ro": {
      "command": "<server command>",
      "args": ["<server args>"],
      "env": {"AWS_PROFILE": "dynamodb-readonly"}
    }
  }
}

The file holds a profile name, not a secret, and any write the agent attempts fails with an access-denied error.

Troubleshooting

The server doesn't appear. Wrong file or invalid JSON. Validate the JSON and confirm you edited ~/.cursor/mcp.json.

It fails to connect, or the login ends in access denied. Check MCP Logs in the Output panel. Then: DynoTable isn't running, the MCP server is off, no profile is exposed, or the port changed. Re-copy the endpoint from the profile's MCP section.

It can't stage. The connection was approved at Read only, or your plan lapsed and DynoTable clamped it to Read only.

No Workbench SQL or aggregates. Your plan or trial lapsed. A Read only grant keeps Workbench SQL.

Tools listed but never used. The request didn't need them. Ask something table-specific.

Edits changed nothing in DynamoDB. They're staged. Open DynoTable's staging area and commit.

FAQ

How do I connect Cursor to DynamoDB?

In DynoTable, expose the profile you want (Expose via MCP) and turn the server on in Settings → MCP. Add the endpoint to ~/.cursor/mcp.json under mcpServers as a url.

Enable the server in Cursor, log in when prompted, and approve the connection in DynoTable.

Where does Cursor store MCP server config?

In .cursor/mcp.json inside a project, or ~/.cursor/mcp.json in your home directory for global servers. Use the global file for a loopback server, because the project file is committed and the port is per-machine.

Do I need to put AWS credentials in mcp.json?

No. With DynoTable the config holds only a loopback URL. With another server, pass a read-only profile name through env (AWS_PROFILE), and reference any token as ${env:NAME} so the value stays in your environment.

Why does my MCP server show no DynamoDB tools?

If the login ended in access denied, no profile is exposed in DynoTable or the server is off: turn on Expose via MCP and reconnect.

If tools load but staging is missing, the connection is at Read only, by your grant or because your plan lapsed. If Workbench SQL is missing, your plan or trial lapsed.

Can Cursor write to my DynamoDB tables?

Not directly through DynoTable: it can stage a change, which is written only when you commit it in the app. A server holding write-capable AWS credentials can write directly; a read-only IAM profile makes that write fail. The overview compares the servers.

Product names are trademarks of their respective owners; referenced for identification only. Cursor config format verified 2026-10-09.

By Dmitriy · Updated