> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect Devin to MongoDB

> Connect Devin to MongoDB Atlas with a scoped database user, an Atlas service account, mongosh and the Atlas CLI in a blueprint, or the MongoDB MCP server.

Devin can work with your MongoDB data the way an engineer with a read-only connection string would: read what collections actually contain, work out why a query is slow, rehearse a migration in a sandbox database, and open a PR. This guide sets that up with identities you create for Devin, so it never runs as one of your engineers.

<Note>
  Everything stays in your Atlas account: a database user, a service account, MongoDB tooling installed through an [environment blueprint](/onboard-devin/environment/blueprints), and optionally an MCP server. Start narrow (read-only production) and widen roles later; the roles are the boundary, and you change them in Atlas without touching Devin.
</Note>

## Two planes, two identities

| Plane | What it reaches | Devin's identity | Credential |
| - | - | - | - |
| **Data plane** | Databases, documents, indexes, `explain()` | A **database user** | Username and password in a connection string |
| **Control plane** | Clusters, Search indexes, Performance Advisor, slow-query logs, database users, access lists | An **Atlas service account** | OAuth 2.0 client ID and client secret |

A database user can't call the Atlas Administration API, and a service account can't read documents through the API. Most teams start with the data plane only and add the service account when Devin needs Performance Advisor or slow-query logs (dedicated clusters, M10 and up). Two caveats:

* A service account that can create database users (`GROUP_OWNER`, `GROUP_DATABASE_ACCESS_ADMIN`) can mint itself a data-plane identity. The MongoDB MCP server does exactly that when asked to connect to a cluster (Option B).
* Slow-query data includes literal query values.

## Choose how Devin connects

All three paths use the same network access (Step 1) and identities (Step 2); they differ in what Devin gets to hold.

