Metadata-Version: 2.4
Name: netlify-mcp
Version: 1.0.0
Summary: Python port of the official Netlify MCP server: manage Netlify projects, deploys, teams, extensions, and env vars from an MCP-compatible agent.
Keywords: mcp,ai,netlify,tools
Author: LOCOMOTIVE Agency
Author-email: LOCOMOTIVE Agency <erick@locomotive.agency>
License-Expression: MIT
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Requires-Dist: mcp>=1.9.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.11.7
Requires-Dist: pydantic-settings>=2.10.1
Requires-Dist: loguru>=0.7.3
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# netlify-mcp (Python)

A Python port of the official [Netlify MCP server](https://docs.netlify.com/welcome/build-with-ai/netlify-mcp-server/), built to behave identically to the TypeScript original for the local stdio use case: same tool names, same input schemas, same response text.

This port targets the **local stdio server only**. Two things in the original are intentionally out of scope:

* The remote proxy deploy mode (`--proxy-path` / JWE flow), used when the MCP server runs behind Netlify's hosted remote endpoint.
* The full remote OAuth/OIDC hosting server.

Everything else is ported: the `user`, `team`, `project`, `deploy`, and `extension` domain tool groups, the `netlify-coding-rules` context tool, and the Claude Design "Send to Netlify" import tools (`import-claude-design-from-url`, `get-design-import-job-status`).

---

## Requirements

* Python 3.12+
* A Netlify account, authenticated via one of:
  * `netlify login` (using the [Netlify CLI](https://cli.netlify.com/)) — this server reads the same `config.json` the CLI writes.
  * The `NETLIFY_PERSONAL_ACCESS_TOKEN` environment variable, which overrides the CLI-managed token when set.

## Install and run

```bash
uv sync
uv run netlify-mcp
```

Or, for one tool per operation instead of the grouped read/write selector tools:

```bash
uv run netlify-mcp --verbose
```

## MCP client configuration

```json
{
  "mcpServers": {
    "netlify": {
      "command": "uv",
      "args": ["run", "--directory", "/path/to/python-netlify-mcp", "netlify-mcp"]
    }
  }
}
```

## Tools

By default, each domain exposes two selector tools: `netlify-<domain>-services-reader` (read-only operations) and `netlify-<domain>-services-updater` (write operations). Each selector takes a `selectSchema` of `{operation, params}` covering every operation listed below for that domain. Pass `--verbose` to instead register one tool per operation, named `netlify-<domain>-<operation>`.

### user

| Operation | Read-only | Description |
| --- | --- | --- |
| `get-user` | Yes | Get the current authenticated Netlify user's account details. |

### team

| Operation | Read-only | Description |
| --- | --- | --- |
| `get-teams` | Yes | List the Netlify teams (accounts) the user belongs to. |
| `get-team` | Yes | Get details for a specific Netlify team. |

### project

| Operation | Read-only | Description |
| --- | --- | --- |
| `get-project` | Yes | Get details for a specific Netlify project. |
| `get-projects` | Yes | List Netlify projects, optionally filtered by team or name. |
| `get-forms-for-project` | Yes | List (or fetch one) Netlify Forms form(s) configured for a project. |
| `update-visitor-access-controls` | No | Configure SSO or password-based visitor access control for a project. |
| `update-forms` | No | Enable or disable Netlify Forms processing for a project. |
| `manage-form-submissions` | No | Get or delete form submissions for a project. |
| `update-project-name` | No | Rename a Netlify project. |
| `manage-env-vars` | No | Get, create/update, or delete environment variables for a project. |
| `create-new-project` | No | Create a new Netlify project. |

### deploy

| Operation | Read-only | Description |
| --- | --- | --- |
| `get-deploy` | Yes | Get a deploy by id. |
| `get-deploy-for-site` | Yes | Get a specific deploy for a given project. |
| `deploy-site` | No | Zip up a local directory and deploy it to a Netlify project. |

### extension

| Operation | Read-only | Description |
| --- | --- | --- |
| `get-extensions` | Yes | List extensions available to any Netlify team. |
| `get-full-extension-details` | Yes | Get full details for a specific extension on a team. |
| `change-extension-installation` | No | Install or uninstall an extension for a team (and optionally a site). |
| `initialize-database` | No | Return setup instructions for the `@netlify/database` package. |

### Standalone tools

These are registered individually, not as part of a domain's reader/updater selector, and are unaffected by `--verbose`.

| Tool | Read-only | Description |
| --- | --- | --- |
| `netlify-coding-rules` | Yes | Context tool that must be called before writing any serverless or Netlify SDK/library code. |
| `import-claude-design-from-url` | No | Deploy a Claude Design export to Netlify as a new project ("Send to Netlify"). |
| `get-design-import-job-status` | Yes | Check the status of an in-progress Claude Design import deploy job. |

## Configuration

Environment variables (see `.env.example`):

| Variable | Description |
| --- | --- |
| `NETLIFY_PERSONAL_ACCESS_TOKEN` | Optional. Skips the CLI-managed token lookup when set. |
| `LOG_LEVEL` | Logging level (default `INFO`). |

## Development

```bash
uv sync --group dev
uv run pytest
uv run ruff check .
uv run mypy src
```
