Skip to main content
Glama
README.md
# esa MCP Worker

A small Cloudflare Worker that reads and writes [esa](https://esa.io/) through MCP. Cloudflare Access Managed OAuth handles client authentication. The Worker verifies the Access JWT and calls esa with one deployment secret.

## Design

The normal request path contains one `/mcp` endpoint, Access JWT verification, MCP dispatch, and an esa API request. The project has no custom OAuth server, admin UI, KV/D1 state, audit pipeline, connection tracking, observer, or post cache.

Six esa tools are always available:

| Tool | Purpose |
| --- | --- |
| `esa_get_post` | Read posts as metadata, outline, excerpt, or bounded Markdown |
| `esa_search_posts` | Run one search or up to ten searches concurrently |
| `esa_read_sections` | Read selected Markdown heading sections |
| `esa_create_post` | Create a post |
| `esa_update_post` | Update selected post fields |
| `esa_patch_post` | Apply ordered text replacements, section replacements, and appends |

When GitHub App settings are present, five lightweight repository tools are added:

| Tool | Purpose |
| --- | --- |
| `repo_get_snapshot` | Read a commit SHA and file catalog |
| `repo_read_files` | Read up to twelve files or line ranges |
| `repo_create_implementation_branch` | Create one atomic implementation commit |
| `repo_get_implementation_status` | Read checks and commit statuses once |
| `repo_publish_implementation` | Fast-forward the default branch after successful checks |

The GitHub flow has no audit wrapper, coding checklist payload, server-side polling, write-confirmation flag, or partial-success fallback.

## Requirements

- Node.js 24.11 or later
- pnpm 10.11.1
- A Cloudflare account
- An esa personal access token

## Setup

Install dependencies and verify the project:

```sh
pnpm install --frozen-lockfile
pnpm verify
```

Configure Worker variables:

```text
ESA_DEFAULT_TEAM=your-team
TEAM_DOMAIN=https://your-team.cloudflareaccess.com
POLICY_AUD=your-access-application-aud
```

Store the esa token as an encrypted Worker secret:

```sh
pnpm exec wrangler secret put ESA_ACCESS_TOKEN
```

Deploy the Worker, then protect `/mcp` with a Cloudflare Access self-hosted application and enable Managed OAuth.

```sh
pnpm run deploy
```

Use this MCP URL:

```text
https://YOUR-WORKER.workers.dev/mcp
```

Cloudflare Access returns authentication failures before requests reach the Worker.

## Optional GitHub tools

Set these values together to enable repository tools:

```text
GITHUB_REPOSITORY=owner/repository
GITHUB_APP_ID=123
GITHUB_APP_INSTALLATION_ID=456
GITHUB_DEFAULT_BRANCH=main
GITHUB_BRANCH_PREFIX=mcp/
GITHUB_REQUIRED_CHECK_NAMES=build,test
```

Store the downloaded GitHub App private key as a Worker secret:

```sh
pnpm exec wrangler secret put GITHUB_APP_PRIVATE_KEY
```

Grant the GitHub App repository access and the permissions required by the tools: Contents read/write, Checks read, and Commit statuses read.

## OpenAPI generation

[openapi.yaml](openapi.yaml) is the canonical source for public tool titles, descriptions, annotations, input schemas, and TypeScript input types. The generator uses `openapi-typescript` for types and Zod's JSON Schema converter for runtime validation:

```sh
pnpm generate
```

`pnpm verify` runs `generate:check` and fails when generated code is stale.

## Errors

Tool failures use `isError: true` and one English message. Upstream HTTP status codes are exposed as `upstream_status`; the Worker does not map them to custom domain status codes.

Write tools do not use `confirm_write`. Pass `expected_revision_number` for esa changes and expected Git/blob SHAs for repository changes that depend on a prior read.

See [docs/reference.md](docs/reference.md) for the detailed behavior and [SECURITY.md](SECURITY.md) for reporting.

## License

[MIT](LICENSE) Copyright (c) 2026 Ierllow