| Path | Best for | Setup |
| - | - | - |
| [**Option A: CLI in a blueprint**](#option-a-cli-in-a-blueprint) | Work Devin runs and repeats in a repo: migrations, backfills, seed data, tests against real-shaped data | Four Devin Secrets and a short blueprint. Start here. |
| [**Option B: MongoDB MCP server**](#option-b-mongodb-mcp-server) | Schema discovery and query/index analysis as tools, with `--readOnly` and `--indexCheck` guardrails | A custom STDIO MCP server using the same credentials. Adds to Option A. |
| [**Option C: MongoDB Atlas plugin**](#option-c-mongodb-atlas-plugin) | Atlas questions and project-wide reads, without storing a MongoDB credential in the session | Marketplace plugin, OAuth login as a dedicated Atlas user; org access mode set to **Read**. |

## Why connect Devin to MongoDB?

* **The schema lives in the documents.** MongoDB has no `information_schema`, and Mongoose or Prisma models drift from what is stored. Devin samples the live collections and works from the real shape.
* **The slow-query loop closes in one session.** Devin reads Performance Advisor and the slow-query log, runs `explain()` on the real collection, finds the code that issues the query, and opens a PR with the fix and the proposed index.
* **The database user's roles decide what Devin can touch.** Start read-only on production with a `devin_dev` sandbox for writes, and every action lands in Atlas logs under Devin's own identity.

## Prerequisites

**Atlas**

* A project with a cluster.
* `Organization Owner` to create a service account; `Project Owner` for the database user and access lists.

**Devin**

* Permission to edit the [environment blueprint](/onboard-devin/environment/blueprints) and add [Secrets](/product-guides/secrets).
* For the MCP paths, **Manage MCP Servers**.

**Network**

* Devin's IPs on the project IP access list (Step 1).
* If you use a Devin [network policy](/product-guides/security-profiles), allow `*.mongodb.net` and `cloud.mongodb.com`, plus the hosts the blueprint installs from: `pgp.mongodb.com` and `repo.mongodb.org` (Option A), `registry.npmjs.org` and `nodejs.org` (Option B). The driver connects on port 27017, not 443; policy entries are hostnames or CIDRs, so there's no port to set. Snapshot builds run under the same policy.

## Step 1: Open network access

Atlas refuses connections from IPs not on the project IP access list. Add the IPs listed under [IP allowlisting](/admin/common-issues#ip-allowlisting), not from memory. Dedicated tenants have their own egress; confirm with your account team.

```bash theme={null}
atlas accessLists create <ip> --type ipAddress --comment "Devin" --projectId <project-id>
atlas accessLists create <cidr> --type cidrBlock --comment "Devin" --projectId <project-id>
```

The list contains both single addresses and a CIDR range; use `--type ipAddress` for single addresses and `--type cidrBlock` for the range.

If your organization requires an API access list on service accounts, add the same IPs on the service account's page in Atlas. Calls from an unlisted IP fail with `403`.

## Step 2: Create Devin's identities

### Database user

Read on production databases, read/write in a sandbox, scoped to named clusters:

```bash theme={null}
atlas dbusers create \
  --username devin-sessions \
  --password "<generated-password>" \
  --role read@analytics,read@billing,readWrite@devin_dev \
  --scope <cluster-name> \
  --projectId <project-id>
```

Without `--scope` the user can reach every cluster in the project. Use a [custom database role](https://www.mongodb.com/docs/atlas/security-add-mongodb-roles/) when built-in roles can't express the boundary. Generate the password with a password manager and don't leave it in shell history. Copy this user's connection string; don't give Devin the cluster admin user.

### Service account (only if Devin needs the control plane)

In Atlas, **Identity & Access > Applications** at the organization level. Start read-only, and pick the shortest client-secret lifetime your rotation allows.

| | Roles | Why |
| - | - | - |
| **Grant** | `ORG_MEMBER` on the organization; `GROUP_READ_ONLY` and `GROUP_DATA_ACCESS_READ_ONLY` on each project | Read-only baseline |
| **Add only if needed** | `GROUP_SEARCH_INDEX_EDITOR` | Devin manages Search indexes |
| **Never** | `GROUP_OWNER`, `GROUP_DATABASE_ACCESS_ADMIN` | Either lets Devin widen its own access |

<Warning>
  The **Never** row matters most with Option B. If the service account can create database users, the MCP server's `atlas-connect-cluster` tool creates a temporary user on the whole cluster (`readAnyDatabase`, or `readWriteAnyDatabase` without `--readOnly`), bypassing the per-database roles on `devin-sessions`. That user lives for 4 hours unless the MCP disconnect tool deletes it first.
</Warning>

## Step 3: Connect Devin

### Option A: CLI in a blueprint

#### 1. Add Devin Secrets

On the blueprint's **Secrets** tab:

| Secret | Value |
| - | - |
| `MONGODB_URI` | The `devin-sessions` connection string, e.g. `mongodb+srv://devin-sessions:<password>@cluster0.abcde.mongodb.net/`. Percent-encode the password. |
| `MONGODB_ATLAS_CLIENT_ID` | Service account client ID (`mdb_sa_id_...`), if using the control plane |
| `MONGODB_ATLAS_CLIENT_SECRET` | Service account client secret |
| `MONGODB_ATLAS_PROJECT_ID` | Default project ID |

Secrets are injected per session, so rotating a value needs no rebuild. The Atlas CLI reads the client ID and secret from these environment variables, so there is no `atlas auth login`. On first use it caches an access token in `~/.config/atlascli/config.toml`; that's fine inside a session, but never create that file in `initialize`.

#### 2. Add the blueprint

```yaml theme={null}
initialize:
  - name: Install the Atlas CLI and mongosh
    run: |
      curl -fsSL https://pgp.mongodb.com/server-8.0.asc \
        | sudo gpg --batch --yes -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor
      echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/8.0 multiverse" \
        | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
      sudo apt-get update
      sudo apt-get install -y mongodb-atlas-cli mongodb-mongosh
      atlas --version && mongosh --version

knowledge:
  - name: mongodb-access
    contents: |
      Connect to MongoDB with `mongosh "$MONGODB_URI"`; the URI is a Devin Secret. The Atlas CLI
      authenticates as a service account from MONGODB_ATLAS_CLIENT_ID and MONGODB_ATLAS_CLIENT_SECRET,
      with MONGODB_ATLAS_PROJECT_ID as the default project. Do not run `atlas auth login`, do not ask
      for a username, password, or API key, and never write the connection string into a file, script,
      log, or PR. Production databases are read-only; write only to the devin_dev database. Ship
      schema, index, and migration changes through a pull request.
```

Swap `jammy` if your image isn't Ubuntu 22.04.

The `knowledge` block matters more than the install: without it, sessions run `atlas auth login` (a browser flow nobody can finish) or ask for a connection string that is already in the environment.

<Warning>
  Don't write credentials to disk in `initialize`. A `~/.mongoshrc.js`, `~/.config/atlascli/config.toml`, or an exported URI in `~/.bashrc` ends up in the snapshot, shared by every future session.
</Warning>

#### 3. Build the snapshot

Save the blueprint, wait for **Success**, then start a new session. Open sessions keep the old snapshot.

### Option B: MongoDB MCP server

The official [`mongodb-mcp-server`](https://github.com/mongodb-js/mongodb-mcp-server) runs as a local process inside the session and uses the Step 2 identities. To get its guardrails, add it as a custom MCP server (**Customize > MCPs > Add MCP > Add custom MCP**, transport **STDIO**) rather than through the marketplace `mongodb` plugin, whose manifest doesn't expose `--readOnly` or `--indexCheck`.

| Field | Value |
| - | - |
| Command | `npx` |
| Arguments | `-y mongodb-mcp-server@<version> --readOnly --indexCheck` |
| Environment | `MDB_MCP_CONNECTION_STRING` (same value as `MONGODB_URI`); optionally `MDB_MCP_API_CLIENT_ID` and `MDB_MCP_API_CLIENT_SECRET` for Atlas tools |

Pin `<version>` to a release you've tested; `npx` fetches the package on every session start. With the read-only service account from Step 2, `atlas-connect-cluster` returns `401`; Devin reaches data through the `preconfigured` connection from `MDB_MCP_CONNECTION_STRING`, which is the intended path.

* `--readOnly` skips registering create, update, and delete tools, and rejects aggregations containing `$out` or `$merge`. Without it, those aggregations run after a confirmation prompt, or unconfirmed if the MCP client doesn't support prompts. Use it for anything pointed at production.
* `--indexCheck` rejects queries whose plan is a collection scan. It's a performance guardrail; if `explain` itself fails, the query runs anyway.

The server requires Node `^20.19.0 || ^22.13.0 || >=24.0.0`. Check `node --version` in a session; if it's older, or `npx` isn't on the path the MCP process sees, add Node to the blueprint:

```yaml theme={null}
initialize:
  - name: Install Node.js for the MongoDB MCP server
    uses: github.com/actions/setup-node@v4
    with:
      node-version: "22"
```

<Warning>
  Keep the read-only database user even with `--readOnly`. Devin can also run `mongosh "$MONGODB_URI"` with the same user, so the user's roles are the boundary that actually holds.
</Warning>

### Option C: MongoDB Atlas plugin

The **MongoDB Atlas** [plugin](/product-guides/plugins) connects Devin to MongoDB's hosted MCP server (`mcp.mongodb.com`) and installs MongoDB's agent skills. Devin acts with the Atlas roles of the user who signs in, capped by the organization's AI client access mode.

1. An Organization Owner enables [AI client access](https://www.mongodb.com/docs/mcp-server/remote-mcp/manage-ai-client-access/) (**Organization Settings > App Connections**) and sets the access mode to **Read**, so write tools aren't registered. The setting applies to every AI client in the organization, not only Devin.
2. Create a dedicated Atlas user for Devin with `GROUP_READ_ONLY` and `GROUP_DATA_ACCESS_READ_ONLY`, only in projects it may read. `GROUP_DATA_ACCESS_READ_ONLY` reads documents in every database in the project, so this is wider than the `devin-sessions` user.
3. Install the plugin and complete the OAuth login once in **Customize > MCPs**, signed in as that user, not as yourself.
4. [Pin the plugin to a commit](/product-guides/plugins#pinning-a-plugin) once it works.

<Note>
  Traffic comes from MongoDB's and Devin's hosted infrastructure, not the session, so Step 1's IP lists and your network policy don't apply. Access ends after 7 days of inactivity or 30 days from sign-in, whichever comes first; sign in again. Revoking access doesn't delete database users or other artifacts the client created, so audit them.
</Note>

### Rebuilds and version pinning

The blueprint installs whatever `apt` resolves at build time, and Option B's `npx` fetches `mongodb-mcp-server` on every session start. Pin both (`mongodb-atlas-cli=<version>`, `mongodb-mongosh=<version>`, `mongodb-mcp-server@<version>`) once they work, and bump them deliberately. Rotating a secret needs no rebuild; changing an installed tool does.

## Step 4: Set permissions

Authentication says who Devin is; database and Atlas roles say what it can touch. MCP flags and knowledge instructions are conveniences on top, not the boundary.

| Profile | Typical work | Database user roles | Service account roles |
| - | - | - | - |
| **Explore** (start here) | Document the schema, explain a slow query, propose an index in a PR | `read` on production databases | `GROUP_READ_ONLY` + `GROUP_DATA_ACCESS_READ_ONLY` |
| **Build** | Write and test migrations, pipelines, and seed data against real-shaped data | Explore, plus `readWrite@devin_dev` | Same as Explore |
| **Operate** | Create indexes or Atlas Search indexes on named collections | Explore, plus a custom role granting `createIndex` on those collections | Explore, plus `GROUP_SEARCH_INDEX_EDITOR` |

For Explore, suggested indexes need only `GROUP_READ_ONLY` (query values come back masked). The slow-query list, sample query values, and log downloads also need `GROUP_DATA_ACCESS_READ_ONLY`; the `GROUP_DATA_ACCESS_READ_WRITE` the Atlas CLI help asks for isn't needed. With `GROUP_READ_ONLY` alone, the MCP `atlas-get-performance-advisor` tool reports "No slow query logs found" rather than the `401`, so an empty result may be a role problem.

<Tip>
  Code still ships through pull requests. Devin reads production to understand the problem and proves the fix in `devin_dev`; the migration or index lands through your normal review.
</Tip>

## Step 5: Verify

Start a new session and ask Devin to run:

**Connectivity.** Which user, which roles, and (if configured) whether the Atlas CLI authenticates:

```bash theme={null}
mongosh "$MONGODB_URI" --quiet --eval 'JSON.stringify(db.runCommand({connectionStatus: 1}), null, 2)'
atlas clusters list --projectId "$MONGODB_ATLAS_PROJECT_ID"
```

**Boundary.** The first insert should fail (`not authorized on <prod-db> to execute command` on dedicated clusters, `user is not allowed to do action [insert] on [<prod-db>.devin_probe]` on M0/Flex); the second should succeed:

```bash theme={null}
mongosh "$MONGODB_URI" --quiet --eval 'db.getSiblingDB("<prod-db>").devin_probe.insertOne({probe: 1})'
mongosh "$MONGODB_URI" --quiet --eval 'db.getSiblingDB("devin_dev").devin_probe.insertOne({probe: 1}); db.getSiblingDB("devin_dev").devin_probe.drop()'
```

Check the roles in `connectionStatus` match the profile you granted; an open connection alone proves little. For the MCP server, ask Devin to list databases through the MCP tools (it uses the `preconfigured` connection), then to insert a document: with `--readOnly` there is no `insert-many` tool, and an aggregation with `$out` is refused.

## Troubleshooting

| Symptom | Applies to | Cause and fix |
| - | - | - |
| Connection times out, or the error mentions the IP access list | A, B | Devin's IPs are missing from the project IP access list (the most common failure), or your network policy blocks `*.mongodb.net` on TCP 27017. |
| `querySrv ENOTFOUND _mongodb._tcp.<host>` | A, B | DNS blocked or hostname wrong. Allow `*.mongodb.net` in the network policy. |
| `Authentication failed` or `bad auth : authentication failed` | A, B | Wrong password or wrong `authSource`. |
| `MongoParseError: Protocol and host list are required` | A, B | The URI password contains `@`, `/`, or `+` and isn't percent-encoded. Encode it; this isn't an auth error. |
| `not authorized on <db> to execute command` or `user is not allowed to do action` | A, B | Signed in but not permitted. Expected when Devin writes to production; otherwise widen the user's roles. |
| Atlas CLI says `unauthorized` or suggests `atlas auth login` | A, B | Service-account secrets missing, wrong, or expired, or the service account's role doesn't allow that action (the MCP server reports this as invalid credentials too). Check the role before rotating secrets. Don't run `atlas auth login`. |
| Atlas CLI returns `403` after authenticating | A, B | The service account's API access list is missing Devin's IPs (Step 1). |
| Devin runs `atlas auth login` or asks for a connection string | A | The `knowledge` block is missing, or the secrets aren't on the blueprint the session uses. |
| Blueprint build fails on `apt-get`, or the MCP server won't start | A, B | Network policy is missing `pgp.mongodb.com`, `repo.mongodb.org`, `registry.npmjs.org`, or `nodejs.org`; or Node is older than 20.19 (run `node --version`). |
| MCP rejects a query for not using an index | B | `--indexCheck` is doing its job. Add the index in a PR, or run the query with `mongosh` against `devin_dev`. Queries that need a collation index are always rejected: the MCP `find` tool has no collation argument. |
| Atlas tools missing or write tools appear | C | AI client access is disabled, or the access mode is **Read and write**, or the signed-in Atlas user has broader roles than intended. Check the mode under **App Connections** and who completed the OAuth login. |
| Credentials work in one session and not the next | A | A stale config file from an earlier `initialize` is in the snapshot. Remove it from the blueprint and rebuild. |

## Limitations

**Stored credentials are required.** Devin's short-lived [OIDC token](/product-guides/oidc) can't be used with MongoDB today: the Administration API accepts only service-account secrets or API keys. Atlas [Workload Identity Federation](https://www.mongodb.com/docs/atlas/workload-oidc/) covers the data plane on dedicated clusters, but needs a driver-level token callback and hasn't been tested with Devin's issuer. If you want to try it, tell your account team.

**Self-hosted MongoDB.** The data-plane steps (database user, `MONGODB_URI`, `mongosh`, MCP server) apply unchanged. There is no Atlas service account or IP access list; network access goes through your [VPN](/onboard-devin/vpn) or your own allowlist.

## Support

For the Atlas side, see the [Atlas security docs](https://www.mongodb.com/docs/atlas/setup-cluster-security/) and [MongoDB MCP Server docs](https://www.mongodb.com/docs/mcp-server/). For the Devin side, contact [support@cognition.ai](mailto:support@cognition.ai) or your account team.
