Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ node_modules/

# Generated build output (published to the target repos by CI)
dist/
# glean-vnext runtime MCP server bundle (regenerated by build:bundle / prebuild)
sources/glean-vnext/dist/

# OS files
.DS_Store
Expand Down
114 changes: 114 additions & 0 deletions docs/glean-vnext-developer-testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
# Glean-vnext — Developer Testing Doc

Merging the glean-vnext runtime MCP server into the existing `glean` emitted plugin.

## Draft PRs
- **pluginpack** (enables this): https://github.com/gleanwork/pluginpack/pull/11 — `feat: per-target MCP config overrides + plugin-root files` (branch `eshwar/per-target-mcp-and-plugin-root-files`)
- **agent-plugins** (this work): https://github.com/gleanwork/agent-plugins/pull/3 — `feat: fold glean-vnext runtime MCP server into the glean plugin` (branch `eshwar/glean-vnext-fold-into-glean`)

---

## What was done

The glean-vnext runtime MCP server moved out of `glean-experimental-plugins` into `agent-plugins` as a **source plugin** at `sources/glean-vnext/`, and is **folded into the existing `glean` emitted plugin** via the `from:` array for claude/cursor/codex. The shipped `glean` plugin now **coexists** with the portable skills:

- It bundles a **local stdio MCP server** named `glean-local` (exposes `find_skills`, `run_tool`, `setup`), the `glean_run` skill, and an auto-approve `PreToolUse` hook.
- Users may **still connect a remote Glean MCP server**; the local server is named `glean-local` to avoid clashing with a remote `glean`.

### Source plugin layout (`sources/glean-vnext/`)
| File | Purpose |
|---|---|
| `plugin.pluginpack.json` | `files` map → `dist/index.js`, `start.mjs`, `package.json` copied to plugin root |
| `.mcp.json` | base MCP config: server `glean-local`, `node ${CLAUDE_PLUGIN_ROOT}/start.mjs` (claude/cursor) |
| `targets/codex/.mcp.json` | per-target override: `node ./start.mjs` + `cwd "."` (codex) |
| `start.mjs` | launcher that boots the bundled server |
| `package.json` | runtime manifest (`"type": "module"`) |
| `src/` (15 TS files) | server source (auth, tools, remote-client, skill-writer, …) |
| `build.mjs` | esbuild: `src/index.ts` → `dist/index.js` (single-file ESM bundle) |
| `tests/` (14 vitest files) | server unit tests (189 tests) |
| `skills/glean_run/SKILL.md` | the `glean_run` skill |
| `hooks/auto-approve-run-tool.mjs` + `hooks.json` | Claude Code PreToolUse auto-approve for `run_tool` |

### Config + build changes
- **`pluginpack.config.ts`**: `glean-vnext` added to each target's `glean` `from:`; `hooks` added to claude/cursor `components` (codex unchanged — no hooks).
- **`package.json`**: `build:bundle` (esbuild) chained into `prebuild` (runs before `pluginpack build`); `test:bundle` / `typecheck:bundle`; deps `@modelcontextprotocol/sdk`, `yaml`, `esbuild`, `tsx`, `typescript`, `vitest`, `@types/node`; CVE `overrides` mirroring the experimental repo.
- **Hook**: server env lookup now checks `mcpServers["glean-local"]` first (was `glean`), fallback to legacy `glean` — fixes a production bug introduced by the rename.
- `.gitignore`: `sources/glean-vnext/dist/` (bundle is a build artifact regenerated by `prebuild`).

---

## ⚠️ Release blocker

agent-plugins depends on **`@gleanwork/pluginpack@^0.7.0`** (published), which lacks the new `files` + per-target `.mcp.json` override features. The work in PR #3 requires **`@gleanwork/pluginpack@^0.8.0`** (PR #11) once published.

