---
title: Envlock MCP Server
description: An MCP server that exposes Envlock tools to AI assistants. Inspect contracts, validate environments, render .env.example files, diff env files, and explain issues.
url: https://pr-1-ff84656b4b8a.thally.app/envlock/mcp
---

# Envlock MCP Server

An MCP server that exposes Envlock tools to AI assistants. Inspect contracts, validate environments, render .env.example files, diff env files, and explain issues.

The `@envlock/mcp` package provides a Model Context Protocol (MCP) server that
exposes Envlock operations as tools for AI assistants. All tools are read-only
and idempotent, and all file paths are confined to the server's working
directory.

## Installation

Run the server directly with `npx`:

```sh
npx -y @envlock/mcp
```

Or install globally:

```sh
npm install -g @envlock/mcp
```

Once installed globally, the binary is available as `envlock-mcp`.

## Client configuration

### Claude Desktop

Add the following to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "envlock": {
      "command": "npx",
      "args": ["-y", "@envlock/mcp"]
    }
  }
}
```

### Project-level configuration

For Claude Code, Cursor, or other MCP clients that support `.mcp.json`:

```json
{
  "mcpServers": {
    "envlock": {
      "command": "npx",
      "args": ["-y", "@envlock/mcp"]
    }
  }
}
```

If the package is already installed, you can use `"args": ["envlock-mcp"]`
instead.

## Server details

- **Name**: `"envlock"`
- **Version**: `"0.1.0"`
- **Transport**: stdio
- **Startup message**: `envlock-mcp ready on stdio` (written to stderr)
- **Server instructions** (sent during the MCP handshake): "Envlock validates
  environment variables against a typed contract (envlock.config.mjs). Use
  envlock_inspect to learn what an app needs, envlock_check to validate a .env
  file, and envlock_render_example to produce .env.example text."

## Tools

All five tools are annotated with `readOnlyHint: true` and
`idempotentHint: true`.

### envlock_check

**Check environment against contract**

Validates an environment source against a schema. Without `envFilePath`, the
server's own `process.env` is used as the source. The `strict` option only
applies when validating a file.

**Input**:

| Parameter | Type | Required | Description |
|---|---|---|---|
| `schemaPath` | `string` | Yes | Path to the envlock config file |
| `envFilePath` | `string` | No | Path to a `.env` file to validate instead of `process.env` |
| `strict` | `boolean` | No | Report undeclared variables (file sources only) |

**Output**: `{ ok, issues, source }`

- `ok` -- `boolean`, whether validation passed
- `issues` -- array of `EnvIssue` objects (each with `key`, `code`, `message`,
  and optional `received`)
- `source` -- string describing what was validated

### envlock_inspect

**Inspect environment contract**

Returns a structured description of every variable declared in the schema.

**Input**:

| Parameter | Type | Required | Description |
|---|---|---|---|
| `schemaPath` | `string` | Yes | Path to the envlock config file |

**Output**: `{ schemaPath, variables }`

- `schemaPath` -- the resolved schema path
- `variables` -- array of `SchemaDescription` objects (each with `key`, `type`,
  `required`, `hasDefault`, `secret`, and optional `default`, `description`,
  `example`, `constraints`)

### envlock_render_example

**Render .env.example**

Generates `.env.example` text from a schema. Unlike the other tools, this
returns plain text rather than JSON.

**Input**:

| Parameter | Type | Required | Description |
|---|---|---|---|
| `schemaPath` | `string` | Yes | Path to the envlock config file |

**Output**: the rendered example text as a single text content block.

### envlock_diff

**Diff env file against contract**

Compares a `.env` file against a schema and reports missing, unknown, and
invalid variables. Always operates in strict mode.

**Input**:

| Parameter | Type | Required | Description |
|---|---|---|---|
| `schemaPath` | `string` | Yes | Path to the envlock config file |
| `envFilePath` | `string` | Yes | Path to the `.env` file to compare |

**Output**: `{ ok, missing, unknown, invalid, source }`

- `ok` -- `boolean`, whether the file matches the contract exactly
- `missing` -- array of key names required by the schema but absent from the
  file
- `unknown` -- array of key names present in the file but not declared in the
  schema
- `invalid` -- array of `EnvIssue` objects for values that failed parsing
- `source` -- string describing what was diffed

### envlock_explain_issue

**Explain a validation issue**

Provides a human-readable explanation and remediation steps for a validation
issue. This is a pure function that does not access any files.

**Input**:

| Parameter | Type | Required | Description |
|---|---|---|---|
| `code` | `"missing"`, `"invalid"`, or `"unknown"` | Yes | The issue code |
| `key` | `string` | Yes | The variable name |
| `message` | `string` | No | The original issue message (included in the explanation) |

**Output**: `{ code, key, summary, steps }`

- `code` -- the issue code echoed back
- `key` -- the variable name echoed back
- `summary` -- a sentence explaining the issue
- `steps` -- an array of remediation steps (three strings)

## Resource template

The server exposes a resource template for reading schema descriptions.

- **URI template**: `envlock://schema/{schemaPath}`
- **Name**: `"envlock-schema"`
- **MIME type**: `application/json`
- **Returns**: the `describeSchema()` JSON for the given schema file

The `schemaPath` parameter in the URI is URL-encoded. There is no `list`
callback, so `resources/list` returns nothing. Discover the template via
`resources/templates/list`. The same path confinement rules apply as for tools.

## Path security

All file paths (both `schemaPath` and `envFilePath`) are resolved relative to
the server's working directory. Any path that would escape the working directory
is rejected with an error.

Error messages produced by path confinement and file loading:

- Path outside the working directory:
  `path "<filePath>" is outside the server working directory (<base>); start envlock-mcp from the project root`
- Schema file not found: `schema file not found: <path>`
- Import failure: `failed to import <path>: <detail>`
- Invalid export: `<path> must export default defineEnv({...}) or a named schema`
- Env file unreadable: `could not read env file <path>: <detail>`

## Programmatic usage

For custom transports or embedding the server in another process, use
`createEnvlockServer` directly.

```ts
import { createEnvlockServer } from "@envlock/mcp";

const server = createEnvlockServer({ cwd: "/path/to/project" });
```

The function accepts an optional `EnvlockServerOptions` object:

```ts
interface EnvlockServerOptions {
  readonly cwd?: string; // defaults to process.cwd()
}
```

The returned value is an `McpServer` instance that you can connect to any
MCP-compatible transport.

## Exported constants

The package exports several constants for programmatic use:

- `TOOL_NAMES` -- maps logical names to MCP tool names:
  `{ check: "envlock_check", inspect: "envlock_inspect", renderExample: "envlock_render_example", diff: "envlock_diff", explainIssue: "envlock_explain_issue" }`
- `SERVER_INFO` -- `{ name: "envlock", version: "0.1.0" }`
- `SCHEMA_RESOURCE_TEMPLATE` -- `"envlock://schema/{schemaPath}"`