Skip to main content
Glama
pavelpikta

lampa-mcp-server

README.md
# lampa-mcp-server

[![lampa-mcp-server MCP server](https://glama.ai/mcp/servers/pavelpikta/lampa-mcp-server/badges/card.svg)](https://glama.ai/mcp/servers/pavelpikta/lampa-mcp-server)

[![lampa-mcp-server MCP server](https://glama.ai/mcp/servers/pavelpikta/lampa-mcp-server/badges/score.svg)](https://glama.ai/mcp/servers/pavelpikta/lampa-mcp-server)
[![TDQS](https://tdqs.dev/reports/qfx61dm6h0/badge.svg)](https://tdqs.dev/reports/qfx61dm6h0)

[![CI](https://github.com/pavelpikta/lampa-mcp-server/actions/workflows/ci.yml/badge.svg)](https://github.com/pavelpikta/lampa-mcp-server/actions/workflows/ci.yml)
[![Release](https://github.com/pavelpikta/lampa-mcp-server/actions/workflows/release.yml/badge.svg)](https://github.com/pavelpikta/lampa-mcp-server/actions/workflows/release.yml)
[![Release](https://img.shields.io/github/v/release/pavelpikta/lampa-mcp-server?label=release)](https://github.com/pavelpikta/lampa-mcp-server/releases/latest)

An [MCP](https://modelcontextprotocol.io) server for AI-assisted development on the [Lampa](https://github.com/yumata/lampa-source) open-source TV app.

It gives AI agents (Claude, Cursor, etc.) structured, read-only access to the Lampa source tree — so they understand the repo before making changes.

Runs in two modes:

- **Local stdio** — Node process spawned by Cursor / Claude Desktop (unchanged workflow)
- **Cloudflare Workers** — remote Streamable HTTP MCP at `/mcp` with GitHub PAT auth and an R2 source snapshot

---

## What it does

The server exposes **16 tools** (plus Worker-only `whoami`) and curated resources (`lampa://plugin-guide`, `lampa://pitfalls`, `lampa://events`, `lampa://landmarks`, `lampa://edit-rules`, `lampa://api-surface`). Tools are read-only: they never write the Lampa repo.

| Tool                   | Role                                                                                       |
| ---------------------- | ------------------------------------------------------------------------------------------ |
| `summarize_repo`       | Snapshot metadata, tree, scripts, optional module listing                                  |
| `search_code`          | Content/regex search                                                                       |
| `find_files`           | Paths by name, feature, UI, styles, or specs                                               |
| `read_source`          | File / core module / template bytes                                                        |
| `analyze_plugin`       | One plugin folder (+ load path if name omitted)                                            |
| `list_catalog`         | Catalogs (API, events, storage, Maker, …)                                                  |
| `trace_symbol`         | Follow one event, component, file, or deprecated API                                       |
| `explain_docs`         | Plugin docs, patterns, packaging                                                           |
| `plan_change`          | Plan + targets + impact + risks                                                            |
| `draft_patch`          | Suggested diffs (does not write)                                                           |
| `scaffold_plugin`      | New plugin / setting / hook text (does not write)                                          |
| `validate_code`        | Plugin score, grep, i18n, build hint                                                       |
| `guide_cub`            | CUB APIs as used in Lampa source                                                           |
| `resolve_edit_path`    | Authoritative `src/` / `plugins/` path                                                     |
| `guide_external_api`   | Third-party content APIs (TMDB, KinoPoisk, Alloha, MDBList, Jackett, TorrServer, Jellyfin)  |
| `guide_plugin_catalog` | Real plugin-catalog packaging/publishing pipeline (manifest, obfuscation, routing)          |

Preferred agent loop:

```
summarize_repo → explain_docs(mode=plugin_docs) | analyze_plugin
  → search_code | list_catalog | trace_symbol
  → resolve_edit_path → plan_change → scaffold_plugin | draft_patch
  → validate_code
```

Use `resolve_edit_path` before editing so you change `src/` / `plugins/` rather than `public/` or `build/`.

Third-party content-provider APIs (TMDB/KinoPoisk/Alloha/MDBList/Jackett/TorrServer/Jellyfin): `guide_external_api`. Shipping a plugin into the real lampa-plugins catalog: `guide_plugin_catalog`. Both are static, curated references — they never expose real credentials and never touch this repo's snapshot.

---

## Requirements

- Node.js 20+
- For **local** mode: a checkout of [lampa-source](https://github.com/yumata/lampa-source)
- For **Workers** mode: a Cloudflare account, R2 bucket, KV namespace, and a GitHub Personal Access Token (`read:user`)

---

## Local stdio setup

```bash
git clone <this-repo>
cd lampa-mcp-server
npm install
npm run build
export LAMPA_REPO_PATH=/path/to/lampa-source
npm start
```

### Claude Desktop

```json
{
  "mcpServers": {
    "lampa-mcp-server": {
      "command": "node",
      "args": ["/absolute/path/to/lampa-mcp-server/dist/index.js"],
      "env": {
        "LAMPA_REPO_PATH": "/absolute/path/to/lampa-source"
      }
    }
  }
}
```

### Cursor

```json
{
  "mcpServers": {
    "lampa-mcp-server": {
      "command": "node",
      "args": ["/absolute/path/to/lampa-mcp-server/dist/index.js"],
      "env": {
        "LAMPA_REPO_PATH": "/absolute/path/to/lampa-source"
      }
    }
  }
}
```

---

## Cloudflare Workers (remote MCP)

Architecture: `createMcpHandler` (MCP SDK v2, stateless) + R2 Lampa snapshot + GitHub PAT auth via `resolveExternalToken` on `@cloudflare/workers-oauth-provider`.

### 1. Create Cloudflare resources

```bash
npx wrangler r2 bucket create lampa-mcp-source
npx wrangler kv namespace create OAUTH_KV
```

Put the returned KV namespace id into [`wrangler.jsonc`](wrangler.jsonc) (`kv_namespaces[0].id`).

### 2. Create a GitHub Personal Access Token

Create a [classic](https://github.com/settings/tokens) or [fine-grained](https://github.com/settings/personal-access-tokens) PAT with at least **`read:user`**.

No GitHub OAuth App / `GITHUB_CLIENT_ID` / `GITHUB_CLIENT_SECRET` is required.

Optional allowlist (comma-separated GitHub logins) in `wrangler.jsonc` vars or `.dev.vars`:

```
ALLOWED_GITHUB_USERS=your-login,coworker
```

### 3. Upload a Lampa source snapshot to R2

```bash
# clone Lampa if needed
git clone https://github.com/yumata/lampa-source temp/lampa-source

# local Miniflare R2 (for wrangler dev)
npm run snapshot:upload:local

# production R2
npm run snapshot:upload
```

Objects land under `lampa/manifest.json`, `lampa/bundle.json` (all source text), and `lampa/indexes/*.json`.

### 4. Deploy

```bash
npm run types:worker
npm run deploy
```

MCP endpoint: `https://lampa-mcp-server.<account>.workers.dev/mcp`

### 5. Connect a remote MCP client

Pass the GitHub PAT as a Bearer token. Cursor example:

```json
{
  "mcpServers": {
    "lampa": {
      "url": "https://lampa-mcp-server.<account>.workers.dev/mcp",
      "headers": {
        "Authorization": "Bearer ghp_YOUR_GITHUB_PAT"
      }
    }
  }
}
```

Or via [`mcp-remote`](https://www.npmjs.com/package/mcp-remote):

```json
{
  "mcpServers": {
    "lampa": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "https://lampa-mcp-server.<account>.workers.dev/mcp",
        "--header",
        "Authorization: Bearer ghp_YOUR_GITHUB_PAT"
      ]
    }
  }
}
```

Prefer storing the PAT in env / secret storage rather than committing it to `mcp.json`.

### Local Worker development

```bash
npm run snapshot:upload:local
npm run dev:worker
```

Then point the MCP inspector / client at `http://localhost:8787/mcp` with `Authorization: Bearer <pat>`.

---

## Recommended agent workflow

```
summarize_repo → explain_docs(mode=plugin_docs) | analyze_plugin
    → search_code | list_catalog | trace_symbol
    → resolve_edit_path → plan_change → scaffold_plugin | draft_patch
    → validate_code
```

Plugin authoring must follow official `docs/en` (Listener app:ready, SettingsApi, double-load guard). Do not emit `$(document).on('appready')` or `Lampa.Settings.add`.

For CUB account/sync work:

```
guide_cub(topic=auth) → guide_cub(topic=catalog) → guide_cub(topic=sync)
    → guide_cub(topic=models) → guide_cub(topic=endpoint)
```

### Breaking change (v1.x → verb_noun tools)

Aliases, thin wrappers, and v1.7 noun-first names were removed so the catalog stays in the 3–15 range Glama scores. Call the replacement instead:

| Removed                                                                                                                    | Use instead                        |
| -------------------------------------------------------------------------------------------------------------------------- | ---------------------------------- |
| `snapshot_info`, `list_scripts`, `list_modules`                                                                            | `summarize_repo`                   |
| `read_file`, `read_file_segment`, `get_core_module`, `list_templates`, `extract_template_html`                             | `read_source`                      |
| `find_feature`, `find_ui_component`, `find_styles_for_module`, `list_related_tests`                                        | `find_files` (`mode=…`)            |
| `plan_feature_change`, `impact_analysis`, `suggest_edit_targets`, `risk_scan`                                              | `plan_change`                      |
| `scaffold_plugin_integration`, `generate_plugin_boilerplate`, `add_setting`, `insert_hook`                                 | `scaffold_plugin`                  |
| `validate_plugin`, `run_grep_checks`, `i18n_check`, `find_translation_keys`, `translation_coverage`, `run_build_hint`      | `validate_code`                    |
| `plugin_docs`, `doc_lookup`, `explain_lampa_pattern`, `platform_packaging_guide`                                           | `explain_docs`                     |
| `lampa_api_surface`, `list_all_events`, `get_storage_schema`, `get_network_map`, `find_settings`, Maker/socket/flags/…     | `list_catalog` (`topic=…`)         |
| `trace_event`, `component_lifecycle`, `module_dependency_map`, `find_api_calls`, `upgrade_migration_checker`               | `trace_symbol`                     |
| `cub_api_catalog`, `cub_endpoint_detail`, `cub_auth_guide`, `cub_data_models`, `cub_sync_guide`, `cub_timeline_hash_guide` | `guide_cub`                        |
| `plugin_load_path`                                                                                                         | `analyze_plugin` (omit `plugin`)   |
| `repo_overview`                                                                                                            | `summarize_repo`                   |
| `plugin_deep_dive`                                                                                                         | `analyze_plugin`                   |
| `map_lampa`                                                                                                                | `list_catalog`                     |
| `trace_lampa`                                                                                                              | `trace_symbol`                     |
| `explain_lampa`                                                                                                            | `explain_docs`                     |
| `cub_guide`                                                                                                                | `guide_cub`                        |

---

## Project structure

```
src/
├── index.ts                 # Local stdio entry
├── worker.ts                # Cloudflare Worker + PAT auth entry
├── server.ts                # Shared createLampaServer factory
├── config.ts                # Local Config (NodeRepoFs)
├── auth/github-handler.ts   # Public pages + GitHub PAT validation
├── fs/                      # RepoFs: types, Node, R2, paths
├── utils/                   # Async analysis helpers
├── tools/                   # MCP tools
└── resources/               # MCP resources
scripts/
└── upload-snapshot.mjs      # R2 snapshot + index uploader
wrangler.jsonc
```

---

## Development

```bash
npm run build                # wrangler types + tsc → dist/
npm run dev                  # build, then run stdio server
npm start                    # run compiled stdio server
npm run typecheck            # wrangler types + tsc --noEmit
npm run lint
npm run format
npm run types:worker         # regenerate worker-configuration.d.ts (gitignored)
npm run dev:worker           # wrangler dev
npm run deploy               # wrangler deploy
npm run snapshot:upload:local
npm run snapshot:upload
```

### Dependencies (what / why)

| Package                                     | Role                                                  |
| ------------------------------------------- | ----------------------------------------------------- |
| `@modelcontextprotocol/server`              | MCP SDK (stdio + shared server factory)               |
| `agents`                                    | Workers MCP handler (`createMcpHandler`)              |
| `@cloudflare/workers-oauth-provider`        | Worker auth wrapper (PAT via `resolveExternalToken`)  |
| `hono`                                      | Public HTML routes (`/`, `/authorize`)                |
| `zod`                                       | Tool input schemas                                    |
| `typescript`                                | TypeScript 6 compiler + types for `typescript-eslint` |
| `wrangler`                                  | Deploy, `wrangler types`, local Worker dev            |
| `eslint` + `typescript-eslint` + `prettier` | Lint / format                                         |

Runtime deps ship with both the stdio CLI and the Worker. Dev deps are local-only.

---

## License

MIT

TDQS

A4.8/5.0

Scored across 16 tools

Disambiguation5/5

Every tool has a clearly distinct role: overview, content search, path lookup, file read, edit-path resolution, catalog dump, plugin analysis, symbol tracing, planning, patching, scaffolding, validation, or a specific documentation guide. The descriptions actively cross-reference what each tool should not be used for, making misselection unlikely.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern, such as summarize_repo, search_code, find_files, draft_patch, and validate_code. The guide_* and explain_* prefixes create recognizable subfamilies without breaking the overall naming convention.

Tool Count4/5

At 16 tools, the surface is slightly above the ideal 3–15 range, but each tool contributes to the snapshot-inspection and plugin-development workflow. The documentation guides could theoretically be consolidated, but their distinct topics make the count acceptable.

Completeness5/5

The tool set covers the full inspection-to-planning lifecycle: orient, search, read, locate, trace, catalog, plan, patch, scaffold, validate, and consult documentation. Write and execute operations are intentionally excluded as snapshot-only behavior, so the surface has no dead ends for its stated purpose.

Maintenance

ActivityActive
ResponsivenessNo issues