**Until 0.8.0 is published, build locally:**
```bash
cd ../pluginpack && npm install && npm run build && npm link
cd ../agent-plugins && npm install && npm link @gleanwork/pluginpack
```
**Footgun:** `npm install` clobbers the link (replaces the symlink with the real 0.7.0). Re-run `npm link @gleanwork/pluginpack` after any install, or `npm test` will silently drop to baseline (vnext's `files`/MCP ignored — file counts fall to 66/62/53 instead of 69/65/56).

**Before merging PR #3:** publish pluginpack 0.8.0, then bump agent-plugins `package.json` `@gleanwork/pluginpack` to `^0.8.0` and drop the `npm link` step.

---

## How to test — automated

```bash
cd /path/to/agent-plugins
npm link @gleanwork/pluginpack # until 0.8.0 published (see release blocker)
npm test # prebuild → build:bundle → pluginpack build → validate
npm run test:bundle # 189 server unit tests (vitest)
npm run typecheck:bundle # tsc --noEmit on the server
```
**Expected:** `npm test` green (Validation passed ×3; 69/65/56 managed files cursor/claude/codex); `test:bundle` 189/189; typecheck clean.

### Verify emitted output
```bash
# claude: .mcp.json uses ${CLAUDE_PLUGIN_ROOT}/start.mjs
cat dist/claude/plugins/glean/.mcp.json
# codex: .mcp.json uses ./start.mjs + cwd "." (per-target override)
cat dist/codex/plugins/glean/.mcp.json
# runtime files shipped at plugin root
ls dist/claude/plugins/glean/{start.mjs,dist/index.js,package.json,hooks/auto-approve-run-tool.mjs}
# glean_run skill alongside the 18 portable skills
ls dist/claude/plugins/glean/skills
# codex manifest references the MCP config
grep mcpServers dist/codex/plugins/glean/.codex-plugin/plugin.json
```

---

## How to test — manual (host-by-host)

Point each host at the emitted `dist/<target>/` directory and exercise the local server.

### Claude Code
```bash
cd /path/to/agent-plugins/dist/claude
claude plugin marketplace add . # or symlink the glean plugin dir
```
- Tools appear as `mcp__glean-local__find_skills` / `run_tool` / `setup`.
- Run `setup` first to authenticate (OAuth to your Glean tenant).
- Invoke the `glean_run` skill; it orchestrates `find_skills` + `run_tool`.
- **Hook check:** with `ENABLE_HITL=true` (set in `.mcp.json`), calling `run_tool` should be auto-approved (no native "allow this tool?" prompt) — the HITL elicitation is the single gate. With `ENABLE_HITL` off, the normal permission flow runs.

### Cursor
Add `dist/cursor` as a plugin via Cursor's plugin UI. Same tool names; the local `glean-local` server boots via `start.mjs`. Run `setup`, then `find_skills`/`run_tool`.

### Codex
Install from `dist/codex` (`.agents/plugins/marketplace.json`):
```bash
codex mcp list # should show glean-local
```
`codex mcp` lists `glean-local`; `.mcp.json` uses `./start.mjs` + `cwd "."` (codex doesn't expand `${CLAUDE_PLUGIN_ROOT}`). Run `setup` → `find_skills` → `run_tool`. No hooks for codex (by design).

### Regression check (coexist)
Confirm the 18 portable skills still work and that a separately-connected **remote** `glean` MCP server still resolves under its own name — the local `glean-local` must not collide with it.

---

## Architecture pointers
- pluginpack branch: per-target `.mcp.json` override replaces the base config for that target (full `mcpServers` object). Only the `.mcp.json` **file form** supports overrides; the `mcpServers` manifest form does not.
- The bundle is a single-file ESM esbuild output (inlines `@modelcontextprotocol/sdk` + `yaml`) so the shipped tree has no scoped-package paths (the plugin-install validator rejects `@` in zip entry paths).
- See `pluginpack-dataflow.md` for the full source-plugin → emitted-plugin pipeline and the detailed vnext transformation example.
Loading