nexus-mcp
README.md
# nexus-mcp
TypeScript **MCP server** for the [Plugin Federation](https://github.com/plugin-federation)
**Nexus** control plane. Coding agents and humans can inspect catalogs, judge
opinions, plugins, proposals, and run governance writes — without pasting
long-lived Nexus API tokens.
## MCP protocol
| Item | Value |
|------|--------|
| Spec revision | **`2026-07-28`** ([stateless modern core](https://modelcontextprotocol.io/specification/2026-07-28)) |
| TypeScript SDK | **`@modelcontextprotocol/server@^2`** (MCP SDK v2) |
| Schema validation | Zod v4 (`zod/v4`) |
| Transport | stdio (primary); protocol versions advertised include modern + 2025-era fallbacks |
Configured in [`src/mcp-protocol.ts`](./src/mcp-protocol.ts) via
`supportedProtocolVersions` (modern `2026-07-28` first).
## Security model
| Identity | How it authenticates | Nexus credential |
|---|---|---|
| **Human** (Cursor, Claude Desktop, local agent) | **GitHub SSO** — device flow (`GITHUB_OAUTH_CLIENT_ID`) or existing `gh auth login` session | Short-lived Nexus JWT via `provider: github_user` (memory only) |
| **GitHub Actions / coding agents in GitHub** | **GitHub OIDC** (`permissions: id-token: write`) + tenant OIDC trust policy | Short-lived Nexus JWT via `provider: github_actions` (memory only) |
**Not supported (by design):**
- `NEXUS_ACCESS_TOKEN` / `NEXUS_BEARER_TOKEN` (static control-plane secrets)
- Gateway enrollment / workload / bootstrap credential tools
- Recording tool catalogs or analyses from chat (CI + OIDC Actions own evidence)
Nexus remains the **only** issuer of API JWTs (ADR 0008).
## Tools (v0.1)
Orientation: `get_session`, `get_tenant`, `list_pipeline_checks`
Plugins: `list_plugins`, `create_plugin`, `get_plugin_draft`, `replace_plugin_draft`,
`compose_plugin_draft`, `list_plugin_variants`, `list_plugin_revisions`
Quality: `get_tool_catalog`, `list_tool_analyses`, `list_tool_judges`,
`get_tool_judge`, `create_tool_judge`, `update_tool_judge`,
`get_latest_schema_verification`, `summarize_source_quality`,
`find_fix_suggestions_for_tool`
Governance: `get_proposal`, `create_proposal`,
`create_proposal_from_schema_verification`, `decide_proposal` (confirm),
`release_plugin_revision` (confirm), `promote_plugin_revision` (confirm)
Exports: `get_compatibility_report`, `create_export`, `get_export_job`
Audit: `list_audit_events`
## Setup
```bash
npm install
npm run build
```
### Environment
| Variable | Required | Purpose |
|---|---|---|
| `NEXUS_URL` | yes | e.g. `https://api.nonprod.plugin-federation.com` |
| `TENANT_ID` | Actions OIDC | Tenant UUID matching OIDC trust policy; also preferred tenant for multi-membership humans |
| `NEXUS_OIDC_AUDIENCE` | Actions | Must match Nexus `NEXUS_OIDC_GITHUB_AUDIENCE` (defaults to `NEXUS_URL`) |
| `GITHUB_OAUTH_CLIENT_ID` | humans (device flow) | Public OAuth App client id for device flow |
| `NEXUS_MCP_ALLOW_GH_CLI` | no | Default `true` — use `gh auth token` when device flow client id unset |
| `NEXUS_MCP_GITHUB_USER_TOKEN` | no | Optional GitHub **user** OAuth token injected by a host (still exchanged; never a Nexus JWT) |
### Human (local)
```bash
# Option A: GitHub CLI already SSO'd
gh auth login
export NEXUS_URL=https://api.nonprod.plugin-federation.com
export TENANT_ID=<optional-preferred-tenant>
npx tsx src/index.ts
# Option B: device flow
export GITHUB_OAUTH_CLIENT_ID=<public-oauth-app-client-id>
npx tsx src/index.ts
# Follow the verification URL + user code on stderr
```
### GitHub Actions / coding agent
```yaml
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "22"
- run: npm ci && npm run build
working-directory: path/to/nexus-mcp
- name: Run agent with Nexus MCP
env:
NEXUS_URL: ${{ vars.NEXUS_URL }}
TENANT_ID: ${{ vars.TENANT_ID }}
NEXUS_OIDC_AUDIENCE: ${{ vars.NEXUS_OIDC_AUDIENCE }}
run: node path/to/nexus-mcp/dist/index.js
```
Register `owner/repo` (immutable ids) on a Nexus **OIDC trust policy** with the
roles the agent needs (contributor / approver / etc.).
### MCP client config (stdio example)
```json
{
"mcpServers": {
"nexus": {
"command": "node",
"args": ["/absolute/path/to/nexus-mcp/dist/index.js"],
"env": {
"NEXUS_URL": "https://api.nonprod.plugin-federation.com",
"TENANT_ID": "11111111-1111-4111-8111-111111111111",
"GITHUB_OAUTH_CLIENT_ID": "Ov23li…"
}
}
}
}
```
## Development
```bash
npm run typecheck
npm run dev
```
## Related
- [ADR 0008 Human GitHub SSO](https://github.com/plugin-federation/plugin-federation/blob/main/docs/architecture/decisions/0008-human-github-sso.md)
- [meteo-static](https://github.com/plugin-federation/meteo-static) / [units-static](https://github.com/plugin-federation/units-static) dogfood MCPs
- Console uses the same `github_user` exchange path
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues